##// END OF EJS Templates
serve: pass the prepared baseui to hgweb...
Simon Heimberg -
r18827:6793ae6e default
parent child Browse files
Show More
@@ -1,5826 +1,5826 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 [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 if bmctx.rev() in anc:
819 if bmctx.rev() in anc:
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
821 (mark, short(bmctx.node())))
821 (mark, short(bmctx.node())))
822 return
822 return
823 raise util.Abort(_("bookmark '%s' already exists "
823 raise util.Abort(_("bookmark '%s' already exists "
824 "(use -f to force)") % mark)
824 "(use -f to force)") % mark)
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
826 and not force):
826 and not force):
827 raise util.Abort(
827 raise util.Abort(
828 _("a bookmark cannot have the name of an existing branch"))
828 _("a bookmark cannot have the name of an existing branch"))
829
829
830 if delete and rename:
830 if delete and rename:
831 raise util.Abort(_("--delete and --rename are incompatible"))
831 raise util.Abort(_("--delete and --rename are incompatible"))
832 if delete and rev:
832 if delete and rev:
833 raise util.Abort(_("--rev is incompatible with --delete"))
833 raise util.Abort(_("--rev is incompatible with --delete"))
834 if rename and rev:
834 if rename and rev:
835 raise util.Abort(_("--rev is incompatible with --rename"))
835 raise util.Abort(_("--rev is incompatible with --rename"))
836 if mark is None and (delete or rev):
836 if mark is None and (delete or rev):
837 raise util.Abort(_("bookmark name required"))
837 raise util.Abort(_("bookmark name required"))
838
838
839 if delete:
839 if delete:
840 if mark not in marks:
840 if mark not in marks:
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
842 if mark == repo._bookmarkcurrent:
842 if mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
843 bookmarks.setcurrent(repo, None)
844 del marks[mark]
844 del marks[mark]
845 marks.write()
845 marks.write()
846
846
847 elif rename:
847 elif rename:
848 if mark is None:
848 if mark is None:
849 raise util.Abort(_("new bookmark name required"))
849 raise util.Abort(_("new bookmark name required"))
850 mark = checkformat(mark)
850 mark = checkformat(mark)
851 if rename not in marks:
851 if rename not in marks:
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 marks[mark] = marks[rename]
854 marks[mark] = marks[rename]
855 if repo._bookmarkcurrent == rename and not inactive:
855 if repo._bookmarkcurrent == rename and not inactive:
856 bookmarks.setcurrent(repo, mark)
856 bookmarks.setcurrent(repo, mark)
857 del marks[rename]
857 del marks[rename]
858 marks.write()
858 marks.write()
859
859
860 elif mark is not None:
860 elif mark is not None:
861 mark = checkformat(mark)
861 mark = checkformat(mark)
862 if inactive and mark == repo._bookmarkcurrent:
862 if inactive and mark == repo._bookmarkcurrent:
863 bookmarks.setcurrent(repo, None)
863 bookmarks.setcurrent(repo, None)
864 return
864 return
865 tgt = cur
865 tgt = cur
866 if rev:
866 if rev:
867 tgt = scmutil.revsingle(repo, rev).node()
867 tgt = scmutil.revsingle(repo, rev).node()
868 checkconflict(repo, mark, force, tgt)
868 checkconflict(repo, mark, force, tgt)
869 marks[mark] = tgt
869 marks[mark] = tgt
870 if not inactive and cur == marks[mark]:
870 if not inactive and cur == marks[mark]:
871 bookmarks.setcurrent(repo, mark)
871 bookmarks.setcurrent(repo, mark)
872 elif cur != tgt and mark == repo._bookmarkcurrent:
872 elif cur != tgt and mark == repo._bookmarkcurrent:
873 bookmarks.setcurrent(repo, None)
873 bookmarks.setcurrent(repo, None)
874 marks.write()
874 marks.write()
875
875
876 # Same message whether trying to deactivate the current bookmark (-i
876 # Same message whether trying to deactivate the current bookmark (-i
877 # with no NAME) or listing bookmarks
877 # with no NAME) or listing bookmarks
878 elif len(marks) == 0:
878 elif len(marks) == 0:
879 ui.status(_("no bookmarks set\n"))
879 ui.status(_("no bookmarks set\n"))
880
880
881 elif inactive:
881 elif inactive:
882 if not repo._bookmarkcurrent:
882 if not repo._bookmarkcurrent:
883 ui.status(_("no active bookmark\n"))
883 ui.status(_("no active bookmark\n"))
884 else:
884 else:
885 bookmarks.setcurrent(repo, None)
885 bookmarks.setcurrent(repo, None)
886
886
887 else: # show bookmarks
887 else: # show bookmarks
888 for bmark, n in sorted(marks.iteritems()):
888 for bmark, n in sorted(marks.iteritems()):
889 current = repo._bookmarkcurrent
889 current = repo._bookmarkcurrent
890 if bmark == current:
890 if bmark == current:
891 prefix, label = '*', 'bookmarks.current'
891 prefix, label = '*', 'bookmarks.current'
892 else:
892 else:
893 prefix, label = ' ', ''
893 prefix, label = ' ', ''
894
894
895 if ui.quiet:
895 if ui.quiet:
896 ui.write("%s\n" % bmark, label=label)
896 ui.write("%s\n" % bmark, label=label)
897 else:
897 else:
898 ui.write(" %s %-25s %d:%s\n" % (
898 ui.write(" %s %-25s %d:%s\n" % (
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
900 label=label)
900 label=label)
901
901
902 @command('branch',
902 @command('branch',
903 [('f', 'force', None,
903 [('f', 'force', None,
904 _('set branch name even if it shadows an existing branch')),
904 _('set branch name even if it shadows an existing branch')),
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
906 _('[-fC] [NAME]'))
906 _('[-fC] [NAME]'))
907 def branch(ui, repo, label=None, **opts):
907 def branch(ui, repo, label=None, **opts):
908 """set or show the current branch name
908 """set or show the current branch name
909
909
910 .. note::
910 .. note::
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
912 light-weight bookmark instead. See :hg:`help glossary` for more
912 light-weight bookmark instead. See :hg:`help glossary` for more
913 information about named branches and bookmarks.
913 information about named branches and bookmarks.
914
914
915 With no argument, show the current branch name. With one argument,
915 With no argument, show the current branch name. With one argument,
916 set the working directory branch name (the branch will not exist
916 set the working directory branch name (the branch will not exist
917 in the repository until the next commit). Standard practice
917 in the repository until the next commit). Standard practice
918 recommends that primary development take place on the 'default'
918 recommends that primary development take place on the 'default'
919 branch.
919 branch.
920
920
921 Unless -f/--force is specified, branch will not let you set a
921 Unless -f/--force is specified, branch will not let you set a
922 branch name that already exists, even if it's inactive.
922 branch name that already exists, even if it's inactive.
923
923
924 Use -C/--clean to reset the working directory branch to that of
924 Use -C/--clean to reset the working directory branch to that of
925 the parent of the working directory, negating a previous branch
925 the parent of the working directory, negating a previous branch
926 change.
926 change.
927
927
928 Use the command :hg:`update` to switch to an existing branch. Use
928 Use the command :hg:`update` to switch to an existing branch. Use
929 :hg:`commit --close-branch` to mark this branch as closed.
929 :hg:`commit --close-branch` to mark this branch as closed.
930
930
931 Returns 0 on success.
931 Returns 0 on success.
932 """
932 """
933 if not opts.get('clean') and not label:
933 if not opts.get('clean') and not label:
934 ui.write("%s\n" % repo.dirstate.branch())
934 ui.write("%s\n" % repo.dirstate.branch())
935 return
935 return
936
936
937 wlock = repo.wlock()
937 wlock = repo.wlock()
938 try:
938 try:
939 if opts.get('clean'):
939 if opts.get('clean'):
940 label = repo[None].p1().branch()
940 label = repo[None].p1().branch()
941 repo.dirstate.setbranch(label)
941 repo.dirstate.setbranch(label)
942 ui.status(_('reset working directory to branch %s\n') % label)
942 ui.status(_('reset working directory to branch %s\n') % label)
943 elif label:
943 elif label:
944 if not opts.get('force') and label in repo.branchmap():
944 if not opts.get('force') and label in repo.branchmap():
945 if label not in [p.branch() for p in repo.parents()]:
945 if label not in [p.branch() for p in repo.parents()]:
946 raise util.Abort(_('a branch of the same name already'
946 raise util.Abort(_('a branch of the same name already'
947 ' exists'),
947 ' exists'),
948 # i18n: "it" refers to an existing branch
948 # i18n: "it" refers to an existing branch
949 hint=_("use 'hg update' to switch to it"))
949 hint=_("use 'hg update' to switch to it"))
950 scmutil.checknewlabel(repo, label, 'branch')
950 scmutil.checknewlabel(repo, label, 'branch')
951 repo.dirstate.setbranch(label)
951 repo.dirstate.setbranch(label)
952 ui.status(_('marked working directory as branch %s\n') % label)
952 ui.status(_('marked working directory as branch %s\n') % label)
953 ui.status(_('(branches are permanent and global, '
953 ui.status(_('(branches are permanent and global, '
954 'did you want a bookmark?)\n'))
954 'did you want a bookmark?)\n'))
955 finally:
955 finally:
956 wlock.release()
956 wlock.release()
957
957
958 @command('branches',
958 @command('branches',
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
960 ('c', 'closed', False, _('show normal and closed branches'))],
960 ('c', 'closed', False, _('show normal and closed branches'))],
961 _('[-ac]'))
961 _('[-ac]'))
962 def branches(ui, repo, active=False, closed=False):
962 def branches(ui, repo, active=False, closed=False):
963 """list repository named branches
963 """list repository named branches
964
964
965 List the repository's named branches, indicating which ones are
965 List the repository's named branches, indicating which ones are
966 inactive. If -c/--closed is specified, also list branches which have
966 inactive. If -c/--closed is specified, also list branches which have
967 been marked closed (see :hg:`commit --close-branch`).
967 been marked closed (see :hg:`commit --close-branch`).
968
968
969 If -a/--active is specified, only show active branches. A branch
969 If -a/--active is specified, only show active branches. A branch
970 is considered active if it contains repository heads.
970 is considered active if it contains repository heads.
971
971
972 Use the command :hg:`update` to switch to an existing branch.
972 Use the command :hg:`update` to switch to an existing branch.
973
973
974 Returns 0.
974 Returns 0.
975 """
975 """
976
976
977 hexfunc = ui.debugflag and hex or short
977 hexfunc = ui.debugflag and hex or short
978
978
979 activebranches = set([repo[n].branch() for n in repo.heads()])
979 activebranches = set([repo[n].branch() for n in repo.heads()])
980 branches = []
980 branches = []
981 for tag, heads in repo.branchmap().iteritems():
981 for tag, heads in repo.branchmap().iteritems():
982 for h in reversed(heads):
982 for h in reversed(heads):
983 ctx = repo[h]
983 ctx = repo[h]
984 isopen = not ctx.closesbranch()
984 isopen = not ctx.closesbranch()
985 if isopen:
985 if isopen:
986 tip = ctx
986 tip = ctx
987 break
987 break
988 else:
988 else:
989 tip = repo[heads[-1]]
989 tip = repo[heads[-1]]
990 isactive = tag in activebranches and isopen
990 isactive = tag in activebranches and isopen
991 branches.append((tip, isactive, isopen))
991 branches.append((tip, isactive, isopen))
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
993 reverse=True)
993 reverse=True)
994
994
995 for ctx, isactive, isopen in branches:
995 for ctx, isactive, isopen in branches:
996 if (not active) or isactive:
996 if (not active) or isactive:
997 if isactive:
997 if isactive:
998 label = 'branches.active'
998 label = 'branches.active'
999 notice = ''
999 notice = ''
1000 elif not isopen:
1000 elif not isopen:
1001 if not closed:
1001 if not closed:
1002 continue
1002 continue
1003 label = 'branches.closed'
1003 label = 'branches.closed'
1004 notice = _(' (closed)')
1004 notice = _(' (closed)')
1005 else:
1005 else:
1006 label = 'branches.inactive'
1006 label = 'branches.inactive'
1007 notice = _(' (inactive)')
1007 notice = _(' (inactive)')
1008 if ctx.branch() == repo.dirstate.branch():
1008 if ctx.branch() == repo.dirstate.branch():
1009 label = 'branches.current'
1009 label = 'branches.current'
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1012 'log.changeset changeset.%s' % ctx.phasestr())
1012 'log.changeset changeset.%s' % ctx.phasestr())
1013 tag = ui.label(ctx.branch(), label)
1013 tag = ui.label(ctx.branch(), label)
1014 if ui.quiet:
1014 if ui.quiet:
1015 ui.write("%s\n" % tag)
1015 ui.write("%s\n" % tag)
1016 else:
1016 else:
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1018
1018
1019 @command('bundle',
1019 @command('bundle',
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1022 _('REV')),
1022 _('REV')),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1024 _('BRANCH')),
1024 _('BRANCH')),
1025 ('', 'base', [],
1025 ('', 'base', [],
1026 _('a base changeset assumed to be available at the destination'),
1026 _('a base changeset assumed to be available at the destination'),
1027 _('REV')),
1027 _('REV')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1032 def bundle(ui, repo, fname, dest=None, **opts):
1032 def bundle(ui, repo, fname, dest=None, **opts):
1033 """create a changegroup file
1033 """create a changegroup file
1034
1034
1035 Generate a compressed changegroup file collecting changesets not
1035 Generate a compressed changegroup file collecting changesets not
1036 known to be in another repository.
1036 known to be in another repository.
1037
1037
1038 If you omit the destination repository, then hg assumes the
1038 If you omit the destination repository, then hg assumes the
1039 destination will have all the nodes you specify with --base
1039 destination will have all the nodes you specify with --base
1040 parameters. To create a bundle containing all changesets, use
1040 parameters. To create a bundle containing all changesets, use
1041 -a/--all (or --base null).
1041 -a/--all (or --base null).
1042
1042
1043 You can change compression method with the -t/--type option.
1043 You can change compression method with the -t/--type option.
1044 The available compression methods are: none, bzip2, and
1044 The available compression methods are: none, bzip2, and
1045 gzip (by default, bundles are compressed using bzip2).
1045 gzip (by default, bundles are compressed using bzip2).
1046
1046
1047 The bundle file can then be transferred using conventional means
1047 The bundle file can then be transferred using conventional means
1048 and applied to another repository with the unbundle or pull
1048 and applied to another repository with the unbundle or pull
1049 command. This is useful when direct push and pull are not
1049 command. This is useful when direct push and pull are not
1050 available or when exporting an entire repository is undesirable.
1050 available or when exporting an entire repository is undesirable.
1051
1051
1052 Applying bundles preserves all changeset contents including
1052 Applying bundles preserves all changeset contents including
1053 permissions, copy/rename information, and revision history.
1053 permissions, copy/rename information, and revision history.
1054
1054
1055 Returns 0 on success, 1 if no changes found.
1055 Returns 0 on success, 1 if no changes found.
1056 """
1056 """
1057 revs = None
1057 revs = None
1058 if 'rev' in opts:
1058 if 'rev' in opts:
1059 revs = scmutil.revrange(repo, opts['rev'])
1059 revs = scmutil.revrange(repo, opts['rev'])
1060
1060
1061 bundletype = opts.get('type', 'bzip2').lower()
1061 bundletype = opts.get('type', 'bzip2').lower()
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1063 bundletype = btypes.get(bundletype)
1063 bundletype = btypes.get(bundletype)
1064 if bundletype not in changegroup.bundletypes:
1064 if bundletype not in changegroup.bundletypes:
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1066
1066
1067 if opts.get('all'):
1067 if opts.get('all'):
1068 base = ['null']
1068 base = ['null']
1069 else:
1069 else:
1070 base = scmutil.revrange(repo, opts.get('base'))
1070 base = scmutil.revrange(repo, opts.get('base'))
1071 if base:
1071 if base:
1072 if dest:
1072 if dest:
1073 raise util.Abort(_("--base is incompatible with specifying "
1073 raise util.Abort(_("--base is incompatible with specifying "
1074 "a destination"))
1074 "a destination"))
1075 common = [repo.lookup(rev) for rev in base]
1075 common = [repo.lookup(rev) for rev in base]
1076 heads = revs and map(repo.lookup, revs) or revs
1076 heads = revs and map(repo.lookup, revs) or revs
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1078 outgoing = None
1078 outgoing = None
1079 else:
1079 else:
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1082 other = hg.peer(repo, opts, dest)
1082 other = hg.peer(repo, opts, dest)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1084 heads = revs and map(repo.lookup, revs) or revs
1084 heads = revs and map(repo.lookup, revs) or revs
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1086 onlyheads=heads,
1086 onlyheads=heads,
1087 force=opts.get('force'),
1087 force=opts.get('force'),
1088 portable=True)
1088 portable=True)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1090 if not cg:
1090 if not cg:
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1092 return 1
1092 return 1
1093
1093
1094 changegroup.writebundle(cg, fname, bundletype)
1094 changegroup.writebundle(cg, fname, bundletype)
1095
1095
1096 @command('cat',
1096 @command('cat',
1097 [('o', 'output', '',
1097 [('o', 'output', '',
1098 _('print output to file with formatted name'), _('FORMAT')),
1098 _('print output to file with formatted name'), _('FORMAT')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1101 ] + walkopts,
1101 ] + walkopts,
1102 _('[OPTION]... FILE...'))
1102 _('[OPTION]... FILE...'))
1103 def cat(ui, repo, file1, *pats, **opts):
1103 def cat(ui, repo, file1, *pats, **opts):
1104 """output the current or given revision of files
1104 """output the current or given revision of files
1105
1105
1106 Print the specified files as they were at the given revision. If
1106 Print the specified files as they were at the given revision. If
1107 no revision is given, the parent of the working directory is used,
1107 no revision is given, the parent of the working directory is used,
1108 or tip if no revision is checked out.
1108 or tip if no revision is checked out.
1109
1109
1110 Output may be to a file, in which case the name of the file is
1110 Output may be to a file, in which case the name of the file is
1111 given using a format string. The formatting rules are the same as
1111 given using a format string. The formatting rules are the same as
1112 for the export command, with the following additions:
1112 for the export command, with the following additions:
1113
1113
1114 :``%s``: basename of file being printed
1114 :``%s``: basename of file being printed
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1116 :``%p``: root-relative path name of file being printed
1116 :``%p``: root-relative path name of file being printed
1117
1117
1118 Returns 0 on success.
1118 Returns 0 on success.
1119 """
1119 """
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1121 err = 1
1121 err = 1
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1123 for abs in ctx.walk(m):
1123 for abs in ctx.walk(m):
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1125 pathname=abs)
1125 pathname=abs)
1126 data = ctx[abs].data()
1126 data = ctx[abs].data()
1127 if opts.get('decode'):
1127 if opts.get('decode'):
1128 data = repo.wwritedata(abs, data)
1128 data = repo.wwritedata(abs, data)
1129 fp.write(data)
1129 fp.write(data)
1130 fp.close()
1130 fp.close()
1131 err = 0
1131 err = 0
1132 return err
1132 return err
1133
1133
1134 @command('^clone',
1134 @command('^clone',
1135 [('U', 'noupdate', None,
1135 [('U', 'noupdate', None,
1136 _('the clone will include an empty working copy (only a repository)')),
1136 _('the clone will include an empty working copy (only a repository)')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1142 ] + remoteopts,
1142 ] + remoteopts,
1143 _('[OPTION]... SOURCE [DEST]'))
1143 _('[OPTION]... SOURCE [DEST]'))
1144 def clone(ui, source, dest=None, **opts):
1144 def clone(ui, source, dest=None, **opts):
1145 """make a copy of an existing repository
1145 """make a copy of an existing repository
1146
1146
1147 Create a copy of an existing repository in a new directory.
1147 Create a copy of an existing repository in a new directory.
1148
1148
1149 If no destination directory name is specified, it defaults to the
1149 If no destination directory name is specified, it defaults to the
1150 basename of the source.
1150 basename of the source.
1151
1151
1152 The location of the source is added to the new repository's
1152 The location of the source is added to the new repository's
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1154
1154
1155 Only local paths and ``ssh://`` URLs are supported as
1155 Only local paths and ``ssh://`` URLs are supported as
1156 destinations. For ``ssh://`` destinations, no working directory or
1156 destinations. For ``ssh://`` destinations, no working directory or
1157 ``.hg/hgrc`` will be created on the remote side.
1157 ``.hg/hgrc`` will be created on the remote side.
1158
1158
1159 To pull only a subset of changesets, specify one or more revisions
1159 To pull only a subset of changesets, specify one or more revisions
1160 identifiers with -r/--rev or branches with -b/--branch. The
1160 identifiers with -r/--rev or branches with -b/--branch. The
1161 resulting clone will contain only the specified changesets and
1161 resulting clone will contain only the specified changesets and
1162 their ancestors. These options (or 'clone src#rev dest') imply
1162 their ancestors. These options (or 'clone src#rev dest') imply
1163 --pull, even for local source repositories. Note that specifying a
1163 --pull, even for local source repositories. Note that specifying a
1164 tag will include the tagged changeset but not the changeset
1164 tag will include the tagged changeset but not the changeset
1165 containing the tag.
1165 containing the tag.
1166
1166
1167 If the source repository has a bookmark called '@' set, that
1167 If the source repository has a bookmark called '@' set, that
1168 revision will be checked out in the new repository by default.
1168 revision will be checked out in the new repository by default.
1169
1169
1170 To check out a particular version, use -u/--update, or
1170 To check out a particular version, use -u/--update, or
1171 -U/--noupdate to create a clone with no working directory.
1171 -U/--noupdate to create a clone with no working directory.
1172
1172
1173 .. container:: verbose
1173 .. container:: verbose
1174
1174
1175 For efficiency, hardlinks are used for cloning whenever the
1175 For efficiency, hardlinks are used for cloning whenever the
1176 source and destination are on the same filesystem (note this
1176 source and destination are on the same filesystem (note this
1177 applies only to the repository data, not to the working
1177 applies only to the repository data, not to the working
1178 directory). Some filesystems, such as AFS, implement hardlinking
1178 directory). Some filesystems, such as AFS, implement hardlinking
1179 incorrectly, but do not report errors. In these cases, use the
1179 incorrectly, but do not report errors. In these cases, use the
1180 --pull option to avoid hardlinking.
1180 --pull option to avoid hardlinking.
1181
1181
1182 In some cases, you can clone repositories and the working
1182 In some cases, you can clone repositories and the working
1183 directory using full hardlinks with ::
1183 directory using full hardlinks with ::
1184
1184
1185 $ cp -al REPO REPOCLONE
1185 $ cp -al REPO REPOCLONE
1186
1186
1187 This is the fastest way to clone, but it is not always safe. The
1187 This is the fastest way to clone, but it is not always safe. The
1188 operation is not atomic (making sure REPO is not modified during
1188 operation is not atomic (making sure REPO is not modified during
1189 the operation is up to you) and you have to make sure your
1189 the operation is up to you) and you have to make sure your
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1191 so). Also, this is not compatible with certain extensions that
1191 so). Also, this is not compatible with certain extensions that
1192 place their metadata under the .hg directory, such as mq.
1192 place their metadata under the .hg directory, such as mq.
1193
1193
1194 Mercurial will update the working directory to the first applicable
1194 Mercurial will update the working directory to the first applicable
1195 revision from this list:
1195 revision from this list:
1196
1196
1197 a) null if -U or the source repository has no changesets
1197 a) null if -U or the source repository has no changesets
1198 b) if -u . and the source repository is local, the first parent of
1198 b) if -u . and the source repository is local, the first parent of
1199 the source repository's working directory
1199 the source repository's working directory
1200 c) the changeset specified with -u (if a branch name, this means the
1200 c) the changeset specified with -u (if a branch name, this means the
1201 latest head of that branch)
1201 latest head of that branch)
1202 d) the changeset specified with -r
1202 d) the changeset specified with -r
1203 e) the tipmost head specified with -b
1203 e) the tipmost head specified with -b
1204 f) the tipmost head specified with the url#branch source syntax
1204 f) the tipmost head specified with the url#branch source syntax
1205 g) the revision marked with the '@' bookmark, if present
1205 g) the revision marked with the '@' bookmark, if present
1206 h) the tipmost head of the default branch
1206 h) the tipmost head of the default branch
1207 i) tip
1207 i) tip
1208
1208
1209 Examples:
1209 Examples:
1210
1210
1211 - clone a remote repository to a new directory named hg/::
1211 - clone a remote repository to a new directory named hg/::
1212
1212
1213 hg clone http://selenic.com/hg
1213 hg clone http://selenic.com/hg
1214
1214
1215 - create a lightweight local clone::
1215 - create a lightweight local clone::
1216
1216
1217 hg clone project/ project-feature/
1217 hg clone project/ project-feature/
1218
1218
1219 - clone from an absolute path on an ssh server (note double-slash)::
1219 - clone from an absolute path on an ssh server (note double-slash)::
1220
1220
1221 hg clone ssh://user@server//home/projects/alpha/
1221 hg clone ssh://user@server//home/projects/alpha/
1222
1222
1223 - do a high-speed clone over a LAN while checking out a
1223 - do a high-speed clone over a LAN while checking out a
1224 specified version::
1224 specified version::
1225
1225
1226 hg clone --uncompressed http://server/repo -u 1.5
1226 hg clone --uncompressed http://server/repo -u 1.5
1227
1227
1228 - create a repository without changesets after a particular revision::
1228 - create a repository without changesets after a particular revision::
1229
1229
1230 hg clone -r 04e544 experimental/ good/
1230 hg clone -r 04e544 experimental/ good/
1231
1231
1232 - clone (and track) a particular named branch::
1232 - clone (and track) a particular named branch::
1233
1233
1234 hg clone http://selenic.com/hg#stable
1234 hg clone http://selenic.com/hg#stable
1235
1235
1236 See :hg:`help urls` for details on specifying URLs.
1236 See :hg:`help urls` for details on specifying URLs.
1237
1237
1238 Returns 0 on success.
1238 Returns 0 on success.
1239 """
1239 """
1240 if opts.get('noupdate') and opts.get('updaterev'):
1240 if opts.get('noupdate') and opts.get('updaterev'):
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1242
1242
1243 r = hg.clone(ui, opts, source, dest,
1243 r = hg.clone(ui, opts, source, dest,
1244 pull=opts.get('pull'),
1244 pull=opts.get('pull'),
1245 stream=opts.get('uncompressed'),
1245 stream=opts.get('uncompressed'),
1246 rev=opts.get('rev'),
1246 rev=opts.get('rev'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1248 branch=opts.get('branch'))
1248 branch=opts.get('branch'))
1249
1249
1250 return r is None
1250 return r is None
1251
1251
1252 @command('^commit|ci',
1252 @command('^commit|ci',
1253 [('A', 'addremove', None,
1253 [('A', 'addremove', None,
1254 _('mark new/missing files as added/removed before committing')),
1254 _('mark new/missing files as added/removed before committing')),
1255 ('', 'close-branch', None,
1255 ('', 'close-branch', None,
1256 _('mark a branch as closed, hiding it from the branch list')),
1256 _('mark a branch as closed, hiding it from the branch list')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1259 _('[OPTION]... [FILE]...'))
1259 _('[OPTION]... [FILE]...'))
1260 def commit(ui, repo, *pats, **opts):
1260 def commit(ui, repo, *pats, **opts):
1261 """commit the specified files or all outstanding changes
1261 """commit the specified files or all outstanding changes
1262
1262
1263 Commit changes to the given files into the repository. Unlike a
1263 Commit changes to the given files into the repository. Unlike a
1264 centralized SCM, this operation is a local operation. See
1264 centralized SCM, this operation is a local operation. See
1265 :hg:`push` for a way to actively distribute your changes.
1265 :hg:`push` for a way to actively distribute your changes.
1266
1266
1267 If a list of files is omitted, all changes reported by :hg:`status`
1267 If a list of files is omitted, all changes reported by :hg:`status`
1268 will be committed.
1268 will be committed.
1269
1269
1270 If you are committing the result of a merge, do not provide any
1270 If you are committing the result of a merge, do not provide any
1271 filenames or -I/-X filters.
1271 filenames or -I/-X filters.
1272
1272
1273 If no commit message is specified, Mercurial starts your
1273 If no commit message is specified, Mercurial starts your
1274 configured editor where you can enter a message. In case your
1274 configured editor where you can enter a message. In case your
1275 commit fails, you will find a backup of your message in
1275 commit fails, you will find a backup of your message in
1276 ``.hg/last-message.txt``.
1276 ``.hg/last-message.txt``.
1277
1277
1278 The --amend flag can be used to amend the parent of the
1278 The --amend flag can be used to amend the parent of the
1279 working directory with a new commit that contains the changes
1279 working directory with a new commit that contains the changes
1280 in the parent in addition to those currently reported by :hg:`status`,
1280 in the parent in addition to those currently reported by :hg:`status`,
1281 if there are any. The old commit is stored in a backup bundle in
1281 if there are any. The old commit is stored in a backup bundle in
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1283 on how to restore it).
1283 on how to restore it).
1284
1284
1285 Message, user and date are taken from the amended commit unless
1285 Message, user and date are taken from the amended commit unless
1286 specified. When a message isn't specified on the command line,
1286 specified. When a message isn't specified on the command line,
1287 the editor will open with the message of the amended commit.
1287 the editor will open with the message of the amended commit.
1288
1288
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1290 or changesets that have children.
1290 or changesets that have children.
1291
1291
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1293
1293
1294 Returns 0 on success, 1 if nothing changed.
1294 Returns 0 on success, 1 if nothing changed.
1295 """
1295 """
1296 if opts.get('subrepos'):
1296 if opts.get('subrepos'):
1297 # Let --subrepos on the command line override config setting.
1297 # Let --subrepos on the command line override config setting.
1298 ui.setconfig('ui', 'commitsubrepos', True)
1298 ui.setconfig('ui', 'commitsubrepos', True)
1299
1299
1300 extra = {}
1300 extra = {}
1301 if opts.get('close_branch'):
1301 if opts.get('close_branch'):
1302 if repo['.'].node() not in repo.branchheads():
1302 if repo['.'].node() not in repo.branchheads():
1303 # The topo heads set is included in the branch heads set of the
1303 # The topo heads set is included in the branch heads set of the
1304 # current branch, so it's sufficient to test branchheads
1304 # current branch, so it's sufficient to test branchheads
1305 raise util.Abort(_('can only close branch heads'))
1305 raise util.Abort(_('can only close branch heads'))
1306 extra['close'] = 1
1306 extra['close'] = 1
1307
1307
1308 branch = repo[None].branch()
1308 branch = repo[None].branch()
1309 bheads = repo.branchheads(branch)
1309 bheads = repo.branchheads(branch)
1310
1310
1311 if opts.get('amend'):
1311 if opts.get('amend'):
1312 if ui.configbool('ui', 'commitsubrepos'):
1312 if ui.configbool('ui', 'commitsubrepos'):
1313 raise util.Abort(_('cannot amend recursively'))
1313 raise util.Abort(_('cannot amend recursively'))
1314
1314
1315 old = repo['.']
1315 old = repo['.']
1316 if old.phase() == phases.public:
1316 if old.phase() == phases.public:
1317 raise util.Abort(_('cannot amend public changesets'))
1317 raise util.Abort(_('cannot amend public changesets'))
1318 if len(old.parents()) > 1:
1318 if len(old.parents()) > 1:
1319 raise util.Abort(_('cannot amend merge changesets'))
1319 raise util.Abort(_('cannot amend merge changesets'))
1320 if len(repo[None].parents()) > 1:
1320 if len(repo[None].parents()) > 1:
1321 raise util.Abort(_('cannot amend while merging'))
1321 raise util.Abort(_('cannot amend while merging'))
1322 if (not obsolete._enabled) and old.children():
1322 if (not obsolete._enabled) and old.children():
1323 raise util.Abort(_('cannot amend changeset with children'))
1323 raise util.Abort(_('cannot amend changeset with children'))
1324
1324
1325 e = cmdutil.commiteditor
1325 e = cmdutil.commiteditor
1326 if opts.get('force_editor'):
1326 if opts.get('force_editor'):
1327 e = cmdutil.commitforceeditor
1327 e = cmdutil.commitforceeditor
1328
1328
1329 def commitfunc(ui, repo, message, match, opts):
1329 def commitfunc(ui, repo, message, match, opts):
1330 editor = e
1330 editor = e
1331 # message contains text from -m or -l, if it's empty,
1331 # message contains text from -m or -l, if it's empty,
1332 # open the editor with the old message
1332 # open the editor with the old message
1333 if not message:
1333 if not message:
1334 message = old.description()
1334 message = old.description()
1335 editor = cmdutil.commitforceeditor
1335 editor = cmdutil.commitforceeditor
1336 return repo.commit(message,
1336 return repo.commit(message,
1337 opts.get('user') or old.user(),
1337 opts.get('user') or old.user(),
1338 opts.get('date') or old.date(),
1338 opts.get('date') or old.date(),
1339 match,
1339 match,
1340 editor=editor,
1340 editor=editor,
1341 extra=extra)
1341 extra=extra)
1342
1342
1343 current = repo._bookmarkcurrent
1343 current = repo._bookmarkcurrent
1344 marks = old.bookmarks()
1344 marks = old.bookmarks()
1345 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1345 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1346 if node == old.node():
1346 if node == old.node():
1347 ui.status(_("nothing changed\n"))
1347 ui.status(_("nothing changed\n"))
1348 return 1
1348 return 1
1349 elif marks:
1349 elif marks:
1350 ui.debug('moving bookmarks %r from %s to %s\n' %
1350 ui.debug('moving bookmarks %r from %s to %s\n' %
1351 (marks, old.hex(), hex(node)))
1351 (marks, old.hex(), hex(node)))
1352 newmarks = repo._bookmarks
1352 newmarks = repo._bookmarks
1353 for bm in marks:
1353 for bm in marks:
1354 newmarks[bm] = node
1354 newmarks[bm] = node
1355 if bm == current:
1355 if bm == current:
1356 bookmarks.setcurrent(repo, bm)
1356 bookmarks.setcurrent(repo, bm)
1357 newmarks.write()
1357 newmarks.write()
1358 else:
1358 else:
1359 e = cmdutil.commiteditor
1359 e = cmdutil.commiteditor
1360 if opts.get('force_editor'):
1360 if opts.get('force_editor'):
1361 e = cmdutil.commitforceeditor
1361 e = cmdutil.commitforceeditor
1362
1362
1363 def commitfunc(ui, repo, message, match, opts):
1363 def commitfunc(ui, repo, message, match, opts):
1364 return repo.commit(message, opts.get('user'), opts.get('date'),
1364 return repo.commit(message, opts.get('user'), opts.get('date'),
1365 match, editor=e, extra=extra)
1365 match, editor=e, extra=extra)
1366
1366
1367 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1367 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1368
1368
1369 if not node:
1369 if not node:
1370 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1370 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1371 if stat[3]:
1371 if stat[3]:
1372 ui.status(_("nothing changed (%d missing files, see "
1372 ui.status(_("nothing changed (%d missing files, see "
1373 "'hg status')\n") % len(stat[3]))
1373 "'hg status')\n") % len(stat[3]))
1374 else:
1374 else:
1375 ui.status(_("nothing changed\n"))
1375 ui.status(_("nothing changed\n"))
1376 return 1
1376 return 1
1377
1377
1378 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1378 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1379
1379
1380 @command('copy|cp',
1380 @command('copy|cp',
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1383 ] + walkopts + dryrunopts,
1383 ] + walkopts + dryrunopts,
1384 _('[OPTION]... [SOURCE]... DEST'))
1384 _('[OPTION]... [SOURCE]... DEST'))
1385 def copy(ui, repo, *pats, **opts):
1385 def copy(ui, repo, *pats, **opts):
1386 """mark files as copied for the next commit
1386 """mark files as copied for the next commit
1387
1387
1388 Mark dest as having copies of source files. If dest is a
1388 Mark dest as having copies of source files. If dest is a
1389 directory, copies are put in that directory. If dest is a file,
1389 directory, copies are put in that directory. If dest is a file,
1390 the source must be a single file.
1390 the source must be a single file.
1391
1391
1392 By default, this command copies the contents of files as they
1392 By default, this command copies the contents of files as they
1393 exist in the working directory. If invoked with -A/--after, the
1393 exist in the working directory. If invoked with -A/--after, the
1394 operation is recorded, but no copying is performed.
1394 operation is recorded, but no copying is performed.
1395
1395
1396 This command takes effect with the next commit. To undo a copy
1396 This command takes effect with the next commit. To undo a copy
1397 before that, see :hg:`revert`.
1397 before that, see :hg:`revert`.
1398
1398
1399 Returns 0 on success, 1 if errors are encountered.
1399 Returns 0 on success, 1 if errors are encountered.
1400 """
1400 """
1401 wlock = repo.wlock(False)
1401 wlock = repo.wlock(False)
1402 try:
1402 try:
1403 return cmdutil.copy(ui, repo, pats, opts)
1403 return cmdutil.copy(ui, repo, pats, opts)
1404 finally:
1404 finally:
1405 wlock.release()
1405 wlock.release()
1406
1406
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1408 def debugancestor(ui, repo, *args):
1408 def debugancestor(ui, repo, *args):
1409 """find the ancestor revision of two revisions in a given index"""
1409 """find the ancestor revision of two revisions in a given index"""
1410 if len(args) == 3:
1410 if len(args) == 3:
1411 index, rev1, rev2 = args
1411 index, rev1, rev2 = args
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1413 lookup = r.lookup
1413 lookup = r.lookup
1414 elif len(args) == 2:
1414 elif len(args) == 2:
1415 if not repo:
1415 if not repo:
1416 raise util.Abort(_("there is no Mercurial repository here "
1416 raise util.Abort(_("there is no Mercurial repository here "
1417 "(.hg not found)"))
1417 "(.hg not found)"))
1418 rev1, rev2 = args
1418 rev1, rev2 = args
1419 r = repo.changelog
1419 r = repo.changelog
1420 lookup = repo.lookup
1420 lookup = repo.lookup
1421 else:
1421 else:
1422 raise util.Abort(_('either two or three arguments required'))
1422 raise util.Abort(_('either two or three arguments required'))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1425
1425
1426 @command('debugbuilddag',
1426 @command('debugbuilddag',
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1430 _('[OPTION]... [TEXT]'))
1430 _('[OPTION]... [TEXT]'))
1431 def debugbuilddag(ui, repo, text=None,
1431 def debugbuilddag(ui, repo, text=None,
1432 mergeable_file=False,
1432 mergeable_file=False,
1433 overwritten_file=False,
1433 overwritten_file=False,
1434 new_file=False):
1434 new_file=False):
1435 """builds a repo with a given DAG from scratch in the current empty repo
1435 """builds a repo with a given DAG from scratch in the current empty repo
1436
1436
1437 The description of the DAG is read from stdin if not given on the
1437 The description of the DAG is read from stdin if not given on the
1438 command line.
1438 command line.
1439
1439
1440 Elements:
1440 Elements:
1441
1441
1442 - "+n" is a linear run of n nodes based on the current default parent
1442 - "+n" is a linear run of n nodes based on the current default parent
1443 - "." is a single node based on the current default parent
1443 - "." is a single node based on the current default parent
1444 - "$" resets the default parent to null (implied at the start);
1444 - "$" resets the default parent to null (implied at the start);
1445 otherwise the default parent is always the last node created
1445 otherwise the default parent is always the last node created
1446 - "<p" sets the default parent to the backref p
1446 - "<p" sets the default parent to the backref p
1447 - "*p" is a fork at parent p, which is a backref
1447 - "*p" is a fork at parent p, which is a backref
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1449 - "/p2" is a merge of the preceding node and p2
1449 - "/p2" is a merge of the preceding node and p2
1450 - ":tag" defines a local tag for the preceding node
1450 - ":tag" defines a local tag for the preceding node
1451 - "@branch" sets the named branch for subsequent nodes
1451 - "@branch" sets the named branch for subsequent nodes
1452 - "#...\\n" is a comment up to the end of the line
1452 - "#...\\n" is a comment up to the end of the line
1453
1453
1454 Whitespace between the above elements is ignored.
1454 Whitespace between the above elements is ignored.
1455
1455
1456 A backref is either
1456 A backref is either
1457
1457
1458 - a number n, which references the node curr-n, where curr is the current
1458 - a number n, which references the node curr-n, where curr is the current
1459 node, or
1459 node, or
1460 - the name of a local tag you placed earlier using ":tag", or
1460 - the name of a local tag you placed earlier using ":tag", or
1461 - empty to denote the default parent.
1461 - empty to denote the default parent.
1462
1462
1463 All string valued-elements are either strictly alphanumeric, or must
1463 All string valued-elements are either strictly alphanumeric, or must
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1465 """
1465 """
1466
1466
1467 if text is None:
1467 if text is None:
1468 ui.status(_("reading DAG from stdin\n"))
1468 ui.status(_("reading DAG from stdin\n"))
1469 text = ui.fin.read()
1469 text = ui.fin.read()
1470
1470
1471 cl = repo.changelog
1471 cl = repo.changelog
1472 if len(cl) > 0:
1472 if len(cl) > 0:
1473 raise util.Abort(_('repository is not empty'))
1473 raise util.Abort(_('repository is not empty'))
1474
1474
1475 # determine number of revs in DAG
1475 # determine number of revs in DAG
1476 total = 0
1476 total = 0
1477 for type, data in dagparser.parsedag(text):
1477 for type, data in dagparser.parsedag(text):
1478 if type == 'n':
1478 if type == 'n':
1479 total += 1
1479 total += 1
1480
1480
1481 if mergeable_file:
1481 if mergeable_file:
1482 linesperrev = 2
1482 linesperrev = 2
1483 # make a file with k lines per rev
1483 # make a file with k lines per rev
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1485 initialmergedlines.append("")
1485 initialmergedlines.append("")
1486
1486
1487 tags = []
1487 tags = []
1488
1488
1489 lock = tr = None
1489 lock = tr = None
1490 try:
1490 try:
1491 lock = repo.lock()
1491 lock = repo.lock()
1492 tr = repo.transaction("builddag")
1492 tr = repo.transaction("builddag")
1493
1493
1494 at = -1
1494 at = -1
1495 atbranch = 'default'
1495 atbranch = 'default'
1496 nodeids = []
1496 nodeids = []
1497 id = 0
1497 id = 0
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1499 for type, data in dagparser.parsedag(text):
1499 for type, data in dagparser.parsedag(text):
1500 if type == 'n':
1500 if type == 'n':
1501 ui.note(('node %s\n' % str(data)))
1501 ui.note(('node %s\n' % str(data)))
1502 id, ps = data
1502 id, ps = data
1503
1503
1504 files = []
1504 files = []
1505 fctxs = {}
1505 fctxs = {}
1506
1506
1507 p2 = None
1507 p2 = None
1508 if mergeable_file:
1508 if mergeable_file:
1509 fn = "mf"
1509 fn = "mf"
1510 p1 = repo[ps[0]]
1510 p1 = repo[ps[0]]
1511 if len(ps) > 1:
1511 if len(ps) > 1:
1512 p2 = repo[ps[1]]
1512 p2 = repo[ps[1]]
1513 pa = p1.ancestor(p2)
1513 pa = p1.ancestor(p2)
1514 base, local, other = [x[fn].data() for x in (pa, p1,
1514 base, local, other = [x[fn].data() for x in (pa, p1,
1515 p2)]
1515 p2)]
1516 m3 = simplemerge.Merge3Text(base, local, other)
1516 m3 = simplemerge.Merge3Text(base, local, other)
1517 ml = [l.strip() for l in m3.merge_lines()]
1517 ml = [l.strip() for l in m3.merge_lines()]
1518 ml.append("")
1518 ml.append("")
1519 elif at > 0:
1519 elif at > 0:
1520 ml = p1[fn].data().split("\n")
1520 ml = p1[fn].data().split("\n")
1521 else:
1521 else:
1522 ml = initialmergedlines
1522 ml = initialmergedlines
1523 ml[id * linesperrev] += " r%i" % id
1523 ml[id * linesperrev] += " r%i" % id
1524 mergedtext = "\n".join(ml)
1524 mergedtext = "\n".join(ml)
1525 files.append(fn)
1525 files.append(fn)
1526 fctxs[fn] = context.memfilectx(fn, mergedtext)
1526 fctxs[fn] = context.memfilectx(fn, mergedtext)
1527
1527
1528 if overwritten_file:
1528 if overwritten_file:
1529 fn = "of"
1529 fn = "of"
1530 files.append(fn)
1530 files.append(fn)
1531 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1532
1532
1533 if new_file:
1533 if new_file:
1534 fn = "nf%i" % id
1534 fn = "nf%i" % id
1535 files.append(fn)
1535 files.append(fn)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1537 if len(ps) > 1:
1537 if len(ps) > 1:
1538 if not p2:
1538 if not p2:
1539 p2 = repo[ps[1]]
1539 p2 = repo[ps[1]]
1540 for fn in p2:
1540 for fn in p2:
1541 if fn.startswith("nf"):
1541 if fn.startswith("nf"):
1542 files.append(fn)
1542 files.append(fn)
1543 fctxs[fn] = p2[fn]
1543 fctxs[fn] = p2[fn]
1544
1544
1545 def fctxfn(repo, cx, path):
1545 def fctxfn(repo, cx, path):
1546 return fctxs.get(path)
1546 return fctxs.get(path)
1547
1547
1548 if len(ps) == 0 or ps[0] < 0:
1548 if len(ps) == 0 or ps[0] < 0:
1549 pars = [None, None]
1549 pars = [None, None]
1550 elif len(ps) == 1:
1550 elif len(ps) == 1:
1551 pars = [nodeids[ps[0]], None]
1551 pars = [nodeids[ps[0]], None]
1552 else:
1552 else:
1553 pars = [nodeids[p] for p in ps]
1553 pars = [nodeids[p] for p in ps]
1554 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1554 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1555 date=(id, 0),
1555 date=(id, 0),
1556 user="debugbuilddag",
1556 user="debugbuilddag",
1557 extra={'branch': atbranch})
1557 extra={'branch': atbranch})
1558 nodeid = repo.commitctx(cx)
1558 nodeid = repo.commitctx(cx)
1559 nodeids.append(nodeid)
1559 nodeids.append(nodeid)
1560 at = id
1560 at = id
1561 elif type == 'l':
1561 elif type == 'l':
1562 id, name = data
1562 id, name = data
1563 ui.note(('tag %s\n' % name))
1563 ui.note(('tag %s\n' % name))
1564 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1564 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1565 elif type == 'a':
1565 elif type == 'a':
1566 ui.note(('branch %s\n' % data))
1566 ui.note(('branch %s\n' % data))
1567 atbranch = data
1567 atbranch = data
1568 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1569 tr.close()
1569 tr.close()
1570
1570
1571 if tags:
1571 if tags:
1572 repo.opener.write("localtags", "".join(tags))
1572 repo.opener.write("localtags", "".join(tags))
1573 finally:
1573 finally:
1574 ui.progress(_('building'), None)
1574 ui.progress(_('building'), None)
1575 release(tr, lock)
1575 release(tr, lock)
1576
1576
1577 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1577 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1578 def debugbundle(ui, bundlepath, all=None, **opts):
1578 def debugbundle(ui, bundlepath, all=None, **opts):
1579 """lists the contents of a bundle"""
1579 """lists the contents of a bundle"""
1580 f = hg.openpath(ui, bundlepath)
1580 f = hg.openpath(ui, bundlepath)
1581 try:
1581 try:
1582 gen = changegroup.readbundle(f, bundlepath)
1582 gen = changegroup.readbundle(f, bundlepath)
1583 if all:
1583 if all:
1584 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1584 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1585
1585
1586 def showchunks(named):
1586 def showchunks(named):
1587 ui.write("\n%s\n" % named)
1587 ui.write("\n%s\n" % named)
1588 chain = None
1588 chain = None
1589 while True:
1589 while True:
1590 chunkdata = gen.deltachunk(chain)
1590 chunkdata = gen.deltachunk(chain)
1591 if not chunkdata:
1591 if not chunkdata:
1592 break
1592 break
1593 node = chunkdata['node']
1593 node = chunkdata['node']
1594 p1 = chunkdata['p1']
1594 p1 = chunkdata['p1']
1595 p2 = chunkdata['p2']
1595 p2 = chunkdata['p2']
1596 cs = chunkdata['cs']
1596 cs = chunkdata['cs']
1597 deltabase = chunkdata['deltabase']
1597 deltabase = chunkdata['deltabase']
1598 delta = chunkdata['delta']
1598 delta = chunkdata['delta']
1599 ui.write("%s %s %s %s %s %s\n" %
1599 ui.write("%s %s %s %s %s %s\n" %
1600 (hex(node), hex(p1), hex(p2),
1600 (hex(node), hex(p1), hex(p2),
1601 hex(cs), hex(deltabase), len(delta)))
1601 hex(cs), hex(deltabase), len(delta)))
1602 chain = node
1602 chain = node
1603
1603
1604 chunkdata = gen.changelogheader()
1604 chunkdata = gen.changelogheader()
1605 showchunks("changelog")
1605 showchunks("changelog")
1606 chunkdata = gen.manifestheader()
1606 chunkdata = gen.manifestheader()
1607 showchunks("manifest")
1607 showchunks("manifest")
1608 while True:
1608 while True:
1609 chunkdata = gen.filelogheader()
1609 chunkdata = gen.filelogheader()
1610 if not chunkdata:
1610 if not chunkdata:
1611 break
1611 break
1612 fname = chunkdata['filename']
1612 fname = chunkdata['filename']
1613 showchunks(fname)
1613 showchunks(fname)
1614 else:
1614 else:
1615 chunkdata = gen.changelogheader()
1615 chunkdata = gen.changelogheader()
1616 chain = None
1616 chain = None
1617 while True:
1617 while True:
1618 chunkdata = gen.deltachunk(chain)
1618 chunkdata = gen.deltachunk(chain)
1619 if not chunkdata:
1619 if not chunkdata:
1620 break
1620 break
1621 node = chunkdata['node']
1621 node = chunkdata['node']
1622 ui.write("%s\n" % hex(node))
1622 ui.write("%s\n" % hex(node))
1623 chain = node
1623 chain = node
1624 finally:
1624 finally:
1625 f.close()
1625 f.close()
1626
1626
1627 @command('debugcheckstate', [], '')
1627 @command('debugcheckstate', [], '')
1628 def debugcheckstate(ui, repo):
1628 def debugcheckstate(ui, repo):
1629 """validate the correctness of the current dirstate"""
1629 """validate the correctness of the current dirstate"""
1630 parent1, parent2 = repo.dirstate.parents()
1630 parent1, parent2 = repo.dirstate.parents()
1631 m1 = repo[parent1].manifest()
1631 m1 = repo[parent1].manifest()
1632 m2 = repo[parent2].manifest()
1632 m2 = repo[parent2].manifest()
1633 errors = 0
1633 errors = 0
1634 for f in repo.dirstate:
1634 for f in repo.dirstate:
1635 state = repo.dirstate[f]
1635 state = repo.dirstate[f]
1636 if state in "nr" and f not in m1:
1636 if state in "nr" and f not in m1:
1637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1638 errors += 1
1638 errors += 1
1639 if state in "a" and f in m1:
1639 if state in "a" and f in m1:
1640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1641 errors += 1
1641 errors += 1
1642 if state in "m" and f not in m1 and f not in m2:
1642 if state in "m" and f not in m1 and f not in m2:
1643 ui.warn(_("%s in state %s, but not in either manifest\n") %
1643 ui.warn(_("%s in state %s, but not in either manifest\n") %
1644 (f, state))
1644 (f, state))
1645 errors += 1
1645 errors += 1
1646 for f in m1:
1646 for f in m1:
1647 state = repo.dirstate[f]
1647 state = repo.dirstate[f]
1648 if state not in "nrm":
1648 if state not in "nrm":
1649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1650 errors += 1
1650 errors += 1
1651 if errors:
1651 if errors:
1652 error = _(".hg/dirstate inconsistent with current parent's manifest")
1652 error = _(".hg/dirstate inconsistent with current parent's manifest")
1653 raise util.Abort(error)
1653 raise util.Abort(error)
1654
1654
1655 @command('debugcommands', [], _('[COMMAND]'))
1655 @command('debugcommands', [], _('[COMMAND]'))
1656 def debugcommands(ui, cmd='', *args):
1656 def debugcommands(ui, cmd='', *args):
1657 """list all available commands and options"""
1657 """list all available commands and options"""
1658 for cmd, vals in sorted(table.iteritems()):
1658 for cmd, vals in sorted(table.iteritems()):
1659 cmd = cmd.split('|')[0].strip('^')
1659 cmd = cmd.split('|')[0].strip('^')
1660 opts = ', '.join([i[1] for i in vals[1]])
1660 opts = ', '.join([i[1] for i in vals[1]])
1661 ui.write('%s: %s\n' % (cmd, opts))
1661 ui.write('%s: %s\n' % (cmd, opts))
1662
1662
1663 @command('debugcomplete',
1663 @command('debugcomplete',
1664 [('o', 'options', None, _('show the command options'))],
1664 [('o', 'options', None, _('show the command options'))],
1665 _('[-o] CMD'))
1665 _('[-o] CMD'))
1666 def debugcomplete(ui, cmd='', **opts):
1666 def debugcomplete(ui, cmd='', **opts):
1667 """returns the completion list associated with the given command"""
1667 """returns the completion list associated with the given command"""
1668
1668
1669 if opts.get('options'):
1669 if opts.get('options'):
1670 options = []
1670 options = []
1671 otables = [globalopts]
1671 otables = [globalopts]
1672 if cmd:
1672 if cmd:
1673 aliases, entry = cmdutil.findcmd(cmd, table, False)
1673 aliases, entry = cmdutil.findcmd(cmd, table, False)
1674 otables.append(entry[1])
1674 otables.append(entry[1])
1675 for t in otables:
1675 for t in otables:
1676 for o in t:
1676 for o in t:
1677 if "(DEPRECATED)" in o[3]:
1677 if "(DEPRECATED)" in o[3]:
1678 continue
1678 continue
1679 if o[0]:
1679 if o[0]:
1680 options.append('-%s' % o[0])
1680 options.append('-%s' % o[0])
1681 options.append('--%s' % o[1])
1681 options.append('--%s' % o[1])
1682 ui.write("%s\n" % "\n".join(options))
1682 ui.write("%s\n" % "\n".join(options))
1683 return
1683 return
1684
1684
1685 cmdlist = cmdutil.findpossible(cmd, table)
1685 cmdlist = cmdutil.findpossible(cmd, table)
1686 if ui.verbose:
1686 if ui.verbose:
1687 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1687 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1688 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1688 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1689
1689
1690 @command('debugdag',
1690 @command('debugdag',
1691 [('t', 'tags', None, _('use tags as labels')),
1691 [('t', 'tags', None, _('use tags as labels')),
1692 ('b', 'branches', None, _('annotate with branch names')),
1692 ('b', 'branches', None, _('annotate with branch names')),
1693 ('', 'dots', None, _('use dots for runs')),
1693 ('', 'dots', None, _('use dots for runs')),
1694 ('s', 'spaces', None, _('separate elements by spaces'))],
1694 ('s', 'spaces', None, _('separate elements by spaces'))],
1695 _('[OPTION]... [FILE [REV]...]'))
1695 _('[OPTION]... [FILE [REV]...]'))
1696 def debugdag(ui, repo, file_=None, *revs, **opts):
1696 def debugdag(ui, repo, file_=None, *revs, **opts):
1697 """format the changelog or an index DAG as a concise textual description
1697 """format the changelog or an index DAG as a concise textual description
1698
1698
1699 If you pass a revlog index, the revlog's DAG is emitted. If you list
1699 If you pass a revlog index, the revlog's DAG is emitted. If you list
1700 revision numbers, they get labeled in the output as rN.
1700 revision numbers, they get labeled in the output as rN.
1701
1701
1702 Otherwise, the changelog DAG of the current repo is emitted.
1702 Otherwise, the changelog DAG of the current repo is emitted.
1703 """
1703 """
1704 spaces = opts.get('spaces')
1704 spaces = opts.get('spaces')
1705 dots = opts.get('dots')
1705 dots = opts.get('dots')
1706 if file_:
1706 if file_:
1707 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1707 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1708 revs = set((int(r) for r in revs))
1708 revs = set((int(r) for r in revs))
1709 def events():
1709 def events():
1710 for r in rlog:
1710 for r in rlog:
1711 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1711 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1712 if p != -1)))
1712 if p != -1)))
1713 if r in revs:
1713 if r in revs:
1714 yield 'l', (r, "r%i" % r)
1714 yield 'l', (r, "r%i" % r)
1715 elif repo:
1715 elif repo:
1716 cl = repo.changelog
1716 cl = repo.changelog
1717 tags = opts.get('tags')
1717 tags = opts.get('tags')
1718 branches = opts.get('branches')
1718 branches = opts.get('branches')
1719 if tags:
1719 if tags:
1720 labels = {}
1720 labels = {}
1721 for l, n in repo.tags().items():
1721 for l, n in repo.tags().items():
1722 labels.setdefault(cl.rev(n), []).append(l)
1722 labels.setdefault(cl.rev(n), []).append(l)
1723 def events():
1723 def events():
1724 b = "default"
1724 b = "default"
1725 for r in cl:
1725 for r in cl:
1726 if branches:
1726 if branches:
1727 newb = cl.read(cl.node(r))[5]['branch']
1727 newb = cl.read(cl.node(r))[5]['branch']
1728 if newb != b:
1728 if newb != b:
1729 yield 'a', newb
1729 yield 'a', newb
1730 b = newb
1730 b = newb
1731 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1731 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1732 if p != -1)))
1732 if p != -1)))
1733 if tags:
1733 if tags:
1734 ls = labels.get(r)
1734 ls = labels.get(r)
1735 if ls:
1735 if ls:
1736 for l in ls:
1736 for l in ls:
1737 yield 'l', (r, l)
1737 yield 'l', (r, l)
1738 else:
1738 else:
1739 raise util.Abort(_('need repo for changelog dag'))
1739 raise util.Abort(_('need repo for changelog dag'))
1740
1740
1741 for line in dagparser.dagtextlines(events(),
1741 for line in dagparser.dagtextlines(events(),
1742 addspaces=spaces,
1742 addspaces=spaces,
1743 wraplabels=True,
1743 wraplabels=True,
1744 wrapannotations=True,
1744 wrapannotations=True,
1745 wrapnonlinear=dots,
1745 wrapnonlinear=dots,
1746 usedots=dots,
1746 usedots=dots,
1747 maxlinewidth=70):
1747 maxlinewidth=70):
1748 ui.write(line)
1748 ui.write(line)
1749 ui.write("\n")
1749 ui.write("\n")
1750
1750
1751 @command('debugdata',
1751 @command('debugdata',
1752 [('c', 'changelog', False, _('open changelog')),
1752 [('c', 'changelog', False, _('open changelog')),
1753 ('m', 'manifest', False, _('open manifest'))],
1753 ('m', 'manifest', False, _('open manifest'))],
1754 _('-c|-m|FILE REV'))
1754 _('-c|-m|FILE REV'))
1755 def debugdata(ui, repo, file_, rev = None, **opts):
1755 def debugdata(ui, repo, file_, rev = None, **opts):
1756 """dump the contents of a data file revision"""
1756 """dump the contents of a data file revision"""
1757 if opts.get('changelog') or opts.get('manifest'):
1757 if opts.get('changelog') or opts.get('manifest'):
1758 file_, rev = None, file_
1758 file_, rev = None, file_
1759 elif rev is None:
1759 elif rev is None:
1760 raise error.CommandError('debugdata', _('invalid arguments'))
1760 raise error.CommandError('debugdata', _('invalid arguments'))
1761 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1761 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1762 try:
1762 try:
1763 ui.write(r.revision(r.lookup(rev)))
1763 ui.write(r.revision(r.lookup(rev)))
1764 except KeyError:
1764 except KeyError:
1765 raise util.Abort(_('invalid revision identifier %s') % rev)
1765 raise util.Abort(_('invalid revision identifier %s') % rev)
1766
1766
1767 @command('debugdate',
1767 @command('debugdate',
1768 [('e', 'extended', None, _('try extended date formats'))],
1768 [('e', 'extended', None, _('try extended date formats'))],
1769 _('[-e] DATE [RANGE]'))
1769 _('[-e] DATE [RANGE]'))
1770 def debugdate(ui, date, range=None, **opts):
1770 def debugdate(ui, date, range=None, **opts):
1771 """parse and display a date"""
1771 """parse and display a date"""
1772 if opts["extended"]:
1772 if opts["extended"]:
1773 d = util.parsedate(date, util.extendeddateformats)
1773 d = util.parsedate(date, util.extendeddateformats)
1774 else:
1774 else:
1775 d = util.parsedate(date)
1775 d = util.parsedate(date)
1776 ui.write(("internal: %s %s\n") % d)
1776 ui.write(("internal: %s %s\n") % d)
1777 ui.write(("standard: %s\n") % util.datestr(d))
1777 ui.write(("standard: %s\n") % util.datestr(d))
1778 if range:
1778 if range:
1779 m = util.matchdate(range)
1779 m = util.matchdate(range)
1780 ui.write(("match: %s\n") % m(d[0]))
1780 ui.write(("match: %s\n") % m(d[0]))
1781
1781
1782 @command('debugdiscovery',
1782 @command('debugdiscovery',
1783 [('', 'old', None, _('use old-style discovery')),
1783 [('', 'old', None, _('use old-style discovery')),
1784 ('', 'nonheads', None,
1784 ('', 'nonheads', None,
1785 _('use old-style discovery with non-heads included')),
1785 _('use old-style discovery with non-heads included')),
1786 ] + remoteopts,
1786 ] + remoteopts,
1787 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1787 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1788 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1788 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1789 """runs the changeset discovery protocol in isolation"""
1789 """runs the changeset discovery protocol in isolation"""
1790 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1790 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1791 opts.get('branch'))
1791 opts.get('branch'))
1792 remote = hg.peer(repo, opts, remoteurl)
1792 remote = hg.peer(repo, opts, remoteurl)
1793 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1793 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1794
1794
1795 # make sure tests are repeatable
1795 # make sure tests are repeatable
1796 random.seed(12323)
1796 random.seed(12323)
1797
1797
1798 def doit(localheads, remoteheads, remote=remote):
1798 def doit(localheads, remoteheads, remote=remote):
1799 if opts.get('old'):
1799 if opts.get('old'):
1800 if localheads:
1800 if localheads:
1801 raise util.Abort('cannot use localheads with old style '
1801 raise util.Abort('cannot use localheads with old style '
1802 'discovery')
1802 'discovery')
1803 if not util.safehasattr(remote, 'branches'):
1803 if not util.safehasattr(remote, 'branches'):
1804 # enable in-client legacy support
1804 # enable in-client legacy support
1805 remote = localrepo.locallegacypeer(remote.local())
1805 remote = localrepo.locallegacypeer(remote.local())
1806 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1806 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1807 force=True)
1807 force=True)
1808 common = set(common)
1808 common = set(common)
1809 if not opts.get('nonheads'):
1809 if not opts.get('nonheads'):
1810 ui.write(("unpruned common: %s\n") %
1810 ui.write(("unpruned common: %s\n") %
1811 " ".join(sorted(short(n) for n in common)))
1811 " ".join(sorted(short(n) for n in common)))
1812 dag = dagutil.revlogdag(repo.changelog)
1812 dag = dagutil.revlogdag(repo.changelog)
1813 all = dag.ancestorset(dag.internalizeall(common))
1813 all = dag.ancestorset(dag.internalizeall(common))
1814 common = dag.externalizeall(dag.headsetofconnecteds(all))
1814 common = dag.externalizeall(dag.headsetofconnecteds(all))
1815 else:
1815 else:
1816 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1816 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1817 common = set(common)
1817 common = set(common)
1818 rheads = set(hds)
1818 rheads = set(hds)
1819 lheads = set(repo.heads())
1819 lheads = set(repo.heads())
1820 ui.write(("common heads: %s\n") %
1820 ui.write(("common heads: %s\n") %
1821 " ".join(sorted(short(n) for n in common)))
1821 " ".join(sorted(short(n) for n in common)))
1822 if lheads <= common:
1822 if lheads <= common:
1823 ui.write(("local is subset\n"))
1823 ui.write(("local is subset\n"))
1824 elif rheads <= common:
1824 elif rheads <= common:
1825 ui.write(("remote is subset\n"))
1825 ui.write(("remote is subset\n"))
1826
1826
1827 serverlogs = opts.get('serverlog')
1827 serverlogs = opts.get('serverlog')
1828 if serverlogs:
1828 if serverlogs:
1829 for filename in serverlogs:
1829 for filename in serverlogs:
1830 logfile = open(filename, 'r')
1830 logfile = open(filename, 'r')
1831 try:
1831 try:
1832 line = logfile.readline()
1832 line = logfile.readline()
1833 while line:
1833 while line:
1834 parts = line.strip().split(';')
1834 parts = line.strip().split(';')
1835 op = parts[1]
1835 op = parts[1]
1836 if op == 'cg':
1836 if op == 'cg':
1837 pass
1837 pass
1838 elif op == 'cgss':
1838 elif op == 'cgss':
1839 doit(parts[2].split(' '), parts[3].split(' '))
1839 doit(parts[2].split(' '), parts[3].split(' '))
1840 elif op == 'unb':
1840 elif op == 'unb':
1841 doit(parts[3].split(' '), parts[2].split(' '))
1841 doit(parts[3].split(' '), parts[2].split(' '))
1842 line = logfile.readline()
1842 line = logfile.readline()
1843 finally:
1843 finally:
1844 logfile.close()
1844 logfile.close()
1845
1845
1846 else:
1846 else:
1847 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1847 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1848 opts.get('remote_head'))
1848 opts.get('remote_head'))
1849 localrevs = opts.get('local_head')
1849 localrevs = opts.get('local_head')
1850 doit(localrevs, remoterevs)
1850 doit(localrevs, remoterevs)
1851
1851
1852 @command('debugfileset',
1852 @command('debugfileset',
1853 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1853 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1854 _('[-r REV] FILESPEC'))
1854 _('[-r REV] FILESPEC'))
1855 def debugfileset(ui, repo, expr, **opts):
1855 def debugfileset(ui, repo, expr, **opts):
1856 '''parse and apply a fileset specification'''
1856 '''parse and apply a fileset specification'''
1857 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1857 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1858 if ui.verbose:
1858 if ui.verbose:
1859 tree = fileset.parse(expr)[0]
1859 tree = fileset.parse(expr)[0]
1860 ui.note(tree, "\n")
1860 ui.note(tree, "\n")
1861
1861
1862 for f in fileset.getfileset(ctx, expr):
1862 for f in fileset.getfileset(ctx, expr):
1863 ui.write("%s\n" % f)
1863 ui.write("%s\n" % f)
1864
1864
1865 @command('debugfsinfo', [], _('[PATH]'))
1865 @command('debugfsinfo', [], _('[PATH]'))
1866 def debugfsinfo(ui, path = "."):
1866 def debugfsinfo(ui, path = "."):
1867 """show information detected about current filesystem"""
1867 """show information detected about current filesystem"""
1868 util.writefile('.debugfsinfo', '')
1868 util.writefile('.debugfsinfo', '')
1869 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1869 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1870 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1870 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1871 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1871 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1872 and 'yes' or 'no'))
1872 and 'yes' or 'no'))
1873 os.unlink('.debugfsinfo')
1873 os.unlink('.debugfsinfo')
1874
1874
1875 @command('debuggetbundle',
1875 @command('debuggetbundle',
1876 [('H', 'head', [], _('id of head node'), _('ID')),
1876 [('H', 'head', [], _('id of head node'), _('ID')),
1877 ('C', 'common', [], _('id of common node'), _('ID')),
1877 ('C', 'common', [], _('id of common node'), _('ID')),
1878 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1878 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1879 _('REPO FILE [-H|-C ID]...'))
1879 _('REPO FILE [-H|-C ID]...'))
1880 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1880 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1881 """retrieves a bundle from a repo
1881 """retrieves a bundle from a repo
1882
1882
1883 Every ID must be a full-length hex node id string. Saves the bundle to the
1883 Every ID must be a full-length hex node id string. Saves the bundle to the
1884 given file.
1884 given file.
1885 """
1885 """
1886 repo = hg.peer(ui, opts, repopath)
1886 repo = hg.peer(ui, opts, repopath)
1887 if not repo.capable('getbundle'):
1887 if not repo.capable('getbundle'):
1888 raise util.Abort("getbundle() not supported by target repository")
1888 raise util.Abort("getbundle() not supported by target repository")
1889 args = {}
1889 args = {}
1890 if common:
1890 if common:
1891 args['common'] = [bin(s) for s in common]
1891 args['common'] = [bin(s) for s in common]
1892 if head:
1892 if head:
1893 args['heads'] = [bin(s) for s in head]
1893 args['heads'] = [bin(s) for s in head]
1894 bundle = repo.getbundle('debug', **args)
1894 bundle = repo.getbundle('debug', **args)
1895
1895
1896 bundletype = opts.get('type', 'bzip2').lower()
1896 bundletype = opts.get('type', 'bzip2').lower()
1897 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1897 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1898 bundletype = btypes.get(bundletype)
1898 bundletype = btypes.get(bundletype)
1899 if bundletype not in changegroup.bundletypes:
1899 if bundletype not in changegroup.bundletypes:
1900 raise util.Abort(_('unknown bundle type specified with --type'))
1900 raise util.Abort(_('unknown bundle type specified with --type'))
1901 changegroup.writebundle(bundle, bundlepath, bundletype)
1901 changegroup.writebundle(bundle, bundlepath, bundletype)
1902
1902
1903 @command('debugignore', [], '')
1903 @command('debugignore', [], '')
1904 def debugignore(ui, repo, *values, **opts):
1904 def debugignore(ui, repo, *values, **opts):
1905 """display the combined ignore pattern"""
1905 """display the combined ignore pattern"""
1906 ignore = repo.dirstate._ignore
1906 ignore = repo.dirstate._ignore
1907 includepat = getattr(ignore, 'includepat', None)
1907 includepat = getattr(ignore, 'includepat', None)
1908 if includepat is not None:
1908 if includepat is not None:
1909 ui.write("%s\n" % includepat)
1909 ui.write("%s\n" % includepat)
1910 else:
1910 else:
1911 raise util.Abort(_("no ignore patterns found"))
1911 raise util.Abort(_("no ignore patterns found"))
1912
1912
1913 @command('debugindex',
1913 @command('debugindex',
1914 [('c', 'changelog', False, _('open changelog')),
1914 [('c', 'changelog', False, _('open changelog')),
1915 ('m', 'manifest', False, _('open manifest')),
1915 ('m', 'manifest', False, _('open manifest')),
1916 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1916 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1917 _('[-f FORMAT] -c|-m|FILE'))
1917 _('[-f FORMAT] -c|-m|FILE'))
1918 def debugindex(ui, repo, file_ = None, **opts):
1918 def debugindex(ui, repo, file_ = None, **opts):
1919 """dump the contents of an index file"""
1919 """dump the contents of an index file"""
1920 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1920 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1921 format = opts.get('format', 0)
1921 format = opts.get('format', 0)
1922 if format not in (0, 1):
1922 if format not in (0, 1):
1923 raise util.Abort(_("unknown format %d") % format)
1923 raise util.Abort(_("unknown format %d") % format)
1924
1924
1925 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1925 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1926 if generaldelta:
1926 if generaldelta:
1927 basehdr = ' delta'
1927 basehdr = ' delta'
1928 else:
1928 else:
1929 basehdr = ' base'
1929 basehdr = ' base'
1930
1930
1931 if format == 0:
1931 if format == 0:
1932 ui.write(" rev offset length " + basehdr + " linkrev"
1932 ui.write(" rev offset length " + basehdr + " linkrev"
1933 " nodeid p1 p2\n")
1933 " nodeid p1 p2\n")
1934 elif format == 1:
1934 elif format == 1:
1935 ui.write(" rev flag offset length"
1935 ui.write(" rev flag offset length"
1936 " size " + basehdr + " link p1 p2"
1936 " size " + basehdr + " link p1 p2"
1937 " nodeid\n")
1937 " nodeid\n")
1938
1938
1939 for i in r:
1939 for i in r:
1940 node = r.node(i)
1940 node = r.node(i)
1941 if generaldelta:
1941 if generaldelta:
1942 base = r.deltaparent(i)
1942 base = r.deltaparent(i)
1943 else:
1943 else:
1944 base = r.chainbase(i)
1944 base = r.chainbase(i)
1945 if format == 0:
1945 if format == 0:
1946 try:
1946 try:
1947 pp = r.parents(node)
1947 pp = r.parents(node)
1948 except Exception:
1948 except Exception:
1949 pp = [nullid, nullid]
1949 pp = [nullid, nullid]
1950 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1950 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1951 i, r.start(i), r.length(i), base, r.linkrev(i),
1951 i, r.start(i), r.length(i), base, r.linkrev(i),
1952 short(node), short(pp[0]), short(pp[1])))
1952 short(node), short(pp[0]), short(pp[1])))
1953 elif format == 1:
1953 elif format == 1:
1954 pr = r.parentrevs(i)
1954 pr = r.parentrevs(i)
1955 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1955 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1956 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1956 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1957 base, r.linkrev(i), pr[0], pr[1], short(node)))
1957 base, r.linkrev(i), pr[0], pr[1], short(node)))
1958
1958
1959 @command('debugindexdot', [], _('FILE'))
1959 @command('debugindexdot', [], _('FILE'))
1960 def debugindexdot(ui, repo, file_):
1960 def debugindexdot(ui, repo, file_):
1961 """dump an index DAG as a graphviz dot file"""
1961 """dump an index DAG as a graphviz dot file"""
1962 r = None
1962 r = None
1963 if repo:
1963 if repo:
1964 filelog = repo.file(file_)
1964 filelog = repo.file(file_)
1965 if len(filelog):
1965 if len(filelog):
1966 r = filelog
1966 r = filelog
1967 if not r:
1967 if not r:
1968 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1968 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1969 ui.write(("digraph G {\n"))
1969 ui.write(("digraph G {\n"))
1970 for i in r:
1970 for i in r:
1971 node = r.node(i)
1971 node = r.node(i)
1972 pp = r.parents(node)
1972 pp = r.parents(node)
1973 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1973 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1974 if pp[1] != nullid:
1974 if pp[1] != nullid:
1975 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1975 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1976 ui.write("}\n")
1976 ui.write("}\n")
1977
1977
1978 @command('debuginstall', [], '')
1978 @command('debuginstall', [], '')
1979 def debuginstall(ui):
1979 def debuginstall(ui):
1980 '''test Mercurial installation
1980 '''test Mercurial installation
1981
1981
1982 Returns 0 on success.
1982 Returns 0 on success.
1983 '''
1983 '''
1984
1984
1985 def writetemp(contents):
1985 def writetemp(contents):
1986 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1986 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1987 f = os.fdopen(fd, "wb")
1987 f = os.fdopen(fd, "wb")
1988 f.write(contents)
1988 f.write(contents)
1989 f.close()
1989 f.close()
1990 return name
1990 return name
1991
1991
1992 problems = 0
1992 problems = 0
1993
1993
1994 # encoding
1994 # encoding
1995 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1995 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1996 try:
1996 try:
1997 encoding.fromlocal("test")
1997 encoding.fromlocal("test")
1998 except util.Abort, inst:
1998 except util.Abort, inst:
1999 ui.write(" %s\n" % inst)
1999 ui.write(" %s\n" % inst)
2000 ui.write(_(" (check that your locale is properly set)\n"))
2000 ui.write(_(" (check that your locale is properly set)\n"))
2001 problems += 1
2001 problems += 1
2002
2002
2003 # Python lib
2003 # Python lib
2004 ui.status(_("checking Python lib (%s)...\n")
2004 ui.status(_("checking Python lib (%s)...\n")
2005 % os.path.dirname(os.__file__))
2005 % os.path.dirname(os.__file__))
2006
2006
2007 # compiled modules
2007 # compiled modules
2008 ui.status(_("checking installed modules (%s)...\n")
2008 ui.status(_("checking installed modules (%s)...\n")
2009 % os.path.dirname(__file__))
2009 % os.path.dirname(__file__))
2010 try:
2010 try:
2011 import bdiff, mpatch, base85, osutil
2011 import bdiff, mpatch, base85, osutil
2012 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2012 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2013 except Exception, inst:
2013 except Exception, inst:
2014 ui.write(" %s\n" % inst)
2014 ui.write(" %s\n" % inst)
2015 ui.write(_(" One or more extensions could not be found"))
2015 ui.write(_(" One or more extensions could not be found"))
2016 ui.write(_(" (check that you compiled the extensions)\n"))
2016 ui.write(_(" (check that you compiled the extensions)\n"))
2017 problems += 1
2017 problems += 1
2018
2018
2019 # templates
2019 # templates
2020 import templater
2020 import templater
2021 p = templater.templatepath()
2021 p = templater.templatepath()
2022 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2022 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2023 try:
2023 try:
2024 templater.templater(templater.templatepath("map-cmdline.default"))
2024 templater.templater(templater.templatepath("map-cmdline.default"))
2025 except Exception, inst:
2025 except Exception, inst:
2026 ui.write(" %s\n" % inst)
2026 ui.write(" %s\n" % inst)
2027 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2027 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2028 problems += 1
2028 problems += 1
2029
2029
2030 # editor
2030 # editor
2031 ui.status(_("checking commit editor...\n"))
2031 ui.status(_("checking commit editor...\n"))
2032 editor = ui.geteditor()
2032 editor = ui.geteditor()
2033 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2033 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2034 if not cmdpath:
2034 if not cmdpath:
2035 if editor == 'vi':
2035 if editor == 'vi':
2036 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2036 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2037 ui.write(_(" (specify a commit editor in your configuration"
2037 ui.write(_(" (specify a commit editor in your configuration"
2038 " file)\n"))
2038 " file)\n"))
2039 else:
2039 else:
2040 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2040 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2041 ui.write(_(" (specify a commit editor in your configuration"
2041 ui.write(_(" (specify a commit editor in your configuration"
2042 " file)\n"))
2042 " file)\n"))
2043 problems += 1
2043 problems += 1
2044
2044
2045 # check username
2045 # check username
2046 ui.status(_("checking username...\n"))
2046 ui.status(_("checking username...\n"))
2047 try:
2047 try:
2048 ui.username()
2048 ui.username()
2049 except util.Abort, e:
2049 except util.Abort, e:
2050 ui.write(" %s\n" % e)
2050 ui.write(" %s\n" % e)
2051 ui.write(_(" (specify a username in your configuration file)\n"))
2051 ui.write(_(" (specify a username in your configuration file)\n"))
2052 problems += 1
2052 problems += 1
2053
2053
2054 if not problems:
2054 if not problems:
2055 ui.status(_("no problems detected\n"))
2055 ui.status(_("no problems detected\n"))
2056 else:
2056 else:
2057 ui.write(_("%s problems detected,"
2057 ui.write(_("%s problems detected,"
2058 " please check your install!\n") % problems)
2058 " please check your install!\n") % problems)
2059
2059
2060 return problems
2060 return problems
2061
2061
2062 @command('debugknown', [], _('REPO ID...'))
2062 @command('debugknown', [], _('REPO ID...'))
2063 def debugknown(ui, repopath, *ids, **opts):
2063 def debugknown(ui, repopath, *ids, **opts):
2064 """test whether node ids are known to a repo
2064 """test whether node ids are known to a repo
2065
2065
2066 Every ID must be a full-length hex node id string. Returns a list of 0s
2066 Every ID must be a full-length hex node id string. Returns a list of 0s
2067 and 1s indicating unknown/known.
2067 and 1s indicating unknown/known.
2068 """
2068 """
2069 repo = hg.peer(ui, opts, repopath)
2069 repo = hg.peer(ui, opts, repopath)
2070 if not repo.capable('known'):
2070 if not repo.capable('known'):
2071 raise util.Abort("known() not supported by target repository")
2071 raise util.Abort("known() not supported by target repository")
2072 flags = repo.known([bin(s) for s in ids])
2072 flags = repo.known([bin(s) for s in ids])
2073 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2073 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2074
2074
2075 @command('debuglabelcomplete', [], _('LABEL...'))
2075 @command('debuglabelcomplete', [], _('LABEL...'))
2076 def debuglabelcomplete(ui, repo, *args):
2076 def debuglabelcomplete(ui, repo, *args):
2077 '''complete "labels" - tags, open branch names, bookmark names'''
2077 '''complete "labels" - tags, open branch names, bookmark names'''
2078
2078
2079 labels = set()
2079 labels = set()
2080 labels.update(t[0] for t in repo.tagslist())
2080 labels.update(t[0] for t in repo.tagslist())
2081 labels.update(repo[n].branch() for n in repo.heads())
2081 labels.update(repo[n].branch() for n in repo.heads())
2082 labels.update(repo._bookmarks.keys())
2082 labels.update(repo._bookmarks.keys())
2083 completions = set()
2083 completions = set()
2084 if not args:
2084 if not args:
2085 args = ['']
2085 args = ['']
2086 for a in args:
2086 for a in args:
2087 completions.update(l for l in labels if l.startswith(a))
2087 completions.update(l for l in labels if l.startswith(a))
2088 ui.write('\n'.join(sorted(completions)))
2088 ui.write('\n'.join(sorted(completions)))
2089 ui.write('\n')
2089 ui.write('\n')
2090
2090
2091 @command('debugobsolete',
2091 @command('debugobsolete',
2092 [('', 'flags', 0, _('markers flag')),
2092 [('', 'flags', 0, _('markers flag')),
2093 ] + commitopts2,
2093 ] + commitopts2,
2094 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2094 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2095 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2095 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2096 """create arbitrary obsolete marker
2096 """create arbitrary obsolete marker
2097
2097
2098 With no arguments it it display the list obsolescence marker."""
2098 With no arguments it it display the list obsolescence marker."""
2099 def parsenodeid(s):
2099 def parsenodeid(s):
2100 try:
2100 try:
2101 # We do not use revsingle/revrange functions here to accept
2101 # We do not use revsingle/revrange functions here to accept
2102 # arbitrary node identifiers, possibly not present in the
2102 # arbitrary node identifiers, possibly not present in the
2103 # local repository.
2103 # local repository.
2104 n = bin(s)
2104 n = bin(s)
2105 if len(n) != len(nullid):
2105 if len(n) != len(nullid):
2106 raise TypeError()
2106 raise TypeError()
2107 return n
2107 return n
2108 except TypeError:
2108 except TypeError:
2109 raise util.Abort('changeset references must be full hexadecimal '
2109 raise util.Abort('changeset references must be full hexadecimal '
2110 'node identifiers')
2110 'node identifiers')
2111
2111
2112 if precursor is not None:
2112 if precursor is not None:
2113 metadata = {}
2113 metadata = {}
2114 if 'date' in opts:
2114 if 'date' in opts:
2115 metadata['date'] = opts['date']
2115 metadata['date'] = opts['date']
2116 metadata['user'] = opts['user'] or ui.username()
2116 metadata['user'] = opts['user'] or ui.username()
2117 succs = tuple(parsenodeid(succ) for succ in successors)
2117 succs = tuple(parsenodeid(succ) for succ in successors)
2118 l = repo.lock()
2118 l = repo.lock()
2119 try:
2119 try:
2120 tr = repo.transaction('debugobsolete')
2120 tr = repo.transaction('debugobsolete')
2121 try:
2121 try:
2122 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2122 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2123 opts['flags'], metadata)
2123 opts['flags'], metadata)
2124 tr.close()
2124 tr.close()
2125 finally:
2125 finally:
2126 tr.release()
2126 tr.release()
2127 finally:
2127 finally:
2128 l.release()
2128 l.release()
2129 else:
2129 else:
2130 for m in obsolete.allmarkers(repo):
2130 for m in obsolete.allmarkers(repo):
2131 ui.write(hex(m.precnode()))
2131 ui.write(hex(m.precnode()))
2132 for repl in m.succnodes():
2132 for repl in m.succnodes():
2133 ui.write(' ')
2133 ui.write(' ')
2134 ui.write(hex(repl))
2134 ui.write(hex(repl))
2135 ui.write(' %X ' % m._data[2])
2135 ui.write(' %X ' % m._data[2])
2136 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2136 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2137 sorted(m.metadata().items()))))
2137 sorted(m.metadata().items()))))
2138 ui.write('\n')
2138 ui.write('\n')
2139
2139
2140 @command('debugpathcomplete',
2140 @command('debugpathcomplete',
2141 [('f', 'full', None, _('complete an entire path')),
2141 [('f', 'full', None, _('complete an entire path')),
2142 ('n', 'normal', None, _('show only normal files')),
2142 ('n', 'normal', None, _('show only normal files')),
2143 ('a', 'added', None, _('show only added files')),
2143 ('a', 'added', None, _('show only added files')),
2144 ('r', 'removed', None, _('show only removed files'))],
2144 ('r', 'removed', None, _('show only removed files'))],
2145 _('FILESPEC...'))
2145 _('FILESPEC...'))
2146 def debugpathcomplete(ui, repo, *specs, **opts):
2146 def debugpathcomplete(ui, repo, *specs, **opts):
2147 '''complete part or all of a tracked path
2147 '''complete part or all of a tracked path
2148
2148
2149 This command supports shells that offer path name completion. It
2149 This command supports shells that offer path name completion. It
2150 currently completes only files already known to the dirstate.
2150 currently completes only files already known to the dirstate.
2151
2151
2152 Completion extends only to the next path segment unless
2152 Completion extends only to the next path segment unless
2153 --full is specified, in which case entire paths are used.'''
2153 --full is specified, in which case entire paths are used.'''
2154
2154
2155 def complete(path, acceptable):
2155 def complete(path, acceptable):
2156 dirstate = repo.dirstate
2156 dirstate = repo.dirstate
2157 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2157 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2158 rootdir = repo.root + os.sep
2158 rootdir = repo.root + os.sep
2159 if spec != repo.root and not spec.startswith(rootdir):
2159 if spec != repo.root and not spec.startswith(rootdir):
2160 return [], []
2160 return [], []
2161 if os.path.isdir(spec):
2161 if os.path.isdir(spec):
2162 spec += '/'
2162 spec += '/'
2163 spec = spec[len(rootdir):]
2163 spec = spec[len(rootdir):]
2164 fixpaths = os.sep != '/'
2164 fixpaths = os.sep != '/'
2165 if fixpaths:
2165 if fixpaths:
2166 spec = spec.replace(os.sep, '/')
2166 spec = spec.replace(os.sep, '/')
2167 speclen = len(spec)
2167 speclen = len(spec)
2168 fullpaths = opts['full']
2168 fullpaths = opts['full']
2169 files, dirs = set(), set()
2169 files, dirs = set(), set()
2170 adddir, addfile = dirs.add, files.add
2170 adddir, addfile = dirs.add, files.add
2171 for f, st in dirstate.iteritems():
2171 for f, st in dirstate.iteritems():
2172 if f.startswith(spec) and st[0] in acceptable:
2172 if f.startswith(spec) and st[0] in acceptable:
2173 if fixpaths:
2173 if fixpaths:
2174 f = f.replace('/', os.sep)
2174 f = f.replace('/', os.sep)
2175 if fullpaths:
2175 if fullpaths:
2176 addfile(f)
2176 addfile(f)
2177 continue
2177 continue
2178 s = f.find(os.sep, speclen)
2178 s = f.find(os.sep, speclen)
2179 if s >= 0:
2179 if s >= 0:
2180 adddir(f[:s + 1])
2180 adddir(f[:s + 1])
2181 else:
2181 else:
2182 addfile(f)
2182 addfile(f)
2183 return files, dirs
2183 return files, dirs
2184
2184
2185 acceptable = ''
2185 acceptable = ''
2186 if opts['normal']:
2186 if opts['normal']:
2187 acceptable += 'nm'
2187 acceptable += 'nm'
2188 if opts['added']:
2188 if opts['added']:
2189 acceptable += 'a'
2189 acceptable += 'a'
2190 if opts['removed']:
2190 if opts['removed']:
2191 acceptable += 'r'
2191 acceptable += 'r'
2192 cwd = repo.getcwd()
2192 cwd = repo.getcwd()
2193 if not specs:
2193 if not specs:
2194 specs = ['.']
2194 specs = ['.']
2195
2195
2196 files, dirs = set(), set()
2196 files, dirs = set(), set()
2197 for spec in specs:
2197 for spec in specs:
2198 f, d = complete(spec, acceptable or 'nmar')
2198 f, d = complete(spec, acceptable or 'nmar')
2199 files.update(f)
2199 files.update(f)
2200 dirs.update(d)
2200 dirs.update(d)
2201 if not files and len(dirs) == 1:
2201 if not files and len(dirs) == 1:
2202 # force the shell to consider a completion that matches one
2202 # force the shell to consider a completion that matches one
2203 # directory and zero files to be ambiguous
2203 # directory and zero files to be ambiguous
2204 dirs.add(iter(dirs).next() + '.')
2204 dirs.add(iter(dirs).next() + '.')
2205 files.update(dirs)
2205 files.update(dirs)
2206 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2206 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2207 ui.write('\n')
2207 ui.write('\n')
2208
2208
2209 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2209 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2210 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2210 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2211 '''access the pushkey key/value protocol
2211 '''access the pushkey key/value protocol
2212
2212
2213 With two args, list the keys in the given namespace.
2213 With two args, list the keys in the given namespace.
2214
2214
2215 With five args, set a key to new if it currently is set to old.
2215 With five args, set a key to new if it currently is set to old.
2216 Reports success or failure.
2216 Reports success or failure.
2217 '''
2217 '''
2218
2218
2219 target = hg.peer(ui, {}, repopath)
2219 target = hg.peer(ui, {}, repopath)
2220 if keyinfo:
2220 if keyinfo:
2221 key, old, new = keyinfo
2221 key, old, new = keyinfo
2222 r = target.pushkey(namespace, key, old, new)
2222 r = target.pushkey(namespace, key, old, new)
2223 ui.status(str(r) + '\n')
2223 ui.status(str(r) + '\n')
2224 return not r
2224 return not r
2225 else:
2225 else:
2226 for k, v in sorted(target.listkeys(namespace).iteritems()):
2226 for k, v in sorted(target.listkeys(namespace).iteritems()):
2227 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2227 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2228 v.encode('string-escape')))
2228 v.encode('string-escape')))
2229
2229
2230 @command('debugpvec', [], _('A B'))
2230 @command('debugpvec', [], _('A B'))
2231 def debugpvec(ui, repo, a, b=None):
2231 def debugpvec(ui, repo, a, b=None):
2232 ca = scmutil.revsingle(repo, a)
2232 ca = scmutil.revsingle(repo, a)
2233 cb = scmutil.revsingle(repo, b)
2233 cb = scmutil.revsingle(repo, b)
2234 pa = pvec.ctxpvec(ca)
2234 pa = pvec.ctxpvec(ca)
2235 pb = pvec.ctxpvec(cb)
2235 pb = pvec.ctxpvec(cb)
2236 if pa == pb:
2236 if pa == pb:
2237 rel = "="
2237 rel = "="
2238 elif pa > pb:
2238 elif pa > pb:
2239 rel = ">"
2239 rel = ">"
2240 elif pa < pb:
2240 elif pa < pb:
2241 rel = "<"
2241 rel = "<"
2242 elif pa | pb:
2242 elif pa | pb:
2243 rel = "|"
2243 rel = "|"
2244 ui.write(_("a: %s\n") % pa)
2244 ui.write(_("a: %s\n") % pa)
2245 ui.write(_("b: %s\n") % pb)
2245 ui.write(_("b: %s\n") % pb)
2246 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2246 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2247 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2247 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2248 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2248 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2249 pa.distance(pb), rel))
2249 pa.distance(pb), rel))
2250
2250
2251 @command('debugrebuildstate',
2251 @command('debugrebuildstate',
2252 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2252 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2253 _('[-r REV] [REV]'))
2253 _('[-r REV] [REV]'))
2254 def debugrebuildstate(ui, repo, rev="tip"):
2254 def debugrebuildstate(ui, repo, rev="tip"):
2255 """rebuild the dirstate as it would look like for the given revision"""
2255 """rebuild the dirstate as it would look like for the given revision"""
2256 ctx = scmutil.revsingle(repo, rev)
2256 ctx = scmutil.revsingle(repo, rev)
2257 wlock = repo.wlock()
2257 wlock = repo.wlock()
2258 try:
2258 try:
2259 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2259 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2260 finally:
2260 finally:
2261 wlock.release()
2261 wlock.release()
2262
2262
2263 @command('debugrename',
2263 @command('debugrename',
2264 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2264 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2265 _('[-r REV] FILE'))
2265 _('[-r REV] FILE'))
2266 def debugrename(ui, repo, file1, *pats, **opts):
2266 def debugrename(ui, repo, file1, *pats, **opts):
2267 """dump rename information"""
2267 """dump rename information"""
2268
2268
2269 ctx = scmutil.revsingle(repo, opts.get('rev'))
2269 ctx = scmutil.revsingle(repo, opts.get('rev'))
2270 m = scmutil.match(ctx, (file1,) + pats, opts)
2270 m = scmutil.match(ctx, (file1,) + pats, opts)
2271 for abs in ctx.walk(m):
2271 for abs in ctx.walk(m):
2272 fctx = ctx[abs]
2272 fctx = ctx[abs]
2273 o = fctx.filelog().renamed(fctx.filenode())
2273 o = fctx.filelog().renamed(fctx.filenode())
2274 rel = m.rel(abs)
2274 rel = m.rel(abs)
2275 if o:
2275 if o:
2276 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2276 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2277 else:
2277 else:
2278 ui.write(_("%s not renamed\n") % rel)
2278 ui.write(_("%s not renamed\n") % rel)
2279
2279
2280 @command('debugrevlog',
2280 @command('debugrevlog',
2281 [('c', 'changelog', False, _('open changelog')),
2281 [('c', 'changelog', False, _('open changelog')),
2282 ('m', 'manifest', False, _('open manifest')),
2282 ('m', 'manifest', False, _('open manifest')),
2283 ('d', 'dump', False, _('dump index data'))],
2283 ('d', 'dump', False, _('dump index data'))],
2284 _('-c|-m|FILE'))
2284 _('-c|-m|FILE'))
2285 def debugrevlog(ui, repo, file_ = None, **opts):
2285 def debugrevlog(ui, repo, file_ = None, **opts):
2286 """show data and statistics about a revlog"""
2286 """show data and statistics about a revlog"""
2287 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2287 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2288
2288
2289 if opts.get("dump"):
2289 if opts.get("dump"):
2290 numrevs = len(r)
2290 numrevs = len(r)
2291 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2291 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2292 " rawsize totalsize compression heads\n")
2292 " rawsize totalsize compression heads\n")
2293 ts = 0
2293 ts = 0
2294 heads = set()
2294 heads = set()
2295 for rev in xrange(numrevs):
2295 for rev in xrange(numrevs):
2296 dbase = r.deltaparent(rev)
2296 dbase = r.deltaparent(rev)
2297 if dbase == -1:
2297 if dbase == -1:
2298 dbase = rev
2298 dbase = rev
2299 cbase = r.chainbase(rev)
2299 cbase = r.chainbase(rev)
2300 p1, p2 = r.parentrevs(rev)
2300 p1, p2 = r.parentrevs(rev)
2301 rs = r.rawsize(rev)
2301 rs = r.rawsize(rev)
2302 ts = ts + rs
2302 ts = ts + rs
2303 heads -= set(r.parentrevs(rev))
2303 heads -= set(r.parentrevs(rev))
2304 heads.add(rev)
2304 heads.add(rev)
2305 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2305 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2306 (rev, p1, p2, r.start(rev), r.end(rev),
2306 (rev, p1, p2, r.start(rev), r.end(rev),
2307 r.start(dbase), r.start(cbase),
2307 r.start(dbase), r.start(cbase),
2308 r.start(p1), r.start(p2),
2308 r.start(p1), r.start(p2),
2309 rs, ts, ts / r.end(rev), len(heads)))
2309 rs, ts, ts / r.end(rev), len(heads)))
2310 return 0
2310 return 0
2311
2311
2312 v = r.version
2312 v = r.version
2313 format = v & 0xFFFF
2313 format = v & 0xFFFF
2314 flags = []
2314 flags = []
2315 gdelta = False
2315 gdelta = False
2316 if v & revlog.REVLOGNGINLINEDATA:
2316 if v & revlog.REVLOGNGINLINEDATA:
2317 flags.append('inline')
2317 flags.append('inline')
2318 if v & revlog.REVLOGGENERALDELTA:
2318 if v & revlog.REVLOGGENERALDELTA:
2319 gdelta = True
2319 gdelta = True
2320 flags.append('generaldelta')
2320 flags.append('generaldelta')
2321 if not flags:
2321 if not flags:
2322 flags = ['(none)']
2322 flags = ['(none)']
2323
2323
2324 nummerges = 0
2324 nummerges = 0
2325 numfull = 0
2325 numfull = 0
2326 numprev = 0
2326 numprev = 0
2327 nump1 = 0
2327 nump1 = 0
2328 nump2 = 0
2328 nump2 = 0
2329 numother = 0
2329 numother = 0
2330 nump1prev = 0
2330 nump1prev = 0
2331 nump2prev = 0
2331 nump2prev = 0
2332 chainlengths = []
2332 chainlengths = []
2333
2333
2334 datasize = [None, 0, 0L]
2334 datasize = [None, 0, 0L]
2335 fullsize = [None, 0, 0L]
2335 fullsize = [None, 0, 0L]
2336 deltasize = [None, 0, 0L]
2336 deltasize = [None, 0, 0L]
2337
2337
2338 def addsize(size, l):
2338 def addsize(size, l):
2339 if l[0] is None or size < l[0]:
2339 if l[0] is None or size < l[0]:
2340 l[0] = size
2340 l[0] = size
2341 if size > l[1]:
2341 if size > l[1]:
2342 l[1] = size
2342 l[1] = size
2343 l[2] += size
2343 l[2] += size
2344
2344
2345 numrevs = len(r)
2345 numrevs = len(r)
2346 for rev in xrange(numrevs):
2346 for rev in xrange(numrevs):
2347 p1, p2 = r.parentrevs(rev)
2347 p1, p2 = r.parentrevs(rev)
2348 delta = r.deltaparent(rev)
2348 delta = r.deltaparent(rev)
2349 if format > 0:
2349 if format > 0:
2350 addsize(r.rawsize(rev), datasize)
2350 addsize(r.rawsize(rev), datasize)
2351 if p2 != nullrev:
2351 if p2 != nullrev:
2352 nummerges += 1
2352 nummerges += 1
2353 size = r.length(rev)
2353 size = r.length(rev)
2354 if delta == nullrev:
2354 if delta == nullrev:
2355 chainlengths.append(0)
2355 chainlengths.append(0)
2356 numfull += 1
2356 numfull += 1
2357 addsize(size, fullsize)
2357 addsize(size, fullsize)
2358 else:
2358 else:
2359 chainlengths.append(chainlengths[delta] + 1)
2359 chainlengths.append(chainlengths[delta] + 1)
2360 addsize(size, deltasize)
2360 addsize(size, deltasize)
2361 if delta == rev - 1:
2361 if delta == rev - 1:
2362 numprev += 1
2362 numprev += 1
2363 if delta == p1:
2363 if delta == p1:
2364 nump1prev += 1
2364 nump1prev += 1
2365 elif delta == p2:
2365 elif delta == p2:
2366 nump2prev += 1
2366 nump2prev += 1
2367 elif delta == p1:
2367 elif delta == p1:
2368 nump1 += 1
2368 nump1 += 1
2369 elif delta == p2:
2369 elif delta == p2:
2370 nump2 += 1
2370 nump2 += 1
2371 elif delta != nullrev:
2371 elif delta != nullrev:
2372 numother += 1
2372 numother += 1
2373
2373
2374 # Adjust size min value for empty cases
2374 # Adjust size min value for empty cases
2375 for size in (datasize, fullsize, deltasize):
2375 for size in (datasize, fullsize, deltasize):
2376 if size[0] is None:
2376 if size[0] is None:
2377 size[0] = 0
2377 size[0] = 0
2378
2378
2379 numdeltas = numrevs - numfull
2379 numdeltas = numrevs - numfull
2380 numoprev = numprev - nump1prev - nump2prev
2380 numoprev = numprev - nump1prev - nump2prev
2381 totalrawsize = datasize[2]
2381 totalrawsize = datasize[2]
2382 datasize[2] /= numrevs
2382 datasize[2] /= numrevs
2383 fulltotal = fullsize[2]
2383 fulltotal = fullsize[2]
2384 fullsize[2] /= numfull
2384 fullsize[2] /= numfull
2385 deltatotal = deltasize[2]
2385 deltatotal = deltasize[2]
2386 if numrevs - numfull > 0:
2386 if numrevs - numfull > 0:
2387 deltasize[2] /= numrevs - numfull
2387 deltasize[2] /= numrevs - numfull
2388 totalsize = fulltotal + deltatotal
2388 totalsize = fulltotal + deltatotal
2389 avgchainlen = sum(chainlengths) / numrevs
2389 avgchainlen = sum(chainlengths) / numrevs
2390 compratio = totalrawsize / totalsize
2390 compratio = totalrawsize / totalsize
2391
2391
2392 basedfmtstr = '%%%dd\n'
2392 basedfmtstr = '%%%dd\n'
2393 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2393 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2394
2394
2395 def dfmtstr(max):
2395 def dfmtstr(max):
2396 return basedfmtstr % len(str(max))
2396 return basedfmtstr % len(str(max))
2397 def pcfmtstr(max, padding=0):
2397 def pcfmtstr(max, padding=0):
2398 return basepcfmtstr % (len(str(max)), ' ' * padding)
2398 return basepcfmtstr % (len(str(max)), ' ' * padding)
2399
2399
2400 def pcfmt(value, total):
2400 def pcfmt(value, total):
2401 return (value, 100 * float(value) / total)
2401 return (value, 100 * float(value) / total)
2402
2402
2403 ui.write(('format : %d\n') % format)
2403 ui.write(('format : %d\n') % format)
2404 ui.write(('flags : %s\n') % ', '.join(flags))
2404 ui.write(('flags : %s\n') % ', '.join(flags))
2405
2405
2406 ui.write('\n')
2406 ui.write('\n')
2407 fmt = pcfmtstr(totalsize)
2407 fmt = pcfmtstr(totalsize)
2408 fmt2 = dfmtstr(totalsize)
2408 fmt2 = dfmtstr(totalsize)
2409 ui.write(('revisions : ') + fmt2 % numrevs)
2409 ui.write(('revisions : ') + fmt2 % numrevs)
2410 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2410 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2411 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2411 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2412 ui.write(('revisions : ') + fmt2 % numrevs)
2412 ui.write(('revisions : ') + fmt2 % numrevs)
2413 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2413 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2414 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2414 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2415 ui.write(('revision size : ') + fmt2 % totalsize)
2415 ui.write(('revision size : ') + fmt2 % totalsize)
2416 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2416 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2417 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2417 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2418
2418
2419 ui.write('\n')
2419 ui.write('\n')
2420 fmt = dfmtstr(max(avgchainlen, compratio))
2420 fmt = dfmtstr(max(avgchainlen, compratio))
2421 ui.write(('avg chain length : ') + fmt % avgchainlen)
2421 ui.write(('avg chain length : ') + fmt % avgchainlen)
2422 ui.write(('compression ratio : ') + fmt % compratio)
2422 ui.write(('compression ratio : ') + fmt % compratio)
2423
2423
2424 if format > 0:
2424 if format > 0:
2425 ui.write('\n')
2425 ui.write('\n')
2426 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2426 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2427 % tuple(datasize))
2427 % tuple(datasize))
2428 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2428 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2429 % tuple(fullsize))
2429 % tuple(fullsize))
2430 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2430 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2431 % tuple(deltasize))
2431 % tuple(deltasize))
2432
2432
2433 if numdeltas > 0:
2433 if numdeltas > 0:
2434 ui.write('\n')
2434 ui.write('\n')
2435 fmt = pcfmtstr(numdeltas)
2435 fmt = pcfmtstr(numdeltas)
2436 fmt2 = pcfmtstr(numdeltas, 4)
2436 fmt2 = pcfmtstr(numdeltas, 4)
2437 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2437 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2438 if numprev > 0:
2438 if numprev > 0:
2439 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2439 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2440 numprev))
2440 numprev))
2441 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2441 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2442 numprev))
2442 numprev))
2443 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2443 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2444 numprev))
2444 numprev))
2445 if gdelta:
2445 if gdelta:
2446 ui.write(('deltas against p1 : ')
2446 ui.write(('deltas against p1 : ')
2447 + fmt % pcfmt(nump1, numdeltas))
2447 + fmt % pcfmt(nump1, numdeltas))
2448 ui.write(('deltas against p2 : ')
2448 ui.write(('deltas against p2 : ')
2449 + fmt % pcfmt(nump2, numdeltas))
2449 + fmt % pcfmt(nump2, numdeltas))
2450 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2450 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2451 numdeltas))
2451 numdeltas))
2452
2452
2453 @command('debugrevspec', [], ('REVSPEC'))
2453 @command('debugrevspec', [], ('REVSPEC'))
2454 def debugrevspec(ui, repo, expr):
2454 def debugrevspec(ui, repo, expr):
2455 """parse and apply a revision specification
2455 """parse and apply a revision specification
2456
2456
2457 Use --verbose to print the parsed tree before and after aliases
2457 Use --verbose to print the parsed tree before and after aliases
2458 expansion.
2458 expansion.
2459 """
2459 """
2460 if ui.verbose:
2460 if ui.verbose:
2461 tree = revset.parse(expr)[0]
2461 tree = revset.parse(expr)[0]
2462 ui.note(revset.prettyformat(tree), "\n")
2462 ui.note(revset.prettyformat(tree), "\n")
2463 newtree = revset.findaliases(ui, tree)
2463 newtree = revset.findaliases(ui, tree)
2464 if newtree != tree:
2464 if newtree != tree:
2465 ui.note(revset.prettyformat(newtree), "\n")
2465 ui.note(revset.prettyformat(newtree), "\n")
2466 func = revset.match(ui, expr)
2466 func = revset.match(ui, expr)
2467 for c in func(repo, range(len(repo))):
2467 for c in func(repo, range(len(repo))):
2468 ui.write("%s\n" % c)
2468 ui.write("%s\n" % c)
2469
2469
2470 @command('debugsetparents', [], _('REV1 [REV2]'))
2470 @command('debugsetparents', [], _('REV1 [REV2]'))
2471 def debugsetparents(ui, repo, rev1, rev2=None):
2471 def debugsetparents(ui, repo, rev1, rev2=None):
2472 """manually set the parents of the current working directory
2472 """manually set the parents of the current working directory
2473
2473
2474 This is useful for writing repository conversion tools, but should
2474 This is useful for writing repository conversion tools, but should
2475 be used with care.
2475 be used with care.
2476
2476
2477 Returns 0 on success.
2477 Returns 0 on success.
2478 """
2478 """
2479
2479
2480 r1 = scmutil.revsingle(repo, rev1).node()
2480 r1 = scmutil.revsingle(repo, rev1).node()
2481 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2481 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2482
2482
2483 wlock = repo.wlock()
2483 wlock = repo.wlock()
2484 try:
2484 try:
2485 repo.setparents(r1, r2)
2485 repo.setparents(r1, r2)
2486 finally:
2486 finally:
2487 wlock.release()
2487 wlock.release()
2488
2488
2489 @command('debugstate',
2489 @command('debugstate',
2490 [('', 'nodates', None, _('do not display the saved mtime')),
2490 [('', 'nodates', None, _('do not display the saved mtime')),
2491 ('', 'datesort', None, _('sort by saved mtime'))],
2491 ('', 'datesort', None, _('sort by saved mtime'))],
2492 _('[OPTION]...'))
2492 _('[OPTION]...'))
2493 def debugstate(ui, repo, nodates=None, datesort=None):
2493 def debugstate(ui, repo, nodates=None, datesort=None):
2494 """show the contents of the current dirstate"""
2494 """show the contents of the current dirstate"""
2495 timestr = ""
2495 timestr = ""
2496 showdate = not nodates
2496 showdate = not nodates
2497 if datesort:
2497 if datesort:
2498 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2498 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2499 else:
2499 else:
2500 keyfunc = None # sort by filename
2500 keyfunc = None # sort by filename
2501 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2501 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2502 if showdate:
2502 if showdate:
2503 if ent[3] == -1:
2503 if ent[3] == -1:
2504 # Pad or slice to locale representation
2504 # Pad or slice to locale representation
2505 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2505 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2506 time.localtime(0)))
2506 time.localtime(0)))
2507 timestr = 'unset'
2507 timestr = 'unset'
2508 timestr = (timestr[:locale_len] +
2508 timestr = (timestr[:locale_len] +
2509 ' ' * (locale_len - len(timestr)))
2509 ' ' * (locale_len - len(timestr)))
2510 else:
2510 else:
2511 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2511 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2512 time.localtime(ent[3]))
2512 time.localtime(ent[3]))
2513 if ent[1] & 020000:
2513 if ent[1] & 020000:
2514 mode = 'lnk'
2514 mode = 'lnk'
2515 else:
2515 else:
2516 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2516 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2517 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2517 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2518 for f in repo.dirstate.copies():
2518 for f in repo.dirstate.copies():
2519 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2519 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2520
2520
2521 @command('debugsub',
2521 @command('debugsub',
2522 [('r', 'rev', '',
2522 [('r', 'rev', '',
2523 _('revision to check'), _('REV'))],
2523 _('revision to check'), _('REV'))],
2524 _('[-r REV] [REV]'))
2524 _('[-r REV] [REV]'))
2525 def debugsub(ui, repo, rev=None):
2525 def debugsub(ui, repo, rev=None):
2526 ctx = scmutil.revsingle(repo, rev, None)
2526 ctx = scmutil.revsingle(repo, rev, None)
2527 for k, v in sorted(ctx.substate.items()):
2527 for k, v in sorted(ctx.substate.items()):
2528 ui.write(('path %s\n') % k)
2528 ui.write(('path %s\n') % k)
2529 ui.write((' source %s\n') % v[0])
2529 ui.write((' source %s\n') % v[0])
2530 ui.write((' revision %s\n') % v[1])
2530 ui.write((' revision %s\n') % v[1])
2531
2531
2532 @command('debugsuccessorssets',
2532 @command('debugsuccessorssets',
2533 [],
2533 [],
2534 _('[REV]'))
2534 _('[REV]'))
2535 def debugsuccessorssets(ui, repo, *revs):
2535 def debugsuccessorssets(ui, repo, *revs):
2536 """show set of successors for revision
2536 """show set of successors for revision
2537
2537
2538 A successors set of changeset A is a consistent group of revisions that
2538 A successors set of changeset A is a consistent group of revisions that
2539 succeed A. It contains non-obsolete changesets only.
2539 succeed A. It contains non-obsolete changesets only.
2540
2540
2541 In most cases a changeset A has a single successors set containing a single
2541 In most cases a changeset A has a single successors set containing a single
2542 successor (changeset A replaced by A').
2542 successor (changeset A replaced by A').
2543
2543
2544 A changeset that is made obsolete with no successors are called "pruned".
2544 A changeset that is made obsolete with no successors are called "pruned".
2545 Such changesets have no successors sets at all.
2545 Such changesets have no successors sets at all.
2546
2546
2547 A changeset that has been "split" will have a successors set containing
2547 A changeset that has been "split" will have a successors set containing
2548 more than one successor.
2548 more than one successor.
2549
2549
2550 A changeset that has been rewritten in multiple different ways is called
2550 A changeset that has been rewritten in multiple different ways is called
2551 "divergent". Such changesets have multiple successor sets (each of which
2551 "divergent". Such changesets have multiple successor sets (each of which
2552 may also be split, i.e. have multiple successors).
2552 may also be split, i.e. have multiple successors).
2553
2553
2554 Results are displayed as follows::
2554 Results are displayed as follows::
2555
2555
2556 <rev1>
2556 <rev1>
2557 <successors-1A>
2557 <successors-1A>
2558 <rev2>
2558 <rev2>
2559 <successors-2A>
2559 <successors-2A>
2560 <successors-2B1> <successors-2B2> <successors-2B3>
2560 <successors-2B1> <successors-2B2> <successors-2B3>
2561
2561
2562 Here rev2 has two possible (i.e. divergent) successors sets. The first
2562 Here rev2 has two possible (i.e. divergent) successors sets. The first
2563 holds one element, whereas the second holds three (i.e. the changeset has
2563 holds one element, whereas the second holds three (i.e. the changeset has
2564 been split).
2564 been split).
2565 """
2565 """
2566 # passed to successorssets caching computation from one call to another
2566 # passed to successorssets caching computation from one call to another
2567 cache = {}
2567 cache = {}
2568 ctx2str = str
2568 ctx2str = str
2569 node2str = short
2569 node2str = short
2570 if ui.debug():
2570 if ui.debug():
2571 def ctx2str(ctx):
2571 def ctx2str(ctx):
2572 return ctx.hex()
2572 return ctx.hex()
2573 node2str = hex
2573 node2str = hex
2574 for rev in scmutil.revrange(repo, revs):
2574 for rev in scmutil.revrange(repo, revs):
2575 ctx = repo[rev]
2575 ctx = repo[rev]
2576 ui.write('%s\n'% ctx2str(ctx))
2576 ui.write('%s\n'% ctx2str(ctx))
2577 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2577 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2578 if succsset:
2578 if succsset:
2579 ui.write(' ')
2579 ui.write(' ')
2580 ui.write(node2str(succsset[0]))
2580 ui.write(node2str(succsset[0]))
2581 for node in succsset[1:]:
2581 for node in succsset[1:]:
2582 ui.write(' ')
2582 ui.write(' ')
2583 ui.write(node2str(node))
2583 ui.write(node2str(node))
2584 ui.write('\n')
2584 ui.write('\n')
2585
2585
2586 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2586 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2587 def debugwalk(ui, repo, *pats, **opts):
2587 def debugwalk(ui, repo, *pats, **opts):
2588 """show how files match on given patterns"""
2588 """show how files match on given patterns"""
2589 m = scmutil.match(repo[None], pats, opts)
2589 m = scmutil.match(repo[None], pats, opts)
2590 items = list(repo.walk(m))
2590 items = list(repo.walk(m))
2591 if not items:
2591 if not items:
2592 return
2592 return
2593 f = lambda fn: fn
2593 f = lambda fn: fn
2594 if ui.configbool('ui', 'slash') and os.sep != '/':
2594 if ui.configbool('ui', 'slash') and os.sep != '/':
2595 f = lambda fn: util.normpath(fn)
2595 f = lambda fn: util.normpath(fn)
2596 fmt = 'f %%-%ds %%-%ds %%s' % (
2596 fmt = 'f %%-%ds %%-%ds %%s' % (
2597 max([len(abs) for abs in items]),
2597 max([len(abs) for abs in items]),
2598 max([len(m.rel(abs)) for abs in items]))
2598 max([len(m.rel(abs)) for abs in items]))
2599 for abs in items:
2599 for abs in items:
2600 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2600 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2601 ui.write("%s\n" % line.rstrip())
2601 ui.write("%s\n" % line.rstrip())
2602
2602
2603 @command('debugwireargs',
2603 @command('debugwireargs',
2604 [('', 'three', '', 'three'),
2604 [('', 'three', '', 'three'),
2605 ('', 'four', '', 'four'),
2605 ('', 'four', '', 'four'),
2606 ('', 'five', '', 'five'),
2606 ('', 'five', '', 'five'),
2607 ] + remoteopts,
2607 ] + remoteopts,
2608 _('REPO [OPTIONS]... [ONE [TWO]]'))
2608 _('REPO [OPTIONS]... [ONE [TWO]]'))
2609 def debugwireargs(ui, repopath, *vals, **opts):
2609 def debugwireargs(ui, repopath, *vals, **opts):
2610 repo = hg.peer(ui, opts, repopath)
2610 repo = hg.peer(ui, opts, repopath)
2611 for opt in remoteopts:
2611 for opt in remoteopts:
2612 del opts[opt[1]]
2612 del opts[opt[1]]
2613 args = {}
2613 args = {}
2614 for k, v in opts.iteritems():
2614 for k, v in opts.iteritems():
2615 if v:
2615 if v:
2616 args[k] = v
2616 args[k] = v
2617 # run twice to check that we don't mess up the stream for the next command
2617 # run twice to check that we don't mess up the stream for the next command
2618 res1 = repo.debugwireargs(*vals, **args)
2618 res1 = repo.debugwireargs(*vals, **args)
2619 res2 = repo.debugwireargs(*vals, **args)
2619 res2 = repo.debugwireargs(*vals, **args)
2620 ui.write("%s\n" % res1)
2620 ui.write("%s\n" % res1)
2621 if res1 != res2:
2621 if res1 != res2:
2622 ui.warn("%s\n" % res2)
2622 ui.warn("%s\n" % res2)
2623
2623
2624 @command('^diff',
2624 @command('^diff',
2625 [('r', 'rev', [], _('revision'), _('REV')),
2625 [('r', 'rev', [], _('revision'), _('REV')),
2626 ('c', 'change', '', _('change made by revision'), _('REV'))
2626 ('c', 'change', '', _('change made by revision'), _('REV'))
2627 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2627 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2628 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2628 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2629 def diff(ui, repo, *pats, **opts):
2629 def diff(ui, repo, *pats, **opts):
2630 """diff repository (or selected files)
2630 """diff repository (or selected files)
2631
2631
2632 Show differences between revisions for the specified files.
2632 Show differences between revisions for the specified files.
2633
2633
2634 Differences between files are shown using the unified diff format.
2634 Differences between files are shown using the unified diff format.
2635
2635
2636 .. note::
2636 .. note::
2637 diff may generate unexpected results for merges, as it will
2637 diff may generate unexpected results for merges, as it will
2638 default to comparing against the working directory's first
2638 default to comparing against the working directory's first
2639 parent changeset if no revisions are specified.
2639 parent changeset if no revisions are specified.
2640
2640
2641 When two revision arguments are given, then changes are shown
2641 When two revision arguments are given, then changes are shown
2642 between those revisions. If only one revision is specified then
2642 between those revisions. If only one revision is specified then
2643 that revision is compared to the working directory, and, when no
2643 that revision is compared to the working directory, and, when no
2644 revisions are specified, the working directory files are compared
2644 revisions are specified, the working directory files are compared
2645 to its parent.
2645 to its parent.
2646
2646
2647 Alternatively you can specify -c/--change with a revision to see
2647 Alternatively you can specify -c/--change with a revision to see
2648 the changes in that changeset relative to its first parent.
2648 the changes in that changeset relative to its first parent.
2649
2649
2650 Without the -a/--text option, diff will avoid generating diffs of
2650 Without the -a/--text option, diff will avoid generating diffs of
2651 files it detects as binary. With -a, diff will generate a diff
2651 files it detects as binary. With -a, diff will generate a diff
2652 anyway, probably with undesirable results.
2652 anyway, probably with undesirable results.
2653
2653
2654 Use the -g/--git option to generate diffs in the git extended diff
2654 Use the -g/--git option to generate diffs in the git extended diff
2655 format. For more information, read :hg:`help diffs`.
2655 format. For more information, read :hg:`help diffs`.
2656
2656
2657 .. container:: verbose
2657 .. container:: verbose
2658
2658
2659 Examples:
2659 Examples:
2660
2660
2661 - compare a file in the current working directory to its parent::
2661 - compare a file in the current working directory to its parent::
2662
2662
2663 hg diff foo.c
2663 hg diff foo.c
2664
2664
2665 - compare two historical versions of a directory, with rename info::
2665 - compare two historical versions of a directory, with rename info::
2666
2666
2667 hg diff --git -r 1.0:1.2 lib/
2667 hg diff --git -r 1.0:1.2 lib/
2668
2668
2669 - get change stats relative to the last change on some date::
2669 - get change stats relative to the last change on some date::
2670
2670
2671 hg diff --stat -r "date('may 2')"
2671 hg diff --stat -r "date('may 2')"
2672
2672
2673 - diff all newly-added files that contain a keyword::
2673 - diff all newly-added files that contain a keyword::
2674
2674
2675 hg diff "set:added() and grep(GNU)"
2675 hg diff "set:added() and grep(GNU)"
2676
2676
2677 - compare a revision and its parents::
2677 - compare a revision and its parents::
2678
2678
2679 hg diff -c 9353 # compare against first parent
2679 hg diff -c 9353 # compare against first parent
2680 hg diff -r 9353^:9353 # same using revset syntax
2680 hg diff -r 9353^:9353 # same using revset syntax
2681 hg diff -r 9353^2:9353 # compare against the second parent
2681 hg diff -r 9353^2:9353 # compare against the second parent
2682
2682
2683 Returns 0 on success.
2683 Returns 0 on success.
2684 """
2684 """
2685
2685
2686 revs = opts.get('rev')
2686 revs = opts.get('rev')
2687 change = opts.get('change')
2687 change = opts.get('change')
2688 stat = opts.get('stat')
2688 stat = opts.get('stat')
2689 reverse = opts.get('reverse')
2689 reverse = opts.get('reverse')
2690
2690
2691 if revs and change:
2691 if revs and change:
2692 msg = _('cannot specify --rev and --change at the same time')
2692 msg = _('cannot specify --rev and --change at the same time')
2693 raise util.Abort(msg)
2693 raise util.Abort(msg)
2694 elif change:
2694 elif change:
2695 node2 = scmutil.revsingle(repo, change, None).node()
2695 node2 = scmutil.revsingle(repo, change, None).node()
2696 node1 = repo[node2].p1().node()
2696 node1 = repo[node2].p1().node()
2697 else:
2697 else:
2698 node1, node2 = scmutil.revpair(repo, revs)
2698 node1, node2 = scmutil.revpair(repo, revs)
2699
2699
2700 if reverse:
2700 if reverse:
2701 node1, node2 = node2, node1
2701 node1, node2 = node2, node1
2702
2702
2703 diffopts = patch.diffopts(ui, opts)
2703 diffopts = patch.diffopts(ui, opts)
2704 m = scmutil.match(repo[node2], pats, opts)
2704 m = scmutil.match(repo[node2], pats, opts)
2705 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2705 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2706 listsubrepos=opts.get('subrepos'))
2706 listsubrepos=opts.get('subrepos'))
2707
2707
2708 @command('^export',
2708 @command('^export',
2709 [('o', 'output', '',
2709 [('o', 'output', '',
2710 _('print output to file with formatted name'), _('FORMAT')),
2710 _('print output to file with formatted name'), _('FORMAT')),
2711 ('', 'switch-parent', None, _('diff against the second parent')),
2711 ('', 'switch-parent', None, _('diff against the second parent')),
2712 ('r', 'rev', [], _('revisions to export'), _('REV')),
2712 ('r', 'rev', [], _('revisions to export'), _('REV')),
2713 ] + diffopts,
2713 ] + diffopts,
2714 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2714 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2715 def export(ui, repo, *changesets, **opts):
2715 def export(ui, repo, *changesets, **opts):
2716 """dump the header and diffs for one or more changesets
2716 """dump the header and diffs for one or more changesets
2717
2717
2718 Print the changeset header and diffs for one or more revisions.
2718 Print the changeset header and diffs for one or more revisions.
2719
2719
2720 The information shown in the changeset header is: author, date,
2720 The information shown in the changeset header is: author, date,
2721 branch name (if non-default), changeset hash, parent(s) and commit
2721 branch name (if non-default), changeset hash, parent(s) and commit
2722 comment.
2722 comment.
2723
2723
2724 .. note::
2724 .. note::
2725 export may generate unexpected diff output for merge
2725 export may generate unexpected diff output for merge
2726 changesets, as it will compare the merge changeset against its
2726 changesets, as it will compare the merge changeset against its
2727 first parent only.
2727 first parent only.
2728
2728
2729 Output may be to a file, in which case the name of the file is
2729 Output may be to a file, in which case the name of the file is
2730 given using a format string. The formatting rules are as follows:
2730 given using a format string. The formatting rules are as follows:
2731
2731
2732 :``%%``: literal "%" character
2732 :``%%``: literal "%" character
2733 :``%H``: changeset hash (40 hexadecimal digits)
2733 :``%H``: changeset hash (40 hexadecimal digits)
2734 :``%N``: number of patches being generated
2734 :``%N``: number of patches being generated
2735 :``%R``: changeset revision number
2735 :``%R``: changeset revision number
2736 :``%b``: basename of the exporting repository
2736 :``%b``: basename of the exporting repository
2737 :``%h``: short-form changeset hash (12 hexadecimal digits)
2737 :``%h``: short-form changeset hash (12 hexadecimal digits)
2738 :``%m``: first line of the commit message (only alphanumeric characters)
2738 :``%m``: first line of the commit message (only alphanumeric characters)
2739 :``%n``: zero-padded sequence number, starting at 1
2739 :``%n``: zero-padded sequence number, starting at 1
2740 :``%r``: zero-padded changeset revision number
2740 :``%r``: zero-padded changeset revision number
2741
2741
2742 Without the -a/--text option, export will avoid generating diffs
2742 Without the -a/--text option, export will avoid generating diffs
2743 of files it detects as binary. With -a, export will generate a
2743 of files it detects as binary. With -a, export will generate a
2744 diff anyway, probably with undesirable results.
2744 diff anyway, probably with undesirable results.
2745
2745
2746 Use the -g/--git option to generate diffs in the git extended diff
2746 Use the -g/--git option to generate diffs in the git extended diff
2747 format. See :hg:`help diffs` for more information.
2747 format. See :hg:`help diffs` for more information.
2748
2748
2749 With the --switch-parent option, the diff will be against the
2749 With the --switch-parent option, the diff will be against the
2750 second parent. It can be useful to review a merge.
2750 second parent. It can be useful to review a merge.
2751
2751
2752 .. container:: verbose
2752 .. container:: verbose
2753
2753
2754 Examples:
2754 Examples:
2755
2755
2756 - use export and import to transplant a bugfix to the current
2756 - use export and import to transplant a bugfix to the current
2757 branch::
2757 branch::
2758
2758
2759 hg export -r 9353 | hg import -
2759 hg export -r 9353 | hg import -
2760
2760
2761 - export all the changesets between two revisions to a file with
2761 - export all the changesets between two revisions to a file with
2762 rename information::
2762 rename information::
2763
2763
2764 hg export --git -r 123:150 > changes.txt
2764 hg export --git -r 123:150 > changes.txt
2765
2765
2766 - split outgoing changes into a series of patches with
2766 - split outgoing changes into a series of patches with
2767 descriptive names::
2767 descriptive names::
2768
2768
2769 hg export -r "outgoing()" -o "%n-%m.patch"
2769 hg export -r "outgoing()" -o "%n-%m.patch"
2770
2770
2771 Returns 0 on success.
2771 Returns 0 on success.
2772 """
2772 """
2773 changesets += tuple(opts.get('rev', []))
2773 changesets += tuple(opts.get('rev', []))
2774 revs = scmutil.revrange(repo, changesets)
2774 revs = scmutil.revrange(repo, changesets)
2775 if not revs:
2775 if not revs:
2776 raise util.Abort(_("export requires at least one changeset"))
2776 raise util.Abort(_("export requires at least one changeset"))
2777 if len(revs) > 1:
2777 if len(revs) > 1:
2778 ui.note(_('exporting patches:\n'))
2778 ui.note(_('exporting patches:\n'))
2779 else:
2779 else:
2780 ui.note(_('exporting patch:\n'))
2780 ui.note(_('exporting patch:\n'))
2781 cmdutil.export(repo, revs, template=opts.get('output'),
2781 cmdutil.export(repo, revs, template=opts.get('output'),
2782 switch_parent=opts.get('switch_parent'),
2782 switch_parent=opts.get('switch_parent'),
2783 opts=patch.diffopts(ui, opts))
2783 opts=patch.diffopts(ui, opts))
2784
2784
2785 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2785 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2786 def forget(ui, repo, *pats, **opts):
2786 def forget(ui, repo, *pats, **opts):
2787 """forget the specified files on the next commit
2787 """forget the specified files on the next commit
2788
2788
2789 Mark the specified files so they will no longer be tracked
2789 Mark the specified files so they will no longer be tracked
2790 after the next commit.
2790 after the next commit.
2791
2791
2792 This only removes files from the current branch, not from the
2792 This only removes files from the current branch, not from the
2793 entire project history, and it does not delete them from the
2793 entire project history, and it does not delete them from the
2794 working directory.
2794 working directory.
2795
2795
2796 To undo a forget before the next commit, see :hg:`add`.
2796 To undo a forget before the next commit, see :hg:`add`.
2797
2797
2798 .. container:: verbose
2798 .. container:: verbose
2799
2799
2800 Examples:
2800 Examples:
2801
2801
2802 - forget newly-added binary files::
2802 - forget newly-added binary files::
2803
2803
2804 hg forget "set:added() and binary()"
2804 hg forget "set:added() and binary()"
2805
2805
2806 - forget files that would be excluded by .hgignore::
2806 - forget files that would be excluded by .hgignore::
2807
2807
2808 hg forget "set:hgignore()"
2808 hg forget "set:hgignore()"
2809
2809
2810 Returns 0 on success.
2810 Returns 0 on success.
2811 """
2811 """
2812
2812
2813 if not pats:
2813 if not pats:
2814 raise util.Abort(_('no files specified'))
2814 raise util.Abort(_('no files specified'))
2815
2815
2816 m = scmutil.match(repo[None], pats, opts)
2816 m = scmutil.match(repo[None], pats, opts)
2817 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2817 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2818 return rejected and 1 or 0
2818 return rejected and 1 or 0
2819
2819
2820 @command(
2820 @command(
2821 'graft',
2821 'graft',
2822 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2822 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2823 ('c', 'continue', False, _('resume interrupted graft')),
2823 ('c', 'continue', False, _('resume interrupted graft')),
2824 ('e', 'edit', False, _('invoke editor on commit messages')),
2824 ('e', 'edit', False, _('invoke editor on commit messages')),
2825 ('', 'log', None, _('append graft info to log message')),
2825 ('', 'log', None, _('append graft info to log message')),
2826 ('D', 'currentdate', False,
2826 ('D', 'currentdate', False,
2827 _('record the current date as commit date')),
2827 _('record the current date as commit date')),
2828 ('U', 'currentuser', False,
2828 ('U', 'currentuser', False,
2829 _('record the current user as committer'), _('DATE'))]
2829 _('record the current user as committer'), _('DATE'))]
2830 + commitopts2 + mergetoolopts + dryrunopts,
2830 + commitopts2 + mergetoolopts + dryrunopts,
2831 _('[OPTION]... [-r] REV...'))
2831 _('[OPTION]... [-r] REV...'))
2832 def graft(ui, repo, *revs, **opts):
2832 def graft(ui, repo, *revs, **opts):
2833 '''copy changes from other branches onto the current branch
2833 '''copy changes from other branches onto the current branch
2834
2834
2835 This command uses Mercurial's merge logic to copy individual
2835 This command uses Mercurial's merge logic to copy individual
2836 changes from other branches without merging branches in the
2836 changes from other branches without merging branches in the
2837 history graph. This is sometimes known as 'backporting' or
2837 history graph. This is sometimes known as 'backporting' or
2838 'cherry-picking'. By default, graft will copy user, date, and
2838 'cherry-picking'. By default, graft will copy user, date, and
2839 description from the source changesets.
2839 description from the source changesets.
2840
2840
2841 Changesets that are ancestors of the current revision, that have
2841 Changesets that are ancestors of the current revision, that have
2842 already been grafted, or that are merges will be skipped.
2842 already been grafted, or that are merges will be skipped.
2843
2843
2844 If --log is specified, log messages will have a comment appended
2844 If --log is specified, log messages will have a comment appended
2845 of the form::
2845 of the form::
2846
2846
2847 (grafted from CHANGESETHASH)
2847 (grafted from CHANGESETHASH)
2848
2848
2849 If a graft merge results in conflicts, the graft process is
2849 If a graft merge results in conflicts, the graft process is
2850 interrupted so that the current merge can be manually resolved.
2850 interrupted so that the current merge can be manually resolved.
2851 Once all conflicts are addressed, the graft process can be
2851 Once all conflicts are addressed, the graft process can be
2852 continued with the -c/--continue option.
2852 continued with the -c/--continue option.
2853
2853
2854 .. note::
2854 .. note::
2855 The -c/--continue option does not reapply earlier options.
2855 The -c/--continue option does not reapply earlier options.
2856
2856
2857 .. container:: verbose
2857 .. container:: verbose
2858
2858
2859 Examples:
2859 Examples:
2860
2860
2861 - copy a single change to the stable branch and edit its description::
2861 - copy a single change to the stable branch and edit its description::
2862
2862
2863 hg update stable
2863 hg update stable
2864 hg graft --edit 9393
2864 hg graft --edit 9393
2865
2865
2866 - graft a range of changesets with one exception, updating dates::
2866 - graft a range of changesets with one exception, updating dates::
2867
2867
2868 hg graft -D "2085::2093 and not 2091"
2868 hg graft -D "2085::2093 and not 2091"
2869
2869
2870 - continue a graft after resolving conflicts::
2870 - continue a graft after resolving conflicts::
2871
2871
2872 hg graft -c
2872 hg graft -c
2873
2873
2874 - show the source of a grafted changeset::
2874 - show the source of a grafted changeset::
2875
2875
2876 hg log --debug -r tip
2876 hg log --debug -r tip
2877
2877
2878 Returns 0 on successful completion.
2878 Returns 0 on successful completion.
2879 '''
2879 '''
2880
2880
2881 revs = list(revs)
2881 revs = list(revs)
2882 revs.extend(opts['rev'])
2882 revs.extend(opts['rev'])
2883
2883
2884 if not opts.get('user') and opts.get('currentuser'):
2884 if not opts.get('user') and opts.get('currentuser'):
2885 opts['user'] = ui.username()
2885 opts['user'] = ui.username()
2886 if not opts.get('date') and opts.get('currentdate'):
2886 if not opts.get('date') and opts.get('currentdate'):
2887 opts['date'] = "%d %d" % util.makedate()
2887 opts['date'] = "%d %d" % util.makedate()
2888
2888
2889 editor = None
2889 editor = None
2890 if opts.get('edit'):
2890 if opts.get('edit'):
2891 editor = cmdutil.commitforceeditor
2891 editor = cmdutil.commitforceeditor
2892
2892
2893 cont = False
2893 cont = False
2894 if opts['continue']:
2894 if opts['continue']:
2895 cont = True
2895 cont = True
2896 if revs:
2896 if revs:
2897 raise util.Abort(_("can't specify --continue and revisions"))
2897 raise util.Abort(_("can't specify --continue and revisions"))
2898 # read in unfinished revisions
2898 # read in unfinished revisions
2899 try:
2899 try:
2900 nodes = repo.opener.read('graftstate').splitlines()
2900 nodes = repo.opener.read('graftstate').splitlines()
2901 revs = [repo[node].rev() for node in nodes]
2901 revs = [repo[node].rev() for node in nodes]
2902 except IOError, inst:
2902 except IOError, inst:
2903 if inst.errno != errno.ENOENT:
2903 if inst.errno != errno.ENOENT:
2904 raise
2904 raise
2905 raise util.Abort(_("no graft state found, can't continue"))
2905 raise util.Abort(_("no graft state found, can't continue"))
2906 else:
2906 else:
2907 cmdutil.bailifchanged(repo)
2907 cmdutil.bailifchanged(repo)
2908 if not revs:
2908 if not revs:
2909 raise util.Abort(_('no revisions specified'))
2909 raise util.Abort(_('no revisions specified'))
2910 revs = scmutil.revrange(repo, revs)
2910 revs = scmutil.revrange(repo, revs)
2911
2911
2912 # check for merges
2912 # check for merges
2913 for rev in repo.revs('%ld and merge()', revs):
2913 for rev in repo.revs('%ld and merge()', revs):
2914 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2914 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2915 revs.remove(rev)
2915 revs.remove(rev)
2916 if not revs:
2916 if not revs:
2917 return -1
2917 return -1
2918
2918
2919 # check for ancestors of dest branch
2919 # check for ancestors of dest branch
2920 for rev in repo.revs('::. and %ld', revs):
2920 for rev in repo.revs('::. and %ld', revs):
2921 ui.warn(_('skipping ancestor revision %s\n') % rev)
2921 ui.warn(_('skipping ancestor revision %s\n') % rev)
2922 revs.remove(rev)
2922 revs.remove(rev)
2923 if not revs:
2923 if not revs:
2924 return -1
2924 return -1
2925
2925
2926 # analyze revs for earlier grafts
2926 # analyze revs for earlier grafts
2927 ids = {}
2927 ids = {}
2928 for ctx in repo.set("%ld", revs):
2928 for ctx in repo.set("%ld", revs):
2929 ids[ctx.hex()] = ctx.rev()
2929 ids[ctx.hex()] = ctx.rev()
2930 n = ctx.extra().get('source')
2930 n = ctx.extra().get('source')
2931 if n:
2931 if n:
2932 ids[n] = ctx.rev()
2932 ids[n] = ctx.rev()
2933
2933
2934 # check ancestors for earlier grafts
2934 # check ancestors for earlier grafts
2935 ui.debug('scanning for duplicate grafts\n')
2935 ui.debug('scanning for duplicate grafts\n')
2936 for ctx in repo.set("::. - ::%ld", revs):
2936 for ctx in repo.set("::. - ::%ld", revs):
2937 n = ctx.extra().get('source')
2937 n = ctx.extra().get('source')
2938 if n in ids:
2938 if n in ids:
2939 r = repo[n].rev()
2939 r = repo[n].rev()
2940 if r in revs:
2940 if r in revs:
2941 ui.warn(_('skipping already grafted revision %s\n') % r)
2941 ui.warn(_('skipping already grafted revision %s\n') % r)
2942 revs.remove(r)
2942 revs.remove(r)
2943 elif ids[n] in revs:
2943 elif ids[n] in revs:
2944 ui.warn(_('skipping already grafted revision %s '
2944 ui.warn(_('skipping already grafted revision %s '
2945 '(same origin %d)\n') % (ids[n], r))
2945 '(same origin %d)\n') % (ids[n], r))
2946 revs.remove(ids[n])
2946 revs.remove(ids[n])
2947 elif ctx.hex() in ids:
2947 elif ctx.hex() in ids:
2948 r = ids[ctx.hex()]
2948 r = ids[ctx.hex()]
2949 ui.warn(_('skipping already grafted revision %s '
2949 ui.warn(_('skipping already grafted revision %s '
2950 '(was grafted from %d)\n') % (r, ctx.rev()))
2950 '(was grafted from %d)\n') % (r, ctx.rev()))
2951 revs.remove(r)
2951 revs.remove(r)
2952 if not revs:
2952 if not revs:
2953 return -1
2953 return -1
2954
2954
2955 wlock = repo.wlock()
2955 wlock = repo.wlock()
2956 try:
2956 try:
2957 current = repo['.']
2957 current = repo['.']
2958 for pos, ctx in enumerate(repo.set("%ld", revs)):
2958 for pos, ctx in enumerate(repo.set("%ld", revs)):
2959
2959
2960 ui.status(_('grafting revision %s\n') % ctx.rev())
2960 ui.status(_('grafting revision %s\n') % ctx.rev())
2961 if opts.get('dry_run'):
2961 if opts.get('dry_run'):
2962 continue
2962 continue
2963
2963
2964 source = ctx.extra().get('source')
2964 source = ctx.extra().get('source')
2965 if not source:
2965 if not source:
2966 source = ctx.hex()
2966 source = ctx.hex()
2967 extra = {'source': source}
2967 extra = {'source': source}
2968 user = ctx.user()
2968 user = ctx.user()
2969 if opts.get('user'):
2969 if opts.get('user'):
2970 user = opts['user']
2970 user = opts['user']
2971 date = ctx.date()
2971 date = ctx.date()
2972 if opts.get('date'):
2972 if opts.get('date'):
2973 date = opts['date']
2973 date = opts['date']
2974 message = ctx.description()
2974 message = ctx.description()
2975 if opts.get('log'):
2975 if opts.get('log'):
2976 message += '\n(grafted from %s)' % ctx.hex()
2976 message += '\n(grafted from %s)' % ctx.hex()
2977
2977
2978 # we don't merge the first commit when continuing
2978 # we don't merge the first commit when continuing
2979 if not cont:
2979 if not cont:
2980 # perform the graft merge with p1(rev) as 'ancestor'
2980 # perform the graft merge with p1(rev) as 'ancestor'
2981 try:
2981 try:
2982 # ui.forcemerge is an internal variable, do not document
2982 # ui.forcemerge is an internal variable, do not document
2983 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2983 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2984 stats = mergemod.update(repo, ctx.node(), True, True, False,
2984 stats = mergemod.update(repo, ctx.node(), True, True, False,
2985 ctx.p1().node())
2985 ctx.p1().node())
2986 finally:
2986 finally:
2987 repo.ui.setconfig('ui', 'forcemerge', '')
2987 repo.ui.setconfig('ui', 'forcemerge', '')
2988 # report any conflicts
2988 # report any conflicts
2989 if stats and stats[3] > 0:
2989 if stats and stats[3] > 0:
2990 # write out state for --continue
2990 # write out state for --continue
2991 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2991 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2992 repo.opener.write('graftstate', ''.join(nodelines))
2992 repo.opener.write('graftstate', ''.join(nodelines))
2993 raise util.Abort(
2993 raise util.Abort(
2994 _("unresolved conflicts, can't continue"),
2994 _("unresolved conflicts, can't continue"),
2995 hint=_('use hg resolve and hg graft --continue'))
2995 hint=_('use hg resolve and hg graft --continue'))
2996 else:
2996 else:
2997 cont = False
2997 cont = False
2998
2998
2999 # drop the second merge parent
2999 # drop the second merge parent
3000 repo.setparents(current.node(), nullid)
3000 repo.setparents(current.node(), nullid)
3001 repo.dirstate.write()
3001 repo.dirstate.write()
3002 # fix up dirstate for copies and renames
3002 # fix up dirstate for copies and renames
3003 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3003 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3004
3004
3005 # commit
3005 # commit
3006 node = repo.commit(text=message, user=user,
3006 node = repo.commit(text=message, user=user,
3007 date=date, extra=extra, editor=editor)
3007 date=date, extra=extra, editor=editor)
3008 if node is None:
3008 if node is None:
3009 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3009 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3010 else:
3010 else:
3011 current = repo[node]
3011 current = repo[node]
3012 finally:
3012 finally:
3013 wlock.release()
3013 wlock.release()
3014
3014
3015 # remove state when we complete successfully
3015 # remove state when we complete successfully
3016 if not opts.get('dry_run'):
3016 if not opts.get('dry_run'):
3017 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3017 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3018
3018
3019 return 0
3019 return 0
3020
3020
3021 @command('grep',
3021 @command('grep',
3022 [('0', 'print0', None, _('end fields with NUL')),
3022 [('0', 'print0', None, _('end fields with NUL')),
3023 ('', 'all', None, _('print all revisions that match')),
3023 ('', 'all', None, _('print all revisions that match')),
3024 ('a', 'text', None, _('treat all files as text')),
3024 ('a', 'text', None, _('treat all files as text')),
3025 ('f', 'follow', None,
3025 ('f', 'follow', None,
3026 _('follow changeset history,'
3026 _('follow changeset history,'
3027 ' or file history across copies and renames')),
3027 ' or file history across copies and renames')),
3028 ('i', 'ignore-case', None, _('ignore case when matching')),
3028 ('i', 'ignore-case', None, _('ignore case when matching')),
3029 ('l', 'files-with-matches', None,
3029 ('l', 'files-with-matches', None,
3030 _('print only filenames and revisions that match')),
3030 _('print only filenames and revisions that match')),
3031 ('n', 'line-number', None, _('print matching line numbers')),
3031 ('n', 'line-number', None, _('print matching line numbers')),
3032 ('r', 'rev', [],
3032 ('r', 'rev', [],
3033 _('only search files changed within revision range'), _('REV')),
3033 _('only search files changed within revision range'), _('REV')),
3034 ('u', 'user', None, _('list the author (long with -v)')),
3034 ('u', 'user', None, _('list the author (long with -v)')),
3035 ('d', 'date', None, _('list the date (short with -q)')),
3035 ('d', 'date', None, _('list the date (short with -q)')),
3036 ] + walkopts,
3036 ] + walkopts,
3037 _('[OPTION]... PATTERN [FILE]...'))
3037 _('[OPTION]... PATTERN [FILE]...'))
3038 def grep(ui, repo, pattern, *pats, **opts):
3038 def grep(ui, repo, pattern, *pats, **opts):
3039 """search for a pattern in specified files and revisions
3039 """search for a pattern in specified files and revisions
3040
3040
3041 Search revisions of files for a regular expression.
3041 Search revisions of files for a regular expression.
3042
3042
3043 This command behaves differently than Unix grep. It only accepts
3043 This command behaves differently than Unix grep. It only accepts
3044 Python/Perl regexps. It searches repository history, not the
3044 Python/Perl regexps. It searches repository history, not the
3045 working directory. It always prints the revision number in which a
3045 working directory. It always prints the revision number in which a
3046 match appears.
3046 match appears.
3047
3047
3048 By default, grep only prints output for the first revision of a
3048 By default, grep only prints output for the first revision of a
3049 file in which it finds a match. To get it to print every revision
3049 file in which it finds a match. To get it to print every revision
3050 that contains a change in match status ("-" for a match that
3050 that contains a change in match status ("-" for a match that
3051 becomes a non-match, or "+" for a non-match that becomes a match),
3051 becomes a non-match, or "+" for a non-match that becomes a match),
3052 use the --all flag.
3052 use the --all flag.
3053
3053
3054 Returns 0 if a match is found, 1 otherwise.
3054 Returns 0 if a match is found, 1 otherwise.
3055 """
3055 """
3056 reflags = re.M
3056 reflags = re.M
3057 if opts.get('ignore_case'):
3057 if opts.get('ignore_case'):
3058 reflags |= re.I
3058 reflags |= re.I
3059 try:
3059 try:
3060 regexp = util.compilere(pattern, reflags)
3060 regexp = util.compilere(pattern, reflags)
3061 except re.error, inst:
3061 except re.error, inst:
3062 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3062 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3063 return 1
3063 return 1
3064 sep, eol = ':', '\n'
3064 sep, eol = ':', '\n'
3065 if opts.get('print0'):
3065 if opts.get('print0'):
3066 sep = eol = '\0'
3066 sep = eol = '\0'
3067
3067
3068 getfile = util.lrucachefunc(repo.file)
3068 getfile = util.lrucachefunc(repo.file)
3069
3069
3070 def matchlines(body):
3070 def matchlines(body):
3071 begin = 0
3071 begin = 0
3072 linenum = 0
3072 linenum = 0
3073 while begin < len(body):
3073 while begin < len(body):
3074 match = regexp.search(body, begin)
3074 match = regexp.search(body, begin)
3075 if not match:
3075 if not match:
3076 break
3076 break
3077 mstart, mend = match.span()
3077 mstart, mend = match.span()
3078 linenum += body.count('\n', begin, mstart) + 1
3078 linenum += body.count('\n', begin, mstart) + 1
3079 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3079 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3080 begin = body.find('\n', mend) + 1 or len(body) + 1
3080 begin = body.find('\n', mend) + 1 or len(body) + 1
3081 lend = begin - 1
3081 lend = begin - 1
3082 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3082 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3083
3083
3084 class linestate(object):
3084 class linestate(object):
3085 def __init__(self, line, linenum, colstart, colend):
3085 def __init__(self, line, linenum, colstart, colend):
3086 self.line = line
3086 self.line = line
3087 self.linenum = linenum
3087 self.linenum = linenum
3088 self.colstart = colstart
3088 self.colstart = colstart
3089 self.colend = colend
3089 self.colend = colend
3090
3090
3091 def __hash__(self):
3091 def __hash__(self):
3092 return hash((self.linenum, self.line))
3092 return hash((self.linenum, self.line))
3093
3093
3094 def __eq__(self, other):
3094 def __eq__(self, other):
3095 return self.line == other.line
3095 return self.line == other.line
3096
3096
3097 matches = {}
3097 matches = {}
3098 copies = {}
3098 copies = {}
3099 def grepbody(fn, rev, body):
3099 def grepbody(fn, rev, body):
3100 matches[rev].setdefault(fn, [])
3100 matches[rev].setdefault(fn, [])
3101 m = matches[rev][fn]
3101 m = matches[rev][fn]
3102 for lnum, cstart, cend, line in matchlines(body):
3102 for lnum, cstart, cend, line in matchlines(body):
3103 s = linestate(line, lnum, cstart, cend)
3103 s = linestate(line, lnum, cstart, cend)
3104 m.append(s)
3104 m.append(s)
3105
3105
3106 def difflinestates(a, b):
3106 def difflinestates(a, b):
3107 sm = difflib.SequenceMatcher(None, a, b)
3107 sm = difflib.SequenceMatcher(None, a, b)
3108 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3108 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3109 if tag == 'insert':
3109 if tag == 'insert':
3110 for i in xrange(blo, bhi):
3110 for i in xrange(blo, bhi):
3111 yield ('+', b[i])
3111 yield ('+', b[i])
3112 elif tag == 'delete':
3112 elif tag == 'delete':
3113 for i in xrange(alo, ahi):
3113 for i in xrange(alo, ahi):
3114 yield ('-', a[i])
3114 yield ('-', a[i])
3115 elif tag == 'replace':
3115 elif tag == 'replace':
3116 for i in xrange(alo, ahi):
3116 for i in xrange(alo, ahi):
3117 yield ('-', a[i])
3117 yield ('-', a[i])
3118 for i in xrange(blo, bhi):
3118 for i in xrange(blo, bhi):
3119 yield ('+', b[i])
3119 yield ('+', b[i])
3120
3120
3121 def display(fn, ctx, pstates, states):
3121 def display(fn, ctx, pstates, states):
3122 rev = ctx.rev()
3122 rev = ctx.rev()
3123 datefunc = ui.quiet and util.shortdate or util.datestr
3123 datefunc = ui.quiet and util.shortdate or util.datestr
3124 found = False
3124 found = False
3125 filerevmatches = {}
3125 filerevmatches = {}
3126 def binary():
3126 def binary():
3127 flog = getfile(fn)
3127 flog = getfile(fn)
3128 return util.binary(flog.read(ctx.filenode(fn)))
3128 return util.binary(flog.read(ctx.filenode(fn)))
3129
3129
3130 if opts.get('all'):
3130 if opts.get('all'):
3131 iter = difflinestates(pstates, states)
3131 iter = difflinestates(pstates, states)
3132 else:
3132 else:
3133 iter = [('', l) for l in states]
3133 iter = [('', l) for l in states]
3134 for change, l in iter:
3134 for change, l in iter:
3135 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3135 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3136 before, match, after = None, None, None
3136 before, match, after = None, None, None
3137
3137
3138 if opts.get('line_number'):
3138 if opts.get('line_number'):
3139 cols.append((str(l.linenum), 'grep.linenumber'))
3139 cols.append((str(l.linenum), 'grep.linenumber'))
3140 if opts.get('all'):
3140 if opts.get('all'):
3141 cols.append((change, 'grep.change'))
3141 cols.append((change, 'grep.change'))
3142 if opts.get('user'):
3142 if opts.get('user'):
3143 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3143 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3144 if opts.get('date'):
3144 if opts.get('date'):
3145 cols.append((datefunc(ctx.date()), 'grep.date'))
3145 cols.append((datefunc(ctx.date()), 'grep.date'))
3146 if opts.get('files_with_matches'):
3146 if opts.get('files_with_matches'):
3147 c = (fn, rev)
3147 c = (fn, rev)
3148 if c in filerevmatches:
3148 if c in filerevmatches:
3149 continue
3149 continue
3150 filerevmatches[c] = 1
3150 filerevmatches[c] = 1
3151 else:
3151 else:
3152 before = l.line[:l.colstart]
3152 before = l.line[:l.colstart]
3153 match = l.line[l.colstart:l.colend]
3153 match = l.line[l.colstart:l.colend]
3154 after = l.line[l.colend:]
3154 after = l.line[l.colend:]
3155 for col, label in cols[:-1]:
3155 for col, label in cols[:-1]:
3156 ui.write(col, label=label)
3156 ui.write(col, label=label)
3157 ui.write(sep, label='grep.sep')
3157 ui.write(sep, label='grep.sep')
3158 ui.write(cols[-1][0], label=cols[-1][1])
3158 ui.write(cols[-1][0], label=cols[-1][1])
3159 if before is not None:
3159 if before is not None:
3160 ui.write(sep, label='grep.sep')
3160 ui.write(sep, label='grep.sep')
3161 if not opts.get('text') and binary():
3161 if not opts.get('text') and binary():
3162 ui.write(" Binary file matches")
3162 ui.write(" Binary file matches")
3163 else:
3163 else:
3164 ui.write(before)
3164 ui.write(before)
3165 ui.write(match, label='grep.match')
3165 ui.write(match, label='grep.match')
3166 ui.write(after)
3166 ui.write(after)
3167 ui.write(eol)
3167 ui.write(eol)
3168 found = True
3168 found = True
3169 return found
3169 return found
3170
3170
3171 skip = {}
3171 skip = {}
3172 revfiles = {}
3172 revfiles = {}
3173 matchfn = scmutil.match(repo[None], pats, opts)
3173 matchfn = scmutil.match(repo[None], pats, opts)
3174 found = False
3174 found = False
3175 follow = opts.get('follow')
3175 follow = opts.get('follow')
3176
3176
3177 def prep(ctx, fns):
3177 def prep(ctx, fns):
3178 rev = ctx.rev()
3178 rev = ctx.rev()
3179 pctx = ctx.p1()
3179 pctx = ctx.p1()
3180 parent = pctx.rev()
3180 parent = pctx.rev()
3181 matches.setdefault(rev, {})
3181 matches.setdefault(rev, {})
3182 matches.setdefault(parent, {})
3182 matches.setdefault(parent, {})
3183 files = revfiles.setdefault(rev, [])
3183 files = revfiles.setdefault(rev, [])
3184 for fn in fns:
3184 for fn in fns:
3185 flog = getfile(fn)
3185 flog = getfile(fn)
3186 try:
3186 try:
3187 fnode = ctx.filenode(fn)
3187 fnode = ctx.filenode(fn)
3188 except error.LookupError:
3188 except error.LookupError:
3189 continue
3189 continue
3190
3190
3191 copied = flog.renamed(fnode)
3191 copied = flog.renamed(fnode)
3192 copy = follow and copied and copied[0]
3192 copy = follow and copied and copied[0]
3193 if copy:
3193 if copy:
3194 copies.setdefault(rev, {})[fn] = copy
3194 copies.setdefault(rev, {})[fn] = copy
3195 if fn in skip:
3195 if fn in skip:
3196 if copy:
3196 if copy:
3197 skip[copy] = True
3197 skip[copy] = True
3198 continue
3198 continue
3199 files.append(fn)
3199 files.append(fn)
3200
3200
3201 if fn not in matches[rev]:
3201 if fn not in matches[rev]:
3202 grepbody(fn, rev, flog.read(fnode))
3202 grepbody(fn, rev, flog.read(fnode))
3203
3203
3204 pfn = copy or fn
3204 pfn = copy or fn
3205 if pfn not in matches[parent]:
3205 if pfn not in matches[parent]:
3206 try:
3206 try:
3207 fnode = pctx.filenode(pfn)
3207 fnode = pctx.filenode(pfn)
3208 grepbody(pfn, parent, flog.read(fnode))
3208 grepbody(pfn, parent, flog.read(fnode))
3209 except error.LookupError:
3209 except error.LookupError:
3210 pass
3210 pass
3211
3211
3212 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3212 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3213 rev = ctx.rev()
3213 rev = ctx.rev()
3214 parent = ctx.p1().rev()
3214 parent = ctx.p1().rev()
3215 for fn in sorted(revfiles.get(rev, [])):
3215 for fn in sorted(revfiles.get(rev, [])):
3216 states = matches[rev][fn]
3216 states = matches[rev][fn]
3217 copy = copies.get(rev, {}).get(fn)
3217 copy = copies.get(rev, {}).get(fn)
3218 if fn in skip:
3218 if fn in skip:
3219 if copy:
3219 if copy:
3220 skip[copy] = True
3220 skip[copy] = True
3221 continue
3221 continue
3222 pstates = matches.get(parent, {}).get(copy or fn, [])
3222 pstates = matches.get(parent, {}).get(copy or fn, [])
3223 if pstates or states:
3223 if pstates or states:
3224 r = display(fn, ctx, pstates, states)
3224 r = display(fn, ctx, pstates, states)
3225 found = found or r
3225 found = found or r
3226 if r and not opts.get('all'):
3226 if r and not opts.get('all'):
3227 skip[fn] = True
3227 skip[fn] = True
3228 if copy:
3228 if copy:
3229 skip[copy] = True
3229 skip[copy] = True
3230 del matches[rev]
3230 del matches[rev]
3231 del revfiles[rev]
3231 del revfiles[rev]
3232
3232
3233 return not found
3233 return not found
3234
3234
3235 @command('heads',
3235 @command('heads',
3236 [('r', 'rev', '',
3236 [('r', 'rev', '',
3237 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3237 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3238 ('t', 'topo', False, _('show topological heads only')),
3238 ('t', 'topo', False, _('show topological heads only')),
3239 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3239 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3240 ('c', 'closed', False, _('show normal and closed branch heads')),
3240 ('c', 'closed', False, _('show normal and closed branch heads')),
3241 ] + templateopts,
3241 ] + templateopts,
3242 _('[-ct] [-r STARTREV] [REV]...'))
3242 _('[-ct] [-r STARTREV] [REV]...'))
3243 def heads(ui, repo, *branchrevs, **opts):
3243 def heads(ui, repo, *branchrevs, **opts):
3244 """show current repository heads or show branch heads
3244 """show current repository heads or show branch heads
3245
3245
3246 With no arguments, show all repository branch heads.
3246 With no arguments, show all repository branch heads.
3247
3247
3248 Repository "heads" are changesets with no child changesets. They are
3248 Repository "heads" are changesets with no child changesets. They are
3249 where development generally takes place and are the usual targets
3249 where development generally takes place and are the usual targets
3250 for update and merge operations. Branch heads are changesets that have
3250 for update and merge operations. Branch heads are changesets that have
3251 no child changeset on the same branch.
3251 no child changeset on the same branch.
3252
3252
3253 If one or more REVs are given, only branch heads on the branches
3253 If one or more REVs are given, only branch heads on the branches
3254 associated with the specified changesets are shown. This means
3254 associated with the specified changesets are shown. This means
3255 that you can use :hg:`heads foo` to see the heads on a branch
3255 that you can use :hg:`heads foo` to see the heads on a branch
3256 named ``foo``.
3256 named ``foo``.
3257
3257
3258 If -c/--closed is specified, also show branch heads marked closed
3258 If -c/--closed is specified, also show branch heads marked closed
3259 (see :hg:`commit --close-branch`).
3259 (see :hg:`commit --close-branch`).
3260
3260
3261 If STARTREV is specified, only those heads that are descendants of
3261 If STARTREV is specified, only those heads that are descendants of
3262 STARTREV will be displayed.
3262 STARTREV will be displayed.
3263
3263
3264 If -t/--topo is specified, named branch mechanics will be ignored and only
3264 If -t/--topo is specified, named branch mechanics will be ignored and only
3265 changesets without children will be shown.
3265 changesets without children will be shown.
3266
3266
3267 Returns 0 if matching heads are found, 1 if not.
3267 Returns 0 if matching heads are found, 1 if not.
3268 """
3268 """
3269
3269
3270 start = None
3270 start = None
3271 if 'rev' in opts:
3271 if 'rev' in opts:
3272 start = scmutil.revsingle(repo, opts['rev'], None).node()
3272 start = scmutil.revsingle(repo, opts['rev'], None).node()
3273
3273
3274 if opts.get('topo'):
3274 if opts.get('topo'):
3275 heads = [repo[h] for h in repo.heads(start)]
3275 heads = [repo[h] for h in repo.heads(start)]
3276 else:
3276 else:
3277 heads = []
3277 heads = []
3278 for branch in repo.branchmap():
3278 for branch in repo.branchmap():
3279 heads += repo.branchheads(branch, start, opts.get('closed'))
3279 heads += repo.branchheads(branch, start, opts.get('closed'))
3280 heads = [repo[h] for h in heads]
3280 heads = [repo[h] for h in heads]
3281
3281
3282 if branchrevs:
3282 if branchrevs:
3283 branches = set(repo[br].branch() for br in branchrevs)
3283 branches = set(repo[br].branch() for br in branchrevs)
3284 heads = [h for h in heads if h.branch() in branches]
3284 heads = [h for h in heads if h.branch() in branches]
3285
3285
3286 if opts.get('active') and branchrevs:
3286 if opts.get('active') and branchrevs:
3287 dagheads = repo.heads(start)
3287 dagheads = repo.heads(start)
3288 heads = [h for h in heads if h.node() in dagheads]
3288 heads = [h for h in heads if h.node() in dagheads]
3289
3289
3290 if branchrevs:
3290 if branchrevs:
3291 haveheads = set(h.branch() for h in heads)
3291 haveheads = set(h.branch() for h in heads)
3292 if branches - haveheads:
3292 if branches - haveheads:
3293 headless = ', '.join(b for b in branches - haveheads)
3293 headless = ', '.join(b for b in branches - haveheads)
3294 msg = _('no open branch heads found on branches %s')
3294 msg = _('no open branch heads found on branches %s')
3295 if opts.get('rev'):
3295 if opts.get('rev'):
3296 msg += _(' (started at %s)') % opts['rev']
3296 msg += _(' (started at %s)') % opts['rev']
3297 ui.warn((msg + '\n') % headless)
3297 ui.warn((msg + '\n') % headless)
3298
3298
3299 if not heads:
3299 if not heads:
3300 return 1
3300 return 1
3301
3301
3302 heads = sorted(heads, key=lambda x: -x.rev())
3302 heads = sorted(heads, key=lambda x: -x.rev())
3303 displayer = cmdutil.show_changeset(ui, repo, opts)
3303 displayer = cmdutil.show_changeset(ui, repo, opts)
3304 for ctx in heads:
3304 for ctx in heads:
3305 displayer.show(ctx)
3305 displayer.show(ctx)
3306 displayer.close()
3306 displayer.close()
3307
3307
3308 @command('help',
3308 @command('help',
3309 [('e', 'extension', None, _('show only help for extensions')),
3309 [('e', 'extension', None, _('show only help for extensions')),
3310 ('c', 'command', None, _('show only help for commands')),
3310 ('c', 'command', None, _('show only help for commands')),
3311 ('k', 'keyword', '', _('show topics matching keyword')),
3311 ('k', 'keyword', '', _('show topics matching keyword')),
3312 ],
3312 ],
3313 _('[-ec] [TOPIC]'))
3313 _('[-ec] [TOPIC]'))
3314 def help_(ui, name=None, **opts):
3314 def help_(ui, name=None, **opts):
3315 """show help for a given topic or a help overview
3315 """show help for a given topic or a help overview
3316
3316
3317 With no arguments, print a list of commands with short help messages.
3317 With no arguments, print a list of commands with short help messages.
3318
3318
3319 Given a topic, extension, or command name, print help for that
3319 Given a topic, extension, or command name, print help for that
3320 topic.
3320 topic.
3321
3321
3322 Returns 0 if successful.
3322 Returns 0 if successful.
3323 """
3323 """
3324
3324
3325 textwidth = min(ui.termwidth(), 80) - 2
3325 textwidth = min(ui.termwidth(), 80) - 2
3326
3326
3327 keep = ui.verbose and ['verbose'] or []
3327 keep = ui.verbose and ['verbose'] or []
3328 text = help.help_(ui, name, **opts)
3328 text = help.help_(ui, name, **opts)
3329
3329
3330 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3330 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3331 if 'verbose' in pruned:
3331 if 'verbose' in pruned:
3332 keep.append('omitted')
3332 keep.append('omitted')
3333 else:
3333 else:
3334 keep.append('notomitted')
3334 keep.append('notomitted')
3335 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3335 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3336 ui.write(formatted)
3336 ui.write(formatted)
3337
3337
3338
3338
3339 @command('identify|id',
3339 @command('identify|id',
3340 [('r', 'rev', '',
3340 [('r', 'rev', '',
3341 _('identify the specified revision'), _('REV')),
3341 _('identify the specified revision'), _('REV')),
3342 ('n', 'num', None, _('show local revision number')),
3342 ('n', 'num', None, _('show local revision number')),
3343 ('i', 'id', None, _('show global revision id')),
3343 ('i', 'id', None, _('show global revision id')),
3344 ('b', 'branch', None, _('show branch')),
3344 ('b', 'branch', None, _('show branch')),
3345 ('t', 'tags', None, _('show tags')),
3345 ('t', 'tags', None, _('show tags')),
3346 ('B', 'bookmarks', None, _('show bookmarks')),
3346 ('B', 'bookmarks', None, _('show bookmarks')),
3347 ] + remoteopts,
3347 ] + remoteopts,
3348 _('[-nibtB] [-r REV] [SOURCE]'))
3348 _('[-nibtB] [-r REV] [SOURCE]'))
3349 def identify(ui, repo, source=None, rev=None,
3349 def identify(ui, repo, source=None, rev=None,
3350 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3350 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3351 """identify the working copy or specified revision
3351 """identify the working copy or specified revision
3352
3352
3353 Print a summary identifying the repository state at REV using one or
3353 Print a summary identifying the repository state at REV using one or
3354 two parent hash identifiers, followed by a "+" if the working
3354 two parent hash identifiers, followed by a "+" if the working
3355 directory has uncommitted changes, the branch name (if not default),
3355 directory has uncommitted changes, the branch name (if not default),
3356 a list of tags, and a list of bookmarks.
3356 a list of tags, and a list of bookmarks.
3357
3357
3358 When REV is not given, print a summary of the current state of the
3358 When REV is not given, print a summary of the current state of the
3359 repository.
3359 repository.
3360
3360
3361 Specifying a path to a repository root or Mercurial bundle will
3361 Specifying a path to a repository root or Mercurial bundle will
3362 cause lookup to operate on that repository/bundle.
3362 cause lookup to operate on that repository/bundle.
3363
3363
3364 .. container:: verbose
3364 .. container:: verbose
3365
3365
3366 Examples:
3366 Examples:
3367
3367
3368 - generate a build identifier for the working directory::
3368 - generate a build identifier for the working directory::
3369
3369
3370 hg id --id > build-id.dat
3370 hg id --id > build-id.dat
3371
3371
3372 - find the revision corresponding to a tag::
3372 - find the revision corresponding to a tag::
3373
3373
3374 hg id -n -r 1.3
3374 hg id -n -r 1.3
3375
3375
3376 - check the most recent revision of a remote repository::
3376 - check the most recent revision of a remote repository::
3377
3377
3378 hg id -r tip http://selenic.com/hg/
3378 hg id -r tip http://selenic.com/hg/
3379
3379
3380 Returns 0 if successful.
3380 Returns 0 if successful.
3381 """
3381 """
3382
3382
3383 if not repo and not source:
3383 if not repo and not source:
3384 raise util.Abort(_("there is no Mercurial repository here "
3384 raise util.Abort(_("there is no Mercurial repository here "
3385 "(.hg not found)"))
3385 "(.hg not found)"))
3386
3386
3387 hexfunc = ui.debugflag and hex or short
3387 hexfunc = ui.debugflag and hex or short
3388 default = not (num or id or branch or tags or bookmarks)
3388 default = not (num or id or branch or tags or bookmarks)
3389 output = []
3389 output = []
3390 revs = []
3390 revs = []
3391
3391
3392 if source:
3392 if source:
3393 source, branches = hg.parseurl(ui.expandpath(source))
3393 source, branches = hg.parseurl(ui.expandpath(source))
3394 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3394 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3395 repo = peer.local()
3395 repo = peer.local()
3396 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3396 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3397
3397
3398 if not repo:
3398 if not repo:
3399 if num or branch or tags:
3399 if num or branch or tags:
3400 raise util.Abort(
3400 raise util.Abort(
3401 _("can't query remote revision number, branch, or tags"))
3401 _("can't query remote revision number, branch, or tags"))
3402 if not rev and revs:
3402 if not rev and revs:
3403 rev = revs[0]
3403 rev = revs[0]
3404 if not rev:
3404 if not rev:
3405 rev = "tip"
3405 rev = "tip"
3406
3406
3407 remoterev = peer.lookup(rev)
3407 remoterev = peer.lookup(rev)
3408 if default or id:
3408 if default or id:
3409 output = [hexfunc(remoterev)]
3409 output = [hexfunc(remoterev)]
3410
3410
3411 def getbms():
3411 def getbms():
3412 bms = []
3412 bms = []
3413
3413
3414 if 'bookmarks' in peer.listkeys('namespaces'):
3414 if 'bookmarks' in peer.listkeys('namespaces'):
3415 hexremoterev = hex(remoterev)
3415 hexremoterev = hex(remoterev)
3416 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3416 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3417 if bmr == hexremoterev]
3417 if bmr == hexremoterev]
3418
3418
3419 return sorted(bms)
3419 return sorted(bms)
3420
3420
3421 if bookmarks:
3421 if bookmarks:
3422 output.extend(getbms())
3422 output.extend(getbms())
3423 elif default and not ui.quiet:
3423 elif default and not ui.quiet:
3424 # multiple bookmarks for a single parent separated by '/'
3424 # multiple bookmarks for a single parent separated by '/'
3425 bm = '/'.join(getbms())
3425 bm = '/'.join(getbms())
3426 if bm:
3426 if bm:
3427 output.append(bm)
3427 output.append(bm)
3428 else:
3428 else:
3429 if not rev:
3429 if not rev:
3430 ctx = repo[None]
3430 ctx = repo[None]
3431 parents = ctx.parents()
3431 parents = ctx.parents()
3432 changed = ""
3432 changed = ""
3433 if default or id or num:
3433 if default or id or num:
3434 if (util.any(repo.status())
3434 if (util.any(repo.status())
3435 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3435 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3436 changed = '+'
3436 changed = '+'
3437 if default or id:
3437 if default or id:
3438 output = ["%s%s" %
3438 output = ["%s%s" %
3439 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3439 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3440 if num:
3440 if num:
3441 output.append("%s%s" %
3441 output.append("%s%s" %
3442 ('+'.join([str(p.rev()) for p in parents]), changed))
3442 ('+'.join([str(p.rev()) for p in parents]), changed))
3443 else:
3443 else:
3444 ctx = scmutil.revsingle(repo, rev)
3444 ctx = scmutil.revsingle(repo, rev)
3445 if default or id:
3445 if default or id:
3446 output = [hexfunc(ctx.node())]
3446 output = [hexfunc(ctx.node())]
3447 if num:
3447 if num:
3448 output.append(str(ctx.rev()))
3448 output.append(str(ctx.rev()))
3449
3449
3450 if default and not ui.quiet:
3450 if default and not ui.quiet:
3451 b = ctx.branch()
3451 b = ctx.branch()
3452 if b != 'default':
3452 if b != 'default':
3453 output.append("(%s)" % b)
3453 output.append("(%s)" % b)
3454
3454
3455 # multiple tags for a single parent separated by '/'
3455 # multiple tags for a single parent separated by '/'
3456 t = '/'.join(ctx.tags())
3456 t = '/'.join(ctx.tags())
3457 if t:
3457 if t:
3458 output.append(t)
3458 output.append(t)
3459
3459
3460 # multiple bookmarks for a single parent separated by '/'
3460 # multiple bookmarks for a single parent separated by '/'
3461 bm = '/'.join(ctx.bookmarks())
3461 bm = '/'.join(ctx.bookmarks())
3462 if bm:
3462 if bm:
3463 output.append(bm)
3463 output.append(bm)
3464 else:
3464 else:
3465 if branch:
3465 if branch:
3466 output.append(ctx.branch())
3466 output.append(ctx.branch())
3467
3467
3468 if tags:
3468 if tags:
3469 output.extend(ctx.tags())
3469 output.extend(ctx.tags())
3470
3470
3471 if bookmarks:
3471 if bookmarks:
3472 output.extend(ctx.bookmarks())
3472 output.extend(ctx.bookmarks())
3473
3473
3474 ui.write("%s\n" % ' '.join(output))
3474 ui.write("%s\n" % ' '.join(output))
3475
3475
3476 @command('import|patch',
3476 @command('import|patch',
3477 [('p', 'strip', 1,
3477 [('p', 'strip', 1,
3478 _('directory strip option for patch. This has the same '
3478 _('directory strip option for patch. This has the same '
3479 'meaning as the corresponding patch option'), _('NUM')),
3479 'meaning as the corresponding patch option'), _('NUM')),
3480 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3480 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3481 ('e', 'edit', False, _('invoke editor on commit messages')),
3481 ('e', 'edit', False, _('invoke editor on commit messages')),
3482 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3482 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3483 ('', 'no-commit', None,
3483 ('', 'no-commit', None,
3484 _("don't commit, just update the working directory")),
3484 _("don't commit, just update the working directory")),
3485 ('', 'bypass', None,
3485 ('', 'bypass', None,
3486 _("apply patch without touching the working directory")),
3486 _("apply patch without touching the working directory")),
3487 ('', 'exact', None,
3487 ('', 'exact', None,
3488 _('apply patch to the nodes from which it was generated')),
3488 _('apply patch to the nodes from which it was generated')),
3489 ('', 'import-branch', None,
3489 ('', 'import-branch', None,
3490 _('use any branch information in patch (implied by --exact)'))] +
3490 _('use any branch information in patch (implied by --exact)'))] +
3491 commitopts + commitopts2 + similarityopts,
3491 commitopts + commitopts2 + similarityopts,
3492 _('[OPTION]... PATCH...'))
3492 _('[OPTION]... PATCH...'))
3493 def import_(ui, repo, patch1=None, *patches, **opts):
3493 def import_(ui, repo, patch1=None, *patches, **opts):
3494 """import an ordered set of patches
3494 """import an ordered set of patches
3495
3495
3496 Import a list of patches and commit them individually (unless
3496 Import a list of patches and commit them individually (unless
3497 --no-commit is specified).
3497 --no-commit is specified).
3498
3498
3499 If there are outstanding changes in the working directory, import
3499 If there are outstanding changes in the working directory, import
3500 will abort unless given the -f/--force flag.
3500 will abort unless given the -f/--force flag.
3501
3501
3502 You can import a patch straight from a mail message. Even patches
3502 You can import a patch straight from a mail message. Even patches
3503 as attachments work (to use the body part, it must have type
3503 as attachments work (to use the body part, it must have type
3504 text/plain or text/x-patch). From and Subject headers of email
3504 text/plain or text/x-patch). From and Subject headers of email
3505 message are used as default committer and commit message. All
3505 message are used as default committer and commit message. All
3506 text/plain body parts before first diff are added to commit
3506 text/plain body parts before first diff are added to commit
3507 message.
3507 message.
3508
3508
3509 If the imported patch was generated by :hg:`export`, user and
3509 If the imported patch was generated by :hg:`export`, user and
3510 description from patch override values from message headers and
3510 description from patch override values from message headers and
3511 body. Values given on command line with -m/--message and -u/--user
3511 body. Values given on command line with -m/--message and -u/--user
3512 override these.
3512 override these.
3513
3513
3514 If --exact is specified, import will set the working directory to
3514 If --exact is specified, import will set the working directory to
3515 the parent of each patch before applying it, and will abort if the
3515 the parent of each patch before applying it, and will abort if the
3516 resulting changeset has a different ID than the one recorded in
3516 resulting changeset has a different ID than the one recorded in
3517 the patch. This may happen due to character set problems or other
3517 the patch. This may happen due to character set problems or other
3518 deficiencies in the text patch format.
3518 deficiencies in the text patch format.
3519
3519
3520 Use --bypass to apply and commit patches directly to the
3520 Use --bypass to apply and commit patches directly to the
3521 repository, not touching the working directory. Without --exact,
3521 repository, not touching the working directory. Without --exact,
3522 patches will be applied on top of the working directory parent
3522 patches will be applied on top of the working directory parent
3523 revision.
3523 revision.
3524
3524
3525 With -s/--similarity, hg will attempt to discover renames and
3525 With -s/--similarity, hg will attempt to discover renames and
3526 copies in the patch in the same way as :hg:`addremove`.
3526 copies in the patch in the same way as :hg:`addremove`.
3527
3527
3528 To read a patch from standard input, use "-" as the patch name. If
3528 To read a patch from standard input, use "-" as the patch name. If
3529 a URL is specified, the patch will be downloaded from it.
3529 a URL is specified, the patch will be downloaded from it.
3530 See :hg:`help dates` for a list of formats valid for -d/--date.
3530 See :hg:`help dates` for a list of formats valid for -d/--date.
3531
3531
3532 .. container:: verbose
3532 .. container:: verbose
3533
3533
3534 Examples:
3534 Examples:
3535
3535
3536 - import a traditional patch from a website and detect renames::
3536 - import a traditional patch from a website and detect renames::
3537
3537
3538 hg import -s 80 http://example.com/bugfix.patch
3538 hg import -s 80 http://example.com/bugfix.patch
3539
3539
3540 - import a changeset from an hgweb server::
3540 - import a changeset from an hgweb server::
3541
3541
3542 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3542 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3543
3543
3544 - import all the patches in an Unix-style mbox::
3544 - import all the patches in an Unix-style mbox::
3545
3545
3546 hg import incoming-patches.mbox
3546 hg import incoming-patches.mbox
3547
3547
3548 - attempt to exactly restore an exported changeset (not always
3548 - attempt to exactly restore an exported changeset (not always
3549 possible)::
3549 possible)::
3550
3550
3551 hg import --exact proposed-fix.patch
3551 hg import --exact proposed-fix.patch
3552
3552
3553 Returns 0 on success.
3553 Returns 0 on success.
3554 """
3554 """
3555
3555
3556 if not patch1:
3556 if not patch1:
3557 raise util.Abort(_('need at least one patch to import'))
3557 raise util.Abort(_('need at least one patch to import'))
3558
3558
3559 patches = (patch1,) + patches
3559 patches = (patch1,) + patches
3560
3560
3561 date = opts.get('date')
3561 date = opts.get('date')
3562 if date:
3562 if date:
3563 opts['date'] = util.parsedate(date)
3563 opts['date'] = util.parsedate(date)
3564
3564
3565 editor = cmdutil.commiteditor
3565 editor = cmdutil.commiteditor
3566 if opts.get('edit'):
3566 if opts.get('edit'):
3567 editor = cmdutil.commitforceeditor
3567 editor = cmdutil.commitforceeditor
3568
3568
3569 update = not opts.get('bypass')
3569 update = not opts.get('bypass')
3570 if not update and opts.get('no_commit'):
3570 if not update and opts.get('no_commit'):
3571 raise util.Abort(_('cannot use --no-commit with --bypass'))
3571 raise util.Abort(_('cannot use --no-commit with --bypass'))
3572 try:
3572 try:
3573 sim = float(opts.get('similarity') or 0)
3573 sim = float(opts.get('similarity') or 0)
3574 except ValueError:
3574 except ValueError:
3575 raise util.Abort(_('similarity must be a number'))
3575 raise util.Abort(_('similarity must be a number'))
3576 if sim < 0 or sim > 100:
3576 if sim < 0 or sim > 100:
3577 raise util.Abort(_('similarity must be between 0 and 100'))
3577 raise util.Abort(_('similarity must be between 0 and 100'))
3578 if sim and not update:
3578 if sim and not update:
3579 raise util.Abort(_('cannot use --similarity with --bypass'))
3579 raise util.Abort(_('cannot use --similarity with --bypass'))
3580
3580
3581 if (opts.get('exact') or not opts.get('force')) and update:
3581 if (opts.get('exact') or not opts.get('force')) and update:
3582 cmdutil.bailifchanged(repo)
3582 cmdutil.bailifchanged(repo)
3583
3583
3584 base = opts["base"]
3584 base = opts["base"]
3585 strip = opts["strip"]
3585 strip = opts["strip"]
3586 wlock = lock = tr = None
3586 wlock = lock = tr = None
3587 msgs = []
3587 msgs = []
3588
3588
3589 def checkexact(repo, n, nodeid):
3589 def checkexact(repo, n, nodeid):
3590 if opts.get('exact') and hex(n) != nodeid:
3590 if opts.get('exact') and hex(n) != nodeid:
3591 raise util.Abort(_('patch is damaged or loses information'))
3591 raise util.Abort(_('patch is damaged or loses information'))
3592
3592
3593 def tryone(ui, hunk, parents):
3593 def tryone(ui, hunk, parents):
3594 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3594 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3595 patch.extract(ui, hunk)
3595 patch.extract(ui, hunk)
3596
3596
3597 if not tmpname:
3597 if not tmpname:
3598 return (None, None)
3598 return (None, None)
3599 msg = _('applied to working directory')
3599 msg = _('applied to working directory')
3600
3600
3601 try:
3601 try:
3602 cmdline_message = cmdutil.logmessage(ui, opts)
3602 cmdline_message = cmdutil.logmessage(ui, opts)
3603 if cmdline_message:
3603 if cmdline_message:
3604 # pickup the cmdline msg
3604 # pickup the cmdline msg
3605 message = cmdline_message
3605 message = cmdline_message
3606 elif message:
3606 elif message:
3607 # pickup the patch msg
3607 # pickup the patch msg
3608 message = message.strip()
3608 message = message.strip()
3609 else:
3609 else:
3610 # launch the editor
3610 # launch the editor
3611 message = None
3611 message = None
3612 ui.debug('message:\n%s\n' % message)
3612 ui.debug('message:\n%s\n' % message)
3613
3613
3614 if len(parents) == 1:
3614 if len(parents) == 1:
3615 parents.append(repo[nullid])
3615 parents.append(repo[nullid])
3616 if opts.get('exact'):
3616 if opts.get('exact'):
3617 if not nodeid or not p1:
3617 if not nodeid or not p1:
3618 raise util.Abort(_('not a Mercurial patch'))
3618 raise util.Abort(_('not a Mercurial patch'))
3619 p1 = repo[p1]
3619 p1 = repo[p1]
3620 p2 = repo[p2 or nullid]
3620 p2 = repo[p2 or nullid]
3621 elif p2:
3621 elif p2:
3622 try:
3622 try:
3623 p1 = repo[p1]
3623 p1 = repo[p1]
3624 p2 = repo[p2]
3624 p2 = repo[p2]
3625 # Without any options, consider p2 only if the
3625 # Without any options, consider p2 only if the
3626 # patch is being applied on top of the recorded
3626 # patch is being applied on top of the recorded
3627 # first parent.
3627 # first parent.
3628 if p1 != parents[0]:
3628 if p1 != parents[0]:
3629 p1 = parents[0]
3629 p1 = parents[0]
3630 p2 = repo[nullid]
3630 p2 = repo[nullid]
3631 except error.RepoError:
3631 except error.RepoError:
3632 p1, p2 = parents
3632 p1, p2 = parents
3633 else:
3633 else:
3634 p1, p2 = parents
3634 p1, p2 = parents
3635
3635
3636 n = None
3636 n = None
3637 if update:
3637 if update:
3638 if p1 != parents[0]:
3638 if p1 != parents[0]:
3639 hg.clean(repo, p1.node())
3639 hg.clean(repo, p1.node())
3640 if p2 != parents[1]:
3640 if p2 != parents[1]:
3641 repo.setparents(p1.node(), p2.node())
3641 repo.setparents(p1.node(), p2.node())
3642
3642
3643 if opts.get('exact') or opts.get('import_branch'):
3643 if opts.get('exact') or opts.get('import_branch'):
3644 repo.dirstate.setbranch(branch or 'default')
3644 repo.dirstate.setbranch(branch or 'default')
3645
3645
3646 files = set()
3646 files = set()
3647 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3647 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3648 eolmode=None, similarity=sim / 100.0)
3648 eolmode=None, similarity=sim / 100.0)
3649 files = list(files)
3649 files = list(files)
3650 if opts.get('no_commit'):
3650 if opts.get('no_commit'):
3651 if message:
3651 if message:
3652 msgs.append(message)
3652 msgs.append(message)
3653 else:
3653 else:
3654 if opts.get('exact') or p2:
3654 if opts.get('exact') or p2:
3655 # If you got here, you either use --force and know what
3655 # If you got here, you either use --force and know what
3656 # you are doing or used --exact or a merge patch while
3656 # you are doing or used --exact or a merge patch while
3657 # being updated to its first parent.
3657 # being updated to its first parent.
3658 m = None
3658 m = None
3659 else:
3659 else:
3660 m = scmutil.matchfiles(repo, files or [])
3660 m = scmutil.matchfiles(repo, files or [])
3661 n = repo.commit(message, opts.get('user') or user,
3661 n = repo.commit(message, opts.get('user') or user,
3662 opts.get('date') or date, match=m,
3662 opts.get('date') or date, match=m,
3663 editor=editor)
3663 editor=editor)
3664 checkexact(repo, n, nodeid)
3664 checkexact(repo, n, nodeid)
3665 else:
3665 else:
3666 if opts.get('exact') or opts.get('import_branch'):
3666 if opts.get('exact') or opts.get('import_branch'):
3667 branch = branch or 'default'
3667 branch = branch or 'default'
3668 else:
3668 else:
3669 branch = p1.branch()
3669 branch = p1.branch()
3670 store = patch.filestore()
3670 store = patch.filestore()
3671 try:
3671 try:
3672 files = set()
3672 files = set()
3673 try:
3673 try:
3674 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3674 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3675 files, eolmode=None)
3675 files, eolmode=None)
3676 except patch.PatchError, e:
3676 except patch.PatchError, e:
3677 raise util.Abort(str(e))
3677 raise util.Abort(str(e))
3678 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3678 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3679 message,
3679 message,
3680 opts.get('user') or user,
3680 opts.get('user') or user,
3681 opts.get('date') or date,
3681 opts.get('date') or date,
3682 branch, files, store,
3682 branch, files, store,
3683 editor=cmdutil.commiteditor)
3683 editor=cmdutil.commiteditor)
3684 repo.savecommitmessage(memctx.description())
3684 repo.savecommitmessage(memctx.description())
3685 n = memctx.commit()
3685 n = memctx.commit()
3686 checkexact(repo, n, nodeid)
3686 checkexact(repo, n, nodeid)
3687 finally:
3687 finally:
3688 store.close()
3688 store.close()
3689 if n:
3689 if n:
3690 # i18n: refers to a short changeset id
3690 # i18n: refers to a short changeset id
3691 msg = _('created %s') % short(n)
3691 msg = _('created %s') % short(n)
3692 return (msg, n)
3692 return (msg, n)
3693 finally:
3693 finally:
3694 os.unlink(tmpname)
3694 os.unlink(tmpname)
3695
3695
3696 try:
3696 try:
3697 try:
3697 try:
3698 wlock = repo.wlock()
3698 wlock = repo.wlock()
3699 if not opts.get('no_commit'):
3699 if not opts.get('no_commit'):
3700 lock = repo.lock()
3700 lock = repo.lock()
3701 tr = repo.transaction('import')
3701 tr = repo.transaction('import')
3702 parents = repo.parents()
3702 parents = repo.parents()
3703 for patchurl in patches:
3703 for patchurl in patches:
3704 if patchurl == '-':
3704 if patchurl == '-':
3705 ui.status(_('applying patch from stdin\n'))
3705 ui.status(_('applying patch from stdin\n'))
3706 patchfile = ui.fin
3706 patchfile = ui.fin
3707 patchurl = 'stdin' # for error message
3707 patchurl = 'stdin' # for error message
3708 else:
3708 else:
3709 patchurl = os.path.join(base, patchurl)
3709 patchurl = os.path.join(base, patchurl)
3710 ui.status(_('applying %s\n') % patchurl)
3710 ui.status(_('applying %s\n') % patchurl)
3711 patchfile = hg.openpath(ui, patchurl)
3711 patchfile = hg.openpath(ui, patchurl)
3712
3712
3713 haspatch = False
3713 haspatch = False
3714 for hunk in patch.split(patchfile):
3714 for hunk in patch.split(patchfile):
3715 (msg, node) = tryone(ui, hunk, parents)
3715 (msg, node) = tryone(ui, hunk, parents)
3716 if msg:
3716 if msg:
3717 haspatch = True
3717 haspatch = True
3718 ui.note(msg + '\n')
3718 ui.note(msg + '\n')
3719 if update or opts.get('exact'):
3719 if update or opts.get('exact'):
3720 parents = repo.parents()
3720 parents = repo.parents()
3721 else:
3721 else:
3722 parents = [repo[node]]
3722 parents = [repo[node]]
3723
3723
3724 if not haspatch:
3724 if not haspatch:
3725 raise util.Abort(_('%s: no diffs found') % patchurl)
3725 raise util.Abort(_('%s: no diffs found') % patchurl)
3726
3726
3727 if tr:
3727 if tr:
3728 tr.close()
3728 tr.close()
3729 if msgs:
3729 if msgs:
3730 repo.savecommitmessage('\n* * *\n'.join(msgs))
3730 repo.savecommitmessage('\n* * *\n'.join(msgs))
3731 except: # re-raises
3731 except: # re-raises
3732 # wlock.release() indirectly calls dirstate.write(): since
3732 # wlock.release() indirectly calls dirstate.write(): since
3733 # we're crashing, we do not want to change the working dir
3733 # we're crashing, we do not want to change the working dir
3734 # parent after all, so make sure it writes nothing
3734 # parent after all, so make sure it writes nothing
3735 repo.dirstate.invalidate()
3735 repo.dirstate.invalidate()
3736 raise
3736 raise
3737 finally:
3737 finally:
3738 if tr:
3738 if tr:
3739 tr.release()
3739 tr.release()
3740 release(lock, wlock)
3740 release(lock, wlock)
3741
3741
3742 @command('incoming|in',
3742 @command('incoming|in',
3743 [('f', 'force', None,
3743 [('f', 'force', None,
3744 _('run even if remote repository is unrelated')),
3744 _('run even if remote repository is unrelated')),
3745 ('n', 'newest-first', None, _('show newest record first')),
3745 ('n', 'newest-first', None, _('show newest record first')),
3746 ('', 'bundle', '',
3746 ('', 'bundle', '',
3747 _('file to store the bundles into'), _('FILE')),
3747 _('file to store the bundles into'), _('FILE')),
3748 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3748 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3749 ('B', 'bookmarks', False, _("compare bookmarks")),
3749 ('B', 'bookmarks', False, _("compare bookmarks")),
3750 ('b', 'branch', [],
3750 ('b', 'branch', [],
3751 _('a specific branch you would like to pull'), _('BRANCH')),
3751 _('a specific branch you would like to pull'), _('BRANCH')),
3752 ] + logopts + remoteopts + subrepoopts,
3752 ] + logopts + remoteopts + subrepoopts,
3753 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3753 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3754 def incoming(ui, repo, source="default", **opts):
3754 def incoming(ui, repo, source="default", **opts):
3755 """show new changesets found in source
3755 """show new changesets found in source
3756
3756
3757 Show new changesets found in the specified path/URL or the default
3757 Show new changesets found in the specified path/URL or the default
3758 pull location. These are the changesets that would have been pulled
3758 pull location. These are the changesets that would have been pulled
3759 if a pull at the time you issued this command.
3759 if a pull at the time you issued this command.
3760
3760
3761 For remote repository, using --bundle avoids downloading the
3761 For remote repository, using --bundle avoids downloading the
3762 changesets twice if the incoming is followed by a pull.
3762 changesets twice if the incoming is followed by a pull.
3763
3763
3764 See pull for valid source format details.
3764 See pull for valid source format details.
3765
3765
3766 Returns 0 if there are incoming changes, 1 otherwise.
3766 Returns 0 if there are incoming changes, 1 otherwise.
3767 """
3767 """
3768 if opts.get('graph'):
3768 if opts.get('graph'):
3769 cmdutil.checkunsupportedgraphflags([], opts)
3769 cmdutil.checkunsupportedgraphflags([], opts)
3770 def display(other, chlist, displayer):
3770 def display(other, chlist, displayer):
3771 revdag = cmdutil.graphrevs(other, chlist, opts)
3771 revdag = cmdutil.graphrevs(other, chlist, opts)
3772 showparents = [ctx.node() for ctx in repo[None].parents()]
3772 showparents = [ctx.node() for ctx in repo[None].parents()]
3773 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3773 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3774 graphmod.asciiedges)
3774 graphmod.asciiedges)
3775
3775
3776 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3776 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3777 return 0
3777 return 0
3778
3778
3779 if opts.get('bundle') and opts.get('subrepos'):
3779 if opts.get('bundle') and opts.get('subrepos'):
3780 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3780 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3781
3781
3782 if opts.get('bookmarks'):
3782 if opts.get('bookmarks'):
3783 source, branches = hg.parseurl(ui.expandpath(source),
3783 source, branches = hg.parseurl(ui.expandpath(source),
3784 opts.get('branch'))
3784 opts.get('branch'))
3785 other = hg.peer(repo, opts, source)
3785 other = hg.peer(repo, opts, source)
3786 if 'bookmarks' not in other.listkeys('namespaces'):
3786 if 'bookmarks' not in other.listkeys('namespaces'):
3787 ui.warn(_("remote doesn't support bookmarks\n"))
3787 ui.warn(_("remote doesn't support bookmarks\n"))
3788 return 0
3788 return 0
3789 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3789 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3790 return bookmarks.diff(ui, repo, other)
3790 return bookmarks.diff(ui, repo, other)
3791
3791
3792 repo._subtoppath = ui.expandpath(source)
3792 repo._subtoppath = ui.expandpath(source)
3793 try:
3793 try:
3794 return hg.incoming(ui, repo, source, opts)
3794 return hg.incoming(ui, repo, source, opts)
3795 finally:
3795 finally:
3796 del repo._subtoppath
3796 del repo._subtoppath
3797
3797
3798
3798
3799 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3799 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3800 def init(ui, dest=".", **opts):
3800 def init(ui, dest=".", **opts):
3801 """create a new repository in the given directory
3801 """create a new repository in the given directory
3802
3802
3803 Initialize a new repository in the given directory. If the given
3803 Initialize a new repository in the given directory. If the given
3804 directory does not exist, it will be created.
3804 directory does not exist, it will be created.
3805
3805
3806 If no directory is given, the current directory is used.
3806 If no directory is given, the current directory is used.
3807
3807
3808 It is possible to specify an ``ssh://`` URL as the destination.
3808 It is possible to specify an ``ssh://`` URL as the destination.
3809 See :hg:`help urls` for more information.
3809 See :hg:`help urls` for more information.
3810
3810
3811 Returns 0 on success.
3811 Returns 0 on success.
3812 """
3812 """
3813 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3813 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3814
3814
3815 @command('locate',
3815 @command('locate',
3816 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3816 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3817 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3817 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3818 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3818 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3819 ] + walkopts,
3819 ] + walkopts,
3820 _('[OPTION]... [PATTERN]...'))
3820 _('[OPTION]... [PATTERN]...'))
3821 def locate(ui, repo, *pats, **opts):
3821 def locate(ui, repo, *pats, **opts):
3822 """locate files matching specific patterns
3822 """locate files matching specific patterns
3823
3823
3824 Print files under Mercurial control in the working directory whose
3824 Print files under Mercurial control in the working directory whose
3825 names match the given patterns.
3825 names match the given patterns.
3826
3826
3827 By default, this command searches all directories in the working
3827 By default, this command searches all directories in the working
3828 directory. To search just the current directory and its
3828 directory. To search just the current directory and its
3829 subdirectories, use "--include .".
3829 subdirectories, use "--include .".
3830
3830
3831 If no patterns are given to match, this command prints the names
3831 If no patterns are given to match, this command prints the names
3832 of all files under Mercurial control in the working directory.
3832 of all files under Mercurial control in the working directory.
3833
3833
3834 If you want to feed the output of this command into the "xargs"
3834 If you want to feed the output of this command into the "xargs"
3835 command, use the -0 option to both this command and "xargs". This
3835 command, use the -0 option to both this command and "xargs". This
3836 will avoid the problem of "xargs" treating single filenames that
3836 will avoid the problem of "xargs" treating single filenames that
3837 contain whitespace as multiple filenames.
3837 contain whitespace as multiple filenames.
3838
3838
3839 Returns 0 if a match is found, 1 otherwise.
3839 Returns 0 if a match is found, 1 otherwise.
3840 """
3840 """
3841 end = opts.get('print0') and '\0' or '\n'
3841 end = opts.get('print0') and '\0' or '\n'
3842 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3842 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3843
3843
3844 ret = 1
3844 ret = 1
3845 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3845 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3846 m.bad = lambda x, y: False
3846 m.bad = lambda x, y: False
3847 for abs in repo[rev].walk(m):
3847 for abs in repo[rev].walk(m):
3848 if not rev and abs not in repo.dirstate:
3848 if not rev and abs not in repo.dirstate:
3849 continue
3849 continue
3850 if opts.get('fullpath'):
3850 if opts.get('fullpath'):
3851 ui.write(repo.wjoin(abs), end)
3851 ui.write(repo.wjoin(abs), end)
3852 else:
3852 else:
3853 ui.write(((pats and m.rel(abs)) or abs), end)
3853 ui.write(((pats and m.rel(abs)) or abs), end)
3854 ret = 0
3854 ret = 0
3855
3855
3856 return ret
3856 return ret
3857
3857
3858 @command('^log|history',
3858 @command('^log|history',
3859 [('f', 'follow', None,
3859 [('f', 'follow', None,
3860 _('follow changeset history, or file history across copies and renames')),
3860 _('follow changeset history, or file history across copies and renames')),
3861 ('', 'follow-first', None,
3861 ('', 'follow-first', None,
3862 _('only follow the first parent of merge changesets (DEPRECATED)')),
3862 _('only follow the first parent of merge changesets (DEPRECATED)')),
3863 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3863 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3864 ('C', 'copies', None, _('show copied files')),
3864 ('C', 'copies', None, _('show copied files')),
3865 ('k', 'keyword', [],
3865 ('k', 'keyword', [],
3866 _('do case-insensitive search for a given text'), _('TEXT')),
3866 _('do case-insensitive search for a given text'), _('TEXT')),
3867 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3867 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3868 ('', 'removed', None, _('include revisions where files were removed')),
3868 ('', 'removed', None, _('include revisions where files were removed')),
3869 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3869 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3870 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3870 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3871 ('', 'only-branch', [],
3871 ('', 'only-branch', [],
3872 _('show only changesets within the given named branch (DEPRECATED)'),
3872 _('show only changesets within the given named branch (DEPRECATED)'),
3873 _('BRANCH')),
3873 _('BRANCH')),
3874 ('b', 'branch', [],
3874 ('b', 'branch', [],
3875 _('show changesets within the given named branch'), _('BRANCH')),
3875 _('show changesets within the given named branch'), _('BRANCH')),
3876 ('P', 'prune', [],
3876 ('P', 'prune', [],
3877 _('do not display revision or any of its ancestors'), _('REV')),
3877 _('do not display revision or any of its ancestors'), _('REV')),
3878 ] + logopts + walkopts,
3878 ] + logopts + walkopts,
3879 _('[OPTION]... [FILE]'))
3879 _('[OPTION]... [FILE]'))
3880 def log(ui, repo, *pats, **opts):
3880 def log(ui, repo, *pats, **opts):
3881 """show revision history of entire repository or files
3881 """show revision history of entire repository or files
3882
3882
3883 Print the revision history of the specified files or the entire
3883 Print the revision history of the specified files or the entire
3884 project.
3884 project.
3885
3885
3886 If no revision range is specified, the default is ``tip:0`` unless
3886 If no revision range is specified, the default is ``tip:0`` unless
3887 --follow is set, in which case the working directory parent is
3887 --follow is set, in which case the working directory parent is
3888 used as the starting revision.
3888 used as the starting revision.
3889
3889
3890 File history is shown without following rename or copy history of
3890 File history is shown without following rename or copy history of
3891 files. Use -f/--follow with a filename to follow history across
3891 files. Use -f/--follow with a filename to follow history across
3892 renames and copies. --follow without a filename will only show
3892 renames and copies. --follow without a filename will only show
3893 ancestors or descendants of the starting revision.
3893 ancestors or descendants of the starting revision.
3894
3894
3895 By default this command prints revision number and changeset id,
3895 By default this command prints revision number and changeset id,
3896 tags, non-trivial parents, user, date and time, and a summary for
3896 tags, non-trivial parents, user, date and time, and a summary for
3897 each commit. When the -v/--verbose switch is used, the list of
3897 each commit. When the -v/--verbose switch is used, the list of
3898 changed files and full commit message are shown.
3898 changed files and full commit message are shown.
3899
3899
3900 .. note::
3900 .. note::
3901 log -p/--patch may generate unexpected diff output for merge
3901 log -p/--patch may generate unexpected diff output for merge
3902 changesets, as it will only compare the merge changeset against
3902 changesets, as it will only compare the merge changeset against
3903 its first parent. Also, only files different from BOTH parents
3903 its first parent. Also, only files different from BOTH parents
3904 will appear in files:.
3904 will appear in files:.
3905
3905
3906 .. note::
3906 .. note::
3907 for performance reasons, log FILE may omit duplicate changes
3907 for performance reasons, log FILE may omit duplicate changes
3908 made on branches and will not show deletions. To see all
3908 made on branches and will not show deletions. To see all
3909 changes including duplicates and deletions, use the --removed
3909 changes including duplicates and deletions, use the --removed
3910 switch.
3910 switch.
3911
3911
3912 .. container:: verbose
3912 .. container:: verbose
3913
3913
3914 Some examples:
3914 Some examples:
3915
3915
3916 - changesets with full descriptions and file lists::
3916 - changesets with full descriptions and file lists::
3917
3917
3918 hg log -v
3918 hg log -v
3919
3919
3920 - changesets ancestral to the working directory::
3920 - changesets ancestral to the working directory::
3921
3921
3922 hg log -f
3922 hg log -f
3923
3923
3924 - last 10 commits on the current branch::
3924 - last 10 commits on the current branch::
3925
3925
3926 hg log -l 10 -b .
3926 hg log -l 10 -b .
3927
3927
3928 - changesets showing all modifications of a file, including removals::
3928 - changesets showing all modifications of a file, including removals::
3929
3929
3930 hg log --removed file.c
3930 hg log --removed file.c
3931
3931
3932 - all changesets that touch a directory, with diffs, excluding merges::
3932 - all changesets that touch a directory, with diffs, excluding merges::
3933
3933
3934 hg log -Mp lib/
3934 hg log -Mp lib/
3935
3935
3936 - all revision numbers that match a keyword::
3936 - all revision numbers that match a keyword::
3937
3937
3938 hg log -k bug --template "{rev}\\n"
3938 hg log -k bug --template "{rev}\\n"
3939
3939
3940 - check if a given changeset is included is a tagged release::
3940 - check if a given changeset is included is a tagged release::
3941
3941
3942 hg log -r "a21ccf and ancestor(1.9)"
3942 hg log -r "a21ccf and ancestor(1.9)"
3943
3943
3944 - find all changesets by some user in a date range::
3944 - find all changesets by some user in a date range::
3945
3945
3946 hg log -k alice -d "may 2008 to jul 2008"
3946 hg log -k alice -d "may 2008 to jul 2008"
3947
3947
3948 - summary of all changesets after the last tag::
3948 - summary of all changesets after the last tag::
3949
3949
3950 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3950 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3951
3951
3952 See :hg:`help dates` for a list of formats valid for -d/--date.
3952 See :hg:`help dates` for a list of formats valid for -d/--date.
3953
3953
3954 See :hg:`help revisions` and :hg:`help revsets` for more about
3954 See :hg:`help revisions` and :hg:`help revsets` for more about
3955 specifying revisions.
3955 specifying revisions.
3956
3956
3957 See :hg:`help templates` for more about pre-packaged styles and
3957 See :hg:`help templates` for more about pre-packaged styles and
3958 specifying custom templates.
3958 specifying custom templates.
3959
3959
3960 Returns 0 on success.
3960 Returns 0 on success.
3961 """
3961 """
3962 if opts.get('graph'):
3962 if opts.get('graph'):
3963 return cmdutil.graphlog(ui, repo, *pats, **opts)
3963 return cmdutil.graphlog(ui, repo, *pats, **opts)
3964
3964
3965 matchfn = scmutil.match(repo[None], pats, opts)
3965 matchfn = scmutil.match(repo[None], pats, opts)
3966 limit = cmdutil.loglimit(opts)
3966 limit = cmdutil.loglimit(opts)
3967 count = 0
3967 count = 0
3968
3968
3969 getrenamed, endrev = None, None
3969 getrenamed, endrev = None, None
3970 if opts.get('copies'):
3970 if opts.get('copies'):
3971 if opts.get('rev'):
3971 if opts.get('rev'):
3972 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3972 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3973 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3973 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3974
3974
3975 df = False
3975 df = False
3976 if opts.get("date"):
3976 if opts.get("date"):
3977 df = util.matchdate(opts["date"])
3977 df = util.matchdate(opts["date"])
3978
3978
3979 branches = opts.get('branch', []) + opts.get('only_branch', [])
3979 branches = opts.get('branch', []) + opts.get('only_branch', [])
3980 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3980 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3981
3981
3982 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3982 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3983 def prep(ctx, fns):
3983 def prep(ctx, fns):
3984 rev = ctx.rev()
3984 rev = ctx.rev()
3985 parents = [p for p in repo.changelog.parentrevs(rev)
3985 parents = [p for p in repo.changelog.parentrevs(rev)
3986 if p != nullrev]
3986 if p != nullrev]
3987 if opts.get('no_merges') and len(parents) == 2:
3987 if opts.get('no_merges') and len(parents) == 2:
3988 return
3988 return
3989 if opts.get('only_merges') and len(parents) != 2:
3989 if opts.get('only_merges') and len(parents) != 2:
3990 return
3990 return
3991 if opts.get('branch') and ctx.branch() not in opts['branch']:
3991 if opts.get('branch') and ctx.branch() not in opts['branch']:
3992 return
3992 return
3993 if df and not df(ctx.date()[0]):
3993 if df and not df(ctx.date()[0]):
3994 return
3994 return
3995
3995
3996 lower = encoding.lower
3996 lower = encoding.lower
3997 if opts.get('user'):
3997 if opts.get('user'):
3998 luser = lower(ctx.user())
3998 luser = lower(ctx.user())
3999 for k in [lower(x) for x in opts['user']]:
3999 for k in [lower(x) for x in opts['user']]:
4000 if (k in luser):
4000 if (k in luser):
4001 break
4001 break
4002 else:
4002 else:
4003 return
4003 return
4004 if opts.get('keyword'):
4004 if opts.get('keyword'):
4005 luser = lower(ctx.user())
4005 luser = lower(ctx.user())
4006 ldesc = lower(ctx.description())
4006 ldesc = lower(ctx.description())
4007 lfiles = lower(" ".join(ctx.files()))
4007 lfiles = lower(" ".join(ctx.files()))
4008 for k in [lower(x) for x in opts['keyword']]:
4008 for k in [lower(x) for x in opts['keyword']]:
4009 if (k in luser or k in ldesc or k in lfiles):
4009 if (k in luser or k in ldesc or k in lfiles):
4010 break
4010 break
4011 else:
4011 else:
4012 return
4012 return
4013
4013
4014 copies = None
4014 copies = None
4015 if getrenamed is not None and rev:
4015 if getrenamed is not None and rev:
4016 copies = []
4016 copies = []
4017 for fn in ctx.files():
4017 for fn in ctx.files():
4018 rename = getrenamed(fn, rev)
4018 rename = getrenamed(fn, rev)
4019 if rename:
4019 if rename:
4020 copies.append((fn, rename[0]))
4020 copies.append((fn, rename[0]))
4021
4021
4022 revmatchfn = None
4022 revmatchfn = None
4023 if opts.get('patch') or opts.get('stat'):
4023 if opts.get('patch') or opts.get('stat'):
4024 if opts.get('follow') or opts.get('follow_first'):
4024 if opts.get('follow') or opts.get('follow_first'):
4025 # note: this might be wrong when following through merges
4025 # note: this might be wrong when following through merges
4026 revmatchfn = scmutil.match(repo[None], fns, default='path')
4026 revmatchfn = scmutil.match(repo[None], fns, default='path')
4027 else:
4027 else:
4028 revmatchfn = matchfn
4028 revmatchfn = matchfn
4029
4029
4030 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4030 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4031
4031
4032 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4032 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4033 if displayer.flush(ctx.rev()):
4033 if displayer.flush(ctx.rev()):
4034 count += 1
4034 count += 1
4035 if count == limit:
4035 if count == limit:
4036 break
4036 break
4037 displayer.close()
4037 displayer.close()
4038
4038
4039 @command('manifest',
4039 @command('manifest',
4040 [('r', 'rev', '', _('revision to display'), _('REV')),
4040 [('r', 'rev', '', _('revision to display'), _('REV')),
4041 ('', 'all', False, _("list files from all revisions"))],
4041 ('', 'all', False, _("list files from all revisions"))],
4042 _('[-r REV]'))
4042 _('[-r REV]'))
4043 def manifest(ui, repo, node=None, rev=None, **opts):
4043 def manifest(ui, repo, node=None, rev=None, **opts):
4044 """output the current or given revision of the project manifest
4044 """output the current or given revision of the project manifest
4045
4045
4046 Print a list of version controlled files for the given revision.
4046 Print a list of version controlled files for the given revision.
4047 If no revision is given, the first parent of the working directory
4047 If no revision is given, the first parent of the working directory
4048 is used, or the null revision if no revision is checked out.
4048 is used, or the null revision if no revision is checked out.
4049
4049
4050 With -v, print file permissions, symlink and executable bits.
4050 With -v, print file permissions, symlink and executable bits.
4051 With --debug, print file revision hashes.
4051 With --debug, print file revision hashes.
4052
4052
4053 If option --all is specified, the list of all files from all revisions
4053 If option --all is specified, the list of all files from all revisions
4054 is printed. This includes deleted and renamed files.
4054 is printed. This includes deleted and renamed files.
4055
4055
4056 Returns 0 on success.
4056 Returns 0 on success.
4057 """
4057 """
4058
4058
4059 fm = ui.formatter('manifest', opts)
4059 fm = ui.formatter('manifest', opts)
4060
4060
4061 if opts.get('all'):
4061 if opts.get('all'):
4062 if rev or node:
4062 if rev or node:
4063 raise util.Abort(_("can't specify a revision with --all"))
4063 raise util.Abort(_("can't specify a revision with --all"))
4064
4064
4065 res = []
4065 res = []
4066 prefix = "data/"
4066 prefix = "data/"
4067 suffix = ".i"
4067 suffix = ".i"
4068 plen = len(prefix)
4068 plen = len(prefix)
4069 slen = len(suffix)
4069 slen = len(suffix)
4070 lock = repo.lock()
4070 lock = repo.lock()
4071 try:
4071 try:
4072 for fn, b, size in repo.store.datafiles():
4072 for fn, b, size in repo.store.datafiles():
4073 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4073 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4074 res.append(fn[plen:-slen])
4074 res.append(fn[plen:-slen])
4075 finally:
4075 finally:
4076 lock.release()
4076 lock.release()
4077 for f in res:
4077 for f in res:
4078 fm.startitem()
4078 fm.startitem()
4079 fm.write("path", '%s\n', f)
4079 fm.write("path", '%s\n', f)
4080 fm.end()
4080 fm.end()
4081 return
4081 return
4082
4082
4083 if rev and node:
4083 if rev and node:
4084 raise util.Abort(_("please specify just one revision"))
4084 raise util.Abort(_("please specify just one revision"))
4085
4085
4086 if not node:
4086 if not node:
4087 node = rev
4087 node = rev
4088
4088
4089 char = {'l': '@', 'x': '*', '': ''}
4089 char = {'l': '@', 'x': '*', '': ''}
4090 mode = {'l': '644', 'x': '755', '': '644'}
4090 mode = {'l': '644', 'x': '755', '': '644'}
4091 ctx = scmutil.revsingle(repo, node)
4091 ctx = scmutil.revsingle(repo, node)
4092 mf = ctx.manifest()
4092 mf = ctx.manifest()
4093 for f in ctx:
4093 for f in ctx:
4094 fm.startitem()
4094 fm.startitem()
4095 fl = ctx[f].flags()
4095 fl = ctx[f].flags()
4096 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4096 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4097 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4097 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4098 fm.write('path', '%s\n', f)
4098 fm.write('path', '%s\n', f)
4099 fm.end()
4099 fm.end()
4100
4100
4101 @command('^merge',
4101 @command('^merge',
4102 [('f', 'force', None, _('force a merge with outstanding changes')),
4102 [('f', 'force', None, _('force a merge with outstanding changes')),
4103 ('r', 'rev', '', _('revision to merge'), _('REV')),
4103 ('r', 'rev', '', _('revision to merge'), _('REV')),
4104 ('P', 'preview', None,
4104 ('P', 'preview', None,
4105 _('review revisions to merge (no merge is performed)'))
4105 _('review revisions to merge (no merge is performed)'))
4106 ] + mergetoolopts,
4106 ] + mergetoolopts,
4107 _('[-P] [-f] [[-r] REV]'))
4107 _('[-P] [-f] [[-r] REV]'))
4108 def merge(ui, repo, node=None, **opts):
4108 def merge(ui, repo, node=None, **opts):
4109 """merge working directory with another revision
4109 """merge working directory with another revision
4110
4110
4111 The current working directory is updated with all changes made in
4111 The current working directory is updated with all changes made in
4112 the requested revision since the last common predecessor revision.
4112 the requested revision since the last common predecessor revision.
4113
4113
4114 Files that changed between either parent are marked as changed for
4114 Files that changed between either parent are marked as changed for
4115 the next commit and a commit must be performed before any further
4115 the next commit and a commit must be performed before any further
4116 updates to the repository are allowed. The next commit will have
4116 updates to the repository are allowed. The next commit will have
4117 two parents.
4117 two parents.
4118
4118
4119 ``--tool`` can be used to specify the merge tool used for file
4119 ``--tool`` can be used to specify the merge tool used for file
4120 merges. It overrides the HGMERGE environment variable and your
4120 merges. It overrides the HGMERGE environment variable and your
4121 configuration files. See :hg:`help merge-tools` for options.
4121 configuration files. See :hg:`help merge-tools` for options.
4122
4122
4123 If no revision is specified, the working directory's parent is a
4123 If no revision is specified, the working directory's parent is a
4124 head revision, and the current branch contains exactly one other
4124 head revision, and the current branch contains exactly one other
4125 head, the other head is merged with by default. Otherwise, an
4125 head, the other head is merged with by default. Otherwise, an
4126 explicit revision with which to merge with must be provided.
4126 explicit revision with which to merge with must be provided.
4127
4127
4128 :hg:`resolve` must be used to resolve unresolved files.
4128 :hg:`resolve` must be used to resolve unresolved files.
4129
4129
4130 To undo an uncommitted merge, use :hg:`update --clean .` which
4130 To undo an uncommitted merge, use :hg:`update --clean .` which
4131 will check out a clean copy of the original merge parent, losing
4131 will check out a clean copy of the original merge parent, losing
4132 all changes.
4132 all changes.
4133
4133
4134 Returns 0 on success, 1 if there are unresolved files.
4134 Returns 0 on success, 1 if there are unresolved files.
4135 """
4135 """
4136
4136
4137 if opts.get('rev') and node:
4137 if opts.get('rev') and node:
4138 raise util.Abort(_("please specify just one revision"))
4138 raise util.Abort(_("please specify just one revision"))
4139 if not node:
4139 if not node:
4140 node = opts.get('rev')
4140 node = opts.get('rev')
4141
4141
4142 if node:
4142 if node:
4143 node = scmutil.revsingle(repo, node).node()
4143 node = scmutil.revsingle(repo, node).node()
4144
4144
4145 if not node and repo._bookmarkcurrent:
4145 if not node and repo._bookmarkcurrent:
4146 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4146 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4147 curhead = repo[repo._bookmarkcurrent].node()
4147 curhead = repo[repo._bookmarkcurrent].node()
4148 if len(bmheads) == 2:
4148 if len(bmheads) == 2:
4149 if curhead == bmheads[0]:
4149 if curhead == bmheads[0]:
4150 node = bmheads[1]
4150 node = bmheads[1]
4151 else:
4151 else:
4152 node = bmheads[0]
4152 node = bmheads[0]
4153 elif len(bmheads) > 2:
4153 elif len(bmheads) > 2:
4154 raise util.Abort(_("multiple matching bookmarks to merge - "
4154 raise util.Abort(_("multiple matching bookmarks to merge - "
4155 "please merge with an explicit rev or bookmark"),
4155 "please merge with an explicit rev or bookmark"),
4156 hint=_("run 'hg heads' to see all heads"))
4156 hint=_("run 'hg heads' to see all heads"))
4157 elif len(bmheads) <= 1:
4157 elif len(bmheads) <= 1:
4158 raise util.Abort(_("no matching bookmark to merge - "
4158 raise util.Abort(_("no matching bookmark to merge - "
4159 "please merge with an explicit rev or bookmark"),
4159 "please merge with an explicit rev or bookmark"),
4160 hint=_("run 'hg heads' to see all heads"))
4160 hint=_("run 'hg heads' to see all heads"))
4161
4161
4162 if not node and not repo._bookmarkcurrent:
4162 if not node and not repo._bookmarkcurrent:
4163 branch = repo[None].branch()
4163 branch = repo[None].branch()
4164 bheads = repo.branchheads(branch)
4164 bheads = repo.branchheads(branch)
4165 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4165 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4166
4166
4167 if len(nbhs) > 2:
4167 if len(nbhs) > 2:
4168 raise util.Abort(_("branch '%s' has %d heads - "
4168 raise util.Abort(_("branch '%s' has %d heads - "
4169 "please merge with an explicit rev")
4169 "please merge with an explicit rev")
4170 % (branch, len(bheads)),
4170 % (branch, len(bheads)),
4171 hint=_("run 'hg heads .' to see heads"))
4171 hint=_("run 'hg heads .' to see heads"))
4172
4172
4173 parent = repo.dirstate.p1()
4173 parent = repo.dirstate.p1()
4174 if len(nbhs) <= 1:
4174 if len(nbhs) <= 1:
4175 if len(bheads) > 1:
4175 if len(bheads) > 1:
4176 raise util.Abort(_("heads are bookmarked - "
4176 raise util.Abort(_("heads are bookmarked - "
4177 "please merge with an explicit rev"),
4177 "please merge with an explicit rev"),
4178 hint=_("run 'hg heads' to see all heads"))
4178 hint=_("run 'hg heads' to see all heads"))
4179 if len(repo.heads()) > 1:
4179 if len(repo.heads()) > 1:
4180 raise util.Abort(_("branch '%s' has one head - "
4180 raise util.Abort(_("branch '%s' has one head - "
4181 "please merge with an explicit rev")
4181 "please merge with an explicit rev")
4182 % branch,
4182 % branch,
4183 hint=_("run 'hg heads' to see all heads"))
4183 hint=_("run 'hg heads' to see all heads"))
4184 msg, hint = _('nothing to merge'), None
4184 msg, hint = _('nothing to merge'), None
4185 if parent != repo.lookup(branch):
4185 if parent != repo.lookup(branch):
4186 hint = _("use 'hg update' instead")
4186 hint = _("use 'hg update' instead")
4187 raise util.Abort(msg, hint=hint)
4187 raise util.Abort(msg, hint=hint)
4188
4188
4189 if parent not in bheads:
4189 if parent not in bheads:
4190 raise util.Abort(_('working directory not at a head revision'),
4190 raise util.Abort(_('working directory not at a head revision'),
4191 hint=_("use 'hg update' or merge with an "
4191 hint=_("use 'hg update' or merge with an "
4192 "explicit revision"))
4192 "explicit revision"))
4193 if parent == nbhs[0]:
4193 if parent == nbhs[0]:
4194 node = nbhs[-1]
4194 node = nbhs[-1]
4195 else:
4195 else:
4196 node = nbhs[0]
4196 node = nbhs[0]
4197
4197
4198 if opts.get('preview'):
4198 if opts.get('preview'):
4199 # find nodes that are ancestors of p2 but not of p1
4199 # find nodes that are ancestors of p2 but not of p1
4200 p1 = repo.lookup('.')
4200 p1 = repo.lookup('.')
4201 p2 = repo.lookup(node)
4201 p2 = repo.lookup(node)
4202 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4202 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4203
4203
4204 displayer = cmdutil.show_changeset(ui, repo, opts)
4204 displayer = cmdutil.show_changeset(ui, repo, opts)
4205 for node in nodes:
4205 for node in nodes:
4206 displayer.show(repo[node])
4206 displayer.show(repo[node])
4207 displayer.close()
4207 displayer.close()
4208 return 0
4208 return 0
4209
4209
4210 try:
4210 try:
4211 # ui.forcemerge is an internal variable, do not document
4211 # ui.forcemerge is an internal variable, do not document
4212 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4212 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4213 return hg.merge(repo, node, force=opts.get('force'))
4213 return hg.merge(repo, node, force=opts.get('force'))
4214 finally:
4214 finally:
4215 ui.setconfig('ui', 'forcemerge', '')
4215 ui.setconfig('ui', 'forcemerge', '')
4216
4216
4217 @command('outgoing|out',
4217 @command('outgoing|out',
4218 [('f', 'force', None, _('run even when the destination is unrelated')),
4218 [('f', 'force', None, _('run even when the destination is unrelated')),
4219 ('r', 'rev', [],
4219 ('r', 'rev', [],
4220 _('a changeset intended to be included in the destination'), _('REV')),
4220 _('a changeset intended to be included in the destination'), _('REV')),
4221 ('n', 'newest-first', None, _('show newest record first')),
4221 ('n', 'newest-first', None, _('show newest record first')),
4222 ('B', 'bookmarks', False, _('compare bookmarks')),
4222 ('B', 'bookmarks', False, _('compare bookmarks')),
4223 ('b', 'branch', [], _('a specific branch you would like to push'),
4223 ('b', 'branch', [], _('a specific branch you would like to push'),
4224 _('BRANCH')),
4224 _('BRANCH')),
4225 ] + logopts + remoteopts + subrepoopts,
4225 ] + logopts + remoteopts + subrepoopts,
4226 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4226 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4227 def outgoing(ui, repo, dest=None, **opts):
4227 def outgoing(ui, repo, dest=None, **opts):
4228 """show changesets not found in the destination
4228 """show changesets not found in the destination
4229
4229
4230 Show changesets not found in the specified destination repository
4230 Show changesets not found in the specified destination repository
4231 or the default push location. These are the changesets that would
4231 or the default push location. These are the changesets that would
4232 be pushed if a push was requested.
4232 be pushed if a push was requested.
4233
4233
4234 See pull for details of valid destination formats.
4234 See pull for details of valid destination formats.
4235
4235
4236 Returns 0 if there are outgoing changes, 1 otherwise.
4236 Returns 0 if there are outgoing changes, 1 otherwise.
4237 """
4237 """
4238 if opts.get('graph'):
4238 if opts.get('graph'):
4239 cmdutil.checkunsupportedgraphflags([], opts)
4239 cmdutil.checkunsupportedgraphflags([], opts)
4240 o = hg._outgoing(ui, repo, dest, opts)
4240 o = hg._outgoing(ui, repo, dest, opts)
4241 if o is None:
4241 if o is None:
4242 return
4242 return
4243
4243
4244 revdag = cmdutil.graphrevs(repo, o, opts)
4244 revdag = cmdutil.graphrevs(repo, o, opts)
4245 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4245 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4246 showparents = [ctx.node() for ctx in repo[None].parents()]
4246 showparents = [ctx.node() for ctx in repo[None].parents()]
4247 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4247 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4248 graphmod.asciiedges)
4248 graphmod.asciiedges)
4249 return 0
4249 return 0
4250
4250
4251 if opts.get('bookmarks'):
4251 if opts.get('bookmarks'):
4252 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4252 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4253 dest, branches = hg.parseurl(dest, opts.get('branch'))
4253 dest, branches = hg.parseurl(dest, opts.get('branch'))
4254 other = hg.peer(repo, opts, dest)
4254 other = hg.peer(repo, opts, dest)
4255 if 'bookmarks' not in other.listkeys('namespaces'):
4255 if 'bookmarks' not in other.listkeys('namespaces'):
4256 ui.warn(_("remote doesn't support bookmarks\n"))
4256 ui.warn(_("remote doesn't support bookmarks\n"))
4257 return 0
4257 return 0
4258 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4258 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4259 return bookmarks.diff(ui, other, repo)
4259 return bookmarks.diff(ui, other, repo)
4260
4260
4261 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4261 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4262 try:
4262 try:
4263 return hg.outgoing(ui, repo, dest, opts)
4263 return hg.outgoing(ui, repo, dest, opts)
4264 finally:
4264 finally:
4265 del repo._subtoppath
4265 del repo._subtoppath
4266
4266
4267 @command('parents',
4267 @command('parents',
4268 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4268 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4269 ] + templateopts,
4269 ] + templateopts,
4270 _('[-r REV] [FILE]'))
4270 _('[-r REV] [FILE]'))
4271 def parents(ui, repo, file_=None, **opts):
4271 def parents(ui, repo, file_=None, **opts):
4272 """show the parents of the working directory or revision
4272 """show the parents of the working directory or revision
4273
4273
4274 Print the working directory's parent revisions. If a revision is
4274 Print the working directory's parent revisions. If a revision is
4275 given via -r/--rev, the parent of that revision will be printed.
4275 given via -r/--rev, the parent of that revision will be printed.
4276 If a file argument is given, the revision in which the file was
4276 If a file argument is given, the revision in which the file was
4277 last changed (before the working directory revision or the
4277 last changed (before the working directory revision or the
4278 argument to --rev if given) is printed.
4278 argument to --rev if given) is printed.
4279
4279
4280 Returns 0 on success.
4280 Returns 0 on success.
4281 """
4281 """
4282
4282
4283 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4283 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4284
4284
4285 if file_:
4285 if file_:
4286 m = scmutil.match(ctx, (file_,), opts)
4286 m = scmutil.match(ctx, (file_,), opts)
4287 if m.anypats() or len(m.files()) != 1:
4287 if m.anypats() or len(m.files()) != 1:
4288 raise util.Abort(_('can only specify an explicit filename'))
4288 raise util.Abort(_('can only specify an explicit filename'))
4289 file_ = m.files()[0]
4289 file_ = m.files()[0]
4290 filenodes = []
4290 filenodes = []
4291 for cp in ctx.parents():
4291 for cp in ctx.parents():
4292 if not cp:
4292 if not cp:
4293 continue
4293 continue
4294 try:
4294 try:
4295 filenodes.append(cp.filenode(file_))
4295 filenodes.append(cp.filenode(file_))
4296 except error.LookupError:
4296 except error.LookupError:
4297 pass
4297 pass
4298 if not filenodes:
4298 if not filenodes:
4299 raise util.Abort(_("'%s' not found in manifest!") % file_)
4299 raise util.Abort(_("'%s' not found in manifest!") % file_)
4300 fl = repo.file(file_)
4300 fl = repo.file(file_)
4301 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4301 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4302 else:
4302 else:
4303 p = [cp.node() for cp in ctx.parents()]
4303 p = [cp.node() for cp in ctx.parents()]
4304
4304
4305 displayer = cmdutil.show_changeset(ui, repo, opts)
4305 displayer = cmdutil.show_changeset(ui, repo, opts)
4306 for n in p:
4306 for n in p:
4307 if n != nullid:
4307 if n != nullid:
4308 displayer.show(repo[n])
4308 displayer.show(repo[n])
4309 displayer.close()
4309 displayer.close()
4310
4310
4311 @command('paths', [], _('[NAME]'))
4311 @command('paths', [], _('[NAME]'))
4312 def paths(ui, repo, search=None):
4312 def paths(ui, repo, search=None):
4313 """show aliases for remote repositories
4313 """show aliases for remote repositories
4314
4314
4315 Show definition of symbolic path name NAME. If no name is given,
4315 Show definition of symbolic path name NAME. If no name is given,
4316 show definition of all available names.
4316 show definition of all available names.
4317
4317
4318 Option -q/--quiet suppresses all output when searching for NAME
4318 Option -q/--quiet suppresses all output when searching for NAME
4319 and shows only the path names when listing all definitions.
4319 and shows only the path names when listing all definitions.
4320
4320
4321 Path names are defined in the [paths] section of your
4321 Path names are defined in the [paths] section of your
4322 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4322 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4323 repository, ``.hg/hgrc`` is used, too.
4323 repository, ``.hg/hgrc`` is used, too.
4324
4324
4325 The path names ``default`` and ``default-push`` have a special
4325 The path names ``default`` and ``default-push`` have a special
4326 meaning. When performing a push or pull operation, they are used
4326 meaning. When performing a push or pull operation, they are used
4327 as fallbacks if no location is specified on the command-line.
4327 as fallbacks if no location is specified on the command-line.
4328 When ``default-push`` is set, it will be used for push and
4328 When ``default-push`` is set, it will be used for push and
4329 ``default`` will be used for pull; otherwise ``default`` is used
4329 ``default`` will be used for pull; otherwise ``default`` is used
4330 as the fallback for both. When cloning a repository, the clone
4330 as the fallback for both. When cloning a repository, the clone
4331 source is written as ``default`` in ``.hg/hgrc``. Note that
4331 source is written as ``default`` in ``.hg/hgrc``. Note that
4332 ``default`` and ``default-push`` apply to all inbound (e.g.
4332 ``default`` and ``default-push`` apply to all inbound (e.g.
4333 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4333 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4334 :hg:`bundle`) operations.
4334 :hg:`bundle`) operations.
4335
4335
4336 See :hg:`help urls` for more information.
4336 See :hg:`help urls` for more information.
4337
4337
4338 Returns 0 on success.
4338 Returns 0 on success.
4339 """
4339 """
4340 if search:
4340 if search:
4341 for name, path in ui.configitems("paths"):
4341 for name, path in ui.configitems("paths"):
4342 if name == search:
4342 if name == search:
4343 ui.status("%s\n" % util.hidepassword(path))
4343 ui.status("%s\n" % util.hidepassword(path))
4344 return
4344 return
4345 if not ui.quiet:
4345 if not ui.quiet:
4346 ui.warn(_("not found!\n"))
4346 ui.warn(_("not found!\n"))
4347 return 1
4347 return 1
4348 else:
4348 else:
4349 for name, path in ui.configitems("paths"):
4349 for name, path in ui.configitems("paths"):
4350 if ui.quiet:
4350 if ui.quiet:
4351 ui.write("%s\n" % name)
4351 ui.write("%s\n" % name)
4352 else:
4352 else:
4353 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4353 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4354
4354
4355 @command('phase',
4355 @command('phase',
4356 [('p', 'public', False, _('set changeset phase to public')),
4356 [('p', 'public', False, _('set changeset phase to public')),
4357 ('d', 'draft', False, _('set changeset phase to draft')),
4357 ('d', 'draft', False, _('set changeset phase to draft')),
4358 ('s', 'secret', False, _('set changeset phase to secret')),
4358 ('s', 'secret', False, _('set changeset phase to secret')),
4359 ('f', 'force', False, _('allow to move boundary backward')),
4359 ('f', 'force', False, _('allow to move boundary backward')),
4360 ('r', 'rev', [], _('target revision'), _('REV')),
4360 ('r', 'rev', [], _('target revision'), _('REV')),
4361 ],
4361 ],
4362 _('[-p|-d|-s] [-f] [-r] REV...'))
4362 _('[-p|-d|-s] [-f] [-r] REV...'))
4363 def phase(ui, repo, *revs, **opts):
4363 def phase(ui, repo, *revs, **opts):
4364 """set or show the current phase name
4364 """set or show the current phase name
4365
4365
4366 With no argument, show the phase name of specified revisions.
4366 With no argument, show the phase name of specified revisions.
4367
4367
4368 With one of -p/--public, -d/--draft or -s/--secret, change the
4368 With one of -p/--public, -d/--draft or -s/--secret, change the
4369 phase value of the specified revisions.
4369 phase value of the specified revisions.
4370
4370
4371 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4371 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4372 lower phase to an higher phase. Phases are ordered as follows::
4372 lower phase to an higher phase. Phases are ordered as follows::
4373
4373
4374 public < draft < secret
4374 public < draft < secret
4375
4375
4376 Return 0 on success, 1 if no phases were changed or some could not
4376 Return 0 on success, 1 if no phases were changed or some could not
4377 be changed.
4377 be changed.
4378 """
4378 """
4379 # search for a unique phase argument
4379 # search for a unique phase argument
4380 targetphase = None
4380 targetphase = None
4381 for idx, name in enumerate(phases.phasenames):
4381 for idx, name in enumerate(phases.phasenames):
4382 if opts[name]:
4382 if opts[name]:
4383 if targetphase is not None:
4383 if targetphase is not None:
4384 raise util.Abort(_('only one phase can be specified'))
4384 raise util.Abort(_('only one phase can be specified'))
4385 targetphase = idx
4385 targetphase = idx
4386
4386
4387 # look for specified revision
4387 # look for specified revision
4388 revs = list(revs)
4388 revs = list(revs)
4389 revs.extend(opts['rev'])
4389 revs.extend(opts['rev'])
4390 if not revs:
4390 if not revs:
4391 raise util.Abort(_('no revisions specified'))
4391 raise util.Abort(_('no revisions specified'))
4392
4392
4393 revs = scmutil.revrange(repo, revs)
4393 revs = scmutil.revrange(repo, revs)
4394
4394
4395 lock = None
4395 lock = None
4396 ret = 0
4396 ret = 0
4397 if targetphase is None:
4397 if targetphase is None:
4398 # display
4398 # display
4399 for r in revs:
4399 for r in revs:
4400 ctx = repo[r]
4400 ctx = repo[r]
4401 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4401 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4402 else:
4402 else:
4403 lock = repo.lock()
4403 lock = repo.lock()
4404 try:
4404 try:
4405 # set phase
4405 # set phase
4406 if not revs:
4406 if not revs:
4407 raise util.Abort(_('empty revision set'))
4407 raise util.Abort(_('empty revision set'))
4408 nodes = [repo[r].node() for r in revs]
4408 nodes = [repo[r].node() for r in revs]
4409 olddata = repo._phasecache.getphaserevs(repo)[:]
4409 olddata = repo._phasecache.getphaserevs(repo)[:]
4410 phases.advanceboundary(repo, targetphase, nodes)
4410 phases.advanceboundary(repo, targetphase, nodes)
4411 if opts['force']:
4411 if opts['force']:
4412 phases.retractboundary(repo, targetphase, nodes)
4412 phases.retractboundary(repo, targetphase, nodes)
4413 finally:
4413 finally:
4414 lock.release()
4414 lock.release()
4415 # moving revision from public to draft may hide them
4415 # moving revision from public to draft may hide them
4416 # We have to check result on an unfiltered repository
4416 # We have to check result on an unfiltered repository
4417 unfi = repo.unfiltered()
4417 unfi = repo.unfiltered()
4418 newdata = repo._phasecache.getphaserevs(unfi)
4418 newdata = repo._phasecache.getphaserevs(unfi)
4419 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4419 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4420 cl = unfi.changelog
4420 cl = unfi.changelog
4421 rejected = [n for n in nodes
4421 rejected = [n for n in nodes
4422 if newdata[cl.rev(n)] < targetphase]
4422 if newdata[cl.rev(n)] < targetphase]
4423 if rejected:
4423 if rejected:
4424 ui.warn(_('cannot move %i changesets to a more permissive '
4424 ui.warn(_('cannot move %i changesets to a more permissive '
4425 'phase, use --force\n') % len(rejected))
4425 'phase, use --force\n') % len(rejected))
4426 ret = 1
4426 ret = 1
4427 if changes:
4427 if changes:
4428 msg = _('phase changed for %i changesets\n') % changes
4428 msg = _('phase changed for %i changesets\n') % changes
4429 if ret:
4429 if ret:
4430 ui.status(msg)
4430 ui.status(msg)
4431 else:
4431 else:
4432 ui.note(msg)
4432 ui.note(msg)
4433 else:
4433 else:
4434 ui.warn(_('no phases changed\n'))
4434 ui.warn(_('no phases changed\n'))
4435 ret = 1
4435 ret = 1
4436 return ret
4436 return ret
4437
4437
4438 def postincoming(ui, repo, modheads, optupdate, checkout):
4438 def postincoming(ui, repo, modheads, optupdate, checkout):
4439 if modheads == 0:
4439 if modheads == 0:
4440 return
4440 return
4441 if optupdate:
4441 if optupdate:
4442 movemarkfrom = repo['.'].node()
4442 movemarkfrom = repo['.'].node()
4443 try:
4443 try:
4444 ret = hg.update(repo, checkout)
4444 ret = hg.update(repo, checkout)
4445 except util.Abort, inst:
4445 except util.Abort, inst:
4446 ui.warn(_("not updating: %s\n") % str(inst))
4446 ui.warn(_("not updating: %s\n") % str(inst))
4447 return 0
4447 return 0
4448 if not ret and not checkout:
4448 if not ret and not checkout:
4449 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4449 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4450 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4450 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4451 return ret
4451 return ret
4452 if modheads > 1:
4452 if modheads > 1:
4453 currentbranchheads = len(repo.branchheads())
4453 currentbranchheads = len(repo.branchheads())
4454 if currentbranchheads == modheads:
4454 if currentbranchheads == modheads:
4455 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4455 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4456 elif currentbranchheads > 1:
4456 elif currentbranchheads > 1:
4457 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4457 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4458 "merge)\n"))
4458 "merge)\n"))
4459 else:
4459 else:
4460 ui.status(_("(run 'hg heads' to see heads)\n"))
4460 ui.status(_("(run 'hg heads' to see heads)\n"))
4461 else:
4461 else:
4462 ui.status(_("(run 'hg update' to get a working copy)\n"))
4462 ui.status(_("(run 'hg update' to get a working copy)\n"))
4463
4463
4464 @command('^pull',
4464 @command('^pull',
4465 [('u', 'update', None,
4465 [('u', 'update', None,
4466 _('update to new branch head if changesets were pulled')),
4466 _('update to new branch head if changesets were pulled')),
4467 ('f', 'force', None, _('run even when remote repository is unrelated')),
4467 ('f', 'force', None, _('run even when remote repository is unrelated')),
4468 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4468 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4469 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4469 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4470 ('b', 'branch', [], _('a specific branch you would like to pull'),
4470 ('b', 'branch', [], _('a specific branch you would like to pull'),
4471 _('BRANCH')),
4471 _('BRANCH')),
4472 ] + remoteopts,
4472 ] + remoteopts,
4473 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4473 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4474 def pull(ui, repo, source="default", **opts):
4474 def pull(ui, repo, source="default", **opts):
4475 """pull changes from the specified source
4475 """pull changes from the specified source
4476
4476
4477 Pull changes from a remote repository to a local one.
4477 Pull changes from a remote repository to a local one.
4478
4478
4479 This finds all changes from the repository at the specified path
4479 This finds all changes from the repository at the specified path
4480 or URL and adds them to a local repository (the current one unless
4480 or URL and adds them to a local repository (the current one unless
4481 -R is specified). By default, this does not update the copy of the
4481 -R is specified). By default, this does not update the copy of the
4482 project in the working directory.
4482 project in the working directory.
4483
4483
4484 Use :hg:`incoming` if you want to see what would have been added
4484 Use :hg:`incoming` if you want to see what would have been added
4485 by a pull at the time you issued this command. If you then decide
4485 by a pull at the time you issued this command. If you then decide
4486 to add those changes to the repository, you should use :hg:`pull
4486 to add those changes to the repository, you should use :hg:`pull
4487 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4487 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4488
4488
4489 If SOURCE is omitted, the 'default' path will be used.
4489 If SOURCE is omitted, the 'default' path will be used.
4490 See :hg:`help urls` for more information.
4490 See :hg:`help urls` for more information.
4491
4491
4492 Returns 0 on success, 1 if an update had unresolved files.
4492 Returns 0 on success, 1 if an update had unresolved files.
4493 """
4493 """
4494 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4494 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4495 other = hg.peer(repo, opts, source)
4495 other = hg.peer(repo, opts, source)
4496 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4496 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4497 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4497 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4498
4498
4499 if opts.get('bookmark'):
4499 if opts.get('bookmark'):
4500 if not revs:
4500 if not revs:
4501 revs = []
4501 revs = []
4502 rb = other.listkeys('bookmarks')
4502 rb = other.listkeys('bookmarks')
4503 for b in opts['bookmark']:
4503 for b in opts['bookmark']:
4504 if b not in rb:
4504 if b not in rb:
4505 raise util.Abort(_('remote bookmark %s not found!') % b)
4505 raise util.Abort(_('remote bookmark %s not found!') % b)
4506 revs.append(rb[b])
4506 revs.append(rb[b])
4507
4507
4508 if revs:
4508 if revs:
4509 try:
4509 try:
4510 revs = [other.lookup(rev) for rev in revs]
4510 revs = [other.lookup(rev) for rev in revs]
4511 except error.CapabilityError:
4511 except error.CapabilityError:
4512 err = _("other repository doesn't support revision lookup, "
4512 err = _("other repository doesn't support revision lookup, "
4513 "so a rev cannot be specified.")
4513 "so a rev cannot be specified.")
4514 raise util.Abort(err)
4514 raise util.Abort(err)
4515
4515
4516 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4516 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4517 bookmarks.updatefromremote(ui, repo, other, source)
4517 bookmarks.updatefromremote(ui, repo, other, source)
4518 if checkout:
4518 if checkout:
4519 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4519 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4520 repo._subtoppath = source
4520 repo._subtoppath = source
4521 try:
4521 try:
4522 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4522 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4523
4523
4524 finally:
4524 finally:
4525 del repo._subtoppath
4525 del repo._subtoppath
4526
4526
4527 # update specified bookmarks
4527 # update specified bookmarks
4528 if opts.get('bookmark'):
4528 if opts.get('bookmark'):
4529 marks = repo._bookmarks
4529 marks = repo._bookmarks
4530 for b in opts['bookmark']:
4530 for b in opts['bookmark']:
4531 # explicit pull overrides local bookmark if any
4531 # explicit pull overrides local bookmark if any
4532 ui.status(_("importing bookmark %s\n") % b)
4532 ui.status(_("importing bookmark %s\n") % b)
4533 marks[b] = repo[rb[b]].node()
4533 marks[b] = repo[rb[b]].node()
4534 marks.write()
4534 marks.write()
4535
4535
4536 return ret
4536 return ret
4537
4537
4538 @command('^push',
4538 @command('^push',
4539 [('f', 'force', None, _('force push')),
4539 [('f', 'force', None, _('force push')),
4540 ('r', 'rev', [],
4540 ('r', 'rev', [],
4541 _('a changeset intended to be included in the destination'),
4541 _('a changeset intended to be included in the destination'),
4542 _('REV')),
4542 _('REV')),
4543 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4543 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4544 ('b', 'branch', [],
4544 ('b', 'branch', [],
4545 _('a specific branch you would like to push'), _('BRANCH')),
4545 _('a specific branch you would like to push'), _('BRANCH')),
4546 ('', 'new-branch', False, _('allow pushing a new branch')),
4546 ('', 'new-branch', False, _('allow pushing a new branch')),
4547 ] + remoteopts,
4547 ] + remoteopts,
4548 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4548 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4549 def push(ui, repo, dest=None, **opts):
4549 def push(ui, repo, dest=None, **opts):
4550 """push changes to the specified destination
4550 """push changes to the specified destination
4551
4551
4552 Push changesets from the local repository to the specified
4552 Push changesets from the local repository to the specified
4553 destination.
4553 destination.
4554
4554
4555 This operation is symmetrical to pull: it is identical to a pull
4555 This operation is symmetrical to pull: it is identical to a pull
4556 in the destination repository from the current one.
4556 in the destination repository from the current one.
4557
4557
4558 By default, push will not allow creation of new heads at the
4558 By default, push will not allow creation of new heads at the
4559 destination, since multiple heads would make it unclear which head
4559 destination, since multiple heads would make it unclear which head
4560 to use. In this situation, it is recommended to pull and merge
4560 to use. In this situation, it is recommended to pull and merge
4561 before pushing.
4561 before pushing.
4562
4562
4563 Use --new-branch if you want to allow push to create a new named
4563 Use --new-branch if you want to allow push to create a new named
4564 branch that is not present at the destination. This allows you to
4564 branch that is not present at the destination. This allows you to
4565 only create a new branch without forcing other changes.
4565 only create a new branch without forcing other changes.
4566
4566
4567 Use -f/--force to override the default behavior and push all
4567 Use -f/--force to override the default behavior and push all
4568 changesets on all branches.
4568 changesets on all branches.
4569
4569
4570 If -r/--rev is used, the specified revision and all its ancestors
4570 If -r/--rev is used, the specified revision and all its ancestors
4571 will be pushed to the remote repository.
4571 will be pushed to the remote repository.
4572
4572
4573 If -B/--bookmark is used, the specified bookmarked revision, its
4573 If -B/--bookmark is used, the specified bookmarked revision, its
4574 ancestors, and the bookmark will be pushed to the remote
4574 ancestors, and the bookmark will be pushed to the remote
4575 repository.
4575 repository.
4576
4576
4577 Please see :hg:`help urls` for important details about ``ssh://``
4577 Please see :hg:`help urls` for important details about ``ssh://``
4578 URLs. If DESTINATION is omitted, a default path will be used.
4578 URLs. If DESTINATION is omitted, a default path will be used.
4579
4579
4580 Returns 0 if push was successful, 1 if nothing to push.
4580 Returns 0 if push was successful, 1 if nothing to push.
4581 """
4581 """
4582
4582
4583 if opts.get('bookmark'):
4583 if opts.get('bookmark'):
4584 for b in opts['bookmark']:
4584 for b in opts['bookmark']:
4585 # translate -B options to -r so changesets get pushed
4585 # translate -B options to -r so changesets get pushed
4586 if b in repo._bookmarks:
4586 if b in repo._bookmarks:
4587 opts.setdefault('rev', []).append(b)
4587 opts.setdefault('rev', []).append(b)
4588 else:
4588 else:
4589 # if we try to push a deleted bookmark, translate it to null
4589 # if we try to push a deleted bookmark, translate it to null
4590 # this lets simultaneous -r, -b options continue working
4590 # this lets simultaneous -r, -b options continue working
4591 opts.setdefault('rev', []).append("null")
4591 opts.setdefault('rev', []).append("null")
4592
4592
4593 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4593 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4594 dest, branches = hg.parseurl(dest, opts.get('branch'))
4594 dest, branches = hg.parseurl(dest, opts.get('branch'))
4595 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4595 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4596 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4596 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4597 other = hg.peer(repo, opts, dest)
4597 other = hg.peer(repo, opts, dest)
4598 if revs:
4598 if revs:
4599 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4599 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4600
4600
4601 repo._subtoppath = dest
4601 repo._subtoppath = dest
4602 try:
4602 try:
4603 # push subrepos depth-first for coherent ordering
4603 # push subrepos depth-first for coherent ordering
4604 c = repo['']
4604 c = repo['']
4605 subs = c.substate # only repos that are committed
4605 subs = c.substate # only repos that are committed
4606 for s in sorted(subs):
4606 for s in sorted(subs):
4607 if c.sub(s).push(opts) == 0:
4607 if c.sub(s).push(opts) == 0:
4608 return False
4608 return False
4609 finally:
4609 finally:
4610 del repo._subtoppath
4610 del repo._subtoppath
4611 result = repo.push(other, opts.get('force'), revs=revs,
4611 result = repo.push(other, opts.get('force'), revs=revs,
4612 newbranch=opts.get('new_branch'))
4612 newbranch=opts.get('new_branch'))
4613
4613
4614 result = not result
4614 result = not result
4615
4615
4616 if opts.get('bookmark'):
4616 if opts.get('bookmark'):
4617 rb = other.listkeys('bookmarks')
4617 rb = other.listkeys('bookmarks')
4618 for b in opts['bookmark']:
4618 for b in opts['bookmark']:
4619 # explicit push overrides remote bookmark if any
4619 # explicit push overrides remote bookmark if any
4620 if b in repo._bookmarks:
4620 if b in repo._bookmarks:
4621 ui.status(_("exporting bookmark %s\n") % b)
4621 ui.status(_("exporting bookmark %s\n") % b)
4622 new = repo[b].hex()
4622 new = repo[b].hex()
4623 elif b in rb:
4623 elif b in rb:
4624 ui.status(_("deleting remote bookmark %s\n") % b)
4624 ui.status(_("deleting remote bookmark %s\n") % b)
4625 new = '' # delete
4625 new = '' # delete
4626 else:
4626 else:
4627 ui.warn(_('bookmark %s does not exist on the local '
4627 ui.warn(_('bookmark %s does not exist on the local '
4628 'or remote repository!\n') % b)
4628 'or remote repository!\n') % b)
4629 return 2
4629 return 2
4630 old = rb.get(b, '')
4630 old = rb.get(b, '')
4631 r = other.pushkey('bookmarks', b, old, new)
4631 r = other.pushkey('bookmarks', b, old, new)
4632 if not r:
4632 if not r:
4633 ui.warn(_('updating bookmark %s failed!\n') % b)
4633 ui.warn(_('updating bookmark %s failed!\n') % b)
4634 if not result:
4634 if not result:
4635 result = 2
4635 result = 2
4636
4636
4637 return result
4637 return result
4638
4638
4639 @command('recover', [])
4639 @command('recover', [])
4640 def recover(ui, repo):
4640 def recover(ui, repo):
4641 """roll back an interrupted transaction
4641 """roll back an interrupted transaction
4642
4642
4643 Recover from an interrupted commit or pull.
4643 Recover from an interrupted commit or pull.
4644
4644
4645 This command tries to fix the repository status after an
4645 This command tries to fix the repository status after an
4646 interrupted operation. It should only be necessary when Mercurial
4646 interrupted operation. It should only be necessary when Mercurial
4647 suggests it.
4647 suggests it.
4648
4648
4649 Returns 0 if successful, 1 if nothing to recover or verify fails.
4649 Returns 0 if successful, 1 if nothing to recover or verify fails.
4650 """
4650 """
4651 if repo.recover():
4651 if repo.recover():
4652 return hg.verify(repo)
4652 return hg.verify(repo)
4653 return 1
4653 return 1
4654
4654
4655 @command('^remove|rm',
4655 @command('^remove|rm',
4656 [('A', 'after', None, _('record delete for missing files')),
4656 [('A', 'after', None, _('record delete for missing files')),
4657 ('f', 'force', None,
4657 ('f', 'force', None,
4658 _('remove (and delete) file even if added or modified')),
4658 _('remove (and delete) file even if added or modified')),
4659 ] + walkopts,
4659 ] + walkopts,
4660 _('[OPTION]... FILE...'))
4660 _('[OPTION]... FILE...'))
4661 def remove(ui, repo, *pats, **opts):
4661 def remove(ui, repo, *pats, **opts):
4662 """remove the specified files on the next commit
4662 """remove the specified files on the next commit
4663
4663
4664 Schedule the indicated files for removal from the current branch.
4664 Schedule the indicated files for removal from the current branch.
4665
4665
4666 This command schedules the files to be removed at the next commit.
4666 This command schedules the files to be removed at the next commit.
4667 To undo a remove before that, see :hg:`revert`. To undo added
4667 To undo a remove before that, see :hg:`revert`. To undo added
4668 files, see :hg:`forget`.
4668 files, see :hg:`forget`.
4669
4669
4670 .. container:: verbose
4670 .. container:: verbose
4671
4671
4672 -A/--after can be used to remove only files that have already
4672 -A/--after can be used to remove only files that have already
4673 been deleted, -f/--force can be used to force deletion, and -Af
4673 been deleted, -f/--force can be used to force deletion, and -Af
4674 can be used to remove files from the next revision without
4674 can be used to remove files from the next revision without
4675 deleting them from the working directory.
4675 deleting them from the working directory.
4676
4676
4677 The following table details the behavior of remove for different
4677 The following table details the behavior of remove for different
4678 file states (columns) and option combinations (rows). The file
4678 file states (columns) and option combinations (rows). The file
4679 states are Added [A], Clean [C], Modified [M] and Missing [!]
4679 states are Added [A], Clean [C], Modified [M] and Missing [!]
4680 (as reported by :hg:`status`). The actions are Warn, Remove
4680 (as reported by :hg:`status`). The actions are Warn, Remove
4681 (from branch) and Delete (from disk):
4681 (from branch) and Delete (from disk):
4682
4682
4683 ======= == == == ==
4683 ======= == == == ==
4684 A C M !
4684 A C M !
4685 ======= == == == ==
4685 ======= == == == ==
4686 none W RD W R
4686 none W RD W R
4687 -f R RD RD R
4687 -f R RD RD R
4688 -A W W W R
4688 -A W W W R
4689 -Af R R R R
4689 -Af R R R R
4690 ======= == == == ==
4690 ======= == == == ==
4691
4691
4692 Note that remove never deletes files in Added [A] state from the
4692 Note that remove never deletes files in Added [A] state from the
4693 working directory, not even if option --force is specified.
4693 working directory, not even if option --force is specified.
4694
4694
4695 Returns 0 on success, 1 if any warnings encountered.
4695 Returns 0 on success, 1 if any warnings encountered.
4696 """
4696 """
4697
4697
4698 ret = 0
4698 ret = 0
4699 after, force = opts.get('after'), opts.get('force')
4699 after, force = opts.get('after'), opts.get('force')
4700 if not pats and not after:
4700 if not pats and not after:
4701 raise util.Abort(_('no files specified'))
4701 raise util.Abort(_('no files specified'))
4702
4702
4703 m = scmutil.match(repo[None], pats, opts)
4703 m = scmutil.match(repo[None], pats, opts)
4704 s = repo.status(match=m, clean=True)
4704 s = repo.status(match=m, clean=True)
4705 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4705 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4706
4706
4707 # warn about failure to delete explicit files/dirs
4707 # warn about failure to delete explicit files/dirs
4708 wctx = repo[None]
4708 wctx = repo[None]
4709 for f in m.files():
4709 for f in m.files():
4710 if f in repo.dirstate or f in wctx.dirs():
4710 if f in repo.dirstate or f in wctx.dirs():
4711 continue
4711 continue
4712 if os.path.exists(m.rel(f)):
4712 if os.path.exists(m.rel(f)):
4713 if os.path.isdir(m.rel(f)):
4713 if os.path.isdir(m.rel(f)):
4714 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4714 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4715 else:
4715 else:
4716 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4716 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4717 # missing files will generate a warning elsewhere
4717 # missing files will generate a warning elsewhere
4718 ret = 1
4718 ret = 1
4719
4719
4720 if force:
4720 if force:
4721 list = modified + deleted + clean + added
4721 list = modified + deleted + clean + added
4722 elif after:
4722 elif after:
4723 list = deleted
4723 list = deleted
4724 for f in modified + added + clean:
4724 for f in modified + added + clean:
4725 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4725 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4726 ret = 1
4726 ret = 1
4727 else:
4727 else:
4728 list = deleted + clean
4728 list = deleted + clean
4729 for f in modified:
4729 for f in modified:
4730 ui.warn(_('not removing %s: file is modified (use -f'
4730 ui.warn(_('not removing %s: file is modified (use -f'
4731 ' to force removal)\n') % m.rel(f))
4731 ' to force removal)\n') % m.rel(f))
4732 ret = 1
4732 ret = 1
4733 for f in added:
4733 for f in added:
4734 ui.warn(_('not removing %s: file has been marked for add'
4734 ui.warn(_('not removing %s: file has been marked for add'
4735 ' (use forget to undo)\n') % m.rel(f))
4735 ' (use forget to undo)\n') % m.rel(f))
4736 ret = 1
4736 ret = 1
4737
4737
4738 for f in sorted(list):
4738 for f in sorted(list):
4739 if ui.verbose or not m.exact(f):
4739 if ui.verbose or not m.exact(f):
4740 ui.status(_('removing %s\n') % m.rel(f))
4740 ui.status(_('removing %s\n') % m.rel(f))
4741
4741
4742 wlock = repo.wlock()
4742 wlock = repo.wlock()
4743 try:
4743 try:
4744 if not after:
4744 if not after:
4745 for f in list:
4745 for f in list:
4746 if f in added:
4746 if f in added:
4747 continue # we never unlink added files on remove
4747 continue # we never unlink added files on remove
4748 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4748 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4749 repo[None].forget(list)
4749 repo[None].forget(list)
4750 finally:
4750 finally:
4751 wlock.release()
4751 wlock.release()
4752
4752
4753 return ret
4753 return ret
4754
4754
4755 @command('rename|move|mv',
4755 @command('rename|move|mv',
4756 [('A', 'after', None, _('record a rename that has already occurred')),
4756 [('A', 'after', None, _('record a rename that has already occurred')),
4757 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4757 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4758 ] + walkopts + dryrunopts,
4758 ] + walkopts + dryrunopts,
4759 _('[OPTION]... SOURCE... DEST'))
4759 _('[OPTION]... SOURCE... DEST'))
4760 def rename(ui, repo, *pats, **opts):
4760 def rename(ui, repo, *pats, **opts):
4761 """rename files; equivalent of copy + remove
4761 """rename files; equivalent of copy + remove
4762
4762
4763 Mark dest as copies of sources; mark sources for deletion. If dest
4763 Mark dest as copies of sources; mark sources for deletion. If dest
4764 is a directory, copies are put in that directory. If dest is a
4764 is a directory, copies are put in that directory. If dest is a
4765 file, there can only be one source.
4765 file, there can only be one source.
4766
4766
4767 By default, this command copies the contents of files as they
4767 By default, this command copies the contents of files as they
4768 exist in the working directory. If invoked with -A/--after, the
4768 exist in the working directory. If invoked with -A/--after, the
4769 operation is recorded, but no copying is performed.
4769 operation is recorded, but no copying is performed.
4770
4770
4771 This command takes effect at the next commit. To undo a rename
4771 This command takes effect at the next commit. To undo a rename
4772 before that, see :hg:`revert`.
4772 before that, see :hg:`revert`.
4773
4773
4774 Returns 0 on success, 1 if errors are encountered.
4774 Returns 0 on success, 1 if errors are encountered.
4775 """
4775 """
4776 wlock = repo.wlock(False)
4776 wlock = repo.wlock(False)
4777 try:
4777 try:
4778 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4778 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4779 finally:
4779 finally:
4780 wlock.release()
4780 wlock.release()
4781
4781
4782 @command('resolve',
4782 @command('resolve',
4783 [('a', 'all', None, _('select all unresolved files')),
4783 [('a', 'all', None, _('select all unresolved files')),
4784 ('l', 'list', None, _('list state of files needing merge')),
4784 ('l', 'list', None, _('list state of files needing merge')),
4785 ('m', 'mark', None, _('mark files as resolved')),
4785 ('m', 'mark', None, _('mark files as resolved')),
4786 ('u', 'unmark', None, _('mark files as unresolved')),
4786 ('u', 'unmark', None, _('mark files as unresolved')),
4787 ('n', 'no-status', None, _('hide status prefix'))]
4787 ('n', 'no-status', None, _('hide status prefix'))]
4788 + mergetoolopts + walkopts,
4788 + mergetoolopts + walkopts,
4789 _('[OPTION]... [FILE]...'))
4789 _('[OPTION]... [FILE]...'))
4790 def resolve(ui, repo, *pats, **opts):
4790 def resolve(ui, repo, *pats, **opts):
4791 """redo merges or set/view the merge status of files
4791 """redo merges or set/view the merge status of files
4792
4792
4793 Merges with unresolved conflicts are often the result of
4793 Merges with unresolved conflicts are often the result of
4794 non-interactive merging using the ``internal:merge`` configuration
4794 non-interactive merging using the ``internal:merge`` configuration
4795 setting, or a command-line merge tool like ``diff3``. The resolve
4795 setting, or a command-line merge tool like ``diff3``. The resolve
4796 command is used to manage the files involved in a merge, after
4796 command is used to manage the files involved in a merge, after
4797 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4797 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4798 working directory must have two parents). See :hg:`help
4798 working directory must have two parents). See :hg:`help
4799 merge-tools` for information on configuring merge tools.
4799 merge-tools` for information on configuring merge tools.
4800
4800
4801 The resolve command can be used in the following ways:
4801 The resolve command can be used in the following ways:
4802
4802
4803 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4803 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4804 files, discarding any previous merge attempts. Re-merging is not
4804 files, discarding any previous merge attempts. Re-merging is not
4805 performed for files already marked as resolved. Use ``--all/-a``
4805 performed for files already marked as resolved. Use ``--all/-a``
4806 to select all unresolved files. ``--tool`` can be used to specify
4806 to select all unresolved files. ``--tool`` can be used to specify
4807 the merge tool used for the given files. It overrides the HGMERGE
4807 the merge tool used for the given files. It overrides the HGMERGE
4808 environment variable and your configuration files. Previous file
4808 environment variable and your configuration files. Previous file
4809 contents are saved with a ``.orig`` suffix.
4809 contents are saved with a ``.orig`` suffix.
4810
4810
4811 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4811 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4812 (e.g. after having manually fixed-up the files). The default is
4812 (e.g. after having manually fixed-up the files). The default is
4813 to mark all unresolved files.
4813 to mark all unresolved files.
4814
4814
4815 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4815 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4816 default is to mark all resolved files.
4816 default is to mark all resolved files.
4817
4817
4818 - :hg:`resolve -l`: list files which had or still have conflicts.
4818 - :hg:`resolve -l`: list files which had or still have conflicts.
4819 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4819 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4820
4820
4821 Note that Mercurial will not let you commit files with unresolved
4821 Note that Mercurial will not let you commit files with unresolved
4822 merge conflicts. You must use :hg:`resolve -m ...` before you can
4822 merge conflicts. You must use :hg:`resolve -m ...` before you can
4823 commit after a conflicting merge.
4823 commit after a conflicting merge.
4824
4824
4825 Returns 0 on success, 1 if any files fail a resolve attempt.
4825 Returns 0 on success, 1 if any files fail a resolve attempt.
4826 """
4826 """
4827
4827
4828 all, mark, unmark, show, nostatus = \
4828 all, mark, unmark, show, nostatus = \
4829 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4829 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4830
4830
4831 if (show and (mark or unmark)) or (mark and unmark):
4831 if (show and (mark or unmark)) or (mark and unmark):
4832 raise util.Abort(_("too many options specified"))
4832 raise util.Abort(_("too many options specified"))
4833 if pats and all:
4833 if pats and all:
4834 raise util.Abort(_("can't specify --all and patterns"))
4834 raise util.Abort(_("can't specify --all and patterns"))
4835 if not (all or pats or show or mark or unmark):
4835 if not (all or pats or show or mark or unmark):
4836 raise util.Abort(_('no files or directories specified; '
4836 raise util.Abort(_('no files or directories specified; '
4837 'use --all to remerge all files'))
4837 'use --all to remerge all files'))
4838
4838
4839 ms = mergemod.mergestate(repo)
4839 ms = mergemod.mergestate(repo)
4840 m = scmutil.match(repo[None], pats, opts)
4840 m = scmutil.match(repo[None], pats, opts)
4841 ret = 0
4841 ret = 0
4842
4842
4843 for f in ms:
4843 for f in ms:
4844 if m(f):
4844 if m(f):
4845 if show:
4845 if show:
4846 if nostatus:
4846 if nostatus:
4847 ui.write("%s\n" % f)
4847 ui.write("%s\n" % f)
4848 else:
4848 else:
4849 ui.write("%s %s\n" % (ms[f].upper(), f),
4849 ui.write("%s %s\n" % (ms[f].upper(), f),
4850 label='resolve.' +
4850 label='resolve.' +
4851 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4851 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4852 elif mark:
4852 elif mark:
4853 ms.mark(f, "r")
4853 ms.mark(f, "r")
4854 elif unmark:
4854 elif unmark:
4855 ms.mark(f, "u")
4855 ms.mark(f, "u")
4856 else:
4856 else:
4857 wctx = repo[None]
4857 wctx = repo[None]
4858 mctx = wctx.parents()[-1]
4858 mctx = wctx.parents()[-1]
4859
4859
4860 # backup pre-resolve (merge uses .orig for its own purposes)
4860 # backup pre-resolve (merge uses .orig for its own purposes)
4861 a = repo.wjoin(f)
4861 a = repo.wjoin(f)
4862 util.copyfile(a, a + ".resolve")
4862 util.copyfile(a, a + ".resolve")
4863
4863
4864 try:
4864 try:
4865 # resolve file
4865 # resolve file
4866 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4866 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4867 if ms.resolve(f, wctx, mctx):
4867 if ms.resolve(f, wctx, mctx):
4868 ret = 1
4868 ret = 1
4869 finally:
4869 finally:
4870 ui.setconfig('ui', 'forcemerge', '')
4870 ui.setconfig('ui', 'forcemerge', '')
4871 ms.commit()
4871 ms.commit()
4872
4872
4873 # replace filemerge's .orig file with our resolve file
4873 # replace filemerge's .orig file with our resolve file
4874 util.rename(a + ".resolve", a + ".orig")
4874 util.rename(a + ".resolve", a + ".orig")
4875
4875
4876 ms.commit()
4876 ms.commit()
4877 return ret
4877 return ret
4878
4878
4879 @command('revert',
4879 @command('revert',
4880 [('a', 'all', None, _('revert all changes when no arguments given')),
4880 [('a', 'all', None, _('revert all changes when no arguments given')),
4881 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4881 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4882 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4882 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4883 ('C', 'no-backup', None, _('do not save backup copies of files')),
4883 ('C', 'no-backup', None, _('do not save backup copies of files')),
4884 ] + walkopts + dryrunopts,
4884 ] + walkopts + dryrunopts,
4885 _('[OPTION]... [-r REV] [NAME]...'))
4885 _('[OPTION]... [-r REV] [NAME]...'))
4886 def revert(ui, repo, *pats, **opts):
4886 def revert(ui, repo, *pats, **opts):
4887 """restore files to their checkout state
4887 """restore files to their checkout state
4888
4888
4889 .. note::
4889 .. note::
4890
4890
4891 To check out earlier revisions, you should use :hg:`update REV`.
4891 To check out earlier revisions, you should use :hg:`update REV`.
4892 To cancel an uncommitted merge (and lose your changes), use
4892 To cancel an uncommitted merge (and lose your changes), use
4893 :hg:`update --clean .`.
4893 :hg:`update --clean .`.
4894
4894
4895 With no revision specified, revert the specified files or directories
4895 With no revision specified, revert the specified files or directories
4896 to the contents they had in the parent of the working directory.
4896 to the contents they had in the parent of the working directory.
4897 This restores the contents of files to an unmodified
4897 This restores the contents of files to an unmodified
4898 state and unschedules adds, removes, copies, and renames. If the
4898 state and unschedules adds, removes, copies, and renames. If the
4899 working directory has two parents, you must explicitly specify a
4899 working directory has two parents, you must explicitly specify a
4900 revision.
4900 revision.
4901
4901
4902 Using the -r/--rev or -d/--date options, revert the given files or
4902 Using the -r/--rev or -d/--date options, revert the given files or
4903 directories to their states as of a specific revision. Because
4903 directories to their states as of a specific revision. Because
4904 revert does not change the working directory parents, this will
4904 revert does not change the working directory parents, this will
4905 cause these files to appear modified. This can be helpful to "back
4905 cause these files to appear modified. This can be helpful to "back
4906 out" some or all of an earlier change. See :hg:`backout` for a
4906 out" some or all of an earlier change. See :hg:`backout` for a
4907 related method.
4907 related method.
4908
4908
4909 Modified files are saved with a .orig suffix before reverting.
4909 Modified files are saved with a .orig suffix before reverting.
4910 To disable these backups, use --no-backup.
4910 To disable these backups, use --no-backup.
4911
4911
4912 See :hg:`help dates` for a list of formats valid for -d/--date.
4912 See :hg:`help dates` for a list of formats valid for -d/--date.
4913
4913
4914 Returns 0 on success.
4914 Returns 0 on success.
4915 """
4915 """
4916
4916
4917 if opts.get("date"):
4917 if opts.get("date"):
4918 if opts.get("rev"):
4918 if opts.get("rev"):
4919 raise util.Abort(_("you can't specify a revision and a date"))
4919 raise util.Abort(_("you can't specify a revision and a date"))
4920 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4920 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4921
4921
4922 parent, p2 = repo.dirstate.parents()
4922 parent, p2 = repo.dirstate.parents()
4923 if not opts.get('rev') and p2 != nullid:
4923 if not opts.get('rev') and p2 != nullid:
4924 # revert after merge is a trap for new users (issue2915)
4924 # revert after merge is a trap for new users (issue2915)
4925 raise util.Abort(_('uncommitted merge with no revision specified'),
4925 raise util.Abort(_('uncommitted merge with no revision specified'),
4926 hint=_('use "hg update" or see "hg help revert"'))
4926 hint=_('use "hg update" or see "hg help revert"'))
4927
4927
4928 ctx = scmutil.revsingle(repo, opts.get('rev'))
4928 ctx = scmutil.revsingle(repo, opts.get('rev'))
4929
4929
4930 if not pats and not opts.get('all'):
4930 if not pats and not opts.get('all'):
4931 msg = _("no files or directories specified")
4931 msg = _("no files or directories specified")
4932 if p2 != nullid:
4932 if p2 != nullid:
4933 hint = _("uncommitted merge, use --all to discard all changes,"
4933 hint = _("uncommitted merge, use --all to discard all changes,"
4934 " or 'hg update -C .' to abort the merge")
4934 " or 'hg update -C .' to abort the merge")
4935 raise util.Abort(msg, hint=hint)
4935 raise util.Abort(msg, hint=hint)
4936 dirty = util.any(repo.status())
4936 dirty = util.any(repo.status())
4937 node = ctx.node()
4937 node = ctx.node()
4938 if node != parent:
4938 if node != parent:
4939 if dirty:
4939 if dirty:
4940 hint = _("uncommitted changes, use --all to discard all"
4940 hint = _("uncommitted changes, use --all to discard all"
4941 " changes, or 'hg update %s' to update") % ctx.rev()
4941 " changes, or 'hg update %s' to update") % ctx.rev()
4942 else:
4942 else:
4943 hint = _("use --all to revert all files,"
4943 hint = _("use --all to revert all files,"
4944 " or 'hg update %s' to update") % ctx.rev()
4944 " or 'hg update %s' to update") % ctx.rev()
4945 elif dirty:
4945 elif dirty:
4946 hint = _("uncommitted changes, use --all to discard all changes")
4946 hint = _("uncommitted changes, use --all to discard all changes")
4947 else:
4947 else:
4948 hint = _("use --all to revert all files")
4948 hint = _("use --all to revert all files")
4949 raise util.Abort(msg, hint=hint)
4949 raise util.Abort(msg, hint=hint)
4950
4950
4951 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4951 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4952
4952
4953 @command('rollback', dryrunopts +
4953 @command('rollback', dryrunopts +
4954 [('f', 'force', False, _('ignore safety measures'))])
4954 [('f', 'force', False, _('ignore safety measures'))])
4955 def rollback(ui, repo, **opts):
4955 def rollback(ui, repo, **opts):
4956 """roll back the last transaction (dangerous)
4956 """roll back the last transaction (dangerous)
4957
4957
4958 This command should be used with care. There is only one level of
4958 This command should be used with care. There is only one level of
4959 rollback, and there is no way to undo a rollback. It will also
4959 rollback, and there is no way to undo a rollback. It will also
4960 restore the dirstate at the time of the last transaction, losing
4960 restore the dirstate at the time of the last transaction, losing
4961 any dirstate changes since that time. This command does not alter
4961 any dirstate changes since that time. This command does not alter
4962 the working directory.
4962 the working directory.
4963
4963
4964 Transactions are used to encapsulate the effects of all commands
4964 Transactions are used to encapsulate the effects of all commands
4965 that create new changesets or propagate existing changesets into a
4965 that create new changesets or propagate existing changesets into a
4966 repository.
4966 repository.
4967
4967
4968 .. container:: verbose
4968 .. container:: verbose
4969
4969
4970 For example, the following commands are transactional, and their
4970 For example, the following commands are transactional, and their
4971 effects can be rolled back:
4971 effects can be rolled back:
4972
4972
4973 - commit
4973 - commit
4974 - import
4974 - import
4975 - pull
4975 - pull
4976 - push (with this repository as the destination)
4976 - push (with this repository as the destination)
4977 - unbundle
4977 - unbundle
4978
4978
4979 To avoid permanent data loss, rollback will refuse to rollback a
4979 To avoid permanent data loss, rollback will refuse to rollback a
4980 commit transaction if it isn't checked out. Use --force to
4980 commit transaction if it isn't checked out. Use --force to
4981 override this protection.
4981 override this protection.
4982
4982
4983 This command is not intended for use on public repositories. Once
4983 This command is not intended for use on public repositories. Once
4984 changes are visible for pull by other users, rolling a transaction
4984 changes are visible for pull by other users, rolling a transaction
4985 back locally is ineffective (someone else may already have pulled
4985 back locally is ineffective (someone else may already have pulled
4986 the changes). Furthermore, a race is possible with readers of the
4986 the changes). Furthermore, a race is possible with readers of the
4987 repository; for example an in-progress pull from the repository
4987 repository; for example an in-progress pull from the repository
4988 may fail if a rollback is performed.
4988 may fail if a rollback is performed.
4989
4989
4990 Returns 0 on success, 1 if no rollback data is available.
4990 Returns 0 on success, 1 if no rollback data is available.
4991 """
4991 """
4992 return repo.rollback(dryrun=opts.get('dry_run'),
4992 return repo.rollback(dryrun=opts.get('dry_run'),
4993 force=opts.get('force'))
4993 force=opts.get('force'))
4994
4994
4995 @command('root', [])
4995 @command('root', [])
4996 def root(ui, repo):
4996 def root(ui, repo):
4997 """print the root (top) of the current working directory
4997 """print the root (top) of the current working directory
4998
4998
4999 Print the root directory of the current repository.
4999 Print the root directory of the current repository.
5000
5000
5001 Returns 0 on success.
5001 Returns 0 on success.
5002 """
5002 """
5003 ui.write(repo.root + "\n")
5003 ui.write(repo.root + "\n")
5004
5004
5005 @command('^serve',
5005 @command('^serve',
5006 [('A', 'accesslog', '', _('name of access log file to write to'),
5006 [('A', 'accesslog', '', _('name of access log file to write to'),
5007 _('FILE')),
5007 _('FILE')),
5008 ('d', 'daemon', None, _('run server in background')),
5008 ('d', 'daemon', None, _('run server in background')),
5009 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5009 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5010 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5010 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5011 # use string type, then we can check if something was passed
5011 # use string type, then we can check if something was passed
5012 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5012 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5013 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5013 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5014 _('ADDR')),
5014 _('ADDR')),
5015 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5015 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5016 _('PREFIX')),
5016 _('PREFIX')),
5017 ('n', 'name', '',
5017 ('n', 'name', '',
5018 _('name to show in web pages (default: working directory)'), _('NAME')),
5018 _('name to show in web pages (default: working directory)'), _('NAME')),
5019 ('', 'web-conf', '',
5019 ('', 'web-conf', '',
5020 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5020 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5021 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5021 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5022 _('FILE')),
5022 _('FILE')),
5023 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5023 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5024 ('', 'stdio', None, _('for remote clients')),
5024 ('', 'stdio', None, _('for remote clients')),
5025 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5025 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5026 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5026 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5027 ('', 'style', '', _('template style to use'), _('STYLE')),
5027 ('', 'style', '', _('template style to use'), _('STYLE')),
5028 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5028 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5029 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5029 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5030 _('[OPTION]...'))
5030 _('[OPTION]...'))
5031 def serve(ui, repo, **opts):
5031 def serve(ui, repo, **opts):
5032 """start stand-alone webserver
5032 """start stand-alone webserver
5033
5033
5034 Start a local HTTP repository browser and pull server. You can use
5034 Start a local HTTP repository browser and pull server. You can use
5035 this for ad-hoc sharing and browsing of repositories. It is
5035 this for ad-hoc sharing and browsing of repositories. It is
5036 recommended to use a real web server to serve a repository for
5036 recommended to use a real web server to serve a repository for
5037 longer periods of time.
5037 longer periods of time.
5038
5038
5039 Please note that the server does not implement access control.
5039 Please note that the server does not implement access control.
5040 This means that, by default, anybody can read from the server and
5040 This means that, by default, anybody can read from the server and
5041 nobody can write to it by default. Set the ``web.allow_push``
5041 nobody can write to it by default. Set the ``web.allow_push``
5042 option to ``*`` to allow everybody to push to the server. You
5042 option to ``*`` to allow everybody to push to the server. You
5043 should use a real web server if you need to authenticate users.
5043 should use a real web server if you need to authenticate users.
5044
5044
5045 By default, the server logs accesses to stdout and errors to
5045 By default, the server logs accesses to stdout and errors to
5046 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5046 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5047 files.
5047 files.
5048
5048
5049 To have the server choose a free port number to listen on, specify
5049 To have the server choose a free port number to listen on, specify
5050 a port number of 0; in this case, the server will print the port
5050 a port number of 0; in this case, the server will print the port
5051 number it uses.
5051 number it uses.
5052
5052
5053 Returns 0 on success.
5053 Returns 0 on success.
5054 """
5054 """
5055
5055
5056 if opts["stdio"] and opts["cmdserver"]:
5056 if opts["stdio"] and opts["cmdserver"]:
5057 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5057 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5058
5058
5059 def checkrepo():
5059 def checkrepo():
5060 if repo is None:
5060 if repo is None:
5061 raise error.RepoError(_("there is no Mercurial repository here"
5061 raise error.RepoError(_("there is no Mercurial repository here"
5062 " (.hg not found)"))
5062 " (.hg not found)"))
5063
5063
5064 if opts["stdio"]:
5064 if opts["stdio"]:
5065 checkrepo()
5065 checkrepo()
5066 s = sshserver.sshserver(ui, repo)
5066 s = sshserver.sshserver(ui, repo)
5067 s.serve_forever()
5067 s.serve_forever()
5068
5068
5069 if opts["cmdserver"]:
5069 if opts["cmdserver"]:
5070 checkrepo()
5070 checkrepo()
5071 s = commandserver.server(ui, repo, opts["cmdserver"])
5071 s = commandserver.server(ui, repo, opts["cmdserver"])
5072 return s.serve()
5072 return s.serve()
5073
5073
5074 # this way we can check if something was given in the command-line
5074 # this way we can check if something was given in the command-line
5075 if opts.get('port'):
5075 if opts.get('port'):
5076 opts['port'] = util.getport(opts.get('port'))
5076 opts['port'] = util.getport(opts.get('port'))
5077
5077
5078 baseui = repo and repo.baseui or ui
5078 baseui = repo and repo.baseui or ui
5079 optlist = ("name templates style address port prefix ipv6"
5079 optlist = ("name templates style address port prefix ipv6"
5080 " accesslog errorlog certificate encoding")
5080 " accesslog errorlog certificate encoding")
5081 for o in optlist.split():
5081 for o in optlist.split():
5082 val = opts.get(o, '')
5082 val = opts.get(o, '')
5083 if val in (None, ''): # should check against default options instead
5083 if val in (None, ''): # should check against default options instead
5084 continue
5084 continue
5085 baseui.setconfig("web", o, val)
5085 baseui.setconfig("web", o, val)
5086 if repo and repo.ui != baseui:
5086 if repo and repo.ui != baseui:
5087 repo.ui.setconfig("web", o, val)
5087 repo.ui.setconfig("web", o, val)
5088
5088
5089 o = opts.get('web_conf') or opts.get('webdir_conf')
5089 o = opts.get('web_conf') or opts.get('webdir_conf')
5090 if not o:
5090 if not o:
5091 if not repo:
5091 if not repo:
5092 raise error.RepoError(_("there is no Mercurial repository"
5092 raise error.RepoError(_("there is no Mercurial repository"
5093 " here (.hg not found)"))
5093 " here (.hg not found)"))
5094 o = repo.root
5094 o = repo.root
5095
5095
5096 app = hgweb.hgweb(o, baseui=ui)
5096 app = hgweb.hgweb(o, baseui=baseui)
5097
5097
5098 class service(object):
5098 class service(object):
5099 def init(self):
5099 def init(self):
5100 util.setsignalhandler()
5100 util.setsignalhandler()
5101 self.httpd = hgweb.server.create_server(ui, app)
5101 self.httpd = hgweb.server.create_server(ui, app)
5102
5102
5103 if opts['port'] and not ui.verbose:
5103 if opts['port'] and not ui.verbose:
5104 return
5104 return
5105
5105
5106 if self.httpd.prefix:
5106 if self.httpd.prefix:
5107 prefix = self.httpd.prefix.strip('/') + '/'
5107 prefix = self.httpd.prefix.strip('/') + '/'
5108 else:
5108 else:
5109 prefix = ''
5109 prefix = ''
5110
5110
5111 port = ':%d' % self.httpd.port
5111 port = ':%d' % self.httpd.port
5112 if port == ':80':
5112 if port == ':80':
5113 port = ''
5113 port = ''
5114
5114
5115 bindaddr = self.httpd.addr
5115 bindaddr = self.httpd.addr
5116 if bindaddr == '0.0.0.0':
5116 if bindaddr == '0.0.0.0':
5117 bindaddr = '*'
5117 bindaddr = '*'
5118 elif ':' in bindaddr: # IPv6
5118 elif ':' in bindaddr: # IPv6
5119 bindaddr = '[%s]' % bindaddr
5119 bindaddr = '[%s]' % bindaddr
5120
5120
5121 fqaddr = self.httpd.fqaddr
5121 fqaddr = self.httpd.fqaddr
5122 if ':' in fqaddr:
5122 if ':' in fqaddr:
5123 fqaddr = '[%s]' % fqaddr
5123 fqaddr = '[%s]' % fqaddr
5124 if opts['port']:
5124 if opts['port']:
5125 write = ui.status
5125 write = ui.status
5126 else:
5126 else:
5127 write = ui.write
5127 write = ui.write
5128 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5128 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5129 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5129 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5130
5130
5131 def run(self):
5131 def run(self):
5132 self.httpd.serve_forever()
5132 self.httpd.serve_forever()
5133
5133
5134 service = service()
5134 service = service()
5135
5135
5136 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5136 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5137
5137
5138 @command('showconfig|debugconfig',
5138 @command('showconfig|debugconfig',
5139 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5139 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5140 _('[-u] [NAME]...'))
5140 _('[-u] [NAME]...'))
5141 def showconfig(ui, repo, *values, **opts):
5141 def showconfig(ui, repo, *values, **opts):
5142 """show combined config settings from all hgrc files
5142 """show combined config settings from all hgrc files
5143
5143
5144 With no arguments, print names and values of all config items.
5144 With no arguments, print names and values of all config items.
5145
5145
5146 With one argument of the form section.name, print just the value
5146 With one argument of the form section.name, print just the value
5147 of that config item.
5147 of that config item.
5148
5148
5149 With multiple arguments, print names and values of all config
5149 With multiple arguments, print names and values of all config
5150 items with matching section names.
5150 items with matching section names.
5151
5151
5152 With --debug, the source (filename and line number) is printed
5152 With --debug, the source (filename and line number) is printed
5153 for each config item.
5153 for each config item.
5154
5154
5155 Returns 0 on success.
5155 Returns 0 on success.
5156 """
5156 """
5157
5157
5158 for f in scmutil.rcpath():
5158 for f in scmutil.rcpath():
5159 ui.debug('read config from: %s\n' % f)
5159 ui.debug('read config from: %s\n' % f)
5160 untrusted = bool(opts.get('untrusted'))
5160 untrusted = bool(opts.get('untrusted'))
5161 if values:
5161 if values:
5162 sections = [v for v in values if '.' not in v]
5162 sections = [v for v in values if '.' not in v]
5163 items = [v for v in values if '.' in v]
5163 items = [v for v in values if '.' in v]
5164 if len(items) > 1 or items and sections:
5164 if len(items) > 1 or items and sections:
5165 raise util.Abort(_('only one config item permitted'))
5165 raise util.Abort(_('only one config item permitted'))
5166 for section, name, value in ui.walkconfig(untrusted=untrusted):
5166 for section, name, value in ui.walkconfig(untrusted=untrusted):
5167 value = str(value).replace('\n', '\\n')
5167 value = str(value).replace('\n', '\\n')
5168 sectname = section + '.' + name
5168 sectname = section + '.' + name
5169 if values:
5169 if values:
5170 for v in values:
5170 for v in values:
5171 if v == section:
5171 if v == section:
5172 ui.debug('%s: ' %
5172 ui.debug('%s: ' %
5173 ui.configsource(section, name, untrusted))
5173 ui.configsource(section, name, untrusted))
5174 ui.write('%s=%s\n' % (sectname, value))
5174 ui.write('%s=%s\n' % (sectname, value))
5175 elif v == sectname:
5175 elif v == sectname:
5176 ui.debug('%s: ' %
5176 ui.debug('%s: ' %
5177 ui.configsource(section, name, untrusted))
5177 ui.configsource(section, name, untrusted))
5178 ui.write(value, '\n')
5178 ui.write(value, '\n')
5179 else:
5179 else:
5180 ui.debug('%s: ' %
5180 ui.debug('%s: ' %
5181 ui.configsource(section, name, untrusted))
5181 ui.configsource(section, name, untrusted))
5182 ui.write('%s=%s\n' % (sectname, value))
5182 ui.write('%s=%s\n' % (sectname, value))
5183
5183
5184 @command('^status|st',
5184 @command('^status|st',
5185 [('A', 'all', None, _('show status of all files')),
5185 [('A', 'all', None, _('show status of all files')),
5186 ('m', 'modified', None, _('show only modified files')),
5186 ('m', 'modified', None, _('show only modified files')),
5187 ('a', 'added', None, _('show only added files')),
5187 ('a', 'added', None, _('show only added files')),
5188 ('r', 'removed', None, _('show only removed files')),
5188 ('r', 'removed', None, _('show only removed files')),
5189 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5189 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5190 ('c', 'clean', None, _('show only files without changes')),
5190 ('c', 'clean', None, _('show only files without changes')),
5191 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5191 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5192 ('i', 'ignored', None, _('show only ignored files')),
5192 ('i', 'ignored', None, _('show only ignored files')),
5193 ('n', 'no-status', None, _('hide status prefix')),
5193 ('n', 'no-status', None, _('hide status prefix')),
5194 ('C', 'copies', None, _('show source of copied files')),
5194 ('C', 'copies', None, _('show source of copied files')),
5195 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5195 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5196 ('', 'rev', [], _('show difference from revision'), _('REV')),
5196 ('', 'rev', [], _('show difference from revision'), _('REV')),
5197 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5197 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5198 ] + walkopts + subrepoopts,
5198 ] + walkopts + subrepoopts,
5199 _('[OPTION]... [FILE]...'))
5199 _('[OPTION]... [FILE]...'))
5200 def status(ui, repo, *pats, **opts):
5200 def status(ui, repo, *pats, **opts):
5201 """show changed files in the working directory
5201 """show changed files in the working directory
5202
5202
5203 Show status of files in the repository. If names are given, only
5203 Show status of files in the repository. If names are given, only
5204 files that match are shown. Files that are clean or ignored or
5204 files that match are shown. Files that are clean or ignored or
5205 the source of a copy/move operation, are not listed unless
5205 the source of a copy/move operation, are not listed unless
5206 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5206 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5207 Unless options described with "show only ..." are given, the
5207 Unless options described with "show only ..." are given, the
5208 options -mardu are used.
5208 options -mardu are used.
5209
5209
5210 Option -q/--quiet hides untracked (unknown and ignored) files
5210 Option -q/--quiet hides untracked (unknown and ignored) files
5211 unless explicitly requested with -u/--unknown or -i/--ignored.
5211 unless explicitly requested with -u/--unknown or -i/--ignored.
5212
5212
5213 .. note::
5213 .. note::
5214 status may appear to disagree with diff if permissions have
5214 status may appear to disagree with diff if permissions have
5215 changed or a merge has occurred. The standard diff format does
5215 changed or a merge has occurred. The standard diff format does
5216 not report permission changes and diff only reports changes
5216 not report permission changes and diff only reports changes
5217 relative to one merge parent.
5217 relative to one merge parent.
5218
5218
5219 If one revision is given, it is used as the base revision.
5219 If one revision is given, it is used as the base revision.
5220 If two revisions are given, the differences between them are
5220 If two revisions are given, the differences between them are
5221 shown. The --change option can also be used as a shortcut to list
5221 shown. The --change option can also be used as a shortcut to list
5222 the changed files of a revision from its first parent.
5222 the changed files of a revision from its first parent.
5223
5223
5224 The codes used to show the status of files are::
5224 The codes used to show the status of files are::
5225
5225
5226 M = modified
5226 M = modified
5227 A = added
5227 A = added
5228 R = removed
5228 R = removed
5229 C = clean
5229 C = clean
5230 ! = missing (deleted by non-hg command, but still tracked)
5230 ! = missing (deleted by non-hg command, but still tracked)
5231 ? = not tracked
5231 ? = not tracked
5232 I = ignored
5232 I = ignored
5233 = origin of the previous file listed as A (added)
5233 = origin of the previous file listed as A (added)
5234
5234
5235 .. container:: verbose
5235 .. container:: verbose
5236
5236
5237 Examples:
5237 Examples:
5238
5238
5239 - show changes in the working directory relative to a
5239 - show changes in the working directory relative to a
5240 changeset::
5240 changeset::
5241
5241
5242 hg status --rev 9353
5242 hg status --rev 9353
5243
5243
5244 - show all changes including copies in an existing changeset::
5244 - show all changes including copies in an existing changeset::
5245
5245
5246 hg status --copies --change 9353
5246 hg status --copies --change 9353
5247
5247
5248 - get a NUL separated list of added files, suitable for xargs::
5248 - get a NUL separated list of added files, suitable for xargs::
5249
5249
5250 hg status -an0
5250 hg status -an0
5251
5251
5252 Returns 0 on success.
5252 Returns 0 on success.
5253 """
5253 """
5254
5254
5255 revs = opts.get('rev')
5255 revs = opts.get('rev')
5256 change = opts.get('change')
5256 change = opts.get('change')
5257
5257
5258 if revs and change:
5258 if revs and change:
5259 msg = _('cannot specify --rev and --change at the same time')
5259 msg = _('cannot specify --rev and --change at the same time')
5260 raise util.Abort(msg)
5260 raise util.Abort(msg)
5261 elif change:
5261 elif change:
5262 node2 = scmutil.revsingle(repo, change, None).node()
5262 node2 = scmutil.revsingle(repo, change, None).node()
5263 node1 = repo[node2].p1().node()
5263 node1 = repo[node2].p1().node()
5264 else:
5264 else:
5265 node1, node2 = scmutil.revpair(repo, revs)
5265 node1, node2 = scmutil.revpair(repo, revs)
5266
5266
5267 cwd = (pats and repo.getcwd()) or ''
5267 cwd = (pats and repo.getcwd()) or ''
5268 end = opts.get('print0') and '\0' or '\n'
5268 end = opts.get('print0') and '\0' or '\n'
5269 copy = {}
5269 copy = {}
5270 states = 'modified added removed deleted unknown ignored clean'.split()
5270 states = 'modified added removed deleted unknown ignored clean'.split()
5271 show = [k for k in states if opts.get(k)]
5271 show = [k for k in states if opts.get(k)]
5272 if opts.get('all'):
5272 if opts.get('all'):
5273 show += ui.quiet and (states[:4] + ['clean']) or states
5273 show += ui.quiet and (states[:4] + ['clean']) or states
5274 if not show:
5274 if not show:
5275 show = ui.quiet and states[:4] or states[:5]
5275 show = ui.quiet and states[:4] or states[:5]
5276
5276
5277 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5277 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5278 'ignored' in show, 'clean' in show, 'unknown' in show,
5278 'ignored' in show, 'clean' in show, 'unknown' in show,
5279 opts.get('subrepos'))
5279 opts.get('subrepos'))
5280 changestates = zip(states, 'MAR!?IC', stat)
5280 changestates = zip(states, 'MAR!?IC', stat)
5281
5281
5282 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5282 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5283 copy = copies.pathcopies(repo[node1], repo[node2])
5283 copy = copies.pathcopies(repo[node1], repo[node2])
5284
5284
5285 fm = ui.formatter('status', opts)
5285 fm = ui.formatter('status', opts)
5286 fmt = '%s' + end
5286 fmt = '%s' + end
5287 showchar = not opts.get('no_status')
5287 showchar = not opts.get('no_status')
5288
5288
5289 for state, char, files in changestates:
5289 for state, char, files in changestates:
5290 if state in show:
5290 if state in show:
5291 label = 'status.' + state
5291 label = 'status.' + state
5292 for f in files:
5292 for f in files:
5293 fm.startitem()
5293 fm.startitem()
5294 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5294 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5295 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5295 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5296 if f in copy:
5296 if f in copy:
5297 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5297 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5298 label='status.copied')
5298 label='status.copied')
5299 fm.end()
5299 fm.end()
5300
5300
5301 @command('^summary|sum',
5301 @command('^summary|sum',
5302 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5302 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5303 def summary(ui, repo, **opts):
5303 def summary(ui, repo, **opts):
5304 """summarize working directory state
5304 """summarize working directory state
5305
5305
5306 This generates a brief summary of the working directory state,
5306 This generates a brief summary of the working directory state,
5307 including parents, branch, commit status, and available updates.
5307 including parents, branch, commit status, and available updates.
5308
5308
5309 With the --remote option, this will check the default paths for
5309 With the --remote option, this will check the default paths for
5310 incoming and outgoing changes. This can be time-consuming.
5310 incoming and outgoing changes. This can be time-consuming.
5311
5311
5312 Returns 0 on success.
5312 Returns 0 on success.
5313 """
5313 """
5314
5314
5315 ctx = repo[None]
5315 ctx = repo[None]
5316 parents = ctx.parents()
5316 parents = ctx.parents()
5317 pnode = parents[0].node()
5317 pnode = parents[0].node()
5318 marks = []
5318 marks = []
5319
5319
5320 for p in parents:
5320 for p in parents:
5321 # label with log.changeset (instead of log.parent) since this
5321 # label with log.changeset (instead of log.parent) since this
5322 # shows a working directory parent *changeset*:
5322 # shows a working directory parent *changeset*:
5323 # i18n: column positioning for "hg summary"
5323 # i18n: column positioning for "hg summary"
5324 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5324 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5325 label='log.changeset changeset.%s' % p.phasestr())
5325 label='log.changeset changeset.%s' % p.phasestr())
5326 ui.write(' '.join(p.tags()), label='log.tag')
5326 ui.write(' '.join(p.tags()), label='log.tag')
5327 if p.bookmarks():
5327 if p.bookmarks():
5328 marks.extend(p.bookmarks())
5328 marks.extend(p.bookmarks())
5329 if p.rev() == -1:
5329 if p.rev() == -1:
5330 if not len(repo):
5330 if not len(repo):
5331 ui.write(_(' (empty repository)'))
5331 ui.write(_(' (empty repository)'))
5332 else:
5332 else:
5333 ui.write(_(' (no revision checked out)'))
5333 ui.write(_(' (no revision checked out)'))
5334 ui.write('\n')
5334 ui.write('\n')
5335 if p.description():
5335 if p.description():
5336 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5336 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5337 label='log.summary')
5337 label='log.summary')
5338
5338
5339 branch = ctx.branch()
5339 branch = ctx.branch()
5340 bheads = repo.branchheads(branch)
5340 bheads = repo.branchheads(branch)
5341 # i18n: column positioning for "hg summary"
5341 # i18n: column positioning for "hg summary"
5342 m = _('branch: %s\n') % branch
5342 m = _('branch: %s\n') % branch
5343 if branch != 'default':
5343 if branch != 'default':
5344 ui.write(m, label='log.branch')
5344 ui.write(m, label='log.branch')
5345 else:
5345 else:
5346 ui.status(m, label='log.branch')
5346 ui.status(m, label='log.branch')
5347
5347
5348 if marks:
5348 if marks:
5349 current = repo._bookmarkcurrent
5349 current = repo._bookmarkcurrent
5350 # i18n: column positioning for "hg summary"
5350 # i18n: column positioning for "hg summary"
5351 ui.write(_('bookmarks:'), label='log.bookmark')
5351 ui.write(_('bookmarks:'), label='log.bookmark')
5352 if current is not None:
5352 if current is not None:
5353 if current in marks:
5353 if current in marks:
5354 ui.write(' *' + current, label='bookmarks.current')
5354 ui.write(' *' + current, label='bookmarks.current')
5355 marks.remove(current)
5355 marks.remove(current)
5356 else:
5356 else:
5357 ui.write(' [%s]' % current, label='bookmarks.current')
5357 ui.write(' [%s]' % current, label='bookmarks.current')
5358 for m in marks:
5358 for m in marks:
5359 ui.write(' ' + m, label='log.bookmark')
5359 ui.write(' ' + m, label='log.bookmark')
5360 ui.write('\n', label='log.bookmark')
5360 ui.write('\n', label='log.bookmark')
5361
5361
5362 st = list(repo.status(unknown=True))[:6]
5362 st = list(repo.status(unknown=True))[:6]
5363
5363
5364 c = repo.dirstate.copies()
5364 c = repo.dirstate.copies()
5365 copied, renamed = [], []
5365 copied, renamed = [], []
5366 for d, s in c.iteritems():
5366 for d, s in c.iteritems():
5367 if s in st[2]:
5367 if s in st[2]:
5368 st[2].remove(s)
5368 st[2].remove(s)
5369 renamed.append(d)
5369 renamed.append(d)
5370 else:
5370 else:
5371 copied.append(d)
5371 copied.append(d)
5372 if d in st[1]:
5372 if d in st[1]:
5373 st[1].remove(d)
5373 st[1].remove(d)
5374 st.insert(3, renamed)
5374 st.insert(3, renamed)
5375 st.insert(4, copied)
5375 st.insert(4, copied)
5376
5376
5377 ms = mergemod.mergestate(repo)
5377 ms = mergemod.mergestate(repo)
5378 st.append([f for f in ms if ms[f] == 'u'])
5378 st.append([f for f in ms if ms[f] == 'u'])
5379
5379
5380 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5380 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5381 st.append(subs)
5381 st.append(subs)
5382
5382
5383 labels = [ui.label(_('%d modified'), 'status.modified'),
5383 labels = [ui.label(_('%d modified'), 'status.modified'),
5384 ui.label(_('%d added'), 'status.added'),
5384 ui.label(_('%d added'), 'status.added'),
5385 ui.label(_('%d removed'), 'status.removed'),
5385 ui.label(_('%d removed'), 'status.removed'),
5386 ui.label(_('%d renamed'), 'status.copied'),
5386 ui.label(_('%d renamed'), 'status.copied'),
5387 ui.label(_('%d copied'), 'status.copied'),
5387 ui.label(_('%d copied'), 'status.copied'),
5388 ui.label(_('%d deleted'), 'status.deleted'),
5388 ui.label(_('%d deleted'), 'status.deleted'),
5389 ui.label(_('%d unknown'), 'status.unknown'),
5389 ui.label(_('%d unknown'), 'status.unknown'),
5390 ui.label(_('%d ignored'), 'status.ignored'),
5390 ui.label(_('%d ignored'), 'status.ignored'),
5391 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5391 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5392 ui.label(_('%d subrepos'), 'status.modified')]
5392 ui.label(_('%d subrepos'), 'status.modified')]
5393 t = []
5393 t = []
5394 for s, l in zip(st, labels):
5394 for s, l in zip(st, labels):
5395 if s:
5395 if s:
5396 t.append(l % len(s))
5396 t.append(l % len(s))
5397
5397
5398 t = ', '.join(t)
5398 t = ', '.join(t)
5399 cleanworkdir = False
5399 cleanworkdir = False
5400
5400
5401 if len(parents) > 1:
5401 if len(parents) > 1:
5402 t += _(' (merge)')
5402 t += _(' (merge)')
5403 elif branch != parents[0].branch():
5403 elif branch != parents[0].branch():
5404 t += _(' (new branch)')
5404 t += _(' (new branch)')
5405 elif (parents[0].closesbranch() and
5405 elif (parents[0].closesbranch() and
5406 pnode in repo.branchheads(branch, closed=True)):
5406 pnode in repo.branchheads(branch, closed=True)):
5407 t += _(' (head closed)')
5407 t += _(' (head closed)')
5408 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5408 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5409 t += _(' (clean)')
5409 t += _(' (clean)')
5410 cleanworkdir = True
5410 cleanworkdir = True
5411 elif pnode not in bheads:
5411 elif pnode not in bheads:
5412 t += _(' (new branch head)')
5412 t += _(' (new branch head)')
5413
5413
5414 if cleanworkdir:
5414 if cleanworkdir:
5415 # i18n: column positioning for "hg summary"
5415 # i18n: column positioning for "hg summary"
5416 ui.status(_('commit: %s\n') % t.strip())
5416 ui.status(_('commit: %s\n') % t.strip())
5417 else:
5417 else:
5418 # i18n: column positioning for "hg summary"
5418 # i18n: column positioning for "hg summary"
5419 ui.write(_('commit: %s\n') % t.strip())
5419 ui.write(_('commit: %s\n') % t.strip())
5420
5420
5421 # all ancestors of branch heads - all ancestors of parent = new csets
5421 # all ancestors of branch heads - all ancestors of parent = new csets
5422 new = [0] * len(repo)
5422 new = [0] * len(repo)
5423 cl = repo.changelog
5423 cl = repo.changelog
5424 for a in [cl.rev(n) for n in bheads]:
5424 for a in [cl.rev(n) for n in bheads]:
5425 new[a] = 1
5425 new[a] = 1
5426 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5426 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5427 new[a] = 1
5427 new[a] = 1
5428 for a in [p.rev() for p in parents]:
5428 for a in [p.rev() for p in parents]:
5429 if a >= 0:
5429 if a >= 0:
5430 new[a] = 0
5430 new[a] = 0
5431 for a in cl.ancestors([p.rev() for p in parents]):
5431 for a in cl.ancestors([p.rev() for p in parents]):
5432 new[a] = 0
5432 new[a] = 0
5433 new = sum(new)
5433 new = sum(new)
5434
5434
5435 if new == 0:
5435 if new == 0:
5436 # i18n: column positioning for "hg summary"
5436 # i18n: column positioning for "hg summary"
5437 ui.status(_('update: (current)\n'))
5437 ui.status(_('update: (current)\n'))
5438 elif pnode not in bheads:
5438 elif pnode not in bheads:
5439 # i18n: column positioning for "hg summary"
5439 # i18n: column positioning for "hg summary"
5440 ui.write(_('update: %d new changesets (update)\n') % new)
5440 ui.write(_('update: %d new changesets (update)\n') % new)
5441 else:
5441 else:
5442 # i18n: column positioning for "hg summary"
5442 # i18n: column positioning for "hg summary"
5443 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5443 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5444 (new, len(bheads)))
5444 (new, len(bheads)))
5445
5445
5446 if opts.get('remote'):
5446 if opts.get('remote'):
5447 t = []
5447 t = []
5448 source, branches = hg.parseurl(ui.expandpath('default'))
5448 source, branches = hg.parseurl(ui.expandpath('default'))
5449 other = hg.peer(repo, {}, source)
5449 other = hg.peer(repo, {}, source)
5450 revs, checkout = hg.addbranchrevs(repo, other, branches,
5450 revs, checkout = hg.addbranchrevs(repo, other, branches,
5451 opts.get('rev'))
5451 opts.get('rev'))
5452 ui.debug('comparing with %s\n' % util.hidepassword(source))
5452 ui.debug('comparing with %s\n' % util.hidepassword(source))
5453 repo.ui.pushbuffer()
5453 repo.ui.pushbuffer()
5454 commoninc = discovery.findcommonincoming(repo, other)
5454 commoninc = discovery.findcommonincoming(repo, other)
5455 _common, incoming, _rheads = commoninc
5455 _common, incoming, _rheads = commoninc
5456 repo.ui.popbuffer()
5456 repo.ui.popbuffer()
5457 if incoming:
5457 if incoming:
5458 t.append(_('1 or more incoming'))
5458 t.append(_('1 or more incoming'))
5459
5459
5460 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5460 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5461 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5461 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5462 if source != dest:
5462 if source != dest:
5463 other = hg.peer(repo, {}, dest)
5463 other = hg.peer(repo, {}, dest)
5464 commoninc = None
5464 commoninc = None
5465 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5465 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5466 repo.ui.pushbuffer()
5466 repo.ui.pushbuffer()
5467 outgoing = discovery.findcommonoutgoing(repo, other,
5467 outgoing = discovery.findcommonoutgoing(repo, other,
5468 commoninc=commoninc)
5468 commoninc=commoninc)
5469 repo.ui.popbuffer()
5469 repo.ui.popbuffer()
5470 o = outgoing.missing
5470 o = outgoing.missing
5471 if o:
5471 if o:
5472 t.append(_('%d outgoing') % len(o))
5472 t.append(_('%d outgoing') % len(o))
5473 if 'bookmarks' in other.listkeys('namespaces'):
5473 if 'bookmarks' in other.listkeys('namespaces'):
5474 lmarks = repo.listkeys('bookmarks')
5474 lmarks = repo.listkeys('bookmarks')
5475 rmarks = other.listkeys('bookmarks')
5475 rmarks = other.listkeys('bookmarks')
5476 diff = set(rmarks) - set(lmarks)
5476 diff = set(rmarks) - set(lmarks)
5477 if len(diff) > 0:
5477 if len(diff) > 0:
5478 t.append(_('%d incoming bookmarks') % len(diff))
5478 t.append(_('%d incoming bookmarks') % len(diff))
5479 diff = set(lmarks) - set(rmarks)
5479 diff = set(lmarks) - set(rmarks)
5480 if len(diff) > 0:
5480 if len(diff) > 0:
5481 t.append(_('%d outgoing bookmarks') % len(diff))
5481 t.append(_('%d outgoing bookmarks') % len(diff))
5482
5482
5483 if t:
5483 if t:
5484 # i18n: column positioning for "hg summary"
5484 # i18n: column positioning for "hg summary"
5485 ui.write(_('remote: %s\n') % (', '.join(t)))
5485 ui.write(_('remote: %s\n') % (', '.join(t)))
5486 else:
5486 else:
5487 # i18n: column positioning for "hg summary"
5487 # i18n: column positioning for "hg summary"
5488 ui.status(_('remote: (synced)\n'))
5488 ui.status(_('remote: (synced)\n'))
5489
5489
5490 @command('tag',
5490 @command('tag',
5491 [('f', 'force', None, _('force tag')),
5491 [('f', 'force', None, _('force tag')),
5492 ('l', 'local', None, _('make the tag local')),
5492 ('l', 'local', None, _('make the tag local')),
5493 ('r', 'rev', '', _('revision to tag'), _('REV')),
5493 ('r', 'rev', '', _('revision to tag'), _('REV')),
5494 ('', 'remove', None, _('remove a tag')),
5494 ('', 'remove', None, _('remove a tag')),
5495 # -l/--local is already there, commitopts cannot be used
5495 # -l/--local is already there, commitopts cannot be used
5496 ('e', 'edit', None, _('edit commit message')),
5496 ('e', 'edit', None, _('edit commit message')),
5497 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5497 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5498 ] + commitopts2,
5498 ] + commitopts2,
5499 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5499 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5500 def tag(ui, repo, name1, *names, **opts):
5500 def tag(ui, repo, name1, *names, **opts):
5501 """add one or more tags for the current or given revision
5501 """add one or more tags for the current or given revision
5502
5502
5503 Name a particular revision using <name>.
5503 Name a particular revision using <name>.
5504
5504
5505 Tags are used to name particular revisions of the repository and are
5505 Tags are used to name particular revisions of the repository and are
5506 very useful to compare different revisions, to go back to significant
5506 very useful to compare different revisions, to go back to significant
5507 earlier versions or to mark branch points as releases, etc. Changing
5507 earlier versions or to mark branch points as releases, etc. Changing
5508 an existing tag is normally disallowed; use -f/--force to override.
5508 an existing tag is normally disallowed; use -f/--force to override.
5509
5509
5510 If no revision is given, the parent of the working directory is
5510 If no revision is given, the parent of the working directory is
5511 used, or tip if no revision is checked out.
5511 used, or tip if no revision is checked out.
5512
5512
5513 To facilitate version control, distribution, and merging of tags,
5513 To facilitate version control, distribution, and merging of tags,
5514 they are stored as a file named ".hgtags" which is managed similarly
5514 they are stored as a file named ".hgtags" which is managed similarly
5515 to other project files and can be hand-edited if necessary. This
5515 to other project files and can be hand-edited if necessary. This
5516 also means that tagging creates a new commit. The file
5516 also means that tagging creates a new commit. The file
5517 ".hg/localtags" is used for local tags (not shared among
5517 ".hg/localtags" is used for local tags (not shared among
5518 repositories).
5518 repositories).
5519
5519
5520 Tag commits are usually made at the head of a branch. If the parent
5520 Tag commits are usually made at the head of a branch. If the parent
5521 of the working directory is not a branch head, :hg:`tag` aborts; use
5521 of the working directory is not a branch head, :hg:`tag` aborts; use
5522 -f/--force to force the tag commit to be based on a non-head
5522 -f/--force to force the tag commit to be based on a non-head
5523 changeset.
5523 changeset.
5524
5524
5525 See :hg:`help dates` for a list of formats valid for -d/--date.
5525 See :hg:`help dates` for a list of formats valid for -d/--date.
5526
5526
5527 Since tag names have priority over branch names during revision
5527 Since tag names have priority over branch names during revision
5528 lookup, using an existing branch name as a tag name is discouraged.
5528 lookup, using an existing branch name as a tag name is discouraged.
5529
5529
5530 Returns 0 on success.
5530 Returns 0 on success.
5531 """
5531 """
5532 wlock = lock = None
5532 wlock = lock = None
5533 try:
5533 try:
5534 wlock = repo.wlock()
5534 wlock = repo.wlock()
5535 lock = repo.lock()
5535 lock = repo.lock()
5536 rev_ = "."
5536 rev_ = "."
5537 names = [t.strip() for t in (name1,) + names]
5537 names = [t.strip() for t in (name1,) + names]
5538 if len(names) != len(set(names)):
5538 if len(names) != len(set(names)):
5539 raise util.Abort(_('tag names must be unique'))
5539 raise util.Abort(_('tag names must be unique'))
5540 for n in names:
5540 for n in names:
5541 scmutil.checknewlabel(repo, n, 'tag')
5541 scmutil.checknewlabel(repo, n, 'tag')
5542 if not n:
5542 if not n:
5543 raise util.Abort(_('tag names cannot consist entirely of '
5543 raise util.Abort(_('tag names cannot consist entirely of '
5544 'whitespace'))
5544 'whitespace'))
5545 if opts.get('rev') and opts.get('remove'):
5545 if opts.get('rev') and opts.get('remove'):
5546 raise util.Abort(_("--rev and --remove are incompatible"))
5546 raise util.Abort(_("--rev and --remove are incompatible"))
5547 if opts.get('rev'):
5547 if opts.get('rev'):
5548 rev_ = opts['rev']
5548 rev_ = opts['rev']
5549 message = opts.get('message')
5549 message = opts.get('message')
5550 if opts.get('remove'):
5550 if opts.get('remove'):
5551 expectedtype = opts.get('local') and 'local' or 'global'
5551 expectedtype = opts.get('local') and 'local' or 'global'
5552 for n in names:
5552 for n in names:
5553 if not repo.tagtype(n):
5553 if not repo.tagtype(n):
5554 raise util.Abort(_("tag '%s' does not exist") % n)
5554 raise util.Abort(_("tag '%s' does not exist") % n)
5555 if repo.tagtype(n) != expectedtype:
5555 if repo.tagtype(n) != expectedtype:
5556 if expectedtype == 'global':
5556 if expectedtype == 'global':
5557 raise util.Abort(_("tag '%s' is not a global tag") % n)
5557 raise util.Abort(_("tag '%s' is not a global tag") % n)
5558 else:
5558 else:
5559 raise util.Abort(_("tag '%s' is not a local tag") % n)
5559 raise util.Abort(_("tag '%s' is not a local tag") % n)
5560 rev_ = nullid
5560 rev_ = nullid
5561 if not message:
5561 if not message:
5562 # we don't translate commit messages
5562 # we don't translate commit messages
5563 message = 'Removed tag %s' % ', '.join(names)
5563 message = 'Removed tag %s' % ', '.join(names)
5564 elif not opts.get('force'):
5564 elif not opts.get('force'):
5565 for n in names:
5565 for n in names:
5566 if n in repo.tags():
5566 if n in repo.tags():
5567 raise util.Abort(_("tag '%s' already exists "
5567 raise util.Abort(_("tag '%s' already exists "
5568 "(use -f to force)") % n)
5568 "(use -f to force)") % n)
5569 if not opts.get('local'):
5569 if not opts.get('local'):
5570 p1, p2 = repo.dirstate.parents()
5570 p1, p2 = repo.dirstate.parents()
5571 if p2 != nullid:
5571 if p2 != nullid:
5572 raise util.Abort(_('uncommitted merge'))
5572 raise util.Abort(_('uncommitted merge'))
5573 bheads = repo.branchheads()
5573 bheads = repo.branchheads()
5574 if not opts.get('force') and bheads and p1 not in bheads:
5574 if not opts.get('force') and bheads and p1 not in bheads:
5575 raise util.Abort(_('not at a branch head (use -f to force)'))
5575 raise util.Abort(_('not at a branch head (use -f to force)'))
5576 r = scmutil.revsingle(repo, rev_).node()
5576 r = scmutil.revsingle(repo, rev_).node()
5577
5577
5578 if not message:
5578 if not message:
5579 # we don't translate commit messages
5579 # we don't translate commit messages
5580 message = ('Added tag %s for changeset %s' %
5580 message = ('Added tag %s for changeset %s' %
5581 (', '.join(names), short(r)))
5581 (', '.join(names), short(r)))
5582
5582
5583 date = opts.get('date')
5583 date = opts.get('date')
5584 if date:
5584 if date:
5585 date = util.parsedate(date)
5585 date = util.parsedate(date)
5586
5586
5587 if opts.get('edit'):
5587 if opts.get('edit'):
5588 message = ui.edit(message, ui.username())
5588 message = ui.edit(message, ui.username())
5589
5589
5590 # don't allow tagging the null rev
5590 # don't allow tagging the null rev
5591 if (not opts.get('remove') and
5591 if (not opts.get('remove') and
5592 scmutil.revsingle(repo, rev_).rev() == nullrev):
5592 scmutil.revsingle(repo, rev_).rev() == nullrev):
5593 raise util.Abort(_("null revision specified"))
5593 raise util.Abort(_("null revision specified"))
5594
5594
5595 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5595 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5596 finally:
5596 finally:
5597 release(lock, wlock)
5597 release(lock, wlock)
5598
5598
5599 @command('tags', [], '')
5599 @command('tags', [], '')
5600 def tags(ui, repo, **opts):
5600 def tags(ui, repo, **opts):
5601 """list repository tags
5601 """list repository tags
5602
5602
5603 This lists both regular and local tags. When the -v/--verbose
5603 This lists both regular and local tags. When the -v/--verbose
5604 switch is used, a third column "local" is printed for local tags.
5604 switch is used, a third column "local" is printed for local tags.
5605
5605
5606 Returns 0 on success.
5606 Returns 0 on success.
5607 """
5607 """
5608
5608
5609 fm = ui.formatter('tags', opts)
5609 fm = ui.formatter('tags', opts)
5610 hexfunc = ui.debugflag and hex or short
5610 hexfunc = ui.debugflag and hex or short
5611 tagtype = ""
5611 tagtype = ""
5612
5612
5613 for t, n in reversed(repo.tagslist()):
5613 for t, n in reversed(repo.tagslist()):
5614 hn = hexfunc(n)
5614 hn = hexfunc(n)
5615 label = 'tags.normal'
5615 label = 'tags.normal'
5616 tagtype = ''
5616 tagtype = ''
5617 if repo.tagtype(t) == 'local':
5617 if repo.tagtype(t) == 'local':
5618 label = 'tags.local'
5618 label = 'tags.local'
5619 tagtype = 'local'
5619 tagtype = 'local'
5620
5620
5621 fm.startitem()
5621 fm.startitem()
5622 fm.write('tag', '%s', t, label=label)
5622 fm.write('tag', '%s', t, label=label)
5623 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5623 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5624 fm.condwrite(not ui.quiet, 'rev id', fmt,
5624 fm.condwrite(not ui.quiet, 'rev id', fmt,
5625 repo.changelog.rev(n), hn, label=label)
5625 repo.changelog.rev(n), hn, label=label)
5626 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5626 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5627 tagtype, label=label)
5627 tagtype, label=label)
5628 fm.plain('\n')
5628 fm.plain('\n')
5629 fm.end()
5629 fm.end()
5630
5630
5631 @command('tip',
5631 @command('tip',
5632 [('p', 'patch', None, _('show patch')),
5632 [('p', 'patch', None, _('show patch')),
5633 ('g', 'git', None, _('use git extended diff format')),
5633 ('g', 'git', None, _('use git extended diff format')),
5634 ] + templateopts,
5634 ] + templateopts,
5635 _('[-p] [-g]'))
5635 _('[-p] [-g]'))
5636 def tip(ui, repo, **opts):
5636 def tip(ui, repo, **opts):
5637 """show the tip revision
5637 """show the tip revision
5638
5638
5639 The tip revision (usually just called the tip) is the changeset
5639 The tip revision (usually just called the tip) is the changeset
5640 most recently added to the repository (and therefore the most
5640 most recently added to the repository (and therefore the most
5641 recently changed head).
5641 recently changed head).
5642
5642
5643 If you have just made a commit, that commit will be the tip. If
5643 If you have just made a commit, that commit will be the tip. If
5644 you have just pulled changes from another repository, the tip of
5644 you have just pulled changes from another repository, the tip of
5645 that repository becomes the current tip. The "tip" tag is special
5645 that repository becomes the current tip. The "tip" tag is special
5646 and cannot be renamed or assigned to a different changeset.
5646 and cannot be renamed or assigned to a different changeset.
5647
5647
5648 Returns 0 on success.
5648 Returns 0 on success.
5649 """
5649 """
5650 displayer = cmdutil.show_changeset(ui, repo, opts)
5650 displayer = cmdutil.show_changeset(ui, repo, opts)
5651 displayer.show(repo['tip'])
5651 displayer.show(repo['tip'])
5652 displayer.close()
5652 displayer.close()
5653
5653
5654 @command('unbundle',
5654 @command('unbundle',
5655 [('u', 'update', None,
5655 [('u', 'update', None,
5656 _('update to new branch head if changesets were unbundled'))],
5656 _('update to new branch head if changesets were unbundled'))],
5657 _('[-u] FILE...'))
5657 _('[-u] FILE...'))
5658 def unbundle(ui, repo, fname1, *fnames, **opts):
5658 def unbundle(ui, repo, fname1, *fnames, **opts):
5659 """apply one or more changegroup files
5659 """apply one or more changegroup files
5660
5660
5661 Apply one or more compressed changegroup files generated by the
5661 Apply one or more compressed changegroup files generated by the
5662 bundle command.
5662 bundle command.
5663
5663
5664 Returns 0 on success, 1 if an update has unresolved files.
5664 Returns 0 on success, 1 if an update has unresolved files.
5665 """
5665 """
5666 fnames = (fname1,) + fnames
5666 fnames = (fname1,) + fnames
5667
5667
5668 lock = repo.lock()
5668 lock = repo.lock()
5669 wc = repo['.']
5669 wc = repo['.']
5670 try:
5670 try:
5671 for fname in fnames:
5671 for fname in fnames:
5672 f = hg.openpath(ui, fname)
5672 f = hg.openpath(ui, fname)
5673 gen = changegroup.readbundle(f, fname)
5673 gen = changegroup.readbundle(f, fname)
5674 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5674 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5675 finally:
5675 finally:
5676 lock.release()
5676 lock.release()
5677 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5677 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5678 return postincoming(ui, repo, modheads, opts.get('update'), None)
5678 return postincoming(ui, repo, modheads, opts.get('update'), None)
5679
5679
5680 @command('^update|up|checkout|co',
5680 @command('^update|up|checkout|co',
5681 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5681 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5682 ('c', 'check', None,
5682 ('c', 'check', None,
5683 _('update across branches if no uncommitted changes')),
5683 _('update across branches if no uncommitted changes')),
5684 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5684 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5685 ('r', 'rev', '', _('revision'), _('REV'))],
5685 ('r', 'rev', '', _('revision'), _('REV'))],
5686 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5686 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5687 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5687 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5688 """update working directory (or switch revisions)
5688 """update working directory (or switch revisions)
5689
5689
5690 Update the repository's working directory to the specified
5690 Update the repository's working directory to the specified
5691 changeset. If no changeset is specified, update to the tip of the
5691 changeset. If no changeset is specified, update to the tip of the
5692 current named branch and move the current bookmark (see :hg:`help
5692 current named branch and move the current bookmark (see :hg:`help
5693 bookmarks`).
5693 bookmarks`).
5694
5694
5695 Update sets the working directory's parent revision to the specified
5695 Update sets the working directory's parent revision to the specified
5696 changeset (see :hg:`help parents`).
5696 changeset (see :hg:`help parents`).
5697
5697
5698 If the changeset is not a descendant or ancestor of the working
5698 If the changeset is not a descendant or ancestor of the working
5699 directory's parent, the update is aborted. With the -c/--check
5699 directory's parent, the update is aborted. With the -c/--check
5700 option, the working directory is checked for uncommitted changes; if
5700 option, the working directory is checked for uncommitted changes; if
5701 none are found, the working directory is updated to the specified
5701 none are found, the working directory is updated to the specified
5702 changeset.
5702 changeset.
5703
5703
5704 .. container:: verbose
5704 .. container:: verbose
5705
5705
5706 The following rules apply when the working directory contains
5706 The following rules apply when the working directory contains
5707 uncommitted changes:
5707 uncommitted changes:
5708
5708
5709 1. If neither -c/--check nor -C/--clean is specified, and if
5709 1. If neither -c/--check nor -C/--clean is specified, and if
5710 the requested changeset is an ancestor or descendant of
5710 the requested changeset is an ancestor or descendant of
5711 the working directory's parent, the uncommitted changes
5711 the working directory's parent, the uncommitted changes
5712 are merged into the requested changeset and the merged
5712 are merged into the requested changeset and the merged
5713 result is left uncommitted. If the requested changeset is
5713 result is left uncommitted. If the requested changeset is
5714 not an ancestor or descendant (that is, it is on another
5714 not an ancestor or descendant (that is, it is on another
5715 branch), the update is aborted and the uncommitted changes
5715 branch), the update is aborted and the uncommitted changes
5716 are preserved.
5716 are preserved.
5717
5717
5718 2. With the -c/--check option, the update is aborted and the
5718 2. With the -c/--check option, the update is aborted and the
5719 uncommitted changes are preserved.
5719 uncommitted changes are preserved.
5720
5720
5721 3. With the -C/--clean option, uncommitted changes are discarded and
5721 3. With the -C/--clean option, uncommitted changes are discarded and
5722 the working directory is updated to the requested changeset.
5722 the working directory is updated to the requested changeset.
5723
5723
5724 To cancel an uncommitted merge (and lose your changes), use
5724 To cancel an uncommitted merge (and lose your changes), use
5725 :hg:`update --clean .`.
5725 :hg:`update --clean .`.
5726
5726
5727 Use null as the changeset to remove the working directory (like
5727 Use null as the changeset to remove the working directory (like
5728 :hg:`clone -U`).
5728 :hg:`clone -U`).
5729
5729
5730 If you want to revert just one file to an older revision, use
5730 If you want to revert just one file to an older revision, use
5731 :hg:`revert [-r REV] NAME`.
5731 :hg:`revert [-r REV] NAME`.
5732
5732
5733 See :hg:`help dates` for a list of formats valid for -d/--date.
5733 See :hg:`help dates` for a list of formats valid for -d/--date.
5734
5734
5735 Returns 0 on success, 1 if there are unresolved files.
5735 Returns 0 on success, 1 if there are unresolved files.
5736 """
5736 """
5737 if rev and node:
5737 if rev and node:
5738 raise util.Abort(_("please specify just one revision"))
5738 raise util.Abort(_("please specify just one revision"))
5739
5739
5740 if rev is None or rev == '':
5740 if rev is None or rev == '':
5741 rev = node
5741 rev = node
5742
5742
5743 # with no argument, we also move the current bookmark, if any
5743 # with no argument, we also move the current bookmark, if any
5744 movemarkfrom = None
5744 movemarkfrom = None
5745 if rev is None:
5745 if rev is None:
5746 curmark = repo._bookmarkcurrent
5746 curmark = repo._bookmarkcurrent
5747 if bookmarks.iscurrent(repo):
5747 if bookmarks.iscurrent(repo):
5748 movemarkfrom = repo['.'].node()
5748 movemarkfrom = repo['.'].node()
5749 elif curmark:
5749 elif curmark:
5750 ui.status(_("updating to active bookmark %s\n") % curmark)
5750 ui.status(_("updating to active bookmark %s\n") % curmark)
5751 rev = curmark
5751 rev = curmark
5752
5752
5753 # if we defined a bookmark, we have to remember the original bookmark name
5753 # if we defined a bookmark, we have to remember the original bookmark name
5754 brev = rev
5754 brev = rev
5755 rev = scmutil.revsingle(repo, rev, rev).rev()
5755 rev = scmutil.revsingle(repo, rev, rev).rev()
5756
5756
5757 if check and clean:
5757 if check and clean:
5758 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5758 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5759
5759
5760 if date:
5760 if date:
5761 if rev is not None:
5761 if rev is not None:
5762 raise util.Abort(_("you can't specify a revision and a date"))
5762 raise util.Abort(_("you can't specify a revision and a date"))
5763 rev = cmdutil.finddate(ui, repo, date)
5763 rev = cmdutil.finddate(ui, repo, date)
5764
5764
5765 if check:
5765 if check:
5766 c = repo[None]
5766 c = repo[None]
5767 if c.dirty(merge=False, branch=False, missing=True):
5767 if c.dirty(merge=False, branch=False, missing=True):
5768 raise util.Abort(_("uncommitted local changes"))
5768 raise util.Abort(_("uncommitted local changes"))
5769 if rev is None:
5769 if rev is None:
5770 rev = repo[repo[None].branch()].rev()
5770 rev = repo[repo[None].branch()].rev()
5771 mergemod._checkunknown(repo, repo[None], repo[rev])
5771 mergemod._checkunknown(repo, repo[None], repo[rev])
5772
5772
5773 if clean:
5773 if clean:
5774 ret = hg.clean(repo, rev)
5774 ret = hg.clean(repo, rev)
5775 else:
5775 else:
5776 ret = hg.update(repo, rev)
5776 ret = hg.update(repo, rev)
5777
5777
5778 if not ret and movemarkfrom:
5778 if not ret and movemarkfrom:
5779 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5779 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5780 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5780 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5781 elif brev in repo._bookmarks:
5781 elif brev in repo._bookmarks:
5782 bookmarks.setcurrent(repo, brev)
5782 bookmarks.setcurrent(repo, brev)
5783 elif brev:
5783 elif brev:
5784 bookmarks.unsetcurrent(repo)
5784 bookmarks.unsetcurrent(repo)
5785
5785
5786 return ret
5786 return ret
5787
5787
5788 @command('verify', [])
5788 @command('verify', [])
5789 def verify(ui, repo):
5789 def verify(ui, repo):
5790 """verify the integrity of the repository
5790 """verify the integrity of the repository
5791
5791
5792 Verify the integrity of the current repository.
5792 Verify the integrity of the current repository.
5793
5793
5794 This will perform an extensive check of the repository's
5794 This will perform an extensive check of the repository's
5795 integrity, validating the hashes and checksums of each entry in
5795 integrity, validating the hashes and checksums of each entry in
5796 the changelog, manifest, and tracked files, as well as the
5796 the changelog, manifest, and tracked files, as well as the
5797 integrity of their crosslinks and indices.
5797 integrity of their crosslinks and indices.
5798
5798
5799 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5799 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5800 for more information about recovery from corruption of the
5800 for more information about recovery from corruption of the
5801 repository.
5801 repository.
5802
5802
5803 Returns 0 on success, 1 if errors are encountered.
5803 Returns 0 on success, 1 if errors are encountered.
5804 """
5804 """
5805 return hg.verify(repo)
5805 return hg.verify(repo)
5806
5806
5807 @command('version', [])
5807 @command('version', [])
5808 def version_(ui):
5808 def version_(ui):
5809 """output version and copyright information"""
5809 """output version and copyright information"""
5810 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5810 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5811 % util.version())
5811 % util.version())
5812 ui.status(_(
5812 ui.status(_(
5813 "(see http://mercurial.selenic.com for more information)\n"
5813 "(see http://mercurial.selenic.com for more information)\n"
5814 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5814 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5815 "This is free software; see the source for copying conditions. "
5815 "This is free software; see the source for copying conditions. "
5816 "There is NO\nwarranty; "
5816 "There is NO\nwarranty; "
5817 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5817 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5818 ))
5818 ))
5819
5819
5820 norepo = ("clone init version help debugcommands debugcomplete"
5820 norepo = ("clone init version help debugcommands debugcomplete"
5821 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5821 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5822 " debugknown debuggetbundle debugbundle")
5822 " debugknown debuggetbundle debugbundle")
5823 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5823 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5824 " debugdata debugindex debugindexdot debugrevlog")
5824 " debugdata debugindex debugindexdot debugrevlog")
5825 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5825 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5826 " remove resolve status debugwalk")
5826 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now