##// END OF EJS Templates
commit: use ui.configbool when checking 'commitsubrepos' setting on --amend...
Adrian Buehlmann -
r16505:db85c24d stable
parent child Browse files
Show More
@@ -1,5717 +1,5717 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, pvec
19 import random, setdiscovery, treediscovery, dagutil, pvec
20 import phases
20 import phases
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="", explicitonly=False)
176 opts.get('subrepos'), prefix="", explicitonly=False)
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199
199
200 Returns 0 if all files are successfully added.
200 Returns 0 if all files are successfully added.
201 """
201 """
202 try:
202 try:
203 sim = float(opts.get('similarity') or 100)
203 sim = float(opts.get('similarity') or 100)
204 except ValueError:
204 except ValueError:
205 raise util.Abort(_('similarity must be a number'))
205 raise util.Abort(_('similarity must be a number'))
206 if sim < 0 or sim > 100:
206 if sim < 0 or sim > 100:
207 raise util.Abort(_('similarity must be between 0 and 100'))
207 raise util.Abort(_('similarity must be between 0 and 100'))
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209
209
210 @command('^annotate|blame',
210 @command('^annotate|blame',
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 ('', 'follow', None,
212 ('', 'follow', None,
213 _('follow copies/renames and list the filename (DEPRECATED)')),
213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('a', 'text', None, _('treat all files as text')),
215 ('a', 'text', None, _('treat all files as text')),
216 ('u', 'user', None, _('list the author (long with -v)')),
216 ('u', 'user', None, _('list the author (long with -v)')),
217 ('f', 'file', None, _('list the filename')),
217 ('f', 'file', None, _('list the filename')),
218 ('d', 'date', None, _('list the date (short with -q)')),
218 ('d', 'date', None, _('list the date (short with -q)')),
219 ('n', 'number', None, _('list the revision number (default)')),
219 ('n', 'number', None, _('list the revision number (default)')),
220 ('c', 'changeset', None, _('list the changeset')),
220 ('c', 'changeset', None, _('list the changeset')),
221 ('l', 'line-number', None, _('show line number at the first appearance'))
221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ] + diffwsopts + walkopts,
222 ] + diffwsopts + walkopts,
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 def annotate(ui, repo, *pats, **opts):
224 def annotate(ui, repo, *pats, **opts):
225 """show changeset information by line for each file
225 """show changeset information by line for each file
226
226
227 List changes in files, showing the revision id responsible for
227 List changes in files, showing the revision id responsible for
228 each line
228 each line
229
229
230 This command is useful for discovering when a change was made and
230 This command is useful for discovering when a change was made and
231 by whom.
231 by whom.
232
232
233 Without the -a/--text option, annotate will avoid processing files
233 Without the -a/--text option, annotate will avoid processing files
234 it detects as binary. With -a, annotate will annotate the file
234 it detects as binary. With -a, annotate will annotate the file
235 anyway, although the results will probably be neither useful
235 anyway, although the results will probably be neither useful
236 nor desirable.
236 nor desirable.
237
237
238 Returns 0 on success.
238 Returns 0 on success.
239 """
239 """
240 if opts.get('follow'):
240 if opts.get('follow'):
241 # --follow is deprecated and now just an alias for -f/--file
241 # --follow is deprecated and now just an alias for -f/--file
242 # to mimic the behavior of Mercurial before version 1.5
242 # to mimic the behavior of Mercurial before version 1.5
243 opts['file'] = True
243 opts['file'] = True
244
244
245 datefunc = ui.quiet and util.shortdate or util.datestr
245 datefunc = ui.quiet and util.shortdate or util.datestr
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247
247
248 if not pats:
248 if not pats:
249 raise util.Abort(_('at least one filename or pattern is required'))
249 raise util.Abort(_('at least one filename or pattern is required'))
250
250
251 hexfn = ui.debugflag and hex or short
251 hexfn = ui.debugflag and hex or short
252
252
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 ('number', ' ', lambda x: str(x[0].rev())),
254 ('number', ' ', lambda x: str(x[0].rev())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('date', ' ', getdate),
256 ('date', ' ', getdate),
257 ('file', ' ', lambda x: x[0].path()),
257 ('file', ' ', lambda x: x[0].path()),
258 ('line_number', ':', lambda x: str(x[1])),
258 ('line_number', ':', lambda x: str(x[1])),
259 ]
259 ]
260
260
261 if (not opts.get('user') and not opts.get('changeset')
261 if (not opts.get('user') and not opts.get('changeset')
262 and not opts.get('date') and not opts.get('file')):
262 and not opts.get('date') and not opts.get('file')):
263 opts['number'] = True
263 opts['number'] = True
264
264
265 linenumber = opts.get('line_number') is not None
265 linenumber = opts.get('line_number') is not None
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
268
268
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271
271
272 def bad(x, y):
272 def bad(x, y):
273 raise util.Abort("%s: %s" % (x, y))
273 raise util.Abort("%s: %s" % (x, y))
274
274
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 m = scmutil.match(ctx, pats, opts)
276 m = scmutil.match(ctx, pats, opts)
277 m.bad = bad
277 m.bad = bad
278 follow = not opts.get('no_follow')
278 follow = not opts.get('no_follow')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
280 for abs in ctx.walk(m):
280 for abs in ctx.walk(m):
281 fctx = ctx[abs]
281 fctx = ctx[abs]
282 if not opts.get('text') and util.binary(fctx.data()):
282 if not opts.get('text') and util.binary(fctx.data()):
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 continue
284 continue
285
285
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 diffopts=diffopts)
287 diffopts=diffopts)
288 pieces = []
288 pieces = []
289
289
290 for f, sep in funcmap:
290 for f, sep in funcmap:
291 l = [f(n) for n, dummy in lines]
291 l = [f(n) for n, dummy in lines]
292 if l:
292 if l:
293 sized = [(x, encoding.colwidth(x)) for x in l]
293 sized = [(x, encoding.colwidth(x)) for x in l]
294 ml = max([w for x, w in sized])
294 ml = max([w for x, w in sized])
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 for x, w in sized])
296 for x, w in sized])
297
297
298 if pieces:
298 if pieces:
299 for p, l in zip(zip(*pieces), lines):
299 for p, l in zip(zip(*pieces), lines):
300 ui.write("%s: %s" % ("".join(p), l[1]))
300 ui.write("%s: %s" % ("".join(p), l[1]))
301
301
302 if lines and not lines[-1][1].endswith('\n'):
302 if lines and not lines[-1][1].endswith('\n'):
303 ui.write('\n')
303 ui.write('\n')
304
304
305 @command('archive',
305 @command('archive',
306 [('', 'no-decode', None, _('do not pass files through decoders')),
306 [('', 'no-decode', None, _('do not pass files through decoders')),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
308 _('PREFIX')),
308 _('PREFIX')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
311 ] + subrepoopts + walkopts,
311 ] + subrepoopts + walkopts,
312 _('[OPTION]... DEST'))
312 _('[OPTION]... DEST'))
313 def archive(ui, repo, dest, **opts):
313 def archive(ui, repo, dest, **opts):
314 '''create an unversioned archive of a repository revision
314 '''create an unversioned archive of a repository revision
315
315
316 By default, the revision used is the parent of the working
316 By default, the revision used is the parent of the working
317 directory; use -r/--rev to specify a different revision.
317 directory; use -r/--rev to specify a different revision.
318
318
319 The archive type is automatically detected based on file
319 The archive type is automatically detected based on file
320 extension (or override using -t/--type).
320 extension (or override using -t/--type).
321
321
322 .. container:: verbose
322 .. container:: verbose
323
323
324 Examples:
324 Examples:
325
325
326 - create a zip file containing the 1.0 release::
326 - create a zip file containing the 1.0 release::
327
327
328 hg archive -r 1.0 project-1.0.zip
328 hg archive -r 1.0 project-1.0.zip
329
329
330 - create a tarball excluding .hg files::
330 - create a tarball excluding .hg files::
331
331
332 hg archive project.tar.gz -X ".hg*"
332 hg archive project.tar.gz -X ".hg*"
333
333
334 Valid types are:
334 Valid types are:
335
335
336 :``files``: a directory full of files (default)
336 :``files``: a directory full of files (default)
337 :``tar``: tar archive, uncompressed
337 :``tar``: tar archive, uncompressed
338 :``tbz2``: tar archive, compressed using bzip2
338 :``tbz2``: tar archive, compressed using bzip2
339 :``tgz``: tar archive, compressed using gzip
339 :``tgz``: tar archive, compressed using gzip
340 :``uzip``: zip archive, uncompressed
340 :``uzip``: zip archive, uncompressed
341 :``zip``: zip archive, compressed using deflate
341 :``zip``: zip archive, compressed using deflate
342
342
343 The exact name of the destination archive or directory is given
343 The exact name of the destination archive or directory is given
344 using a format string; see :hg:`help export` for details.
344 using a format string; see :hg:`help export` for details.
345
345
346 Each member added to an archive file has a directory prefix
346 Each member added to an archive file has a directory prefix
347 prepended. Use -p/--prefix to specify a format string for the
347 prepended. Use -p/--prefix to specify a format string for the
348 prefix. The default is the basename of the archive, with suffixes
348 prefix. The default is the basename of the archive, with suffixes
349 removed.
349 removed.
350
350
351 Returns 0 on success.
351 Returns 0 on success.
352 '''
352 '''
353
353
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
355 if not ctx:
355 if not ctx:
356 raise util.Abort(_('no working directory: please specify a revision'))
356 raise util.Abort(_('no working directory: please specify a revision'))
357 node = ctx.node()
357 node = ctx.node()
358 dest = cmdutil.makefilename(repo, dest, node)
358 dest = cmdutil.makefilename(repo, dest, node)
359 if os.path.realpath(dest) == repo.root:
359 if os.path.realpath(dest) == repo.root:
360 raise util.Abort(_('repository root cannot be destination'))
360 raise util.Abort(_('repository root cannot be destination'))
361
361
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
363 prefix = opts.get('prefix')
363 prefix = opts.get('prefix')
364
364
365 if dest == '-':
365 if dest == '-':
366 if kind == 'files':
366 if kind == 'files':
367 raise util.Abort(_('cannot archive plain files to stdout'))
367 raise util.Abort(_('cannot archive plain files to stdout'))
368 dest = cmdutil.makefileobj(repo, dest)
368 dest = cmdutil.makefileobj(repo, dest)
369 if not prefix:
369 if not prefix:
370 prefix = os.path.basename(repo.root) + '-%h'
370 prefix = os.path.basename(repo.root) + '-%h'
371
371
372 prefix = cmdutil.makefilename(repo, prefix, node)
372 prefix = cmdutil.makefilename(repo, prefix, node)
373 matchfn = scmutil.match(ctx, [], opts)
373 matchfn = scmutil.match(ctx, [], opts)
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
375 matchfn, prefix, subrepos=opts.get('subrepos'))
375 matchfn, prefix, subrepos=opts.get('subrepos'))
376
376
377 @command('backout',
377 @command('backout',
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
379 ('', 'parent', '',
379 ('', 'parent', '',
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
383 _('[OPTION]... [-r] REV'))
383 _('[OPTION]... [-r] REV'))
384 def backout(ui, repo, node=None, rev=None, **opts):
384 def backout(ui, repo, node=None, rev=None, **opts):
385 '''reverse effect of earlier changeset
385 '''reverse effect of earlier changeset
386
386
387 Prepare a new changeset with the effect of REV undone in the
387 Prepare a new changeset with the effect of REV undone in the
388 current working directory.
388 current working directory.
389
389
390 If REV is the parent of the working directory, then this new changeset
390 If REV is the parent of the working directory, then this new changeset
391 is committed automatically. Otherwise, hg needs to merge the
391 is committed automatically. Otherwise, hg needs to merge the
392 changes and the merged result is left uncommitted.
392 changes and the merged result is left uncommitted.
393
393
394 .. note::
394 .. note::
395 backout cannot be used to fix either an unwanted or
395 backout cannot be used to fix either an unwanted or
396 incorrect merge.
396 incorrect merge.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 By default, the pending changeset will have one parent,
400 By default, the pending changeset will have one parent,
401 maintaining a linear history. With --merge, the pending
401 maintaining a linear history. With --merge, the pending
402 changeset will instead have two parents: the old parent of the
402 changeset will instead have two parents: the old parent of the
403 working directory and a new child of REV that simply undoes REV.
403 working directory and a new child of REV that simply undoes REV.
404
404
405 Before version 1.7, the behavior without --merge was equivalent
405 Before version 1.7, the behavior without --merge was equivalent
406 to specifying --merge followed by :hg:`update --clean .` to
406 to specifying --merge followed by :hg:`update --clean .` to
407 cancel the merge and leave the child of REV as a head to be
407 cancel the merge and leave the child of REV as a head to be
408 merged separately.
408 merged separately.
409
409
410 See :hg:`help dates` for a list of formats valid for -d/--date.
410 See :hg:`help dates` for a list of formats valid for -d/--date.
411
411
412 Returns 0 on success.
412 Returns 0 on success.
413 '''
413 '''
414 if rev and node:
414 if rev and node:
415 raise util.Abort(_("please specify just one revision"))
415 raise util.Abort(_("please specify just one revision"))
416
416
417 if not rev:
417 if not rev:
418 rev = node
418 rev = node
419
419
420 if not rev:
420 if not rev:
421 raise util.Abort(_("please specify a revision to backout"))
421 raise util.Abort(_("please specify a revision to backout"))
422
422
423 date = opts.get('date')
423 date = opts.get('date')
424 if date:
424 if date:
425 opts['date'] = util.parsedate(date)
425 opts['date'] = util.parsedate(date)
426
426
427 cmdutil.bailifchanged(repo)
427 cmdutil.bailifchanged(repo)
428 node = scmutil.revsingle(repo, rev).node()
428 node = scmutil.revsingle(repo, rev).node()
429
429
430 op1, op2 = repo.dirstate.parents()
430 op1, op2 = repo.dirstate.parents()
431 a = repo.changelog.ancestor(op1, node)
431 a = repo.changelog.ancestor(op1, node)
432 if a != node:
432 if a != node:
433 raise util.Abort(_('cannot backout change on a different branch'))
433 raise util.Abort(_('cannot backout change on a different branch'))
434
434
435 p1, p2 = repo.changelog.parents(node)
435 p1, p2 = repo.changelog.parents(node)
436 if p1 == nullid:
436 if p1 == nullid:
437 raise util.Abort(_('cannot backout a change with no parents'))
437 raise util.Abort(_('cannot backout a change with no parents'))
438 if p2 != nullid:
438 if p2 != nullid:
439 if not opts.get('parent'):
439 if not opts.get('parent'):
440 raise util.Abort(_('cannot backout a merge changeset'))
440 raise util.Abort(_('cannot backout a merge changeset'))
441 p = repo.lookup(opts['parent'])
441 p = repo.lookup(opts['parent'])
442 if p not in (p1, p2):
442 if p not in (p1, p2):
443 raise util.Abort(_('%s is not a parent of %s') %
443 raise util.Abort(_('%s is not a parent of %s') %
444 (short(p), short(node)))
444 (short(p), short(node)))
445 parent = p
445 parent = p
446 else:
446 else:
447 if opts.get('parent'):
447 if opts.get('parent'):
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
449 parent = p1
449 parent = p1
450
450
451 # the backout should appear on the same branch
451 # the backout should appear on the same branch
452 wlock = repo.wlock()
452 wlock = repo.wlock()
453 try:
453 try:
454 branch = repo.dirstate.branch()
454 branch = repo.dirstate.branch()
455 hg.clean(repo, node, show_stats=False)
455 hg.clean(repo, node, show_stats=False)
456 repo.dirstate.setbranch(branch)
456 repo.dirstate.setbranch(branch)
457 revert_opts = opts.copy()
457 revert_opts = opts.copy()
458 revert_opts['date'] = None
458 revert_opts['date'] = None
459 revert_opts['all'] = True
459 revert_opts['all'] = True
460 revert_opts['rev'] = hex(parent)
460 revert_opts['rev'] = hex(parent)
461 revert_opts['no_backup'] = None
461 revert_opts['no_backup'] = None
462 revert(ui, repo, **revert_opts)
462 revert(ui, repo, **revert_opts)
463 if not opts.get('merge') and op1 != node:
463 if not opts.get('merge') and op1 != node:
464 try:
464 try:
465 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
465 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 return hg.update(repo, op1)
466 return hg.update(repo, op1)
467 finally:
467 finally:
468 ui.setconfig('ui', 'forcemerge', '')
468 ui.setconfig('ui', 'forcemerge', '')
469
469
470 commit_opts = opts.copy()
470 commit_opts = opts.copy()
471 commit_opts['addremove'] = False
471 commit_opts['addremove'] = False
472 if not commit_opts['message'] and not commit_opts['logfile']:
472 if not commit_opts['message'] and not commit_opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 commit_opts['message'] = "Backed out changeset %s" % short(node)
474 commit_opts['message'] = "Backed out changeset %s" % short(node)
475 commit_opts['force_editor'] = True
475 commit_opts['force_editor'] = True
476 commit(ui, repo, **commit_opts)
476 commit(ui, repo, **commit_opts)
477 def nice(node):
477 def nice(node):
478 return '%d:%s' % (repo.changelog.rev(node), short(node))
478 return '%d:%s' % (repo.changelog.rev(node), short(node))
479 ui.status(_('changeset %s backs out changeset %s\n') %
479 ui.status(_('changeset %s backs out changeset %s\n') %
480 (nice(repo.changelog.tip()), nice(node)))
480 (nice(repo.changelog.tip()), nice(node)))
481 if opts.get('merge') and op1 != node:
481 if opts.get('merge') and op1 != node:
482 hg.clean(repo, op1, show_stats=False)
482 hg.clean(repo, op1, show_stats=False)
483 ui.status(_('merging with changeset %s\n')
483 ui.status(_('merging with changeset %s\n')
484 % nice(repo.changelog.tip()))
484 % nice(repo.changelog.tip()))
485 try:
485 try:
486 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
486 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
487 return hg.merge(repo, hex(repo.changelog.tip()))
487 return hg.merge(repo, hex(repo.changelog.tip()))
488 finally:
488 finally:
489 ui.setconfig('ui', 'forcemerge', '')
489 ui.setconfig('ui', 'forcemerge', '')
490 finally:
490 finally:
491 wlock.release()
491 wlock.release()
492 return 0
492 return 0
493
493
494 @command('bisect',
494 @command('bisect',
495 [('r', 'reset', False, _('reset bisect state')),
495 [('r', 'reset', False, _('reset bisect state')),
496 ('g', 'good', False, _('mark changeset good')),
496 ('g', 'good', False, _('mark changeset good')),
497 ('b', 'bad', False, _('mark changeset bad')),
497 ('b', 'bad', False, _('mark changeset bad')),
498 ('s', 'skip', False, _('skip testing changeset')),
498 ('s', 'skip', False, _('skip testing changeset')),
499 ('e', 'extend', False, _('extend the bisect range')),
499 ('e', 'extend', False, _('extend the bisect range')),
500 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
500 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
501 ('U', 'noupdate', False, _('do not update to target'))],
501 ('U', 'noupdate', False, _('do not update to target'))],
502 _("[-gbsr] [-U] [-c CMD] [REV]"))
502 _("[-gbsr] [-U] [-c CMD] [REV]"))
503 def bisect(ui, repo, rev=None, extra=None, command=None,
503 def bisect(ui, repo, rev=None, extra=None, command=None,
504 reset=None, good=None, bad=None, skip=None, extend=None,
504 reset=None, good=None, bad=None, skip=None, extend=None,
505 noupdate=None):
505 noupdate=None):
506 """subdivision search of changesets
506 """subdivision search of changesets
507
507
508 This command helps to find changesets which introduce problems. To
508 This command helps to find changesets which introduce problems. To
509 use, mark the earliest changeset you know exhibits the problem as
509 use, mark the earliest changeset you know exhibits the problem as
510 bad, then mark the latest changeset which is free from the problem
510 bad, then mark the latest changeset which is free from the problem
511 as good. Bisect will update your working directory to a revision
511 as good. Bisect will update your working directory to a revision
512 for testing (unless the -U/--noupdate option is specified). Once
512 for testing (unless the -U/--noupdate option is specified). Once
513 you have performed tests, mark the working directory as good or
513 you have performed tests, mark the working directory as good or
514 bad, and bisect will either update to another candidate changeset
514 bad, and bisect will either update to another candidate changeset
515 or announce that it has found the bad revision.
515 or announce that it has found the bad revision.
516
516
517 As a shortcut, you can also use the revision argument to mark a
517 As a shortcut, you can also use the revision argument to mark a
518 revision as good or bad without checking it out first.
518 revision as good or bad without checking it out first.
519
519
520 If you supply a command, it will be used for automatic bisection.
520 If you supply a command, it will be used for automatic bisection.
521 Its exit status will be used to mark revisions as good or bad:
521 Its exit status will be used to mark revisions as good or bad:
522 status 0 means good, 125 means to skip the revision, 127
522 status 0 means good, 125 means to skip the revision, 127
523 (command not found) will abort the bisection, and any other
523 (command not found) will abort the bisection, and any other
524 non-zero exit status means the revision is bad.
524 non-zero exit status means the revision is bad.
525
525
526 .. container:: verbose
526 .. container:: verbose
527
527
528 Some examples:
528 Some examples:
529
529
530 - start a bisection with known bad revision 12, and good revision 34::
530 - start a bisection with known bad revision 12, and good revision 34::
531
531
532 hg bisect --bad 34
532 hg bisect --bad 34
533 hg bisect --good 12
533 hg bisect --good 12
534
534
535 - advance the current bisection by marking current revision as good or
535 - advance the current bisection by marking current revision as good or
536 bad::
536 bad::
537
537
538 hg bisect --good
538 hg bisect --good
539 hg bisect --bad
539 hg bisect --bad
540
540
541 - mark the current revision, or a known revision, to be skipped (eg. if
541 - mark the current revision, or a known revision, to be skipped (eg. if
542 that revision is not usable because of another issue)::
542 that revision is not usable because of another issue)::
543
543
544 hg bisect --skip
544 hg bisect --skip
545 hg bisect --skip 23
545 hg bisect --skip 23
546
546
547 - forget the current bisection::
547 - forget the current bisection::
548
548
549 hg bisect --reset
549 hg bisect --reset
550
550
551 - use 'make && make tests' to automatically find the first broken
551 - use 'make && make tests' to automatically find the first broken
552 revision::
552 revision::
553
553
554 hg bisect --reset
554 hg bisect --reset
555 hg bisect --bad 34
555 hg bisect --bad 34
556 hg bisect --good 12
556 hg bisect --good 12
557 hg bisect --command 'make && make tests'
557 hg bisect --command 'make && make tests'
558
558
559 - see all changesets whose states are already known in the current
559 - see all changesets whose states are already known in the current
560 bisection::
560 bisection::
561
561
562 hg log -r "bisect(pruned)"
562 hg log -r "bisect(pruned)"
563
563
564 - see all changesets that took part in the current bisection::
564 - see all changesets that took part in the current bisection::
565
565
566 hg log -r "bisect(range)"
566 hg log -r "bisect(range)"
567
567
568 - with the graphlog extension, you can even get a nice graph::
568 - with the graphlog extension, you can even get a nice graph::
569
569
570 hg log --graph -r "bisect(range)"
570 hg log --graph -r "bisect(range)"
571
571
572 See :hg:`help revsets` for more about the `bisect()` keyword.
572 See :hg:`help revsets` for more about the `bisect()` keyword.
573
573
574 Returns 0 on success.
574 Returns 0 on success.
575 """
575 """
576 def extendbisectrange(nodes, good):
576 def extendbisectrange(nodes, good):
577 # bisect is incomplete when it ends on a merge node and
577 # bisect is incomplete when it ends on a merge node and
578 # one of the parent was not checked.
578 # one of the parent was not checked.
579 parents = repo[nodes[0]].parents()
579 parents = repo[nodes[0]].parents()
580 if len(parents) > 1:
580 if len(parents) > 1:
581 side = good and state['bad'] or state['good']
581 side = good and state['bad'] or state['good']
582 num = len(set(i.node() for i in parents) & set(side))
582 num = len(set(i.node() for i in parents) & set(side))
583 if num == 1:
583 if num == 1:
584 return parents[0].ancestor(parents[1])
584 return parents[0].ancestor(parents[1])
585 return None
585 return None
586
586
587 def print_result(nodes, good):
587 def print_result(nodes, good):
588 displayer = cmdutil.show_changeset(ui, repo, {})
588 displayer = cmdutil.show_changeset(ui, repo, {})
589 if len(nodes) == 1:
589 if len(nodes) == 1:
590 # narrowed it down to a single revision
590 # narrowed it down to a single revision
591 if good:
591 if good:
592 ui.write(_("The first good revision is:\n"))
592 ui.write(_("The first good revision is:\n"))
593 else:
593 else:
594 ui.write(_("The first bad revision is:\n"))
594 ui.write(_("The first bad revision is:\n"))
595 displayer.show(repo[nodes[0]])
595 displayer.show(repo[nodes[0]])
596 extendnode = extendbisectrange(nodes, good)
596 extendnode = extendbisectrange(nodes, good)
597 if extendnode is not None:
597 if extendnode is not None:
598 ui.write(_('Not all ancestors of this changeset have been'
598 ui.write(_('Not all ancestors of this changeset have been'
599 ' checked.\nUse bisect --extend to continue the '
599 ' checked.\nUse bisect --extend to continue the '
600 'bisection from\nthe common ancestor, %s.\n')
600 'bisection from\nthe common ancestor, %s.\n')
601 % extendnode)
601 % extendnode)
602 else:
602 else:
603 # multiple possible revisions
603 # multiple possible revisions
604 if good:
604 if good:
605 ui.write(_("Due to skipped revisions, the first "
605 ui.write(_("Due to skipped revisions, the first "
606 "good revision could be any of:\n"))
606 "good revision could be any of:\n"))
607 else:
607 else:
608 ui.write(_("Due to skipped revisions, the first "
608 ui.write(_("Due to skipped revisions, the first "
609 "bad revision could be any of:\n"))
609 "bad revision could be any of:\n"))
610 for n in nodes:
610 for n in nodes:
611 displayer.show(repo[n])
611 displayer.show(repo[n])
612 displayer.close()
612 displayer.close()
613
613
614 def check_state(state, interactive=True):
614 def check_state(state, interactive=True):
615 if not state['good'] or not state['bad']:
615 if not state['good'] or not state['bad']:
616 if (good or bad or skip or reset) and interactive:
616 if (good or bad or skip or reset) and interactive:
617 return
617 return
618 if not state['good']:
618 if not state['good']:
619 raise util.Abort(_('cannot bisect (no known good revisions)'))
619 raise util.Abort(_('cannot bisect (no known good revisions)'))
620 else:
620 else:
621 raise util.Abort(_('cannot bisect (no known bad revisions)'))
621 raise util.Abort(_('cannot bisect (no known bad revisions)'))
622 return True
622 return True
623
623
624 # backward compatibility
624 # backward compatibility
625 if rev in "good bad reset init".split():
625 if rev in "good bad reset init".split():
626 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
626 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
627 cmd, rev, extra = rev, extra, None
627 cmd, rev, extra = rev, extra, None
628 if cmd == "good":
628 if cmd == "good":
629 good = True
629 good = True
630 elif cmd == "bad":
630 elif cmd == "bad":
631 bad = True
631 bad = True
632 else:
632 else:
633 reset = True
633 reset = True
634 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
634 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
635 raise util.Abort(_('incompatible arguments'))
635 raise util.Abort(_('incompatible arguments'))
636
636
637 if reset:
637 if reset:
638 p = repo.join("bisect.state")
638 p = repo.join("bisect.state")
639 if os.path.exists(p):
639 if os.path.exists(p):
640 os.unlink(p)
640 os.unlink(p)
641 return
641 return
642
642
643 state = hbisect.load_state(repo)
643 state = hbisect.load_state(repo)
644
644
645 if command:
645 if command:
646 changesets = 1
646 changesets = 1
647 try:
647 try:
648 while changesets:
648 while changesets:
649 # update state
649 # update state
650 status = util.system(command, out=ui.fout)
650 status = util.system(command, out=ui.fout)
651 if status == 125:
651 if status == 125:
652 transition = "skip"
652 transition = "skip"
653 elif status == 0:
653 elif status == 0:
654 transition = "good"
654 transition = "good"
655 # status < 0 means process was killed
655 # status < 0 means process was killed
656 elif status == 127:
656 elif status == 127:
657 raise util.Abort(_("failed to execute %s") % command)
657 raise util.Abort(_("failed to execute %s") % command)
658 elif status < 0:
658 elif status < 0:
659 raise util.Abort(_("%s killed") % command)
659 raise util.Abort(_("%s killed") % command)
660 else:
660 else:
661 transition = "bad"
661 transition = "bad"
662 ctx = scmutil.revsingle(repo, rev)
662 ctx = scmutil.revsingle(repo, rev)
663 rev = None # clear for future iterations
663 rev = None # clear for future iterations
664 state[transition].append(ctx.node())
664 state[transition].append(ctx.node())
665 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
665 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
666 check_state(state, interactive=False)
666 check_state(state, interactive=False)
667 # bisect
667 # bisect
668 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
668 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
669 # update to next check
669 # update to next check
670 cmdutil.bailifchanged(repo)
670 cmdutil.bailifchanged(repo)
671 hg.clean(repo, nodes[0], show_stats=False)
671 hg.clean(repo, nodes[0], show_stats=False)
672 finally:
672 finally:
673 hbisect.save_state(repo, state)
673 hbisect.save_state(repo, state)
674 print_result(nodes, good)
674 print_result(nodes, good)
675 return
675 return
676
676
677 # update state
677 # update state
678
678
679 if rev:
679 if rev:
680 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
680 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
681 else:
681 else:
682 nodes = [repo.lookup('.')]
682 nodes = [repo.lookup('.')]
683
683
684 if good or bad or skip:
684 if good or bad or skip:
685 if good:
685 if good:
686 state['good'] += nodes
686 state['good'] += nodes
687 elif bad:
687 elif bad:
688 state['bad'] += nodes
688 state['bad'] += nodes
689 elif skip:
689 elif skip:
690 state['skip'] += nodes
690 state['skip'] += nodes
691 hbisect.save_state(repo, state)
691 hbisect.save_state(repo, state)
692
692
693 if not check_state(state):
693 if not check_state(state):
694 return
694 return
695
695
696 # actually bisect
696 # actually bisect
697 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
697 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 if extend:
698 if extend:
699 if not changesets:
699 if not changesets:
700 extendnode = extendbisectrange(nodes, good)
700 extendnode = extendbisectrange(nodes, good)
701 if extendnode is not None:
701 if extendnode is not None:
702 ui.write(_("Extending search to changeset %d:%s\n"
702 ui.write(_("Extending search to changeset %d:%s\n"
703 % (extendnode.rev(), extendnode)))
703 % (extendnode.rev(), extendnode)))
704 if noupdate:
704 if noupdate:
705 return
705 return
706 cmdutil.bailifchanged(repo)
706 cmdutil.bailifchanged(repo)
707 return hg.clean(repo, extendnode.node())
707 return hg.clean(repo, extendnode.node())
708 raise util.Abort(_("nothing to extend"))
708 raise util.Abort(_("nothing to extend"))
709
709
710 if changesets == 0:
710 if changesets == 0:
711 print_result(nodes, good)
711 print_result(nodes, good)
712 else:
712 else:
713 assert len(nodes) == 1 # only a single node can be tested next
713 assert len(nodes) == 1 # only a single node can be tested next
714 node = nodes[0]
714 node = nodes[0]
715 # compute the approximate number of remaining tests
715 # compute the approximate number of remaining tests
716 tests, size = 0, 2
716 tests, size = 0, 2
717 while size <= changesets:
717 while size <= changesets:
718 tests, size = tests + 1, size * 2
718 tests, size = tests + 1, size * 2
719 rev = repo.changelog.rev(node)
719 rev = repo.changelog.rev(node)
720 ui.write(_("Testing changeset %d:%s "
720 ui.write(_("Testing changeset %d:%s "
721 "(%d changesets remaining, ~%d tests)\n")
721 "(%d changesets remaining, ~%d tests)\n")
722 % (rev, short(node), changesets, tests))
722 % (rev, short(node), changesets, tests))
723 if not noupdate:
723 if not noupdate:
724 cmdutil.bailifchanged(repo)
724 cmdutil.bailifchanged(repo)
725 return hg.clean(repo, node)
725 return hg.clean(repo, node)
726
726
727 @command('bookmarks',
727 @command('bookmarks',
728 [('f', 'force', False, _('force')),
728 [('f', 'force', False, _('force')),
729 ('r', 'rev', '', _('revision'), _('REV')),
729 ('r', 'rev', '', _('revision'), _('REV')),
730 ('d', 'delete', False, _('delete a given bookmark')),
730 ('d', 'delete', False, _('delete a given bookmark')),
731 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
731 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
732 ('i', 'inactive', False, _('mark a bookmark inactive'))],
732 ('i', 'inactive', False, _('mark a bookmark inactive'))],
733 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
733 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
734 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
734 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
735 rename=None, inactive=False):
735 rename=None, inactive=False):
736 '''track a line of development with movable markers
736 '''track a line of development with movable markers
737
737
738 Bookmarks are pointers to certain commits that move when committing.
738 Bookmarks are pointers to certain commits that move when committing.
739 Bookmarks are local. They can be renamed, copied and deleted. It is
739 Bookmarks are local. They can be renamed, copied and deleted. It is
740 possible to use :hg:`merge NAME` to merge from a given bookmark, and
740 possible to use :hg:`merge NAME` to merge from a given bookmark, and
741 :hg:`update NAME` to update to a given bookmark.
741 :hg:`update NAME` to update to a given bookmark.
742
742
743 You can use :hg:`bookmark NAME` to set a bookmark on the working
743 You can use :hg:`bookmark NAME` to set a bookmark on the working
744 directory's parent revision with the given name. If you specify
744 directory's parent revision with the given name. If you specify
745 a revision using -r REV (where REV may be an existing bookmark),
745 a revision using -r REV (where REV may be an existing bookmark),
746 the bookmark is assigned to that revision.
746 the bookmark is assigned to that revision.
747
747
748 Bookmarks can be pushed and pulled between repositories (see :hg:`help
748 Bookmarks can be pushed and pulled between repositories (see :hg:`help
749 push` and :hg:`help pull`). This requires both the local and remote
749 push` and :hg:`help pull`). This requires both the local and remote
750 repositories to support bookmarks. For versions prior to 1.8, this means
750 repositories to support bookmarks. For versions prior to 1.8, this means
751 the bookmarks extension must be enabled.
751 the bookmarks extension must be enabled.
752
752
753 With -i/--inactive, the new bookmark will not be made the active
753 With -i/--inactive, the new bookmark will not be made the active
754 bookmark. If -r/--rev is given, the new bookmark will not be made
754 bookmark. If -r/--rev is given, the new bookmark will not be made
755 active even if -i/--inactive is not given. If no NAME is given, the
755 active even if -i/--inactive is not given. If no NAME is given, the
756 current active bookmark will be marked inactive.
756 current active bookmark will be marked inactive.
757 '''
757 '''
758 hexfn = ui.debugflag and hex or short
758 hexfn = ui.debugflag and hex or short
759 marks = repo._bookmarks
759 marks = repo._bookmarks
760 cur = repo.changectx('.').node()
760 cur = repo.changectx('.').node()
761
761
762 if delete:
762 if delete:
763 if mark is None:
763 if mark is None:
764 raise util.Abort(_("bookmark name required"))
764 raise util.Abort(_("bookmark name required"))
765 if mark not in marks:
765 if mark not in marks:
766 raise util.Abort(_("bookmark '%s' does not exist") % mark)
766 raise util.Abort(_("bookmark '%s' does not exist") % mark)
767 if mark == repo._bookmarkcurrent:
767 if mark == repo._bookmarkcurrent:
768 bookmarks.setcurrent(repo, None)
768 bookmarks.setcurrent(repo, None)
769 del marks[mark]
769 del marks[mark]
770 bookmarks.write(repo)
770 bookmarks.write(repo)
771 return
771 return
772
772
773 if rename:
773 if rename:
774 if rename not in marks:
774 if rename not in marks:
775 raise util.Abort(_("bookmark '%s' does not exist") % rename)
775 raise util.Abort(_("bookmark '%s' does not exist") % rename)
776 if mark in marks and not force:
776 if mark in marks and not force:
777 raise util.Abort(_("bookmark '%s' already exists "
777 raise util.Abort(_("bookmark '%s' already exists "
778 "(use -f to force)") % mark)
778 "(use -f to force)") % mark)
779 if mark is None:
779 if mark is None:
780 raise util.Abort(_("new bookmark name required"))
780 raise util.Abort(_("new bookmark name required"))
781 marks[mark] = marks[rename]
781 marks[mark] = marks[rename]
782 if repo._bookmarkcurrent == rename and not inactive:
782 if repo._bookmarkcurrent == rename and not inactive:
783 bookmarks.setcurrent(repo, mark)
783 bookmarks.setcurrent(repo, mark)
784 del marks[rename]
784 del marks[rename]
785 bookmarks.write(repo)
785 bookmarks.write(repo)
786 return
786 return
787
787
788 if mark is not None:
788 if mark is not None:
789 if "\n" in mark:
789 if "\n" in mark:
790 raise util.Abort(_("bookmark name cannot contain newlines"))
790 raise util.Abort(_("bookmark name cannot contain newlines"))
791 mark = mark.strip()
791 mark = mark.strip()
792 if not mark:
792 if not mark:
793 raise util.Abort(_("bookmark names cannot consist entirely of "
793 raise util.Abort(_("bookmark names cannot consist entirely of "
794 "whitespace"))
794 "whitespace"))
795 if inactive and mark == repo._bookmarkcurrent:
795 if inactive and mark == repo._bookmarkcurrent:
796 bookmarks.setcurrent(repo, None)
796 bookmarks.setcurrent(repo, None)
797 return
797 return
798 if mark in marks and not force:
798 if mark in marks and not force:
799 raise util.Abort(_("bookmark '%s' already exists "
799 raise util.Abort(_("bookmark '%s' already exists "
800 "(use -f to force)") % mark)
800 "(use -f to force)") % mark)
801 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
801 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
802 and not force):
802 and not force):
803 raise util.Abort(
803 raise util.Abort(
804 _("a bookmark cannot have the name of an existing branch"))
804 _("a bookmark cannot have the name of an existing branch"))
805 if rev:
805 if rev:
806 marks[mark] = repo.lookup(rev)
806 marks[mark] = repo.lookup(rev)
807 else:
807 else:
808 marks[mark] = cur
808 marks[mark] = cur
809 if not inactive and cur == marks[mark]:
809 if not inactive and cur == marks[mark]:
810 bookmarks.setcurrent(repo, mark)
810 bookmarks.setcurrent(repo, mark)
811 bookmarks.write(repo)
811 bookmarks.write(repo)
812 return
812 return
813
813
814 if mark is None:
814 if mark is None:
815 if rev:
815 if rev:
816 raise util.Abort(_("bookmark name required"))
816 raise util.Abort(_("bookmark name required"))
817 if len(marks) == 0:
817 if len(marks) == 0:
818 ui.status(_("no bookmarks set\n"))
818 ui.status(_("no bookmarks set\n"))
819 else:
819 else:
820 for bmark, n in sorted(marks.iteritems()):
820 for bmark, n in sorted(marks.iteritems()):
821 current = repo._bookmarkcurrent
821 current = repo._bookmarkcurrent
822 if bmark == current and n == cur:
822 if bmark == current and n == cur:
823 prefix, label = '*', 'bookmarks.current'
823 prefix, label = '*', 'bookmarks.current'
824 else:
824 else:
825 prefix, label = ' ', ''
825 prefix, label = ' ', ''
826
826
827 if ui.quiet:
827 if ui.quiet:
828 ui.write("%s\n" % bmark, label=label)
828 ui.write("%s\n" % bmark, label=label)
829 else:
829 else:
830 ui.write(" %s %-25s %d:%s\n" % (
830 ui.write(" %s %-25s %d:%s\n" % (
831 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
831 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
832 label=label)
832 label=label)
833 return
833 return
834
834
835 @command('branch',
835 @command('branch',
836 [('f', 'force', None,
836 [('f', 'force', None,
837 _('set branch name even if it shadows an existing branch')),
837 _('set branch name even if it shadows an existing branch')),
838 ('C', 'clean', None, _('reset branch name to parent branch name'))],
838 ('C', 'clean', None, _('reset branch name to parent branch name'))],
839 _('[-fC] [NAME]'))
839 _('[-fC] [NAME]'))
840 def branch(ui, repo, label=None, **opts):
840 def branch(ui, repo, label=None, **opts):
841 """set or show the current branch name
841 """set or show the current branch name
842
842
843 .. note::
843 .. note::
844 Branch names are permanent and global. Use :hg:`bookmark` to create a
844 Branch names are permanent and global. Use :hg:`bookmark` to create a
845 light-weight bookmark instead. See :hg:`help glossary` for more
845 light-weight bookmark instead. See :hg:`help glossary` for more
846 information about named branches and bookmarks.
846 information about named branches and bookmarks.
847
847
848 With no argument, show the current branch name. With one argument,
848 With no argument, show the current branch name. With one argument,
849 set the working directory branch name (the branch will not exist
849 set the working directory branch name (the branch will not exist
850 in the repository until the next commit). Standard practice
850 in the repository until the next commit). Standard practice
851 recommends that primary development take place on the 'default'
851 recommends that primary development take place on the 'default'
852 branch.
852 branch.
853
853
854 Unless -f/--force is specified, branch will not let you set a
854 Unless -f/--force is specified, branch will not let you set a
855 branch name that already exists, even if it's inactive.
855 branch name that already exists, even if it's inactive.
856
856
857 Use -C/--clean to reset the working directory branch to that of
857 Use -C/--clean to reset the working directory branch to that of
858 the parent of the working directory, negating a previous branch
858 the parent of the working directory, negating a previous branch
859 change.
859 change.
860
860
861 Use the command :hg:`update` to switch to an existing branch. Use
861 Use the command :hg:`update` to switch to an existing branch. Use
862 :hg:`commit --close-branch` to mark this branch as closed.
862 :hg:`commit --close-branch` to mark this branch as closed.
863
863
864 Returns 0 on success.
864 Returns 0 on success.
865 """
865 """
866 if not opts.get('clean') and not label:
866 if not opts.get('clean') and not label:
867 ui.write("%s\n" % repo.dirstate.branch())
867 ui.write("%s\n" % repo.dirstate.branch())
868 return
868 return
869
869
870 wlock = repo.wlock()
870 wlock = repo.wlock()
871 try:
871 try:
872 if opts.get('clean'):
872 if opts.get('clean'):
873 label = repo[None].p1().branch()
873 label = repo[None].p1().branch()
874 repo.dirstate.setbranch(label)
874 repo.dirstate.setbranch(label)
875 ui.status(_('reset working directory to branch %s\n') % label)
875 ui.status(_('reset working directory to branch %s\n') % label)
876 elif label:
876 elif label:
877 if not opts.get('force') and label in repo.branchtags():
877 if not opts.get('force') and label in repo.branchtags():
878 if label not in [p.branch() for p in repo.parents()]:
878 if label not in [p.branch() for p in repo.parents()]:
879 raise util.Abort(_('a branch of the same name already'
879 raise util.Abort(_('a branch of the same name already'
880 ' exists'),
880 ' exists'),
881 # i18n: "it" refers to an existing branch
881 # i18n: "it" refers to an existing branch
882 hint=_("use 'hg update' to switch to it"))
882 hint=_("use 'hg update' to switch to it"))
883 repo.dirstate.setbranch(label)
883 repo.dirstate.setbranch(label)
884 ui.status(_('marked working directory as branch %s\n') % label)
884 ui.status(_('marked working directory as branch %s\n') % label)
885 ui.status(_('(branches are permanent and global, '
885 ui.status(_('(branches are permanent and global, '
886 'did you want a bookmark?)\n'))
886 'did you want a bookmark?)\n'))
887 finally:
887 finally:
888 wlock.release()
888 wlock.release()
889
889
890 @command('branches',
890 @command('branches',
891 [('a', 'active', False, _('show only branches that have unmerged heads')),
891 [('a', 'active', False, _('show only branches that have unmerged heads')),
892 ('c', 'closed', False, _('show normal and closed branches'))],
892 ('c', 'closed', False, _('show normal and closed branches'))],
893 _('[-ac]'))
893 _('[-ac]'))
894 def branches(ui, repo, active=False, closed=False):
894 def branches(ui, repo, active=False, closed=False):
895 """list repository named branches
895 """list repository named branches
896
896
897 List the repository's named branches, indicating which ones are
897 List the repository's named branches, indicating which ones are
898 inactive. If -c/--closed is specified, also list branches which have
898 inactive. If -c/--closed is specified, also list branches which have
899 been marked closed (see :hg:`commit --close-branch`).
899 been marked closed (see :hg:`commit --close-branch`).
900
900
901 If -a/--active is specified, only show active branches. A branch
901 If -a/--active is specified, only show active branches. A branch
902 is considered active if it contains repository heads.
902 is considered active if it contains repository heads.
903
903
904 Use the command :hg:`update` to switch to an existing branch.
904 Use the command :hg:`update` to switch to an existing branch.
905
905
906 Returns 0.
906 Returns 0.
907 """
907 """
908
908
909 hexfunc = ui.debugflag and hex or short
909 hexfunc = ui.debugflag and hex or short
910 activebranches = [repo[n].branch() for n in repo.heads()]
910 activebranches = [repo[n].branch() for n in repo.heads()]
911 def testactive(tag, node):
911 def testactive(tag, node):
912 realhead = tag in activebranches
912 realhead = tag in activebranches
913 open = node in repo.branchheads(tag, closed=False)
913 open = node in repo.branchheads(tag, closed=False)
914 return realhead and open
914 return realhead and open
915 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
915 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
916 for tag, node in repo.branchtags().items()],
916 for tag, node in repo.branchtags().items()],
917 reverse=True)
917 reverse=True)
918
918
919 for isactive, node, tag in branches:
919 for isactive, node, tag in branches:
920 if (not active) or isactive:
920 if (not active) or isactive:
921 if ui.quiet:
921 if ui.quiet:
922 ui.write("%s\n" % tag)
922 ui.write("%s\n" % tag)
923 else:
923 else:
924 hn = repo.lookup(node)
924 hn = repo.lookup(node)
925 if isactive:
925 if isactive:
926 label = 'branches.active'
926 label = 'branches.active'
927 notice = ''
927 notice = ''
928 elif hn not in repo.branchheads(tag, closed=False):
928 elif hn not in repo.branchheads(tag, closed=False):
929 if not closed:
929 if not closed:
930 continue
930 continue
931 label = 'branches.closed'
931 label = 'branches.closed'
932 notice = _(' (closed)')
932 notice = _(' (closed)')
933 else:
933 else:
934 label = 'branches.inactive'
934 label = 'branches.inactive'
935 notice = _(' (inactive)')
935 notice = _(' (inactive)')
936 if tag == repo.dirstate.branch():
936 if tag == repo.dirstate.branch():
937 label = 'branches.current'
937 label = 'branches.current'
938 rev = str(node).rjust(31 - encoding.colwidth(tag))
938 rev = str(node).rjust(31 - encoding.colwidth(tag))
939 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
939 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
940 tag = ui.label(tag, label)
940 tag = ui.label(tag, label)
941 ui.write("%s %s%s\n" % (tag, rev, notice))
941 ui.write("%s %s%s\n" % (tag, rev, notice))
942
942
943 @command('bundle',
943 @command('bundle',
944 [('f', 'force', None, _('run even when the destination is unrelated')),
944 [('f', 'force', None, _('run even when the destination is unrelated')),
945 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
945 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
946 _('REV')),
946 _('REV')),
947 ('b', 'branch', [], _('a specific branch you would like to bundle'),
947 ('b', 'branch', [], _('a specific branch you would like to bundle'),
948 _('BRANCH')),
948 _('BRANCH')),
949 ('', 'base', [],
949 ('', 'base', [],
950 _('a base changeset assumed to be available at the destination'),
950 _('a base changeset assumed to be available at the destination'),
951 _('REV')),
951 _('REV')),
952 ('a', 'all', None, _('bundle all changesets in the repository')),
952 ('a', 'all', None, _('bundle all changesets in the repository')),
953 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
953 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
954 ] + remoteopts,
954 ] + remoteopts,
955 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
955 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
956 def bundle(ui, repo, fname, dest=None, **opts):
956 def bundle(ui, repo, fname, dest=None, **opts):
957 """create a changegroup file
957 """create a changegroup file
958
958
959 Generate a compressed changegroup file collecting changesets not
959 Generate a compressed changegroup file collecting changesets not
960 known to be in another repository.
960 known to be in another repository.
961
961
962 If you omit the destination repository, then hg assumes the
962 If you omit the destination repository, then hg assumes the
963 destination will have all the nodes you specify with --base
963 destination will have all the nodes you specify with --base
964 parameters. To create a bundle containing all changesets, use
964 parameters. To create a bundle containing all changesets, use
965 -a/--all (or --base null).
965 -a/--all (or --base null).
966
966
967 You can change compression method with the -t/--type option.
967 You can change compression method with the -t/--type option.
968 The available compression methods are: none, bzip2, and
968 The available compression methods are: none, bzip2, and
969 gzip (by default, bundles are compressed using bzip2).
969 gzip (by default, bundles are compressed using bzip2).
970
970
971 The bundle file can then be transferred using conventional means
971 The bundle file can then be transferred using conventional means
972 and applied to another repository with the unbundle or pull
972 and applied to another repository with the unbundle or pull
973 command. This is useful when direct push and pull are not
973 command. This is useful when direct push and pull are not
974 available or when exporting an entire repository is undesirable.
974 available or when exporting an entire repository is undesirable.
975
975
976 Applying bundles preserves all changeset contents including
976 Applying bundles preserves all changeset contents including
977 permissions, copy/rename information, and revision history.
977 permissions, copy/rename information, and revision history.
978
978
979 Returns 0 on success, 1 if no changes found.
979 Returns 0 on success, 1 if no changes found.
980 """
980 """
981 revs = None
981 revs = None
982 if 'rev' in opts:
982 if 'rev' in opts:
983 revs = scmutil.revrange(repo, opts['rev'])
983 revs = scmutil.revrange(repo, opts['rev'])
984
984
985 bundletype = opts.get('type', 'bzip2').lower()
985 bundletype = opts.get('type', 'bzip2').lower()
986 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
986 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
987 bundletype = btypes.get(bundletype)
987 bundletype = btypes.get(bundletype)
988 if bundletype not in changegroup.bundletypes:
988 if bundletype not in changegroup.bundletypes:
989 raise util.Abort(_('unknown bundle type specified with --type'))
989 raise util.Abort(_('unknown bundle type specified with --type'))
990
990
991 if opts.get('all'):
991 if opts.get('all'):
992 base = ['null']
992 base = ['null']
993 else:
993 else:
994 base = scmutil.revrange(repo, opts.get('base'))
994 base = scmutil.revrange(repo, opts.get('base'))
995 if base:
995 if base:
996 if dest:
996 if dest:
997 raise util.Abort(_("--base is incompatible with specifying "
997 raise util.Abort(_("--base is incompatible with specifying "
998 "a destination"))
998 "a destination"))
999 common = [repo.lookup(rev) for rev in base]
999 common = [repo.lookup(rev) for rev in base]
1000 heads = revs and map(repo.lookup, revs) or revs
1000 heads = revs and map(repo.lookup, revs) or revs
1001 cg = repo.getbundle('bundle', heads=heads, common=common)
1001 cg = repo.getbundle('bundle', heads=heads, common=common)
1002 outgoing = None
1002 outgoing = None
1003 else:
1003 else:
1004 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1004 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1005 dest, branches = hg.parseurl(dest, opts.get('branch'))
1005 dest, branches = hg.parseurl(dest, opts.get('branch'))
1006 other = hg.peer(repo, opts, dest)
1006 other = hg.peer(repo, opts, dest)
1007 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1007 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1008 heads = revs and map(repo.lookup, revs) or revs
1008 heads = revs and map(repo.lookup, revs) or revs
1009 outgoing = discovery.findcommonoutgoing(repo, other,
1009 outgoing = discovery.findcommonoutgoing(repo, other,
1010 onlyheads=heads,
1010 onlyheads=heads,
1011 force=opts.get('force'))
1011 force=opts.get('force'))
1012 cg = repo.getlocalbundle('bundle', outgoing)
1012 cg = repo.getlocalbundle('bundle', outgoing)
1013 if not cg:
1013 if not cg:
1014 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1014 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1015 return 1
1015 return 1
1016
1016
1017 changegroup.writebundle(cg, fname, bundletype)
1017 changegroup.writebundle(cg, fname, bundletype)
1018
1018
1019 @command('cat',
1019 @command('cat',
1020 [('o', 'output', '',
1020 [('o', 'output', '',
1021 _('print output to file with formatted name'), _('FORMAT')),
1021 _('print output to file with formatted name'), _('FORMAT')),
1022 ('r', 'rev', '', _('print the given revision'), _('REV')),
1022 ('r', 'rev', '', _('print the given revision'), _('REV')),
1023 ('', 'decode', None, _('apply any matching decode filter')),
1023 ('', 'decode', None, _('apply any matching decode filter')),
1024 ] + walkopts,
1024 ] + walkopts,
1025 _('[OPTION]... FILE...'))
1025 _('[OPTION]... FILE...'))
1026 def cat(ui, repo, file1, *pats, **opts):
1026 def cat(ui, repo, file1, *pats, **opts):
1027 """output the current or given revision of files
1027 """output the current or given revision of files
1028
1028
1029 Print the specified files as they were at the given revision. If
1029 Print the specified files as they were at the given revision. If
1030 no revision is given, the parent of the working directory is used,
1030 no revision is given, the parent of the working directory is used,
1031 or tip if no revision is checked out.
1031 or tip if no revision is checked out.
1032
1032
1033 Output may be to a file, in which case the name of the file is
1033 Output may be to a file, in which case the name of the file is
1034 given using a format string. The formatting rules are the same as
1034 given using a format string. The formatting rules are the same as
1035 for the export command, with the following additions:
1035 for the export command, with the following additions:
1036
1036
1037 :``%s``: basename of file being printed
1037 :``%s``: basename of file being printed
1038 :``%d``: dirname of file being printed, or '.' if in repository root
1038 :``%d``: dirname of file being printed, or '.' if in repository root
1039 :``%p``: root-relative path name of file being printed
1039 :``%p``: root-relative path name of file being printed
1040
1040
1041 Returns 0 on success.
1041 Returns 0 on success.
1042 """
1042 """
1043 ctx = scmutil.revsingle(repo, opts.get('rev'))
1043 ctx = scmutil.revsingle(repo, opts.get('rev'))
1044 err = 1
1044 err = 1
1045 m = scmutil.match(ctx, (file1,) + pats, opts)
1045 m = scmutil.match(ctx, (file1,) + pats, opts)
1046 for abs in ctx.walk(m):
1046 for abs in ctx.walk(m):
1047 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1047 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1048 pathname=abs)
1048 pathname=abs)
1049 data = ctx[abs].data()
1049 data = ctx[abs].data()
1050 if opts.get('decode'):
1050 if opts.get('decode'):
1051 data = repo.wwritedata(abs, data)
1051 data = repo.wwritedata(abs, data)
1052 fp.write(data)
1052 fp.write(data)
1053 fp.close()
1053 fp.close()
1054 err = 0
1054 err = 0
1055 return err
1055 return err
1056
1056
1057 @command('^clone',
1057 @command('^clone',
1058 [('U', 'noupdate', None,
1058 [('U', 'noupdate', None,
1059 _('the clone will include an empty working copy (only a repository)')),
1059 _('the clone will include an empty working copy (only a repository)')),
1060 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1060 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1061 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1061 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1062 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1062 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1063 ('', 'pull', None, _('use pull protocol to copy metadata')),
1063 ('', 'pull', None, _('use pull protocol to copy metadata')),
1064 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1064 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1065 ] + remoteopts,
1065 ] + remoteopts,
1066 _('[OPTION]... SOURCE [DEST]'))
1066 _('[OPTION]... SOURCE [DEST]'))
1067 def clone(ui, source, dest=None, **opts):
1067 def clone(ui, source, dest=None, **opts):
1068 """make a copy of an existing repository
1068 """make a copy of an existing repository
1069
1069
1070 Create a copy of an existing repository in a new directory.
1070 Create a copy of an existing repository in a new directory.
1071
1071
1072 If no destination directory name is specified, it defaults to the
1072 If no destination directory name is specified, it defaults to the
1073 basename of the source.
1073 basename of the source.
1074
1074
1075 The location of the source is added to the new repository's
1075 The location of the source is added to the new repository's
1076 ``.hg/hgrc`` file, as the default to be used for future pulls.
1076 ``.hg/hgrc`` file, as the default to be used for future pulls.
1077
1077
1078 Only local paths and ``ssh://`` URLs are supported as
1078 Only local paths and ``ssh://`` URLs are supported as
1079 destinations. For ``ssh://`` destinations, no working directory or
1079 destinations. For ``ssh://`` destinations, no working directory or
1080 ``.hg/hgrc`` will be created on the remote side.
1080 ``.hg/hgrc`` will be created on the remote side.
1081
1081
1082 To pull only a subset of changesets, specify one or more revisions
1082 To pull only a subset of changesets, specify one or more revisions
1083 identifiers with -r/--rev or branches with -b/--branch. The
1083 identifiers with -r/--rev or branches with -b/--branch. The
1084 resulting clone will contain only the specified changesets and
1084 resulting clone will contain only the specified changesets and
1085 their ancestors. These options (or 'clone src#rev dest') imply
1085 their ancestors. These options (or 'clone src#rev dest') imply
1086 --pull, even for local source repositories. Note that specifying a
1086 --pull, even for local source repositories. Note that specifying a
1087 tag will include the tagged changeset but not the changeset
1087 tag will include the tagged changeset but not the changeset
1088 containing the tag.
1088 containing the tag.
1089
1089
1090 To check out a particular version, use -u/--update, or
1090 To check out a particular version, use -u/--update, or
1091 -U/--noupdate to create a clone with no working directory.
1091 -U/--noupdate to create a clone with no working directory.
1092
1092
1093 .. container:: verbose
1093 .. container:: verbose
1094
1094
1095 For efficiency, hardlinks are used for cloning whenever the
1095 For efficiency, hardlinks are used for cloning whenever the
1096 source and destination are on the same filesystem (note this
1096 source and destination are on the same filesystem (note this
1097 applies only to the repository data, not to the working
1097 applies only to the repository data, not to the working
1098 directory). Some filesystems, such as AFS, implement hardlinking
1098 directory). Some filesystems, such as AFS, implement hardlinking
1099 incorrectly, but do not report errors. In these cases, use the
1099 incorrectly, but do not report errors. In these cases, use the
1100 --pull option to avoid hardlinking.
1100 --pull option to avoid hardlinking.
1101
1101
1102 In some cases, you can clone repositories and the working
1102 In some cases, you can clone repositories and the working
1103 directory using full hardlinks with ::
1103 directory using full hardlinks with ::
1104
1104
1105 $ cp -al REPO REPOCLONE
1105 $ cp -al REPO REPOCLONE
1106
1106
1107 This is the fastest way to clone, but it is not always safe. The
1107 This is the fastest way to clone, but it is not always safe. The
1108 operation is not atomic (making sure REPO is not modified during
1108 operation is not atomic (making sure REPO is not modified during
1109 the operation is up to you) and you have to make sure your
1109 the operation is up to you) and you have to make sure your
1110 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1110 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1111 so). Also, this is not compatible with certain extensions that
1111 so). Also, this is not compatible with certain extensions that
1112 place their metadata under the .hg directory, such as mq.
1112 place their metadata under the .hg directory, such as mq.
1113
1113
1114 Mercurial will update the working directory to the first applicable
1114 Mercurial will update the working directory to the first applicable
1115 revision from this list:
1115 revision from this list:
1116
1116
1117 a) null if -U or the source repository has no changesets
1117 a) null if -U or the source repository has no changesets
1118 b) if -u . and the source repository is local, the first parent of
1118 b) if -u . and the source repository is local, the first parent of
1119 the source repository's working directory
1119 the source repository's working directory
1120 c) the changeset specified with -u (if a branch name, this means the
1120 c) the changeset specified with -u (if a branch name, this means the
1121 latest head of that branch)
1121 latest head of that branch)
1122 d) the changeset specified with -r
1122 d) the changeset specified with -r
1123 e) the tipmost head specified with -b
1123 e) the tipmost head specified with -b
1124 f) the tipmost head specified with the url#branch source syntax
1124 f) the tipmost head specified with the url#branch source syntax
1125 g) the tipmost head of the default branch
1125 g) the tipmost head of the default branch
1126 h) tip
1126 h) tip
1127
1127
1128 Examples:
1128 Examples:
1129
1129
1130 - clone a remote repository to a new directory named hg/::
1130 - clone a remote repository to a new directory named hg/::
1131
1131
1132 hg clone http://selenic.com/hg
1132 hg clone http://selenic.com/hg
1133
1133
1134 - create a lightweight local clone::
1134 - create a lightweight local clone::
1135
1135
1136 hg clone project/ project-feature/
1136 hg clone project/ project-feature/
1137
1137
1138 - clone from an absolute path on an ssh server (note double-slash)::
1138 - clone from an absolute path on an ssh server (note double-slash)::
1139
1139
1140 hg clone ssh://user@server//home/projects/alpha/
1140 hg clone ssh://user@server//home/projects/alpha/
1141
1141
1142 - do a high-speed clone over a LAN while checking out a
1142 - do a high-speed clone over a LAN while checking out a
1143 specified version::
1143 specified version::
1144
1144
1145 hg clone --uncompressed http://server/repo -u 1.5
1145 hg clone --uncompressed http://server/repo -u 1.5
1146
1146
1147 - create a repository without changesets after a particular revision::
1147 - create a repository without changesets after a particular revision::
1148
1148
1149 hg clone -r 04e544 experimental/ good/
1149 hg clone -r 04e544 experimental/ good/
1150
1150
1151 - clone (and track) a particular named branch::
1151 - clone (and track) a particular named branch::
1152
1152
1153 hg clone http://selenic.com/hg#stable
1153 hg clone http://selenic.com/hg#stable
1154
1154
1155 See :hg:`help urls` for details on specifying URLs.
1155 See :hg:`help urls` for details on specifying URLs.
1156
1156
1157 Returns 0 on success.
1157 Returns 0 on success.
1158 """
1158 """
1159 if opts.get('noupdate') and opts.get('updaterev'):
1159 if opts.get('noupdate') and opts.get('updaterev'):
1160 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1160 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1161
1161
1162 r = hg.clone(ui, opts, source, dest,
1162 r = hg.clone(ui, opts, source, dest,
1163 pull=opts.get('pull'),
1163 pull=opts.get('pull'),
1164 stream=opts.get('uncompressed'),
1164 stream=opts.get('uncompressed'),
1165 rev=opts.get('rev'),
1165 rev=opts.get('rev'),
1166 update=opts.get('updaterev') or not opts.get('noupdate'),
1166 update=opts.get('updaterev') or not opts.get('noupdate'),
1167 branch=opts.get('branch'))
1167 branch=opts.get('branch'))
1168
1168
1169 return r is None
1169 return r is None
1170
1170
1171 @command('^commit|ci',
1171 @command('^commit|ci',
1172 [('A', 'addremove', None,
1172 [('A', 'addremove', None,
1173 _('mark new/missing files as added/removed before committing')),
1173 _('mark new/missing files as added/removed before committing')),
1174 ('', 'close-branch', None,
1174 ('', 'close-branch', None,
1175 _('mark a branch as closed, hiding it from the branch list')),
1175 _('mark a branch as closed, hiding it from the branch list')),
1176 ('', 'amend', None, _('amend the parent of the working dir')),
1176 ('', 'amend', None, _('amend the parent of the working dir')),
1177 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1177 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1178 _('[OPTION]... [FILE]...'))
1178 _('[OPTION]... [FILE]...'))
1179 def commit(ui, repo, *pats, **opts):
1179 def commit(ui, repo, *pats, **opts):
1180 """commit the specified files or all outstanding changes
1180 """commit the specified files or all outstanding changes
1181
1181
1182 Commit changes to the given files into the repository. Unlike a
1182 Commit changes to the given files into the repository. Unlike a
1183 centralized SCM, this operation is a local operation. See
1183 centralized SCM, this operation is a local operation. See
1184 :hg:`push` for a way to actively distribute your changes.
1184 :hg:`push` for a way to actively distribute your changes.
1185
1185
1186 If a list of files is omitted, all changes reported by :hg:`status`
1186 If a list of files is omitted, all changes reported by :hg:`status`
1187 will be committed.
1187 will be committed.
1188
1188
1189 If you are committing the result of a merge, do not provide any
1189 If you are committing the result of a merge, do not provide any
1190 filenames or -I/-X filters.
1190 filenames or -I/-X filters.
1191
1191
1192 If no commit message is specified, Mercurial starts your
1192 If no commit message is specified, Mercurial starts your
1193 configured editor where you can enter a message. In case your
1193 configured editor where you can enter a message. In case your
1194 commit fails, you will find a backup of your message in
1194 commit fails, you will find a backup of your message in
1195 ``.hg/last-message.txt``.
1195 ``.hg/last-message.txt``.
1196
1196
1197 The --amend flag can be used to amend the parent of the
1197 The --amend flag can be used to amend the parent of the
1198 working directory with a new commit that contains the changes
1198 working directory with a new commit that contains the changes
1199 in the parent in addition to those currently reported by :hg:`status`,
1199 in the parent in addition to those currently reported by :hg:`status`,
1200 if there are any. The old commit is stored in a backup bundle in
1200 if there are any. The old commit is stored in a backup bundle in
1201 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1201 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1202 on how to restore it).
1202 on how to restore it).
1203
1203
1204 Message, user and date are taken from the amended commit unless
1204 Message, user and date are taken from the amended commit unless
1205 specified. When a message isn't specified on the command line,
1205 specified. When a message isn't specified on the command line,
1206 the editor will open with the message of the amended commit.
1206 the editor will open with the message of the amended commit.
1207
1207
1208 It is not possible to amend public changesets (see :hg:`help phases`)
1208 It is not possible to amend public changesets (see :hg:`help phases`)
1209 or changesets that have children.
1209 or changesets that have children.
1210
1210
1211 See :hg:`help dates` for a list of formats valid for -d/--date.
1211 See :hg:`help dates` for a list of formats valid for -d/--date.
1212
1212
1213 Returns 0 on success, 1 if nothing changed.
1213 Returns 0 on success, 1 if nothing changed.
1214 """
1214 """
1215 if opts.get('subrepos'):
1215 if opts.get('subrepos'):
1216 # Let --subrepos on the command line overide config setting.
1216 # Let --subrepos on the command line overide config setting.
1217 ui.setconfig('ui', 'commitsubrepos', True)
1217 ui.setconfig('ui', 'commitsubrepos', True)
1218
1218
1219 extra = {}
1219 extra = {}
1220 if opts.get('close_branch'):
1220 if opts.get('close_branch'):
1221 if repo['.'].node() not in repo.branchheads():
1221 if repo['.'].node() not in repo.branchheads():
1222 # The topo heads set is included in the branch heads set of the
1222 # The topo heads set is included in the branch heads set of the
1223 # current branch, so it's sufficient to test branchheads
1223 # current branch, so it's sufficient to test branchheads
1224 raise util.Abort(_('can only close branch heads'))
1224 raise util.Abort(_('can only close branch heads'))
1225 extra['close'] = 1
1225 extra['close'] = 1
1226
1226
1227 branch = repo[None].branch()
1227 branch = repo[None].branch()
1228 bheads = repo.branchheads(branch)
1228 bheads = repo.branchheads(branch)
1229
1229
1230 if opts.get('amend'):
1230 if opts.get('amend'):
1231 if ui.config('ui', 'commitsubrepos'):
1231 if ui.configbool('ui', 'commitsubrepos'):
1232 raise util.Abort(_('cannot amend recursively'))
1232 raise util.Abort(_('cannot amend recursively'))
1233
1233
1234 old = repo['.']
1234 old = repo['.']
1235 if old.phase() == phases.public:
1235 if old.phase() == phases.public:
1236 raise util.Abort(_('cannot amend public changesets'))
1236 raise util.Abort(_('cannot amend public changesets'))
1237 if len(old.parents()) > 1:
1237 if len(old.parents()) > 1:
1238 raise util.Abort(_('cannot amend merge changesets'))
1238 raise util.Abort(_('cannot amend merge changesets'))
1239 if len(repo[None].parents()) > 1:
1239 if len(repo[None].parents()) > 1:
1240 raise util.Abort(_('cannot amend while merging'))
1240 raise util.Abort(_('cannot amend while merging'))
1241 if old.children():
1241 if old.children():
1242 raise util.Abort(_('cannot amend changeset with children'))
1242 raise util.Abort(_('cannot amend changeset with children'))
1243
1243
1244 e = cmdutil.commiteditor
1244 e = cmdutil.commiteditor
1245 if opts.get('force_editor'):
1245 if opts.get('force_editor'):
1246 e = cmdutil.commitforceeditor
1246 e = cmdutil.commitforceeditor
1247
1247
1248 def commitfunc(ui, repo, message, match, opts):
1248 def commitfunc(ui, repo, message, match, opts):
1249 editor = e
1249 editor = e
1250 # message contains text from -m or -l, if it's empty,
1250 # message contains text from -m or -l, if it's empty,
1251 # open the editor with the old message
1251 # open the editor with the old message
1252 if not message:
1252 if not message:
1253 message = old.description()
1253 message = old.description()
1254 editor = cmdutil.commitforceeditor
1254 editor = cmdutil.commitforceeditor
1255 return repo.commit(message,
1255 return repo.commit(message,
1256 opts.get('user') or old.user(),
1256 opts.get('user') or old.user(),
1257 opts.get('date') or old.date(),
1257 opts.get('date') or old.date(),
1258 match,
1258 match,
1259 editor=editor,
1259 editor=editor,
1260 extra=extra)
1260 extra=extra)
1261
1261
1262 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1262 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1263 if node == old.node():
1263 if node == old.node():
1264 ui.status(_("nothing changed\n"))
1264 ui.status(_("nothing changed\n"))
1265 return 1
1265 return 1
1266 else:
1266 else:
1267 e = cmdutil.commiteditor
1267 e = cmdutil.commiteditor
1268 if opts.get('force_editor'):
1268 if opts.get('force_editor'):
1269 e = cmdutil.commitforceeditor
1269 e = cmdutil.commitforceeditor
1270
1270
1271 def commitfunc(ui, repo, message, match, opts):
1271 def commitfunc(ui, repo, message, match, opts):
1272 return repo.commit(message, opts.get('user'), opts.get('date'),
1272 return repo.commit(message, opts.get('user'), opts.get('date'),
1273 match, editor=e, extra=extra)
1273 match, editor=e, extra=extra)
1274
1274
1275 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1275 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1276
1276
1277 if not node:
1277 if not node:
1278 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1278 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1279 if stat[3]:
1279 if stat[3]:
1280 ui.status(_("nothing changed (%d missing files, see "
1280 ui.status(_("nothing changed (%d missing files, see "
1281 "'hg status')\n") % len(stat[3]))
1281 "'hg status')\n") % len(stat[3]))
1282 else:
1282 else:
1283 ui.status(_("nothing changed\n"))
1283 ui.status(_("nothing changed\n"))
1284 return 1
1284 return 1
1285
1285
1286 ctx = repo[node]
1286 ctx = repo[node]
1287 parents = ctx.parents()
1287 parents = ctx.parents()
1288
1288
1289 if (not opts.get('amend') and bheads and node not in bheads and not
1289 if (not opts.get('amend') and bheads and node not in bheads and not
1290 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1290 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1291 ui.status(_('created new head\n'))
1291 ui.status(_('created new head\n'))
1292 # The message is not printed for initial roots. For the other
1292 # The message is not printed for initial roots. For the other
1293 # changesets, it is printed in the following situations:
1293 # changesets, it is printed in the following situations:
1294 #
1294 #
1295 # Par column: for the 2 parents with ...
1295 # Par column: for the 2 parents with ...
1296 # N: null or no parent
1296 # N: null or no parent
1297 # B: parent is on another named branch
1297 # B: parent is on another named branch
1298 # C: parent is a regular non head changeset
1298 # C: parent is a regular non head changeset
1299 # H: parent was a branch head of the current branch
1299 # H: parent was a branch head of the current branch
1300 # Msg column: whether we print "created new head" message
1300 # Msg column: whether we print "created new head" message
1301 # In the following, it is assumed that there already exists some
1301 # In the following, it is assumed that there already exists some
1302 # initial branch heads of the current branch, otherwise nothing is
1302 # initial branch heads of the current branch, otherwise nothing is
1303 # printed anyway.
1303 # printed anyway.
1304 #
1304 #
1305 # Par Msg Comment
1305 # Par Msg Comment
1306 # NN y additional topo root
1306 # NN y additional topo root
1307 #
1307 #
1308 # BN y additional branch root
1308 # BN y additional branch root
1309 # CN y additional topo head
1309 # CN y additional topo head
1310 # HN n usual case
1310 # HN n usual case
1311 #
1311 #
1312 # BB y weird additional branch root
1312 # BB y weird additional branch root
1313 # CB y branch merge
1313 # CB y branch merge
1314 # HB n merge with named branch
1314 # HB n merge with named branch
1315 #
1315 #
1316 # CC y additional head from merge
1316 # CC y additional head from merge
1317 # CH n merge with a head
1317 # CH n merge with a head
1318 #
1318 #
1319 # HH n head merge: head count decreases
1319 # HH n head merge: head count decreases
1320
1320
1321 if not opts.get('close_branch'):
1321 if not opts.get('close_branch'):
1322 for r in parents:
1322 for r in parents:
1323 if r.extra().get('close') and r.branch() == branch:
1323 if r.extra().get('close') and r.branch() == branch:
1324 ui.status(_('reopening closed branch head %d\n') % r)
1324 ui.status(_('reopening closed branch head %d\n') % r)
1325
1325
1326 if ui.debugflag:
1326 if ui.debugflag:
1327 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1327 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1328 elif ui.verbose:
1328 elif ui.verbose:
1329 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1329 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1330
1330
1331 @command('copy|cp',
1331 @command('copy|cp',
1332 [('A', 'after', None, _('record a copy that has already occurred')),
1332 [('A', 'after', None, _('record a copy that has already occurred')),
1333 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1333 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1334 ] + walkopts + dryrunopts,
1334 ] + walkopts + dryrunopts,
1335 _('[OPTION]... [SOURCE]... DEST'))
1335 _('[OPTION]... [SOURCE]... DEST'))
1336 def copy(ui, repo, *pats, **opts):
1336 def copy(ui, repo, *pats, **opts):
1337 """mark files as copied for the next commit
1337 """mark files as copied for the next commit
1338
1338
1339 Mark dest as having copies of source files. If dest is a
1339 Mark dest as having copies of source files. If dest is a
1340 directory, copies are put in that directory. If dest is a file,
1340 directory, copies are put in that directory. If dest is a file,
1341 the source must be a single file.
1341 the source must be a single file.
1342
1342
1343 By default, this command copies the contents of files as they
1343 By default, this command copies the contents of files as they
1344 exist in the working directory. If invoked with -A/--after, the
1344 exist in the working directory. If invoked with -A/--after, the
1345 operation is recorded, but no copying is performed.
1345 operation is recorded, but no copying is performed.
1346
1346
1347 This command takes effect with the next commit. To undo a copy
1347 This command takes effect with the next commit. To undo a copy
1348 before that, see :hg:`revert`.
1348 before that, see :hg:`revert`.
1349
1349
1350 Returns 0 on success, 1 if errors are encountered.
1350 Returns 0 on success, 1 if errors are encountered.
1351 """
1351 """
1352 wlock = repo.wlock(False)
1352 wlock = repo.wlock(False)
1353 try:
1353 try:
1354 return cmdutil.copy(ui, repo, pats, opts)
1354 return cmdutil.copy(ui, repo, pats, opts)
1355 finally:
1355 finally:
1356 wlock.release()
1356 wlock.release()
1357
1357
1358 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1358 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1359 def debugancestor(ui, repo, *args):
1359 def debugancestor(ui, repo, *args):
1360 """find the ancestor revision of two revisions in a given index"""
1360 """find the ancestor revision of two revisions in a given index"""
1361 if len(args) == 3:
1361 if len(args) == 3:
1362 index, rev1, rev2 = args
1362 index, rev1, rev2 = args
1363 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1363 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1364 lookup = r.lookup
1364 lookup = r.lookup
1365 elif len(args) == 2:
1365 elif len(args) == 2:
1366 if not repo:
1366 if not repo:
1367 raise util.Abort(_("there is no Mercurial repository here "
1367 raise util.Abort(_("there is no Mercurial repository here "
1368 "(.hg not found)"))
1368 "(.hg not found)"))
1369 rev1, rev2 = args
1369 rev1, rev2 = args
1370 r = repo.changelog
1370 r = repo.changelog
1371 lookup = repo.lookup
1371 lookup = repo.lookup
1372 else:
1372 else:
1373 raise util.Abort(_('either two or three arguments required'))
1373 raise util.Abort(_('either two or three arguments required'))
1374 a = r.ancestor(lookup(rev1), lookup(rev2))
1374 a = r.ancestor(lookup(rev1), lookup(rev2))
1375 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1375 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1376
1376
1377 @command('debugbuilddag',
1377 @command('debugbuilddag',
1378 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1378 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1379 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1379 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1380 ('n', 'new-file', None, _('add new file at each rev'))],
1380 ('n', 'new-file', None, _('add new file at each rev'))],
1381 _('[OPTION]... [TEXT]'))
1381 _('[OPTION]... [TEXT]'))
1382 def debugbuilddag(ui, repo, text=None,
1382 def debugbuilddag(ui, repo, text=None,
1383 mergeable_file=False,
1383 mergeable_file=False,
1384 overwritten_file=False,
1384 overwritten_file=False,
1385 new_file=False):
1385 new_file=False):
1386 """builds a repo with a given DAG from scratch in the current empty repo
1386 """builds a repo with a given DAG from scratch in the current empty repo
1387
1387
1388 The description of the DAG is read from stdin if not given on the
1388 The description of the DAG is read from stdin if not given on the
1389 command line.
1389 command line.
1390
1390
1391 Elements:
1391 Elements:
1392
1392
1393 - "+n" is a linear run of n nodes based on the current default parent
1393 - "+n" is a linear run of n nodes based on the current default parent
1394 - "." is a single node based on the current default parent
1394 - "." is a single node based on the current default parent
1395 - "$" resets the default parent to null (implied at the start);
1395 - "$" resets the default parent to null (implied at the start);
1396 otherwise the default parent is always the last node created
1396 otherwise the default parent is always the last node created
1397 - "<p" sets the default parent to the backref p
1397 - "<p" sets the default parent to the backref p
1398 - "*p" is a fork at parent p, which is a backref
1398 - "*p" is a fork at parent p, which is a backref
1399 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1399 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1400 - "/p2" is a merge of the preceding node and p2
1400 - "/p2" is a merge of the preceding node and p2
1401 - ":tag" defines a local tag for the preceding node
1401 - ":tag" defines a local tag for the preceding node
1402 - "@branch" sets the named branch for subsequent nodes
1402 - "@branch" sets the named branch for subsequent nodes
1403 - "#...\\n" is a comment up to the end of the line
1403 - "#...\\n" is a comment up to the end of the line
1404
1404
1405 Whitespace between the above elements is ignored.
1405 Whitespace between the above elements is ignored.
1406
1406
1407 A backref is either
1407 A backref is either
1408
1408
1409 - a number n, which references the node curr-n, where curr is the current
1409 - a number n, which references the node curr-n, where curr is the current
1410 node, or
1410 node, or
1411 - the name of a local tag you placed earlier using ":tag", or
1411 - the name of a local tag you placed earlier using ":tag", or
1412 - empty to denote the default parent.
1412 - empty to denote the default parent.
1413
1413
1414 All string valued-elements are either strictly alphanumeric, or must
1414 All string valued-elements are either strictly alphanumeric, or must
1415 be enclosed in double quotes ("..."), with "\\" as escape character.
1415 be enclosed in double quotes ("..."), with "\\" as escape character.
1416 """
1416 """
1417
1417
1418 if text is None:
1418 if text is None:
1419 ui.status(_("reading DAG from stdin\n"))
1419 ui.status(_("reading DAG from stdin\n"))
1420 text = ui.fin.read()
1420 text = ui.fin.read()
1421
1421
1422 cl = repo.changelog
1422 cl = repo.changelog
1423 if len(cl) > 0:
1423 if len(cl) > 0:
1424 raise util.Abort(_('repository is not empty'))
1424 raise util.Abort(_('repository is not empty'))
1425
1425
1426 # determine number of revs in DAG
1426 # determine number of revs in DAG
1427 total = 0
1427 total = 0
1428 for type, data in dagparser.parsedag(text):
1428 for type, data in dagparser.parsedag(text):
1429 if type == 'n':
1429 if type == 'n':
1430 total += 1
1430 total += 1
1431
1431
1432 if mergeable_file:
1432 if mergeable_file:
1433 linesperrev = 2
1433 linesperrev = 2
1434 # make a file with k lines per rev
1434 # make a file with k lines per rev
1435 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1435 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1436 initialmergedlines.append("")
1436 initialmergedlines.append("")
1437
1437
1438 tags = []
1438 tags = []
1439
1439
1440 lock = tr = None
1440 lock = tr = None
1441 try:
1441 try:
1442 lock = repo.lock()
1442 lock = repo.lock()
1443 tr = repo.transaction("builddag")
1443 tr = repo.transaction("builddag")
1444
1444
1445 at = -1
1445 at = -1
1446 atbranch = 'default'
1446 atbranch = 'default'
1447 nodeids = []
1447 nodeids = []
1448 id = 0
1448 id = 0
1449 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1449 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1450 for type, data in dagparser.parsedag(text):
1450 for type, data in dagparser.parsedag(text):
1451 if type == 'n':
1451 if type == 'n':
1452 ui.note('node %s\n' % str(data))
1452 ui.note('node %s\n' % str(data))
1453 id, ps = data
1453 id, ps = data
1454
1454
1455 files = []
1455 files = []
1456 fctxs = {}
1456 fctxs = {}
1457
1457
1458 p2 = None
1458 p2 = None
1459 if mergeable_file:
1459 if mergeable_file:
1460 fn = "mf"
1460 fn = "mf"
1461 p1 = repo[ps[0]]
1461 p1 = repo[ps[0]]
1462 if len(ps) > 1:
1462 if len(ps) > 1:
1463 p2 = repo[ps[1]]
1463 p2 = repo[ps[1]]
1464 pa = p1.ancestor(p2)
1464 pa = p1.ancestor(p2)
1465 base, local, other = [x[fn].data() for x in pa, p1, p2]
1465 base, local, other = [x[fn].data() for x in pa, p1, p2]
1466 m3 = simplemerge.Merge3Text(base, local, other)
1466 m3 = simplemerge.Merge3Text(base, local, other)
1467 ml = [l.strip() for l in m3.merge_lines()]
1467 ml = [l.strip() for l in m3.merge_lines()]
1468 ml.append("")
1468 ml.append("")
1469 elif at > 0:
1469 elif at > 0:
1470 ml = p1[fn].data().split("\n")
1470 ml = p1[fn].data().split("\n")
1471 else:
1471 else:
1472 ml = initialmergedlines
1472 ml = initialmergedlines
1473 ml[id * linesperrev] += " r%i" % id
1473 ml[id * linesperrev] += " r%i" % id
1474 mergedtext = "\n".join(ml)
1474 mergedtext = "\n".join(ml)
1475 files.append(fn)
1475 files.append(fn)
1476 fctxs[fn] = context.memfilectx(fn, mergedtext)
1476 fctxs[fn] = context.memfilectx(fn, mergedtext)
1477
1477
1478 if overwritten_file:
1478 if overwritten_file:
1479 fn = "of"
1479 fn = "of"
1480 files.append(fn)
1480 files.append(fn)
1481 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1481 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1482
1482
1483 if new_file:
1483 if new_file:
1484 fn = "nf%i" % id
1484 fn = "nf%i" % id
1485 files.append(fn)
1485 files.append(fn)
1486 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1486 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1487 if len(ps) > 1:
1487 if len(ps) > 1:
1488 if not p2:
1488 if not p2:
1489 p2 = repo[ps[1]]
1489 p2 = repo[ps[1]]
1490 for fn in p2:
1490 for fn in p2:
1491 if fn.startswith("nf"):
1491 if fn.startswith("nf"):
1492 files.append(fn)
1492 files.append(fn)
1493 fctxs[fn] = p2[fn]
1493 fctxs[fn] = p2[fn]
1494
1494
1495 def fctxfn(repo, cx, path):
1495 def fctxfn(repo, cx, path):
1496 return fctxs.get(path)
1496 return fctxs.get(path)
1497
1497
1498 if len(ps) == 0 or ps[0] < 0:
1498 if len(ps) == 0 or ps[0] < 0:
1499 pars = [None, None]
1499 pars = [None, None]
1500 elif len(ps) == 1:
1500 elif len(ps) == 1:
1501 pars = [nodeids[ps[0]], None]
1501 pars = [nodeids[ps[0]], None]
1502 else:
1502 else:
1503 pars = [nodeids[p] for p in ps]
1503 pars = [nodeids[p] for p in ps]
1504 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1504 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1505 date=(id, 0),
1505 date=(id, 0),
1506 user="debugbuilddag",
1506 user="debugbuilddag",
1507 extra={'branch': atbranch})
1507 extra={'branch': atbranch})
1508 nodeid = repo.commitctx(cx)
1508 nodeid = repo.commitctx(cx)
1509 nodeids.append(nodeid)
1509 nodeids.append(nodeid)
1510 at = id
1510 at = id
1511 elif type == 'l':
1511 elif type == 'l':
1512 id, name = data
1512 id, name = data
1513 ui.note('tag %s\n' % name)
1513 ui.note('tag %s\n' % name)
1514 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1514 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1515 elif type == 'a':
1515 elif type == 'a':
1516 ui.note('branch %s\n' % data)
1516 ui.note('branch %s\n' % data)
1517 atbranch = data
1517 atbranch = data
1518 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1518 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1519 tr.close()
1519 tr.close()
1520
1520
1521 if tags:
1521 if tags:
1522 repo.opener.write("localtags", "".join(tags))
1522 repo.opener.write("localtags", "".join(tags))
1523 finally:
1523 finally:
1524 ui.progress(_('building'), None)
1524 ui.progress(_('building'), None)
1525 release(tr, lock)
1525 release(tr, lock)
1526
1526
1527 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1527 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1528 def debugbundle(ui, bundlepath, all=None, **opts):
1528 def debugbundle(ui, bundlepath, all=None, **opts):
1529 """lists the contents of a bundle"""
1529 """lists the contents of a bundle"""
1530 f = url.open(ui, bundlepath)
1530 f = url.open(ui, bundlepath)
1531 try:
1531 try:
1532 gen = changegroup.readbundle(f, bundlepath)
1532 gen = changegroup.readbundle(f, bundlepath)
1533 if all:
1533 if all:
1534 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1534 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1535
1535
1536 def showchunks(named):
1536 def showchunks(named):
1537 ui.write("\n%s\n" % named)
1537 ui.write("\n%s\n" % named)
1538 chain = None
1538 chain = None
1539 while True:
1539 while True:
1540 chunkdata = gen.deltachunk(chain)
1540 chunkdata = gen.deltachunk(chain)
1541 if not chunkdata:
1541 if not chunkdata:
1542 break
1542 break
1543 node = chunkdata['node']
1543 node = chunkdata['node']
1544 p1 = chunkdata['p1']
1544 p1 = chunkdata['p1']
1545 p2 = chunkdata['p2']
1545 p2 = chunkdata['p2']
1546 cs = chunkdata['cs']
1546 cs = chunkdata['cs']
1547 deltabase = chunkdata['deltabase']
1547 deltabase = chunkdata['deltabase']
1548 delta = chunkdata['delta']
1548 delta = chunkdata['delta']
1549 ui.write("%s %s %s %s %s %s\n" %
1549 ui.write("%s %s %s %s %s %s\n" %
1550 (hex(node), hex(p1), hex(p2),
1550 (hex(node), hex(p1), hex(p2),
1551 hex(cs), hex(deltabase), len(delta)))
1551 hex(cs), hex(deltabase), len(delta)))
1552 chain = node
1552 chain = node
1553
1553
1554 chunkdata = gen.changelogheader()
1554 chunkdata = gen.changelogheader()
1555 showchunks("changelog")
1555 showchunks("changelog")
1556 chunkdata = gen.manifestheader()
1556 chunkdata = gen.manifestheader()
1557 showchunks("manifest")
1557 showchunks("manifest")
1558 while True:
1558 while True:
1559 chunkdata = gen.filelogheader()
1559 chunkdata = gen.filelogheader()
1560 if not chunkdata:
1560 if not chunkdata:
1561 break
1561 break
1562 fname = chunkdata['filename']
1562 fname = chunkdata['filename']
1563 showchunks(fname)
1563 showchunks(fname)
1564 else:
1564 else:
1565 chunkdata = gen.changelogheader()
1565 chunkdata = gen.changelogheader()
1566 chain = None
1566 chain = None
1567 while True:
1567 while True:
1568 chunkdata = gen.deltachunk(chain)
1568 chunkdata = gen.deltachunk(chain)
1569 if not chunkdata:
1569 if not chunkdata:
1570 break
1570 break
1571 node = chunkdata['node']
1571 node = chunkdata['node']
1572 ui.write("%s\n" % hex(node))
1572 ui.write("%s\n" % hex(node))
1573 chain = node
1573 chain = node
1574 finally:
1574 finally:
1575 f.close()
1575 f.close()
1576
1576
1577 @command('debugcheckstate', [], '')
1577 @command('debugcheckstate', [], '')
1578 def debugcheckstate(ui, repo):
1578 def debugcheckstate(ui, repo):
1579 """validate the correctness of the current dirstate"""
1579 """validate the correctness of the current dirstate"""
1580 parent1, parent2 = repo.dirstate.parents()
1580 parent1, parent2 = repo.dirstate.parents()
1581 m1 = repo[parent1].manifest()
1581 m1 = repo[parent1].manifest()
1582 m2 = repo[parent2].manifest()
1582 m2 = repo[parent2].manifest()
1583 errors = 0
1583 errors = 0
1584 for f in repo.dirstate:
1584 for f in repo.dirstate:
1585 state = repo.dirstate[f]
1585 state = repo.dirstate[f]
1586 if state in "nr" and f not in m1:
1586 if state in "nr" and f not in m1:
1587 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1587 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1588 errors += 1
1588 errors += 1
1589 if state in "a" and f in m1:
1589 if state in "a" and f in m1:
1590 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1590 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1591 errors += 1
1591 errors += 1
1592 if state in "m" and f not in m1 and f not in m2:
1592 if state in "m" and f not in m1 and f not in m2:
1593 ui.warn(_("%s in state %s, but not in either manifest\n") %
1593 ui.warn(_("%s in state %s, but not in either manifest\n") %
1594 (f, state))
1594 (f, state))
1595 errors += 1
1595 errors += 1
1596 for f in m1:
1596 for f in m1:
1597 state = repo.dirstate[f]
1597 state = repo.dirstate[f]
1598 if state not in "nrm":
1598 if state not in "nrm":
1599 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1599 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1600 errors += 1
1600 errors += 1
1601 if errors:
1601 if errors:
1602 error = _(".hg/dirstate inconsistent with current parent's manifest")
1602 error = _(".hg/dirstate inconsistent with current parent's manifest")
1603 raise util.Abort(error)
1603 raise util.Abort(error)
1604
1604
1605 @command('debugcommands', [], _('[COMMAND]'))
1605 @command('debugcommands', [], _('[COMMAND]'))
1606 def debugcommands(ui, cmd='', *args):
1606 def debugcommands(ui, cmd='', *args):
1607 """list all available commands and options"""
1607 """list all available commands and options"""
1608 for cmd, vals in sorted(table.iteritems()):
1608 for cmd, vals in sorted(table.iteritems()):
1609 cmd = cmd.split('|')[0].strip('^')
1609 cmd = cmd.split('|')[0].strip('^')
1610 opts = ', '.join([i[1] for i in vals[1]])
1610 opts = ', '.join([i[1] for i in vals[1]])
1611 ui.write('%s: %s\n' % (cmd, opts))
1611 ui.write('%s: %s\n' % (cmd, opts))
1612
1612
1613 @command('debugcomplete',
1613 @command('debugcomplete',
1614 [('o', 'options', None, _('show the command options'))],
1614 [('o', 'options', None, _('show the command options'))],
1615 _('[-o] CMD'))
1615 _('[-o] CMD'))
1616 def debugcomplete(ui, cmd='', **opts):
1616 def debugcomplete(ui, cmd='', **opts):
1617 """returns the completion list associated with the given command"""
1617 """returns the completion list associated with the given command"""
1618
1618
1619 if opts.get('options'):
1619 if opts.get('options'):
1620 options = []
1620 options = []
1621 otables = [globalopts]
1621 otables = [globalopts]
1622 if cmd:
1622 if cmd:
1623 aliases, entry = cmdutil.findcmd(cmd, table, False)
1623 aliases, entry = cmdutil.findcmd(cmd, table, False)
1624 otables.append(entry[1])
1624 otables.append(entry[1])
1625 for t in otables:
1625 for t in otables:
1626 for o in t:
1626 for o in t:
1627 if "(DEPRECATED)" in o[3]:
1627 if "(DEPRECATED)" in o[3]:
1628 continue
1628 continue
1629 if o[0]:
1629 if o[0]:
1630 options.append('-%s' % o[0])
1630 options.append('-%s' % o[0])
1631 options.append('--%s' % o[1])
1631 options.append('--%s' % o[1])
1632 ui.write("%s\n" % "\n".join(options))
1632 ui.write("%s\n" % "\n".join(options))
1633 return
1633 return
1634
1634
1635 cmdlist = cmdutil.findpossible(cmd, table)
1635 cmdlist = cmdutil.findpossible(cmd, table)
1636 if ui.verbose:
1636 if ui.verbose:
1637 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1637 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1638 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1638 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1639
1639
1640 @command('debugdag',
1640 @command('debugdag',
1641 [('t', 'tags', None, _('use tags as labels')),
1641 [('t', 'tags', None, _('use tags as labels')),
1642 ('b', 'branches', None, _('annotate with branch names')),
1642 ('b', 'branches', None, _('annotate with branch names')),
1643 ('', 'dots', None, _('use dots for runs')),
1643 ('', 'dots', None, _('use dots for runs')),
1644 ('s', 'spaces', None, _('separate elements by spaces'))],
1644 ('s', 'spaces', None, _('separate elements by spaces'))],
1645 _('[OPTION]... [FILE [REV]...]'))
1645 _('[OPTION]... [FILE [REV]...]'))
1646 def debugdag(ui, repo, file_=None, *revs, **opts):
1646 def debugdag(ui, repo, file_=None, *revs, **opts):
1647 """format the changelog or an index DAG as a concise textual description
1647 """format the changelog or an index DAG as a concise textual description
1648
1648
1649 If you pass a revlog index, the revlog's DAG is emitted. If you list
1649 If you pass a revlog index, the revlog's DAG is emitted. If you list
1650 revision numbers, they get labelled in the output as rN.
1650 revision numbers, they get labelled in the output as rN.
1651
1651
1652 Otherwise, the changelog DAG of the current repo is emitted.
1652 Otherwise, the changelog DAG of the current repo is emitted.
1653 """
1653 """
1654 spaces = opts.get('spaces')
1654 spaces = opts.get('spaces')
1655 dots = opts.get('dots')
1655 dots = opts.get('dots')
1656 if file_:
1656 if file_:
1657 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1657 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1658 revs = set((int(r) for r in revs))
1658 revs = set((int(r) for r in revs))
1659 def events():
1659 def events():
1660 for r in rlog:
1660 for r in rlog:
1661 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1661 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1662 if r in revs:
1662 if r in revs:
1663 yield 'l', (r, "r%i" % r)
1663 yield 'l', (r, "r%i" % r)
1664 elif repo:
1664 elif repo:
1665 cl = repo.changelog
1665 cl = repo.changelog
1666 tags = opts.get('tags')
1666 tags = opts.get('tags')
1667 branches = opts.get('branches')
1667 branches = opts.get('branches')
1668 if tags:
1668 if tags:
1669 labels = {}
1669 labels = {}
1670 for l, n in repo.tags().items():
1670 for l, n in repo.tags().items():
1671 labels.setdefault(cl.rev(n), []).append(l)
1671 labels.setdefault(cl.rev(n), []).append(l)
1672 def events():
1672 def events():
1673 b = "default"
1673 b = "default"
1674 for r in cl:
1674 for r in cl:
1675 if branches:
1675 if branches:
1676 newb = cl.read(cl.node(r))[5]['branch']
1676 newb = cl.read(cl.node(r))[5]['branch']
1677 if newb != b:
1677 if newb != b:
1678 yield 'a', newb
1678 yield 'a', newb
1679 b = newb
1679 b = newb
1680 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1680 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1681 if tags:
1681 if tags:
1682 ls = labels.get(r)
1682 ls = labels.get(r)
1683 if ls:
1683 if ls:
1684 for l in ls:
1684 for l in ls:
1685 yield 'l', (r, l)
1685 yield 'l', (r, l)
1686 else:
1686 else:
1687 raise util.Abort(_('need repo for changelog dag'))
1687 raise util.Abort(_('need repo for changelog dag'))
1688
1688
1689 for line in dagparser.dagtextlines(events(),
1689 for line in dagparser.dagtextlines(events(),
1690 addspaces=spaces,
1690 addspaces=spaces,
1691 wraplabels=True,
1691 wraplabels=True,
1692 wrapannotations=True,
1692 wrapannotations=True,
1693 wrapnonlinear=dots,
1693 wrapnonlinear=dots,
1694 usedots=dots,
1694 usedots=dots,
1695 maxlinewidth=70):
1695 maxlinewidth=70):
1696 ui.write(line)
1696 ui.write(line)
1697 ui.write("\n")
1697 ui.write("\n")
1698
1698
1699 @command('debugdata',
1699 @command('debugdata',
1700 [('c', 'changelog', False, _('open changelog')),
1700 [('c', 'changelog', False, _('open changelog')),
1701 ('m', 'manifest', False, _('open manifest'))],
1701 ('m', 'manifest', False, _('open manifest'))],
1702 _('-c|-m|FILE REV'))
1702 _('-c|-m|FILE REV'))
1703 def debugdata(ui, repo, file_, rev = None, **opts):
1703 def debugdata(ui, repo, file_, rev = None, **opts):
1704 """dump the contents of a data file revision"""
1704 """dump the contents of a data file revision"""
1705 if opts.get('changelog') or opts.get('manifest'):
1705 if opts.get('changelog') or opts.get('manifest'):
1706 file_, rev = None, file_
1706 file_, rev = None, file_
1707 elif rev is None:
1707 elif rev is None:
1708 raise error.CommandError('debugdata', _('invalid arguments'))
1708 raise error.CommandError('debugdata', _('invalid arguments'))
1709 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1709 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1710 try:
1710 try:
1711 ui.write(r.revision(r.lookup(rev)))
1711 ui.write(r.revision(r.lookup(rev)))
1712 except KeyError:
1712 except KeyError:
1713 raise util.Abort(_('invalid revision identifier %s') % rev)
1713 raise util.Abort(_('invalid revision identifier %s') % rev)
1714
1714
1715 @command('debugdate',
1715 @command('debugdate',
1716 [('e', 'extended', None, _('try extended date formats'))],
1716 [('e', 'extended', None, _('try extended date formats'))],
1717 _('[-e] DATE [RANGE]'))
1717 _('[-e] DATE [RANGE]'))
1718 def debugdate(ui, date, range=None, **opts):
1718 def debugdate(ui, date, range=None, **opts):
1719 """parse and display a date"""
1719 """parse and display a date"""
1720 if opts["extended"]:
1720 if opts["extended"]:
1721 d = util.parsedate(date, util.extendeddateformats)
1721 d = util.parsedate(date, util.extendeddateformats)
1722 else:
1722 else:
1723 d = util.parsedate(date)
1723 d = util.parsedate(date)
1724 ui.write("internal: %s %s\n" % d)
1724 ui.write("internal: %s %s\n" % d)
1725 ui.write("standard: %s\n" % util.datestr(d))
1725 ui.write("standard: %s\n" % util.datestr(d))
1726 if range:
1726 if range:
1727 m = util.matchdate(range)
1727 m = util.matchdate(range)
1728 ui.write("match: %s\n" % m(d[0]))
1728 ui.write("match: %s\n" % m(d[0]))
1729
1729
1730 @command('debugdiscovery',
1730 @command('debugdiscovery',
1731 [('', 'old', None, _('use old-style discovery')),
1731 [('', 'old', None, _('use old-style discovery')),
1732 ('', 'nonheads', None,
1732 ('', 'nonheads', None,
1733 _('use old-style discovery with non-heads included')),
1733 _('use old-style discovery with non-heads included')),
1734 ] + remoteopts,
1734 ] + remoteopts,
1735 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1735 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1736 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1736 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1737 """runs the changeset discovery protocol in isolation"""
1737 """runs the changeset discovery protocol in isolation"""
1738 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1738 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1739 remote = hg.peer(repo, opts, remoteurl)
1739 remote = hg.peer(repo, opts, remoteurl)
1740 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1740 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1741
1741
1742 # make sure tests are repeatable
1742 # make sure tests are repeatable
1743 random.seed(12323)
1743 random.seed(12323)
1744
1744
1745 def doit(localheads, remoteheads):
1745 def doit(localheads, remoteheads):
1746 if opts.get('old'):
1746 if opts.get('old'):
1747 if localheads:
1747 if localheads:
1748 raise util.Abort('cannot use localheads with old style discovery')
1748 raise util.Abort('cannot use localheads with old style discovery')
1749 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1749 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1750 force=True)
1750 force=True)
1751 common = set(common)
1751 common = set(common)
1752 if not opts.get('nonheads'):
1752 if not opts.get('nonheads'):
1753 ui.write("unpruned common: %s\n" % " ".join([short(n)
1753 ui.write("unpruned common: %s\n" % " ".join([short(n)
1754 for n in common]))
1754 for n in common]))
1755 dag = dagutil.revlogdag(repo.changelog)
1755 dag = dagutil.revlogdag(repo.changelog)
1756 all = dag.ancestorset(dag.internalizeall(common))
1756 all = dag.ancestorset(dag.internalizeall(common))
1757 common = dag.externalizeall(dag.headsetofconnecteds(all))
1757 common = dag.externalizeall(dag.headsetofconnecteds(all))
1758 else:
1758 else:
1759 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1759 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1760 common = set(common)
1760 common = set(common)
1761 rheads = set(hds)
1761 rheads = set(hds)
1762 lheads = set(repo.heads())
1762 lheads = set(repo.heads())
1763 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1763 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1764 if lheads <= common:
1764 if lheads <= common:
1765 ui.write("local is subset\n")
1765 ui.write("local is subset\n")
1766 elif rheads <= common:
1766 elif rheads <= common:
1767 ui.write("remote is subset\n")
1767 ui.write("remote is subset\n")
1768
1768
1769 serverlogs = opts.get('serverlog')
1769 serverlogs = opts.get('serverlog')
1770 if serverlogs:
1770 if serverlogs:
1771 for filename in serverlogs:
1771 for filename in serverlogs:
1772 logfile = open(filename, 'r')
1772 logfile = open(filename, 'r')
1773 try:
1773 try:
1774 line = logfile.readline()
1774 line = logfile.readline()
1775 while line:
1775 while line:
1776 parts = line.strip().split(';')
1776 parts = line.strip().split(';')
1777 op = parts[1]
1777 op = parts[1]
1778 if op == 'cg':
1778 if op == 'cg':
1779 pass
1779 pass
1780 elif op == 'cgss':
1780 elif op == 'cgss':
1781 doit(parts[2].split(' '), parts[3].split(' '))
1781 doit(parts[2].split(' '), parts[3].split(' '))
1782 elif op == 'unb':
1782 elif op == 'unb':
1783 doit(parts[3].split(' '), parts[2].split(' '))
1783 doit(parts[3].split(' '), parts[2].split(' '))
1784 line = logfile.readline()
1784 line = logfile.readline()
1785 finally:
1785 finally:
1786 logfile.close()
1786 logfile.close()
1787
1787
1788 else:
1788 else:
1789 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1789 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1790 opts.get('remote_head'))
1790 opts.get('remote_head'))
1791 localrevs = opts.get('local_head')
1791 localrevs = opts.get('local_head')
1792 doit(localrevs, remoterevs)
1792 doit(localrevs, remoterevs)
1793
1793
1794 @command('debugfileset', [], ('REVSPEC'))
1794 @command('debugfileset', [], ('REVSPEC'))
1795 def debugfileset(ui, repo, expr):
1795 def debugfileset(ui, repo, expr):
1796 '''parse and apply a fileset specification'''
1796 '''parse and apply a fileset specification'''
1797 if ui.verbose:
1797 if ui.verbose:
1798 tree = fileset.parse(expr)[0]
1798 tree = fileset.parse(expr)[0]
1799 ui.note(tree, "\n")
1799 ui.note(tree, "\n")
1800
1800
1801 for f in fileset.getfileset(repo[None], expr):
1801 for f in fileset.getfileset(repo[None], expr):
1802 ui.write("%s\n" % f)
1802 ui.write("%s\n" % f)
1803
1803
1804 @command('debugfsinfo', [], _('[PATH]'))
1804 @command('debugfsinfo', [], _('[PATH]'))
1805 def debugfsinfo(ui, path = "."):
1805 def debugfsinfo(ui, path = "."):
1806 """show information detected about current filesystem"""
1806 """show information detected about current filesystem"""
1807 util.writefile('.debugfsinfo', '')
1807 util.writefile('.debugfsinfo', '')
1808 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1808 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1809 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1809 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1810 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1810 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1811 and 'yes' or 'no'))
1811 and 'yes' or 'no'))
1812 os.unlink('.debugfsinfo')
1812 os.unlink('.debugfsinfo')
1813
1813
1814 @command('debuggetbundle',
1814 @command('debuggetbundle',
1815 [('H', 'head', [], _('id of head node'), _('ID')),
1815 [('H', 'head', [], _('id of head node'), _('ID')),
1816 ('C', 'common', [], _('id of common node'), _('ID')),
1816 ('C', 'common', [], _('id of common node'), _('ID')),
1817 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1817 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1818 _('REPO FILE [-H|-C ID]...'))
1818 _('REPO FILE [-H|-C ID]...'))
1819 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1819 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1820 """retrieves a bundle from a repo
1820 """retrieves a bundle from a repo
1821
1821
1822 Every ID must be a full-length hex node id string. Saves the bundle to the
1822 Every ID must be a full-length hex node id string. Saves the bundle to the
1823 given file.
1823 given file.
1824 """
1824 """
1825 repo = hg.peer(ui, opts, repopath)
1825 repo = hg.peer(ui, opts, repopath)
1826 if not repo.capable('getbundle'):
1826 if not repo.capable('getbundle'):
1827 raise util.Abort("getbundle() not supported by target repository")
1827 raise util.Abort("getbundle() not supported by target repository")
1828 args = {}
1828 args = {}
1829 if common:
1829 if common:
1830 args['common'] = [bin(s) for s in common]
1830 args['common'] = [bin(s) for s in common]
1831 if head:
1831 if head:
1832 args['heads'] = [bin(s) for s in head]
1832 args['heads'] = [bin(s) for s in head]
1833 bundle = repo.getbundle('debug', **args)
1833 bundle = repo.getbundle('debug', **args)
1834
1834
1835 bundletype = opts.get('type', 'bzip2').lower()
1835 bundletype = opts.get('type', 'bzip2').lower()
1836 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1836 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1837 bundletype = btypes.get(bundletype)
1837 bundletype = btypes.get(bundletype)
1838 if bundletype not in changegroup.bundletypes:
1838 if bundletype not in changegroup.bundletypes:
1839 raise util.Abort(_('unknown bundle type specified with --type'))
1839 raise util.Abort(_('unknown bundle type specified with --type'))
1840 changegroup.writebundle(bundle, bundlepath, bundletype)
1840 changegroup.writebundle(bundle, bundlepath, bundletype)
1841
1841
1842 @command('debugignore', [], '')
1842 @command('debugignore', [], '')
1843 def debugignore(ui, repo, *values, **opts):
1843 def debugignore(ui, repo, *values, **opts):
1844 """display the combined ignore pattern"""
1844 """display the combined ignore pattern"""
1845 ignore = repo.dirstate._ignore
1845 ignore = repo.dirstate._ignore
1846 includepat = getattr(ignore, 'includepat', None)
1846 includepat = getattr(ignore, 'includepat', None)
1847 if includepat is not None:
1847 if includepat is not None:
1848 ui.write("%s\n" % includepat)
1848 ui.write("%s\n" % includepat)
1849 else:
1849 else:
1850 raise util.Abort(_("no ignore patterns found"))
1850 raise util.Abort(_("no ignore patterns found"))
1851
1851
1852 @command('debugindex',
1852 @command('debugindex',
1853 [('c', 'changelog', False, _('open changelog')),
1853 [('c', 'changelog', False, _('open changelog')),
1854 ('m', 'manifest', False, _('open manifest')),
1854 ('m', 'manifest', False, _('open manifest')),
1855 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1855 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1856 _('[-f FORMAT] -c|-m|FILE'))
1856 _('[-f FORMAT] -c|-m|FILE'))
1857 def debugindex(ui, repo, file_ = None, **opts):
1857 def debugindex(ui, repo, file_ = None, **opts):
1858 """dump the contents of an index file"""
1858 """dump the contents of an index file"""
1859 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1859 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1860 format = opts.get('format', 0)
1860 format = opts.get('format', 0)
1861 if format not in (0, 1):
1861 if format not in (0, 1):
1862 raise util.Abort(_("unknown format %d") % format)
1862 raise util.Abort(_("unknown format %d") % format)
1863
1863
1864 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1864 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1865 if generaldelta:
1865 if generaldelta:
1866 basehdr = ' delta'
1866 basehdr = ' delta'
1867 else:
1867 else:
1868 basehdr = ' base'
1868 basehdr = ' base'
1869
1869
1870 if format == 0:
1870 if format == 0:
1871 ui.write(" rev offset length " + basehdr + " linkrev"
1871 ui.write(" rev offset length " + basehdr + " linkrev"
1872 " nodeid p1 p2\n")
1872 " nodeid p1 p2\n")
1873 elif format == 1:
1873 elif format == 1:
1874 ui.write(" rev flag offset length"
1874 ui.write(" rev flag offset length"
1875 " size " + basehdr + " link p1 p2 nodeid\n")
1875 " size " + basehdr + " link p1 p2 nodeid\n")
1876
1876
1877 for i in r:
1877 for i in r:
1878 node = r.node(i)
1878 node = r.node(i)
1879 if generaldelta:
1879 if generaldelta:
1880 base = r.deltaparent(i)
1880 base = r.deltaparent(i)
1881 else:
1881 else:
1882 base = r.chainbase(i)
1882 base = r.chainbase(i)
1883 if format == 0:
1883 if format == 0:
1884 try:
1884 try:
1885 pp = r.parents(node)
1885 pp = r.parents(node)
1886 except:
1886 except:
1887 pp = [nullid, nullid]
1887 pp = [nullid, nullid]
1888 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1888 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1889 i, r.start(i), r.length(i), base, r.linkrev(i),
1889 i, r.start(i), r.length(i), base, r.linkrev(i),
1890 short(node), short(pp[0]), short(pp[1])))
1890 short(node), short(pp[0]), short(pp[1])))
1891 elif format == 1:
1891 elif format == 1:
1892 pr = r.parentrevs(i)
1892 pr = r.parentrevs(i)
1893 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1893 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1894 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1894 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1895 base, r.linkrev(i), pr[0], pr[1], short(node)))
1895 base, r.linkrev(i), pr[0], pr[1], short(node)))
1896
1896
1897 @command('debugindexdot', [], _('FILE'))
1897 @command('debugindexdot', [], _('FILE'))
1898 def debugindexdot(ui, repo, file_):
1898 def debugindexdot(ui, repo, file_):
1899 """dump an index DAG as a graphviz dot file"""
1899 """dump an index DAG as a graphviz dot file"""
1900 r = None
1900 r = None
1901 if repo:
1901 if repo:
1902 filelog = repo.file(file_)
1902 filelog = repo.file(file_)
1903 if len(filelog):
1903 if len(filelog):
1904 r = filelog
1904 r = filelog
1905 if not r:
1905 if not r:
1906 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1906 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1907 ui.write("digraph G {\n")
1907 ui.write("digraph G {\n")
1908 for i in r:
1908 for i in r:
1909 node = r.node(i)
1909 node = r.node(i)
1910 pp = r.parents(node)
1910 pp = r.parents(node)
1911 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1911 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1912 if pp[1] != nullid:
1912 if pp[1] != nullid:
1913 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1913 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1914 ui.write("}\n")
1914 ui.write("}\n")
1915
1915
1916 @command('debuginstall', [], '')
1916 @command('debuginstall', [], '')
1917 def debuginstall(ui):
1917 def debuginstall(ui):
1918 '''test Mercurial installation
1918 '''test Mercurial installation
1919
1919
1920 Returns 0 on success.
1920 Returns 0 on success.
1921 '''
1921 '''
1922
1922
1923 def writetemp(contents):
1923 def writetemp(contents):
1924 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1924 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1925 f = os.fdopen(fd, "wb")
1925 f = os.fdopen(fd, "wb")
1926 f.write(contents)
1926 f.write(contents)
1927 f.close()
1927 f.close()
1928 return name
1928 return name
1929
1929
1930 problems = 0
1930 problems = 0
1931
1931
1932 # encoding
1932 # encoding
1933 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1933 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1934 try:
1934 try:
1935 encoding.fromlocal("test")
1935 encoding.fromlocal("test")
1936 except util.Abort, inst:
1936 except util.Abort, inst:
1937 ui.write(" %s\n" % inst)
1937 ui.write(" %s\n" % inst)
1938 ui.write(_(" (check that your locale is properly set)\n"))
1938 ui.write(_(" (check that your locale is properly set)\n"))
1939 problems += 1
1939 problems += 1
1940
1940
1941 # compiled modules
1941 # compiled modules
1942 ui.status(_("Checking installed modules (%s)...\n")
1942 ui.status(_("Checking installed modules (%s)...\n")
1943 % os.path.dirname(__file__))
1943 % os.path.dirname(__file__))
1944 try:
1944 try:
1945 import bdiff, mpatch, base85, osutil
1945 import bdiff, mpatch, base85, osutil
1946 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1946 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1947 except Exception, inst:
1947 except Exception, inst:
1948 ui.write(" %s\n" % inst)
1948 ui.write(" %s\n" % inst)
1949 ui.write(_(" One or more extensions could not be found"))
1949 ui.write(_(" One or more extensions could not be found"))
1950 ui.write(_(" (check that you compiled the extensions)\n"))
1950 ui.write(_(" (check that you compiled the extensions)\n"))
1951 problems += 1
1951 problems += 1
1952
1952
1953 # templates
1953 # templates
1954 import templater
1954 import templater
1955 p = templater.templatepath()
1955 p = templater.templatepath()
1956 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1956 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1957 try:
1957 try:
1958 templater.templater(templater.templatepath("map-cmdline.default"))
1958 templater.templater(templater.templatepath("map-cmdline.default"))
1959 except Exception, inst:
1959 except Exception, inst:
1960 ui.write(" %s\n" % inst)
1960 ui.write(" %s\n" % inst)
1961 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1961 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1962 problems += 1
1962 problems += 1
1963
1963
1964 # editor
1964 # editor
1965 ui.status(_("Checking commit editor...\n"))
1965 ui.status(_("Checking commit editor...\n"))
1966 editor = ui.geteditor()
1966 editor = ui.geteditor()
1967 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1967 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1968 if not cmdpath:
1968 if not cmdpath:
1969 if editor == 'vi':
1969 if editor == 'vi':
1970 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1970 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1971 ui.write(_(" (specify a commit editor in your configuration"
1971 ui.write(_(" (specify a commit editor in your configuration"
1972 " file)\n"))
1972 " file)\n"))
1973 else:
1973 else:
1974 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1974 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1975 ui.write(_(" (specify a commit editor in your configuration"
1975 ui.write(_(" (specify a commit editor in your configuration"
1976 " file)\n"))
1976 " file)\n"))
1977 problems += 1
1977 problems += 1
1978
1978
1979 # check username
1979 # check username
1980 ui.status(_("Checking username...\n"))
1980 ui.status(_("Checking username...\n"))
1981 try:
1981 try:
1982 ui.username()
1982 ui.username()
1983 except util.Abort, e:
1983 except util.Abort, e:
1984 ui.write(" %s\n" % e)
1984 ui.write(" %s\n" % e)
1985 ui.write(_(" (specify a username in your configuration file)\n"))
1985 ui.write(_(" (specify a username in your configuration file)\n"))
1986 problems += 1
1986 problems += 1
1987
1987
1988 if not problems:
1988 if not problems:
1989 ui.status(_("No problems detected\n"))
1989 ui.status(_("No problems detected\n"))
1990 else:
1990 else:
1991 ui.write(_("%s problems detected,"
1991 ui.write(_("%s problems detected,"
1992 " please check your install!\n") % problems)
1992 " please check your install!\n") % problems)
1993
1993
1994 return problems
1994 return problems
1995
1995
1996 @command('debugknown', [], _('REPO ID...'))
1996 @command('debugknown', [], _('REPO ID...'))
1997 def debugknown(ui, repopath, *ids, **opts):
1997 def debugknown(ui, repopath, *ids, **opts):
1998 """test whether node ids are known to a repo
1998 """test whether node ids are known to a repo
1999
1999
2000 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
2000 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
2001 indicating unknown/known.
2001 indicating unknown/known.
2002 """
2002 """
2003 repo = hg.peer(ui, opts, repopath)
2003 repo = hg.peer(ui, opts, repopath)
2004 if not repo.capable('known'):
2004 if not repo.capable('known'):
2005 raise util.Abort("known() not supported by target repository")
2005 raise util.Abort("known() not supported by target repository")
2006 flags = repo.known([bin(s) for s in ids])
2006 flags = repo.known([bin(s) for s in ids])
2007 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2007 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2008
2008
2009 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2009 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2010 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2010 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2011 '''access the pushkey key/value protocol
2011 '''access the pushkey key/value protocol
2012
2012
2013 With two args, list the keys in the given namespace.
2013 With two args, list the keys in the given namespace.
2014
2014
2015 With five args, set a key to new if it currently is set to old.
2015 With five args, set a key to new if it currently is set to old.
2016 Reports success or failure.
2016 Reports success or failure.
2017 '''
2017 '''
2018
2018
2019 target = hg.peer(ui, {}, repopath)
2019 target = hg.peer(ui, {}, repopath)
2020 if keyinfo:
2020 if keyinfo:
2021 key, old, new = keyinfo
2021 key, old, new = keyinfo
2022 r = target.pushkey(namespace, key, old, new)
2022 r = target.pushkey(namespace, key, old, new)
2023 ui.status(str(r) + '\n')
2023 ui.status(str(r) + '\n')
2024 return not r
2024 return not r
2025 else:
2025 else:
2026 for k, v in target.listkeys(namespace).iteritems():
2026 for k, v in target.listkeys(namespace).iteritems():
2027 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2027 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2028 v.encode('string-escape')))
2028 v.encode('string-escape')))
2029
2029
2030 @command('debugpvec', [], _('A B'))
2030 @command('debugpvec', [], _('A B'))
2031 def debugpvec(ui, repo, a, b=None):
2031 def debugpvec(ui, repo, a, b=None):
2032 ca = scmutil.revsingle(repo, a)
2032 ca = scmutil.revsingle(repo, a)
2033 cb = scmutil.revsingle(repo, b)
2033 cb = scmutil.revsingle(repo, b)
2034 pa = pvec.ctxpvec(ca)
2034 pa = pvec.ctxpvec(ca)
2035 pb = pvec.ctxpvec(cb)
2035 pb = pvec.ctxpvec(cb)
2036 if pa == pb:
2036 if pa == pb:
2037 rel = "="
2037 rel = "="
2038 elif pa > pb:
2038 elif pa > pb:
2039 rel = ">"
2039 rel = ">"
2040 elif pa < pb:
2040 elif pa < pb:
2041 rel = "<"
2041 rel = "<"
2042 elif pa | pb:
2042 elif pa | pb:
2043 rel = "|"
2043 rel = "|"
2044 ui.write(_("a: %s\n") % pa)
2044 ui.write(_("a: %s\n") % pa)
2045 ui.write(_("b: %s\n") % pb)
2045 ui.write(_("b: %s\n") % pb)
2046 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2046 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2047 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2047 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2048 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2048 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2049 pa.distance(pb), rel))
2049 pa.distance(pb), rel))
2050
2050
2051 @command('debugrebuildstate',
2051 @command('debugrebuildstate',
2052 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2052 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2053 _('[-r REV] [REV]'))
2053 _('[-r REV] [REV]'))
2054 def debugrebuildstate(ui, repo, rev="tip"):
2054 def debugrebuildstate(ui, repo, rev="tip"):
2055 """rebuild the dirstate as it would look like for the given revision"""
2055 """rebuild the dirstate as it would look like for the given revision"""
2056 ctx = scmutil.revsingle(repo, rev)
2056 ctx = scmutil.revsingle(repo, rev)
2057 wlock = repo.wlock()
2057 wlock = repo.wlock()
2058 try:
2058 try:
2059 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2059 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2060 finally:
2060 finally:
2061 wlock.release()
2061 wlock.release()
2062
2062
2063 @command('debugrename',
2063 @command('debugrename',
2064 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2064 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2065 _('[-r REV] FILE'))
2065 _('[-r REV] FILE'))
2066 def debugrename(ui, repo, file1, *pats, **opts):
2066 def debugrename(ui, repo, file1, *pats, **opts):
2067 """dump rename information"""
2067 """dump rename information"""
2068
2068
2069 ctx = scmutil.revsingle(repo, opts.get('rev'))
2069 ctx = scmutil.revsingle(repo, opts.get('rev'))
2070 m = scmutil.match(ctx, (file1,) + pats, opts)
2070 m = scmutil.match(ctx, (file1,) + pats, opts)
2071 for abs in ctx.walk(m):
2071 for abs in ctx.walk(m):
2072 fctx = ctx[abs]
2072 fctx = ctx[abs]
2073 o = fctx.filelog().renamed(fctx.filenode())
2073 o = fctx.filelog().renamed(fctx.filenode())
2074 rel = m.rel(abs)
2074 rel = m.rel(abs)
2075 if o:
2075 if o:
2076 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2076 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2077 else:
2077 else:
2078 ui.write(_("%s not renamed\n") % rel)
2078 ui.write(_("%s not renamed\n") % rel)
2079
2079
2080 @command('debugrevlog',
2080 @command('debugrevlog',
2081 [('c', 'changelog', False, _('open changelog')),
2081 [('c', 'changelog', False, _('open changelog')),
2082 ('m', 'manifest', False, _('open manifest')),
2082 ('m', 'manifest', False, _('open manifest')),
2083 ('d', 'dump', False, _('dump index data'))],
2083 ('d', 'dump', False, _('dump index data'))],
2084 _('-c|-m|FILE'))
2084 _('-c|-m|FILE'))
2085 def debugrevlog(ui, repo, file_ = None, **opts):
2085 def debugrevlog(ui, repo, file_ = None, **opts):
2086 """show data and statistics about a revlog"""
2086 """show data and statistics about a revlog"""
2087 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2087 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2088
2088
2089 if opts.get("dump"):
2089 if opts.get("dump"):
2090 numrevs = len(r)
2090 numrevs = len(r)
2091 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2091 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2092 " rawsize totalsize compression heads\n")
2092 " rawsize totalsize compression heads\n")
2093 ts = 0
2093 ts = 0
2094 heads = set()
2094 heads = set()
2095 for rev in xrange(numrevs):
2095 for rev in xrange(numrevs):
2096 dbase = r.deltaparent(rev)
2096 dbase = r.deltaparent(rev)
2097 if dbase == -1:
2097 if dbase == -1:
2098 dbase = rev
2098 dbase = rev
2099 cbase = r.chainbase(rev)
2099 cbase = r.chainbase(rev)
2100 p1, p2 = r.parentrevs(rev)
2100 p1, p2 = r.parentrevs(rev)
2101 rs = r.rawsize(rev)
2101 rs = r.rawsize(rev)
2102 ts = ts + rs
2102 ts = ts + rs
2103 heads -= set(r.parentrevs(rev))
2103 heads -= set(r.parentrevs(rev))
2104 heads.add(rev)
2104 heads.add(rev)
2105 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2105 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2106 (rev, p1, p2, r.start(rev), r.end(rev),
2106 (rev, p1, p2, r.start(rev), r.end(rev),
2107 r.start(dbase), r.start(cbase),
2107 r.start(dbase), r.start(cbase),
2108 r.start(p1), r.start(p2),
2108 r.start(p1), r.start(p2),
2109 rs, ts, ts / r.end(rev), len(heads)))
2109 rs, ts, ts / r.end(rev), len(heads)))
2110 return 0
2110 return 0
2111
2111
2112 v = r.version
2112 v = r.version
2113 format = v & 0xFFFF
2113 format = v & 0xFFFF
2114 flags = []
2114 flags = []
2115 gdelta = False
2115 gdelta = False
2116 if v & revlog.REVLOGNGINLINEDATA:
2116 if v & revlog.REVLOGNGINLINEDATA:
2117 flags.append('inline')
2117 flags.append('inline')
2118 if v & revlog.REVLOGGENERALDELTA:
2118 if v & revlog.REVLOGGENERALDELTA:
2119 gdelta = True
2119 gdelta = True
2120 flags.append('generaldelta')
2120 flags.append('generaldelta')
2121 if not flags:
2121 if not flags:
2122 flags = ['(none)']
2122 flags = ['(none)']
2123
2123
2124 nummerges = 0
2124 nummerges = 0
2125 numfull = 0
2125 numfull = 0
2126 numprev = 0
2126 numprev = 0
2127 nump1 = 0
2127 nump1 = 0
2128 nump2 = 0
2128 nump2 = 0
2129 numother = 0
2129 numother = 0
2130 nump1prev = 0
2130 nump1prev = 0
2131 nump2prev = 0
2131 nump2prev = 0
2132 chainlengths = []
2132 chainlengths = []
2133
2133
2134 datasize = [None, 0, 0L]
2134 datasize = [None, 0, 0L]
2135 fullsize = [None, 0, 0L]
2135 fullsize = [None, 0, 0L]
2136 deltasize = [None, 0, 0L]
2136 deltasize = [None, 0, 0L]
2137
2137
2138 def addsize(size, l):
2138 def addsize(size, l):
2139 if l[0] is None or size < l[0]:
2139 if l[0] is None or size < l[0]:
2140 l[0] = size
2140 l[0] = size
2141 if size > l[1]:
2141 if size > l[1]:
2142 l[1] = size
2142 l[1] = size
2143 l[2] += size
2143 l[2] += size
2144
2144
2145 numrevs = len(r)
2145 numrevs = len(r)
2146 for rev in xrange(numrevs):
2146 for rev in xrange(numrevs):
2147 p1, p2 = r.parentrevs(rev)
2147 p1, p2 = r.parentrevs(rev)
2148 delta = r.deltaparent(rev)
2148 delta = r.deltaparent(rev)
2149 if format > 0:
2149 if format > 0:
2150 addsize(r.rawsize(rev), datasize)
2150 addsize(r.rawsize(rev), datasize)
2151 if p2 != nullrev:
2151 if p2 != nullrev:
2152 nummerges += 1
2152 nummerges += 1
2153 size = r.length(rev)
2153 size = r.length(rev)
2154 if delta == nullrev:
2154 if delta == nullrev:
2155 chainlengths.append(0)
2155 chainlengths.append(0)
2156 numfull += 1
2156 numfull += 1
2157 addsize(size, fullsize)
2157 addsize(size, fullsize)
2158 else:
2158 else:
2159 chainlengths.append(chainlengths[delta] + 1)
2159 chainlengths.append(chainlengths[delta] + 1)
2160 addsize(size, deltasize)
2160 addsize(size, deltasize)
2161 if delta == rev - 1:
2161 if delta == rev - 1:
2162 numprev += 1
2162 numprev += 1
2163 if delta == p1:
2163 if delta == p1:
2164 nump1prev += 1
2164 nump1prev += 1
2165 elif delta == p2:
2165 elif delta == p2:
2166 nump2prev += 1
2166 nump2prev += 1
2167 elif delta == p1:
2167 elif delta == p1:
2168 nump1 += 1
2168 nump1 += 1
2169 elif delta == p2:
2169 elif delta == p2:
2170 nump2 += 1
2170 nump2 += 1
2171 elif delta != nullrev:
2171 elif delta != nullrev:
2172 numother += 1
2172 numother += 1
2173
2173
2174 numdeltas = numrevs - numfull
2174 numdeltas = numrevs - numfull
2175 numoprev = numprev - nump1prev - nump2prev
2175 numoprev = numprev - nump1prev - nump2prev
2176 totalrawsize = datasize[2]
2176 totalrawsize = datasize[2]
2177 datasize[2] /= numrevs
2177 datasize[2] /= numrevs
2178 fulltotal = fullsize[2]
2178 fulltotal = fullsize[2]
2179 fullsize[2] /= numfull
2179 fullsize[2] /= numfull
2180 deltatotal = deltasize[2]
2180 deltatotal = deltasize[2]
2181 deltasize[2] /= numrevs - numfull
2181 deltasize[2] /= numrevs - numfull
2182 totalsize = fulltotal + deltatotal
2182 totalsize = fulltotal + deltatotal
2183 avgchainlen = sum(chainlengths) / numrevs
2183 avgchainlen = sum(chainlengths) / numrevs
2184 compratio = totalrawsize / totalsize
2184 compratio = totalrawsize / totalsize
2185
2185
2186 basedfmtstr = '%%%dd\n'
2186 basedfmtstr = '%%%dd\n'
2187 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2187 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2188
2188
2189 def dfmtstr(max):
2189 def dfmtstr(max):
2190 return basedfmtstr % len(str(max))
2190 return basedfmtstr % len(str(max))
2191 def pcfmtstr(max, padding=0):
2191 def pcfmtstr(max, padding=0):
2192 return basepcfmtstr % (len(str(max)), ' ' * padding)
2192 return basepcfmtstr % (len(str(max)), ' ' * padding)
2193
2193
2194 def pcfmt(value, total):
2194 def pcfmt(value, total):
2195 return (value, 100 * float(value) / total)
2195 return (value, 100 * float(value) / total)
2196
2196
2197 ui.write('format : %d\n' % format)
2197 ui.write('format : %d\n' % format)
2198 ui.write('flags : %s\n' % ', '.join(flags))
2198 ui.write('flags : %s\n' % ', '.join(flags))
2199
2199
2200 ui.write('\n')
2200 ui.write('\n')
2201 fmt = pcfmtstr(totalsize)
2201 fmt = pcfmtstr(totalsize)
2202 fmt2 = dfmtstr(totalsize)
2202 fmt2 = dfmtstr(totalsize)
2203 ui.write('revisions : ' + fmt2 % numrevs)
2203 ui.write('revisions : ' + fmt2 % numrevs)
2204 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2204 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2205 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2205 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2206 ui.write('revisions : ' + fmt2 % numrevs)
2206 ui.write('revisions : ' + fmt2 % numrevs)
2207 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2207 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2208 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2208 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2209 ui.write('revision size : ' + fmt2 % totalsize)
2209 ui.write('revision size : ' + fmt2 % totalsize)
2210 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2210 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2211 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2211 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2212
2212
2213 ui.write('\n')
2213 ui.write('\n')
2214 fmt = dfmtstr(max(avgchainlen, compratio))
2214 fmt = dfmtstr(max(avgchainlen, compratio))
2215 ui.write('avg chain length : ' + fmt % avgchainlen)
2215 ui.write('avg chain length : ' + fmt % avgchainlen)
2216 ui.write('compression ratio : ' + fmt % compratio)
2216 ui.write('compression ratio : ' + fmt % compratio)
2217
2217
2218 if format > 0:
2218 if format > 0:
2219 ui.write('\n')
2219 ui.write('\n')
2220 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2220 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2221 % tuple(datasize))
2221 % tuple(datasize))
2222 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2222 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2223 % tuple(fullsize))
2223 % tuple(fullsize))
2224 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2224 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2225 % tuple(deltasize))
2225 % tuple(deltasize))
2226
2226
2227 if numdeltas > 0:
2227 if numdeltas > 0:
2228 ui.write('\n')
2228 ui.write('\n')
2229 fmt = pcfmtstr(numdeltas)
2229 fmt = pcfmtstr(numdeltas)
2230 fmt2 = pcfmtstr(numdeltas, 4)
2230 fmt2 = pcfmtstr(numdeltas, 4)
2231 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2231 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2232 if numprev > 0:
2232 if numprev > 0:
2233 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2233 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2234 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2234 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2235 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2235 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2236 if gdelta:
2236 if gdelta:
2237 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2237 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2238 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2238 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2239 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2239 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2240
2240
2241 @command('debugrevspec', [], ('REVSPEC'))
2241 @command('debugrevspec', [], ('REVSPEC'))
2242 def debugrevspec(ui, repo, expr):
2242 def debugrevspec(ui, repo, expr):
2243 """parse and apply a revision specification
2243 """parse and apply a revision specification
2244
2244
2245 Use --verbose to print the parsed tree before and after aliases
2245 Use --verbose to print the parsed tree before and after aliases
2246 expansion.
2246 expansion.
2247 """
2247 """
2248 if ui.verbose:
2248 if ui.verbose:
2249 tree = revset.parse(expr)[0]
2249 tree = revset.parse(expr)[0]
2250 ui.note(revset.prettyformat(tree), "\n")
2250 ui.note(revset.prettyformat(tree), "\n")
2251 newtree = revset.findaliases(ui, tree)
2251 newtree = revset.findaliases(ui, tree)
2252 if newtree != tree:
2252 if newtree != tree:
2253 ui.note(revset.prettyformat(newtree), "\n")
2253 ui.note(revset.prettyformat(newtree), "\n")
2254 func = revset.match(ui, expr)
2254 func = revset.match(ui, expr)
2255 for c in func(repo, range(len(repo))):
2255 for c in func(repo, range(len(repo))):
2256 ui.write("%s\n" % c)
2256 ui.write("%s\n" % c)
2257
2257
2258 @command('debugsetparents', [], _('REV1 [REV2]'))
2258 @command('debugsetparents', [], _('REV1 [REV2]'))
2259 def debugsetparents(ui, repo, rev1, rev2=None):
2259 def debugsetparents(ui, repo, rev1, rev2=None):
2260 """manually set the parents of the current working directory
2260 """manually set the parents of the current working directory
2261
2261
2262 This is useful for writing repository conversion tools, but should
2262 This is useful for writing repository conversion tools, but should
2263 be used with care.
2263 be used with care.
2264
2264
2265 Returns 0 on success.
2265 Returns 0 on success.
2266 """
2266 """
2267
2267
2268 r1 = scmutil.revsingle(repo, rev1).node()
2268 r1 = scmutil.revsingle(repo, rev1).node()
2269 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2269 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2270
2270
2271 wlock = repo.wlock()
2271 wlock = repo.wlock()
2272 try:
2272 try:
2273 repo.dirstate.setparents(r1, r2)
2273 repo.dirstate.setparents(r1, r2)
2274 finally:
2274 finally:
2275 wlock.release()
2275 wlock.release()
2276
2276
2277 @command('debugstate',
2277 @command('debugstate',
2278 [('', 'nodates', None, _('do not display the saved mtime')),
2278 [('', 'nodates', None, _('do not display the saved mtime')),
2279 ('', 'datesort', None, _('sort by saved mtime'))],
2279 ('', 'datesort', None, _('sort by saved mtime'))],
2280 _('[OPTION]...'))
2280 _('[OPTION]...'))
2281 def debugstate(ui, repo, nodates=None, datesort=None):
2281 def debugstate(ui, repo, nodates=None, datesort=None):
2282 """show the contents of the current dirstate"""
2282 """show the contents of the current dirstate"""
2283 timestr = ""
2283 timestr = ""
2284 showdate = not nodates
2284 showdate = not nodates
2285 if datesort:
2285 if datesort:
2286 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2286 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2287 else:
2287 else:
2288 keyfunc = None # sort by filename
2288 keyfunc = None # sort by filename
2289 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2289 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2290 if showdate:
2290 if showdate:
2291 if ent[3] == -1:
2291 if ent[3] == -1:
2292 # Pad or slice to locale representation
2292 # Pad or slice to locale representation
2293 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2293 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2294 time.localtime(0)))
2294 time.localtime(0)))
2295 timestr = 'unset'
2295 timestr = 'unset'
2296 timestr = (timestr[:locale_len] +
2296 timestr = (timestr[:locale_len] +
2297 ' ' * (locale_len - len(timestr)))
2297 ' ' * (locale_len - len(timestr)))
2298 else:
2298 else:
2299 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2299 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2300 time.localtime(ent[3]))
2300 time.localtime(ent[3]))
2301 if ent[1] & 020000:
2301 if ent[1] & 020000:
2302 mode = 'lnk'
2302 mode = 'lnk'
2303 else:
2303 else:
2304 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2304 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2305 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2305 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2306 for f in repo.dirstate.copies():
2306 for f in repo.dirstate.copies():
2307 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2307 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2308
2308
2309 @command('debugsub',
2309 @command('debugsub',
2310 [('r', 'rev', '',
2310 [('r', 'rev', '',
2311 _('revision to check'), _('REV'))],
2311 _('revision to check'), _('REV'))],
2312 _('[-r REV] [REV]'))
2312 _('[-r REV] [REV]'))
2313 def debugsub(ui, repo, rev=None):
2313 def debugsub(ui, repo, rev=None):
2314 ctx = scmutil.revsingle(repo, rev, None)
2314 ctx = scmutil.revsingle(repo, rev, None)
2315 for k, v in sorted(ctx.substate.items()):
2315 for k, v in sorted(ctx.substate.items()):
2316 ui.write('path %s\n' % k)
2316 ui.write('path %s\n' % k)
2317 ui.write(' source %s\n' % v[0])
2317 ui.write(' source %s\n' % v[0])
2318 ui.write(' revision %s\n' % v[1])
2318 ui.write(' revision %s\n' % v[1])
2319
2319
2320 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2320 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2321 def debugwalk(ui, repo, *pats, **opts):
2321 def debugwalk(ui, repo, *pats, **opts):
2322 """show how files match on given patterns"""
2322 """show how files match on given patterns"""
2323 m = scmutil.match(repo[None], pats, opts)
2323 m = scmutil.match(repo[None], pats, opts)
2324 items = list(repo.walk(m))
2324 items = list(repo.walk(m))
2325 if not items:
2325 if not items:
2326 return
2326 return
2327 fmt = 'f %%-%ds %%-%ds %%s' % (
2327 fmt = 'f %%-%ds %%-%ds %%s' % (
2328 max([len(abs) for abs in items]),
2328 max([len(abs) for abs in items]),
2329 max([len(m.rel(abs)) for abs in items]))
2329 max([len(m.rel(abs)) for abs in items]))
2330 for abs in items:
2330 for abs in items:
2331 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2331 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2332 ui.write("%s\n" % line.rstrip())
2332 ui.write("%s\n" % line.rstrip())
2333
2333
2334 @command('debugwireargs',
2334 @command('debugwireargs',
2335 [('', 'three', '', 'three'),
2335 [('', 'three', '', 'three'),
2336 ('', 'four', '', 'four'),
2336 ('', 'four', '', 'four'),
2337 ('', 'five', '', 'five'),
2337 ('', 'five', '', 'five'),
2338 ] + remoteopts,
2338 ] + remoteopts,
2339 _('REPO [OPTIONS]... [ONE [TWO]]'))
2339 _('REPO [OPTIONS]... [ONE [TWO]]'))
2340 def debugwireargs(ui, repopath, *vals, **opts):
2340 def debugwireargs(ui, repopath, *vals, **opts):
2341 repo = hg.peer(ui, opts, repopath)
2341 repo = hg.peer(ui, opts, repopath)
2342 for opt in remoteopts:
2342 for opt in remoteopts:
2343 del opts[opt[1]]
2343 del opts[opt[1]]
2344 args = {}
2344 args = {}
2345 for k, v in opts.iteritems():
2345 for k, v in opts.iteritems():
2346 if v:
2346 if v:
2347 args[k] = v
2347 args[k] = v
2348 # run twice to check that we don't mess up the stream for the next command
2348 # run twice to check that we don't mess up the stream for the next command
2349 res1 = repo.debugwireargs(*vals, **args)
2349 res1 = repo.debugwireargs(*vals, **args)
2350 res2 = repo.debugwireargs(*vals, **args)
2350 res2 = repo.debugwireargs(*vals, **args)
2351 ui.write("%s\n" % res1)
2351 ui.write("%s\n" % res1)
2352 if res1 != res2:
2352 if res1 != res2:
2353 ui.warn("%s\n" % res2)
2353 ui.warn("%s\n" % res2)
2354
2354
2355 @command('^diff',
2355 @command('^diff',
2356 [('r', 'rev', [], _('revision'), _('REV')),
2356 [('r', 'rev', [], _('revision'), _('REV')),
2357 ('c', 'change', '', _('change made by revision'), _('REV'))
2357 ('c', 'change', '', _('change made by revision'), _('REV'))
2358 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2358 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2359 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2359 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2360 def diff(ui, repo, *pats, **opts):
2360 def diff(ui, repo, *pats, **opts):
2361 """diff repository (or selected files)
2361 """diff repository (or selected files)
2362
2362
2363 Show differences between revisions for the specified files.
2363 Show differences between revisions for the specified files.
2364
2364
2365 Differences between files are shown using the unified diff format.
2365 Differences between files are shown using the unified diff format.
2366
2366
2367 .. note::
2367 .. note::
2368 diff may generate unexpected results for merges, as it will
2368 diff may generate unexpected results for merges, as it will
2369 default to comparing against the working directory's first
2369 default to comparing against the working directory's first
2370 parent changeset if no revisions are specified.
2370 parent changeset if no revisions are specified.
2371
2371
2372 When two revision arguments are given, then changes are shown
2372 When two revision arguments are given, then changes are shown
2373 between those revisions. If only one revision is specified then
2373 between those revisions. If only one revision is specified then
2374 that revision is compared to the working directory, and, when no
2374 that revision is compared to the working directory, and, when no
2375 revisions are specified, the working directory files are compared
2375 revisions are specified, the working directory files are compared
2376 to its parent.
2376 to its parent.
2377
2377
2378 Alternatively you can specify -c/--change with a revision to see
2378 Alternatively you can specify -c/--change with a revision to see
2379 the changes in that changeset relative to its first parent.
2379 the changes in that changeset relative to its first parent.
2380
2380
2381 Without the -a/--text option, diff will avoid generating diffs of
2381 Without the -a/--text option, diff will avoid generating diffs of
2382 files it detects as binary. With -a, diff will generate a diff
2382 files it detects as binary. With -a, diff will generate a diff
2383 anyway, probably with undesirable results.
2383 anyway, probably with undesirable results.
2384
2384
2385 Use the -g/--git option to generate diffs in the git extended diff
2385 Use the -g/--git option to generate diffs in the git extended diff
2386 format. For more information, read :hg:`help diffs`.
2386 format. For more information, read :hg:`help diffs`.
2387
2387
2388 .. container:: verbose
2388 .. container:: verbose
2389
2389
2390 Examples:
2390 Examples:
2391
2391
2392 - compare a file in the current working directory to its parent::
2392 - compare a file in the current working directory to its parent::
2393
2393
2394 hg diff foo.c
2394 hg diff foo.c
2395
2395
2396 - compare two historical versions of a directory, with rename info::
2396 - compare two historical versions of a directory, with rename info::
2397
2397
2398 hg diff --git -r 1.0:1.2 lib/
2398 hg diff --git -r 1.0:1.2 lib/
2399
2399
2400 - get change stats relative to the last change on some date::
2400 - get change stats relative to the last change on some date::
2401
2401
2402 hg diff --stat -r "date('may 2')"
2402 hg diff --stat -r "date('may 2')"
2403
2403
2404 - diff all newly-added files that contain a keyword::
2404 - diff all newly-added files that contain a keyword::
2405
2405
2406 hg diff "set:added() and grep(GNU)"
2406 hg diff "set:added() and grep(GNU)"
2407
2407
2408 - compare a revision and its parents::
2408 - compare a revision and its parents::
2409
2409
2410 hg diff -c 9353 # compare against first parent
2410 hg diff -c 9353 # compare against first parent
2411 hg diff -r 9353^:9353 # same using revset syntax
2411 hg diff -r 9353^:9353 # same using revset syntax
2412 hg diff -r 9353^2:9353 # compare against the second parent
2412 hg diff -r 9353^2:9353 # compare against the second parent
2413
2413
2414 Returns 0 on success.
2414 Returns 0 on success.
2415 """
2415 """
2416
2416
2417 revs = opts.get('rev')
2417 revs = opts.get('rev')
2418 change = opts.get('change')
2418 change = opts.get('change')
2419 stat = opts.get('stat')
2419 stat = opts.get('stat')
2420 reverse = opts.get('reverse')
2420 reverse = opts.get('reverse')
2421
2421
2422 if revs and change:
2422 if revs and change:
2423 msg = _('cannot specify --rev and --change at the same time')
2423 msg = _('cannot specify --rev and --change at the same time')
2424 raise util.Abort(msg)
2424 raise util.Abort(msg)
2425 elif change:
2425 elif change:
2426 node2 = scmutil.revsingle(repo, change, None).node()
2426 node2 = scmutil.revsingle(repo, change, None).node()
2427 node1 = repo[node2].p1().node()
2427 node1 = repo[node2].p1().node()
2428 else:
2428 else:
2429 node1, node2 = scmutil.revpair(repo, revs)
2429 node1, node2 = scmutil.revpair(repo, revs)
2430
2430
2431 if reverse:
2431 if reverse:
2432 node1, node2 = node2, node1
2432 node1, node2 = node2, node1
2433
2433
2434 diffopts = patch.diffopts(ui, opts)
2434 diffopts = patch.diffopts(ui, opts)
2435 m = scmutil.match(repo[node2], pats, opts)
2435 m = scmutil.match(repo[node2], pats, opts)
2436 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2436 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2437 listsubrepos=opts.get('subrepos'))
2437 listsubrepos=opts.get('subrepos'))
2438
2438
2439 @command('^export',
2439 @command('^export',
2440 [('o', 'output', '',
2440 [('o', 'output', '',
2441 _('print output to file with formatted name'), _('FORMAT')),
2441 _('print output to file with formatted name'), _('FORMAT')),
2442 ('', 'switch-parent', None, _('diff against the second parent')),
2442 ('', 'switch-parent', None, _('diff against the second parent')),
2443 ('r', 'rev', [], _('revisions to export'), _('REV')),
2443 ('r', 'rev', [], _('revisions to export'), _('REV')),
2444 ] + diffopts,
2444 ] + diffopts,
2445 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2445 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2446 def export(ui, repo, *changesets, **opts):
2446 def export(ui, repo, *changesets, **opts):
2447 """dump the header and diffs for one or more changesets
2447 """dump the header and diffs for one or more changesets
2448
2448
2449 Print the changeset header and diffs for one or more revisions.
2449 Print the changeset header and diffs for one or more revisions.
2450
2450
2451 The information shown in the changeset header is: author, date,
2451 The information shown in the changeset header is: author, date,
2452 branch name (if non-default), changeset hash, parent(s) and commit
2452 branch name (if non-default), changeset hash, parent(s) and commit
2453 comment.
2453 comment.
2454
2454
2455 .. note::
2455 .. note::
2456 export may generate unexpected diff output for merge
2456 export may generate unexpected diff output for merge
2457 changesets, as it will compare the merge changeset against its
2457 changesets, as it will compare the merge changeset against its
2458 first parent only.
2458 first parent only.
2459
2459
2460 Output may be to a file, in which case the name of the file is
2460 Output may be to a file, in which case the name of the file is
2461 given using a format string. The formatting rules are as follows:
2461 given using a format string. The formatting rules are as follows:
2462
2462
2463 :``%%``: literal "%" character
2463 :``%%``: literal "%" character
2464 :``%H``: changeset hash (40 hexadecimal digits)
2464 :``%H``: changeset hash (40 hexadecimal digits)
2465 :``%N``: number of patches being generated
2465 :``%N``: number of patches being generated
2466 :``%R``: changeset revision number
2466 :``%R``: changeset revision number
2467 :``%b``: basename of the exporting repository
2467 :``%b``: basename of the exporting repository
2468 :``%h``: short-form changeset hash (12 hexadecimal digits)
2468 :``%h``: short-form changeset hash (12 hexadecimal digits)
2469 :``%m``: first line of the commit message (only alphanumeric characters)
2469 :``%m``: first line of the commit message (only alphanumeric characters)
2470 :``%n``: zero-padded sequence number, starting at 1
2470 :``%n``: zero-padded sequence number, starting at 1
2471 :``%r``: zero-padded changeset revision number
2471 :``%r``: zero-padded changeset revision number
2472
2472
2473 Without the -a/--text option, export will avoid generating diffs
2473 Without the -a/--text option, export will avoid generating diffs
2474 of files it detects as binary. With -a, export will generate a
2474 of files it detects as binary. With -a, export will generate a
2475 diff anyway, probably with undesirable results.
2475 diff anyway, probably with undesirable results.
2476
2476
2477 Use the -g/--git option to generate diffs in the git extended diff
2477 Use the -g/--git option to generate diffs in the git extended diff
2478 format. See :hg:`help diffs` for more information.
2478 format. See :hg:`help diffs` for more information.
2479
2479
2480 With the --switch-parent option, the diff will be against the
2480 With the --switch-parent option, the diff will be against the
2481 second parent. It can be useful to review a merge.
2481 second parent. It can be useful to review a merge.
2482
2482
2483 .. container:: verbose
2483 .. container:: verbose
2484
2484
2485 Examples:
2485 Examples:
2486
2486
2487 - use export and import to transplant a bugfix to the current
2487 - use export and import to transplant a bugfix to the current
2488 branch::
2488 branch::
2489
2489
2490 hg export -r 9353 | hg import -
2490 hg export -r 9353 | hg import -
2491
2491
2492 - export all the changesets between two revisions to a file with
2492 - export all the changesets between two revisions to a file with
2493 rename information::
2493 rename information::
2494
2494
2495 hg export --git -r 123:150 > changes.txt
2495 hg export --git -r 123:150 > changes.txt
2496
2496
2497 - split outgoing changes into a series of patches with
2497 - split outgoing changes into a series of patches with
2498 descriptive names::
2498 descriptive names::
2499
2499
2500 hg export -r "outgoing()" -o "%n-%m.patch"
2500 hg export -r "outgoing()" -o "%n-%m.patch"
2501
2501
2502 Returns 0 on success.
2502 Returns 0 on success.
2503 """
2503 """
2504 changesets += tuple(opts.get('rev', []))
2504 changesets += tuple(opts.get('rev', []))
2505 revs = scmutil.revrange(repo, changesets)
2505 revs = scmutil.revrange(repo, changesets)
2506 if not revs:
2506 if not revs:
2507 raise util.Abort(_("export requires at least one changeset"))
2507 raise util.Abort(_("export requires at least one changeset"))
2508 if len(revs) > 1:
2508 if len(revs) > 1:
2509 ui.note(_('exporting patches:\n'))
2509 ui.note(_('exporting patches:\n'))
2510 else:
2510 else:
2511 ui.note(_('exporting patch:\n'))
2511 ui.note(_('exporting patch:\n'))
2512 cmdutil.export(repo, revs, template=opts.get('output'),
2512 cmdutil.export(repo, revs, template=opts.get('output'),
2513 switch_parent=opts.get('switch_parent'),
2513 switch_parent=opts.get('switch_parent'),
2514 opts=patch.diffopts(ui, opts))
2514 opts=patch.diffopts(ui, opts))
2515
2515
2516 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2516 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2517 def forget(ui, repo, *pats, **opts):
2517 def forget(ui, repo, *pats, **opts):
2518 """forget the specified files on the next commit
2518 """forget the specified files on the next commit
2519
2519
2520 Mark the specified files so they will no longer be tracked
2520 Mark the specified files so they will no longer be tracked
2521 after the next commit.
2521 after the next commit.
2522
2522
2523 This only removes files from the current branch, not from the
2523 This only removes files from the current branch, not from the
2524 entire project history, and it does not delete them from the
2524 entire project history, and it does not delete them from the
2525 working directory.
2525 working directory.
2526
2526
2527 To undo a forget before the next commit, see :hg:`add`.
2527 To undo a forget before the next commit, see :hg:`add`.
2528
2528
2529 .. container:: verbose
2529 .. container:: verbose
2530
2530
2531 Examples:
2531 Examples:
2532
2532
2533 - forget newly-added binary files::
2533 - forget newly-added binary files::
2534
2534
2535 hg forget "set:added() and binary()"
2535 hg forget "set:added() and binary()"
2536
2536
2537 - forget files that would be excluded by .hgignore::
2537 - forget files that would be excluded by .hgignore::
2538
2538
2539 hg forget "set:hgignore()"
2539 hg forget "set:hgignore()"
2540
2540
2541 Returns 0 on success.
2541 Returns 0 on success.
2542 """
2542 """
2543
2543
2544 if not pats:
2544 if not pats:
2545 raise util.Abort(_('no files specified'))
2545 raise util.Abort(_('no files specified'))
2546
2546
2547 m = scmutil.match(repo[None], pats, opts)
2547 m = scmutil.match(repo[None], pats, opts)
2548 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2548 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2549 return rejected and 1 or 0
2549 return rejected and 1 or 0
2550
2550
2551 @command(
2551 @command(
2552 'graft',
2552 'graft',
2553 [('c', 'continue', False, _('resume interrupted graft')),
2553 [('c', 'continue', False, _('resume interrupted graft')),
2554 ('e', 'edit', False, _('invoke editor on commit messages')),
2554 ('e', 'edit', False, _('invoke editor on commit messages')),
2555 ('D', 'currentdate', False,
2555 ('D', 'currentdate', False,
2556 _('record the current date as commit date')),
2556 _('record the current date as commit date')),
2557 ('U', 'currentuser', False,
2557 ('U', 'currentuser', False,
2558 _('record the current user as committer'), _('DATE'))]
2558 _('record the current user as committer'), _('DATE'))]
2559 + commitopts2 + mergetoolopts + dryrunopts,
2559 + commitopts2 + mergetoolopts + dryrunopts,
2560 _('[OPTION]... REVISION...'))
2560 _('[OPTION]... REVISION...'))
2561 def graft(ui, repo, *revs, **opts):
2561 def graft(ui, repo, *revs, **opts):
2562 '''copy changes from other branches onto the current branch
2562 '''copy changes from other branches onto the current branch
2563
2563
2564 This command uses Mercurial's merge logic to copy individual
2564 This command uses Mercurial's merge logic to copy individual
2565 changes from other branches without merging branches in the
2565 changes from other branches without merging branches in the
2566 history graph. This is sometimes known as 'backporting' or
2566 history graph. This is sometimes known as 'backporting' or
2567 'cherry-picking'. By default, graft will copy user, date, and
2567 'cherry-picking'. By default, graft will copy user, date, and
2568 description from the source changesets.
2568 description from the source changesets.
2569
2569
2570 Changesets that are ancestors of the current revision, that have
2570 Changesets that are ancestors of the current revision, that have
2571 already been grafted, or that are merges will be skipped.
2571 already been grafted, or that are merges will be skipped.
2572
2572
2573 If a graft merge results in conflicts, the graft process is
2573 If a graft merge results in conflicts, the graft process is
2574 interrupted so that the current merge can be manually resolved.
2574 interrupted so that the current merge can be manually resolved.
2575 Once all conflicts are addressed, the graft process can be
2575 Once all conflicts are addressed, the graft process can be
2576 continued with the -c/--continue option.
2576 continued with the -c/--continue option.
2577
2577
2578 .. note::
2578 .. note::
2579 The -c/--continue option does not reapply earlier options.
2579 The -c/--continue option does not reapply earlier options.
2580
2580
2581 .. container:: verbose
2581 .. container:: verbose
2582
2582
2583 Examples:
2583 Examples:
2584
2584
2585 - copy a single change to the stable branch and edit its description::
2585 - copy a single change to the stable branch and edit its description::
2586
2586
2587 hg update stable
2587 hg update stable
2588 hg graft --edit 9393
2588 hg graft --edit 9393
2589
2589
2590 - graft a range of changesets with one exception, updating dates::
2590 - graft a range of changesets with one exception, updating dates::
2591
2591
2592 hg graft -D "2085::2093 and not 2091"
2592 hg graft -D "2085::2093 and not 2091"
2593
2593
2594 - continue a graft after resolving conflicts::
2594 - continue a graft after resolving conflicts::
2595
2595
2596 hg graft -c
2596 hg graft -c
2597
2597
2598 - show the source of a grafted changeset::
2598 - show the source of a grafted changeset::
2599
2599
2600 hg log --debug -r tip
2600 hg log --debug -r tip
2601
2601
2602 Returns 0 on successful completion.
2602 Returns 0 on successful completion.
2603 '''
2603 '''
2604
2604
2605 if not opts.get('user') and opts.get('currentuser'):
2605 if not opts.get('user') and opts.get('currentuser'):
2606 opts['user'] = ui.username()
2606 opts['user'] = ui.username()
2607 if not opts.get('date') and opts.get('currentdate'):
2607 if not opts.get('date') and opts.get('currentdate'):
2608 opts['date'] = "%d %d" % util.makedate()
2608 opts['date'] = "%d %d" % util.makedate()
2609
2609
2610 editor = None
2610 editor = None
2611 if opts.get('edit'):
2611 if opts.get('edit'):
2612 editor = cmdutil.commitforceeditor
2612 editor = cmdutil.commitforceeditor
2613
2613
2614 cont = False
2614 cont = False
2615 if opts['continue']:
2615 if opts['continue']:
2616 cont = True
2616 cont = True
2617 if revs:
2617 if revs:
2618 raise util.Abort(_("can't specify --continue and revisions"))
2618 raise util.Abort(_("can't specify --continue and revisions"))
2619 # read in unfinished revisions
2619 # read in unfinished revisions
2620 try:
2620 try:
2621 nodes = repo.opener.read('graftstate').splitlines()
2621 nodes = repo.opener.read('graftstate').splitlines()
2622 revs = [repo[node].rev() for node in nodes]
2622 revs = [repo[node].rev() for node in nodes]
2623 except IOError, inst:
2623 except IOError, inst:
2624 if inst.errno != errno.ENOENT:
2624 if inst.errno != errno.ENOENT:
2625 raise
2625 raise
2626 raise util.Abort(_("no graft state found, can't continue"))
2626 raise util.Abort(_("no graft state found, can't continue"))
2627 else:
2627 else:
2628 cmdutil.bailifchanged(repo)
2628 cmdutil.bailifchanged(repo)
2629 if not revs:
2629 if not revs:
2630 raise util.Abort(_('no revisions specified'))
2630 raise util.Abort(_('no revisions specified'))
2631 revs = scmutil.revrange(repo, revs)
2631 revs = scmutil.revrange(repo, revs)
2632
2632
2633 # check for merges
2633 # check for merges
2634 for rev in repo.revs('%ld and merge()', revs):
2634 for rev in repo.revs('%ld and merge()', revs):
2635 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2635 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2636 revs.remove(rev)
2636 revs.remove(rev)
2637 if not revs:
2637 if not revs:
2638 return -1
2638 return -1
2639
2639
2640 # check for ancestors of dest branch
2640 # check for ancestors of dest branch
2641 for rev in repo.revs('::. and %ld', revs):
2641 for rev in repo.revs('::. and %ld', revs):
2642 ui.warn(_('skipping ancestor revision %s\n') % rev)
2642 ui.warn(_('skipping ancestor revision %s\n') % rev)
2643 revs.remove(rev)
2643 revs.remove(rev)
2644 if not revs:
2644 if not revs:
2645 return -1
2645 return -1
2646
2646
2647 # analyze revs for earlier grafts
2647 # analyze revs for earlier grafts
2648 ids = {}
2648 ids = {}
2649 for ctx in repo.set("%ld", revs):
2649 for ctx in repo.set("%ld", revs):
2650 ids[ctx.hex()] = ctx.rev()
2650 ids[ctx.hex()] = ctx.rev()
2651 n = ctx.extra().get('source')
2651 n = ctx.extra().get('source')
2652 if n:
2652 if n:
2653 ids[n] = ctx.rev()
2653 ids[n] = ctx.rev()
2654
2654
2655 # check ancestors for earlier grafts
2655 # check ancestors for earlier grafts
2656 ui.debug('scanning for duplicate grafts\n')
2656 ui.debug('scanning for duplicate grafts\n')
2657 for ctx in repo.set("::. - ::%ld", revs):
2657 for ctx in repo.set("::. - ::%ld", revs):
2658 n = ctx.extra().get('source')
2658 n = ctx.extra().get('source')
2659 if n in ids:
2659 if n in ids:
2660 r = repo[n].rev()
2660 r = repo[n].rev()
2661 if r in revs:
2661 if r in revs:
2662 ui.warn(_('skipping already grafted revision %s\n') % r)
2662 ui.warn(_('skipping already grafted revision %s\n') % r)
2663 revs.remove(r)
2663 revs.remove(r)
2664 elif ids[n] in revs:
2664 elif ids[n] in revs:
2665 ui.warn(_('skipping already grafted revision %s '
2665 ui.warn(_('skipping already grafted revision %s '
2666 '(same origin %d)\n') % (ids[n], r))
2666 '(same origin %d)\n') % (ids[n], r))
2667 revs.remove(ids[n])
2667 revs.remove(ids[n])
2668 elif ctx.hex() in ids:
2668 elif ctx.hex() in ids:
2669 r = ids[ctx.hex()]
2669 r = ids[ctx.hex()]
2670 ui.warn(_('skipping already grafted revision %s '
2670 ui.warn(_('skipping already grafted revision %s '
2671 '(was grafted from %d)\n') % (r, ctx.rev()))
2671 '(was grafted from %d)\n') % (r, ctx.rev()))
2672 revs.remove(r)
2672 revs.remove(r)
2673 if not revs:
2673 if not revs:
2674 return -1
2674 return -1
2675
2675
2676 wlock = repo.wlock()
2676 wlock = repo.wlock()
2677 try:
2677 try:
2678 for pos, ctx in enumerate(repo.set("%ld", revs)):
2678 for pos, ctx in enumerate(repo.set("%ld", revs)):
2679 current = repo['.']
2679 current = repo['.']
2680
2680
2681 ui.status(_('grafting revision %s\n') % ctx.rev())
2681 ui.status(_('grafting revision %s\n') % ctx.rev())
2682 if opts.get('dry_run'):
2682 if opts.get('dry_run'):
2683 continue
2683 continue
2684
2684
2685 # we don't merge the first commit when continuing
2685 # we don't merge the first commit when continuing
2686 if not cont:
2686 if not cont:
2687 # perform the graft merge with p1(rev) as 'ancestor'
2687 # perform the graft merge with p1(rev) as 'ancestor'
2688 try:
2688 try:
2689 # ui.forcemerge is an internal variable, do not document
2689 # ui.forcemerge is an internal variable, do not document
2690 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2690 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2691 stats = mergemod.update(repo, ctx.node(), True, True, False,
2691 stats = mergemod.update(repo, ctx.node(), True, True, False,
2692 ctx.p1().node())
2692 ctx.p1().node())
2693 finally:
2693 finally:
2694 ui.setconfig('ui', 'forcemerge', '')
2694 ui.setconfig('ui', 'forcemerge', '')
2695 # drop the second merge parent
2695 # drop the second merge parent
2696 repo.dirstate.setparents(current.node(), nullid)
2696 repo.dirstate.setparents(current.node(), nullid)
2697 repo.dirstate.write()
2697 repo.dirstate.write()
2698 # fix up dirstate for copies and renames
2698 # fix up dirstate for copies and renames
2699 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2699 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2700 # report any conflicts
2700 # report any conflicts
2701 if stats and stats[3] > 0:
2701 if stats and stats[3] > 0:
2702 # write out state for --continue
2702 # write out state for --continue
2703 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2703 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2704 repo.opener.write('graftstate', ''.join(nodelines))
2704 repo.opener.write('graftstate', ''.join(nodelines))
2705 raise util.Abort(
2705 raise util.Abort(
2706 _("unresolved conflicts, can't continue"),
2706 _("unresolved conflicts, can't continue"),
2707 hint=_('use hg resolve and hg graft --continue'))
2707 hint=_('use hg resolve and hg graft --continue'))
2708 else:
2708 else:
2709 cont = False
2709 cont = False
2710
2710
2711 # commit
2711 # commit
2712 source = ctx.extra().get('source')
2712 source = ctx.extra().get('source')
2713 if not source:
2713 if not source:
2714 source = ctx.hex()
2714 source = ctx.hex()
2715 extra = {'source': source}
2715 extra = {'source': source}
2716 user = ctx.user()
2716 user = ctx.user()
2717 if opts.get('user'):
2717 if opts.get('user'):
2718 user = opts['user']
2718 user = opts['user']
2719 date = ctx.date()
2719 date = ctx.date()
2720 if opts.get('date'):
2720 if opts.get('date'):
2721 date = opts['date']
2721 date = opts['date']
2722 repo.commit(text=ctx.description(), user=user,
2722 repo.commit(text=ctx.description(), user=user,
2723 date=date, extra=extra, editor=editor)
2723 date=date, extra=extra, editor=editor)
2724 finally:
2724 finally:
2725 wlock.release()
2725 wlock.release()
2726
2726
2727 # remove state when we complete successfully
2727 # remove state when we complete successfully
2728 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2728 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2729 util.unlinkpath(repo.join('graftstate'))
2729 util.unlinkpath(repo.join('graftstate'))
2730
2730
2731 return 0
2731 return 0
2732
2732
2733 @command('grep',
2733 @command('grep',
2734 [('0', 'print0', None, _('end fields with NUL')),
2734 [('0', 'print0', None, _('end fields with NUL')),
2735 ('', 'all', None, _('print all revisions that match')),
2735 ('', 'all', None, _('print all revisions that match')),
2736 ('a', 'text', None, _('treat all files as text')),
2736 ('a', 'text', None, _('treat all files as text')),
2737 ('f', 'follow', None,
2737 ('f', 'follow', None,
2738 _('follow changeset history,'
2738 _('follow changeset history,'
2739 ' or file history across copies and renames')),
2739 ' or file history across copies and renames')),
2740 ('i', 'ignore-case', None, _('ignore case when matching')),
2740 ('i', 'ignore-case', None, _('ignore case when matching')),
2741 ('l', 'files-with-matches', None,
2741 ('l', 'files-with-matches', None,
2742 _('print only filenames and revisions that match')),
2742 _('print only filenames and revisions that match')),
2743 ('n', 'line-number', None, _('print matching line numbers')),
2743 ('n', 'line-number', None, _('print matching line numbers')),
2744 ('r', 'rev', [],
2744 ('r', 'rev', [],
2745 _('only search files changed within revision range'), _('REV')),
2745 _('only search files changed within revision range'), _('REV')),
2746 ('u', 'user', None, _('list the author (long with -v)')),
2746 ('u', 'user', None, _('list the author (long with -v)')),
2747 ('d', 'date', None, _('list the date (short with -q)')),
2747 ('d', 'date', None, _('list the date (short with -q)')),
2748 ] + walkopts,
2748 ] + walkopts,
2749 _('[OPTION]... PATTERN [FILE]...'))
2749 _('[OPTION]... PATTERN [FILE]...'))
2750 def grep(ui, repo, pattern, *pats, **opts):
2750 def grep(ui, repo, pattern, *pats, **opts):
2751 """search for a pattern in specified files and revisions
2751 """search for a pattern in specified files and revisions
2752
2752
2753 Search revisions of files for a regular expression.
2753 Search revisions of files for a regular expression.
2754
2754
2755 This command behaves differently than Unix grep. It only accepts
2755 This command behaves differently than Unix grep. It only accepts
2756 Python/Perl regexps. It searches repository history, not the
2756 Python/Perl regexps. It searches repository history, not the
2757 working directory. It always prints the revision number in which a
2757 working directory. It always prints the revision number in which a
2758 match appears.
2758 match appears.
2759
2759
2760 By default, grep only prints output for the first revision of a
2760 By default, grep only prints output for the first revision of a
2761 file in which it finds a match. To get it to print every revision
2761 file in which it finds a match. To get it to print every revision
2762 that contains a change in match status ("-" for a match that
2762 that contains a change in match status ("-" for a match that
2763 becomes a non-match, or "+" for a non-match that becomes a match),
2763 becomes a non-match, or "+" for a non-match that becomes a match),
2764 use the --all flag.
2764 use the --all flag.
2765
2765
2766 Returns 0 if a match is found, 1 otherwise.
2766 Returns 0 if a match is found, 1 otherwise.
2767 """
2767 """
2768 reflags = re.M
2768 reflags = re.M
2769 if opts.get('ignore_case'):
2769 if opts.get('ignore_case'):
2770 reflags |= re.I
2770 reflags |= re.I
2771 try:
2771 try:
2772 regexp = re.compile(pattern, reflags)
2772 regexp = re.compile(pattern, reflags)
2773 except re.error, inst:
2773 except re.error, inst:
2774 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2774 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2775 return 1
2775 return 1
2776 sep, eol = ':', '\n'
2776 sep, eol = ':', '\n'
2777 if opts.get('print0'):
2777 if opts.get('print0'):
2778 sep = eol = '\0'
2778 sep = eol = '\0'
2779
2779
2780 getfile = util.lrucachefunc(repo.file)
2780 getfile = util.lrucachefunc(repo.file)
2781
2781
2782 def matchlines(body):
2782 def matchlines(body):
2783 begin = 0
2783 begin = 0
2784 linenum = 0
2784 linenum = 0
2785 while True:
2785 while True:
2786 match = regexp.search(body, begin)
2786 match = regexp.search(body, begin)
2787 if not match:
2787 if not match:
2788 break
2788 break
2789 mstart, mend = match.span()
2789 mstart, mend = match.span()
2790 linenum += body.count('\n', begin, mstart) + 1
2790 linenum += body.count('\n', begin, mstart) + 1
2791 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2791 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2792 begin = body.find('\n', mend) + 1 or len(body) + 1
2792 begin = body.find('\n', mend) + 1 or len(body) + 1
2793 lend = begin - 1
2793 lend = begin - 1
2794 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2794 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2795
2795
2796 class linestate(object):
2796 class linestate(object):
2797 def __init__(self, line, linenum, colstart, colend):
2797 def __init__(self, line, linenum, colstart, colend):
2798 self.line = line
2798 self.line = line
2799 self.linenum = linenum
2799 self.linenum = linenum
2800 self.colstart = colstart
2800 self.colstart = colstart
2801 self.colend = colend
2801 self.colend = colend
2802
2802
2803 def __hash__(self):
2803 def __hash__(self):
2804 return hash((self.linenum, self.line))
2804 return hash((self.linenum, self.line))
2805
2805
2806 def __eq__(self, other):
2806 def __eq__(self, other):
2807 return self.line == other.line
2807 return self.line == other.line
2808
2808
2809 matches = {}
2809 matches = {}
2810 copies = {}
2810 copies = {}
2811 def grepbody(fn, rev, body):
2811 def grepbody(fn, rev, body):
2812 matches[rev].setdefault(fn, [])
2812 matches[rev].setdefault(fn, [])
2813 m = matches[rev][fn]
2813 m = matches[rev][fn]
2814 for lnum, cstart, cend, line in matchlines(body):
2814 for lnum, cstart, cend, line in matchlines(body):
2815 s = linestate(line, lnum, cstart, cend)
2815 s = linestate(line, lnum, cstart, cend)
2816 m.append(s)
2816 m.append(s)
2817
2817
2818 def difflinestates(a, b):
2818 def difflinestates(a, b):
2819 sm = difflib.SequenceMatcher(None, a, b)
2819 sm = difflib.SequenceMatcher(None, a, b)
2820 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2820 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2821 if tag == 'insert':
2821 if tag == 'insert':
2822 for i in xrange(blo, bhi):
2822 for i in xrange(blo, bhi):
2823 yield ('+', b[i])
2823 yield ('+', b[i])
2824 elif tag == 'delete':
2824 elif tag == 'delete':
2825 for i in xrange(alo, ahi):
2825 for i in xrange(alo, ahi):
2826 yield ('-', a[i])
2826 yield ('-', a[i])
2827 elif tag == 'replace':
2827 elif tag == 'replace':
2828 for i in xrange(alo, ahi):
2828 for i in xrange(alo, ahi):
2829 yield ('-', a[i])
2829 yield ('-', a[i])
2830 for i in xrange(blo, bhi):
2830 for i in xrange(blo, bhi):
2831 yield ('+', b[i])
2831 yield ('+', b[i])
2832
2832
2833 def display(fn, ctx, pstates, states):
2833 def display(fn, ctx, pstates, states):
2834 rev = ctx.rev()
2834 rev = ctx.rev()
2835 datefunc = ui.quiet and util.shortdate or util.datestr
2835 datefunc = ui.quiet and util.shortdate or util.datestr
2836 found = False
2836 found = False
2837 filerevmatches = {}
2837 filerevmatches = {}
2838 def binary():
2838 def binary():
2839 flog = getfile(fn)
2839 flog = getfile(fn)
2840 return util.binary(flog.read(ctx.filenode(fn)))
2840 return util.binary(flog.read(ctx.filenode(fn)))
2841
2841
2842 if opts.get('all'):
2842 if opts.get('all'):
2843 iter = difflinestates(pstates, states)
2843 iter = difflinestates(pstates, states)
2844 else:
2844 else:
2845 iter = [('', l) for l in states]
2845 iter = [('', l) for l in states]
2846 for change, l in iter:
2846 for change, l in iter:
2847 cols = [fn, str(rev)]
2847 cols = [fn, str(rev)]
2848 before, match, after = None, None, None
2848 before, match, after = None, None, None
2849 if opts.get('line_number'):
2849 if opts.get('line_number'):
2850 cols.append(str(l.linenum))
2850 cols.append(str(l.linenum))
2851 if opts.get('all'):
2851 if opts.get('all'):
2852 cols.append(change)
2852 cols.append(change)
2853 if opts.get('user'):
2853 if opts.get('user'):
2854 cols.append(ui.shortuser(ctx.user()))
2854 cols.append(ui.shortuser(ctx.user()))
2855 if opts.get('date'):
2855 if opts.get('date'):
2856 cols.append(datefunc(ctx.date()))
2856 cols.append(datefunc(ctx.date()))
2857 if opts.get('files_with_matches'):
2857 if opts.get('files_with_matches'):
2858 c = (fn, rev)
2858 c = (fn, rev)
2859 if c in filerevmatches:
2859 if c in filerevmatches:
2860 continue
2860 continue
2861 filerevmatches[c] = 1
2861 filerevmatches[c] = 1
2862 else:
2862 else:
2863 before = l.line[:l.colstart]
2863 before = l.line[:l.colstart]
2864 match = l.line[l.colstart:l.colend]
2864 match = l.line[l.colstart:l.colend]
2865 after = l.line[l.colend:]
2865 after = l.line[l.colend:]
2866 ui.write(sep.join(cols))
2866 ui.write(sep.join(cols))
2867 if before is not None:
2867 if before is not None:
2868 if not opts.get('text') and binary():
2868 if not opts.get('text') and binary():
2869 ui.write(sep + " Binary file matches")
2869 ui.write(sep + " Binary file matches")
2870 else:
2870 else:
2871 ui.write(sep + before)
2871 ui.write(sep + before)
2872 ui.write(match, label='grep.match')
2872 ui.write(match, label='grep.match')
2873 ui.write(after)
2873 ui.write(after)
2874 ui.write(eol)
2874 ui.write(eol)
2875 found = True
2875 found = True
2876 return found
2876 return found
2877
2877
2878 skip = {}
2878 skip = {}
2879 revfiles = {}
2879 revfiles = {}
2880 matchfn = scmutil.match(repo[None], pats, opts)
2880 matchfn = scmutil.match(repo[None], pats, opts)
2881 found = False
2881 found = False
2882 follow = opts.get('follow')
2882 follow = opts.get('follow')
2883
2883
2884 def prep(ctx, fns):
2884 def prep(ctx, fns):
2885 rev = ctx.rev()
2885 rev = ctx.rev()
2886 pctx = ctx.p1()
2886 pctx = ctx.p1()
2887 parent = pctx.rev()
2887 parent = pctx.rev()
2888 matches.setdefault(rev, {})
2888 matches.setdefault(rev, {})
2889 matches.setdefault(parent, {})
2889 matches.setdefault(parent, {})
2890 files = revfiles.setdefault(rev, [])
2890 files = revfiles.setdefault(rev, [])
2891 for fn in fns:
2891 for fn in fns:
2892 flog = getfile(fn)
2892 flog = getfile(fn)
2893 try:
2893 try:
2894 fnode = ctx.filenode(fn)
2894 fnode = ctx.filenode(fn)
2895 except error.LookupError:
2895 except error.LookupError:
2896 continue
2896 continue
2897
2897
2898 copied = flog.renamed(fnode)
2898 copied = flog.renamed(fnode)
2899 copy = follow and copied and copied[0]
2899 copy = follow and copied and copied[0]
2900 if copy:
2900 if copy:
2901 copies.setdefault(rev, {})[fn] = copy
2901 copies.setdefault(rev, {})[fn] = copy
2902 if fn in skip:
2902 if fn in skip:
2903 if copy:
2903 if copy:
2904 skip[copy] = True
2904 skip[copy] = True
2905 continue
2905 continue
2906 files.append(fn)
2906 files.append(fn)
2907
2907
2908 if fn not in matches[rev]:
2908 if fn not in matches[rev]:
2909 grepbody(fn, rev, flog.read(fnode))
2909 grepbody(fn, rev, flog.read(fnode))
2910
2910
2911 pfn = copy or fn
2911 pfn = copy or fn
2912 if pfn not in matches[parent]:
2912 if pfn not in matches[parent]:
2913 try:
2913 try:
2914 fnode = pctx.filenode(pfn)
2914 fnode = pctx.filenode(pfn)
2915 grepbody(pfn, parent, flog.read(fnode))
2915 grepbody(pfn, parent, flog.read(fnode))
2916 except error.LookupError:
2916 except error.LookupError:
2917 pass
2917 pass
2918
2918
2919 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2919 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2920 rev = ctx.rev()
2920 rev = ctx.rev()
2921 parent = ctx.p1().rev()
2921 parent = ctx.p1().rev()
2922 for fn in sorted(revfiles.get(rev, [])):
2922 for fn in sorted(revfiles.get(rev, [])):
2923 states = matches[rev][fn]
2923 states = matches[rev][fn]
2924 copy = copies.get(rev, {}).get(fn)
2924 copy = copies.get(rev, {}).get(fn)
2925 if fn in skip:
2925 if fn in skip:
2926 if copy:
2926 if copy:
2927 skip[copy] = True
2927 skip[copy] = True
2928 continue
2928 continue
2929 pstates = matches.get(parent, {}).get(copy or fn, [])
2929 pstates = matches.get(parent, {}).get(copy or fn, [])
2930 if pstates or states:
2930 if pstates or states:
2931 r = display(fn, ctx, pstates, states)
2931 r = display(fn, ctx, pstates, states)
2932 found = found or r
2932 found = found or r
2933 if r and not opts.get('all'):
2933 if r and not opts.get('all'):
2934 skip[fn] = True
2934 skip[fn] = True
2935 if copy:
2935 if copy:
2936 skip[copy] = True
2936 skip[copy] = True
2937 del matches[rev]
2937 del matches[rev]
2938 del revfiles[rev]
2938 del revfiles[rev]
2939
2939
2940 return not found
2940 return not found
2941
2941
2942 @command('heads',
2942 @command('heads',
2943 [('r', 'rev', '',
2943 [('r', 'rev', '',
2944 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2944 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2945 ('t', 'topo', False, _('show topological heads only')),
2945 ('t', 'topo', False, _('show topological heads only')),
2946 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2946 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2947 ('c', 'closed', False, _('show normal and closed branch heads')),
2947 ('c', 'closed', False, _('show normal and closed branch heads')),
2948 ] + templateopts,
2948 ] + templateopts,
2949 _('[-ac] [-r STARTREV] [REV]...'))
2949 _('[-ac] [-r STARTREV] [REV]...'))
2950 def heads(ui, repo, *branchrevs, **opts):
2950 def heads(ui, repo, *branchrevs, **opts):
2951 """show current repository heads or show branch heads
2951 """show current repository heads or show branch heads
2952
2952
2953 With no arguments, show all repository branch heads.
2953 With no arguments, show all repository branch heads.
2954
2954
2955 Repository "heads" are changesets with no child changesets. They are
2955 Repository "heads" are changesets with no child changesets. They are
2956 where development generally takes place and are the usual targets
2956 where development generally takes place and are the usual targets
2957 for update and merge operations. Branch heads are changesets that have
2957 for update and merge operations. Branch heads are changesets that have
2958 no child changeset on the same branch.
2958 no child changeset on the same branch.
2959
2959
2960 If one or more REVs are given, only branch heads on the branches
2960 If one or more REVs are given, only branch heads on the branches
2961 associated with the specified changesets are shown. This means
2961 associated with the specified changesets are shown. This means
2962 that you can use :hg:`heads foo` to see the heads on a branch
2962 that you can use :hg:`heads foo` to see the heads on a branch
2963 named ``foo``.
2963 named ``foo``.
2964
2964
2965 If -c/--closed is specified, also show branch heads marked closed
2965 If -c/--closed is specified, also show branch heads marked closed
2966 (see :hg:`commit --close-branch`).
2966 (see :hg:`commit --close-branch`).
2967
2967
2968 If STARTREV is specified, only those heads that are descendants of
2968 If STARTREV is specified, only those heads that are descendants of
2969 STARTREV will be displayed.
2969 STARTREV will be displayed.
2970
2970
2971 If -t/--topo is specified, named branch mechanics will be ignored and only
2971 If -t/--topo is specified, named branch mechanics will be ignored and only
2972 changesets without children will be shown.
2972 changesets without children will be shown.
2973
2973
2974 Returns 0 if matching heads are found, 1 if not.
2974 Returns 0 if matching heads are found, 1 if not.
2975 """
2975 """
2976
2976
2977 start = None
2977 start = None
2978 if 'rev' in opts:
2978 if 'rev' in opts:
2979 start = scmutil.revsingle(repo, opts['rev'], None).node()
2979 start = scmutil.revsingle(repo, opts['rev'], None).node()
2980
2980
2981 if opts.get('topo'):
2981 if opts.get('topo'):
2982 heads = [repo[h] for h in repo.heads(start)]
2982 heads = [repo[h] for h in repo.heads(start)]
2983 else:
2983 else:
2984 heads = []
2984 heads = []
2985 for branch in repo.branchmap():
2985 for branch in repo.branchmap():
2986 heads += repo.branchheads(branch, start, opts.get('closed'))
2986 heads += repo.branchheads(branch, start, opts.get('closed'))
2987 heads = [repo[h] for h in heads]
2987 heads = [repo[h] for h in heads]
2988
2988
2989 if branchrevs:
2989 if branchrevs:
2990 branches = set(repo[br].branch() for br in branchrevs)
2990 branches = set(repo[br].branch() for br in branchrevs)
2991 heads = [h for h in heads if h.branch() in branches]
2991 heads = [h for h in heads if h.branch() in branches]
2992
2992
2993 if opts.get('active') and branchrevs:
2993 if opts.get('active') and branchrevs:
2994 dagheads = repo.heads(start)
2994 dagheads = repo.heads(start)
2995 heads = [h for h in heads if h.node() in dagheads]
2995 heads = [h for h in heads if h.node() in dagheads]
2996
2996
2997 if branchrevs:
2997 if branchrevs:
2998 haveheads = set(h.branch() for h in heads)
2998 haveheads = set(h.branch() for h in heads)
2999 if branches - haveheads:
2999 if branches - haveheads:
3000 headless = ', '.join(b for b in branches - haveheads)
3000 headless = ', '.join(b for b in branches - haveheads)
3001 msg = _('no open branch heads found on branches %s')
3001 msg = _('no open branch heads found on branches %s')
3002 if opts.get('rev'):
3002 if opts.get('rev'):
3003 msg += _(' (started at %s)') % opts['rev']
3003 msg += _(' (started at %s)') % opts['rev']
3004 ui.warn((msg + '\n') % headless)
3004 ui.warn((msg + '\n') % headless)
3005
3005
3006 if not heads:
3006 if not heads:
3007 return 1
3007 return 1
3008
3008
3009 heads = sorted(heads, key=lambda x: -x.rev())
3009 heads = sorted(heads, key=lambda x: -x.rev())
3010 displayer = cmdutil.show_changeset(ui, repo, opts)
3010 displayer = cmdutil.show_changeset(ui, repo, opts)
3011 for ctx in heads:
3011 for ctx in heads:
3012 displayer.show(ctx)
3012 displayer.show(ctx)
3013 displayer.close()
3013 displayer.close()
3014
3014
3015 @command('help',
3015 @command('help',
3016 [('e', 'extension', None, _('show only help for extensions')),
3016 [('e', 'extension', None, _('show only help for extensions')),
3017 ('c', 'command', None, _('show only help for commands'))],
3017 ('c', 'command', None, _('show only help for commands'))],
3018 _('[-ec] [TOPIC]'))
3018 _('[-ec] [TOPIC]'))
3019 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3019 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3020 """show help for a given topic or a help overview
3020 """show help for a given topic or a help overview
3021
3021
3022 With no arguments, print a list of commands with short help messages.
3022 With no arguments, print a list of commands with short help messages.
3023
3023
3024 Given a topic, extension, or command name, print help for that
3024 Given a topic, extension, or command name, print help for that
3025 topic.
3025 topic.
3026
3026
3027 Returns 0 if successful.
3027 Returns 0 if successful.
3028 """
3028 """
3029
3029
3030 textwidth = min(ui.termwidth(), 80) - 2
3030 textwidth = min(ui.termwidth(), 80) - 2
3031
3031
3032 def optrst(options):
3032 def optrst(options):
3033 data = []
3033 data = []
3034 multioccur = False
3034 multioccur = False
3035 for option in options:
3035 for option in options:
3036 if len(option) == 5:
3036 if len(option) == 5:
3037 shortopt, longopt, default, desc, optlabel = option
3037 shortopt, longopt, default, desc, optlabel = option
3038 else:
3038 else:
3039 shortopt, longopt, default, desc = option
3039 shortopt, longopt, default, desc = option
3040 optlabel = _("VALUE") # default label
3040 optlabel = _("VALUE") # default label
3041
3041
3042 if _("DEPRECATED") in desc and not ui.verbose:
3042 if _("DEPRECATED") in desc and not ui.verbose:
3043 continue
3043 continue
3044
3044
3045 so = ''
3045 so = ''
3046 if shortopt:
3046 if shortopt:
3047 so = '-' + shortopt
3047 so = '-' + shortopt
3048 lo = '--' + longopt
3048 lo = '--' + longopt
3049 if default:
3049 if default:
3050 desc += _(" (default: %s)") % default
3050 desc += _(" (default: %s)") % default
3051
3051
3052 if isinstance(default, list):
3052 if isinstance(default, list):
3053 lo += " %s [+]" % optlabel
3053 lo += " %s [+]" % optlabel
3054 multioccur = True
3054 multioccur = True
3055 elif (default is not None) and not isinstance(default, bool):
3055 elif (default is not None) and not isinstance(default, bool):
3056 lo += " %s" % optlabel
3056 lo += " %s" % optlabel
3057
3057
3058 data.append((so, lo, desc))
3058 data.append((so, lo, desc))
3059
3059
3060 rst = minirst.maketable(data, 1)
3060 rst = minirst.maketable(data, 1)
3061
3061
3062 if multioccur:
3062 if multioccur:
3063 rst += _("\n[+] marked option can be specified multiple times\n")
3063 rst += _("\n[+] marked option can be specified multiple times\n")
3064
3064
3065 return rst
3065 return rst
3066
3066
3067 # list all option lists
3067 # list all option lists
3068 def opttext(optlist, width):
3068 def opttext(optlist, width):
3069 rst = ''
3069 rst = ''
3070 if not optlist:
3070 if not optlist:
3071 return ''
3071 return ''
3072
3072
3073 for title, options in optlist:
3073 for title, options in optlist:
3074 rst += '\n%s\n' % title
3074 rst += '\n%s\n' % title
3075 if options:
3075 if options:
3076 rst += "\n"
3076 rst += "\n"
3077 rst += optrst(options)
3077 rst += optrst(options)
3078 rst += '\n'
3078 rst += '\n'
3079
3079
3080 return '\n' + minirst.format(rst, width)
3080 return '\n' + minirst.format(rst, width)
3081
3081
3082 def addglobalopts(optlist, aliases):
3082 def addglobalopts(optlist, aliases):
3083 if ui.quiet:
3083 if ui.quiet:
3084 return []
3084 return []
3085
3085
3086 if ui.verbose:
3086 if ui.verbose:
3087 optlist.append((_("global options:"), globalopts))
3087 optlist.append((_("global options:"), globalopts))
3088 if name == 'shortlist':
3088 if name == 'shortlist':
3089 optlist.append((_('use "hg help" for the full list '
3089 optlist.append((_('use "hg help" for the full list '
3090 'of commands'), ()))
3090 'of commands'), ()))
3091 else:
3091 else:
3092 if name == 'shortlist':
3092 if name == 'shortlist':
3093 msg = _('use "hg help" for the full list of commands '
3093 msg = _('use "hg help" for the full list of commands '
3094 'or "hg -v" for details')
3094 'or "hg -v" for details')
3095 elif name and not full:
3095 elif name and not full:
3096 msg = _('use "hg help %s" to show the full help text') % name
3096 msg = _('use "hg help %s" to show the full help text') % name
3097 elif aliases:
3097 elif aliases:
3098 msg = _('use "hg -v help%s" to show builtin aliases and '
3098 msg = _('use "hg -v help%s" to show builtin aliases and '
3099 'global options') % (name and " " + name or "")
3099 'global options') % (name and " " + name or "")
3100 else:
3100 else:
3101 msg = _('use "hg -v help %s" to show more info') % name
3101 msg = _('use "hg -v help %s" to show more info') % name
3102 optlist.append((msg, ()))
3102 optlist.append((msg, ()))
3103
3103
3104 def helpcmd(name):
3104 def helpcmd(name):
3105 try:
3105 try:
3106 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3106 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3107 except error.AmbiguousCommand, inst:
3107 except error.AmbiguousCommand, inst:
3108 # py3k fix: except vars can't be used outside the scope of the
3108 # py3k fix: except vars can't be used outside the scope of the
3109 # except block, nor can be used inside a lambda. python issue4617
3109 # except block, nor can be used inside a lambda. python issue4617
3110 prefix = inst.args[0]
3110 prefix = inst.args[0]
3111 select = lambda c: c.lstrip('^').startswith(prefix)
3111 select = lambda c: c.lstrip('^').startswith(prefix)
3112 helplist(select)
3112 helplist(select)
3113 return
3113 return
3114
3114
3115 # check if it's an invalid alias and display its error if it is
3115 # check if it's an invalid alias and display its error if it is
3116 if getattr(entry[0], 'badalias', False):
3116 if getattr(entry[0], 'badalias', False):
3117 if not unknowncmd:
3117 if not unknowncmd:
3118 entry[0](ui)
3118 entry[0](ui)
3119 return
3119 return
3120
3120
3121 rst = ""
3121 rst = ""
3122
3122
3123 # synopsis
3123 # synopsis
3124 if len(entry) > 2:
3124 if len(entry) > 2:
3125 if entry[2].startswith('hg'):
3125 if entry[2].startswith('hg'):
3126 rst += "%s\n" % entry[2]
3126 rst += "%s\n" % entry[2]
3127 else:
3127 else:
3128 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3128 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3129 else:
3129 else:
3130 rst += 'hg %s\n' % aliases[0]
3130 rst += 'hg %s\n' % aliases[0]
3131
3131
3132 # aliases
3132 # aliases
3133 if full and not ui.quiet and len(aliases) > 1:
3133 if full and not ui.quiet and len(aliases) > 1:
3134 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3134 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3135
3135
3136 # description
3136 # description
3137 doc = gettext(entry[0].__doc__)
3137 doc = gettext(entry[0].__doc__)
3138 if not doc:
3138 if not doc:
3139 doc = _("(no help text available)")
3139 doc = _("(no help text available)")
3140 if util.safehasattr(entry[0], 'definition'): # aliased command
3140 if util.safehasattr(entry[0], 'definition'): # aliased command
3141 if entry[0].definition.startswith('!'): # shell alias
3141 if entry[0].definition.startswith('!'): # shell alias
3142 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3142 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3143 else:
3143 else:
3144 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3144 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3145 if ui.quiet or not full:
3145 if ui.quiet or not full:
3146 doc = doc.splitlines()[0]
3146 doc = doc.splitlines()[0]
3147 rst += "\n" + doc + "\n"
3147 rst += "\n" + doc + "\n"
3148
3148
3149 # check if this command shadows a non-trivial (multi-line)
3149 # check if this command shadows a non-trivial (multi-line)
3150 # extension help text
3150 # extension help text
3151 try:
3151 try:
3152 mod = extensions.find(name)
3152 mod = extensions.find(name)
3153 doc = gettext(mod.__doc__) or ''
3153 doc = gettext(mod.__doc__) or ''
3154 if '\n' in doc.strip():
3154 if '\n' in doc.strip():
3155 msg = _('use "hg help -e %s" to show help for '
3155 msg = _('use "hg help -e %s" to show help for '
3156 'the %s extension') % (name, name)
3156 'the %s extension') % (name, name)
3157 rst += '\n%s\n' % msg
3157 rst += '\n%s\n' % msg
3158 except KeyError:
3158 except KeyError:
3159 pass
3159 pass
3160
3160
3161 # options
3161 # options
3162 if not ui.quiet and entry[1]:
3162 if not ui.quiet and entry[1]:
3163 rst += '\n'
3163 rst += '\n'
3164 rst += _("options:")
3164 rst += _("options:")
3165 rst += '\n\n'
3165 rst += '\n\n'
3166 rst += optrst(entry[1])
3166 rst += optrst(entry[1])
3167
3167
3168 if ui.verbose:
3168 if ui.verbose:
3169 rst += '\n'
3169 rst += '\n'
3170 rst += _("global options:")
3170 rst += _("global options:")
3171 rst += '\n\n'
3171 rst += '\n\n'
3172 rst += optrst(globalopts)
3172 rst += optrst(globalopts)
3173
3173
3174 keep = ui.verbose and ['verbose'] or []
3174 keep = ui.verbose and ['verbose'] or []
3175 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3175 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3176 ui.write(formatted)
3176 ui.write(formatted)
3177
3177
3178 if not ui.verbose:
3178 if not ui.verbose:
3179 if not full:
3179 if not full:
3180 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3180 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3181 % name)
3181 % name)
3182 elif not ui.quiet:
3182 elif not ui.quiet:
3183 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3183 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3184
3184
3185
3185
3186 def helplist(select=None):
3186 def helplist(select=None):
3187 # list of commands
3187 # list of commands
3188 if name == "shortlist":
3188 if name == "shortlist":
3189 header = _('basic commands:\n\n')
3189 header = _('basic commands:\n\n')
3190 else:
3190 else:
3191 header = _('list of commands:\n\n')
3191 header = _('list of commands:\n\n')
3192
3192
3193 h = {}
3193 h = {}
3194 cmds = {}
3194 cmds = {}
3195 for c, e in table.iteritems():
3195 for c, e in table.iteritems():
3196 f = c.split("|", 1)[0]
3196 f = c.split("|", 1)[0]
3197 if select and not select(f):
3197 if select and not select(f):
3198 continue
3198 continue
3199 if (not select and name != 'shortlist' and
3199 if (not select and name != 'shortlist' and
3200 e[0].__module__ != __name__):
3200 e[0].__module__ != __name__):
3201 continue
3201 continue
3202 if name == "shortlist" and not f.startswith("^"):
3202 if name == "shortlist" and not f.startswith("^"):
3203 continue
3203 continue
3204 f = f.lstrip("^")
3204 f = f.lstrip("^")
3205 if not ui.debugflag and f.startswith("debug"):
3205 if not ui.debugflag and f.startswith("debug"):
3206 continue
3206 continue
3207 doc = e[0].__doc__
3207 doc = e[0].__doc__
3208 if doc and 'DEPRECATED' in doc and not ui.verbose:
3208 if doc and 'DEPRECATED' in doc and not ui.verbose:
3209 continue
3209 continue
3210 doc = gettext(doc)
3210 doc = gettext(doc)
3211 if not doc:
3211 if not doc:
3212 doc = _("(no help text available)")
3212 doc = _("(no help text available)")
3213 h[f] = doc.splitlines()[0].rstrip()
3213 h[f] = doc.splitlines()[0].rstrip()
3214 cmds[f] = c.lstrip("^")
3214 cmds[f] = c.lstrip("^")
3215
3215
3216 if not h:
3216 if not h:
3217 ui.status(_('no commands defined\n'))
3217 ui.status(_('no commands defined\n'))
3218 return
3218 return
3219
3219
3220 ui.status(header)
3220 ui.status(header)
3221 fns = sorted(h)
3221 fns = sorted(h)
3222 m = max(map(len, fns))
3222 m = max(map(len, fns))
3223 for f in fns:
3223 for f in fns:
3224 if ui.verbose:
3224 if ui.verbose:
3225 commands = cmds[f].replace("|",", ")
3225 commands = cmds[f].replace("|",", ")
3226 ui.write(" %s:\n %s\n"%(commands, h[f]))
3226 ui.write(" %s:\n %s\n"%(commands, h[f]))
3227 else:
3227 else:
3228 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3228 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3229 initindent=' %-*s ' % (m, f),
3229 initindent=' %-*s ' % (m, f),
3230 hangindent=' ' * (m + 4))))
3230 hangindent=' ' * (m + 4))))
3231
3231
3232 if not name:
3232 if not name:
3233 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3233 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3234 if text:
3234 if text:
3235 ui.write("\n%s" % minirst.format(text, textwidth))
3235 ui.write("\n%s" % minirst.format(text, textwidth))
3236
3236
3237 ui.write(_("\nadditional help topics:\n\n"))
3237 ui.write(_("\nadditional help topics:\n\n"))
3238 topics = []
3238 topics = []
3239 for names, header, doc in help.helptable:
3239 for names, header, doc in help.helptable:
3240 topics.append((sorted(names, key=len, reverse=True)[0], header))
3240 topics.append((sorted(names, key=len, reverse=True)[0], header))
3241 topics_len = max([len(s[0]) for s in topics])
3241 topics_len = max([len(s[0]) for s in topics])
3242 for t, desc in topics:
3242 for t, desc in topics:
3243 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3243 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3244
3244
3245 optlist = []
3245 optlist = []
3246 addglobalopts(optlist, True)
3246 addglobalopts(optlist, True)
3247 ui.write(opttext(optlist, textwidth))
3247 ui.write(opttext(optlist, textwidth))
3248
3248
3249 def helptopic(name):
3249 def helptopic(name):
3250 for names, header, doc in help.helptable:
3250 for names, header, doc in help.helptable:
3251 if name in names:
3251 if name in names:
3252 break
3252 break
3253 else:
3253 else:
3254 raise error.UnknownCommand(name)
3254 raise error.UnknownCommand(name)
3255
3255
3256 # description
3256 # description
3257 if not doc:
3257 if not doc:
3258 doc = _("(no help text available)")
3258 doc = _("(no help text available)")
3259 if util.safehasattr(doc, '__call__'):
3259 if util.safehasattr(doc, '__call__'):
3260 doc = doc()
3260 doc = doc()
3261
3261
3262 ui.write("%s\n\n" % header)
3262 ui.write("%s\n\n" % header)
3263 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3263 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3264 try:
3264 try:
3265 cmdutil.findcmd(name, table)
3265 cmdutil.findcmd(name, table)
3266 ui.write(_('\nuse "hg help -c %s" to see help for '
3266 ui.write(_('\nuse "hg help -c %s" to see help for '
3267 'the %s command\n') % (name, name))
3267 'the %s command\n') % (name, name))
3268 except error.UnknownCommand:
3268 except error.UnknownCommand:
3269 pass
3269 pass
3270
3270
3271 def helpext(name):
3271 def helpext(name):
3272 try:
3272 try:
3273 mod = extensions.find(name)
3273 mod = extensions.find(name)
3274 doc = gettext(mod.__doc__) or _('no help text available')
3274 doc = gettext(mod.__doc__) or _('no help text available')
3275 except KeyError:
3275 except KeyError:
3276 mod = None
3276 mod = None
3277 doc = extensions.disabledext(name)
3277 doc = extensions.disabledext(name)
3278 if not doc:
3278 if not doc:
3279 raise error.UnknownCommand(name)
3279 raise error.UnknownCommand(name)
3280
3280
3281 if '\n' not in doc:
3281 if '\n' not in doc:
3282 head, tail = doc, ""
3282 head, tail = doc, ""
3283 else:
3283 else:
3284 head, tail = doc.split('\n', 1)
3284 head, tail = doc.split('\n', 1)
3285 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3285 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3286 if tail:
3286 if tail:
3287 ui.write(minirst.format(tail, textwidth))
3287 ui.write(minirst.format(tail, textwidth))
3288 ui.status('\n')
3288 ui.status('\n')
3289
3289
3290 if mod:
3290 if mod:
3291 try:
3291 try:
3292 ct = mod.cmdtable
3292 ct = mod.cmdtable
3293 except AttributeError:
3293 except AttributeError:
3294 ct = {}
3294 ct = {}
3295 modcmds = set([c.split('|', 1)[0] for c in ct])
3295 modcmds = set([c.split('|', 1)[0] for c in ct])
3296 helplist(modcmds.__contains__)
3296 helplist(modcmds.__contains__)
3297 else:
3297 else:
3298 ui.write(_('use "hg help extensions" for information on enabling '
3298 ui.write(_('use "hg help extensions" for information on enabling '
3299 'extensions\n'))
3299 'extensions\n'))
3300
3300
3301 def helpextcmd(name):
3301 def helpextcmd(name):
3302 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3302 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3303 doc = gettext(mod.__doc__).splitlines()[0]
3303 doc = gettext(mod.__doc__).splitlines()[0]
3304
3304
3305 msg = help.listexts(_("'%s' is provided by the following "
3305 msg = help.listexts(_("'%s' is provided by the following "
3306 "extension:") % cmd, {ext: doc}, indent=4)
3306 "extension:") % cmd, {ext: doc}, indent=4)
3307 ui.write(minirst.format(msg, textwidth))
3307 ui.write(minirst.format(msg, textwidth))
3308 ui.write('\n')
3308 ui.write('\n')
3309 ui.write(_('use "hg help extensions" for information on enabling '
3309 ui.write(_('use "hg help extensions" for information on enabling '
3310 'extensions\n'))
3310 'extensions\n'))
3311
3311
3312 if name and name != 'shortlist':
3312 if name and name != 'shortlist':
3313 i = None
3313 i = None
3314 if unknowncmd:
3314 if unknowncmd:
3315 queries = (helpextcmd,)
3315 queries = (helpextcmd,)
3316 elif opts.get('extension'):
3316 elif opts.get('extension'):
3317 queries = (helpext,)
3317 queries = (helpext,)
3318 elif opts.get('command'):
3318 elif opts.get('command'):
3319 queries = (helpcmd,)
3319 queries = (helpcmd,)
3320 else:
3320 else:
3321 queries = (helptopic, helpcmd, helpext, helpextcmd)
3321 queries = (helptopic, helpcmd, helpext, helpextcmd)
3322 for f in queries:
3322 for f in queries:
3323 try:
3323 try:
3324 f(name)
3324 f(name)
3325 i = None
3325 i = None
3326 break
3326 break
3327 except error.UnknownCommand, inst:
3327 except error.UnknownCommand, inst:
3328 i = inst
3328 i = inst
3329 if i:
3329 if i:
3330 raise i
3330 raise i
3331 else:
3331 else:
3332 # program name
3332 # program name
3333 ui.status(_("Mercurial Distributed SCM\n"))
3333 ui.status(_("Mercurial Distributed SCM\n"))
3334 ui.status('\n')
3334 ui.status('\n')
3335 helplist()
3335 helplist()
3336
3336
3337
3337
3338 @command('identify|id',
3338 @command('identify|id',
3339 [('r', 'rev', '',
3339 [('r', 'rev', '',
3340 _('identify the specified revision'), _('REV')),
3340 _('identify the specified revision'), _('REV')),
3341 ('n', 'num', None, _('show local revision number')),
3341 ('n', 'num', None, _('show local revision number')),
3342 ('i', 'id', None, _('show global revision id')),
3342 ('i', 'id', None, _('show global revision id')),
3343 ('b', 'branch', None, _('show branch')),
3343 ('b', 'branch', None, _('show branch')),
3344 ('t', 'tags', None, _('show tags')),
3344 ('t', 'tags', None, _('show tags')),
3345 ('B', 'bookmarks', None, _('show bookmarks')),
3345 ('B', 'bookmarks', None, _('show bookmarks')),
3346 ] + remoteopts,
3346 ] + remoteopts,
3347 _('[-nibtB] [-r REV] [SOURCE]'))
3347 _('[-nibtB] [-r REV] [SOURCE]'))
3348 def identify(ui, repo, source=None, rev=None,
3348 def identify(ui, repo, source=None, rev=None,
3349 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3349 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3350 """identify the working copy or specified revision
3350 """identify the working copy or specified revision
3351
3351
3352 Print a summary identifying the repository state at REV using one or
3352 Print a summary identifying the repository state at REV using one or
3353 two parent hash identifiers, followed by a "+" if the working
3353 two parent hash identifiers, followed by a "+" if the working
3354 directory has uncommitted changes, the branch name (if not default),
3354 directory has uncommitted changes, the branch name (if not default),
3355 a list of tags, and a list of bookmarks.
3355 a list of tags, and a list of bookmarks.
3356
3356
3357 When REV is not given, print a summary of the current state of the
3357 When REV is not given, print a summary of the current state of the
3358 repository.
3358 repository.
3359
3359
3360 Specifying a path to a repository root or Mercurial bundle will
3360 Specifying a path to a repository root or Mercurial bundle will
3361 cause lookup to operate on that repository/bundle.
3361 cause lookup to operate on that repository/bundle.
3362
3362
3363 .. container:: verbose
3363 .. container:: verbose
3364
3364
3365 Examples:
3365 Examples:
3366
3366
3367 - generate a build identifier for the working directory::
3367 - generate a build identifier for the working directory::
3368
3368
3369 hg id --id > build-id.dat
3369 hg id --id > build-id.dat
3370
3370
3371 - find the revision corresponding to a tag::
3371 - find the revision corresponding to a tag::
3372
3372
3373 hg id -n -r 1.3
3373 hg id -n -r 1.3
3374
3374
3375 - check the most recent revision of a remote repository::
3375 - check the most recent revision of a remote repository::
3376
3376
3377 hg id -r tip http://selenic.com/hg/
3377 hg id -r tip http://selenic.com/hg/
3378
3378
3379 Returns 0 if successful.
3379 Returns 0 if successful.
3380 """
3380 """
3381
3381
3382 if not repo and not source:
3382 if not repo and not source:
3383 raise util.Abort(_("there is no Mercurial repository here "
3383 raise util.Abort(_("there is no Mercurial repository here "
3384 "(.hg not found)"))
3384 "(.hg not found)"))
3385
3385
3386 hexfunc = ui.debugflag and hex or short
3386 hexfunc = ui.debugflag and hex or short
3387 default = not (num or id or branch or tags or bookmarks)
3387 default = not (num or id or branch or tags or bookmarks)
3388 output = []
3388 output = []
3389 revs = []
3389 revs = []
3390
3390
3391 if source:
3391 if source:
3392 source, branches = hg.parseurl(ui.expandpath(source))
3392 source, branches = hg.parseurl(ui.expandpath(source))
3393 repo = hg.peer(ui, opts, source)
3393 repo = hg.peer(ui, opts, source)
3394 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3394 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3395
3395
3396 if not repo.local():
3396 if not repo.local():
3397 if num or branch or tags:
3397 if num or branch or tags:
3398 raise util.Abort(
3398 raise util.Abort(
3399 _("can't query remote revision number, branch, or tags"))
3399 _("can't query remote revision number, branch, or tags"))
3400 if not rev and revs:
3400 if not rev and revs:
3401 rev = revs[0]
3401 rev = revs[0]
3402 if not rev:
3402 if not rev:
3403 rev = "tip"
3403 rev = "tip"
3404
3404
3405 remoterev = repo.lookup(rev)
3405 remoterev = repo.lookup(rev)
3406 if default or id:
3406 if default or id:
3407 output = [hexfunc(remoterev)]
3407 output = [hexfunc(remoterev)]
3408
3408
3409 def getbms():
3409 def getbms():
3410 bms = []
3410 bms = []
3411
3411
3412 if 'bookmarks' in repo.listkeys('namespaces'):
3412 if 'bookmarks' in repo.listkeys('namespaces'):
3413 hexremoterev = hex(remoterev)
3413 hexremoterev = hex(remoterev)
3414 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3414 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3415 if bmr == hexremoterev]
3415 if bmr == hexremoterev]
3416
3416
3417 return bms
3417 return bms
3418
3418
3419 if bookmarks:
3419 if bookmarks:
3420 output.extend(getbms())
3420 output.extend(getbms())
3421 elif default and not ui.quiet:
3421 elif default and not ui.quiet:
3422 # multiple bookmarks for a single parent separated by '/'
3422 # multiple bookmarks for a single parent separated by '/'
3423 bm = '/'.join(getbms())
3423 bm = '/'.join(getbms())
3424 if bm:
3424 if bm:
3425 output.append(bm)
3425 output.append(bm)
3426 else:
3426 else:
3427 if not rev:
3427 if not rev:
3428 ctx = repo[None]
3428 ctx = repo[None]
3429 parents = ctx.parents()
3429 parents = ctx.parents()
3430 changed = ""
3430 changed = ""
3431 if default or id or num:
3431 if default or id or num:
3432 changed = util.any(repo.status()) and "+" or ""
3432 changed = util.any(repo.status()) and "+" or ""
3433 if default or id:
3433 if default or id:
3434 output = ["%s%s" %
3434 output = ["%s%s" %
3435 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3435 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3436 if num:
3436 if num:
3437 output.append("%s%s" %
3437 output.append("%s%s" %
3438 ('+'.join([str(p.rev()) for p in parents]), changed))
3438 ('+'.join([str(p.rev()) for p in parents]), changed))
3439 else:
3439 else:
3440 ctx = scmutil.revsingle(repo, rev)
3440 ctx = scmutil.revsingle(repo, rev)
3441 if default or id:
3441 if default or id:
3442 output = [hexfunc(ctx.node())]
3442 output = [hexfunc(ctx.node())]
3443 if num:
3443 if num:
3444 output.append(str(ctx.rev()))
3444 output.append(str(ctx.rev()))
3445
3445
3446 if default and not ui.quiet:
3446 if default and not ui.quiet:
3447 b = ctx.branch()
3447 b = ctx.branch()
3448 if b != 'default':
3448 if b != 'default':
3449 output.append("(%s)" % b)
3449 output.append("(%s)" % b)
3450
3450
3451 # multiple tags for a single parent separated by '/'
3451 # multiple tags for a single parent separated by '/'
3452 t = '/'.join(ctx.tags())
3452 t = '/'.join(ctx.tags())
3453 if t:
3453 if t:
3454 output.append(t)
3454 output.append(t)
3455
3455
3456 # multiple bookmarks for a single parent separated by '/'
3456 # multiple bookmarks for a single parent separated by '/'
3457 bm = '/'.join(ctx.bookmarks())
3457 bm = '/'.join(ctx.bookmarks())
3458 if bm:
3458 if bm:
3459 output.append(bm)
3459 output.append(bm)
3460 else:
3460 else:
3461 if branch:
3461 if branch:
3462 output.append(ctx.branch())
3462 output.append(ctx.branch())
3463
3463
3464 if tags:
3464 if tags:
3465 output.extend(ctx.tags())
3465 output.extend(ctx.tags())
3466
3466
3467 if bookmarks:
3467 if bookmarks:
3468 output.extend(ctx.bookmarks())
3468 output.extend(ctx.bookmarks())
3469
3469
3470 ui.write("%s\n" % ' '.join(output))
3470 ui.write("%s\n" % ' '.join(output))
3471
3471
3472 @command('import|patch',
3472 @command('import|patch',
3473 [('p', 'strip', 1,
3473 [('p', 'strip', 1,
3474 _('directory strip option for patch. This has the same '
3474 _('directory strip option for patch. This has the same '
3475 'meaning as the corresponding patch option'), _('NUM')),
3475 'meaning as the corresponding patch option'), _('NUM')),
3476 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3476 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3477 ('e', 'edit', False, _('invoke editor on commit messages')),
3477 ('e', 'edit', False, _('invoke editor on commit messages')),
3478 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3478 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3479 ('', 'no-commit', None,
3479 ('', 'no-commit', None,
3480 _("don't commit, just update the working directory")),
3480 _("don't commit, just update the working directory")),
3481 ('', 'bypass', None,
3481 ('', 'bypass', None,
3482 _("apply patch without touching the working directory")),
3482 _("apply patch without touching the working directory")),
3483 ('', 'exact', None,
3483 ('', 'exact', None,
3484 _('apply patch to the nodes from which it was generated')),
3484 _('apply patch to the nodes from which it was generated')),
3485 ('', 'import-branch', None,
3485 ('', 'import-branch', None,
3486 _('use any branch information in patch (implied by --exact)'))] +
3486 _('use any branch information in patch (implied by --exact)'))] +
3487 commitopts + commitopts2 + similarityopts,
3487 commitopts + commitopts2 + similarityopts,
3488 _('[OPTION]... PATCH...'))
3488 _('[OPTION]... PATCH...'))
3489 def import_(ui, repo, patch1=None, *patches, **opts):
3489 def import_(ui, repo, patch1=None, *patches, **opts):
3490 """import an ordered set of patches
3490 """import an ordered set of patches
3491
3491
3492 Import a list of patches and commit them individually (unless
3492 Import a list of patches and commit them individually (unless
3493 --no-commit is specified).
3493 --no-commit is specified).
3494
3494
3495 If there are outstanding changes in the working directory, import
3495 If there are outstanding changes in the working directory, import
3496 will abort unless given the -f/--force flag.
3496 will abort unless given the -f/--force flag.
3497
3497
3498 You can import a patch straight from a mail message. Even patches
3498 You can import a patch straight from a mail message. Even patches
3499 as attachments work (to use the body part, it must have type
3499 as attachments work (to use the body part, it must have type
3500 text/plain or text/x-patch). From and Subject headers of email
3500 text/plain or text/x-patch). From and Subject headers of email
3501 message are used as default committer and commit message. All
3501 message are used as default committer and commit message. All
3502 text/plain body parts before first diff are added to commit
3502 text/plain body parts before first diff are added to commit
3503 message.
3503 message.
3504
3504
3505 If the imported patch was generated by :hg:`export`, user and
3505 If the imported patch was generated by :hg:`export`, user and
3506 description from patch override values from message headers and
3506 description from patch override values from message headers and
3507 body. Values given on command line with -m/--message and -u/--user
3507 body. Values given on command line with -m/--message and -u/--user
3508 override these.
3508 override these.
3509
3509
3510 If --exact is specified, import will set the working directory to
3510 If --exact is specified, import will set the working directory to
3511 the parent of each patch before applying it, and will abort if the
3511 the parent of each patch before applying it, and will abort if the
3512 resulting changeset has a different ID than the one recorded in
3512 resulting changeset has a different ID than the one recorded in
3513 the patch. This may happen due to character set problems or other
3513 the patch. This may happen due to character set problems or other
3514 deficiencies in the text patch format.
3514 deficiencies in the text patch format.
3515
3515
3516 Use --bypass to apply and commit patches directly to the
3516 Use --bypass to apply and commit patches directly to the
3517 repository, not touching the working directory. Without --exact,
3517 repository, not touching the working directory. Without --exact,
3518 patches will be applied on top of the working directory parent
3518 patches will be applied on top of the working directory parent
3519 revision.
3519 revision.
3520
3520
3521 With -s/--similarity, hg will attempt to discover renames and
3521 With -s/--similarity, hg will attempt to discover renames and
3522 copies in the patch in the same way as :hg:`addremove`.
3522 copies in the patch in the same way as :hg:`addremove`.
3523
3523
3524 To read a patch from standard input, use "-" as the patch name. If
3524 To read a patch from standard input, use "-" as the patch name. If
3525 a URL is specified, the patch will be downloaded from it.
3525 a URL is specified, the patch will be downloaded from it.
3526 See :hg:`help dates` for a list of formats valid for -d/--date.
3526 See :hg:`help dates` for a list of formats valid for -d/--date.
3527
3527
3528 .. container:: verbose
3528 .. container:: verbose
3529
3529
3530 Examples:
3530 Examples:
3531
3531
3532 - import a traditional patch from a website and detect renames::
3532 - import a traditional patch from a website and detect renames::
3533
3533
3534 hg import -s 80 http://example.com/bugfix.patch
3534 hg import -s 80 http://example.com/bugfix.patch
3535
3535
3536 - import a changeset from an hgweb server::
3536 - import a changeset from an hgweb server::
3537
3537
3538 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3538 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3539
3539
3540 - import all the patches in an Unix-style mbox::
3540 - import all the patches in an Unix-style mbox::
3541
3541
3542 hg import incoming-patches.mbox
3542 hg import incoming-patches.mbox
3543
3543
3544 - attempt to exactly restore an exported changeset (not always
3544 - attempt to exactly restore an exported changeset (not always
3545 possible)::
3545 possible)::
3546
3546
3547 hg import --exact proposed-fix.patch
3547 hg import --exact proposed-fix.patch
3548
3548
3549 Returns 0 on success.
3549 Returns 0 on success.
3550 """
3550 """
3551
3551
3552 if not patch1:
3552 if not patch1:
3553 raise util.Abort(_('need at least one patch to import'))
3553 raise util.Abort(_('need at least one patch to import'))
3554
3554
3555 patches = (patch1,) + patches
3555 patches = (patch1,) + patches
3556
3556
3557 date = opts.get('date')
3557 date = opts.get('date')
3558 if date:
3558 if date:
3559 opts['date'] = util.parsedate(date)
3559 opts['date'] = util.parsedate(date)
3560
3560
3561 editor = cmdutil.commiteditor
3561 editor = cmdutil.commiteditor
3562 if opts.get('edit'):
3562 if opts.get('edit'):
3563 editor = cmdutil.commitforceeditor
3563 editor = cmdutil.commitforceeditor
3564
3564
3565 update = not opts.get('bypass')
3565 update = not opts.get('bypass')
3566 if not update and opts.get('no_commit'):
3566 if not update and opts.get('no_commit'):
3567 raise util.Abort(_('cannot use --no-commit with --bypass'))
3567 raise util.Abort(_('cannot use --no-commit with --bypass'))
3568 try:
3568 try:
3569 sim = float(opts.get('similarity') or 0)
3569 sim = float(opts.get('similarity') or 0)
3570 except ValueError:
3570 except ValueError:
3571 raise util.Abort(_('similarity must be a number'))
3571 raise util.Abort(_('similarity must be a number'))
3572 if sim < 0 or sim > 100:
3572 if sim < 0 or sim > 100:
3573 raise util.Abort(_('similarity must be between 0 and 100'))
3573 raise util.Abort(_('similarity must be between 0 and 100'))
3574 if sim and not update:
3574 if sim and not update:
3575 raise util.Abort(_('cannot use --similarity with --bypass'))
3575 raise util.Abort(_('cannot use --similarity with --bypass'))
3576
3576
3577 if (opts.get('exact') or not opts.get('force')) and update:
3577 if (opts.get('exact') or not opts.get('force')) and update:
3578 cmdutil.bailifchanged(repo)
3578 cmdutil.bailifchanged(repo)
3579
3579
3580 base = opts["base"]
3580 base = opts["base"]
3581 strip = opts["strip"]
3581 strip = opts["strip"]
3582 wlock = lock = tr = None
3582 wlock = lock = tr = None
3583 msgs = []
3583 msgs = []
3584
3584
3585 def checkexact(repo, n, nodeid):
3585 def checkexact(repo, n, nodeid):
3586 if opts.get('exact') and hex(n) != nodeid:
3586 if opts.get('exact') and hex(n) != nodeid:
3587 repo.rollback()
3587 repo.rollback()
3588 raise util.Abort(_('patch is damaged or loses information'))
3588 raise util.Abort(_('patch is damaged or loses information'))
3589
3589
3590 def tryone(ui, hunk, parents):
3590 def tryone(ui, hunk, parents):
3591 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3591 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3592 patch.extract(ui, hunk)
3592 patch.extract(ui, hunk)
3593
3593
3594 if not tmpname:
3594 if not tmpname:
3595 return (None, None)
3595 return (None, None)
3596 msg = _('applied to working directory')
3596 msg = _('applied to working directory')
3597
3597
3598 try:
3598 try:
3599 cmdline_message = cmdutil.logmessage(ui, opts)
3599 cmdline_message = cmdutil.logmessage(ui, opts)
3600 if cmdline_message:
3600 if cmdline_message:
3601 # pickup the cmdline msg
3601 # pickup the cmdline msg
3602 message = cmdline_message
3602 message = cmdline_message
3603 elif message:
3603 elif message:
3604 # pickup the patch msg
3604 # pickup the patch msg
3605 message = message.strip()
3605 message = message.strip()
3606 else:
3606 else:
3607 # launch the editor
3607 # launch the editor
3608 message = None
3608 message = None
3609 ui.debug('message:\n%s\n' % message)
3609 ui.debug('message:\n%s\n' % message)
3610
3610
3611 if len(parents) == 1:
3611 if len(parents) == 1:
3612 parents.append(repo[nullid])
3612 parents.append(repo[nullid])
3613 if opts.get('exact'):
3613 if opts.get('exact'):
3614 if not nodeid or not p1:
3614 if not nodeid or not p1:
3615 raise util.Abort(_('not a Mercurial patch'))
3615 raise util.Abort(_('not a Mercurial patch'))
3616 p1 = repo[p1]
3616 p1 = repo[p1]
3617 p2 = repo[p2 or nullid]
3617 p2 = repo[p2 or nullid]
3618 elif p2:
3618 elif p2:
3619 try:
3619 try:
3620 p1 = repo[p1]
3620 p1 = repo[p1]
3621 p2 = repo[p2]
3621 p2 = repo[p2]
3622 # Without any options, consider p2 only if the
3622 # Without any options, consider p2 only if the
3623 # patch is being applied on top of the recorded
3623 # patch is being applied on top of the recorded
3624 # first parent.
3624 # first parent.
3625 if p1 != parents[0]:
3625 if p1 != parents[0]:
3626 p1 = parents[0]
3626 p1 = parents[0]
3627 p2 = repo[nullid]
3627 p2 = repo[nullid]
3628 except error.RepoError:
3628 except error.RepoError:
3629 p1, p2 = parents
3629 p1, p2 = parents
3630 else:
3630 else:
3631 p1, p2 = parents
3631 p1, p2 = parents
3632
3632
3633 n = None
3633 n = None
3634 if update:
3634 if update:
3635 if p1 != parents[0]:
3635 if p1 != parents[0]:
3636 hg.clean(repo, p1.node())
3636 hg.clean(repo, p1.node())
3637 if p2 != parents[1]:
3637 if p2 != parents[1]:
3638 repo.dirstate.setparents(p1.node(), p2.node())
3638 repo.dirstate.setparents(p1.node(), p2.node())
3639
3639
3640 if opts.get('exact') or opts.get('import_branch'):
3640 if opts.get('exact') or opts.get('import_branch'):
3641 repo.dirstate.setbranch(branch or 'default')
3641 repo.dirstate.setbranch(branch or 'default')
3642
3642
3643 files = set()
3643 files = set()
3644 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3644 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3645 eolmode=None, similarity=sim / 100.0)
3645 eolmode=None, similarity=sim / 100.0)
3646 files = list(files)
3646 files = list(files)
3647 if opts.get('no_commit'):
3647 if opts.get('no_commit'):
3648 if message:
3648 if message:
3649 msgs.append(message)
3649 msgs.append(message)
3650 else:
3650 else:
3651 if opts.get('exact') or p2:
3651 if opts.get('exact') or p2:
3652 # If you got here, you either use --force and know what
3652 # If you got here, you either use --force and know what
3653 # you are doing or used --exact or a merge patch while
3653 # you are doing or used --exact or a merge patch while
3654 # being updated to its first parent.
3654 # being updated to its first parent.
3655 m = None
3655 m = None
3656 else:
3656 else:
3657 m = scmutil.matchfiles(repo, files or [])
3657 m = scmutil.matchfiles(repo, files or [])
3658 n = repo.commit(message, opts.get('user') or user,
3658 n = repo.commit(message, opts.get('user') or user,
3659 opts.get('date') or date, match=m,
3659 opts.get('date') or date, match=m,
3660 editor=editor)
3660 editor=editor)
3661 checkexact(repo, n, nodeid)
3661 checkexact(repo, n, nodeid)
3662 else:
3662 else:
3663 if opts.get('exact') or opts.get('import_branch'):
3663 if opts.get('exact') or opts.get('import_branch'):
3664 branch = branch or 'default'
3664 branch = branch or 'default'
3665 else:
3665 else:
3666 branch = p1.branch()
3666 branch = p1.branch()
3667 store = patch.filestore()
3667 store = patch.filestore()
3668 try:
3668 try:
3669 files = set()
3669 files = set()
3670 try:
3670 try:
3671 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3671 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3672 files, eolmode=None)
3672 files, eolmode=None)
3673 except patch.PatchError, e:
3673 except patch.PatchError, e:
3674 raise util.Abort(str(e))
3674 raise util.Abort(str(e))
3675 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3675 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3676 message,
3676 message,
3677 opts.get('user') or user,
3677 opts.get('user') or user,
3678 opts.get('date') or date,
3678 opts.get('date') or date,
3679 branch, files, store,
3679 branch, files, store,
3680 editor=cmdutil.commiteditor)
3680 editor=cmdutil.commiteditor)
3681 repo.savecommitmessage(memctx.description())
3681 repo.savecommitmessage(memctx.description())
3682 n = memctx.commit()
3682 n = memctx.commit()
3683 checkexact(repo, n, nodeid)
3683 checkexact(repo, n, nodeid)
3684 finally:
3684 finally:
3685 store.close()
3685 store.close()
3686 if n:
3686 if n:
3687 # i18n: refers to a short changeset id
3687 # i18n: refers to a short changeset id
3688 msg = _('created %s') % short(n)
3688 msg = _('created %s') % short(n)
3689 return (msg, n)
3689 return (msg, n)
3690 finally:
3690 finally:
3691 os.unlink(tmpname)
3691 os.unlink(tmpname)
3692
3692
3693 try:
3693 try:
3694 try:
3694 try:
3695 wlock = repo.wlock()
3695 wlock = repo.wlock()
3696 if not opts.get('no_commit'):
3696 if not opts.get('no_commit'):
3697 lock = repo.lock()
3697 lock = repo.lock()
3698 tr = repo.transaction('import')
3698 tr = repo.transaction('import')
3699 parents = repo.parents()
3699 parents = repo.parents()
3700 for patchurl in patches:
3700 for patchurl in patches:
3701 if patchurl == '-':
3701 if patchurl == '-':
3702 ui.status(_('applying patch from stdin\n'))
3702 ui.status(_('applying patch from stdin\n'))
3703 patchfile = ui.fin
3703 patchfile = ui.fin
3704 patchurl = 'stdin' # for error message
3704 patchurl = 'stdin' # for error message
3705 else:
3705 else:
3706 patchurl = os.path.join(base, patchurl)
3706 patchurl = os.path.join(base, patchurl)
3707 ui.status(_('applying %s\n') % patchurl)
3707 ui.status(_('applying %s\n') % patchurl)
3708 patchfile = url.open(ui, patchurl)
3708 patchfile = url.open(ui, patchurl)
3709
3709
3710 haspatch = False
3710 haspatch = False
3711 for hunk in patch.split(patchfile):
3711 for hunk in patch.split(patchfile):
3712 (msg, node) = tryone(ui, hunk, parents)
3712 (msg, node) = tryone(ui, hunk, parents)
3713 if msg:
3713 if msg:
3714 haspatch = True
3714 haspatch = True
3715 ui.note(msg + '\n')
3715 ui.note(msg + '\n')
3716 if update or opts.get('exact'):
3716 if update or opts.get('exact'):
3717 parents = repo.parents()
3717 parents = repo.parents()
3718 else:
3718 else:
3719 parents = [repo[node]]
3719 parents = [repo[node]]
3720
3720
3721 if not haspatch:
3721 if not haspatch:
3722 raise util.Abort(_('%s: no diffs found') % patchurl)
3722 raise util.Abort(_('%s: no diffs found') % patchurl)
3723
3723
3724 if tr:
3724 if tr:
3725 tr.close()
3725 tr.close()
3726 if msgs:
3726 if msgs:
3727 repo.savecommitmessage('\n* * *\n'.join(msgs))
3727 repo.savecommitmessage('\n* * *\n'.join(msgs))
3728 except:
3728 except:
3729 # wlock.release() indirectly calls dirstate.write(): since
3729 # wlock.release() indirectly calls dirstate.write(): since
3730 # we're crashing, we do not want to change the working dir
3730 # we're crashing, we do not want to change the working dir
3731 # parent after all, so make sure it writes nothing
3731 # parent after all, so make sure it writes nothing
3732 repo.dirstate.invalidate()
3732 repo.dirstate.invalidate()
3733 raise
3733 raise
3734 finally:
3734 finally:
3735 if tr:
3735 if tr:
3736 tr.release()
3736 tr.release()
3737 release(lock, wlock)
3737 release(lock, wlock)
3738
3738
3739 @command('incoming|in',
3739 @command('incoming|in',
3740 [('f', 'force', None,
3740 [('f', 'force', None,
3741 _('run even if remote repository is unrelated')),
3741 _('run even if remote repository is unrelated')),
3742 ('n', 'newest-first', None, _('show newest record first')),
3742 ('n', 'newest-first', None, _('show newest record first')),
3743 ('', 'bundle', '',
3743 ('', 'bundle', '',
3744 _('file to store the bundles into'), _('FILE')),
3744 _('file to store the bundles into'), _('FILE')),
3745 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3745 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3746 ('B', 'bookmarks', False, _("compare bookmarks")),
3746 ('B', 'bookmarks', False, _("compare bookmarks")),
3747 ('b', 'branch', [],
3747 ('b', 'branch', [],
3748 _('a specific branch you would like to pull'), _('BRANCH')),
3748 _('a specific branch you would like to pull'), _('BRANCH')),
3749 ] + logopts + remoteopts + subrepoopts,
3749 ] + logopts + remoteopts + subrepoopts,
3750 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3750 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3751 def incoming(ui, repo, source="default", **opts):
3751 def incoming(ui, repo, source="default", **opts):
3752 """show new changesets found in source
3752 """show new changesets found in source
3753
3753
3754 Show new changesets found in the specified path/URL or the default
3754 Show new changesets found in the specified path/URL or the default
3755 pull location. These are the changesets that would have been pulled
3755 pull location. These are the changesets that would have been pulled
3756 if a pull at the time you issued this command.
3756 if a pull at the time you issued this command.
3757
3757
3758 For remote repository, using --bundle avoids downloading the
3758 For remote repository, using --bundle avoids downloading the
3759 changesets twice if the incoming is followed by a pull.
3759 changesets twice if the incoming is followed by a pull.
3760
3760
3761 See pull for valid source format details.
3761 See pull for valid source format details.
3762
3762
3763 Returns 0 if there are incoming changes, 1 otherwise.
3763 Returns 0 if there are incoming changes, 1 otherwise.
3764 """
3764 """
3765 if opts.get('bundle') and opts.get('subrepos'):
3765 if opts.get('bundle') and opts.get('subrepos'):
3766 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3766 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3767
3767
3768 if opts.get('bookmarks'):
3768 if opts.get('bookmarks'):
3769 source, branches = hg.parseurl(ui.expandpath(source),
3769 source, branches = hg.parseurl(ui.expandpath(source),
3770 opts.get('branch'))
3770 opts.get('branch'))
3771 other = hg.peer(repo, opts, source)
3771 other = hg.peer(repo, opts, source)
3772 if 'bookmarks' not in other.listkeys('namespaces'):
3772 if 'bookmarks' not in other.listkeys('namespaces'):
3773 ui.warn(_("remote doesn't support bookmarks\n"))
3773 ui.warn(_("remote doesn't support bookmarks\n"))
3774 return 0
3774 return 0
3775 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3775 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3776 return bookmarks.diff(ui, repo, other)
3776 return bookmarks.diff(ui, repo, other)
3777
3777
3778 repo._subtoppath = ui.expandpath(source)
3778 repo._subtoppath = ui.expandpath(source)
3779 try:
3779 try:
3780 return hg.incoming(ui, repo, source, opts)
3780 return hg.incoming(ui, repo, source, opts)
3781 finally:
3781 finally:
3782 del repo._subtoppath
3782 del repo._subtoppath
3783
3783
3784
3784
3785 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3785 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3786 def init(ui, dest=".", **opts):
3786 def init(ui, dest=".", **opts):
3787 """create a new repository in the given directory
3787 """create a new repository in the given directory
3788
3788
3789 Initialize a new repository in the given directory. If the given
3789 Initialize a new repository in the given directory. If the given
3790 directory does not exist, it will be created.
3790 directory does not exist, it will be created.
3791
3791
3792 If no directory is given, the current directory is used.
3792 If no directory is given, the current directory is used.
3793
3793
3794 It is possible to specify an ``ssh://`` URL as the destination.
3794 It is possible to specify an ``ssh://`` URL as the destination.
3795 See :hg:`help urls` for more information.
3795 See :hg:`help urls` for more information.
3796
3796
3797 Returns 0 on success.
3797 Returns 0 on success.
3798 """
3798 """
3799 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3799 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3800
3800
3801 @command('locate',
3801 @command('locate',
3802 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3802 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3803 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3803 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3804 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3804 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3805 ] + walkopts,
3805 ] + walkopts,
3806 _('[OPTION]... [PATTERN]...'))
3806 _('[OPTION]... [PATTERN]...'))
3807 def locate(ui, repo, *pats, **opts):
3807 def locate(ui, repo, *pats, **opts):
3808 """locate files matching specific patterns
3808 """locate files matching specific patterns
3809
3809
3810 Print files under Mercurial control in the working directory whose
3810 Print files under Mercurial control in the working directory whose
3811 names match the given patterns.
3811 names match the given patterns.
3812
3812
3813 By default, this command searches all directories in the working
3813 By default, this command searches all directories in the working
3814 directory. To search just the current directory and its
3814 directory. To search just the current directory and its
3815 subdirectories, use "--include .".
3815 subdirectories, use "--include .".
3816
3816
3817 If no patterns are given to match, this command prints the names
3817 If no patterns are given to match, this command prints the names
3818 of all files under Mercurial control in the working directory.
3818 of all files under Mercurial control in the working directory.
3819
3819
3820 If you want to feed the output of this command into the "xargs"
3820 If you want to feed the output of this command into the "xargs"
3821 command, use the -0 option to both this command and "xargs". This
3821 command, use the -0 option to both this command and "xargs". This
3822 will avoid the problem of "xargs" treating single filenames that
3822 will avoid the problem of "xargs" treating single filenames that
3823 contain whitespace as multiple filenames.
3823 contain whitespace as multiple filenames.
3824
3824
3825 Returns 0 if a match is found, 1 otherwise.
3825 Returns 0 if a match is found, 1 otherwise.
3826 """
3826 """
3827 end = opts.get('print0') and '\0' or '\n'
3827 end = opts.get('print0') and '\0' or '\n'
3828 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3828 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3829
3829
3830 ret = 1
3830 ret = 1
3831 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3831 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3832 m.bad = lambda x, y: False
3832 m.bad = lambda x, y: False
3833 for abs in repo[rev].walk(m):
3833 for abs in repo[rev].walk(m):
3834 if not rev and abs not in repo.dirstate:
3834 if not rev and abs not in repo.dirstate:
3835 continue
3835 continue
3836 if opts.get('fullpath'):
3836 if opts.get('fullpath'):
3837 ui.write(repo.wjoin(abs), end)
3837 ui.write(repo.wjoin(abs), end)
3838 else:
3838 else:
3839 ui.write(((pats and m.rel(abs)) or abs), end)
3839 ui.write(((pats and m.rel(abs)) or abs), end)
3840 ret = 0
3840 ret = 0
3841
3841
3842 return ret
3842 return ret
3843
3843
3844 @command('^log|history',
3844 @command('^log|history',
3845 [('f', 'follow', None,
3845 [('f', 'follow', None,
3846 _('follow changeset history, or file history across copies and renames')),
3846 _('follow changeset history, or file history across copies and renames')),
3847 ('', 'follow-first', None,
3847 ('', 'follow-first', None,
3848 _('only follow the first parent of merge changesets (DEPRECATED)')),
3848 _('only follow the first parent of merge changesets (DEPRECATED)')),
3849 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3849 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3850 ('C', 'copies', None, _('show copied files')),
3850 ('C', 'copies', None, _('show copied files')),
3851 ('k', 'keyword', [],
3851 ('k', 'keyword', [],
3852 _('do case-insensitive search for a given text'), _('TEXT')),
3852 _('do case-insensitive search for a given text'), _('TEXT')),
3853 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3853 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3854 ('', 'removed', None, _('include revisions where files were removed')),
3854 ('', 'removed', None, _('include revisions where files were removed')),
3855 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3855 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3856 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3856 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3857 ('', 'only-branch', [],
3857 ('', 'only-branch', [],
3858 _('show only changesets within the given named branch (DEPRECATED)'),
3858 _('show only changesets within the given named branch (DEPRECATED)'),
3859 _('BRANCH')),
3859 _('BRANCH')),
3860 ('b', 'branch', [],
3860 ('b', 'branch', [],
3861 _('show changesets within the given named branch'), _('BRANCH')),
3861 _('show changesets within the given named branch'), _('BRANCH')),
3862 ('P', 'prune', [],
3862 ('P', 'prune', [],
3863 _('do not display revision or any of its ancestors'), _('REV')),
3863 _('do not display revision or any of its ancestors'), _('REV')),
3864 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3864 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3865 ] + logopts + walkopts,
3865 ] + logopts + walkopts,
3866 _('[OPTION]... [FILE]'))
3866 _('[OPTION]... [FILE]'))
3867 def log(ui, repo, *pats, **opts):
3867 def log(ui, repo, *pats, **opts):
3868 """show revision history of entire repository or files
3868 """show revision history of entire repository or files
3869
3869
3870 Print the revision history of the specified files or the entire
3870 Print the revision history of the specified files or the entire
3871 project.
3871 project.
3872
3872
3873 If no revision range is specified, the default is ``tip:0`` unless
3873 If no revision range is specified, the default is ``tip:0`` unless
3874 --follow is set, in which case the working directory parent is
3874 --follow is set, in which case the working directory parent is
3875 used as the starting revision.
3875 used as the starting revision.
3876
3876
3877 File history is shown without following rename or copy history of
3877 File history is shown without following rename or copy history of
3878 files. Use -f/--follow with a filename to follow history across
3878 files. Use -f/--follow with a filename to follow history across
3879 renames and copies. --follow without a filename will only show
3879 renames and copies. --follow without a filename will only show
3880 ancestors or descendants of the starting revision.
3880 ancestors or descendants of the starting revision.
3881
3881
3882 By default this command prints revision number and changeset id,
3882 By default this command prints revision number and changeset id,
3883 tags, non-trivial parents, user, date and time, and a summary for
3883 tags, non-trivial parents, user, date and time, and a summary for
3884 each commit. When the -v/--verbose switch is used, the list of
3884 each commit. When the -v/--verbose switch is used, the list of
3885 changed files and full commit message are shown.
3885 changed files and full commit message are shown.
3886
3886
3887 .. note::
3887 .. note::
3888 log -p/--patch may generate unexpected diff output for merge
3888 log -p/--patch may generate unexpected diff output for merge
3889 changesets, as it will only compare the merge changeset against
3889 changesets, as it will only compare the merge changeset against
3890 its first parent. Also, only files different from BOTH parents
3890 its first parent. Also, only files different from BOTH parents
3891 will appear in files:.
3891 will appear in files:.
3892
3892
3893 .. note::
3893 .. note::
3894 for performance reasons, log FILE may omit duplicate changes
3894 for performance reasons, log FILE may omit duplicate changes
3895 made on branches and will not show deletions. To see all
3895 made on branches and will not show deletions. To see all
3896 changes including duplicates and deletions, use the --removed
3896 changes including duplicates and deletions, use the --removed
3897 switch.
3897 switch.
3898
3898
3899 .. container:: verbose
3899 .. container:: verbose
3900
3900
3901 Some examples:
3901 Some examples:
3902
3902
3903 - changesets with full descriptions and file lists::
3903 - changesets with full descriptions and file lists::
3904
3904
3905 hg log -v
3905 hg log -v
3906
3906
3907 - changesets ancestral to the working directory::
3907 - changesets ancestral to the working directory::
3908
3908
3909 hg log -f
3909 hg log -f
3910
3910
3911 - last 10 commits on the current branch::
3911 - last 10 commits on the current branch::
3912
3912
3913 hg log -l 10 -b .
3913 hg log -l 10 -b .
3914
3914
3915 - changesets showing all modifications of a file, including removals::
3915 - changesets showing all modifications of a file, including removals::
3916
3916
3917 hg log --removed file.c
3917 hg log --removed file.c
3918
3918
3919 - all changesets that touch a directory, with diffs, excluding merges::
3919 - all changesets that touch a directory, with diffs, excluding merges::
3920
3920
3921 hg log -Mp lib/
3921 hg log -Mp lib/
3922
3922
3923 - all revision numbers that match a keyword::
3923 - all revision numbers that match a keyword::
3924
3924
3925 hg log -k bug --template "{rev}\\n"
3925 hg log -k bug --template "{rev}\\n"
3926
3926
3927 - check if a given changeset is included is a tagged release::
3927 - check if a given changeset is included is a tagged release::
3928
3928
3929 hg log -r "a21ccf and ancestor(1.9)"
3929 hg log -r "a21ccf and ancestor(1.9)"
3930
3930
3931 - find all changesets by some user in a date range::
3931 - find all changesets by some user in a date range::
3932
3932
3933 hg log -k alice -d "may 2008 to jul 2008"
3933 hg log -k alice -d "may 2008 to jul 2008"
3934
3934
3935 - summary of all changesets after the last tag::
3935 - summary of all changesets after the last tag::
3936
3936
3937 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3937 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3938
3938
3939 See :hg:`help dates` for a list of formats valid for -d/--date.
3939 See :hg:`help dates` for a list of formats valid for -d/--date.
3940
3940
3941 See :hg:`help revisions` and :hg:`help revsets` for more about
3941 See :hg:`help revisions` and :hg:`help revsets` for more about
3942 specifying revisions.
3942 specifying revisions.
3943
3943
3944 Returns 0 on success.
3944 Returns 0 on success.
3945 """
3945 """
3946
3946
3947 matchfn = scmutil.match(repo[None], pats, opts)
3947 matchfn = scmutil.match(repo[None], pats, opts)
3948 limit = cmdutil.loglimit(opts)
3948 limit = cmdutil.loglimit(opts)
3949 count = 0
3949 count = 0
3950
3950
3951 getrenamed, endrev = None, None
3951 getrenamed, endrev = None, None
3952 if opts.get('copies'):
3952 if opts.get('copies'):
3953 if opts.get('rev'):
3953 if opts.get('rev'):
3954 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3954 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3955 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3955 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3956
3956
3957 df = False
3957 df = False
3958 if opts["date"]:
3958 if opts["date"]:
3959 df = util.matchdate(opts["date"])
3959 df = util.matchdate(opts["date"])
3960
3960
3961 branches = opts.get('branch', []) + opts.get('only_branch', [])
3961 branches = opts.get('branch', []) + opts.get('only_branch', [])
3962 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3962 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3963
3963
3964 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3964 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3965 def prep(ctx, fns):
3965 def prep(ctx, fns):
3966 rev = ctx.rev()
3966 rev = ctx.rev()
3967 parents = [p for p in repo.changelog.parentrevs(rev)
3967 parents = [p for p in repo.changelog.parentrevs(rev)
3968 if p != nullrev]
3968 if p != nullrev]
3969 if opts.get('no_merges') and len(parents) == 2:
3969 if opts.get('no_merges') and len(parents) == 2:
3970 return
3970 return
3971 if opts.get('only_merges') and len(parents) != 2:
3971 if opts.get('only_merges') and len(parents) != 2:
3972 return
3972 return
3973 if opts.get('branch') and ctx.branch() not in opts['branch']:
3973 if opts.get('branch') and ctx.branch() not in opts['branch']:
3974 return
3974 return
3975 if not opts.get('hidden') and ctx.hidden():
3975 if not opts.get('hidden') and ctx.hidden():
3976 return
3976 return
3977 if df and not df(ctx.date()[0]):
3977 if df and not df(ctx.date()[0]):
3978 return
3978 return
3979
3979
3980 lower = encoding.lower
3980 lower = encoding.lower
3981 if opts.get('user'):
3981 if opts.get('user'):
3982 luser = lower(ctx.user())
3982 luser = lower(ctx.user())
3983 for k in [lower(x) for x in opts['user']]:
3983 for k in [lower(x) for x in opts['user']]:
3984 if (k in luser):
3984 if (k in luser):
3985 break
3985 break
3986 else:
3986 else:
3987 return
3987 return
3988 if opts.get('keyword'):
3988 if opts.get('keyword'):
3989 luser = lower(ctx.user())
3989 luser = lower(ctx.user())
3990 ldesc = lower(ctx.description())
3990 ldesc = lower(ctx.description())
3991 lfiles = lower(" ".join(ctx.files()))
3991 lfiles = lower(" ".join(ctx.files()))
3992 for k in [lower(x) for x in opts['keyword']]:
3992 for k in [lower(x) for x in opts['keyword']]:
3993 if (k in luser or k in ldesc or k in lfiles):
3993 if (k in luser or k in ldesc or k in lfiles):
3994 break
3994 break
3995 else:
3995 else:
3996 return
3996 return
3997
3997
3998 copies = None
3998 copies = None
3999 if getrenamed is not None and rev:
3999 if getrenamed is not None and rev:
4000 copies = []
4000 copies = []
4001 for fn in ctx.files():
4001 for fn in ctx.files():
4002 rename = getrenamed(fn, rev)
4002 rename = getrenamed(fn, rev)
4003 if rename:
4003 if rename:
4004 copies.append((fn, rename[0]))
4004 copies.append((fn, rename[0]))
4005
4005
4006 revmatchfn = None
4006 revmatchfn = None
4007 if opts.get('patch') or opts.get('stat'):
4007 if opts.get('patch') or opts.get('stat'):
4008 if opts.get('follow') or opts.get('follow_first'):
4008 if opts.get('follow') or opts.get('follow_first'):
4009 # note: this might be wrong when following through merges
4009 # note: this might be wrong when following through merges
4010 revmatchfn = scmutil.match(repo[None], fns, default='path')
4010 revmatchfn = scmutil.match(repo[None], fns, default='path')
4011 else:
4011 else:
4012 revmatchfn = matchfn
4012 revmatchfn = matchfn
4013
4013
4014 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4014 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4015
4015
4016 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4016 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4017 if count == limit:
4017 if count == limit:
4018 break
4018 break
4019 if displayer.flush(ctx.rev()):
4019 if displayer.flush(ctx.rev()):
4020 count += 1
4020 count += 1
4021 displayer.close()
4021 displayer.close()
4022
4022
4023 @command('manifest',
4023 @command('manifest',
4024 [('r', 'rev', '', _('revision to display'), _('REV')),
4024 [('r', 'rev', '', _('revision to display'), _('REV')),
4025 ('', 'all', False, _("list files from all revisions"))],
4025 ('', 'all', False, _("list files from all revisions"))],
4026 _('[-r REV]'))
4026 _('[-r REV]'))
4027 def manifest(ui, repo, node=None, rev=None, **opts):
4027 def manifest(ui, repo, node=None, rev=None, **opts):
4028 """output the current or given revision of the project manifest
4028 """output the current or given revision of the project manifest
4029
4029
4030 Print a list of version controlled files for the given revision.
4030 Print a list of version controlled files for the given revision.
4031 If no revision is given, the first parent of the working directory
4031 If no revision is given, the first parent of the working directory
4032 is used, or the null revision if no revision is checked out.
4032 is used, or the null revision if no revision is checked out.
4033
4033
4034 With -v, print file permissions, symlink and executable bits.
4034 With -v, print file permissions, symlink and executable bits.
4035 With --debug, print file revision hashes.
4035 With --debug, print file revision hashes.
4036
4036
4037 If option --all is specified, the list of all files from all revisions
4037 If option --all is specified, the list of all files from all revisions
4038 is printed. This includes deleted and renamed files.
4038 is printed. This includes deleted and renamed files.
4039
4039
4040 Returns 0 on success.
4040 Returns 0 on success.
4041 """
4041 """
4042 if opts.get('all'):
4042 if opts.get('all'):
4043 if rev or node:
4043 if rev or node:
4044 raise util.Abort(_("can't specify a revision with --all"))
4044 raise util.Abort(_("can't specify a revision with --all"))
4045
4045
4046 res = []
4046 res = []
4047 prefix = "data/"
4047 prefix = "data/"
4048 suffix = ".i"
4048 suffix = ".i"
4049 plen = len(prefix)
4049 plen = len(prefix)
4050 slen = len(suffix)
4050 slen = len(suffix)
4051 lock = repo.lock()
4051 lock = repo.lock()
4052 try:
4052 try:
4053 for fn, b, size in repo.store.datafiles():
4053 for fn, b, size in repo.store.datafiles():
4054 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4054 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4055 res.append(fn[plen:-slen])
4055 res.append(fn[plen:-slen])
4056 finally:
4056 finally:
4057 lock.release()
4057 lock.release()
4058 for f in sorted(res):
4058 for f in sorted(res):
4059 ui.write("%s\n" % f)
4059 ui.write("%s\n" % f)
4060 return
4060 return
4061
4061
4062 if rev and node:
4062 if rev and node:
4063 raise util.Abort(_("please specify just one revision"))
4063 raise util.Abort(_("please specify just one revision"))
4064
4064
4065 if not node:
4065 if not node:
4066 node = rev
4066 node = rev
4067
4067
4068 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4068 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4069 ctx = scmutil.revsingle(repo, node)
4069 ctx = scmutil.revsingle(repo, node)
4070 for f in ctx:
4070 for f in ctx:
4071 if ui.debugflag:
4071 if ui.debugflag:
4072 ui.write("%40s " % hex(ctx.manifest()[f]))
4072 ui.write("%40s " % hex(ctx.manifest()[f]))
4073 if ui.verbose:
4073 if ui.verbose:
4074 ui.write(decor[ctx.flags(f)])
4074 ui.write(decor[ctx.flags(f)])
4075 ui.write("%s\n" % f)
4075 ui.write("%s\n" % f)
4076
4076
4077 @command('^merge',
4077 @command('^merge',
4078 [('f', 'force', None, _('force a merge with outstanding changes')),
4078 [('f', 'force', None, _('force a merge with outstanding changes')),
4079 ('r', 'rev', '', _('revision to merge'), _('REV')),
4079 ('r', 'rev', '', _('revision to merge'), _('REV')),
4080 ('P', 'preview', None,
4080 ('P', 'preview', None,
4081 _('review revisions to merge (no merge is performed)'))
4081 _('review revisions to merge (no merge is performed)'))
4082 ] + mergetoolopts,
4082 ] + mergetoolopts,
4083 _('[-P] [-f] [[-r] REV]'))
4083 _('[-P] [-f] [[-r] REV]'))
4084 def merge(ui, repo, node=None, **opts):
4084 def merge(ui, repo, node=None, **opts):
4085 """merge working directory with another revision
4085 """merge working directory with another revision
4086
4086
4087 The current working directory is updated with all changes made in
4087 The current working directory is updated with all changes made in
4088 the requested revision since the last common predecessor revision.
4088 the requested revision since the last common predecessor revision.
4089
4089
4090 Files that changed between either parent are marked as changed for
4090 Files that changed between either parent are marked as changed for
4091 the next commit and a commit must be performed before any further
4091 the next commit and a commit must be performed before any further
4092 updates to the repository are allowed. The next commit will have
4092 updates to the repository are allowed. The next commit will have
4093 two parents.
4093 two parents.
4094
4094
4095 ``--tool`` can be used to specify the merge tool used for file
4095 ``--tool`` can be used to specify the merge tool used for file
4096 merges. It overrides the HGMERGE environment variable and your
4096 merges. It overrides the HGMERGE environment variable and your
4097 configuration files. See :hg:`help merge-tools` for options.
4097 configuration files. See :hg:`help merge-tools` for options.
4098
4098
4099 If no revision is specified, the working directory's parent is a
4099 If no revision is specified, the working directory's parent is a
4100 head revision, and the current branch contains exactly one other
4100 head revision, and the current branch contains exactly one other
4101 head, the other head is merged with by default. Otherwise, an
4101 head, the other head is merged with by default. Otherwise, an
4102 explicit revision with which to merge with must be provided.
4102 explicit revision with which to merge with must be provided.
4103
4103
4104 :hg:`resolve` must be used to resolve unresolved files.
4104 :hg:`resolve` must be used to resolve unresolved files.
4105
4105
4106 To undo an uncommitted merge, use :hg:`update --clean .` which
4106 To undo an uncommitted merge, use :hg:`update --clean .` which
4107 will check out a clean copy of the original merge parent, losing
4107 will check out a clean copy of the original merge parent, losing
4108 all changes.
4108 all changes.
4109
4109
4110 Returns 0 on success, 1 if there are unresolved files.
4110 Returns 0 on success, 1 if there are unresolved files.
4111 """
4111 """
4112
4112
4113 if opts.get('rev') and node:
4113 if opts.get('rev') and node:
4114 raise util.Abort(_("please specify just one revision"))
4114 raise util.Abort(_("please specify just one revision"))
4115 if not node:
4115 if not node:
4116 node = opts.get('rev')
4116 node = opts.get('rev')
4117
4117
4118 if not node:
4118 if not node:
4119 branch = repo[None].branch()
4119 branch = repo[None].branch()
4120 bheads = repo.branchheads(branch)
4120 bheads = repo.branchheads(branch)
4121 if len(bheads) > 2:
4121 if len(bheads) > 2:
4122 raise util.Abort(_("branch '%s' has %d heads - "
4122 raise util.Abort(_("branch '%s' has %d heads - "
4123 "please merge with an explicit rev")
4123 "please merge with an explicit rev")
4124 % (branch, len(bheads)),
4124 % (branch, len(bheads)),
4125 hint=_("run 'hg heads .' to see heads"))
4125 hint=_("run 'hg heads .' to see heads"))
4126
4126
4127 parent = repo.dirstate.p1()
4127 parent = repo.dirstate.p1()
4128 if len(bheads) == 1:
4128 if len(bheads) == 1:
4129 if len(repo.heads()) > 1:
4129 if len(repo.heads()) > 1:
4130 raise util.Abort(_("branch '%s' has one head - "
4130 raise util.Abort(_("branch '%s' has one head - "
4131 "please merge with an explicit rev")
4131 "please merge with an explicit rev")
4132 % branch,
4132 % branch,
4133 hint=_("run 'hg heads' to see all heads"))
4133 hint=_("run 'hg heads' to see all heads"))
4134 msg, hint = _('nothing to merge'), None
4134 msg, hint = _('nothing to merge'), None
4135 if parent != repo.lookup(branch):
4135 if parent != repo.lookup(branch):
4136 hint = _("use 'hg update' instead")
4136 hint = _("use 'hg update' instead")
4137 raise util.Abort(msg, hint=hint)
4137 raise util.Abort(msg, hint=hint)
4138
4138
4139 if parent not in bheads:
4139 if parent not in bheads:
4140 raise util.Abort(_('working directory not at a head revision'),
4140 raise util.Abort(_('working directory not at a head revision'),
4141 hint=_("use 'hg update' or merge with an "
4141 hint=_("use 'hg update' or merge with an "
4142 "explicit revision"))
4142 "explicit revision"))
4143 node = parent == bheads[0] and bheads[-1] or bheads[0]
4143 node = parent == bheads[0] and bheads[-1] or bheads[0]
4144 else:
4144 else:
4145 node = scmutil.revsingle(repo, node).node()
4145 node = scmutil.revsingle(repo, node).node()
4146
4146
4147 if opts.get('preview'):
4147 if opts.get('preview'):
4148 # find nodes that are ancestors of p2 but not of p1
4148 # find nodes that are ancestors of p2 but not of p1
4149 p1 = repo.lookup('.')
4149 p1 = repo.lookup('.')
4150 p2 = repo.lookup(node)
4150 p2 = repo.lookup(node)
4151 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4151 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4152
4152
4153 displayer = cmdutil.show_changeset(ui, repo, opts)
4153 displayer = cmdutil.show_changeset(ui, repo, opts)
4154 for node in nodes:
4154 for node in nodes:
4155 displayer.show(repo[node])
4155 displayer.show(repo[node])
4156 displayer.close()
4156 displayer.close()
4157 return 0
4157 return 0
4158
4158
4159 try:
4159 try:
4160 # ui.forcemerge is an internal variable, do not document
4160 # ui.forcemerge is an internal variable, do not document
4161 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4161 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4162 return hg.merge(repo, node, force=opts.get('force'))
4162 return hg.merge(repo, node, force=opts.get('force'))
4163 finally:
4163 finally:
4164 ui.setconfig('ui', 'forcemerge', '')
4164 ui.setconfig('ui', 'forcemerge', '')
4165
4165
4166 @command('outgoing|out',
4166 @command('outgoing|out',
4167 [('f', 'force', None, _('run even when the destination is unrelated')),
4167 [('f', 'force', None, _('run even when the destination is unrelated')),
4168 ('r', 'rev', [],
4168 ('r', 'rev', [],
4169 _('a changeset intended to be included in the destination'), _('REV')),
4169 _('a changeset intended to be included in the destination'), _('REV')),
4170 ('n', 'newest-first', None, _('show newest record first')),
4170 ('n', 'newest-first', None, _('show newest record first')),
4171 ('B', 'bookmarks', False, _('compare bookmarks')),
4171 ('B', 'bookmarks', False, _('compare bookmarks')),
4172 ('b', 'branch', [], _('a specific branch you would like to push'),
4172 ('b', 'branch', [], _('a specific branch you would like to push'),
4173 _('BRANCH')),
4173 _('BRANCH')),
4174 ] + logopts + remoteopts + subrepoopts,
4174 ] + logopts + remoteopts + subrepoopts,
4175 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4175 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4176 def outgoing(ui, repo, dest=None, **opts):
4176 def outgoing(ui, repo, dest=None, **opts):
4177 """show changesets not found in the destination
4177 """show changesets not found in the destination
4178
4178
4179 Show changesets not found in the specified destination repository
4179 Show changesets not found in the specified destination repository
4180 or the default push location. These are the changesets that would
4180 or the default push location. These are the changesets that would
4181 be pushed if a push was requested.
4181 be pushed if a push was requested.
4182
4182
4183 See pull for details of valid destination formats.
4183 See pull for details of valid destination formats.
4184
4184
4185 Returns 0 if there are outgoing changes, 1 otherwise.
4185 Returns 0 if there are outgoing changes, 1 otherwise.
4186 """
4186 """
4187
4187
4188 if opts.get('bookmarks'):
4188 if opts.get('bookmarks'):
4189 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4189 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4190 dest, branches = hg.parseurl(dest, opts.get('branch'))
4190 dest, branches = hg.parseurl(dest, opts.get('branch'))
4191 other = hg.peer(repo, opts, dest)
4191 other = hg.peer(repo, opts, dest)
4192 if 'bookmarks' not in other.listkeys('namespaces'):
4192 if 'bookmarks' not in other.listkeys('namespaces'):
4193 ui.warn(_("remote doesn't support bookmarks\n"))
4193 ui.warn(_("remote doesn't support bookmarks\n"))
4194 return 0
4194 return 0
4195 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4195 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4196 return bookmarks.diff(ui, other, repo)
4196 return bookmarks.diff(ui, other, repo)
4197
4197
4198 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4198 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4199 try:
4199 try:
4200 return hg.outgoing(ui, repo, dest, opts)
4200 return hg.outgoing(ui, repo, dest, opts)
4201 finally:
4201 finally:
4202 del repo._subtoppath
4202 del repo._subtoppath
4203
4203
4204 @command('parents',
4204 @command('parents',
4205 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4205 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4206 ] + templateopts,
4206 ] + templateopts,
4207 _('[-r REV] [FILE]'))
4207 _('[-r REV] [FILE]'))
4208 def parents(ui, repo, file_=None, **opts):
4208 def parents(ui, repo, file_=None, **opts):
4209 """show the parents of the working directory or revision
4209 """show the parents of the working directory or revision
4210
4210
4211 Print the working directory's parent revisions. If a revision is
4211 Print the working directory's parent revisions. If a revision is
4212 given via -r/--rev, the parent of that revision will be printed.
4212 given via -r/--rev, the parent of that revision will be printed.
4213 If a file argument is given, the revision in which the file was
4213 If a file argument is given, the revision in which the file was
4214 last changed (before the working directory revision or the
4214 last changed (before the working directory revision or the
4215 argument to --rev if given) is printed.
4215 argument to --rev if given) is printed.
4216
4216
4217 Returns 0 on success.
4217 Returns 0 on success.
4218 """
4218 """
4219
4219
4220 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4220 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4221
4221
4222 if file_:
4222 if file_:
4223 m = scmutil.match(ctx, (file_,), opts)
4223 m = scmutil.match(ctx, (file_,), opts)
4224 if m.anypats() or len(m.files()) != 1:
4224 if m.anypats() or len(m.files()) != 1:
4225 raise util.Abort(_('can only specify an explicit filename'))
4225 raise util.Abort(_('can only specify an explicit filename'))
4226 file_ = m.files()[0]
4226 file_ = m.files()[0]
4227 filenodes = []
4227 filenodes = []
4228 for cp in ctx.parents():
4228 for cp in ctx.parents():
4229 if not cp:
4229 if not cp:
4230 continue
4230 continue
4231 try:
4231 try:
4232 filenodes.append(cp.filenode(file_))
4232 filenodes.append(cp.filenode(file_))
4233 except error.LookupError:
4233 except error.LookupError:
4234 pass
4234 pass
4235 if not filenodes:
4235 if not filenodes:
4236 raise util.Abort(_("'%s' not found in manifest!") % file_)
4236 raise util.Abort(_("'%s' not found in manifest!") % file_)
4237 fl = repo.file(file_)
4237 fl = repo.file(file_)
4238 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4238 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4239 else:
4239 else:
4240 p = [cp.node() for cp in ctx.parents()]
4240 p = [cp.node() for cp in ctx.parents()]
4241
4241
4242 displayer = cmdutil.show_changeset(ui, repo, opts)
4242 displayer = cmdutil.show_changeset(ui, repo, opts)
4243 for n in p:
4243 for n in p:
4244 if n != nullid:
4244 if n != nullid:
4245 displayer.show(repo[n])
4245 displayer.show(repo[n])
4246 displayer.close()
4246 displayer.close()
4247
4247
4248 @command('paths', [], _('[NAME]'))
4248 @command('paths', [], _('[NAME]'))
4249 def paths(ui, repo, search=None):
4249 def paths(ui, repo, search=None):
4250 """show aliases for remote repositories
4250 """show aliases for remote repositories
4251
4251
4252 Show definition of symbolic path name NAME. If no name is given,
4252 Show definition of symbolic path name NAME. If no name is given,
4253 show definition of all available names.
4253 show definition of all available names.
4254
4254
4255 Option -q/--quiet suppresses all output when searching for NAME
4255 Option -q/--quiet suppresses all output when searching for NAME
4256 and shows only the path names when listing all definitions.
4256 and shows only the path names when listing all definitions.
4257
4257
4258 Path names are defined in the [paths] section of your
4258 Path names are defined in the [paths] section of your
4259 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4259 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4260 repository, ``.hg/hgrc`` is used, too.
4260 repository, ``.hg/hgrc`` is used, too.
4261
4261
4262 The path names ``default`` and ``default-push`` have a special
4262 The path names ``default`` and ``default-push`` have a special
4263 meaning. When performing a push or pull operation, they are used
4263 meaning. When performing a push or pull operation, they are used
4264 as fallbacks if no location is specified on the command-line.
4264 as fallbacks if no location is specified on the command-line.
4265 When ``default-push`` is set, it will be used for push and
4265 When ``default-push`` is set, it will be used for push and
4266 ``default`` will be used for pull; otherwise ``default`` is used
4266 ``default`` will be used for pull; otherwise ``default`` is used
4267 as the fallback for both. When cloning a repository, the clone
4267 as the fallback for both. When cloning a repository, the clone
4268 source is written as ``default`` in ``.hg/hgrc``. Note that
4268 source is written as ``default`` in ``.hg/hgrc``. Note that
4269 ``default`` and ``default-push`` apply to all inbound (e.g.
4269 ``default`` and ``default-push`` apply to all inbound (e.g.
4270 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4270 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4271 :hg:`bundle`) operations.
4271 :hg:`bundle`) operations.
4272
4272
4273 See :hg:`help urls` for more information.
4273 See :hg:`help urls` for more information.
4274
4274
4275 Returns 0 on success.
4275 Returns 0 on success.
4276 """
4276 """
4277 if search:
4277 if search:
4278 for name, path in ui.configitems("paths"):
4278 for name, path in ui.configitems("paths"):
4279 if name == search:
4279 if name == search:
4280 ui.status("%s\n" % util.hidepassword(path))
4280 ui.status("%s\n" % util.hidepassword(path))
4281 return
4281 return
4282 if not ui.quiet:
4282 if not ui.quiet:
4283 ui.warn(_("not found!\n"))
4283 ui.warn(_("not found!\n"))
4284 return 1
4284 return 1
4285 else:
4285 else:
4286 for name, path in ui.configitems("paths"):
4286 for name, path in ui.configitems("paths"):
4287 if ui.quiet:
4287 if ui.quiet:
4288 ui.write("%s\n" % name)
4288 ui.write("%s\n" % name)
4289 else:
4289 else:
4290 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4290 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4291
4291
4292 @command('^phase',
4292 @command('^phase',
4293 [('p', 'public', False, _('set changeset phase to public')),
4293 [('p', 'public', False, _('set changeset phase to public')),
4294 ('d', 'draft', False, _('set changeset phase to draft')),
4294 ('d', 'draft', False, _('set changeset phase to draft')),
4295 ('s', 'secret', False, _('set changeset phase to secret')),
4295 ('s', 'secret', False, _('set changeset phase to secret')),
4296 ('f', 'force', False, _('allow to move boundary backward')),
4296 ('f', 'force', False, _('allow to move boundary backward')),
4297 ('r', 'rev', [], _('target revision'), _('REV')),
4297 ('r', 'rev', [], _('target revision'), _('REV')),
4298 ],
4298 ],
4299 _('[-p|-d|-s] [-f] [-r] REV...'))
4299 _('[-p|-d|-s] [-f] [-r] REV...'))
4300 def phase(ui, repo, *revs, **opts):
4300 def phase(ui, repo, *revs, **opts):
4301 """set or show the current phase name
4301 """set or show the current phase name
4302
4302
4303 With no argument, show the phase name of specified revisions.
4303 With no argument, show the phase name of specified revisions.
4304
4304
4305 With one of -p/--public, -d/--draft or -s/--secret, change the
4305 With one of -p/--public, -d/--draft or -s/--secret, change the
4306 phase value of the specified revisions.
4306 phase value of the specified revisions.
4307
4307
4308 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4308 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4309 lower phase to an higher phase. Phases are ordered as follows::
4309 lower phase to an higher phase. Phases are ordered as follows::
4310
4310
4311 public < draft < secret
4311 public < draft < secret
4312
4312
4313 Return 0 on success, 1 if no phases were changed or some could not
4313 Return 0 on success, 1 if no phases were changed or some could not
4314 be changed.
4314 be changed.
4315 """
4315 """
4316 # search for a unique phase argument
4316 # search for a unique phase argument
4317 targetphase = None
4317 targetphase = None
4318 for idx, name in enumerate(phases.phasenames):
4318 for idx, name in enumerate(phases.phasenames):
4319 if opts[name]:
4319 if opts[name]:
4320 if targetphase is not None:
4320 if targetphase is not None:
4321 raise util.Abort(_('only one phase can be specified'))
4321 raise util.Abort(_('only one phase can be specified'))
4322 targetphase = idx
4322 targetphase = idx
4323
4323
4324 # look for specified revision
4324 # look for specified revision
4325 revs = list(revs)
4325 revs = list(revs)
4326 revs.extend(opts['rev'])
4326 revs.extend(opts['rev'])
4327 if not revs:
4327 if not revs:
4328 raise util.Abort(_('no revisions specified'))
4328 raise util.Abort(_('no revisions specified'))
4329
4329
4330 revs = scmutil.revrange(repo, revs)
4330 revs = scmutil.revrange(repo, revs)
4331
4331
4332 lock = None
4332 lock = None
4333 ret = 0
4333 ret = 0
4334 if targetphase is None:
4334 if targetphase is None:
4335 # display
4335 # display
4336 for r in revs:
4336 for r in revs:
4337 ctx = repo[r]
4337 ctx = repo[r]
4338 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4338 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4339 else:
4339 else:
4340 lock = repo.lock()
4340 lock = repo.lock()
4341 try:
4341 try:
4342 # set phase
4342 # set phase
4343 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4343 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4344 if not nodes:
4344 if not nodes:
4345 raise util.Abort(_('empty revision set'))
4345 raise util.Abort(_('empty revision set'))
4346 olddata = repo._phaserev[:]
4346 olddata = repo._phaserev[:]
4347 phases.advanceboundary(repo, targetphase, nodes)
4347 phases.advanceboundary(repo, targetphase, nodes)
4348 if opts['force']:
4348 if opts['force']:
4349 phases.retractboundary(repo, targetphase, nodes)
4349 phases.retractboundary(repo, targetphase, nodes)
4350 finally:
4350 finally:
4351 lock.release()
4351 lock.release()
4352 if olddata is not None:
4352 if olddata is not None:
4353 changes = 0
4353 changes = 0
4354 newdata = repo._phaserev
4354 newdata = repo._phaserev
4355 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4355 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4356 rejected = [n for n in nodes
4356 rejected = [n for n in nodes
4357 if newdata[repo[n].rev()] < targetphase]
4357 if newdata[repo[n].rev()] < targetphase]
4358 if rejected:
4358 if rejected:
4359 ui.warn(_('cannot move %i changesets to a more permissive '
4359 ui.warn(_('cannot move %i changesets to a more permissive '
4360 'phase, use --force\n') % len(rejected))
4360 'phase, use --force\n') % len(rejected))
4361 ret = 1
4361 ret = 1
4362 if changes:
4362 if changes:
4363 msg = _('phase changed for %i changesets\n') % changes
4363 msg = _('phase changed for %i changesets\n') % changes
4364 if ret:
4364 if ret:
4365 ui.status(msg)
4365 ui.status(msg)
4366 else:
4366 else:
4367 ui.note(msg)
4367 ui.note(msg)
4368 else:
4368 else:
4369 ui.warn(_('no phases changed\n'))
4369 ui.warn(_('no phases changed\n'))
4370 ret = 1
4370 ret = 1
4371 return ret
4371 return ret
4372
4372
4373 def postincoming(ui, repo, modheads, optupdate, checkout):
4373 def postincoming(ui, repo, modheads, optupdate, checkout):
4374 if modheads == 0:
4374 if modheads == 0:
4375 return
4375 return
4376 if optupdate:
4376 if optupdate:
4377 movemarkfrom = repo['.'].node()
4377 movemarkfrom = repo['.'].node()
4378 try:
4378 try:
4379 ret = hg.update(repo, checkout)
4379 ret = hg.update(repo, checkout)
4380 except util.Abort, inst:
4380 except util.Abort, inst:
4381 ui.warn(_("not updating: %s\n") % str(inst))
4381 ui.warn(_("not updating: %s\n") % str(inst))
4382 return 0
4382 return 0
4383 if not ret and not checkout:
4383 if not ret and not checkout:
4384 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4384 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4385 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4385 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4386 return ret
4386 return ret
4387 if modheads > 1:
4387 if modheads > 1:
4388 currentbranchheads = len(repo.branchheads())
4388 currentbranchheads = len(repo.branchheads())
4389 if currentbranchheads == modheads:
4389 if currentbranchheads == modheads:
4390 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4390 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4391 elif currentbranchheads > 1:
4391 elif currentbranchheads > 1:
4392 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4392 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4393 else:
4393 else:
4394 ui.status(_("(run 'hg heads' to see heads)\n"))
4394 ui.status(_("(run 'hg heads' to see heads)\n"))
4395 else:
4395 else:
4396 ui.status(_("(run 'hg update' to get a working copy)\n"))
4396 ui.status(_("(run 'hg update' to get a working copy)\n"))
4397
4397
4398 @command('^pull',
4398 @command('^pull',
4399 [('u', 'update', None,
4399 [('u', 'update', None,
4400 _('update to new branch head if changesets were pulled')),
4400 _('update to new branch head if changesets were pulled')),
4401 ('f', 'force', None, _('run even when remote repository is unrelated')),
4401 ('f', 'force', None, _('run even when remote repository is unrelated')),
4402 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4402 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4403 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4403 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4404 ('b', 'branch', [], _('a specific branch you would like to pull'),
4404 ('b', 'branch', [], _('a specific branch you would like to pull'),
4405 _('BRANCH')),
4405 _('BRANCH')),
4406 ] + remoteopts,
4406 ] + remoteopts,
4407 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4407 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4408 def pull(ui, repo, source="default", **opts):
4408 def pull(ui, repo, source="default", **opts):
4409 """pull changes from the specified source
4409 """pull changes from the specified source
4410
4410
4411 Pull changes from a remote repository to a local one.
4411 Pull changes from a remote repository to a local one.
4412
4412
4413 This finds all changes from the repository at the specified path
4413 This finds all changes from the repository at the specified path
4414 or URL and adds them to a local repository (the current one unless
4414 or URL and adds them to a local repository (the current one unless
4415 -R is specified). By default, this does not update the copy of the
4415 -R is specified). By default, this does not update the copy of the
4416 project in the working directory.
4416 project in the working directory.
4417
4417
4418 Use :hg:`incoming` if you want to see what would have been added
4418 Use :hg:`incoming` if you want to see what would have been added
4419 by a pull at the time you issued this command. If you then decide
4419 by a pull at the time you issued this command. If you then decide
4420 to add those changes to the repository, you should use :hg:`pull
4420 to add those changes to the repository, you should use :hg:`pull
4421 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4421 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4422
4422
4423 If SOURCE is omitted, the 'default' path will be used.
4423 If SOURCE is omitted, the 'default' path will be used.
4424 See :hg:`help urls` for more information.
4424 See :hg:`help urls` for more information.
4425
4425
4426 Returns 0 on success, 1 if an update had unresolved files.
4426 Returns 0 on success, 1 if an update had unresolved files.
4427 """
4427 """
4428 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4428 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4429 other = hg.peer(repo, opts, source)
4429 other = hg.peer(repo, opts, source)
4430 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4430 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4431 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4431 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4432
4432
4433 if opts.get('bookmark'):
4433 if opts.get('bookmark'):
4434 if not revs:
4434 if not revs:
4435 revs = []
4435 revs = []
4436 rb = other.listkeys('bookmarks')
4436 rb = other.listkeys('bookmarks')
4437 for b in opts['bookmark']:
4437 for b in opts['bookmark']:
4438 if b not in rb:
4438 if b not in rb:
4439 raise util.Abort(_('remote bookmark %s not found!') % b)
4439 raise util.Abort(_('remote bookmark %s not found!') % b)
4440 revs.append(rb[b])
4440 revs.append(rb[b])
4441
4441
4442 if revs:
4442 if revs:
4443 try:
4443 try:
4444 revs = [other.lookup(rev) for rev in revs]
4444 revs = [other.lookup(rev) for rev in revs]
4445 except error.CapabilityError:
4445 except error.CapabilityError:
4446 err = _("other repository doesn't support revision lookup, "
4446 err = _("other repository doesn't support revision lookup, "
4447 "so a rev cannot be specified.")
4447 "so a rev cannot be specified.")
4448 raise util.Abort(err)
4448 raise util.Abort(err)
4449
4449
4450 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4450 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4451 bookmarks.updatefromremote(ui, repo, other, source)
4451 bookmarks.updatefromremote(ui, repo, other, source)
4452 if checkout:
4452 if checkout:
4453 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4453 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4454 repo._subtoppath = source
4454 repo._subtoppath = source
4455 try:
4455 try:
4456 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4456 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4457
4457
4458 finally:
4458 finally:
4459 del repo._subtoppath
4459 del repo._subtoppath
4460
4460
4461 # update specified bookmarks
4461 # update specified bookmarks
4462 if opts.get('bookmark'):
4462 if opts.get('bookmark'):
4463 for b in opts['bookmark']:
4463 for b in opts['bookmark']:
4464 # explicit pull overrides local bookmark if any
4464 # explicit pull overrides local bookmark if any
4465 ui.status(_("importing bookmark %s\n") % b)
4465 ui.status(_("importing bookmark %s\n") % b)
4466 repo._bookmarks[b] = repo[rb[b]].node()
4466 repo._bookmarks[b] = repo[rb[b]].node()
4467 bookmarks.write(repo)
4467 bookmarks.write(repo)
4468
4468
4469 return ret
4469 return ret
4470
4470
4471 @command('^push',
4471 @command('^push',
4472 [('f', 'force', None, _('force push')),
4472 [('f', 'force', None, _('force push')),
4473 ('r', 'rev', [],
4473 ('r', 'rev', [],
4474 _('a changeset intended to be included in the destination'),
4474 _('a changeset intended to be included in the destination'),
4475 _('REV')),
4475 _('REV')),
4476 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4476 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4477 ('b', 'branch', [],
4477 ('b', 'branch', [],
4478 _('a specific branch you would like to push'), _('BRANCH')),
4478 _('a specific branch you would like to push'), _('BRANCH')),
4479 ('', 'new-branch', False, _('allow pushing a new branch')),
4479 ('', 'new-branch', False, _('allow pushing a new branch')),
4480 ] + remoteopts,
4480 ] + remoteopts,
4481 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4481 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4482 def push(ui, repo, dest=None, **opts):
4482 def push(ui, repo, dest=None, **opts):
4483 """push changes to the specified destination
4483 """push changes to the specified destination
4484
4484
4485 Push changesets from the local repository to the specified
4485 Push changesets from the local repository to the specified
4486 destination.
4486 destination.
4487
4487
4488 This operation is symmetrical to pull: it is identical to a pull
4488 This operation is symmetrical to pull: it is identical to a pull
4489 in the destination repository from the current one.
4489 in the destination repository from the current one.
4490
4490
4491 By default, push will not allow creation of new heads at the
4491 By default, push will not allow creation of new heads at the
4492 destination, since multiple heads would make it unclear which head
4492 destination, since multiple heads would make it unclear which head
4493 to use. In this situation, it is recommended to pull and merge
4493 to use. In this situation, it is recommended to pull and merge
4494 before pushing.
4494 before pushing.
4495
4495
4496 Use --new-branch if you want to allow push to create a new named
4496 Use --new-branch if you want to allow push to create a new named
4497 branch that is not present at the destination. This allows you to
4497 branch that is not present at the destination. This allows you to
4498 only create a new branch without forcing other changes.
4498 only create a new branch without forcing other changes.
4499
4499
4500 Use -f/--force to override the default behavior and push all
4500 Use -f/--force to override the default behavior and push all
4501 changesets on all branches.
4501 changesets on all branches.
4502
4502
4503 If -r/--rev is used, the specified revision and all its ancestors
4503 If -r/--rev is used, the specified revision and all its ancestors
4504 will be pushed to the remote repository.
4504 will be pushed to the remote repository.
4505
4505
4506 Please see :hg:`help urls` for important details about ``ssh://``
4506 Please see :hg:`help urls` for important details about ``ssh://``
4507 URLs. If DESTINATION is omitted, a default path will be used.
4507 URLs. If DESTINATION is omitted, a default path will be used.
4508
4508
4509 Returns 0 if push was successful, 1 if nothing to push.
4509 Returns 0 if push was successful, 1 if nothing to push.
4510 """
4510 """
4511
4511
4512 if opts.get('bookmark'):
4512 if opts.get('bookmark'):
4513 for b in opts['bookmark']:
4513 for b in opts['bookmark']:
4514 # translate -B options to -r so changesets get pushed
4514 # translate -B options to -r so changesets get pushed
4515 if b in repo._bookmarks:
4515 if b in repo._bookmarks:
4516 opts.setdefault('rev', []).append(b)
4516 opts.setdefault('rev', []).append(b)
4517 else:
4517 else:
4518 # if we try to push a deleted bookmark, translate it to null
4518 # if we try to push a deleted bookmark, translate it to null
4519 # this lets simultaneous -r, -b options continue working
4519 # this lets simultaneous -r, -b options continue working
4520 opts.setdefault('rev', []).append("null")
4520 opts.setdefault('rev', []).append("null")
4521
4521
4522 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4522 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4523 dest, branches = hg.parseurl(dest, opts.get('branch'))
4523 dest, branches = hg.parseurl(dest, opts.get('branch'))
4524 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4524 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4525 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4525 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4526 other = hg.peer(repo, opts, dest)
4526 other = hg.peer(repo, opts, dest)
4527 if revs:
4527 if revs:
4528 revs = [repo.lookup(rev) for rev in revs]
4528 revs = [repo.lookup(rev) for rev in revs]
4529
4529
4530 repo._subtoppath = dest
4530 repo._subtoppath = dest
4531 try:
4531 try:
4532 # push subrepos depth-first for coherent ordering
4532 # push subrepos depth-first for coherent ordering
4533 c = repo['']
4533 c = repo['']
4534 subs = c.substate # only repos that are committed
4534 subs = c.substate # only repos that are committed
4535 for s in sorted(subs):
4535 for s in sorted(subs):
4536 if c.sub(s).push(opts) == 0:
4536 if c.sub(s).push(opts) == 0:
4537 return False
4537 return False
4538 finally:
4538 finally:
4539 del repo._subtoppath
4539 del repo._subtoppath
4540 result = repo.push(other, opts.get('force'), revs=revs,
4540 result = repo.push(other, opts.get('force'), revs=revs,
4541 newbranch=opts.get('new_branch'))
4541 newbranch=opts.get('new_branch'))
4542
4542
4543 result = not result
4543 result = not result
4544
4544
4545 if opts.get('bookmark'):
4545 if opts.get('bookmark'):
4546 rb = other.listkeys('bookmarks')
4546 rb = other.listkeys('bookmarks')
4547 for b in opts['bookmark']:
4547 for b in opts['bookmark']:
4548 # explicit push overrides remote bookmark if any
4548 # explicit push overrides remote bookmark if any
4549 if b in repo._bookmarks:
4549 if b in repo._bookmarks:
4550 ui.status(_("exporting bookmark %s\n") % b)
4550 ui.status(_("exporting bookmark %s\n") % b)
4551 new = repo[b].hex()
4551 new = repo[b].hex()
4552 elif b in rb:
4552 elif b in rb:
4553 ui.status(_("deleting remote bookmark %s\n") % b)
4553 ui.status(_("deleting remote bookmark %s\n") % b)
4554 new = '' # delete
4554 new = '' # delete
4555 else:
4555 else:
4556 ui.warn(_('bookmark %s does not exist on the local '
4556 ui.warn(_('bookmark %s does not exist on the local '
4557 'or remote repository!\n') % b)
4557 'or remote repository!\n') % b)
4558 return 2
4558 return 2
4559 old = rb.get(b, '')
4559 old = rb.get(b, '')
4560 r = other.pushkey('bookmarks', b, old, new)
4560 r = other.pushkey('bookmarks', b, old, new)
4561 if not r:
4561 if not r:
4562 ui.warn(_('updating bookmark %s failed!\n') % b)
4562 ui.warn(_('updating bookmark %s failed!\n') % b)
4563 if not result:
4563 if not result:
4564 result = 2
4564 result = 2
4565
4565
4566 return result
4566 return result
4567
4567
4568 @command('recover', [])
4568 @command('recover', [])
4569 def recover(ui, repo):
4569 def recover(ui, repo):
4570 """roll back an interrupted transaction
4570 """roll back an interrupted transaction
4571
4571
4572 Recover from an interrupted commit or pull.
4572 Recover from an interrupted commit or pull.
4573
4573
4574 This command tries to fix the repository status after an
4574 This command tries to fix the repository status after an
4575 interrupted operation. It should only be necessary when Mercurial
4575 interrupted operation. It should only be necessary when Mercurial
4576 suggests it.
4576 suggests it.
4577
4577
4578 Returns 0 if successful, 1 if nothing to recover or verify fails.
4578 Returns 0 if successful, 1 if nothing to recover or verify fails.
4579 """
4579 """
4580 if repo.recover():
4580 if repo.recover():
4581 return hg.verify(repo)
4581 return hg.verify(repo)
4582 return 1
4582 return 1
4583
4583
4584 @command('^remove|rm',
4584 @command('^remove|rm',
4585 [('A', 'after', None, _('record delete for missing files')),
4585 [('A', 'after', None, _('record delete for missing files')),
4586 ('f', 'force', None,
4586 ('f', 'force', None,
4587 _('remove (and delete) file even if added or modified')),
4587 _('remove (and delete) file even if added or modified')),
4588 ] + walkopts,
4588 ] + walkopts,
4589 _('[OPTION]... FILE...'))
4589 _('[OPTION]... FILE...'))
4590 def remove(ui, repo, *pats, **opts):
4590 def remove(ui, repo, *pats, **opts):
4591 """remove the specified files on the next commit
4591 """remove the specified files on the next commit
4592
4592
4593 Schedule the indicated files for removal from the current branch.
4593 Schedule the indicated files for removal from the current branch.
4594
4594
4595 This command schedules the files to be removed at the next commit.
4595 This command schedules the files to be removed at the next commit.
4596 To undo a remove before that, see :hg:`revert`. To undo added
4596 To undo a remove before that, see :hg:`revert`. To undo added
4597 files, see :hg:`forget`.
4597 files, see :hg:`forget`.
4598
4598
4599 .. container:: verbose
4599 .. container:: verbose
4600
4600
4601 -A/--after can be used to remove only files that have already
4601 -A/--after can be used to remove only files that have already
4602 been deleted, -f/--force can be used to force deletion, and -Af
4602 been deleted, -f/--force can be used to force deletion, and -Af
4603 can be used to remove files from the next revision without
4603 can be used to remove files from the next revision without
4604 deleting them from the working directory.
4604 deleting them from the working directory.
4605
4605
4606 The following table details the behavior of remove for different
4606 The following table details the behavior of remove for different
4607 file states (columns) and option combinations (rows). The file
4607 file states (columns) and option combinations (rows). The file
4608 states are Added [A], Clean [C], Modified [M] and Missing [!]
4608 states are Added [A], Clean [C], Modified [M] and Missing [!]
4609 (as reported by :hg:`status`). The actions are Warn, Remove
4609 (as reported by :hg:`status`). The actions are Warn, Remove
4610 (from branch) and Delete (from disk):
4610 (from branch) and Delete (from disk):
4611
4611
4612 ======= == == == ==
4612 ======= == == == ==
4613 A C M !
4613 A C M !
4614 ======= == == == ==
4614 ======= == == == ==
4615 none W RD W R
4615 none W RD W R
4616 -f R RD RD R
4616 -f R RD RD R
4617 -A W W W R
4617 -A W W W R
4618 -Af R R R R
4618 -Af R R R R
4619 ======= == == == ==
4619 ======= == == == ==
4620
4620
4621 Note that remove never deletes files in Added [A] state from the
4621 Note that remove never deletes files in Added [A] state from the
4622 working directory, not even if option --force is specified.
4622 working directory, not even if option --force is specified.
4623
4623
4624 Returns 0 on success, 1 if any warnings encountered.
4624 Returns 0 on success, 1 if any warnings encountered.
4625 """
4625 """
4626
4626
4627 ret = 0
4627 ret = 0
4628 after, force = opts.get('after'), opts.get('force')
4628 after, force = opts.get('after'), opts.get('force')
4629 if not pats and not after:
4629 if not pats and not after:
4630 raise util.Abort(_('no files specified'))
4630 raise util.Abort(_('no files specified'))
4631
4631
4632 m = scmutil.match(repo[None], pats, opts)
4632 m = scmutil.match(repo[None], pats, opts)
4633 s = repo.status(match=m, clean=True)
4633 s = repo.status(match=m, clean=True)
4634 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4634 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4635
4635
4636 for f in m.files():
4636 for f in m.files():
4637 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4637 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4638 if os.path.exists(m.rel(f)):
4638 if os.path.exists(m.rel(f)):
4639 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4639 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4640 ret = 1
4640 ret = 1
4641
4641
4642 if force:
4642 if force:
4643 list = modified + deleted + clean + added
4643 list = modified + deleted + clean + added
4644 elif after:
4644 elif after:
4645 list = deleted
4645 list = deleted
4646 for f in modified + added + clean:
4646 for f in modified + added + clean:
4647 ui.warn(_('not removing %s: file still exists (use -f'
4647 ui.warn(_('not removing %s: file still exists (use -f'
4648 ' to force removal)\n') % m.rel(f))
4648 ' to force removal)\n') % m.rel(f))
4649 ret = 1
4649 ret = 1
4650 else:
4650 else:
4651 list = deleted + clean
4651 list = deleted + clean
4652 for f in modified:
4652 for f in modified:
4653 ui.warn(_('not removing %s: file is modified (use -f'
4653 ui.warn(_('not removing %s: file is modified (use -f'
4654 ' to force removal)\n') % m.rel(f))
4654 ' to force removal)\n') % m.rel(f))
4655 ret = 1
4655 ret = 1
4656 for f in added:
4656 for f in added:
4657 ui.warn(_('not removing %s: file has been marked for add'
4657 ui.warn(_('not removing %s: file has been marked for add'
4658 ' (use forget to undo)\n') % m.rel(f))
4658 ' (use forget to undo)\n') % m.rel(f))
4659 ret = 1
4659 ret = 1
4660
4660
4661 for f in sorted(list):
4661 for f in sorted(list):
4662 if ui.verbose or not m.exact(f):
4662 if ui.verbose or not m.exact(f):
4663 ui.status(_('removing %s\n') % m.rel(f))
4663 ui.status(_('removing %s\n') % m.rel(f))
4664
4664
4665 wlock = repo.wlock()
4665 wlock = repo.wlock()
4666 try:
4666 try:
4667 if not after:
4667 if not after:
4668 for f in list:
4668 for f in list:
4669 if f in added:
4669 if f in added:
4670 continue # we never unlink added files on remove
4670 continue # we never unlink added files on remove
4671 try:
4671 try:
4672 util.unlinkpath(repo.wjoin(f))
4672 util.unlinkpath(repo.wjoin(f))
4673 except OSError, inst:
4673 except OSError, inst:
4674 if inst.errno != errno.ENOENT:
4674 if inst.errno != errno.ENOENT:
4675 raise
4675 raise
4676 repo[None].forget(list)
4676 repo[None].forget(list)
4677 finally:
4677 finally:
4678 wlock.release()
4678 wlock.release()
4679
4679
4680 return ret
4680 return ret
4681
4681
4682 @command('rename|move|mv',
4682 @command('rename|move|mv',
4683 [('A', 'after', None, _('record a rename that has already occurred')),
4683 [('A', 'after', None, _('record a rename that has already occurred')),
4684 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4684 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4685 ] + walkopts + dryrunopts,
4685 ] + walkopts + dryrunopts,
4686 _('[OPTION]... SOURCE... DEST'))
4686 _('[OPTION]... SOURCE... DEST'))
4687 def rename(ui, repo, *pats, **opts):
4687 def rename(ui, repo, *pats, **opts):
4688 """rename files; equivalent of copy + remove
4688 """rename files; equivalent of copy + remove
4689
4689
4690 Mark dest as copies of sources; mark sources for deletion. If dest
4690 Mark dest as copies of sources; mark sources for deletion. If dest
4691 is a directory, copies are put in that directory. If dest is a
4691 is a directory, copies are put in that directory. If dest is a
4692 file, there can only be one source.
4692 file, there can only be one source.
4693
4693
4694 By default, this command copies the contents of files as they
4694 By default, this command copies the contents of files as they
4695 exist in the working directory. If invoked with -A/--after, the
4695 exist in the working directory. If invoked with -A/--after, the
4696 operation is recorded, but no copying is performed.
4696 operation is recorded, but no copying is performed.
4697
4697
4698 This command takes effect at the next commit. To undo a rename
4698 This command takes effect at the next commit. To undo a rename
4699 before that, see :hg:`revert`.
4699 before that, see :hg:`revert`.
4700
4700
4701 Returns 0 on success, 1 if errors are encountered.
4701 Returns 0 on success, 1 if errors are encountered.
4702 """
4702 """
4703 wlock = repo.wlock(False)
4703 wlock = repo.wlock(False)
4704 try:
4704 try:
4705 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4705 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4706 finally:
4706 finally:
4707 wlock.release()
4707 wlock.release()
4708
4708
4709 @command('resolve',
4709 @command('resolve',
4710 [('a', 'all', None, _('select all unresolved files')),
4710 [('a', 'all', None, _('select all unresolved files')),
4711 ('l', 'list', None, _('list state of files needing merge')),
4711 ('l', 'list', None, _('list state of files needing merge')),
4712 ('m', 'mark', None, _('mark files as resolved')),
4712 ('m', 'mark', None, _('mark files as resolved')),
4713 ('u', 'unmark', None, _('mark files as unresolved')),
4713 ('u', 'unmark', None, _('mark files as unresolved')),
4714 ('n', 'no-status', None, _('hide status prefix'))]
4714 ('n', 'no-status', None, _('hide status prefix'))]
4715 + mergetoolopts + walkopts,
4715 + mergetoolopts + walkopts,
4716 _('[OPTION]... [FILE]...'))
4716 _('[OPTION]... [FILE]...'))
4717 def resolve(ui, repo, *pats, **opts):
4717 def resolve(ui, repo, *pats, **opts):
4718 """redo merges or set/view the merge status of files
4718 """redo merges or set/view the merge status of files
4719
4719
4720 Merges with unresolved conflicts are often the result of
4720 Merges with unresolved conflicts are often the result of
4721 non-interactive merging using the ``internal:merge`` configuration
4721 non-interactive merging using the ``internal:merge`` configuration
4722 setting, or a command-line merge tool like ``diff3``. The resolve
4722 setting, or a command-line merge tool like ``diff3``. The resolve
4723 command is used to manage the files involved in a merge, after
4723 command is used to manage the files involved in a merge, after
4724 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4724 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4725 working directory must have two parents). See :hg:`help
4725 working directory must have two parents). See :hg:`help
4726 merge-tools` for information on configuring merge tools.
4726 merge-tools` for information on configuring merge tools.
4727
4727
4728 The resolve command can be used in the following ways:
4728 The resolve command can be used in the following ways:
4729
4729
4730 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4730 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4731 files, discarding any previous merge attempts. Re-merging is not
4731 files, discarding any previous merge attempts. Re-merging is not
4732 performed for files already marked as resolved. Use ``--all/-a``
4732 performed for files already marked as resolved. Use ``--all/-a``
4733 to select all unresolved files. ``--tool`` can be used to specify
4733 to select all unresolved files. ``--tool`` can be used to specify
4734 the merge tool used for the given files. It overrides the HGMERGE
4734 the merge tool used for the given files. It overrides the HGMERGE
4735 environment variable and your configuration files. Previous file
4735 environment variable and your configuration files. Previous file
4736 contents are saved with a ``.orig`` suffix.
4736 contents are saved with a ``.orig`` suffix.
4737
4737
4738 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4738 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4739 (e.g. after having manually fixed-up the files). The default is
4739 (e.g. after having manually fixed-up the files). The default is
4740 to mark all unresolved files.
4740 to mark all unresolved files.
4741
4741
4742 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4742 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4743 default is to mark all resolved files.
4743 default is to mark all resolved files.
4744
4744
4745 - :hg:`resolve -l`: list files which had or still have conflicts.
4745 - :hg:`resolve -l`: list files which had or still have conflicts.
4746 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4746 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4747
4747
4748 Note that Mercurial will not let you commit files with unresolved
4748 Note that Mercurial will not let you commit files with unresolved
4749 merge conflicts. You must use :hg:`resolve -m ...` before you can
4749 merge conflicts. You must use :hg:`resolve -m ...` before you can
4750 commit after a conflicting merge.
4750 commit after a conflicting merge.
4751
4751
4752 Returns 0 on success, 1 if any files fail a resolve attempt.
4752 Returns 0 on success, 1 if any files fail a resolve attempt.
4753 """
4753 """
4754
4754
4755 all, mark, unmark, show, nostatus = \
4755 all, mark, unmark, show, nostatus = \
4756 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4756 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4757
4757
4758 if (show and (mark or unmark)) or (mark and unmark):
4758 if (show and (mark or unmark)) or (mark and unmark):
4759 raise util.Abort(_("too many options specified"))
4759 raise util.Abort(_("too many options specified"))
4760 if pats and all:
4760 if pats and all:
4761 raise util.Abort(_("can't specify --all and patterns"))
4761 raise util.Abort(_("can't specify --all and patterns"))
4762 if not (all or pats or show or mark or unmark):
4762 if not (all or pats or show or mark or unmark):
4763 raise util.Abort(_('no files or directories specified; '
4763 raise util.Abort(_('no files or directories specified; '
4764 'use --all to remerge all files'))
4764 'use --all to remerge all files'))
4765
4765
4766 ms = mergemod.mergestate(repo)
4766 ms = mergemod.mergestate(repo)
4767 m = scmutil.match(repo[None], pats, opts)
4767 m = scmutil.match(repo[None], pats, opts)
4768 ret = 0
4768 ret = 0
4769
4769
4770 for f in ms:
4770 for f in ms:
4771 if m(f):
4771 if m(f):
4772 if show:
4772 if show:
4773 if nostatus:
4773 if nostatus:
4774 ui.write("%s\n" % f)
4774 ui.write("%s\n" % f)
4775 else:
4775 else:
4776 ui.write("%s %s\n" % (ms[f].upper(), f),
4776 ui.write("%s %s\n" % (ms[f].upper(), f),
4777 label='resolve.' +
4777 label='resolve.' +
4778 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4778 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4779 elif mark:
4779 elif mark:
4780 ms.mark(f, "r")
4780 ms.mark(f, "r")
4781 elif unmark:
4781 elif unmark:
4782 ms.mark(f, "u")
4782 ms.mark(f, "u")
4783 else:
4783 else:
4784 wctx = repo[None]
4784 wctx = repo[None]
4785 mctx = wctx.parents()[-1]
4785 mctx = wctx.parents()[-1]
4786
4786
4787 # backup pre-resolve (merge uses .orig for its own purposes)
4787 # backup pre-resolve (merge uses .orig for its own purposes)
4788 a = repo.wjoin(f)
4788 a = repo.wjoin(f)
4789 util.copyfile(a, a + ".resolve")
4789 util.copyfile(a, a + ".resolve")
4790
4790
4791 try:
4791 try:
4792 # resolve file
4792 # resolve file
4793 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4793 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4794 if ms.resolve(f, wctx, mctx):
4794 if ms.resolve(f, wctx, mctx):
4795 ret = 1
4795 ret = 1
4796 finally:
4796 finally:
4797 ui.setconfig('ui', 'forcemerge', '')
4797 ui.setconfig('ui', 'forcemerge', '')
4798
4798
4799 # replace filemerge's .orig file with our resolve file
4799 # replace filemerge's .orig file with our resolve file
4800 util.rename(a + ".resolve", a + ".orig")
4800 util.rename(a + ".resolve", a + ".orig")
4801
4801
4802 ms.commit()
4802 ms.commit()
4803 return ret
4803 return ret
4804
4804
4805 @command('revert',
4805 @command('revert',
4806 [('a', 'all', None, _('revert all changes when no arguments given')),
4806 [('a', 'all', None, _('revert all changes when no arguments given')),
4807 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4807 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4808 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4808 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4809 ('C', 'no-backup', None, _('do not save backup copies of files')),
4809 ('C', 'no-backup', None, _('do not save backup copies of files')),
4810 ] + walkopts + dryrunopts,
4810 ] + walkopts + dryrunopts,
4811 _('[OPTION]... [-r REV] [NAME]...'))
4811 _('[OPTION]... [-r REV] [NAME]...'))
4812 def revert(ui, repo, *pats, **opts):
4812 def revert(ui, repo, *pats, **opts):
4813 """restore files to their checkout state
4813 """restore files to their checkout state
4814
4814
4815 .. note::
4815 .. note::
4816 To check out earlier revisions, you should use :hg:`update REV`.
4816 To check out earlier revisions, you should use :hg:`update REV`.
4817 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4817 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4818
4818
4819 With no revision specified, revert the specified files or directories
4819 With no revision specified, revert the specified files or directories
4820 to the contents they had in the parent of the working directory.
4820 to the contents they had in the parent of the working directory.
4821 This restores the contents of files to an unmodified
4821 This restores the contents of files to an unmodified
4822 state and unschedules adds, removes, copies, and renames. If the
4822 state and unschedules adds, removes, copies, and renames. If the
4823 working directory has two parents, you must explicitly specify a
4823 working directory has two parents, you must explicitly specify a
4824 revision.
4824 revision.
4825
4825
4826 Using the -r/--rev or -d/--date options, revert the given files or
4826 Using the -r/--rev or -d/--date options, revert the given files or
4827 directories to their states as of a specific revision. Because
4827 directories to their states as of a specific revision. Because
4828 revert does not change the working directory parents, this will
4828 revert does not change the working directory parents, this will
4829 cause these files to appear modified. This can be helpful to "back
4829 cause these files to appear modified. This can be helpful to "back
4830 out" some or all of an earlier change. See :hg:`backout` for a
4830 out" some or all of an earlier change. See :hg:`backout` for a
4831 related method.
4831 related method.
4832
4832
4833 Modified files are saved with a .orig suffix before reverting.
4833 Modified files are saved with a .orig suffix before reverting.
4834 To disable these backups, use --no-backup.
4834 To disable these backups, use --no-backup.
4835
4835
4836 See :hg:`help dates` for a list of formats valid for -d/--date.
4836 See :hg:`help dates` for a list of formats valid for -d/--date.
4837
4837
4838 Returns 0 on success.
4838 Returns 0 on success.
4839 """
4839 """
4840
4840
4841 if opts.get("date"):
4841 if opts.get("date"):
4842 if opts.get("rev"):
4842 if opts.get("rev"):
4843 raise util.Abort(_("you can't specify a revision and a date"))
4843 raise util.Abort(_("you can't specify a revision and a date"))
4844 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4844 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4845
4845
4846 parent, p2 = repo.dirstate.parents()
4846 parent, p2 = repo.dirstate.parents()
4847 if not opts.get('rev') and p2 != nullid:
4847 if not opts.get('rev') and p2 != nullid:
4848 # revert after merge is a trap for new users (issue2915)
4848 # revert after merge is a trap for new users (issue2915)
4849 raise util.Abort(_('uncommitted merge with no revision specified'),
4849 raise util.Abort(_('uncommitted merge with no revision specified'),
4850 hint=_('use "hg update" or see "hg help revert"'))
4850 hint=_('use "hg update" or see "hg help revert"'))
4851
4851
4852 ctx = scmutil.revsingle(repo, opts.get('rev'))
4852 ctx = scmutil.revsingle(repo, opts.get('rev'))
4853
4853
4854 if not pats and not opts.get('all'):
4854 if not pats and not opts.get('all'):
4855 msg = _("no files or directories specified")
4855 msg = _("no files or directories specified")
4856 if p2 != nullid:
4856 if p2 != nullid:
4857 hint = _("uncommitted merge, use --all to discard all changes,"
4857 hint = _("uncommitted merge, use --all to discard all changes,"
4858 " or 'hg update -C .' to abort the merge")
4858 " or 'hg update -C .' to abort the merge")
4859 raise util.Abort(msg, hint=hint)
4859 raise util.Abort(msg, hint=hint)
4860 dirty = util.any(repo.status())
4860 dirty = util.any(repo.status())
4861 node = ctx.node()
4861 node = ctx.node()
4862 if node != parent:
4862 if node != parent:
4863 if dirty:
4863 if dirty:
4864 hint = _("uncommitted changes, use --all to discard all"
4864 hint = _("uncommitted changes, use --all to discard all"
4865 " changes, or 'hg update %s' to update") % ctx.rev()
4865 " changes, or 'hg update %s' to update") % ctx.rev()
4866 else:
4866 else:
4867 hint = _("use --all to revert all files,"
4867 hint = _("use --all to revert all files,"
4868 " or 'hg update %s' to update") % ctx.rev()
4868 " or 'hg update %s' to update") % ctx.rev()
4869 elif dirty:
4869 elif dirty:
4870 hint = _("uncommitted changes, use --all to discard all changes")
4870 hint = _("uncommitted changes, use --all to discard all changes")
4871 else:
4871 else:
4872 hint = _("use --all to revert all files")
4872 hint = _("use --all to revert all files")
4873 raise util.Abort(msg, hint=hint)
4873 raise util.Abort(msg, hint=hint)
4874
4874
4875 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4875 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4876
4876
4877 @command('rollback', dryrunopts +
4877 @command('rollback', dryrunopts +
4878 [('f', 'force', False, _('ignore safety measures'))])
4878 [('f', 'force', False, _('ignore safety measures'))])
4879 def rollback(ui, repo, **opts):
4879 def rollback(ui, repo, **opts):
4880 """roll back the last transaction (dangerous)
4880 """roll back the last transaction (dangerous)
4881
4881
4882 This command should be used with care. There is only one level of
4882 This command should be used with care. There is only one level of
4883 rollback, and there is no way to undo a rollback. It will also
4883 rollback, and there is no way to undo a rollback. It will also
4884 restore the dirstate at the time of the last transaction, losing
4884 restore the dirstate at the time of the last transaction, losing
4885 any dirstate changes since that time. This command does not alter
4885 any dirstate changes since that time. This command does not alter
4886 the working directory.
4886 the working directory.
4887
4887
4888 Transactions are used to encapsulate the effects of all commands
4888 Transactions are used to encapsulate the effects of all commands
4889 that create new changesets or propagate existing changesets into a
4889 that create new changesets or propagate existing changesets into a
4890 repository. For example, the following commands are transactional,
4890 repository. For example, the following commands are transactional,
4891 and their effects can be rolled back:
4891 and their effects can be rolled back:
4892
4892
4893 - commit
4893 - commit
4894 - import
4894 - import
4895 - pull
4895 - pull
4896 - push (with this repository as the destination)
4896 - push (with this repository as the destination)
4897 - unbundle
4897 - unbundle
4898
4898
4899 To avoid permanent data loss, rollback will refuse to rollback a
4899 To avoid permanent data loss, rollback will refuse to rollback a
4900 commit transaction if it isn't checked out. Use --force to
4900 commit transaction if it isn't checked out. Use --force to
4901 override this protection.
4901 override this protection.
4902
4902
4903 This command is not intended for use on public repositories. Once
4903 This command is not intended for use on public repositories. Once
4904 changes are visible for pull by other users, rolling a transaction
4904 changes are visible for pull by other users, rolling a transaction
4905 back locally is ineffective (someone else may already have pulled
4905 back locally is ineffective (someone else may already have pulled
4906 the changes). Furthermore, a race is possible with readers of the
4906 the changes). Furthermore, a race is possible with readers of the
4907 repository; for example an in-progress pull from the repository
4907 repository; for example an in-progress pull from the repository
4908 may fail if a rollback is performed.
4908 may fail if a rollback is performed.
4909
4909
4910 Returns 0 on success, 1 if no rollback data is available.
4910 Returns 0 on success, 1 if no rollback data is available.
4911 """
4911 """
4912 return repo.rollback(dryrun=opts.get('dry_run'),
4912 return repo.rollback(dryrun=opts.get('dry_run'),
4913 force=opts.get('force'))
4913 force=opts.get('force'))
4914
4914
4915 @command('root', [])
4915 @command('root', [])
4916 def root(ui, repo):
4916 def root(ui, repo):
4917 """print the root (top) of the current working directory
4917 """print the root (top) of the current working directory
4918
4918
4919 Print the root directory of the current repository.
4919 Print the root directory of the current repository.
4920
4920
4921 Returns 0 on success.
4921 Returns 0 on success.
4922 """
4922 """
4923 ui.write(repo.root + "\n")
4923 ui.write(repo.root + "\n")
4924
4924
4925 @command('^serve',
4925 @command('^serve',
4926 [('A', 'accesslog', '', _('name of access log file to write to'),
4926 [('A', 'accesslog', '', _('name of access log file to write to'),
4927 _('FILE')),
4927 _('FILE')),
4928 ('d', 'daemon', None, _('run server in background')),
4928 ('d', 'daemon', None, _('run server in background')),
4929 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4929 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4930 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4930 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4931 # use string type, then we can check if something was passed
4931 # use string type, then we can check if something was passed
4932 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4932 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4933 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4933 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4934 _('ADDR')),
4934 _('ADDR')),
4935 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4935 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4936 _('PREFIX')),
4936 _('PREFIX')),
4937 ('n', 'name', '',
4937 ('n', 'name', '',
4938 _('name to show in web pages (default: working directory)'), _('NAME')),
4938 _('name to show in web pages (default: working directory)'), _('NAME')),
4939 ('', 'web-conf', '',
4939 ('', 'web-conf', '',
4940 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4940 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4941 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4941 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4942 _('FILE')),
4942 _('FILE')),
4943 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4943 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4944 ('', 'stdio', None, _('for remote clients')),
4944 ('', 'stdio', None, _('for remote clients')),
4945 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4945 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4946 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4946 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4947 ('', 'style', '', _('template style to use'), _('STYLE')),
4947 ('', 'style', '', _('template style to use'), _('STYLE')),
4948 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4948 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4949 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4949 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4950 _('[OPTION]...'))
4950 _('[OPTION]...'))
4951 def serve(ui, repo, **opts):
4951 def serve(ui, repo, **opts):
4952 """start stand-alone webserver
4952 """start stand-alone webserver
4953
4953
4954 Start a local HTTP repository browser and pull server. You can use
4954 Start a local HTTP repository browser and pull server. You can use
4955 this for ad-hoc sharing and browsing of repositories. It is
4955 this for ad-hoc sharing and browsing of repositories. It is
4956 recommended to use a real web server to serve a repository for
4956 recommended to use a real web server to serve a repository for
4957 longer periods of time.
4957 longer periods of time.
4958
4958
4959 Please note that the server does not implement access control.
4959 Please note that the server does not implement access control.
4960 This means that, by default, anybody can read from the server and
4960 This means that, by default, anybody can read from the server and
4961 nobody can write to it by default. Set the ``web.allow_push``
4961 nobody can write to it by default. Set the ``web.allow_push``
4962 option to ``*`` to allow everybody to push to the server. You
4962 option to ``*`` to allow everybody to push to the server. You
4963 should use a real web server if you need to authenticate users.
4963 should use a real web server if you need to authenticate users.
4964
4964
4965 By default, the server logs accesses to stdout and errors to
4965 By default, the server logs accesses to stdout and errors to
4966 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4966 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4967 files.
4967 files.
4968
4968
4969 To have the server choose a free port number to listen on, specify
4969 To have the server choose a free port number to listen on, specify
4970 a port number of 0; in this case, the server will print the port
4970 a port number of 0; in this case, the server will print the port
4971 number it uses.
4971 number it uses.
4972
4972
4973 Returns 0 on success.
4973 Returns 0 on success.
4974 """
4974 """
4975
4975
4976 if opts["stdio"] and opts["cmdserver"]:
4976 if opts["stdio"] and opts["cmdserver"]:
4977 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4977 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4978
4978
4979 def checkrepo():
4979 def checkrepo():
4980 if repo is None:
4980 if repo is None:
4981 raise error.RepoError(_("There is no Mercurial repository here"
4981 raise error.RepoError(_("There is no Mercurial repository here"
4982 " (.hg not found)"))
4982 " (.hg not found)"))
4983
4983
4984 if opts["stdio"]:
4984 if opts["stdio"]:
4985 checkrepo()
4985 checkrepo()
4986 s = sshserver.sshserver(ui, repo)
4986 s = sshserver.sshserver(ui, repo)
4987 s.serve_forever()
4987 s.serve_forever()
4988
4988
4989 if opts["cmdserver"]:
4989 if opts["cmdserver"]:
4990 checkrepo()
4990 checkrepo()
4991 s = commandserver.server(ui, repo, opts["cmdserver"])
4991 s = commandserver.server(ui, repo, opts["cmdserver"])
4992 return s.serve()
4992 return s.serve()
4993
4993
4994 # this way we can check if something was given in the command-line
4994 # this way we can check if something was given in the command-line
4995 if opts.get('port'):
4995 if opts.get('port'):
4996 opts['port'] = util.getport(opts.get('port'))
4996 opts['port'] = util.getport(opts.get('port'))
4997
4997
4998 baseui = repo and repo.baseui or ui
4998 baseui = repo and repo.baseui or ui
4999 optlist = ("name templates style address port prefix ipv6"
4999 optlist = ("name templates style address port prefix ipv6"
5000 " accesslog errorlog certificate encoding")
5000 " accesslog errorlog certificate encoding")
5001 for o in optlist.split():
5001 for o in optlist.split():
5002 val = opts.get(o, '')
5002 val = opts.get(o, '')
5003 if val in (None, ''): # should check against default options instead
5003 if val in (None, ''): # should check against default options instead
5004 continue
5004 continue
5005 baseui.setconfig("web", o, val)
5005 baseui.setconfig("web", o, val)
5006 if repo and repo.ui != baseui:
5006 if repo and repo.ui != baseui:
5007 repo.ui.setconfig("web", o, val)
5007 repo.ui.setconfig("web", o, val)
5008
5008
5009 o = opts.get('web_conf') or opts.get('webdir_conf')
5009 o = opts.get('web_conf') or opts.get('webdir_conf')
5010 if not o:
5010 if not o:
5011 if not repo:
5011 if not repo:
5012 raise error.RepoError(_("There is no Mercurial repository"
5012 raise error.RepoError(_("There is no Mercurial repository"
5013 " here (.hg not found)"))
5013 " here (.hg not found)"))
5014 o = repo.root
5014 o = repo.root
5015
5015
5016 app = hgweb.hgweb(o, baseui=ui)
5016 app = hgweb.hgweb(o, baseui=ui)
5017
5017
5018 class service(object):
5018 class service(object):
5019 def init(self):
5019 def init(self):
5020 util.setsignalhandler()
5020 util.setsignalhandler()
5021 self.httpd = hgweb.server.create_server(ui, app)
5021 self.httpd = hgweb.server.create_server(ui, app)
5022
5022
5023 if opts['port'] and not ui.verbose:
5023 if opts['port'] and not ui.verbose:
5024 return
5024 return
5025
5025
5026 if self.httpd.prefix:
5026 if self.httpd.prefix:
5027 prefix = self.httpd.prefix.strip('/') + '/'
5027 prefix = self.httpd.prefix.strip('/') + '/'
5028 else:
5028 else:
5029 prefix = ''
5029 prefix = ''
5030
5030
5031 port = ':%d' % self.httpd.port
5031 port = ':%d' % self.httpd.port
5032 if port == ':80':
5032 if port == ':80':
5033 port = ''
5033 port = ''
5034
5034
5035 bindaddr = self.httpd.addr
5035 bindaddr = self.httpd.addr
5036 if bindaddr == '0.0.0.0':
5036 if bindaddr == '0.0.0.0':
5037 bindaddr = '*'
5037 bindaddr = '*'
5038 elif ':' in bindaddr: # IPv6
5038 elif ':' in bindaddr: # IPv6
5039 bindaddr = '[%s]' % bindaddr
5039 bindaddr = '[%s]' % bindaddr
5040
5040
5041 fqaddr = self.httpd.fqaddr
5041 fqaddr = self.httpd.fqaddr
5042 if ':' in fqaddr:
5042 if ':' in fqaddr:
5043 fqaddr = '[%s]' % fqaddr
5043 fqaddr = '[%s]' % fqaddr
5044 if opts['port']:
5044 if opts['port']:
5045 write = ui.status
5045 write = ui.status
5046 else:
5046 else:
5047 write = ui.write
5047 write = ui.write
5048 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5048 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5049 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5049 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5050
5050
5051 def run(self):
5051 def run(self):
5052 self.httpd.serve_forever()
5052 self.httpd.serve_forever()
5053
5053
5054 service = service()
5054 service = service()
5055
5055
5056 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5056 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5057
5057
5058 @command('showconfig|debugconfig',
5058 @command('showconfig|debugconfig',
5059 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5059 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5060 _('[-u] [NAME]...'))
5060 _('[-u] [NAME]...'))
5061 def showconfig(ui, repo, *values, **opts):
5061 def showconfig(ui, repo, *values, **opts):
5062 """show combined config settings from all hgrc files
5062 """show combined config settings from all hgrc files
5063
5063
5064 With no arguments, print names and values of all config items.
5064 With no arguments, print names and values of all config items.
5065
5065
5066 With one argument of the form section.name, print just the value
5066 With one argument of the form section.name, print just the value
5067 of that config item.
5067 of that config item.
5068
5068
5069 With multiple arguments, print names and values of all config
5069 With multiple arguments, print names and values of all config
5070 items with matching section names.
5070 items with matching section names.
5071
5071
5072 With --debug, the source (filename and line number) is printed
5072 With --debug, the source (filename and line number) is printed
5073 for each config item.
5073 for each config item.
5074
5074
5075 Returns 0 on success.
5075 Returns 0 on success.
5076 """
5076 """
5077
5077
5078 for f in scmutil.rcpath():
5078 for f in scmutil.rcpath():
5079 ui.debug('read config from: %s\n' % f)
5079 ui.debug('read config from: %s\n' % f)
5080 untrusted = bool(opts.get('untrusted'))
5080 untrusted = bool(opts.get('untrusted'))
5081 if values:
5081 if values:
5082 sections = [v for v in values if '.' not in v]
5082 sections = [v for v in values if '.' not in v]
5083 items = [v for v in values if '.' in v]
5083 items = [v for v in values if '.' in v]
5084 if len(items) > 1 or items and sections:
5084 if len(items) > 1 or items and sections:
5085 raise util.Abort(_('only one config item permitted'))
5085 raise util.Abort(_('only one config item permitted'))
5086 for section, name, value in ui.walkconfig(untrusted=untrusted):
5086 for section, name, value in ui.walkconfig(untrusted=untrusted):
5087 value = str(value).replace('\n', '\\n')
5087 value = str(value).replace('\n', '\\n')
5088 sectname = section + '.' + name
5088 sectname = section + '.' + name
5089 if values:
5089 if values:
5090 for v in values:
5090 for v in values:
5091 if v == section:
5091 if v == section:
5092 ui.debug('%s: ' %
5092 ui.debug('%s: ' %
5093 ui.configsource(section, name, untrusted))
5093 ui.configsource(section, name, untrusted))
5094 ui.write('%s=%s\n' % (sectname, value))
5094 ui.write('%s=%s\n' % (sectname, value))
5095 elif v == sectname:
5095 elif v == sectname:
5096 ui.debug('%s: ' %
5096 ui.debug('%s: ' %
5097 ui.configsource(section, name, untrusted))
5097 ui.configsource(section, name, untrusted))
5098 ui.write(value, '\n')
5098 ui.write(value, '\n')
5099 else:
5099 else:
5100 ui.debug('%s: ' %
5100 ui.debug('%s: ' %
5101 ui.configsource(section, name, untrusted))
5101 ui.configsource(section, name, untrusted))
5102 ui.write('%s=%s\n' % (sectname, value))
5102 ui.write('%s=%s\n' % (sectname, value))
5103
5103
5104 @command('^status|st',
5104 @command('^status|st',
5105 [('A', 'all', None, _('show status of all files')),
5105 [('A', 'all', None, _('show status of all files')),
5106 ('m', 'modified', None, _('show only modified files')),
5106 ('m', 'modified', None, _('show only modified files')),
5107 ('a', 'added', None, _('show only added files')),
5107 ('a', 'added', None, _('show only added files')),
5108 ('r', 'removed', None, _('show only removed files')),
5108 ('r', 'removed', None, _('show only removed files')),
5109 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5109 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5110 ('c', 'clean', None, _('show only files without changes')),
5110 ('c', 'clean', None, _('show only files without changes')),
5111 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5111 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5112 ('i', 'ignored', None, _('show only ignored files')),
5112 ('i', 'ignored', None, _('show only ignored files')),
5113 ('n', 'no-status', None, _('hide status prefix')),
5113 ('n', 'no-status', None, _('hide status prefix')),
5114 ('C', 'copies', None, _('show source of copied files')),
5114 ('C', 'copies', None, _('show source of copied files')),
5115 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5115 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5116 ('', 'rev', [], _('show difference from revision'), _('REV')),
5116 ('', 'rev', [], _('show difference from revision'), _('REV')),
5117 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5117 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5118 ] + walkopts + subrepoopts,
5118 ] + walkopts + subrepoopts,
5119 _('[OPTION]... [FILE]...'))
5119 _('[OPTION]... [FILE]...'))
5120 def status(ui, repo, *pats, **opts):
5120 def status(ui, repo, *pats, **opts):
5121 """show changed files in the working directory
5121 """show changed files in the working directory
5122
5122
5123 Show status of files in the repository. If names are given, only
5123 Show status of files in the repository. If names are given, only
5124 files that match are shown. Files that are clean or ignored or
5124 files that match are shown. Files that are clean or ignored or
5125 the source of a copy/move operation, are not listed unless
5125 the source of a copy/move operation, are not listed unless
5126 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5126 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5127 Unless options described with "show only ..." are given, the
5127 Unless options described with "show only ..." are given, the
5128 options -mardu are used.
5128 options -mardu are used.
5129
5129
5130 Option -q/--quiet hides untracked (unknown and ignored) files
5130 Option -q/--quiet hides untracked (unknown and ignored) files
5131 unless explicitly requested with -u/--unknown or -i/--ignored.
5131 unless explicitly requested with -u/--unknown or -i/--ignored.
5132
5132
5133 .. note::
5133 .. note::
5134 status may appear to disagree with diff if permissions have
5134 status may appear to disagree with diff if permissions have
5135 changed or a merge has occurred. The standard diff format does
5135 changed or a merge has occurred. The standard diff format does
5136 not report permission changes and diff only reports changes
5136 not report permission changes and diff only reports changes
5137 relative to one merge parent.
5137 relative to one merge parent.
5138
5138
5139 If one revision is given, it is used as the base revision.
5139 If one revision is given, it is used as the base revision.
5140 If two revisions are given, the differences between them are
5140 If two revisions are given, the differences between them are
5141 shown. The --change option can also be used as a shortcut to list
5141 shown. The --change option can also be used as a shortcut to list
5142 the changed files of a revision from its first parent.
5142 the changed files of a revision from its first parent.
5143
5143
5144 The codes used to show the status of files are::
5144 The codes used to show the status of files are::
5145
5145
5146 M = modified
5146 M = modified
5147 A = added
5147 A = added
5148 R = removed
5148 R = removed
5149 C = clean
5149 C = clean
5150 ! = missing (deleted by non-hg command, but still tracked)
5150 ! = missing (deleted by non-hg command, but still tracked)
5151 ? = not tracked
5151 ? = not tracked
5152 I = ignored
5152 I = ignored
5153 = origin of the previous file listed as A (added)
5153 = origin of the previous file listed as A (added)
5154
5154
5155 .. container:: verbose
5155 .. container:: verbose
5156
5156
5157 Examples:
5157 Examples:
5158
5158
5159 - show changes in the working directory relative to a
5159 - show changes in the working directory relative to a
5160 changeset::
5160 changeset::
5161
5161
5162 hg status --rev 9353
5162 hg status --rev 9353
5163
5163
5164 - show all changes including copies in an existing changeset::
5164 - show all changes including copies in an existing changeset::
5165
5165
5166 hg status --copies --change 9353
5166 hg status --copies --change 9353
5167
5167
5168 - get a NUL separated list of added files, suitable for xargs::
5168 - get a NUL separated list of added files, suitable for xargs::
5169
5169
5170 hg status -an0
5170 hg status -an0
5171
5171
5172 Returns 0 on success.
5172 Returns 0 on success.
5173 """
5173 """
5174
5174
5175 revs = opts.get('rev')
5175 revs = opts.get('rev')
5176 change = opts.get('change')
5176 change = opts.get('change')
5177
5177
5178 if revs and change:
5178 if revs and change:
5179 msg = _('cannot specify --rev and --change at the same time')
5179 msg = _('cannot specify --rev and --change at the same time')
5180 raise util.Abort(msg)
5180 raise util.Abort(msg)
5181 elif change:
5181 elif change:
5182 node2 = scmutil.revsingle(repo, change, None).node()
5182 node2 = scmutil.revsingle(repo, change, None).node()
5183 node1 = repo[node2].p1().node()
5183 node1 = repo[node2].p1().node()
5184 else:
5184 else:
5185 node1, node2 = scmutil.revpair(repo, revs)
5185 node1, node2 = scmutil.revpair(repo, revs)
5186
5186
5187 cwd = (pats and repo.getcwd()) or ''
5187 cwd = (pats and repo.getcwd()) or ''
5188 end = opts.get('print0') and '\0' or '\n'
5188 end = opts.get('print0') and '\0' or '\n'
5189 copy = {}
5189 copy = {}
5190 states = 'modified added removed deleted unknown ignored clean'.split()
5190 states = 'modified added removed deleted unknown ignored clean'.split()
5191 show = [k for k in states if opts.get(k)]
5191 show = [k for k in states if opts.get(k)]
5192 if opts.get('all'):
5192 if opts.get('all'):
5193 show += ui.quiet and (states[:4] + ['clean']) or states
5193 show += ui.quiet and (states[:4] + ['clean']) or states
5194 if not show:
5194 if not show:
5195 show = ui.quiet and states[:4] or states[:5]
5195 show = ui.quiet and states[:4] or states[:5]
5196
5196
5197 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5197 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5198 'ignored' in show, 'clean' in show, 'unknown' in show,
5198 'ignored' in show, 'clean' in show, 'unknown' in show,
5199 opts.get('subrepos'))
5199 opts.get('subrepos'))
5200 changestates = zip(states, 'MAR!?IC', stat)
5200 changestates = zip(states, 'MAR!?IC', stat)
5201
5201
5202 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5202 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5203 copy = copies.pathcopies(repo[node1], repo[node2])
5203 copy = copies.pathcopies(repo[node1], repo[node2])
5204
5204
5205 fm = ui.formatter('status', opts)
5205 fm = ui.formatter('status', opts)
5206 format = '%s %s' + end
5206 format = '%s %s' + end
5207 if opts.get('no_status'):
5207 if opts.get('no_status'):
5208 format = '%.0s%s' + end
5208 format = '%.0s%s' + end
5209
5209
5210 for state, char, files in changestates:
5210 for state, char, files in changestates:
5211 if state in show:
5211 if state in show:
5212 label = 'status.' + state
5212 label = 'status.' + state
5213 for f in files:
5213 for f in files:
5214 fm.startitem()
5214 fm.startitem()
5215 fm.write("status path", format, char,
5215 fm.write("status path", format, char,
5216 repo.pathto(f, cwd), label=label)
5216 repo.pathto(f, cwd), label=label)
5217 if f in copy:
5217 if f in copy:
5218 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5218 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5219 label='status.copied')
5219 label='status.copied')
5220 fm.end()
5220 fm.end()
5221
5221
5222 @command('^summary|sum',
5222 @command('^summary|sum',
5223 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5223 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5224 def summary(ui, repo, **opts):
5224 def summary(ui, repo, **opts):
5225 """summarize working directory state
5225 """summarize working directory state
5226
5226
5227 This generates a brief summary of the working directory state,
5227 This generates a brief summary of the working directory state,
5228 including parents, branch, commit status, and available updates.
5228 including parents, branch, commit status, and available updates.
5229
5229
5230 With the --remote option, this will check the default paths for
5230 With the --remote option, this will check the default paths for
5231 incoming and outgoing changes. This can be time-consuming.
5231 incoming and outgoing changes. This can be time-consuming.
5232
5232
5233 Returns 0 on success.
5233 Returns 0 on success.
5234 """
5234 """
5235
5235
5236 ctx = repo[None]
5236 ctx = repo[None]
5237 parents = ctx.parents()
5237 parents = ctx.parents()
5238 pnode = parents[0].node()
5238 pnode = parents[0].node()
5239 marks = []
5239 marks = []
5240
5240
5241 for p in parents:
5241 for p in parents:
5242 # label with log.changeset (instead of log.parent) since this
5242 # label with log.changeset (instead of log.parent) since this
5243 # shows a working directory parent *changeset*:
5243 # shows a working directory parent *changeset*:
5244 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5244 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5245 label='log.changeset')
5245 label='log.changeset')
5246 ui.write(' '.join(p.tags()), label='log.tag')
5246 ui.write(' '.join(p.tags()), label='log.tag')
5247 if p.bookmarks():
5247 if p.bookmarks():
5248 marks.extend(p.bookmarks())
5248 marks.extend(p.bookmarks())
5249 if p.rev() == -1:
5249 if p.rev() == -1:
5250 if not len(repo):
5250 if not len(repo):
5251 ui.write(_(' (empty repository)'))
5251 ui.write(_(' (empty repository)'))
5252 else:
5252 else:
5253 ui.write(_(' (no revision checked out)'))
5253 ui.write(_(' (no revision checked out)'))
5254 ui.write('\n')
5254 ui.write('\n')
5255 if p.description():
5255 if p.description():
5256 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5256 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5257 label='log.summary')
5257 label='log.summary')
5258
5258
5259 branch = ctx.branch()
5259 branch = ctx.branch()
5260 bheads = repo.branchheads(branch)
5260 bheads = repo.branchheads(branch)
5261 m = _('branch: %s\n') % branch
5261 m = _('branch: %s\n') % branch
5262 if branch != 'default':
5262 if branch != 'default':
5263 ui.write(m, label='log.branch')
5263 ui.write(m, label='log.branch')
5264 else:
5264 else:
5265 ui.status(m, label='log.branch')
5265 ui.status(m, label='log.branch')
5266
5266
5267 if marks:
5267 if marks:
5268 current = repo._bookmarkcurrent
5268 current = repo._bookmarkcurrent
5269 ui.write(_('bookmarks:'), label='log.bookmark')
5269 ui.write(_('bookmarks:'), label='log.bookmark')
5270 if current is not None:
5270 if current is not None:
5271 try:
5271 try:
5272 marks.remove(current)
5272 marks.remove(current)
5273 ui.write(' *' + current, label='bookmarks.current')
5273 ui.write(' *' + current, label='bookmarks.current')
5274 except ValueError:
5274 except ValueError:
5275 # current bookmark not in parent ctx marks
5275 # current bookmark not in parent ctx marks
5276 pass
5276 pass
5277 for m in marks:
5277 for m in marks:
5278 ui.write(' ' + m, label='log.bookmark')
5278 ui.write(' ' + m, label='log.bookmark')
5279 ui.write('\n', label='log.bookmark')
5279 ui.write('\n', label='log.bookmark')
5280
5280
5281 st = list(repo.status(unknown=True))[:6]
5281 st = list(repo.status(unknown=True))[:6]
5282
5282
5283 c = repo.dirstate.copies()
5283 c = repo.dirstate.copies()
5284 copied, renamed = [], []
5284 copied, renamed = [], []
5285 for d, s in c.iteritems():
5285 for d, s in c.iteritems():
5286 if s in st[2]:
5286 if s in st[2]:
5287 st[2].remove(s)
5287 st[2].remove(s)
5288 renamed.append(d)
5288 renamed.append(d)
5289 else:
5289 else:
5290 copied.append(d)
5290 copied.append(d)
5291 if d in st[1]:
5291 if d in st[1]:
5292 st[1].remove(d)
5292 st[1].remove(d)
5293 st.insert(3, renamed)
5293 st.insert(3, renamed)
5294 st.insert(4, copied)
5294 st.insert(4, copied)
5295
5295
5296 ms = mergemod.mergestate(repo)
5296 ms = mergemod.mergestate(repo)
5297 st.append([f for f in ms if ms[f] == 'u'])
5297 st.append([f for f in ms if ms[f] == 'u'])
5298
5298
5299 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5299 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5300 st.append(subs)
5300 st.append(subs)
5301
5301
5302 labels = [ui.label(_('%d modified'), 'status.modified'),
5302 labels = [ui.label(_('%d modified'), 'status.modified'),
5303 ui.label(_('%d added'), 'status.added'),
5303 ui.label(_('%d added'), 'status.added'),
5304 ui.label(_('%d removed'), 'status.removed'),
5304 ui.label(_('%d removed'), 'status.removed'),
5305 ui.label(_('%d renamed'), 'status.copied'),
5305 ui.label(_('%d renamed'), 'status.copied'),
5306 ui.label(_('%d copied'), 'status.copied'),
5306 ui.label(_('%d copied'), 'status.copied'),
5307 ui.label(_('%d deleted'), 'status.deleted'),
5307 ui.label(_('%d deleted'), 'status.deleted'),
5308 ui.label(_('%d unknown'), 'status.unknown'),
5308 ui.label(_('%d unknown'), 'status.unknown'),
5309 ui.label(_('%d ignored'), 'status.ignored'),
5309 ui.label(_('%d ignored'), 'status.ignored'),
5310 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5310 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5311 ui.label(_('%d subrepos'), 'status.modified')]
5311 ui.label(_('%d subrepos'), 'status.modified')]
5312 t = []
5312 t = []
5313 for s, l in zip(st, labels):
5313 for s, l in zip(st, labels):
5314 if s:
5314 if s:
5315 t.append(l % len(s))
5315 t.append(l % len(s))
5316
5316
5317 t = ', '.join(t)
5317 t = ', '.join(t)
5318 cleanworkdir = False
5318 cleanworkdir = False
5319
5319
5320 if len(parents) > 1:
5320 if len(parents) > 1:
5321 t += _(' (merge)')
5321 t += _(' (merge)')
5322 elif branch != parents[0].branch():
5322 elif branch != parents[0].branch():
5323 t += _(' (new branch)')
5323 t += _(' (new branch)')
5324 elif (parents[0].extra().get('close') and
5324 elif (parents[0].extra().get('close') and
5325 pnode in repo.branchheads(branch, closed=True)):
5325 pnode in repo.branchheads(branch, closed=True)):
5326 t += _(' (head closed)')
5326 t += _(' (head closed)')
5327 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5327 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5328 t += _(' (clean)')
5328 t += _(' (clean)')
5329 cleanworkdir = True
5329 cleanworkdir = True
5330 elif pnode not in bheads:
5330 elif pnode not in bheads:
5331 t += _(' (new branch head)')
5331 t += _(' (new branch head)')
5332
5332
5333 if cleanworkdir:
5333 if cleanworkdir:
5334 ui.status(_('commit: %s\n') % t.strip())
5334 ui.status(_('commit: %s\n') % t.strip())
5335 else:
5335 else:
5336 ui.write(_('commit: %s\n') % t.strip())
5336 ui.write(_('commit: %s\n') % t.strip())
5337
5337
5338 # all ancestors of branch heads - all ancestors of parent = new csets
5338 # all ancestors of branch heads - all ancestors of parent = new csets
5339 new = [0] * len(repo)
5339 new = [0] * len(repo)
5340 cl = repo.changelog
5340 cl = repo.changelog
5341 for a in [cl.rev(n) for n in bheads]:
5341 for a in [cl.rev(n) for n in bheads]:
5342 new[a] = 1
5342 new[a] = 1
5343 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5343 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5344 new[a] = 1
5344 new[a] = 1
5345 for a in [p.rev() for p in parents]:
5345 for a in [p.rev() for p in parents]:
5346 if a >= 0:
5346 if a >= 0:
5347 new[a] = 0
5347 new[a] = 0
5348 for a in cl.ancestors(*[p.rev() for p in parents]):
5348 for a in cl.ancestors(*[p.rev() for p in parents]):
5349 new[a] = 0
5349 new[a] = 0
5350 new = sum(new)
5350 new = sum(new)
5351
5351
5352 if new == 0:
5352 if new == 0:
5353 ui.status(_('update: (current)\n'))
5353 ui.status(_('update: (current)\n'))
5354 elif pnode not in bheads:
5354 elif pnode not in bheads:
5355 ui.write(_('update: %d new changesets (update)\n') % new)
5355 ui.write(_('update: %d new changesets (update)\n') % new)
5356 else:
5356 else:
5357 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5357 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5358 (new, len(bheads)))
5358 (new, len(bheads)))
5359
5359
5360 if opts.get('remote'):
5360 if opts.get('remote'):
5361 t = []
5361 t = []
5362 source, branches = hg.parseurl(ui.expandpath('default'))
5362 source, branches = hg.parseurl(ui.expandpath('default'))
5363 other = hg.peer(repo, {}, source)
5363 other = hg.peer(repo, {}, source)
5364 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5364 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5365 ui.debug('comparing with %s\n' % util.hidepassword(source))
5365 ui.debug('comparing with %s\n' % util.hidepassword(source))
5366 repo.ui.pushbuffer()
5366 repo.ui.pushbuffer()
5367 commoninc = discovery.findcommonincoming(repo, other)
5367 commoninc = discovery.findcommonincoming(repo, other)
5368 _common, incoming, _rheads = commoninc
5368 _common, incoming, _rheads = commoninc
5369 repo.ui.popbuffer()
5369 repo.ui.popbuffer()
5370 if incoming:
5370 if incoming:
5371 t.append(_('1 or more incoming'))
5371 t.append(_('1 or more incoming'))
5372
5372
5373 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5373 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5374 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5374 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5375 if source != dest:
5375 if source != dest:
5376 other = hg.peer(repo, {}, dest)
5376 other = hg.peer(repo, {}, dest)
5377 commoninc = None
5377 commoninc = None
5378 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5378 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5379 repo.ui.pushbuffer()
5379 repo.ui.pushbuffer()
5380 outgoing = discovery.findcommonoutgoing(repo, other,
5380 outgoing = discovery.findcommonoutgoing(repo, other,
5381 commoninc=commoninc)
5381 commoninc=commoninc)
5382 repo.ui.popbuffer()
5382 repo.ui.popbuffer()
5383 o = outgoing.missing
5383 o = outgoing.missing
5384 if o:
5384 if o:
5385 t.append(_('%d outgoing') % len(o))
5385 t.append(_('%d outgoing') % len(o))
5386 if 'bookmarks' in other.listkeys('namespaces'):
5386 if 'bookmarks' in other.listkeys('namespaces'):
5387 lmarks = repo.listkeys('bookmarks')
5387 lmarks = repo.listkeys('bookmarks')
5388 rmarks = other.listkeys('bookmarks')
5388 rmarks = other.listkeys('bookmarks')
5389 diff = set(rmarks) - set(lmarks)
5389 diff = set(rmarks) - set(lmarks)
5390 if len(diff) > 0:
5390 if len(diff) > 0:
5391 t.append(_('%d incoming bookmarks') % len(diff))
5391 t.append(_('%d incoming bookmarks') % len(diff))
5392 diff = set(lmarks) - set(rmarks)
5392 diff = set(lmarks) - set(rmarks)
5393 if len(diff) > 0:
5393 if len(diff) > 0:
5394 t.append(_('%d outgoing bookmarks') % len(diff))
5394 t.append(_('%d outgoing bookmarks') % len(diff))
5395
5395
5396 if t:
5396 if t:
5397 ui.write(_('remote: %s\n') % (', '.join(t)))
5397 ui.write(_('remote: %s\n') % (', '.join(t)))
5398 else:
5398 else:
5399 ui.status(_('remote: (synced)\n'))
5399 ui.status(_('remote: (synced)\n'))
5400
5400
5401 @command('tag',
5401 @command('tag',
5402 [('f', 'force', None, _('force tag')),
5402 [('f', 'force', None, _('force tag')),
5403 ('l', 'local', None, _('make the tag local')),
5403 ('l', 'local', None, _('make the tag local')),
5404 ('r', 'rev', '', _('revision to tag'), _('REV')),
5404 ('r', 'rev', '', _('revision to tag'), _('REV')),
5405 ('', 'remove', None, _('remove a tag')),
5405 ('', 'remove', None, _('remove a tag')),
5406 # -l/--local is already there, commitopts cannot be used
5406 # -l/--local is already there, commitopts cannot be used
5407 ('e', 'edit', None, _('edit commit message')),
5407 ('e', 'edit', None, _('edit commit message')),
5408 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5408 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5409 ] + commitopts2,
5409 ] + commitopts2,
5410 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5410 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5411 def tag(ui, repo, name1, *names, **opts):
5411 def tag(ui, repo, name1, *names, **opts):
5412 """add one or more tags for the current or given revision
5412 """add one or more tags for the current or given revision
5413
5413
5414 Name a particular revision using <name>.
5414 Name a particular revision using <name>.
5415
5415
5416 Tags are used to name particular revisions of the repository and are
5416 Tags are used to name particular revisions of the repository and are
5417 very useful to compare different revisions, to go back to significant
5417 very useful to compare different revisions, to go back to significant
5418 earlier versions or to mark branch points as releases, etc. Changing
5418 earlier versions or to mark branch points as releases, etc. Changing
5419 an existing tag is normally disallowed; use -f/--force to override.
5419 an existing tag is normally disallowed; use -f/--force to override.
5420
5420
5421 If no revision is given, the parent of the working directory is
5421 If no revision is given, the parent of the working directory is
5422 used, or tip if no revision is checked out.
5422 used, or tip if no revision is checked out.
5423
5423
5424 To facilitate version control, distribution, and merging of tags,
5424 To facilitate version control, distribution, and merging of tags,
5425 they are stored as a file named ".hgtags" which is managed similarly
5425 they are stored as a file named ".hgtags" which is managed similarly
5426 to other project files and can be hand-edited if necessary. This
5426 to other project files and can be hand-edited if necessary. This
5427 also means that tagging creates a new commit. The file
5427 also means that tagging creates a new commit. The file
5428 ".hg/localtags" is used for local tags (not shared among
5428 ".hg/localtags" is used for local tags (not shared among
5429 repositories).
5429 repositories).
5430
5430
5431 Tag commits are usually made at the head of a branch. If the parent
5431 Tag commits are usually made at the head of a branch. If the parent
5432 of the working directory is not a branch head, :hg:`tag` aborts; use
5432 of the working directory is not a branch head, :hg:`tag` aborts; use
5433 -f/--force to force the tag commit to be based on a non-head
5433 -f/--force to force the tag commit to be based on a non-head
5434 changeset.
5434 changeset.
5435
5435
5436 See :hg:`help dates` for a list of formats valid for -d/--date.
5436 See :hg:`help dates` for a list of formats valid for -d/--date.
5437
5437
5438 Since tag names have priority over branch names during revision
5438 Since tag names have priority over branch names during revision
5439 lookup, using an existing branch name as a tag name is discouraged.
5439 lookup, using an existing branch name as a tag name is discouraged.
5440
5440
5441 Returns 0 on success.
5441 Returns 0 on success.
5442 """
5442 """
5443 wlock = lock = None
5443 wlock = lock = None
5444 try:
5444 try:
5445 wlock = repo.wlock()
5445 wlock = repo.wlock()
5446 lock = repo.lock()
5446 lock = repo.lock()
5447 rev_ = "."
5447 rev_ = "."
5448 names = [t.strip() for t in (name1,) + names]
5448 names = [t.strip() for t in (name1,) + names]
5449 if len(names) != len(set(names)):
5449 if len(names) != len(set(names)):
5450 raise util.Abort(_('tag names must be unique'))
5450 raise util.Abort(_('tag names must be unique'))
5451 for n in names:
5451 for n in names:
5452 if n in ['tip', '.', 'null']:
5452 if n in ['tip', '.', 'null']:
5453 raise util.Abort(_("the name '%s' is reserved") % n)
5453 raise util.Abort(_("the name '%s' is reserved") % n)
5454 if not n:
5454 if not n:
5455 raise util.Abort(_('tag names cannot consist entirely of '
5455 raise util.Abort(_('tag names cannot consist entirely of '
5456 'whitespace'))
5456 'whitespace'))
5457 if opts.get('rev') and opts.get('remove'):
5457 if opts.get('rev') and opts.get('remove'):
5458 raise util.Abort(_("--rev and --remove are incompatible"))
5458 raise util.Abort(_("--rev and --remove are incompatible"))
5459 if opts.get('rev'):
5459 if opts.get('rev'):
5460 rev_ = opts['rev']
5460 rev_ = opts['rev']
5461 message = opts.get('message')
5461 message = opts.get('message')
5462 if opts.get('remove'):
5462 if opts.get('remove'):
5463 expectedtype = opts.get('local') and 'local' or 'global'
5463 expectedtype = opts.get('local') and 'local' or 'global'
5464 for n in names:
5464 for n in names:
5465 if not repo.tagtype(n):
5465 if not repo.tagtype(n):
5466 raise util.Abort(_("tag '%s' does not exist") % n)
5466 raise util.Abort(_("tag '%s' does not exist") % n)
5467 if repo.tagtype(n) != expectedtype:
5467 if repo.tagtype(n) != expectedtype:
5468 if expectedtype == 'global':
5468 if expectedtype == 'global':
5469 raise util.Abort(_("tag '%s' is not a global tag") % n)
5469 raise util.Abort(_("tag '%s' is not a global tag") % n)
5470 else:
5470 else:
5471 raise util.Abort(_("tag '%s' is not a local tag") % n)
5471 raise util.Abort(_("tag '%s' is not a local tag") % n)
5472 rev_ = nullid
5472 rev_ = nullid
5473 if not message:
5473 if not message:
5474 # we don't translate commit messages
5474 # we don't translate commit messages
5475 message = 'Removed tag %s' % ', '.join(names)
5475 message = 'Removed tag %s' % ', '.join(names)
5476 elif not opts.get('force'):
5476 elif not opts.get('force'):
5477 for n in names:
5477 for n in names:
5478 if n in repo.tags():
5478 if n in repo.tags():
5479 raise util.Abort(_("tag '%s' already exists "
5479 raise util.Abort(_("tag '%s' already exists "
5480 "(use -f to force)") % n)
5480 "(use -f to force)") % n)
5481 if not opts.get('local'):
5481 if not opts.get('local'):
5482 p1, p2 = repo.dirstate.parents()
5482 p1, p2 = repo.dirstate.parents()
5483 if p2 != nullid:
5483 if p2 != nullid:
5484 raise util.Abort(_('uncommitted merge'))
5484 raise util.Abort(_('uncommitted merge'))
5485 bheads = repo.branchheads()
5485 bheads = repo.branchheads()
5486 if not opts.get('force') and bheads and p1 not in bheads:
5486 if not opts.get('force') and bheads and p1 not in bheads:
5487 raise util.Abort(_('not at a branch head (use -f to force)'))
5487 raise util.Abort(_('not at a branch head (use -f to force)'))
5488 r = scmutil.revsingle(repo, rev_).node()
5488 r = scmutil.revsingle(repo, rev_).node()
5489
5489
5490 if not message:
5490 if not message:
5491 # we don't translate commit messages
5491 # we don't translate commit messages
5492 message = ('Added tag %s for changeset %s' %
5492 message = ('Added tag %s for changeset %s' %
5493 (', '.join(names), short(r)))
5493 (', '.join(names), short(r)))
5494
5494
5495 date = opts.get('date')
5495 date = opts.get('date')
5496 if date:
5496 if date:
5497 date = util.parsedate(date)
5497 date = util.parsedate(date)
5498
5498
5499 if opts.get('edit'):
5499 if opts.get('edit'):
5500 message = ui.edit(message, ui.username())
5500 message = ui.edit(message, ui.username())
5501
5501
5502 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5502 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5503 finally:
5503 finally:
5504 release(lock, wlock)
5504 release(lock, wlock)
5505
5505
5506 @command('tags', [], '')
5506 @command('tags', [], '')
5507 def tags(ui, repo):
5507 def tags(ui, repo):
5508 """list repository tags
5508 """list repository tags
5509
5509
5510 This lists both regular and local tags. When the -v/--verbose
5510 This lists both regular and local tags. When the -v/--verbose
5511 switch is used, a third column "local" is printed for local tags.
5511 switch is used, a third column "local" is printed for local tags.
5512
5512
5513 Returns 0 on success.
5513 Returns 0 on success.
5514 """
5514 """
5515
5515
5516 hexfunc = ui.debugflag and hex or short
5516 hexfunc = ui.debugflag and hex or short
5517 tagtype = ""
5517 tagtype = ""
5518
5518
5519 for t, n in reversed(repo.tagslist()):
5519 for t, n in reversed(repo.tagslist()):
5520 if ui.quiet:
5520 if ui.quiet:
5521 ui.write("%s\n" % t, label='tags.normal')
5521 ui.write("%s\n" % t, label='tags.normal')
5522 continue
5522 continue
5523
5523
5524 hn = hexfunc(n)
5524 hn = hexfunc(n)
5525 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5525 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5526 rev = ui.label(r, 'log.changeset')
5526 rev = ui.label(r, 'log.changeset')
5527 spaces = " " * (30 - encoding.colwidth(t))
5527 spaces = " " * (30 - encoding.colwidth(t))
5528
5528
5529 tag = ui.label(t, 'tags.normal')
5529 tag = ui.label(t, 'tags.normal')
5530 if ui.verbose:
5530 if ui.verbose:
5531 if repo.tagtype(t) == 'local':
5531 if repo.tagtype(t) == 'local':
5532 tagtype = " local"
5532 tagtype = " local"
5533 tag = ui.label(t, 'tags.local')
5533 tag = ui.label(t, 'tags.local')
5534 else:
5534 else:
5535 tagtype = ""
5535 tagtype = ""
5536 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5536 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5537
5537
5538 @command('tip',
5538 @command('tip',
5539 [('p', 'patch', None, _('show patch')),
5539 [('p', 'patch', None, _('show patch')),
5540 ('g', 'git', None, _('use git extended diff format')),
5540 ('g', 'git', None, _('use git extended diff format')),
5541 ] + templateopts,
5541 ] + templateopts,
5542 _('[-p] [-g]'))
5542 _('[-p] [-g]'))
5543 def tip(ui, repo, **opts):
5543 def tip(ui, repo, **opts):
5544 """show the tip revision
5544 """show the tip revision
5545
5545
5546 The tip revision (usually just called the tip) is the changeset
5546 The tip revision (usually just called the tip) is the changeset
5547 most recently added to the repository (and therefore the most
5547 most recently added to the repository (and therefore the most
5548 recently changed head).
5548 recently changed head).
5549
5549
5550 If you have just made a commit, that commit will be the tip. If
5550 If you have just made a commit, that commit will be the tip. If
5551 you have just pulled changes from another repository, the tip of
5551 you have just pulled changes from another repository, the tip of
5552 that repository becomes the current tip. The "tip" tag is special
5552 that repository becomes the current tip. The "tip" tag is special
5553 and cannot be renamed or assigned to a different changeset.
5553 and cannot be renamed or assigned to a different changeset.
5554
5554
5555 Returns 0 on success.
5555 Returns 0 on success.
5556 """
5556 """
5557 displayer = cmdutil.show_changeset(ui, repo, opts)
5557 displayer = cmdutil.show_changeset(ui, repo, opts)
5558 displayer.show(repo[len(repo) - 1])
5558 displayer.show(repo[len(repo) - 1])
5559 displayer.close()
5559 displayer.close()
5560
5560
5561 @command('unbundle',
5561 @command('unbundle',
5562 [('u', 'update', None,
5562 [('u', 'update', None,
5563 _('update to new branch head if changesets were unbundled'))],
5563 _('update to new branch head if changesets were unbundled'))],
5564 _('[-u] FILE...'))
5564 _('[-u] FILE...'))
5565 def unbundle(ui, repo, fname1, *fnames, **opts):
5565 def unbundle(ui, repo, fname1, *fnames, **opts):
5566 """apply one or more changegroup files
5566 """apply one or more changegroup files
5567
5567
5568 Apply one or more compressed changegroup files generated by the
5568 Apply one or more compressed changegroup files generated by the
5569 bundle command.
5569 bundle command.
5570
5570
5571 Returns 0 on success, 1 if an update has unresolved files.
5571 Returns 0 on success, 1 if an update has unresolved files.
5572 """
5572 """
5573 fnames = (fname1,) + fnames
5573 fnames = (fname1,) + fnames
5574
5574
5575 lock = repo.lock()
5575 lock = repo.lock()
5576 wc = repo['.']
5576 wc = repo['.']
5577 try:
5577 try:
5578 for fname in fnames:
5578 for fname in fnames:
5579 f = url.open(ui, fname)
5579 f = url.open(ui, fname)
5580 gen = changegroup.readbundle(f, fname)
5580 gen = changegroup.readbundle(f, fname)
5581 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5581 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5582 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5582 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5583 finally:
5583 finally:
5584 lock.release()
5584 lock.release()
5585 return postincoming(ui, repo, modheads, opts.get('update'), None)
5585 return postincoming(ui, repo, modheads, opts.get('update'), None)
5586
5586
5587 @command('^update|up|checkout|co',
5587 @command('^update|up|checkout|co',
5588 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5588 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5589 ('c', 'check', None,
5589 ('c', 'check', None,
5590 _('update across branches if no uncommitted changes')),
5590 _('update across branches if no uncommitted changes')),
5591 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5591 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5592 ('r', 'rev', '', _('revision'), _('REV'))],
5592 ('r', 'rev', '', _('revision'), _('REV'))],
5593 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5593 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5594 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5594 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5595 """update working directory (or switch revisions)
5595 """update working directory (or switch revisions)
5596
5596
5597 Update the repository's working directory to the specified
5597 Update the repository's working directory to the specified
5598 changeset. If no changeset is specified, update to the tip of the
5598 changeset. If no changeset is specified, update to the tip of the
5599 current named branch and move the current bookmark (see :hg:`help
5599 current named branch and move the current bookmark (see :hg:`help
5600 bookmarks`).
5600 bookmarks`).
5601
5601
5602 If the changeset is not a descendant of the working directory's
5602 If the changeset is not a descendant of the working directory's
5603 parent, the update is aborted. With the -c/--check option, the
5603 parent, the update is aborted. With the -c/--check option, the
5604 working directory is checked for uncommitted changes; if none are
5604 working directory is checked for uncommitted changes; if none are
5605 found, the working directory is updated to the specified
5605 found, the working directory is updated to the specified
5606 changeset.
5606 changeset.
5607
5607
5608 Update sets the working directory's parent revison to the specified
5608 Update sets the working directory's parent revison to the specified
5609 changeset (see :hg:`help parents`).
5609 changeset (see :hg:`help parents`).
5610
5610
5611 The following rules apply when the working directory contains
5611 The following rules apply when the working directory contains
5612 uncommitted changes:
5612 uncommitted changes:
5613
5613
5614 1. If neither -c/--check nor -C/--clean is specified, and if
5614 1. If neither -c/--check nor -C/--clean is specified, and if
5615 the requested changeset is an ancestor or descendant of
5615 the requested changeset is an ancestor or descendant of
5616 the working directory's parent, the uncommitted changes
5616 the working directory's parent, the uncommitted changes
5617 are merged into the requested changeset and the merged
5617 are merged into the requested changeset and the merged
5618 result is left uncommitted. If the requested changeset is
5618 result is left uncommitted. If the requested changeset is
5619 not an ancestor or descendant (that is, it is on another
5619 not an ancestor or descendant (that is, it is on another
5620 branch), the update is aborted and the uncommitted changes
5620 branch), the update is aborted and the uncommitted changes
5621 are preserved.
5621 are preserved.
5622
5622
5623 2. With the -c/--check option, the update is aborted and the
5623 2. With the -c/--check option, the update is aborted and the
5624 uncommitted changes are preserved.
5624 uncommitted changes are preserved.
5625
5625
5626 3. With the -C/--clean option, uncommitted changes are discarded and
5626 3. With the -C/--clean option, uncommitted changes are discarded and
5627 the working directory is updated to the requested changeset.
5627 the working directory is updated to the requested changeset.
5628
5628
5629 Use null as the changeset to remove the working directory (like
5629 Use null as the changeset to remove the working directory (like
5630 :hg:`clone -U`).
5630 :hg:`clone -U`).
5631
5631
5632 If you want to revert just one file to an older revision, use
5632 If you want to revert just one file to an older revision, use
5633 :hg:`revert [-r REV] NAME`.
5633 :hg:`revert [-r REV] NAME`.
5634
5634
5635 See :hg:`help dates` for a list of formats valid for -d/--date.
5635 See :hg:`help dates` for a list of formats valid for -d/--date.
5636
5636
5637 Returns 0 on success, 1 if there are unresolved files.
5637 Returns 0 on success, 1 if there are unresolved files.
5638 """
5638 """
5639 if rev and node:
5639 if rev and node:
5640 raise util.Abort(_("please specify just one revision"))
5640 raise util.Abort(_("please specify just one revision"))
5641
5641
5642 if rev is None or rev == '':
5642 if rev is None or rev == '':
5643 rev = node
5643 rev = node
5644
5644
5645 # with no argument, we also move the current bookmark, if any
5645 # with no argument, we also move the current bookmark, if any
5646 movemarkfrom = None
5646 movemarkfrom = None
5647 if rev is None or node == '':
5647 if rev is None or node == '':
5648 movemarkfrom = repo['.'].node()
5648 movemarkfrom = repo['.'].node()
5649
5649
5650 # if we defined a bookmark, we have to remember the original bookmark name
5650 # if we defined a bookmark, we have to remember the original bookmark name
5651 brev = rev
5651 brev = rev
5652 rev = scmutil.revsingle(repo, rev, rev).rev()
5652 rev = scmutil.revsingle(repo, rev, rev).rev()
5653
5653
5654 if check and clean:
5654 if check and clean:
5655 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5655 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5656
5656
5657 if date:
5657 if date:
5658 if rev is not None:
5658 if rev is not None:
5659 raise util.Abort(_("you can't specify a revision and a date"))
5659 raise util.Abort(_("you can't specify a revision and a date"))
5660 rev = cmdutil.finddate(ui, repo, date)
5660 rev = cmdutil.finddate(ui, repo, date)
5661
5661
5662 if check:
5662 if check:
5663 c = repo[None]
5663 c = repo[None]
5664 if c.dirty(merge=False, branch=False):
5664 if c.dirty(merge=False, branch=False):
5665 raise util.Abort(_("uncommitted local changes"))
5665 raise util.Abort(_("uncommitted local changes"))
5666 if rev is None:
5666 if rev is None:
5667 rev = repo[repo[None].branch()].rev()
5667 rev = repo[repo[None].branch()].rev()
5668 mergemod._checkunknown(repo, repo[None], repo[rev])
5668 mergemod._checkunknown(repo, repo[None], repo[rev])
5669
5669
5670 if clean:
5670 if clean:
5671 ret = hg.clean(repo, rev)
5671 ret = hg.clean(repo, rev)
5672 else:
5672 else:
5673 ret = hg.update(repo, rev)
5673 ret = hg.update(repo, rev)
5674
5674
5675 if not ret and movemarkfrom:
5675 if not ret and movemarkfrom:
5676 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5676 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5677 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5677 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5678 elif brev in repo._bookmarks:
5678 elif brev in repo._bookmarks:
5679 bookmarks.setcurrent(repo, brev)
5679 bookmarks.setcurrent(repo, brev)
5680 elif brev:
5680 elif brev:
5681 bookmarks.unsetcurrent(repo)
5681 bookmarks.unsetcurrent(repo)
5682
5682
5683 return ret
5683 return ret
5684
5684
5685 @command('verify', [])
5685 @command('verify', [])
5686 def verify(ui, repo):
5686 def verify(ui, repo):
5687 """verify the integrity of the repository
5687 """verify the integrity of the repository
5688
5688
5689 Verify the integrity of the current repository.
5689 Verify the integrity of the current repository.
5690
5690
5691 This will perform an extensive check of the repository's
5691 This will perform an extensive check of the repository's
5692 integrity, validating the hashes and checksums of each entry in
5692 integrity, validating the hashes and checksums of each entry in
5693 the changelog, manifest, and tracked files, as well as the
5693 the changelog, manifest, and tracked files, as well as the
5694 integrity of their crosslinks and indices.
5694 integrity of their crosslinks and indices.
5695
5695
5696 Returns 0 on success, 1 if errors are encountered.
5696 Returns 0 on success, 1 if errors are encountered.
5697 """
5697 """
5698 return hg.verify(repo)
5698 return hg.verify(repo)
5699
5699
5700 @command('version', [])
5700 @command('version', [])
5701 def version_(ui):
5701 def version_(ui):
5702 """output version and copyright information"""
5702 """output version and copyright information"""
5703 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5703 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5704 % util.version())
5704 % util.version())
5705 ui.status(_(
5705 ui.status(_(
5706 "(see http://mercurial.selenic.com for more information)\n"
5706 "(see http://mercurial.selenic.com for more information)\n"
5707 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5707 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5708 "This is free software; see the source for copying conditions. "
5708 "This is free software; see the source for copying conditions. "
5709 "There is NO\nwarranty; "
5709 "There is NO\nwarranty; "
5710 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5710 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5711 ))
5711 ))
5712
5712
5713 norepo = ("clone init version help debugcommands debugcomplete"
5713 norepo = ("clone init version help debugcommands debugcomplete"
5714 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5714 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5715 " debugknown debuggetbundle debugbundle")
5715 " debugknown debuggetbundle debugbundle")
5716 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5716 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5717 " debugdata debugindex debugindexdot debugrevlog")
5717 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now