##// END OF EJS Templates
log: remove tip from example
Matt Mackall -
r19401:49acaa2b default
parent child Browse files
Show More
@@ -1,5884 +1,5884 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 hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [OPTIONS]... [NAME]...'))
770 _('hg bookmarks [OPTIONS]... [NAME]...'))
771 def bookmark(ui, repo, *names, **opts):
771 def bookmark(ui, repo, *names, **opts):
772 '''track a line of development with movable markers
772 '''track a line of development with movable markers
773
773
774 Bookmarks are pointers to certain commits that move when committing.
774 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are local. They can be renamed, copied and deleted. It is
775 Bookmarks are local. They can be renamed, copied and deleted. It is
776 possible to use :hg:`merge NAME` to merge from a given bookmark, and
776 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 :hg:`update NAME` to update to a given bookmark.
777 :hg:`update NAME` to update to a given bookmark.
778
778
779 You can use :hg:`bookmark NAME` to set a bookmark on the working
779 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 directory's parent revision with the given name. If you specify
780 directory's parent revision with the given name. If you specify
781 a revision using -r REV (where REV may be an existing bookmark),
781 a revision using -r REV (where REV may be an existing bookmark),
782 the bookmark is assigned to that revision.
782 the bookmark is assigned to that revision.
783
783
784 Bookmarks can be pushed and pulled between repositories (see :hg:`help
784 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 push` and :hg:`help pull`). This requires both the local and remote
785 push` and :hg:`help pull`). This requires both the local and remote
786 repositories to support bookmarks. For versions prior to 1.8, this means
786 repositories to support bookmarks. For versions prior to 1.8, this means
787 the bookmarks extension must be enabled.
787 the bookmarks extension must be enabled.
788
788
789 If you set a bookmark called '@', new clones of the repository will
789 If you set a bookmark called '@', new clones of the repository will
790 have that revision checked out (and the bookmark made active) by
790 have that revision checked out (and the bookmark made active) by
791 default.
791 default.
792
792
793 With -i/--inactive, the new bookmark will not be made the active
793 With -i/--inactive, the new bookmark will not be made the active
794 bookmark. If -r/--rev is given, the new bookmark will not be made
794 bookmark. If -r/--rev is given, the new bookmark will not be made
795 active even if -i/--inactive is not given. If no NAME is given, the
795 active even if -i/--inactive is not given. If no NAME is given, the
796 current active bookmark will be marked inactive.
796 current active bookmark will be marked inactive.
797 '''
797 '''
798 force = opts.get('force')
798 force = opts.get('force')
799 rev = opts.get('rev')
799 rev = opts.get('rev')
800 delete = opts.get('delete')
800 delete = opts.get('delete')
801 rename = opts.get('rename')
801 rename = opts.get('rename')
802 inactive = opts.get('inactive')
802 inactive = opts.get('inactive')
803
803
804 hexfn = ui.debugflag and hex or short
804 hexfn = ui.debugflag and hex or short
805 marks = repo._bookmarks
805 marks = repo._bookmarks
806 cur = repo.changectx('.').node()
806 cur = repo.changectx('.').node()
807
807
808 def checkformat(mark):
808 def checkformat(mark):
809 mark = mark.strip()
809 mark = mark.strip()
810 if not mark:
810 if not mark:
811 raise util.Abort(_("bookmark names cannot consist entirely of "
811 raise util.Abort(_("bookmark names cannot consist entirely of "
812 "whitespace"))
812 "whitespace"))
813 scmutil.checknewlabel(repo, mark, 'bookmark')
813 scmutil.checknewlabel(repo, mark, 'bookmark')
814 return mark
814 return mark
815
815
816 def checkconflict(repo, mark, force=False, target=None):
816 def checkconflict(repo, mark, force=False, target=None):
817 if mark in marks and not force:
817 if mark in marks and not force:
818 if target:
818 if target:
819 if marks[mark] == target and target == cur:
819 if marks[mark] == target and target == cur:
820 # re-activating a bookmark
820 # re-activating a bookmark
821 return
821 return
822 anc = repo.changelog.ancestors([repo[target].rev()])
822 anc = repo.changelog.ancestors([repo[target].rev()])
823 bmctx = repo[marks[mark]]
823 bmctx = repo[marks[mark]]
824 divs = [repo[b].node() for b in marks
824 divs = [repo[b].node() for b in marks
825 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
825 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
826
826
827 # allow resolving a single divergent bookmark even if moving
827 # allow resolving a single divergent bookmark even if moving
828 # the bookmark across branches when a revision is specified
828 # the bookmark across branches when a revision is specified
829 # that contains a divergent bookmark
829 # that contains a divergent bookmark
830 if bmctx.rev() not in anc and target in divs:
830 if bmctx.rev() not in anc and target in divs:
831 bookmarks.deletedivergent(repo, [target], mark)
831 bookmarks.deletedivergent(repo, [target], mark)
832 return
832 return
833
833
834 deletefrom = [b for b in divs
834 deletefrom = [b for b in divs
835 if repo[b].rev() in anc or b == target]
835 if repo[b].rev() in anc or b == target]
836 bookmarks.deletedivergent(repo, deletefrom, mark)
836 bookmarks.deletedivergent(repo, deletefrom, mark)
837 if bmctx.rev() in anc:
837 if bmctx.rev() in anc:
838 ui.status(_("moving bookmark '%s' forward from %s\n") %
838 ui.status(_("moving bookmark '%s' forward from %s\n") %
839 (mark, short(bmctx.node())))
839 (mark, short(bmctx.node())))
840 return
840 return
841 raise util.Abort(_("bookmark '%s' already exists "
841 raise util.Abort(_("bookmark '%s' already exists "
842 "(use -f to force)") % mark)
842 "(use -f to force)") % mark)
843 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
843 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
844 and not force):
844 and not force):
845 raise util.Abort(
845 raise util.Abort(
846 _("a bookmark cannot have the name of an existing branch"))
846 _("a bookmark cannot have the name of an existing branch"))
847
847
848 if delete and rename:
848 if delete and rename:
849 raise util.Abort(_("--delete and --rename are incompatible"))
849 raise util.Abort(_("--delete and --rename are incompatible"))
850 if delete and rev:
850 if delete and rev:
851 raise util.Abort(_("--rev is incompatible with --delete"))
851 raise util.Abort(_("--rev is incompatible with --delete"))
852 if rename and rev:
852 if rename and rev:
853 raise util.Abort(_("--rev is incompatible with --rename"))
853 raise util.Abort(_("--rev is incompatible with --rename"))
854 if not names and (delete or rev):
854 if not names and (delete or rev):
855 raise util.Abort(_("bookmark name required"))
855 raise util.Abort(_("bookmark name required"))
856
856
857 if delete:
857 if delete:
858 for mark in names:
858 for mark in names:
859 if mark not in marks:
859 if mark not in marks:
860 raise util.Abort(_("bookmark '%s' does not exist") % mark)
860 raise util.Abort(_("bookmark '%s' does not exist") % mark)
861 if mark == repo._bookmarkcurrent:
861 if mark == repo._bookmarkcurrent:
862 bookmarks.setcurrent(repo, None)
862 bookmarks.setcurrent(repo, None)
863 del marks[mark]
863 del marks[mark]
864 marks.write()
864 marks.write()
865
865
866 elif rename:
866 elif rename:
867 if not names:
867 if not names:
868 raise util.Abort(_("new bookmark name required"))
868 raise util.Abort(_("new bookmark name required"))
869 elif len(names) > 1:
869 elif len(names) > 1:
870 raise util.Abort(_("only one new bookmark name allowed"))
870 raise util.Abort(_("only one new bookmark name allowed"))
871 mark = checkformat(names[0])
871 mark = checkformat(names[0])
872 if rename not in marks:
872 if rename not in marks:
873 raise util.Abort(_("bookmark '%s' does not exist") % rename)
873 raise util.Abort(_("bookmark '%s' does not exist") % rename)
874 checkconflict(repo, mark, force)
874 checkconflict(repo, mark, force)
875 marks[mark] = marks[rename]
875 marks[mark] = marks[rename]
876 if repo._bookmarkcurrent == rename and not inactive:
876 if repo._bookmarkcurrent == rename and not inactive:
877 bookmarks.setcurrent(repo, mark)
877 bookmarks.setcurrent(repo, mark)
878 del marks[rename]
878 del marks[rename]
879 marks.write()
879 marks.write()
880
880
881 elif names:
881 elif names:
882 newact = None
882 newact = None
883 for mark in names:
883 for mark in names:
884 mark = checkformat(mark)
884 mark = checkformat(mark)
885 if newact is None:
885 if newact is None:
886 newact = mark
886 newact = mark
887 if inactive and mark == repo._bookmarkcurrent:
887 if inactive and mark == repo._bookmarkcurrent:
888 bookmarks.setcurrent(repo, None)
888 bookmarks.setcurrent(repo, None)
889 return
889 return
890 tgt = cur
890 tgt = cur
891 if rev:
891 if rev:
892 tgt = scmutil.revsingle(repo, rev).node()
892 tgt = scmutil.revsingle(repo, rev).node()
893 checkconflict(repo, mark, force, tgt)
893 checkconflict(repo, mark, force, tgt)
894 marks[mark] = tgt
894 marks[mark] = tgt
895 if not inactive and cur == marks[newact] and not rev:
895 if not inactive and cur == marks[newact] and not rev:
896 bookmarks.setcurrent(repo, newact)
896 bookmarks.setcurrent(repo, newact)
897 elif cur != tgt and newact == repo._bookmarkcurrent:
897 elif cur != tgt and newact == repo._bookmarkcurrent:
898 bookmarks.setcurrent(repo, None)
898 bookmarks.setcurrent(repo, None)
899 marks.write()
899 marks.write()
900
900
901 # Same message whether trying to deactivate the current bookmark (-i
901 # Same message whether trying to deactivate the current bookmark (-i
902 # with no NAME) or listing bookmarks
902 # with no NAME) or listing bookmarks
903 elif len(marks) == 0:
903 elif len(marks) == 0:
904 ui.status(_("no bookmarks set\n"))
904 ui.status(_("no bookmarks set\n"))
905
905
906 elif inactive:
906 elif inactive:
907 if not repo._bookmarkcurrent:
907 if not repo._bookmarkcurrent:
908 ui.status(_("no active bookmark\n"))
908 ui.status(_("no active bookmark\n"))
909 else:
909 else:
910 bookmarks.setcurrent(repo, None)
910 bookmarks.setcurrent(repo, None)
911
911
912 else: # show bookmarks
912 else: # show bookmarks
913 for bmark, n in sorted(marks.iteritems()):
913 for bmark, n in sorted(marks.iteritems()):
914 current = repo._bookmarkcurrent
914 current = repo._bookmarkcurrent
915 if bmark == current:
915 if bmark == current:
916 prefix, label = '*', 'bookmarks.current'
916 prefix, label = '*', 'bookmarks.current'
917 else:
917 else:
918 prefix, label = ' ', ''
918 prefix, label = ' ', ''
919
919
920 if ui.quiet:
920 if ui.quiet:
921 ui.write("%s\n" % bmark, label=label)
921 ui.write("%s\n" % bmark, label=label)
922 else:
922 else:
923 ui.write(" %s %-25s %d:%s\n" % (
923 ui.write(" %s %-25s %d:%s\n" % (
924 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
924 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
925 label=label)
925 label=label)
926
926
927 @command('branch',
927 @command('branch',
928 [('f', 'force', None,
928 [('f', 'force', None,
929 _('set branch name even if it shadows an existing branch')),
929 _('set branch name even if it shadows an existing branch')),
930 ('C', 'clean', None, _('reset branch name to parent branch name'))],
930 ('C', 'clean', None, _('reset branch name to parent branch name'))],
931 _('[-fC] [NAME]'))
931 _('[-fC] [NAME]'))
932 def branch(ui, repo, label=None, **opts):
932 def branch(ui, repo, label=None, **opts):
933 """set or show the current branch name
933 """set or show the current branch name
934
934
935 .. note::
935 .. note::
936 Branch names are permanent and global. Use :hg:`bookmark` to create a
936 Branch names are permanent and global. Use :hg:`bookmark` to create a
937 light-weight bookmark instead. See :hg:`help glossary` for more
937 light-weight bookmark instead. See :hg:`help glossary` for more
938 information about named branches and bookmarks.
938 information about named branches and bookmarks.
939
939
940 With no argument, show the current branch name. With one argument,
940 With no argument, show the current branch name. With one argument,
941 set the working directory branch name (the branch will not exist
941 set the working directory branch name (the branch will not exist
942 in the repository until the next commit). Standard practice
942 in the repository until the next commit). Standard practice
943 recommends that primary development take place on the 'default'
943 recommends that primary development take place on the 'default'
944 branch.
944 branch.
945
945
946 Unless -f/--force is specified, branch will not let you set a
946 Unless -f/--force is specified, branch will not let you set a
947 branch name that already exists, even if it's inactive.
947 branch name that already exists, even if it's inactive.
948
948
949 Use -C/--clean to reset the working directory branch to that of
949 Use -C/--clean to reset the working directory branch to that of
950 the parent of the working directory, negating a previous branch
950 the parent of the working directory, negating a previous branch
951 change.
951 change.
952
952
953 Use the command :hg:`update` to switch to an existing branch. Use
953 Use the command :hg:`update` to switch to an existing branch. Use
954 :hg:`commit --close-branch` to mark this branch as closed.
954 :hg:`commit --close-branch` to mark this branch as closed.
955
955
956 Returns 0 on success.
956 Returns 0 on success.
957 """
957 """
958 if label:
958 if label:
959 label = label.strip()
959 label = label.strip()
960
960
961 if not opts.get('clean') and not label:
961 if not opts.get('clean') and not label:
962 ui.write("%s\n" % repo.dirstate.branch())
962 ui.write("%s\n" % repo.dirstate.branch())
963 return
963 return
964
964
965 wlock = repo.wlock()
965 wlock = repo.wlock()
966 try:
966 try:
967 if opts.get('clean'):
967 if opts.get('clean'):
968 label = repo[None].p1().branch()
968 label = repo[None].p1().branch()
969 repo.dirstate.setbranch(label)
969 repo.dirstate.setbranch(label)
970 ui.status(_('reset working directory to branch %s\n') % label)
970 ui.status(_('reset working directory to branch %s\n') % label)
971 elif label:
971 elif label:
972 if not opts.get('force') and label in repo.branchmap():
972 if not opts.get('force') and label in repo.branchmap():
973 if label not in [p.branch() for p in repo.parents()]:
973 if label not in [p.branch() for p in repo.parents()]:
974 raise util.Abort(_('a branch of the same name already'
974 raise util.Abort(_('a branch of the same name already'
975 ' exists'),
975 ' exists'),
976 # i18n: "it" refers to an existing branch
976 # i18n: "it" refers to an existing branch
977 hint=_("use 'hg update' to switch to it"))
977 hint=_("use 'hg update' to switch to it"))
978 scmutil.checknewlabel(repo, label, 'branch')
978 scmutil.checknewlabel(repo, label, 'branch')
979 repo.dirstate.setbranch(label)
979 repo.dirstate.setbranch(label)
980 ui.status(_('marked working directory as branch %s\n') % label)
980 ui.status(_('marked working directory as branch %s\n') % label)
981 ui.status(_('(branches are permanent and global, '
981 ui.status(_('(branches are permanent and global, '
982 'did you want a bookmark?)\n'))
982 'did you want a bookmark?)\n'))
983 finally:
983 finally:
984 wlock.release()
984 wlock.release()
985
985
986 @command('branches',
986 @command('branches',
987 [('a', 'active', False, _('show only branches that have unmerged heads')),
987 [('a', 'active', False, _('show only branches that have unmerged heads')),
988 ('c', 'closed', False, _('show normal and closed branches'))],
988 ('c', 'closed', False, _('show normal and closed branches'))],
989 _('[-ac]'))
989 _('[-ac]'))
990 def branches(ui, repo, active=False, closed=False):
990 def branches(ui, repo, active=False, closed=False):
991 """list repository named branches
991 """list repository named branches
992
992
993 List the repository's named branches, indicating which ones are
993 List the repository's named branches, indicating which ones are
994 inactive. If -c/--closed is specified, also list branches which have
994 inactive. If -c/--closed is specified, also list branches which have
995 been marked closed (see :hg:`commit --close-branch`).
995 been marked closed (see :hg:`commit --close-branch`).
996
996
997 If -a/--active is specified, only show active branches. A branch
997 If -a/--active is specified, only show active branches. A branch
998 is considered active if it contains repository heads.
998 is considered active if it contains repository heads.
999
999
1000 Use the command :hg:`update` to switch to an existing branch.
1000 Use the command :hg:`update` to switch to an existing branch.
1001
1001
1002 Returns 0.
1002 Returns 0.
1003 """
1003 """
1004
1004
1005 hexfunc = ui.debugflag and hex or short
1005 hexfunc = ui.debugflag and hex or short
1006
1006
1007 activebranches = set([repo[n].branch() for n in repo.heads()])
1007 activebranches = set([repo[n].branch() for n in repo.heads()])
1008 branches = []
1008 branches = []
1009 for tag, heads in repo.branchmap().iteritems():
1009 for tag, heads in repo.branchmap().iteritems():
1010 for h in reversed(heads):
1010 for h in reversed(heads):
1011 ctx = repo[h]
1011 ctx = repo[h]
1012 isopen = not ctx.closesbranch()
1012 isopen = not ctx.closesbranch()
1013 if isopen:
1013 if isopen:
1014 tip = ctx
1014 tip = ctx
1015 break
1015 break
1016 else:
1016 else:
1017 tip = repo[heads[-1]]
1017 tip = repo[heads[-1]]
1018 isactive = tag in activebranches and isopen
1018 isactive = tag in activebranches and isopen
1019 branches.append((tip, isactive, isopen))
1019 branches.append((tip, isactive, isopen))
1020 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1020 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1021 reverse=True)
1021 reverse=True)
1022
1022
1023 for ctx, isactive, isopen in branches:
1023 for ctx, isactive, isopen in branches:
1024 if (not active) or isactive:
1024 if (not active) or isactive:
1025 if isactive:
1025 if isactive:
1026 label = 'branches.active'
1026 label = 'branches.active'
1027 notice = ''
1027 notice = ''
1028 elif not isopen:
1028 elif not isopen:
1029 if not closed:
1029 if not closed:
1030 continue
1030 continue
1031 label = 'branches.closed'
1031 label = 'branches.closed'
1032 notice = _(' (closed)')
1032 notice = _(' (closed)')
1033 else:
1033 else:
1034 label = 'branches.inactive'
1034 label = 'branches.inactive'
1035 notice = _(' (inactive)')
1035 notice = _(' (inactive)')
1036 if ctx.branch() == repo.dirstate.branch():
1036 if ctx.branch() == repo.dirstate.branch():
1037 label = 'branches.current'
1037 label = 'branches.current'
1038 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1038 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1039 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1039 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1040 'log.changeset changeset.%s' % ctx.phasestr())
1040 'log.changeset changeset.%s' % ctx.phasestr())
1041 tag = ui.label(ctx.branch(), label)
1041 tag = ui.label(ctx.branch(), label)
1042 if ui.quiet:
1042 if ui.quiet:
1043 ui.write("%s\n" % tag)
1043 ui.write("%s\n" % tag)
1044 else:
1044 else:
1045 ui.write("%s %s%s\n" % (tag, rev, notice))
1045 ui.write("%s %s%s\n" % (tag, rev, notice))
1046
1046
1047 @command('bundle',
1047 @command('bundle',
1048 [('f', 'force', None, _('run even when the destination is unrelated')),
1048 [('f', 'force', None, _('run even when the destination is unrelated')),
1049 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1049 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1050 _('REV')),
1050 _('REV')),
1051 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1051 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1052 _('BRANCH')),
1052 _('BRANCH')),
1053 ('', 'base', [],
1053 ('', 'base', [],
1054 _('a base changeset assumed to be available at the destination'),
1054 _('a base changeset assumed to be available at the destination'),
1055 _('REV')),
1055 _('REV')),
1056 ('a', 'all', None, _('bundle all changesets in the repository')),
1056 ('a', 'all', None, _('bundle all changesets in the repository')),
1057 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1057 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1058 ] + remoteopts,
1058 ] + remoteopts,
1059 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1059 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1060 def bundle(ui, repo, fname, dest=None, **opts):
1060 def bundle(ui, repo, fname, dest=None, **opts):
1061 """create a changegroup file
1061 """create a changegroup file
1062
1062
1063 Generate a compressed changegroup file collecting changesets not
1063 Generate a compressed changegroup file collecting changesets not
1064 known to be in another repository.
1064 known to be in another repository.
1065
1065
1066 If you omit the destination repository, then hg assumes the
1066 If you omit the destination repository, then hg assumes the
1067 destination will have all the nodes you specify with --base
1067 destination will have all the nodes you specify with --base
1068 parameters. To create a bundle containing all changesets, use
1068 parameters. To create a bundle containing all changesets, use
1069 -a/--all (or --base null).
1069 -a/--all (or --base null).
1070
1070
1071 You can change compression method with the -t/--type option.
1071 You can change compression method with the -t/--type option.
1072 The available compression methods are: none, bzip2, and
1072 The available compression methods are: none, bzip2, and
1073 gzip (by default, bundles are compressed using bzip2).
1073 gzip (by default, bundles are compressed using bzip2).
1074
1074
1075 The bundle file can then be transferred using conventional means
1075 The bundle file can then be transferred using conventional means
1076 and applied to another repository with the unbundle or pull
1076 and applied to another repository with the unbundle or pull
1077 command. This is useful when direct push and pull are not
1077 command. This is useful when direct push and pull are not
1078 available or when exporting an entire repository is undesirable.
1078 available or when exporting an entire repository is undesirable.
1079
1079
1080 Applying bundles preserves all changeset contents including
1080 Applying bundles preserves all changeset contents including
1081 permissions, copy/rename information, and revision history.
1081 permissions, copy/rename information, and revision history.
1082
1082
1083 Returns 0 on success, 1 if no changes found.
1083 Returns 0 on success, 1 if no changes found.
1084 """
1084 """
1085 revs = None
1085 revs = None
1086 if 'rev' in opts:
1086 if 'rev' in opts:
1087 revs = scmutil.revrange(repo, opts['rev'])
1087 revs = scmutil.revrange(repo, opts['rev'])
1088
1088
1089 bundletype = opts.get('type', 'bzip2').lower()
1089 bundletype = opts.get('type', 'bzip2').lower()
1090 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1090 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1091 bundletype = btypes.get(bundletype)
1091 bundletype = btypes.get(bundletype)
1092 if bundletype not in changegroup.bundletypes:
1092 if bundletype not in changegroup.bundletypes:
1093 raise util.Abort(_('unknown bundle type specified with --type'))
1093 raise util.Abort(_('unknown bundle type specified with --type'))
1094
1094
1095 if opts.get('all'):
1095 if opts.get('all'):
1096 base = ['null']
1096 base = ['null']
1097 else:
1097 else:
1098 base = scmutil.revrange(repo, opts.get('base'))
1098 base = scmutil.revrange(repo, opts.get('base'))
1099 # TODO: get desired bundlecaps from command line.
1099 # TODO: get desired bundlecaps from command line.
1100 bundlecaps = None
1100 bundlecaps = None
1101 if base:
1101 if base:
1102 if dest:
1102 if dest:
1103 raise util.Abort(_("--base is incompatible with specifying "
1103 raise util.Abort(_("--base is incompatible with specifying "
1104 "a destination"))
1104 "a destination"))
1105 common = [repo.lookup(rev) for rev in base]
1105 common = [repo.lookup(rev) for rev in base]
1106 heads = revs and map(repo.lookup, revs) or revs
1106 heads = revs and map(repo.lookup, revs) or revs
1107 cg = repo.getbundle('bundle', heads=heads, common=common,
1107 cg = repo.getbundle('bundle', heads=heads, common=common,
1108 bundlecaps=bundlecaps)
1108 bundlecaps=bundlecaps)
1109 outgoing = None
1109 outgoing = None
1110 else:
1110 else:
1111 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1111 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1112 dest, branches = hg.parseurl(dest, opts.get('branch'))
1112 dest, branches = hg.parseurl(dest, opts.get('branch'))
1113 other = hg.peer(repo, opts, dest)
1113 other = hg.peer(repo, opts, dest)
1114 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1114 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1115 heads = revs and map(repo.lookup, revs) or revs
1115 heads = revs and map(repo.lookup, revs) or revs
1116 outgoing = discovery.findcommonoutgoing(repo, other,
1116 outgoing = discovery.findcommonoutgoing(repo, other,
1117 onlyheads=heads,
1117 onlyheads=heads,
1118 force=opts.get('force'),
1118 force=opts.get('force'),
1119 portable=True)
1119 portable=True)
1120 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1120 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1121 if not cg:
1121 if not cg:
1122 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1122 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1123 return 1
1123 return 1
1124
1124
1125 changegroup.writebundle(cg, fname, bundletype)
1125 changegroup.writebundle(cg, fname, bundletype)
1126
1126
1127 @command('cat',
1127 @command('cat',
1128 [('o', 'output', '',
1128 [('o', 'output', '',
1129 _('print output to file with formatted name'), _('FORMAT')),
1129 _('print output to file with formatted name'), _('FORMAT')),
1130 ('r', 'rev', '', _('print the given revision'), _('REV')),
1130 ('r', 'rev', '', _('print the given revision'), _('REV')),
1131 ('', 'decode', None, _('apply any matching decode filter')),
1131 ('', 'decode', None, _('apply any matching decode filter')),
1132 ] + walkopts,
1132 ] + walkopts,
1133 _('[OPTION]... FILE...'))
1133 _('[OPTION]... FILE...'))
1134 def cat(ui, repo, file1, *pats, **opts):
1134 def cat(ui, repo, file1, *pats, **opts):
1135 """output the current or given revision of files
1135 """output the current or given revision of files
1136
1136
1137 Print the specified files as they were at the given revision. If
1137 Print the specified files as they were at the given revision. If
1138 no revision is given, the parent of the working directory is used.
1138 no revision is given, the parent of the working directory is used.
1139
1139
1140 Output may be to a file, in which case the name of the file is
1140 Output may be to a file, in which case the name of the file is
1141 given using a format string. The formatting rules are the same as
1141 given using a format string. The formatting rules are the same as
1142 for the export command, with the following additions:
1142 for the export command, with the following additions:
1143
1143
1144 :``%s``: basename of file being printed
1144 :``%s``: basename of file being printed
1145 :``%d``: dirname of file being printed, or '.' if in repository root
1145 :``%d``: dirname of file being printed, or '.' if in repository root
1146 :``%p``: root-relative path name of file being printed
1146 :``%p``: root-relative path name of file being printed
1147
1147
1148 Returns 0 on success.
1148 Returns 0 on success.
1149 """
1149 """
1150 ctx = scmutil.revsingle(repo, opts.get('rev'))
1150 ctx = scmutil.revsingle(repo, opts.get('rev'))
1151 err = 1
1151 err = 1
1152 m = scmutil.match(ctx, (file1,) + pats, opts)
1152 m = scmutil.match(ctx, (file1,) + pats, opts)
1153 for abs in ctx.walk(m):
1153 for abs in ctx.walk(m):
1154 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1154 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1155 pathname=abs)
1155 pathname=abs)
1156 data = ctx[abs].data()
1156 data = ctx[abs].data()
1157 if opts.get('decode'):
1157 if opts.get('decode'):
1158 data = repo.wwritedata(abs, data)
1158 data = repo.wwritedata(abs, data)
1159 fp.write(data)
1159 fp.write(data)
1160 fp.close()
1160 fp.close()
1161 err = 0
1161 err = 0
1162 return err
1162 return err
1163
1163
1164 @command('^clone',
1164 @command('^clone',
1165 [('U', 'noupdate', None,
1165 [('U', 'noupdate', None,
1166 _('the clone will include an empty working copy (only a repository)')),
1166 _('the clone will include an empty working copy (only a repository)')),
1167 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1167 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1168 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1168 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1169 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1169 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1170 ('', 'pull', None, _('use pull protocol to copy metadata')),
1170 ('', 'pull', None, _('use pull protocol to copy metadata')),
1171 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1171 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1172 ] + remoteopts,
1172 ] + remoteopts,
1173 _('[OPTION]... SOURCE [DEST]'))
1173 _('[OPTION]... SOURCE [DEST]'))
1174 def clone(ui, source, dest=None, **opts):
1174 def clone(ui, source, dest=None, **opts):
1175 """make a copy of an existing repository
1175 """make a copy of an existing repository
1176
1176
1177 Create a copy of an existing repository in a new directory.
1177 Create a copy of an existing repository in a new directory.
1178
1178
1179 If no destination directory name is specified, it defaults to the
1179 If no destination directory name is specified, it defaults to the
1180 basename of the source.
1180 basename of the source.
1181
1181
1182 The location of the source is added to the new repository's
1182 The location of the source is added to the new repository's
1183 ``.hg/hgrc`` file, as the default to be used for future pulls.
1183 ``.hg/hgrc`` file, as the default to be used for future pulls.
1184
1184
1185 Only local paths and ``ssh://`` URLs are supported as
1185 Only local paths and ``ssh://`` URLs are supported as
1186 destinations. For ``ssh://`` destinations, no working directory or
1186 destinations. For ``ssh://`` destinations, no working directory or
1187 ``.hg/hgrc`` will be created on the remote side.
1187 ``.hg/hgrc`` will be created on the remote side.
1188
1188
1189 To pull only a subset of changesets, specify one or more revisions
1189 To pull only a subset of changesets, specify one or more revisions
1190 identifiers with -r/--rev or branches with -b/--branch. The
1190 identifiers with -r/--rev or branches with -b/--branch. The
1191 resulting clone will contain only the specified changesets and
1191 resulting clone will contain only the specified changesets and
1192 their ancestors. These options (or 'clone src#rev dest') imply
1192 their ancestors. These options (or 'clone src#rev dest') imply
1193 --pull, even for local source repositories. Note that specifying a
1193 --pull, even for local source repositories. Note that specifying a
1194 tag will include the tagged changeset but not the changeset
1194 tag will include the tagged changeset but not the changeset
1195 containing the tag.
1195 containing the tag.
1196
1196
1197 If the source repository has a bookmark called '@' set, that
1197 If the source repository has a bookmark called '@' set, that
1198 revision will be checked out in the new repository by default.
1198 revision will be checked out in the new repository by default.
1199
1199
1200 To check out a particular version, use -u/--update, or
1200 To check out a particular version, use -u/--update, or
1201 -U/--noupdate to create a clone with no working directory.
1201 -U/--noupdate to create a clone with no working directory.
1202
1202
1203 .. container:: verbose
1203 .. container:: verbose
1204
1204
1205 For efficiency, hardlinks are used for cloning whenever the
1205 For efficiency, hardlinks are used for cloning whenever the
1206 source and destination are on the same filesystem (note this
1206 source and destination are on the same filesystem (note this
1207 applies only to the repository data, not to the working
1207 applies only to the repository data, not to the working
1208 directory). Some filesystems, such as AFS, implement hardlinking
1208 directory). Some filesystems, such as AFS, implement hardlinking
1209 incorrectly, but do not report errors. In these cases, use the
1209 incorrectly, but do not report errors. In these cases, use the
1210 --pull option to avoid hardlinking.
1210 --pull option to avoid hardlinking.
1211
1211
1212 In some cases, you can clone repositories and the working
1212 In some cases, you can clone repositories and the working
1213 directory using full hardlinks with ::
1213 directory using full hardlinks with ::
1214
1214
1215 $ cp -al REPO REPOCLONE
1215 $ cp -al REPO REPOCLONE
1216
1216
1217 This is the fastest way to clone, but it is not always safe. The
1217 This is the fastest way to clone, but it is not always safe. The
1218 operation is not atomic (making sure REPO is not modified during
1218 operation is not atomic (making sure REPO is not modified during
1219 the operation is up to you) and you have to make sure your
1219 the operation is up to you) and you have to make sure your
1220 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1220 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1221 so). Also, this is not compatible with certain extensions that
1221 so). Also, this is not compatible with certain extensions that
1222 place their metadata under the .hg directory, such as mq.
1222 place their metadata under the .hg directory, such as mq.
1223
1223
1224 Mercurial will update the working directory to the first applicable
1224 Mercurial will update the working directory to the first applicable
1225 revision from this list:
1225 revision from this list:
1226
1226
1227 a) null if -U or the source repository has no changesets
1227 a) null if -U or the source repository has no changesets
1228 b) if -u . and the source repository is local, the first parent of
1228 b) if -u . and the source repository is local, the first parent of
1229 the source repository's working directory
1229 the source repository's working directory
1230 c) the changeset specified with -u (if a branch name, this means the
1230 c) the changeset specified with -u (if a branch name, this means the
1231 latest head of that branch)
1231 latest head of that branch)
1232 d) the changeset specified with -r
1232 d) the changeset specified with -r
1233 e) the tipmost head specified with -b
1233 e) the tipmost head specified with -b
1234 f) the tipmost head specified with the url#branch source syntax
1234 f) the tipmost head specified with the url#branch source syntax
1235 g) the revision marked with the '@' bookmark, if present
1235 g) the revision marked with the '@' bookmark, if present
1236 h) the tipmost head of the default branch
1236 h) the tipmost head of the default branch
1237 i) tip
1237 i) tip
1238
1238
1239 Examples:
1239 Examples:
1240
1240
1241 - clone a remote repository to a new directory named hg/::
1241 - clone a remote repository to a new directory named hg/::
1242
1242
1243 hg clone http://selenic.com/hg
1243 hg clone http://selenic.com/hg
1244
1244
1245 - create a lightweight local clone::
1245 - create a lightweight local clone::
1246
1246
1247 hg clone project/ project-feature/
1247 hg clone project/ project-feature/
1248
1248
1249 - clone from an absolute path on an ssh server (note double-slash)::
1249 - clone from an absolute path on an ssh server (note double-slash)::
1250
1250
1251 hg clone ssh://user@server//home/projects/alpha/
1251 hg clone ssh://user@server//home/projects/alpha/
1252
1252
1253 - do a high-speed clone over a LAN while checking out a
1253 - do a high-speed clone over a LAN while checking out a
1254 specified version::
1254 specified version::
1255
1255
1256 hg clone --uncompressed http://server/repo -u 1.5
1256 hg clone --uncompressed http://server/repo -u 1.5
1257
1257
1258 - create a repository without changesets after a particular revision::
1258 - create a repository without changesets after a particular revision::
1259
1259
1260 hg clone -r 04e544 experimental/ good/
1260 hg clone -r 04e544 experimental/ good/
1261
1261
1262 - clone (and track) a particular named branch::
1262 - clone (and track) a particular named branch::
1263
1263
1264 hg clone http://selenic.com/hg#stable
1264 hg clone http://selenic.com/hg#stable
1265
1265
1266 See :hg:`help urls` for details on specifying URLs.
1266 See :hg:`help urls` for details on specifying URLs.
1267
1267
1268 Returns 0 on success.
1268 Returns 0 on success.
1269 """
1269 """
1270 if opts.get('noupdate') and opts.get('updaterev'):
1270 if opts.get('noupdate') and opts.get('updaterev'):
1271 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1271 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1272
1272
1273 r = hg.clone(ui, opts, source, dest,
1273 r = hg.clone(ui, opts, source, dest,
1274 pull=opts.get('pull'),
1274 pull=opts.get('pull'),
1275 stream=opts.get('uncompressed'),
1275 stream=opts.get('uncompressed'),
1276 rev=opts.get('rev'),
1276 rev=opts.get('rev'),
1277 update=opts.get('updaterev') or not opts.get('noupdate'),
1277 update=opts.get('updaterev') or not opts.get('noupdate'),
1278 branch=opts.get('branch'))
1278 branch=opts.get('branch'))
1279
1279
1280 return r is None
1280 return r is None
1281
1281
1282 @command('^commit|ci',
1282 @command('^commit|ci',
1283 [('A', 'addremove', None,
1283 [('A', 'addremove', None,
1284 _('mark new/missing files as added/removed before committing')),
1284 _('mark new/missing files as added/removed before committing')),
1285 ('', 'close-branch', None,
1285 ('', 'close-branch', None,
1286 _('mark a branch as closed, hiding it from the branch list')),
1286 _('mark a branch as closed, hiding it from the branch list')),
1287 ('', 'amend', None, _('amend the parent of the working dir')),
1287 ('', 'amend', None, _('amend the parent of the working dir')),
1288 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1288 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1289 _('[OPTION]... [FILE]...'))
1289 _('[OPTION]... [FILE]...'))
1290 def commit(ui, repo, *pats, **opts):
1290 def commit(ui, repo, *pats, **opts):
1291 """commit the specified files or all outstanding changes
1291 """commit the specified files or all outstanding changes
1292
1292
1293 Commit changes to the given files into the repository. Unlike a
1293 Commit changes to the given files into the repository. Unlike a
1294 centralized SCM, this operation is a local operation. See
1294 centralized SCM, this operation is a local operation. See
1295 :hg:`push` for a way to actively distribute your changes.
1295 :hg:`push` for a way to actively distribute your changes.
1296
1296
1297 If a list of files is omitted, all changes reported by :hg:`status`
1297 If a list of files is omitted, all changes reported by :hg:`status`
1298 will be committed.
1298 will be committed.
1299
1299
1300 If you are committing the result of a merge, do not provide any
1300 If you are committing the result of a merge, do not provide any
1301 filenames or -I/-X filters.
1301 filenames or -I/-X filters.
1302
1302
1303 If no commit message is specified, Mercurial starts your
1303 If no commit message is specified, Mercurial starts your
1304 configured editor where you can enter a message. In case your
1304 configured editor where you can enter a message. In case your
1305 commit fails, you will find a backup of your message in
1305 commit fails, you will find a backup of your message in
1306 ``.hg/last-message.txt``.
1306 ``.hg/last-message.txt``.
1307
1307
1308 The --amend flag can be used to amend the parent of the
1308 The --amend flag can be used to amend the parent of the
1309 working directory with a new commit that contains the changes
1309 working directory with a new commit that contains the changes
1310 in the parent in addition to those currently reported by :hg:`status`,
1310 in the parent in addition to those currently reported by :hg:`status`,
1311 if there are any. The old commit is stored in a backup bundle in
1311 if there are any. The old commit is stored in a backup bundle in
1312 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1312 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1313 on how to restore it).
1313 on how to restore it).
1314
1314
1315 Message, user and date are taken from the amended commit unless
1315 Message, user and date are taken from the amended commit unless
1316 specified. When a message isn't specified on the command line,
1316 specified. When a message isn't specified on the command line,
1317 the editor will open with the message of the amended commit.
1317 the editor will open with the message of the amended commit.
1318
1318
1319 It is not possible to amend public changesets (see :hg:`help phases`)
1319 It is not possible to amend public changesets (see :hg:`help phases`)
1320 or changesets that have children.
1320 or changesets that have children.
1321
1321
1322 See :hg:`help dates` for a list of formats valid for -d/--date.
1322 See :hg:`help dates` for a list of formats valid for -d/--date.
1323
1323
1324 Returns 0 on success, 1 if nothing changed.
1324 Returns 0 on success, 1 if nothing changed.
1325 """
1325 """
1326 if opts.get('subrepos'):
1326 if opts.get('subrepos'):
1327 if opts.get('amend'):
1327 if opts.get('amend'):
1328 raise util.Abort(_('cannot amend with --subrepos'))
1328 raise util.Abort(_('cannot amend with --subrepos'))
1329 # Let --subrepos on the command line override config setting.
1329 # Let --subrepos on the command line override config setting.
1330 ui.setconfig('ui', 'commitsubrepos', True)
1330 ui.setconfig('ui', 'commitsubrepos', True)
1331
1331
1332 if repo.vfs.exists('graftstate'):
1332 if repo.vfs.exists('graftstate'):
1333 raise util.Abort(_('cannot commit an interrupted graft operation'),
1333 raise util.Abort(_('cannot commit an interrupted graft operation'),
1334 hint=_('use "hg graft -c" to continue graft'))
1334 hint=_('use "hg graft -c" to continue graft'))
1335
1335
1336 branch = repo[None].branch()
1336 branch = repo[None].branch()
1337 bheads = repo.branchheads(branch)
1337 bheads = repo.branchheads(branch)
1338
1338
1339 extra = {}
1339 extra = {}
1340 if opts.get('close_branch'):
1340 if opts.get('close_branch'):
1341 extra['close'] = 1
1341 extra['close'] = 1
1342
1342
1343 if not bheads:
1343 if not bheads:
1344 raise util.Abort(_('can only close branch heads'))
1344 raise util.Abort(_('can only close branch heads'))
1345 elif opts.get('amend'):
1345 elif opts.get('amend'):
1346 if repo.parents()[0].p1().branch() != branch and \
1346 if repo.parents()[0].p1().branch() != branch and \
1347 repo.parents()[0].p2().branch() != branch:
1347 repo.parents()[0].p2().branch() != branch:
1348 raise util.Abort(_('can only close branch heads'))
1348 raise util.Abort(_('can only close branch heads'))
1349
1349
1350 if opts.get('amend'):
1350 if opts.get('amend'):
1351 if ui.configbool('ui', 'commitsubrepos'):
1351 if ui.configbool('ui', 'commitsubrepos'):
1352 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1352 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1353
1353
1354 old = repo['.']
1354 old = repo['.']
1355 if old.phase() == phases.public:
1355 if old.phase() == phases.public:
1356 raise util.Abort(_('cannot amend public changesets'))
1356 raise util.Abort(_('cannot amend public changesets'))
1357 if len(repo[None].parents()) > 1:
1357 if len(repo[None].parents()) > 1:
1358 raise util.Abort(_('cannot amend while merging'))
1358 raise util.Abort(_('cannot amend while merging'))
1359 if (not obsolete._enabled) and old.children():
1359 if (not obsolete._enabled) and old.children():
1360 raise util.Abort(_('cannot amend changeset with children'))
1360 raise util.Abort(_('cannot amend changeset with children'))
1361
1361
1362 e = cmdutil.commiteditor
1362 e = cmdutil.commiteditor
1363 if opts.get('force_editor'):
1363 if opts.get('force_editor'):
1364 e = cmdutil.commitforceeditor
1364 e = cmdutil.commitforceeditor
1365
1365
1366 def commitfunc(ui, repo, message, match, opts):
1366 def commitfunc(ui, repo, message, match, opts):
1367 editor = e
1367 editor = e
1368 # message contains text from -m or -l, if it's empty,
1368 # message contains text from -m or -l, if it's empty,
1369 # open the editor with the old message
1369 # open the editor with the old message
1370 if not message:
1370 if not message:
1371 message = old.description()
1371 message = old.description()
1372 editor = cmdutil.commitforceeditor
1372 editor = cmdutil.commitforceeditor
1373 return repo.commit(message,
1373 return repo.commit(message,
1374 opts.get('user') or old.user(),
1374 opts.get('user') or old.user(),
1375 opts.get('date') or old.date(),
1375 opts.get('date') or old.date(),
1376 match,
1376 match,
1377 editor=editor,
1377 editor=editor,
1378 extra=extra)
1378 extra=extra)
1379
1379
1380 current = repo._bookmarkcurrent
1380 current = repo._bookmarkcurrent
1381 marks = old.bookmarks()
1381 marks = old.bookmarks()
1382 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1382 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1383 if node == old.node():
1383 if node == old.node():
1384 ui.status(_("nothing changed\n"))
1384 ui.status(_("nothing changed\n"))
1385 return 1
1385 return 1
1386 elif marks:
1386 elif marks:
1387 ui.debug('moving bookmarks %r from %s to %s\n' %
1387 ui.debug('moving bookmarks %r from %s to %s\n' %
1388 (marks, old.hex(), hex(node)))
1388 (marks, old.hex(), hex(node)))
1389 newmarks = repo._bookmarks
1389 newmarks = repo._bookmarks
1390 for bm in marks:
1390 for bm in marks:
1391 newmarks[bm] = node
1391 newmarks[bm] = node
1392 if bm == current:
1392 if bm == current:
1393 bookmarks.setcurrent(repo, bm)
1393 bookmarks.setcurrent(repo, bm)
1394 newmarks.write()
1394 newmarks.write()
1395 else:
1395 else:
1396 e = cmdutil.commiteditor
1396 e = cmdutil.commiteditor
1397 if opts.get('force_editor'):
1397 if opts.get('force_editor'):
1398 e = cmdutil.commitforceeditor
1398 e = cmdutil.commitforceeditor
1399
1399
1400 def commitfunc(ui, repo, message, match, opts):
1400 def commitfunc(ui, repo, message, match, opts):
1401 return repo.commit(message, opts.get('user'), opts.get('date'),
1401 return repo.commit(message, opts.get('user'), opts.get('date'),
1402 match, editor=e, extra=extra)
1402 match, editor=e, extra=extra)
1403
1403
1404 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1404 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1405
1405
1406 if not node:
1406 if not node:
1407 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1407 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1408 if stat[3]:
1408 if stat[3]:
1409 ui.status(_("nothing changed (%d missing files, see "
1409 ui.status(_("nothing changed (%d missing files, see "
1410 "'hg status')\n") % len(stat[3]))
1410 "'hg status')\n") % len(stat[3]))
1411 else:
1411 else:
1412 ui.status(_("nothing changed\n"))
1412 ui.status(_("nothing changed\n"))
1413 return 1
1413 return 1
1414
1414
1415 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1415 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1416
1416
1417 @command('copy|cp',
1417 @command('copy|cp',
1418 [('A', 'after', None, _('record a copy that has already occurred')),
1418 [('A', 'after', None, _('record a copy that has already occurred')),
1419 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1419 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1420 ] + walkopts + dryrunopts,
1420 ] + walkopts + dryrunopts,
1421 _('[OPTION]... [SOURCE]... DEST'))
1421 _('[OPTION]... [SOURCE]... DEST'))
1422 def copy(ui, repo, *pats, **opts):
1422 def copy(ui, repo, *pats, **opts):
1423 """mark files as copied for the next commit
1423 """mark files as copied for the next commit
1424
1424
1425 Mark dest as having copies of source files. If dest is a
1425 Mark dest as having copies of source files. If dest is a
1426 directory, copies are put in that directory. If dest is a file,
1426 directory, copies are put in that directory. If dest is a file,
1427 the source must be a single file.
1427 the source must be a single file.
1428
1428
1429 By default, this command copies the contents of files as they
1429 By default, this command copies the contents of files as they
1430 exist in the working directory. If invoked with -A/--after, the
1430 exist in the working directory. If invoked with -A/--after, the
1431 operation is recorded, but no copying is performed.
1431 operation is recorded, but no copying is performed.
1432
1432
1433 This command takes effect with the next commit. To undo a copy
1433 This command takes effect with the next commit. To undo a copy
1434 before that, see :hg:`revert`.
1434 before that, see :hg:`revert`.
1435
1435
1436 Returns 0 on success, 1 if errors are encountered.
1436 Returns 0 on success, 1 if errors are encountered.
1437 """
1437 """
1438 wlock = repo.wlock(False)
1438 wlock = repo.wlock(False)
1439 try:
1439 try:
1440 return cmdutil.copy(ui, repo, pats, opts)
1440 return cmdutil.copy(ui, repo, pats, opts)
1441 finally:
1441 finally:
1442 wlock.release()
1442 wlock.release()
1443
1443
1444 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1444 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1445 def debugancestor(ui, repo, *args):
1445 def debugancestor(ui, repo, *args):
1446 """find the ancestor revision of two revisions in a given index"""
1446 """find the ancestor revision of two revisions in a given index"""
1447 if len(args) == 3:
1447 if len(args) == 3:
1448 index, rev1, rev2 = args
1448 index, rev1, rev2 = args
1449 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1449 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1450 lookup = r.lookup
1450 lookup = r.lookup
1451 elif len(args) == 2:
1451 elif len(args) == 2:
1452 if not repo:
1452 if not repo:
1453 raise util.Abort(_("there is no Mercurial repository here "
1453 raise util.Abort(_("there is no Mercurial repository here "
1454 "(.hg not found)"))
1454 "(.hg not found)"))
1455 rev1, rev2 = args
1455 rev1, rev2 = args
1456 r = repo.changelog
1456 r = repo.changelog
1457 lookup = repo.lookup
1457 lookup = repo.lookup
1458 else:
1458 else:
1459 raise util.Abort(_('either two or three arguments required'))
1459 raise util.Abort(_('either two or three arguments required'))
1460 a = r.ancestor(lookup(rev1), lookup(rev2))
1460 a = r.ancestor(lookup(rev1), lookup(rev2))
1461 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1461 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1462
1462
1463 @command('debugbuilddag',
1463 @command('debugbuilddag',
1464 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1464 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1465 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1465 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1466 ('n', 'new-file', None, _('add new file at each rev'))],
1466 ('n', 'new-file', None, _('add new file at each rev'))],
1467 _('[OPTION]... [TEXT]'))
1467 _('[OPTION]... [TEXT]'))
1468 def debugbuilddag(ui, repo, text=None,
1468 def debugbuilddag(ui, repo, text=None,
1469 mergeable_file=False,
1469 mergeable_file=False,
1470 overwritten_file=False,
1470 overwritten_file=False,
1471 new_file=False):
1471 new_file=False):
1472 """builds a repo with a given DAG from scratch in the current empty repo
1472 """builds a repo with a given DAG from scratch in the current empty repo
1473
1473
1474 The description of the DAG is read from stdin if not given on the
1474 The description of the DAG is read from stdin if not given on the
1475 command line.
1475 command line.
1476
1476
1477 Elements:
1477 Elements:
1478
1478
1479 - "+n" is a linear run of n nodes based on the current default parent
1479 - "+n" is a linear run of n nodes based on the current default parent
1480 - "." is a single node based on the current default parent
1480 - "." is a single node based on the current default parent
1481 - "$" resets the default parent to null (implied at the start);
1481 - "$" resets the default parent to null (implied at the start);
1482 otherwise the default parent is always the last node created
1482 otherwise the default parent is always the last node created
1483 - "<p" sets the default parent to the backref p
1483 - "<p" sets the default parent to the backref p
1484 - "*p" is a fork at parent p, which is a backref
1484 - "*p" is a fork at parent p, which is a backref
1485 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1485 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1486 - "/p2" is a merge of the preceding node and p2
1486 - "/p2" is a merge of the preceding node and p2
1487 - ":tag" defines a local tag for the preceding node
1487 - ":tag" defines a local tag for the preceding node
1488 - "@branch" sets the named branch for subsequent nodes
1488 - "@branch" sets the named branch for subsequent nodes
1489 - "#...\\n" is a comment up to the end of the line
1489 - "#...\\n" is a comment up to the end of the line
1490
1490
1491 Whitespace between the above elements is ignored.
1491 Whitespace between the above elements is ignored.
1492
1492
1493 A backref is either
1493 A backref is either
1494
1494
1495 - a number n, which references the node curr-n, where curr is the current
1495 - a number n, which references the node curr-n, where curr is the current
1496 node, or
1496 node, or
1497 - the name of a local tag you placed earlier using ":tag", or
1497 - the name of a local tag you placed earlier using ":tag", or
1498 - empty to denote the default parent.
1498 - empty to denote the default parent.
1499
1499
1500 All string valued-elements are either strictly alphanumeric, or must
1500 All string valued-elements are either strictly alphanumeric, or must
1501 be enclosed in double quotes ("..."), with "\\" as escape character.
1501 be enclosed in double quotes ("..."), with "\\" as escape character.
1502 """
1502 """
1503
1503
1504 if text is None:
1504 if text is None:
1505 ui.status(_("reading DAG from stdin\n"))
1505 ui.status(_("reading DAG from stdin\n"))
1506 text = ui.fin.read()
1506 text = ui.fin.read()
1507
1507
1508 cl = repo.changelog
1508 cl = repo.changelog
1509 if len(cl) > 0:
1509 if len(cl) > 0:
1510 raise util.Abort(_('repository is not empty'))
1510 raise util.Abort(_('repository is not empty'))
1511
1511
1512 # determine number of revs in DAG
1512 # determine number of revs in DAG
1513 total = 0
1513 total = 0
1514 for type, data in dagparser.parsedag(text):
1514 for type, data in dagparser.parsedag(text):
1515 if type == 'n':
1515 if type == 'n':
1516 total += 1
1516 total += 1
1517
1517
1518 if mergeable_file:
1518 if mergeable_file:
1519 linesperrev = 2
1519 linesperrev = 2
1520 # make a file with k lines per rev
1520 # make a file with k lines per rev
1521 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1521 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1522 initialmergedlines.append("")
1522 initialmergedlines.append("")
1523
1523
1524 tags = []
1524 tags = []
1525
1525
1526 lock = tr = None
1526 lock = tr = None
1527 try:
1527 try:
1528 lock = repo.lock()
1528 lock = repo.lock()
1529 tr = repo.transaction("builddag")
1529 tr = repo.transaction("builddag")
1530
1530
1531 at = -1
1531 at = -1
1532 atbranch = 'default'
1532 atbranch = 'default'
1533 nodeids = []
1533 nodeids = []
1534 id = 0
1534 id = 0
1535 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1535 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1536 for type, data in dagparser.parsedag(text):
1536 for type, data in dagparser.parsedag(text):
1537 if type == 'n':
1537 if type == 'n':
1538 ui.note(('node %s\n' % str(data)))
1538 ui.note(('node %s\n' % str(data)))
1539 id, ps = data
1539 id, ps = data
1540
1540
1541 files = []
1541 files = []
1542 fctxs = {}
1542 fctxs = {}
1543
1543
1544 p2 = None
1544 p2 = None
1545 if mergeable_file:
1545 if mergeable_file:
1546 fn = "mf"
1546 fn = "mf"
1547 p1 = repo[ps[0]]
1547 p1 = repo[ps[0]]
1548 if len(ps) > 1:
1548 if len(ps) > 1:
1549 p2 = repo[ps[1]]
1549 p2 = repo[ps[1]]
1550 pa = p1.ancestor(p2)
1550 pa = p1.ancestor(p2)
1551 base, local, other = [x[fn].data() for x in (pa, p1,
1551 base, local, other = [x[fn].data() for x in (pa, p1,
1552 p2)]
1552 p2)]
1553 m3 = simplemerge.Merge3Text(base, local, other)
1553 m3 = simplemerge.Merge3Text(base, local, other)
1554 ml = [l.strip() for l in m3.merge_lines()]
1554 ml = [l.strip() for l in m3.merge_lines()]
1555 ml.append("")
1555 ml.append("")
1556 elif at > 0:
1556 elif at > 0:
1557 ml = p1[fn].data().split("\n")
1557 ml = p1[fn].data().split("\n")
1558 else:
1558 else:
1559 ml = initialmergedlines
1559 ml = initialmergedlines
1560 ml[id * linesperrev] += " r%i" % id
1560 ml[id * linesperrev] += " r%i" % id
1561 mergedtext = "\n".join(ml)
1561 mergedtext = "\n".join(ml)
1562 files.append(fn)
1562 files.append(fn)
1563 fctxs[fn] = context.memfilectx(fn, mergedtext)
1563 fctxs[fn] = context.memfilectx(fn, mergedtext)
1564
1564
1565 if overwritten_file:
1565 if overwritten_file:
1566 fn = "of"
1566 fn = "of"
1567 files.append(fn)
1567 files.append(fn)
1568 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1568 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1569
1569
1570 if new_file:
1570 if new_file:
1571 fn = "nf%i" % id
1571 fn = "nf%i" % id
1572 files.append(fn)
1572 files.append(fn)
1573 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1573 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1574 if len(ps) > 1:
1574 if len(ps) > 1:
1575 if not p2:
1575 if not p2:
1576 p2 = repo[ps[1]]
1576 p2 = repo[ps[1]]
1577 for fn in p2:
1577 for fn in p2:
1578 if fn.startswith("nf"):
1578 if fn.startswith("nf"):
1579 files.append(fn)
1579 files.append(fn)
1580 fctxs[fn] = p2[fn]
1580 fctxs[fn] = p2[fn]
1581
1581
1582 def fctxfn(repo, cx, path):
1582 def fctxfn(repo, cx, path):
1583 return fctxs.get(path)
1583 return fctxs.get(path)
1584
1584
1585 if len(ps) == 0 or ps[0] < 0:
1585 if len(ps) == 0 or ps[0] < 0:
1586 pars = [None, None]
1586 pars = [None, None]
1587 elif len(ps) == 1:
1587 elif len(ps) == 1:
1588 pars = [nodeids[ps[0]], None]
1588 pars = [nodeids[ps[0]], None]
1589 else:
1589 else:
1590 pars = [nodeids[p] for p in ps]
1590 pars = [nodeids[p] for p in ps]
1591 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1591 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1592 date=(id, 0),
1592 date=(id, 0),
1593 user="debugbuilddag",
1593 user="debugbuilddag",
1594 extra={'branch': atbranch})
1594 extra={'branch': atbranch})
1595 nodeid = repo.commitctx(cx)
1595 nodeid = repo.commitctx(cx)
1596 nodeids.append(nodeid)
1596 nodeids.append(nodeid)
1597 at = id
1597 at = id
1598 elif type == 'l':
1598 elif type == 'l':
1599 id, name = data
1599 id, name = data
1600 ui.note(('tag %s\n' % name))
1600 ui.note(('tag %s\n' % name))
1601 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1601 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1602 elif type == 'a':
1602 elif type == 'a':
1603 ui.note(('branch %s\n' % data))
1603 ui.note(('branch %s\n' % data))
1604 atbranch = data
1604 atbranch = data
1605 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1605 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1606 tr.close()
1606 tr.close()
1607
1607
1608 if tags:
1608 if tags:
1609 repo.opener.write("localtags", "".join(tags))
1609 repo.opener.write("localtags", "".join(tags))
1610 finally:
1610 finally:
1611 ui.progress(_('building'), None)
1611 ui.progress(_('building'), None)
1612 release(tr, lock)
1612 release(tr, lock)
1613
1613
1614 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1614 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1615 def debugbundle(ui, bundlepath, all=None, **opts):
1615 def debugbundle(ui, bundlepath, all=None, **opts):
1616 """lists the contents of a bundle"""
1616 """lists the contents of a bundle"""
1617 f = hg.openpath(ui, bundlepath)
1617 f = hg.openpath(ui, bundlepath)
1618 try:
1618 try:
1619 gen = changegroup.readbundle(f, bundlepath)
1619 gen = changegroup.readbundle(f, bundlepath)
1620 if all:
1620 if all:
1621 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1621 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1622
1622
1623 def showchunks(named):
1623 def showchunks(named):
1624 ui.write("\n%s\n" % named)
1624 ui.write("\n%s\n" % named)
1625 chain = None
1625 chain = None
1626 while True:
1626 while True:
1627 chunkdata = gen.deltachunk(chain)
1627 chunkdata = gen.deltachunk(chain)
1628 if not chunkdata:
1628 if not chunkdata:
1629 break
1629 break
1630 node = chunkdata['node']
1630 node = chunkdata['node']
1631 p1 = chunkdata['p1']
1631 p1 = chunkdata['p1']
1632 p2 = chunkdata['p2']
1632 p2 = chunkdata['p2']
1633 cs = chunkdata['cs']
1633 cs = chunkdata['cs']
1634 deltabase = chunkdata['deltabase']
1634 deltabase = chunkdata['deltabase']
1635 delta = chunkdata['delta']
1635 delta = chunkdata['delta']
1636 ui.write("%s %s %s %s %s %s\n" %
1636 ui.write("%s %s %s %s %s %s\n" %
1637 (hex(node), hex(p1), hex(p2),
1637 (hex(node), hex(p1), hex(p2),
1638 hex(cs), hex(deltabase), len(delta)))
1638 hex(cs), hex(deltabase), len(delta)))
1639 chain = node
1639 chain = node
1640
1640
1641 chunkdata = gen.changelogheader()
1641 chunkdata = gen.changelogheader()
1642 showchunks("changelog")
1642 showchunks("changelog")
1643 chunkdata = gen.manifestheader()
1643 chunkdata = gen.manifestheader()
1644 showchunks("manifest")
1644 showchunks("manifest")
1645 while True:
1645 while True:
1646 chunkdata = gen.filelogheader()
1646 chunkdata = gen.filelogheader()
1647 if not chunkdata:
1647 if not chunkdata:
1648 break
1648 break
1649 fname = chunkdata['filename']
1649 fname = chunkdata['filename']
1650 showchunks(fname)
1650 showchunks(fname)
1651 else:
1651 else:
1652 chunkdata = gen.changelogheader()
1652 chunkdata = gen.changelogheader()
1653 chain = None
1653 chain = None
1654 while True:
1654 while True:
1655 chunkdata = gen.deltachunk(chain)
1655 chunkdata = gen.deltachunk(chain)
1656 if not chunkdata:
1656 if not chunkdata:
1657 break
1657 break
1658 node = chunkdata['node']
1658 node = chunkdata['node']
1659 ui.write("%s\n" % hex(node))
1659 ui.write("%s\n" % hex(node))
1660 chain = node
1660 chain = node
1661 finally:
1661 finally:
1662 f.close()
1662 f.close()
1663
1663
1664 @command('debugcheckstate', [], '')
1664 @command('debugcheckstate', [], '')
1665 def debugcheckstate(ui, repo):
1665 def debugcheckstate(ui, repo):
1666 """validate the correctness of the current dirstate"""
1666 """validate the correctness of the current dirstate"""
1667 parent1, parent2 = repo.dirstate.parents()
1667 parent1, parent2 = repo.dirstate.parents()
1668 m1 = repo[parent1].manifest()
1668 m1 = repo[parent1].manifest()
1669 m2 = repo[parent2].manifest()
1669 m2 = repo[parent2].manifest()
1670 errors = 0
1670 errors = 0
1671 for f in repo.dirstate:
1671 for f in repo.dirstate:
1672 state = repo.dirstate[f]
1672 state = repo.dirstate[f]
1673 if state in "nr" and f not in m1:
1673 if state in "nr" and f not in m1:
1674 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1674 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1675 errors += 1
1675 errors += 1
1676 if state in "a" and f in m1:
1676 if state in "a" and f in m1:
1677 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1677 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1678 errors += 1
1678 errors += 1
1679 if state in "m" and f not in m1 and f not in m2:
1679 if state in "m" and f not in m1 and f not in m2:
1680 ui.warn(_("%s in state %s, but not in either manifest\n") %
1680 ui.warn(_("%s in state %s, but not in either manifest\n") %
1681 (f, state))
1681 (f, state))
1682 errors += 1
1682 errors += 1
1683 for f in m1:
1683 for f in m1:
1684 state = repo.dirstate[f]
1684 state = repo.dirstate[f]
1685 if state not in "nrm":
1685 if state not in "nrm":
1686 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1686 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1687 errors += 1
1687 errors += 1
1688 if errors:
1688 if errors:
1689 error = _(".hg/dirstate inconsistent with current parent's manifest")
1689 error = _(".hg/dirstate inconsistent with current parent's manifest")
1690 raise util.Abort(error)
1690 raise util.Abort(error)
1691
1691
1692 @command('debugcommands', [], _('[COMMAND]'))
1692 @command('debugcommands', [], _('[COMMAND]'))
1693 def debugcommands(ui, cmd='', *args):
1693 def debugcommands(ui, cmd='', *args):
1694 """list all available commands and options"""
1694 """list all available commands and options"""
1695 for cmd, vals in sorted(table.iteritems()):
1695 for cmd, vals in sorted(table.iteritems()):
1696 cmd = cmd.split('|')[0].strip('^')
1696 cmd = cmd.split('|')[0].strip('^')
1697 opts = ', '.join([i[1] for i in vals[1]])
1697 opts = ', '.join([i[1] for i in vals[1]])
1698 ui.write('%s: %s\n' % (cmd, opts))
1698 ui.write('%s: %s\n' % (cmd, opts))
1699
1699
1700 @command('debugcomplete',
1700 @command('debugcomplete',
1701 [('o', 'options', None, _('show the command options'))],
1701 [('o', 'options', None, _('show the command options'))],
1702 _('[-o] CMD'))
1702 _('[-o] CMD'))
1703 def debugcomplete(ui, cmd='', **opts):
1703 def debugcomplete(ui, cmd='', **opts):
1704 """returns the completion list associated with the given command"""
1704 """returns the completion list associated with the given command"""
1705
1705
1706 if opts.get('options'):
1706 if opts.get('options'):
1707 options = []
1707 options = []
1708 otables = [globalopts]
1708 otables = [globalopts]
1709 if cmd:
1709 if cmd:
1710 aliases, entry = cmdutil.findcmd(cmd, table, False)
1710 aliases, entry = cmdutil.findcmd(cmd, table, False)
1711 otables.append(entry[1])
1711 otables.append(entry[1])
1712 for t in otables:
1712 for t in otables:
1713 for o in t:
1713 for o in t:
1714 if "(DEPRECATED)" in o[3]:
1714 if "(DEPRECATED)" in o[3]:
1715 continue
1715 continue
1716 if o[0]:
1716 if o[0]:
1717 options.append('-%s' % o[0])
1717 options.append('-%s' % o[0])
1718 options.append('--%s' % o[1])
1718 options.append('--%s' % o[1])
1719 ui.write("%s\n" % "\n".join(options))
1719 ui.write("%s\n" % "\n".join(options))
1720 return
1720 return
1721
1721
1722 cmdlist = cmdutil.findpossible(cmd, table)
1722 cmdlist = cmdutil.findpossible(cmd, table)
1723 if ui.verbose:
1723 if ui.verbose:
1724 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1724 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1725 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1725 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1726
1726
1727 @command('debugdag',
1727 @command('debugdag',
1728 [('t', 'tags', None, _('use tags as labels')),
1728 [('t', 'tags', None, _('use tags as labels')),
1729 ('b', 'branches', None, _('annotate with branch names')),
1729 ('b', 'branches', None, _('annotate with branch names')),
1730 ('', 'dots', None, _('use dots for runs')),
1730 ('', 'dots', None, _('use dots for runs')),
1731 ('s', 'spaces', None, _('separate elements by spaces'))],
1731 ('s', 'spaces', None, _('separate elements by spaces'))],
1732 _('[OPTION]... [FILE [REV]...]'))
1732 _('[OPTION]... [FILE [REV]...]'))
1733 def debugdag(ui, repo, file_=None, *revs, **opts):
1733 def debugdag(ui, repo, file_=None, *revs, **opts):
1734 """format the changelog or an index DAG as a concise textual description
1734 """format the changelog or an index DAG as a concise textual description
1735
1735
1736 If you pass a revlog index, the revlog's DAG is emitted. If you list
1736 If you pass a revlog index, the revlog's DAG is emitted. If you list
1737 revision numbers, they get labeled in the output as rN.
1737 revision numbers, they get labeled in the output as rN.
1738
1738
1739 Otherwise, the changelog DAG of the current repo is emitted.
1739 Otherwise, the changelog DAG of the current repo is emitted.
1740 """
1740 """
1741 spaces = opts.get('spaces')
1741 spaces = opts.get('spaces')
1742 dots = opts.get('dots')
1742 dots = opts.get('dots')
1743 if file_:
1743 if file_:
1744 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1744 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1745 revs = set((int(r) for r in revs))
1745 revs = set((int(r) for r in revs))
1746 def events():
1746 def events():
1747 for r in rlog:
1747 for r in rlog:
1748 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1748 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1749 if p != -1)))
1749 if p != -1)))
1750 if r in revs:
1750 if r in revs:
1751 yield 'l', (r, "r%i" % r)
1751 yield 'l', (r, "r%i" % r)
1752 elif repo:
1752 elif repo:
1753 cl = repo.changelog
1753 cl = repo.changelog
1754 tags = opts.get('tags')
1754 tags = opts.get('tags')
1755 branches = opts.get('branches')
1755 branches = opts.get('branches')
1756 if tags:
1756 if tags:
1757 labels = {}
1757 labels = {}
1758 for l, n in repo.tags().items():
1758 for l, n in repo.tags().items():
1759 labels.setdefault(cl.rev(n), []).append(l)
1759 labels.setdefault(cl.rev(n), []).append(l)
1760 def events():
1760 def events():
1761 b = "default"
1761 b = "default"
1762 for r in cl:
1762 for r in cl:
1763 if branches:
1763 if branches:
1764 newb = cl.read(cl.node(r))[5]['branch']
1764 newb = cl.read(cl.node(r))[5]['branch']
1765 if newb != b:
1765 if newb != b:
1766 yield 'a', newb
1766 yield 'a', newb
1767 b = newb
1767 b = newb
1768 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1768 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1769 if p != -1)))
1769 if p != -1)))
1770 if tags:
1770 if tags:
1771 ls = labels.get(r)
1771 ls = labels.get(r)
1772 if ls:
1772 if ls:
1773 for l in ls:
1773 for l in ls:
1774 yield 'l', (r, l)
1774 yield 'l', (r, l)
1775 else:
1775 else:
1776 raise util.Abort(_('need repo for changelog dag'))
1776 raise util.Abort(_('need repo for changelog dag'))
1777
1777
1778 for line in dagparser.dagtextlines(events(),
1778 for line in dagparser.dagtextlines(events(),
1779 addspaces=spaces,
1779 addspaces=spaces,
1780 wraplabels=True,
1780 wraplabels=True,
1781 wrapannotations=True,
1781 wrapannotations=True,
1782 wrapnonlinear=dots,
1782 wrapnonlinear=dots,
1783 usedots=dots,
1783 usedots=dots,
1784 maxlinewidth=70):
1784 maxlinewidth=70):
1785 ui.write(line)
1785 ui.write(line)
1786 ui.write("\n")
1786 ui.write("\n")
1787
1787
1788 @command('debugdata',
1788 @command('debugdata',
1789 [('c', 'changelog', False, _('open changelog')),
1789 [('c', 'changelog', False, _('open changelog')),
1790 ('m', 'manifest', False, _('open manifest'))],
1790 ('m', 'manifest', False, _('open manifest'))],
1791 _('-c|-m|FILE REV'))
1791 _('-c|-m|FILE REV'))
1792 def debugdata(ui, repo, file_, rev = None, **opts):
1792 def debugdata(ui, repo, file_, rev = None, **opts):
1793 """dump the contents of a data file revision"""
1793 """dump the contents of a data file revision"""
1794 if opts.get('changelog') or opts.get('manifest'):
1794 if opts.get('changelog') or opts.get('manifest'):
1795 file_, rev = None, file_
1795 file_, rev = None, file_
1796 elif rev is None:
1796 elif rev is None:
1797 raise error.CommandError('debugdata', _('invalid arguments'))
1797 raise error.CommandError('debugdata', _('invalid arguments'))
1798 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1798 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1799 try:
1799 try:
1800 ui.write(r.revision(r.lookup(rev)))
1800 ui.write(r.revision(r.lookup(rev)))
1801 except KeyError:
1801 except KeyError:
1802 raise util.Abort(_('invalid revision identifier %s') % rev)
1802 raise util.Abort(_('invalid revision identifier %s') % rev)
1803
1803
1804 @command('debugdate',
1804 @command('debugdate',
1805 [('e', 'extended', None, _('try extended date formats'))],
1805 [('e', 'extended', None, _('try extended date formats'))],
1806 _('[-e] DATE [RANGE]'))
1806 _('[-e] DATE [RANGE]'))
1807 def debugdate(ui, date, range=None, **opts):
1807 def debugdate(ui, date, range=None, **opts):
1808 """parse and display a date"""
1808 """parse and display a date"""
1809 if opts["extended"]:
1809 if opts["extended"]:
1810 d = util.parsedate(date, util.extendeddateformats)
1810 d = util.parsedate(date, util.extendeddateformats)
1811 else:
1811 else:
1812 d = util.parsedate(date)
1812 d = util.parsedate(date)
1813 ui.write(("internal: %s %s\n") % d)
1813 ui.write(("internal: %s %s\n") % d)
1814 ui.write(("standard: %s\n") % util.datestr(d))
1814 ui.write(("standard: %s\n") % util.datestr(d))
1815 if range:
1815 if range:
1816 m = util.matchdate(range)
1816 m = util.matchdate(range)
1817 ui.write(("match: %s\n") % m(d[0]))
1817 ui.write(("match: %s\n") % m(d[0]))
1818
1818
1819 @command('debugdiscovery',
1819 @command('debugdiscovery',
1820 [('', 'old', None, _('use old-style discovery')),
1820 [('', 'old', None, _('use old-style discovery')),
1821 ('', 'nonheads', None,
1821 ('', 'nonheads', None,
1822 _('use old-style discovery with non-heads included')),
1822 _('use old-style discovery with non-heads included')),
1823 ] + remoteopts,
1823 ] + remoteopts,
1824 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1824 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1825 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1825 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1826 """runs the changeset discovery protocol in isolation"""
1826 """runs the changeset discovery protocol in isolation"""
1827 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1827 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1828 opts.get('branch'))
1828 opts.get('branch'))
1829 remote = hg.peer(repo, opts, remoteurl)
1829 remote = hg.peer(repo, opts, remoteurl)
1830 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1830 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1831
1831
1832 # make sure tests are repeatable
1832 # make sure tests are repeatable
1833 random.seed(12323)
1833 random.seed(12323)
1834
1834
1835 def doit(localheads, remoteheads, remote=remote):
1835 def doit(localheads, remoteheads, remote=remote):
1836 if opts.get('old'):
1836 if opts.get('old'):
1837 if localheads:
1837 if localheads:
1838 raise util.Abort('cannot use localheads with old style '
1838 raise util.Abort('cannot use localheads with old style '
1839 'discovery')
1839 'discovery')
1840 if not util.safehasattr(remote, 'branches'):
1840 if not util.safehasattr(remote, 'branches'):
1841 # enable in-client legacy support
1841 # enable in-client legacy support
1842 remote = localrepo.locallegacypeer(remote.local())
1842 remote = localrepo.locallegacypeer(remote.local())
1843 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1843 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1844 force=True)
1844 force=True)
1845 common = set(common)
1845 common = set(common)
1846 if not opts.get('nonheads'):
1846 if not opts.get('nonheads'):
1847 ui.write(("unpruned common: %s\n") %
1847 ui.write(("unpruned common: %s\n") %
1848 " ".join(sorted(short(n) for n in common)))
1848 " ".join(sorted(short(n) for n in common)))
1849 dag = dagutil.revlogdag(repo.changelog)
1849 dag = dagutil.revlogdag(repo.changelog)
1850 all = dag.ancestorset(dag.internalizeall(common))
1850 all = dag.ancestorset(dag.internalizeall(common))
1851 common = dag.externalizeall(dag.headsetofconnecteds(all))
1851 common = dag.externalizeall(dag.headsetofconnecteds(all))
1852 else:
1852 else:
1853 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1853 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1854 common = set(common)
1854 common = set(common)
1855 rheads = set(hds)
1855 rheads = set(hds)
1856 lheads = set(repo.heads())
1856 lheads = set(repo.heads())
1857 ui.write(("common heads: %s\n") %
1857 ui.write(("common heads: %s\n") %
1858 " ".join(sorted(short(n) for n in common)))
1858 " ".join(sorted(short(n) for n in common)))
1859 if lheads <= common:
1859 if lheads <= common:
1860 ui.write(("local is subset\n"))
1860 ui.write(("local is subset\n"))
1861 elif rheads <= common:
1861 elif rheads <= common:
1862 ui.write(("remote is subset\n"))
1862 ui.write(("remote is subset\n"))
1863
1863
1864 serverlogs = opts.get('serverlog')
1864 serverlogs = opts.get('serverlog')
1865 if serverlogs:
1865 if serverlogs:
1866 for filename in serverlogs:
1866 for filename in serverlogs:
1867 logfile = open(filename, 'r')
1867 logfile = open(filename, 'r')
1868 try:
1868 try:
1869 line = logfile.readline()
1869 line = logfile.readline()
1870 while line:
1870 while line:
1871 parts = line.strip().split(';')
1871 parts = line.strip().split(';')
1872 op = parts[1]
1872 op = parts[1]
1873 if op == 'cg':
1873 if op == 'cg':
1874 pass
1874 pass
1875 elif op == 'cgss':
1875 elif op == 'cgss':
1876 doit(parts[2].split(' '), parts[3].split(' '))
1876 doit(parts[2].split(' '), parts[3].split(' '))
1877 elif op == 'unb':
1877 elif op == 'unb':
1878 doit(parts[3].split(' '), parts[2].split(' '))
1878 doit(parts[3].split(' '), parts[2].split(' '))
1879 line = logfile.readline()
1879 line = logfile.readline()
1880 finally:
1880 finally:
1881 logfile.close()
1881 logfile.close()
1882
1882
1883 else:
1883 else:
1884 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1884 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1885 opts.get('remote_head'))
1885 opts.get('remote_head'))
1886 localrevs = opts.get('local_head')
1886 localrevs = opts.get('local_head')
1887 doit(localrevs, remoterevs)
1887 doit(localrevs, remoterevs)
1888
1888
1889 @command('debugfileset',
1889 @command('debugfileset',
1890 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1890 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1891 _('[-r REV] FILESPEC'))
1891 _('[-r REV] FILESPEC'))
1892 def debugfileset(ui, repo, expr, **opts):
1892 def debugfileset(ui, repo, expr, **opts):
1893 '''parse and apply a fileset specification'''
1893 '''parse and apply a fileset specification'''
1894 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1894 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1895 if ui.verbose:
1895 if ui.verbose:
1896 tree = fileset.parse(expr)[0]
1896 tree = fileset.parse(expr)[0]
1897 ui.note(tree, "\n")
1897 ui.note(tree, "\n")
1898
1898
1899 for f in fileset.getfileset(ctx, expr):
1899 for f in fileset.getfileset(ctx, expr):
1900 ui.write("%s\n" % f)
1900 ui.write("%s\n" % f)
1901
1901
1902 @command('debugfsinfo', [], _('[PATH]'))
1902 @command('debugfsinfo', [], _('[PATH]'))
1903 def debugfsinfo(ui, path = "."):
1903 def debugfsinfo(ui, path = "."):
1904 """show information detected about current filesystem"""
1904 """show information detected about current filesystem"""
1905 util.writefile('.debugfsinfo', '')
1905 util.writefile('.debugfsinfo', '')
1906 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1906 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1907 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1907 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1908 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1908 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1909 and 'yes' or 'no'))
1909 and 'yes' or 'no'))
1910 os.unlink('.debugfsinfo')
1910 os.unlink('.debugfsinfo')
1911
1911
1912 @command('debuggetbundle',
1912 @command('debuggetbundle',
1913 [('H', 'head', [], _('id of head node'), _('ID')),
1913 [('H', 'head', [], _('id of head node'), _('ID')),
1914 ('C', 'common', [], _('id of common node'), _('ID')),
1914 ('C', 'common', [], _('id of common node'), _('ID')),
1915 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1915 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1916 _('REPO FILE [-H|-C ID]...'))
1916 _('REPO FILE [-H|-C ID]...'))
1917 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1917 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1918 """retrieves a bundle from a repo
1918 """retrieves a bundle from a repo
1919
1919
1920 Every ID must be a full-length hex node id string. Saves the bundle to the
1920 Every ID must be a full-length hex node id string. Saves the bundle to the
1921 given file.
1921 given file.
1922 """
1922 """
1923 repo = hg.peer(ui, opts, repopath)
1923 repo = hg.peer(ui, opts, repopath)
1924 if not repo.capable('getbundle'):
1924 if not repo.capable('getbundle'):
1925 raise util.Abort("getbundle() not supported by target repository")
1925 raise util.Abort("getbundle() not supported by target repository")
1926 args = {}
1926 args = {}
1927 if common:
1927 if common:
1928 args['common'] = [bin(s) for s in common]
1928 args['common'] = [bin(s) for s in common]
1929 if head:
1929 if head:
1930 args['heads'] = [bin(s) for s in head]
1930 args['heads'] = [bin(s) for s in head]
1931 # TODO: get desired bundlecaps from command line.
1931 # TODO: get desired bundlecaps from command line.
1932 args['bundlecaps'] = None
1932 args['bundlecaps'] = None
1933 bundle = repo.getbundle('debug', **args)
1933 bundle = repo.getbundle('debug', **args)
1934
1934
1935 bundletype = opts.get('type', 'bzip2').lower()
1935 bundletype = opts.get('type', 'bzip2').lower()
1936 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1936 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1937 bundletype = btypes.get(bundletype)
1937 bundletype = btypes.get(bundletype)
1938 if bundletype not in changegroup.bundletypes:
1938 if bundletype not in changegroup.bundletypes:
1939 raise util.Abort(_('unknown bundle type specified with --type'))
1939 raise util.Abort(_('unknown bundle type specified with --type'))
1940 changegroup.writebundle(bundle, bundlepath, bundletype)
1940 changegroup.writebundle(bundle, bundlepath, bundletype)
1941
1941
1942 @command('debugignore', [], '')
1942 @command('debugignore', [], '')
1943 def debugignore(ui, repo, *values, **opts):
1943 def debugignore(ui, repo, *values, **opts):
1944 """display the combined ignore pattern"""
1944 """display the combined ignore pattern"""
1945 ignore = repo.dirstate._ignore
1945 ignore = repo.dirstate._ignore
1946 includepat = getattr(ignore, 'includepat', None)
1946 includepat = getattr(ignore, 'includepat', None)
1947 if includepat is not None:
1947 if includepat is not None:
1948 ui.write("%s\n" % includepat)
1948 ui.write("%s\n" % includepat)
1949 else:
1949 else:
1950 raise util.Abort(_("no ignore patterns found"))
1950 raise util.Abort(_("no ignore patterns found"))
1951
1951
1952 @command('debugindex',
1952 @command('debugindex',
1953 [('c', 'changelog', False, _('open changelog')),
1953 [('c', 'changelog', False, _('open changelog')),
1954 ('m', 'manifest', False, _('open manifest')),
1954 ('m', 'manifest', False, _('open manifest')),
1955 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1955 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1956 _('[-f FORMAT] -c|-m|FILE'))
1956 _('[-f FORMAT] -c|-m|FILE'))
1957 def debugindex(ui, repo, file_ = None, **opts):
1957 def debugindex(ui, repo, file_ = None, **opts):
1958 """dump the contents of an index file"""
1958 """dump the contents of an index file"""
1959 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1959 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1960 format = opts.get('format', 0)
1960 format = opts.get('format', 0)
1961 if format not in (0, 1):
1961 if format not in (0, 1):
1962 raise util.Abort(_("unknown format %d") % format)
1962 raise util.Abort(_("unknown format %d") % format)
1963
1963
1964 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1964 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1965 if generaldelta:
1965 if generaldelta:
1966 basehdr = ' delta'
1966 basehdr = ' delta'
1967 else:
1967 else:
1968 basehdr = ' base'
1968 basehdr = ' base'
1969
1969
1970 if format == 0:
1970 if format == 0:
1971 ui.write(" rev offset length " + basehdr + " linkrev"
1971 ui.write(" rev offset length " + basehdr + " linkrev"
1972 " nodeid p1 p2\n")
1972 " nodeid p1 p2\n")
1973 elif format == 1:
1973 elif format == 1:
1974 ui.write(" rev flag offset length"
1974 ui.write(" rev flag offset length"
1975 " size " + basehdr + " link p1 p2"
1975 " size " + basehdr + " link p1 p2"
1976 " nodeid\n")
1976 " nodeid\n")
1977
1977
1978 for i in r:
1978 for i in r:
1979 node = r.node(i)
1979 node = r.node(i)
1980 if generaldelta:
1980 if generaldelta:
1981 base = r.deltaparent(i)
1981 base = r.deltaparent(i)
1982 else:
1982 else:
1983 base = r.chainbase(i)
1983 base = r.chainbase(i)
1984 if format == 0:
1984 if format == 0:
1985 try:
1985 try:
1986 pp = r.parents(node)
1986 pp = r.parents(node)
1987 except Exception:
1987 except Exception:
1988 pp = [nullid, nullid]
1988 pp = [nullid, nullid]
1989 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1989 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1990 i, r.start(i), r.length(i), base, r.linkrev(i),
1990 i, r.start(i), r.length(i), base, r.linkrev(i),
1991 short(node), short(pp[0]), short(pp[1])))
1991 short(node), short(pp[0]), short(pp[1])))
1992 elif format == 1:
1992 elif format == 1:
1993 pr = r.parentrevs(i)
1993 pr = r.parentrevs(i)
1994 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1994 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1995 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1995 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1996 base, r.linkrev(i), pr[0], pr[1], short(node)))
1996 base, r.linkrev(i), pr[0], pr[1], short(node)))
1997
1997
1998 @command('debugindexdot', [], _('FILE'))
1998 @command('debugindexdot', [], _('FILE'))
1999 def debugindexdot(ui, repo, file_):
1999 def debugindexdot(ui, repo, file_):
2000 """dump an index DAG as a graphviz dot file"""
2000 """dump an index DAG as a graphviz dot file"""
2001 r = None
2001 r = None
2002 if repo:
2002 if repo:
2003 filelog = repo.file(file_)
2003 filelog = repo.file(file_)
2004 if len(filelog):
2004 if len(filelog):
2005 r = filelog
2005 r = filelog
2006 if not r:
2006 if not r:
2007 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2007 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2008 ui.write(("digraph G {\n"))
2008 ui.write(("digraph G {\n"))
2009 for i in r:
2009 for i in r:
2010 node = r.node(i)
2010 node = r.node(i)
2011 pp = r.parents(node)
2011 pp = r.parents(node)
2012 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2012 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2013 if pp[1] != nullid:
2013 if pp[1] != nullid:
2014 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2014 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2015 ui.write("}\n")
2015 ui.write("}\n")
2016
2016
2017 @command('debuginstall', [], '')
2017 @command('debuginstall', [], '')
2018 def debuginstall(ui):
2018 def debuginstall(ui):
2019 '''test Mercurial installation
2019 '''test Mercurial installation
2020
2020
2021 Returns 0 on success.
2021 Returns 0 on success.
2022 '''
2022 '''
2023
2023
2024 def writetemp(contents):
2024 def writetemp(contents):
2025 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2025 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2026 f = os.fdopen(fd, "wb")
2026 f = os.fdopen(fd, "wb")
2027 f.write(contents)
2027 f.write(contents)
2028 f.close()
2028 f.close()
2029 return name
2029 return name
2030
2030
2031 problems = 0
2031 problems = 0
2032
2032
2033 # encoding
2033 # encoding
2034 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2034 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2035 try:
2035 try:
2036 encoding.fromlocal("test")
2036 encoding.fromlocal("test")
2037 except util.Abort, inst:
2037 except util.Abort, inst:
2038 ui.write(" %s\n" % inst)
2038 ui.write(" %s\n" % inst)
2039 ui.write(_(" (check that your locale is properly set)\n"))
2039 ui.write(_(" (check that your locale is properly set)\n"))
2040 problems += 1
2040 problems += 1
2041
2041
2042 # Python lib
2042 # Python lib
2043 ui.status(_("checking Python lib (%s)...\n")
2043 ui.status(_("checking Python lib (%s)...\n")
2044 % os.path.dirname(os.__file__))
2044 % os.path.dirname(os.__file__))
2045
2045
2046 # compiled modules
2046 # compiled modules
2047 ui.status(_("checking installed modules (%s)...\n")
2047 ui.status(_("checking installed modules (%s)...\n")
2048 % os.path.dirname(__file__))
2048 % os.path.dirname(__file__))
2049 try:
2049 try:
2050 import bdiff, mpatch, base85, osutil
2050 import bdiff, mpatch, base85, osutil
2051 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2051 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2052 except Exception, inst:
2052 except Exception, inst:
2053 ui.write(" %s\n" % inst)
2053 ui.write(" %s\n" % inst)
2054 ui.write(_(" One or more extensions could not be found"))
2054 ui.write(_(" One or more extensions could not be found"))
2055 ui.write(_(" (check that you compiled the extensions)\n"))
2055 ui.write(_(" (check that you compiled the extensions)\n"))
2056 problems += 1
2056 problems += 1
2057
2057
2058 # templates
2058 # templates
2059 import templater
2059 import templater
2060 p = templater.templatepath()
2060 p = templater.templatepath()
2061 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2061 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2062 try:
2062 try:
2063 templater.templater(templater.templatepath("map-cmdline.default"))
2063 templater.templater(templater.templatepath("map-cmdline.default"))
2064 except Exception, inst:
2064 except Exception, inst:
2065 ui.write(" %s\n" % inst)
2065 ui.write(" %s\n" % inst)
2066 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2066 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2067 problems += 1
2067 problems += 1
2068
2068
2069 # editor
2069 # editor
2070 ui.status(_("checking commit editor...\n"))
2070 ui.status(_("checking commit editor...\n"))
2071 editor = ui.geteditor()
2071 editor = ui.geteditor()
2072 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2072 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2073 if not cmdpath:
2073 if not cmdpath:
2074 if editor == 'vi':
2074 if editor == 'vi':
2075 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2075 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2076 ui.write(_(" (specify a commit editor in your configuration"
2076 ui.write(_(" (specify a commit editor in your configuration"
2077 " file)\n"))
2077 " file)\n"))
2078 else:
2078 else:
2079 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2079 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2080 ui.write(_(" (specify a commit editor in your configuration"
2080 ui.write(_(" (specify a commit editor in your configuration"
2081 " file)\n"))
2081 " file)\n"))
2082 problems += 1
2082 problems += 1
2083
2083
2084 # check username
2084 # check username
2085 ui.status(_("checking username...\n"))
2085 ui.status(_("checking username...\n"))
2086 try:
2086 try:
2087 ui.username()
2087 ui.username()
2088 except util.Abort, e:
2088 except util.Abort, e:
2089 ui.write(" %s\n" % e)
2089 ui.write(" %s\n" % e)
2090 ui.write(_(" (specify a username in your configuration file)\n"))
2090 ui.write(_(" (specify a username in your configuration file)\n"))
2091 problems += 1
2091 problems += 1
2092
2092
2093 if not problems:
2093 if not problems:
2094 ui.status(_("no problems detected\n"))
2094 ui.status(_("no problems detected\n"))
2095 else:
2095 else:
2096 ui.write(_("%s problems detected,"
2096 ui.write(_("%s problems detected,"
2097 " please check your install!\n") % problems)
2097 " please check your install!\n") % problems)
2098
2098
2099 return problems
2099 return problems
2100
2100
2101 @command('debugknown', [], _('REPO ID...'))
2101 @command('debugknown', [], _('REPO ID...'))
2102 def debugknown(ui, repopath, *ids, **opts):
2102 def debugknown(ui, repopath, *ids, **opts):
2103 """test whether node ids are known to a repo
2103 """test whether node ids are known to a repo
2104
2104
2105 Every ID must be a full-length hex node id string. Returns a list of 0s
2105 Every ID must be a full-length hex node id string. Returns a list of 0s
2106 and 1s indicating unknown/known.
2106 and 1s indicating unknown/known.
2107 """
2107 """
2108 repo = hg.peer(ui, opts, repopath)
2108 repo = hg.peer(ui, opts, repopath)
2109 if not repo.capable('known'):
2109 if not repo.capable('known'):
2110 raise util.Abort("known() not supported by target repository")
2110 raise util.Abort("known() not supported by target repository")
2111 flags = repo.known([bin(s) for s in ids])
2111 flags = repo.known([bin(s) for s in ids])
2112 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2112 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2113
2113
2114 @command('debuglabelcomplete', [], _('LABEL...'))
2114 @command('debuglabelcomplete', [], _('LABEL...'))
2115 def debuglabelcomplete(ui, repo, *args):
2115 def debuglabelcomplete(ui, repo, *args):
2116 '''complete "labels" - tags, open branch names, bookmark names'''
2116 '''complete "labels" - tags, open branch names, bookmark names'''
2117
2117
2118 labels = set()
2118 labels = set()
2119 labels.update(t[0] for t in repo.tagslist())
2119 labels.update(t[0] for t in repo.tagslist())
2120 labels.update(repo._bookmarks.keys())
2120 labels.update(repo._bookmarks.keys())
2121 for heads in repo.branchmap().itervalues():
2121 for heads in repo.branchmap().itervalues():
2122 for h in heads:
2122 for h in heads:
2123 ctx = repo[h]
2123 ctx = repo[h]
2124 if not ctx.closesbranch():
2124 if not ctx.closesbranch():
2125 labels.add(ctx.branch())
2125 labels.add(ctx.branch())
2126 completions = set()
2126 completions = set()
2127 if not args:
2127 if not args:
2128 args = ['']
2128 args = ['']
2129 for a in args:
2129 for a in args:
2130 completions.update(l for l in labels if l.startswith(a))
2130 completions.update(l for l in labels if l.startswith(a))
2131 ui.write('\n'.join(sorted(completions)))
2131 ui.write('\n'.join(sorted(completions)))
2132 ui.write('\n')
2132 ui.write('\n')
2133
2133
2134 @command('debugobsolete',
2134 @command('debugobsolete',
2135 [('', 'flags', 0, _('markers flag')),
2135 [('', 'flags', 0, _('markers flag')),
2136 ] + commitopts2,
2136 ] + commitopts2,
2137 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2137 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2138 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2138 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2139 """create arbitrary obsolete marker
2139 """create arbitrary obsolete marker
2140
2140
2141 With no arguments, displays the list of obsolescence markers."""
2141 With no arguments, displays the list of obsolescence markers."""
2142 def parsenodeid(s):
2142 def parsenodeid(s):
2143 try:
2143 try:
2144 # We do not use revsingle/revrange functions here to accept
2144 # We do not use revsingle/revrange functions here to accept
2145 # arbitrary node identifiers, possibly not present in the
2145 # arbitrary node identifiers, possibly not present in the
2146 # local repository.
2146 # local repository.
2147 n = bin(s)
2147 n = bin(s)
2148 if len(n) != len(nullid):
2148 if len(n) != len(nullid):
2149 raise TypeError()
2149 raise TypeError()
2150 return n
2150 return n
2151 except TypeError:
2151 except TypeError:
2152 raise util.Abort('changeset references must be full hexadecimal '
2152 raise util.Abort('changeset references must be full hexadecimal '
2153 'node identifiers')
2153 'node identifiers')
2154
2154
2155 if precursor is not None:
2155 if precursor is not None:
2156 metadata = {}
2156 metadata = {}
2157 if 'date' in opts:
2157 if 'date' in opts:
2158 metadata['date'] = opts['date']
2158 metadata['date'] = opts['date']
2159 metadata['user'] = opts['user'] or ui.username()
2159 metadata['user'] = opts['user'] or ui.username()
2160 succs = tuple(parsenodeid(succ) for succ in successors)
2160 succs = tuple(parsenodeid(succ) for succ in successors)
2161 l = repo.lock()
2161 l = repo.lock()
2162 try:
2162 try:
2163 tr = repo.transaction('debugobsolete')
2163 tr = repo.transaction('debugobsolete')
2164 try:
2164 try:
2165 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2165 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2166 opts['flags'], metadata)
2166 opts['flags'], metadata)
2167 tr.close()
2167 tr.close()
2168 finally:
2168 finally:
2169 tr.release()
2169 tr.release()
2170 finally:
2170 finally:
2171 l.release()
2171 l.release()
2172 else:
2172 else:
2173 for m in obsolete.allmarkers(repo):
2173 for m in obsolete.allmarkers(repo):
2174 ui.write(hex(m.precnode()))
2174 ui.write(hex(m.precnode()))
2175 for repl in m.succnodes():
2175 for repl in m.succnodes():
2176 ui.write(' ')
2176 ui.write(' ')
2177 ui.write(hex(repl))
2177 ui.write(hex(repl))
2178 ui.write(' %X ' % m._data[2])
2178 ui.write(' %X ' % m._data[2])
2179 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2179 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2180 sorted(m.metadata().items()))))
2180 sorted(m.metadata().items()))))
2181 ui.write('\n')
2181 ui.write('\n')
2182
2182
2183 @command('debugpathcomplete',
2183 @command('debugpathcomplete',
2184 [('f', 'full', None, _('complete an entire path')),
2184 [('f', 'full', None, _('complete an entire path')),
2185 ('n', 'normal', None, _('show only normal files')),
2185 ('n', 'normal', None, _('show only normal files')),
2186 ('a', 'added', None, _('show only added files')),
2186 ('a', 'added', None, _('show only added files')),
2187 ('r', 'removed', None, _('show only removed files'))],
2187 ('r', 'removed', None, _('show only removed files'))],
2188 _('FILESPEC...'))
2188 _('FILESPEC...'))
2189 def debugpathcomplete(ui, repo, *specs, **opts):
2189 def debugpathcomplete(ui, repo, *specs, **opts):
2190 '''complete part or all of a tracked path
2190 '''complete part or all of a tracked path
2191
2191
2192 This command supports shells that offer path name completion. It
2192 This command supports shells that offer path name completion. It
2193 currently completes only files already known to the dirstate.
2193 currently completes only files already known to the dirstate.
2194
2194
2195 Completion extends only to the next path segment unless
2195 Completion extends only to the next path segment unless
2196 --full is specified, in which case entire paths are used.'''
2196 --full is specified, in which case entire paths are used.'''
2197
2197
2198 def complete(path, acceptable):
2198 def complete(path, acceptable):
2199 dirstate = repo.dirstate
2199 dirstate = repo.dirstate
2200 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2200 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2201 rootdir = repo.root + os.sep
2201 rootdir = repo.root + os.sep
2202 if spec != repo.root and not spec.startswith(rootdir):
2202 if spec != repo.root and not spec.startswith(rootdir):
2203 return [], []
2203 return [], []
2204 if os.path.isdir(spec):
2204 if os.path.isdir(spec):
2205 spec += '/'
2205 spec += '/'
2206 spec = spec[len(rootdir):]
2206 spec = spec[len(rootdir):]
2207 fixpaths = os.sep != '/'
2207 fixpaths = os.sep != '/'
2208 if fixpaths:
2208 if fixpaths:
2209 spec = spec.replace(os.sep, '/')
2209 spec = spec.replace(os.sep, '/')
2210 speclen = len(spec)
2210 speclen = len(spec)
2211 fullpaths = opts['full']
2211 fullpaths = opts['full']
2212 files, dirs = set(), set()
2212 files, dirs = set(), set()
2213 adddir, addfile = dirs.add, files.add
2213 adddir, addfile = dirs.add, files.add
2214 for f, st in dirstate.iteritems():
2214 for f, st in dirstate.iteritems():
2215 if f.startswith(spec) and st[0] in acceptable:
2215 if f.startswith(spec) and st[0] in acceptable:
2216 if fixpaths:
2216 if fixpaths:
2217 f = f.replace('/', os.sep)
2217 f = f.replace('/', os.sep)
2218 if fullpaths:
2218 if fullpaths:
2219 addfile(f)
2219 addfile(f)
2220 continue
2220 continue
2221 s = f.find(os.sep, speclen)
2221 s = f.find(os.sep, speclen)
2222 if s >= 0:
2222 if s >= 0:
2223 adddir(f[:s + 1])
2223 adddir(f[:s + 1])
2224 else:
2224 else:
2225 addfile(f)
2225 addfile(f)
2226 return files, dirs
2226 return files, dirs
2227
2227
2228 acceptable = ''
2228 acceptable = ''
2229 if opts['normal']:
2229 if opts['normal']:
2230 acceptable += 'nm'
2230 acceptable += 'nm'
2231 if opts['added']:
2231 if opts['added']:
2232 acceptable += 'a'
2232 acceptable += 'a'
2233 if opts['removed']:
2233 if opts['removed']:
2234 acceptable += 'r'
2234 acceptable += 'r'
2235 cwd = repo.getcwd()
2235 cwd = repo.getcwd()
2236 if not specs:
2236 if not specs:
2237 specs = ['.']
2237 specs = ['.']
2238
2238
2239 files, dirs = set(), set()
2239 files, dirs = set(), set()
2240 for spec in specs:
2240 for spec in specs:
2241 f, d = complete(spec, acceptable or 'nmar')
2241 f, d = complete(spec, acceptable or 'nmar')
2242 files.update(f)
2242 files.update(f)
2243 dirs.update(d)
2243 dirs.update(d)
2244 if not files and len(dirs) == 1:
2244 if not files and len(dirs) == 1:
2245 # force the shell to consider a completion that matches one
2245 # force the shell to consider a completion that matches one
2246 # directory and zero files to be ambiguous
2246 # directory and zero files to be ambiguous
2247 dirs.add(iter(dirs).next() + '.')
2247 dirs.add(iter(dirs).next() + '.')
2248 files.update(dirs)
2248 files.update(dirs)
2249 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2249 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2250 ui.write('\n')
2250 ui.write('\n')
2251
2251
2252 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2252 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2253 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2253 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2254 '''access the pushkey key/value protocol
2254 '''access the pushkey key/value protocol
2255
2255
2256 With two args, list the keys in the given namespace.
2256 With two args, list the keys in the given namespace.
2257
2257
2258 With five args, set a key to new if it currently is set to old.
2258 With five args, set a key to new if it currently is set to old.
2259 Reports success or failure.
2259 Reports success or failure.
2260 '''
2260 '''
2261
2261
2262 target = hg.peer(ui, {}, repopath)
2262 target = hg.peer(ui, {}, repopath)
2263 if keyinfo:
2263 if keyinfo:
2264 key, old, new = keyinfo
2264 key, old, new = keyinfo
2265 r = target.pushkey(namespace, key, old, new)
2265 r = target.pushkey(namespace, key, old, new)
2266 ui.status(str(r) + '\n')
2266 ui.status(str(r) + '\n')
2267 return not r
2267 return not r
2268 else:
2268 else:
2269 for k, v in sorted(target.listkeys(namespace).iteritems()):
2269 for k, v in sorted(target.listkeys(namespace).iteritems()):
2270 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2270 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2271 v.encode('string-escape')))
2271 v.encode('string-escape')))
2272
2272
2273 @command('debugpvec', [], _('A B'))
2273 @command('debugpvec', [], _('A B'))
2274 def debugpvec(ui, repo, a, b=None):
2274 def debugpvec(ui, repo, a, b=None):
2275 ca = scmutil.revsingle(repo, a)
2275 ca = scmutil.revsingle(repo, a)
2276 cb = scmutil.revsingle(repo, b)
2276 cb = scmutil.revsingle(repo, b)
2277 pa = pvec.ctxpvec(ca)
2277 pa = pvec.ctxpvec(ca)
2278 pb = pvec.ctxpvec(cb)
2278 pb = pvec.ctxpvec(cb)
2279 if pa == pb:
2279 if pa == pb:
2280 rel = "="
2280 rel = "="
2281 elif pa > pb:
2281 elif pa > pb:
2282 rel = ">"
2282 rel = ">"
2283 elif pa < pb:
2283 elif pa < pb:
2284 rel = "<"
2284 rel = "<"
2285 elif pa | pb:
2285 elif pa | pb:
2286 rel = "|"
2286 rel = "|"
2287 ui.write(_("a: %s\n") % pa)
2287 ui.write(_("a: %s\n") % pa)
2288 ui.write(_("b: %s\n") % pb)
2288 ui.write(_("b: %s\n") % pb)
2289 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2289 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2290 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2290 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2291 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2291 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2292 pa.distance(pb), rel))
2292 pa.distance(pb), rel))
2293
2293
2294 @command('debugrebuilddirstate|debugrebuildstate',
2294 @command('debugrebuilddirstate|debugrebuildstate',
2295 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2295 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2296 _('[-r REV]'))
2296 _('[-r REV]'))
2297 def debugrebuilddirstate(ui, repo, rev):
2297 def debugrebuilddirstate(ui, repo, rev):
2298 """rebuild the dirstate as it would look like for the given revision
2298 """rebuild the dirstate as it would look like for the given revision
2299
2299
2300 If no revision is specified the first current parent will be used.
2300 If no revision is specified the first current parent will be used.
2301
2301
2302 The dirstate will be set to the files of the given revision.
2302 The dirstate will be set to the files of the given revision.
2303 The actual working directory content or existing dirstate
2303 The actual working directory content or existing dirstate
2304 information such as adds or removes is not considered.
2304 information such as adds or removes is not considered.
2305
2305
2306 One use of this command is to make the next :hg:`status` invocation
2306 One use of this command is to make the next :hg:`status` invocation
2307 check the actual file content.
2307 check the actual file content.
2308 """
2308 """
2309 ctx = scmutil.revsingle(repo, rev)
2309 ctx = scmutil.revsingle(repo, rev)
2310 wlock = repo.wlock()
2310 wlock = repo.wlock()
2311 try:
2311 try:
2312 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2312 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2313 finally:
2313 finally:
2314 wlock.release()
2314 wlock.release()
2315
2315
2316 @command('debugrename',
2316 @command('debugrename',
2317 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2317 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2318 _('[-r REV] FILE'))
2318 _('[-r REV] FILE'))
2319 def debugrename(ui, repo, file1, *pats, **opts):
2319 def debugrename(ui, repo, file1, *pats, **opts):
2320 """dump rename information"""
2320 """dump rename information"""
2321
2321
2322 ctx = scmutil.revsingle(repo, opts.get('rev'))
2322 ctx = scmutil.revsingle(repo, opts.get('rev'))
2323 m = scmutil.match(ctx, (file1,) + pats, opts)
2323 m = scmutil.match(ctx, (file1,) + pats, opts)
2324 for abs in ctx.walk(m):
2324 for abs in ctx.walk(m):
2325 fctx = ctx[abs]
2325 fctx = ctx[abs]
2326 o = fctx.filelog().renamed(fctx.filenode())
2326 o = fctx.filelog().renamed(fctx.filenode())
2327 rel = m.rel(abs)
2327 rel = m.rel(abs)
2328 if o:
2328 if o:
2329 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2329 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2330 else:
2330 else:
2331 ui.write(_("%s not renamed\n") % rel)
2331 ui.write(_("%s not renamed\n") % rel)
2332
2332
2333 @command('debugrevlog',
2333 @command('debugrevlog',
2334 [('c', 'changelog', False, _('open changelog')),
2334 [('c', 'changelog', False, _('open changelog')),
2335 ('m', 'manifest', False, _('open manifest')),
2335 ('m', 'manifest', False, _('open manifest')),
2336 ('d', 'dump', False, _('dump index data'))],
2336 ('d', 'dump', False, _('dump index data'))],
2337 _('-c|-m|FILE'))
2337 _('-c|-m|FILE'))
2338 def debugrevlog(ui, repo, file_ = None, **opts):
2338 def debugrevlog(ui, repo, file_ = None, **opts):
2339 """show data and statistics about a revlog"""
2339 """show data and statistics about a revlog"""
2340 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2340 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2341
2341
2342 if opts.get("dump"):
2342 if opts.get("dump"):
2343 numrevs = len(r)
2343 numrevs = len(r)
2344 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2344 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2345 " rawsize totalsize compression heads\n")
2345 " rawsize totalsize compression heads\n")
2346 ts = 0
2346 ts = 0
2347 heads = set()
2347 heads = set()
2348 for rev in xrange(numrevs):
2348 for rev in xrange(numrevs):
2349 dbase = r.deltaparent(rev)
2349 dbase = r.deltaparent(rev)
2350 if dbase == -1:
2350 if dbase == -1:
2351 dbase = rev
2351 dbase = rev
2352 cbase = r.chainbase(rev)
2352 cbase = r.chainbase(rev)
2353 p1, p2 = r.parentrevs(rev)
2353 p1, p2 = r.parentrevs(rev)
2354 rs = r.rawsize(rev)
2354 rs = r.rawsize(rev)
2355 ts = ts + rs
2355 ts = ts + rs
2356 heads -= set(r.parentrevs(rev))
2356 heads -= set(r.parentrevs(rev))
2357 heads.add(rev)
2357 heads.add(rev)
2358 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2358 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2359 (rev, p1, p2, r.start(rev), r.end(rev),
2359 (rev, p1, p2, r.start(rev), r.end(rev),
2360 r.start(dbase), r.start(cbase),
2360 r.start(dbase), r.start(cbase),
2361 r.start(p1), r.start(p2),
2361 r.start(p1), r.start(p2),
2362 rs, ts, ts / r.end(rev), len(heads)))
2362 rs, ts, ts / r.end(rev), len(heads)))
2363 return 0
2363 return 0
2364
2364
2365 v = r.version
2365 v = r.version
2366 format = v & 0xFFFF
2366 format = v & 0xFFFF
2367 flags = []
2367 flags = []
2368 gdelta = False
2368 gdelta = False
2369 if v & revlog.REVLOGNGINLINEDATA:
2369 if v & revlog.REVLOGNGINLINEDATA:
2370 flags.append('inline')
2370 flags.append('inline')
2371 if v & revlog.REVLOGGENERALDELTA:
2371 if v & revlog.REVLOGGENERALDELTA:
2372 gdelta = True
2372 gdelta = True
2373 flags.append('generaldelta')
2373 flags.append('generaldelta')
2374 if not flags:
2374 if not flags:
2375 flags = ['(none)']
2375 flags = ['(none)']
2376
2376
2377 nummerges = 0
2377 nummerges = 0
2378 numfull = 0
2378 numfull = 0
2379 numprev = 0
2379 numprev = 0
2380 nump1 = 0
2380 nump1 = 0
2381 nump2 = 0
2381 nump2 = 0
2382 numother = 0
2382 numother = 0
2383 nump1prev = 0
2383 nump1prev = 0
2384 nump2prev = 0
2384 nump2prev = 0
2385 chainlengths = []
2385 chainlengths = []
2386
2386
2387 datasize = [None, 0, 0L]
2387 datasize = [None, 0, 0L]
2388 fullsize = [None, 0, 0L]
2388 fullsize = [None, 0, 0L]
2389 deltasize = [None, 0, 0L]
2389 deltasize = [None, 0, 0L]
2390
2390
2391 def addsize(size, l):
2391 def addsize(size, l):
2392 if l[0] is None or size < l[0]:
2392 if l[0] is None or size < l[0]:
2393 l[0] = size
2393 l[0] = size
2394 if size > l[1]:
2394 if size > l[1]:
2395 l[1] = size
2395 l[1] = size
2396 l[2] += size
2396 l[2] += size
2397
2397
2398 numrevs = len(r)
2398 numrevs = len(r)
2399 for rev in xrange(numrevs):
2399 for rev in xrange(numrevs):
2400 p1, p2 = r.parentrevs(rev)
2400 p1, p2 = r.parentrevs(rev)
2401 delta = r.deltaparent(rev)
2401 delta = r.deltaparent(rev)
2402 if format > 0:
2402 if format > 0:
2403 addsize(r.rawsize(rev), datasize)
2403 addsize(r.rawsize(rev), datasize)
2404 if p2 != nullrev:
2404 if p2 != nullrev:
2405 nummerges += 1
2405 nummerges += 1
2406 size = r.length(rev)
2406 size = r.length(rev)
2407 if delta == nullrev:
2407 if delta == nullrev:
2408 chainlengths.append(0)
2408 chainlengths.append(0)
2409 numfull += 1
2409 numfull += 1
2410 addsize(size, fullsize)
2410 addsize(size, fullsize)
2411 else:
2411 else:
2412 chainlengths.append(chainlengths[delta] + 1)
2412 chainlengths.append(chainlengths[delta] + 1)
2413 addsize(size, deltasize)
2413 addsize(size, deltasize)
2414 if delta == rev - 1:
2414 if delta == rev - 1:
2415 numprev += 1
2415 numprev += 1
2416 if delta == p1:
2416 if delta == p1:
2417 nump1prev += 1
2417 nump1prev += 1
2418 elif delta == p2:
2418 elif delta == p2:
2419 nump2prev += 1
2419 nump2prev += 1
2420 elif delta == p1:
2420 elif delta == p1:
2421 nump1 += 1
2421 nump1 += 1
2422 elif delta == p2:
2422 elif delta == p2:
2423 nump2 += 1
2423 nump2 += 1
2424 elif delta != nullrev:
2424 elif delta != nullrev:
2425 numother += 1
2425 numother += 1
2426
2426
2427 # Adjust size min value for empty cases
2427 # Adjust size min value for empty cases
2428 for size in (datasize, fullsize, deltasize):
2428 for size in (datasize, fullsize, deltasize):
2429 if size[0] is None:
2429 if size[0] is None:
2430 size[0] = 0
2430 size[0] = 0
2431
2431
2432 numdeltas = numrevs - numfull
2432 numdeltas = numrevs - numfull
2433 numoprev = numprev - nump1prev - nump2prev
2433 numoprev = numprev - nump1prev - nump2prev
2434 totalrawsize = datasize[2]
2434 totalrawsize = datasize[2]
2435 datasize[2] /= numrevs
2435 datasize[2] /= numrevs
2436 fulltotal = fullsize[2]
2436 fulltotal = fullsize[2]
2437 fullsize[2] /= numfull
2437 fullsize[2] /= numfull
2438 deltatotal = deltasize[2]
2438 deltatotal = deltasize[2]
2439 if numrevs - numfull > 0:
2439 if numrevs - numfull > 0:
2440 deltasize[2] /= numrevs - numfull
2440 deltasize[2] /= numrevs - numfull
2441 totalsize = fulltotal + deltatotal
2441 totalsize = fulltotal + deltatotal
2442 avgchainlen = sum(chainlengths) / numrevs
2442 avgchainlen = sum(chainlengths) / numrevs
2443 compratio = totalrawsize / totalsize
2443 compratio = totalrawsize / totalsize
2444
2444
2445 basedfmtstr = '%%%dd\n'
2445 basedfmtstr = '%%%dd\n'
2446 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2446 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2447
2447
2448 def dfmtstr(max):
2448 def dfmtstr(max):
2449 return basedfmtstr % len(str(max))
2449 return basedfmtstr % len(str(max))
2450 def pcfmtstr(max, padding=0):
2450 def pcfmtstr(max, padding=0):
2451 return basepcfmtstr % (len(str(max)), ' ' * padding)
2451 return basepcfmtstr % (len(str(max)), ' ' * padding)
2452
2452
2453 def pcfmt(value, total):
2453 def pcfmt(value, total):
2454 return (value, 100 * float(value) / total)
2454 return (value, 100 * float(value) / total)
2455
2455
2456 ui.write(('format : %d\n') % format)
2456 ui.write(('format : %d\n') % format)
2457 ui.write(('flags : %s\n') % ', '.join(flags))
2457 ui.write(('flags : %s\n') % ', '.join(flags))
2458
2458
2459 ui.write('\n')
2459 ui.write('\n')
2460 fmt = pcfmtstr(totalsize)
2460 fmt = pcfmtstr(totalsize)
2461 fmt2 = dfmtstr(totalsize)
2461 fmt2 = dfmtstr(totalsize)
2462 ui.write(('revisions : ') + fmt2 % numrevs)
2462 ui.write(('revisions : ') + fmt2 % numrevs)
2463 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2463 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2464 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2464 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2465 ui.write(('revisions : ') + fmt2 % numrevs)
2465 ui.write(('revisions : ') + fmt2 % numrevs)
2466 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2466 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2467 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2467 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2468 ui.write(('revision size : ') + fmt2 % totalsize)
2468 ui.write(('revision size : ') + fmt2 % totalsize)
2469 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2469 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2470 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2470 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2471
2471
2472 ui.write('\n')
2472 ui.write('\n')
2473 fmt = dfmtstr(max(avgchainlen, compratio))
2473 fmt = dfmtstr(max(avgchainlen, compratio))
2474 ui.write(('avg chain length : ') + fmt % avgchainlen)
2474 ui.write(('avg chain length : ') + fmt % avgchainlen)
2475 ui.write(('compression ratio : ') + fmt % compratio)
2475 ui.write(('compression ratio : ') + fmt % compratio)
2476
2476
2477 if format > 0:
2477 if format > 0:
2478 ui.write('\n')
2478 ui.write('\n')
2479 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2479 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2480 % tuple(datasize))
2480 % tuple(datasize))
2481 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2481 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2482 % tuple(fullsize))
2482 % tuple(fullsize))
2483 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2483 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2484 % tuple(deltasize))
2484 % tuple(deltasize))
2485
2485
2486 if numdeltas > 0:
2486 if numdeltas > 0:
2487 ui.write('\n')
2487 ui.write('\n')
2488 fmt = pcfmtstr(numdeltas)
2488 fmt = pcfmtstr(numdeltas)
2489 fmt2 = pcfmtstr(numdeltas, 4)
2489 fmt2 = pcfmtstr(numdeltas, 4)
2490 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2490 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2491 if numprev > 0:
2491 if numprev > 0:
2492 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2492 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2493 numprev))
2493 numprev))
2494 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2494 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2495 numprev))
2495 numprev))
2496 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2496 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2497 numprev))
2497 numprev))
2498 if gdelta:
2498 if gdelta:
2499 ui.write(('deltas against p1 : ')
2499 ui.write(('deltas against p1 : ')
2500 + fmt % pcfmt(nump1, numdeltas))
2500 + fmt % pcfmt(nump1, numdeltas))
2501 ui.write(('deltas against p2 : ')
2501 ui.write(('deltas against p2 : ')
2502 + fmt % pcfmt(nump2, numdeltas))
2502 + fmt % pcfmt(nump2, numdeltas))
2503 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2503 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2504 numdeltas))
2504 numdeltas))
2505
2505
2506 @command('debugrevspec', [], ('REVSPEC'))
2506 @command('debugrevspec', [], ('REVSPEC'))
2507 def debugrevspec(ui, repo, expr):
2507 def debugrevspec(ui, repo, expr):
2508 """parse and apply a revision specification
2508 """parse and apply a revision specification
2509
2509
2510 Use --verbose to print the parsed tree before and after aliases
2510 Use --verbose to print the parsed tree before and after aliases
2511 expansion.
2511 expansion.
2512 """
2512 """
2513 if ui.verbose:
2513 if ui.verbose:
2514 tree = revset.parse(expr)[0]
2514 tree = revset.parse(expr)[0]
2515 ui.note(revset.prettyformat(tree), "\n")
2515 ui.note(revset.prettyformat(tree), "\n")
2516 newtree = revset.findaliases(ui, tree)
2516 newtree = revset.findaliases(ui, tree)
2517 if newtree != tree:
2517 if newtree != tree:
2518 ui.note(revset.prettyformat(newtree), "\n")
2518 ui.note(revset.prettyformat(newtree), "\n")
2519 func = revset.match(ui, expr)
2519 func = revset.match(ui, expr)
2520 for c in func(repo, range(len(repo))):
2520 for c in func(repo, range(len(repo))):
2521 ui.write("%s\n" % c)
2521 ui.write("%s\n" % c)
2522
2522
2523 @command('debugsetparents', [], _('REV1 [REV2]'))
2523 @command('debugsetparents', [], _('REV1 [REV2]'))
2524 def debugsetparents(ui, repo, rev1, rev2=None):
2524 def debugsetparents(ui, repo, rev1, rev2=None):
2525 """manually set the parents of the current working directory
2525 """manually set the parents of the current working directory
2526
2526
2527 This is useful for writing repository conversion tools, but should
2527 This is useful for writing repository conversion tools, but should
2528 be used with care.
2528 be used with care.
2529
2529
2530 Returns 0 on success.
2530 Returns 0 on success.
2531 """
2531 """
2532
2532
2533 r1 = scmutil.revsingle(repo, rev1).node()
2533 r1 = scmutil.revsingle(repo, rev1).node()
2534 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2534 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2535
2535
2536 wlock = repo.wlock()
2536 wlock = repo.wlock()
2537 try:
2537 try:
2538 repo.setparents(r1, r2)
2538 repo.setparents(r1, r2)
2539 finally:
2539 finally:
2540 wlock.release()
2540 wlock.release()
2541
2541
2542 @command('debugdirstate|debugstate',
2542 @command('debugdirstate|debugstate',
2543 [('', 'nodates', None, _('do not display the saved mtime')),
2543 [('', 'nodates', None, _('do not display the saved mtime')),
2544 ('', 'datesort', None, _('sort by saved mtime'))],
2544 ('', 'datesort', None, _('sort by saved mtime'))],
2545 _('[OPTION]...'))
2545 _('[OPTION]...'))
2546 def debugstate(ui, repo, nodates=None, datesort=None):
2546 def debugstate(ui, repo, nodates=None, datesort=None):
2547 """show the contents of the current dirstate"""
2547 """show the contents of the current dirstate"""
2548 timestr = ""
2548 timestr = ""
2549 showdate = not nodates
2549 showdate = not nodates
2550 if datesort:
2550 if datesort:
2551 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2551 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2552 else:
2552 else:
2553 keyfunc = None # sort by filename
2553 keyfunc = None # sort by filename
2554 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2554 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2555 if showdate:
2555 if showdate:
2556 if ent[3] == -1:
2556 if ent[3] == -1:
2557 # Pad or slice to locale representation
2557 # Pad or slice to locale representation
2558 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2558 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2559 time.localtime(0)))
2559 time.localtime(0)))
2560 timestr = 'unset'
2560 timestr = 'unset'
2561 timestr = (timestr[:locale_len] +
2561 timestr = (timestr[:locale_len] +
2562 ' ' * (locale_len - len(timestr)))
2562 ' ' * (locale_len - len(timestr)))
2563 else:
2563 else:
2564 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2564 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2565 time.localtime(ent[3]))
2565 time.localtime(ent[3]))
2566 if ent[1] & 020000:
2566 if ent[1] & 020000:
2567 mode = 'lnk'
2567 mode = 'lnk'
2568 else:
2568 else:
2569 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2569 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2570 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2570 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2571 for f in repo.dirstate.copies():
2571 for f in repo.dirstate.copies():
2572 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2572 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2573
2573
2574 @command('debugsub',
2574 @command('debugsub',
2575 [('r', 'rev', '',
2575 [('r', 'rev', '',
2576 _('revision to check'), _('REV'))],
2576 _('revision to check'), _('REV'))],
2577 _('[-r REV] [REV]'))
2577 _('[-r REV] [REV]'))
2578 def debugsub(ui, repo, rev=None):
2578 def debugsub(ui, repo, rev=None):
2579 ctx = scmutil.revsingle(repo, rev, None)
2579 ctx = scmutil.revsingle(repo, rev, None)
2580 for k, v in sorted(ctx.substate.items()):
2580 for k, v in sorted(ctx.substate.items()):
2581 ui.write(('path %s\n') % k)
2581 ui.write(('path %s\n') % k)
2582 ui.write((' source %s\n') % v[0])
2582 ui.write((' source %s\n') % v[0])
2583 ui.write((' revision %s\n') % v[1])
2583 ui.write((' revision %s\n') % v[1])
2584
2584
2585 @command('debugsuccessorssets',
2585 @command('debugsuccessorssets',
2586 [],
2586 [],
2587 _('[REV]'))
2587 _('[REV]'))
2588 def debugsuccessorssets(ui, repo, *revs):
2588 def debugsuccessorssets(ui, repo, *revs):
2589 """show set of successors for revision
2589 """show set of successors for revision
2590
2590
2591 A successors set of changeset A is a consistent group of revisions that
2591 A successors set of changeset A is a consistent group of revisions that
2592 succeed A. It contains non-obsolete changesets only.
2592 succeed A. It contains non-obsolete changesets only.
2593
2593
2594 In most cases a changeset A has a single successors set containing a single
2594 In most cases a changeset A has a single successors set containing a single
2595 successor (changeset A replaced by A').
2595 successor (changeset A replaced by A').
2596
2596
2597 A changeset that is made obsolete with no successors are called "pruned".
2597 A changeset that is made obsolete with no successors are called "pruned".
2598 Such changesets have no successors sets at all.
2598 Such changesets have no successors sets at all.
2599
2599
2600 A changeset that has been "split" will have a successors set containing
2600 A changeset that has been "split" will have a successors set containing
2601 more than one successor.
2601 more than one successor.
2602
2602
2603 A changeset that has been rewritten in multiple different ways is called
2603 A changeset that has been rewritten in multiple different ways is called
2604 "divergent". Such changesets have multiple successor sets (each of which
2604 "divergent". Such changesets have multiple successor sets (each of which
2605 may also be split, i.e. have multiple successors).
2605 may also be split, i.e. have multiple successors).
2606
2606
2607 Results are displayed as follows::
2607 Results are displayed as follows::
2608
2608
2609 <rev1>
2609 <rev1>
2610 <successors-1A>
2610 <successors-1A>
2611 <rev2>
2611 <rev2>
2612 <successors-2A>
2612 <successors-2A>
2613 <successors-2B1> <successors-2B2> <successors-2B3>
2613 <successors-2B1> <successors-2B2> <successors-2B3>
2614
2614
2615 Here rev2 has two possible (i.e. divergent) successors sets. The first
2615 Here rev2 has two possible (i.e. divergent) successors sets. The first
2616 holds one element, whereas the second holds three (i.e. the changeset has
2616 holds one element, whereas the second holds three (i.e. the changeset has
2617 been split).
2617 been split).
2618 """
2618 """
2619 # passed to successorssets caching computation from one call to another
2619 # passed to successorssets caching computation from one call to another
2620 cache = {}
2620 cache = {}
2621 ctx2str = str
2621 ctx2str = str
2622 node2str = short
2622 node2str = short
2623 if ui.debug():
2623 if ui.debug():
2624 def ctx2str(ctx):
2624 def ctx2str(ctx):
2625 return ctx.hex()
2625 return ctx.hex()
2626 node2str = hex
2626 node2str = hex
2627 for rev in scmutil.revrange(repo, revs):
2627 for rev in scmutil.revrange(repo, revs):
2628 ctx = repo[rev]
2628 ctx = repo[rev]
2629 ui.write('%s\n'% ctx2str(ctx))
2629 ui.write('%s\n'% ctx2str(ctx))
2630 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2630 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2631 if succsset:
2631 if succsset:
2632 ui.write(' ')
2632 ui.write(' ')
2633 ui.write(node2str(succsset[0]))
2633 ui.write(node2str(succsset[0]))
2634 for node in succsset[1:]:
2634 for node in succsset[1:]:
2635 ui.write(' ')
2635 ui.write(' ')
2636 ui.write(node2str(node))
2636 ui.write(node2str(node))
2637 ui.write('\n')
2637 ui.write('\n')
2638
2638
2639 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2639 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2640 def debugwalk(ui, repo, *pats, **opts):
2640 def debugwalk(ui, repo, *pats, **opts):
2641 """show how files match on given patterns"""
2641 """show how files match on given patterns"""
2642 m = scmutil.match(repo[None], pats, opts)
2642 m = scmutil.match(repo[None], pats, opts)
2643 items = list(repo.walk(m))
2643 items = list(repo.walk(m))
2644 if not items:
2644 if not items:
2645 return
2645 return
2646 f = lambda fn: fn
2646 f = lambda fn: fn
2647 if ui.configbool('ui', 'slash') and os.sep != '/':
2647 if ui.configbool('ui', 'slash') and os.sep != '/':
2648 f = lambda fn: util.normpath(fn)
2648 f = lambda fn: util.normpath(fn)
2649 fmt = 'f %%-%ds %%-%ds %%s' % (
2649 fmt = 'f %%-%ds %%-%ds %%s' % (
2650 max([len(abs) for abs in items]),
2650 max([len(abs) for abs in items]),
2651 max([len(m.rel(abs)) for abs in items]))
2651 max([len(m.rel(abs)) for abs in items]))
2652 for abs in items:
2652 for abs in items:
2653 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2653 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2654 ui.write("%s\n" % line.rstrip())
2654 ui.write("%s\n" % line.rstrip())
2655
2655
2656 @command('debugwireargs',
2656 @command('debugwireargs',
2657 [('', 'three', '', 'three'),
2657 [('', 'three', '', 'three'),
2658 ('', 'four', '', 'four'),
2658 ('', 'four', '', 'four'),
2659 ('', 'five', '', 'five'),
2659 ('', 'five', '', 'five'),
2660 ] + remoteopts,
2660 ] + remoteopts,
2661 _('REPO [OPTIONS]... [ONE [TWO]]'))
2661 _('REPO [OPTIONS]... [ONE [TWO]]'))
2662 def debugwireargs(ui, repopath, *vals, **opts):
2662 def debugwireargs(ui, repopath, *vals, **opts):
2663 repo = hg.peer(ui, opts, repopath)
2663 repo = hg.peer(ui, opts, repopath)
2664 for opt in remoteopts:
2664 for opt in remoteopts:
2665 del opts[opt[1]]
2665 del opts[opt[1]]
2666 args = {}
2666 args = {}
2667 for k, v in opts.iteritems():
2667 for k, v in opts.iteritems():
2668 if v:
2668 if v:
2669 args[k] = v
2669 args[k] = v
2670 # run twice to check that we don't mess up the stream for the next command
2670 # run twice to check that we don't mess up the stream for the next command
2671 res1 = repo.debugwireargs(*vals, **args)
2671 res1 = repo.debugwireargs(*vals, **args)
2672 res2 = repo.debugwireargs(*vals, **args)
2672 res2 = repo.debugwireargs(*vals, **args)
2673 ui.write("%s\n" % res1)
2673 ui.write("%s\n" % res1)
2674 if res1 != res2:
2674 if res1 != res2:
2675 ui.warn("%s\n" % res2)
2675 ui.warn("%s\n" % res2)
2676
2676
2677 @command('^diff',
2677 @command('^diff',
2678 [('r', 'rev', [], _('revision'), _('REV')),
2678 [('r', 'rev', [], _('revision'), _('REV')),
2679 ('c', 'change', '', _('change made by revision'), _('REV'))
2679 ('c', 'change', '', _('change made by revision'), _('REV'))
2680 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2680 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2681 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2681 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2682 def diff(ui, repo, *pats, **opts):
2682 def diff(ui, repo, *pats, **opts):
2683 """diff repository (or selected files)
2683 """diff repository (or selected files)
2684
2684
2685 Show differences between revisions for the specified files.
2685 Show differences between revisions for the specified files.
2686
2686
2687 Differences between files are shown using the unified diff format.
2687 Differences between files are shown using the unified diff format.
2688
2688
2689 .. note::
2689 .. note::
2690 diff may generate unexpected results for merges, as it will
2690 diff may generate unexpected results for merges, as it will
2691 default to comparing against the working directory's first
2691 default to comparing against the working directory's first
2692 parent changeset if no revisions are specified.
2692 parent changeset if no revisions are specified.
2693
2693
2694 When two revision arguments are given, then changes are shown
2694 When two revision arguments are given, then changes are shown
2695 between those revisions. If only one revision is specified then
2695 between those revisions. If only one revision is specified then
2696 that revision is compared to the working directory, and, when no
2696 that revision is compared to the working directory, and, when no
2697 revisions are specified, the working directory files are compared
2697 revisions are specified, the working directory files are compared
2698 to its parent.
2698 to its parent.
2699
2699
2700 Alternatively you can specify -c/--change with a revision to see
2700 Alternatively you can specify -c/--change with a revision to see
2701 the changes in that changeset relative to its first parent.
2701 the changes in that changeset relative to its first parent.
2702
2702
2703 Without the -a/--text option, diff will avoid generating diffs of
2703 Without the -a/--text option, diff will avoid generating diffs of
2704 files it detects as binary. With -a, diff will generate a diff
2704 files it detects as binary. With -a, diff will generate a diff
2705 anyway, probably with undesirable results.
2705 anyway, probably with undesirable results.
2706
2706
2707 Use the -g/--git option to generate diffs in the git extended diff
2707 Use the -g/--git option to generate diffs in the git extended diff
2708 format. For more information, read :hg:`help diffs`.
2708 format. For more information, read :hg:`help diffs`.
2709
2709
2710 .. container:: verbose
2710 .. container:: verbose
2711
2711
2712 Examples:
2712 Examples:
2713
2713
2714 - compare a file in the current working directory to its parent::
2714 - compare a file in the current working directory to its parent::
2715
2715
2716 hg diff foo.c
2716 hg diff foo.c
2717
2717
2718 - compare two historical versions of a directory, with rename info::
2718 - compare two historical versions of a directory, with rename info::
2719
2719
2720 hg diff --git -r 1.0:1.2 lib/
2720 hg diff --git -r 1.0:1.2 lib/
2721
2721
2722 - get change stats relative to the last change on some date::
2722 - get change stats relative to the last change on some date::
2723
2723
2724 hg diff --stat -r "date('may 2')"
2724 hg diff --stat -r "date('may 2')"
2725
2725
2726 - diff all newly-added files that contain a keyword::
2726 - diff all newly-added files that contain a keyword::
2727
2727
2728 hg diff "set:added() and grep(GNU)"
2728 hg diff "set:added() and grep(GNU)"
2729
2729
2730 - compare a revision and its parents::
2730 - compare a revision and its parents::
2731
2731
2732 hg diff -c 9353 # compare against first parent
2732 hg diff -c 9353 # compare against first parent
2733 hg diff -r 9353^:9353 # same using revset syntax
2733 hg diff -r 9353^:9353 # same using revset syntax
2734 hg diff -r 9353^2:9353 # compare against the second parent
2734 hg diff -r 9353^2:9353 # compare against the second parent
2735
2735
2736 Returns 0 on success.
2736 Returns 0 on success.
2737 """
2737 """
2738
2738
2739 revs = opts.get('rev')
2739 revs = opts.get('rev')
2740 change = opts.get('change')
2740 change = opts.get('change')
2741 stat = opts.get('stat')
2741 stat = opts.get('stat')
2742 reverse = opts.get('reverse')
2742 reverse = opts.get('reverse')
2743
2743
2744 if revs and change:
2744 if revs and change:
2745 msg = _('cannot specify --rev and --change at the same time')
2745 msg = _('cannot specify --rev and --change at the same time')
2746 raise util.Abort(msg)
2746 raise util.Abort(msg)
2747 elif change:
2747 elif change:
2748 node2 = scmutil.revsingle(repo, change, None).node()
2748 node2 = scmutil.revsingle(repo, change, None).node()
2749 node1 = repo[node2].p1().node()
2749 node1 = repo[node2].p1().node()
2750 else:
2750 else:
2751 node1, node2 = scmutil.revpair(repo, revs)
2751 node1, node2 = scmutil.revpair(repo, revs)
2752
2752
2753 if reverse:
2753 if reverse:
2754 node1, node2 = node2, node1
2754 node1, node2 = node2, node1
2755
2755
2756 diffopts = patch.diffopts(ui, opts)
2756 diffopts = patch.diffopts(ui, opts)
2757 m = scmutil.match(repo[node2], pats, opts)
2757 m = scmutil.match(repo[node2], pats, opts)
2758 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2758 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2759 listsubrepos=opts.get('subrepos'))
2759 listsubrepos=opts.get('subrepos'))
2760
2760
2761 @command('^export',
2761 @command('^export',
2762 [('o', 'output', '',
2762 [('o', 'output', '',
2763 _('print output to file with formatted name'), _('FORMAT')),
2763 _('print output to file with formatted name'), _('FORMAT')),
2764 ('', 'switch-parent', None, _('diff against the second parent')),
2764 ('', 'switch-parent', None, _('diff against the second parent')),
2765 ('r', 'rev', [], _('revisions to export'), _('REV')),
2765 ('r', 'rev', [], _('revisions to export'), _('REV')),
2766 ] + diffopts,
2766 ] + diffopts,
2767 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2767 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2768 def export(ui, repo, *changesets, **opts):
2768 def export(ui, repo, *changesets, **opts):
2769 """dump the header and diffs for one or more changesets
2769 """dump the header and diffs for one or more changesets
2770
2770
2771 Print the changeset header and diffs for one or more revisions.
2771 Print the changeset header and diffs for one or more revisions.
2772 If no revision is given, the parent of the working directory is used.
2772 If no revision is given, the parent of the working directory is used.
2773
2773
2774 The information shown in the changeset header is: author, date,
2774 The information shown in the changeset header is: author, date,
2775 branch name (if non-default), changeset hash, parent(s) and commit
2775 branch name (if non-default), changeset hash, parent(s) and commit
2776 comment.
2776 comment.
2777
2777
2778 .. note::
2778 .. note::
2779 export may generate unexpected diff output for merge
2779 export may generate unexpected diff output for merge
2780 changesets, as it will compare the merge changeset against its
2780 changesets, as it will compare the merge changeset against its
2781 first parent only.
2781 first parent only.
2782
2782
2783 Output may be to a file, in which case the name of the file is
2783 Output may be to a file, in which case the name of the file is
2784 given using a format string. The formatting rules are as follows:
2784 given using a format string. The formatting rules are as follows:
2785
2785
2786 :``%%``: literal "%" character
2786 :``%%``: literal "%" character
2787 :``%H``: changeset hash (40 hexadecimal digits)
2787 :``%H``: changeset hash (40 hexadecimal digits)
2788 :``%N``: number of patches being generated
2788 :``%N``: number of patches being generated
2789 :``%R``: changeset revision number
2789 :``%R``: changeset revision number
2790 :``%b``: basename of the exporting repository
2790 :``%b``: basename of the exporting repository
2791 :``%h``: short-form changeset hash (12 hexadecimal digits)
2791 :``%h``: short-form changeset hash (12 hexadecimal digits)
2792 :``%m``: first line of the commit message (only alphanumeric characters)
2792 :``%m``: first line of the commit message (only alphanumeric characters)
2793 :``%n``: zero-padded sequence number, starting at 1
2793 :``%n``: zero-padded sequence number, starting at 1
2794 :``%r``: zero-padded changeset revision number
2794 :``%r``: zero-padded changeset revision number
2795
2795
2796 Without the -a/--text option, export will avoid generating diffs
2796 Without the -a/--text option, export will avoid generating diffs
2797 of files it detects as binary. With -a, export will generate a
2797 of files it detects as binary. With -a, export will generate a
2798 diff anyway, probably with undesirable results.
2798 diff anyway, probably with undesirable results.
2799
2799
2800 Use the -g/--git option to generate diffs in the git extended diff
2800 Use the -g/--git option to generate diffs in the git extended diff
2801 format. See :hg:`help diffs` for more information.
2801 format. See :hg:`help diffs` for more information.
2802
2802
2803 With the --switch-parent option, the diff will be against the
2803 With the --switch-parent option, the diff will be against the
2804 second parent. It can be useful to review a merge.
2804 second parent. It can be useful to review a merge.
2805
2805
2806 .. container:: verbose
2806 .. container:: verbose
2807
2807
2808 Examples:
2808 Examples:
2809
2809
2810 - use export and import to transplant a bugfix to the current
2810 - use export and import to transplant a bugfix to the current
2811 branch::
2811 branch::
2812
2812
2813 hg export -r 9353 | hg import -
2813 hg export -r 9353 | hg import -
2814
2814
2815 - export all the changesets between two revisions to a file with
2815 - export all the changesets between two revisions to a file with
2816 rename information::
2816 rename information::
2817
2817
2818 hg export --git -r 123:150 > changes.txt
2818 hg export --git -r 123:150 > changes.txt
2819
2819
2820 - split outgoing changes into a series of patches with
2820 - split outgoing changes into a series of patches with
2821 descriptive names::
2821 descriptive names::
2822
2822
2823 hg export -r "outgoing()" -o "%n-%m.patch"
2823 hg export -r "outgoing()" -o "%n-%m.patch"
2824
2824
2825 Returns 0 on success.
2825 Returns 0 on success.
2826 """
2826 """
2827 changesets += tuple(opts.get('rev', []))
2827 changesets += tuple(opts.get('rev', []))
2828 if not changesets:
2828 if not changesets:
2829 changesets = ['.']
2829 changesets = ['.']
2830 revs = scmutil.revrange(repo, changesets)
2830 revs = scmutil.revrange(repo, changesets)
2831 if not revs:
2831 if not revs:
2832 raise util.Abort(_("export requires at least one changeset"))
2832 raise util.Abort(_("export requires at least one changeset"))
2833 if len(revs) > 1:
2833 if len(revs) > 1:
2834 ui.note(_('exporting patches:\n'))
2834 ui.note(_('exporting patches:\n'))
2835 else:
2835 else:
2836 ui.note(_('exporting patch:\n'))
2836 ui.note(_('exporting patch:\n'))
2837 cmdutil.export(repo, revs, template=opts.get('output'),
2837 cmdutil.export(repo, revs, template=opts.get('output'),
2838 switch_parent=opts.get('switch_parent'),
2838 switch_parent=opts.get('switch_parent'),
2839 opts=patch.diffopts(ui, opts))
2839 opts=patch.diffopts(ui, opts))
2840
2840
2841 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2841 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2842 def forget(ui, repo, *pats, **opts):
2842 def forget(ui, repo, *pats, **opts):
2843 """forget the specified files on the next commit
2843 """forget the specified files on the next commit
2844
2844
2845 Mark the specified files so they will no longer be tracked
2845 Mark the specified files so they will no longer be tracked
2846 after the next commit.
2846 after the next commit.
2847
2847
2848 This only removes files from the current branch, not from the
2848 This only removes files from the current branch, not from the
2849 entire project history, and it does not delete them from the
2849 entire project history, and it does not delete them from the
2850 working directory.
2850 working directory.
2851
2851
2852 To undo a forget before the next commit, see :hg:`add`.
2852 To undo a forget before the next commit, see :hg:`add`.
2853
2853
2854 .. container:: verbose
2854 .. container:: verbose
2855
2855
2856 Examples:
2856 Examples:
2857
2857
2858 - forget newly-added binary files::
2858 - forget newly-added binary files::
2859
2859
2860 hg forget "set:added() and binary()"
2860 hg forget "set:added() and binary()"
2861
2861
2862 - forget files that would be excluded by .hgignore::
2862 - forget files that would be excluded by .hgignore::
2863
2863
2864 hg forget "set:hgignore()"
2864 hg forget "set:hgignore()"
2865
2865
2866 Returns 0 on success.
2866 Returns 0 on success.
2867 """
2867 """
2868
2868
2869 if not pats:
2869 if not pats:
2870 raise util.Abort(_('no files specified'))
2870 raise util.Abort(_('no files specified'))
2871
2871
2872 m = scmutil.match(repo[None], pats, opts)
2872 m = scmutil.match(repo[None], pats, opts)
2873 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2873 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2874 return rejected and 1 or 0
2874 return rejected and 1 or 0
2875
2875
2876 @command(
2876 @command(
2877 'graft',
2877 'graft',
2878 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2878 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2879 ('c', 'continue', False, _('resume interrupted graft')),
2879 ('c', 'continue', False, _('resume interrupted graft')),
2880 ('e', 'edit', False, _('invoke editor on commit messages')),
2880 ('e', 'edit', False, _('invoke editor on commit messages')),
2881 ('', 'log', None, _('append graft info to log message')),
2881 ('', 'log', None, _('append graft info to log message')),
2882 ('D', 'currentdate', False,
2882 ('D', 'currentdate', False,
2883 _('record the current date as commit date')),
2883 _('record the current date as commit date')),
2884 ('U', 'currentuser', False,
2884 ('U', 'currentuser', False,
2885 _('record the current user as committer'), _('DATE'))]
2885 _('record the current user as committer'), _('DATE'))]
2886 + commitopts2 + mergetoolopts + dryrunopts,
2886 + commitopts2 + mergetoolopts + dryrunopts,
2887 _('[OPTION]... [-r] REV...'))
2887 _('[OPTION]... [-r] REV...'))
2888 def graft(ui, repo, *revs, **opts):
2888 def graft(ui, repo, *revs, **opts):
2889 '''copy changes from other branches onto the current branch
2889 '''copy changes from other branches onto the current branch
2890
2890
2891 This command uses Mercurial's merge logic to copy individual
2891 This command uses Mercurial's merge logic to copy individual
2892 changes from other branches without merging branches in the
2892 changes from other branches without merging branches in the
2893 history graph. This is sometimes known as 'backporting' or
2893 history graph. This is sometimes known as 'backporting' or
2894 'cherry-picking'. By default, graft will copy user, date, and
2894 'cherry-picking'. By default, graft will copy user, date, and
2895 description from the source changesets.
2895 description from the source changesets.
2896
2896
2897 Changesets that are ancestors of the current revision, that have
2897 Changesets that are ancestors of the current revision, that have
2898 already been grafted, or that are merges will be skipped.
2898 already been grafted, or that are merges will be skipped.
2899
2899
2900 If --log is specified, log messages will have a comment appended
2900 If --log is specified, log messages will have a comment appended
2901 of the form::
2901 of the form::
2902
2902
2903 (grafted from CHANGESETHASH)
2903 (grafted from CHANGESETHASH)
2904
2904
2905 If a graft merge results in conflicts, the graft process is
2905 If a graft merge results in conflicts, the graft process is
2906 interrupted so that the current merge can be manually resolved.
2906 interrupted so that the current merge can be manually resolved.
2907 Once all conflicts are addressed, the graft process can be
2907 Once all conflicts are addressed, the graft process can be
2908 continued with the -c/--continue option.
2908 continued with the -c/--continue option.
2909
2909
2910 .. note::
2910 .. note::
2911 The -c/--continue option does not reapply earlier options.
2911 The -c/--continue option does not reapply earlier options.
2912
2912
2913 .. container:: verbose
2913 .. container:: verbose
2914
2914
2915 Examples:
2915 Examples:
2916
2916
2917 - copy a single change to the stable branch and edit its description::
2917 - copy a single change to the stable branch and edit its description::
2918
2918
2919 hg update stable
2919 hg update stable
2920 hg graft --edit 9393
2920 hg graft --edit 9393
2921
2921
2922 - graft a range of changesets with one exception, updating dates::
2922 - graft a range of changesets with one exception, updating dates::
2923
2923
2924 hg graft -D "2085::2093 and not 2091"
2924 hg graft -D "2085::2093 and not 2091"
2925
2925
2926 - continue a graft after resolving conflicts::
2926 - continue a graft after resolving conflicts::
2927
2927
2928 hg graft -c
2928 hg graft -c
2929
2929
2930 - show the source of a grafted changeset::
2930 - show the source of a grafted changeset::
2931
2931
2932 hg log --debug -r tip
2932 hg log --debug -r .
2933
2933
2934 Returns 0 on successful completion.
2934 Returns 0 on successful completion.
2935 '''
2935 '''
2936
2936
2937 revs = list(revs)
2937 revs = list(revs)
2938 revs.extend(opts['rev'])
2938 revs.extend(opts['rev'])
2939
2939
2940 if not opts.get('user') and opts.get('currentuser'):
2940 if not opts.get('user') and opts.get('currentuser'):
2941 opts['user'] = ui.username()
2941 opts['user'] = ui.username()
2942 if not opts.get('date') and opts.get('currentdate'):
2942 if not opts.get('date') and opts.get('currentdate'):
2943 opts['date'] = "%d %d" % util.makedate()
2943 opts['date'] = "%d %d" % util.makedate()
2944
2944
2945 editor = None
2945 editor = None
2946 if opts.get('edit'):
2946 if opts.get('edit'):
2947 editor = cmdutil.commitforceeditor
2947 editor = cmdutil.commitforceeditor
2948
2948
2949 cont = False
2949 cont = False
2950 if opts['continue']:
2950 if opts['continue']:
2951 cont = True
2951 cont = True
2952 if revs:
2952 if revs:
2953 raise util.Abort(_("can't specify --continue and revisions"))
2953 raise util.Abort(_("can't specify --continue and revisions"))
2954 # read in unfinished revisions
2954 # read in unfinished revisions
2955 try:
2955 try:
2956 nodes = repo.opener.read('graftstate').splitlines()
2956 nodes = repo.opener.read('graftstate').splitlines()
2957 revs = [repo[node].rev() for node in nodes]
2957 revs = [repo[node].rev() for node in nodes]
2958 except IOError, inst:
2958 except IOError, inst:
2959 if inst.errno != errno.ENOENT:
2959 if inst.errno != errno.ENOENT:
2960 raise
2960 raise
2961 raise util.Abort(_("no graft state found, can't continue"))
2961 raise util.Abort(_("no graft state found, can't continue"))
2962 else:
2962 else:
2963 cmdutil.bailifchanged(repo)
2963 cmdutil.bailifchanged(repo)
2964 if not revs:
2964 if not revs:
2965 raise util.Abort(_('no revisions specified'))
2965 raise util.Abort(_('no revisions specified'))
2966 revs = scmutil.revrange(repo, revs)
2966 revs = scmutil.revrange(repo, revs)
2967
2967
2968 # check for merges
2968 # check for merges
2969 for rev in repo.revs('%ld and merge()', revs):
2969 for rev in repo.revs('%ld and merge()', revs):
2970 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2970 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2971 revs.remove(rev)
2971 revs.remove(rev)
2972 if not revs:
2972 if not revs:
2973 return -1
2973 return -1
2974
2974
2975 # check for ancestors of dest branch
2975 # check for ancestors of dest branch
2976 crev = repo['.'].rev()
2976 crev = repo['.'].rev()
2977 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2977 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2978 # don't mutate while iterating, create a copy
2978 # don't mutate while iterating, create a copy
2979 for rev in list(revs):
2979 for rev in list(revs):
2980 if rev in ancestors:
2980 if rev in ancestors:
2981 ui.warn(_('skipping ancestor revision %s\n') % rev)
2981 ui.warn(_('skipping ancestor revision %s\n') % rev)
2982 revs.remove(rev)
2982 revs.remove(rev)
2983 if not revs:
2983 if not revs:
2984 return -1
2984 return -1
2985
2985
2986 # analyze revs for earlier grafts
2986 # analyze revs for earlier grafts
2987 ids = {}
2987 ids = {}
2988 for ctx in repo.set("%ld", revs):
2988 for ctx in repo.set("%ld", revs):
2989 ids[ctx.hex()] = ctx.rev()
2989 ids[ctx.hex()] = ctx.rev()
2990 n = ctx.extra().get('source')
2990 n = ctx.extra().get('source')
2991 if n:
2991 if n:
2992 ids[n] = ctx.rev()
2992 ids[n] = ctx.rev()
2993
2993
2994 # check ancestors for earlier grafts
2994 # check ancestors for earlier grafts
2995 ui.debug('scanning for duplicate grafts\n')
2995 ui.debug('scanning for duplicate grafts\n')
2996
2996
2997 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2997 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2998 ctx = repo[rev]
2998 ctx = repo[rev]
2999 n = ctx.extra().get('source')
2999 n = ctx.extra().get('source')
3000 if n in ids:
3000 if n in ids:
3001 r = repo[n].rev()
3001 r = repo[n].rev()
3002 if r in revs:
3002 if r in revs:
3003 ui.warn(_('skipping already grafted revision %s\n') % r)
3003 ui.warn(_('skipping already grafted revision %s\n') % r)
3004 revs.remove(r)
3004 revs.remove(r)
3005 elif ids[n] in revs:
3005 elif ids[n] in revs:
3006 ui.warn(_('skipping already grafted revision %s '
3006 ui.warn(_('skipping already grafted revision %s '
3007 '(same origin %d)\n') % (ids[n], r))
3007 '(same origin %d)\n') % (ids[n], r))
3008 revs.remove(ids[n])
3008 revs.remove(ids[n])
3009 elif ctx.hex() in ids:
3009 elif ctx.hex() in ids:
3010 r = ids[ctx.hex()]
3010 r = ids[ctx.hex()]
3011 ui.warn(_('skipping already grafted revision %s '
3011 ui.warn(_('skipping already grafted revision %s '
3012 '(was grafted from %d)\n') % (r, rev))
3012 '(was grafted from %d)\n') % (r, rev))
3013 revs.remove(r)
3013 revs.remove(r)
3014 if not revs:
3014 if not revs:
3015 return -1
3015 return -1
3016
3016
3017 wlock = repo.wlock()
3017 wlock = repo.wlock()
3018 try:
3018 try:
3019 current = repo['.']
3019 current = repo['.']
3020 for pos, ctx in enumerate(repo.set("%ld", revs)):
3020 for pos, ctx in enumerate(repo.set("%ld", revs)):
3021
3021
3022 ui.status(_('grafting revision %s\n') % ctx.rev())
3022 ui.status(_('grafting revision %s\n') % ctx.rev())
3023 if opts.get('dry_run'):
3023 if opts.get('dry_run'):
3024 continue
3024 continue
3025
3025
3026 source = ctx.extra().get('source')
3026 source = ctx.extra().get('source')
3027 if not source:
3027 if not source:
3028 source = ctx.hex()
3028 source = ctx.hex()
3029 extra = {'source': source}
3029 extra = {'source': source}
3030 user = ctx.user()
3030 user = ctx.user()
3031 if opts.get('user'):
3031 if opts.get('user'):
3032 user = opts['user']
3032 user = opts['user']
3033 date = ctx.date()
3033 date = ctx.date()
3034 if opts.get('date'):
3034 if opts.get('date'):
3035 date = opts['date']
3035 date = opts['date']
3036 message = ctx.description()
3036 message = ctx.description()
3037 if opts.get('log'):
3037 if opts.get('log'):
3038 message += '\n(grafted from %s)' % ctx.hex()
3038 message += '\n(grafted from %s)' % ctx.hex()
3039
3039
3040 # we don't merge the first commit when continuing
3040 # we don't merge the first commit when continuing
3041 if not cont:
3041 if not cont:
3042 # perform the graft merge with p1(rev) as 'ancestor'
3042 # perform the graft merge with p1(rev) as 'ancestor'
3043 try:
3043 try:
3044 # ui.forcemerge is an internal variable, do not document
3044 # ui.forcemerge is an internal variable, do not document
3045 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3045 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3046 stats = mergemod.update(repo, ctx.node(), True, True, False,
3046 stats = mergemod.update(repo, ctx.node(), True, True, False,
3047 ctx.p1().node())
3047 ctx.p1().node())
3048 finally:
3048 finally:
3049 repo.ui.setconfig('ui', 'forcemerge', '')
3049 repo.ui.setconfig('ui', 'forcemerge', '')
3050 # report any conflicts
3050 # report any conflicts
3051 if stats and stats[3] > 0:
3051 if stats and stats[3] > 0:
3052 # write out state for --continue
3052 # write out state for --continue
3053 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3053 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3054 repo.opener.write('graftstate', ''.join(nodelines))
3054 repo.opener.write('graftstate', ''.join(nodelines))
3055 raise util.Abort(
3055 raise util.Abort(
3056 _("unresolved conflicts, can't continue"),
3056 _("unresolved conflicts, can't continue"),
3057 hint=_('use hg resolve and hg graft --continue'))
3057 hint=_('use hg resolve and hg graft --continue'))
3058 else:
3058 else:
3059 cont = False
3059 cont = False
3060
3060
3061 # drop the second merge parent
3061 # drop the second merge parent
3062 repo.setparents(current.node(), nullid)
3062 repo.setparents(current.node(), nullid)
3063 repo.dirstate.write()
3063 repo.dirstate.write()
3064 # fix up dirstate for copies and renames
3064 # fix up dirstate for copies and renames
3065 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3065 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3066
3066
3067 # commit
3067 # commit
3068 node = repo.commit(text=message, user=user,
3068 node = repo.commit(text=message, user=user,
3069 date=date, extra=extra, editor=editor)
3069 date=date, extra=extra, editor=editor)
3070 if node is None:
3070 if node is None:
3071 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3071 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3072 else:
3072 else:
3073 current = repo[node]
3073 current = repo[node]
3074 finally:
3074 finally:
3075 wlock.release()
3075 wlock.release()
3076
3076
3077 # remove state when we complete successfully
3077 # remove state when we complete successfully
3078 if not opts.get('dry_run'):
3078 if not opts.get('dry_run'):
3079 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3079 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3080
3080
3081 return 0
3081 return 0
3082
3082
3083 @command('grep',
3083 @command('grep',
3084 [('0', 'print0', None, _('end fields with NUL')),
3084 [('0', 'print0', None, _('end fields with NUL')),
3085 ('', 'all', None, _('print all revisions that match')),
3085 ('', 'all', None, _('print all revisions that match')),
3086 ('a', 'text', None, _('treat all files as text')),
3086 ('a', 'text', None, _('treat all files as text')),
3087 ('f', 'follow', None,
3087 ('f', 'follow', None,
3088 _('follow changeset history,'
3088 _('follow changeset history,'
3089 ' or file history across copies and renames')),
3089 ' or file history across copies and renames')),
3090 ('i', 'ignore-case', None, _('ignore case when matching')),
3090 ('i', 'ignore-case', None, _('ignore case when matching')),
3091 ('l', 'files-with-matches', None,
3091 ('l', 'files-with-matches', None,
3092 _('print only filenames and revisions that match')),
3092 _('print only filenames and revisions that match')),
3093 ('n', 'line-number', None, _('print matching line numbers')),
3093 ('n', 'line-number', None, _('print matching line numbers')),
3094 ('r', 'rev', [],
3094 ('r', 'rev', [],
3095 _('only search files changed within revision range'), _('REV')),
3095 _('only search files changed within revision range'), _('REV')),
3096 ('u', 'user', None, _('list the author (long with -v)')),
3096 ('u', 'user', None, _('list the author (long with -v)')),
3097 ('d', 'date', None, _('list the date (short with -q)')),
3097 ('d', 'date', None, _('list the date (short with -q)')),
3098 ] + walkopts,
3098 ] + walkopts,
3099 _('[OPTION]... PATTERN [FILE]...'))
3099 _('[OPTION]... PATTERN [FILE]...'))
3100 def grep(ui, repo, pattern, *pats, **opts):
3100 def grep(ui, repo, pattern, *pats, **opts):
3101 """search for a pattern in specified files and revisions
3101 """search for a pattern in specified files and revisions
3102
3102
3103 Search revisions of files for a regular expression.
3103 Search revisions of files for a regular expression.
3104
3104
3105 This command behaves differently than Unix grep. It only accepts
3105 This command behaves differently than Unix grep. It only accepts
3106 Python/Perl regexps. It searches repository history, not the
3106 Python/Perl regexps. It searches repository history, not the
3107 working directory. It always prints the revision number in which a
3107 working directory. It always prints the revision number in which a
3108 match appears.
3108 match appears.
3109
3109
3110 By default, grep only prints output for the first revision of a
3110 By default, grep only prints output for the first revision of a
3111 file in which it finds a match. To get it to print every revision
3111 file in which it finds a match. To get it to print every revision
3112 that contains a change in match status ("-" for a match that
3112 that contains a change in match status ("-" for a match that
3113 becomes a non-match, or "+" for a non-match that becomes a match),
3113 becomes a non-match, or "+" for a non-match that becomes a match),
3114 use the --all flag.
3114 use the --all flag.
3115
3115
3116 Returns 0 if a match is found, 1 otherwise.
3116 Returns 0 if a match is found, 1 otherwise.
3117 """
3117 """
3118 reflags = re.M
3118 reflags = re.M
3119 if opts.get('ignore_case'):
3119 if opts.get('ignore_case'):
3120 reflags |= re.I
3120 reflags |= re.I
3121 try:
3121 try:
3122 regexp = util.compilere(pattern, reflags)
3122 regexp = util.compilere(pattern, reflags)
3123 except re.error, inst:
3123 except re.error, inst:
3124 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3124 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3125 return 1
3125 return 1
3126 sep, eol = ':', '\n'
3126 sep, eol = ':', '\n'
3127 if opts.get('print0'):
3127 if opts.get('print0'):
3128 sep = eol = '\0'
3128 sep = eol = '\0'
3129
3129
3130 getfile = util.lrucachefunc(repo.file)
3130 getfile = util.lrucachefunc(repo.file)
3131
3131
3132 def matchlines(body):
3132 def matchlines(body):
3133 begin = 0
3133 begin = 0
3134 linenum = 0
3134 linenum = 0
3135 while begin < len(body):
3135 while begin < len(body):
3136 match = regexp.search(body, begin)
3136 match = regexp.search(body, begin)
3137 if not match:
3137 if not match:
3138 break
3138 break
3139 mstart, mend = match.span()
3139 mstart, mend = match.span()
3140 linenum += body.count('\n', begin, mstart) + 1
3140 linenum += body.count('\n', begin, mstart) + 1
3141 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3141 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3142 begin = body.find('\n', mend) + 1 or len(body) + 1
3142 begin = body.find('\n', mend) + 1 or len(body) + 1
3143 lend = begin - 1
3143 lend = begin - 1
3144 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3144 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3145
3145
3146 class linestate(object):
3146 class linestate(object):
3147 def __init__(self, line, linenum, colstart, colend):
3147 def __init__(self, line, linenum, colstart, colend):
3148 self.line = line
3148 self.line = line
3149 self.linenum = linenum
3149 self.linenum = linenum
3150 self.colstart = colstart
3150 self.colstart = colstart
3151 self.colend = colend
3151 self.colend = colend
3152
3152
3153 def __hash__(self):
3153 def __hash__(self):
3154 return hash((self.linenum, self.line))
3154 return hash((self.linenum, self.line))
3155
3155
3156 def __eq__(self, other):
3156 def __eq__(self, other):
3157 return self.line == other.line
3157 return self.line == other.line
3158
3158
3159 matches = {}
3159 matches = {}
3160 copies = {}
3160 copies = {}
3161 def grepbody(fn, rev, body):
3161 def grepbody(fn, rev, body):
3162 matches[rev].setdefault(fn, [])
3162 matches[rev].setdefault(fn, [])
3163 m = matches[rev][fn]
3163 m = matches[rev][fn]
3164 for lnum, cstart, cend, line in matchlines(body):
3164 for lnum, cstart, cend, line in matchlines(body):
3165 s = linestate(line, lnum, cstart, cend)
3165 s = linestate(line, lnum, cstart, cend)
3166 m.append(s)
3166 m.append(s)
3167
3167
3168 def difflinestates(a, b):
3168 def difflinestates(a, b):
3169 sm = difflib.SequenceMatcher(None, a, b)
3169 sm = difflib.SequenceMatcher(None, a, b)
3170 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3170 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3171 if tag == 'insert':
3171 if tag == 'insert':
3172 for i in xrange(blo, bhi):
3172 for i in xrange(blo, bhi):
3173 yield ('+', b[i])
3173 yield ('+', b[i])
3174 elif tag == 'delete':
3174 elif tag == 'delete':
3175 for i in xrange(alo, ahi):
3175 for i in xrange(alo, ahi):
3176 yield ('-', a[i])
3176 yield ('-', a[i])
3177 elif tag == 'replace':
3177 elif tag == 'replace':
3178 for i in xrange(alo, ahi):
3178 for i in xrange(alo, ahi):
3179 yield ('-', a[i])
3179 yield ('-', a[i])
3180 for i in xrange(blo, bhi):
3180 for i in xrange(blo, bhi):
3181 yield ('+', b[i])
3181 yield ('+', b[i])
3182
3182
3183 def display(fn, ctx, pstates, states):
3183 def display(fn, ctx, pstates, states):
3184 rev = ctx.rev()
3184 rev = ctx.rev()
3185 datefunc = ui.quiet and util.shortdate or util.datestr
3185 datefunc = ui.quiet and util.shortdate or util.datestr
3186 found = False
3186 found = False
3187 filerevmatches = {}
3187 filerevmatches = {}
3188 def binary():
3188 def binary():
3189 flog = getfile(fn)
3189 flog = getfile(fn)
3190 return util.binary(flog.read(ctx.filenode(fn)))
3190 return util.binary(flog.read(ctx.filenode(fn)))
3191
3191
3192 if opts.get('all'):
3192 if opts.get('all'):
3193 iter = difflinestates(pstates, states)
3193 iter = difflinestates(pstates, states)
3194 else:
3194 else:
3195 iter = [('', l) for l in states]
3195 iter = [('', l) for l in states]
3196 for change, l in iter:
3196 for change, l in iter:
3197 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3197 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3198 before, match, after = None, None, None
3198 before, match, after = None, None, None
3199
3199
3200 if opts.get('line_number'):
3200 if opts.get('line_number'):
3201 cols.append((str(l.linenum), 'grep.linenumber'))
3201 cols.append((str(l.linenum), 'grep.linenumber'))
3202 if opts.get('all'):
3202 if opts.get('all'):
3203 cols.append((change, 'grep.change'))
3203 cols.append((change, 'grep.change'))
3204 if opts.get('user'):
3204 if opts.get('user'):
3205 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3205 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3206 if opts.get('date'):
3206 if opts.get('date'):
3207 cols.append((datefunc(ctx.date()), 'grep.date'))
3207 cols.append((datefunc(ctx.date()), 'grep.date'))
3208 if opts.get('files_with_matches'):
3208 if opts.get('files_with_matches'):
3209 c = (fn, rev)
3209 c = (fn, rev)
3210 if c in filerevmatches:
3210 if c in filerevmatches:
3211 continue
3211 continue
3212 filerevmatches[c] = 1
3212 filerevmatches[c] = 1
3213 else:
3213 else:
3214 before = l.line[:l.colstart]
3214 before = l.line[:l.colstart]
3215 match = l.line[l.colstart:l.colend]
3215 match = l.line[l.colstart:l.colend]
3216 after = l.line[l.colend:]
3216 after = l.line[l.colend:]
3217 for col, label in cols[:-1]:
3217 for col, label in cols[:-1]:
3218 ui.write(col, label=label)
3218 ui.write(col, label=label)
3219 ui.write(sep, label='grep.sep')
3219 ui.write(sep, label='grep.sep')
3220 ui.write(cols[-1][0], label=cols[-1][1])
3220 ui.write(cols[-1][0], label=cols[-1][1])
3221 if before is not None:
3221 if before is not None:
3222 ui.write(sep, label='grep.sep')
3222 ui.write(sep, label='grep.sep')
3223 if not opts.get('text') and binary():
3223 if not opts.get('text') and binary():
3224 ui.write(" Binary file matches")
3224 ui.write(" Binary file matches")
3225 else:
3225 else:
3226 ui.write(before)
3226 ui.write(before)
3227 ui.write(match, label='grep.match')
3227 ui.write(match, label='grep.match')
3228 ui.write(after)
3228 ui.write(after)
3229 ui.write(eol)
3229 ui.write(eol)
3230 found = True
3230 found = True
3231 return found
3231 return found
3232
3232
3233 skip = {}
3233 skip = {}
3234 revfiles = {}
3234 revfiles = {}
3235 matchfn = scmutil.match(repo[None], pats, opts)
3235 matchfn = scmutil.match(repo[None], pats, opts)
3236 found = False
3236 found = False
3237 follow = opts.get('follow')
3237 follow = opts.get('follow')
3238
3238
3239 def prep(ctx, fns):
3239 def prep(ctx, fns):
3240 rev = ctx.rev()
3240 rev = ctx.rev()
3241 pctx = ctx.p1()
3241 pctx = ctx.p1()
3242 parent = pctx.rev()
3242 parent = pctx.rev()
3243 matches.setdefault(rev, {})
3243 matches.setdefault(rev, {})
3244 matches.setdefault(parent, {})
3244 matches.setdefault(parent, {})
3245 files = revfiles.setdefault(rev, [])
3245 files = revfiles.setdefault(rev, [])
3246 for fn in fns:
3246 for fn in fns:
3247 flog = getfile(fn)
3247 flog = getfile(fn)
3248 try:
3248 try:
3249 fnode = ctx.filenode(fn)
3249 fnode = ctx.filenode(fn)
3250 except error.LookupError:
3250 except error.LookupError:
3251 continue
3251 continue
3252
3252
3253 copied = flog.renamed(fnode)
3253 copied = flog.renamed(fnode)
3254 copy = follow and copied and copied[0]
3254 copy = follow and copied and copied[0]
3255 if copy:
3255 if copy:
3256 copies.setdefault(rev, {})[fn] = copy
3256 copies.setdefault(rev, {})[fn] = copy
3257 if fn in skip:
3257 if fn in skip:
3258 if copy:
3258 if copy:
3259 skip[copy] = True
3259 skip[copy] = True
3260 continue
3260 continue
3261 files.append(fn)
3261 files.append(fn)
3262
3262
3263 if fn not in matches[rev]:
3263 if fn not in matches[rev]:
3264 grepbody(fn, rev, flog.read(fnode))
3264 grepbody(fn, rev, flog.read(fnode))
3265
3265
3266 pfn = copy or fn
3266 pfn = copy or fn
3267 if pfn not in matches[parent]:
3267 if pfn not in matches[parent]:
3268 try:
3268 try:
3269 fnode = pctx.filenode(pfn)
3269 fnode = pctx.filenode(pfn)
3270 grepbody(pfn, parent, flog.read(fnode))
3270 grepbody(pfn, parent, flog.read(fnode))
3271 except error.LookupError:
3271 except error.LookupError:
3272 pass
3272 pass
3273
3273
3274 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3274 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3275 rev = ctx.rev()
3275 rev = ctx.rev()
3276 parent = ctx.p1().rev()
3276 parent = ctx.p1().rev()
3277 for fn in sorted(revfiles.get(rev, [])):
3277 for fn in sorted(revfiles.get(rev, [])):
3278 states = matches[rev][fn]
3278 states = matches[rev][fn]
3279 copy = copies.get(rev, {}).get(fn)
3279 copy = copies.get(rev, {}).get(fn)
3280 if fn in skip:
3280 if fn in skip:
3281 if copy:
3281 if copy:
3282 skip[copy] = True
3282 skip[copy] = True
3283 continue
3283 continue
3284 pstates = matches.get(parent, {}).get(copy or fn, [])
3284 pstates = matches.get(parent, {}).get(copy or fn, [])
3285 if pstates or states:
3285 if pstates or states:
3286 r = display(fn, ctx, pstates, states)
3286 r = display(fn, ctx, pstates, states)
3287 found = found or r
3287 found = found or r
3288 if r and not opts.get('all'):
3288 if r and not opts.get('all'):
3289 skip[fn] = True
3289 skip[fn] = True
3290 if copy:
3290 if copy:
3291 skip[copy] = True
3291 skip[copy] = True
3292 del matches[rev]
3292 del matches[rev]
3293 del revfiles[rev]
3293 del revfiles[rev]
3294
3294
3295 return not found
3295 return not found
3296
3296
3297 @command('heads',
3297 @command('heads',
3298 [('r', 'rev', '',
3298 [('r', 'rev', '',
3299 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3299 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3300 ('t', 'topo', False, _('show topological heads only')),
3300 ('t', 'topo', False, _('show topological heads only')),
3301 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3301 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3302 ('c', 'closed', False, _('show normal and closed branch heads')),
3302 ('c', 'closed', False, _('show normal and closed branch heads')),
3303 ] + templateopts,
3303 ] + templateopts,
3304 _('[-ct] [-r STARTREV] [REV]...'))
3304 _('[-ct] [-r STARTREV] [REV]...'))
3305 def heads(ui, repo, *branchrevs, **opts):
3305 def heads(ui, repo, *branchrevs, **opts):
3306 """show current repository heads or show branch heads
3306 """show current repository heads or show branch heads
3307
3307
3308 With no arguments, show all repository branch heads.
3308 With no arguments, show all repository branch heads.
3309
3309
3310 Repository "heads" are changesets with no child changesets. They are
3310 Repository "heads" are changesets with no child changesets. They are
3311 where development generally takes place and are the usual targets
3311 where development generally takes place and are the usual targets
3312 for update and merge operations. Branch heads are changesets that have
3312 for update and merge operations. Branch heads are changesets that have
3313 no child changeset on the same branch.
3313 no child changeset on the same branch.
3314
3314
3315 If one or more REVs are given, only branch heads on the branches
3315 If one or more REVs are given, only branch heads on the branches
3316 associated with the specified changesets are shown. This means
3316 associated with the specified changesets are shown. This means
3317 that you can use :hg:`heads foo` to see the heads on a branch
3317 that you can use :hg:`heads foo` to see the heads on a branch
3318 named ``foo``.
3318 named ``foo``.
3319
3319
3320 If -c/--closed is specified, also show branch heads marked closed
3320 If -c/--closed is specified, also show branch heads marked closed
3321 (see :hg:`commit --close-branch`).
3321 (see :hg:`commit --close-branch`).
3322
3322
3323 If STARTREV is specified, only those heads that are descendants of
3323 If STARTREV is specified, only those heads that are descendants of
3324 STARTREV will be displayed.
3324 STARTREV will be displayed.
3325
3325
3326 If -t/--topo is specified, named branch mechanics will be ignored and only
3326 If -t/--topo is specified, named branch mechanics will be ignored and only
3327 changesets without children will be shown.
3327 changesets without children will be shown.
3328
3328
3329 Returns 0 if matching heads are found, 1 if not.
3329 Returns 0 if matching heads are found, 1 if not.
3330 """
3330 """
3331
3331
3332 start = None
3332 start = None
3333 if 'rev' in opts:
3333 if 'rev' in opts:
3334 start = scmutil.revsingle(repo, opts['rev'], None).node()
3334 start = scmutil.revsingle(repo, opts['rev'], None).node()
3335
3335
3336 if opts.get('topo'):
3336 if opts.get('topo'):
3337 heads = [repo[h] for h in repo.heads(start)]
3337 heads = [repo[h] for h in repo.heads(start)]
3338 else:
3338 else:
3339 heads = []
3339 heads = []
3340 for branch in repo.branchmap():
3340 for branch in repo.branchmap():
3341 heads += repo.branchheads(branch, start, opts.get('closed'))
3341 heads += repo.branchheads(branch, start, opts.get('closed'))
3342 heads = [repo[h] for h in heads]
3342 heads = [repo[h] for h in heads]
3343
3343
3344 if branchrevs:
3344 if branchrevs:
3345 branches = set(repo[br].branch() for br in branchrevs)
3345 branches = set(repo[br].branch() for br in branchrevs)
3346 heads = [h for h in heads if h.branch() in branches]
3346 heads = [h for h in heads if h.branch() in branches]
3347
3347
3348 if opts.get('active') and branchrevs:
3348 if opts.get('active') and branchrevs:
3349 dagheads = repo.heads(start)
3349 dagheads = repo.heads(start)
3350 heads = [h for h in heads if h.node() in dagheads]
3350 heads = [h for h in heads if h.node() in dagheads]
3351
3351
3352 if branchrevs:
3352 if branchrevs:
3353 haveheads = set(h.branch() for h in heads)
3353 haveheads = set(h.branch() for h in heads)
3354 if branches - haveheads:
3354 if branches - haveheads:
3355 headless = ', '.join(b for b in branches - haveheads)
3355 headless = ', '.join(b for b in branches - haveheads)
3356 msg = _('no open branch heads found on branches %s')
3356 msg = _('no open branch heads found on branches %s')
3357 if opts.get('rev'):
3357 if opts.get('rev'):
3358 msg += _(' (started at %s)') % opts['rev']
3358 msg += _(' (started at %s)') % opts['rev']
3359 ui.warn((msg + '\n') % headless)
3359 ui.warn((msg + '\n') % headless)
3360
3360
3361 if not heads:
3361 if not heads:
3362 return 1
3362 return 1
3363
3363
3364 heads = sorted(heads, key=lambda x: -x.rev())
3364 heads = sorted(heads, key=lambda x: -x.rev())
3365 displayer = cmdutil.show_changeset(ui, repo, opts)
3365 displayer = cmdutil.show_changeset(ui, repo, opts)
3366 for ctx in heads:
3366 for ctx in heads:
3367 displayer.show(ctx)
3367 displayer.show(ctx)
3368 displayer.close()
3368 displayer.close()
3369
3369
3370 @command('help',
3370 @command('help',
3371 [('e', 'extension', None, _('show only help for extensions')),
3371 [('e', 'extension', None, _('show only help for extensions')),
3372 ('c', 'command', None, _('show only help for commands')),
3372 ('c', 'command', None, _('show only help for commands')),
3373 ('k', 'keyword', '', _('show topics matching keyword')),
3373 ('k', 'keyword', '', _('show topics matching keyword')),
3374 ],
3374 ],
3375 _('[-ec] [TOPIC]'))
3375 _('[-ec] [TOPIC]'))
3376 def help_(ui, name=None, **opts):
3376 def help_(ui, name=None, **opts):
3377 """show help for a given topic or a help overview
3377 """show help for a given topic or a help overview
3378
3378
3379 With no arguments, print a list of commands with short help messages.
3379 With no arguments, print a list of commands with short help messages.
3380
3380
3381 Given a topic, extension, or command name, print help for that
3381 Given a topic, extension, or command name, print help for that
3382 topic.
3382 topic.
3383
3383
3384 Returns 0 if successful.
3384 Returns 0 if successful.
3385 """
3385 """
3386
3386
3387 textwidth = min(ui.termwidth(), 80) - 2
3387 textwidth = min(ui.termwidth(), 80) - 2
3388
3388
3389 keep = ui.verbose and ['verbose'] or []
3389 keep = ui.verbose and ['verbose'] or []
3390 text = help.help_(ui, name, **opts)
3390 text = help.help_(ui, name, **opts)
3391
3391
3392 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3392 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3393 if 'verbose' in pruned:
3393 if 'verbose' in pruned:
3394 keep.append('omitted')
3394 keep.append('omitted')
3395 else:
3395 else:
3396 keep.append('notomitted')
3396 keep.append('notomitted')
3397 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3397 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3398 ui.write(formatted)
3398 ui.write(formatted)
3399
3399
3400
3400
3401 @command('identify|id',
3401 @command('identify|id',
3402 [('r', 'rev', '',
3402 [('r', 'rev', '',
3403 _('identify the specified revision'), _('REV')),
3403 _('identify the specified revision'), _('REV')),
3404 ('n', 'num', None, _('show local revision number')),
3404 ('n', 'num', None, _('show local revision number')),
3405 ('i', 'id', None, _('show global revision id')),
3405 ('i', 'id', None, _('show global revision id')),
3406 ('b', 'branch', None, _('show branch')),
3406 ('b', 'branch', None, _('show branch')),
3407 ('t', 'tags', None, _('show tags')),
3407 ('t', 'tags', None, _('show tags')),
3408 ('B', 'bookmarks', None, _('show bookmarks')),
3408 ('B', 'bookmarks', None, _('show bookmarks')),
3409 ] + remoteopts,
3409 ] + remoteopts,
3410 _('[-nibtB] [-r REV] [SOURCE]'))
3410 _('[-nibtB] [-r REV] [SOURCE]'))
3411 def identify(ui, repo, source=None, rev=None,
3411 def identify(ui, repo, source=None, rev=None,
3412 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3412 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3413 """identify the working copy or specified revision
3413 """identify the working copy or specified revision
3414
3414
3415 Print a summary identifying the repository state at REV using one or
3415 Print a summary identifying the repository state at REV using one or
3416 two parent hash identifiers, followed by a "+" if the working
3416 two parent hash identifiers, followed by a "+" if the working
3417 directory has uncommitted changes, the branch name (if not default),
3417 directory has uncommitted changes, the branch name (if not default),
3418 a list of tags, and a list of bookmarks.
3418 a list of tags, and a list of bookmarks.
3419
3419
3420 When REV is not given, print a summary of the current state of the
3420 When REV is not given, print a summary of the current state of the
3421 repository.
3421 repository.
3422
3422
3423 Specifying a path to a repository root or Mercurial bundle will
3423 Specifying a path to a repository root or Mercurial bundle will
3424 cause lookup to operate on that repository/bundle.
3424 cause lookup to operate on that repository/bundle.
3425
3425
3426 .. container:: verbose
3426 .. container:: verbose
3427
3427
3428 Examples:
3428 Examples:
3429
3429
3430 - generate a build identifier for the working directory::
3430 - generate a build identifier for the working directory::
3431
3431
3432 hg id --id > build-id.dat
3432 hg id --id > build-id.dat
3433
3433
3434 - find the revision corresponding to a tag::
3434 - find the revision corresponding to a tag::
3435
3435
3436 hg id -n -r 1.3
3436 hg id -n -r 1.3
3437
3437
3438 - check the most recent revision of a remote repository::
3438 - check the most recent revision of a remote repository::
3439
3439
3440 hg id -r tip http://selenic.com/hg/
3440 hg id -r tip http://selenic.com/hg/
3441
3441
3442 Returns 0 if successful.
3442 Returns 0 if successful.
3443 """
3443 """
3444
3444
3445 if not repo and not source:
3445 if not repo and not source:
3446 raise util.Abort(_("there is no Mercurial repository here "
3446 raise util.Abort(_("there is no Mercurial repository here "
3447 "(.hg not found)"))
3447 "(.hg not found)"))
3448
3448
3449 hexfunc = ui.debugflag and hex or short
3449 hexfunc = ui.debugflag and hex or short
3450 default = not (num or id or branch or tags or bookmarks)
3450 default = not (num or id or branch or tags or bookmarks)
3451 output = []
3451 output = []
3452 revs = []
3452 revs = []
3453
3453
3454 if source:
3454 if source:
3455 source, branches = hg.parseurl(ui.expandpath(source))
3455 source, branches = hg.parseurl(ui.expandpath(source))
3456 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3456 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3457 repo = peer.local()
3457 repo = peer.local()
3458 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3458 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3459
3459
3460 if not repo:
3460 if not repo:
3461 if num or branch or tags:
3461 if num or branch or tags:
3462 raise util.Abort(
3462 raise util.Abort(
3463 _("can't query remote revision number, branch, or tags"))
3463 _("can't query remote revision number, branch, or tags"))
3464 if not rev and revs:
3464 if not rev and revs:
3465 rev = revs[0]
3465 rev = revs[0]
3466 if not rev:
3466 if not rev:
3467 rev = "tip"
3467 rev = "tip"
3468
3468
3469 remoterev = peer.lookup(rev)
3469 remoterev = peer.lookup(rev)
3470 if default or id:
3470 if default or id:
3471 output = [hexfunc(remoterev)]
3471 output = [hexfunc(remoterev)]
3472
3472
3473 def getbms():
3473 def getbms():
3474 bms = []
3474 bms = []
3475
3475
3476 if 'bookmarks' in peer.listkeys('namespaces'):
3476 if 'bookmarks' in peer.listkeys('namespaces'):
3477 hexremoterev = hex(remoterev)
3477 hexremoterev = hex(remoterev)
3478 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3478 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3479 if bmr == hexremoterev]
3479 if bmr == hexremoterev]
3480
3480
3481 return sorted(bms)
3481 return sorted(bms)
3482
3482
3483 if bookmarks:
3483 if bookmarks:
3484 output.extend(getbms())
3484 output.extend(getbms())
3485 elif default and not ui.quiet:
3485 elif default and not ui.quiet:
3486 # multiple bookmarks for a single parent separated by '/'
3486 # multiple bookmarks for a single parent separated by '/'
3487 bm = '/'.join(getbms())
3487 bm = '/'.join(getbms())
3488 if bm:
3488 if bm:
3489 output.append(bm)
3489 output.append(bm)
3490 else:
3490 else:
3491 if not rev:
3491 if not rev:
3492 ctx = repo[None]
3492 ctx = repo[None]
3493 parents = ctx.parents()
3493 parents = ctx.parents()
3494 changed = ""
3494 changed = ""
3495 if default or id or num:
3495 if default or id or num:
3496 if (util.any(repo.status())
3496 if (util.any(repo.status())
3497 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3497 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3498 changed = '+'
3498 changed = '+'
3499 if default or id:
3499 if default or id:
3500 output = ["%s%s" %
3500 output = ["%s%s" %
3501 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3501 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3502 if num:
3502 if num:
3503 output.append("%s%s" %
3503 output.append("%s%s" %
3504 ('+'.join([str(p.rev()) for p in parents]), changed))
3504 ('+'.join([str(p.rev()) for p in parents]), changed))
3505 else:
3505 else:
3506 ctx = scmutil.revsingle(repo, rev)
3506 ctx = scmutil.revsingle(repo, rev)
3507 if default or id:
3507 if default or id:
3508 output = [hexfunc(ctx.node())]
3508 output = [hexfunc(ctx.node())]
3509 if num:
3509 if num:
3510 output.append(str(ctx.rev()))
3510 output.append(str(ctx.rev()))
3511
3511
3512 if default and not ui.quiet:
3512 if default and not ui.quiet:
3513 b = ctx.branch()
3513 b = ctx.branch()
3514 if b != 'default':
3514 if b != 'default':
3515 output.append("(%s)" % b)
3515 output.append("(%s)" % b)
3516
3516
3517 # multiple tags for a single parent separated by '/'
3517 # multiple tags for a single parent separated by '/'
3518 t = '/'.join(ctx.tags())
3518 t = '/'.join(ctx.tags())
3519 if t:
3519 if t:
3520 output.append(t)
3520 output.append(t)
3521
3521
3522 # multiple bookmarks for a single parent separated by '/'
3522 # multiple bookmarks for a single parent separated by '/'
3523 bm = '/'.join(ctx.bookmarks())
3523 bm = '/'.join(ctx.bookmarks())
3524 if bm:
3524 if bm:
3525 output.append(bm)
3525 output.append(bm)
3526 else:
3526 else:
3527 if branch:
3527 if branch:
3528 output.append(ctx.branch())
3528 output.append(ctx.branch())
3529
3529
3530 if tags:
3530 if tags:
3531 output.extend(ctx.tags())
3531 output.extend(ctx.tags())
3532
3532
3533 if bookmarks:
3533 if bookmarks:
3534 output.extend(ctx.bookmarks())
3534 output.extend(ctx.bookmarks())
3535
3535
3536 ui.write("%s\n" % ' '.join(output))
3536 ui.write("%s\n" % ' '.join(output))
3537
3537
3538 @command('import|patch',
3538 @command('import|patch',
3539 [('p', 'strip', 1,
3539 [('p', 'strip', 1,
3540 _('directory strip option for patch. This has the same '
3540 _('directory strip option for patch. This has the same '
3541 'meaning as the corresponding patch option'), _('NUM')),
3541 'meaning as the corresponding patch option'), _('NUM')),
3542 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3542 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3543 ('e', 'edit', False, _('invoke editor on commit messages')),
3543 ('e', 'edit', False, _('invoke editor on commit messages')),
3544 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3544 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3545 ('', 'no-commit', None,
3545 ('', 'no-commit', None,
3546 _("don't commit, just update the working directory")),
3546 _("don't commit, just update the working directory")),
3547 ('', 'bypass', None,
3547 ('', 'bypass', None,
3548 _("apply patch without touching the working directory")),
3548 _("apply patch without touching the working directory")),
3549 ('', 'exact', None,
3549 ('', 'exact', None,
3550 _('apply patch to the nodes from which it was generated')),
3550 _('apply patch to the nodes from which it was generated')),
3551 ('', 'import-branch', None,
3551 ('', 'import-branch', None,
3552 _('use any branch information in patch (implied by --exact)'))] +
3552 _('use any branch information in patch (implied by --exact)'))] +
3553 commitopts + commitopts2 + similarityopts,
3553 commitopts + commitopts2 + similarityopts,
3554 _('[OPTION]... PATCH...'))
3554 _('[OPTION]... PATCH...'))
3555 def import_(ui, repo, patch1=None, *patches, **opts):
3555 def import_(ui, repo, patch1=None, *patches, **opts):
3556 """import an ordered set of patches
3556 """import an ordered set of patches
3557
3557
3558 Import a list of patches and commit them individually (unless
3558 Import a list of patches and commit them individually (unless
3559 --no-commit is specified).
3559 --no-commit is specified).
3560
3560
3561 If there are outstanding changes in the working directory, import
3561 If there are outstanding changes in the working directory, import
3562 will abort unless given the -f/--force flag.
3562 will abort unless given the -f/--force flag.
3563
3563
3564 You can import a patch straight from a mail message. Even patches
3564 You can import a patch straight from a mail message. Even patches
3565 as attachments work (to use the body part, it must have type
3565 as attachments work (to use the body part, it must have type
3566 text/plain or text/x-patch). From and Subject headers of email
3566 text/plain or text/x-patch). From and Subject headers of email
3567 message are used as default committer and commit message. All
3567 message are used as default committer and commit message. All
3568 text/plain body parts before first diff are added to commit
3568 text/plain body parts before first diff are added to commit
3569 message.
3569 message.
3570
3570
3571 If the imported patch was generated by :hg:`export`, user and
3571 If the imported patch was generated by :hg:`export`, user and
3572 description from patch override values from message headers and
3572 description from patch override values from message headers and
3573 body. Values given on command line with -m/--message and -u/--user
3573 body. Values given on command line with -m/--message and -u/--user
3574 override these.
3574 override these.
3575
3575
3576 If --exact is specified, import will set the working directory to
3576 If --exact is specified, import will set the working directory to
3577 the parent of each patch before applying it, and will abort if the
3577 the parent of each patch before applying it, and will abort if the
3578 resulting changeset has a different ID than the one recorded in
3578 resulting changeset has a different ID than the one recorded in
3579 the patch. This may happen due to character set problems or other
3579 the patch. This may happen due to character set problems or other
3580 deficiencies in the text patch format.
3580 deficiencies in the text patch format.
3581
3581
3582 Use --bypass to apply and commit patches directly to the
3582 Use --bypass to apply and commit patches directly to the
3583 repository, not touching the working directory. Without --exact,
3583 repository, not touching the working directory. Without --exact,
3584 patches will be applied on top of the working directory parent
3584 patches will be applied on top of the working directory parent
3585 revision.
3585 revision.
3586
3586
3587 With -s/--similarity, hg will attempt to discover renames and
3587 With -s/--similarity, hg will attempt to discover renames and
3588 copies in the patch in the same way as :hg:`addremove`.
3588 copies in the patch in the same way as :hg:`addremove`.
3589
3589
3590 To read a patch from standard input, use "-" as the patch name. If
3590 To read a patch from standard input, use "-" as the patch name. If
3591 a URL is specified, the patch will be downloaded from it.
3591 a URL is specified, the patch will be downloaded from it.
3592 See :hg:`help dates` for a list of formats valid for -d/--date.
3592 See :hg:`help dates` for a list of formats valid for -d/--date.
3593
3593
3594 .. container:: verbose
3594 .. container:: verbose
3595
3595
3596 Examples:
3596 Examples:
3597
3597
3598 - import a traditional patch from a website and detect renames::
3598 - import a traditional patch from a website and detect renames::
3599
3599
3600 hg import -s 80 http://example.com/bugfix.patch
3600 hg import -s 80 http://example.com/bugfix.patch
3601
3601
3602 - import a changeset from an hgweb server::
3602 - import a changeset from an hgweb server::
3603
3603
3604 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3604 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3605
3605
3606 - import all the patches in an Unix-style mbox::
3606 - import all the patches in an Unix-style mbox::
3607
3607
3608 hg import incoming-patches.mbox
3608 hg import incoming-patches.mbox
3609
3609
3610 - attempt to exactly restore an exported changeset (not always
3610 - attempt to exactly restore an exported changeset (not always
3611 possible)::
3611 possible)::
3612
3612
3613 hg import --exact proposed-fix.patch
3613 hg import --exact proposed-fix.patch
3614
3614
3615 Returns 0 on success.
3615 Returns 0 on success.
3616 """
3616 """
3617
3617
3618 if not patch1:
3618 if not patch1:
3619 raise util.Abort(_('need at least one patch to import'))
3619 raise util.Abort(_('need at least one patch to import'))
3620
3620
3621 patches = (patch1,) + patches
3621 patches = (patch1,) + patches
3622
3622
3623 date = opts.get('date')
3623 date = opts.get('date')
3624 if date:
3624 if date:
3625 opts['date'] = util.parsedate(date)
3625 opts['date'] = util.parsedate(date)
3626
3626
3627 editor = cmdutil.commiteditor
3627 editor = cmdutil.commiteditor
3628 if opts.get('edit'):
3628 if opts.get('edit'):
3629 editor = cmdutil.commitforceeditor
3629 editor = cmdutil.commitforceeditor
3630
3630
3631 update = not opts.get('bypass')
3631 update = not opts.get('bypass')
3632 if not update and opts.get('no_commit'):
3632 if not update and opts.get('no_commit'):
3633 raise util.Abort(_('cannot use --no-commit with --bypass'))
3633 raise util.Abort(_('cannot use --no-commit with --bypass'))
3634 try:
3634 try:
3635 sim = float(opts.get('similarity') or 0)
3635 sim = float(opts.get('similarity') or 0)
3636 except ValueError:
3636 except ValueError:
3637 raise util.Abort(_('similarity must be a number'))
3637 raise util.Abort(_('similarity must be a number'))
3638 if sim < 0 or sim > 100:
3638 if sim < 0 or sim > 100:
3639 raise util.Abort(_('similarity must be between 0 and 100'))
3639 raise util.Abort(_('similarity must be between 0 and 100'))
3640 if sim and not update:
3640 if sim and not update:
3641 raise util.Abort(_('cannot use --similarity with --bypass'))
3641 raise util.Abort(_('cannot use --similarity with --bypass'))
3642
3642
3643 if (opts.get('exact') or not opts.get('force')) and update:
3643 if (opts.get('exact') or not opts.get('force')) and update:
3644 cmdutil.bailifchanged(repo)
3644 cmdutil.bailifchanged(repo)
3645
3645
3646 base = opts["base"]
3646 base = opts["base"]
3647 strip = opts["strip"]
3647 strip = opts["strip"]
3648 wlock = lock = tr = None
3648 wlock = lock = tr = None
3649 msgs = []
3649 msgs = []
3650
3650
3651 def tryone(ui, hunk, parents):
3651 def tryone(ui, hunk, parents):
3652 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3652 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3653 patch.extract(ui, hunk)
3653 patch.extract(ui, hunk)
3654
3654
3655 if not tmpname:
3655 if not tmpname:
3656 return (None, None)
3656 return (None, None)
3657 msg = _('applied to working directory')
3657 msg = _('applied to working directory')
3658
3658
3659 try:
3659 try:
3660 cmdline_message = cmdutil.logmessage(ui, opts)
3660 cmdline_message = cmdutil.logmessage(ui, opts)
3661 if cmdline_message:
3661 if cmdline_message:
3662 # pickup the cmdline msg
3662 # pickup the cmdline msg
3663 message = cmdline_message
3663 message = cmdline_message
3664 elif message:
3664 elif message:
3665 # pickup the patch msg
3665 # pickup the patch msg
3666 message = message.strip()
3666 message = message.strip()
3667 else:
3667 else:
3668 # launch the editor
3668 # launch the editor
3669 message = None
3669 message = None
3670 ui.debug('message:\n%s\n' % message)
3670 ui.debug('message:\n%s\n' % message)
3671
3671
3672 if len(parents) == 1:
3672 if len(parents) == 1:
3673 parents.append(repo[nullid])
3673 parents.append(repo[nullid])
3674 if opts.get('exact'):
3674 if opts.get('exact'):
3675 if not nodeid or not p1:
3675 if not nodeid or not p1:
3676 raise util.Abort(_('not a Mercurial patch'))
3676 raise util.Abort(_('not a Mercurial patch'))
3677 p1 = repo[p1]
3677 p1 = repo[p1]
3678 p2 = repo[p2 or nullid]
3678 p2 = repo[p2 or nullid]
3679 elif p2:
3679 elif p2:
3680 try:
3680 try:
3681 p1 = repo[p1]
3681 p1 = repo[p1]
3682 p2 = repo[p2]
3682 p2 = repo[p2]
3683 # Without any options, consider p2 only if the
3683 # Without any options, consider p2 only if the
3684 # patch is being applied on top of the recorded
3684 # patch is being applied on top of the recorded
3685 # first parent.
3685 # first parent.
3686 if p1 != parents[0]:
3686 if p1 != parents[0]:
3687 p1 = parents[0]
3687 p1 = parents[0]
3688 p2 = repo[nullid]
3688 p2 = repo[nullid]
3689 except error.RepoError:
3689 except error.RepoError:
3690 p1, p2 = parents
3690 p1, p2 = parents
3691 else:
3691 else:
3692 p1, p2 = parents
3692 p1, p2 = parents
3693
3693
3694 n = None
3694 n = None
3695 if update:
3695 if update:
3696 if p1 != parents[0]:
3696 if p1 != parents[0]:
3697 hg.clean(repo, p1.node())
3697 hg.clean(repo, p1.node())
3698 if p2 != parents[1]:
3698 if p2 != parents[1]:
3699 repo.setparents(p1.node(), p2.node())
3699 repo.setparents(p1.node(), p2.node())
3700
3700
3701 if opts.get('exact') or opts.get('import_branch'):
3701 if opts.get('exact') or opts.get('import_branch'):
3702 repo.dirstate.setbranch(branch or 'default')
3702 repo.dirstate.setbranch(branch or 'default')
3703
3703
3704 files = set()
3704 files = set()
3705 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3705 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3706 eolmode=None, similarity=sim / 100.0)
3706 eolmode=None, similarity=sim / 100.0)
3707 files = list(files)
3707 files = list(files)
3708 if opts.get('no_commit'):
3708 if opts.get('no_commit'):
3709 if message:
3709 if message:
3710 msgs.append(message)
3710 msgs.append(message)
3711 else:
3711 else:
3712 if opts.get('exact') or p2:
3712 if opts.get('exact') or p2:
3713 # If you got here, you either use --force and know what
3713 # If you got here, you either use --force and know what
3714 # you are doing or used --exact or a merge patch while
3714 # you are doing or used --exact or a merge patch while
3715 # being updated to its first parent.
3715 # being updated to its first parent.
3716 m = None
3716 m = None
3717 else:
3717 else:
3718 m = scmutil.matchfiles(repo, files or [])
3718 m = scmutil.matchfiles(repo, files or [])
3719 n = repo.commit(message, opts.get('user') or user,
3719 n = repo.commit(message, opts.get('user') or user,
3720 opts.get('date') or date, match=m,
3720 opts.get('date') or date, match=m,
3721 editor=editor)
3721 editor=editor)
3722 else:
3722 else:
3723 if opts.get('exact') or opts.get('import_branch'):
3723 if opts.get('exact') or opts.get('import_branch'):
3724 branch = branch or 'default'
3724 branch = branch or 'default'
3725 else:
3725 else:
3726 branch = p1.branch()
3726 branch = p1.branch()
3727 store = patch.filestore()
3727 store = patch.filestore()
3728 try:
3728 try:
3729 files = set()
3729 files = set()
3730 try:
3730 try:
3731 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3731 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3732 files, eolmode=None)
3732 files, eolmode=None)
3733 except patch.PatchError, e:
3733 except patch.PatchError, e:
3734 raise util.Abort(str(e))
3734 raise util.Abort(str(e))
3735 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3735 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3736 message,
3736 message,
3737 opts.get('user') or user,
3737 opts.get('user') or user,
3738 opts.get('date') or date,
3738 opts.get('date') or date,
3739 branch, files, store,
3739 branch, files, store,
3740 editor=cmdutil.commiteditor)
3740 editor=cmdutil.commiteditor)
3741 repo.savecommitmessage(memctx.description())
3741 repo.savecommitmessage(memctx.description())
3742 n = memctx.commit()
3742 n = memctx.commit()
3743 finally:
3743 finally:
3744 store.close()
3744 store.close()
3745 if opts.get('exact') and hex(n) != nodeid:
3745 if opts.get('exact') and hex(n) != nodeid:
3746 raise util.Abort(_('patch is damaged or loses information'))
3746 raise util.Abort(_('patch is damaged or loses information'))
3747 if n:
3747 if n:
3748 # i18n: refers to a short changeset id
3748 # i18n: refers to a short changeset id
3749 msg = _('created %s') % short(n)
3749 msg = _('created %s') % short(n)
3750 return (msg, n)
3750 return (msg, n)
3751 finally:
3751 finally:
3752 os.unlink(tmpname)
3752 os.unlink(tmpname)
3753
3753
3754 try:
3754 try:
3755 try:
3755 try:
3756 wlock = repo.wlock()
3756 wlock = repo.wlock()
3757 if not opts.get('no_commit'):
3757 if not opts.get('no_commit'):
3758 lock = repo.lock()
3758 lock = repo.lock()
3759 tr = repo.transaction('import')
3759 tr = repo.transaction('import')
3760 parents = repo.parents()
3760 parents = repo.parents()
3761 for patchurl in patches:
3761 for patchurl in patches:
3762 if patchurl == '-':
3762 if patchurl == '-':
3763 ui.status(_('applying patch from stdin\n'))
3763 ui.status(_('applying patch from stdin\n'))
3764 patchfile = ui.fin
3764 patchfile = ui.fin
3765 patchurl = 'stdin' # for error message
3765 patchurl = 'stdin' # for error message
3766 else:
3766 else:
3767 patchurl = os.path.join(base, patchurl)
3767 patchurl = os.path.join(base, patchurl)
3768 ui.status(_('applying %s\n') % patchurl)
3768 ui.status(_('applying %s\n') % patchurl)
3769 patchfile = hg.openpath(ui, patchurl)
3769 patchfile = hg.openpath(ui, patchurl)
3770
3770
3771 haspatch = False
3771 haspatch = False
3772 for hunk in patch.split(patchfile):
3772 for hunk in patch.split(patchfile):
3773 (msg, node) = tryone(ui, hunk, parents)
3773 (msg, node) = tryone(ui, hunk, parents)
3774 if msg:
3774 if msg:
3775 haspatch = True
3775 haspatch = True
3776 ui.note(msg + '\n')
3776 ui.note(msg + '\n')
3777 if update or opts.get('exact'):
3777 if update or opts.get('exact'):
3778 parents = repo.parents()
3778 parents = repo.parents()
3779 else:
3779 else:
3780 parents = [repo[node]]
3780 parents = [repo[node]]
3781
3781
3782 if not haspatch:
3782 if not haspatch:
3783 raise util.Abort(_('%s: no diffs found') % patchurl)
3783 raise util.Abort(_('%s: no diffs found') % patchurl)
3784
3784
3785 if tr:
3785 if tr:
3786 tr.close()
3786 tr.close()
3787 if msgs:
3787 if msgs:
3788 repo.savecommitmessage('\n* * *\n'.join(msgs))
3788 repo.savecommitmessage('\n* * *\n'.join(msgs))
3789 except: # re-raises
3789 except: # re-raises
3790 # wlock.release() indirectly calls dirstate.write(): since
3790 # wlock.release() indirectly calls dirstate.write(): since
3791 # we're crashing, we do not want to change the working dir
3791 # we're crashing, we do not want to change the working dir
3792 # parent after all, so make sure it writes nothing
3792 # parent after all, so make sure it writes nothing
3793 repo.dirstate.invalidate()
3793 repo.dirstate.invalidate()
3794 raise
3794 raise
3795 finally:
3795 finally:
3796 if tr:
3796 if tr:
3797 tr.release()
3797 tr.release()
3798 release(lock, wlock)
3798 release(lock, wlock)
3799
3799
3800 @command('incoming|in',
3800 @command('incoming|in',
3801 [('f', 'force', None,
3801 [('f', 'force', None,
3802 _('run even if remote repository is unrelated')),
3802 _('run even if remote repository is unrelated')),
3803 ('n', 'newest-first', None, _('show newest record first')),
3803 ('n', 'newest-first', None, _('show newest record first')),
3804 ('', 'bundle', '',
3804 ('', 'bundle', '',
3805 _('file to store the bundles into'), _('FILE')),
3805 _('file to store the bundles into'), _('FILE')),
3806 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3806 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3807 ('B', 'bookmarks', False, _("compare bookmarks")),
3807 ('B', 'bookmarks', False, _("compare bookmarks")),
3808 ('b', 'branch', [],
3808 ('b', 'branch', [],
3809 _('a specific branch you would like to pull'), _('BRANCH')),
3809 _('a specific branch you would like to pull'), _('BRANCH')),
3810 ] + logopts + remoteopts + subrepoopts,
3810 ] + logopts + remoteopts + subrepoopts,
3811 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3811 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3812 def incoming(ui, repo, source="default", **opts):
3812 def incoming(ui, repo, source="default", **opts):
3813 """show new changesets found in source
3813 """show new changesets found in source
3814
3814
3815 Show new changesets found in the specified path/URL or the default
3815 Show new changesets found in the specified path/URL or the default
3816 pull location. These are the changesets that would have been pulled
3816 pull location. These are the changesets that would have been pulled
3817 if a pull at the time you issued this command.
3817 if a pull at the time you issued this command.
3818
3818
3819 For remote repository, using --bundle avoids downloading the
3819 For remote repository, using --bundle avoids downloading the
3820 changesets twice if the incoming is followed by a pull.
3820 changesets twice if the incoming is followed by a pull.
3821
3821
3822 See pull for valid source format details.
3822 See pull for valid source format details.
3823
3823
3824 Returns 0 if there are incoming changes, 1 otherwise.
3824 Returns 0 if there are incoming changes, 1 otherwise.
3825 """
3825 """
3826 if opts.get('graph'):
3826 if opts.get('graph'):
3827 cmdutil.checkunsupportedgraphflags([], opts)
3827 cmdutil.checkunsupportedgraphflags([], opts)
3828 def display(other, chlist, displayer):
3828 def display(other, chlist, displayer):
3829 revdag = cmdutil.graphrevs(other, chlist, opts)
3829 revdag = cmdutil.graphrevs(other, chlist, opts)
3830 showparents = [ctx.node() for ctx in repo[None].parents()]
3830 showparents = [ctx.node() for ctx in repo[None].parents()]
3831 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3831 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3832 graphmod.asciiedges)
3832 graphmod.asciiedges)
3833
3833
3834 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3834 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3835 return 0
3835 return 0
3836
3836
3837 if opts.get('bundle') and opts.get('subrepos'):
3837 if opts.get('bundle') and opts.get('subrepos'):
3838 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3838 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3839
3839
3840 if opts.get('bookmarks'):
3840 if opts.get('bookmarks'):
3841 source, branches = hg.parseurl(ui.expandpath(source),
3841 source, branches = hg.parseurl(ui.expandpath(source),
3842 opts.get('branch'))
3842 opts.get('branch'))
3843 other = hg.peer(repo, opts, source)
3843 other = hg.peer(repo, opts, source)
3844 if 'bookmarks' not in other.listkeys('namespaces'):
3844 if 'bookmarks' not in other.listkeys('namespaces'):
3845 ui.warn(_("remote doesn't support bookmarks\n"))
3845 ui.warn(_("remote doesn't support bookmarks\n"))
3846 return 0
3846 return 0
3847 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3847 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3848 return bookmarks.diff(ui, repo, other)
3848 return bookmarks.diff(ui, repo, other)
3849
3849
3850 repo._subtoppath = ui.expandpath(source)
3850 repo._subtoppath = ui.expandpath(source)
3851 try:
3851 try:
3852 return hg.incoming(ui, repo, source, opts)
3852 return hg.incoming(ui, repo, source, opts)
3853 finally:
3853 finally:
3854 del repo._subtoppath
3854 del repo._subtoppath
3855
3855
3856
3856
3857 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3857 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3858 def init(ui, dest=".", **opts):
3858 def init(ui, dest=".", **opts):
3859 """create a new repository in the given directory
3859 """create a new repository in the given directory
3860
3860
3861 Initialize a new repository in the given directory. If the given
3861 Initialize a new repository in the given directory. If the given
3862 directory does not exist, it will be created.
3862 directory does not exist, it will be created.
3863
3863
3864 If no directory is given, the current directory is used.
3864 If no directory is given, the current directory is used.
3865
3865
3866 It is possible to specify an ``ssh://`` URL as the destination.
3866 It is possible to specify an ``ssh://`` URL as the destination.
3867 See :hg:`help urls` for more information.
3867 See :hg:`help urls` for more information.
3868
3868
3869 Returns 0 on success.
3869 Returns 0 on success.
3870 """
3870 """
3871 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3871 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3872
3872
3873 @command('locate',
3873 @command('locate',
3874 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3874 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3875 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3875 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3876 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3876 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3877 ] + walkopts,
3877 ] + walkopts,
3878 _('[OPTION]... [PATTERN]...'))
3878 _('[OPTION]... [PATTERN]...'))
3879 def locate(ui, repo, *pats, **opts):
3879 def locate(ui, repo, *pats, **opts):
3880 """locate files matching specific patterns
3880 """locate files matching specific patterns
3881
3881
3882 Print files under Mercurial control in the working directory whose
3882 Print files under Mercurial control in the working directory whose
3883 names match the given patterns.
3883 names match the given patterns.
3884
3884
3885 By default, this command searches all directories in the working
3885 By default, this command searches all directories in the working
3886 directory. To search just the current directory and its
3886 directory. To search just the current directory and its
3887 subdirectories, use "--include .".
3887 subdirectories, use "--include .".
3888
3888
3889 If no patterns are given to match, this command prints the names
3889 If no patterns are given to match, this command prints the names
3890 of all files under Mercurial control in the working directory.
3890 of all files under Mercurial control in the working directory.
3891
3891
3892 If you want to feed the output of this command into the "xargs"
3892 If you want to feed the output of this command into the "xargs"
3893 command, use the -0 option to both this command and "xargs". This
3893 command, use the -0 option to both this command and "xargs". This
3894 will avoid the problem of "xargs" treating single filenames that
3894 will avoid the problem of "xargs" treating single filenames that
3895 contain whitespace as multiple filenames.
3895 contain whitespace as multiple filenames.
3896
3896
3897 Returns 0 if a match is found, 1 otherwise.
3897 Returns 0 if a match is found, 1 otherwise.
3898 """
3898 """
3899 end = opts.get('print0') and '\0' or '\n'
3899 end = opts.get('print0') and '\0' or '\n'
3900 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3900 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3901
3901
3902 ret = 1
3902 ret = 1
3903 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3903 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3904 m.bad = lambda x, y: False
3904 m.bad = lambda x, y: False
3905 for abs in repo[rev].walk(m):
3905 for abs in repo[rev].walk(m):
3906 if not rev and abs not in repo.dirstate:
3906 if not rev and abs not in repo.dirstate:
3907 continue
3907 continue
3908 if opts.get('fullpath'):
3908 if opts.get('fullpath'):
3909 ui.write(repo.wjoin(abs), end)
3909 ui.write(repo.wjoin(abs), end)
3910 else:
3910 else:
3911 ui.write(((pats and m.rel(abs)) or abs), end)
3911 ui.write(((pats and m.rel(abs)) or abs), end)
3912 ret = 0
3912 ret = 0
3913
3913
3914 return ret
3914 return ret
3915
3915
3916 @command('^log|history',
3916 @command('^log|history',
3917 [('f', 'follow', None,
3917 [('f', 'follow', None,
3918 _('follow changeset history, or file history across copies and renames')),
3918 _('follow changeset history, or file history across copies and renames')),
3919 ('', 'follow-first', None,
3919 ('', 'follow-first', None,
3920 _('only follow the first parent of merge changesets (DEPRECATED)')),
3920 _('only follow the first parent of merge changesets (DEPRECATED)')),
3921 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3921 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3922 ('C', 'copies', None, _('show copied files')),
3922 ('C', 'copies', None, _('show copied files')),
3923 ('k', 'keyword', [],
3923 ('k', 'keyword', [],
3924 _('do case-insensitive search for a given text'), _('TEXT')),
3924 _('do case-insensitive search for a given text'), _('TEXT')),
3925 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3925 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3926 ('', 'removed', None, _('include revisions where files were removed')),
3926 ('', 'removed', None, _('include revisions where files were removed')),
3927 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3927 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3928 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3928 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3929 ('', 'only-branch', [],
3929 ('', 'only-branch', [],
3930 _('show only changesets within the given named branch (DEPRECATED)'),
3930 _('show only changesets within the given named branch (DEPRECATED)'),
3931 _('BRANCH')),
3931 _('BRANCH')),
3932 ('b', 'branch', [],
3932 ('b', 'branch', [],
3933 _('show changesets within the given named branch'), _('BRANCH')),
3933 _('show changesets within the given named branch'), _('BRANCH')),
3934 ('P', 'prune', [],
3934 ('P', 'prune', [],
3935 _('do not display revision or any of its ancestors'), _('REV')),
3935 _('do not display revision or any of its ancestors'), _('REV')),
3936 ] + logopts + walkopts,
3936 ] + logopts + walkopts,
3937 _('[OPTION]... [FILE]'))
3937 _('[OPTION]... [FILE]'))
3938 def log(ui, repo, *pats, **opts):
3938 def log(ui, repo, *pats, **opts):
3939 """show revision history of entire repository or files
3939 """show revision history of entire repository or files
3940
3940
3941 Print the revision history of the specified files or the entire
3941 Print the revision history of the specified files or the entire
3942 project.
3942 project.
3943
3943
3944 If no revision range is specified, the default is ``tip:0`` unless
3944 If no revision range is specified, the default is ``tip:0`` unless
3945 --follow is set, in which case the working directory parent is
3945 --follow is set, in which case the working directory parent is
3946 used as the starting revision.
3946 used as the starting revision.
3947
3947
3948 File history is shown without following rename or copy history of
3948 File history is shown without following rename or copy history of
3949 files. Use -f/--follow with a filename to follow history across
3949 files. Use -f/--follow with a filename to follow history across
3950 renames and copies. --follow without a filename will only show
3950 renames and copies. --follow without a filename will only show
3951 ancestors or descendants of the starting revision.
3951 ancestors or descendants of the starting revision.
3952
3952
3953 By default this command prints revision number and changeset id,
3953 By default this command prints revision number and changeset id,
3954 tags, non-trivial parents, user, date and time, and a summary for
3954 tags, non-trivial parents, user, date and time, and a summary for
3955 each commit. When the -v/--verbose switch is used, the list of
3955 each commit. When the -v/--verbose switch is used, the list of
3956 changed files and full commit message are shown.
3956 changed files and full commit message are shown.
3957
3957
3958 .. note::
3958 .. note::
3959 log -p/--patch may generate unexpected diff output for merge
3959 log -p/--patch may generate unexpected diff output for merge
3960 changesets, as it will only compare the merge changeset against
3960 changesets, as it will only compare the merge changeset against
3961 its first parent. Also, only files different from BOTH parents
3961 its first parent. Also, only files different from BOTH parents
3962 will appear in files:.
3962 will appear in files:.
3963
3963
3964 .. note::
3964 .. note::
3965 for performance reasons, log FILE may omit duplicate changes
3965 for performance reasons, log FILE may omit duplicate changes
3966 made on branches and will not show deletions. To see all
3966 made on branches and will not show deletions. To see all
3967 changes including duplicates and deletions, use the --removed
3967 changes including duplicates and deletions, use the --removed
3968 switch.
3968 switch.
3969
3969
3970 .. container:: verbose
3970 .. container:: verbose
3971
3971
3972 Some examples:
3972 Some examples:
3973
3973
3974 - changesets with full descriptions and file lists::
3974 - changesets with full descriptions and file lists::
3975
3975
3976 hg log -v
3976 hg log -v
3977
3977
3978 - changesets ancestral to the working directory::
3978 - changesets ancestral to the working directory::
3979
3979
3980 hg log -f
3980 hg log -f
3981
3981
3982 - last 10 commits on the current branch::
3982 - last 10 commits on the current branch::
3983
3983
3984 hg log -l 10 -b .
3984 hg log -l 10 -b .
3985
3985
3986 - changesets showing all modifications of a file, including removals::
3986 - changesets showing all modifications of a file, including removals::
3987
3987
3988 hg log --removed file.c
3988 hg log --removed file.c
3989
3989
3990 - all changesets that touch a directory, with diffs, excluding merges::
3990 - all changesets that touch a directory, with diffs, excluding merges::
3991
3991
3992 hg log -Mp lib/
3992 hg log -Mp lib/
3993
3993
3994 - all revision numbers that match a keyword::
3994 - all revision numbers that match a keyword::
3995
3995
3996 hg log -k bug --template "{rev}\\n"
3996 hg log -k bug --template "{rev}\\n"
3997
3997
3998 - check if a given changeset is included is a tagged release::
3998 - check if a given changeset is included is a tagged release::
3999
3999
4000 hg log -r "a21ccf and ancestor(1.9)"
4000 hg log -r "a21ccf and ancestor(1.9)"
4001
4001
4002 - find all changesets by some user in a date range::
4002 - find all changesets by some user in a date range::
4003
4003
4004 hg log -k alice -d "may 2008 to jul 2008"
4004 hg log -k alice -d "may 2008 to jul 2008"
4005
4005
4006 - summary of all changesets after the last tag::
4006 - summary of all changesets after the last tag::
4007
4007
4008 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4008 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4009
4009
4010 See :hg:`help dates` for a list of formats valid for -d/--date.
4010 See :hg:`help dates` for a list of formats valid for -d/--date.
4011
4011
4012 See :hg:`help revisions` and :hg:`help revsets` for more about
4012 See :hg:`help revisions` and :hg:`help revsets` for more about
4013 specifying revisions.
4013 specifying revisions.
4014
4014
4015 See :hg:`help templates` for more about pre-packaged styles and
4015 See :hg:`help templates` for more about pre-packaged styles and
4016 specifying custom templates.
4016 specifying custom templates.
4017
4017
4018 Returns 0 on success.
4018 Returns 0 on success.
4019 """
4019 """
4020 if opts.get('graph'):
4020 if opts.get('graph'):
4021 return cmdutil.graphlog(ui, repo, *pats, **opts)
4021 return cmdutil.graphlog(ui, repo, *pats, **opts)
4022
4022
4023 matchfn = scmutil.match(repo[None], pats, opts)
4023 matchfn = scmutil.match(repo[None], pats, opts)
4024 limit = cmdutil.loglimit(opts)
4024 limit = cmdutil.loglimit(opts)
4025 count = 0
4025 count = 0
4026
4026
4027 getrenamed, endrev = None, None
4027 getrenamed, endrev = None, None
4028 if opts.get('copies'):
4028 if opts.get('copies'):
4029 if opts.get('rev'):
4029 if opts.get('rev'):
4030 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4030 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4031 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4031 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4032
4032
4033 df = False
4033 df = False
4034 if opts.get("date"):
4034 if opts.get("date"):
4035 df = util.matchdate(opts["date"])
4035 df = util.matchdate(opts["date"])
4036
4036
4037 branches = opts.get('branch', []) + opts.get('only_branch', [])
4037 branches = opts.get('branch', []) + opts.get('only_branch', [])
4038 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4038 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4039
4039
4040 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4040 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4041 def prep(ctx, fns):
4041 def prep(ctx, fns):
4042 rev = ctx.rev()
4042 rev = ctx.rev()
4043 parents = [p for p in repo.changelog.parentrevs(rev)
4043 parents = [p for p in repo.changelog.parentrevs(rev)
4044 if p != nullrev]
4044 if p != nullrev]
4045 if opts.get('no_merges') and len(parents) == 2:
4045 if opts.get('no_merges') and len(parents) == 2:
4046 return
4046 return
4047 if opts.get('only_merges') and len(parents) != 2:
4047 if opts.get('only_merges') and len(parents) != 2:
4048 return
4048 return
4049 if opts.get('branch') and ctx.branch() not in opts['branch']:
4049 if opts.get('branch') and ctx.branch() not in opts['branch']:
4050 return
4050 return
4051 if df and not df(ctx.date()[0]):
4051 if df and not df(ctx.date()[0]):
4052 return
4052 return
4053
4053
4054 lower = encoding.lower
4054 lower = encoding.lower
4055 if opts.get('user'):
4055 if opts.get('user'):
4056 luser = lower(ctx.user())
4056 luser = lower(ctx.user())
4057 for k in [lower(x) for x in opts['user']]:
4057 for k in [lower(x) for x in opts['user']]:
4058 if (k in luser):
4058 if (k in luser):
4059 break
4059 break
4060 else:
4060 else:
4061 return
4061 return
4062 if opts.get('keyword'):
4062 if opts.get('keyword'):
4063 luser = lower(ctx.user())
4063 luser = lower(ctx.user())
4064 ldesc = lower(ctx.description())
4064 ldesc = lower(ctx.description())
4065 lfiles = lower(" ".join(ctx.files()))
4065 lfiles = lower(" ".join(ctx.files()))
4066 for k in [lower(x) for x in opts['keyword']]:
4066 for k in [lower(x) for x in opts['keyword']]:
4067 if (k in luser or k in ldesc or k in lfiles):
4067 if (k in luser or k in ldesc or k in lfiles):
4068 break
4068 break
4069 else:
4069 else:
4070 return
4070 return
4071
4071
4072 copies = None
4072 copies = None
4073 if getrenamed is not None and rev:
4073 if getrenamed is not None and rev:
4074 copies = []
4074 copies = []
4075 for fn in ctx.files():
4075 for fn in ctx.files():
4076 rename = getrenamed(fn, rev)
4076 rename = getrenamed(fn, rev)
4077 if rename:
4077 if rename:
4078 copies.append((fn, rename[0]))
4078 copies.append((fn, rename[0]))
4079
4079
4080 revmatchfn = None
4080 revmatchfn = None
4081 if opts.get('patch') or opts.get('stat'):
4081 if opts.get('patch') or opts.get('stat'):
4082 if opts.get('follow') or opts.get('follow_first'):
4082 if opts.get('follow') or opts.get('follow_first'):
4083 # note: this might be wrong when following through merges
4083 # note: this might be wrong when following through merges
4084 revmatchfn = scmutil.match(repo[None], fns, default='path')
4084 revmatchfn = scmutil.match(repo[None], fns, default='path')
4085 else:
4085 else:
4086 revmatchfn = matchfn
4086 revmatchfn = matchfn
4087
4087
4088 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4088 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4089
4089
4090 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4090 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4091 if displayer.flush(ctx.rev()):
4091 if displayer.flush(ctx.rev()):
4092 count += 1
4092 count += 1
4093 if count == limit:
4093 if count == limit:
4094 break
4094 break
4095 displayer.close()
4095 displayer.close()
4096
4096
4097 @command('manifest',
4097 @command('manifest',
4098 [('r', 'rev', '', _('revision to display'), _('REV')),
4098 [('r', 'rev', '', _('revision to display'), _('REV')),
4099 ('', 'all', False, _("list files from all revisions"))],
4099 ('', 'all', False, _("list files from all revisions"))],
4100 _('[-r REV]'))
4100 _('[-r REV]'))
4101 def manifest(ui, repo, node=None, rev=None, **opts):
4101 def manifest(ui, repo, node=None, rev=None, **opts):
4102 """output the current or given revision of the project manifest
4102 """output the current or given revision of the project manifest
4103
4103
4104 Print a list of version controlled files for the given revision.
4104 Print a list of version controlled files for the given revision.
4105 If no revision is given, the first parent of the working directory
4105 If no revision is given, the first parent of the working directory
4106 is used, or the null revision if no revision is checked out.
4106 is used, or the null revision if no revision is checked out.
4107
4107
4108 With -v, print file permissions, symlink and executable bits.
4108 With -v, print file permissions, symlink and executable bits.
4109 With --debug, print file revision hashes.
4109 With --debug, print file revision hashes.
4110
4110
4111 If option --all is specified, the list of all files from all revisions
4111 If option --all is specified, the list of all files from all revisions
4112 is printed. This includes deleted and renamed files.
4112 is printed. This includes deleted and renamed files.
4113
4113
4114 Returns 0 on success.
4114 Returns 0 on success.
4115 """
4115 """
4116
4116
4117 fm = ui.formatter('manifest', opts)
4117 fm = ui.formatter('manifest', opts)
4118
4118
4119 if opts.get('all'):
4119 if opts.get('all'):
4120 if rev or node:
4120 if rev or node:
4121 raise util.Abort(_("can't specify a revision with --all"))
4121 raise util.Abort(_("can't specify a revision with --all"))
4122
4122
4123 res = []
4123 res = []
4124 prefix = "data/"
4124 prefix = "data/"
4125 suffix = ".i"
4125 suffix = ".i"
4126 plen = len(prefix)
4126 plen = len(prefix)
4127 slen = len(suffix)
4127 slen = len(suffix)
4128 lock = repo.lock()
4128 lock = repo.lock()
4129 try:
4129 try:
4130 for fn, b, size in repo.store.datafiles():
4130 for fn, b, size in repo.store.datafiles():
4131 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4131 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4132 res.append(fn[plen:-slen])
4132 res.append(fn[plen:-slen])
4133 finally:
4133 finally:
4134 lock.release()
4134 lock.release()
4135 for f in res:
4135 for f in res:
4136 fm.startitem()
4136 fm.startitem()
4137 fm.write("path", '%s\n', f)
4137 fm.write("path", '%s\n', f)
4138 fm.end()
4138 fm.end()
4139 return
4139 return
4140
4140
4141 if rev and node:
4141 if rev and node:
4142 raise util.Abort(_("please specify just one revision"))
4142 raise util.Abort(_("please specify just one revision"))
4143
4143
4144 if not node:
4144 if not node:
4145 node = rev
4145 node = rev
4146
4146
4147 char = {'l': '@', 'x': '*', '': ''}
4147 char = {'l': '@', 'x': '*', '': ''}
4148 mode = {'l': '644', 'x': '755', '': '644'}
4148 mode = {'l': '644', 'x': '755', '': '644'}
4149 ctx = scmutil.revsingle(repo, node)
4149 ctx = scmutil.revsingle(repo, node)
4150 mf = ctx.manifest()
4150 mf = ctx.manifest()
4151 for f in ctx:
4151 for f in ctx:
4152 fm.startitem()
4152 fm.startitem()
4153 fl = ctx[f].flags()
4153 fl = ctx[f].flags()
4154 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4154 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4155 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4155 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4156 fm.write('path', '%s\n', f)
4156 fm.write('path', '%s\n', f)
4157 fm.end()
4157 fm.end()
4158
4158
4159 @command('^merge',
4159 @command('^merge',
4160 [('f', 'force', None, _('force a merge with outstanding changes')),
4160 [('f', 'force', None, _('force a merge with outstanding changes')),
4161 ('r', 'rev', '', _('revision to merge'), _('REV')),
4161 ('r', 'rev', '', _('revision to merge'), _('REV')),
4162 ('P', 'preview', None,
4162 ('P', 'preview', None,
4163 _('review revisions to merge (no merge is performed)'))
4163 _('review revisions to merge (no merge is performed)'))
4164 ] + mergetoolopts,
4164 ] + mergetoolopts,
4165 _('[-P] [-f] [[-r] REV]'))
4165 _('[-P] [-f] [[-r] REV]'))
4166 def merge(ui, repo, node=None, **opts):
4166 def merge(ui, repo, node=None, **opts):
4167 """merge working directory with another revision
4167 """merge working directory with another revision
4168
4168
4169 The current working directory is updated with all changes made in
4169 The current working directory is updated with all changes made in
4170 the requested revision since the last common predecessor revision.
4170 the requested revision since the last common predecessor revision.
4171
4171
4172 Files that changed between either parent are marked as changed for
4172 Files that changed between either parent are marked as changed for
4173 the next commit and a commit must be performed before any further
4173 the next commit and a commit must be performed before any further
4174 updates to the repository are allowed. The next commit will have
4174 updates to the repository are allowed. The next commit will have
4175 two parents.
4175 two parents.
4176
4176
4177 ``--tool`` can be used to specify the merge tool used for file
4177 ``--tool`` can be used to specify the merge tool used for file
4178 merges. It overrides the HGMERGE environment variable and your
4178 merges. It overrides the HGMERGE environment variable and your
4179 configuration files. See :hg:`help merge-tools` for options.
4179 configuration files. See :hg:`help merge-tools` for options.
4180
4180
4181 If no revision is specified, the working directory's parent is a
4181 If no revision is specified, the working directory's parent is a
4182 head revision, and the current branch contains exactly one other
4182 head revision, and the current branch contains exactly one other
4183 head, the other head is merged with by default. Otherwise, an
4183 head, the other head is merged with by default. Otherwise, an
4184 explicit revision with which to merge with must be provided.
4184 explicit revision with which to merge with must be provided.
4185
4185
4186 :hg:`resolve` must be used to resolve unresolved files.
4186 :hg:`resolve` must be used to resolve unresolved files.
4187
4187
4188 To undo an uncommitted merge, use :hg:`update --clean .` which
4188 To undo an uncommitted merge, use :hg:`update --clean .` which
4189 will check out a clean copy of the original merge parent, losing
4189 will check out a clean copy of the original merge parent, losing
4190 all changes.
4190 all changes.
4191
4191
4192 Returns 0 on success, 1 if there are unresolved files.
4192 Returns 0 on success, 1 if there are unresolved files.
4193 """
4193 """
4194
4194
4195 if opts.get('rev') and node:
4195 if opts.get('rev') and node:
4196 raise util.Abort(_("please specify just one revision"))
4196 raise util.Abort(_("please specify just one revision"))
4197 if not node:
4197 if not node:
4198 node = opts.get('rev')
4198 node = opts.get('rev')
4199
4199
4200 if node:
4200 if node:
4201 node = scmutil.revsingle(repo, node).node()
4201 node = scmutil.revsingle(repo, node).node()
4202
4202
4203 if not node and repo._bookmarkcurrent:
4203 if not node and repo._bookmarkcurrent:
4204 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4204 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4205 curhead = repo[repo._bookmarkcurrent].node()
4205 curhead = repo[repo._bookmarkcurrent].node()
4206 if len(bmheads) == 2:
4206 if len(bmheads) == 2:
4207 if curhead == bmheads[0]:
4207 if curhead == bmheads[0]:
4208 node = bmheads[1]
4208 node = bmheads[1]
4209 else:
4209 else:
4210 node = bmheads[0]
4210 node = bmheads[0]
4211 elif len(bmheads) > 2:
4211 elif len(bmheads) > 2:
4212 raise util.Abort(_("multiple matching bookmarks to merge - "
4212 raise util.Abort(_("multiple matching bookmarks to merge - "
4213 "please merge with an explicit rev or bookmark"),
4213 "please merge with an explicit rev or bookmark"),
4214 hint=_("run 'hg heads' to see all heads"))
4214 hint=_("run 'hg heads' to see all heads"))
4215 elif len(bmheads) <= 1:
4215 elif len(bmheads) <= 1:
4216 raise util.Abort(_("no matching bookmark to merge - "
4216 raise util.Abort(_("no matching bookmark to merge - "
4217 "please merge with an explicit rev or bookmark"),
4217 "please merge with an explicit rev or bookmark"),
4218 hint=_("run 'hg heads' to see all heads"))
4218 hint=_("run 'hg heads' to see all heads"))
4219
4219
4220 if not node and not repo._bookmarkcurrent:
4220 if not node and not repo._bookmarkcurrent:
4221 branch = repo[None].branch()
4221 branch = repo[None].branch()
4222 bheads = repo.branchheads(branch)
4222 bheads = repo.branchheads(branch)
4223 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4223 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4224
4224
4225 if len(nbhs) > 2:
4225 if len(nbhs) > 2:
4226 raise util.Abort(_("branch '%s' has %d heads - "
4226 raise util.Abort(_("branch '%s' has %d heads - "
4227 "please merge with an explicit rev")
4227 "please merge with an explicit rev")
4228 % (branch, len(bheads)),
4228 % (branch, len(bheads)),
4229 hint=_("run 'hg heads .' to see heads"))
4229 hint=_("run 'hg heads .' to see heads"))
4230
4230
4231 parent = repo.dirstate.p1()
4231 parent = repo.dirstate.p1()
4232 if len(nbhs) <= 1:
4232 if len(nbhs) <= 1:
4233 if len(bheads) > 1:
4233 if len(bheads) > 1:
4234 raise util.Abort(_("heads are bookmarked - "
4234 raise util.Abort(_("heads are bookmarked - "
4235 "please merge with an explicit rev"),
4235 "please merge with an explicit rev"),
4236 hint=_("run 'hg heads' to see all heads"))
4236 hint=_("run 'hg heads' to see all heads"))
4237 if len(repo.heads()) > 1:
4237 if len(repo.heads()) > 1:
4238 raise util.Abort(_("branch '%s' has one head - "
4238 raise util.Abort(_("branch '%s' has one head - "
4239 "please merge with an explicit rev")
4239 "please merge with an explicit rev")
4240 % branch,
4240 % branch,
4241 hint=_("run 'hg heads' to see all heads"))
4241 hint=_("run 'hg heads' to see all heads"))
4242 msg, hint = _('nothing to merge'), None
4242 msg, hint = _('nothing to merge'), None
4243 if parent != repo.lookup(branch):
4243 if parent != repo.lookup(branch):
4244 hint = _("use 'hg update' instead")
4244 hint = _("use 'hg update' instead")
4245 raise util.Abort(msg, hint=hint)
4245 raise util.Abort(msg, hint=hint)
4246
4246
4247 if parent not in bheads:
4247 if parent not in bheads:
4248 raise util.Abort(_('working directory not at a head revision'),
4248 raise util.Abort(_('working directory not at a head revision'),
4249 hint=_("use 'hg update' or merge with an "
4249 hint=_("use 'hg update' or merge with an "
4250 "explicit revision"))
4250 "explicit revision"))
4251 if parent == nbhs[0]:
4251 if parent == nbhs[0]:
4252 node = nbhs[-1]
4252 node = nbhs[-1]
4253 else:
4253 else:
4254 node = nbhs[0]
4254 node = nbhs[0]
4255
4255
4256 if opts.get('preview'):
4256 if opts.get('preview'):
4257 # find nodes that are ancestors of p2 but not of p1
4257 # find nodes that are ancestors of p2 but not of p1
4258 p1 = repo.lookup('.')
4258 p1 = repo.lookup('.')
4259 p2 = repo.lookup(node)
4259 p2 = repo.lookup(node)
4260 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4260 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4261
4261
4262 displayer = cmdutil.show_changeset(ui, repo, opts)
4262 displayer = cmdutil.show_changeset(ui, repo, opts)
4263 for node in nodes:
4263 for node in nodes:
4264 displayer.show(repo[node])
4264 displayer.show(repo[node])
4265 displayer.close()
4265 displayer.close()
4266 return 0
4266 return 0
4267
4267
4268 try:
4268 try:
4269 # ui.forcemerge is an internal variable, do not document
4269 # ui.forcemerge is an internal variable, do not document
4270 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4270 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4271 return hg.merge(repo, node, force=opts.get('force'))
4271 return hg.merge(repo, node, force=opts.get('force'))
4272 finally:
4272 finally:
4273 ui.setconfig('ui', 'forcemerge', '')
4273 ui.setconfig('ui', 'forcemerge', '')
4274
4274
4275 @command('outgoing|out',
4275 @command('outgoing|out',
4276 [('f', 'force', None, _('run even when the destination is unrelated')),
4276 [('f', 'force', None, _('run even when the destination is unrelated')),
4277 ('r', 'rev', [],
4277 ('r', 'rev', [],
4278 _('a changeset intended to be included in the destination'), _('REV')),
4278 _('a changeset intended to be included in the destination'), _('REV')),
4279 ('n', 'newest-first', None, _('show newest record first')),
4279 ('n', 'newest-first', None, _('show newest record first')),
4280 ('B', 'bookmarks', False, _('compare bookmarks')),
4280 ('B', 'bookmarks', False, _('compare bookmarks')),
4281 ('b', 'branch', [], _('a specific branch you would like to push'),
4281 ('b', 'branch', [], _('a specific branch you would like to push'),
4282 _('BRANCH')),
4282 _('BRANCH')),
4283 ] + logopts + remoteopts + subrepoopts,
4283 ] + logopts + remoteopts + subrepoopts,
4284 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4284 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4285 def outgoing(ui, repo, dest=None, **opts):
4285 def outgoing(ui, repo, dest=None, **opts):
4286 """show changesets not found in the destination
4286 """show changesets not found in the destination
4287
4287
4288 Show changesets not found in the specified destination repository
4288 Show changesets not found in the specified destination repository
4289 or the default push location. These are the changesets that would
4289 or the default push location. These are the changesets that would
4290 be pushed if a push was requested.
4290 be pushed if a push was requested.
4291
4291
4292 See pull for details of valid destination formats.
4292 See pull for details of valid destination formats.
4293
4293
4294 Returns 0 if there are outgoing changes, 1 otherwise.
4294 Returns 0 if there are outgoing changes, 1 otherwise.
4295 """
4295 """
4296 if opts.get('graph'):
4296 if opts.get('graph'):
4297 cmdutil.checkunsupportedgraphflags([], opts)
4297 cmdutil.checkunsupportedgraphflags([], opts)
4298 o = hg._outgoing(ui, repo, dest, opts)
4298 o = hg._outgoing(ui, repo, dest, opts)
4299 if o is None:
4299 if o is None:
4300 return
4300 return
4301
4301
4302 revdag = cmdutil.graphrevs(repo, o, opts)
4302 revdag = cmdutil.graphrevs(repo, o, opts)
4303 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4303 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4304 showparents = [ctx.node() for ctx in repo[None].parents()]
4304 showparents = [ctx.node() for ctx in repo[None].parents()]
4305 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4305 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4306 graphmod.asciiedges)
4306 graphmod.asciiedges)
4307 return 0
4307 return 0
4308
4308
4309 if opts.get('bookmarks'):
4309 if opts.get('bookmarks'):
4310 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4310 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4311 dest, branches = hg.parseurl(dest, opts.get('branch'))
4311 dest, branches = hg.parseurl(dest, opts.get('branch'))
4312 other = hg.peer(repo, opts, dest)
4312 other = hg.peer(repo, opts, dest)
4313 if 'bookmarks' not in other.listkeys('namespaces'):
4313 if 'bookmarks' not in other.listkeys('namespaces'):
4314 ui.warn(_("remote doesn't support bookmarks\n"))
4314 ui.warn(_("remote doesn't support bookmarks\n"))
4315 return 0
4315 return 0
4316 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4316 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4317 return bookmarks.diff(ui, other, repo)
4317 return bookmarks.diff(ui, other, repo)
4318
4318
4319 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4319 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4320 try:
4320 try:
4321 return hg.outgoing(ui, repo, dest, opts)
4321 return hg.outgoing(ui, repo, dest, opts)
4322 finally:
4322 finally:
4323 del repo._subtoppath
4323 del repo._subtoppath
4324
4324
4325 @command('parents',
4325 @command('parents',
4326 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4326 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4327 ] + templateopts,
4327 ] + templateopts,
4328 _('[-r REV] [FILE]'))
4328 _('[-r REV] [FILE]'))
4329 def parents(ui, repo, file_=None, **opts):
4329 def parents(ui, repo, file_=None, **opts):
4330 """show the parents of the working directory or revision
4330 """show the parents of the working directory or revision
4331
4331
4332 Print the working directory's parent revisions. If a revision is
4332 Print the working directory's parent revisions. If a revision is
4333 given via -r/--rev, the parent of that revision will be printed.
4333 given via -r/--rev, the parent of that revision will be printed.
4334 If a file argument is given, the revision in which the file was
4334 If a file argument is given, the revision in which the file was
4335 last changed (before the working directory revision or the
4335 last changed (before the working directory revision or the
4336 argument to --rev if given) is printed.
4336 argument to --rev if given) is printed.
4337
4337
4338 Returns 0 on success.
4338 Returns 0 on success.
4339 """
4339 """
4340
4340
4341 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4341 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4342
4342
4343 if file_:
4343 if file_:
4344 m = scmutil.match(ctx, (file_,), opts)
4344 m = scmutil.match(ctx, (file_,), opts)
4345 if m.anypats() or len(m.files()) != 1:
4345 if m.anypats() or len(m.files()) != 1:
4346 raise util.Abort(_('can only specify an explicit filename'))
4346 raise util.Abort(_('can only specify an explicit filename'))
4347 file_ = m.files()[0]
4347 file_ = m.files()[0]
4348 filenodes = []
4348 filenodes = []
4349 for cp in ctx.parents():
4349 for cp in ctx.parents():
4350 if not cp:
4350 if not cp:
4351 continue
4351 continue
4352 try:
4352 try:
4353 filenodes.append(cp.filenode(file_))
4353 filenodes.append(cp.filenode(file_))
4354 except error.LookupError:
4354 except error.LookupError:
4355 pass
4355 pass
4356 if not filenodes:
4356 if not filenodes:
4357 raise util.Abort(_("'%s' not found in manifest!") % file_)
4357 raise util.Abort(_("'%s' not found in manifest!") % file_)
4358 p = []
4358 p = []
4359 for fn in filenodes:
4359 for fn in filenodes:
4360 fctx = repo.filectx(file_, fileid=fn)
4360 fctx = repo.filectx(file_, fileid=fn)
4361 p.append(fctx.node())
4361 p.append(fctx.node())
4362 else:
4362 else:
4363 p = [cp.node() for cp in ctx.parents()]
4363 p = [cp.node() for cp in ctx.parents()]
4364
4364
4365 displayer = cmdutil.show_changeset(ui, repo, opts)
4365 displayer = cmdutil.show_changeset(ui, repo, opts)
4366 for n in p:
4366 for n in p:
4367 if n != nullid:
4367 if n != nullid:
4368 displayer.show(repo[n])
4368 displayer.show(repo[n])
4369 displayer.close()
4369 displayer.close()
4370
4370
4371 @command('paths', [], _('[NAME]'))
4371 @command('paths', [], _('[NAME]'))
4372 def paths(ui, repo, search=None):
4372 def paths(ui, repo, search=None):
4373 """show aliases for remote repositories
4373 """show aliases for remote repositories
4374
4374
4375 Show definition of symbolic path name NAME. If no name is given,
4375 Show definition of symbolic path name NAME. If no name is given,
4376 show definition of all available names.
4376 show definition of all available names.
4377
4377
4378 Option -q/--quiet suppresses all output when searching for NAME
4378 Option -q/--quiet suppresses all output when searching for NAME
4379 and shows only the path names when listing all definitions.
4379 and shows only the path names when listing all definitions.
4380
4380
4381 Path names are defined in the [paths] section of your
4381 Path names are defined in the [paths] section of your
4382 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4382 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4383 repository, ``.hg/hgrc`` is used, too.
4383 repository, ``.hg/hgrc`` is used, too.
4384
4384
4385 The path names ``default`` and ``default-push`` have a special
4385 The path names ``default`` and ``default-push`` have a special
4386 meaning. When performing a push or pull operation, they are used
4386 meaning. When performing a push or pull operation, they are used
4387 as fallbacks if no location is specified on the command-line.
4387 as fallbacks if no location is specified on the command-line.
4388 When ``default-push`` is set, it will be used for push and
4388 When ``default-push`` is set, it will be used for push and
4389 ``default`` will be used for pull; otherwise ``default`` is used
4389 ``default`` will be used for pull; otherwise ``default`` is used
4390 as the fallback for both. When cloning a repository, the clone
4390 as the fallback for both. When cloning a repository, the clone
4391 source is written as ``default`` in ``.hg/hgrc``. Note that
4391 source is written as ``default`` in ``.hg/hgrc``. Note that
4392 ``default`` and ``default-push`` apply to all inbound (e.g.
4392 ``default`` and ``default-push`` apply to all inbound (e.g.
4393 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4393 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4394 :hg:`bundle`) operations.
4394 :hg:`bundle`) operations.
4395
4395
4396 See :hg:`help urls` for more information.
4396 See :hg:`help urls` for more information.
4397
4397
4398 Returns 0 on success.
4398 Returns 0 on success.
4399 """
4399 """
4400 if search:
4400 if search:
4401 for name, path in ui.configitems("paths"):
4401 for name, path in ui.configitems("paths"):
4402 if name == search:
4402 if name == search:
4403 ui.status("%s\n" % util.hidepassword(path))
4403 ui.status("%s\n" % util.hidepassword(path))
4404 return
4404 return
4405 if not ui.quiet:
4405 if not ui.quiet:
4406 ui.warn(_("not found!\n"))
4406 ui.warn(_("not found!\n"))
4407 return 1
4407 return 1
4408 else:
4408 else:
4409 for name, path in ui.configitems("paths"):
4409 for name, path in ui.configitems("paths"):
4410 if ui.quiet:
4410 if ui.quiet:
4411 ui.write("%s\n" % name)
4411 ui.write("%s\n" % name)
4412 else:
4412 else:
4413 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4413 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4414
4414
4415 @command('phase',
4415 @command('phase',
4416 [('p', 'public', False, _('set changeset phase to public')),
4416 [('p', 'public', False, _('set changeset phase to public')),
4417 ('d', 'draft', False, _('set changeset phase to draft')),
4417 ('d', 'draft', False, _('set changeset phase to draft')),
4418 ('s', 'secret', False, _('set changeset phase to secret')),
4418 ('s', 'secret', False, _('set changeset phase to secret')),
4419 ('f', 'force', False, _('allow to move boundary backward')),
4419 ('f', 'force', False, _('allow to move boundary backward')),
4420 ('r', 'rev', [], _('target revision'), _('REV')),
4420 ('r', 'rev', [], _('target revision'), _('REV')),
4421 ],
4421 ],
4422 _('[-p|-d|-s] [-f] [-r] REV...'))
4422 _('[-p|-d|-s] [-f] [-r] REV...'))
4423 def phase(ui, repo, *revs, **opts):
4423 def phase(ui, repo, *revs, **opts):
4424 """set or show the current phase name
4424 """set or show the current phase name
4425
4425
4426 With no argument, show the phase name of specified revisions.
4426 With no argument, show the phase name of specified revisions.
4427
4427
4428 With one of -p/--public, -d/--draft or -s/--secret, change the
4428 With one of -p/--public, -d/--draft or -s/--secret, change the
4429 phase value of the specified revisions.
4429 phase value of the specified revisions.
4430
4430
4431 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4431 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4432 lower phase to an higher phase. Phases are ordered as follows::
4432 lower phase to an higher phase. Phases are ordered as follows::
4433
4433
4434 public < draft < secret
4434 public < draft < secret
4435
4435
4436 Return 0 on success, 1 if no phases were changed or some could not
4436 Return 0 on success, 1 if no phases were changed or some could not
4437 be changed.
4437 be changed.
4438 """
4438 """
4439 # search for a unique phase argument
4439 # search for a unique phase argument
4440 targetphase = None
4440 targetphase = None
4441 for idx, name in enumerate(phases.phasenames):
4441 for idx, name in enumerate(phases.phasenames):
4442 if opts[name]:
4442 if opts[name]:
4443 if targetphase is not None:
4443 if targetphase is not None:
4444 raise util.Abort(_('only one phase can be specified'))
4444 raise util.Abort(_('only one phase can be specified'))
4445 targetphase = idx
4445 targetphase = idx
4446
4446
4447 # look for specified revision
4447 # look for specified revision
4448 revs = list(revs)
4448 revs = list(revs)
4449 revs.extend(opts['rev'])
4449 revs.extend(opts['rev'])
4450 if not revs:
4450 if not revs:
4451 raise util.Abort(_('no revisions specified'))
4451 raise util.Abort(_('no revisions specified'))
4452
4452
4453 revs = scmutil.revrange(repo, revs)
4453 revs = scmutil.revrange(repo, revs)
4454
4454
4455 lock = None
4455 lock = None
4456 ret = 0
4456 ret = 0
4457 if targetphase is None:
4457 if targetphase is None:
4458 # display
4458 # display
4459 for r in revs:
4459 for r in revs:
4460 ctx = repo[r]
4460 ctx = repo[r]
4461 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4461 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4462 else:
4462 else:
4463 lock = repo.lock()
4463 lock = repo.lock()
4464 try:
4464 try:
4465 # set phase
4465 # set phase
4466 if not revs:
4466 if not revs:
4467 raise util.Abort(_('empty revision set'))
4467 raise util.Abort(_('empty revision set'))
4468 nodes = [repo[r].node() for r in revs]
4468 nodes = [repo[r].node() for r in revs]
4469 olddata = repo._phasecache.getphaserevs(repo)[:]
4469 olddata = repo._phasecache.getphaserevs(repo)[:]
4470 phases.advanceboundary(repo, targetphase, nodes)
4470 phases.advanceboundary(repo, targetphase, nodes)
4471 if opts['force']:
4471 if opts['force']:
4472 phases.retractboundary(repo, targetphase, nodes)
4472 phases.retractboundary(repo, targetphase, nodes)
4473 finally:
4473 finally:
4474 lock.release()
4474 lock.release()
4475 # moving revision from public to draft may hide them
4475 # moving revision from public to draft may hide them
4476 # We have to check result on an unfiltered repository
4476 # We have to check result on an unfiltered repository
4477 unfi = repo.unfiltered()
4477 unfi = repo.unfiltered()
4478 newdata = repo._phasecache.getphaserevs(unfi)
4478 newdata = repo._phasecache.getphaserevs(unfi)
4479 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4479 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4480 cl = unfi.changelog
4480 cl = unfi.changelog
4481 rejected = [n for n in nodes
4481 rejected = [n for n in nodes
4482 if newdata[cl.rev(n)] < targetphase]
4482 if newdata[cl.rev(n)] < targetphase]
4483 if rejected:
4483 if rejected:
4484 ui.warn(_('cannot move %i changesets to a more permissive '
4484 ui.warn(_('cannot move %i changesets to a more permissive '
4485 'phase, use --force\n') % len(rejected))
4485 'phase, use --force\n') % len(rejected))
4486 ret = 1
4486 ret = 1
4487 if changes:
4487 if changes:
4488 msg = _('phase changed for %i changesets\n') % changes
4488 msg = _('phase changed for %i changesets\n') % changes
4489 if ret:
4489 if ret:
4490 ui.status(msg)
4490 ui.status(msg)
4491 else:
4491 else:
4492 ui.note(msg)
4492 ui.note(msg)
4493 else:
4493 else:
4494 ui.warn(_('no phases changed\n'))
4494 ui.warn(_('no phases changed\n'))
4495 ret = 1
4495 ret = 1
4496 return ret
4496 return ret
4497
4497
4498 def postincoming(ui, repo, modheads, optupdate, checkout):
4498 def postincoming(ui, repo, modheads, optupdate, checkout):
4499 if modheads == 0:
4499 if modheads == 0:
4500 return
4500 return
4501 if optupdate:
4501 if optupdate:
4502 movemarkfrom = repo['.'].node()
4502 movemarkfrom = repo['.'].node()
4503 try:
4503 try:
4504 ret = hg.update(repo, checkout)
4504 ret = hg.update(repo, checkout)
4505 except util.Abort, inst:
4505 except util.Abort, inst:
4506 ui.warn(_("not updating: %s\n") % str(inst))
4506 ui.warn(_("not updating: %s\n") % str(inst))
4507 return 0
4507 return 0
4508 if not ret and not checkout:
4508 if not ret and not checkout:
4509 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4509 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4510 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4510 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4511 return ret
4511 return ret
4512 if modheads > 1:
4512 if modheads > 1:
4513 currentbranchheads = len(repo.branchheads())
4513 currentbranchheads = len(repo.branchheads())
4514 if currentbranchheads == modheads:
4514 if currentbranchheads == modheads:
4515 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4515 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4516 elif currentbranchheads > 1:
4516 elif currentbranchheads > 1:
4517 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4517 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4518 "merge)\n"))
4518 "merge)\n"))
4519 else:
4519 else:
4520 ui.status(_("(run 'hg heads' to see heads)\n"))
4520 ui.status(_("(run 'hg heads' to see heads)\n"))
4521 else:
4521 else:
4522 ui.status(_("(run 'hg update' to get a working copy)\n"))
4522 ui.status(_("(run 'hg update' to get a working copy)\n"))
4523
4523
4524 @command('^pull',
4524 @command('^pull',
4525 [('u', 'update', None,
4525 [('u', 'update', None,
4526 _('update to new branch head if changesets were pulled')),
4526 _('update to new branch head if changesets were pulled')),
4527 ('f', 'force', None, _('run even when remote repository is unrelated')),
4527 ('f', 'force', None, _('run even when remote repository is unrelated')),
4528 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4528 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4529 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4529 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4530 ('b', 'branch', [], _('a specific branch you would like to pull'),
4530 ('b', 'branch', [], _('a specific branch you would like to pull'),
4531 _('BRANCH')),
4531 _('BRANCH')),
4532 ] + remoteopts,
4532 ] + remoteopts,
4533 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4533 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4534 def pull(ui, repo, source="default", **opts):
4534 def pull(ui, repo, source="default", **opts):
4535 """pull changes from the specified source
4535 """pull changes from the specified source
4536
4536
4537 Pull changes from a remote repository to a local one.
4537 Pull changes from a remote repository to a local one.
4538
4538
4539 This finds all changes from the repository at the specified path
4539 This finds all changes from the repository at the specified path
4540 or URL and adds them to a local repository (the current one unless
4540 or URL and adds them to a local repository (the current one unless
4541 -R is specified). By default, this does not update the copy of the
4541 -R is specified). By default, this does not update the copy of the
4542 project in the working directory.
4542 project in the working directory.
4543
4543
4544 Use :hg:`incoming` if you want to see what would have been added
4544 Use :hg:`incoming` if you want to see what would have been added
4545 by a pull at the time you issued this command. If you then decide
4545 by a pull at the time you issued this command. If you then decide
4546 to add those changes to the repository, you should use :hg:`pull
4546 to add those changes to the repository, you should use :hg:`pull
4547 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4547 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4548
4548
4549 If SOURCE is omitted, the 'default' path will be used.
4549 If SOURCE is omitted, the 'default' path will be used.
4550 See :hg:`help urls` for more information.
4550 See :hg:`help urls` for more information.
4551
4551
4552 Returns 0 on success, 1 if an update had unresolved files.
4552 Returns 0 on success, 1 if an update had unresolved files.
4553 """
4553 """
4554 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4554 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4555 other = hg.peer(repo, opts, source)
4555 other = hg.peer(repo, opts, source)
4556 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4556 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4557 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4557 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4558
4558
4559 remotebookmarks = other.listkeys('bookmarks')
4559 remotebookmarks = other.listkeys('bookmarks')
4560
4560
4561 if opts.get('bookmark'):
4561 if opts.get('bookmark'):
4562 if not revs:
4562 if not revs:
4563 revs = []
4563 revs = []
4564 for b in opts['bookmark']:
4564 for b in opts['bookmark']:
4565 if b not in remotebookmarks:
4565 if b not in remotebookmarks:
4566 raise util.Abort(_('remote bookmark %s not found!') % b)
4566 raise util.Abort(_('remote bookmark %s not found!') % b)
4567 revs.append(remotebookmarks[b])
4567 revs.append(remotebookmarks[b])
4568
4568
4569 if revs:
4569 if revs:
4570 try:
4570 try:
4571 revs = [other.lookup(rev) for rev in revs]
4571 revs = [other.lookup(rev) for rev in revs]
4572 except error.CapabilityError:
4572 except error.CapabilityError:
4573 err = _("other repository doesn't support revision lookup, "
4573 err = _("other repository doesn't support revision lookup, "
4574 "so a rev cannot be specified.")
4574 "so a rev cannot be specified.")
4575 raise util.Abort(err)
4575 raise util.Abort(err)
4576
4576
4577 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4577 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4578 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4578 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4579 if checkout:
4579 if checkout:
4580 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4580 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4581 repo._subtoppath = source
4581 repo._subtoppath = source
4582 try:
4582 try:
4583 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4583 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4584
4584
4585 finally:
4585 finally:
4586 del repo._subtoppath
4586 del repo._subtoppath
4587
4587
4588 # update specified bookmarks
4588 # update specified bookmarks
4589 if opts.get('bookmark'):
4589 if opts.get('bookmark'):
4590 marks = repo._bookmarks
4590 marks = repo._bookmarks
4591 for b in opts['bookmark']:
4591 for b in opts['bookmark']:
4592 # explicit pull overrides local bookmark if any
4592 # explicit pull overrides local bookmark if any
4593 ui.status(_("importing bookmark %s\n") % b)
4593 ui.status(_("importing bookmark %s\n") % b)
4594 marks[b] = repo[remotebookmarks[b]].node()
4594 marks[b] = repo[remotebookmarks[b]].node()
4595 marks.write()
4595 marks.write()
4596
4596
4597 return ret
4597 return ret
4598
4598
4599 @command('^push',
4599 @command('^push',
4600 [('f', 'force', None, _('force push')),
4600 [('f', 'force', None, _('force push')),
4601 ('r', 'rev', [],
4601 ('r', 'rev', [],
4602 _('a changeset intended to be included in the destination'),
4602 _('a changeset intended to be included in the destination'),
4603 _('REV')),
4603 _('REV')),
4604 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4604 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4605 ('b', 'branch', [],
4605 ('b', 'branch', [],
4606 _('a specific branch you would like to push'), _('BRANCH')),
4606 _('a specific branch you would like to push'), _('BRANCH')),
4607 ('', 'new-branch', False, _('allow pushing a new branch')),
4607 ('', 'new-branch', False, _('allow pushing a new branch')),
4608 ] + remoteopts,
4608 ] + remoteopts,
4609 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4609 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4610 def push(ui, repo, dest=None, **opts):
4610 def push(ui, repo, dest=None, **opts):
4611 """push changes to the specified destination
4611 """push changes to the specified destination
4612
4612
4613 Push changesets from the local repository to the specified
4613 Push changesets from the local repository to the specified
4614 destination.
4614 destination.
4615
4615
4616 This operation is symmetrical to pull: it is identical to a pull
4616 This operation is symmetrical to pull: it is identical to a pull
4617 in the destination repository from the current one.
4617 in the destination repository from the current one.
4618
4618
4619 By default, push will not allow creation of new heads at the
4619 By default, push will not allow creation of new heads at the
4620 destination, since multiple heads would make it unclear which head
4620 destination, since multiple heads would make it unclear which head
4621 to use. In this situation, it is recommended to pull and merge
4621 to use. In this situation, it is recommended to pull and merge
4622 before pushing.
4622 before pushing.
4623
4623
4624 Use --new-branch if you want to allow push to create a new named
4624 Use --new-branch if you want to allow push to create a new named
4625 branch that is not present at the destination. This allows you to
4625 branch that is not present at the destination. This allows you to
4626 only create a new branch without forcing other changes.
4626 only create a new branch without forcing other changes.
4627
4627
4628 Use -f/--force to override the default behavior and push all
4628 Use -f/--force to override the default behavior and push all
4629 changesets on all branches.
4629 changesets on all branches.
4630
4630
4631 If -r/--rev is used, the specified revision and all its ancestors
4631 If -r/--rev is used, the specified revision and all its ancestors
4632 will be pushed to the remote repository.
4632 will be pushed to the remote repository.
4633
4633
4634 If -B/--bookmark is used, the specified bookmarked revision, its
4634 If -B/--bookmark is used, the specified bookmarked revision, its
4635 ancestors, and the bookmark will be pushed to the remote
4635 ancestors, and the bookmark will be pushed to the remote
4636 repository.
4636 repository.
4637
4637
4638 Please see :hg:`help urls` for important details about ``ssh://``
4638 Please see :hg:`help urls` for important details about ``ssh://``
4639 URLs. If DESTINATION is omitted, a default path will be used.
4639 URLs. If DESTINATION is omitted, a default path will be used.
4640
4640
4641 Returns 0 if push was successful, 1 if nothing to push.
4641 Returns 0 if push was successful, 1 if nothing to push.
4642 """
4642 """
4643
4643
4644 if opts.get('bookmark'):
4644 if opts.get('bookmark'):
4645 for b in opts['bookmark']:
4645 for b in opts['bookmark']:
4646 # translate -B options to -r so changesets get pushed
4646 # translate -B options to -r so changesets get pushed
4647 if b in repo._bookmarks:
4647 if b in repo._bookmarks:
4648 opts.setdefault('rev', []).append(b)
4648 opts.setdefault('rev', []).append(b)
4649 else:
4649 else:
4650 # if we try to push a deleted bookmark, translate it to null
4650 # if we try to push a deleted bookmark, translate it to null
4651 # this lets simultaneous -r, -b options continue working
4651 # this lets simultaneous -r, -b options continue working
4652 opts.setdefault('rev', []).append("null")
4652 opts.setdefault('rev', []).append("null")
4653
4653
4654 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4654 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4655 dest, branches = hg.parseurl(dest, opts.get('branch'))
4655 dest, branches = hg.parseurl(dest, opts.get('branch'))
4656 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4656 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4657 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4657 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4658 other = hg.peer(repo, opts, dest)
4658 other = hg.peer(repo, opts, dest)
4659 if revs:
4659 if revs:
4660 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4660 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4661
4661
4662 repo._subtoppath = dest
4662 repo._subtoppath = dest
4663 try:
4663 try:
4664 # push subrepos depth-first for coherent ordering
4664 # push subrepos depth-first for coherent ordering
4665 c = repo['']
4665 c = repo['']
4666 subs = c.substate # only repos that are committed
4666 subs = c.substate # only repos that are committed
4667 for s in sorted(subs):
4667 for s in sorted(subs):
4668 if c.sub(s).push(opts) == 0:
4668 if c.sub(s).push(opts) == 0:
4669 return False
4669 return False
4670 finally:
4670 finally:
4671 del repo._subtoppath
4671 del repo._subtoppath
4672 result = repo.push(other, opts.get('force'), revs=revs,
4672 result = repo.push(other, opts.get('force'), revs=revs,
4673 newbranch=opts.get('new_branch'))
4673 newbranch=opts.get('new_branch'))
4674
4674
4675 result = not result
4675 result = not result
4676
4676
4677 if opts.get('bookmark'):
4677 if opts.get('bookmark'):
4678 rb = other.listkeys('bookmarks')
4678 rb = other.listkeys('bookmarks')
4679 for b in opts['bookmark']:
4679 for b in opts['bookmark']:
4680 # explicit push overrides remote bookmark if any
4680 # explicit push overrides remote bookmark if any
4681 if b in repo._bookmarks:
4681 if b in repo._bookmarks:
4682 ui.status(_("exporting bookmark %s\n") % b)
4682 ui.status(_("exporting bookmark %s\n") % b)
4683 new = repo[b].hex()
4683 new = repo[b].hex()
4684 elif b in rb:
4684 elif b in rb:
4685 ui.status(_("deleting remote bookmark %s\n") % b)
4685 ui.status(_("deleting remote bookmark %s\n") % b)
4686 new = '' # delete
4686 new = '' # delete
4687 else:
4687 else:
4688 ui.warn(_('bookmark %s does not exist on the local '
4688 ui.warn(_('bookmark %s does not exist on the local '
4689 'or remote repository!\n') % b)
4689 'or remote repository!\n') % b)
4690 return 2
4690 return 2
4691 old = rb.get(b, '')
4691 old = rb.get(b, '')
4692 r = other.pushkey('bookmarks', b, old, new)
4692 r = other.pushkey('bookmarks', b, old, new)
4693 if not r:
4693 if not r:
4694 ui.warn(_('updating bookmark %s failed!\n') % b)
4694 ui.warn(_('updating bookmark %s failed!\n') % b)
4695 if not result:
4695 if not result:
4696 result = 2
4696 result = 2
4697
4697
4698 return result
4698 return result
4699
4699
4700 @command('recover', [])
4700 @command('recover', [])
4701 def recover(ui, repo):
4701 def recover(ui, repo):
4702 """roll back an interrupted transaction
4702 """roll back an interrupted transaction
4703
4703
4704 Recover from an interrupted commit or pull.
4704 Recover from an interrupted commit or pull.
4705
4705
4706 This command tries to fix the repository status after an
4706 This command tries to fix the repository status after an
4707 interrupted operation. It should only be necessary when Mercurial
4707 interrupted operation. It should only be necessary when Mercurial
4708 suggests it.
4708 suggests it.
4709
4709
4710 Returns 0 if successful, 1 if nothing to recover or verify fails.
4710 Returns 0 if successful, 1 if nothing to recover or verify fails.
4711 """
4711 """
4712 if repo.recover():
4712 if repo.recover():
4713 return hg.verify(repo)
4713 return hg.verify(repo)
4714 return 1
4714 return 1
4715
4715
4716 @command('^remove|rm',
4716 @command('^remove|rm',
4717 [('A', 'after', None, _('record delete for missing files')),
4717 [('A', 'after', None, _('record delete for missing files')),
4718 ('f', 'force', None,
4718 ('f', 'force', None,
4719 _('remove (and delete) file even if added or modified')),
4719 _('remove (and delete) file even if added or modified')),
4720 ] + walkopts,
4720 ] + walkopts,
4721 _('[OPTION]... FILE...'))
4721 _('[OPTION]... FILE...'))
4722 def remove(ui, repo, *pats, **opts):
4722 def remove(ui, repo, *pats, **opts):
4723 """remove the specified files on the next commit
4723 """remove the specified files on the next commit
4724
4724
4725 Schedule the indicated files for removal from the current branch.
4725 Schedule the indicated files for removal from the current branch.
4726
4726
4727 This command schedules the files to be removed at the next commit.
4727 This command schedules the files to be removed at the next commit.
4728 To undo a remove before that, see :hg:`revert`. To undo added
4728 To undo a remove before that, see :hg:`revert`. To undo added
4729 files, see :hg:`forget`.
4729 files, see :hg:`forget`.
4730
4730
4731 .. container:: verbose
4731 .. container:: verbose
4732
4732
4733 -A/--after can be used to remove only files that have already
4733 -A/--after can be used to remove only files that have already
4734 been deleted, -f/--force can be used to force deletion, and -Af
4734 been deleted, -f/--force can be used to force deletion, and -Af
4735 can be used to remove files from the next revision without
4735 can be used to remove files from the next revision without
4736 deleting them from the working directory.
4736 deleting them from the working directory.
4737
4737
4738 The following table details the behavior of remove for different
4738 The following table details the behavior of remove for different
4739 file states (columns) and option combinations (rows). The file
4739 file states (columns) and option combinations (rows). The file
4740 states are Added [A], Clean [C], Modified [M] and Missing [!]
4740 states are Added [A], Clean [C], Modified [M] and Missing [!]
4741 (as reported by :hg:`status`). The actions are Warn, Remove
4741 (as reported by :hg:`status`). The actions are Warn, Remove
4742 (from branch) and Delete (from disk):
4742 (from branch) and Delete (from disk):
4743
4743
4744 ======= == == == ==
4744 ======= == == == ==
4745 A C M !
4745 A C M !
4746 ======= == == == ==
4746 ======= == == == ==
4747 none W RD W R
4747 none W RD W R
4748 -f R RD RD R
4748 -f R RD RD R
4749 -A W W W R
4749 -A W W W R
4750 -Af R R R R
4750 -Af R R R R
4751 ======= == == == ==
4751 ======= == == == ==
4752
4752
4753 Note that remove never deletes files in Added [A] state from the
4753 Note that remove never deletes files in Added [A] state from the
4754 working directory, not even if option --force is specified.
4754 working directory, not even if option --force is specified.
4755
4755
4756 Returns 0 on success, 1 if any warnings encountered.
4756 Returns 0 on success, 1 if any warnings encountered.
4757 """
4757 """
4758
4758
4759 ret = 0
4759 ret = 0
4760 after, force = opts.get('after'), opts.get('force')
4760 after, force = opts.get('after'), opts.get('force')
4761 if not pats and not after:
4761 if not pats and not after:
4762 raise util.Abort(_('no files specified'))
4762 raise util.Abort(_('no files specified'))
4763
4763
4764 m = scmutil.match(repo[None], pats, opts)
4764 m = scmutil.match(repo[None], pats, opts)
4765 s = repo.status(match=m, clean=True)
4765 s = repo.status(match=m, clean=True)
4766 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4766 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4767
4767
4768 # warn about failure to delete explicit files/dirs
4768 # warn about failure to delete explicit files/dirs
4769 wctx = repo[None]
4769 wctx = repo[None]
4770 for f in m.files():
4770 for f in m.files():
4771 if f in repo.dirstate or f in wctx.dirs():
4771 if f in repo.dirstate or f in wctx.dirs():
4772 continue
4772 continue
4773 if os.path.exists(m.rel(f)):
4773 if os.path.exists(m.rel(f)):
4774 if os.path.isdir(m.rel(f)):
4774 if os.path.isdir(m.rel(f)):
4775 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4775 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4776 else:
4776 else:
4777 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4777 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4778 # missing files will generate a warning elsewhere
4778 # missing files will generate a warning elsewhere
4779 ret = 1
4779 ret = 1
4780
4780
4781 if force:
4781 if force:
4782 list = modified + deleted + clean + added
4782 list = modified + deleted + clean + added
4783 elif after:
4783 elif after:
4784 list = deleted
4784 list = deleted
4785 for f in modified + added + clean:
4785 for f in modified + added + clean:
4786 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4786 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4787 ret = 1
4787 ret = 1
4788 else:
4788 else:
4789 list = deleted + clean
4789 list = deleted + clean
4790 for f in modified:
4790 for f in modified:
4791 ui.warn(_('not removing %s: file is modified (use -f'
4791 ui.warn(_('not removing %s: file is modified (use -f'
4792 ' to force removal)\n') % m.rel(f))
4792 ' to force removal)\n') % m.rel(f))
4793 ret = 1
4793 ret = 1
4794 for f in added:
4794 for f in added:
4795 ui.warn(_('not removing %s: file has been marked for add'
4795 ui.warn(_('not removing %s: file has been marked for add'
4796 ' (use forget to undo)\n') % m.rel(f))
4796 ' (use forget to undo)\n') % m.rel(f))
4797 ret = 1
4797 ret = 1
4798
4798
4799 for f in sorted(list):
4799 for f in sorted(list):
4800 if ui.verbose or not m.exact(f):
4800 if ui.verbose or not m.exact(f):
4801 ui.status(_('removing %s\n') % m.rel(f))
4801 ui.status(_('removing %s\n') % m.rel(f))
4802
4802
4803 wlock = repo.wlock()
4803 wlock = repo.wlock()
4804 try:
4804 try:
4805 if not after:
4805 if not after:
4806 for f in list:
4806 for f in list:
4807 if f in added:
4807 if f in added:
4808 continue # we never unlink added files on remove
4808 continue # we never unlink added files on remove
4809 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4809 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4810 repo[None].forget(list)
4810 repo[None].forget(list)
4811 finally:
4811 finally:
4812 wlock.release()
4812 wlock.release()
4813
4813
4814 return ret
4814 return ret
4815
4815
4816 @command('rename|move|mv',
4816 @command('rename|move|mv',
4817 [('A', 'after', None, _('record a rename that has already occurred')),
4817 [('A', 'after', None, _('record a rename that has already occurred')),
4818 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4818 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4819 ] + walkopts + dryrunopts,
4819 ] + walkopts + dryrunopts,
4820 _('[OPTION]... SOURCE... DEST'))
4820 _('[OPTION]... SOURCE... DEST'))
4821 def rename(ui, repo, *pats, **opts):
4821 def rename(ui, repo, *pats, **opts):
4822 """rename files; equivalent of copy + remove
4822 """rename files; equivalent of copy + remove
4823
4823
4824 Mark dest as copies of sources; mark sources for deletion. If dest
4824 Mark dest as copies of sources; mark sources for deletion. If dest
4825 is a directory, copies are put in that directory. If dest is a
4825 is a directory, copies are put in that directory. If dest is a
4826 file, there can only be one source.
4826 file, there can only be one source.
4827
4827
4828 By default, this command copies the contents of files as they
4828 By default, this command copies the contents of files as they
4829 exist in the working directory. If invoked with -A/--after, the
4829 exist in the working directory. If invoked with -A/--after, the
4830 operation is recorded, but no copying is performed.
4830 operation is recorded, but no copying is performed.
4831
4831
4832 This command takes effect at the next commit. To undo a rename
4832 This command takes effect at the next commit. To undo a rename
4833 before that, see :hg:`revert`.
4833 before that, see :hg:`revert`.
4834
4834
4835 Returns 0 on success, 1 if errors are encountered.
4835 Returns 0 on success, 1 if errors are encountered.
4836 """
4836 """
4837 wlock = repo.wlock(False)
4837 wlock = repo.wlock(False)
4838 try:
4838 try:
4839 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4839 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4840 finally:
4840 finally:
4841 wlock.release()
4841 wlock.release()
4842
4842
4843 @command('resolve',
4843 @command('resolve',
4844 [('a', 'all', None, _('select all unresolved files')),
4844 [('a', 'all', None, _('select all unresolved files')),
4845 ('l', 'list', None, _('list state of files needing merge')),
4845 ('l', 'list', None, _('list state of files needing merge')),
4846 ('m', 'mark', None, _('mark files as resolved')),
4846 ('m', 'mark', None, _('mark files as resolved')),
4847 ('u', 'unmark', None, _('mark files as unresolved')),
4847 ('u', 'unmark', None, _('mark files as unresolved')),
4848 ('n', 'no-status', None, _('hide status prefix'))]
4848 ('n', 'no-status', None, _('hide status prefix'))]
4849 + mergetoolopts + walkopts,
4849 + mergetoolopts + walkopts,
4850 _('[OPTION]... [FILE]...'))
4850 _('[OPTION]... [FILE]...'))
4851 def resolve(ui, repo, *pats, **opts):
4851 def resolve(ui, repo, *pats, **opts):
4852 """redo merges or set/view the merge status of files
4852 """redo merges or set/view the merge status of files
4853
4853
4854 Merges with unresolved conflicts are often the result of
4854 Merges with unresolved conflicts are often the result of
4855 non-interactive merging using the ``internal:merge`` configuration
4855 non-interactive merging using the ``internal:merge`` configuration
4856 setting, or a command-line merge tool like ``diff3``. The resolve
4856 setting, or a command-line merge tool like ``diff3``. The resolve
4857 command is used to manage the files involved in a merge, after
4857 command is used to manage the files involved in a merge, after
4858 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4858 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4859 working directory must have two parents). See :hg:`help
4859 working directory must have two parents). See :hg:`help
4860 merge-tools` for information on configuring merge tools.
4860 merge-tools` for information on configuring merge tools.
4861
4861
4862 The resolve command can be used in the following ways:
4862 The resolve command can be used in the following ways:
4863
4863
4864 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4864 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4865 files, discarding any previous merge attempts. Re-merging is not
4865 files, discarding any previous merge attempts. Re-merging is not
4866 performed for files already marked as resolved. Use ``--all/-a``
4866 performed for files already marked as resolved. Use ``--all/-a``
4867 to select all unresolved files. ``--tool`` can be used to specify
4867 to select all unresolved files. ``--tool`` can be used to specify
4868 the merge tool used for the given files. It overrides the HGMERGE
4868 the merge tool used for the given files. It overrides the HGMERGE
4869 environment variable and your configuration files. Previous file
4869 environment variable and your configuration files. Previous file
4870 contents are saved with a ``.orig`` suffix.
4870 contents are saved with a ``.orig`` suffix.
4871
4871
4872 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4872 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4873 (e.g. after having manually fixed-up the files). The default is
4873 (e.g. after having manually fixed-up the files). The default is
4874 to mark all unresolved files.
4874 to mark all unresolved files.
4875
4875
4876 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4876 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4877 default is to mark all resolved files.
4877 default is to mark all resolved files.
4878
4878
4879 - :hg:`resolve -l`: list files which had or still have conflicts.
4879 - :hg:`resolve -l`: list files which had or still have conflicts.
4880 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4880 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4881
4881
4882 Note that Mercurial will not let you commit files with unresolved
4882 Note that Mercurial will not let you commit files with unresolved
4883 merge conflicts. You must use :hg:`resolve -m ...` before you can
4883 merge conflicts. You must use :hg:`resolve -m ...` before you can
4884 commit after a conflicting merge.
4884 commit after a conflicting merge.
4885
4885
4886 Returns 0 on success, 1 if any files fail a resolve attempt.
4886 Returns 0 on success, 1 if any files fail a resolve attempt.
4887 """
4887 """
4888
4888
4889 all, mark, unmark, show, nostatus = \
4889 all, mark, unmark, show, nostatus = \
4890 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4890 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4891
4891
4892 if (show and (mark or unmark)) or (mark and unmark):
4892 if (show and (mark or unmark)) or (mark and unmark):
4893 raise util.Abort(_("too many options specified"))
4893 raise util.Abort(_("too many options specified"))
4894 if pats and all:
4894 if pats and all:
4895 raise util.Abort(_("can't specify --all and patterns"))
4895 raise util.Abort(_("can't specify --all and patterns"))
4896 if not (all or pats or show or mark or unmark):
4896 if not (all or pats or show or mark or unmark):
4897 raise util.Abort(_('no files or directories specified; '
4897 raise util.Abort(_('no files or directories specified; '
4898 'use --all to remerge all files'))
4898 'use --all to remerge all files'))
4899
4899
4900 ms = mergemod.mergestate(repo)
4900 ms = mergemod.mergestate(repo)
4901 m = scmutil.match(repo[None], pats, opts)
4901 m = scmutil.match(repo[None], pats, opts)
4902 ret = 0
4902 ret = 0
4903
4903
4904 for f in ms:
4904 for f in ms:
4905 if m(f):
4905 if m(f):
4906 if show:
4906 if show:
4907 if nostatus:
4907 if nostatus:
4908 ui.write("%s\n" % f)
4908 ui.write("%s\n" % f)
4909 else:
4909 else:
4910 ui.write("%s %s\n" % (ms[f].upper(), f),
4910 ui.write("%s %s\n" % (ms[f].upper(), f),
4911 label='resolve.' +
4911 label='resolve.' +
4912 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4912 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4913 elif mark:
4913 elif mark:
4914 ms.mark(f, "r")
4914 ms.mark(f, "r")
4915 elif unmark:
4915 elif unmark:
4916 ms.mark(f, "u")
4916 ms.mark(f, "u")
4917 else:
4917 else:
4918 wctx = repo[None]
4918 wctx = repo[None]
4919 mctx = wctx.parents()[-1]
4919 mctx = wctx.parents()[-1]
4920
4920
4921 # backup pre-resolve (merge uses .orig for its own purposes)
4921 # backup pre-resolve (merge uses .orig for its own purposes)
4922 a = repo.wjoin(f)
4922 a = repo.wjoin(f)
4923 util.copyfile(a, a + ".resolve")
4923 util.copyfile(a, a + ".resolve")
4924
4924
4925 try:
4925 try:
4926 # resolve file
4926 # resolve file
4927 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4927 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4928 if ms.resolve(f, wctx, mctx):
4928 if ms.resolve(f, wctx, mctx):
4929 ret = 1
4929 ret = 1
4930 finally:
4930 finally:
4931 ui.setconfig('ui', 'forcemerge', '')
4931 ui.setconfig('ui', 'forcemerge', '')
4932 ms.commit()
4932 ms.commit()
4933
4933
4934 # replace filemerge's .orig file with our resolve file
4934 # replace filemerge's .orig file with our resolve file
4935 util.rename(a + ".resolve", a + ".orig")
4935 util.rename(a + ".resolve", a + ".orig")
4936
4936
4937 ms.commit()
4937 ms.commit()
4938 return ret
4938 return ret
4939
4939
4940 @command('revert',
4940 @command('revert',
4941 [('a', 'all', None, _('revert all changes when no arguments given')),
4941 [('a', 'all', None, _('revert all changes when no arguments given')),
4942 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4942 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4943 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4943 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4944 ('C', 'no-backup', None, _('do not save backup copies of files')),
4944 ('C', 'no-backup', None, _('do not save backup copies of files')),
4945 ] + walkopts + dryrunopts,
4945 ] + walkopts + dryrunopts,
4946 _('[OPTION]... [-r REV] [NAME]...'))
4946 _('[OPTION]... [-r REV] [NAME]...'))
4947 def revert(ui, repo, *pats, **opts):
4947 def revert(ui, repo, *pats, **opts):
4948 """restore files to their checkout state
4948 """restore files to their checkout state
4949
4949
4950 .. note::
4950 .. note::
4951 To check out earlier revisions, you should use :hg:`update REV`.
4951 To check out earlier revisions, you should use :hg:`update REV`.
4952 To cancel an uncommitted merge (and lose your changes),
4952 To cancel an uncommitted merge (and lose your changes),
4953 use :hg:`update --clean .`.
4953 use :hg:`update --clean .`.
4954
4954
4955 With no revision specified, revert the specified files or directories
4955 With no revision specified, revert the specified files or directories
4956 to the contents they had in the parent of the working directory.
4956 to the contents they had in the parent of the working directory.
4957 This restores the contents of files to an unmodified
4957 This restores the contents of files to an unmodified
4958 state and unschedules adds, removes, copies, and renames. If the
4958 state and unschedules adds, removes, copies, and renames. If the
4959 working directory has two parents, you must explicitly specify a
4959 working directory has two parents, you must explicitly specify a
4960 revision.
4960 revision.
4961
4961
4962 Using the -r/--rev or -d/--date options, revert the given files or
4962 Using the -r/--rev or -d/--date options, revert the given files or
4963 directories to their states as of a specific revision. Because
4963 directories to their states as of a specific revision. Because
4964 revert does not change the working directory parents, this will
4964 revert does not change the working directory parents, this will
4965 cause these files to appear modified. This can be helpful to "back
4965 cause these files to appear modified. This can be helpful to "back
4966 out" some or all of an earlier change. See :hg:`backout` for a
4966 out" some or all of an earlier change. See :hg:`backout` for a
4967 related method.
4967 related method.
4968
4968
4969 Modified files are saved with a .orig suffix before reverting.
4969 Modified files are saved with a .orig suffix before reverting.
4970 To disable these backups, use --no-backup.
4970 To disable these backups, use --no-backup.
4971
4971
4972 See :hg:`help dates` for a list of formats valid for -d/--date.
4972 See :hg:`help dates` for a list of formats valid for -d/--date.
4973
4973
4974 Returns 0 on success.
4974 Returns 0 on success.
4975 """
4975 """
4976
4976
4977 if opts.get("date"):
4977 if opts.get("date"):
4978 if opts.get("rev"):
4978 if opts.get("rev"):
4979 raise util.Abort(_("you can't specify a revision and a date"))
4979 raise util.Abort(_("you can't specify a revision and a date"))
4980 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4980 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4981
4981
4982 parent, p2 = repo.dirstate.parents()
4982 parent, p2 = repo.dirstate.parents()
4983 if not opts.get('rev') and p2 != nullid:
4983 if not opts.get('rev') and p2 != nullid:
4984 # revert after merge is a trap for new users (issue2915)
4984 # revert after merge is a trap for new users (issue2915)
4985 raise util.Abort(_('uncommitted merge with no revision specified'),
4985 raise util.Abort(_('uncommitted merge with no revision specified'),
4986 hint=_('use "hg update" or see "hg help revert"'))
4986 hint=_('use "hg update" or see "hg help revert"'))
4987
4987
4988 ctx = scmutil.revsingle(repo, opts.get('rev'))
4988 ctx = scmutil.revsingle(repo, opts.get('rev'))
4989
4989
4990 if not pats and not opts.get('all'):
4990 if not pats and not opts.get('all'):
4991 msg = _("no files or directories specified")
4991 msg = _("no files or directories specified")
4992 if p2 != nullid:
4992 if p2 != nullid:
4993 hint = _("uncommitted merge, use --all to discard all changes,"
4993 hint = _("uncommitted merge, use --all to discard all changes,"
4994 " or 'hg update -C .' to abort the merge")
4994 " or 'hg update -C .' to abort the merge")
4995 raise util.Abort(msg, hint=hint)
4995 raise util.Abort(msg, hint=hint)
4996 dirty = util.any(repo.status())
4996 dirty = util.any(repo.status())
4997 node = ctx.node()
4997 node = ctx.node()
4998 if node != parent:
4998 if node != parent:
4999 if dirty:
4999 if dirty:
5000 hint = _("uncommitted changes, use --all to discard all"
5000 hint = _("uncommitted changes, use --all to discard all"
5001 " changes, or 'hg update %s' to update") % ctx.rev()
5001 " changes, or 'hg update %s' to update") % ctx.rev()
5002 else:
5002 else:
5003 hint = _("use --all to revert all files,"
5003 hint = _("use --all to revert all files,"
5004 " or 'hg update %s' to update") % ctx.rev()
5004 " or 'hg update %s' to update") % ctx.rev()
5005 elif dirty:
5005 elif dirty:
5006 hint = _("uncommitted changes, use --all to discard all changes")
5006 hint = _("uncommitted changes, use --all to discard all changes")
5007 else:
5007 else:
5008 hint = _("use --all to revert all files")
5008 hint = _("use --all to revert all files")
5009 raise util.Abort(msg, hint=hint)
5009 raise util.Abort(msg, hint=hint)
5010
5010
5011 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5011 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5012
5012
5013 @command('rollback', dryrunopts +
5013 @command('rollback', dryrunopts +
5014 [('f', 'force', False, _('ignore safety measures'))])
5014 [('f', 'force', False, _('ignore safety measures'))])
5015 def rollback(ui, repo, **opts):
5015 def rollback(ui, repo, **opts):
5016 """roll back the last transaction (dangerous)
5016 """roll back the last transaction (dangerous)
5017
5017
5018 This command should be used with care. There is only one level of
5018 This command should be used with care. There is only one level of
5019 rollback, and there is no way to undo a rollback. It will also
5019 rollback, and there is no way to undo a rollback. It will also
5020 restore the dirstate at the time of the last transaction, losing
5020 restore the dirstate at the time of the last transaction, losing
5021 any dirstate changes since that time. This command does not alter
5021 any dirstate changes since that time. This command does not alter
5022 the working directory.
5022 the working directory.
5023
5023
5024 Transactions are used to encapsulate the effects of all commands
5024 Transactions are used to encapsulate the effects of all commands
5025 that create new changesets or propagate existing changesets into a
5025 that create new changesets or propagate existing changesets into a
5026 repository.
5026 repository.
5027
5027
5028 .. container:: verbose
5028 .. container:: verbose
5029
5029
5030 For example, the following commands are transactional, and their
5030 For example, the following commands are transactional, and their
5031 effects can be rolled back:
5031 effects can be rolled back:
5032
5032
5033 - commit
5033 - commit
5034 - import
5034 - import
5035 - pull
5035 - pull
5036 - push (with this repository as the destination)
5036 - push (with this repository as the destination)
5037 - unbundle
5037 - unbundle
5038
5038
5039 To avoid permanent data loss, rollback will refuse to rollback a
5039 To avoid permanent data loss, rollback will refuse to rollback a
5040 commit transaction if it isn't checked out. Use --force to
5040 commit transaction if it isn't checked out. Use --force to
5041 override this protection.
5041 override this protection.
5042
5042
5043 This command is not intended for use on public repositories. Once
5043 This command is not intended for use on public repositories. Once
5044 changes are visible for pull by other users, rolling a transaction
5044 changes are visible for pull by other users, rolling a transaction
5045 back locally is ineffective (someone else may already have pulled
5045 back locally is ineffective (someone else may already have pulled
5046 the changes). Furthermore, a race is possible with readers of the
5046 the changes). Furthermore, a race is possible with readers of the
5047 repository; for example an in-progress pull from the repository
5047 repository; for example an in-progress pull from the repository
5048 may fail if a rollback is performed.
5048 may fail if a rollback is performed.
5049
5049
5050 Returns 0 on success, 1 if no rollback data is available.
5050 Returns 0 on success, 1 if no rollback data is available.
5051 """
5051 """
5052 return repo.rollback(dryrun=opts.get('dry_run'),
5052 return repo.rollback(dryrun=opts.get('dry_run'),
5053 force=opts.get('force'))
5053 force=opts.get('force'))
5054
5054
5055 @command('root', [])
5055 @command('root', [])
5056 def root(ui, repo):
5056 def root(ui, repo):
5057 """print the root (top) of the current working directory
5057 """print the root (top) of the current working directory
5058
5058
5059 Print the root directory of the current repository.
5059 Print the root directory of the current repository.
5060
5060
5061 Returns 0 on success.
5061 Returns 0 on success.
5062 """
5062 """
5063 ui.write(repo.root + "\n")
5063 ui.write(repo.root + "\n")
5064
5064
5065 @command('^serve',
5065 @command('^serve',
5066 [('A', 'accesslog', '', _('name of access log file to write to'),
5066 [('A', 'accesslog', '', _('name of access log file to write to'),
5067 _('FILE')),
5067 _('FILE')),
5068 ('d', 'daemon', None, _('run server in background')),
5068 ('d', 'daemon', None, _('run server in background')),
5069 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5069 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5070 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5070 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5071 # use string type, then we can check if something was passed
5071 # use string type, then we can check if something was passed
5072 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5072 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5073 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5073 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5074 _('ADDR')),
5074 _('ADDR')),
5075 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5075 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5076 _('PREFIX')),
5076 _('PREFIX')),
5077 ('n', 'name', '',
5077 ('n', 'name', '',
5078 _('name to show in web pages (default: working directory)'), _('NAME')),
5078 _('name to show in web pages (default: working directory)'), _('NAME')),
5079 ('', 'web-conf', '',
5079 ('', 'web-conf', '',
5080 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5080 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5081 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5081 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5082 _('FILE')),
5082 _('FILE')),
5083 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5083 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5084 ('', 'stdio', None, _('for remote clients')),
5084 ('', 'stdio', None, _('for remote clients')),
5085 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5085 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5086 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5086 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5087 ('', 'style', '', _('template style to use'), _('STYLE')),
5087 ('', 'style', '', _('template style to use'), _('STYLE')),
5088 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5088 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5089 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5089 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5090 _('[OPTION]...'))
5090 _('[OPTION]...'))
5091 def serve(ui, repo, **opts):
5091 def serve(ui, repo, **opts):
5092 """start stand-alone webserver
5092 """start stand-alone webserver
5093
5093
5094 Start a local HTTP repository browser and pull server. You can use
5094 Start a local HTTP repository browser and pull server. You can use
5095 this for ad-hoc sharing and browsing of repositories. It is
5095 this for ad-hoc sharing and browsing of repositories. It is
5096 recommended to use a real web server to serve a repository for
5096 recommended to use a real web server to serve a repository for
5097 longer periods of time.
5097 longer periods of time.
5098
5098
5099 Please note that the server does not implement access control.
5099 Please note that the server does not implement access control.
5100 This means that, by default, anybody can read from the server and
5100 This means that, by default, anybody can read from the server and
5101 nobody can write to it by default. Set the ``web.allow_push``
5101 nobody can write to it by default. Set the ``web.allow_push``
5102 option to ``*`` to allow everybody to push to the server. You
5102 option to ``*`` to allow everybody to push to the server. You
5103 should use a real web server if you need to authenticate users.
5103 should use a real web server if you need to authenticate users.
5104
5104
5105 By default, the server logs accesses to stdout and errors to
5105 By default, the server logs accesses to stdout and errors to
5106 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5106 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5107 files.
5107 files.
5108
5108
5109 To have the server choose a free port number to listen on, specify
5109 To have the server choose a free port number to listen on, specify
5110 a port number of 0; in this case, the server will print the port
5110 a port number of 0; in this case, the server will print the port
5111 number it uses.
5111 number it uses.
5112
5112
5113 Returns 0 on success.
5113 Returns 0 on success.
5114 """
5114 """
5115
5115
5116 if opts["stdio"] and opts["cmdserver"]:
5116 if opts["stdio"] and opts["cmdserver"]:
5117 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5117 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5118
5118
5119 def checkrepo():
5119 def checkrepo():
5120 if repo is None:
5120 if repo is None:
5121 raise error.RepoError(_("there is no Mercurial repository here"
5121 raise error.RepoError(_("there is no Mercurial repository here"
5122 " (.hg not found)"))
5122 " (.hg not found)"))
5123
5123
5124 if opts["stdio"]:
5124 if opts["stdio"]:
5125 checkrepo()
5125 checkrepo()
5126 s = sshserver.sshserver(ui, repo)
5126 s = sshserver.sshserver(ui, repo)
5127 s.serve_forever()
5127 s.serve_forever()
5128
5128
5129 if opts["cmdserver"]:
5129 if opts["cmdserver"]:
5130 checkrepo()
5130 checkrepo()
5131 s = commandserver.server(ui, repo, opts["cmdserver"])
5131 s = commandserver.server(ui, repo, opts["cmdserver"])
5132 return s.serve()
5132 return s.serve()
5133
5133
5134 # this way we can check if something was given in the command-line
5134 # this way we can check if something was given in the command-line
5135 if opts.get('port'):
5135 if opts.get('port'):
5136 opts['port'] = util.getport(opts.get('port'))
5136 opts['port'] = util.getport(opts.get('port'))
5137
5137
5138 baseui = repo and repo.baseui or ui
5138 baseui = repo and repo.baseui or ui
5139 optlist = ("name templates style address port prefix ipv6"
5139 optlist = ("name templates style address port prefix ipv6"
5140 " accesslog errorlog certificate encoding")
5140 " accesslog errorlog certificate encoding")
5141 for o in optlist.split():
5141 for o in optlist.split():
5142 val = opts.get(o, '')
5142 val = opts.get(o, '')
5143 if val in (None, ''): # should check against default options instead
5143 if val in (None, ''): # should check against default options instead
5144 continue
5144 continue
5145 baseui.setconfig("web", o, val)
5145 baseui.setconfig("web", o, val)
5146 if repo and repo.ui != baseui:
5146 if repo and repo.ui != baseui:
5147 repo.ui.setconfig("web", o, val)
5147 repo.ui.setconfig("web", o, val)
5148
5148
5149 o = opts.get('web_conf') or opts.get('webdir_conf')
5149 o = opts.get('web_conf') or opts.get('webdir_conf')
5150 if not o:
5150 if not o:
5151 if not repo:
5151 if not repo:
5152 raise error.RepoError(_("there is no Mercurial repository"
5152 raise error.RepoError(_("there is no Mercurial repository"
5153 " here (.hg not found)"))
5153 " here (.hg not found)"))
5154 o = repo
5154 o = repo
5155
5155
5156 app = hgweb.hgweb(o, baseui=baseui)
5156 app = hgweb.hgweb(o, baseui=baseui)
5157
5157
5158 class service(object):
5158 class service(object):
5159 def init(self):
5159 def init(self):
5160 util.setsignalhandler()
5160 util.setsignalhandler()
5161 self.httpd = hgweb.server.create_server(ui, app)
5161 self.httpd = hgweb.server.create_server(ui, app)
5162
5162
5163 if opts['port'] and not ui.verbose:
5163 if opts['port'] and not ui.verbose:
5164 return
5164 return
5165
5165
5166 if self.httpd.prefix:
5166 if self.httpd.prefix:
5167 prefix = self.httpd.prefix.strip('/') + '/'
5167 prefix = self.httpd.prefix.strip('/') + '/'
5168 else:
5168 else:
5169 prefix = ''
5169 prefix = ''
5170
5170
5171 port = ':%d' % self.httpd.port
5171 port = ':%d' % self.httpd.port
5172 if port == ':80':
5172 if port == ':80':
5173 port = ''
5173 port = ''
5174
5174
5175 bindaddr = self.httpd.addr
5175 bindaddr = self.httpd.addr
5176 if bindaddr == '0.0.0.0':
5176 if bindaddr == '0.0.0.0':
5177 bindaddr = '*'
5177 bindaddr = '*'
5178 elif ':' in bindaddr: # IPv6
5178 elif ':' in bindaddr: # IPv6
5179 bindaddr = '[%s]' % bindaddr
5179 bindaddr = '[%s]' % bindaddr
5180
5180
5181 fqaddr = self.httpd.fqaddr
5181 fqaddr = self.httpd.fqaddr
5182 if ':' in fqaddr:
5182 if ':' in fqaddr:
5183 fqaddr = '[%s]' % fqaddr
5183 fqaddr = '[%s]' % fqaddr
5184 if opts['port']:
5184 if opts['port']:
5185 write = ui.status
5185 write = ui.status
5186 else:
5186 else:
5187 write = ui.write
5187 write = ui.write
5188 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5188 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5189 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5189 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5190
5190
5191 def run(self):
5191 def run(self):
5192 self.httpd.serve_forever()
5192 self.httpd.serve_forever()
5193
5193
5194 service = service()
5194 service = service()
5195
5195
5196 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5196 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5197
5197
5198 @command('showconfig|debugconfig',
5198 @command('showconfig|debugconfig',
5199 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5199 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5200 _('[-u] [NAME]...'))
5200 _('[-u] [NAME]...'))
5201 def showconfig(ui, repo, *values, **opts):
5201 def showconfig(ui, repo, *values, **opts):
5202 """show combined config settings from all hgrc files
5202 """show combined config settings from all hgrc files
5203
5203
5204 With no arguments, print names and values of all config items.
5204 With no arguments, print names and values of all config items.
5205
5205
5206 With one argument of the form section.name, print just the value
5206 With one argument of the form section.name, print just the value
5207 of that config item.
5207 of that config item.
5208
5208
5209 With multiple arguments, print names and values of all config
5209 With multiple arguments, print names and values of all config
5210 items with matching section names.
5210 items with matching section names.
5211
5211
5212 With --debug, the source (filename and line number) is printed
5212 With --debug, the source (filename and line number) is printed
5213 for each config item.
5213 for each config item.
5214
5214
5215 Returns 0 on success.
5215 Returns 0 on success.
5216 """
5216 """
5217
5217
5218 for f in scmutil.rcpath():
5218 for f in scmutil.rcpath():
5219 ui.debug('read config from: %s\n' % f)
5219 ui.debug('read config from: %s\n' % f)
5220 untrusted = bool(opts.get('untrusted'))
5220 untrusted = bool(opts.get('untrusted'))
5221 if values:
5221 if values:
5222 sections = [v for v in values if '.' not in v]
5222 sections = [v for v in values if '.' not in v]
5223 items = [v for v in values if '.' in v]
5223 items = [v for v in values if '.' in v]
5224 if len(items) > 1 or items and sections:
5224 if len(items) > 1 or items and sections:
5225 raise util.Abort(_('only one config item permitted'))
5225 raise util.Abort(_('only one config item permitted'))
5226 for section, name, value in ui.walkconfig(untrusted=untrusted):
5226 for section, name, value in ui.walkconfig(untrusted=untrusted):
5227 value = str(value).replace('\n', '\\n')
5227 value = str(value).replace('\n', '\\n')
5228 sectname = section + '.' + name
5228 sectname = section + '.' + name
5229 if values:
5229 if values:
5230 for v in values:
5230 for v in values:
5231 if v == section:
5231 if v == section:
5232 ui.debug('%s: ' %
5232 ui.debug('%s: ' %
5233 ui.configsource(section, name, untrusted))
5233 ui.configsource(section, name, untrusted))
5234 ui.write('%s=%s\n' % (sectname, value))
5234 ui.write('%s=%s\n' % (sectname, value))
5235 elif v == sectname:
5235 elif v == sectname:
5236 ui.debug('%s: ' %
5236 ui.debug('%s: ' %
5237 ui.configsource(section, name, untrusted))
5237 ui.configsource(section, name, untrusted))
5238 ui.write(value, '\n')
5238 ui.write(value, '\n')
5239 else:
5239 else:
5240 ui.debug('%s: ' %
5240 ui.debug('%s: ' %
5241 ui.configsource(section, name, untrusted))
5241 ui.configsource(section, name, untrusted))
5242 ui.write('%s=%s\n' % (sectname, value))
5242 ui.write('%s=%s\n' % (sectname, value))
5243
5243
5244 @command('^status|st',
5244 @command('^status|st',
5245 [('A', 'all', None, _('show status of all files')),
5245 [('A', 'all', None, _('show status of all files')),
5246 ('m', 'modified', None, _('show only modified files')),
5246 ('m', 'modified', None, _('show only modified files')),
5247 ('a', 'added', None, _('show only added files')),
5247 ('a', 'added', None, _('show only added files')),
5248 ('r', 'removed', None, _('show only removed files')),
5248 ('r', 'removed', None, _('show only removed files')),
5249 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5249 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5250 ('c', 'clean', None, _('show only files without changes')),
5250 ('c', 'clean', None, _('show only files without changes')),
5251 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5251 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5252 ('i', 'ignored', None, _('show only ignored files')),
5252 ('i', 'ignored', None, _('show only ignored files')),
5253 ('n', 'no-status', None, _('hide status prefix')),
5253 ('n', 'no-status', None, _('hide status prefix')),
5254 ('C', 'copies', None, _('show source of copied files')),
5254 ('C', 'copies', None, _('show source of copied files')),
5255 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5255 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5256 ('', 'rev', [], _('show difference from revision'), _('REV')),
5256 ('', 'rev', [], _('show difference from revision'), _('REV')),
5257 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5257 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5258 ] + walkopts + subrepoopts,
5258 ] + walkopts + subrepoopts,
5259 _('[OPTION]... [FILE]...'))
5259 _('[OPTION]... [FILE]...'))
5260 def status(ui, repo, *pats, **opts):
5260 def status(ui, repo, *pats, **opts):
5261 """show changed files in the working directory
5261 """show changed files in the working directory
5262
5262
5263 Show status of files in the repository. If names are given, only
5263 Show status of files in the repository. If names are given, only
5264 files that match are shown. Files that are clean or ignored or
5264 files that match are shown. Files that are clean or ignored or
5265 the source of a copy/move operation, are not listed unless
5265 the source of a copy/move operation, are not listed unless
5266 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5266 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5267 Unless options described with "show only ..." are given, the
5267 Unless options described with "show only ..." are given, the
5268 options -mardu are used.
5268 options -mardu are used.
5269
5269
5270 Option -q/--quiet hides untracked (unknown and ignored) files
5270 Option -q/--quiet hides untracked (unknown and ignored) files
5271 unless explicitly requested with -u/--unknown or -i/--ignored.
5271 unless explicitly requested with -u/--unknown or -i/--ignored.
5272
5272
5273 .. note::
5273 .. note::
5274 status may appear to disagree with diff if permissions have
5274 status may appear to disagree with diff if permissions have
5275 changed or a merge has occurred. The standard diff format does
5275 changed or a merge has occurred. The standard diff format does
5276 not report permission changes and diff only reports changes
5276 not report permission changes and diff only reports changes
5277 relative to one merge parent.
5277 relative to one merge parent.
5278
5278
5279 If one revision is given, it is used as the base revision.
5279 If one revision is given, it is used as the base revision.
5280 If two revisions are given, the differences between them are
5280 If two revisions are given, the differences between them are
5281 shown. The --change option can also be used as a shortcut to list
5281 shown. The --change option can also be used as a shortcut to list
5282 the changed files of a revision from its first parent.
5282 the changed files of a revision from its first parent.
5283
5283
5284 The codes used to show the status of files are::
5284 The codes used to show the status of files are::
5285
5285
5286 M = modified
5286 M = modified
5287 A = added
5287 A = added
5288 R = removed
5288 R = removed
5289 C = clean
5289 C = clean
5290 ! = missing (deleted by non-hg command, but still tracked)
5290 ! = missing (deleted by non-hg command, but still tracked)
5291 ? = not tracked
5291 ? = not tracked
5292 I = ignored
5292 I = ignored
5293 = origin of the previous file listed as A (added)
5293 = origin of the previous file listed as A (added)
5294
5294
5295 .. container:: verbose
5295 .. container:: verbose
5296
5296
5297 Examples:
5297 Examples:
5298
5298
5299 - show changes in the working directory relative to a
5299 - show changes in the working directory relative to a
5300 changeset::
5300 changeset::
5301
5301
5302 hg status --rev 9353
5302 hg status --rev 9353
5303
5303
5304 - show all changes including copies in an existing changeset::
5304 - show all changes including copies in an existing changeset::
5305
5305
5306 hg status --copies --change 9353
5306 hg status --copies --change 9353
5307
5307
5308 - get a NUL separated list of added files, suitable for xargs::
5308 - get a NUL separated list of added files, suitable for xargs::
5309
5309
5310 hg status -an0
5310 hg status -an0
5311
5311
5312 Returns 0 on success.
5312 Returns 0 on success.
5313 """
5313 """
5314
5314
5315 revs = opts.get('rev')
5315 revs = opts.get('rev')
5316 change = opts.get('change')
5316 change = opts.get('change')
5317
5317
5318 if revs and change:
5318 if revs and change:
5319 msg = _('cannot specify --rev and --change at the same time')
5319 msg = _('cannot specify --rev and --change at the same time')
5320 raise util.Abort(msg)
5320 raise util.Abort(msg)
5321 elif change:
5321 elif change:
5322 node2 = scmutil.revsingle(repo, change, None).node()
5322 node2 = scmutil.revsingle(repo, change, None).node()
5323 node1 = repo[node2].p1().node()
5323 node1 = repo[node2].p1().node()
5324 else:
5324 else:
5325 node1, node2 = scmutil.revpair(repo, revs)
5325 node1, node2 = scmutil.revpair(repo, revs)
5326
5326
5327 cwd = (pats and repo.getcwd()) or ''
5327 cwd = (pats and repo.getcwd()) or ''
5328 end = opts.get('print0') and '\0' or '\n'
5328 end = opts.get('print0') and '\0' or '\n'
5329 copy = {}
5329 copy = {}
5330 states = 'modified added removed deleted unknown ignored clean'.split()
5330 states = 'modified added removed deleted unknown ignored clean'.split()
5331 show = [k for k in states if opts.get(k)]
5331 show = [k for k in states if opts.get(k)]
5332 if opts.get('all'):
5332 if opts.get('all'):
5333 show += ui.quiet and (states[:4] + ['clean']) or states
5333 show += ui.quiet and (states[:4] + ['clean']) or states
5334 if not show:
5334 if not show:
5335 show = ui.quiet and states[:4] or states[:5]
5335 show = ui.quiet and states[:4] or states[:5]
5336
5336
5337 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5337 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5338 'ignored' in show, 'clean' in show, 'unknown' in show,
5338 'ignored' in show, 'clean' in show, 'unknown' in show,
5339 opts.get('subrepos'))
5339 opts.get('subrepos'))
5340 changestates = zip(states, 'MAR!?IC', stat)
5340 changestates = zip(states, 'MAR!?IC', stat)
5341
5341
5342 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5342 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5343 copy = copies.pathcopies(repo[node1], repo[node2])
5343 copy = copies.pathcopies(repo[node1], repo[node2])
5344
5344
5345 fm = ui.formatter('status', opts)
5345 fm = ui.formatter('status', opts)
5346 fmt = '%s' + end
5346 fmt = '%s' + end
5347 showchar = not opts.get('no_status')
5347 showchar = not opts.get('no_status')
5348
5348
5349 for state, char, files in changestates:
5349 for state, char, files in changestates:
5350 if state in show:
5350 if state in show:
5351 label = 'status.' + state
5351 label = 'status.' + state
5352 for f in files:
5352 for f in files:
5353 fm.startitem()
5353 fm.startitem()
5354 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5354 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5355 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5355 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5356 if f in copy:
5356 if f in copy:
5357 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5357 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5358 label='status.copied')
5358 label='status.copied')
5359 fm.end()
5359 fm.end()
5360
5360
5361 @command('^summary|sum',
5361 @command('^summary|sum',
5362 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5362 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5363 def summary(ui, repo, **opts):
5363 def summary(ui, repo, **opts):
5364 """summarize working directory state
5364 """summarize working directory state
5365
5365
5366 This generates a brief summary of the working directory state,
5366 This generates a brief summary of the working directory state,
5367 including parents, branch, commit status, and available updates.
5367 including parents, branch, commit status, and available updates.
5368
5368
5369 With the --remote option, this will check the default paths for
5369 With the --remote option, this will check the default paths for
5370 incoming and outgoing changes. This can be time-consuming.
5370 incoming and outgoing changes. This can be time-consuming.
5371
5371
5372 Returns 0 on success.
5372 Returns 0 on success.
5373 """
5373 """
5374
5374
5375 ctx = repo[None]
5375 ctx = repo[None]
5376 parents = ctx.parents()
5376 parents = ctx.parents()
5377 pnode = parents[0].node()
5377 pnode = parents[0].node()
5378 marks = []
5378 marks = []
5379
5379
5380 for p in parents:
5380 for p in parents:
5381 # label with log.changeset (instead of log.parent) since this
5381 # label with log.changeset (instead of log.parent) since this
5382 # shows a working directory parent *changeset*:
5382 # shows a working directory parent *changeset*:
5383 # i18n: column positioning for "hg summary"
5383 # i18n: column positioning for "hg summary"
5384 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5384 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5385 label='log.changeset changeset.%s' % p.phasestr())
5385 label='log.changeset changeset.%s' % p.phasestr())
5386 ui.write(' '.join(p.tags()), label='log.tag')
5386 ui.write(' '.join(p.tags()), label='log.tag')
5387 if p.bookmarks():
5387 if p.bookmarks():
5388 marks.extend(p.bookmarks())
5388 marks.extend(p.bookmarks())
5389 if p.rev() == -1:
5389 if p.rev() == -1:
5390 if not len(repo):
5390 if not len(repo):
5391 ui.write(_(' (empty repository)'))
5391 ui.write(_(' (empty repository)'))
5392 else:
5392 else:
5393 ui.write(_(' (no revision checked out)'))
5393 ui.write(_(' (no revision checked out)'))
5394 ui.write('\n')
5394 ui.write('\n')
5395 if p.description():
5395 if p.description():
5396 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5396 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5397 label='log.summary')
5397 label='log.summary')
5398
5398
5399 branch = ctx.branch()
5399 branch = ctx.branch()
5400 bheads = repo.branchheads(branch)
5400 bheads = repo.branchheads(branch)
5401 # i18n: column positioning for "hg summary"
5401 # i18n: column positioning for "hg summary"
5402 m = _('branch: %s\n') % branch
5402 m = _('branch: %s\n') % branch
5403 if branch != 'default':
5403 if branch != 'default':
5404 ui.write(m, label='log.branch')
5404 ui.write(m, label='log.branch')
5405 else:
5405 else:
5406 ui.status(m, label='log.branch')
5406 ui.status(m, label='log.branch')
5407
5407
5408 if marks:
5408 if marks:
5409 current = repo._bookmarkcurrent
5409 current = repo._bookmarkcurrent
5410 # i18n: column positioning for "hg summary"
5410 # i18n: column positioning for "hg summary"
5411 ui.write(_('bookmarks:'), label='log.bookmark')
5411 ui.write(_('bookmarks:'), label='log.bookmark')
5412 if current is not None:
5412 if current is not None:
5413 if current in marks:
5413 if current in marks:
5414 ui.write(' *' + current, label='bookmarks.current')
5414 ui.write(' *' + current, label='bookmarks.current')
5415 marks.remove(current)
5415 marks.remove(current)
5416 else:
5416 else:
5417 ui.write(' [%s]' % current, label='bookmarks.current')
5417 ui.write(' [%s]' % current, label='bookmarks.current')
5418 for m in marks:
5418 for m in marks:
5419 ui.write(' ' + m, label='log.bookmark')
5419 ui.write(' ' + m, label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5421
5421
5422 st = list(repo.status(unknown=True))[:6]
5422 st = list(repo.status(unknown=True))[:6]
5423
5423
5424 c = repo.dirstate.copies()
5424 c = repo.dirstate.copies()
5425 copied, renamed = [], []
5425 copied, renamed = [], []
5426 for d, s in c.iteritems():
5426 for d, s in c.iteritems():
5427 if s in st[2]:
5427 if s in st[2]:
5428 st[2].remove(s)
5428 st[2].remove(s)
5429 renamed.append(d)
5429 renamed.append(d)
5430 else:
5430 else:
5431 copied.append(d)
5431 copied.append(d)
5432 if d in st[1]:
5432 if d in st[1]:
5433 st[1].remove(d)
5433 st[1].remove(d)
5434 st.insert(3, renamed)
5434 st.insert(3, renamed)
5435 st.insert(4, copied)
5435 st.insert(4, copied)
5436
5436
5437 ms = mergemod.mergestate(repo)
5437 ms = mergemod.mergestate(repo)
5438 st.append([f for f in ms if ms[f] == 'u'])
5438 st.append([f for f in ms if ms[f] == 'u'])
5439
5439
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5441 st.append(subs)
5441 st.append(subs)
5442
5442
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5444 ui.label(_('%d added'), 'status.added'),
5444 ui.label(_('%d added'), 'status.added'),
5445 ui.label(_('%d removed'), 'status.removed'),
5445 ui.label(_('%d removed'), 'status.removed'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5452 ui.label(_('%d subrepos'), 'status.modified')]
5452 ui.label(_('%d subrepos'), 'status.modified')]
5453 t = []
5453 t = []
5454 for s, l in zip(st, labels):
5454 for s, l in zip(st, labels):
5455 if s:
5455 if s:
5456 t.append(l % len(s))
5456 t.append(l % len(s))
5457
5457
5458 t = ', '.join(t)
5458 t = ', '.join(t)
5459 cleanworkdir = False
5459 cleanworkdir = False
5460
5460
5461 if len(parents) > 1:
5461 if len(parents) > 1:
5462 t += _(' (merge)')
5462 t += _(' (merge)')
5463 elif branch != parents[0].branch():
5463 elif branch != parents[0].branch():
5464 t += _(' (new branch)')
5464 t += _(' (new branch)')
5465 elif (parents[0].closesbranch() and
5465 elif (parents[0].closesbranch() and
5466 pnode in repo.branchheads(branch, closed=True)):
5466 pnode in repo.branchheads(branch, closed=True)):
5467 t += _(' (head closed)')
5467 t += _(' (head closed)')
5468 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5468 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5469 t += _(' (clean)')
5469 t += _(' (clean)')
5470 cleanworkdir = True
5470 cleanworkdir = True
5471 elif pnode not in bheads:
5471 elif pnode not in bheads:
5472 t += _(' (new branch head)')
5472 t += _(' (new branch head)')
5473
5473
5474 if cleanworkdir:
5474 if cleanworkdir:
5475 # i18n: column positioning for "hg summary"
5475 # i18n: column positioning for "hg summary"
5476 ui.status(_('commit: %s\n') % t.strip())
5476 ui.status(_('commit: %s\n') % t.strip())
5477 else:
5477 else:
5478 # i18n: column positioning for "hg summary"
5478 # i18n: column positioning for "hg summary"
5479 ui.write(_('commit: %s\n') % t.strip())
5479 ui.write(_('commit: %s\n') % t.strip())
5480
5480
5481 # all ancestors of branch heads - all ancestors of parent = new csets
5481 # all ancestors of branch heads - all ancestors of parent = new csets
5482 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5482 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5483 bheads))
5483 bheads))
5484
5484
5485 if new == 0:
5485 if new == 0:
5486 # i18n: column positioning for "hg summary"
5486 # i18n: column positioning for "hg summary"
5487 ui.status(_('update: (current)\n'))
5487 ui.status(_('update: (current)\n'))
5488 elif pnode not in bheads:
5488 elif pnode not in bheads:
5489 # i18n: column positioning for "hg summary"
5489 # i18n: column positioning for "hg summary"
5490 ui.write(_('update: %d new changesets (update)\n') % new)
5490 ui.write(_('update: %d new changesets (update)\n') % new)
5491 else:
5491 else:
5492 # i18n: column positioning for "hg summary"
5492 # i18n: column positioning for "hg summary"
5493 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5493 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5494 (new, len(bheads)))
5494 (new, len(bheads)))
5495
5495
5496 cmdutil.summaryhooks(ui, repo)
5496 cmdutil.summaryhooks(ui, repo)
5497
5497
5498 if opts.get('remote'):
5498 if opts.get('remote'):
5499 t = []
5499 t = []
5500 source, branches = hg.parseurl(ui.expandpath('default'))
5500 source, branches = hg.parseurl(ui.expandpath('default'))
5501 sbranch = branches[0]
5501 sbranch = branches[0]
5502 other = hg.peer(repo, {}, source)
5502 other = hg.peer(repo, {}, source)
5503 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5503 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5504 if revs:
5504 if revs:
5505 revs = [other.lookup(rev) for rev in revs]
5505 revs = [other.lookup(rev) for rev in revs]
5506 ui.debug('comparing with %s\n' % util.hidepassword(source))
5506 ui.debug('comparing with %s\n' % util.hidepassword(source))
5507 repo.ui.pushbuffer()
5507 repo.ui.pushbuffer()
5508 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5508 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5509 _common, incoming, _rheads = commoninc
5509 _common, incoming, _rheads = commoninc
5510 repo.ui.popbuffer()
5510 repo.ui.popbuffer()
5511 if incoming:
5511 if incoming:
5512 t.append(_('1 or more incoming'))
5512 t.append(_('1 or more incoming'))
5513
5513
5514 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5514 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5515 dbranch = branches[0]
5515 dbranch = branches[0]
5516 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5516 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5517 if source != dest:
5517 if source != dest:
5518 other = hg.peer(repo, {}, dest)
5518 other = hg.peer(repo, {}, dest)
5519 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5519 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5520 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5520 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5521 commoninc = None
5521 commoninc = None
5522 if revs:
5522 if revs:
5523 revs = [repo.lookup(rev) for rev in revs]
5523 revs = [repo.lookup(rev) for rev in revs]
5524 repo.ui.pushbuffer()
5524 repo.ui.pushbuffer()
5525 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5525 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5526 commoninc=commoninc)
5526 commoninc=commoninc)
5527 repo.ui.popbuffer()
5527 repo.ui.popbuffer()
5528 o = outgoing.missing
5528 o = outgoing.missing
5529 if o:
5529 if o:
5530 t.append(_('%d outgoing') % len(o))
5530 t.append(_('%d outgoing') % len(o))
5531 if 'bookmarks' in other.listkeys('namespaces'):
5531 if 'bookmarks' in other.listkeys('namespaces'):
5532 lmarks = repo.listkeys('bookmarks')
5532 lmarks = repo.listkeys('bookmarks')
5533 rmarks = other.listkeys('bookmarks')
5533 rmarks = other.listkeys('bookmarks')
5534 diff = set(rmarks) - set(lmarks)
5534 diff = set(rmarks) - set(lmarks)
5535 if len(diff) > 0:
5535 if len(diff) > 0:
5536 t.append(_('%d incoming bookmarks') % len(diff))
5536 t.append(_('%d incoming bookmarks') % len(diff))
5537 diff = set(lmarks) - set(rmarks)
5537 diff = set(lmarks) - set(rmarks)
5538 if len(diff) > 0:
5538 if len(diff) > 0:
5539 t.append(_('%d outgoing bookmarks') % len(diff))
5539 t.append(_('%d outgoing bookmarks') % len(diff))
5540
5540
5541 if t:
5541 if t:
5542 # i18n: column positioning for "hg summary"
5542 # i18n: column positioning for "hg summary"
5543 ui.write(_('remote: %s\n') % (', '.join(t)))
5543 ui.write(_('remote: %s\n') % (', '.join(t)))
5544 else:
5544 else:
5545 # i18n: column positioning for "hg summary"
5545 # i18n: column positioning for "hg summary"
5546 ui.status(_('remote: (synced)\n'))
5546 ui.status(_('remote: (synced)\n'))
5547
5547
5548 @command('tag',
5548 @command('tag',
5549 [('f', 'force', None, _('force tag')),
5549 [('f', 'force', None, _('force tag')),
5550 ('l', 'local', None, _('make the tag local')),
5550 ('l', 'local', None, _('make the tag local')),
5551 ('r', 'rev', '', _('revision to tag'), _('REV')),
5551 ('r', 'rev', '', _('revision to tag'), _('REV')),
5552 ('', 'remove', None, _('remove a tag')),
5552 ('', 'remove', None, _('remove a tag')),
5553 # -l/--local is already there, commitopts cannot be used
5553 # -l/--local is already there, commitopts cannot be used
5554 ('e', 'edit', None, _('edit commit message')),
5554 ('e', 'edit', None, _('edit commit message')),
5555 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5555 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5556 ] + commitopts2,
5556 ] + commitopts2,
5557 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5557 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5558 def tag(ui, repo, name1, *names, **opts):
5558 def tag(ui, repo, name1, *names, **opts):
5559 """add one or more tags for the current or given revision
5559 """add one or more tags for the current or given revision
5560
5560
5561 Name a particular revision using <name>.
5561 Name a particular revision using <name>.
5562
5562
5563 Tags are used to name particular revisions of the repository and are
5563 Tags are used to name particular revisions of the repository and are
5564 very useful to compare different revisions, to go back to significant
5564 very useful to compare different revisions, to go back to significant
5565 earlier versions or to mark branch points as releases, etc. Changing
5565 earlier versions or to mark branch points as releases, etc. Changing
5566 an existing tag is normally disallowed; use -f/--force to override.
5566 an existing tag is normally disallowed; use -f/--force to override.
5567
5567
5568 If no revision is given, the parent of the working directory is
5568 If no revision is given, the parent of the working directory is
5569 used, or tip if no revision is checked out.
5569 used, or tip if no revision is checked out.
5570
5570
5571 To facilitate version control, distribution, and merging of tags,
5571 To facilitate version control, distribution, and merging of tags,
5572 they are stored as a file named ".hgtags" which is managed similarly
5572 they are stored as a file named ".hgtags" which is managed similarly
5573 to other project files and can be hand-edited if necessary. This
5573 to other project files and can be hand-edited if necessary. This
5574 also means that tagging creates a new commit. The file
5574 also means that tagging creates a new commit. The file
5575 ".hg/localtags" is used for local tags (not shared among
5575 ".hg/localtags" is used for local tags (not shared among
5576 repositories).
5576 repositories).
5577
5577
5578 Tag commits are usually made at the head of a branch. If the parent
5578 Tag commits are usually made at the head of a branch. If the parent
5579 of the working directory is not a branch head, :hg:`tag` aborts; use
5579 of the working directory is not a branch head, :hg:`tag` aborts; use
5580 -f/--force to force the tag commit to be based on a non-head
5580 -f/--force to force the tag commit to be based on a non-head
5581 changeset.
5581 changeset.
5582
5582
5583 See :hg:`help dates` for a list of formats valid for -d/--date.
5583 See :hg:`help dates` for a list of formats valid for -d/--date.
5584
5584
5585 Since tag names have priority over branch names during revision
5585 Since tag names have priority over branch names during revision
5586 lookup, using an existing branch name as a tag name is discouraged.
5586 lookup, using an existing branch name as a tag name is discouraged.
5587
5587
5588 Returns 0 on success.
5588 Returns 0 on success.
5589 """
5589 """
5590 wlock = lock = None
5590 wlock = lock = None
5591 try:
5591 try:
5592 wlock = repo.wlock()
5592 wlock = repo.wlock()
5593 lock = repo.lock()
5593 lock = repo.lock()
5594 rev_ = "."
5594 rev_ = "."
5595 names = [t.strip() for t in (name1,) + names]
5595 names = [t.strip() for t in (name1,) + names]
5596 if len(names) != len(set(names)):
5596 if len(names) != len(set(names)):
5597 raise util.Abort(_('tag names must be unique'))
5597 raise util.Abort(_('tag names must be unique'))
5598 for n in names:
5598 for n in names:
5599 scmutil.checknewlabel(repo, n, 'tag')
5599 scmutil.checknewlabel(repo, n, 'tag')
5600 if not n:
5600 if not n:
5601 raise util.Abort(_('tag names cannot consist entirely of '
5601 raise util.Abort(_('tag names cannot consist entirely of '
5602 'whitespace'))
5602 'whitespace'))
5603 if opts.get('rev') and opts.get('remove'):
5603 if opts.get('rev') and opts.get('remove'):
5604 raise util.Abort(_("--rev and --remove are incompatible"))
5604 raise util.Abort(_("--rev and --remove are incompatible"))
5605 if opts.get('rev'):
5605 if opts.get('rev'):
5606 rev_ = opts['rev']
5606 rev_ = opts['rev']
5607 message = opts.get('message')
5607 message = opts.get('message')
5608 if opts.get('remove'):
5608 if opts.get('remove'):
5609 expectedtype = opts.get('local') and 'local' or 'global'
5609 expectedtype = opts.get('local') and 'local' or 'global'
5610 for n in names:
5610 for n in names:
5611 if not repo.tagtype(n):
5611 if not repo.tagtype(n):
5612 raise util.Abort(_("tag '%s' does not exist") % n)
5612 raise util.Abort(_("tag '%s' does not exist") % n)
5613 if repo.tagtype(n) != expectedtype:
5613 if repo.tagtype(n) != expectedtype:
5614 if expectedtype == 'global':
5614 if expectedtype == 'global':
5615 raise util.Abort(_("tag '%s' is not a global tag") % n)
5615 raise util.Abort(_("tag '%s' is not a global tag") % n)
5616 else:
5616 else:
5617 raise util.Abort(_("tag '%s' is not a local tag") % n)
5617 raise util.Abort(_("tag '%s' is not a local tag") % n)
5618 rev_ = nullid
5618 rev_ = nullid
5619 if not message:
5619 if not message:
5620 # we don't translate commit messages
5620 # we don't translate commit messages
5621 message = 'Removed tag %s' % ', '.join(names)
5621 message = 'Removed tag %s' % ', '.join(names)
5622 elif not opts.get('force'):
5622 elif not opts.get('force'):
5623 for n in names:
5623 for n in names:
5624 if n in repo.tags():
5624 if n in repo.tags():
5625 raise util.Abort(_("tag '%s' already exists "
5625 raise util.Abort(_("tag '%s' already exists "
5626 "(use -f to force)") % n)
5626 "(use -f to force)") % n)
5627 if not opts.get('local'):
5627 if not opts.get('local'):
5628 p1, p2 = repo.dirstate.parents()
5628 p1, p2 = repo.dirstate.parents()
5629 if p2 != nullid:
5629 if p2 != nullid:
5630 raise util.Abort(_('uncommitted merge'))
5630 raise util.Abort(_('uncommitted merge'))
5631 bheads = repo.branchheads()
5631 bheads = repo.branchheads()
5632 if not opts.get('force') and bheads and p1 not in bheads:
5632 if not opts.get('force') and bheads and p1 not in bheads:
5633 raise util.Abort(_('not at a branch head (use -f to force)'))
5633 raise util.Abort(_('not at a branch head (use -f to force)'))
5634 r = scmutil.revsingle(repo, rev_).node()
5634 r = scmutil.revsingle(repo, rev_).node()
5635
5635
5636 if not message:
5636 if not message:
5637 # we don't translate commit messages
5637 # we don't translate commit messages
5638 message = ('Added tag %s for changeset %s' %
5638 message = ('Added tag %s for changeset %s' %
5639 (', '.join(names), short(r)))
5639 (', '.join(names), short(r)))
5640
5640
5641 date = opts.get('date')
5641 date = opts.get('date')
5642 if date:
5642 if date:
5643 date = util.parsedate(date)
5643 date = util.parsedate(date)
5644
5644
5645 if opts.get('edit'):
5645 if opts.get('edit'):
5646 message = ui.edit(message, ui.username())
5646 message = ui.edit(message, ui.username())
5647
5647
5648 # don't allow tagging the null rev
5648 # don't allow tagging the null rev
5649 if (not opts.get('remove') and
5649 if (not opts.get('remove') and
5650 scmutil.revsingle(repo, rev_).rev() == nullrev):
5650 scmutil.revsingle(repo, rev_).rev() == nullrev):
5651 raise util.Abort(_("cannot tag null revision"))
5651 raise util.Abort(_("cannot tag null revision"))
5652
5652
5653 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5653 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5654 finally:
5654 finally:
5655 release(lock, wlock)
5655 release(lock, wlock)
5656
5656
5657 @command('tags', [], '')
5657 @command('tags', [], '')
5658 def tags(ui, repo, **opts):
5658 def tags(ui, repo, **opts):
5659 """list repository tags
5659 """list repository tags
5660
5660
5661 This lists both regular and local tags. When the -v/--verbose
5661 This lists both regular and local tags. When the -v/--verbose
5662 switch is used, a third column "local" is printed for local tags.
5662 switch is used, a third column "local" is printed for local tags.
5663
5663
5664 Returns 0 on success.
5664 Returns 0 on success.
5665 """
5665 """
5666
5666
5667 fm = ui.formatter('tags', opts)
5667 fm = ui.formatter('tags', opts)
5668 hexfunc = ui.debugflag and hex or short
5668 hexfunc = ui.debugflag and hex or short
5669 tagtype = ""
5669 tagtype = ""
5670
5670
5671 for t, n in reversed(repo.tagslist()):
5671 for t, n in reversed(repo.tagslist()):
5672 hn = hexfunc(n)
5672 hn = hexfunc(n)
5673 label = 'tags.normal'
5673 label = 'tags.normal'
5674 tagtype = ''
5674 tagtype = ''
5675 if repo.tagtype(t) == 'local':
5675 if repo.tagtype(t) == 'local':
5676 label = 'tags.local'
5676 label = 'tags.local'
5677 tagtype = 'local'
5677 tagtype = 'local'
5678
5678
5679 fm.startitem()
5679 fm.startitem()
5680 fm.write('tag', '%s', t, label=label)
5680 fm.write('tag', '%s', t, label=label)
5681 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5681 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5682 fm.condwrite(not ui.quiet, 'rev id', fmt,
5682 fm.condwrite(not ui.quiet, 'rev id', fmt,
5683 repo.changelog.rev(n), hn, label=label)
5683 repo.changelog.rev(n), hn, label=label)
5684 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5684 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5685 tagtype, label=label)
5685 tagtype, label=label)
5686 fm.plain('\n')
5686 fm.plain('\n')
5687 fm.end()
5687 fm.end()
5688
5688
5689 @command('tip',
5689 @command('tip',
5690 [('p', 'patch', None, _('show patch')),
5690 [('p', 'patch', None, _('show patch')),
5691 ('g', 'git', None, _('use git extended diff format')),
5691 ('g', 'git', None, _('use git extended diff format')),
5692 ] + templateopts,
5692 ] + templateopts,
5693 _('[-p] [-g]'))
5693 _('[-p] [-g]'))
5694 def tip(ui, repo, **opts):
5694 def tip(ui, repo, **opts):
5695 """show the tip revision
5695 """show the tip revision
5696
5696
5697 The tip revision (usually just called the tip) is the changeset
5697 The tip revision (usually just called the tip) is the changeset
5698 most recently added to the repository (and therefore the most
5698 most recently added to the repository (and therefore the most
5699 recently changed head).
5699 recently changed head).
5700
5700
5701 If you have just made a commit, that commit will be the tip. If
5701 If you have just made a commit, that commit will be the tip. If
5702 you have just pulled changes from another repository, the tip of
5702 you have just pulled changes from another repository, the tip of
5703 that repository becomes the current tip. The "tip" tag is special
5703 that repository becomes the current tip. The "tip" tag is special
5704 and cannot be renamed or assigned to a different changeset.
5704 and cannot be renamed or assigned to a different changeset.
5705
5705
5706 Returns 0 on success.
5706 Returns 0 on success.
5707 """
5707 """
5708 displayer = cmdutil.show_changeset(ui, repo, opts)
5708 displayer = cmdutil.show_changeset(ui, repo, opts)
5709 displayer.show(repo['tip'])
5709 displayer.show(repo['tip'])
5710 displayer.close()
5710 displayer.close()
5711
5711
5712 @command('unbundle',
5712 @command('unbundle',
5713 [('u', 'update', None,
5713 [('u', 'update', None,
5714 _('update to new branch head if changesets were unbundled'))],
5714 _('update to new branch head if changesets were unbundled'))],
5715 _('[-u] FILE...'))
5715 _('[-u] FILE...'))
5716 def unbundle(ui, repo, fname1, *fnames, **opts):
5716 def unbundle(ui, repo, fname1, *fnames, **opts):
5717 """apply one or more changegroup files
5717 """apply one or more changegroup files
5718
5718
5719 Apply one or more compressed changegroup files generated by the
5719 Apply one or more compressed changegroup files generated by the
5720 bundle command.
5720 bundle command.
5721
5721
5722 Returns 0 on success, 1 if an update has unresolved files.
5722 Returns 0 on success, 1 if an update has unresolved files.
5723 """
5723 """
5724 fnames = (fname1,) + fnames
5724 fnames = (fname1,) + fnames
5725
5725
5726 lock = repo.lock()
5726 lock = repo.lock()
5727 wc = repo['.']
5727 wc = repo['.']
5728 try:
5728 try:
5729 for fname in fnames:
5729 for fname in fnames:
5730 f = hg.openpath(ui, fname)
5730 f = hg.openpath(ui, fname)
5731 gen = changegroup.readbundle(f, fname)
5731 gen = changegroup.readbundle(f, fname)
5732 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5732 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5733 finally:
5733 finally:
5734 lock.release()
5734 lock.release()
5735 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5735 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5736 return postincoming(ui, repo, modheads, opts.get('update'), None)
5736 return postincoming(ui, repo, modheads, opts.get('update'), None)
5737
5737
5738 @command('^update|up|checkout|co',
5738 @command('^update|up|checkout|co',
5739 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5739 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5740 ('c', 'check', None,
5740 ('c', 'check', None,
5741 _('update across branches if no uncommitted changes')),
5741 _('update across branches if no uncommitted changes')),
5742 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5742 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5743 ('r', 'rev', '', _('revision'), _('REV'))],
5743 ('r', 'rev', '', _('revision'), _('REV'))],
5744 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5744 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5745 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5745 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5746 """update working directory (or switch revisions)
5746 """update working directory (or switch revisions)
5747
5747
5748 Update the repository's working directory to the specified
5748 Update the repository's working directory to the specified
5749 changeset. If no changeset is specified, update to the tip of the
5749 changeset. If no changeset is specified, update to the tip of the
5750 current named branch and move the current bookmark (see :hg:`help
5750 current named branch and move the current bookmark (see :hg:`help
5751 bookmarks`).
5751 bookmarks`).
5752
5752
5753 Update sets the working directory's parent revision to the specified
5753 Update sets the working directory's parent revision to the specified
5754 changeset (see :hg:`help parents`).
5754 changeset (see :hg:`help parents`).
5755
5755
5756 If the changeset is not a descendant or ancestor of the working
5756 If the changeset is not a descendant or ancestor of the working
5757 directory's parent, the update is aborted. With the -c/--check
5757 directory's parent, the update is aborted. With the -c/--check
5758 option, the working directory is checked for uncommitted changes; if
5758 option, the working directory is checked for uncommitted changes; if
5759 none are found, the working directory is updated to the specified
5759 none are found, the working directory is updated to the specified
5760 changeset.
5760 changeset.
5761
5761
5762 .. container:: verbose
5762 .. container:: verbose
5763
5763
5764 The following rules apply when the working directory contains
5764 The following rules apply when the working directory contains
5765 uncommitted changes:
5765 uncommitted changes:
5766
5766
5767 1. If neither -c/--check nor -C/--clean is specified, and if
5767 1. If neither -c/--check nor -C/--clean is specified, and if
5768 the requested changeset is an ancestor or descendant of
5768 the requested changeset is an ancestor or descendant of
5769 the working directory's parent, the uncommitted changes
5769 the working directory's parent, the uncommitted changes
5770 are merged into the requested changeset and the merged
5770 are merged into the requested changeset and the merged
5771 result is left uncommitted. If the requested changeset is
5771 result is left uncommitted. If the requested changeset is
5772 not an ancestor or descendant (that is, it is on another
5772 not an ancestor or descendant (that is, it is on another
5773 branch), the update is aborted and the uncommitted changes
5773 branch), the update is aborted and the uncommitted changes
5774 are preserved.
5774 are preserved.
5775
5775
5776 2. With the -c/--check option, the update is aborted and the
5776 2. With the -c/--check option, the update is aborted and the
5777 uncommitted changes are preserved.
5777 uncommitted changes are preserved.
5778
5778
5779 3. With the -C/--clean option, uncommitted changes are discarded and
5779 3. With the -C/--clean option, uncommitted changes are discarded and
5780 the working directory is updated to the requested changeset.
5780 the working directory is updated to the requested changeset.
5781
5781
5782 To cancel an uncommitted merge (and lose your changes), use
5782 To cancel an uncommitted merge (and lose your changes), use
5783 :hg:`update --clean .`.
5783 :hg:`update --clean .`.
5784
5784
5785 Use null as the changeset to remove the working directory (like
5785 Use null as the changeset to remove the working directory (like
5786 :hg:`clone -U`).
5786 :hg:`clone -U`).
5787
5787
5788 If you want to revert just one file to an older revision, use
5788 If you want to revert just one file to an older revision, use
5789 :hg:`revert [-r REV] NAME`.
5789 :hg:`revert [-r REV] NAME`.
5790
5790
5791 See :hg:`help dates` for a list of formats valid for -d/--date.
5791 See :hg:`help dates` for a list of formats valid for -d/--date.
5792
5792
5793 Returns 0 on success, 1 if there are unresolved files.
5793 Returns 0 on success, 1 if there are unresolved files.
5794 """
5794 """
5795 if rev and node:
5795 if rev and node:
5796 raise util.Abort(_("please specify just one revision"))
5796 raise util.Abort(_("please specify just one revision"))
5797
5797
5798 if rev is None or rev == '':
5798 if rev is None or rev == '':
5799 rev = node
5799 rev = node
5800
5800
5801 # with no argument, we also move the current bookmark, if any
5801 # with no argument, we also move the current bookmark, if any
5802 movemarkfrom = None
5802 movemarkfrom = None
5803 if rev is None:
5803 if rev is None:
5804 curmark = repo._bookmarkcurrent
5804 curmark = repo._bookmarkcurrent
5805 if bookmarks.iscurrent(repo):
5805 if bookmarks.iscurrent(repo):
5806 movemarkfrom = repo['.'].node()
5806 movemarkfrom = repo['.'].node()
5807 elif curmark:
5807 elif curmark:
5808 ui.status(_("updating to active bookmark %s\n") % curmark)
5808 ui.status(_("updating to active bookmark %s\n") % curmark)
5809 rev = curmark
5809 rev = curmark
5810
5810
5811 # if we defined a bookmark, we have to remember the original bookmark name
5811 # if we defined a bookmark, we have to remember the original bookmark name
5812 brev = rev
5812 brev = rev
5813 rev = scmutil.revsingle(repo, rev, rev).rev()
5813 rev = scmutil.revsingle(repo, rev, rev).rev()
5814
5814
5815 if check and clean:
5815 if check and clean:
5816 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5816 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5817
5817
5818 if date:
5818 if date:
5819 if rev is not None:
5819 if rev is not None:
5820 raise util.Abort(_("you can't specify a revision and a date"))
5820 raise util.Abort(_("you can't specify a revision and a date"))
5821 rev = cmdutil.finddate(ui, repo, date)
5821 rev = cmdutil.finddate(ui, repo, date)
5822
5822
5823 if check:
5823 if check:
5824 c = repo[None]
5824 c = repo[None]
5825 if c.dirty(merge=False, branch=False, missing=True):
5825 if c.dirty(merge=False, branch=False, missing=True):
5826 raise util.Abort(_("uncommitted local changes"))
5826 raise util.Abort(_("uncommitted local changes"))
5827 if rev is None:
5827 if rev is None:
5828 rev = repo[repo[None].branch()].rev()
5828 rev = repo[repo[None].branch()].rev()
5829 mergemod._checkunknown(repo, repo[None], repo[rev])
5829 mergemod._checkunknown(repo, repo[None], repo[rev])
5830
5830
5831 if clean:
5831 if clean:
5832 ret = hg.clean(repo, rev)
5832 ret = hg.clean(repo, rev)
5833 else:
5833 else:
5834 ret = hg.update(repo, rev)
5834 ret = hg.update(repo, rev)
5835
5835
5836 if not ret and movemarkfrom:
5836 if not ret and movemarkfrom:
5837 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5837 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5838 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5838 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5839 elif brev in repo._bookmarks:
5839 elif brev in repo._bookmarks:
5840 bookmarks.setcurrent(repo, brev)
5840 bookmarks.setcurrent(repo, brev)
5841 elif brev:
5841 elif brev:
5842 bookmarks.unsetcurrent(repo)
5842 bookmarks.unsetcurrent(repo)
5843
5843
5844 return ret
5844 return ret
5845
5845
5846 @command('verify', [])
5846 @command('verify', [])
5847 def verify(ui, repo):
5847 def verify(ui, repo):
5848 """verify the integrity of the repository
5848 """verify the integrity of the repository
5849
5849
5850 Verify the integrity of the current repository.
5850 Verify the integrity of the current repository.
5851
5851
5852 This will perform an extensive check of the repository's
5852 This will perform an extensive check of the repository's
5853 integrity, validating the hashes and checksums of each entry in
5853 integrity, validating the hashes and checksums of each entry in
5854 the changelog, manifest, and tracked files, as well as the
5854 the changelog, manifest, and tracked files, as well as the
5855 integrity of their crosslinks and indices.
5855 integrity of their crosslinks and indices.
5856
5856
5857 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5857 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5858 for more information about recovery from corruption of the
5858 for more information about recovery from corruption of the
5859 repository.
5859 repository.
5860
5860
5861 Returns 0 on success, 1 if errors are encountered.
5861 Returns 0 on success, 1 if errors are encountered.
5862 """
5862 """
5863 return hg.verify(repo)
5863 return hg.verify(repo)
5864
5864
5865 @command('version', [])
5865 @command('version', [])
5866 def version_(ui):
5866 def version_(ui):
5867 """output version and copyright information"""
5867 """output version and copyright information"""
5868 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5868 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5869 % util.version())
5869 % util.version())
5870 ui.status(_(
5870 ui.status(_(
5871 "(see http://mercurial.selenic.com for more information)\n"
5871 "(see http://mercurial.selenic.com for more information)\n"
5872 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5872 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5873 "This is free software; see the source for copying conditions. "
5873 "This is free software; see the source for copying conditions. "
5874 "There is NO\nwarranty; "
5874 "There is NO\nwarranty; "
5875 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5875 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5876 ))
5876 ))
5877
5877
5878 norepo = ("clone init version help debugcommands debugcomplete"
5878 norepo = ("clone init version help debugcommands debugcomplete"
5879 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5879 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5880 " debugknown debuggetbundle debugbundle")
5880 " debugknown debuggetbundle debugbundle")
5881 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5881 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5882 " debugdata debugindex debugindexdot debugrevlog")
5882 " debugdata debugindex debugindexdot debugrevlog")
5883 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5883 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5884 " remove resolve status debugwalk")
5884 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now