##// END OF EJS Templates
resolve: keep wlock while resolving...
Mads Kiilerich <madski at unity3d.com> -
r21709:14560418 stable
parent child Browse files
Show More
@@ -1,5925 +1,5930 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 _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 from hgweb import server as hgweb_server
17 from hgweb import server as hgweb_server
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod
20 import dagparser, context, simplemerge, graphmod
21 import random
21 import random
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import phases, obsolete, exchange
23 import phases, obsolete, exchange
24
24
25 table = {}
25 table = {}
26
26
27 command = cmdutil.command(table)
27 command = cmdutil.command(table)
28
28
29 # common command options
29 # common command options
30
30
31 globalopts = [
31 globalopts = [
32 ('R', 'repository', '',
32 ('R', 'repository', '',
33 _('repository root directory or name of overlay bundle file'),
33 _('repository root directory or name of overlay bundle file'),
34 _('REPO')),
34 _('REPO')),
35 ('', 'cwd', '',
35 ('', 'cwd', '',
36 _('change working directory'), _('DIR')),
36 _('change working directory'), _('DIR')),
37 ('y', 'noninteractive', None,
37 ('y', 'noninteractive', None,
38 _('do not prompt, automatically pick the first choice for all prompts')),
38 _('do not prompt, automatically pick the first choice for all prompts')),
39 ('q', 'quiet', None, _('suppress output')),
39 ('q', 'quiet', None, _('suppress output')),
40 ('v', 'verbose', None, _('enable additional output')),
40 ('v', 'verbose', None, _('enable additional output')),
41 ('', 'config', [],
41 ('', 'config', [],
42 _('set/override config option (use \'section.name=value\')'),
42 _('set/override config option (use \'section.name=value\')'),
43 _('CONFIG')),
43 _('CONFIG')),
44 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debug', None, _('enable debugging output')),
45 ('', 'debugger', None, _('start debugger')),
45 ('', 'debugger', None, _('start debugger')),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
47 _('ENCODE')),
47 _('ENCODE')),
48 ('', 'encodingmode', encoding.encodingmode,
48 ('', 'encodingmode', encoding.encodingmode,
49 _('set the charset encoding mode'), _('MODE')),
49 _('set the charset encoding mode'), _('MODE')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
51 ('', 'time', None, _('time how long the command takes')),
51 ('', 'time', None, _('time how long the command takes')),
52 ('', 'profile', None, _('print command execution profile')),
52 ('', 'profile', None, _('print command execution profile')),
53 ('', 'version', None, _('output version information and exit')),
53 ('', 'version', None, _('output version information and exit')),
54 ('h', 'help', None, _('display help and exit')),
54 ('h', 'help', None, _('display help and exit')),
55 ('', 'hidden', False, _('consider hidden changesets')),
55 ('', 'hidden', False, _('consider hidden changesets')),
56 ]
56 ]
57
57
58 dryrunopts = [('n', 'dry-run', None,
58 dryrunopts = [('n', 'dry-run', None,
59 _('do not perform actions, just print output'))]
59 _('do not perform actions, just print output'))]
60
60
61 remoteopts = [
61 remoteopts = [
62 ('e', 'ssh', '',
62 ('e', 'ssh', '',
63 _('specify ssh command to use'), _('CMD')),
63 _('specify ssh command to use'), _('CMD')),
64 ('', 'remotecmd', '',
64 ('', 'remotecmd', '',
65 _('specify hg command to run on the remote side'), _('CMD')),
65 _('specify hg command to run on the remote side'), _('CMD')),
66 ('', 'insecure', None,
66 ('', 'insecure', None,
67 _('do not verify server certificate (ignoring web.cacerts config)')),
67 _('do not verify server certificate (ignoring web.cacerts config)')),
68 ]
68 ]
69
69
70 walkopts = [
70 walkopts = [
71 ('I', 'include', [],
71 ('I', 'include', [],
72 _('include names matching the given patterns'), _('PATTERN')),
72 _('include names matching the given patterns'), _('PATTERN')),
73 ('X', 'exclude', [],
73 ('X', 'exclude', [],
74 _('exclude names matching the given patterns'), _('PATTERN')),
74 _('exclude names matching the given patterns'), _('PATTERN')),
75 ]
75 ]
76
76
77 commitopts = [
77 commitopts = [
78 ('m', 'message', '',
78 ('m', 'message', '',
79 _('use text as commit message'), _('TEXT')),
79 _('use text as commit message'), _('TEXT')),
80 ('l', 'logfile', '',
80 ('l', 'logfile', '',
81 _('read commit message from file'), _('FILE')),
81 _('read commit message from file'), _('FILE')),
82 ]
82 ]
83
83
84 commitopts2 = [
84 commitopts2 = [
85 ('d', 'date', '',
85 ('d', 'date', '',
86 _('record the specified date as commit date'), _('DATE')),
86 _('record the specified date as commit date'), _('DATE')),
87 ('u', 'user', '',
87 ('u', 'user', '',
88 _('record the specified user as committer'), _('USER')),
88 _('record the specified user as committer'), _('USER')),
89 ]
89 ]
90
90
91 templateopts = [
91 templateopts = [
92 ('', 'style', '',
92 ('', 'style', '',
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
94 ('T', 'template', '',
94 ('T', 'template', '',
95 _('display with template'), _('TEMPLATE')),
95 _('display with template'), _('TEMPLATE')),
96 ]
96 ]
97
97
98 logopts = [
98 logopts = [
99 ('p', 'patch', None, _('show patch')),
99 ('p', 'patch', None, _('show patch')),
100 ('g', 'git', None, _('use git extended diff format')),
100 ('g', 'git', None, _('use git extended diff format')),
101 ('l', 'limit', '',
101 ('l', 'limit', '',
102 _('limit number of changes displayed'), _('NUM')),
102 _('limit number of changes displayed'), _('NUM')),
103 ('M', 'no-merges', None, _('do not show merges')),
103 ('M', 'no-merges', None, _('do not show merges')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
105 ('G', 'graph', None, _("show the revision DAG")),
105 ('G', 'graph', None, _("show the revision DAG")),
106 ] + templateopts
106 ] + templateopts
107
107
108 diffopts = [
108 diffopts = [
109 ('a', 'text', None, _('treat all files as text')),
109 ('a', 'text', None, _('treat all files as text')),
110 ('g', 'git', None, _('use git extended diff format')),
110 ('g', 'git', None, _('use git extended diff format')),
111 ('', 'nodates', None, _('omit dates from diff headers'))
111 ('', 'nodates', None, _('omit dates from diff headers'))
112 ]
112 ]
113
113
114 diffwsopts = [
114 diffwsopts = [
115 ('w', 'ignore-all-space', None,
115 ('w', 'ignore-all-space', None,
116 _('ignore white space when comparing lines')),
116 _('ignore white space when comparing lines')),
117 ('b', 'ignore-space-change', None,
117 ('b', 'ignore-space-change', None,
118 _('ignore changes in the amount of white space')),
118 _('ignore changes in the amount of white space')),
119 ('B', 'ignore-blank-lines', None,
119 ('B', 'ignore-blank-lines', None,
120 _('ignore changes whose lines are all blank')),
120 _('ignore changes whose lines are all blank')),
121 ]
121 ]
122
122
123 diffopts2 = [
123 diffopts2 = [
124 ('p', 'show-function', None, _('show which function each change is in')),
124 ('p', 'show-function', None, _('show which function each change is in')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
126 ] + diffwsopts + [
126 ] + diffwsopts + [
127 ('U', 'unified', '',
127 ('U', 'unified', '',
128 _('number of lines of context to show'), _('NUM')),
128 _('number of lines of context to show'), _('NUM')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
130 ]
130 ]
131
131
132 mergetoolopts = [
132 mergetoolopts = [
133 ('t', 'tool', '', _('specify merge tool')),
133 ('t', 'tool', '', _('specify merge tool')),
134 ]
134 ]
135
135
136 similarityopts = [
136 similarityopts = [
137 ('s', 'similarity', '',
137 ('s', 'similarity', '',
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
139 ]
139 ]
140
140
141 subrepoopts = [
141 subrepoopts = [
142 ('S', 'subrepos', None,
142 ('S', 'subrepos', None,
143 _('recurse into subrepositories'))
143 _('recurse into subrepositories'))
144 ]
144 ]
145
145
146 # Commands start here, listed alphabetically
146 # Commands start here, listed alphabetically
147
147
148 @command('^add',
148 @command('^add',
149 walkopts + subrepoopts + dryrunopts,
149 walkopts + subrepoopts + dryrunopts,
150 _('[OPTION]... [FILE]...'))
150 _('[OPTION]... [FILE]...'))
151 def add(ui, repo, *pats, **opts):
151 def add(ui, repo, *pats, **opts):
152 """add the specified files on the next commit
152 """add the specified files on the next commit
153
153
154 Schedule files to be version controlled and added to the
154 Schedule files to be version controlled and added to the
155 repository.
155 repository.
156
156
157 The files will be added to the repository at the next commit. To
157 The files will be added to the repository at the next commit. To
158 undo an add before that, see :hg:`forget`.
158 undo an add before that, see :hg:`forget`.
159
159
160 If no names are given, add all files to the repository.
160 If no names are given, add all files to the repository.
161
161
162 .. container:: verbose
162 .. container:: verbose
163
163
164 An example showing how new (unknown) files are added
164 An example showing how new (unknown) files are added
165 automatically by :hg:`add`::
165 automatically by :hg:`add`::
166
166
167 $ ls
167 $ ls
168 foo.c
168 foo.c
169 $ hg status
169 $ hg status
170 ? foo.c
170 ? foo.c
171 $ hg add
171 $ hg add
172 adding foo.c
172 adding foo.c
173 $ hg status
173 $ hg status
174 A foo.c
174 A foo.c
175
175
176 Returns 0 if all files are successfully added.
176 Returns 0 if all files are successfully added.
177 """
177 """
178
178
179 m = scmutil.match(repo[None], pats, opts)
179 m = scmutil.match(repo[None], pats, opts)
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
181 opts.get('subrepos'), prefix="", explicitonly=False)
181 opts.get('subrepos'), prefix="", explicitonly=False)
182 return rejected and 1 or 0
182 return rejected and 1 or 0
183
183
184 @command('addremove',
184 @command('addremove',
185 similarityopts + walkopts + dryrunopts,
185 similarityopts + walkopts + dryrunopts,
186 _('[OPTION]... [FILE]...'))
186 _('[OPTION]... [FILE]...'))
187 def addremove(ui, repo, *pats, **opts):
187 def addremove(ui, repo, *pats, **opts):
188 """add all new files, delete all missing files
188 """add all new files, delete all missing files
189
189
190 Add all new files and remove all missing files from the
190 Add all new files and remove all missing files from the
191 repository.
191 repository.
192
192
193 New files are ignored if they match any of the patterns in
193 New files are ignored if they match any of the patterns in
194 ``.hgignore``. As with add, these changes take effect at the next
194 ``.hgignore``. As with add, these changes take effect at the next
195 commit.
195 commit.
196
196
197 Use the -s/--similarity option to detect renamed files. This
197 Use the -s/--similarity option to detect renamed files. This
198 option takes a percentage between 0 (disabled) and 100 (files must
198 option takes a percentage between 0 (disabled) and 100 (files must
199 be identical) as its parameter. With a parameter greater than 0,
199 be identical) as its parameter. With a parameter greater than 0,
200 this compares every removed file with every added file and records
200 this compares every removed file with every added file and records
201 those similar enough as renames. Detecting renamed files this way
201 those similar enough as renames. Detecting renamed files this way
202 can be expensive. After using this option, :hg:`status -C` can be
202 can be expensive. After using this option, :hg:`status -C` can be
203 used to check which files were identified as moved or renamed. If
203 used to check which files were identified as moved or renamed. If
204 not specified, -s/--similarity defaults to 100 and only renames of
204 not specified, -s/--similarity defaults to 100 and only renames of
205 identical files are detected.
205 identical files are detected.
206
206
207 Returns 0 if all files are successfully added.
207 Returns 0 if all files are successfully added.
208 """
208 """
209 try:
209 try:
210 sim = float(opts.get('similarity') or 100)
210 sim = float(opts.get('similarity') or 100)
211 except ValueError:
211 except ValueError:
212 raise util.Abort(_('similarity must be a number'))
212 raise util.Abort(_('similarity must be a number'))
213 if sim < 0 or sim > 100:
213 if sim < 0 or sim > 100:
214 raise util.Abort(_('similarity must be between 0 and 100'))
214 raise util.Abort(_('similarity must be between 0 and 100'))
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
216
216
217 @command('^annotate|blame',
217 @command('^annotate|blame',
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
219 ('', 'follow', None,
219 ('', 'follow', None,
220 _('follow copies/renames and list the filename (DEPRECATED)')),
220 _('follow copies/renames and list the filename (DEPRECATED)')),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
222 ('a', 'text', None, _('treat all files as text')),
222 ('a', 'text', None, _('treat all files as text')),
223 ('u', 'user', None, _('list the author (long with -v)')),
223 ('u', 'user', None, _('list the author (long with -v)')),
224 ('f', 'file', None, _('list the filename')),
224 ('f', 'file', None, _('list the filename')),
225 ('d', 'date', None, _('list the date (short with -q)')),
225 ('d', 'date', None, _('list the date (short with -q)')),
226 ('n', 'number', None, _('list the revision number (default)')),
226 ('n', 'number', None, _('list the revision number (default)')),
227 ('c', 'changeset', None, _('list the changeset')),
227 ('c', 'changeset', None, _('list the changeset')),
228 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ('l', 'line-number', None, _('show line number at the first appearance'))
229 ] + diffwsopts + walkopts,
229 ] + diffwsopts + walkopts,
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
231 def annotate(ui, repo, *pats, **opts):
231 def annotate(ui, repo, *pats, **opts):
232 """show changeset information by line for each file
232 """show changeset information by line for each file
233
233
234 List changes in files, showing the revision id responsible for
234 List changes in files, showing the revision id responsible for
235 each line
235 each line
236
236
237 This command is useful for discovering when a change was made and
237 This command is useful for discovering when a change was made and
238 by whom.
238 by whom.
239
239
240 Without the -a/--text option, annotate will avoid processing files
240 Without the -a/--text option, annotate will avoid processing files
241 it detects as binary. With -a, annotate will annotate the file
241 it detects as binary. With -a, annotate will annotate the file
242 anyway, although the results will probably be neither useful
242 anyway, although the results will probably be neither useful
243 nor desirable.
243 nor desirable.
244
244
245 Returns 0 on success.
245 Returns 0 on success.
246 """
246 """
247 if opts.get('follow'):
247 if opts.get('follow'):
248 # --follow is deprecated and now just an alias for -f/--file
248 # --follow is deprecated and now just an alias for -f/--file
249 # to mimic the behavior of Mercurial before version 1.5
249 # to mimic the behavior of Mercurial before version 1.5
250 opts['file'] = True
250 opts['file'] = True
251
251
252 datefunc = ui.quiet and util.shortdate or util.datestr
252 datefunc = ui.quiet and util.shortdate or util.datestr
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
254
254
255 if not pats:
255 if not pats:
256 raise util.Abort(_('at least one filename or pattern is required'))
256 raise util.Abort(_('at least one filename or pattern is required'))
257
257
258 hexfn = ui.debugflag and hex or short
258 hexfn = ui.debugflag and hex or short
259
259
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
261 ('number', ' ', lambda x: str(x[0].rev())),
261 ('number', ' ', lambda x: str(x[0].rev())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
263 ('date', ' ', getdate),
263 ('date', ' ', getdate),
264 ('file', ' ', lambda x: x[0].path()),
264 ('file', ' ', lambda x: x[0].path()),
265 ('line_number', ':', lambda x: str(x[1])),
265 ('line_number', ':', lambda x: str(x[1])),
266 ]
266 ]
267
267
268 if (not opts.get('user') and not opts.get('changeset')
268 if (not opts.get('user') and not opts.get('changeset')
269 and not opts.get('date') and not opts.get('file')):
269 and not opts.get('date') and not opts.get('file')):
270 opts['number'] = True
270 opts['number'] = True
271
271
272 linenumber = opts.get('line_number') is not None
272 linenumber = opts.get('line_number') is not None
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
275
275
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
278
278
279 def bad(x, y):
279 def bad(x, y):
280 raise util.Abort("%s: %s" % (x, y))
280 raise util.Abort("%s: %s" % (x, y))
281
281
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 m = scmutil.match(ctx, pats, opts)
283 m = scmutil.match(ctx, pats, opts)
284 m.bad = bad
284 m.bad = bad
285 follow = not opts.get('no_follow')
285 follow = not opts.get('no_follow')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
287 for abs in ctx.walk(m):
287 for abs in ctx.walk(m):
288 fctx = ctx[abs]
288 fctx = ctx[abs]
289 if not opts.get('text') and util.binary(fctx.data()):
289 if not opts.get('text') and util.binary(fctx.data()):
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
291 continue
291 continue
292
292
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
294 diffopts=diffopts)
294 diffopts=diffopts)
295 pieces = []
295 pieces = []
296
296
297 for f, sep in funcmap:
297 for f, sep in funcmap:
298 l = [f(n) for n, dummy in lines]
298 l = [f(n) for n, dummy in lines]
299 if l:
299 if l:
300 sized = [(x, encoding.colwidth(x)) for x in l]
300 sized = [(x, encoding.colwidth(x)) for x in l]
301 ml = max([w for x, w in sized])
301 ml = max([w for x, w in sized])
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
303 for x, w in sized])
303 for x, w in sized])
304
304
305 if pieces:
305 if pieces:
306 for p, l in zip(zip(*pieces), lines):
306 for p, l in zip(zip(*pieces), lines):
307 ui.write("%s: %s" % ("".join(p), l[1]))
307 ui.write("%s: %s" % ("".join(p), l[1]))
308
308
309 if lines and not lines[-1][1].endswith('\n'):
309 if lines and not lines[-1][1].endswith('\n'):
310 ui.write('\n')
310 ui.write('\n')
311
311
312 @command('archive',
312 @command('archive',
313 [('', 'no-decode', None, _('do not pass files through decoders')),
313 [('', 'no-decode', None, _('do not pass files through decoders')),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
315 _('PREFIX')),
315 _('PREFIX')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
318 ] + subrepoopts + walkopts,
318 ] + subrepoopts + walkopts,
319 _('[OPTION]... DEST'))
319 _('[OPTION]... DEST'))
320 def archive(ui, repo, dest, **opts):
320 def archive(ui, repo, dest, **opts):
321 '''create an unversioned archive of a repository revision
321 '''create an unversioned archive of a repository revision
322
322
323 By default, the revision used is the parent of the working
323 By default, the revision used is the parent of the working
324 directory; use -r/--rev to specify a different revision.
324 directory; use -r/--rev to specify a different revision.
325
325
326 The archive type is automatically detected based on file
326 The archive type is automatically detected based on file
327 extension (or override using -t/--type).
327 extension (or override using -t/--type).
328
328
329 .. container:: verbose
329 .. container:: verbose
330
330
331 Examples:
331 Examples:
332
332
333 - create a zip file containing the 1.0 release::
333 - create a zip file containing the 1.0 release::
334
334
335 hg archive -r 1.0 project-1.0.zip
335 hg archive -r 1.0 project-1.0.zip
336
336
337 - create a tarball excluding .hg files::
337 - create a tarball excluding .hg files::
338
338
339 hg archive project.tar.gz -X ".hg*"
339 hg archive project.tar.gz -X ".hg*"
340
340
341 Valid types are:
341 Valid types are:
342
342
343 :``files``: a directory full of files (default)
343 :``files``: a directory full of files (default)
344 :``tar``: tar archive, uncompressed
344 :``tar``: tar archive, uncompressed
345 :``tbz2``: tar archive, compressed using bzip2
345 :``tbz2``: tar archive, compressed using bzip2
346 :``tgz``: tar archive, compressed using gzip
346 :``tgz``: tar archive, compressed using gzip
347 :``uzip``: zip archive, uncompressed
347 :``uzip``: zip archive, uncompressed
348 :``zip``: zip archive, compressed using deflate
348 :``zip``: zip archive, compressed using deflate
349
349
350 The exact name of the destination archive or directory is given
350 The exact name of the destination archive or directory is given
351 using a format string; see :hg:`help export` for details.
351 using a format string; see :hg:`help export` for details.
352
352
353 Each member added to an archive file has a directory prefix
353 Each member added to an archive file has a directory prefix
354 prepended. Use -p/--prefix to specify a format string for the
354 prepended. Use -p/--prefix to specify a format string for the
355 prefix. The default is the basename of the archive, with suffixes
355 prefix. The default is the basename of the archive, with suffixes
356 removed.
356 removed.
357
357
358 Returns 0 on success.
358 Returns 0 on success.
359 '''
359 '''
360
360
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
362 if not ctx:
362 if not ctx:
363 raise util.Abort(_('no working directory: please specify a revision'))
363 raise util.Abort(_('no working directory: please specify a revision'))
364 node = ctx.node()
364 node = ctx.node()
365 dest = cmdutil.makefilename(repo, dest, node)
365 dest = cmdutil.makefilename(repo, dest, node)
366 if os.path.realpath(dest) == repo.root:
366 if os.path.realpath(dest) == repo.root:
367 raise util.Abort(_('repository root cannot be destination'))
367 raise util.Abort(_('repository root cannot be destination'))
368
368
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
370 prefix = opts.get('prefix')
370 prefix = opts.get('prefix')
371
371
372 if dest == '-':
372 if dest == '-':
373 if kind == 'files':
373 if kind == 'files':
374 raise util.Abort(_('cannot archive plain files to stdout'))
374 raise util.Abort(_('cannot archive plain files to stdout'))
375 dest = cmdutil.makefileobj(repo, dest)
375 dest = cmdutil.makefileobj(repo, dest)
376 if not prefix:
376 if not prefix:
377 prefix = os.path.basename(repo.root) + '-%h'
377 prefix = os.path.basename(repo.root) + '-%h'
378
378
379 prefix = cmdutil.makefilename(repo, prefix, node)
379 prefix = cmdutil.makefilename(repo, prefix, node)
380 matchfn = scmutil.match(ctx, [], opts)
380 matchfn = scmutil.match(ctx, [], opts)
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
382 matchfn, prefix, subrepos=opts.get('subrepos'))
382 matchfn, prefix, subrepos=opts.get('subrepos'))
383
383
384 @command('backout',
384 @command('backout',
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
386 ('', 'parent', '',
386 ('', 'parent', '',
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
390 _('[OPTION]... [-r] REV'))
390 _('[OPTION]... [-r] REV'))
391 def backout(ui, repo, node=None, rev=None, **opts):
391 def backout(ui, repo, node=None, rev=None, **opts):
392 '''reverse effect of earlier changeset
392 '''reverse effect of earlier changeset
393
393
394 Prepare a new changeset with the effect of REV undone in the
394 Prepare a new changeset with the effect of REV undone in the
395 current working directory.
395 current working directory.
396
396
397 If REV is the parent of the working directory, then this new changeset
397 If REV is the parent of the working directory, then this new changeset
398 is committed automatically. Otherwise, hg needs to merge the
398 is committed automatically. Otherwise, hg needs to merge the
399 changes and the merged result is left uncommitted.
399 changes and the merged result is left uncommitted.
400
400
401 .. note::
401 .. note::
402
402
403 backout cannot be used to fix either an unwanted or
403 backout cannot be used to fix either an unwanted or
404 incorrect merge.
404 incorrect merge.
405
405
406 .. container:: verbose
406 .. container:: verbose
407
407
408 By default, the pending changeset will have one parent,
408 By default, the pending changeset will have one parent,
409 maintaining a linear history. With --merge, the pending
409 maintaining a linear history. With --merge, the pending
410 changeset will instead have two parents: the old parent of the
410 changeset will instead have two parents: the old parent of the
411 working directory and a new child of REV that simply undoes REV.
411 working directory and a new child of REV that simply undoes REV.
412
412
413 Before version 1.7, the behavior without --merge was equivalent
413 Before version 1.7, the behavior without --merge was equivalent
414 to specifying --merge followed by :hg:`update --clean .` to
414 to specifying --merge followed by :hg:`update --clean .` to
415 cancel the merge and leave the child of REV as a head to be
415 cancel the merge and leave the child of REV as a head to be
416 merged separately.
416 merged separately.
417
417
418 See :hg:`help dates` for a list of formats valid for -d/--date.
418 See :hg:`help dates` for a list of formats valid for -d/--date.
419
419
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
421 files.
421 files.
422 '''
422 '''
423 if rev and node:
423 if rev and node:
424 raise util.Abort(_("please specify just one revision"))
424 raise util.Abort(_("please specify just one revision"))
425
425
426 if not rev:
426 if not rev:
427 rev = node
427 rev = node
428
428
429 if not rev:
429 if not rev:
430 raise util.Abort(_("please specify a revision to backout"))
430 raise util.Abort(_("please specify a revision to backout"))
431
431
432 date = opts.get('date')
432 date = opts.get('date')
433 if date:
433 if date:
434 opts['date'] = util.parsedate(date)
434 opts['date'] = util.parsedate(date)
435
435
436 cmdutil.checkunfinished(repo)
436 cmdutil.checkunfinished(repo)
437 cmdutil.bailifchanged(repo)
437 cmdutil.bailifchanged(repo)
438 node = scmutil.revsingle(repo, rev).node()
438 node = scmutil.revsingle(repo, rev).node()
439
439
440 op1, op2 = repo.dirstate.parents()
440 op1, op2 = repo.dirstate.parents()
441 if node not in repo.changelog.commonancestorsheads(op1, node):
441 if node not in repo.changelog.commonancestorsheads(op1, node):
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
443
443
444 p1, p2 = repo.changelog.parents(node)
444 p1, p2 = repo.changelog.parents(node)
445 if p1 == nullid:
445 if p1 == nullid:
446 raise util.Abort(_('cannot backout a change with no parents'))
446 raise util.Abort(_('cannot backout a change with no parents'))
447 if p2 != nullid:
447 if p2 != nullid:
448 if not opts.get('parent'):
448 if not opts.get('parent'):
449 raise util.Abort(_('cannot backout a merge changeset'))
449 raise util.Abort(_('cannot backout a merge changeset'))
450 p = repo.lookup(opts['parent'])
450 p = repo.lookup(opts['parent'])
451 if p not in (p1, p2):
451 if p not in (p1, p2):
452 raise util.Abort(_('%s is not a parent of %s') %
452 raise util.Abort(_('%s is not a parent of %s') %
453 (short(p), short(node)))
453 (short(p), short(node)))
454 parent = p
454 parent = p
455 else:
455 else:
456 if opts.get('parent'):
456 if opts.get('parent'):
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
458 parent = p1
458 parent = p1
459
459
460 # the backout should appear on the same branch
460 # the backout should appear on the same branch
461 wlock = repo.wlock()
461 wlock = repo.wlock()
462 try:
462 try:
463 branch = repo.dirstate.branch()
463 branch = repo.dirstate.branch()
464 bheads = repo.branchheads(branch)
464 bheads = repo.branchheads(branch)
465 rctx = scmutil.revsingle(repo, hex(parent))
465 rctx = scmutil.revsingle(repo, hex(parent))
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
469 'backout')
469 'backout')
470 stats = mergemod.update(repo, parent, True, True, False,
470 stats = mergemod.update(repo, parent, True, True, False,
471 node, False)
471 node, False)
472 repo.setparents(op1, op2)
472 repo.setparents(op1, op2)
473 hg._showstats(repo, stats)
473 hg._showstats(repo, stats)
474 if stats[3]:
474 if stats[3]:
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
476 "file merges\n"))
476 "file merges\n"))
477 else:
477 else:
478 msg = _("changeset %s backed out, "
478 msg = _("changeset %s backed out, "
479 "don't forget to commit.\n")
479 "don't forget to commit.\n")
480 ui.status(msg % short(node))
480 ui.status(msg % short(node))
481 return stats[3] > 0
481 return stats[3] > 0
482 finally:
482 finally:
483 ui.setconfig('ui', 'forcemerge', '', '')
483 ui.setconfig('ui', 'forcemerge', '', '')
484 else:
484 else:
485 hg.clean(repo, node, show_stats=False)
485 hg.clean(repo, node, show_stats=False)
486 repo.dirstate.setbranch(branch)
486 repo.dirstate.setbranch(branch)
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
488
488
489
489
490 e = cmdutil.commiteditor
490 e = cmdutil.commiteditor
491 if not opts['message'] and not opts['logfile']:
491 if not opts['message'] and not opts['logfile']:
492 # we don't translate commit messages
492 # we don't translate commit messages
493 opts['message'] = "Backed out changeset %s" % short(node)
493 opts['message'] = "Backed out changeset %s" % short(node)
494 e = cmdutil.commitforceeditor
494 e = cmdutil.commitforceeditor
495
495
496 def commitfunc(ui, repo, message, match, opts):
496 def commitfunc(ui, repo, message, match, opts):
497 return repo.commit(message, opts.get('user'), opts.get('date'),
497 return repo.commit(message, opts.get('user'), opts.get('date'),
498 match, editor=e)
498 match, editor=e)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
500 if not newnode:
500 if not newnode:
501 ui.status(_("nothing changed\n"))
501 ui.status(_("nothing changed\n"))
502 return 1
502 return 1
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
504
504
505 def nice(node):
505 def nice(node):
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
507 ui.status(_('changeset %s backs out changeset %s\n') %
507 ui.status(_('changeset %s backs out changeset %s\n') %
508 (nice(repo.changelog.tip()), nice(node)))
508 (nice(repo.changelog.tip()), nice(node)))
509 if opts.get('merge') and op1 != node:
509 if opts.get('merge') and op1 != node:
510 hg.clean(repo, op1, show_stats=False)
510 hg.clean(repo, op1, show_stats=False)
511 ui.status(_('merging with changeset %s\n')
511 ui.status(_('merging with changeset %s\n')
512 % nice(repo.changelog.tip()))
512 % nice(repo.changelog.tip()))
513 try:
513 try:
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
515 'backout')
515 'backout')
516 return hg.merge(repo, hex(repo.changelog.tip()))
516 return hg.merge(repo, hex(repo.changelog.tip()))
517 finally:
517 finally:
518 ui.setconfig('ui', 'forcemerge', '', '')
518 ui.setconfig('ui', 'forcemerge', '', '')
519 finally:
519 finally:
520 wlock.release()
520 wlock.release()
521 return 0
521 return 0
522
522
523 @command('bisect',
523 @command('bisect',
524 [('r', 'reset', False, _('reset bisect state')),
524 [('r', 'reset', False, _('reset bisect state')),
525 ('g', 'good', False, _('mark changeset good')),
525 ('g', 'good', False, _('mark changeset good')),
526 ('b', 'bad', False, _('mark changeset bad')),
526 ('b', 'bad', False, _('mark changeset bad')),
527 ('s', 'skip', False, _('skip testing changeset')),
527 ('s', 'skip', False, _('skip testing changeset')),
528 ('e', 'extend', False, _('extend the bisect range')),
528 ('e', 'extend', False, _('extend the bisect range')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
530 ('U', 'noupdate', False, _('do not update to target'))],
530 ('U', 'noupdate', False, _('do not update to target'))],
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
532 def bisect(ui, repo, rev=None, extra=None, command=None,
532 def bisect(ui, repo, rev=None, extra=None, command=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
534 noupdate=None):
534 noupdate=None):
535 """subdivision search of changesets
535 """subdivision search of changesets
536
536
537 This command helps to find changesets which introduce problems. To
537 This command helps to find changesets which introduce problems. To
538 use, mark the earliest changeset you know exhibits the problem as
538 use, mark the earliest changeset you know exhibits the problem as
539 bad, then mark the latest changeset which is free from the problem
539 bad, then mark the latest changeset which is free from the problem
540 as good. Bisect will update your working directory to a revision
540 as good. Bisect will update your working directory to a revision
541 for testing (unless the -U/--noupdate option is specified). Once
541 for testing (unless the -U/--noupdate option is specified). Once
542 you have performed tests, mark the working directory as good or
542 you have performed tests, mark the working directory as good or
543 bad, and bisect will either update to another candidate changeset
543 bad, and bisect will either update to another candidate changeset
544 or announce that it has found the bad revision.
544 or announce that it has found the bad revision.
545
545
546 As a shortcut, you can also use the revision argument to mark a
546 As a shortcut, you can also use the revision argument to mark a
547 revision as good or bad without checking it out first.
547 revision as good or bad without checking it out first.
548
548
549 If you supply a command, it will be used for automatic bisection.
549 If you supply a command, it will be used for automatic bisection.
550 The environment variable HG_NODE will contain the ID of the
550 The environment variable HG_NODE will contain the ID of the
551 changeset being tested. The exit status of the command will be
551 changeset being tested. The exit status of the command will be
552 used to mark revisions as good or bad: status 0 means good, 125
552 used to mark revisions as good or bad: status 0 means good, 125
553 means to skip the revision, 127 (command not found) will abort the
553 means to skip the revision, 127 (command not found) will abort the
554 bisection, and any other non-zero exit status means the revision
554 bisection, and any other non-zero exit status means the revision
555 is bad.
555 is bad.
556
556
557 .. container:: verbose
557 .. container:: verbose
558
558
559 Some examples:
559 Some examples:
560
560
561 - start a bisection with known bad revision 34, and good revision 12::
561 - start a bisection with known bad revision 34, and good revision 12::
562
562
563 hg bisect --bad 34
563 hg bisect --bad 34
564 hg bisect --good 12
564 hg bisect --good 12
565
565
566 - advance the current bisection by marking current revision as good or
566 - advance the current bisection by marking current revision as good or
567 bad::
567 bad::
568
568
569 hg bisect --good
569 hg bisect --good
570 hg bisect --bad
570 hg bisect --bad
571
571
572 - mark the current revision, or a known revision, to be skipped (e.g. if
572 - mark the current revision, or a known revision, to be skipped (e.g. if
573 that revision is not usable because of another issue)::
573 that revision is not usable because of another issue)::
574
574
575 hg bisect --skip
575 hg bisect --skip
576 hg bisect --skip 23
576 hg bisect --skip 23
577
577
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
579
579
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
581
581
582 - forget the current bisection::
582 - forget the current bisection::
583
583
584 hg bisect --reset
584 hg bisect --reset
585
585
586 - use 'make && make tests' to automatically find the first broken
586 - use 'make && make tests' to automatically find the first broken
587 revision::
587 revision::
588
588
589 hg bisect --reset
589 hg bisect --reset
590 hg bisect --bad 34
590 hg bisect --bad 34
591 hg bisect --good 12
591 hg bisect --good 12
592 hg bisect --command "make && make tests"
592 hg bisect --command "make && make tests"
593
593
594 - see all changesets whose states are already known in the current
594 - see all changesets whose states are already known in the current
595 bisection::
595 bisection::
596
596
597 hg log -r "bisect(pruned)"
597 hg log -r "bisect(pruned)"
598
598
599 - see the changeset currently being bisected (especially useful
599 - see the changeset currently being bisected (especially useful
600 if running with -U/--noupdate)::
600 if running with -U/--noupdate)::
601
601
602 hg log -r "bisect(current)"
602 hg log -r "bisect(current)"
603
603
604 - see all changesets that took part in the current bisection::
604 - see all changesets that took part in the current bisection::
605
605
606 hg log -r "bisect(range)"
606 hg log -r "bisect(range)"
607
607
608 - you can even get a nice graph::
608 - you can even get a nice graph::
609
609
610 hg log --graph -r "bisect(range)"
610 hg log --graph -r "bisect(range)"
611
611
612 See :hg:`help revsets` for more about the `bisect()` keyword.
612 See :hg:`help revsets` for more about the `bisect()` keyword.
613
613
614 Returns 0 on success.
614 Returns 0 on success.
615 """
615 """
616 def extendbisectrange(nodes, good):
616 def extendbisectrange(nodes, good):
617 # bisect is incomplete when it ends on a merge node and
617 # bisect is incomplete when it ends on a merge node and
618 # one of the parent was not checked.
618 # one of the parent was not checked.
619 parents = repo[nodes[0]].parents()
619 parents = repo[nodes[0]].parents()
620 if len(parents) > 1:
620 if len(parents) > 1:
621 side = good and state['bad'] or state['good']
621 side = good and state['bad'] or state['good']
622 num = len(set(i.node() for i in parents) & set(side))
622 num = len(set(i.node() for i in parents) & set(side))
623 if num == 1:
623 if num == 1:
624 return parents[0].ancestor(parents[1])
624 return parents[0].ancestor(parents[1])
625 return None
625 return None
626
626
627 def print_result(nodes, good):
627 def print_result(nodes, good):
628 displayer = cmdutil.show_changeset(ui, repo, {})
628 displayer = cmdutil.show_changeset(ui, repo, {})
629 if len(nodes) == 1:
629 if len(nodes) == 1:
630 # narrowed it down to a single revision
630 # narrowed it down to a single revision
631 if good:
631 if good:
632 ui.write(_("The first good revision is:\n"))
632 ui.write(_("The first good revision is:\n"))
633 else:
633 else:
634 ui.write(_("The first bad revision is:\n"))
634 ui.write(_("The first bad revision is:\n"))
635 displayer.show(repo[nodes[0]])
635 displayer.show(repo[nodes[0]])
636 extendnode = extendbisectrange(nodes, good)
636 extendnode = extendbisectrange(nodes, good)
637 if extendnode is not None:
637 if extendnode is not None:
638 ui.write(_('Not all ancestors of this changeset have been'
638 ui.write(_('Not all ancestors of this changeset have been'
639 ' checked.\nUse bisect --extend to continue the '
639 ' checked.\nUse bisect --extend to continue the '
640 'bisection from\nthe common ancestor, %s.\n')
640 'bisection from\nthe common ancestor, %s.\n')
641 % extendnode)
641 % extendnode)
642 else:
642 else:
643 # multiple possible revisions
643 # multiple possible revisions
644 if good:
644 if good:
645 ui.write(_("Due to skipped revisions, the first "
645 ui.write(_("Due to skipped revisions, the first "
646 "good revision could be any of:\n"))
646 "good revision could be any of:\n"))
647 else:
647 else:
648 ui.write(_("Due to skipped revisions, the first "
648 ui.write(_("Due to skipped revisions, the first "
649 "bad revision could be any of:\n"))
649 "bad revision could be any of:\n"))
650 for n in nodes:
650 for n in nodes:
651 displayer.show(repo[n])
651 displayer.show(repo[n])
652 displayer.close()
652 displayer.close()
653
653
654 def check_state(state, interactive=True):
654 def check_state(state, interactive=True):
655 if not state['good'] or not state['bad']:
655 if not state['good'] or not state['bad']:
656 if (good or bad or skip or reset) and interactive:
656 if (good or bad or skip or reset) and interactive:
657 return
657 return
658 if not state['good']:
658 if not state['good']:
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
660 else:
660 else:
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
662 return True
662 return True
663
663
664 # backward compatibility
664 # backward compatibility
665 if rev in "good bad reset init".split():
665 if rev in "good bad reset init".split():
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
667 cmd, rev, extra = rev, extra, None
667 cmd, rev, extra = rev, extra, None
668 if cmd == "good":
668 if cmd == "good":
669 good = True
669 good = True
670 elif cmd == "bad":
670 elif cmd == "bad":
671 bad = True
671 bad = True
672 else:
672 else:
673 reset = True
673 reset = True
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
675 raise util.Abort(_('incompatible arguments'))
675 raise util.Abort(_('incompatible arguments'))
676
676
677 cmdutil.checkunfinished(repo)
677 cmdutil.checkunfinished(repo)
678
678
679 if reset:
679 if reset:
680 p = repo.join("bisect.state")
680 p = repo.join("bisect.state")
681 if os.path.exists(p):
681 if os.path.exists(p):
682 os.unlink(p)
682 os.unlink(p)
683 return
683 return
684
684
685 state = hbisect.load_state(repo)
685 state = hbisect.load_state(repo)
686
686
687 if command:
687 if command:
688 changesets = 1
688 changesets = 1
689 if noupdate:
689 if noupdate:
690 try:
690 try:
691 node = state['current'][0]
691 node = state['current'][0]
692 except LookupError:
692 except LookupError:
693 raise util.Abort(_('current bisect revision is unknown - '
693 raise util.Abort(_('current bisect revision is unknown - '
694 'start a new bisect to fix'))
694 'start a new bisect to fix'))
695 else:
695 else:
696 node, p2 = repo.dirstate.parents()
696 node, p2 = repo.dirstate.parents()
697 if p2 != nullid:
697 if p2 != nullid:
698 raise util.Abort(_('current bisect revision is a merge'))
698 raise util.Abort(_('current bisect revision is a merge'))
699 try:
699 try:
700 while changesets:
700 while changesets:
701 # update state
701 # update state
702 state['current'] = [node]
702 state['current'] = [node]
703 hbisect.save_state(repo, state)
703 hbisect.save_state(repo, state)
704 status = util.system(command,
704 status = util.system(command,
705 environ={'HG_NODE': hex(node)},
705 environ={'HG_NODE': hex(node)},
706 out=ui.fout)
706 out=ui.fout)
707 if status == 125:
707 if status == 125:
708 transition = "skip"
708 transition = "skip"
709 elif status == 0:
709 elif status == 0:
710 transition = "good"
710 transition = "good"
711 # status < 0 means process was killed
711 # status < 0 means process was killed
712 elif status == 127:
712 elif status == 127:
713 raise util.Abort(_("failed to execute %s") % command)
713 raise util.Abort(_("failed to execute %s") % command)
714 elif status < 0:
714 elif status < 0:
715 raise util.Abort(_("%s killed") % command)
715 raise util.Abort(_("%s killed") % command)
716 else:
716 else:
717 transition = "bad"
717 transition = "bad"
718 ctx = scmutil.revsingle(repo, rev, node)
718 ctx = scmutil.revsingle(repo, rev, node)
719 rev = None # clear for future iterations
719 rev = None # clear for future iterations
720 state[transition].append(ctx.node())
720 state[transition].append(ctx.node())
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
722 check_state(state, interactive=False)
722 check_state(state, interactive=False)
723 # bisect
723 # bisect
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
725 # update to next check
725 # update to next check
726 node = nodes[0]
726 node = nodes[0]
727 if not noupdate:
727 if not noupdate:
728 cmdutil.bailifchanged(repo)
728 cmdutil.bailifchanged(repo)
729 hg.clean(repo, node, show_stats=False)
729 hg.clean(repo, node, show_stats=False)
730 finally:
730 finally:
731 state['current'] = [node]
731 state['current'] = [node]
732 hbisect.save_state(repo, state)
732 hbisect.save_state(repo, state)
733 print_result(nodes, bgood)
733 print_result(nodes, bgood)
734 return
734 return
735
735
736 # update state
736 # update state
737
737
738 if rev:
738 if rev:
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
740 else:
740 else:
741 nodes = [repo.lookup('.')]
741 nodes = [repo.lookup('.')]
742
742
743 if good or bad or skip:
743 if good or bad or skip:
744 if good:
744 if good:
745 state['good'] += nodes
745 state['good'] += nodes
746 elif bad:
746 elif bad:
747 state['bad'] += nodes
747 state['bad'] += nodes
748 elif skip:
748 elif skip:
749 state['skip'] += nodes
749 state['skip'] += nodes
750 hbisect.save_state(repo, state)
750 hbisect.save_state(repo, state)
751
751
752 if not check_state(state):
752 if not check_state(state):
753 return
753 return
754
754
755 # actually bisect
755 # actually bisect
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
757 if extend:
757 if extend:
758 if not changesets:
758 if not changesets:
759 extendnode = extendbisectrange(nodes, good)
759 extendnode = extendbisectrange(nodes, good)
760 if extendnode is not None:
760 if extendnode is not None:
761 ui.write(_("Extending search to changeset %d:%s\n")
761 ui.write(_("Extending search to changeset %d:%s\n")
762 % (extendnode.rev(), extendnode))
762 % (extendnode.rev(), extendnode))
763 state['current'] = [extendnode.node()]
763 state['current'] = [extendnode.node()]
764 hbisect.save_state(repo, state)
764 hbisect.save_state(repo, state)
765 if noupdate:
765 if noupdate:
766 return
766 return
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, extendnode.node())
768 return hg.clean(repo, extendnode.node())
769 raise util.Abort(_("nothing to extend"))
769 raise util.Abort(_("nothing to extend"))
770
770
771 if changesets == 0:
771 if changesets == 0:
772 print_result(nodes, good)
772 print_result(nodes, good)
773 else:
773 else:
774 assert len(nodes) == 1 # only a single node can be tested next
774 assert len(nodes) == 1 # only a single node can be tested next
775 node = nodes[0]
775 node = nodes[0]
776 # compute the approximate number of remaining tests
776 # compute the approximate number of remaining tests
777 tests, size = 0, 2
777 tests, size = 0, 2
778 while size <= changesets:
778 while size <= changesets:
779 tests, size = tests + 1, size * 2
779 tests, size = tests + 1, size * 2
780 rev = repo.changelog.rev(node)
780 rev = repo.changelog.rev(node)
781 ui.write(_("Testing changeset %d:%s "
781 ui.write(_("Testing changeset %d:%s "
782 "(%d changesets remaining, ~%d tests)\n")
782 "(%d changesets remaining, ~%d tests)\n")
783 % (rev, short(node), changesets, tests))
783 % (rev, short(node), changesets, tests))
784 state['current'] = [node]
784 state['current'] = [node]
785 hbisect.save_state(repo, state)
785 hbisect.save_state(repo, state)
786 if not noupdate:
786 if not noupdate:
787 cmdutil.bailifchanged(repo)
787 cmdutil.bailifchanged(repo)
788 return hg.clean(repo, node)
788 return hg.clean(repo, node)
789
789
790 @command('bookmarks|bookmark',
790 @command('bookmarks|bookmark',
791 [('f', 'force', False, _('force')),
791 [('f', 'force', False, _('force')),
792 ('r', 'rev', '', _('revision'), _('REV')),
792 ('r', 'rev', '', _('revision'), _('REV')),
793 ('d', 'delete', False, _('delete a given bookmark')),
793 ('d', 'delete', False, _('delete a given bookmark')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
797 def bookmark(ui, repo, *names, **opts):
797 def bookmark(ui, repo, *names, **opts):
798 '''track a line of development with movable markers
798 '''track a line of development with movable markers
799
799
800 Bookmarks are pointers to certain commits that move when committing.
800 Bookmarks are pointers to certain commits that move when committing.
801 Bookmarks are local. They can be renamed, copied and deleted. It is
801 Bookmarks are local. They can be renamed, copied and deleted. It is
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
803 :hg:`update NAME` to update to a given bookmark.
803 :hg:`update NAME` to update to a given bookmark.
804
804
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
806 directory's parent revision with the given name. If you specify
806 directory's parent revision with the given name. If you specify
807 a revision using -r REV (where REV may be an existing bookmark),
807 a revision using -r REV (where REV may be an existing bookmark),
808 the bookmark is assigned to that revision.
808 the bookmark is assigned to that revision.
809
809
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
811 push` and :hg:`help pull`). This requires both the local and remote
811 push` and :hg:`help pull`). This requires both the local and remote
812 repositories to support bookmarks. For versions prior to 1.8, this means
812 repositories to support bookmarks. For versions prior to 1.8, this means
813 the bookmarks extension must be enabled.
813 the bookmarks extension must be enabled.
814
814
815 If you set a bookmark called '@', new clones of the repository will
815 If you set a bookmark called '@', new clones of the repository will
816 have that revision checked out (and the bookmark made active) by
816 have that revision checked out (and the bookmark made active) by
817 default.
817 default.
818
818
819 With -i/--inactive, the new bookmark will not be made the active
819 With -i/--inactive, the new bookmark will not be made the active
820 bookmark. If -r/--rev is given, the new bookmark will not be made
820 bookmark. If -r/--rev is given, the new bookmark will not be made
821 active even if -i/--inactive is not given. If no NAME is given, the
821 active even if -i/--inactive is not given. If no NAME is given, the
822 current active bookmark will be marked inactive.
822 current active bookmark will be marked inactive.
823 '''
823 '''
824 force = opts.get('force')
824 force = opts.get('force')
825 rev = opts.get('rev')
825 rev = opts.get('rev')
826 delete = opts.get('delete')
826 delete = opts.get('delete')
827 rename = opts.get('rename')
827 rename = opts.get('rename')
828 inactive = opts.get('inactive')
828 inactive = opts.get('inactive')
829
829
830 def checkformat(mark):
830 def checkformat(mark):
831 mark = mark.strip()
831 mark = mark.strip()
832 if not mark:
832 if not mark:
833 raise util.Abort(_("bookmark names cannot consist entirely of "
833 raise util.Abort(_("bookmark names cannot consist entirely of "
834 "whitespace"))
834 "whitespace"))
835 scmutil.checknewlabel(repo, mark, 'bookmark')
835 scmutil.checknewlabel(repo, mark, 'bookmark')
836 return mark
836 return mark
837
837
838 def checkconflict(repo, mark, cur, force=False, target=None):
838 def checkconflict(repo, mark, cur, force=False, target=None):
839 if mark in marks and not force:
839 if mark in marks and not force:
840 if target:
840 if target:
841 if marks[mark] == target and target == cur:
841 if marks[mark] == target and target == cur:
842 # re-activating a bookmark
842 # re-activating a bookmark
843 return
843 return
844 anc = repo.changelog.ancestors([repo[target].rev()])
844 anc = repo.changelog.ancestors([repo[target].rev()])
845 bmctx = repo[marks[mark]]
845 bmctx = repo[marks[mark]]
846 divs = [repo[b].node() for b in marks
846 divs = [repo[b].node() for b in marks
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
848
848
849 # allow resolving a single divergent bookmark even if moving
849 # allow resolving a single divergent bookmark even if moving
850 # the bookmark across branches when a revision is specified
850 # the bookmark across branches when a revision is specified
851 # that contains a divergent bookmark
851 # that contains a divergent bookmark
852 if bmctx.rev() not in anc and target in divs:
852 if bmctx.rev() not in anc and target in divs:
853 bookmarks.deletedivergent(repo, [target], mark)
853 bookmarks.deletedivergent(repo, [target], mark)
854 return
854 return
855
855
856 deletefrom = [b for b in divs
856 deletefrom = [b for b in divs
857 if repo[b].rev() in anc or b == target]
857 if repo[b].rev() in anc or b == target]
858 bookmarks.deletedivergent(repo, deletefrom, mark)
858 bookmarks.deletedivergent(repo, deletefrom, mark)
859 if bookmarks.validdest(repo, bmctx, repo[target]):
859 if bookmarks.validdest(repo, bmctx, repo[target]):
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
861 (mark, short(bmctx.node())))
861 (mark, short(bmctx.node())))
862 return
862 return
863 raise util.Abort(_("bookmark '%s' already exists "
863 raise util.Abort(_("bookmark '%s' already exists "
864 "(use -f to force)") % mark)
864 "(use -f to force)") % mark)
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
866 and not force):
866 and not force):
867 raise util.Abort(
867 raise util.Abort(
868 _("a bookmark cannot have the name of an existing branch"))
868 _("a bookmark cannot have the name of an existing branch"))
869
869
870 if delete and rename:
870 if delete and rename:
871 raise util.Abort(_("--delete and --rename are incompatible"))
871 raise util.Abort(_("--delete and --rename are incompatible"))
872 if delete and rev:
872 if delete and rev:
873 raise util.Abort(_("--rev is incompatible with --delete"))
873 raise util.Abort(_("--rev is incompatible with --delete"))
874 if rename and rev:
874 if rename and rev:
875 raise util.Abort(_("--rev is incompatible with --rename"))
875 raise util.Abort(_("--rev is incompatible with --rename"))
876 if not names and (delete or rev):
876 if not names and (delete or rev):
877 raise util.Abort(_("bookmark name required"))
877 raise util.Abort(_("bookmark name required"))
878
878
879 if delete or rename or names or inactive:
879 if delete or rename or names or inactive:
880 wlock = repo.wlock()
880 wlock = repo.wlock()
881 try:
881 try:
882 cur = repo.changectx('.').node()
882 cur = repo.changectx('.').node()
883 marks = repo._bookmarks
883 marks = repo._bookmarks
884 if delete:
884 if delete:
885 for mark in names:
885 for mark in names:
886 if mark not in marks:
886 if mark not in marks:
887 raise util.Abort(_("bookmark '%s' does not exist") %
887 raise util.Abort(_("bookmark '%s' does not exist") %
888 mark)
888 mark)
889 if mark == repo._bookmarkcurrent:
889 if mark == repo._bookmarkcurrent:
890 bookmarks.unsetcurrent(repo)
890 bookmarks.unsetcurrent(repo)
891 del marks[mark]
891 del marks[mark]
892 marks.write()
892 marks.write()
893
893
894 elif rename:
894 elif rename:
895 if not names:
895 if not names:
896 raise util.Abort(_("new bookmark name required"))
896 raise util.Abort(_("new bookmark name required"))
897 elif len(names) > 1:
897 elif len(names) > 1:
898 raise util.Abort(_("only one new bookmark name allowed"))
898 raise util.Abort(_("only one new bookmark name allowed"))
899 mark = checkformat(names[0])
899 mark = checkformat(names[0])
900 if rename not in marks:
900 if rename not in marks:
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
902 checkconflict(repo, mark, cur, force)
902 checkconflict(repo, mark, cur, force)
903 marks[mark] = marks[rename]
903 marks[mark] = marks[rename]
904 if repo._bookmarkcurrent == rename and not inactive:
904 if repo._bookmarkcurrent == rename and not inactive:
905 bookmarks.setcurrent(repo, mark)
905 bookmarks.setcurrent(repo, mark)
906 del marks[rename]
906 del marks[rename]
907 marks.write()
907 marks.write()
908
908
909 elif names:
909 elif names:
910 newact = None
910 newact = None
911 for mark in names:
911 for mark in names:
912 mark = checkformat(mark)
912 mark = checkformat(mark)
913 if newact is None:
913 if newact is None:
914 newact = mark
914 newact = mark
915 if inactive and mark == repo._bookmarkcurrent:
915 if inactive and mark == repo._bookmarkcurrent:
916 bookmarks.unsetcurrent(repo)
916 bookmarks.unsetcurrent(repo)
917 return
917 return
918 tgt = cur
918 tgt = cur
919 if rev:
919 if rev:
920 tgt = scmutil.revsingle(repo, rev).node()
920 tgt = scmutil.revsingle(repo, rev).node()
921 checkconflict(repo, mark, cur, force, tgt)
921 checkconflict(repo, mark, cur, force, tgt)
922 marks[mark] = tgt
922 marks[mark] = tgt
923 if not inactive and cur == marks[newact] and not rev:
923 if not inactive and cur == marks[newact] and not rev:
924 bookmarks.setcurrent(repo, newact)
924 bookmarks.setcurrent(repo, newact)
925 elif cur != tgt and newact == repo._bookmarkcurrent:
925 elif cur != tgt and newact == repo._bookmarkcurrent:
926 bookmarks.unsetcurrent(repo)
926 bookmarks.unsetcurrent(repo)
927 marks.write()
927 marks.write()
928
928
929 elif inactive:
929 elif inactive:
930 if len(marks) == 0:
930 if len(marks) == 0:
931 ui.status(_("no bookmarks set\n"))
931 ui.status(_("no bookmarks set\n"))
932 elif not repo._bookmarkcurrent:
932 elif not repo._bookmarkcurrent:
933 ui.status(_("no active bookmark\n"))
933 ui.status(_("no active bookmark\n"))
934 else:
934 else:
935 bookmarks.unsetcurrent(repo)
935 bookmarks.unsetcurrent(repo)
936 finally:
936 finally:
937 wlock.release()
937 wlock.release()
938 else: # show bookmarks
938 else: # show bookmarks
939 hexfn = ui.debugflag and hex or short
939 hexfn = ui.debugflag and hex or short
940 marks = repo._bookmarks
940 marks = repo._bookmarks
941 if len(marks) == 0:
941 if len(marks) == 0:
942 ui.status(_("no bookmarks set\n"))
942 ui.status(_("no bookmarks set\n"))
943 else:
943 else:
944 for bmark, n in sorted(marks.iteritems()):
944 for bmark, n in sorted(marks.iteritems()):
945 current = repo._bookmarkcurrent
945 current = repo._bookmarkcurrent
946 if bmark == current:
946 if bmark == current:
947 prefix, label = '*', 'bookmarks.current'
947 prefix, label = '*', 'bookmarks.current'
948 else:
948 else:
949 prefix, label = ' ', ''
949 prefix, label = ' ', ''
950
950
951 if ui.quiet:
951 if ui.quiet:
952 ui.write("%s\n" % bmark, label=label)
952 ui.write("%s\n" % bmark, label=label)
953 else:
953 else:
954 pad = " " * (25 - encoding.colwidth(bmark))
954 pad = " " * (25 - encoding.colwidth(bmark))
955 ui.write(" %s %s%s %d:%s\n" % (
955 ui.write(" %s %s%s %d:%s\n" % (
956 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
956 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
957 label=label)
957 label=label)
958
958
959 @command('branch',
959 @command('branch',
960 [('f', 'force', None,
960 [('f', 'force', None,
961 _('set branch name even if it shadows an existing branch')),
961 _('set branch name even if it shadows an existing branch')),
962 ('C', 'clean', None, _('reset branch name to parent branch name'))],
962 ('C', 'clean', None, _('reset branch name to parent branch name'))],
963 _('[-fC] [NAME]'))
963 _('[-fC] [NAME]'))
964 def branch(ui, repo, label=None, **opts):
964 def branch(ui, repo, label=None, **opts):
965 """set or show the current branch name
965 """set or show the current branch name
966
966
967 .. note::
967 .. note::
968
968
969 Branch names are permanent and global. Use :hg:`bookmark` to create a
969 Branch names are permanent and global. Use :hg:`bookmark` to create a
970 light-weight bookmark instead. See :hg:`help glossary` for more
970 light-weight bookmark instead. See :hg:`help glossary` for more
971 information about named branches and bookmarks.
971 information about named branches and bookmarks.
972
972
973 With no argument, show the current branch name. With one argument,
973 With no argument, show the current branch name. With one argument,
974 set the working directory branch name (the branch will not exist
974 set the working directory branch name (the branch will not exist
975 in the repository until the next commit). Standard practice
975 in the repository until the next commit). Standard practice
976 recommends that primary development take place on the 'default'
976 recommends that primary development take place on the 'default'
977 branch.
977 branch.
978
978
979 Unless -f/--force is specified, branch will not let you set a
979 Unless -f/--force is specified, branch will not let you set a
980 branch name that already exists, even if it's inactive.
980 branch name that already exists, even if it's inactive.
981
981
982 Use -C/--clean to reset the working directory branch to that of
982 Use -C/--clean to reset the working directory branch to that of
983 the parent of the working directory, negating a previous branch
983 the parent of the working directory, negating a previous branch
984 change.
984 change.
985
985
986 Use the command :hg:`update` to switch to an existing branch. Use
986 Use the command :hg:`update` to switch to an existing branch. Use
987 :hg:`commit --close-branch` to mark this branch as closed.
987 :hg:`commit --close-branch` to mark this branch as closed.
988
988
989 Returns 0 on success.
989 Returns 0 on success.
990 """
990 """
991 if label:
991 if label:
992 label = label.strip()
992 label = label.strip()
993
993
994 if not opts.get('clean') and not label:
994 if not opts.get('clean') and not label:
995 ui.write("%s\n" % repo.dirstate.branch())
995 ui.write("%s\n" % repo.dirstate.branch())
996 return
996 return
997
997
998 wlock = repo.wlock()
998 wlock = repo.wlock()
999 try:
999 try:
1000 if opts.get('clean'):
1000 if opts.get('clean'):
1001 label = repo[None].p1().branch()
1001 label = repo[None].p1().branch()
1002 repo.dirstate.setbranch(label)
1002 repo.dirstate.setbranch(label)
1003 ui.status(_('reset working directory to branch %s\n') % label)
1003 ui.status(_('reset working directory to branch %s\n') % label)
1004 elif label:
1004 elif label:
1005 if not opts.get('force') and label in repo.branchmap():
1005 if not opts.get('force') and label in repo.branchmap():
1006 if label not in [p.branch() for p in repo.parents()]:
1006 if label not in [p.branch() for p in repo.parents()]:
1007 raise util.Abort(_('a branch of the same name already'
1007 raise util.Abort(_('a branch of the same name already'
1008 ' exists'),
1008 ' exists'),
1009 # i18n: "it" refers to an existing branch
1009 # i18n: "it" refers to an existing branch
1010 hint=_("use 'hg update' to switch to it"))
1010 hint=_("use 'hg update' to switch to it"))
1011 scmutil.checknewlabel(repo, label, 'branch')
1011 scmutil.checknewlabel(repo, label, 'branch')
1012 repo.dirstate.setbranch(label)
1012 repo.dirstate.setbranch(label)
1013 ui.status(_('marked working directory as branch %s\n') % label)
1013 ui.status(_('marked working directory as branch %s\n') % label)
1014 ui.status(_('(branches are permanent and global, '
1014 ui.status(_('(branches are permanent and global, '
1015 'did you want a bookmark?)\n'))
1015 'did you want a bookmark?)\n'))
1016 finally:
1016 finally:
1017 wlock.release()
1017 wlock.release()
1018
1018
1019 @command('branches',
1019 @command('branches',
1020 [('a', 'active', False, _('show only branches that have unmerged heads')),
1020 [('a', 'active', False, _('show only branches that have unmerged heads')),
1021 ('c', 'closed', False, _('show normal and closed branches'))],
1021 ('c', 'closed', False, _('show normal and closed branches'))],
1022 _('[-ac]'))
1022 _('[-ac]'))
1023 def branches(ui, repo, active=False, closed=False):
1023 def branches(ui, repo, active=False, closed=False):
1024 """list repository named branches
1024 """list repository named branches
1025
1025
1026 List the repository's named branches, indicating which ones are
1026 List the repository's named branches, indicating which ones are
1027 inactive. If -c/--closed is specified, also list branches which have
1027 inactive. If -c/--closed is specified, also list branches which have
1028 been marked closed (see :hg:`commit --close-branch`).
1028 been marked closed (see :hg:`commit --close-branch`).
1029
1029
1030 If -a/--active is specified, only show active branches. A branch
1030 If -a/--active is specified, only show active branches. A branch
1031 is considered active if it contains repository heads.
1031 is considered active if it contains repository heads.
1032
1032
1033 Use the command :hg:`update` to switch to an existing branch.
1033 Use the command :hg:`update` to switch to an existing branch.
1034
1034
1035 Returns 0.
1035 Returns 0.
1036 """
1036 """
1037
1037
1038 hexfunc = ui.debugflag and hex or short
1038 hexfunc = ui.debugflag and hex or short
1039
1039
1040 allheads = set(repo.heads())
1040 allheads = set(repo.heads())
1041 branches = []
1041 branches = []
1042 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1042 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1043 isactive = not isclosed and bool(set(heads) & allheads)
1043 isactive = not isclosed and bool(set(heads) & allheads)
1044 branches.append((tag, repo[tip], isactive, not isclosed))
1044 branches.append((tag, repo[tip], isactive, not isclosed))
1045 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1045 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1046 reverse=True)
1046 reverse=True)
1047
1047
1048 for tag, ctx, isactive, isopen in branches:
1048 for tag, ctx, isactive, isopen in branches:
1049 if (not active) or isactive:
1049 if (not active) or isactive:
1050 if isactive:
1050 if isactive:
1051 label = 'branches.active'
1051 label = 'branches.active'
1052 notice = ''
1052 notice = ''
1053 elif not isopen:
1053 elif not isopen:
1054 if not closed:
1054 if not closed:
1055 continue
1055 continue
1056 label = 'branches.closed'
1056 label = 'branches.closed'
1057 notice = _(' (closed)')
1057 notice = _(' (closed)')
1058 else:
1058 else:
1059 label = 'branches.inactive'
1059 label = 'branches.inactive'
1060 notice = _(' (inactive)')
1060 notice = _(' (inactive)')
1061 if tag == repo.dirstate.branch():
1061 if tag == repo.dirstate.branch():
1062 label = 'branches.current'
1062 label = 'branches.current'
1063 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1063 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1064 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1064 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1065 'log.changeset changeset.%s' % ctx.phasestr())
1065 'log.changeset changeset.%s' % ctx.phasestr())
1066 labeledtag = ui.label(tag, label)
1066 labeledtag = ui.label(tag, label)
1067 if ui.quiet:
1067 if ui.quiet:
1068 ui.write("%s\n" % labeledtag)
1068 ui.write("%s\n" % labeledtag)
1069 else:
1069 else:
1070 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1070 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1071
1071
1072 @command('bundle',
1072 @command('bundle',
1073 [('f', 'force', None, _('run even when the destination is unrelated')),
1073 [('f', 'force', None, _('run even when the destination is unrelated')),
1074 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1074 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1075 _('REV')),
1075 _('REV')),
1076 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1076 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1077 _('BRANCH')),
1077 _('BRANCH')),
1078 ('', 'base', [],
1078 ('', 'base', [],
1079 _('a base changeset assumed to be available at the destination'),
1079 _('a base changeset assumed to be available at the destination'),
1080 _('REV')),
1080 _('REV')),
1081 ('a', 'all', None, _('bundle all changesets in the repository')),
1081 ('a', 'all', None, _('bundle all changesets in the repository')),
1082 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1082 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1083 ] + remoteopts,
1083 ] + remoteopts,
1084 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1084 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1085 def bundle(ui, repo, fname, dest=None, **opts):
1085 def bundle(ui, repo, fname, dest=None, **opts):
1086 """create a changegroup file
1086 """create a changegroup file
1087
1087
1088 Generate a compressed changegroup file collecting changesets not
1088 Generate a compressed changegroup file collecting changesets not
1089 known to be in another repository.
1089 known to be in another repository.
1090
1090
1091 If you omit the destination repository, then hg assumes the
1091 If you omit the destination repository, then hg assumes the
1092 destination will have all the nodes you specify with --base
1092 destination will have all the nodes you specify with --base
1093 parameters. To create a bundle containing all changesets, use
1093 parameters. To create a bundle containing all changesets, use
1094 -a/--all (or --base null).
1094 -a/--all (or --base null).
1095
1095
1096 You can change compression method with the -t/--type option.
1096 You can change compression method with the -t/--type option.
1097 The available compression methods are: none, bzip2, and
1097 The available compression methods are: none, bzip2, and
1098 gzip (by default, bundles are compressed using bzip2).
1098 gzip (by default, bundles are compressed using bzip2).
1099
1099
1100 The bundle file can then be transferred using conventional means
1100 The bundle file can then be transferred using conventional means
1101 and applied to another repository with the unbundle or pull
1101 and applied to another repository with the unbundle or pull
1102 command. This is useful when direct push and pull are not
1102 command. This is useful when direct push and pull are not
1103 available or when exporting an entire repository is undesirable.
1103 available or when exporting an entire repository is undesirable.
1104
1104
1105 Applying bundles preserves all changeset contents including
1105 Applying bundles preserves all changeset contents including
1106 permissions, copy/rename information, and revision history.
1106 permissions, copy/rename information, and revision history.
1107
1107
1108 Returns 0 on success, 1 if no changes found.
1108 Returns 0 on success, 1 if no changes found.
1109 """
1109 """
1110 revs = None
1110 revs = None
1111 if 'rev' in opts:
1111 if 'rev' in opts:
1112 revs = scmutil.revrange(repo, opts['rev'])
1112 revs = scmutil.revrange(repo, opts['rev'])
1113
1113
1114 bundletype = opts.get('type', 'bzip2').lower()
1114 bundletype = opts.get('type', 'bzip2').lower()
1115 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1115 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1116 bundletype = btypes.get(bundletype)
1116 bundletype = btypes.get(bundletype)
1117 if bundletype not in changegroup.bundletypes:
1117 if bundletype not in changegroup.bundletypes:
1118 raise util.Abort(_('unknown bundle type specified with --type'))
1118 raise util.Abort(_('unknown bundle type specified with --type'))
1119
1119
1120 if opts.get('all'):
1120 if opts.get('all'):
1121 base = ['null']
1121 base = ['null']
1122 else:
1122 else:
1123 base = scmutil.revrange(repo, opts.get('base'))
1123 base = scmutil.revrange(repo, opts.get('base'))
1124 # TODO: get desired bundlecaps from command line.
1124 # TODO: get desired bundlecaps from command line.
1125 bundlecaps = None
1125 bundlecaps = None
1126 if base:
1126 if base:
1127 if dest:
1127 if dest:
1128 raise util.Abort(_("--base is incompatible with specifying "
1128 raise util.Abort(_("--base is incompatible with specifying "
1129 "a destination"))
1129 "a destination"))
1130 common = [repo.lookup(rev) for rev in base]
1130 common = [repo.lookup(rev) for rev in base]
1131 heads = revs and map(repo.lookup, revs) or revs
1131 heads = revs and map(repo.lookup, revs) or revs
1132 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1132 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1133 bundlecaps=bundlecaps)
1133 bundlecaps=bundlecaps)
1134 outgoing = None
1134 outgoing = None
1135 else:
1135 else:
1136 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1136 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1137 dest, branches = hg.parseurl(dest, opts.get('branch'))
1137 dest, branches = hg.parseurl(dest, opts.get('branch'))
1138 other = hg.peer(repo, opts, dest)
1138 other = hg.peer(repo, opts, dest)
1139 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1139 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1140 heads = revs and map(repo.lookup, revs) or revs
1140 heads = revs and map(repo.lookup, revs) or revs
1141 outgoing = discovery.findcommonoutgoing(repo, other,
1141 outgoing = discovery.findcommonoutgoing(repo, other,
1142 onlyheads=heads,
1142 onlyheads=heads,
1143 force=opts.get('force'),
1143 force=opts.get('force'),
1144 portable=True)
1144 portable=True)
1145 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1145 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1146 if not cg:
1146 if not cg:
1147 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1147 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1148 return 1
1148 return 1
1149
1149
1150 changegroup.writebundle(cg, fname, bundletype)
1150 changegroup.writebundle(cg, fname, bundletype)
1151
1151
1152 @command('cat',
1152 @command('cat',
1153 [('o', 'output', '',
1153 [('o', 'output', '',
1154 _('print output to file with formatted name'), _('FORMAT')),
1154 _('print output to file with formatted name'), _('FORMAT')),
1155 ('r', 'rev', '', _('print the given revision'), _('REV')),
1155 ('r', 'rev', '', _('print the given revision'), _('REV')),
1156 ('', 'decode', None, _('apply any matching decode filter')),
1156 ('', 'decode', None, _('apply any matching decode filter')),
1157 ] + walkopts,
1157 ] + walkopts,
1158 _('[OPTION]... FILE...'))
1158 _('[OPTION]... FILE...'))
1159 def cat(ui, repo, file1, *pats, **opts):
1159 def cat(ui, repo, file1, *pats, **opts):
1160 """output the current or given revision of files
1160 """output the current or given revision of files
1161
1161
1162 Print the specified files as they were at the given revision. If
1162 Print the specified files as they were at the given revision. If
1163 no revision is given, the parent of the working directory is used.
1163 no revision is given, the parent of the working directory is used.
1164
1164
1165 Output may be to a file, in which case the name of the file is
1165 Output may be to a file, in which case the name of the file is
1166 given using a format string. The formatting rules as follows:
1166 given using a format string. The formatting rules as follows:
1167
1167
1168 :``%%``: literal "%" character
1168 :``%%``: literal "%" character
1169 :``%s``: basename of file being printed
1169 :``%s``: basename of file being printed
1170 :``%d``: dirname of file being printed, or '.' if in repository root
1170 :``%d``: dirname of file being printed, or '.' if in repository root
1171 :``%p``: root-relative path name of file being printed
1171 :``%p``: root-relative path name of file being printed
1172 :``%H``: changeset hash (40 hexadecimal digits)
1172 :``%H``: changeset hash (40 hexadecimal digits)
1173 :``%R``: changeset revision number
1173 :``%R``: changeset revision number
1174 :``%h``: short-form changeset hash (12 hexadecimal digits)
1174 :``%h``: short-form changeset hash (12 hexadecimal digits)
1175 :``%r``: zero-padded changeset revision number
1175 :``%r``: zero-padded changeset revision number
1176 :``%b``: basename of the exporting repository
1176 :``%b``: basename of the exporting repository
1177
1177
1178 Returns 0 on success.
1178 Returns 0 on success.
1179 """
1179 """
1180 ctx = scmutil.revsingle(repo, opts.get('rev'))
1180 ctx = scmutil.revsingle(repo, opts.get('rev'))
1181 m = scmutil.match(ctx, (file1,) + pats, opts)
1181 m = scmutil.match(ctx, (file1,) + pats, opts)
1182
1182
1183 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1183 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1184
1184
1185 @command('^clone',
1185 @command('^clone',
1186 [('U', 'noupdate', None,
1186 [('U', 'noupdate', None,
1187 _('the clone will include an empty working copy (only a repository)')),
1187 _('the clone will include an empty working copy (only a repository)')),
1188 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1188 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1189 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1189 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1190 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1190 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1191 ('', 'pull', None, _('use pull protocol to copy metadata')),
1191 ('', 'pull', None, _('use pull protocol to copy metadata')),
1192 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1192 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1193 ] + remoteopts,
1193 ] + remoteopts,
1194 _('[OPTION]... SOURCE [DEST]'))
1194 _('[OPTION]... SOURCE [DEST]'))
1195 def clone(ui, source, dest=None, **opts):
1195 def clone(ui, source, dest=None, **opts):
1196 """make a copy of an existing repository
1196 """make a copy of an existing repository
1197
1197
1198 Create a copy of an existing repository in a new directory.
1198 Create a copy of an existing repository in a new directory.
1199
1199
1200 If no destination directory name is specified, it defaults to the
1200 If no destination directory name is specified, it defaults to the
1201 basename of the source.
1201 basename of the source.
1202
1202
1203 The location of the source is added to the new repository's
1203 The location of the source is added to the new repository's
1204 ``.hg/hgrc`` file, as the default to be used for future pulls.
1204 ``.hg/hgrc`` file, as the default to be used for future pulls.
1205
1205
1206 Only local paths and ``ssh://`` URLs are supported as
1206 Only local paths and ``ssh://`` URLs are supported as
1207 destinations. For ``ssh://`` destinations, no working directory or
1207 destinations. For ``ssh://`` destinations, no working directory or
1208 ``.hg/hgrc`` will be created on the remote side.
1208 ``.hg/hgrc`` will be created on the remote side.
1209
1209
1210 To pull only a subset of changesets, specify one or more revisions
1210 To pull only a subset of changesets, specify one or more revisions
1211 identifiers with -r/--rev or branches with -b/--branch. The
1211 identifiers with -r/--rev or branches with -b/--branch. The
1212 resulting clone will contain only the specified changesets and
1212 resulting clone will contain only the specified changesets and
1213 their ancestors. These options (or 'clone src#rev dest') imply
1213 their ancestors. These options (or 'clone src#rev dest') imply
1214 --pull, even for local source repositories. Note that specifying a
1214 --pull, even for local source repositories. Note that specifying a
1215 tag will include the tagged changeset but not the changeset
1215 tag will include the tagged changeset but not the changeset
1216 containing the tag.
1216 containing the tag.
1217
1217
1218 If the source repository has a bookmark called '@' set, that
1218 If the source repository has a bookmark called '@' set, that
1219 revision will be checked out in the new repository by default.
1219 revision will be checked out in the new repository by default.
1220
1220
1221 To check out a particular version, use -u/--update, or
1221 To check out a particular version, use -u/--update, or
1222 -U/--noupdate to create a clone with no working directory.
1222 -U/--noupdate to create a clone with no working directory.
1223
1223
1224 .. container:: verbose
1224 .. container:: verbose
1225
1225
1226 For efficiency, hardlinks are used for cloning whenever the
1226 For efficiency, hardlinks are used for cloning whenever the
1227 source and destination are on the same filesystem (note this
1227 source and destination are on the same filesystem (note this
1228 applies only to the repository data, not to the working
1228 applies only to the repository data, not to the working
1229 directory). Some filesystems, such as AFS, implement hardlinking
1229 directory). Some filesystems, such as AFS, implement hardlinking
1230 incorrectly, but do not report errors. In these cases, use the
1230 incorrectly, but do not report errors. In these cases, use the
1231 --pull option to avoid hardlinking.
1231 --pull option to avoid hardlinking.
1232
1232
1233 In some cases, you can clone repositories and the working
1233 In some cases, you can clone repositories and the working
1234 directory using full hardlinks with ::
1234 directory using full hardlinks with ::
1235
1235
1236 $ cp -al REPO REPOCLONE
1236 $ cp -al REPO REPOCLONE
1237
1237
1238 This is the fastest way to clone, but it is not always safe. The
1238 This is the fastest way to clone, but it is not always safe. The
1239 operation is not atomic (making sure REPO is not modified during
1239 operation is not atomic (making sure REPO is not modified during
1240 the operation is up to you) and you have to make sure your
1240 the operation is up to you) and you have to make sure your
1241 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1241 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1242 so). Also, this is not compatible with certain extensions that
1242 so). Also, this is not compatible with certain extensions that
1243 place their metadata under the .hg directory, such as mq.
1243 place their metadata under the .hg directory, such as mq.
1244
1244
1245 Mercurial will update the working directory to the first applicable
1245 Mercurial will update the working directory to the first applicable
1246 revision from this list:
1246 revision from this list:
1247
1247
1248 a) null if -U or the source repository has no changesets
1248 a) null if -U or the source repository has no changesets
1249 b) if -u . and the source repository is local, the first parent of
1249 b) if -u . and the source repository is local, the first parent of
1250 the source repository's working directory
1250 the source repository's working directory
1251 c) the changeset specified with -u (if a branch name, this means the
1251 c) the changeset specified with -u (if a branch name, this means the
1252 latest head of that branch)
1252 latest head of that branch)
1253 d) the changeset specified with -r
1253 d) the changeset specified with -r
1254 e) the tipmost head specified with -b
1254 e) the tipmost head specified with -b
1255 f) the tipmost head specified with the url#branch source syntax
1255 f) the tipmost head specified with the url#branch source syntax
1256 g) the revision marked with the '@' bookmark, if present
1256 g) the revision marked with the '@' bookmark, if present
1257 h) the tipmost head of the default branch
1257 h) the tipmost head of the default branch
1258 i) tip
1258 i) tip
1259
1259
1260 Examples:
1260 Examples:
1261
1261
1262 - clone a remote repository to a new directory named hg/::
1262 - clone a remote repository to a new directory named hg/::
1263
1263
1264 hg clone http://selenic.com/hg
1264 hg clone http://selenic.com/hg
1265
1265
1266 - create a lightweight local clone::
1266 - create a lightweight local clone::
1267
1267
1268 hg clone project/ project-feature/
1268 hg clone project/ project-feature/
1269
1269
1270 - clone from an absolute path on an ssh server (note double-slash)::
1270 - clone from an absolute path on an ssh server (note double-slash)::
1271
1271
1272 hg clone ssh://user@server//home/projects/alpha/
1272 hg clone ssh://user@server//home/projects/alpha/
1273
1273
1274 - do a high-speed clone over a LAN while checking out a
1274 - do a high-speed clone over a LAN while checking out a
1275 specified version::
1275 specified version::
1276
1276
1277 hg clone --uncompressed http://server/repo -u 1.5
1277 hg clone --uncompressed http://server/repo -u 1.5
1278
1278
1279 - create a repository without changesets after a particular revision::
1279 - create a repository without changesets after a particular revision::
1280
1280
1281 hg clone -r 04e544 experimental/ good/
1281 hg clone -r 04e544 experimental/ good/
1282
1282
1283 - clone (and track) a particular named branch::
1283 - clone (and track) a particular named branch::
1284
1284
1285 hg clone http://selenic.com/hg#stable
1285 hg clone http://selenic.com/hg#stable
1286
1286
1287 See :hg:`help urls` for details on specifying URLs.
1287 See :hg:`help urls` for details on specifying URLs.
1288
1288
1289 Returns 0 on success.
1289 Returns 0 on success.
1290 """
1290 """
1291 if opts.get('noupdate') and opts.get('updaterev'):
1291 if opts.get('noupdate') and opts.get('updaterev'):
1292 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1292 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1293
1293
1294 r = hg.clone(ui, opts, source, dest,
1294 r = hg.clone(ui, opts, source, dest,
1295 pull=opts.get('pull'),
1295 pull=opts.get('pull'),
1296 stream=opts.get('uncompressed'),
1296 stream=opts.get('uncompressed'),
1297 rev=opts.get('rev'),
1297 rev=opts.get('rev'),
1298 update=opts.get('updaterev') or not opts.get('noupdate'),
1298 update=opts.get('updaterev') or not opts.get('noupdate'),
1299 branch=opts.get('branch'))
1299 branch=opts.get('branch'))
1300
1300
1301 return r is None
1301 return r is None
1302
1302
1303 @command('^commit|ci',
1303 @command('^commit|ci',
1304 [('A', 'addremove', None,
1304 [('A', 'addremove', None,
1305 _('mark new/missing files as added/removed before committing')),
1305 _('mark new/missing files as added/removed before committing')),
1306 ('', 'close-branch', None,
1306 ('', 'close-branch', None,
1307 _('mark a branch as closed, hiding it from the branch list')),
1307 _('mark a branch as closed, hiding it from the branch list')),
1308 ('', 'amend', None, _('amend the parent of the working dir')),
1308 ('', 'amend', None, _('amend the parent of the working dir')),
1309 ('s', 'secret', None, _('use the secret phase for committing')),
1309 ('s', 'secret', None, _('use the secret phase for committing')),
1310 ('e', 'edit', None,
1310 ('e', 'edit', None,
1311 _('further edit commit message already specified')),
1311 _('further edit commit message already specified')),
1312 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1312 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1313 _('[OPTION]... [FILE]...'))
1313 _('[OPTION]... [FILE]...'))
1314 def commit(ui, repo, *pats, **opts):
1314 def commit(ui, repo, *pats, **opts):
1315 """commit the specified files or all outstanding changes
1315 """commit the specified files or all outstanding changes
1316
1316
1317 Commit changes to the given files into the repository. Unlike a
1317 Commit changes to the given files into the repository. Unlike a
1318 centralized SCM, this operation is a local operation. See
1318 centralized SCM, this operation is a local operation. See
1319 :hg:`push` for a way to actively distribute your changes.
1319 :hg:`push` for a way to actively distribute your changes.
1320
1320
1321 If a list of files is omitted, all changes reported by :hg:`status`
1321 If a list of files is omitted, all changes reported by :hg:`status`
1322 will be committed.
1322 will be committed.
1323
1323
1324 If you are committing the result of a merge, do not provide any
1324 If you are committing the result of a merge, do not provide any
1325 filenames or -I/-X filters.
1325 filenames or -I/-X filters.
1326
1326
1327 If no commit message is specified, Mercurial starts your
1327 If no commit message is specified, Mercurial starts your
1328 configured editor where you can enter a message. In case your
1328 configured editor where you can enter a message. In case your
1329 commit fails, you will find a backup of your message in
1329 commit fails, you will find a backup of your message in
1330 ``.hg/last-message.txt``.
1330 ``.hg/last-message.txt``.
1331
1331
1332 The --amend flag can be used to amend the parent of the
1332 The --amend flag can be used to amend the parent of the
1333 working directory with a new commit that contains the changes
1333 working directory with a new commit that contains the changes
1334 in the parent in addition to those currently reported by :hg:`status`,
1334 in the parent in addition to those currently reported by :hg:`status`,
1335 if there are any. The old commit is stored in a backup bundle in
1335 if there are any. The old commit is stored in a backup bundle in
1336 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1336 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1337 on how to restore it).
1337 on how to restore it).
1338
1338
1339 Message, user and date are taken from the amended commit unless
1339 Message, user and date are taken from the amended commit unless
1340 specified. When a message isn't specified on the command line,
1340 specified. When a message isn't specified on the command line,
1341 the editor will open with the message of the amended commit.
1341 the editor will open with the message of the amended commit.
1342
1342
1343 It is not possible to amend public changesets (see :hg:`help phases`)
1343 It is not possible to amend public changesets (see :hg:`help phases`)
1344 or changesets that have children.
1344 or changesets that have children.
1345
1345
1346 See :hg:`help dates` for a list of formats valid for -d/--date.
1346 See :hg:`help dates` for a list of formats valid for -d/--date.
1347
1347
1348 Returns 0 on success, 1 if nothing changed.
1348 Returns 0 on success, 1 if nothing changed.
1349 """
1349 """
1350 forceeditor = opts.get('edit')
1350 forceeditor = opts.get('edit')
1351
1351
1352 if opts.get('subrepos'):
1352 if opts.get('subrepos'):
1353 if opts.get('amend'):
1353 if opts.get('amend'):
1354 raise util.Abort(_('cannot amend with --subrepos'))
1354 raise util.Abort(_('cannot amend with --subrepos'))
1355 # Let --subrepos on the command line override config setting.
1355 # Let --subrepos on the command line override config setting.
1356 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1356 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1357
1357
1358 # Save this for restoring it later
1358 # Save this for restoring it later
1359 oldcommitphase = ui.config('phases', 'new-commit')
1359 oldcommitphase = ui.config('phases', 'new-commit')
1360
1360
1361 cmdutil.checkunfinished(repo, commit=True)
1361 cmdutil.checkunfinished(repo, commit=True)
1362
1362
1363 branch = repo[None].branch()
1363 branch = repo[None].branch()
1364 bheads = repo.branchheads(branch)
1364 bheads = repo.branchheads(branch)
1365
1365
1366 extra = {}
1366 extra = {}
1367 if opts.get('close_branch'):
1367 if opts.get('close_branch'):
1368 extra['close'] = 1
1368 extra['close'] = 1
1369
1369
1370 if not bheads:
1370 if not bheads:
1371 raise util.Abort(_('can only close branch heads'))
1371 raise util.Abort(_('can only close branch heads'))
1372 elif opts.get('amend'):
1372 elif opts.get('amend'):
1373 if repo.parents()[0].p1().branch() != branch and \
1373 if repo.parents()[0].p1().branch() != branch and \
1374 repo.parents()[0].p2().branch() != branch:
1374 repo.parents()[0].p2().branch() != branch:
1375 raise util.Abort(_('can only close branch heads'))
1375 raise util.Abort(_('can only close branch heads'))
1376
1376
1377 if opts.get('amend'):
1377 if opts.get('amend'):
1378 if ui.configbool('ui', 'commitsubrepos'):
1378 if ui.configbool('ui', 'commitsubrepos'):
1379 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1379 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1380
1380
1381 old = repo['.']
1381 old = repo['.']
1382 if old.phase() == phases.public:
1382 if old.phase() == phases.public:
1383 raise util.Abort(_('cannot amend public changesets'))
1383 raise util.Abort(_('cannot amend public changesets'))
1384 if len(repo[None].parents()) > 1:
1384 if len(repo[None].parents()) > 1:
1385 raise util.Abort(_('cannot amend while merging'))
1385 raise util.Abort(_('cannot amend while merging'))
1386 if (not obsolete._enabled) and old.children():
1386 if (not obsolete._enabled) and old.children():
1387 raise util.Abort(_('cannot amend changeset with children'))
1387 raise util.Abort(_('cannot amend changeset with children'))
1388
1388
1389 # commitfunc is used only for temporary amend commit by cmdutil.amend
1389 # commitfunc is used only for temporary amend commit by cmdutil.amend
1390 def commitfunc(ui, repo, message, match, opts):
1390 def commitfunc(ui, repo, message, match, opts):
1391 return repo.commit(message,
1391 return repo.commit(message,
1392 opts.get('user') or old.user(),
1392 opts.get('user') or old.user(),
1393 opts.get('date') or old.date(),
1393 opts.get('date') or old.date(),
1394 match,
1394 match,
1395 extra=extra)
1395 extra=extra)
1396
1396
1397 current = repo._bookmarkcurrent
1397 current = repo._bookmarkcurrent
1398 marks = old.bookmarks()
1398 marks = old.bookmarks()
1399 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1399 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1400 if node == old.node():
1400 if node == old.node():
1401 ui.status(_("nothing changed\n"))
1401 ui.status(_("nothing changed\n"))
1402 return 1
1402 return 1
1403 elif marks:
1403 elif marks:
1404 ui.debug('moving bookmarks %r from %s to %s\n' %
1404 ui.debug('moving bookmarks %r from %s to %s\n' %
1405 (marks, old.hex(), hex(node)))
1405 (marks, old.hex(), hex(node)))
1406 newmarks = repo._bookmarks
1406 newmarks = repo._bookmarks
1407 for bm in marks:
1407 for bm in marks:
1408 newmarks[bm] = node
1408 newmarks[bm] = node
1409 if bm == current:
1409 if bm == current:
1410 bookmarks.setcurrent(repo, bm)
1410 bookmarks.setcurrent(repo, bm)
1411 newmarks.write()
1411 newmarks.write()
1412 else:
1412 else:
1413 e = cmdutil.commiteditor
1413 e = cmdutil.commiteditor
1414 if forceeditor:
1414 if forceeditor:
1415 e = cmdutil.commitforceeditor
1415 e = cmdutil.commitforceeditor
1416
1416
1417 def commitfunc(ui, repo, message, match, opts):
1417 def commitfunc(ui, repo, message, match, opts):
1418 try:
1418 try:
1419 if opts.get('secret'):
1419 if opts.get('secret'):
1420 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1420 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1421 # Propagate to subrepos
1421 # Propagate to subrepos
1422 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1422 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1423 'commit')
1423 'commit')
1424
1424
1425 return repo.commit(message, opts.get('user'), opts.get('date'),
1425 return repo.commit(message, opts.get('user'), opts.get('date'),
1426 match, editor=e, extra=extra)
1426 match, editor=e, extra=extra)
1427 finally:
1427 finally:
1428 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1428 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1429 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1429 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1430 'commit')
1430 'commit')
1431
1431
1432
1432
1433 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1433 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1434
1434
1435 if not node:
1435 if not node:
1436 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1436 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1437 if stat[3]:
1437 if stat[3]:
1438 ui.status(_("nothing changed (%d missing files, see "
1438 ui.status(_("nothing changed (%d missing files, see "
1439 "'hg status')\n") % len(stat[3]))
1439 "'hg status')\n") % len(stat[3]))
1440 else:
1440 else:
1441 ui.status(_("nothing changed\n"))
1441 ui.status(_("nothing changed\n"))
1442 return 1
1442 return 1
1443
1443
1444 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1444 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1445
1445
1446 @command('config|showconfig|debugconfig',
1446 @command('config|showconfig|debugconfig',
1447 [('u', 'untrusted', None, _('show untrusted configuration options')),
1447 [('u', 'untrusted', None, _('show untrusted configuration options')),
1448 ('e', 'edit', None, _('edit user config')),
1448 ('e', 'edit', None, _('edit user config')),
1449 ('l', 'local', None, _('edit repository config')),
1449 ('l', 'local', None, _('edit repository config')),
1450 ('g', 'global', None, _('edit global config'))],
1450 ('g', 'global', None, _('edit global config'))],
1451 _('[-u] [NAME]...'))
1451 _('[-u] [NAME]...'))
1452 def config(ui, repo, *values, **opts):
1452 def config(ui, repo, *values, **opts):
1453 """show combined config settings from all hgrc files
1453 """show combined config settings from all hgrc files
1454
1454
1455 With no arguments, print names and values of all config items.
1455 With no arguments, print names and values of all config items.
1456
1456
1457 With one argument of the form section.name, print just the value
1457 With one argument of the form section.name, print just the value
1458 of that config item.
1458 of that config item.
1459
1459
1460 With multiple arguments, print names and values of all config
1460 With multiple arguments, print names and values of all config
1461 items with matching section names.
1461 items with matching section names.
1462
1462
1463 With --edit, start an editor on the user-level config file. With
1463 With --edit, start an editor on the user-level config file. With
1464 --global, edit the system-wide config file. With --local, edit the
1464 --global, edit the system-wide config file. With --local, edit the
1465 repository-level config file.
1465 repository-level config file.
1466
1466
1467 With --debug, the source (filename and line number) is printed
1467 With --debug, the source (filename and line number) is printed
1468 for each config item.
1468 for each config item.
1469
1469
1470 See :hg:`help config` for more information about config files.
1470 See :hg:`help config` for more information about config files.
1471
1471
1472 Returns 0 on success.
1472 Returns 0 on success.
1473
1473
1474 """
1474 """
1475
1475
1476 if opts.get('edit') or opts.get('local') or opts.get('global'):
1476 if opts.get('edit') or opts.get('local') or opts.get('global'):
1477 if opts.get('local') and opts.get('global'):
1477 if opts.get('local') and opts.get('global'):
1478 raise util.Abort(_("can't use --local and --global together"))
1478 raise util.Abort(_("can't use --local and --global together"))
1479
1479
1480 if opts.get('local'):
1480 if opts.get('local'):
1481 if not repo:
1481 if not repo:
1482 raise util.Abort(_("can't use --local outside a repository"))
1482 raise util.Abort(_("can't use --local outside a repository"))
1483 paths = [repo.join('hgrc')]
1483 paths = [repo.join('hgrc')]
1484 elif opts.get('global'):
1484 elif opts.get('global'):
1485 paths = scmutil.systemrcpath()
1485 paths = scmutil.systemrcpath()
1486 else:
1486 else:
1487 paths = scmutil.userrcpath()
1487 paths = scmutil.userrcpath()
1488
1488
1489 for f in paths:
1489 for f in paths:
1490 if os.path.exists(f):
1490 if os.path.exists(f):
1491 break
1491 break
1492 else:
1492 else:
1493 f = paths[0]
1493 f = paths[0]
1494 fp = open(f, "w")
1494 fp = open(f, "w")
1495 fp.write(
1495 fp.write(
1496 '# example config (see "hg help config" for more info)\n'
1496 '# example config (see "hg help config" for more info)\n'
1497 '\n'
1497 '\n'
1498 '[ui]\n'
1498 '[ui]\n'
1499 '# name and email, e.g.\n'
1499 '# name and email, e.g.\n'
1500 '# username = Jane Doe <jdoe@example.com>\n'
1500 '# username = Jane Doe <jdoe@example.com>\n'
1501 'username =\n'
1501 'username =\n'
1502 '\n'
1502 '\n'
1503 '[extensions]\n'
1503 '[extensions]\n'
1504 '# uncomment these lines to enable some popular extensions\n'
1504 '# uncomment these lines to enable some popular extensions\n'
1505 '# (see "hg help extensions" for more info)\n'
1505 '# (see "hg help extensions" for more info)\n'
1506 '# pager =\n'
1506 '# pager =\n'
1507 '# progress =\n'
1507 '# progress =\n'
1508 '# color =\n')
1508 '# color =\n')
1509 fp.close()
1509 fp.close()
1510
1510
1511 editor = ui.geteditor()
1511 editor = ui.geteditor()
1512 util.system("%s \"%s\"" % (editor, f),
1512 util.system("%s \"%s\"" % (editor, f),
1513 onerr=util.Abort, errprefix=_("edit failed"),
1513 onerr=util.Abort, errprefix=_("edit failed"),
1514 out=ui.fout)
1514 out=ui.fout)
1515 return
1515 return
1516
1516
1517 for f in scmutil.rcpath():
1517 for f in scmutil.rcpath():
1518 ui.debug('read config from: %s\n' % f)
1518 ui.debug('read config from: %s\n' % f)
1519 untrusted = bool(opts.get('untrusted'))
1519 untrusted = bool(opts.get('untrusted'))
1520 if values:
1520 if values:
1521 sections = [v for v in values if '.' not in v]
1521 sections = [v for v in values if '.' not in v]
1522 items = [v for v in values if '.' in v]
1522 items = [v for v in values if '.' in v]
1523 if len(items) > 1 or items and sections:
1523 if len(items) > 1 or items and sections:
1524 raise util.Abort(_('only one config item permitted'))
1524 raise util.Abort(_('only one config item permitted'))
1525 for section, name, value in ui.walkconfig(untrusted=untrusted):
1525 for section, name, value in ui.walkconfig(untrusted=untrusted):
1526 value = str(value).replace('\n', '\\n')
1526 value = str(value).replace('\n', '\\n')
1527 sectname = section + '.' + name
1527 sectname = section + '.' + name
1528 if values:
1528 if values:
1529 for v in values:
1529 for v in values:
1530 if v == section:
1530 if v == section:
1531 ui.debug('%s: ' %
1531 ui.debug('%s: ' %
1532 ui.configsource(section, name, untrusted))
1532 ui.configsource(section, name, untrusted))
1533 ui.write('%s=%s\n' % (sectname, value))
1533 ui.write('%s=%s\n' % (sectname, value))
1534 elif v == sectname:
1534 elif v == sectname:
1535 ui.debug('%s: ' %
1535 ui.debug('%s: ' %
1536 ui.configsource(section, name, untrusted))
1536 ui.configsource(section, name, untrusted))
1537 ui.write(value, '\n')
1537 ui.write(value, '\n')
1538 else:
1538 else:
1539 ui.debug('%s: ' %
1539 ui.debug('%s: ' %
1540 ui.configsource(section, name, untrusted))
1540 ui.configsource(section, name, untrusted))
1541 ui.write('%s=%s\n' % (sectname, value))
1541 ui.write('%s=%s\n' % (sectname, value))
1542
1542
1543 @command('copy|cp',
1543 @command('copy|cp',
1544 [('A', 'after', None, _('record a copy that has already occurred')),
1544 [('A', 'after', None, _('record a copy that has already occurred')),
1545 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1545 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1546 ] + walkopts + dryrunopts,
1546 ] + walkopts + dryrunopts,
1547 _('[OPTION]... [SOURCE]... DEST'))
1547 _('[OPTION]... [SOURCE]... DEST'))
1548 def copy(ui, repo, *pats, **opts):
1548 def copy(ui, repo, *pats, **opts):
1549 """mark files as copied for the next commit
1549 """mark files as copied for the next commit
1550
1550
1551 Mark dest as having copies of source files. If dest is a
1551 Mark dest as having copies of source files. If dest is a
1552 directory, copies are put in that directory. If dest is a file,
1552 directory, copies are put in that directory. If dest is a file,
1553 the source must be a single file.
1553 the source must be a single file.
1554
1554
1555 By default, this command copies the contents of files as they
1555 By default, this command copies the contents of files as they
1556 exist in the working directory. If invoked with -A/--after, the
1556 exist in the working directory. If invoked with -A/--after, the
1557 operation is recorded, but no copying is performed.
1557 operation is recorded, but no copying is performed.
1558
1558
1559 This command takes effect with the next commit. To undo a copy
1559 This command takes effect with the next commit. To undo a copy
1560 before that, see :hg:`revert`.
1560 before that, see :hg:`revert`.
1561
1561
1562 Returns 0 on success, 1 if errors are encountered.
1562 Returns 0 on success, 1 if errors are encountered.
1563 """
1563 """
1564 wlock = repo.wlock(False)
1564 wlock = repo.wlock(False)
1565 try:
1565 try:
1566 return cmdutil.copy(ui, repo, pats, opts)
1566 return cmdutil.copy(ui, repo, pats, opts)
1567 finally:
1567 finally:
1568 wlock.release()
1568 wlock.release()
1569
1569
1570 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1570 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1571 def debugancestor(ui, repo, *args):
1571 def debugancestor(ui, repo, *args):
1572 """find the ancestor revision of two revisions in a given index"""
1572 """find the ancestor revision of two revisions in a given index"""
1573 if len(args) == 3:
1573 if len(args) == 3:
1574 index, rev1, rev2 = args
1574 index, rev1, rev2 = args
1575 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1575 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1576 lookup = r.lookup
1576 lookup = r.lookup
1577 elif len(args) == 2:
1577 elif len(args) == 2:
1578 if not repo:
1578 if not repo:
1579 raise util.Abort(_("there is no Mercurial repository here "
1579 raise util.Abort(_("there is no Mercurial repository here "
1580 "(.hg not found)"))
1580 "(.hg not found)"))
1581 rev1, rev2 = args
1581 rev1, rev2 = args
1582 r = repo.changelog
1582 r = repo.changelog
1583 lookup = repo.lookup
1583 lookup = repo.lookup
1584 else:
1584 else:
1585 raise util.Abort(_('either two or three arguments required'))
1585 raise util.Abort(_('either two or three arguments required'))
1586 a = r.ancestor(lookup(rev1), lookup(rev2))
1586 a = r.ancestor(lookup(rev1), lookup(rev2))
1587 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1587 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1588
1588
1589 @command('debugbuilddag',
1589 @command('debugbuilddag',
1590 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1590 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1591 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1591 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1592 ('n', 'new-file', None, _('add new file at each rev'))],
1592 ('n', 'new-file', None, _('add new file at each rev'))],
1593 _('[OPTION]... [TEXT]'))
1593 _('[OPTION]... [TEXT]'))
1594 def debugbuilddag(ui, repo, text=None,
1594 def debugbuilddag(ui, repo, text=None,
1595 mergeable_file=False,
1595 mergeable_file=False,
1596 overwritten_file=False,
1596 overwritten_file=False,
1597 new_file=False):
1597 new_file=False):
1598 """builds a repo with a given DAG from scratch in the current empty repo
1598 """builds a repo with a given DAG from scratch in the current empty repo
1599
1599
1600 The description of the DAG is read from stdin if not given on the
1600 The description of the DAG is read from stdin if not given on the
1601 command line.
1601 command line.
1602
1602
1603 Elements:
1603 Elements:
1604
1604
1605 - "+n" is a linear run of n nodes based on the current default parent
1605 - "+n" is a linear run of n nodes based on the current default parent
1606 - "." is a single node based on the current default parent
1606 - "." is a single node based on the current default parent
1607 - "$" resets the default parent to null (implied at the start);
1607 - "$" resets the default parent to null (implied at the start);
1608 otherwise the default parent is always the last node created
1608 otherwise the default parent is always the last node created
1609 - "<p" sets the default parent to the backref p
1609 - "<p" sets the default parent to the backref p
1610 - "*p" is a fork at parent p, which is a backref
1610 - "*p" is a fork at parent p, which is a backref
1611 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1611 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1612 - "/p2" is a merge of the preceding node and p2
1612 - "/p2" is a merge of the preceding node and p2
1613 - ":tag" defines a local tag for the preceding node
1613 - ":tag" defines a local tag for the preceding node
1614 - "@branch" sets the named branch for subsequent nodes
1614 - "@branch" sets the named branch for subsequent nodes
1615 - "#...\\n" is a comment up to the end of the line
1615 - "#...\\n" is a comment up to the end of the line
1616
1616
1617 Whitespace between the above elements is ignored.
1617 Whitespace between the above elements is ignored.
1618
1618
1619 A backref is either
1619 A backref is either
1620
1620
1621 - a number n, which references the node curr-n, where curr is the current
1621 - a number n, which references the node curr-n, where curr is the current
1622 node, or
1622 node, or
1623 - the name of a local tag you placed earlier using ":tag", or
1623 - the name of a local tag you placed earlier using ":tag", or
1624 - empty to denote the default parent.
1624 - empty to denote the default parent.
1625
1625
1626 All string valued-elements are either strictly alphanumeric, or must
1626 All string valued-elements are either strictly alphanumeric, or must
1627 be enclosed in double quotes ("..."), with "\\" as escape character.
1627 be enclosed in double quotes ("..."), with "\\" as escape character.
1628 """
1628 """
1629
1629
1630 if text is None:
1630 if text is None:
1631 ui.status(_("reading DAG from stdin\n"))
1631 ui.status(_("reading DAG from stdin\n"))
1632 text = ui.fin.read()
1632 text = ui.fin.read()
1633
1633
1634 cl = repo.changelog
1634 cl = repo.changelog
1635 if len(cl) > 0:
1635 if len(cl) > 0:
1636 raise util.Abort(_('repository is not empty'))
1636 raise util.Abort(_('repository is not empty'))
1637
1637
1638 # determine number of revs in DAG
1638 # determine number of revs in DAG
1639 total = 0
1639 total = 0
1640 for type, data in dagparser.parsedag(text):
1640 for type, data in dagparser.parsedag(text):
1641 if type == 'n':
1641 if type == 'n':
1642 total += 1
1642 total += 1
1643
1643
1644 if mergeable_file:
1644 if mergeable_file:
1645 linesperrev = 2
1645 linesperrev = 2
1646 # make a file with k lines per rev
1646 # make a file with k lines per rev
1647 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1647 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1648 initialmergedlines.append("")
1648 initialmergedlines.append("")
1649
1649
1650 tags = []
1650 tags = []
1651
1651
1652 lock = tr = None
1652 lock = tr = None
1653 try:
1653 try:
1654 lock = repo.lock()
1654 lock = repo.lock()
1655 tr = repo.transaction("builddag")
1655 tr = repo.transaction("builddag")
1656
1656
1657 at = -1
1657 at = -1
1658 atbranch = 'default'
1658 atbranch = 'default'
1659 nodeids = []
1659 nodeids = []
1660 id = 0
1660 id = 0
1661 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1661 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1662 for type, data in dagparser.parsedag(text):
1662 for type, data in dagparser.parsedag(text):
1663 if type == 'n':
1663 if type == 'n':
1664 ui.note(('node %s\n' % str(data)))
1664 ui.note(('node %s\n' % str(data)))
1665 id, ps = data
1665 id, ps = data
1666
1666
1667 files = []
1667 files = []
1668 fctxs = {}
1668 fctxs = {}
1669
1669
1670 p2 = None
1670 p2 = None
1671 if mergeable_file:
1671 if mergeable_file:
1672 fn = "mf"
1672 fn = "mf"
1673 p1 = repo[ps[0]]
1673 p1 = repo[ps[0]]
1674 if len(ps) > 1:
1674 if len(ps) > 1:
1675 p2 = repo[ps[1]]
1675 p2 = repo[ps[1]]
1676 pa = p1.ancestor(p2)
1676 pa = p1.ancestor(p2)
1677 base, local, other = [x[fn].data() for x in (pa, p1,
1677 base, local, other = [x[fn].data() for x in (pa, p1,
1678 p2)]
1678 p2)]
1679 m3 = simplemerge.Merge3Text(base, local, other)
1679 m3 = simplemerge.Merge3Text(base, local, other)
1680 ml = [l.strip() for l in m3.merge_lines()]
1680 ml = [l.strip() for l in m3.merge_lines()]
1681 ml.append("")
1681 ml.append("")
1682 elif at > 0:
1682 elif at > 0:
1683 ml = p1[fn].data().split("\n")
1683 ml = p1[fn].data().split("\n")
1684 else:
1684 else:
1685 ml = initialmergedlines
1685 ml = initialmergedlines
1686 ml[id * linesperrev] += " r%i" % id
1686 ml[id * linesperrev] += " r%i" % id
1687 mergedtext = "\n".join(ml)
1687 mergedtext = "\n".join(ml)
1688 files.append(fn)
1688 files.append(fn)
1689 fctxs[fn] = context.memfilectx(fn, mergedtext)
1689 fctxs[fn] = context.memfilectx(fn, mergedtext)
1690
1690
1691 if overwritten_file:
1691 if overwritten_file:
1692 fn = "of"
1692 fn = "of"
1693 files.append(fn)
1693 files.append(fn)
1694 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1694 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1695
1695
1696 if new_file:
1696 if new_file:
1697 fn = "nf%i" % id
1697 fn = "nf%i" % id
1698 files.append(fn)
1698 files.append(fn)
1699 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1699 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1700 if len(ps) > 1:
1700 if len(ps) > 1:
1701 if not p2:
1701 if not p2:
1702 p2 = repo[ps[1]]
1702 p2 = repo[ps[1]]
1703 for fn in p2:
1703 for fn in p2:
1704 if fn.startswith("nf"):
1704 if fn.startswith("nf"):
1705 files.append(fn)
1705 files.append(fn)
1706 fctxs[fn] = p2[fn]
1706 fctxs[fn] = p2[fn]
1707
1707
1708 def fctxfn(repo, cx, path):
1708 def fctxfn(repo, cx, path):
1709 return fctxs.get(path)
1709 return fctxs.get(path)
1710
1710
1711 if len(ps) == 0 or ps[0] < 0:
1711 if len(ps) == 0 or ps[0] < 0:
1712 pars = [None, None]
1712 pars = [None, None]
1713 elif len(ps) == 1:
1713 elif len(ps) == 1:
1714 pars = [nodeids[ps[0]], None]
1714 pars = [nodeids[ps[0]], None]
1715 else:
1715 else:
1716 pars = [nodeids[p] for p in ps]
1716 pars = [nodeids[p] for p in ps]
1717 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1717 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1718 date=(id, 0),
1718 date=(id, 0),
1719 user="debugbuilddag",
1719 user="debugbuilddag",
1720 extra={'branch': atbranch})
1720 extra={'branch': atbranch})
1721 nodeid = repo.commitctx(cx)
1721 nodeid = repo.commitctx(cx)
1722 nodeids.append(nodeid)
1722 nodeids.append(nodeid)
1723 at = id
1723 at = id
1724 elif type == 'l':
1724 elif type == 'l':
1725 id, name = data
1725 id, name = data
1726 ui.note(('tag %s\n' % name))
1726 ui.note(('tag %s\n' % name))
1727 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1727 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1728 elif type == 'a':
1728 elif type == 'a':
1729 ui.note(('branch %s\n' % data))
1729 ui.note(('branch %s\n' % data))
1730 atbranch = data
1730 atbranch = data
1731 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1731 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1732 tr.close()
1732 tr.close()
1733
1733
1734 if tags:
1734 if tags:
1735 repo.opener.write("localtags", "".join(tags))
1735 repo.opener.write("localtags", "".join(tags))
1736 finally:
1736 finally:
1737 ui.progress(_('building'), None)
1737 ui.progress(_('building'), None)
1738 release(tr, lock)
1738 release(tr, lock)
1739
1739
1740 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1740 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1741 def debugbundle(ui, bundlepath, all=None, **opts):
1741 def debugbundle(ui, bundlepath, all=None, **opts):
1742 """lists the contents of a bundle"""
1742 """lists the contents of a bundle"""
1743 f = hg.openpath(ui, bundlepath)
1743 f = hg.openpath(ui, bundlepath)
1744 try:
1744 try:
1745 gen = exchange.readbundle(ui, f, bundlepath)
1745 gen = exchange.readbundle(ui, f, bundlepath)
1746 if all:
1746 if all:
1747 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1747 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1748
1748
1749 def showchunks(named):
1749 def showchunks(named):
1750 ui.write("\n%s\n" % named)
1750 ui.write("\n%s\n" % named)
1751 chain = None
1751 chain = None
1752 while True:
1752 while True:
1753 chunkdata = gen.deltachunk(chain)
1753 chunkdata = gen.deltachunk(chain)
1754 if not chunkdata:
1754 if not chunkdata:
1755 break
1755 break
1756 node = chunkdata['node']
1756 node = chunkdata['node']
1757 p1 = chunkdata['p1']
1757 p1 = chunkdata['p1']
1758 p2 = chunkdata['p2']
1758 p2 = chunkdata['p2']
1759 cs = chunkdata['cs']
1759 cs = chunkdata['cs']
1760 deltabase = chunkdata['deltabase']
1760 deltabase = chunkdata['deltabase']
1761 delta = chunkdata['delta']
1761 delta = chunkdata['delta']
1762 ui.write("%s %s %s %s %s %s\n" %
1762 ui.write("%s %s %s %s %s %s\n" %
1763 (hex(node), hex(p1), hex(p2),
1763 (hex(node), hex(p1), hex(p2),
1764 hex(cs), hex(deltabase), len(delta)))
1764 hex(cs), hex(deltabase), len(delta)))
1765 chain = node
1765 chain = node
1766
1766
1767 chunkdata = gen.changelogheader()
1767 chunkdata = gen.changelogheader()
1768 showchunks("changelog")
1768 showchunks("changelog")
1769 chunkdata = gen.manifestheader()
1769 chunkdata = gen.manifestheader()
1770 showchunks("manifest")
1770 showchunks("manifest")
1771 while True:
1771 while True:
1772 chunkdata = gen.filelogheader()
1772 chunkdata = gen.filelogheader()
1773 if not chunkdata:
1773 if not chunkdata:
1774 break
1774 break
1775 fname = chunkdata['filename']
1775 fname = chunkdata['filename']
1776 showchunks(fname)
1776 showchunks(fname)
1777 else:
1777 else:
1778 chunkdata = gen.changelogheader()
1778 chunkdata = gen.changelogheader()
1779 chain = None
1779 chain = None
1780 while True:
1780 while True:
1781 chunkdata = gen.deltachunk(chain)
1781 chunkdata = gen.deltachunk(chain)
1782 if not chunkdata:
1782 if not chunkdata:
1783 break
1783 break
1784 node = chunkdata['node']
1784 node = chunkdata['node']
1785 ui.write("%s\n" % hex(node))
1785 ui.write("%s\n" % hex(node))
1786 chain = node
1786 chain = node
1787 finally:
1787 finally:
1788 f.close()
1788 f.close()
1789
1789
1790 @command('debugcheckstate', [], '')
1790 @command('debugcheckstate', [], '')
1791 def debugcheckstate(ui, repo):
1791 def debugcheckstate(ui, repo):
1792 """validate the correctness of the current dirstate"""
1792 """validate the correctness of the current dirstate"""
1793 parent1, parent2 = repo.dirstate.parents()
1793 parent1, parent2 = repo.dirstate.parents()
1794 m1 = repo[parent1].manifest()
1794 m1 = repo[parent1].manifest()
1795 m2 = repo[parent2].manifest()
1795 m2 = repo[parent2].manifest()
1796 errors = 0
1796 errors = 0
1797 for f in repo.dirstate:
1797 for f in repo.dirstate:
1798 state = repo.dirstate[f]
1798 state = repo.dirstate[f]
1799 if state in "nr" and f not in m1:
1799 if state in "nr" and f not in m1:
1800 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1800 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1801 errors += 1
1801 errors += 1
1802 if state in "a" and f in m1:
1802 if state in "a" and f in m1:
1803 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1803 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1804 errors += 1
1804 errors += 1
1805 if state in "m" and f not in m1 and f not in m2:
1805 if state in "m" and f not in m1 and f not in m2:
1806 ui.warn(_("%s in state %s, but not in either manifest\n") %
1806 ui.warn(_("%s in state %s, but not in either manifest\n") %
1807 (f, state))
1807 (f, state))
1808 errors += 1
1808 errors += 1
1809 for f in m1:
1809 for f in m1:
1810 state = repo.dirstate[f]
1810 state = repo.dirstate[f]
1811 if state not in "nrm":
1811 if state not in "nrm":
1812 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1812 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1813 errors += 1
1813 errors += 1
1814 if errors:
1814 if errors:
1815 error = _(".hg/dirstate inconsistent with current parent's manifest")
1815 error = _(".hg/dirstate inconsistent with current parent's manifest")
1816 raise util.Abort(error)
1816 raise util.Abort(error)
1817
1817
1818 @command('debugcommands', [], _('[COMMAND]'))
1818 @command('debugcommands', [], _('[COMMAND]'))
1819 def debugcommands(ui, cmd='', *args):
1819 def debugcommands(ui, cmd='', *args):
1820 """list all available commands and options"""
1820 """list all available commands and options"""
1821 for cmd, vals in sorted(table.iteritems()):
1821 for cmd, vals in sorted(table.iteritems()):
1822 cmd = cmd.split('|')[0].strip('^')
1822 cmd = cmd.split('|')[0].strip('^')
1823 opts = ', '.join([i[1] for i in vals[1]])
1823 opts = ', '.join([i[1] for i in vals[1]])
1824 ui.write('%s: %s\n' % (cmd, opts))
1824 ui.write('%s: %s\n' % (cmd, opts))
1825
1825
1826 @command('debugcomplete',
1826 @command('debugcomplete',
1827 [('o', 'options', None, _('show the command options'))],
1827 [('o', 'options', None, _('show the command options'))],
1828 _('[-o] CMD'))
1828 _('[-o] CMD'))
1829 def debugcomplete(ui, cmd='', **opts):
1829 def debugcomplete(ui, cmd='', **opts):
1830 """returns the completion list associated with the given command"""
1830 """returns the completion list associated with the given command"""
1831
1831
1832 if opts.get('options'):
1832 if opts.get('options'):
1833 options = []
1833 options = []
1834 otables = [globalopts]
1834 otables = [globalopts]
1835 if cmd:
1835 if cmd:
1836 aliases, entry = cmdutil.findcmd(cmd, table, False)
1836 aliases, entry = cmdutil.findcmd(cmd, table, False)
1837 otables.append(entry[1])
1837 otables.append(entry[1])
1838 for t in otables:
1838 for t in otables:
1839 for o in t:
1839 for o in t:
1840 if "(DEPRECATED)" in o[3]:
1840 if "(DEPRECATED)" in o[3]:
1841 continue
1841 continue
1842 if o[0]:
1842 if o[0]:
1843 options.append('-%s' % o[0])
1843 options.append('-%s' % o[0])
1844 options.append('--%s' % o[1])
1844 options.append('--%s' % o[1])
1845 ui.write("%s\n" % "\n".join(options))
1845 ui.write("%s\n" % "\n".join(options))
1846 return
1846 return
1847
1847
1848 cmdlist = cmdutil.findpossible(cmd, table)
1848 cmdlist = cmdutil.findpossible(cmd, table)
1849 if ui.verbose:
1849 if ui.verbose:
1850 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1850 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1851 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1851 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1852
1852
1853 @command('debugdag',
1853 @command('debugdag',
1854 [('t', 'tags', None, _('use tags as labels')),
1854 [('t', 'tags', None, _('use tags as labels')),
1855 ('b', 'branches', None, _('annotate with branch names')),
1855 ('b', 'branches', None, _('annotate with branch names')),
1856 ('', 'dots', None, _('use dots for runs')),
1856 ('', 'dots', None, _('use dots for runs')),
1857 ('s', 'spaces', None, _('separate elements by spaces'))],
1857 ('s', 'spaces', None, _('separate elements by spaces'))],
1858 _('[OPTION]... [FILE [REV]...]'))
1858 _('[OPTION]... [FILE [REV]...]'))
1859 def debugdag(ui, repo, file_=None, *revs, **opts):
1859 def debugdag(ui, repo, file_=None, *revs, **opts):
1860 """format the changelog or an index DAG as a concise textual description
1860 """format the changelog or an index DAG as a concise textual description
1861
1861
1862 If you pass a revlog index, the revlog's DAG is emitted. If you list
1862 If you pass a revlog index, the revlog's DAG is emitted. If you list
1863 revision numbers, they get labeled in the output as rN.
1863 revision numbers, they get labeled in the output as rN.
1864
1864
1865 Otherwise, the changelog DAG of the current repo is emitted.
1865 Otherwise, the changelog DAG of the current repo is emitted.
1866 """
1866 """
1867 spaces = opts.get('spaces')
1867 spaces = opts.get('spaces')
1868 dots = opts.get('dots')
1868 dots = opts.get('dots')
1869 if file_:
1869 if file_:
1870 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1870 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1871 revs = set((int(r) for r in revs))
1871 revs = set((int(r) for r in revs))
1872 def events():
1872 def events():
1873 for r in rlog:
1873 for r in rlog:
1874 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1874 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1875 if p != -1)))
1875 if p != -1)))
1876 if r in revs:
1876 if r in revs:
1877 yield 'l', (r, "r%i" % r)
1877 yield 'l', (r, "r%i" % r)
1878 elif repo:
1878 elif repo:
1879 cl = repo.changelog
1879 cl = repo.changelog
1880 tags = opts.get('tags')
1880 tags = opts.get('tags')
1881 branches = opts.get('branches')
1881 branches = opts.get('branches')
1882 if tags:
1882 if tags:
1883 labels = {}
1883 labels = {}
1884 for l, n in repo.tags().items():
1884 for l, n in repo.tags().items():
1885 labels.setdefault(cl.rev(n), []).append(l)
1885 labels.setdefault(cl.rev(n), []).append(l)
1886 def events():
1886 def events():
1887 b = "default"
1887 b = "default"
1888 for r in cl:
1888 for r in cl:
1889 if branches:
1889 if branches:
1890 newb = cl.read(cl.node(r))[5]['branch']
1890 newb = cl.read(cl.node(r))[5]['branch']
1891 if newb != b:
1891 if newb != b:
1892 yield 'a', newb
1892 yield 'a', newb
1893 b = newb
1893 b = newb
1894 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1894 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1895 if p != -1)))
1895 if p != -1)))
1896 if tags:
1896 if tags:
1897 ls = labels.get(r)
1897 ls = labels.get(r)
1898 if ls:
1898 if ls:
1899 for l in ls:
1899 for l in ls:
1900 yield 'l', (r, l)
1900 yield 'l', (r, l)
1901 else:
1901 else:
1902 raise util.Abort(_('need repo for changelog dag'))
1902 raise util.Abort(_('need repo for changelog dag'))
1903
1903
1904 for line in dagparser.dagtextlines(events(),
1904 for line in dagparser.dagtextlines(events(),
1905 addspaces=spaces,
1905 addspaces=spaces,
1906 wraplabels=True,
1906 wraplabels=True,
1907 wrapannotations=True,
1907 wrapannotations=True,
1908 wrapnonlinear=dots,
1908 wrapnonlinear=dots,
1909 usedots=dots,
1909 usedots=dots,
1910 maxlinewidth=70):
1910 maxlinewidth=70):
1911 ui.write(line)
1911 ui.write(line)
1912 ui.write("\n")
1912 ui.write("\n")
1913
1913
1914 @command('debugdata',
1914 @command('debugdata',
1915 [('c', 'changelog', False, _('open changelog')),
1915 [('c', 'changelog', False, _('open changelog')),
1916 ('m', 'manifest', False, _('open manifest'))],
1916 ('m', 'manifest', False, _('open manifest'))],
1917 _('-c|-m|FILE REV'))
1917 _('-c|-m|FILE REV'))
1918 def debugdata(ui, repo, file_, rev=None, **opts):
1918 def debugdata(ui, repo, file_, rev=None, **opts):
1919 """dump the contents of a data file revision"""
1919 """dump the contents of a data file revision"""
1920 if opts.get('changelog') or opts.get('manifest'):
1920 if opts.get('changelog') or opts.get('manifest'):
1921 file_, rev = None, file_
1921 file_, rev = None, file_
1922 elif rev is None:
1922 elif rev is None:
1923 raise error.CommandError('debugdata', _('invalid arguments'))
1923 raise error.CommandError('debugdata', _('invalid arguments'))
1924 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1924 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1925 try:
1925 try:
1926 ui.write(r.revision(r.lookup(rev)))
1926 ui.write(r.revision(r.lookup(rev)))
1927 except KeyError:
1927 except KeyError:
1928 raise util.Abort(_('invalid revision identifier %s') % rev)
1928 raise util.Abort(_('invalid revision identifier %s') % rev)
1929
1929
1930 @command('debugdate',
1930 @command('debugdate',
1931 [('e', 'extended', None, _('try extended date formats'))],
1931 [('e', 'extended', None, _('try extended date formats'))],
1932 _('[-e] DATE [RANGE]'))
1932 _('[-e] DATE [RANGE]'))
1933 def debugdate(ui, date, range=None, **opts):
1933 def debugdate(ui, date, range=None, **opts):
1934 """parse and display a date"""
1934 """parse and display a date"""
1935 if opts["extended"]:
1935 if opts["extended"]:
1936 d = util.parsedate(date, util.extendeddateformats)
1936 d = util.parsedate(date, util.extendeddateformats)
1937 else:
1937 else:
1938 d = util.parsedate(date)
1938 d = util.parsedate(date)
1939 ui.write(("internal: %s %s\n") % d)
1939 ui.write(("internal: %s %s\n") % d)
1940 ui.write(("standard: %s\n") % util.datestr(d))
1940 ui.write(("standard: %s\n") % util.datestr(d))
1941 if range:
1941 if range:
1942 m = util.matchdate(range)
1942 m = util.matchdate(range)
1943 ui.write(("match: %s\n") % m(d[0]))
1943 ui.write(("match: %s\n") % m(d[0]))
1944
1944
1945 @command('debugdiscovery',
1945 @command('debugdiscovery',
1946 [('', 'old', None, _('use old-style discovery')),
1946 [('', 'old', None, _('use old-style discovery')),
1947 ('', 'nonheads', None,
1947 ('', 'nonheads', None,
1948 _('use old-style discovery with non-heads included')),
1948 _('use old-style discovery with non-heads included')),
1949 ] + remoteopts,
1949 ] + remoteopts,
1950 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1950 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1951 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1951 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1952 """runs the changeset discovery protocol in isolation"""
1952 """runs the changeset discovery protocol in isolation"""
1953 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1953 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1954 opts.get('branch'))
1954 opts.get('branch'))
1955 remote = hg.peer(repo, opts, remoteurl)
1955 remote = hg.peer(repo, opts, remoteurl)
1956 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1956 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1957
1957
1958 # make sure tests are repeatable
1958 # make sure tests are repeatable
1959 random.seed(12323)
1959 random.seed(12323)
1960
1960
1961 def doit(localheads, remoteheads, remote=remote):
1961 def doit(localheads, remoteheads, remote=remote):
1962 if opts.get('old'):
1962 if opts.get('old'):
1963 if localheads:
1963 if localheads:
1964 raise util.Abort('cannot use localheads with old style '
1964 raise util.Abort('cannot use localheads with old style '
1965 'discovery')
1965 'discovery')
1966 if not util.safehasattr(remote, 'branches'):
1966 if not util.safehasattr(remote, 'branches'):
1967 # enable in-client legacy support
1967 # enable in-client legacy support
1968 remote = localrepo.locallegacypeer(remote.local())
1968 remote = localrepo.locallegacypeer(remote.local())
1969 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1969 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1970 force=True)
1970 force=True)
1971 common = set(common)
1971 common = set(common)
1972 if not opts.get('nonheads'):
1972 if not opts.get('nonheads'):
1973 ui.write(("unpruned common: %s\n") %
1973 ui.write(("unpruned common: %s\n") %
1974 " ".join(sorted(short(n) for n in common)))
1974 " ".join(sorted(short(n) for n in common)))
1975 dag = dagutil.revlogdag(repo.changelog)
1975 dag = dagutil.revlogdag(repo.changelog)
1976 all = dag.ancestorset(dag.internalizeall(common))
1976 all = dag.ancestorset(dag.internalizeall(common))
1977 common = dag.externalizeall(dag.headsetofconnecteds(all))
1977 common = dag.externalizeall(dag.headsetofconnecteds(all))
1978 else:
1978 else:
1979 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1979 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1980 common = set(common)
1980 common = set(common)
1981 rheads = set(hds)
1981 rheads = set(hds)
1982 lheads = set(repo.heads())
1982 lheads = set(repo.heads())
1983 ui.write(("common heads: %s\n") %
1983 ui.write(("common heads: %s\n") %
1984 " ".join(sorted(short(n) for n in common)))
1984 " ".join(sorted(short(n) for n in common)))
1985 if lheads <= common:
1985 if lheads <= common:
1986 ui.write(("local is subset\n"))
1986 ui.write(("local is subset\n"))
1987 elif rheads <= common:
1987 elif rheads <= common:
1988 ui.write(("remote is subset\n"))
1988 ui.write(("remote is subset\n"))
1989
1989
1990 serverlogs = opts.get('serverlog')
1990 serverlogs = opts.get('serverlog')
1991 if serverlogs:
1991 if serverlogs:
1992 for filename in serverlogs:
1992 for filename in serverlogs:
1993 logfile = open(filename, 'r')
1993 logfile = open(filename, 'r')
1994 try:
1994 try:
1995 line = logfile.readline()
1995 line = logfile.readline()
1996 while line:
1996 while line:
1997 parts = line.strip().split(';')
1997 parts = line.strip().split(';')
1998 op = parts[1]
1998 op = parts[1]
1999 if op == 'cg':
1999 if op == 'cg':
2000 pass
2000 pass
2001 elif op == 'cgss':
2001 elif op == 'cgss':
2002 doit(parts[2].split(' '), parts[3].split(' '))
2002 doit(parts[2].split(' '), parts[3].split(' '))
2003 elif op == 'unb':
2003 elif op == 'unb':
2004 doit(parts[3].split(' '), parts[2].split(' '))
2004 doit(parts[3].split(' '), parts[2].split(' '))
2005 line = logfile.readline()
2005 line = logfile.readline()
2006 finally:
2006 finally:
2007 logfile.close()
2007 logfile.close()
2008
2008
2009 else:
2009 else:
2010 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2010 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2011 opts.get('remote_head'))
2011 opts.get('remote_head'))
2012 localrevs = opts.get('local_head')
2012 localrevs = opts.get('local_head')
2013 doit(localrevs, remoterevs)
2013 doit(localrevs, remoterevs)
2014
2014
2015 @command('debugfileset',
2015 @command('debugfileset',
2016 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2016 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2017 _('[-r REV] FILESPEC'))
2017 _('[-r REV] FILESPEC'))
2018 def debugfileset(ui, repo, expr, **opts):
2018 def debugfileset(ui, repo, expr, **opts):
2019 '''parse and apply a fileset specification'''
2019 '''parse and apply a fileset specification'''
2020 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2020 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2021 if ui.verbose:
2021 if ui.verbose:
2022 tree = fileset.parse(expr)[0]
2022 tree = fileset.parse(expr)[0]
2023 ui.note(tree, "\n")
2023 ui.note(tree, "\n")
2024
2024
2025 for f in ctx.getfileset(expr):
2025 for f in ctx.getfileset(expr):
2026 ui.write("%s\n" % f)
2026 ui.write("%s\n" % f)
2027
2027
2028 @command('debugfsinfo', [], _('[PATH]'))
2028 @command('debugfsinfo', [], _('[PATH]'))
2029 def debugfsinfo(ui, path="."):
2029 def debugfsinfo(ui, path="."):
2030 """show information detected about current filesystem"""
2030 """show information detected about current filesystem"""
2031 util.writefile('.debugfsinfo', '')
2031 util.writefile('.debugfsinfo', '')
2032 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2032 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2033 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2033 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2034 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2034 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2035 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2035 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2036 and 'yes' or 'no'))
2036 and 'yes' or 'no'))
2037 os.unlink('.debugfsinfo')
2037 os.unlink('.debugfsinfo')
2038
2038
2039 @command('debuggetbundle',
2039 @command('debuggetbundle',
2040 [('H', 'head', [], _('id of head node'), _('ID')),
2040 [('H', 'head', [], _('id of head node'), _('ID')),
2041 ('C', 'common', [], _('id of common node'), _('ID')),
2041 ('C', 'common', [], _('id of common node'), _('ID')),
2042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2043 _('REPO FILE [-H|-C ID]...'))
2043 _('REPO FILE [-H|-C ID]...'))
2044 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2044 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2045 """retrieves a bundle from a repo
2045 """retrieves a bundle from a repo
2046
2046
2047 Every ID must be a full-length hex node id string. Saves the bundle to the
2047 Every ID must be a full-length hex node id string. Saves the bundle to the
2048 given file.
2048 given file.
2049 """
2049 """
2050 repo = hg.peer(ui, opts, repopath)
2050 repo = hg.peer(ui, opts, repopath)
2051 if not repo.capable('getbundle'):
2051 if not repo.capable('getbundle'):
2052 raise util.Abort("getbundle() not supported by target repository")
2052 raise util.Abort("getbundle() not supported by target repository")
2053 args = {}
2053 args = {}
2054 if common:
2054 if common:
2055 args['common'] = [bin(s) for s in common]
2055 args['common'] = [bin(s) for s in common]
2056 if head:
2056 if head:
2057 args['heads'] = [bin(s) for s in head]
2057 args['heads'] = [bin(s) for s in head]
2058 # TODO: get desired bundlecaps from command line.
2058 # TODO: get desired bundlecaps from command line.
2059 args['bundlecaps'] = None
2059 args['bundlecaps'] = None
2060 bundle = repo.getbundle('debug', **args)
2060 bundle = repo.getbundle('debug', **args)
2061
2061
2062 bundletype = opts.get('type', 'bzip2').lower()
2062 bundletype = opts.get('type', 'bzip2').lower()
2063 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2063 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2064 bundletype = btypes.get(bundletype)
2064 bundletype = btypes.get(bundletype)
2065 if bundletype not in changegroup.bundletypes:
2065 if bundletype not in changegroup.bundletypes:
2066 raise util.Abort(_('unknown bundle type specified with --type'))
2066 raise util.Abort(_('unknown bundle type specified with --type'))
2067 changegroup.writebundle(bundle, bundlepath, bundletype)
2067 changegroup.writebundle(bundle, bundlepath, bundletype)
2068
2068
2069 @command('debugignore', [], '')
2069 @command('debugignore', [], '')
2070 def debugignore(ui, repo, *values, **opts):
2070 def debugignore(ui, repo, *values, **opts):
2071 """display the combined ignore pattern"""
2071 """display the combined ignore pattern"""
2072 ignore = repo.dirstate._ignore
2072 ignore = repo.dirstate._ignore
2073 includepat = getattr(ignore, 'includepat', None)
2073 includepat = getattr(ignore, 'includepat', None)
2074 if includepat is not None:
2074 if includepat is not None:
2075 ui.write("%s\n" % includepat)
2075 ui.write("%s\n" % includepat)
2076 else:
2076 else:
2077 raise util.Abort(_("no ignore patterns found"))
2077 raise util.Abort(_("no ignore patterns found"))
2078
2078
2079 @command('debugindex',
2079 @command('debugindex',
2080 [('c', 'changelog', False, _('open changelog')),
2080 [('c', 'changelog', False, _('open changelog')),
2081 ('m', 'manifest', False, _('open manifest')),
2081 ('m', 'manifest', False, _('open manifest')),
2082 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2082 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2083 _('[-f FORMAT] -c|-m|FILE'))
2083 _('[-f FORMAT] -c|-m|FILE'))
2084 def debugindex(ui, repo, file_=None, **opts):
2084 def debugindex(ui, repo, file_=None, **opts):
2085 """dump the contents of an index file"""
2085 """dump the contents of an index file"""
2086 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2086 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2087 format = opts.get('format', 0)
2087 format = opts.get('format', 0)
2088 if format not in (0, 1):
2088 if format not in (0, 1):
2089 raise util.Abort(_("unknown format %d") % format)
2089 raise util.Abort(_("unknown format %d") % format)
2090
2090
2091 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2091 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2092 if generaldelta:
2092 if generaldelta:
2093 basehdr = ' delta'
2093 basehdr = ' delta'
2094 else:
2094 else:
2095 basehdr = ' base'
2095 basehdr = ' base'
2096
2096
2097 if format == 0:
2097 if format == 0:
2098 ui.write(" rev offset length " + basehdr + " linkrev"
2098 ui.write(" rev offset length " + basehdr + " linkrev"
2099 " nodeid p1 p2\n")
2099 " nodeid p1 p2\n")
2100 elif format == 1:
2100 elif format == 1:
2101 ui.write(" rev flag offset length"
2101 ui.write(" rev flag offset length"
2102 " size " + basehdr + " link p1 p2"
2102 " size " + basehdr + " link p1 p2"
2103 " nodeid\n")
2103 " nodeid\n")
2104
2104
2105 for i in r:
2105 for i in r:
2106 node = r.node(i)
2106 node = r.node(i)
2107 if generaldelta:
2107 if generaldelta:
2108 base = r.deltaparent(i)
2108 base = r.deltaparent(i)
2109 else:
2109 else:
2110 base = r.chainbase(i)
2110 base = r.chainbase(i)
2111 if format == 0:
2111 if format == 0:
2112 try:
2112 try:
2113 pp = r.parents(node)
2113 pp = r.parents(node)
2114 except Exception:
2114 except Exception:
2115 pp = [nullid, nullid]
2115 pp = [nullid, nullid]
2116 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2116 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2117 i, r.start(i), r.length(i), base, r.linkrev(i),
2117 i, r.start(i), r.length(i), base, r.linkrev(i),
2118 short(node), short(pp[0]), short(pp[1])))
2118 short(node), short(pp[0]), short(pp[1])))
2119 elif format == 1:
2119 elif format == 1:
2120 pr = r.parentrevs(i)
2120 pr = r.parentrevs(i)
2121 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2121 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2122 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2122 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2123 base, r.linkrev(i), pr[0], pr[1], short(node)))
2123 base, r.linkrev(i), pr[0], pr[1], short(node)))
2124
2124
2125 @command('debugindexdot', [], _('FILE'))
2125 @command('debugindexdot', [], _('FILE'))
2126 def debugindexdot(ui, repo, file_):
2126 def debugindexdot(ui, repo, file_):
2127 """dump an index DAG as a graphviz dot file"""
2127 """dump an index DAG as a graphviz dot file"""
2128 r = None
2128 r = None
2129 if repo:
2129 if repo:
2130 filelog = repo.file(file_)
2130 filelog = repo.file(file_)
2131 if len(filelog):
2131 if len(filelog):
2132 r = filelog
2132 r = filelog
2133 if not r:
2133 if not r:
2134 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2134 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2135 ui.write(("digraph G {\n"))
2135 ui.write(("digraph G {\n"))
2136 for i in r:
2136 for i in r:
2137 node = r.node(i)
2137 node = r.node(i)
2138 pp = r.parents(node)
2138 pp = r.parents(node)
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2140 if pp[1] != nullid:
2140 if pp[1] != nullid:
2141 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2141 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2142 ui.write("}\n")
2142 ui.write("}\n")
2143
2143
2144 @command('debuginstall', [], '')
2144 @command('debuginstall', [], '')
2145 def debuginstall(ui):
2145 def debuginstall(ui):
2146 '''test Mercurial installation
2146 '''test Mercurial installation
2147
2147
2148 Returns 0 on success.
2148 Returns 0 on success.
2149 '''
2149 '''
2150
2150
2151 def writetemp(contents):
2151 def writetemp(contents):
2152 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2152 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2153 f = os.fdopen(fd, "wb")
2153 f = os.fdopen(fd, "wb")
2154 f.write(contents)
2154 f.write(contents)
2155 f.close()
2155 f.close()
2156 return name
2156 return name
2157
2157
2158 problems = 0
2158 problems = 0
2159
2159
2160 # encoding
2160 # encoding
2161 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2161 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2162 try:
2162 try:
2163 encoding.fromlocal("test")
2163 encoding.fromlocal("test")
2164 except util.Abort, inst:
2164 except util.Abort, inst:
2165 ui.write(" %s\n" % inst)
2165 ui.write(" %s\n" % inst)
2166 ui.write(_(" (check that your locale is properly set)\n"))
2166 ui.write(_(" (check that your locale is properly set)\n"))
2167 problems += 1
2167 problems += 1
2168
2168
2169 # Python
2169 # Python
2170 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2170 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2171 ui.status(_("checking Python version (%s)\n")
2171 ui.status(_("checking Python version (%s)\n")
2172 % ("%s.%s.%s" % sys.version_info[:3]))
2172 % ("%s.%s.%s" % sys.version_info[:3]))
2173 ui.status(_("checking Python lib (%s)...\n")
2173 ui.status(_("checking Python lib (%s)...\n")
2174 % os.path.dirname(os.__file__))
2174 % os.path.dirname(os.__file__))
2175
2175
2176 # compiled modules
2176 # compiled modules
2177 ui.status(_("checking installed modules (%s)...\n")
2177 ui.status(_("checking installed modules (%s)...\n")
2178 % os.path.dirname(__file__))
2178 % os.path.dirname(__file__))
2179 try:
2179 try:
2180 import bdiff, mpatch, base85, osutil
2180 import bdiff, mpatch, base85, osutil
2181 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2181 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2182 except Exception, inst:
2182 except Exception, inst:
2183 ui.write(" %s\n" % inst)
2183 ui.write(" %s\n" % inst)
2184 ui.write(_(" One or more extensions could not be found"))
2184 ui.write(_(" One or more extensions could not be found"))
2185 ui.write(_(" (check that you compiled the extensions)\n"))
2185 ui.write(_(" (check that you compiled the extensions)\n"))
2186 problems += 1
2186 problems += 1
2187
2187
2188 # templates
2188 # templates
2189 import templater
2189 import templater
2190 p = templater.templatepath()
2190 p = templater.templatepath()
2191 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2191 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2192 if p:
2192 if p:
2193 m = templater.templatepath("map-cmdline.default")
2193 m = templater.templatepath("map-cmdline.default")
2194 if m:
2194 if m:
2195 # template found, check if it is working
2195 # template found, check if it is working
2196 try:
2196 try:
2197 templater.templater(m)
2197 templater.templater(m)
2198 except Exception, inst:
2198 except Exception, inst:
2199 ui.write(" %s\n" % inst)
2199 ui.write(" %s\n" % inst)
2200 p = None
2200 p = None
2201 else:
2201 else:
2202 ui.write(_(" template 'default' not found\n"))
2202 ui.write(_(" template 'default' not found\n"))
2203 p = None
2203 p = None
2204 else:
2204 else:
2205 ui.write(_(" no template directories found\n"))
2205 ui.write(_(" no template directories found\n"))
2206 if not p:
2206 if not p:
2207 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2207 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2208 problems += 1
2208 problems += 1
2209
2209
2210 # editor
2210 # editor
2211 ui.status(_("checking commit editor...\n"))
2211 ui.status(_("checking commit editor...\n"))
2212 editor = ui.geteditor()
2212 editor = ui.geteditor()
2213 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2213 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2214 if not cmdpath:
2214 if not cmdpath:
2215 if editor == 'vi':
2215 if editor == 'vi':
2216 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2216 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2217 ui.write(_(" (specify a commit editor in your configuration"
2217 ui.write(_(" (specify a commit editor in your configuration"
2218 " file)\n"))
2218 " file)\n"))
2219 else:
2219 else:
2220 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2220 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2221 ui.write(_(" (specify a commit editor in your configuration"
2221 ui.write(_(" (specify a commit editor in your configuration"
2222 " file)\n"))
2222 " file)\n"))
2223 problems += 1
2223 problems += 1
2224
2224
2225 # check username
2225 # check username
2226 ui.status(_("checking username...\n"))
2226 ui.status(_("checking username...\n"))
2227 try:
2227 try:
2228 ui.username()
2228 ui.username()
2229 except util.Abort, e:
2229 except util.Abort, e:
2230 ui.write(" %s\n" % e)
2230 ui.write(" %s\n" % e)
2231 ui.write(_(" (specify a username in your configuration file)\n"))
2231 ui.write(_(" (specify a username in your configuration file)\n"))
2232 problems += 1
2232 problems += 1
2233
2233
2234 if not problems:
2234 if not problems:
2235 ui.status(_("no problems detected\n"))
2235 ui.status(_("no problems detected\n"))
2236 else:
2236 else:
2237 ui.write(_("%s problems detected,"
2237 ui.write(_("%s problems detected,"
2238 " please check your install!\n") % problems)
2238 " please check your install!\n") % problems)
2239
2239
2240 return problems
2240 return problems
2241
2241
2242 @command('debugknown', [], _('REPO ID...'))
2242 @command('debugknown', [], _('REPO ID...'))
2243 def debugknown(ui, repopath, *ids, **opts):
2243 def debugknown(ui, repopath, *ids, **opts):
2244 """test whether node ids are known to a repo
2244 """test whether node ids are known to a repo
2245
2245
2246 Every ID must be a full-length hex node id string. Returns a list of 0s
2246 Every ID must be a full-length hex node id string. Returns a list of 0s
2247 and 1s indicating unknown/known.
2247 and 1s indicating unknown/known.
2248 """
2248 """
2249 repo = hg.peer(ui, opts, repopath)
2249 repo = hg.peer(ui, opts, repopath)
2250 if not repo.capable('known'):
2250 if not repo.capable('known'):
2251 raise util.Abort("known() not supported by target repository")
2251 raise util.Abort("known() not supported by target repository")
2252 flags = repo.known([bin(s) for s in ids])
2252 flags = repo.known([bin(s) for s in ids])
2253 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2253 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2254
2254
2255 @command('debuglabelcomplete', [], _('LABEL...'))
2255 @command('debuglabelcomplete', [], _('LABEL...'))
2256 def debuglabelcomplete(ui, repo, *args):
2256 def debuglabelcomplete(ui, repo, *args):
2257 '''complete "labels" - tags, open branch names, bookmark names'''
2257 '''complete "labels" - tags, open branch names, bookmark names'''
2258
2258
2259 labels = set()
2259 labels = set()
2260 labels.update(t[0] for t in repo.tagslist())
2260 labels.update(t[0] for t in repo.tagslist())
2261 labels.update(repo._bookmarks.keys())
2261 labels.update(repo._bookmarks.keys())
2262 labels.update(tag for (tag, heads, tip, closed)
2262 labels.update(tag for (tag, heads, tip, closed)
2263 in repo.branchmap().iterbranches() if not closed)
2263 in repo.branchmap().iterbranches() if not closed)
2264 completions = set()
2264 completions = set()
2265 if not args:
2265 if not args:
2266 args = ['']
2266 args = ['']
2267 for a in args:
2267 for a in args:
2268 completions.update(l for l in labels if l.startswith(a))
2268 completions.update(l for l in labels if l.startswith(a))
2269 ui.write('\n'.join(sorted(completions)))
2269 ui.write('\n'.join(sorted(completions)))
2270 ui.write('\n')
2270 ui.write('\n')
2271
2271
2272 @command('debugobsolete',
2272 @command('debugobsolete',
2273 [('', 'flags', 0, _('markers flag')),
2273 [('', 'flags', 0, _('markers flag')),
2274 ] + commitopts2,
2274 ] + commitopts2,
2275 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2275 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2276 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2276 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2277 """create arbitrary obsolete marker
2277 """create arbitrary obsolete marker
2278
2278
2279 With no arguments, displays the list of obsolescence markers."""
2279 With no arguments, displays the list of obsolescence markers."""
2280 def parsenodeid(s):
2280 def parsenodeid(s):
2281 try:
2281 try:
2282 # We do not use revsingle/revrange functions here to accept
2282 # We do not use revsingle/revrange functions here to accept
2283 # arbitrary node identifiers, possibly not present in the
2283 # arbitrary node identifiers, possibly not present in the
2284 # local repository.
2284 # local repository.
2285 n = bin(s)
2285 n = bin(s)
2286 if len(n) != len(nullid):
2286 if len(n) != len(nullid):
2287 raise TypeError()
2287 raise TypeError()
2288 return n
2288 return n
2289 except TypeError:
2289 except TypeError:
2290 raise util.Abort('changeset references must be full hexadecimal '
2290 raise util.Abort('changeset references must be full hexadecimal '
2291 'node identifiers')
2291 'node identifiers')
2292
2292
2293 if precursor is not None:
2293 if precursor is not None:
2294 metadata = {}
2294 metadata = {}
2295 if 'date' in opts:
2295 if 'date' in opts:
2296 metadata['date'] = opts['date']
2296 metadata['date'] = opts['date']
2297 metadata['user'] = opts['user'] or ui.username()
2297 metadata['user'] = opts['user'] or ui.username()
2298 succs = tuple(parsenodeid(succ) for succ in successors)
2298 succs = tuple(parsenodeid(succ) for succ in successors)
2299 l = repo.lock()
2299 l = repo.lock()
2300 try:
2300 try:
2301 tr = repo.transaction('debugobsolete')
2301 tr = repo.transaction('debugobsolete')
2302 try:
2302 try:
2303 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2303 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2304 opts['flags'], metadata)
2304 opts['flags'], metadata)
2305 tr.close()
2305 tr.close()
2306 finally:
2306 finally:
2307 tr.release()
2307 tr.release()
2308 finally:
2308 finally:
2309 l.release()
2309 l.release()
2310 else:
2310 else:
2311 for m in obsolete.allmarkers(repo):
2311 for m in obsolete.allmarkers(repo):
2312 cmdutil.showmarker(ui, m)
2312 cmdutil.showmarker(ui, m)
2313
2313
2314 @command('debugpathcomplete',
2314 @command('debugpathcomplete',
2315 [('f', 'full', None, _('complete an entire path')),
2315 [('f', 'full', None, _('complete an entire path')),
2316 ('n', 'normal', None, _('show only normal files')),
2316 ('n', 'normal', None, _('show only normal files')),
2317 ('a', 'added', None, _('show only added files')),
2317 ('a', 'added', None, _('show only added files')),
2318 ('r', 'removed', None, _('show only removed files'))],
2318 ('r', 'removed', None, _('show only removed files'))],
2319 _('FILESPEC...'))
2319 _('FILESPEC...'))
2320 def debugpathcomplete(ui, repo, *specs, **opts):
2320 def debugpathcomplete(ui, repo, *specs, **opts):
2321 '''complete part or all of a tracked path
2321 '''complete part or all of a tracked path
2322
2322
2323 This command supports shells that offer path name completion. It
2323 This command supports shells that offer path name completion. It
2324 currently completes only files already known to the dirstate.
2324 currently completes only files already known to the dirstate.
2325
2325
2326 Completion extends only to the next path segment unless
2326 Completion extends only to the next path segment unless
2327 --full is specified, in which case entire paths are used.'''
2327 --full is specified, in which case entire paths are used.'''
2328
2328
2329 def complete(path, acceptable):
2329 def complete(path, acceptable):
2330 dirstate = repo.dirstate
2330 dirstate = repo.dirstate
2331 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2331 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2332 rootdir = repo.root + os.sep
2332 rootdir = repo.root + os.sep
2333 if spec != repo.root and not spec.startswith(rootdir):
2333 if spec != repo.root and not spec.startswith(rootdir):
2334 return [], []
2334 return [], []
2335 if os.path.isdir(spec):
2335 if os.path.isdir(spec):
2336 spec += '/'
2336 spec += '/'
2337 spec = spec[len(rootdir):]
2337 spec = spec[len(rootdir):]
2338 fixpaths = os.sep != '/'
2338 fixpaths = os.sep != '/'
2339 if fixpaths:
2339 if fixpaths:
2340 spec = spec.replace(os.sep, '/')
2340 spec = spec.replace(os.sep, '/')
2341 speclen = len(spec)
2341 speclen = len(spec)
2342 fullpaths = opts['full']
2342 fullpaths = opts['full']
2343 files, dirs = set(), set()
2343 files, dirs = set(), set()
2344 adddir, addfile = dirs.add, files.add
2344 adddir, addfile = dirs.add, files.add
2345 for f, st in dirstate.iteritems():
2345 for f, st in dirstate.iteritems():
2346 if f.startswith(spec) and st[0] in acceptable:
2346 if f.startswith(spec) and st[0] in acceptable:
2347 if fixpaths:
2347 if fixpaths:
2348 f = f.replace('/', os.sep)
2348 f = f.replace('/', os.sep)
2349 if fullpaths:
2349 if fullpaths:
2350 addfile(f)
2350 addfile(f)
2351 continue
2351 continue
2352 s = f.find(os.sep, speclen)
2352 s = f.find(os.sep, speclen)
2353 if s >= 0:
2353 if s >= 0:
2354 adddir(f[:s])
2354 adddir(f[:s])
2355 else:
2355 else:
2356 addfile(f)
2356 addfile(f)
2357 return files, dirs
2357 return files, dirs
2358
2358
2359 acceptable = ''
2359 acceptable = ''
2360 if opts['normal']:
2360 if opts['normal']:
2361 acceptable += 'nm'
2361 acceptable += 'nm'
2362 if opts['added']:
2362 if opts['added']:
2363 acceptable += 'a'
2363 acceptable += 'a'
2364 if opts['removed']:
2364 if opts['removed']:
2365 acceptable += 'r'
2365 acceptable += 'r'
2366 cwd = repo.getcwd()
2366 cwd = repo.getcwd()
2367 if not specs:
2367 if not specs:
2368 specs = ['.']
2368 specs = ['.']
2369
2369
2370 files, dirs = set(), set()
2370 files, dirs = set(), set()
2371 for spec in specs:
2371 for spec in specs:
2372 f, d = complete(spec, acceptable or 'nmar')
2372 f, d = complete(spec, acceptable or 'nmar')
2373 files.update(f)
2373 files.update(f)
2374 dirs.update(d)
2374 dirs.update(d)
2375 files.update(dirs)
2375 files.update(dirs)
2376 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2376 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2377 ui.write('\n')
2377 ui.write('\n')
2378
2378
2379 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2379 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2380 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2380 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2381 '''access the pushkey key/value protocol
2381 '''access the pushkey key/value protocol
2382
2382
2383 With two args, list the keys in the given namespace.
2383 With two args, list the keys in the given namespace.
2384
2384
2385 With five args, set a key to new if it currently is set to old.
2385 With five args, set a key to new if it currently is set to old.
2386 Reports success or failure.
2386 Reports success or failure.
2387 '''
2387 '''
2388
2388
2389 target = hg.peer(ui, {}, repopath)
2389 target = hg.peer(ui, {}, repopath)
2390 if keyinfo:
2390 if keyinfo:
2391 key, old, new = keyinfo
2391 key, old, new = keyinfo
2392 r = target.pushkey(namespace, key, old, new)
2392 r = target.pushkey(namespace, key, old, new)
2393 ui.status(str(r) + '\n')
2393 ui.status(str(r) + '\n')
2394 return not r
2394 return not r
2395 else:
2395 else:
2396 for k, v in sorted(target.listkeys(namespace).iteritems()):
2396 for k, v in sorted(target.listkeys(namespace).iteritems()):
2397 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2397 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2398 v.encode('string-escape')))
2398 v.encode('string-escape')))
2399
2399
2400 @command('debugpvec', [], _('A B'))
2400 @command('debugpvec', [], _('A B'))
2401 def debugpvec(ui, repo, a, b=None):
2401 def debugpvec(ui, repo, a, b=None):
2402 ca = scmutil.revsingle(repo, a)
2402 ca = scmutil.revsingle(repo, a)
2403 cb = scmutil.revsingle(repo, b)
2403 cb = scmutil.revsingle(repo, b)
2404 pa = pvec.ctxpvec(ca)
2404 pa = pvec.ctxpvec(ca)
2405 pb = pvec.ctxpvec(cb)
2405 pb = pvec.ctxpvec(cb)
2406 if pa == pb:
2406 if pa == pb:
2407 rel = "="
2407 rel = "="
2408 elif pa > pb:
2408 elif pa > pb:
2409 rel = ">"
2409 rel = ">"
2410 elif pa < pb:
2410 elif pa < pb:
2411 rel = "<"
2411 rel = "<"
2412 elif pa | pb:
2412 elif pa | pb:
2413 rel = "|"
2413 rel = "|"
2414 ui.write(_("a: %s\n") % pa)
2414 ui.write(_("a: %s\n") % pa)
2415 ui.write(_("b: %s\n") % pb)
2415 ui.write(_("b: %s\n") % pb)
2416 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2416 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2417 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2417 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2418 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2418 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2419 pa.distance(pb), rel))
2419 pa.distance(pb), rel))
2420
2420
2421 @command('debugrebuilddirstate|debugrebuildstate',
2421 @command('debugrebuilddirstate|debugrebuildstate',
2422 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2422 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2423 _('[-r REV]'))
2423 _('[-r REV]'))
2424 def debugrebuilddirstate(ui, repo, rev):
2424 def debugrebuilddirstate(ui, repo, rev):
2425 """rebuild the dirstate as it would look like for the given revision
2425 """rebuild the dirstate as it would look like for the given revision
2426
2426
2427 If no revision is specified the first current parent will be used.
2427 If no revision is specified the first current parent will be used.
2428
2428
2429 The dirstate will be set to the files of the given revision.
2429 The dirstate will be set to the files of the given revision.
2430 The actual working directory content or existing dirstate
2430 The actual working directory content or existing dirstate
2431 information such as adds or removes is not considered.
2431 information such as adds or removes is not considered.
2432
2432
2433 One use of this command is to make the next :hg:`status` invocation
2433 One use of this command is to make the next :hg:`status` invocation
2434 check the actual file content.
2434 check the actual file content.
2435 """
2435 """
2436 ctx = scmutil.revsingle(repo, rev)
2436 ctx = scmutil.revsingle(repo, rev)
2437 wlock = repo.wlock()
2437 wlock = repo.wlock()
2438 try:
2438 try:
2439 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2439 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2440 finally:
2440 finally:
2441 wlock.release()
2441 wlock.release()
2442
2442
2443 @command('debugrename',
2443 @command('debugrename',
2444 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2444 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2445 _('[-r REV] FILE'))
2445 _('[-r REV] FILE'))
2446 def debugrename(ui, repo, file1, *pats, **opts):
2446 def debugrename(ui, repo, file1, *pats, **opts):
2447 """dump rename information"""
2447 """dump rename information"""
2448
2448
2449 ctx = scmutil.revsingle(repo, opts.get('rev'))
2449 ctx = scmutil.revsingle(repo, opts.get('rev'))
2450 m = scmutil.match(ctx, (file1,) + pats, opts)
2450 m = scmutil.match(ctx, (file1,) + pats, opts)
2451 for abs in ctx.walk(m):
2451 for abs in ctx.walk(m):
2452 fctx = ctx[abs]
2452 fctx = ctx[abs]
2453 o = fctx.filelog().renamed(fctx.filenode())
2453 o = fctx.filelog().renamed(fctx.filenode())
2454 rel = m.rel(abs)
2454 rel = m.rel(abs)
2455 if o:
2455 if o:
2456 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2456 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2457 else:
2457 else:
2458 ui.write(_("%s not renamed\n") % rel)
2458 ui.write(_("%s not renamed\n") % rel)
2459
2459
2460 @command('debugrevlog',
2460 @command('debugrevlog',
2461 [('c', 'changelog', False, _('open changelog')),
2461 [('c', 'changelog', False, _('open changelog')),
2462 ('m', 'manifest', False, _('open manifest')),
2462 ('m', 'manifest', False, _('open manifest')),
2463 ('d', 'dump', False, _('dump index data'))],
2463 ('d', 'dump', False, _('dump index data'))],
2464 _('-c|-m|FILE'))
2464 _('-c|-m|FILE'))
2465 def debugrevlog(ui, repo, file_=None, **opts):
2465 def debugrevlog(ui, repo, file_=None, **opts):
2466 """show data and statistics about a revlog"""
2466 """show data and statistics about a revlog"""
2467 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2467 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2468
2468
2469 if opts.get("dump"):
2469 if opts.get("dump"):
2470 numrevs = len(r)
2470 numrevs = len(r)
2471 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2471 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2472 " rawsize totalsize compression heads\n")
2472 " rawsize totalsize compression heads\n")
2473 ts = 0
2473 ts = 0
2474 heads = set()
2474 heads = set()
2475 for rev in xrange(numrevs):
2475 for rev in xrange(numrevs):
2476 dbase = r.deltaparent(rev)
2476 dbase = r.deltaparent(rev)
2477 if dbase == -1:
2477 if dbase == -1:
2478 dbase = rev
2478 dbase = rev
2479 cbase = r.chainbase(rev)
2479 cbase = r.chainbase(rev)
2480 p1, p2 = r.parentrevs(rev)
2480 p1, p2 = r.parentrevs(rev)
2481 rs = r.rawsize(rev)
2481 rs = r.rawsize(rev)
2482 ts = ts + rs
2482 ts = ts + rs
2483 heads -= set(r.parentrevs(rev))
2483 heads -= set(r.parentrevs(rev))
2484 heads.add(rev)
2484 heads.add(rev)
2485 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2485 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2486 (rev, p1, p2, r.start(rev), r.end(rev),
2486 (rev, p1, p2, r.start(rev), r.end(rev),
2487 r.start(dbase), r.start(cbase),
2487 r.start(dbase), r.start(cbase),
2488 r.start(p1), r.start(p2),
2488 r.start(p1), r.start(p2),
2489 rs, ts, ts / r.end(rev), len(heads)))
2489 rs, ts, ts / r.end(rev), len(heads)))
2490 return 0
2490 return 0
2491
2491
2492 v = r.version
2492 v = r.version
2493 format = v & 0xFFFF
2493 format = v & 0xFFFF
2494 flags = []
2494 flags = []
2495 gdelta = False
2495 gdelta = False
2496 if v & revlog.REVLOGNGINLINEDATA:
2496 if v & revlog.REVLOGNGINLINEDATA:
2497 flags.append('inline')
2497 flags.append('inline')
2498 if v & revlog.REVLOGGENERALDELTA:
2498 if v & revlog.REVLOGGENERALDELTA:
2499 gdelta = True
2499 gdelta = True
2500 flags.append('generaldelta')
2500 flags.append('generaldelta')
2501 if not flags:
2501 if not flags:
2502 flags = ['(none)']
2502 flags = ['(none)']
2503
2503
2504 nummerges = 0
2504 nummerges = 0
2505 numfull = 0
2505 numfull = 0
2506 numprev = 0
2506 numprev = 0
2507 nump1 = 0
2507 nump1 = 0
2508 nump2 = 0
2508 nump2 = 0
2509 numother = 0
2509 numother = 0
2510 nump1prev = 0
2510 nump1prev = 0
2511 nump2prev = 0
2511 nump2prev = 0
2512 chainlengths = []
2512 chainlengths = []
2513
2513
2514 datasize = [None, 0, 0L]
2514 datasize = [None, 0, 0L]
2515 fullsize = [None, 0, 0L]
2515 fullsize = [None, 0, 0L]
2516 deltasize = [None, 0, 0L]
2516 deltasize = [None, 0, 0L]
2517
2517
2518 def addsize(size, l):
2518 def addsize(size, l):
2519 if l[0] is None or size < l[0]:
2519 if l[0] is None or size < l[0]:
2520 l[0] = size
2520 l[0] = size
2521 if size > l[1]:
2521 if size > l[1]:
2522 l[1] = size
2522 l[1] = size
2523 l[2] += size
2523 l[2] += size
2524
2524
2525 numrevs = len(r)
2525 numrevs = len(r)
2526 for rev in xrange(numrevs):
2526 for rev in xrange(numrevs):
2527 p1, p2 = r.parentrevs(rev)
2527 p1, p2 = r.parentrevs(rev)
2528 delta = r.deltaparent(rev)
2528 delta = r.deltaparent(rev)
2529 if format > 0:
2529 if format > 0:
2530 addsize(r.rawsize(rev), datasize)
2530 addsize(r.rawsize(rev), datasize)
2531 if p2 != nullrev:
2531 if p2 != nullrev:
2532 nummerges += 1
2532 nummerges += 1
2533 size = r.length(rev)
2533 size = r.length(rev)
2534 if delta == nullrev:
2534 if delta == nullrev:
2535 chainlengths.append(0)
2535 chainlengths.append(0)
2536 numfull += 1
2536 numfull += 1
2537 addsize(size, fullsize)
2537 addsize(size, fullsize)
2538 else:
2538 else:
2539 chainlengths.append(chainlengths[delta] + 1)
2539 chainlengths.append(chainlengths[delta] + 1)
2540 addsize(size, deltasize)
2540 addsize(size, deltasize)
2541 if delta == rev - 1:
2541 if delta == rev - 1:
2542 numprev += 1
2542 numprev += 1
2543 if delta == p1:
2543 if delta == p1:
2544 nump1prev += 1
2544 nump1prev += 1
2545 elif delta == p2:
2545 elif delta == p2:
2546 nump2prev += 1
2546 nump2prev += 1
2547 elif delta == p1:
2547 elif delta == p1:
2548 nump1 += 1
2548 nump1 += 1
2549 elif delta == p2:
2549 elif delta == p2:
2550 nump2 += 1
2550 nump2 += 1
2551 elif delta != nullrev:
2551 elif delta != nullrev:
2552 numother += 1
2552 numother += 1
2553
2553
2554 # Adjust size min value for empty cases
2554 # Adjust size min value for empty cases
2555 for size in (datasize, fullsize, deltasize):
2555 for size in (datasize, fullsize, deltasize):
2556 if size[0] is None:
2556 if size[0] is None:
2557 size[0] = 0
2557 size[0] = 0
2558
2558
2559 numdeltas = numrevs - numfull
2559 numdeltas = numrevs - numfull
2560 numoprev = numprev - nump1prev - nump2prev
2560 numoprev = numprev - nump1prev - nump2prev
2561 totalrawsize = datasize[2]
2561 totalrawsize = datasize[2]
2562 datasize[2] /= numrevs
2562 datasize[2] /= numrevs
2563 fulltotal = fullsize[2]
2563 fulltotal = fullsize[2]
2564 fullsize[2] /= numfull
2564 fullsize[2] /= numfull
2565 deltatotal = deltasize[2]
2565 deltatotal = deltasize[2]
2566 if numrevs - numfull > 0:
2566 if numrevs - numfull > 0:
2567 deltasize[2] /= numrevs - numfull
2567 deltasize[2] /= numrevs - numfull
2568 totalsize = fulltotal + deltatotal
2568 totalsize = fulltotal + deltatotal
2569 avgchainlen = sum(chainlengths) / numrevs
2569 avgchainlen = sum(chainlengths) / numrevs
2570 compratio = totalrawsize / totalsize
2570 compratio = totalrawsize / totalsize
2571
2571
2572 basedfmtstr = '%%%dd\n'
2572 basedfmtstr = '%%%dd\n'
2573 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2573 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2574
2574
2575 def dfmtstr(max):
2575 def dfmtstr(max):
2576 return basedfmtstr % len(str(max))
2576 return basedfmtstr % len(str(max))
2577 def pcfmtstr(max, padding=0):
2577 def pcfmtstr(max, padding=0):
2578 return basepcfmtstr % (len(str(max)), ' ' * padding)
2578 return basepcfmtstr % (len(str(max)), ' ' * padding)
2579
2579
2580 def pcfmt(value, total):
2580 def pcfmt(value, total):
2581 return (value, 100 * float(value) / total)
2581 return (value, 100 * float(value) / total)
2582
2582
2583 ui.write(('format : %d\n') % format)
2583 ui.write(('format : %d\n') % format)
2584 ui.write(('flags : %s\n') % ', '.join(flags))
2584 ui.write(('flags : %s\n') % ', '.join(flags))
2585
2585
2586 ui.write('\n')
2586 ui.write('\n')
2587 fmt = pcfmtstr(totalsize)
2587 fmt = pcfmtstr(totalsize)
2588 fmt2 = dfmtstr(totalsize)
2588 fmt2 = dfmtstr(totalsize)
2589 ui.write(('revisions : ') + fmt2 % numrevs)
2589 ui.write(('revisions : ') + fmt2 % numrevs)
2590 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2590 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2591 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2591 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2592 ui.write(('revisions : ') + fmt2 % numrevs)
2592 ui.write(('revisions : ') + fmt2 % numrevs)
2593 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2593 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2594 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2594 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2595 ui.write(('revision size : ') + fmt2 % totalsize)
2595 ui.write(('revision size : ') + fmt2 % totalsize)
2596 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2596 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2597 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2597 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2598
2598
2599 ui.write('\n')
2599 ui.write('\n')
2600 fmt = dfmtstr(max(avgchainlen, compratio))
2600 fmt = dfmtstr(max(avgchainlen, compratio))
2601 ui.write(('avg chain length : ') + fmt % avgchainlen)
2601 ui.write(('avg chain length : ') + fmt % avgchainlen)
2602 ui.write(('compression ratio : ') + fmt % compratio)
2602 ui.write(('compression ratio : ') + fmt % compratio)
2603
2603
2604 if format > 0:
2604 if format > 0:
2605 ui.write('\n')
2605 ui.write('\n')
2606 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2606 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2607 % tuple(datasize))
2607 % tuple(datasize))
2608 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2608 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2609 % tuple(fullsize))
2609 % tuple(fullsize))
2610 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2610 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2611 % tuple(deltasize))
2611 % tuple(deltasize))
2612
2612
2613 if numdeltas > 0:
2613 if numdeltas > 0:
2614 ui.write('\n')
2614 ui.write('\n')
2615 fmt = pcfmtstr(numdeltas)
2615 fmt = pcfmtstr(numdeltas)
2616 fmt2 = pcfmtstr(numdeltas, 4)
2616 fmt2 = pcfmtstr(numdeltas, 4)
2617 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2617 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2618 if numprev > 0:
2618 if numprev > 0:
2619 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2619 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2620 numprev))
2620 numprev))
2621 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2621 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2622 numprev))
2622 numprev))
2623 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2623 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2624 numprev))
2624 numprev))
2625 if gdelta:
2625 if gdelta:
2626 ui.write(('deltas against p1 : ')
2626 ui.write(('deltas against p1 : ')
2627 + fmt % pcfmt(nump1, numdeltas))
2627 + fmt % pcfmt(nump1, numdeltas))
2628 ui.write(('deltas against p2 : ')
2628 ui.write(('deltas against p2 : ')
2629 + fmt % pcfmt(nump2, numdeltas))
2629 + fmt % pcfmt(nump2, numdeltas))
2630 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2630 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2631 numdeltas))
2631 numdeltas))
2632
2632
2633 @command('debugrevspec',
2633 @command('debugrevspec',
2634 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2634 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2635 ('REVSPEC'))
2635 ('REVSPEC'))
2636 def debugrevspec(ui, repo, expr, **opts):
2636 def debugrevspec(ui, repo, expr, **opts):
2637 """parse and apply a revision specification
2637 """parse and apply a revision specification
2638
2638
2639 Use --verbose to print the parsed tree before and after aliases
2639 Use --verbose to print the parsed tree before and after aliases
2640 expansion.
2640 expansion.
2641 """
2641 """
2642 if ui.verbose:
2642 if ui.verbose:
2643 tree = revset.parse(expr)[0]
2643 tree = revset.parse(expr)[0]
2644 ui.note(revset.prettyformat(tree), "\n")
2644 ui.note(revset.prettyformat(tree), "\n")
2645 newtree = revset.findaliases(ui, tree)
2645 newtree = revset.findaliases(ui, tree)
2646 if newtree != tree:
2646 if newtree != tree:
2647 ui.note(revset.prettyformat(newtree), "\n")
2647 ui.note(revset.prettyformat(newtree), "\n")
2648 if opts["optimize"]:
2648 if opts["optimize"]:
2649 weight, optimizedtree = revset.optimize(newtree, True)
2649 weight, optimizedtree = revset.optimize(newtree, True)
2650 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2650 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2651 func = revset.match(ui, expr)
2651 func = revset.match(ui, expr)
2652 for c in func(repo, revset.spanset(repo)):
2652 for c in func(repo, revset.spanset(repo)):
2653 ui.write("%s\n" % c)
2653 ui.write("%s\n" % c)
2654
2654
2655 @command('debugsetparents', [], _('REV1 [REV2]'))
2655 @command('debugsetparents', [], _('REV1 [REV2]'))
2656 def debugsetparents(ui, repo, rev1, rev2=None):
2656 def debugsetparents(ui, repo, rev1, rev2=None):
2657 """manually set the parents of the current working directory
2657 """manually set the parents of the current working directory
2658
2658
2659 This is useful for writing repository conversion tools, but should
2659 This is useful for writing repository conversion tools, but should
2660 be used with care.
2660 be used with care.
2661
2661
2662 Returns 0 on success.
2662 Returns 0 on success.
2663 """
2663 """
2664
2664
2665 r1 = scmutil.revsingle(repo, rev1).node()
2665 r1 = scmutil.revsingle(repo, rev1).node()
2666 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2666 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2667
2667
2668 wlock = repo.wlock()
2668 wlock = repo.wlock()
2669 try:
2669 try:
2670 repo.setparents(r1, r2)
2670 repo.setparents(r1, r2)
2671 finally:
2671 finally:
2672 wlock.release()
2672 wlock.release()
2673
2673
2674 @command('debugdirstate|debugstate',
2674 @command('debugdirstate|debugstate',
2675 [('', 'nodates', None, _('do not display the saved mtime')),
2675 [('', 'nodates', None, _('do not display the saved mtime')),
2676 ('', 'datesort', None, _('sort by saved mtime'))],
2676 ('', 'datesort', None, _('sort by saved mtime'))],
2677 _('[OPTION]...'))
2677 _('[OPTION]...'))
2678 def debugstate(ui, repo, nodates=None, datesort=None):
2678 def debugstate(ui, repo, nodates=None, datesort=None):
2679 """show the contents of the current dirstate"""
2679 """show the contents of the current dirstate"""
2680 timestr = ""
2680 timestr = ""
2681 showdate = not nodates
2681 showdate = not nodates
2682 if datesort:
2682 if datesort:
2683 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2683 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2684 else:
2684 else:
2685 keyfunc = None # sort by filename
2685 keyfunc = None # sort by filename
2686 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2686 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2687 if showdate:
2687 if showdate:
2688 if ent[3] == -1:
2688 if ent[3] == -1:
2689 # Pad or slice to locale representation
2689 # Pad or slice to locale representation
2690 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2690 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2691 time.localtime(0)))
2691 time.localtime(0)))
2692 timestr = 'unset'
2692 timestr = 'unset'
2693 timestr = (timestr[:locale_len] +
2693 timestr = (timestr[:locale_len] +
2694 ' ' * (locale_len - len(timestr)))
2694 ' ' * (locale_len - len(timestr)))
2695 else:
2695 else:
2696 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2696 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2697 time.localtime(ent[3]))
2697 time.localtime(ent[3]))
2698 if ent[1] & 020000:
2698 if ent[1] & 020000:
2699 mode = 'lnk'
2699 mode = 'lnk'
2700 else:
2700 else:
2701 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2701 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2702 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2702 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2703 for f in repo.dirstate.copies():
2703 for f in repo.dirstate.copies():
2704 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2704 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2705
2705
2706 @command('debugsub',
2706 @command('debugsub',
2707 [('r', 'rev', '',
2707 [('r', 'rev', '',
2708 _('revision to check'), _('REV'))],
2708 _('revision to check'), _('REV'))],
2709 _('[-r REV] [REV]'))
2709 _('[-r REV] [REV]'))
2710 def debugsub(ui, repo, rev=None):
2710 def debugsub(ui, repo, rev=None):
2711 ctx = scmutil.revsingle(repo, rev, None)
2711 ctx = scmutil.revsingle(repo, rev, None)
2712 for k, v in sorted(ctx.substate.items()):
2712 for k, v in sorted(ctx.substate.items()):
2713 ui.write(('path %s\n') % k)
2713 ui.write(('path %s\n') % k)
2714 ui.write((' source %s\n') % v[0])
2714 ui.write((' source %s\n') % v[0])
2715 ui.write((' revision %s\n') % v[1])
2715 ui.write((' revision %s\n') % v[1])
2716
2716
2717 @command('debugsuccessorssets',
2717 @command('debugsuccessorssets',
2718 [],
2718 [],
2719 _('[REV]'))
2719 _('[REV]'))
2720 def debugsuccessorssets(ui, repo, *revs):
2720 def debugsuccessorssets(ui, repo, *revs):
2721 """show set of successors for revision
2721 """show set of successors for revision
2722
2722
2723 A successors set of changeset A is a consistent group of revisions that
2723 A successors set of changeset A is a consistent group of revisions that
2724 succeed A. It contains non-obsolete changesets only.
2724 succeed A. It contains non-obsolete changesets only.
2725
2725
2726 In most cases a changeset A has a single successors set containing a single
2726 In most cases a changeset A has a single successors set containing a single
2727 successor (changeset A replaced by A').
2727 successor (changeset A replaced by A').
2728
2728
2729 A changeset that is made obsolete with no successors are called "pruned".
2729 A changeset that is made obsolete with no successors are called "pruned".
2730 Such changesets have no successors sets at all.
2730 Such changesets have no successors sets at all.
2731
2731
2732 A changeset that has been "split" will have a successors set containing
2732 A changeset that has been "split" will have a successors set containing
2733 more than one successor.
2733 more than one successor.
2734
2734
2735 A changeset that has been rewritten in multiple different ways is called
2735 A changeset that has been rewritten in multiple different ways is called
2736 "divergent". Such changesets have multiple successor sets (each of which
2736 "divergent". Such changesets have multiple successor sets (each of which
2737 may also be split, i.e. have multiple successors).
2737 may also be split, i.e. have multiple successors).
2738
2738
2739 Results are displayed as follows::
2739 Results are displayed as follows::
2740
2740
2741 <rev1>
2741 <rev1>
2742 <successors-1A>
2742 <successors-1A>
2743 <rev2>
2743 <rev2>
2744 <successors-2A>
2744 <successors-2A>
2745 <successors-2B1> <successors-2B2> <successors-2B3>
2745 <successors-2B1> <successors-2B2> <successors-2B3>
2746
2746
2747 Here rev2 has two possible (i.e. divergent) successors sets. The first
2747 Here rev2 has two possible (i.e. divergent) successors sets. The first
2748 holds one element, whereas the second holds three (i.e. the changeset has
2748 holds one element, whereas the second holds three (i.e. the changeset has
2749 been split).
2749 been split).
2750 """
2750 """
2751 # passed to successorssets caching computation from one call to another
2751 # passed to successorssets caching computation from one call to another
2752 cache = {}
2752 cache = {}
2753 ctx2str = str
2753 ctx2str = str
2754 node2str = short
2754 node2str = short
2755 if ui.debug():
2755 if ui.debug():
2756 def ctx2str(ctx):
2756 def ctx2str(ctx):
2757 return ctx.hex()
2757 return ctx.hex()
2758 node2str = hex
2758 node2str = hex
2759 for rev in scmutil.revrange(repo, revs):
2759 for rev in scmutil.revrange(repo, revs):
2760 ctx = repo[rev]
2760 ctx = repo[rev]
2761 ui.write('%s\n'% ctx2str(ctx))
2761 ui.write('%s\n'% ctx2str(ctx))
2762 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2762 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2763 if succsset:
2763 if succsset:
2764 ui.write(' ')
2764 ui.write(' ')
2765 ui.write(node2str(succsset[0]))
2765 ui.write(node2str(succsset[0]))
2766 for node in succsset[1:]:
2766 for node in succsset[1:]:
2767 ui.write(' ')
2767 ui.write(' ')
2768 ui.write(node2str(node))
2768 ui.write(node2str(node))
2769 ui.write('\n')
2769 ui.write('\n')
2770
2770
2771 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2771 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2772 def debugwalk(ui, repo, *pats, **opts):
2772 def debugwalk(ui, repo, *pats, **opts):
2773 """show how files match on given patterns"""
2773 """show how files match on given patterns"""
2774 m = scmutil.match(repo[None], pats, opts)
2774 m = scmutil.match(repo[None], pats, opts)
2775 items = list(repo.walk(m))
2775 items = list(repo.walk(m))
2776 if not items:
2776 if not items:
2777 return
2777 return
2778 f = lambda fn: fn
2778 f = lambda fn: fn
2779 if ui.configbool('ui', 'slash') and os.sep != '/':
2779 if ui.configbool('ui', 'slash') and os.sep != '/':
2780 f = lambda fn: util.normpath(fn)
2780 f = lambda fn: util.normpath(fn)
2781 fmt = 'f %%-%ds %%-%ds %%s' % (
2781 fmt = 'f %%-%ds %%-%ds %%s' % (
2782 max([len(abs) for abs in items]),
2782 max([len(abs) for abs in items]),
2783 max([len(m.rel(abs)) for abs in items]))
2783 max([len(m.rel(abs)) for abs in items]))
2784 for abs in items:
2784 for abs in items:
2785 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2785 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2786 ui.write("%s\n" % line.rstrip())
2786 ui.write("%s\n" % line.rstrip())
2787
2787
2788 @command('debugwireargs',
2788 @command('debugwireargs',
2789 [('', 'three', '', 'three'),
2789 [('', 'three', '', 'three'),
2790 ('', 'four', '', 'four'),
2790 ('', 'four', '', 'four'),
2791 ('', 'five', '', 'five'),
2791 ('', 'five', '', 'five'),
2792 ] + remoteopts,
2792 ] + remoteopts,
2793 _('REPO [OPTIONS]... [ONE [TWO]]'))
2793 _('REPO [OPTIONS]... [ONE [TWO]]'))
2794 def debugwireargs(ui, repopath, *vals, **opts):
2794 def debugwireargs(ui, repopath, *vals, **opts):
2795 repo = hg.peer(ui, opts, repopath)
2795 repo = hg.peer(ui, opts, repopath)
2796 for opt in remoteopts:
2796 for opt in remoteopts:
2797 del opts[opt[1]]
2797 del opts[opt[1]]
2798 args = {}
2798 args = {}
2799 for k, v in opts.iteritems():
2799 for k, v in opts.iteritems():
2800 if v:
2800 if v:
2801 args[k] = v
2801 args[k] = v
2802 # run twice to check that we don't mess up the stream for the next command
2802 # run twice to check that we don't mess up the stream for the next command
2803 res1 = repo.debugwireargs(*vals, **args)
2803 res1 = repo.debugwireargs(*vals, **args)
2804 res2 = repo.debugwireargs(*vals, **args)
2804 res2 = repo.debugwireargs(*vals, **args)
2805 ui.write("%s\n" % res1)
2805 ui.write("%s\n" % res1)
2806 if res1 != res2:
2806 if res1 != res2:
2807 ui.warn("%s\n" % res2)
2807 ui.warn("%s\n" % res2)
2808
2808
2809 @command('^diff',
2809 @command('^diff',
2810 [('r', 'rev', [], _('revision'), _('REV')),
2810 [('r', 'rev', [], _('revision'), _('REV')),
2811 ('c', 'change', '', _('change made by revision'), _('REV'))
2811 ('c', 'change', '', _('change made by revision'), _('REV'))
2812 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2812 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2813 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2813 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2814 def diff(ui, repo, *pats, **opts):
2814 def diff(ui, repo, *pats, **opts):
2815 """diff repository (or selected files)
2815 """diff repository (or selected files)
2816
2816
2817 Show differences between revisions for the specified files.
2817 Show differences between revisions for the specified files.
2818
2818
2819 Differences between files are shown using the unified diff format.
2819 Differences between files are shown using the unified diff format.
2820
2820
2821 .. note::
2821 .. note::
2822
2822
2823 diff may generate unexpected results for merges, as it will
2823 diff may generate unexpected results for merges, as it will
2824 default to comparing against the working directory's first
2824 default to comparing against the working directory's first
2825 parent changeset if no revisions are specified.
2825 parent changeset if no revisions are specified.
2826
2826
2827 When two revision arguments are given, then changes are shown
2827 When two revision arguments are given, then changes are shown
2828 between those revisions. If only one revision is specified then
2828 between those revisions. If only one revision is specified then
2829 that revision is compared to the working directory, and, when no
2829 that revision is compared to the working directory, and, when no
2830 revisions are specified, the working directory files are compared
2830 revisions are specified, the working directory files are compared
2831 to its parent.
2831 to its parent.
2832
2832
2833 Alternatively you can specify -c/--change with a revision to see
2833 Alternatively you can specify -c/--change with a revision to see
2834 the changes in that changeset relative to its first parent.
2834 the changes in that changeset relative to its first parent.
2835
2835
2836 Without the -a/--text option, diff will avoid generating diffs of
2836 Without the -a/--text option, diff will avoid generating diffs of
2837 files it detects as binary. With -a, diff will generate a diff
2837 files it detects as binary. With -a, diff will generate a diff
2838 anyway, probably with undesirable results.
2838 anyway, probably with undesirable results.
2839
2839
2840 Use the -g/--git option to generate diffs in the git extended diff
2840 Use the -g/--git option to generate diffs in the git extended diff
2841 format. For more information, read :hg:`help diffs`.
2841 format. For more information, read :hg:`help diffs`.
2842
2842
2843 .. container:: verbose
2843 .. container:: verbose
2844
2844
2845 Examples:
2845 Examples:
2846
2846
2847 - compare a file in the current working directory to its parent::
2847 - compare a file in the current working directory to its parent::
2848
2848
2849 hg diff foo.c
2849 hg diff foo.c
2850
2850
2851 - compare two historical versions of a directory, with rename info::
2851 - compare two historical versions of a directory, with rename info::
2852
2852
2853 hg diff --git -r 1.0:1.2 lib/
2853 hg diff --git -r 1.0:1.2 lib/
2854
2854
2855 - get change stats relative to the last change on some date::
2855 - get change stats relative to the last change on some date::
2856
2856
2857 hg diff --stat -r "date('may 2')"
2857 hg diff --stat -r "date('may 2')"
2858
2858
2859 - diff all newly-added files that contain a keyword::
2859 - diff all newly-added files that contain a keyword::
2860
2860
2861 hg diff "set:added() and grep(GNU)"
2861 hg diff "set:added() and grep(GNU)"
2862
2862
2863 - compare a revision and its parents::
2863 - compare a revision and its parents::
2864
2864
2865 hg diff -c 9353 # compare against first parent
2865 hg diff -c 9353 # compare against first parent
2866 hg diff -r 9353^:9353 # same using revset syntax
2866 hg diff -r 9353^:9353 # same using revset syntax
2867 hg diff -r 9353^2:9353 # compare against the second parent
2867 hg diff -r 9353^2:9353 # compare against the second parent
2868
2868
2869 Returns 0 on success.
2869 Returns 0 on success.
2870 """
2870 """
2871
2871
2872 revs = opts.get('rev')
2872 revs = opts.get('rev')
2873 change = opts.get('change')
2873 change = opts.get('change')
2874 stat = opts.get('stat')
2874 stat = opts.get('stat')
2875 reverse = opts.get('reverse')
2875 reverse = opts.get('reverse')
2876
2876
2877 if revs and change:
2877 if revs and change:
2878 msg = _('cannot specify --rev and --change at the same time')
2878 msg = _('cannot specify --rev and --change at the same time')
2879 raise util.Abort(msg)
2879 raise util.Abort(msg)
2880 elif change:
2880 elif change:
2881 node2 = scmutil.revsingle(repo, change, None).node()
2881 node2 = scmutil.revsingle(repo, change, None).node()
2882 node1 = repo[node2].p1().node()
2882 node1 = repo[node2].p1().node()
2883 else:
2883 else:
2884 node1, node2 = scmutil.revpair(repo, revs)
2884 node1, node2 = scmutil.revpair(repo, revs)
2885
2885
2886 if reverse:
2886 if reverse:
2887 node1, node2 = node2, node1
2887 node1, node2 = node2, node1
2888
2888
2889 diffopts = patch.diffopts(ui, opts)
2889 diffopts = patch.diffopts(ui, opts)
2890 m = scmutil.match(repo[node2], pats, opts)
2890 m = scmutil.match(repo[node2], pats, opts)
2891 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2891 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2892 listsubrepos=opts.get('subrepos'))
2892 listsubrepos=opts.get('subrepos'))
2893
2893
2894 @command('^export',
2894 @command('^export',
2895 [('o', 'output', '',
2895 [('o', 'output', '',
2896 _('print output to file with formatted name'), _('FORMAT')),
2896 _('print output to file with formatted name'), _('FORMAT')),
2897 ('', 'switch-parent', None, _('diff against the second parent')),
2897 ('', 'switch-parent', None, _('diff against the second parent')),
2898 ('r', 'rev', [], _('revisions to export'), _('REV')),
2898 ('r', 'rev', [], _('revisions to export'), _('REV')),
2899 ] + diffopts,
2899 ] + diffopts,
2900 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2900 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2901 def export(ui, repo, *changesets, **opts):
2901 def export(ui, repo, *changesets, **opts):
2902 """dump the header and diffs for one or more changesets
2902 """dump the header and diffs for one or more changesets
2903
2903
2904 Print the changeset header and diffs for one or more revisions.
2904 Print the changeset header and diffs for one or more revisions.
2905 If no revision is given, the parent of the working directory is used.
2905 If no revision is given, the parent of the working directory is used.
2906
2906
2907 The information shown in the changeset header is: author, date,
2907 The information shown in the changeset header is: author, date,
2908 branch name (if non-default), changeset hash, parent(s) and commit
2908 branch name (if non-default), changeset hash, parent(s) and commit
2909 comment.
2909 comment.
2910
2910
2911 .. note::
2911 .. note::
2912
2912
2913 export may generate unexpected diff output for merge
2913 export may generate unexpected diff output for merge
2914 changesets, as it will compare the merge changeset against its
2914 changesets, as it will compare the merge changeset against its
2915 first parent only.
2915 first parent only.
2916
2916
2917 Output may be to a file, in which case the name of the file is
2917 Output may be to a file, in which case the name of the file is
2918 given using a format string. The formatting rules are as follows:
2918 given using a format string. The formatting rules are as follows:
2919
2919
2920 :``%%``: literal "%" character
2920 :``%%``: literal "%" character
2921 :``%H``: changeset hash (40 hexadecimal digits)
2921 :``%H``: changeset hash (40 hexadecimal digits)
2922 :``%N``: number of patches being generated
2922 :``%N``: number of patches being generated
2923 :``%R``: changeset revision number
2923 :``%R``: changeset revision number
2924 :``%b``: basename of the exporting repository
2924 :``%b``: basename of the exporting repository
2925 :``%h``: short-form changeset hash (12 hexadecimal digits)
2925 :``%h``: short-form changeset hash (12 hexadecimal digits)
2926 :``%m``: first line of the commit message (only alphanumeric characters)
2926 :``%m``: first line of the commit message (only alphanumeric characters)
2927 :``%n``: zero-padded sequence number, starting at 1
2927 :``%n``: zero-padded sequence number, starting at 1
2928 :``%r``: zero-padded changeset revision number
2928 :``%r``: zero-padded changeset revision number
2929
2929
2930 Without the -a/--text option, export will avoid generating diffs
2930 Without the -a/--text option, export will avoid generating diffs
2931 of files it detects as binary. With -a, export will generate a
2931 of files it detects as binary. With -a, export will generate a
2932 diff anyway, probably with undesirable results.
2932 diff anyway, probably with undesirable results.
2933
2933
2934 Use the -g/--git option to generate diffs in the git extended diff
2934 Use the -g/--git option to generate diffs in the git extended diff
2935 format. See :hg:`help diffs` for more information.
2935 format. See :hg:`help diffs` for more information.
2936
2936
2937 With the --switch-parent option, the diff will be against the
2937 With the --switch-parent option, the diff will be against the
2938 second parent. It can be useful to review a merge.
2938 second parent. It can be useful to review a merge.
2939
2939
2940 .. container:: verbose
2940 .. container:: verbose
2941
2941
2942 Examples:
2942 Examples:
2943
2943
2944 - use export and import to transplant a bugfix to the current
2944 - use export and import to transplant a bugfix to the current
2945 branch::
2945 branch::
2946
2946
2947 hg export -r 9353 | hg import -
2947 hg export -r 9353 | hg import -
2948
2948
2949 - export all the changesets between two revisions to a file with
2949 - export all the changesets between two revisions to a file with
2950 rename information::
2950 rename information::
2951
2951
2952 hg export --git -r 123:150 > changes.txt
2952 hg export --git -r 123:150 > changes.txt
2953
2953
2954 - split outgoing changes into a series of patches with
2954 - split outgoing changes into a series of patches with
2955 descriptive names::
2955 descriptive names::
2956
2956
2957 hg export -r "outgoing()" -o "%n-%m.patch"
2957 hg export -r "outgoing()" -o "%n-%m.patch"
2958
2958
2959 Returns 0 on success.
2959 Returns 0 on success.
2960 """
2960 """
2961 changesets += tuple(opts.get('rev', []))
2961 changesets += tuple(opts.get('rev', []))
2962 if not changesets:
2962 if not changesets:
2963 changesets = ['.']
2963 changesets = ['.']
2964 revs = scmutil.revrange(repo, changesets)
2964 revs = scmutil.revrange(repo, changesets)
2965 if not revs:
2965 if not revs:
2966 raise util.Abort(_("export requires at least one changeset"))
2966 raise util.Abort(_("export requires at least one changeset"))
2967 if len(revs) > 1:
2967 if len(revs) > 1:
2968 ui.note(_('exporting patches:\n'))
2968 ui.note(_('exporting patches:\n'))
2969 else:
2969 else:
2970 ui.note(_('exporting patch:\n'))
2970 ui.note(_('exporting patch:\n'))
2971 cmdutil.export(repo, revs, template=opts.get('output'),
2971 cmdutil.export(repo, revs, template=opts.get('output'),
2972 switch_parent=opts.get('switch_parent'),
2972 switch_parent=opts.get('switch_parent'),
2973 opts=patch.diffopts(ui, opts))
2973 opts=patch.diffopts(ui, opts))
2974
2974
2975 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2975 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2976 def forget(ui, repo, *pats, **opts):
2976 def forget(ui, repo, *pats, **opts):
2977 """forget the specified files on the next commit
2977 """forget the specified files on the next commit
2978
2978
2979 Mark the specified files so they will no longer be tracked
2979 Mark the specified files so they will no longer be tracked
2980 after the next commit.
2980 after the next commit.
2981
2981
2982 This only removes files from the current branch, not from the
2982 This only removes files from the current branch, not from the
2983 entire project history, and it does not delete them from the
2983 entire project history, and it does not delete them from the
2984 working directory.
2984 working directory.
2985
2985
2986 To undo a forget before the next commit, see :hg:`add`.
2986 To undo a forget before the next commit, see :hg:`add`.
2987
2987
2988 .. container:: verbose
2988 .. container:: verbose
2989
2989
2990 Examples:
2990 Examples:
2991
2991
2992 - forget newly-added binary files::
2992 - forget newly-added binary files::
2993
2993
2994 hg forget "set:added() and binary()"
2994 hg forget "set:added() and binary()"
2995
2995
2996 - forget files that would be excluded by .hgignore::
2996 - forget files that would be excluded by .hgignore::
2997
2997
2998 hg forget "set:hgignore()"
2998 hg forget "set:hgignore()"
2999
2999
3000 Returns 0 on success.
3000 Returns 0 on success.
3001 """
3001 """
3002
3002
3003 if not pats:
3003 if not pats:
3004 raise util.Abort(_('no files specified'))
3004 raise util.Abort(_('no files specified'))
3005
3005
3006 m = scmutil.match(repo[None], pats, opts)
3006 m = scmutil.match(repo[None], pats, opts)
3007 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3007 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3008 return rejected and 1 or 0
3008 return rejected and 1 or 0
3009
3009
3010 @command(
3010 @command(
3011 'graft',
3011 'graft',
3012 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3012 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3013 ('c', 'continue', False, _('resume interrupted graft')),
3013 ('c', 'continue', False, _('resume interrupted graft')),
3014 ('e', 'edit', False, _('invoke editor on commit messages')),
3014 ('e', 'edit', False, _('invoke editor on commit messages')),
3015 ('', 'log', None, _('append graft info to log message')),
3015 ('', 'log', None, _('append graft info to log message')),
3016 ('D', 'currentdate', False,
3016 ('D', 'currentdate', False,
3017 _('record the current date as commit date')),
3017 _('record the current date as commit date')),
3018 ('U', 'currentuser', False,
3018 ('U', 'currentuser', False,
3019 _('record the current user as committer'), _('DATE'))]
3019 _('record the current user as committer'), _('DATE'))]
3020 + commitopts2 + mergetoolopts + dryrunopts,
3020 + commitopts2 + mergetoolopts + dryrunopts,
3021 _('[OPTION]... [-r] REV...'))
3021 _('[OPTION]... [-r] REV...'))
3022 def graft(ui, repo, *revs, **opts):
3022 def graft(ui, repo, *revs, **opts):
3023 '''copy changes from other branches onto the current branch
3023 '''copy changes from other branches onto the current branch
3024
3024
3025 This command uses Mercurial's merge logic to copy individual
3025 This command uses Mercurial's merge logic to copy individual
3026 changes from other branches without merging branches in the
3026 changes from other branches without merging branches in the
3027 history graph. This is sometimes known as 'backporting' or
3027 history graph. This is sometimes known as 'backporting' or
3028 'cherry-picking'. By default, graft will copy user, date, and
3028 'cherry-picking'. By default, graft will copy user, date, and
3029 description from the source changesets.
3029 description from the source changesets.
3030
3030
3031 Changesets that are ancestors of the current revision, that have
3031 Changesets that are ancestors of the current revision, that have
3032 already been grafted, or that are merges will be skipped.
3032 already been grafted, or that are merges will be skipped.
3033
3033
3034 If --log is specified, log messages will have a comment appended
3034 If --log is specified, log messages will have a comment appended
3035 of the form::
3035 of the form::
3036
3036
3037 (grafted from CHANGESETHASH)
3037 (grafted from CHANGESETHASH)
3038
3038
3039 If a graft merge results in conflicts, the graft process is
3039 If a graft merge results in conflicts, the graft process is
3040 interrupted so that the current merge can be manually resolved.
3040 interrupted so that the current merge can be manually resolved.
3041 Once all conflicts are addressed, the graft process can be
3041 Once all conflicts are addressed, the graft process can be
3042 continued with the -c/--continue option.
3042 continued with the -c/--continue option.
3043
3043
3044 .. note::
3044 .. note::
3045
3045
3046 The -c/--continue option does not reapply earlier options.
3046 The -c/--continue option does not reapply earlier options.
3047
3047
3048 .. container:: verbose
3048 .. container:: verbose
3049
3049
3050 Examples:
3050 Examples:
3051
3051
3052 - copy a single change to the stable branch and edit its description::
3052 - copy a single change to the stable branch and edit its description::
3053
3053
3054 hg update stable
3054 hg update stable
3055 hg graft --edit 9393
3055 hg graft --edit 9393
3056
3056
3057 - graft a range of changesets with one exception, updating dates::
3057 - graft a range of changesets with one exception, updating dates::
3058
3058
3059 hg graft -D "2085::2093 and not 2091"
3059 hg graft -D "2085::2093 and not 2091"
3060
3060
3061 - continue a graft after resolving conflicts::
3061 - continue a graft after resolving conflicts::
3062
3062
3063 hg graft -c
3063 hg graft -c
3064
3064
3065 - show the source of a grafted changeset::
3065 - show the source of a grafted changeset::
3066
3066
3067 hg log --debug -r .
3067 hg log --debug -r .
3068
3068
3069 Returns 0 on successful completion.
3069 Returns 0 on successful completion.
3070 '''
3070 '''
3071
3071
3072 revs = list(revs)
3072 revs = list(revs)
3073 revs.extend(opts['rev'])
3073 revs.extend(opts['rev'])
3074
3074
3075 if not opts.get('user') and opts.get('currentuser'):
3075 if not opts.get('user') and opts.get('currentuser'):
3076 opts['user'] = ui.username()
3076 opts['user'] = ui.username()
3077 if not opts.get('date') and opts.get('currentdate'):
3077 if not opts.get('date') and opts.get('currentdate'):
3078 opts['date'] = "%d %d" % util.makedate()
3078 opts['date'] = "%d %d" % util.makedate()
3079
3079
3080 editor = None
3080 editor = None
3081 if opts.get('edit'):
3081 if opts.get('edit'):
3082 editor = cmdutil.commitforceeditor
3082 editor = cmdutil.commitforceeditor
3083
3083
3084 cont = False
3084 cont = False
3085 if opts['continue']:
3085 if opts['continue']:
3086 cont = True
3086 cont = True
3087 if revs:
3087 if revs:
3088 raise util.Abort(_("can't specify --continue and revisions"))
3088 raise util.Abort(_("can't specify --continue and revisions"))
3089 # read in unfinished revisions
3089 # read in unfinished revisions
3090 try:
3090 try:
3091 nodes = repo.opener.read('graftstate').splitlines()
3091 nodes = repo.opener.read('graftstate').splitlines()
3092 revs = [repo[node].rev() for node in nodes]
3092 revs = [repo[node].rev() for node in nodes]
3093 except IOError, inst:
3093 except IOError, inst:
3094 if inst.errno != errno.ENOENT:
3094 if inst.errno != errno.ENOENT:
3095 raise
3095 raise
3096 raise util.Abort(_("no graft state found, can't continue"))
3096 raise util.Abort(_("no graft state found, can't continue"))
3097 else:
3097 else:
3098 cmdutil.checkunfinished(repo)
3098 cmdutil.checkunfinished(repo)
3099 cmdutil.bailifchanged(repo)
3099 cmdutil.bailifchanged(repo)
3100 if not revs:
3100 if not revs:
3101 raise util.Abort(_('no revisions specified'))
3101 raise util.Abort(_('no revisions specified'))
3102 revs = scmutil.revrange(repo, revs)
3102 revs = scmutil.revrange(repo, revs)
3103
3103
3104 # check for merges
3104 # check for merges
3105 for rev in repo.revs('%ld and merge()', revs):
3105 for rev in repo.revs('%ld and merge()', revs):
3106 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3106 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3107 revs.remove(rev)
3107 revs.remove(rev)
3108 if not revs:
3108 if not revs:
3109 return -1
3109 return -1
3110
3110
3111 # check for ancestors of dest branch
3111 # check for ancestors of dest branch
3112 crev = repo['.'].rev()
3112 crev = repo['.'].rev()
3113 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3113 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3114 # Cannot use x.remove(y) on smart set, this has to be a list.
3114 # Cannot use x.remove(y) on smart set, this has to be a list.
3115 # XXX make this lazy in the future
3115 # XXX make this lazy in the future
3116 revs = list(revs)
3116 revs = list(revs)
3117 # don't mutate while iterating, create a copy
3117 # don't mutate while iterating, create a copy
3118 for rev in list(revs):
3118 for rev in list(revs):
3119 if rev in ancestors:
3119 if rev in ancestors:
3120 ui.warn(_('skipping ancestor revision %s\n') % rev)
3120 ui.warn(_('skipping ancestor revision %s\n') % rev)
3121 # XXX remove on list is slow
3121 # XXX remove on list is slow
3122 revs.remove(rev)
3122 revs.remove(rev)
3123 if not revs:
3123 if not revs:
3124 return -1
3124 return -1
3125
3125
3126 # analyze revs for earlier grafts
3126 # analyze revs for earlier grafts
3127 ids = {}
3127 ids = {}
3128 for ctx in repo.set("%ld", revs):
3128 for ctx in repo.set("%ld", revs):
3129 ids[ctx.hex()] = ctx.rev()
3129 ids[ctx.hex()] = ctx.rev()
3130 n = ctx.extra().get('source')
3130 n = ctx.extra().get('source')
3131 if n:
3131 if n:
3132 ids[n] = ctx.rev()
3132 ids[n] = ctx.rev()
3133
3133
3134 # check ancestors for earlier grafts
3134 # check ancestors for earlier grafts
3135 ui.debug('scanning for duplicate grafts\n')
3135 ui.debug('scanning for duplicate grafts\n')
3136
3136
3137 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3137 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3138 ctx = repo[rev]
3138 ctx = repo[rev]
3139 n = ctx.extra().get('source')
3139 n = ctx.extra().get('source')
3140 if n in ids:
3140 if n in ids:
3141 r = repo[n].rev()
3141 r = repo[n].rev()
3142 if r in revs:
3142 if r in revs:
3143 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3143 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3144 % (r, rev))
3144 % (r, rev))
3145 revs.remove(r)
3145 revs.remove(r)
3146 elif ids[n] in revs:
3146 elif ids[n] in revs:
3147 ui.warn(_('skipping already grafted revision %s '
3147 ui.warn(_('skipping already grafted revision %s '
3148 '(%s also has origin %d)\n') % (ids[n], rev, r))
3148 '(%s also has origin %d)\n') % (ids[n], rev, r))
3149 revs.remove(ids[n])
3149 revs.remove(ids[n])
3150 elif ctx.hex() in ids:
3150 elif ctx.hex() in ids:
3151 r = ids[ctx.hex()]
3151 r = ids[ctx.hex()]
3152 ui.warn(_('skipping already grafted revision %s '
3152 ui.warn(_('skipping already grafted revision %s '
3153 '(was grafted from %d)\n') % (r, rev))
3153 '(was grafted from %d)\n') % (r, rev))
3154 revs.remove(r)
3154 revs.remove(r)
3155 if not revs:
3155 if not revs:
3156 return -1
3156 return -1
3157
3157
3158 wlock = repo.wlock()
3158 wlock = repo.wlock()
3159 try:
3159 try:
3160 current = repo['.']
3160 current = repo['.']
3161 for pos, ctx in enumerate(repo.set("%ld", revs)):
3161 for pos, ctx in enumerate(repo.set("%ld", revs)):
3162
3162
3163 ui.status(_('grafting revision %s\n') % ctx.rev())
3163 ui.status(_('grafting revision %s\n') % ctx.rev())
3164 if opts.get('dry_run'):
3164 if opts.get('dry_run'):
3165 continue
3165 continue
3166
3166
3167 source = ctx.extra().get('source')
3167 source = ctx.extra().get('source')
3168 if not source:
3168 if not source:
3169 source = ctx.hex()
3169 source = ctx.hex()
3170 extra = {'source': source}
3170 extra = {'source': source}
3171 user = ctx.user()
3171 user = ctx.user()
3172 if opts.get('user'):
3172 if opts.get('user'):
3173 user = opts['user']
3173 user = opts['user']
3174 date = ctx.date()
3174 date = ctx.date()
3175 if opts.get('date'):
3175 if opts.get('date'):
3176 date = opts['date']
3176 date = opts['date']
3177 message = ctx.description()
3177 message = ctx.description()
3178 if opts.get('log'):
3178 if opts.get('log'):
3179 message += '\n(grafted from %s)' % ctx.hex()
3179 message += '\n(grafted from %s)' % ctx.hex()
3180
3180
3181 # we don't merge the first commit when continuing
3181 # we don't merge the first commit when continuing
3182 if not cont:
3182 if not cont:
3183 # perform the graft merge with p1(rev) as 'ancestor'
3183 # perform the graft merge with p1(rev) as 'ancestor'
3184 try:
3184 try:
3185 # ui.forcemerge is an internal variable, do not document
3185 # ui.forcemerge is an internal variable, do not document
3186 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3186 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3187 'graft')
3187 'graft')
3188 stats = mergemod.update(repo, ctx.node(), True, True, False,
3188 stats = mergemod.update(repo, ctx.node(), True, True, False,
3189 ctx.p1().node())
3189 ctx.p1().node())
3190 finally:
3190 finally:
3191 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3191 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3192 # report any conflicts
3192 # report any conflicts
3193 if stats and stats[3] > 0:
3193 if stats and stats[3] > 0:
3194 # write out state for --continue
3194 # write out state for --continue
3195 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3195 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3196 repo.opener.write('graftstate', ''.join(nodelines))
3196 repo.opener.write('graftstate', ''.join(nodelines))
3197 raise util.Abort(
3197 raise util.Abort(
3198 _("unresolved conflicts, can't continue"),
3198 _("unresolved conflicts, can't continue"),
3199 hint=_('use hg resolve and hg graft --continue'))
3199 hint=_('use hg resolve and hg graft --continue'))
3200 else:
3200 else:
3201 cont = False
3201 cont = False
3202
3202
3203 # drop the second merge parent
3203 # drop the second merge parent
3204 repo.setparents(current.node(), nullid)
3204 repo.setparents(current.node(), nullid)
3205 repo.dirstate.write()
3205 repo.dirstate.write()
3206 # fix up dirstate for copies and renames
3206 # fix up dirstate for copies and renames
3207 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3207 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3208
3208
3209 # commit
3209 # commit
3210 node = repo.commit(text=message, user=user,
3210 node = repo.commit(text=message, user=user,
3211 date=date, extra=extra, editor=editor)
3211 date=date, extra=extra, editor=editor)
3212 if node is None:
3212 if node is None:
3213 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3213 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3214 else:
3214 else:
3215 current = repo[node]
3215 current = repo[node]
3216 finally:
3216 finally:
3217 wlock.release()
3217 wlock.release()
3218
3218
3219 # remove state when we complete successfully
3219 # remove state when we complete successfully
3220 if not opts.get('dry_run'):
3220 if not opts.get('dry_run'):
3221 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3221 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3222
3222
3223 return 0
3223 return 0
3224
3224
3225 @command('grep',
3225 @command('grep',
3226 [('0', 'print0', None, _('end fields with NUL')),
3226 [('0', 'print0', None, _('end fields with NUL')),
3227 ('', 'all', None, _('print all revisions that match')),
3227 ('', 'all', None, _('print all revisions that match')),
3228 ('a', 'text', None, _('treat all files as text')),
3228 ('a', 'text', None, _('treat all files as text')),
3229 ('f', 'follow', None,
3229 ('f', 'follow', None,
3230 _('follow changeset history,'
3230 _('follow changeset history,'
3231 ' or file history across copies and renames')),
3231 ' or file history across copies and renames')),
3232 ('i', 'ignore-case', None, _('ignore case when matching')),
3232 ('i', 'ignore-case', None, _('ignore case when matching')),
3233 ('l', 'files-with-matches', None,
3233 ('l', 'files-with-matches', None,
3234 _('print only filenames and revisions that match')),
3234 _('print only filenames and revisions that match')),
3235 ('n', 'line-number', None, _('print matching line numbers')),
3235 ('n', 'line-number', None, _('print matching line numbers')),
3236 ('r', 'rev', [],
3236 ('r', 'rev', [],
3237 _('only search files changed within revision range'), _('REV')),
3237 _('only search files changed within revision range'), _('REV')),
3238 ('u', 'user', None, _('list the author (long with -v)')),
3238 ('u', 'user', None, _('list the author (long with -v)')),
3239 ('d', 'date', None, _('list the date (short with -q)')),
3239 ('d', 'date', None, _('list the date (short with -q)')),
3240 ] + walkopts,
3240 ] + walkopts,
3241 _('[OPTION]... PATTERN [FILE]...'))
3241 _('[OPTION]... PATTERN [FILE]...'))
3242 def grep(ui, repo, pattern, *pats, **opts):
3242 def grep(ui, repo, pattern, *pats, **opts):
3243 """search for a pattern in specified files and revisions
3243 """search for a pattern in specified files and revisions
3244
3244
3245 Search revisions of files for a regular expression.
3245 Search revisions of files for a regular expression.
3246
3246
3247 This command behaves differently than Unix grep. It only accepts
3247 This command behaves differently than Unix grep. It only accepts
3248 Python/Perl regexps. It searches repository history, not the
3248 Python/Perl regexps. It searches repository history, not the
3249 working directory. It always prints the revision number in which a
3249 working directory. It always prints the revision number in which a
3250 match appears.
3250 match appears.
3251
3251
3252 By default, grep only prints output for the first revision of a
3252 By default, grep only prints output for the first revision of a
3253 file in which it finds a match. To get it to print every revision
3253 file in which it finds a match. To get it to print every revision
3254 that contains a change in match status ("-" for a match that
3254 that contains a change in match status ("-" for a match that
3255 becomes a non-match, or "+" for a non-match that becomes a match),
3255 becomes a non-match, or "+" for a non-match that becomes a match),
3256 use the --all flag.
3256 use the --all flag.
3257
3257
3258 Returns 0 if a match is found, 1 otherwise.
3258 Returns 0 if a match is found, 1 otherwise.
3259 """
3259 """
3260 reflags = re.M
3260 reflags = re.M
3261 if opts.get('ignore_case'):
3261 if opts.get('ignore_case'):
3262 reflags |= re.I
3262 reflags |= re.I
3263 try:
3263 try:
3264 regexp = util.compilere(pattern, reflags)
3264 regexp = util.compilere(pattern, reflags)
3265 except re.error, inst:
3265 except re.error, inst:
3266 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3266 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3267 return 1
3267 return 1
3268 sep, eol = ':', '\n'
3268 sep, eol = ':', '\n'
3269 if opts.get('print0'):
3269 if opts.get('print0'):
3270 sep = eol = '\0'
3270 sep = eol = '\0'
3271
3271
3272 getfile = util.lrucachefunc(repo.file)
3272 getfile = util.lrucachefunc(repo.file)
3273
3273
3274 def matchlines(body):
3274 def matchlines(body):
3275 begin = 0
3275 begin = 0
3276 linenum = 0
3276 linenum = 0
3277 while begin < len(body):
3277 while begin < len(body):
3278 match = regexp.search(body, begin)
3278 match = regexp.search(body, begin)
3279 if not match:
3279 if not match:
3280 break
3280 break
3281 mstart, mend = match.span()
3281 mstart, mend = match.span()
3282 linenum += body.count('\n', begin, mstart) + 1
3282 linenum += body.count('\n', begin, mstart) + 1
3283 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3283 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3284 begin = body.find('\n', mend) + 1 or len(body) + 1
3284 begin = body.find('\n', mend) + 1 or len(body) + 1
3285 lend = begin - 1
3285 lend = begin - 1
3286 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3286 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3287
3287
3288 class linestate(object):
3288 class linestate(object):
3289 def __init__(self, line, linenum, colstart, colend):
3289 def __init__(self, line, linenum, colstart, colend):
3290 self.line = line
3290 self.line = line
3291 self.linenum = linenum
3291 self.linenum = linenum
3292 self.colstart = colstart
3292 self.colstart = colstart
3293 self.colend = colend
3293 self.colend = colend
3294
3294
3295 def __hash__(self):
3295 def __hash__(self):
3296 return hash((self.linenum, self.line))
3296 return hash((self.linenum, self.line))
3297
3297
3298 def __eq__(self, other):
3298 def __eq__(self, other):
3299 return self.line == other.line
3299 return self.line == other.line
3300
3300
3301 def __iter__(self):
3301 def __iter__(self):
3302 yield (self.line[:self.colstart], '')
3302 yield (self.line[:self.colstart], '')
3303 yield (self.line[self.colstart:self.colend], 'grep.match')
3303 yield (self.line[self.colstart:self.colend], 'grep.match')
3304 rest = self.line[self.colend:]
3304 rest = self.line[self.colend:]
3305 while rest != '':
3305 while rest != '':
3306 match = regexp.search(rest)
3306 match = regexp.search(rest)
3307 if not match:
3307 if not match:
3308 yield (rest, '')
3308 yield (rest, '')
3309 break
3309 break
3310 mstart, mend = match.span()
3310 mstart, mend = match.span()
3311 yield (rest[:mstart], '')
3311 yield (rest[:mstart], '')
3312 yield (rest[mstart:mend], 'grep.match')
3312 yield (rest[mstart:mend], 'grep.match')
3313 rest = rest[mend:]
3313 rest = rest[mend:]
3314
3314
3315 matches = {}
3315 matches = {}
3316 copies = {}
3316 copies = {}
3317 def grepbody(fn, rev, body):
3317 def grepbody(fn, rev, body):
3318 matches[rev].setdefault(fn, [])
3318 matches[rev].setdefault(fn, [])
3319 m = matches[rev][fn]
3319 m = matches[rev][fn]
3320 for lnum, cstart, cend, line in matchlines(body):
3320 for lnum, cstart, cend, line in matchlines(body):
3321 s = linestate(line, lnum, cstart, cend)
3321 s = linestate(line, lnum, cstart, cend)
3322 m.append(s)
3322 m.append(s)
3323
3323
3324 def difflinestates(a, b):
3324 def difflinestates(a, b):
3325 sm = difflib.SequenceMatcher(None, a, b)
3325 sm = difflib.SequenceMatcher(None, a, b)
3326 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3326 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3327 if tag == 'insert':
3327 if tag == 'insert':
3328 for i in xrange(blo, bhi):
3328 for i in xrange(blo, bhi):
3329 yield ('+', b[i])
3329 yield ('+', b[i])
3330 elif tag == 'delete':
3330 elif tag == 'delete':
3331 for i in xrange(alo, ahi):
3331 for i in xrange(alo, ahi):
3332 yield ('-', a[i])
3332 yield ('-', a[i])
3333 elif tag == 'replace':
3333 elif tag == 'replace':
3334 for i in xrange(alo, ahi):
3334 for i in xrange(alo, ahi):
3335 yield ('-', a[i])
3335 yield ('-', a[i])
3336 for i in xrange(blo, bhi):
3336 for i in xrange(blo, bhi):
3337 yield ('+', b[i])
3337 yield ('+', b[i])
3338
3338
3339 def display(fn, ctx, pstates, states):
3339 def display(fn, ctx, pstates, states):
3340 rev = ctx.rev()
3340 rev = ctx.rev()
3341 datefunc = ui.quiet and util.shortdate or util.datestr
3341 datefunc = ui.quiet and util.shortdate or util.datestr
3342 found = False
3342 found = False
3343 @util.cachefunc
3343 @util.cachefunc
3344 def binary():
3344 def binary():
3345 flog = getfile(fn)
3345 flog = getfile(fn)
3346 return util.binary(flog.read(ctx.filenode(fn)))
3346 return util.binary(flog.read(ctx.filenode(fn)))
3347
3347
3348 if opts.get('all'):
3348 if opts.get('all'):
3349 iter = difflinestates(pstates, states)
3349 iter = difflinestates(pstates, states)
3350 else:
3350 else:
3351 iter = [('', l) for l in states]
3351 iter = [('', l) for l in states]
3352 for change, l in iter:
3352 for change, l in iter:
3353 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3353 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3354
3354
3355 if opts.get('line_number'):
3355 if opts.get('line_number'):
3356 cols.append((str(l.linenum), 'grep.linenumber'))
3356 cols.append((str(l.linenum), 'grep.linenumber'))
3357 if opts.get('all'):
3357 if opts.get('all'):
3358 cols.append((change, 'grep.change'))
3358 cols.append((change, 'grep.change'))
3359 if opts.get('user'):
3359 if opts.get('user'):
3360 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3360 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3361 if opts.get('date'):
3361 if opts.get('date'):
3362 cols.append((datefunc(ctx.date()), 'grep.date'))
3362 cols.append((datefunc(ctx.date()), 'grep.date'))
3363 for col, label in cols[:-1]:
3363 for col, label in cols[:-1]:
3364 ui.write(col, label=label)
3364 ui.write(col, label=label)
3365 ui.write(sep, label='grep.sep')
3365 ui.write(sep, label='grep.sep')
3366 ui.write(cols[-1][0], label=cols[-1][1])
3366 ui.write(cols[-1][0], label=cols[-1][1])
3367 if not opts.get('files_with_matches'):
3367 if not opts.get('files_with_matches'):
3368 ui.write(sep, label='grep.sep')
3368 ui.write(sep, label='grep.sep')
3369 if not opts.get('text') and binary():
3369 if not opts.get('text') and binary():
3370 ui.write(" Binary file matches")
3370 ui.write(" Binary file matches")
3371 else:
3371 else:
3372 for s, label in l:
3372 for s, label in l:
3373 ui.write(s, label=label)
3373 ui.write(s, label=label)
3374 ui.write(eol)
3374 ui.write(eol)
3375 found = True
3375 found = True
3376 if opts.get('files_with_matches'):
3376 if opts.get('files_with_matches'):
3377 break
3377 break
3378 return found
3378 return found
3379
3379
3380 skip = {}
3380 skip = {}
3381 revfiles = {}
3381 revfiles = {}
3382 matchfn = scmutil.match(repo[None], pats, opts)
3382 matchfn = scmutil.match(repo[None], pats, opts)
3383 found = False
3383 found = False
3384 follow = opts.get('follow')
3384 follow = opts.get('follow')
3385
3385
3386 def prep(ctx, fns):
3386 def prep(ctx, fns):
3387 rev = ctx.rev()
3387 rev = ctx.rev()
3388 pctx = ctx.p1()
3388 pctx = ctx.p1()
3389 parent = pctx.rev()
3389 parent = pctx.rev()
3390 matches.setdefault(rev, {})
3390 matches.setdefault(rev, {})
3391 matches.setdefault(parent, {})
3391 matches.setdefault(parent, {})
3392 files = revfiles.setdefault(rev, [])
3392 files = revfiles.setdefault(rev, [])
3393 for fn in fns:
3393 for fn in fns:
3394 flog = getfile(fn)
3394 flog = getfile(fn)
3395 try:
3395 try:
3396 fnode = ctx.filenode(fn)
3396 fnode = ctx.filenode(fn)
3397 except error.LookupError:
3397 except error.LookupError:
3398 continue
3398 continue
3399
3399
3400 copied = flog.renamed(fnode)
3400 copied = flog.renamed(fnode)
3401 copy = follow and copied and copied[0]
3401 copy = follow and copied and copied[0]
3402 if copy:
3402 if copy:
3403 copies.setdefault(rev, {})[fn] = copy
3403 copies.setdefault(rev, {})[fn] = copy
3404 if fn in skip:
3404 if fn in skip:
3405 if copy:
3405 if copy:
3406 skip[copy] = True
3406 skip[copy] = True
3407 continue
3407 continue
3408 files.append(fn)
3408 files.append(fn)
3409
3409
3410 if fn not in matches[rev]:
3410 if fn not in matches[rev]:
3411 grepbody(fn, rev, flog.read(fnode))
3411 grepbody(fn, rev, flog.read(fnode))
3412
3412
3413 pfn = copy or fn
3413 pfn = copy or fn
3414 if pfn not in matches[parent]:
3414 if pfn not in matches[parent]:
3415 try:
3415 try:
3416 fnode = pctx.filenode(pfn)
3416 fnode = pctx.filenode(pfn)
3417 grepbody(pfn, parent, flog.read(fnode))
3417 grepbody(pfn, parent, flog.read(fnode))
3418 except error.LookupError:
3418 except error.LookupError:
3419 pass
3419 pass
3420
3420
3421 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3421 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3422 rev = ctx.rev()
3422 rev = ctx.rev()
3423 parent = ctx.p1().rev()
3423 parent = ctx.p1().rev()
3424 for fn in sorted(revfiles.get(rev, [])):
3424 for fn in sorted(revfiles.get(rev, [])):
3425 states = matches[rev][fn]
3425 states = matches[rev][fn]
3426 copy = copies.get(rev, {}).get(fn)
3426 copy = copies.get(rev, {}).get(fn)
3427 if fn in skip:
3427 if fn in skip:
3428 if copy:
3428 if copy:
3429 skip[copy] = True
3429 skip[copy] = True
3430 continue
3430 continue
3431 pstates = matches.get(parent, {}).get(copy or fn, [])
3431 pstates = matches.get(parent, {}).get(copy or fn, [])
3432 if pstates or states:
3432 if pstates or states:
3433 r = display(fn, ctx, pstates, states)
3433 r = display(fn, ctx, pstates, states)
3434 found = found or r
3434 found = found or r
3435 if r and not opts.get('all'):
3435 if r and not opts.get('all'):
3436 skip[fn] = True
3436 skip[fn] = True
3437 if copy:
3437 if copy:
3438 skip[copy] = True
3438 skip[copy] = True
3439 del matches[rev]
3439 del matches[rev]
3440 del revfiles[rev]
3440 del revfiles[rev]
3441
3441
3442 return not found
3442 return not found
3443
3443
3444 @command('heads',
3444 @command('heads',
3445 [('r', 'rev', '',
3445 [('r', 'rev', '',
3446 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3446 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3447 ('t', 'topo', False, _('show topological heads only')),
3447 ('t', 'topo', False, _('show topological heads only')),
3448 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3448 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3449 ('c', 'closed', False, _('show normal and closed branch heads')),
3449 ('c', 'closed', False, _('show normal and closed branch heads')),
3450 ] + templateopts,
3450 ] + templateopts,
3451 _('[-ct] [-r STARTREV] [REV]...'))
3451 _('[-ct] [-r STARTREV] [REV]...'))
3452 def heads(ui, repo, *branchrevs, **opts):
3452 def heads(ui, repo, *branchrevs, **opts):
3453 """show branch heads
3453 """show branch heads
3454
3454
3455 With no arguments, show all open branch heads in the repository.
3455 With no arguments, show all open branch heads in the repository.
3456 Branch heads are changesets that have no descendants on the
3456 Branch heads are changesets that have no descendants on the
3457 same branch. They are where development generally takes place and
3457 same branch. They are where development generally takes place and
3458 are the usual targets for update and merge operations.
3458 are the usual targets for update and merge operations.
3459
3459
3460 If one or more REVs are given, only open branch heads on the
3460 If one or more REVs are given, only open branch heads on the
3461 branches associated with the specified changesets are shown. This
3461 branches associated with the specified changesets are shown. This
3462 means that you can use :hg:`heads .` to see the heads on the
3462 means that you can use :hg:`heads .` to see the heads on the
3463 currently checked-out branch.
3463 currently checked-out branch.
3464
3464
3465 If -c/--closed is specified, also show branch heads marked closed
3465 If -c/--closed is specified, also show branch heads marked closed
3466 (see :hg:`commit --close-branch`).
3466 (see :hg:`commit --close-branch`).
3467
3467
3468 If STARTREV is specified, only those heads that are descendants of
3468 If STARTREV is specified, only those heads that are descendants of
3469 STARTREV will be displayed.
3469 STARTREV will be displayed.
3470
3470
3471 If -t/--topo is specified, named branch mechanics will be ignored and only
3471 If -t/--topo is specified, named branch mechanics will be ignored and only
3472 topological heads (changesets with no children) will be shown.
3472 topological heads (changesets with no children) will be shown.
3473
3473
3474 Returns 0 if matching heads are found, 1 if not.
3474 Returns 0 if matching heads are found, 1 if not.
3475 """
3475 """
3476
3476
3477 start = None
3477 start = None
3478 if 'rev' in opts:
3478 if 'rev' in opts:
3479 start = scmutil.revsingle(repo, opts['rev'], None).node()
3479 start = scmutil.revsingle(repo, opts['rev'], None).node()
3480
3480
3481 if opts.get('topo'):
3481 if opts.get('topo'):
3482 heads = [repo[h] for h in repo.heads(start)]
3482 heads = [repo[h] for h in repo.heads(start)]
3483 else:
3483 else:
3484 heads = []
3484 heads = []
3485 for branch in repo.branchmap():
3485 for branch in repo.branchmap():
3486 heads += repo.branchheads(branch, start, opts.get('closed'))
3486 heads += repo.branchheads(branch, start, opts.get('closed'))
3487 heads = [repo[h] for h in heads]
3487 heads = [repo[h] for h in heads]
3488
3488
3489 if branchrevs:
3489 if branchrevs:
3490 branches = set(repo[br].branch() for br in branchrevs)
3490 branches = set(repo[br].branch() for br in branchrevs)
3491 heads = [h for h in heads if h.branch() in branches]
3491 heads = [h for h in heads if h.branch() in branches]
3492
3492
3493 if opts.get('active') and branchrevs:
3493 if opts.get('active') and branchrevs:
3494 dagheads = repo.heads(start)
3494 dagheads = repo.heads(start)
3495 heads = [h for h in heads if h.node() in dagheads]
3495 heads = [h for h in heads if h.node() in dagheads]
3496
3496
3497 if branchrevs:
3497 if branchrevs:
3498 haveheads = set(h.branch() for h in heads)
3498 haveheads = set(h.branch() for h in heads)
3499 if branches - haveheads:
3499 if branches - haveheads:
3500 headless = ', '.join(b for b in branches - haveheads)
3500 headless = ', '.join(b for b in branches - haveheads)
3501 msg = _('no open branch heads found on branches %s')
3501 msg = _('no open branch heads found on branches %s')
3502 if opts.get('rev'):
3502 if opts.get('rev'):
3503 msg += _(' (started at %s)') % opts['rev']
3503 msg += _(' (started at %s)') % opts['rev']
3504 ui.warn((msg + '\n') % headless)
3504 ui.warn((msg + '\n') % headless)
3505
3505
3506 if not heads:
3506 if not heads:
3507 return 1
3507 return 1
3508
3508
3509 heads = sorted(heads, key=lambda x: -x.rev())
3509 heads = sorted(heads, key=lambda x: -x.rev())
3510 displayer = cmdutil.show_changeset(ui, repo, opts)
3510 displayer = cmdutil.show_changeset(ui, repo, opts)
3511 for ctx in heads:
3511 for ctx in heads:
3512 displayer.show(ctx)
3512 displayer.show(ctx)
3513 displayer.close()
3513 displayer.close()
3514
3514
3515 @command('help',
3515 @command('help',
3516 [('e', 'extension', None, _('show only help for extensions')),
3516 [('e', 'extension', None, _('show only help for extensions')),
3517 ('c', 'command', None, _('show only help for commands')),
3517 ('c', 'command', None, _('show only help for commands')),
3518 ('k', 'keyword', '', _('show topics matching keyword')),
3518 ('k', 'keyword', '', _('show topics matching keyword')),
3519 ],
3519 ],
3520 _('[-ec] [TOPIC]'))
3520 _('[-ec] [TOPIC]'))
3521 def help_(ui, name=None, **opts):
3521 def help_(ui, name=None, **opts):
3522 """show help for a given topic or a help overview
3522 """show help for a given topic or a help overview
3523
3523
3524 With no arguments, print a list of commands with short help messages.
3524 With no arguments, print a list of commands with short help messages.
3525
3525
3526 Given a topic, extension, or command name, print help for that
3526 Given a topic, extension, or command name, print help for that
3527 topic.
3527 topic.
3528
3528
3529 Returns 0 if successful.
3529 Returns 0 if successful.
3530 """
3530 """
3531
3531
3532 textwidth = min(ui.termwidth(), 80) - 2
3532 textwidth = min(ui.termwidth(), 80) - 2
3533
3533
3534 keep = ui.verbose and ['verbose'] or []
3534 keep = ui.verbose and ['verbose'] or []
3535 text = help.help_(ui, name, **opts)
3535 text = help.help_(ui, name, **opts)
3536
3536
3537 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3537 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3538 if 'verbose' in pruned:
3538 if 'verbose' in pruned:
3539 keep.append('omitted')
3539 keep.append('omitted')
3540 else:
3540 else:
3541 keep.append('notomitted')
3541 keep.append('notomitted')
3542 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3542 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3543 ui.write(formatted)
3543 ui.write(formatted)
3544
3544
3545
3545
3546 @command('identify|id',
3546 @command('identify|id',
3547 [('r', 'rev', '',
3547 [('r', 'rev', '',
3548 _('identify the specified revision'), _('REV')),
3548 _('identify the specified revision'), _('REV')),
3549 ('n', 'num', None, _('show local revision number')),
3549 ('n', 'num', None, _('show local revision number')),
3550 ('i', 'id', None, _('show global revision id')),
3550 ('i', 'id', None, _('show global revision id')),
3551 ('b', 'branch', None, _('show branch')),
3551 ('b', 'branch', None, _('show branch')),
3552 ('t', 'tags', None, _('show tags')),
3552 ('t', 'tags', None, _('show tags')),
3553 ('B', 'bookmarks', None, _('show bookmarks')),
3553 ('B', 'bookmarks', None, _('show bookmarks')),
3554 ] + remoteopts,
3554 ] + remoteopts,
3555 _('[-nibtB] [-r REV] [SOURCE]'))
3555 _('[-nibtB] [-r REV] [SOURCE]'))
3556 def identify(ui, repo, source=None, rev=None,
3556 def identify(ui, repo, source=None, rev=None,
3557 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3557 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3558 """identify the working copy or specified revision
3558 """identify the working copy or specified revision
3559
3559
3560 Print a summary identifying the repository state at REV using one or
3560 Print a summary identifying the repository state at REV using one or
3561 two parent hash identifiers, followed by a "+" if the working
3561 two parent hash identifiers, followed by a "+" if the working
3562 directory has uncommitted changes, the branch name (if not default),
3562 directory has uncommitted changes, the branch name (if not default),
3563 a list of tags, and a list of bookmarks.
3563 a list of tags, and a list of bookmarks.
3564
3564
3565 When REV is not given, print a summary of the current state of the
3565 When REV is not given, print a summary of the current state of the
3566 repository.
3566 repository.
3567
3567
3568 Specifying a path to a repository root or Mercurial bundle will
3568 Specifying a path to a repository root or Mercurial bundle will
3569 cause lookup to operate on that repository/bundle.
3569 cause lookup to operate on that repository/bundle.
3570
3570
3571 .. container:: verbose
3571 .. container:: verbose
3572
3572
3573 Examples:
3573 Examples:
3574
3574
3575 - generate a build identifier for the working directory::
3575 - generate a build identifier for the working directory::
3576
3576
3577 hg id --id > build-id.dat
3577 hg id --id > build-id.dat
3578
3578
3579 - find the revision corresponding to a tag::
3579 - find the revision corresponding to a tag::
3580
3580
3581 hg id -n -r 1.3
3581 hg id -n -r 1.3
3582
3582
3583 - check the most recent revision of a remote repository::
3583 - check the most recent revision of a remote repository::
3584
3584
3585 hg id -r tip http://selenic.com/hg/
3585 hg id -r tip http://selenic.com/hg/
3586
3586
3587 Returns 0 if successful.
3587 Returns 0 if successful.
3588 """
3588 """
3589
3589
3590 if not repo and not source:
3590 if not repo and not source:
3591 raise util.Abort(_("there is no Mercurial repository here "
3591 raise util.Abort(_("there is no Mercurial repository here "
3592 "(.hg not found)"))
3592 "(.hg not found)"))
3593
3593
3594 hexfunc = ui.debugflag and hex or short
3594 hexfunc = ui.debugflag and hex or short
3595 default = not (num or id or branch or tags or bookmarks)
3595 default = not (num or id or branch or tags or bookmarks)
3596 output = []
3596 output = []
3597 revs = []
3597 revs = []
3598
3598
3599 if source:
3599 if source:
3600 source, branches = hg.parseurl(ui.expandpath(source))
3600 source, branches = hg.parseurl(ui.expandpath(source))
3601 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3601 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3602 repo = peer.local()
3602 repo = peer.local()
3603 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3603 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3604
3604
3605 if not repo:
3605 if not repo:
3606 if num or branch or tags:
3606 if num or branch or tags:
3607 raise util.Abort(
3607 raise util.Abort(
3608 _("can't query remote revision number, branch, or tags"))
3608 _("can't query remote revision number, branch, or tags"))
3609 if not rev and revs:
3609 if not rev and revs:
3610 rev = revs[0]
3610 rev = revs[0]
3611 if not rev:
3611 if not rev:
3612 rev = "tip"
3612 rev = "tip"
3613
3613
3614 remoterev = peer.lookup(rev)
3614 remoterev = peer.lookup(rev)
3615 if default or id:
3615 if default or id:
3616 output = [hexfunc(remoterev)]
3616 output = [hexfunc(remoterev)]
3617
3617
3618 def getbms():
3618 def getbms():
3619 bms = []
3619 bms = []
3620
3620
3621 if 'bookmarks' in peer.listkeys('namespaces'):
3621 if 'bookmarks' in peer.listkeys('namespaces'):
3622 hexremoterev = hex(remoterev)
3622 hexremoterev = hex(remoterev)
3623 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3623 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3624 if bmr == hexremoterev]
3624 if bmr == hexremoterev]
3625
3625
3626 return sorted(bms)
3626 return sorted(bms)
3627
3627
3628 if bookmarks:
3628 if bookmarks:
3629 output.extend(getbms())
3629 output.extend(getbms())
3630 elif default and not ui.quiet:
3630 elif default and not ui.quiet:
3631 # multiple bookmarks for a single parent separated by '/'
3631 # multiple bookmarks for a single parent separated by '/'
3632 bm = '/'.join(getbms())
3632 bm = '/'.join(getbms())
3633 if bm:
3633 if bm:
3634 output.append(bm)
3634 output.append(bm)
3635 else:
3635 else:
3636 if not rev:
3636 if not rev:
3637 ctx = repo[None]
3637 ctx = repo[None]
3638 parents = ctx.parents()
3638 parents = ctx.parents()
3639 changed = ""
3639 changed = ""
3640 if default or id or num:
3640 if default or id or num:
3641 if (util.any(repo.status())
3641 if (util.any(repo.status())
3642 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3642 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3643 changed = '+'
3643 changed = '+'
3644 if default or id:
3644 if default or id:
3645 output = ["%s%s" %
3645 output = ["%s%s" %
3646 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3646 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3647 if num:
3647 if num:
3648 output.append("%s%s" %
3648 output.append("%s%s" %
3649 ('+'.join([str(p.rev()) for p in parents]), changed))
3649 ('+'.join([str(p.rev()) for p in parents]), changed))
3650 else:
3650 else:
3651 ctx = scmutil.revsingle(repo, rev)
3651 ctx = scmutil.revsingle(repo, rev)
3652 if default or id:
3652 if default or id:
3653 output = [hexfunc(ctx.node())]
3653 output = [hexfunc(ctx.node())]
3654 if num:
3654 if num:
3655 output.append(str(ctx.rev()))
3655 output.append(str(ctx.rev()))
3656
3656
3657 if default and not ui.quiet:
3657 if default and not ui.quiet:
3658 b = ctx.branch()
3658 b = ctx.branch()
3659 if b != 'default':
3659 if b != 'default':
3660 output.append("(%s)" % b)
3660 output.append("(%s)" % b)
3661
3661
3662 # multiple tags for a single parent separated by '/'
3662 # multiple tags for a single parent separated by '/'
3663 t = '/'.join(ctx.tags())
3663 t = '/'.join(ctx.tags())
3664 if t:
3664 if t:
3665 output.append(t)
3665 output.append(t)
3666
3666
3667 # multiple bookmarks for a single parent separated by '/'
3667 # multiple bookmarks for a single parent separated by '/'
3668 bm = '/'.join(ctx.bookmarks())
3668 bm = '/'.join(ctx.bookmarks())
3669 if bm:
3669 if bm:
3670 output.append(bm)
3670 output.append(bm)
3671 else:
3671 else:
3672 if branch:
3672 if branch:
3673 output.append(ctx.branch())
3673 output.append(ctx.branch())
3674
3674
3675 if tags:
3675 if tags:
3676 output.extend(ctx.tags())
3676 output.extend(ctx.tags())
3677
3677
3678 if bookmarks:
3678 if bookmarks:
3679 output.extend(ctx.bookmarks())
3679 output.extend(ctx.bookmarks())
3680
3680
3681 ui.write("%s\n" % ' '.join(output))
3681 ui.write("%s\n" % ' '.join(output))
3682
3682
3683 @command('import|patch',
3683 @command('import|patch',
3684 [('p', 'strip', 1,
3684 [('p', 'strip', 1,
3685 _('directory strip option for patch. This has the same '
3685 _('directory strip option for patch. This has the same '
3686 'meaning as the corresponding patch option'), _('NUM')),
3686 'meaning as the corresponding patch option'), _('NUM')),
3687 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3687 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3688 ('e', 'edit', False, _('invoke editor on commit messages')),
3688 ('e', 'edit', False, _('invoke editor on commit messages')),
3689 ('f', 'force', None,
3689 ('f', 'force', None,
3690 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3690 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3691 ('', 'no-commit', None,
3691 ('', 'no-commit', None,
3692 _("don't commit, just update the working directory")),
3692 _("don't commit, just update the working directory")),
3693 ('', 'bypass', None,
3693 ('', 'bypass', None,
3694 _("apply patch without touching the working directory")),
3694 _("apply patch without touching the working directory")),
3695 ('', 'exact', None,
3695 ('', 'exact', None,
3696 _('apply patch to the nodes from which it was generated')),
3696 _('apply patch to the nodes from which it was generated')),
3697 ('', 'import-branch', None,
3697 ('', 'import-branch', None,
3698 _('use any branch information in patch (implied by --exact)'))] +
3698 _('use any branch information in patch (implied by --exact)'))] +
3699 commitopts + commitopts2 + similarityopts,
3699 commitopts + commitopts2 + similarityopts,
3700 _('[OPTION]... PATCH...'))
3700 _('[OPTION]... PATCH...'))
3701 def import_(ui, repo, patch1=None, *patches, **opts):
3701 def import_(ui, repo, patch1=None, *patches, **opts):
3702 """import an ordered set of patches
3702 """import an ordered set of patches
3703
3703
3704 Import a list of patches and commit them individually (unless
3704 Import a list of patches and commit them individually (unless
3705 --no-commit is specified).
3705 --no-commit is specified).
3706
3706
3707 Because import first applies changes to the working directory,
3707 Because import first applies changes to the working directory,
3708 import will abort if there are outstanding changes.
3708 import will abort if there are outstanding changes.
3709
3709
3710 You can import a patch straight from a mail message. Even patches
3710 You can import a patch straight from a mail message. Even patches
3711 as attachments work (to use the body part, it must have type
3711 as attachments work (to use the body part, it must have type
3712 text/plain or text/x-patch). From and Subject headers of email
3712 text/plain or text/x-patch). From and Subject headers of email
3713 message are used as default committer and commit message. All
3713 message are used as default committer and commit message. All
3714 text/plain body parts before first diff are added to commit
3714 text/plain body parts before first diff are added to commit
3715 message.
3715 message.
3716
3716
3717 If the imported patch was generated by :hg:`export`, user and
3717 If the imported patch was generated by :hg:`export`, user and
3718 description from patch override values from message headers and
3718 description from patch override values from message headers and
3719 body. Values given on command line with -m/--message and -u/--user
3719 body. Values given on command line with -m/--message and -u/--user
3720 override these.
3720 override these.
3721
3721
3722 If --exact is specified, import will set the working directory to
3722 If --exact is specified, import will set the working directory to
3723 the parent of each patch before applying it, and will abort if the
3723 the parent of each patch before applying it, and will abort if the
3724 resulting changeset has a different ID than the one recorded in
3724 resulting changeset has a different ID than the one recorded in
3725 the patch. This may happen due to character set problems or other
3725 the patch. This may happen due to character set problems or other
3726 deficiencies in the text patch format.
3726 deficiencies in the text patch format.
3727
3727
3728 Use --bypass to apply and commit patches directly to the
3728 Use --bypass to apply and commit patches directly to the
3729 repository, not touching the working directory. Without --exact,
3729 repository, not touching the working directory. Without --exact,
3730 patches will be applied on top of the working directory parent
3730 patches will be applied on top of the working directory parent
3731 revision.
3731 revision.
3732
3732
3733 With -s/--similarity, hg will attempt to discover renames and
3733 With -s/--similarity, hg will attempt to discover renames and
3734 copies in the patch in the same way as :hg:`addremove`.
3734 copies in the patch in the same way as :hg:`addremove`.
3735
3735
3736 To read a patch from standard input, use "-" as the patch name. If
3736 To read a patch from standard input, use "-" as the patch name. If
3737 a URL is specified, the patch will be downloaded from it.
3737 a URL is specified, the patch will be downloaded from it.
3738 See :hg:`help dates` for a list of formats valid for -d/--date.
3738 See :hg:`help dates` for a list of formats valid for -d/--date.
3739
3739
3740 .. container:: verbose
3740 .. container:: verbose
3741
3741
3742 Examples:
3742 Examples:
3743
3743
3744 - import a traditional patch from a website and detect renames::
3744 - import a traditional patch from a website and detect renames::
3745
3745
3746 hg import -s 80 http://example.com/bugfix.patch
3746 hg import -s 80 http://example.com/bugfix.patch
3747
3747
3748 - import a changeset from an hgweb server::
3748 - import a changeset from an hgweb server::
3749
3749
3750 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3750 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3751
3751
3752 - import all the patches in an Unix-style mbox::
3752 - import all the patches in an Unix-style mbox::
3753
3753
3754 hg import incoming-patches.mbox
3754 hg import incoming-patches.mbox
3755
3755
3756 - attempt to exactly restore an exported changeset (not always
3756 - attempt to exactly restore an exported changeset (not always
3757 possible)::
3757 possible)::
3758
3758
3759 hg import --exact proposed-fix.patch
3759 hg import --exact proposed-fix.patch
3760
3760
3761 Returns 0 on success.
3761 Returns 0 on success.
3762 """
3762 """
3763
3763
3764 if not patch1:
3764 if not patch1:
3765 raise util.Abort(_('need at least one patch to import'))
3765 raise util.Abort(_('need at least one patch to import'))
3766
3766
3767 patches = (patch1,) + patches
3767 patches = (patch1,) + patches
3768
3768
3769 date = opts.get('date')
3769 date = opts.get('date')
3770 if date:
3770 if date:
3771 opts['date'] = util.parsedate(date)
3771 opts['date'] = util.parsedate(date)
3772
3772
3773 update = not opts.get('bypass')
3773 update = not opts.get('bypass')
3774 if not update and opts.get('no_commit'):
3774 if not update and opts.get('no_commit'):
3775 raise util.Abort(_('cannot use --no-commit with --bypass'))
3775 raise util.Abort(_('cannot use --no-commit with --bypass'))
3776 try:
3776 try:
3777 sim = float(opts.get('similarity') or 0)
3777 sim = float(opts.get('similarity') or 0)
3778 except ValueError:
3778 except ValueError:
3779 raise util.Abort(_('similarity must be a number'))
3779 raise util.Abort(_('similarity must be a number'))
3780 if sim < 0 or sim > 100:
3780 if sim < 0 or sim > 100:
3781 raise util.Abort(_('similarity must be between 0 and 100'))
3781 raise util.Abort(_('similarity must be between 0 and 100'))
3782 if sim and not update:
3782 if sim and not update:
3783 raise util.Abort(_('cannot use --similarity with --bypass'))
3783 raise util.Abort(_('cannot use --similarity with --bypass'))
3784
3784
3785 if update:
3785 if update:
3786 cmdutil.checkunfinished(repo)
3786 cmdutil.checkunfinished(repo)
3787 if (opts.get('exact') or not opts.get('force')) and update:
3787 if (opts.get('exact') or not opts.get('force')) and update:
3788 cmdutil.bailifchanged(repo)
3788 cmdutil.bailifchanged(repo)
3789
3789
3790 base = opts["base"]
3790 base = opts["base"]
3791 wlock = lock = tr = None
3791 wlock = lock = tr = None
3792 msgs = []
3792 msgs = []
3793
3793
3794
3794
3795 try:
3795 try:
3796 try:
3796 try:
3797 wlock = repo.wlock()
3797 wlock = repo.wlock()
3798 if not opts.get('no_commit'):
3798 if not opts.get('no_commit'):
3799 lock = repo.lock()
3799 lock = repo.lock()
3800 tr = repo.transaction('import')
3800 tr = repo.transaction('import')
3801 parents = repo.parents()
3801 parents = repo.parents()
3802 for patchurl in patches:
3802 for patchurl in patches:
3803 if patchurl == '-':
3803 if patchurl == '-':
3804 ui.status(_('applying patch from stdin\n'))
3804 ui.status(_('applying patch from stdin\n'))
3805 patchfile = ui.fin
3805 patchfile = ui.fin
3806 patchurl = 'stdin' # for error message
3806 patchurl = 'stdin' # for error message
3807 else:
3807 else:
3808 patchurl = os.path.join(base, patchurl)
3808 patchurl = os.path.join(base, patchurl)
3809 ui.status(_('applying %s\n') % patchurl)
3809 ui.status(_('applying %s\n') % patchurl)
3810 patchfile = hg.openpath(ui, patchurl)
3810 patchfile = hg.openpath(ui, patchurl)
3811
3811
3812 haspatch = False
3812 haspatch = False
3813 for hunk in patch.split(patchfile):
3813 for hunk in patch.split(patchfile):
3814 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3814 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3815 opts, msgs, hg.clean)
3815 opts, msgs, hg.clean)
3816 if msg:
3816 if msg:
3817 haspatch = True
3817 haspatch = True
3818 ui.note(msg + '\n')
3818 ui.note(msg + '\n')
3819 if update or opts.get('exact'):
3819 if update or opts.get('exact'):
3820 parents = repo.parents()
3820 parents = repo.parents()
3821 else:
3821 else:
3822 parents = [repo[node]]
3822 parents = [repo[node]]
3823
3823
3824 if not haspatch:
3824 if not haspatch:
3825 raise util.Abort(_('%s: no diffs found') % patchurl)
3825 raise util.Abort(_('%s: no diffs found') % patchurl)
3826
3826
3827 if tr:
3827 if tr:
3828 tr.close()
3828 tr.close()
3829 if msgs:
3829 if msgs:
3830 repo.savecommitmessage('\n* * *\n'.join(msgs))
3830 repo.savecommitmessage('\n* * *\n'.join(msgs))
3831 except: # re-raises
3831 except: # re-raises
3832 # wlock.release() indirectly calls dirstate.write(): since
3832 # wlock.release() indirectly calls dirstate.write(): since
3833 # we're crashing, we do not want to change the working dir
3833 # we're crashing, we do not want to change the working dir
3834 # parent after all, so make sure it writes nothing
3834 # parent after all, so make sure it writes nothing
3835 repo.dirstate.invalidate()
3835 repo.dirstate.invalidate()
3836 raise
3836 raise
3837 finally:
3837 finally:
3838 if tr:
3838 if tr:
3839 tr.release()
3839 tr.release()
3840 release(lock, wlock)
3840 release(lock, wlock)
3841
3841
3842 @command('incoming|in',
3842 @command('incoming|in',
3843 [('f', 'force', None,
3843 [('f', 'force', None,
3844 _('run even if remote repository is unrelated')),
3844 _('run even if remote repository is unrelated')),
3845 ('n', 'newest-first', None, _('show newest record first')),
3845 ('n', 'newest-first', None, _('show newest record first')),
3846 ('', 'bundle', '',
3846 ('', 'bundle', '',
3847 _('file to store the bundles into'), _('FILE')),
3847 _('file to store the bundles into'), _('FILE')),
3848 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3848 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3849 ('B', 'bookmarks', False, _("compare bookmarks")),
3849 ('B', 'bookmarks', False, _("compare bookmarks")),
3850 ('b', 'branch', [],
3850 ('b', 'branch', [],
3851 _('a specific branch you would like to pull'), _('BRANCH')),
3851 _('a specific branch you would like to pull'), _('BRANCH')),
3852 ] + logopts + remoteopts + subrepoopts,
3852 ] + logopts + remoteopts + subrepoopts,
3853 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3853 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3854 def incoming(ui, repo, source="default", **opts):
3854 def incoming(ui, repo, source="default", **opts):
3855 """show new changesets found in source
3855 """show new changesets found in source
3856
3856
3857 Show new changesets found in the specified path/URL or the default
3857 Show new changesets found in the specified path/URL or the default
3858 pull location. These are the changesets that would have been pulled
3858 pull location. These are the changesets that would have been pulled
3859 if a pull at the time you issued this command.
3859 if a pull at the time you issued this command.
3860
3860
3861 For remote repository, using --bundle avoids downloading the
3861 For remote repository, using --bundle avoids downloading the
3862 changesets twice if the incoming is followed by a pull.
3862 changesets twice if the incoming is followed by a pull.
3863
3863
3864 See pull for valid source format details.
3864 See pull for valid source format details.
3865
3865
3866 .. container:: verbose
3866 .. container:: verbose
3867
3867
3868 Examples:
3868 Examples:
3869
3869
3870 - show incoming changes with patches and full description::
3870 - show incoming changes with patches and full description::
3871
3871
3872 hg incoming -vp
3872 hg incoming -vp
3873
3873
3874 - show incoming changes excluding merges, store a bundle::
3874 - show incoming changes excluding merges, store a bundle::
3875
3875
3876 hg in -vpM --bundle incoming.hg
3876 hg in -vpM --bundle incoming.hg
3877 hg pull incoming.hg
3877 hg pull incoming.hg
3878
3878
3879 - briefly list changes inside a bundle::
3879 - briefly list changes inside a bundle::
3880
3880
3881 hg in changes.hg -T "{desc|firstline}\\n"
3881 hg in changes.hg -T "{desc|firstline}\\n"
3882
3882
3883 Returns 0 if there are incoming changes, 1 otherwise.
3883 Returns 0 if there are incoming changes, 1 otherwise.
3884 """
3884 """
3885 if opts.get('graph'):
3885 if opts.get('graph'):
3886 cmdutil.checkunsupportedgraphflags([], opts)
3886 cmdutil.checkunsupportedgraphflags([], opts)
3887 def display(other, chlist, displayer):
3887 def display(other, chlist, displayer):
3888 revdag = cmdutil.graphrevs(other, chlist, opts)
3888 revdag = cmdutil.graphrevs(other, chlist, opts)
3889 showparents = [ctx.node() for ctx in repo[None].parents()]
3889 showparents = [ctx.node() for ctx in repo[None].parents()]
3890 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3890 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3891 graphmod.asciiedges)
3891 graphmod.asciiedges)
3892
3892
3893 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3893 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3894 return 0
3894 return 0
3895
3895
3896 if opts.get('bundle') and opts.get('subrepos'):
3896 if opts.get('bundle') and opts.get('subrepos'):
3897 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3897 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3898
3898
3899 if opts.get('bookmarks'):
3899 if opts.get('bookmarks'):
3900 source, branches = hg.parseurl(ui.expandpath(source),
3900 source, branches = hg.parseurl(ui.expandpath(source),
3901 opts.get('branch'))
3901 opts.get('branch'))
3902 other = hg.peer(repo, opts, source)
3902 other = hg.peer(repo, opts, source)
3903 if 'bookmarks' not in other.listkeys('namespaces'):
3903 if 'bookmarks' not in other.listkeys('namespaces'):
3904 ui.warn(_("remote doesn't support bookmarks\n"))
3904 ui.warn(_("remote doesn't support bookmarks\n"))
3905 return 0
3905 return 0
3906 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3906 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3907 return bookmarks.diff(ui, repo, other)
3907 return bookmarks.diff(ui, repo, other)
3908
3908
3909 repo._subtoppath = ui.expandpath(source)
3909 repo._subtoppath = ui.expandpath(source)
3910 try:
3910 try:
3911 return hg.incoming(ui, repo, source, opts)
3911 return hg.incoming(ui, repo, source, opts)
3912 finally:
3912 finally:
3913 del repo._subtoppath
3913 del repo._subtoppath
3914
3914
3915
3915
3916 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3916 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3917 def init(ui, dest=".", **opts):
3917 def init(ui, dest=".", **opts):
3918 """create a new repository in the given directory
3918 """create a new repository in the given directory
3919
3919
3920 Initialize a new repository in the given directory. If the given
3920 Initialize a new repository in the given directory. If the given
3921 directory does not exist, it will be created.
3921 directory does not exist, it will be created.
3922
3922
3923 If no directory is given, the current directory is used.
3923 If no directory is given, the current directory is used.
3924
3924
3925 It is possible to specify an ``ssh://`` URL as the destination.
3925 It is possible to specify an ``ssh://`` URL as the destination.
3926 See :hg:`help urls` for more information.
3926 See :hg:`help urls` for more information.
3927
3927
3928 Returns 0 on success.
3928 Returns 0 on success.
3929 """
3929 """
3930 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3930 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3931
3931
3932 @command('locate',
3932 @command('locate',
3933 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3933 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3934 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3934 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3935 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3935 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3936 ] + walkopts,
3936 ] + walkopts,
3937 _('[OPTION]... [PATTERN]...'))
3937 _('[OPTION]... [PATTERN]...'))
3938 def locate(ui, repo, *pats, **opts):
3938 def locate(ui, repo, *pats, **opts):
3939 """locate files matching specific patterns
3939 """locate files matching specific patterns
3940
3940
3941 Print files under Mercurial control in the working directory whose
3941 Print files under Mercurial control in the working directory whose
3942 names match the given patterns.
3942 names match the given patterns.
3943
3943
3944 By default, this command searches all directories in the working
3944 By default, this command searches all directories in the working
3945 directory. To search just the current directory and its
3945 directory. To search just the current directory and its
3946 subdirectories, use "--include .".
3946 subdirectories, use "--include .".
3947
3947
3948 If no patterns are given to match, this command prints the names
3948 If no patterns are given to match, this command prints the names
3949 of all files under Mercurial control in the working directory.
3949 of all files under Mercurial control in the working directory.
3950
3950
3951 If you want to feed the output of this command into the "xargs"
3951 If you want to feed the output of this command into the "xargs"
3952 command, use the -0 option to both this command and "xargs". This
3952 command, use the -0 option to both this command and "xargs". This
3953 will avoid the problem of "xargs" treating single filenames that
3953 will avoid the problem of "xargs" treating single filenames that
3954 contain whitespace as multiple filenames.
3954 contain whitespace as multiple filenames.
3955
3955
3956 Returns 0 if a match is found, 1 otherwise.
3956 Returns 0 if a match is found, 1 otherwise.
3957 """
3957 """
3958 end = opts.get('print0') and '\0' or '\n'
3958 end = opts.get('print0') and '\0' or '\n'
3959 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3959 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3960
3960
3961 ret = 1
3961 ret = 1
3962 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3962 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3963 m.bad = lambda x, y: False
3963 m.bad = lambda x, y: False
3964 for abs in repo[rev].walk(m):
3964 for abs in repo[rev].walk(m):
3965 if not rev and abs not in repo.dirstate:
3965 if not rev and abs not in repo.dirstate:
3966 continue
3966 continue
3967 if opts.get('fullpath'):
3967 if opts.get('fullpath'):
3968 ui.write(repo.wjoin(abs), end)
3968 ui.write(repo.wjoin(abs), end)
3969 else:
3969 else:
3970 ui.write(((pats and m.rel(abs)) or abs), end)
3970 ui.write(((pats and m.rel(abs)) or abs), end)
3971 ret = 0
3971 ret = 0
3972
3972
3973 return ret
3973 return ret
3974
3974
3975 @command('^log|history',
3975 @command('^log|history',
3976 [('f', 'follow', None,
3976 [('f', 'follow', None,
3977 _('follow changeset history, or file history across copies and renames')),
3977 _('follow changeset history, or file history across copies and renames')),
3978 ('', 'follow-first', None,
3978 ('', 'follow-first', None,
3979 _('only follow the first parent of merge changesets (DEPRECATED)')),
3979 _('only follow the first parent of merge changesets (DEPRECATED)')),
3980 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3980 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3981 ('C', 'copies', None, _('show copied files')),
3981 ('C', 'copies', None, _('show copied files')),
3982 ('k', 'keyword', [],
3982 ('k', 'keyword', [],
3983 _('do case-insensitive search for a given text'), _('TEXT')),
3983 _('do case-insensitive search for a given text'), _('TEXT')),
3984 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3984 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3985 ('', 'removed', None, _('include revisions where files were removed')),
3985 ('', 'removed', None, _('include revisions where files were removed')),
3986 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3986 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3987 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3987 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3988 ('', 'only-branch', [],
3988 ('', 'only-branch', [],
3989 _('show only changesets within the given named branch (DEPRECATED)'),
3989 _('show only changesets within the given named branch (DEPRECATED)'),
3990 _('BRANCH')),
3990 _('BRANCH')),
3991 ('b', 'branch', [],
3991 ('b', 'branch', [],
3992 _('show changesets within the given named branch'), _('BRANCH')),
3992 _('show changesets within the given named branch'), _('BRANCH')),
3993 ('P', 'prune', [],
3993 ('P', 'prune', [],
3994 _('do not display revision or any of its ancestors'), _('REV')),
3994 _('do not display revision or any of its ancestors'), _('REV')),
3995 ] + logopts + walkopts,
3995 ] + logopts + walkopts,
3996 _('[OPTION]... [FILE]'))
3996 _('[OPTION]... [FILE]'))
3997 def log(ui, repo, *pats, **opts):
3997 def log(ui, repo, *pats, **opts):
3998 """show revision history of entire repository or files
3998 """show revision history of entire repository or files
3999
3999
4000 Print the revision history of the specified files or the entire
4000 Print the revision history of the specified files or the entire
4001 project.
4001 project.
4002
4002
4003 If no revision range is specified, the default is ``tip:0`` unless
4003 If no revision range is specified, the default is ``tip:0`` unless
4004 --follow is set, in which case the working directory parent is
4004 --follow is set, in which case the working directory parent is
4005 used as the starting revision.
4005 used as the starting revision.
4006
4006
4007 File history is shown without following rename or copy history of
4007 File history is shown without following rename or copy history of
4008 files. Use -f/--follow with a filename to follow history across
4008 files. Use -f/--follow with a filename to follow history across
4009 renames and copies. --follow without a filename will only show
4009 renames and copies. --follow without a filename will only show
4010 ancestors or descendants of the starting revision.
4010 ancestors or descendants of the starting revision.
4011
4011
4012 By default this command prints revision number and changeset id,
4012 By default this command prints revision number and changeset id,
4013 tags, non-trivial parents, user, date and time, and a summary for
4013 tags, non-trivial parents, user, date and time, and a summary for
4014 each commit. When the -v/--verbose switch is used, the list of
4014 each commit. When the -v/--verbose switch is used, the list of
4015 changed files and full commit message are shown.
4015 changed files and full commit message are shown.
4016
4016
4017 With --graph the revisions are shown as an ASCII art DAG with the most
4017 With --graph the revisions are shown as an ASCII art DAG with the most
4018 recent changeset at the top.
4018 recent changeset at the top.
4019 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4019 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4020 and '+' represents a fork where the changeset from the lines below is a
4020 and '+' represents a fork where the changeset from the lines below is a
4021 parent of the 'o' merge on the same line.
4021 parent of the 'o' merge on the same line.
4022
4022
4023 .. note::
4023 .. note::
4024
4024
4025 log -p/--patch may generate unexpected diff output for merge
4025 log -p/--patch may generate unexpected diff output for merge
4026 changesets, as it will only compare the merge changeset against
4026 changesets, as it will only compare the merge changeset against
4027 its first parent. Also, only files different from BOTH parents
4027 its first parent. Also, only files different from BOTH parents
4028 will appear in files:.
4028 will appear in files:.
4029
4029
4030 .. note::
4030 .. note::
4031
4031
4032 for performance reasons, log FILE may omit duplicate changes
4032 for performance reasons, log FILE may omit duplicate changes
4033 made on branches and will not show deletions. To see all
4033 made on branches and will not show deletions. To see all
4034 changes including duplicates and deletions, use the --removed
4034 changes including duplicates and deletions, use the --removed
4035 switch.
4035 switch.
4036
4036
4037 .. container:: verbose
4037 .. container:: verbose
4038
4038
4039 Some examples:
4039 Some examples:
4040
4040
4041 - changesets with full descriptions and file lists::
4041 - changesets with full descriptions and file lists::
4042
4042
4043 hg log -v
4043 hg log -v
4044
4044
4045 - changesets ancestral to the working directory::
4045 - changesets ancestral to the working directory::
4046
4046
4047 hg log -f
4047 hg log -f
4048
4048
4049 - last 10 commits on the current branch::
4049 - last 10 commits on the current branch::
4050
4050
4051 hg log -l 10 -b .
4051 hg log -l 10 -b .
4052
4052
4053 - changesets showing all modifications of a file, including removals::
4053 - changesets showing all modifications of a file, including removals::
4054
4054
4055 hg log --removed file.c
4055 hg log --removed file.c
4056
4056
4057 - all changesets that touch a directory, with diffs, excluding merges::
4057 - all changesets that touch a directory, with diffs, excluding merges::
4058
4058
4059 hg log -Mp lib/
4059 hg log -Mp lib/
4060
4060
4061 - all revision numbers that match a keyword::
4061 - all revision numbers that match a keyword::
4062
4062
4063 hg log -k bug --template "{rev}\\n"
4063 hg log -k bug --template "{rev}\\n"
4064
4064
4065 - check if a given changeset is included is a tagged release::
4065 - check if a given changeset is included is a tagged release::
4066
4066
4067 hg log -r "a21ccf and ancestor(1.9)"
4067 hg log -r "a21ccf and ancestor(1.9)"
4068
4068
4069 - find all changesets by some user in a date range::
4069 - find all changesets by some user in a date range::
4070
4070
4071 hg log -k alice -d "may 2008 to jul 2008"
4071 hg log -k alice -d "may 2008 to jul 2008"
4072
4072
4073 - summary of all changesets after the last tag::
4073 - summary of all changesets after the last tag::
4074
4074
4075 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4075 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4076
4076
4077 See :hg:`help dates` for a list of formats valid for -d/--date.
4077 See :hg:`help dates` for a list of formats valid for -d/--date.
4078
4078
4079 See :hg:`help revisions` and :hg:`help revsets` for more about
4079 See :hg:`help revisions` and :hg:`help revsets` for more about
4080 specifying revisions.
4080 specifying revisions.
4081
4081
4082 See :hg:`help templates` for more about pre-packaged styles and
4082 See :hg:`help templates` for more about pre-packaged styles and
4083 specifying custom templates.
4083 specifying custom templates.
4084
4084
4085 Returns 0 on success.
4085 Returns 0 on success.
4086 """
4086 """
4087 if opts.get('graph'):
4087 if opts.get('graph'):
4088 return cmdutil.graphlog(ui, repo, *pats, **opts)
4088 return cmdutil.graphlog(ui, repo, *pats, **opts)
4089
4089
4090 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4090 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4091 limit = cmdutil.loglimit(opts)
4091 limit = cmdutil.loglimit(opts)
4092 count = 0
4092 count = 0
4093
4093
4094 getrenamed = None
4094 getrenamed = None
4095 if opts.get('copies'):
4095 if opts.get('copies'):
4096 endrev = None
4096 endrev = None
4097 if opts.get('rev'):
4097 if opts.get('rev'):
4098 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4098 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4099 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4099 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4100
4100
4101 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4101 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4102 for rev in revs:
4102 for rev in revs:
4103 if count == limit:
4103 if count == limit:
4104 break
4104 break
4105 ctx = repo[rev]
4105 ctx = repo[rev]
4106 copies = None
4106 copies = None
4107 if getrenamed is not None and rev:
4107 if getrenamed is not None and rev:
4108 copies = []
4108 copies = []
4109 for fn in ctx.files():
4109 for fn in ctx.files():
4110 rename = getrenamed(fn, rev)
4110 rename = getrenamed(fn, rev)
4111 if rename:
4111 if rename:
4112 copies.append((fn, rename[0]))
4112 copies.append((fn, rename[0]))
4113 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4113 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4114 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4114 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4115 if displayer.flush(rev):
4115 if displayer.flush(rev):
4116 count += 1
4116 count += 1
4117
4117
4118 displayer.close()
4118 displayer.close()
4119
4119
4120 @command('manifest',
4120 @command('manifest',
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4122 ('', 'all', False, _("list files from all revisions"))],
4122 ('', 'all', False, _("list files from all revisions"))],
4123 _('[-r REV]'))
4123 _('[-r REV]'))
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4125 """output the current or given revision of the project manifest
4125 """output the current or given revision of the project manifest
4126
4126
4127 Print a list of version controlled files for the given revision.
4127 Print a list of version controlled files for the given revision.
4128 If no revision is given, the first parent of the working directory
4128 If no revision is given, the first parent of the working directory
4129 is used, or the null revision if no revision is checked out.
4129 is used, or the null revision if no revision is checked out.
4130
4130
4131 With -v, print file permissions, symlink and executable bits.
4131 With -v, print file permissions, symlink and executable bits.
4132 With --debug, print file revision hashes.
4132 With --debug, print file revision hashes.
4133
4133
4134 If option --all is specified, the list of all files from all revisions
4134 If option --all is specified, the list of all files from all revisions
4135 is printed. This includes deleted and renamed files.
4135 is printed. This includes deleted and renamed files.
4136
4136
4137 Returns 0 on success.
4137 Returns 0 on success.
4138 """
4138 """
4139
4139
4140 fm = ui.formatter('manifest', opts)
4140 fm = ui.formatter('manifest', opts)
4141
4141
4142 if opts.get('all'):
4142 if opts.get('all'):
4143 if rev or node:
4143 if rev or node:
4144 raise util.Abort(_("can't specify a revision with --all"))
4144 raise util.Abort(_("can't specify a revision with --all"))
4145
4145
4146 res = []
4146 res = []
4147 prefix = "data/"
4147 prefix = "data/"
4148 suffix = ".i"
4148 suffix = ".i"
4149 plen = len(prefix)
4149 plen = len(prefix)
4150 slen = len(suffix)
4150 slen = len(suffix)
4151 lock = repo.lock()
4151 lock = repo.lock()
4152 try:
4152 try:
4153 for fn, b, size in repo.store.datafiles():
4153 for fn, b, size in repo.store.datafiles():
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4155 res.append(fn[plen:-slen])
4155 res.append(fn[plen:-slen])
4156 finally:
4156 finally:
4157 lock.release()
4157 lock.release()
4158 for f in res:
4158 for f in res:
4159 fm.startitem()
4159 fm.startitem()
4160 fm.write("path", '%s\n', f)
4160 fm.write("path", '%s\n', f)
4161 fm.end()
4161 fm.end()
4162 return
4162 return
4163
4163
4164 if rev and node:
4164 if rev and node:
4165 raise util.Abort(_("please specify just one revision"))
4165 raise util.Abort(_("please specify just one revision"))
4166
4166
4167 if not node:
4167 if not node:
4168 node = rev
4168 node = rev
4169
4169
4170 char = {'l': '@', 'x': '*', '': ''}
4170 char = {'l': '@', 'x': '*', '': ''}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4172 ctx = scmutil.revsingle(repo, node)
4172 ctx = scmutil.revsingle(repo, node)
4173 mf = ctx.manifest()
4173 mf = ctx.manifest()
4174 for f in ctx:
4174 for f in ctx:
4175 fm.startitem()
4175 fm.startitem()
4176 fl = ctx[f].flags()
4176 fl = ctx[f].flags()
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4179 fm.write('path', '%s\n', f)
4179 fm.write('path', '%s\n', f)
4180 fm.end()
4180 fm.end()
4181
4181
4182 @command('^merge',
4182 @command('^merge',
4183 [('f', 'force', None,
4183 [('f', 'force', None,
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4186 ('P', 'preview', None,
4186 ('P', 'preview', None,
4187 _('review revisions to merge (no merge is performed)'))
4187 _('review revisions to merge (no merge is performed)'))
4188 ] + mergetoolopts,
4188 ] + mergetoolopts,
4189 _('[-P] [-f] [[-r] REV]'))
4189 _('[-P] [-f] [[-r] REV]'))
4190 def merge(ui, repo, node=None, **opts):
4190 def merge(ui, repo, node=None, **opts):
4191 """merge working directory with another revision
4191 """merge working directory with another revision
4192
4192
4193 The current working directory is updated with all changes made in
4193 The current working directory is updated with all changes made in
4194 the requested revision since the last common predecessor revision.
4194 the requested revision since the last common predecessor revision.
4195
4195
4196 Files that changed between either parent are marked as changed for
4196 Files that changed between either parent are marked as changed for
4197 the next commit and a commit must be performed before any further
4197 the next commit and a commit must be performed before any further
4198 updates to the repository are allowed. The next commit will have
4198 updates to the repository are allowed. The next commit will have
4199 two parents.
4199 two parents.
4200
4200
4201 ``--tool`` can be used to specify the merge tool used for file
4201 ``--tool`` can be used to specify the merge tool used for file
4202 merges. It overrides the HGMERGE environment variable and your
4202 merges. It overrides the HGMERGE environment variable and your
4203 configuration files. See :hg:`help merge-tools` for options.
4203 configuration files. See :hg:`help merge-tools` for options.
4204
4204
4205 If no revision is specified, the working directory's parent is a
4205 If no revision is specified, the working directory's parent is a
4206 head revision, and the current branch contains exactly one other
4206 head revision, and the current branch contains exactly one other
4207 head, the other head is merged with by default. Otherwise, an
4207 head, the other head is merged with by default. Otherwise, an
4208 explicit revision with which to merge with must be provided.
4208 explicit revision with which to merge with must be provided.
4209
4209
4210 :hg:`resolve` must be used to resolve unresolved files.
4210 :hg:`resolve` must be used to resolve unresolved files.
4211
4211
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4213 will check out a clean copy of the original merge parent, losing
4213 will check out a clean copy of the original merge parent, losing
4214 all changes.
4214 all changes.
4215
4215
4216 Returns 0 on success, 1 if there are unresolved files.
4216 Returns 0 on success, 1 if there are unresolved files.
4217 """
4217 """
4218
4218
4219 if opts.get('rev') and node:
4219 if opts.get('rev') and node:
4220 raise util.Abort(_("please specify just one revision"))
4220 raise util.Abort(_("please specify just one revision"))
4221 if not node:
4221 if not node:
4222 node = opts.get('rev')
4222 node = opts.get('rev')
4223
4223
4224 if node:
4224 if node:
4225 node = scmutil.revsingle(repo, node).node()
4225 node = scmutil.revsingle(repo, node).node()
4226
4226
4227 if not node and repo._bookmarkcurrent:
4227 if not node and repo._bookmarkcurrent:
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4229 curhead = repo[repo._bookmarkcurrent].node()
4229 curhead = repo[repo._bookmarkcurrent].node()
4230 if len(bmheads) == 2:
4230 if len(bmheads) == 2:
4231 if curhead == bmheads[0]:
4231 if curhead == bmheads[0]:
4232 node = bmheads[1]
4232 node = bmheads[1]
4233 else:
4233 else:
4234 node = bmheads[0]
4234 node = bmheads[0]
4235 elif len(bmheads) > 2:
4235 elif len(bmheads) > 2:
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4237 "please merge with an explicit rev or bookmark"),
4237 "please merge with an explicit rev or bookmark"),
4238 hint=_("run 'hg heads' to see all heads"))
4238 hint=_("run 'hg heads' to see all heads"))
4239 elif len(bmheads) <= 1:
4239 elif len(bmheads) <= 1:
4240 raise util.Abort(_("no matching bookmark to merge - "
4240 raise util.Abort(_("no matching bookmark to merge - "
4241 "please merge with an explicit rev or bookmark"),
4241 "please merge with an explicit rev or bookmark"),
4242 hint=_("run 'hg heads' to see all heads"))
4242 hint=_("run 'hg heads' to see all heads"))
4243
4243
4244 if not node and not repo._bookmarkcurrent:
4244 if not node and not repo._bookmarkcurrent:
4245 branch = repo[None].branch()
4245 branch = repo[None].branch()
4246 bheads = repo.branchheads(branch)
4246 bheads = repo.branchheads(branch)
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4248
4248
4249 if len(nbhs) > 2:
4249 if len(nbhs) > 2:
4250 raise util.Abort(_("branch '%s' has %d heads - "
4250 raise util.Abort(_("branch '%s' has %d heads - "
4251 "please merge with an explicit rev")
4251 "please merge with an explicit rev")
4252 % (branch, len(bheads)),
4252 % (branch, len(bheads)),
4253 hint=_("run 'hg heads .' to see heads"))
4253 hint=_("run 'hg heads .' to see heads"))
4254
4254
4255 parent = repo.dirstate.p1()
4255 parent = repo.dirstate.p1()
4256 if len(nbhs) <= 1:
4256 if len(nbhs) <= 1:
4257 if len(bheads) > 1:
4257 if len(bheads) > 1:
4258 raise util.Abort(_("heads are bookmarked - "
4258 raise util.Abort(_("heads are bookmarked - "
4259 "please merge with an explicit rev"),
4259 "please merge with an explicit rev"),
4260 hint=_("run 'hg heads' to see all heads"))
4260 hint=_("run 'hg heads' to see all heads"))
4261 if len(repo.heads()) > 1:
4261 if len(repo.heads()) > 1:
4262 raise util.Abort(_("branch '%s' has one head - "
4262 raise util.Abort(_("branch '%s' has one head - "
4263 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4264 % branch,
4264 % branch,
4265 hint=_("run 'hg heads' to see all heads"))
4265 hint=_("run 'hg heads' to see all heads"))
4266 msg, hint = _('nothing to merge'), None
4266 msg, hint = _('nothing to merge'), None
4267 if parent != repo.lookup(branch):
4267 if parent != repo.lookup(branch):
4268 hint = _("use 'hg update' instead")
4268 hint = _("use 'hg update' instead")
4269 raise util.Abort(msg, hint=hint)
4269 raise util.Abort(msg, hint=hint)
4270
4270
4271 if parent not in bheads:
4271 if parent not in bheads:
4272 raise util.Abort(_('working directory not at a head revision'),
4272 raise util.Abort(_('working directory not at a head revision'),
4273 hint=_("use 'hg update' or merge with an "
4273 hint=_("use 'hg update' or merge with an "
4274 "explicit revision"))
4274 "explicit revision"))
4275 if parent == nbhs[0]:
4275 if parent == nbhs[0]:
4276 node = nbhs[-1]
4276 node = nbhs[-1]
4277 else:
4277 else:
4278 node = nbhs[0]
4278 node = nbhs[0]
4279
4279
4280 if opts.get('preview'):
4280 if opts.get('preview'):
4281 # find nodes that are ancestors of p2 but not of p1
4281 # find nodes that are ancestors of p2 but not of p1
4282 p1 = repo.lookup('.')
4282 p1 = repo.lookup('.')
4283 p2 = repo.lookup(node)
4283 p2 = repo.lookup(node)
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4285
4285
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4287 for node in nodes:
4287 for node in nodes:
4288 displayer.show(repo[node])
4288 displayer.show(repo[node])
4289 displayer.close()
4289 displayer.close()
4290 return 0
4290 return 0
4291
4291
4292 try:
4292 try:
4293 # ui.forcemerge is an internal variable, do not document
4293 # ui.forcemerge is an internal variable, do not document
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4295 return hg.merge(repo, node, force=opts.get('force'))
4295 return hg.merge(repo, node, force=opts.get('force'))
4296 finally:
4296 finally:
4297 ui.setconfig('ui', 'forcemerge', '', 'merge')
4297 ui.setconfig('ui', 'forcemerge', '', 'merge')
4298
4298
4299 @command('outgoing|out',
4299 @command('outgoing|out',
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4301 ('r', 'rev', [],
4301 ('r', 'rev', [],
4302 _('a changeset intended to be included in the destination'), _('REV')),
4302 _('a changeset intended to be included in the destination'), _('REV')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4306 _('BRANCH')),
4306 _('BRANCH')),
4307 ] + logopts + remoteopts + subrepoopts,
4307 ] + logopts + remoteopts + subrepoopts,
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4309 def outgoing(ui, repo, dest=None, **opts):
4309 def outgoing(ui, repo, dest=None, **opts):
4310 """show changesets not found in the destination
4310 """show changesets not found in the destination
4311
4311
4312 Show changesets not found in the specified destination repository
4312 Show changesets not found in the specified destination repository
4313 or the default push location. These are the changesets that would
4313 or the default push location. These are the changesets that would
4314 be pushed if a push was requested.
4314 be pushed if a push was requested.
4315
4315
4316 See pull for details of valid destination formats.
4316 See pull for details of valid destination formats.
4317
4317
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4319 """
4319 """
4320 if opts.get('graph'):
4320 if opts.get('graph'):
4321 cmdutil.checkunsupportedgraphflags([], opts)
4321 cmdutil.checkunsupportedgraphflags([], opts)
4322 o, other = hg._outgoing(ui, repo, dest, opts)
4322 o, other = hg._outgoing(ui, repo, dest, opts)
4323 if not o:
4323 if not o:
4324 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4324 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4325 return
4325 return
4326
4326
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4331 graphmod.asciiedges)
4331 graphmod.asciiedges)
4332 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4332 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4333 return 0
4333 return 0
4334
4334
4335 if opts.get('bookmarks'):
4335 if opts.get('bookmarks'):
4336 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4336 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4337 dest, branches = hg.parseurl(dest, opts.get('branch'))
4337 dest, branches = hg.parseurl(dest, opts.get('branch'))
4338 other = hg.peer(repo, opts, dest)
4338 other = hg.peer(repo, opts, dest)
4339 if 'bookmarks' not in other.listkeys('namespaces'):
4339 if 'bookmarks' not in other.listkeys('namespaces'):
4340 ui.warn(_("remote doesn't support bookmarks\n"))
4340 ui.warn(_("remote doesn't support bookmarks\n"))
4341 return 0
4341 return 0
4342 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4342 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4343 return bookmarks.diff(ui, other, repo)
4343 return bookmarks.diff(ui, other, repo)
4344
4344
4345 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4345 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4346 try:
4346 try:
4347 return hg.outgoing(ui, repo, dest, opts)
4347 return hg.outgoing(ui, repo, dest, opts)
4348 finally:
4348 finally:
4349 del repo._subtoppath
4349 del repo._subtoppath
4350
4350
4351 @command('parents',
4351 @command('parents',
4352 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4352 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4353 ] + templateopts,
4353 ] + templateopts,
4354 _('[-r REV] [FILE]'))
4354 _('[-r REV] [FILE]'))
4355 def parents(ui, repo, file_=None, **opts):
4355 def parents(ui, repo, file_=None, **opts):
4356 """show the parents of the working directory or revision
4356 """show the parents of the working directory or revision
4357
4357
4358 Print the working directory's parent revisions. If a revision is
4358 Print the working directory's parent revisions. If a revision is
4359 given via -r/--rev, the parent of that revision will be printed.
4359 given via -r/--rev, the parent of that revision will be printed.
4360 If a file argument is given, the revision in which the file was
4360 If a file argument is given, the revision in which the file was
4361 last changed (before the working directory revision or the
4361 last changed (before the working directory revision or the
4362 argument to --rev if given) is printed.
4362 argument to --rev if given) is printed.
4363
4363
4364 Returns 0 on success.
4364 Returns 0 on success.
4365 """
4365 """
4366
4366
4367 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4367 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4368
4368
4369 if file_:
4369 if file_:
4370 m = scmutil.match(ctx, (file_,), opts)
4370 m = scmutil.match(ctx, (file_,), opts)
4371 if m.anypats() or len(m.files()) != 1:
4371 if m.anypats() or len(m.files()) != 1:
4372 raise util.Abort(_('can only specify an explicit filename'))
4372 raise util.Abort(_('can only specify an explicit filename'))
4373 file_ = m.files()[0]
4373 file_ = m.files()[0]
4374 filenodes = []
4374 filenodes = []
4375 for cp in ctx.parents():
4375 for cp in ctx.parents():
4376 if not cp:
4376 if not cp:
4377 continue
4377 continue
4378 try:
4378 try:
4379 filenodes.append(cp.filenode(file_))
4379 filenodes.append(cp.filenode(file_))
4380 except error.LookupError:
4380 except error.LookupError:
4381 pass
4381 pass
4382 if not filenodes:
4382 if not filenodes:
4383 raise util.Abort(_("'%s' not found in manifest!") % file_)
4383 raise util.Abort(_("'%s' not found in manifest!") % file_)
4384 p = []
4384 p = []
4385 for fn in filenodes:
4385 for fn in filenodes:
4386 fctx = repo.filectx(file_, fileid=fn)
4386 fctx = repo.filectx(file_, fileid=fn)
4387 p.append(fctx.node())
4387 p.append(fctx.node())
4388 else:
4388 else:
4389 p = [cp.node() for cp in ctx.parents()]
4389 p = [cp.node() for cp in ctx.parents()]
4390
4390
4391 displayer = cmdutil.show_changeset(ui, repo, opts)
4391 displayer = cmdutil.show_changeset(ui, repo, opts)
4392 for n in p:
4392 for n in p:
4393 if n != nullid:
4393 if n != nullid:
4394 displayer.show(repo[n])
4394 displayer.show(repo[n])
4395 displayer.close()
4395 displayer.close()
4396
4396
4397 @command('paths', [], _('[NAME]'))
4397 @command('paths', [], _('[NAME]'))
4398 def paths(ui, repo, search=None):
4398 def paths(ui, repo, search=None):
4399 """show aliases for remote repositories
4399 """show aliases for remote repositories
4400
4400
4401 Show definition of symbolic path name NAME. If no name is given,
4401 Show definition of symbolic path name NAME. If no name is given,
4402 show definition of all available names.
4402 show definition of all available names.
4403
4403
4404 Option -q/--quiet suppresses all output when searching for NAME
4404 Option -q/--quiet suppresses all output when searching for NAME
4405 and shows only the path names when listing all definitions.
4405 and shows only the path names when listing all definitions.
4406
4406
4407 Path names are defined in the [paths] section of your
4407 Path names are defined in the [paths] section of your
4408 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4408 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4409 repository, ``.hg/hgrc`` is used, too.
4409 repository, ``.hg/hgrc`` is used, too.
4410
4410
4411 The path names ``default`` and ``default-push`` have a special
4411 The path names ``default`` and ``default-push`` have a special
4412 meaning. When performing a push or pull operation, they are used
4412 meaning. When performing a push or pull operation, they are used
4413 as fallbacks if no location is specified on the command-line.
4413 as fallbacks if no location is specified on the command-line.
4414 When ``default-push`` is set, it will be used for push and
4414 When ``default-push`` is set, it will be used for push and
4415 ``default`` will be used for pull; otherwise ``default`` is used
4415 ``default`` will be used for pull; otherwise ``default`` is used
4416 as the fallback for both. When cloning a repository, the clone
4416 as the fallback for both. When cloning a repository, the clone
4417 source is written as ``default`` in ``.hg/hgrc``. Note that
4417 source is written as ``default`` in ``.hg/hgrc``. Note that
4418 ``default`` and ``default-push`` apply to all inbound (e.g.
4418 ``default`` and ``default-push`` apply to all inbound (e.g.
4419 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4419 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4420 :hg:`bundle`) operations.
4420 :hg:`bundle`) operations.
4421
4421
4422 See :hg:`help urls` for more information.
4422 See :hg:`help urls` for more information.
4423
4423
4424 Returns 0 on success.
4424 Returns 0 on success.
4425 """
4425 """
4426 if search:
4426 if search:
4427 for name, path in ui.configitems("paths"):
4427 for name, path in ui.configitems("paths"):
4428 if name == search:
4428 if name == search:
4429 ui.status("%s\n" % util.hidepassword(path))
4429 ui.status("%s\n" % util.hidepassword(path))
4430 return
4430 return
4431 if not ui.quiet:
4431 if not ui.quiet:
4432 ui.warn(_("not found!\n"))
4432 ui.warn(_("not found!\n"))
4433 return 1
4433 return 1
4434 else:
4434 else:
4435 for name, path in ui.configitems("paths"):
4435 for name, path in ui.configitems("paths"):
4436 if ui.quiet:
4436 if ui.quiet:
4437 ui.write("%s\n" % name)
4437 ui.write("%s\n" % name)
4438 else:
4438 else:
4439 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4439 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4440
4440
4441 @command('phase',
4441 @command('phase',
4442 [('p', 'public', False, _('set changeset phase to public')),
4442 [('p', 'public', False, _('set changeset phase to public')),
4443 ('d', 'draft', False, _('set changeset phase to draft')),
4443 ('d', 'draft', False, _('set changeset phase to draft')),
4444 ('s', 'secret', False, _('set changeset phase to secret')),
4444 ('s', 'secret', False, _('set changeset phase to secret')),
4445 ('f', 'force', False, _('allow to move boundary backward')),
4445 ('f', 'force', False, _('allow to move boundary backward')),
4446 ('r', 'rev', [], _('target revision'), _('REV')),
4446 ('r', 'rev', [], _('target revision'), _('REV')),
4447 ],
4447 ],
4448 _('[-p|-d|-s] [-f] [-r] REV...'))
4448 _('[-p|-d|-s] [-f] [-r] REV...'))
4449 def phase(ui, repo, *revs, **opts):
4449 def phase(ui, repo, *revs, **opts):
4450 """set or show the current phase name
4450 """set or show the current phase name
4451
4451
4452 With no argument, show the phase name of specified revisions.
4452 With no argument, show the phase name of specified revisions.
4453
4453
4454 With one of -p/--public, -d/--draft or -s/--secret, change the
4454 With one of -p/--public, -d/--draft or -s/--secret, change the
4455 phase value of the specified revisions.
4455 phase value of the specified revisions.
4456
4456
4457 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4457 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4458 lower phase to an higher phase. Phases are ordered as follows::
4458 lower phase to an higher phase. Phases are ordered as follows::
4459
4459
4460 public < draft < secret
4460 public < draft < secret
4461
4461
4462 Returns 0 on success, 1 if no phases were changed or some could not
4462 Returns 0 on success, 1 if no phases were changed or some could not
4463 be changed.
4463 be changed.
4464 """
4464 """
4465 # search for a unique phase argument
4465 # search for a unique phase argument
4466 targetphase = None
4466 targetphase = None
4467 for idx, name in enumerate(phases.phasenames):
4467 for idx, name in enumerate(phases.phasenames):
4468 if opts[name]:
4468 if opts[name]:
4469 if targetphase is not None:
4469 if targetphase is not None:
4470 raise util.Abort(_('only one phase can be specified'))
4470 raise util.Abort(_('only one phase can be specified'))
4471 targetphase = idx
4471 targetphase = idx
4472
4472
4473 # look for specified revision
4473 # look for specified revision
4474 revs = list(revs)
4474 revs = list(revs)
4475 revs.extend(opts['rev'])
4475 revs.extend(opts['rev'])
4476 if not revs:
4476 if not revs:
4477 raise util.Abort(_('no revisions specified'))
4477 raise util.Abort(_('no revisions specified'))
4478
4478
4479 revs = scmutil.revrange(repo, revs)
4479 revs = scmutil.revrange(repo, revs)
4480
4480
4481 lock = None
4481 lock = None
4482 ret = 0
4482 ret = 0
4483 if targetphase is None:
4483 if targetphase is None:
4484 # display
4484 # display
4485 for r in revs:
4485 for r in revs:
4486 ctx = repo[r]
4486 ctx = repo[r]
4487 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4487 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4488 else:
4488 else:
4489 lock = repo.lock()
4489 lock = repo.lock()
4490 try:
4490 try:
4491 # set phase
4491 # set phase
4492 if not revs:
4492 if not revs:
4493 raise util.Abort(_('empty revision set'))
4493 raise util.Abort(_('empty revision set'))
4494 nodes = [repo[r].node() for r in revs]
4494 nodes = [repo[r].node() for r in revs]
4495 olddata = repo._phasecache.getphaserevs(repo)[:]
4495 olddata = repo._phasecache.getphaserevs(repo)[:]
4496 phases.advanceboundary(repo, targetphase, nodes)
4496 phases.advanceboundary(repo, targetphase, nodes)
4497 if opts['force']:
4497 if opts['force']:
4498 phases.retractboundary(repo, targetphase, nodes)
4498 phases.retractboundary(repo, targetphase, nodes)
4499 finally:
4499 finally:
4500 lock.release()
4500 lock.release()
4501 # moving revision from public to draft may hide them
4501 # moving revision from public to draft may hide them
4502 # We have to check result on an unfiltered repository
4502 # We have to check result on an unfiltered repository
4503 unfi = repo.unfiltered()
4503 unfi = repo.unfiltered()
4504 newdata = repo._phasecache.getphaserevs(unfi)
4504 newdata = repo._phasecache.getphaserevs(unfi)
4505 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4505 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4506 cl = unfi.changelog
4506 cl = unfi.changelog
4507 rejected = [n for n in nodes
4507 rejected = [n for n in nodes
4508 if newdata[cl.rev(n)] < targetphase]
4508 if newdata[cl.rev(n)] < targetphase]
4509 if rejected:
4509 if rejected:
4510 ui.warn(_('cannot move %i changesets to a higher '
4510 ui.warn(_('cannot move %i changesets to a higher '
4511 'phase, use --force\n') % len(rejected))
4511 'phase, use --force\n') % len(rejected))
4512 ret = 1
4512 ret = 1
4513 if changes:
4513 if changes:
4514 msg = _('phase changed for %i changesets\n') % changes
4514 msg = _('phase changed for %i changesets\n') % changes
4515 if ret:
4515 if ret:
4516 ui.status(msg)
4516 ui.status(msg)
4517 else:
4517 else:
4518 ui.note(msg)
4518 ui.note(msg)
4519 else:
4519 else:
4520 ui.warn(_('no phases changed\n'))
4520 ui.warn(_('no phases changed\n'))
4521 ret = 1
4521 ret = 1
4522 return ret
4522 return ret
4523
4523
4524 def postincoming(ui, repo, modheads, optupdate, checkout):
4524 def postincoming(ui, repo, modheads, optupdate, checkout):
4525 if modheads == 0:
4525 if modheads == 0:
4526 return
4526 return
4527 if optupdate:
4527 if optupdate:
4528 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4528 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4529 try:
4529 try:
4530 ret = hg.update(repo, checkout)
4530 ret = hg.update(repo, checkout)
4531 except util.Abort, inst:
4531 except util.Abort, inst:
4532 ui.warn(_("not updating: %s\n") % str(inst))
4532 ui.warn(_("not updating: %s\n") % str(inst))
4533 if inst.hint:
4533 if inst.hint:
4534 ui.warn(_("(%s)\n") % inst.hint)
4534 ui.warn(_("(%s)\n") % inst.hint)
4535 return 0
4535 return 0
4536 if not ret and not checkout:
4536 if not ret and not checkout:
4537 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4537 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4538 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4538 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4539 return ret
4539 return ret
4540 if modheads > 1:
4540 if modheads > 1:
4541 currentbranchheads = len(repo.branchheads())
4541 currentbranchheads = len(repo.branchheads())
4542 if currentbranchheads == modheads:
4542 if currentbranchheads == modheads:
4543 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4543 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4544 elif currentbranchheads > 1:
4544 elif currentbranchheads > 1:
4545 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4545 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4546 "merge)\n"))
4546 "merge)\n"))
4547 else:
4547 else:
4548 ui.status(_("(run 'hg heads' to see heads)\n"))
4548 ui.status(_("(run 'hg heads' to see heads)\n"))
4549 else:
4549 else:
4550 ui.status(_("(run 'hg update' to get a working copy)\n"))
4550 ui.status(_("(run 'hg update' to get a working copy)\n"))
4551
4551
4552 @command('^pull',
4552 @command('^pull',
4553 [('u', 'update', None,
4553 [('u', 'update', None,
4554 _('update to new branch head if changesets were pulled')),
4554 _('update to new branch head if changesets were pulled')),
4555 ('f', 'force', None, _('run even when remote repository is unrelated')),
4555 ('f', 'force', None, _('run even when remote repository is unrelated')),
4556 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4556 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4557 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4557 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4558 ('b', 'branch', [], _('a specific branch you would like to pull'),
4558 ('b', 'branch', [], _('a specific branch you would like to pull'),
4559 _('BRANCH')),
4559 _('BRANCH')),
4560 ] + remoteopts,
4560 ] + remoteopts,
4561 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4561 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4562 def pull(ui, repo, source="default", **opts):
4562 def pull(ui, repo, source="default", **opts):
4563 """pull changes from the specified source
4563 """pull changes from the specified source
4564
4564
4565 Pull changes from a remote repository to a local one.
4565 Pull changes from a remote repository to a local one.
4566
4566
4567 This finds all changes from the repository at the specified path
4567 This finds all changes from the repository at the specified path
4568 or URL and adds them to a local repository (the current one unless
4568 or URL and adds them to a local repository (the current one unless
4569 -R is specified). By default, this does not update the copy of the
4569 -R is specified). By default, this does not update the copy of the
4570 project in the working directory.
4570 project in the working directory.
4571
4571
4572 Use :hg:`incoming` if you want to see what would have been added
4572 Use :hg:`incoming` if you want to see what would have been added
4573 by a pull at the time you issued this command. If you then decide
4573 by a pull at the time you issued this command. If you then decide
4574 to add those changes to the repository, you should use :hg:`pull
4574 to add those changes to the repository, you should use :hg:`pull
4575 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4575 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4576
4576
4577 If SOURCE is omitted, the 'default' path will be used.
4577 If SOURCE is omitted, the 'default' path will be used.
4578 See :hg:`help urls` for more information.
4578 See :hg:`help urls` for more information.
4579
4579
4580 Returns 0 on success, 1 if an update had unresolved files.
4580 Returns 0 on success, 1 if an update had unresolved files.
4581 """
4581 """
4582 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4582 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4583 other = hg.peer(repo, opts, source)
4583 other = hg.peer(repo, opts, source)
4584 try:
4584 try:
4585 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4585 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4586 revs, checkout = hg.addbranchrevs(repo, other, branches,
4586 revs, checkout = hg.addbranchrevs(repo, other, branches,
4587 opts.get('rev'))
4587 opts.get('rev'))
4588
4588
4589 remotebookmarks = other.listkeys('bookmarks')
4589 remotebookmarks = other.listkeys('bookmarks')
4590
4590
4591 if opts.get('bookmark'):
4591 if opts.get('bookmark'):
4592 if not revs:
4592 if not revs:
4593 revs = []
4593 revs = []
4594 for b in opts['bookmark']:
4594 for b in opts['bookmark']:
4595 if b not in remotebookmarks:
4595 if b not in remotebookmarks:
4596 raise util.Abort(_('remote bookmark %s not found!') % b)
4596 raise util.Abort(_('remote bookmark %s not found!') % b)
4597 revs.append(remotebookmarks[b])
4597 revs.append(remotebookmarks[b])
4598
4598
4599 if revs:
4599 if revs:
4600 try:
4600 try:
4601 revs = [other.lookup(rev) for rev in revs]
4601 revs = [other.lookup(rev) for rev in revs]
4602 except error.CapabilityError:
4602 except error.CapabilityError:
4603 err = _("other repository doesn't support revision lookup, "
4603 err = _("other repository doesn't support revision lookup, "
4604 "so a rev cannot be specified.")
4604 "so a rev cannot be specified.")
4605 raise util.Abort(err)
4605 raise util.Abort(err)
4606
4606
4607 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4607 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4608 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4608 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4609 if checkout:
4609 if checkout:
4610 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4610 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4611 repo._subtoppath = source
4611 repo._subtoppath = source
4612 try:
4612 try:
4613 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4613 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4614
4614
4615 finally:
4615 finally:
4616 del repo._subtoppath
4616 del repo._subtoppath
4617
4617
4618 # update specified bookmarks
4618 # update specified bookmarks
4619 if opts.get('bookmark'):
4619 if opts.get('bookmark'):
4620 marks = repo._bookmarks
4620 marks = repo._bookmarks
4621 for b in opts['bookmark']:
4621 for b in opts['bookmark']:
4622 # explicit pull overrides local bookmark if any
4622 # explicit pull overrides local bookmark if any
4623 ui.status(_("importing bookmark %s\n") % b)
4623 ui.status(_("importing bookmark %s\n") % b)
4624 marks[b] = repo[remotebookmarks[b]].node()
4624 marks[b] = repo[remotebookmarks[b]].node()
4625 marks.write()
4625 marks.write()
4626 finally:
4626 finally:
4627 other.close()
4627 other.close()
4628 return ret
4628 return ret
4629
4629
4630 @command('^push',
4630 @command('^push',
4631 [('f', 'force', None, _('force push')),
4631 [('f', 'force', None, _('force push')),
4632 ('r', 'rev', [],
4632 ('r', 'rev', [],
4633 _('a changeset intended to be included in the destination'),
4633 _('a changeset intended to be included in the destination'),
4634 _('REV')),
4634 _('REV')),
4635 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4635 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4636 ('b', 'branch', [],
4636 ('b', 'branch', [],
4637 _('a specific branch you would like to push'), _('BRANCH')),
4637 _('a specific branch you would like to push'), _('BRANCH')),
4638 ('', 'new-branch', False, _('allow pushing a new branch')),
4638 ('', 'new-branch', False, _('allow pushing a new branch')),
4639 ] + remoteopts,
4639 ] + remoteopts,
4640 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4640 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4641 def push(ui, repo, dest=None, **opts):
4641 def push(ui, repo, dest=None, **opts):
4642 """push changes to the specified destination
4642 """push changes to the specified destination
4643
4643
4644 Push changesets from the local repository to the specified
4644 Push changesets from the local repository to the specified
4645 destination.
4645 destination.
4646
4646
4647 This operation is symmetrical to pull: it is identical to a pull
4647 This operation is symmetrical to pull: it is identical to a pull
4648 in the destination repository from the current one.
4648 in the destination repository from the current one.
4649
4649
4650 By default, push will not allow creation of new heads at the
4650 By default, push will not allow creation of new heads at the
4651 destination, since multiple heads would make it unclear which head
4651 destination, since multiple heads would make it unclear which head
4652 to use. In this situation, it is recommended to pull and merge
4652 to use. In this situation, it is recommended to pull and merge
4653 before pushing.
4653 before pushing.
4654
4654
4655 Use --new-branch if you want to allow push to create a new named
4655 Use --new-branch if you want to allow push to create a new named
4656 branch that is not present at the destination. This allows you to
4656 branch that is not present at the destination. This allows you to
4657 only create a new branch without forcing other changes.
4657 only create a new branch without forcing other changes.
4658
4658
4659 .. note::
4659 .. note::
4660
4660
4661 Extra care should be taken with the -f/--force option,
4661 Extra care should be taken with the -f/--force option,
4662 which will push all new heads on all branches, an action which will
4662 which will push all new heads on all branches, an action which will
4663 almost always cause confusion for collaborators.
4663 almost always cause confusion for collaborators.
4664
4664
4665 If -r/--rev is used, the specified revision and all its ancestors
4665 If -r/--rev is used, the specified revision and all its ancestors
4666 will be pushed to the remote repository.
4666 will be pushed to the remote repository.
4667
4667
4668 If -B/--bookmark is used, the specified bookmarked revision, its
4668 If -B/--bookmark is used, the specified bookmarked revision, its
4669 ancestors, and the bookmark will be pushed to the remote
4669 ancestors, and the bookmark will be pushed to the remote
4670 repository.
4670 repository.
4671
4671
4672 Please see :hg:`help urls` for important details about ``ssh://``
4672 Please see :hg:`help urls` for important details about ``ssh://``
4673 URLs. If DESTINATION is omitted, a default path will be used.
4673 URLs. If DESTINATION is omitted, a default path will be used.
4674
4674
4675 Returns 0 if push was successful, 1 if nothing to push.
4675 Returns 0 if push was successful, 1 if nothing to push.
4676 """
4676 """
4677
4677
4678 if opts.get('bookmark'):
4678 if opts.get('bookmark'):
4679 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4679 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4680 for b in opts['bookmark']:
4680 for b in opts['bookmark']:
4681 # translate -B options to -r so changesets get pushed
4681 # translate -B options to -r so changesets get pushed
4682 if b in repo._bookmarks:
4682 if b in repo._bookmarks:
4683 opts.setdefault('rev', []).append(b)
4683 opts.setdefault('rev', []).append(b)
4684 else:
4684 else:
4685 # if we try to push a deleted bookmark, translate it to null
4685 # if we try to push a deleted bookmark, translate it to null
4686 # this lets simultaneous -r, -b options continue working
4686 # this lets simultaneous -r, -b options continue working
4687 opts.setdefault('rev', []).append("null")
4687 opts.setdefault('rev', []).append("null")
4688
4688
4689 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4689 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4690 dest, branches = hg.parseurl(dest, opts.get('branch'))
4690 dest, branches = hg.parseurl(dest, opts.get('branch'))
4691 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4691 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4692 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4692 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4693 try:
4693 try:
4694 other = hg.peer(repo, opts, dest)
4694 other = hg.peer(repo, opts, dest)
4695 except error.RepoError:
4695 except error.RepoError:
4696 if dest == "default-push":
4696 if dest == "default-push":
4697 raise util.Abort(_("default repository not configured!"),
4697 raise util.Abort(_("default repository not configured!"),
4698 hint=_('see the "path" section in "hg help config"'))
4698 hint=_('see the "path" section in "hg help config"'))
4699 else:
4699 else:
4700 raise
4700 raise
4701
4701
4702 if revs:
4702 if revs:
4703 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4703 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4704
4704
4705 repo._subtoppath = dest
4705 repo._subtoppath = dest
4706 try:
4706 try:
4707 # push subrepos depth-first for coherent ordering
4707 # push subrepos depth-first for coherent ordering
4708 c = repo['']
4708 c = repo['']
4709 subs = c.substate # only repos that are committed
4709 subs = c.substate # only repos that are committed
4710 for s in sorted(subs):
4710 for s in sorted(subs):
4711 result = c.sub(s).push(opts)
4711 result = c.sub(s).push(opts)
4712 if result == 0:
4712 if result == 0:
4713 return not result
4713 return not result
4714 finally:
4714 finally:
4715 del repo._subtoppath
4715 del repo._subtoppath
4716 result = repo.push(other, opts.get('force'), revs=revs,
4716 result = repo.push(other, opts.get('force'), revs=revs,
4717 newbranch=opts.get('new_branch'))
4717 newbranch=opts.get('new_branch'))
4718
4718
4719 result = not result
4719 result = not result
4720
4720
4721 if opts.get('bookmark'):
4721 if opts.get('bookmark'):
4722 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4722 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4723 if bresult == 2:
4723 if bresult == 2:
4724 return 2
4724 return 2
4725 if not result and bresult:
4725 if not result and bresult:
4726 result = 2
4726 result = 2
4727
4727
4728 return result
4728 return result
4729
4729
4730 @command('recover', [])
4730 @command('recover', [])
4731 def recover(ui, repo):
4731 def recover(ui, repo):
4732 """roll back an interrupted transaction
4732 """roll back an interrupted transaction
4733
4733
4734 Recover from an interrupted commit or pull.
4734 Recover from an interrupted commit or pull.
4735
4735
4736 This command tries to fix the repository status after an
4736 This command tries to fix the repository status after an
4737 interrupted operation. It should only be necessary when Mercurial
4737 interrupted operation. It should only be necessary when Mercurial
4738 suggests it.
4738 suggests it.
4739
4739
4740 Returns 0 if successful, 1 if nothing to recover or verify fails.
4740 Returns 0 if successful, 1 if nothing to recover or verify fails.
4741 """
4741 """
4742 if repo.recover():
4742 if repo.recover():
4743 return hg.verify(repo)
4743 return hg.verify(repo)
4744 return 1
4744 return 1
4745
4745
4746 @command('^remove|rm',
4746 @command('^remove|rm',
4747 [('A', 'after', None, _('record delete for missing files')),
4747 [('A', 'after', None, _('record delete for missing files')),
4748 ('f', 'force', None,
4748 ('f', 'force', None,
4749 _('remove (and delete) file even if added or modified')),
4749 _('remove (and delete) file even if added or modified')),
4750 ] + walkopts,
4750 ] + walkopts,
4751 _('[OPTION]... FILE...'))
4751 _('[OPTION]... FILE...'))
4752 def remove(ui, repo, *pats, **opts):
4752 def remove(ui, repo, *pats, **opts):
4753 """remove the specified files on the next commit
4753 """remove the specified files on the next commit
4754
4754
4755 Schedule the indicated files for removal from the current branch.
4755 Schedule the indicated files for removal from the current branch.
4756
4756
4757 This command schedules the files to be removed at the next commit.
4757 This command schedules the files to be removed at the next commit.
4758 To undo a remove before that, see :hg:`revert`. To undo added
4758 To undo a remove before that, see :hg:`revert`. To undo added
4759 files, see :hg:`forget`.
4759 files, see :hg:`forget`.
4760
4760
4761 .. container:: verbose
4761 .. container:: verbose
4762
4762
4763 -A/--after can be used to remove only files that have already
4763 -A/--after can be used to remove only files that have already
4764 been deleted, -f/--force can be used to force deletion, and -Af
4764 been deleted, -f/--force can be used to force deletion, and -Af
4765 can be used to remove files from the next revision without
4765 can be used to remove files from the next revision without
4766 deleting them from the working directory.
4766 deleting them from the working directory.
4767
4767
4768 The following table details the behavior of remove for different
4768 The following table details the behavior of remove for different
4769 file states (columns) and option combinations (rows). The file
4769 file states (columns) and option combinations (rows). The file
4770 states are Added [A], Clean [C], Modified [M] and Missing [!]
4770 states are Added [A], Clean [C], Modified [M] and Missing [!]
4771 (as reported by :hg:`status`). The actions are Warn, Remove
4771 (as reported by :hg:`status`). The actions are Warn, Remove
4772 (from branch) and Delete (from disk):
4772 (from branch) and Delete (from disk):
4773
4773
4774 ========= == == == ==
4774 ========= == == == ==
4775 opt/state A C M !
4775 opt/state A C M !
4776 ========= == == == ==
4776 ========= == == == ==
4777 none W RD W R
4777 none W RD W R
4778 -f R RD RD R
4778 -f R RD RD R
4779 -A W W W R
4779 -A W W W R
4780 -Af R R R R
4780 -Af R R R R
4781 ========= == == == ==
4781 ========= == == == ==
4782
4782
4783 Note that remove never deletes files in Added [A] state from the
4783 Note that remove never deletes files in Added [A] state from the
4784 working directory, not even if option --force is specified.
4784 working directory, not even if option --force is specified.
4785
4785
4786 Returns 0 on success, 1 if any warnings encountered.
4786 Returns 0 on success, 1 if any warnings encountered.
4787 """
4787 """
4788
4788
4789 ret = 0
4789 ret = 0
4790 after, force = opts.get('after'), opts.get('force')
4790 after, force = opts.get('after'), opts.get('force')
4791 if not pats and not after:
4791 if not pats and not after:
4792 raise util.Abort(_('no files specified'))
4792 raise util.Abort(_('no files specified'))
4793
4793
4794 m = scmutil.match(repo[None], pats, opts)
4794 m = scmutil.match(repo[None], pats, opts)
4795 s = repo.status(match=m, clean=True)
4795 s = repo.status(match=m, clean=True)
4796 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4796 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4797
4797
4798 # warn about failure to delete explicit files/dirs
4798 # warn about failure to delete explicit files/dirs
4799 wctx = repo[None]
4799 wctx = repo[None]
4800 for f in m.files():
4800 for f in m.files():
4801 if f in repo.dirstate or f in wctx.dirs():
4801 if f in repo.dirstate or f in wctx.dirs():
4802 continue
4802 continue
4803 if os.path.exists(m.rel(f)):
4803 if os.path.exists(m.rel(f)):
4804 if os.path.isdir(m.rel(f)):
4804 if os.path.isdir(m.rel(f)):
4805 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4805 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4806 else:
4806 else:
4807 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4807 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4808 # missing files will generate a warning elsewhere
4808 # missing files will generate a warning elsewhere
4809 ret = 1
4809 ret = 1
4810
4810
4811 if force:
4811 if force:
4812 list = modified + deleted + clean + added
4812 list = modified + deleted + clean + added
4813 elif after:
4813 elif after:
4814 list = deleted
4814 list = deleted
4815 for f in modified + added + clean:
4815 for f in modified + added + clean:
4816 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4816 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4817 ret = 1
4817 ret = 1
4818 else:
4818 else:
4819 list = deleted + clean
4819 list = deleted + clean
4820 for f in modified:
4820 for f in modified:
4821 ui.warn(_('not removing %s: file is modified (use -f'
4821 ui.warn(_('not removing %s: file is modified (use -f'
4822 ' to force removal)\n') % m.rel(f))
4822 ' to force removal)\n') % m.rel(f))
4823 ret = 1
4823 ret = 1
4824 for f in added:
4824 for f in added:
4825 ui.warn(_('not removing %s: file has been marked for add'
4825 ui.warn(_('not removing %s: file has been marked for add'
4826 ' (use forget to undo)\n') % m.rel(f))
4826 ' (use forget to undo)\n') % m.rel(f))
4827 ret = 1
4827 ret = 1
4828
4828
4829 for f in sorted(list):
4829 for f in sorted(list):
4830 if ui.verbose or not m.exact(f):
4830 if ui.verbose or not m.exact(f):
4831 ui.status(_('removing %s\n') % m.rel(f))
4831 ui.status(_('removing %s\n') % m.rel(f))
4832
4832
4833 wlock = repo.wlock()
4833 wlock = repo.wlock()
4834 try:
4834 try:
4835 if not after:
4835 if not after:
4836 for f in list:
4836 for f in list:
4837 if f in added:
4837 if f in added:
4838 continue # we never unlink added files on remove
4838 continue # we never unlink added files on remove
4839 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4839 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4840 repo[None].forget(list)
4840 repo[None].forget(list)
4841 finally:
4841 finally:
4842 wlock.release()
4842 wlock.release()
4843
4843
4844 return ret
4844 return ret
4845
4845
4846 @command('rename|move|mv',
4846 @command('rename|move|mv',
4847 [('A', 'after', None, _('record a rename that has already occurred')),
4847 [('A', 'after', None, _('record a rename that has already occurred')),
4848 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4848 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4849 ] + walkopts + dryrunopts,
4849 ] + walkopts + dryrunopts,
4850 _('[OPTION]... SOURCE... DEST'))
4850 _('[OPTION]... SOURCE... DEST'))
4851 def rename(ui, repo, *pats, **opts):
4851 def rename(ui, repo, *pats, **opts):
4852 """rename files; equivalent of copy + remove
4852 """rename files; equivalent of copy + remove
4853
4853
4854 Mark dest as copies of sources; mark sources for deletion. If dest
4854 Mark dest as copies of sources; mark sources for deletion. If dest
4855 is a directory, copies are put in that directory. If dest is a
4855 is a directory, copies are put in that directory. If dest is a
4856 file, there can only be one source.
4856 file, there can only be one source.
4857
4857
4858 By default, this command copies the contents of files as they
4858 By default, this command copies the contents of files as they
4859 exist in the working directory. If invoked with -A/--after, the
4859 exist in the working directory. If invoked with -A/--after, the
4860 operation is recorded, but no copying is performed.
4860 operation is recorded, but no copying is performed.
4861
4861
4862 This command takes effect at the next commit. To undo a rename
4862 This command takes effect at the next commit. To undo a rename
4863 before that, see :hg:`revert`.
4863 before that, see :hg:`revert`.
4864
4864
4865 Returns 0 on success, 1 if errors are encountered.
4865 Returns 0 on success, 1 if errors are encountered.
4866 """
4866 """
4867 wlock = repo.wlock(False)
4867 wlock = repo.wlock(False)
4868 try:
4868 try:
4869 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4869 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4870 finally:
4870 finally:
4871 wlock.release()
4871 wlock.release()
4872
4872
4873 @command('resolve',
4873 @command('resolve',
4874 [('a', 'all', None, _('select all unresolved files')),
4874 [('a', 'all', None, _('select all unresolved files')),
4875 ('l', 'list', None, _('list state of files needing merge')),
4875 ('l', 'list', None, _('list state of files needing merge')),
4876 ('m', 'mark', None, _('mark files as resolved')),
4876 ('m', 'mark', None, _('mark files as resolved')),
4877 ('u', 'unmark', None, _('mark files as unresolved')),
4877 ('u', 'unmark', None, _('mark files as unresolved')),
4878 ('n', 'no-status', None, _('hide status prefix'))]
4878 ('n', 'no-status', None, _('hide status prefix'))]
4879 + mergetoolopts + walkopts,
4879 + mergetoolopts + walkopts,
4880 _('[OPTION]... [FILE]...'))
4880 _('[OPTION]... [FILE]...'))
4881 def resolve(ui, repo, *pats, **opts):
4881 def resolve(ui, repo, *pats, **opts):
4882 """redo merges or set/view the merge status of files
4882 """redo merges or set/view the merge status of files
4883
4883
4884 Merges with unresolved conflicts are often the result of
4884 Merges with unresolved conflicts are often the result of
4885 non-interactive merging using the ``internal:merge`` configuration
4885 non-interactive merging using the ``internal:merge`` configuration
4886 setting, or a command-line merge tool like ``diff3``. The resolve
4886 setting, or a command-line merge tool like ``diff3``. The resolve
4887 command is used to manage the files involved in a merge, after
4887 command is used to manage the files involved in a merge, after
4888 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4888 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4889 working directory must have two parents). See :hg:`help
4889 working directory must have two parents). See :hg:`help
4890 merge-tools` for information on configuring merge tools.
4890 merge-tools` for information on configuring merge tools.
4891
4891
4892 The resolve command can be used in the following ways:
4892 The resolve command can be used in the following ways:
4893
4893
4894 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4894 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4895 files, discarding any previous merge attempts. Re-merging is not
4895 files, discarding any previous merge attempts. Re-merging is not
4896 performed for files already marked as resolved. Use ``--all/-a``
4896 performed for files already marked as resolved. Use ``--all/-a``
4897 to select all unresolved files. ``--tool`` can be used to specify
4897 to select all unresolved files. ``--tool`` can be used to specify
4898 the merge tool used for the given files. It overrides the HGMERGE
4898 the merge tool used for the given files. It overrides the HGMERGE
4899 environment variable and your configuration files. Previous file
4899 environment variable and your configuration files. Previous file
4900 contents are saved with a ``.orig`` suffix.
4900 contents are saved with a ``.orig`` suffix.
4901
4901
4902 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4902 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4903 (e.g. after having manually fixed-up the files). The default is
4903 (e.g. after having manually fixed-up the files). The default is
4904 to mark all unresolved files.
4904 to mark all unresolved files.
4905
4905
4906 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4906 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4907 default is to mark all resolved files.
4907 default is to mark all resolved files.
4908
4908
4909 - :hg:`resolve -l`: list files which had or still have conflicts.
4909 - :hg:`resolve -l`: list files which had or still have conflicts.
4910 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4910 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4911
4911
4912 Note that Mercurial will not let you commit files with unresolved
4912 Note that Mercurial will not let you commit files with unresolved
4913 merge conflicts. You must use :hg:`resolve -m ...` before you can
4913 merge conflicts. You must use :hg:`resolve -m ...` before you can
4914 commit after a conflicting merge.
4914 commit after a conflicting merge.
4915
4915
4916 Returns 0 on success, 1 if any files fail a resolve attempt.
4916 Returns 0 on success, 1 if any files fail a resolve attempt.
4917 """
4917 """
4918
4918
4919 all, mark, unmark, show, nostatus = \
4919 all, mark, unmark, show, nostatus = \
4920 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4920 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4921
4921
4922 if (show and (mark or unmark)) or (mark and unmark):
4922 if (show and (mark or unmark)) or (mark and unmark):
4923 raise util.Abort(_("too many options specified"))
4923 raise util.Abort(_("too many options specified"))
4924 if pats and all:
4924 if pats and all:
4925 raise util.Abort(_("can't specify --all and patterns"))
4925 raise util.Abort(_("can't specify --all and patterns"))
4926 if not (all or pats or show or mark or unmark):
4926 if not (all or pats or show or mark or unmark):
4927 raise util.Abort(_('no files or directories specified; '
4927 raise util.Abort(_('no files or directories specified; '
4928 'use --all to remerge all files'))
4928 'use --all to remerge all files'))
4929
4929
4930 ms = mergemod.mergestate(repo)
4930 wlock = repo.wlock()
4931 m = scmutil.match(repo[None], pats, opts)
4931 try:
4932 ret = 0
4932 ms = mergemod.mergestate(repo)
4933
4933 m = scmutil.match(repo[None], pats, opts)
4934 for f in ms:
4934 ret = 0
4935 if m(f):
4935
4936 if show:
4936 for f in ms:
4937 if nostatus:
4937 if m(f):
4938 ui.write("%s\n" % f)
4938 if show:
4939 if nostatus:
4940 ui.write("%s\n" % f)
4941 else:
4942 ui.write("%s %s\n" % (ms[f].upper(), f),
4943 label='resolve.' +
4944 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4945 elif mark:
4946 ms.mark(f, "r")
4947 elif unmark:
4948 ms.mark(f, "u")
4939 else:
4949 else:
4940 ui.write("%s %s\n" % (ms[f].upper(), f),
4950 wctx = repo[None]
4941 label='resolve.' +
4951
4942 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4952 # backup pre-resolve (merge uses .orig for its own purposes)
4943 elif mark:
4953 a = repo.wjoin(f)
4944 ms.mark(f, "r")
4954 util.copyfile(a, a + ".resolve")
4945 elif unmark:
4955
4946 ms.mark(f, "u")
4956 try:
4947 else:
4957 # resolve file
4948 wctx = repo[None]
4958 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4949
4959 'resolve')
4950 # backup pre-resolve (merge uses .orig for its own purposes)
4960 if ms.resolve(f, wctx):
4951 a = repo.wjoin(f)
4961 ret = 1
4952 util.copyfile(a, a + ".resolve")
4962 finally:
4953
4963 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4954 try:
4964 ms.commit()
4955 # resolve file
4965
4956 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4966 # replace filemerge's .orig file with our resolve file
4957 'resolve')
4967 util.rename(a + ".resolve", a + ".orig")
4958 if ms.resolve(f, wctx):
4968
4959 ret = 1
4969 ms.commit()
4960 finally:
4970 finally:
4961 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4971 wlock.release()
4962 ms.commit()
4972
4963
4964 # replace filemerge's .orig file with our resolve file
4965 util.rename(a + ".resolve", a + ".orig")
4966
4967 ms.commit()
4968 return ret
4973 return ret
4969
4974
4970 @command('revert',
4975 @command('revert',
4971 [('a', 'all', None, _('revert all changes when no arguments given')),
4976 [('a', 'all', None, _('revert all changes when no arguments given')),
4972 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4977 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4973 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4978 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4974 ('C', 'no-backup', None, _('do not save backup copies of files')),
4979 ('C', 'no-backup', None, _('do not save backup copies of files')),
4975 ] + walkopts + dryrunopts,
4980 ] + walkopts + dryrunopts,
4976 _('[OPTION]... [-r REV] [NAME]...'))
4981 _('[OPTION]... [-r REV] [NAME]...'))
4977 def revert(ui, repo, *pats, **opts):
4982 def revert(ui, repo, *pats, **opts):
4978 """restore files to their checkout state
4983 """restore files to their checkout state
4979
4984
4980 .. note::
4985 .. note::
4981
4986
4982 To check out earlier revisions, you should use :hg:`update REV`.
4987 To check out earlier revisions, you should use :hg:`update REV`.
4983 To cancel an uncommitted merge (and lose your changes),
4988 To cancel an uncommitted merge (and lose your changes),
4984 use :hg:`update --clean .`.
4989 use :hg:`update --clean .`.
4985
4990
4986 With no revision specified, revert the specified files or directories
4991 With no revision specified, revert the specified files or directories
4987 to the contents they had in the parent of the working directory.
4992 to the contents they had in the parent of the working directory.
4988 This restores the contents of files to an unmodified
4993 This restores the contents of files to an unmodified
4989 state and unschedules adds, removes, copies, and renames. If the
4994 state and unschedules adds, removes, copies, and renames. If the
4990 working directory has two parents, you must explicitly specify a
4995 working directory has two parents, you must explicitly specify a
4991 revision.
4996 revision.
4992
4997
4993 Using the -r/--rev or -d/--date options, revert the given files or
4998 Using the -r/--rev or -d/--date options, revert the given files or
4994 directories to their states as of a specific revision. Because
4999 directories to their states as of a specific revision. Because
4995 revert does not change the working directory parents, this will
5000 revert does not change the working directory parents, this will
4996 cause these files to appear modified. This can be helpful to "back
5001 cause these files to appear modified. This can be helpful to "back
4997 out" some or all of an earlier change. See :hg:`backout` for a
5002 out" some or all of an earlier change. See :hg:`backout` for a
4998 related method.
5003 related method.
4999
5004
5000 Modified files are saved with a .orig suffix before reverting.
5005 Modified files are saved with a .orig suffix before reverting.
5001 To disable these backups, use --no-backup.
5006 To disable these backups, use --no-backup.
5002
5007
5003 See :hg:`help dates` for a list of formats valid for -d/--date.
5008 See :hg:`help dates` for a list of formats valid for -d/--date.
5004
5009
5005 Returns 0 on success.
5010 Returns 0 on success.
5006 """
5011 """
5007
5012
5008 if opts.get("date"):
5013 if opts.get("date"):
5009 if opts.get("rev"):
5014 if opts.get("rev"):
5010 raise util.Abort(_("you can't specify a revision and a date"))
5015 raise util.Abort(_("you can't specify a revision and a date"))
5011 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5016 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5012
5017
5013 parent, p2 = repo.dirstate.parents()
5018 parent, p2 = repo.dirstate.parents()
5014 if not opts.get('rev') and p2 != nullid:
5019 if not opts.get('rev') and p2 != nullid:
5015 # revert after merge is a trap for new users (issue2915)
5020 # revert after merge is a trap for new users (issue2915)
5016 raise util.Abort(_('uncommitted merge with no revision specified'),
5021 raise util.Abort(_('uncommitted merge with no revision specified'),
5017 hint=_('use "hg update" or see "hg help revert"'))
5022 hint=_('use "hg update" or see "hg help revert"'))
5018
5023
5019 ctx = scmutil.revsingle(repo, opts.get('rev'))
5024 ctx = scmutil.revsingle(repo, opts.get('rev'))
5020
5025
5021 if not pats and not opts.get('all'):
5026 if not pats and not opts.get('all'):
5022 msg = _("no files or directories specified")
5027 msg = _("no files or directories specified")
5023 if p2 != nullid:
5028 if p2 != nullid:
5024 hint = _("uncommitted merge, use --all to discard all changes,"
5029 hint = _("uncommitted merge, use --all to discard all changes,"
5025 " or 'hg update -C .' to abort the merge")
5030 " or 'hg update -C .' to abort the merge")
5026 raise util.Abort(msg, hint=hint)
5031 raise util.Abort(msg, hint=hint)
5027 dirty = util.any(repo.status())
5032 dirty = util.any(repo.status())
5028 node = ctx.node()
5033 node = ctx.node()
5029 if node != parent:
5034 if node != parent:
5030 if dirty:
5035 if dirty:
5031 hint = _("uncommitted changes, use --all to discard all"
5036 hint = _("uncommitted changes, use --all to discard all"
5032 " changes, or 'hg update %s' to update") % ctx.rev()
5037 " changes, or 'hg update %s' to update") % ctx.rev()
5033 else:
5038 else:
5034 hint = _("use --all to revert all files,"
5039 hint = _("use --all to revert all files,"
5035 " or 'hg update %s' to update") % ctx.rev()
5040 " or 'hg update %s' to update") % ctx.rev()
5036 elif dirty:
5041 elif dirty:
5037 hint = _("uncommitted changes, use --all to discard all changes")
5042 hint = _("uncommitted changes, use --all to discard all changes")
5038 else:
5043 else:
5039 hint = _("use --all to revert all files")
5044 hint = _("use --all to revert all files")
5040 raise util.Abort(msg, hint=hint)
5045 raise util.Abort(msg, hint=hint)
5041
5046
5042 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5047 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5043
5048
5044 @command('rollback', dryrunopts +
5049 @command('rollback', dryrunopts +
5045 [('f', 'force', False, _('ignore safety measures'))])
5050 [('f', 'force', False, _('ignore safety measures'))])
5046 def rollback(ui, repo, **opts):
5051 def rollback(ui, repo, **opts):
5047 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5052 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5048
5053
5049 Please use :hg:`commit --amend` instead of rollback to correct
5054 Please use :hg:`commit --amend` instead of rollback to correct
5050 mistakes in the last commit.
5055 mistakes in the last commit.
5051
5056
5052 This command should be used with care. There is only one level of
5057 This command should be used with care. There is only one level of
5053 rollback, and there is no way to undo a rollback. It will also
5058 rollback, and there is no way to undo a rollback. It will also
5054 restore the dirstate at the time of the last transaction, losing
5059 restore the dirstate at the time of the last transaction, losing
5055 any dirstate changes since that time. This command does not alter
5060 any dirstate changes since that time. This command does not alter
5056 the working directory.
5061 the working directory.
5057
5062
5058 Transactions are used to encapsulate the effects of all commands
5063 Transactions are used to encapsulate the effects of all commands
5059 that create new changesets or propagate existing changesets into a
5064 that create new changesets or propagate existing changesets into a
5060 repository.
5065 repository.
5061
5066
5062 .. container:: verbose
5067 .. container:: verbose
5063
5068
5064 For example, the following commands are transactional, and their
5069 For example, the following commands are transactional, and their
5065 effects can be rolled back:
5070 effects can be rolled back:
5066
5071
5067 - commit
5072 - commit
5068 - import
5073 - import
5069 - pull
5074 - pull
5070 - push (with this repository as the destination)
5075 - push (with this repository as the destination)
5071 - unbundle
5076 - unbundle
5072
5077
5073 To avoid permanent data loss, rollback will refuse to rollback a
5078 To avoid permanent data loss, rollback will refuse to rollback a
5074 commit transaction if it isn't checked out. Use --force to
5079 commit transaction if it isn't checked out. Use --force to
5075 override this protection.
5080 override this protection.
5076
5081
5077 This command is not intended for use on public repositories. Once
5082 This command is not intended for use on public repositories. Once
5078 changes are visible for pull by other users, rolling a transaction
5083 changes are visible for pull by other users, rolling a transaction
5079 back locally is ineffective (someone else may already have pulled
5084 back locally is ineffective (someone else may already have pulled
5080 the changes). Furthermore, a race is possible with readers of the
5085 the changes). Furthermore, a race is possible with readers of the
5081 repository; for example an in-progress pull from the repository
5086 repository; for example an in-progress pull from the repository
5082 may fail if a rollback is performed.
5087 may fail if a rollback is performed.
5083
5088
5084 Returns 0 on success, 1 if no rollback data is available.
5089 Returns 0 on success, 1 if no rollback data is available.
5085 """
5090 """
5086 return repo.rollback(dryrun=opts.get('dry_run'),
5091 return repo.rollback(dryrun=opts.get('dry_run'),
5087 force=opts.get('force'))
5092 force=opts.get('force'))
5088
5093
5089 @command('root', [])
5094 @command('root', [])
5090 def root(ui, repo):
5095 def root(ui, repo):
5091 """print the root (top) of the current working directory
5096 """print the root (top) of the current working directory
5092
5097
5093 Print the root directory of the current repository.
5098 Print the root directory of the current repository.
5094
5099
5095 Returns 0 on success.
5100 Returns 0 on success.
5096 """
5101 """
5097 ui.write(repo.root + "\n")
5102 ui.write(repo.root + "\n")
5098
5103
5099 @command('^serve',
5104 @command('^serve',
5100 [('A', 'accesslog', '', _('name of access log file to write to'),
5105 [('A', 'accesslog', '', _('name of access log file to write to'),
5101 _('FILE')),
5106 _('FILE')),
5102 ('d', 'daemon', None, _('run server in background')),
5107 ('d', 'daemon', None, _('run server in background')),
5103 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5108 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5104 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5109 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5105 # use string type, then we can check if something was passed
5110 # use string type, then we can check if something was passed
5106 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5111 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5107 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5112 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5108 _('ADDR')),
5113 _('ADDR')),
5109 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5114 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5110 _('PREFIX')),
5115 _('PREFIX')),
5111 ('n', 'name', '',
5116 ('n', 'name', '',
5112 _('name to show in web pages (default: working directory)'), _('NAME')),
5117 _('name to show in web pages (default: working directory)'), _('NAME')),
5113 ('', 'web-conf', '',
5118 ('', 'web-conf', '',
5114 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5119 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5115 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5120 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5116 _('FILE')),
5121 _('FILE')),
5117 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5122 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5118 ('', 'stdio', None, _('for remote clients')),
5123 ('', 'stdio', None, _('for remote clients')),
5119 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5124 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5120 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5125 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5121 ('', 'style', '', _('template style to use'), _('STYLE')),
5126 ('', 'style', '', _('template style to use'), _('STYLE')),
5122 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5127 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5123 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5128 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5124 _('[OPTION]...'))
5129 _('[OPTION]...'))
5125 def serve(ui, repo, **opts):
5130 def serve(ui, repo, **opts):
5126 """start stand-alone webserver
5131 """start stand-alone webserver
5127
5132
5128 Start a local HTTP repository browser and pull server. You can use
5133 Start a local HTTP repository browser and pull server. You can use
5129 this for ad-hoc sharing and browsing of repositories. It is
5134 this for ad-hoc sharing and browsing of repositories. It is
5130 recommended to use a real web server to serve a repository for
5135 recommended to use a real web server to serve a repository for
5131 longer periods of time.
5136 longer periods of time.
5132
5137
5133 Please note that the server does not implement access control.
5138 Please note that the server does not implement access control.
5134 This means that, by default, anybody can read from the server and
5139 This means that, by default, anybody can read from the server and
5135 nobody can write to it by default. Set the ``web.allow_push``
5140 nobody can write to it by default. Set the ``web.allow_push``
5136 option to ``*`` to allow everybody to push to the server. You
5141 option to ``*`` to allow everybody to push to the server. You
5137 should use a real web server if you need to authenticate users.
5142 should use a real web server if you need to authenticate users.
5138
5143
5139 By default, the server logs accesses to stdout and errors to
5144 By default, the server logs accesses to stdout and errors to
5140 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5145 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5141 files.
5146 files.
5142
5147
5143 To have the server choose a free port number to listen on, specify
5148 To have the server choose a free port number to listen on, specify
5144 a port number of 0; in this case, the server will print the port
5149 a port number of 0; in this case, the server will print the port
5145 number it uses.
5150 number it uses.
5146
5151
5147 Returns 0 on success.
5152 Returns 0 on success.
5148 """
5153 """
5149
5154
5150 if opts["stdio"] and opts["cmdserver"]:
5155 if opts["stdio"] and opts["cmdserver"]:
5151 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5156 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5152
5157
5153 def checkrepo():
5158 def checkrepo():
5154 if repo is None:
5159 if repo is None:
5155 raise error.RepoError(_("there is no Mercurial repository here"
5160 raise error.RepoError(_("there is no Mercurial repository here"
5156 " (.hg not found)"))
5161 " (.hg not found)"))
5157
5162
5158 if opts["stdio"]:
5163 if opts["stdio"]:
5159 checkrepo()
5164 checkrepo()
5160 s = sshserver.sshserver(ui, repo)
5165 s = sshserver.sshserver(ui, repo)
5161 s.serve_forever()
5166 s.serve_forever()
5162
5167
5163 if opts["cmdserver"]:
5168 if opts["cmdserver"]:
5164 s = commandserver.server(ui, repo, opts["cmdserver"])
5169 s = commandserver.server(ui, repo, opts["cmdserver"])
5165 return s.serve()
5170 return s.serve()
5166
5171
5167 # this way we can check if something was given in the command-line
5172 # this way we can check if something was given in the command-line
5168 if opts.get('port'):
5173 if opts.get('port'):
5169 opts['port'] = util.getport(opts.get('port'))
5174 opts['port'] = util.getport(opts.get('port'))
5170
5175
5171 baseui = repo and repo.baseui or ui
5176 baseui = repo and repo.baseui or ui
5172 optlist = ("name templates style address port prefix ipv6"
5177 optlist = ("name templates style address port prefix ipv6"
5173 " accesslog errorlog certificate encoding")
5178 " accesslog errorlog certificate encoding")
5174 for o in optlist.split():
5179 for o in optlist.split():
5175 val = opts.get(o, '')
5180 val = opts.get(o, '')
5176 if val in (None, ''): # should check against default options instead
5181 if val in (None, ''): # should check against default options instead
5177 continue
5182 continue
5178 baseui.setconfig("web", o, val, 'serve')
5183 baseui.setconfig("web", o, val, 'serve')
5179 if repo and repo.ui != baseui:
5184 if repo and repo.ui != baseui:
5180 repo.ui.setconfig("web", o, val, 'serve')
5185 repo.ui.setconfig("web", o, val, 'serve')
5181
5186
5182 o = opts.get('web_conf') or opts.get('webdir_conf')
5187 o = opts.get('web_conf') or opts.get('webdir_conf')
5183 if not o:
5188 if not o:
5184 if not repo:
5189 if not repo:
5185 raise error.RepoError(_("there is no Mercurial repository"
5190 raise error.RepoError(_("there is no Mercurial repository"
5186 " here (.hg not found)"))
5191 " here (.hg not found)"))
5187 o = repo
5192 o = repo
5188
5193
5189 app = hgweb.hgweb(o, baseui=baseui)
5194 app = hgweb.hgweb(o, baseui=baseui)
5190 service = httpservice(ui, app, opts)
5195 service = httpservice(ui, app, opts)
5191 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5196 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5192
5197
5193 class httpservice(object):
5198 class httpservice(object):
5194 def __init__(self, ui, app, opts):
5199 def __init__(self, ui, app, opts):
5195 self.ui = ui
5200 self.ui = ui
5196 self.app = app
5201 self.app = app
5197 self.opts = opts
5202 self.opts = opts
5198
5203
5199 def init(self):
5204 def init(self):
5200 util.setsignalhandler()
5205 util.setsignalhandler()
5201 self.httpd = hgweb_server.create_server(self.ui, self.app)
5206 self.httpd = hgweb_server.create_server(self.ui, self.app)
5202
5207
5203 if self.opts['port'] and not self.ui.verbose:
5208 if self.opts['port'] and not self.ui.verbose:
5204 return
5209 return
5205
5210
5206 if self.httpd.prefix:
5211 if self.httpd.prefix:
5207 prefix = self.httpd.prefix.strip('/') + '/'
5212 prefix = self.httpd.prefix.strip('/') + '/'
5208 else:
5213 else:
5209 prefix = ''
5214 prefix = ''
5210
5215
5211 port = ':%d' % self.httpd.port
5216 port = ':%d' % self.httpd.port
5212 if port == ':80':
5217 if port == ':80':
5213 port = ''
5218 port = ''
5214
5219
5215 bindaddr = self.httpd.addr
5220 bindaddr = self.httpd.addr
5216 if bindaddr == '0.0.0.0':
5221 if bindaddr == '0.0.0.0':
5217 bindaddr = '*'
5222 bindaddr = '*'
5218 elif ':' in bindaddr: # IPv6
5223 elif ':' in bindaddr: # IPv6
5219 bindaddr = '[%s]' % bindaddr
5224 bindaddr = '[%s]' % bindaddr
5220
5225
5221 fqaddr = self.httpd.fqaddr
5226 fqaddr = self.httpd.fqaddr
5222 if ':' in fqaddr:
5227 if ':' in fqaddr:
5223 fqaddr = '[%s]' % fqaddr
5228 fqaddr = '[%s]' % fqaddr
5224 if self.opts['port']:
5229 if self.opts['port']:
5225 write = self.ui.status
5230 write = self.ui.status
5226 else:
5231 else:
5227 write = self.ui.write
5232 write = self.ui.write
5228 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5233 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5229 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5234 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5230
5235
5231 def run(self):
5236 def run(self):
5232 self.httpd.serve_forever()
5237 self.httpd.serve_forever()
5233
5238
5234
5239
5235 @command('^status|st',
5240 @command('^status|st',
5236 [('A', 'all', None, _('show status of all files')),
5241 [('A', 'all', None, _('show status of all files')),
5237 ('m', 'modified', None, _('show only modified files')),
5242 ('m', 'modified', None, _('show only modified files')),
5238 ('a', 'added', None, _('show only added files')),
5243 ('a', 'added', None, _('show only added files')),
5239 ('r', 'removed', None, _('show only removed files')),
5244 ('r', 'removed', None, _('show only removed files')),
5240 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5245 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5241 ('c', 'clean', None, _('show only files without changes')),
5246 ('c', 'clean', None, _('show only files without changes')),
5242 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5247 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5243 ('i', 'ignored', None, _('show only ignored files')),
5248 ('i', 'ignored', None, _('show only ignored files')),
5244 ('n', 'no-status', None, _('hide status prefix')),
5249 ('n', 'no-status', None, _('hide status prefix')),
5245 ('C', 'copies', None, _('show source of copied files')),
5250 ('C', 'copies', None, _('show source of copied files')),
5246 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5251 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5247 ('', 'rev', [], _('show difference from revision'), _('REV')),
5252 ('', 'rev', [], _('show difference from revision'), _('REV')),
5248 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5253 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5249 ] + walkopts + subrepoopts,
5254 ] + walkopts + subrepoopts,
5250 _('[OPTION]... [FILE]...'))
5255 _('[OPTION]... [FILE]...'))
5251 def status(ui, repo, *pats, **opts):
5256 def status(ui, repo, *pats, **opts):
5252 """show changed files in the working directory
5257 """show changed files in the working directory
5253
5258
5254 Show status of files in the repository. If names are given, only
5259 Show status of files in the repository. If names are given, only
5255 files that match are shown. Files that are clean or ignored or
5260 files that match are shown. Files that are clean or ignored or
5256 the source of a copy/move operation, are not listed unless
5261 the source of a copy/move operation, are not listed unless
5257 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5262 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5258 Unless options described with "show only ..." are given, the
5263 Unless options described with "show only ..." are given, the
5259 options -mardu are used.
5264 options -mardu are used.
5260
5265
5261 Option -q/--quiet hides untracked (unknown and ignored) files
5266 Option -q/--quiet hides untracked (unknown and ignored) files
5262 unless explicitly requested with -u/--unknown or -i/--ignored.
5267 unless explicitly requested with -u/--unknown or -i/--ignored.
5263
5268
5264 .. note::
5269 .. note::
5265
5270
5266 status may appear to disagree with diff if permissions have
5271 status may appear to disagree with diff if permissions have
5267 changed or a merge has occurred. The standard diff format does
5272 changed or a merge has occurred. The standard diff format does
5268 not report permission changes and diff only reports changes
5273 not report permission changes and diff only reports changes
5269 relative to one merge parent.
5274 relative to one merge parent.
5270
5275
5271 If one revision is given, it is used as the base revision.
5276 If one revision is given, it is used as the base revision.
5272 If two revisions are given, the differences between them are
5277 If two revisions are given, the differences between them are
5273 shown. The --change option can also be used as a shortcut to list
5278 shown. The --change option can also be used as a shortcut to list
5274 the changed files of a revision from its first parent.
5279 the changed files of a revision from its first parent.
5275
5280
5276 The codes used to show the status of files are::
5281 The codes used to show the status of files are::
5277
5282
5278 M = modified
5283 M = modified
5279 A = added
5284 A = added
5280 R = removed
5285 R = removed
5281 C = clean
5286 C = clean
5282 ! = missing (deleted by non-hg command, but still tracked)
5287 ! = missing (deleted by non-hg command, but still tracked)
5283 ? = not tracked
5288 ? = not tracked
5284 I = ignored
5289 I = ignored
5285 = origin of the previous file (with --copies)
5290 = origin of the previous file (with --copies)
5286
5291
5287 .. container:: verbose
5292 .. container:: verbose
5288
5293
5289 Examples:
5294 Examples:
5290
5295
5291 - show changes in the working directory relative to a
5296 - show changes in the working directory relative to a
5292 changeset::
5297 changeset::
5293
5298
5294 hg status --rev 9353
5299 hg status --rev 9353
5295
5300
5296 - show all changes including copies in an existing changeset::
5301 - show all changes including copies in an existing changeset::
5297
5302
5298 hg status --copies --change 9353
5303 hg status --copies --change 9353
5299
5304
5300 - get a NUL separated list of added files, suitable for xargs::
5305 - get a NUL separated list of added files, suitable for xargs::
5301
5306
5302 hg status -an0
5307 hg status -an0
5303
5308
5304 Returns 0 on success.
5309 Returns 0 on success.
5305 """
5310 """
5306
5311
5307 revs = opts.get('rev')
5312 revs = opts.get('rev')
5308 change = opts.get('change')
5313 change = opts.get('change')
5309
5314
5310 if revs and change:
5315 if revs and change:
5311 msg = _('cannot specify --rev and --change at the same time')
5316 msg = _('cannot specify --rev and --change at the same time')
5312 raise util.Abort(msg)
5317 raise util.Abort(msg)
5313 elif change:
5318 elif change:
5314 node2 = scmutil.revsingle(repo, change, None).node()
5319 node2 = scmutil.revsingle(repo, change, None).node()
5315 node1 = repo[node2].p1().node()
5320 node1 = repo[node2].p1().node()
5316 else:
5321 else:
5317 node1, node2 = scmutil.revpair(repo, revs)
5322 node1, node2 = scmutil.revpair(repo, revs)
5318
5323
5319 cwd = (pats and repo.getcwd()) or ''
5324 cwd = (pats and repo.getcwd()) or ''
5320 end = opts.get('print0') and '\0' or '\n'
5325 end = opts.get('print0') and '\0' or '\n'
5321 copy = {}
5326 copy = {}
5322 states = 'modified added removed deleted unknown ignored clean'.split()
5327 states = 'modified added removed deleted unknown ignored clean'.split()
5323 show = [k for k in states if opts.get(k)]
5328 show = [k for k in states if opts.get(k)]
5324 if opts.get('all'):
5329 if opts.get('all'):
5325 show += ui.quiet and (states[:4] + ['clean']) or states
5330 show += ui.quiet and (states[:4] + ['clean']) or states
5326 if not show:
5331 if not show:
5327 show = ui.quiet and states[:4] or states[:5]
5332 show = ui.quiet and states[:4] or states[:5]
5328
5333
5329 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5334 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5330 'ignored' in show, 'clean' in show, 'unknown' in show,
5335 'ignored' in show, 'clean' in show, 'unknown' in show,
5331 opts.get('subrepos'))
5336 opts.get('subrepos'))
5332 changestates = zip(states, 'MAR!?IC', stat)
5337 changestates = zip(states, 'MAR!?IC', stat)
5333
5338
5334 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5339 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5335 copy = copies.pathcopies(repo[node1], repo[node2])
5340 copy = copies.pathcopies(repo[node1], repo[node2])
5336
5341
5337 fm = ui.formatter('status', opts)
5342 fm = ui.formatter('status', opts)
5338 fmt = '%s' + end
5343 fmt = '%s' + end
5339 showchar = not opts.get('no_status')
5344 showchar = not opts.get('no_status')
5340
5345
5341 for state, char, files in changestates:
5346 for state, char, files in changestates:
5342 if state in show:
5347 if state in show:
5343 label = 'status.' + state
5348 label = 'status.' + state
5344 for f in files:
5349 for f in files:
5345 fm.startitem()
5350 fm.startitem()
5346 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5351 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5347 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5352 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5348 if f in copy:
5353 if f in copy:
5349 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5354 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5350 label='status.copied')
5355 label='status.copied')
5351 fm.end()
5356 fm.end()
5352
5357
5353 @command('^summary|sum',
5358 @command('^summary|sum',
5354 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5359 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5355 def summary(ui, repo, **opts):
5360 def summary(ui, repo, **opts):
5356 """summarize working directory state
5361 """summarize working directory state
5357
5362
5358 This generates a brief summary of the working directory state,
5363 This generates a brief summary of the working directory state,
5359 including parents, branch, commit status, and available updates.
5364 including parents, branch, commit status, and available updates.
5360
5365
5361 With the --remote option, this will check the default paths for
5366 With the --remote option, this will check the default paths for
5362 incoming and outgoing changes. This can be time-consuming.
5367 incoming and outgoing changes. This can be time-consuming.
5363
5368
5364 Returns 0 on success.
5369 Returns 0 on success.
5365 """
5370 """
5366
5371
5367 ctx = repo[None]
5372 ctx = repo[None]
5368 parents = ctx.parents()
5373 parents = ctx.parents()
5369 pnode = parents[0].node()
5374 pnode = parents[0].node()
5370 marks = []
5375 marks = []
5371
5376
5372 for p in parents:
5377 for p in parents:
5373 # label with log.changeset (instead of log.parent) since this
5378 # label with log.changeset (instead of log.parent) since this
5374 # shows a working directory parent *changeset*:
5379 # shows a working directory parent *changeset*:
5375 # i18n: column positioning for "hg summary"
5380 # i18n: column positioning for "hg summary"
5376 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5381 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5377 label='log.changeset changeset.%s' % p.phasestr())
5382 label='log.changeset changeset.%s' % p.phasestr())
5378 ui.write(' '.join(p.tags()), label='log.tag')
5383 ui.write(' '.join(p.tags()), label='log.tag')
5379 if p.bookmarks():
5384 if p.bookmarks():
5380 marks.extend(p.bookmarks())
5385 marks.extend(p.bookmarks())
5381 if p.rev() == -1:
5386 if p.rev() == -1:
5382 if not len(repo):
5387 if not len(repo):
5383 ui.write(_(' (empty repository)'))
5388 ui.write(_(' (empty repository)'))
5384 else:
5389 else:
5385 ui.write(_(' (no revision checked out)'))
5390 ui.write(_(' (no revision checked out)'))
5386 ui.write('\n')
5391 ui.write('\n')
5387 if p.description():
5392 if p.description():
5388 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5393 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5389 label='log.summary')
5394 label='log.summary')
5390
5395
5391 branch = ctx.branch()
5396 branch = ctx.branch()
5392 bheads = repo.branchheads(branch)
5397 bheads = repo.branchheads(branch)
5393 # i18n: column positioning for "hg summary"
5398 # i18n: column positioning for "hg summary"
5394 m = _('branch: %s\n') % branch
5399 m = _('branch: %s\n') % branch
5395 if branch != 'default':
5400 if branch != 'default':
5396 ui.write(m, label='log.branch')
5401 ui.write(m, label='log.branch')
5397 else:
5402 else:
5398 ui.status(m, label='log.branch')
5403 ui.status(m, label='log.branch')
5399
5404
5400 if marks:
5405 if marks:
5401 current = repo._bookmarkcurrent
5406 current = repo._bookmarkcurrent
5402 # i18n: column positioning for "hg summary"
5407 # i18n: column positioning for "hg summary"
5403 ui.write(_('bookmarks:'), label='log.bookmark')
5408 ui.write(_('bookmarks:'), label='log.bookmark')
5404 if current is not None:
5409 if current is not None:
5405 if current in marks:
5410 if current in marks:
5406 ui.write(' *' + current, label='bookmarks.current')
5411 ui.write(' *' + current, label='bookmarks.current')
5407 marks.remove(current)
5412 marks.remove(current)
5408 else:
5413 else:
5409 ui.write(' [%s]' % current, label='bookmarks.current')
5414 ui.write(' [%s]' % current, label='bookmarks.current')
5410 for m in marks:
5415 for m in marks:
5411 ui.write(' ' + m, label='log.bookmark')
5416 ui.write(' ' + m, label='log.bookmark')
5412 ui.write('\n', label='log.bookmark')
5417 ui.write('\n', label='log.bookmark')
5413
5418
5414 st = list(repo.status(unknown=True))[:6]
5419 st = list(repo.status(unknown=True))[:6]
5415
5420
5416 c = repo.dirstate.copies()
5421 c = repo.dirstate.copies()
5417 copied, renamed = [], []
5422 copied, renamed = [], []
5418 for d, s in c.iteritems():
5423 for d, s in c.iteritems():
5419 if s in st[2]:
5424 if s in st[2]:
5420 st[2].remove(s)
5425 st[2].remove(s)
5421 renamed.append(d)
5426 renamed.append(d)
5422 else:
5427 else:
5423 copied.append(d)
5428 copied.append(d)
5424 if d in st[1]:
5429 if d in st[1]:
5425 st[1].remove(d)
5430 st[1].remove(d)
5426 st.insert(3, renamed)
5431 st.insert(3, renamed)
5427 st.insert(4, copied)
5432 st.insert(4, copied)
5428
5433
5429 ms = mergemod.mergestate(repo)
5434 ms = mergemod.mergestate(repo)
5430 st.append([f for f in ms if ms[f] == 'u'])
5435 st.append([f for f in ms if ms[f] == 'u'])
5431
5436
5432 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5437 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5433 st.append(subs)
5438 st.append(subs)
5434
5439
5435 labels = [ui.label(_('%d modified'), 'status.modified'),
5440 labels = [ui.label(_('%d modified'), 'status.modified'),
5436 ui.label(_('%d added'), 'status.added'),
5441 ui.label(_('%d added'), 'status.added'),
5437 ui.label(_('%d removed'), 'status.removed'),
5442 ui.label(_('%d removed'), 'status.removed'),
5438 ui.label(_('%d renamed'), 'status.copied'),
5443 ui.label(_('%d renamed'), 'status.copied'),
5439 ui.label(_('%d copied'), 'status.copied'),
5444 ui.label(_('%d copied'), 'status.copied'),
5440 ui.label(_('%d deleted'), 'status.deleted'),
5445 ui.label(_('%d deleted'), 'status.deleted'),
5441 ui.label(_('%d unknown'), 'status.unknown'),
5446 ui.label(_('%d unknown'), 'status.unknown'),
5442 ui.label(_('%d ignored'), 'status.ignored'),
5447 ui.label(_('%d ignored'), 'status.ignored'),
5443 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5448 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5444 ui.label(_('%d subrepos'), 'status.modified')]
5449 ui.label(_('%d subrepos'), 'status.modified')]
5445 t = []
5450 t = []
5446 for s, l in zip(st, labels):
5451 for s, l in zip(st, labels):
5447 if s:
5452 if s:
5448 t.append(l % len(s))
5453 t.append(l % len(s))
5449
5454
5450 t = ', '.join(t)
5455 t = ', '.join(t)
5451 cleanworkdir = False
5456 cleanworkdir = False
5452
5457
5453 if repo.vfs.exists('updatestate'):
5458 if repo.vfs.exists('updatestate'):
5454 t += _(' (interrupted update)')
5459 t += _(' (interrupted update)')
5455 elif len(parents) > 1:
5460 elif len(parents) > 1:
5456 t += _(' (merge)')
5461 t += _(' (merge)')
5457 elif branch != parents[0].branch():
5462 elif branch != parents[0].branch():
5458 t += _(' (new branch)')
5463 t += _(' (new branch)')
5459 elif (parents[0].closesbranch() and
5464 elif (parents[0].closesbranch() and
5460 pnode in repo.branchheads(branch, closed=True)):
5465 pnode in repo.branchheads(branch, closed=True)):
5461 t += _(' (head closed)')
5466 t += _(' (head closed)')
5462 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5467 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5463 t += _(' (clean)')
5468 t += _(' (clean)')
5464 cleanworkdir = True
5469 cleanworkdir = True
5465 elif pnode not in bheads:
5470 elif pnode not in bheads:
5466 t += _(' (new branch head)')
5471 t += _(' (new branch head)')
5467
5472
5468 if cleanworkdir:
5473 if cleanworkdir:
5469 # i18n: column positioning for "hg summary"
5474 # i18n: column positioning for "hg summary"
5470 ui.status(_('commit: %s\n') % t.strip())
5475 ui.status(_('commit: %s\n') % t.strip())
5471 else:
5476 else:
5472 # i18n: column positioning for "hg summary"
5477 # i18n: column positioning for "hg summary"
5473 ui.write(_('commit: %s\n') % t.strip())
5478 ui.write(_('commit: %s\n') % t.strip())
5474
5479
5475 # all ancestors of branch heads - all ancestors of parent = new csets
5480 # all ancestors of branch heads - all ancestors of parent = new csets
5476 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5481 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5477 bheads))
5482 bheads))
5478
5483
5479 if new == 0:
5484 if new == 0:
5480 # i18n: column positioning for "hg summary"
5485 # i18n: column positioning for "hg summary"
5481 ui.status(_('update: (current)\n'))
5486 ui.status(_('update: (current)\n'))
5482 elif pnode not in bheads:
5487 elif pnode not in bheads:
5483 # i18n: column positioning for "hg summary"
5488 # i18n: column positioning for "hg summary"
5484 ui.write(_('update: %d new changesets (update)\n') % new)
5489 ui.write(_('update: %d new changesets (update)\n') % new)
5485 else:
5490 else:
5486 # i18n: column positioning for "hg summary"
5491 # i18n: column positioning for "hg summary"
5487 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5492 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5488 (new, len(bheads)))
5493 (new, len(bheads)))
5489
5494
5490 cmdutil.summaryhooks(ui, repo)
5495 cmdutil.summaryhooks(ui, repo)
5491
5496
5492 if opts.get('remote'):
5497 if opts.get('remote'):
5493 needsincoming, needsoutgoing = True, True
5498 needsincoming, needsoutgoing = True, True
5494 else:
5499 else:
5495 needsincoming, needsoutgoing = False, False
5500 needsincoming, needsoutgoing = False, False
5496 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5501 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5497 if i:
5502 if i:
5498 needsincoming = True
5503 needsincoming = True
5499 if o:
5504 if o:
5500 needsoutgoing = True
5505 needsoutgoing = True
5501 if not needsincoming and not needsoutgoing:
5506 if not needsincoming and not needsoutgoing:
5502 return
5507 return
5503
5508
5504 def getincoming():
5509 def getincoming():
5505 source, branches = hg.parseurl(ui.expandpath('default'))
5510 source, branches = hg.parseurl(ui.expandpath('default'))
5506 sbranch = branches[0]
5511 sbranch = branches[0]
5507 try:
5512 try:
5508 other = hg.peer(repo, {}, source)
5513 other = hg.peer(repo, {}, source)
5509 except error.RepoError:
5514 except error.RepoError:
5510 if opts.get('remote'):
5515 if opts.get('remote'):
5511 raise
5516 raise
5512 return source, sbranch, None, None, None
5517 return source, sbranch, None, None, None
5513 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5518 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5514 if revs:
5519 if revs:
5515 revs = [other.lookup(rev) for rev in revs]
5520 revs = [other.lookup(rev) for rev in revs]
5516 ui.debug('comparing with %s\n' % util.hidepassword(source))
5521 ui.debug('comparing with %s\n' % util.hidepassword(source))
5517 repo.ui.pushbuffer()
5522 repo.ui.pushbuffer()
5518 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5523 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5519 repo.ui.popbuffer()
5524 repo.ui.popbuffer()
5520 return source, sbranch, other, commoninc, commoninc[1]
5525 return source, sbranch, other, commoninc, commoninc[1]
5521
5526
5522 if needsincoming:
5527 if needsincoming:
5523 source, sbranch, sother, commoninc, incoming = getincoming()
5528 source, sbranch, sother, commoninc, incoming = getincoming()
5524 else:
5529 else:
5525 source = sbranch = sother = commoninc = incoming = None
5530 source = sbranch = sother = commoninc = incoming = None
5526
5531
5527 def getoutgoing():
5532 def getoutgoing():
5528 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5533 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5529 dbranch = branches[0]
5534 dbranch = branches[0]
5530 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5535 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5531 if source != dest:
5536 if source != dest:
5532 try:
5537 try:
5533 dother = hg.peer(repo, {}, dest)
5538 dother = hg.peer(repo, {}, dest)
5534 except error.RepoError:
5539 except error.RepoError:
5535 if opts.get('remote'):
5540 if opts.get('remote'):
5536 raise
5541 raise
5537 return dest, dbranch, None, None
5542 return dest, dbranch, None, None
5538 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5543 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5539 elif sother is None:
5544 elif sother is None:
5540 # there is no explicit destination peer, but source one is invalid
5545 # there is no explicit destination peer, but source one is invalid
5541 return dest, dbranch, None, None
5546 return dest, dbranch, None, None
5542 else:
5547 else:
5543 dother = sother
5548 dother = sother
5544 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5549 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5545 common = None
5550 common = None
5546 else:
5551 else:
5547 common = commoninc
5552 common = commoninc
5548 if revs:
5553 if revs:
5549 revs = [repo.lookup(rev) for rev in revs]
5554 revs = [repo.lookup(rev) for rev in revs]
5550 repo.ui.pushbuffer()
5555 repo.ui.pushbuffer()
5551 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5556 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5552 commoninc=common)
5557 commoninc=common)
5553 repo.ui.popbuffer()
5558 repo.ui.popbuffer()
5554 return dest, dbranch, dother, outgoing
5559 return dest, dbranch, dother, outgoing
5555
5560
5556 if needsoutgoing:
5561 if needsoutgoing:
5557 dest, dbranch, dother, outgoing = getoutgoing()
5562 dest, dbranch, dother, outgoing = getoutgoing()
5558 else:
5563 else:
5559 dest = dbranch = dother = outgoing = None
5564 dest = dbranch = dother = outgoing = None
5560
5565
5561 if opts.get('remote'):
5566 if opts.get('remote'):
5562 t = []
5567 t = []
5563 if incoming:
5568 if incoming:
5564 t.append(_('1 or more incoming'))
5569 t.append(_('1 or more incoming'))
5565 o = outgoing.missing
5570 o = outgoing.missing
5566 if o:
5571 if o:
5567 t.append(_('%d outgoing') % len(o))
5572 t.append(_('%d outgoing') % len(o))
5568 other = dother or sother
5573 other = dother or sother
5569 if 'bookmarks' in other.listkeys('namespaces'):
5574 if 'bookmarks' in other.listkeys('namespaces'):
5570 lmarks = repo.listkeys('bookmarks')
5575 lmarks = repo.listkeys('bookmarks')
5571 rmarks = other.listkeys('bookmarks')
5576 rmarks = other.listkeys('bookmarks')
5572 diff = set(rmarks) - set(lmarks)
5577 diff = set(rmarks) - set(lmarks)
5573 if len(diff) > 0:
5578 if len(diff) > 0:
5574 t.append(_('%d incoming bookmarks') % len(diff))
5579 t.append(_('%d incoming bookmarks') % len(diff))
5575 diff = set(lmarks) - set(rmarks)
5580 diff = set(lmarks) - set(rmarks)
5576 if len(diff) > 0:
5581 if len(diff) > 0:
5577 t.append(_('%d outgoing bookmarks') % len(diff))
5582 t.append(_('%d outgoing bookmarks') % len(diff))
5578
5583
5579 if t:
5584 if t:
5580 # i18n: column positioning for "hg summary"
5585 # i18n: column positioning for "hg summary"
5581 ui.write(_('remote: %s\n') % (', '.join(t)))
5586 ui.write(_('remote: %s\n') % (', '.join(t)))
5582 else:
5587 else:
5583 # i18n: column positioning for "hg summary"
5588 # i18n: column positioning for "hg summary"
5584 ui.status(_('remote: (synced)\n'))
5589 ui.status(_('remote: (synced)\n'))
5585
5590
5586 cmdutil.summaryremotehooks(ui, repo, opts,
5591 cmdutil.summaryremotehooks(ui, repo, opts,
5587 ((source, sbranch, sother, commoninc),
5592 ((source, sbranch, sother, commoninc),
5588 (dest, dbranch, dother, outgoing)))
5593 (dest, dbranch, dother, outgoing)))
5589
5594
5590 @command('tag',
5595 @command('tag',
5591 [('f', 'force', None, _('force tag')),
5596 [('f', 'force', None, _('force tag')),
5592 ('l', 'local', None, _('make the tag local')),
5597 ('l', 'local', None, _('make the tag local')),
5593 ('r', 'rev', '', _('revision to tag'), _('REV')),
5598 ('r', 'rev', '', _('revision to tag'), _('REV')),
5594 ('', 'remove', None, _('remove a tag')),
5599 ('', 'remove', None, _('remove a tag')),
5595 # -l/--local is already there, commitopts cannot be used
5600 # -l/--local is already there, commitopts cannot be used
5596 ('e', 'edit', None, _('edit commit message')),
5601 ('e', 'edit', None, _('edit commit message')),
5597 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5602 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5598 ] + commitopts2,
5603 ] + commitopts2,
5599 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5604 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5600 def tag(ui, repo, name1, *names, **opts):
5605 def tag(ui, repo, name1, *names, **opts):
5601 """add one or more tags for the current or given revision
5606 """add one or more tags for the current or given revision
5602
5607
5603 Name a particular revision using <name>.
5608 Name a particular revision using <name>.
5604
5609
5605 Tags are used to name particular revisions of the repository and are
5610 Tags are used to name particular revisions of the repository and are
5606 very useful to compare different revisions, to go back to significant
5611 very useful to compare different revisions, to go back to significant
5607 earlier versions or to mark branch points as releases, etc. Changing
5612 earlier versions or to mark branch points as releases, etc. Changing
5608 an existing tag is normally disallowed; use -f/--force to override.
5613 an existing tag is normally disallowed; use -f/--force to override.
5609
5614
5610 If no revision is given, the parent of the working directory is
5615 If no revision is given, the parent of the working directory is
5611 used.
5616 used.
5612
5617
5613 To facilitate version control, distribution, and merging of tags,
5618 To facilitate version control, distribution, and merging of tags,
5614 they are stored as a file named ".hgtags" which is managed similarly
5619 they are stored as a file named ".hgtags" which is managed similarly
5615 to other project files and can be hand-edited if necessary. This
5620 to other project files and can be hand-edited if necessary. This
5616 also means that tagging creates a new commit. The file
5621 also means that tagging creates a new commit. The file
5617 ".hg/localtags" is used for local tags (not shared among
5622 ".hg/localtags" is used for local tags (not shared among
5618 repositories).
5623 repositories).
5619
5624
5620 Tag commits are usually made at the head of a branch. If the parent
5625 Tag commits are usually made at the head of a branch. If the parent
5621 of the working directory is not a branch head, :hg:`tag` aborts; use
5626 of the working directory is not a branch head, :hg:`tag` aborts; use
5622 -f/--force to force the tag commit to be based on a non-head
5627 -f/--force to force the tag commit to be based on a non-head
5623 changeset.
5628 changeset.
5624
5629
5625 See :hg:`help dates` for a list of formats valid for -d/--date.
5630 See :hg:`help dates` for a list of formats valid for -d/--date.
5626
5631
5627 Since tag names have priority over branch names during revision
5632 Since tag names have priority over branch names during revision
5628 lookup, using an existing branch name as a tag name is discouraged.
5633 lookup, using an existing branch name as a tag name is discouraged.
5629
5634
5630 Returns 0 on success.
5635 Returns 0 on success.
5631 """
5636 """
5632 wlock = lock = None
5637 wlock = lock = None
5633 try:
5638 try:
5634 wlock = repo.wlock()
5639 wlock = repo.wlock()
5635 lock = repo.lock()
5640 lock = repo.lock()
5636 rev_ = "."
5641 rev_ = "."
5637 names = [t.strip() for t in (name1,) + names]
5642 names = [t.strip() for t in (name1,) + names]
5638 if len(names) != len(set(names)):
5643 if len(names) != len(set(names)):
5639 raise util.Abort(_('tag names must be unique'))
5644 raise util.Abort(_('tag names must be unique'))
5640 for n in names:
5645 for n in names:
5641 scmutil.checknewlabel(repo, n, 'tag')
5646 scmutil.checknewlabel(repo, n, 'tag')
5642 if not n:
5647 if not n:
5643 raise util.Abort(_('tag names cannot consist entirely of '
5648 raise util.Abort(_('tag names cannot consist entirely of '
5644 'whitespace'))
5649 'whitespace'))
5645 if opts.get('rev') and opts.get('remove'):
5650 if opts.get('rev') and opts.get('remove'):
5646 raise util.Abort(_("--rev and --remove are incompatible"))
5651 raise util.Abort(_("--rev and --remove are incompatible"))
5647 if opts.get('rev'):
5652 if opts.get('rev'):
5648 rev_ = opts['rev']
5653 rev_ = opts['rev']
5649 message = opts.get('message')
5654 message = opts.get('message')
5650 if opts.get('remove'):
5655 if opts.get('remove'):
5651 expectedtype = opts.get('local') and 'local' or 'global'
5656 expectedtype = opts.get('local') and 'local' or 'global'
5652 for n in names:
5657 for n in names:
5653 if not repo.tagtype(n):
5658 if not repo.tagtype(n):
5654 raise util.Abort(_("tag '%s' does not exist") % n)
5659 raise util.Abort(_("tag '%s' does not exist") % n)
5655 if repo.tagtype(n) != expectedtype:
5660 if repo.tagtype(n) != expectedtype:
5656 if expectedtype == 'global':
5661 if expectedtype == 'global':
5657 raise util.Abort(_("tag '%s' is not a global tag") % n)
5662 raise util.Abort(_("tag '%s' is not a global tag") % n)
5658 else:
5663 else:
5659 raise util.Abort(_("tag '%s' is not a local tag") % n)
5664 raise util.Abort(_("tag '%s' is not a local tag") % n)
5660 rev_ = nullid
5665 rev_ = nullid
5661 if not message:
5666 if not message:
5662 # we don't translate commit messages
5667 # we don't translate commit messages
5663 message = 'Removed tag %s' % ', '.join(names)
5668 message = 'Removed tag %s' % ', '.join(names)
5664 elif not opts.get('force'):
5669 elif not opts.get('force'):
5665 for n in names:
5670 for n in names:
5666 if n in repo.tags():
5671 if n in repo.tags():
5667 raise util.Abort(_("tag '%s' already exists "
5672 raise util.Abort(_("tag '%s' already exists "
5668 "(use -f to force)") % n)
5673 "(use -f to force)") % n)
5669 if not opts.get('local'):
5674 if not opts.get('local'):
5670 p1, p2 = repo.dirstate.parents()
5675 p1, p2 = repo.dirstate.parents()
5671 if p2 != nullid:
5676 if p2 != nullid:
5672 raise util.Abort(_('uncommitted merge'))
5677 raise util.Abort(_('uncommitted merge'))
5673 bheads = repo.branchheads()
5678 bheads = repo.branchheads()
5674 if not opts.get('force') and bheads and p1 not in bheads:
5679 if not opts.get('force') and bheads and p1 not in bheads:
5675 raise util.Abort(_('not at a branch head (use -f to force)'))
5680 raise util.Abort(_('not at a branch head (use -f to force)'))
5676 r = scmutil.revsingle(repo, rev_).node()
5681 r = scmutil.revsingle(repo, rev_).node()
5677
5682
5678 if not message:
5683 if not message:
5679 # we don't translate commit messages
5684 # we don't translate commit messages
5680 message = ('Added tag %s for changeset %s' %
5685 message = ('Added tag %s for changeset %s' %
5681 (', '.join(names), short(r)))
5686 (', '.join(names), short(r)))
5682
5687
5683 date = opts.get('date')
5688 date = opts.get('date')
5684 if date:
5689 if date:
5685 date = util.parsedate(date)
5690 date = util.parsedate(date)
5686
5691
5687 if opts.get('edit'):
5692 if opts.get('edit'):
5688 message = ui.edit(message, ui.username())
5693 message = ui.edit(message, ui.username())
5689 repo.savecommitmessage(message)
5694 repo.savecommitmessage(message)
5690
5695
5691 # don't allow tagging the null rev
5696 # don't allow tagging the null rev
5692 if (not opts.get('remove') and
5697 if (not opts.get('remove') and
5693 scmutil.revsingle(repo, rev_).rev() == nullrev):
5698 scmutil.revsingle(repo, rev_).rev() == nullrev):
5694 raise util.Abort(_("cannot tag null revision"))
5699 raise util.Abort(_("cannot tag null revision"))
5695
5700
5696 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5701 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5697 finally:
5702 finally:
5698 release(lock, wlock)
5703 release(lock, wlock)
5699
5704
5700 @command('tags', [], '')
5705 @command('tags', [], '')
5701 def tags(ui, repo, **opts):
5706 def tags(ui, repo, **opts):
5702 """list repository tags
5707 """list repository tags
5703
5708
5704 This lists both regular and local tags. When the -v/--verbose
5709 This lists both regular and local tags. When the -v/--verbose
5705 switch is used, a third column "local" is printed for local tags.
5710 switch is used, a third column "local" is printed for local tags.
5706
5711
5707 Returns 0 on success.
5712 Returns 0 on success.
5708 """
5713 """
5709
5714
5710 fm = ui.formatter('tags', opts)
5715 fm = ui.formatter('tags', opts)
5711 hexfunc = ui.debugflag and hex or short
5716 hexfunc = ui.debugflag and hex or short
5712 tagtype = ""
5717 tagtype = ""
5713
5718
5714 for t, n in reversed(repo.tagslist()):
5719 for t, n in reversed(repo.tagslist()):
5715 hn = hexfunc(n)
5720 hn = hexfunc(n)
5716 label = 'tags.normal'
5721 label = 'tags.normal'
5717 tagtype = ''
5722 tagtype = ''
5718 if repo.tagtype(t) == 'local':
5723 if repo.tagtype(t) == 'local':
5719 label = 'tags.local'
5724 label = 'tags.local'
5720 tagtype = 'local'
5725 tagtype = 'local'
5721
5726
5722 fm.startitem()
5727 fm.startitem()
5723 fm.write('tag', '%s', t, label=label)
5728 fm.write('tag', '%s', t, label=label)
5724 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5729 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5725 fm.condwrite(not ui.quiet, 'rev id', fmt,
5730 fm.condwrite(not ui.quiet, 'rev id', fmt,
5726 repo.changelog.rev(n), hn, label=label)
5731 repo.changelog.rev(n), hn, label=label)
5727 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5732 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5728 tagtype, label=label)
5733 tagtype, label=label)
5729 fm.plain('\n')
5734 fm.plain('\n')
5730 fm.end()
5735 fm.end()
5731
5736
5732 @command('tip',
5737 @command('tip',
5733 [('p', 'patch', None, _('show patch')),
5738 [('p', 'patch', None, _('show patch')),
5734 ('g', 'git', None, _('use git extended diff format')),
5739 ('g', 'git', None, _('use git extended diff format')),
5735 ] + templateopts,
5740 ] + templateopts,
5736 _('[-p] [-g]'))
5741 _('[-p] [-g]'))
5737 def tip(ui, repo, **opts):
5742 def tip(ui, repo, **opts):
5738 """show the tip revision (DEPRECATED)
5743 """show the tip revision (DEPRECATED)
5739
5744
5740 The tip revision (usually just called the tip) is the changeset
5745 The tip revision (usually just called the tip) is the changeset
5741 most recently added to the repository (and therefore the most
5746 most recently added to the repository (and therefore the most
5742 recently changed head).
5747 recently changed head).
5743
5748
5744 If you have just made a commit, that commit will be the tip. If
5749 If you have just made a commit, that commit will be the tip. If
5745 you have just pulled changes from another repository, the tip of
5750 you have just pulled changes from another repository, the tip of
5746 that repository becomes the current tip. The "tip" tag is special
5751 that repository becomes the current tip. The "tip" tag is special
5747 and cannot be renamed or assigned to a different changeset.
5752 and cannot be renamed or assigned to a different changeset.
5748
5753
5749 This command is deprecated, please use :hg:`heads` instead.
5754 This command is deprecated, please use :hg:`heads` instead.
5750
5755
5751 Returns 0 on success.
5756 Returns 0 on success.
5752 """
5757 """
5753 displayer = cmdutil.show_changeset(ui, repo, opts)
5758 displayer = cmdutil.show_changeset(ui, repo, opts)
5754 displayer.show(repo['tip'])
5759 displayer.show(repo['tip'])
5755 displayer.close()
5760 displayer.close()
5756
5761
5757 @command('unbundle',
5762 @command('unbundle',
5758 [('u', 'update', None,
5763 [('u', 'update', None,
5759 _('update to new branch head if changesets were unbundled'))],
5764 _('update to new branch head if changesets were unbundled'))],
5760 _('[-u] FILE...'))
5765 _('[-u] FILE...'))
5761 def unbundle(ui, repo, fname1, *fnames, **opts):
5766 def unbundle(ui, repo, fname1, *fnames, **opts):
5762 """apply one or more changegroup files
5767 """apply one or more changegroup files
5763
5768
5764 Apply one or more compressed changegroup files generated by the
5769 Apply one or more compressed changegroup files generated by the
5765 bundle command.
5770 bundle command.
5766
5771
5767 Returns 0 on success, 1 if an update has unresolved files.
5772 Returns 0 on success, 1 if an update has unresolved files.
5768 """
5773 """
5769 fnames = (fname1,) + fnames
5774 fnames = (fname1,) + fnames
5770
5775
5771 lock = repo.lock()
5776 lock = repo.lock()
5772 wc = repo['.']
5777 wc = repo['.']
5773 try:
5778 try:
5774 for fname in fnames:
5779 for fname in fnames:
5775 f = hg.openpath(ui, fname)
5780 f = hg.openpath(ui, fname)
5776 gen = exchange.readbundle(ui, f, fname)
5781 gen = exchange.readbundle(ui, f, fname)
5777 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5782 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5778 'bundle:' + fname)
5783 'bundle:' + fname)
5779 finally:
5784 finally:
5780 lock.release()
5785 lock.release()
5781 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5786 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5782 return postincoming(ui, repo, modheads, opts.get('update'), None)
5787 return postincoming(ui, repo, modheads, opts.get('update'), None)
5783
5788
5784 @command('^update|up|checkout|co',
5789 @command('^update|up|checkout|co',
5785 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5790 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5786 ('c', 'check', None,
5791 ('c', 'check', None,
5787 _('update across branches if no uncommitted changes')),
5792 _('update across branches if no uncommitted changes')),
5788 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5793 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5789 ('r', 'rev', '', _('revision'), _('REV'))],
5794 ('r', 'rev', '', _('revision'), _('REV'))],
5790 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5795 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5791 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5796 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5792 """update working directory (or switch revisions)
5797 """update working directory (or switch revisions)
5793
5798
5794 Update the repository's working directory to the specified
5799 Update the repository's working directory to the specified
5795 changeset. If no changeset is specified, update to the tip of the
5800 changeset. If no changeset is specified, update to the tip of the
5796 current named branch and move the current bookmark (see :hg:`help
5801 current named branch and move the current bookmark (see :hg:`help
5797 bookmarks`).
5802 bookmarks`).
5798
5803
5799 Update sets the working directory's parent revision to the specified
5804 Update sets the working directory's parent revision to the specified
5800 changeset (see :hg:`help parents`).
5805 changeset (see :hg:`help parents`).
5801
5806
5802 If the changeset is not a descendant or ancestor of the working
5807 If the changeset is not a descendant or ancestor of the working
5803 directory's parent, the update is aborted. With the -c/--check
5808 directory's parent, the update is aborted. With the -c/--check
5804 option, the working directory is checked for uncommitted changes; if
5809 option, the working directory is checked for uncommitted changes; if
5805 none are found, the working directory is updated to the specified
5810 none are found, the working directory is updated to the specified
5806 changeset.
5811 changeset.
5807
5812
5808 .. container:: verbose
5813 .. container:: verbose
5809
5814
5810 The following rules apply when the working directory contains
5815 The following rules apply when the working directory contains
5811 uncommitted changes:
5816 uncommitted changes:
5812
5817
5813 1. If neither -c/--check nor -C/--clean is specified, and if
5818 1. If neither -c/--check nor -C/--clean is specified, and if
5814 the requested changeset is an ancestor or descendant of
5819 the requested changeset is an ancestor or descendant of
5815 the working directory's parent, the uncommitted changes
5820 the working directory's parent, the uncommitted changes
5816 are merged into the requested changeset and the merged
5821 are merged into the requested changeset and the merged
5817 result is left uncommitted. If the requested changeset is
5822 result is left uncommitted. If the requested changeset is
5818 not an ancestor or descendant (that is, it is on another
5823 not an ancestor or descendant (that is, it is on another
5819 branch), the update is aborted and the uncommitted changes
5824 branch), the update is aborted and the uncommitted changes
5820 are preserved.
5825 are preserved.
5821
5826
5822 2. With the -c/--check option, the update is aborted and the
5827 2. With the -c/--check option, the update is aborted and the
5823 uncommitted changes are preserved.
5828 uncommitted changes are preserved.
5824
5829
5825 3. With the -C/--clean option, uncommitted changes are discarded and
5830 3. With the -C/--clean option, uncommitted changes are discarded and
5826 the working directory is updated to the requested changeset.
5831 the working directory is updated to the requested changeset.
5827
5832
5828 To cancel an uncommitted merge (and lose your changes), use
5833 To cancel an uncommitted merge (and lose your changes), use
5829 :hg:`update --clean .`.
5834 :hg:`update --clean .`.
5830
5835
5831 Use null as the changeset to remove the working directory (like
5836 Use null as the changeset to remove the working directory (like
5832 :hg:`clone -U`).
5837 :hg:`clone -U`).
5833
5838
5834 If you want to revert just one file to an older revision, use
5839 If you want to revert just one file to an older revision, use
5835 :hg:`revert [-r REV] NAME`.
5840 :hg:`revert [-r REV] NAME`.
5836
5841
5837 See :hg:`help dates` for a list of formats valid for -d/--date.
5842 See :hg:`help dates` for a list of formats valid for -d/--date.
5838
5843
5839 Returns 0 on success, 1 if there are unresolved files.
5844 Returns 0 on success, 1 if there are unresolved files.
5840 """
5845 """
5841 if rev and node:
5846 if rev and node:
5842 raise util.Abort(_("please specify just one revision"))
5847 raise util.Abort(_("please specify just one revision"))
5843
5848
5844 if rev is None or rev == '':
5849 if rev is None or rev == '':
5845 rev = node
5850 rev = node
5846
5851
5847 cmdutil.clearunfinished(repo)
5852 cmdutil.clearunfinished(repo)
5848
5853
5849 # with no argument, we also move the current bookmark, if any
5854 # with no argument, we also move the current bookmark, if any
5850 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5855 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5851
5856
5852 # if we defined a bookmark, we have to remember the original bookmark name
5857 # if we defined a bookmark, we have to remember the original bookmark name
5853 brev = rev
5858 brev = rev
5854 rev = scmutil.revsingle(repo, rev, rev).rev()
5859 rev = scmutil.revsingle(repo, rev, rev).rev()
5855
5860
5856 if check and clean:
5861 if check and clean:
5857 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5862 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5858
5863
5859 if date:
5864 if date:
5860 if rev is not None:
5865 if rev is not None:
5861 raise util.Abort(_("you can't specify a revision and a date"))
5866 raise util.Abort(_("you can't specify a revision and a date"))
5862 rev = cmdutil.finddate(ui, repo, date)
5867 rev = cmdutil.finddate(ui, repo, date)
5863
5868
5864 if check:
5869 if check:
5865 c = repo[None]
5870 c = repo[None]
5866 if c.dirty(merge=False, branch=False, missing=True):
5871 if c.dirty(merge=False, branch=False, missing=True):
5867 raise util.Abort(_("uncommitted changes"))
5872 raise util.Abort(_("uncommitted changes"))
5868 if rev is None:
5873 if rev is None:
5869 rev = repo[repo[None].branch()].rev()
5874 rev = repo[repo[None].branch()].rev()
5870 mergemod._checkunknown(repo, repo[None], repo[rev])
5875 mergemod._checkunknown(repo, repo[None], repo[rev])
5871
5876
5872 if clean:
5877 if clean:
5873 ret = hg.clean(repo, rev)
5878 ret = hg.clean(repo, rev)
5874 else:
5879 else:
5875 ret = hg.update(repo, rev)
5880 ret = hg.update(repo, rev)
5876
5881
5877 if not ret and movemarkfrom:
5882 if not ret and movemarkfrom:
5878 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5883 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5879 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5884 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5880 elif brev in repo._bookmarks:
5885 elif brev in repo._bookmarks:
5881 bookmarks.setcurrent(repo, brev)
5886 bookmarks.setcurrent(repo, brev)
5882 elif brev:
5887 elif brev:
5883 bookmarks.unsetcurrent(repo)
5888 bookmarks.unsetcurrent(repo)
5884
5889
5885 return ret
5890 return ret
5886
5891
5887 @command('verify', [])
5892 @command('verify', [])
5888 def verify(ui, repo):
5893 def verify(ui, repo):
5889 """verify the integrity of the repository
5894 """verify the integrity of the repository
5890
5895
5891 Verify the integrity of the current repository.
5896 Verify the integrity of the current repository.
5892
5897
5893 This will perform an extensive check of the repository's
5898 This will perform an extensive check of the repository's
5894 integrity, validating the hashes and checksums of each entry in
5899 integrity, validating the hashes and checksums of each entry in
5895 the changelog, manifest, and tracked files, as well as the
5900 the changelog, manifest, and tracked files, as well as the
5896 integrity of their crosslinks and indices.
5901 integrity of their crosslinks and indices.
5897
5902
5898 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5903 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5899 for more information about recovery from corruption of the
5904 for more information about recovery from corruption of the
5900 repository.
5905 repository.
5901
5906
5902 Returns 0 on success, 1 if errors are encountered.
5907 Returns 0 on success, 1 if errors are encountered.
5903 """
5908 """
5904 return hg.verify(repo)
5909 return hg.verify(repo)
5905
5910
5906 @command('version', [])
5911 @command('version', [])
5907 def version_(ui):
5912 def version_(ui):
5908 """output version and copyright information"""
5913 """output version and copyright information"""
5909 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5914 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5910 % util.version())
5915 % util.version())
5911 ui.status(_(
5916 ui.status(_(
5912 "(see http://mercurial.selenic.com for more information)\n"
5917 "(see http://mercurial.selenic.com for more information)\n"
5913 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5918 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5914 "This is free software; see the source for copying conditions. "
5919 "This is free software; see the source for copying conditions. "
5915 "There is NO\nwarranty; "
5920 "There is NO\nwarranty; "
5916 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5921 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5917 ))
5922 ))
5918
5923
5919 norepo = ("clone init version help debugcommands debugcomplete"
5924 norepo = ("clone init version help debugcommands debugcomplete"
5920 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5925 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5921 " debugknown debuggetbundle debugbundle")
5926 " debugknown debuggetbundle debugbundle")
5922 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5927 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5923 " debugdata debugindex debugindexdot debugrevlog")
5928 " debugdata debugindex debugindexdot debugrevlog")
5924 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5929 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5925 " remove resolve status debugwalk")
5930 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now