##// END OF EJS Templates
branches: avoid unnecessary changectx.branch() calls...
Brodie Rao -
r20182:04036798 default
parent child Browse files
Show More
@@ -1,5913 +1,5913 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, commandserver
15 import sshserver, hgweb, commandserver
16 from hgweb import server as hgweb_server
16 from hgweb import server as hgweb_server
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge, graphmod
19 import dagparser, context, simplemerge, graphmod
20 import random
20 import random
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import phases, obsolete
22 import phases, obsolete
23
23
24 table = {}
24 table = {}
25
25
26 command = cmdutil.command(table)
26 command = cmdutil.command(table)
27
27
28 # common command options
28 # common command options
29
29
30 globalopts = [
30 globalopts = [
31 ('R', 'repository', '',
31 ('R', 'repository', '',
32 _('repository root directory or name of overlay bundle file'),
32 _('repository root directory or name of overlay bundle file'),
33 _('REPO')),
33 _('REPO')),
34 ('', 'cwd', '',
34 ('', 'cwd', '',
35 _('change working directory'), _('DIR')),
35 _('change working directory'), _('DIR')),
36 ('y', 'noninteractive', None,
36 ('y', 'noninteractive', None,
37 _('do not prompt, automatically pick the first choice for all prompts')),
37 _('do not prompt, automatically pick the first choice for all prompts')),
38 ('q', 'quiet', None, _('suppress output')),
38 ('q', 'quiet', None, _('suppress output')),
39 ('v', 'verbose', None, _('enable additional output')),
39 ('v', 'verbose', None, _('enable additional output')),
40 ('', 'config', [],
40 ('', 'config', [],
41 _('set/override config option (use \'section.name=value\')'),
41 _('set/override config option (use \'section.name=value\')'),
42 _('CONFIG')),
42 _('CONFIG')),
43 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debugger', None, _('start debugger')),
44 ('', 'debugger', None, _('start debugger')),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 _('ENCODE')),
46 _('ENCODE')),
47 ('', 'encodingmode', encoding.encodingmode,
47 ('', 'encodingmode', encoding.encodingmode,
48 _('set the charset encoding mode'), _('MODE')),
48 _('set the charset encoding mode'), _('MODE')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'time', None, _('time how long the command takes')),
50 ('', 'time', None, _('time how long the command takes')),
51 ('', 'profile', None, _('print command execution profile')),
51 ('', 'profile', None, _('print command execution profile')),
52 ('', 'version', None, _('output version information and exit')),
52 ('', 'version', None, _('output version information and exit')),
53 ('h', 'help', None, _('display help and exit')),
53 ('h', 'help', None, _('display help and exit')),
54 ('', 'hidden', False, _('consider hidden changesets')),
54 ('', 'hidden', False, _('consider hidden changesets')),
55 ]
55 ]
56
56
57 dryrunopts = [('n', 'dry-run', None,
57 dryrunopts = [('n', 'dry-run', None,
58 _('do not perform actions, just print output'))]
58 _('do not perform actions, just print output'))]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 templateopts = [
90 templateopts = [
91 ('', 'style', '',
91 ('', 'style', '',
92 _('display using template map file'), _('STYLE')),
92 _('display using template map file'), _('STYLE')),
93 ('', 'template', '',
93 ('', 'template', '',
94 _('display with template'), _('TEMPLATE')),
94 _('display with template'), _('TEMPLATE')),
95 ]
95 ]
96
96
97 logopts = [
97 logopts = [
98 ('p', 'patch', None, _('show patch')),
98 ('p', 'patch', None, _('show patch')),
99 ('g', 'git', None, _('use git extended diff format')),
99 ('g', 'git', None, _('use git extended diff format')),
100 ('l', 'limit', '',
100 ('l', 'limit', '',
101 _('limit number of changes displayed'), _('NUM')),
101 _('limit number of changes displayed'), _('NUM')),
102 ('M', 'no-merges', None, _('do not show merges')),
102 ('M', 'no-merges', None, _('do not show merges')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('G', 'graph', None, _("show the revision DAG")),
104 ('G', 'graph', None, _("show the revision DAG")),
105 ] + templateopts
105 ] + templateopts
106
106
107 diffopts = [
107 diffopts = [
108 ('a', 'text', None, _('treat all files as text')),
108 ('a', 'text', None, _('treat all files as text')),
109 ('g', 'git', None, _('use git extended diff format')),
109 ('g', 'git', None, _('use git extended diff format')),
110 ('', 'nodates', None, _('omit dates from diff headers'))
110 ('', 'nodates', None, _('omit dates from diff headers'))
111 ]
111 ]
112
112
113 diffwsopts = [
113 diffwsopts = [
114 ('w', 'ignore-all-space', None,
114 ('w', 'ignore-all-space', None,
115 _('ignore white space when comparing lines')),
115 _('ignore white space when comparing lines')),
116 ('b', 'ignore-space-change', None,
116 ('b', 'ignore-space-change', None,
117 _('ignore changes in the amount of white space')),
117 _('ignore changes in the amount of white space')),
118 ('B', 'ignore-blank-lines', None,
118 ('B', 'ignore-blank-lines', None,
119 _('ignore changes whose lines are all blank')),
119 _('ignore changes whose lines are all blank')),
120 ]
120 ]
121
121
122 diffopts2 = [
122 diffopts2 = [
123 ('p', 'show-function', None, _('show which function each change is in')),
123 ('p', 'show-function', None, _('show which function each change is in')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ] + diffwsopts + [
125 ] + diffwsopts + [
126 ('U', 'unified', '',
126 ('U', 'unified', '',
127 _('number of lines of context to show'), _('NUM')),
127 _('number of lines of context to show'), _('NUM')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ]
129 ]
130
130
131 mergetoolopts = [
131 mergetoolopts = [
132 ('t', 'tool', '', _('specify merge tool')),
132 ('t', 'tool', '', _('specify merge tool')),
133 ]
133 ]
134
134
135 similarityopts = [
135 similarityopts = [
136 ('s', 'similarity', '',
136 ('s', 'similarity', '',
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 ]
138 ]
139
139
140 subrepoopts = [
140 subrepoopts = [
141 ('S', 'subrepos', None,
141 ('S', 'subrepos', None,
142 _('recurse into subrepositories'))
142 _('recurse into subrepositories'))
143 ]
143 ]
144
144
145 # Commands start here, listed alphabetically
145 # Commands start here, listed alphabetically
146
146
147 @command('^add',
147 @command('^add',
148 walkopts + subrepoopts + dryrunopts,
148 walkopts + subrepoopts + dryrunopts,
149 _('[OPTION]... [FILE]...'))
149 _('[OPTION]... [FILE]...'))
150 def add(ui, repo, *pats, **opts):
150 def add(ui, repo, *pats, **opts):
151 """add the specified files on the next commit
151 """add the specified files on the next commit
152
152
153 Schedule files to be version controlled and added to the
153 Schedule files to be version controlled and added to the
154 repository.
154 repository.
155
155
156 The files will be added to the repository at the next commit. To
156 The files will be added to the repository at the next commit. To
157 undo an add before that, see :hg:`forget`.
157 undo an add before that, see :hg:`forget`.
158
158
159 If no names are given, add all files to the repository.
159 If no names are given, add all files to the repository.
160
160
161 .. container:: verbose
161 .. container:: verbose
162
162
163 An example showing how new (unknown) files are added
163 An example showing how new (unknown) files are added
164 automatically by :hg:`add`::
164 automatically by :hg:`add`::
165
165
166 $ ls
166 $ ls
167 foo.c
167 foo.c
168 $ hg status
168 $ hg status
169 ? foo.c
169 ? foo.c
170 $ hg add
170 $ hg add
171 adding foo.c
171 adding foo.c
172 $ hg status
172 $ hg status
173 A foo.c
173 A foo.c
174
174
175 Returns 0 if all files are successfully added.
175 Returns 0 if all files are successfully added.
176 """
176 """
177
177
178 m = scmutil.match(repo[None], pats, opts)
178 m = scmutil.match(repo[None], pats, opts)
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 opts.get('subrepos'), prefix="", explicitonly=False)
180 opts.get('subrepos'), prefix="", explicitonly=False)
181 return rejected and 1 or 0
181 return rejected and 1 or 0
182
182
183 @command('addremove',
183 @command('addremove',
184 similarityopts + walkopts + dryrunopts,
184 similarityopts + walkopts + dryrunopts,
185 _('[OPTION]... [FILE]...'))
185 _('[OPTION]... [FILE]...'))
186 def addremove(ui, repo, *pats, **opts):
186 def addremove(ui, repo, *pats, **opts):
187 """add all new files, delete all missing files
187 """add all new files, delete all missing files
188
188
189 Add all new files and remove all missing files from the
189 Add all new files and remove all missing files from the
190 repository.
190 repository.
191
191
192 New files are ignored if they match any of the patterns in
192 New files are ignored if they match any of the patterns in
193 ``.hgignore``. As with add, these changes take effect at the next
193 ``.hgignore``. As with add, these changes take effect at the next
194 commit.
194 commit.
195
195
196 Use the -s/--similarity option to detect renamed files. This
196 Use the -s/--similarity option to detect renamed files. This
197 option takes a percentage between 0 (disabled) and 100 (files must
197 option takes a percentage between 0 (disabled) and 100 (files must
198 be identical) as its parameter. With a parameter greater than 0,
198 be identical) as its parameter. With a parameter greater than 0,
199 this compares every removed file with every added file and records
199 this compares every removed file with every added file and records
200 those similar enough as renames. Detecting renamed files this way
200 those similar enough as renames. Detecting renamed files this way
201 can be expensive. After using this option, :hg:`status -C` can be
201 can be expensive. After using this option, :hg:`status -C` can be
202 used to check which files were identified as moved or renamed. If
202 used to check which files were identified as moved or renamed. If
203 not specified, -s/--similarity defaults to 100 and only renames of
203 not specified, -s/--similarity defaults to 100 and only renames of
204 identical files are detected.
204 identical files are detected.
205
205
206 Returns 0 if all files are successfully added.
206 Returns 0 if all files are successfully added.
207 """
207 """
208 try:
208 try:
209 sim = float(opts.get('similarity') or 100)
209 sim = float(opts.get('similarity') or 100)
210 except ValueError:
210 except ValueError:
211 raise util.Abort(_('similarity must be a number'))
211 raise util.Abort(_('similarity must be a number'))
212 if sim < 0 or sim > 100:
212 if sim < 0 or sim > 100:
213 raise util.Abort(_('similarity must be between 0 and 100'))
213 raise util.Abort(_('similarity must be between 0 and 100'))
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215
215
216 @command('^annotate|blame',
216 @command('^annotate|blame',
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 ('', 'follow', None,
218 ('', 'follow', None,
219 _('follow copies/renames and list the filename (DEPRECATED)')),
219 _('follow copies/renames and list the filename (DEPRECATED)')),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('a', 'text', None, _('treat all files as text')),
221 ('a', 'text', None, _('treat all files as text')),
222 ('u', 'user', None, _('list the author (long with -v)')),
222 ('u', 'user', None, _('list the author (long with -v)')),
223 ('f', 'file', None, _('list the filename')),
223 ('f', 'file', None, _('list the filename')),
224 ('d', 'date', None, _('list the date (short with -q)')),
224 ('d', 'date', None, _('list the date (short with -q)')),
225 ('n', 'number', None, _('list the revision number (default)')),
225 ('n', 'number', None, _('list the revision number (default)')),
226 ('c', 'changeset', None, _('list the changeset')),
226 ('c', 'changeset', None, _('list the changeset')),
227 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ] + diffwsopts + walkopts,
228 ] + diffwsopts + walkopts,
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 def annotate(ui, repo, *pats, **opts):
230 def annotate(ui, repo, *pats, **opts):
231 """show changeset information by line for each file
231 """show changeset information by line for each file
232
232
233 List changes in files, showing the revision id responsible for
233 List changes in files, showing the revision id responsible for
234 each line
234 each line
235
235
236 This command is useful for discovering when a change was made and
236 This command is useful for discovering when a change was made and
237 by whom.
237 by whom.
238
238
239 Without the -a/--text option, annotate will avoid processing files
239 Without the -a/--text option, annotate will avoid processing files
240 it detects as binary. With -a, annotate will annotate the file
240 it detects as binary. With -a, annotate will annotate the file
241 anyway, although the results will probably be neither useful
241 anyway, although the results will probably be neither useful
242 nor desirable.
242 nor desirable.
243
243
244 Returns 0 on success.
244 Returns 0 on success.
245 """
245 """
246 if opts.get('follow'):
246 if opts.get('follow'):
247 # --follow is deprecated and now just an alias for -f/--file
247 # --follow is deprecated and now just an alias for -f/--file
248 # to mimic the behavior of Mercurial before version 1.5
248 # to mimic the behavior of Mercurial before version 1.5
249 opts['file'] = True
249 opts['file'] = True
250
250
251 datefunc = ui.quiet and util.shortdate or util.datestr
251 datefunc = ui.quiet and util.shortdate or util.datestr
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253
253
254 if not pats:
254 if not pats:
255 raise util.Abort(_('at least one filename or pattern is required'))
255 raise util.Abort(_('at least one filename or pattern is required'))
256
256
257 hexfn = ui.debugflag and hex or short
257 hexfn = ui.debugflag and hex or short
258
258
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 ('number', ' ', lambda x: str(x[0].rev())),
260 ('number', ' ', lambda x: str(x[0].rev())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('date', ' ', getdate),
262 ('date', ' ', getdate),
263 ('file', ' ', lambda x: x[0].path()),
263 ('file', ' ', lambda x: x[0].path()),
264 ('line_number', ':', lambda x: str(x[1])),
264 ('line_number', ':', lambda x: str(x[1])),
265 ]
265 ]
266
266
267 if (not opts.get('user') and not opts.get('changeset')
267 if (not opts.get('user') and not opts.get('changeset')
268 and not opts.get('date') and not opts.get('file')):
268 and not opts.get('date') and not opts.get('file')):
269 opts['number'] = True
269 opts['number'] = True
270
270
271 linenumber = opts.get('line_number') is not None
271 linenumber = opts.get('line_number') is not None
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
274
274
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277
277
278 def bad(x, y):
278 def bad(x, y):
279 raise util.Abort("%s: %s" % (x, y))
279 raise util.Abort("%s: %s" % (x, y))
280
280
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 m = scmutil.match(ctx, pats, opts)
282 m = scmutil.match(ctx, pats, opts)
283 m.bad = bad
283 m.bad = bad
284 follow = not opts.get('no_follow')
284 follow = not opts.get('no_follow')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
286 for abs in ctx.walk(m):
286 for abs in ctx.walk(m):
287 fctx = ctx[abs]
287 fctx = ctx[abs]
288 if not opts.get('text') and util.binary(fctx.data()):
288 if not opts.get('text') and util.binary(fctx.data()):
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 continue
290 continue
291
291
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 diffopts=diffopts)
293 diffopts=diffopts)
294 pieces = []
294 pieces = []
295
295
296 for f, sep in funcmap:
296 for f, sep in funcmap:
297 l = [f(n) for n, dummy in lines]
297 l = [f(n) for n, dummy in lines]
298 if l:
298 if l:
299 sized = [(x, encoding.colwidth(x)) for x in l]
299 sized = [(x, encoding.colwidth(x)) for x in l]
300 ml = max([w for x, w in sized])
300 ml = max([w for x, w in sized])
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 for x, w in sized])
302 for x, w in sized])
303
303
304 if pieces:
304 if pieces:
305 for p, l in zip(zip(*pieces), lines):
305 for p, l in zip(zip(*pieces), lines):
306 ui.write("%s: %s" % ("".join(p), l[1]))
306 ui.write("%s: %s" % ("".join(p), l[1]))
307
307
308 if lines and not lines[-1][1].endswith('\n'):
308 if lines and not lines[-1][1].endswith('\n'):
309 ui.write('\n')
309 ui.write('\n')
310
310
311 @command('archive',
311 @command('archive',
312 [('', 'no-decode', None, _('do not pass files through decoders')),
312 [('', 'no-decode', None, _('do not pass files through decoders')),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 _('PREFIX')),
314 _('PREFIX')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ] + subrepoopts + walkopts,
317 ] + subrepoopts + walkopts,
318 _('[OPTION]... DEST'))
318 _('[OPTION]... DEST'))
319 def archive(ui, repo, dest, **opts):
319 def archive(ui, repo, dest, **opts):
320 '''create an unversioned archive of a repository revision
320 '''create an unversioned archive of a repository revision
321
321
322 By default, the revision used is the parent of the working
322 By default, the revision used is the parent of the working
323 directory; use -r/--rev to specify a different revision.
323 directory; use -r/--rev to specify a different revision.
324
324
325 The archive type is automatically detected based on file
325 The archive type is automatically detected based on file
326 extension (or override using -t/--type).
326 extension (or override using -t/--type).
327
327
328 .. container:: verbose
328 .. container:: verbose
329
329
330 Examples:
330 Examples:
331
331
332 - create a zip file containing the 1.0 release::
332 - create a zip file containing the 1.0 release::
333
333
334 hg archive -r 1.0 project-1.0.zip
334 hg archive -r 1.0 project-1.0.zip
335
335
336 - create a tarball excluding .hg files::
336 - create a tarball excluding .hg files::
337
337
338 hg archive project.tar.gz -X ".hg*"
338 hg archive project.tar.gz -X ".hg*"
339
339
340 Valid types are:
340 Valid types are:
341
341
342 :``files``: a directory full of files (default)
342 :``files``: a directory full of files (default)
343 :``tar``: tar archive, uncompressed
343 :``tar``: tar archive, uncompressed
344 :``tbz2``: tar archive, compressed using bzip2
344 :``tbz2``: tar archive, compressed using bzip2
345 :``tgz``: tar archive, compressed using gzip
345 :``tgz``: tar archive, compressed using gzip
346 :``uzip``: zip archive, uncompressed
346 :``uzip``: zip archive, uncompressed
347 :``zip``: zip archive, compressed using deflate
347 :``zip``: zip archive, compressed using deflate
348
348
349 The exact name of the destination archive or directory is given
349 The exact name of the destination archive or directory is given
350 using a format string; see :hg:`help export` for details.
350 using a format string; see :hg:`help export` for details.
351
351
352 Each member added to an archive file has a directory prefix
352 Each member added to an archive file has a directory prefix
353 prepended. Use -p/--prefix to specify a format string for the
353 prepended. Use -p/--prefix to specify a format string for the
354 prefix. The default is the basename of the archive, with suffixes
354 prefix. The default is the basename of the archive, with suffixes
355 removed.
355 removed.
356
356
357 Returns 0 on success.
357 Returns 0 on success.
358 '''
358 '''
359
359
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 if not ctx:
361 if not ctx:
362 raise util.Abort(_('no working directory: please specify a revision'))
362 raise util.Abort(_('no working directory: please specify a revision'))
363 node = ctx.node()
363 node = ctx.node()
364 dest = cmdutil.makefilename(repo, dest, node)
364 dest = cmdutil.makefilename(repo, dest, node)
365 if os.path.realpath(dest) == repo.root:
365 if os.path.realpath(dest) == repo.root:
366 raise util.Abort(_('repository root cannot be destination'))
366 raise util.Abort(_('repository root cannot be destination'))
367
367
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 prefix = opts.get('prefix')
369 prefix = opts.get('prefix')
370
370
371 if dest == '-':
371 if dest == '-':
372 if kind == 'files':
372 if kind == 'files':
373 raise util.Abort(_('cannot archive plain files to stdout'))
373 raise util.Abort(_('cannot archive plain files to stdout'))
374 dest = cmdutil.makefileobj(repo, dest)
374 dest = cmdutil.makefileobj(repo, dest)
375 if not prefix:
375 if not prefix:
376 prefix = os.path.basename(repo.root) + '-%h'
376 prefix = os.path.basename(repo.root) + '-%h'
377
377
378 prefix = cmdutil.makefilename(repo, prefix, node)
378 prefix = cmdutil.makefilename(repo, prefix, node)
379 matchfn = scmutil.match(ctx, [], opts)
379 matchfn = scmutil.match(ctx, [], opts)
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 matchfn, prefix, subrepos=opts.get('subrepos'))
381 matchfn, prefix, subrepos=opts.get('subrepos'))
382
382
383 @command('backout',
383 @command('backout',
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 ('', 'parent', '',
385 ('', 'parent', '',
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 _('[OPTION]... [-r] REV'))
389 _('[OPTION]... [-r] REV'))
390 def backout(ui, repo, node=None, rev=None, **opts):
390 def backout(ui, repo, node=None, rev=None, **opts):
391 '''reverse effect of earlier changeset
391 '''reverse effect of earlier changeset
392
392
393 Prepare a new changeset with the effect of REV undone in the
393 Prepare a new changeset with the effect of REV undone in the
394 current working directory.
394 current working directory.
395
395
396 If REV is the parent of the working directory, then this new changeset
396 If REV is the parent of the working directory, then this new changeset
397 is committed automatically. Otherwise, hg needs to merge the
397 is committed automatically. Otherwise, hg needs to merge the
398 changes and the merged result is left uncommitted.
398 changes and the merged result is left uncommitted.
399
399
400 .. note::
400 .. note::
401
401
402 backout cannot be used to fix either an unwanted or
402 backout cannot be used to fix either an unwanted or
403 incorrect merge.
403 incorrect merge.
404
404
405 .. container:: verbose
405 .. container:: verbose
406
406
407 By default, the pending changeset will have one parent,
407 By default, the pending changeset will have one parent,
408 maintaining a linear history. With --merge, the pending
408 maintaining a linear history. With --merge, the pending
409 changeset will instead have two parents: the old parent of the
409 changeset will instead have two parents: the old parent of the
410 working directory and a new child of REV that simply undoes REV.
410 working directory and a new child of REV that simply undoes REV.
411
411
412 Before version 1.7, the behavior without --merge was equivalent
412 Before version 1.7, the behavior without --merge was equivalent
413 to specifying --merge followed by :hg:`update --clean .` to
413 to specifying --merge followed by :hg:`update --clean .` to
414 cancel the merge and leave the child of REV as a head to be
414 cancel the merge and leave the child of REV as a head to be
415 merged separately.
415 merged separately.
416
416
417 See :hg:`help dates` for a list of formats valid for -d/--date.
417 See :hg:`help dates` for a list of formats valid for -d/--date.
418
418
419 Returns 0 on success.
419 Returns 0 on success.
420 '''
420 '''
421 if rev and node:
421 if rev and node:
422 raise util.Abort(_("please specify just one revision"))
422 raise util.Abort(_("please specify just one revision"))
423
423
424 if not rev:
424 if not rev:
425 rev = node
425 rev = node
426
426
427 if not rev:
427 if not rev:
428 raise util.Abort(_("please specify a revision to backout"))
428 raise util.Abort(_("please specify a revision to backout"))
429
429
430 date = opts.get('date')
430 date = opts.get('date')
431 if date:
431 if date:
432 opts['date'] = util.parsedate(date)
432 opts['date'] = util.parsedate(date)
433
433
434 cmdutil.checkunfinished(repo)
434 cmdutil.checkunfinished(repo)
435 cmdutil.bailifchanged(repo)
435 cmdutil.bailifchanged(repo)
436 node = scmutil.revsingle(repo, rev).node()
436 node = scmutil.revsingle(repo, rev).node()
437
437
438 op1, op2 = repo.dirstate.parents()
438 op1, op2 = repo.dirstate.parents()
439 a = repo.changelog.ancestor(op1, node)
439 a = repo.changelog.ancestor(op1, node)
440 if a != node:
440 if a != node:
441 raise util.Abort(_('cannot backout change on a different branch'))
441 raise util.Abort(_('cannot backout change on a different branch'))
442
442
443 p1, p2 = repo.changelog.parents(node)
443 p1, p2 = repo.changelog.parents(node)
444 if p1 == nullid:
444 if p1 == nullid:
445 raise util.Abort(_('cannot backout a change with no parents'))
445 raise util.Abort(_('cannot backout a change with no parents'))
446 if p2 != nullid:
446 if p2 != nullid:
447 if not opts.get('parent'):
447 if not opts.get('parent'):
448 raise util.Abort(_('cannot backout a merge changeset'))
448 raise util.Abort(_('cannot backout a merge changeset'))
449 p = repo.lookup(opts['parent'])
449 p = repo.lookup(opts['parent'])
450 if p not in (p1, p2):
450 if p not in (p1, p2):
451 raise util.Abort(_('%s is not a parent of %s') %
451 raise util.Abort(_('%s is not a parent of %s') %
452 (short(p), short(node)))
452 (short(p), short(node)))
453 parent = p
453 parent = p
454 else:
454 else:
455 if opts.get('parent'):
455 if opts.get('parent'):
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 parent = p1
457 parent = p1
458
458
459 # the backout should appear on the same branch
459 # the backout should appear on the same branch
460 wlock = repo.wlock()
460 wlock = repo.wlock()
461 try:
461 try:
462 branch = repo.dirstate.branch()
462 branch = repo.dirstate.branch()
463 bheads = repo.branchheads(branch)
463 bheads = repo.branchheads(branch)
464 hg.clean(repo, node, show_stats=False)
464 hg.clean(repo, node, show_stats=False)
465 repo.dirstate.setbranch(branch)
465 repo.dirstate.setbranch(branch)
466 rctx = scmutil.revsingle(repo, hex(parent))
466 rctx = scmutil.revsingle(repo, hex(parent))
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
468 if not opts.get('merge') and op1 != node:
468 if not opts.get('merge') and op1 != node:
469 try:
469 try:
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
471 return hg.update(repo, op1)
471 return hg.update(repo, op1)
472 finally:
472 finally:
473 ui.setconfig('ui', 'forcemerge', '')
473 ui.setconfig('ui', 'forcemerge', '')
474
474
475 e = cmdutil.commiteditor
475 e = cmdutil.commiteditor
476 if not opts['message'] and not opts['logfile']:
476 if not opts['message'] and not opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 opts['message'] = "Backed out changeset %s" % short(node)
478 opts['message'] = "Backed out changeset %s" % short(node)
479 e = cmdutil.commitforceeditor
479 e = cmdutil.commitforceeditor
480
480
481 def commitfunc(ui, repo, message, match, opts):
481 def commitfunc(ui, repo, message, match, opts):
482 return repo.commit(message, opts.get('user'), opts.get('date'),
482 return repo.commit(message, opts.get('user'), opts.get('date'),
483 match, editor=e)
483 match, editor=e)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
486
486
487 def nice(node):
487 def nice(node):
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
489 ui.status(_('changeset %s backs out changeset %s\n') %
489 ui.status(_('changeset %s backs out changeset %s\n') %
490 (nice(repo.changelog.tip()), nice(node)))
490 (nice(repo.changelog.tip()), nice(node)))
491 if opts.get('merge') and op1 != node:
491 if opts.get('merge') and op1 != node:
492 hg.clean(repo, op1, show_stats=False)
492 hg.clean(repo, op1, show_stats=False)
493 ui.status(_('merging with changeset %s\n')
493 ui.status(_('merging with changeset %s\n')
494 % nice(repo.changelog.tip()))
494 % nice(repo.changelog.tip()))
495 try:
495 try:
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
497 return hg.merge(repo, hex(repo.changelog.tip()))
497 return hg.merge(repo, hex(repo.changelog.tip()))
498 finally:
498 finally:
499 ui.setconfig('ui', 'forcemerge', '')
499 ui.setconfig('ui', 'forcemerge', '')
500 finally:
500 finally:
501 wlock.release()
501 wlock.release()
502 return 0
502 return 0
503
503
504 @command('bisect',
504 @command('bisect',
505 [('r', 'reset', False, _('reset bisect state')),
505 [('r', 'reset', False, _('reset bisect state')),
506 ('g', 'good', False, _('mark changeset good')),
506 ('g', 'good', False, _('mark changeset good')),
507 ('b', 'bad', False, _('mark changeset bad')),
507 ('b', 'bad', False, _('mark changeset bad')),
508 ('s', 'skip', False, _('skip testing changeset')),
508 ('s', 'skip', False, _('skip testing changeset')),
509 ('e', 'extend', False, _('extend the bisect range')),
509 ('e', 'extend', False, _('extend the bisect range')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
511 ('U', 'noupdate', False, _('do not update to target'))],
511 ('U', 'noupdate', False, _('do not update to target'))],
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
513 def bisect(ui, repo, rev=None, extra=None, command=None,
513 def bisect(ui, repo, rev=None, extra=None, command=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
515 noupdate=None):
515 noupdate=None):
516 """subdivision search of changesets
516 """subdivision search of changesets
517
517
518 This command helps to find changesets which introduce problems. To
518 This command helps to find changesets which introduce problems. To
519 use, mark the earliest changeset you know exhibits the problem as
519 use, mark the earliest changeset you know exhibits the problem as
520 bad, then mark the latest changeset which is free from the problem
520 bad, then mark the latest changeset which is free from the problem
521 as good. Bisect will update your working directory to a revision
521 as good. Bisect will update your working directory to a revision
522 for testing (unless the -U/--noupdate option is specified). Once
522 for testing (unless the -U/--noupdate option is specified). Once
523 you have performed tests, mark the working directory as good or
523 you have performed tests, mark the working directory as good or
524 bad, and bisect will either update to another candidate changeset
524 bad, and bisect will either update to another candidate changeset
525 or announce that it has found the bad revision.
525 or announce that it has found the bad revision.
526
526
527 As a shortcut, you can also use the revision argument to mark a
527 As a shortcut, you can also use the revision argument to mark a
528 revision as good or bad without checking it out first.
528 revision as good or bad without checking it out first.
529
529
530 If you supply a command, it will be used for automatic bisection.
530 If you supply a command, it will be used for automatic bisection.
531 The environment variable HG_NODE will contain the ID of the
531 The environment variable HG_NODE will contain the ID of the
532 changeset being tested. The exit status of the command will be
532 changeset being tested. The exit status of the command will be
533 used to mark revisions as good or bad: status 0 means good, 125
533 used to mark revisions as good or bad: status 0 means good, 125
534 means to skip the revision, 127 (command not found) will abort the
534 means to skip the revision, 127 (command not found) will abort the
535 bisection, and any other non-zero exit status means the revision
535 bisection, and any other non-zero exit status means the revision
536 is bad.
536 is bad.
537
537
538 .. container:: verbose
538 .. container:: verbose
539
539
540 Some examples:
540 Some examples:
541
541
542 - start a bisection with known bad revision 34, and good revision 12::
542 - start a bisection with known bad revision 34, and good revision 12::
543
543
544 hg bisect --bad 34
544 hg bisect --bad 34
545 hg bisect --good 12
545 hg bisect --good 12
546
546
547 - advance the current bisection by marking current revision as good or
547 - advance the current bisection by marking current revision as good or
548 bad::
548 bad::
549
549
550 hg bisect --good
550 hg bisect --good
551 hg bisect --bad
551 hg bisect --bad
552
552
553 - mark the current revision, or a known revision, to be skipped (e.g. if
553 - mark the current revision, or a known revision, to be skipped (e.g. if
554 that revision is not usable because of another issue)::
554 that revision is not usable because of another issue)::
555
555
556 hg bisect --skip
556 hg bisect --skip
557 hg bisect --skip 23
557 hg bisect --skip 23
558
558
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
560
560
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
562
562
563 - forget the current bisection::
563 - forget the current bisection::
564
564
565 hg bisect --reset
565 hg bisect --reset
566
566
567 - use 'make && make tests' to automatically find the first broken
567 - use 'make && make tests' to automatically find the first broken
568 revision::
568 revision::
569
569
570 hg bisect --reset
570 hg bisect --reset
571 hg bisect --bad 34
571 hg bisect --bad 34
572 hg bisect --good 12
572 hg bisect --good 12
573 hg bisect --command "make && make tests"
573 hg bisect --command "make && make tests"
574
574
575 - see all changesets whose states are already known in the current
575 - see all changesets whose states are already known in the current
576 bisection::
576 bisection::
577
577
578 hg log -r "bisect(pruned)"
578 hg log -r "bisect(pruned)"
579
579
580 - see the changeset currently being bisected (especially useful
580 - see the changeset currently being bisected (especially useful
581 if running with -U/--noupdate)::
581 if running with -U/--noupdate)::
582
582
583 hg log -r "bisect(current)"
583 hg log -r "bisect(current)"
584
584
585 - see all changesets that took part in the current bisection::
585 - see all changesets that took part in the current bisection::
586
586
587 hg log -r "bisect(range)"
587 hg log -r "bisect(range)"
588
588
589 - you can even get a nice graph::
589 - you can even get a nice graph::
590
590
591 hg log --graph -r "bisect(range)"
591 hg log --graph -r "bisect(range)"
592
592
593 See :hg:`help revsets` for more about the `bisect()` keyword.
593 See :hg:`help revsets` for more about the `bisect()` keyword.
594
594
595 Returns 0 on success.
595 Returns 0 on success.
596 """
596 """
597 def extendbisectrange(nodes, good):
597 def extendbisectrange(nodes, good):
598 # bisect is incomplete when it ends on a merge node and
598 # bisect is incomplete when it ends on a merge node and
599 # one of the parent was not checked.
599 # one of the parent was not checked.
600 parents = repo[nodes[0]].parents()
600 parents = repo[nodes[0]].parents()
601 if len(parents) > 1:
601 if len(parents) > 1:
602 side = good and state['bad'] or state['good']
602 side = good and state['bad'] or state['good']
603 num = len(set(i.node() for i in parents) & set(side))
603 num = len(set(i.node() for i in parents) & set(side))
604 if num == 1:
604 if num == 1:
605 return parents[0].ancestor(parents[1])
605 return parents[0].ancestor(parents[1])
606 return None
606 return None
607
607
608 def print_result(nodes, good):
608 def print_result(nodes, good):
609 displayer = cmdutil.show_changeset(ui, repo, {})
609 displayer = cmdutil.show_changeset(ui, repo, {})
610 if len(nodes) == 1:
610 if len(nodes) == 1:
611 # narrowed it down to a single revision
611 # narrowed it down to a single revision
612 if good:
612 if good:
613 ui.write(_("The first good revision is:\n"))
613 ui.write(_("The first good revision is:\n"))
614 else:
614 else:
615 ui.write(_("The first bad revision is:\n"))
615 ui.write(_("The first bad revision is:\n"))
616 displayer.show(repo[nodes[0]])
616 displayer.show(repo[nodes[0]])
617 extendnode = extendbisectrange(nodes, good)
617 extendnode = extendbisectrange(nodes, good)
618 if extendnode is not None:
618 if extendnode is not None:
619 ui.write(_('Not all ancestors of this changeset have been'
619 ui.write(_('Not all ancestors of this changeset have been'
620 ' checked.\nUse bisect --extend to continue the '
620 ' checked.\nUse bisect --extend to continue the '
621 'bisection from\nthe common ancestor, %s.\n')
621 'bisection from\nthe common ancestor, %s.\n')
622 % extendnode)
622 % extendnode)
623 else:
623 else:
624 # multiple possible revisions
624 # multiple possible revisions
625 if good:
625 if good:
626 ui.write(_("Due to skipped revisions, the first "
626 ui.write(_("Due to skipped revisions, the first "
627 "good revision could be any of:\n"))
627 "good revision could be any of:\n"))
628 else:
628 else:
629 ui.write(_("Due to skipped revisions, the first "
629 ui.write(_("Due to skipped revisions, the first "
630 "bad revision could be any of:\n"))
630 "bad revision could be any of:\n"))
631 for n in nodes:
631 for n in nodes:
632 displayer.show(repo[n])
632 displayer.show(repo[n])
633 displayer.close()
633 displayer.close()
634
634
635 def check_state(state, interactive=True):
635 def check_state(state, interactive=True):
636 if not state['good'] or not state['bad']:
636 if not state['good'] or not state['bad']:
637 if (good or bad or skip or reset) and interactive:
637 if (good or bad or skip or reset) and interactive:
638 return
638 return
639 if not state['good']:
639 if not state['good']:
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
641 else:
641 else:
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
643 return True
643 return True
644
644
645 # backward compatibility
645 # backward compatibility
646 if rev in "good bad reset init".split():
646 if rev in "good bad reset init".split():
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
648 cmd, rev, extra = rev, extra, None
648 cmd, rev, extra = rev, extra, None
649 if cmd == "good":
649 if cmd == "good":
650 good = True
650 good = True
651 elif cmd == "bad":
651 elif cmd == "bad":
652 bad = True
652 bad = True
653 else:
653 else:
654 reset = True
654 reset = True
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
656 raise util.Abort(_('incompatible arguments'))
656 raise util.Abort(_('incompatible arguments'))
657
657
658 cmdutil.checkunfinished(repo)
658 cmdutil.checkunfinished(repo)
659
659
660 if reset:
660 if reset:
661 p = repo.join("bisect.state")
661 p = repo.join("bisect.state")
662 if os.path.exists(p):
662 if os.path.exists(p):
663 os.unlink(p)
663 os.unlink(p)
664 return
664 return
665
665
666 state = hbisect.load_state(repo)
666 state = hbisect.load_state(repo)
667
667
668 if command:
668 if command:
669 changesets = 1
669 changesets = 1
670 try:
670 try:
671 node = state['current'][0]
671 node = state['current'][0]
672 except LookupError:
672 except LookupError:
673 if noupdate:
673 if noupdate:
674 raise util.Abort(_('current bisect revision is unknown - '
674 raise util.Abort(_('current bisect revision is unknown - '
675 'start a new bisect to fix'))
675 'start a new bisect to fix'))
676 node, p2 = repo.dirstate.parents()
676 node, p2 = repo.dirstate.parents()
677 if p2 != nullid:
677 if p2 != nullid:
678 raise util.Abort(_('current bisect revision is a merge'))
678 raise util.Abort(_('current bisect revision is a merge'))
679 try:
679 try:
680 while changesets:
680 while changesets:
681 # update state
681 # update state
682 state['current'] = [node]
682 state['current'] = [node]
683 hbisect.save_state(repo, state)
683 hbisect.save_state(repo, state)
684 status = util.system(command,
684 status = util.system(command,
685 environ={'HG_NODE': hex(node)},
685 environ={'HG_NODE': hex(node)},
686 out=ui.fout)
686 out=ui.fout)
687 if status == 125:
687 if status == 125:
688 transition = "skip"
688 transition = "skip"
689 elif status == 0:
689 elif status == 0:
690 transition = "good"
690 transition = "good"
691 # status < 0 means process was killed
691 # status < 0 means process was killed
692 elif status == 127:
692 elif status == 127:
693 raise util.Abort(_("failed to execute %s") % command)
693 raise util.Abort(_("failed to execute %s") % command)
694 elif status < 0:
694 elif status < 0:
695 raise util.Abort(_("%s killed") % command)
695 raise util.Abort(_("%s killed") % command)
696 else:
696 else:
697 transition = "bad"
697 transition = "bad"
698 ctx = scmutil.revsingle(repo, rev, node)
698 ctx = scmutil.revsingle(repo, rev, node)
699 rev = None # clear for future iterations
699 rev = None # clear for future iterations
700 state[transition].append(ctx.node())
700 state[transition].append(ctx.node())
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
702 check_state(state, interactive=False)
702 check_state(state, interactive=False)
703 # bisect
703 # bisect
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
705 # update to next check
705 # update to next check
706 node = nodes[0]
706 node = nodes[0]
707 if not noupdate:
707 if not noupdate:
708 cmdutil.bailifchanged(repo)
708 cmdutil.bailifchanged(repo)
709 hg.clean(repo, node, show_stats=False)
709 hg.clean(repo, node, show_stats=False)
710 finally:
710 finally:
711 state['current'] = [node]
711 state['current'] = [node]
712 hbisect.save_state(repo, state)
712 hbisect.save_state(repo, state)
713 print_result(nodes, bgood)
713 print_result(nodes, bgood)
714 return
714 return
715
715
716 # update state
716 # update state
717
717
718 if rev:
718 if rev:
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
720 else:
720 else:
721 nodes = [repo.lookup('.')]
721 nodes = [repo.lookup('.')]
722
722
723 if good or bad or skip:
723 if good or bad or skip:
724 if good:
724 if good:
725 state['good'] += nodes
725 state['good'] += nodes
726 elif bad:
726 elif bad:
727 state['bad'] += nodes
727 state['bad'] += nodes
728 elif skip:
728 elif skip:
729 state['skip'] += nodes
729 state['skip'] += nodes
730 hbisect.save_state(repo, state)
730 hbisect.save_state(repo, state)
731
731
732 if not check_state(state):
732 if not check_state(state):
733 return
733 return
734
734
735 # actually bisect
735 # actually bisect
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
737 if extend:
737 if extend:
738 if not changesets:
738 if not changesets:
739 extendnode = extendbisectrange(nodes, good)
739 extendnode = extendbisectrange(nodes, good)
740 if extendnode is not None:
740 if extendnode is not None:
741 ui.write(_("Extending search to changeset %d:%s\n"
741 ui.write(_("Extending search to changeset %d:%s\n"
742 % (extendnode.rev(), extendnode)))
742 % (extendnode.rev(), extendnode)))
743 state['current'] = [extendnode.node()]
743 state['current'] = [extendnode.node()]
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745 if noupdate:
745 if noupdate:
746 return
746 return
747 cmdutil.bailifchanged(repo)
747 cmdutil.bailifchanged(repo)
748 return hg.clean(repo, extendnode.node())
748 return hg.clean(repo, extendnode.node())
749 raise util.Abort(_("nothing to extend"))
749 raise util.Abort(_("nothing to extend"))
750
750
751 if changesets == 0:
751 if changesets == 0:
752 print_result(nodes, good)
752 print_result(nodes, good)
753 else:
753 else:
754 assert len(nodes) == 1 # only a single node can be tested next
754 assert len(nodes) == 1 # only a single node can be tested next
755 node = nodes[0]
755 node = nodes[0]
756 # compute the approximate number of remaining tests
756 # compute the approximate number of remaining tests
757 tests, size = 0, 2
757 tests, size = 0, 2
758 while size <= changesets:
758 while size <= changesets:
759 tests, size = tests + 1, size * 2
759 tests, size = tests + 1, size * 2
760 rev = repo.changelog.rev(node)
760 rev = repo.changelog.rev(node)
761 ui.write(_("Testing changeset %d:%s "
761 ui.write(_("Testing changeset %d:%s "
762 "(%d changesets remaining, ~%d tests)\n")
762 "(%d changesets remaining, ~%d tests)\n")
763 % (rev, short(node), changesets, tests))
763 % (rev, short(node), changesets, tests))
764 state['current'] = [node]
764 state['current'] = [node]
765 hbisect.save_state(repo, state)
765 hbisect.save_state(repo, state)
766 if not noupdate:
766 if not noupdate:
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, node)
768 return hg.clean(repo, node)
769
769
770 @command('bookmarks|bookmark',
770 @command('bookmarks|bookmark',
771 [('f', 'force', False, _('force')),
771 [('f', 'force', False, _('force')),
772 ('r', 'rev', '', _('revision'), _('REV')),
772 ('r', 'rev', '', _('revision'), _('REV')),
773 ('d', 'delete', False, _('delete a given bookmark')),
773 ('d', 'delete', False, _('delete a given bookmark')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
777 def bookmark(ui, repo, *names, **opts):
777 def bookmark(ui, repo, *names, **opts):
778 '''track a line of development with movable markers
778 '''track a line of development with movable markers
779
779
780 Bookmarks are pointers to certain commits that move when committing.
780 Bookmarks are pointers to certain commits that move when committing.
781 Bookmarks are local. They can be renamed, copied and deleted. It is
781 Bookmarks are local. They can be renamed, copied and deleted. It is
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
783 :hg:`update NAME` to update to a given bookmark.
783 :hg:`update NAME` to update to a given bookmark.
784
784
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
786 directory's parent revision with the given name. If you specify
786 directory's parent revision with the given name. If you specify
787 a revision using -r REV (where REV may be an existing bookmark),
787 a revision using -r REV (where REV may be an existing bookmark),
788 the bookmark is assigned to that revision.
788 the bookmark is assigned to that revision.
789
789
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
791 push` and :hg:`help pull`). This requires both the local and remote
791 push` and :hg:`help pull`). This requires both the local and remote
792 repositories to support bookmarks. For versions prior to 1.8, this means
792 repositories to support bookmarks. For versions prior to 1.8, this means
793 the bookmarks extension must be enabled.
793 the bookmarks extension must be enabled.
794
794
795 If you set a bookmark called '@', new clones of the repository will
795 If you set a bookmark called '@', new clones of the repository will
796 have that revision checked out (and the bookmark made active) by
796 have that revision checked out (and the bookmark made active) by
797 default.
797 default.
798
798
799 With -i/--inactive, the new bookmark will not be made the active
799 With -i/--inactive, the new bookmark will not be made the active
800 bookmark. If -r/--rev is given, the new bookmark will not be made
800 bookmark. If -r/--rev is given, the new bookmark will not be made
801 active even if -i/--inactive is not given. If no NAME is given, the
801 active even if -i/--inactive is not given. If no NAME is given, the
802 current active bookmark will be marked inactive.
802 current active bookmark will be marked inactive.
803 '''
803 '''
804 force = opts.get('force')
804 force = opts.get('force')
805 rev = opts.get('rev')
805 rev = opts.get('rev')
806 delete = opts.get('delete')
806 delete = opts.get('delete')
807 rename = opts.get('rename')
807 rename = opts.get('rename')
808 inactive = opts.get('inactive')
808 inactive = opts.get('inactive')
809
809
810 hexfn = ui.debugflag and hex or short
810 hexfn = ui.debugflag and hex or short
811 marks = repo._bookmarks
811 marks = repo._bookmarks
812 cur = repo.changectx('.').node()
812 cur = repo.changectx('.').node()
813
813
814 def checkformat(mark):
814 def checkformat(mark):
815 mark = mark.strip()
815 mark = mark.strip()
816 if not mark:
816 if not mark:
817 raise util.Abort(_("bookmark names cannot consist entirely of "
817 raise util.Abort(_("bookmark names cannot consist entirely of "
818 "whitespace"))
818 "whitespace"))
819 scmutil.checknewlabel(repo, mark, 'bookmark')
819 scmutil.checknewlabel(repo, mark, 'bookmark')
820 return mark
820 return mark
821
821
822 def checkconflict(repo, mark, force=False, target=None):
822 def checkconflict(repo, mark, force=False, target=None):
823 if mark in marks and not force:
823 if mark in marks and not force:
824 if target:
824 if target:
825 if marks[mark] == target and target == cur:
825 if marks[mark] == target and target == cur:
826 # re-activating a bookmark
826 # re-activating a bookmark
827 return
827 return
828 anc = repo.changelog.ancestors([repo[target].rev()])
828 anc = repo.changelog.ancestors([repo[target].rev()])
829 bmctx = repo[marks[mark]]
829 bmctx = repo[marks[mark]]
830 divs = [repo[b].node() for b in marks
830 divs = [repo[b].node() for b in marks
831 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
831 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
832
832
833 # allow resolving a single divergent bookmark even if moving
833 # allow resolving a single divergent bookmark even if moving
834 # the bookmark across branches when a revision is specified
834 # the bookmark across branches when a revision is specified
835 # that contains a divergent bookmark
835 # that contains a divergent bookmark
836 if bmctx.rev() not in anc and target in divs:
836 if bmctx.rev() not in anc and target in divs:
837 bookmarks.deletedivergent(repo, [target], mark)
837 bookmarks.deletedivergent(repo, [target], mark)
838 return
838 return
839
839
840 # consider successor changesets as well
840 # consider successor changesets as well
841 foreground = obsolete.foreground(repo, [marks[mark]])
841 foreground = obsolete.foreground(repo, [marks[mark]])
842 deletefrom = [b for b in divs
842 deletefrom = [b for b in divs
843 if repo[b].rev() in anc or b == target]
843 if repo[b].rev() in anc or b == target]
844 bookmarks.deletedivergent(repo, deletefrom, mark)
844 bookmarks.deletedivergent(repo, deletefrom, mark)
845 if bmctx.rev() in anc or target in foreground:
845 if bmctx.rev() in anc or target in foreground:
846 ui.status(_("moving bookmark '%s' forward from %s\n") %
846 ui.status(_("moving bookmark '%s' forward from %s\n") %
847 (mark, short(bmctx.node())))
847 (mark, short(bmctx.node())))
848 return
848 return
849 raise util.Abort(_("bookmark '%s' already exists "
849 raise util.Abort(_("bookmark '%s' already exists "
850 "(use -f to force)") % mark)
850 "(use -f to force)") % mark)
851 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
851 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
852 and not force):
852 and not force):
853 raise util.Abort(
853 raise util.Abort(
854 _("a bookmark cannot have the name of an existing branch"))
854 _("a bookmark cannot have the name of an existing branch"))
855
855
856 if delete and rename:
856 if delete and rename:
857 raise util.Abort(_("--delete and --rename are incompatible"))
857 raise util.Abort(_("--delete and --rename are incompatible"))
858 if delete and rev:
858 if delete and rev:
859 raise util.Abort(_("--rev is incompatible with --delete"))
859 raise util.Abort(_("--rev is incompatible with --delete"))
860 if rename and rev:
860 if rename and rev:
861 raise util.Abort(_("--rev is incompatible with --rename"))
861 raise util.Abort(_("--rev is incompatible with --rename"))
862 if not names and (delete or rev):
862 if not names and (delete or rev):
863 raise util.Abort(_("bookmark name required"))
863 raise util.Abort(_("bookmark name required"))
864
864
865 if delete:
865 if delete:
866 for mark in names:
866 for mark in names:
867 if mark not in marks:
867 if mark not in marks:
868 raise util.Abort(_("bookmark '%s' does not exist") % mark)
868 raise util.Abort(_("bookmark '%s' does not exist") % mark)
869 if mark == repo._bookmarkcurrent:
869 if mark == repo._bookmarkcurrent:
870 bookmarks.unsetcurrent(repo)
870 bookmarks.unsetcurrent(repo)
871 del marks[mark]
871 del marks[mark]
872 marks.write()
872 marks.write()
873
873
874 elif rename:
874 elif rename:
875 if not names:
875 if not names:
876 raise util.Abort(_("new bookmark name required"))
876 raise util.Abort(_("new bookmark name required"))
877 elif len(names) > 1:
877 elif len(names) > 1:
878 raise util.Abort(_("only one new bookmark name allowed"))
878 raise util.Abort(_("only one new bookmark name allowed"))
879 mark = checkformat(names[0])
879 mark = checkformat(names[0])
880 if rename not in marks:
880 if rename not in marks:
881 raise util.Abort(_("bookmark '%s' does not exist") % rename)
881 raise util.Abort(_("bookmark '%s' does not exist") % rename)
882 checkconflict(repo, mark, force)
882 checkconflict(repo, mark, force)
883 marks[mark] = marks[rename]
883 marks[mark] = marks[rename]
884 if repo._bookmarkcurrent == rename and not inactive:
884 if repo._bookmarkcurrent == rename and not inactive:
885 bookmarks.setcurrent(repo, mark)
885 bookmarks.setcurrent(repo, mark)
886 del marks[rename]
886 del marks[rename]
887 marks.write()
887 marks.write()
888
888
889 elif names:
889 elif names:
890 newact = None
890 newact = None
891 for mark in names:
891 for mark in names:
892 mark = checkformat(mark)
892 mark = checkformat(mark)
893 if newact is None:
893 if newact is None:
894 newact = mark
894 newact = mark
895 if inactive and mark == repo._bookmarkcurrent:
895 if inactive and mark == repo._bookmarkcurrent:
896 bookmarks.unsetcurrent(repo)
896 bookmarks.unsetcurrent(repo)
897 return
897 return
898 tgt = cur
898 tgt = cur
899 if rev:
899 if rev:
900 tgt = scmutil.revsingle(repo, rev).node()
900 tgt = scmutil.revsingle(repo, rev).node()
901 checkconflict(repo, mark, force, tgt)
901 checkconflict(repo, mark, force, tgt)
902 marks[mark] = tgt
902 marks[mark] = tgt
903 if not inactive and cur == marks[newact] and not rev:
903 if not inactive and cur == marks[newact] and not rev:
904 bookmarks.setcurrent(repo, newact)
904 bookmarks.setcurrent(repo, newact)
905 elif cur != tgt and newact == repo._bookmarkcurrent:
905 elif cur != tgt and newact == repo._bookmarkcurrent:
906 bookmarks.unsetcurrent(repo)
906 bookmarks.unsetcurrent(repo)
907 marks.write()
907 marks.write()
908
908
909 # Same message whether trying to deactivate the current bookmark (-i
909 # Same message whether trying to deactivate the current bookmark (-i
910 # with no NAME) or listing bookmarks
910 # with no NAME) or listing bookmarks
911 elif len(marks) == 0:
911 elif len(marks) == 0:
912 ui.status(_("no bookmarks set\n"))
912 ui.status(_("no bookmarks set\n"))
913
913
914 elif inactive:
914 elif inactive:
915 if not repo._bookmarkcurrent:
915 if not repo._bookmarkcurrent:
916 ui.status(_("no active bookmark\n"))
916 ui.status(_("no active bookmark\n"))
917 else:
917 else:
918 bookmarks.unsetcurrent(repo)
918 bookmarks.unsetcurrent(repo)
919
919
920 else: # show bookmarks
920 else: # show bookmarks
921 for bmark, n in sorted(marks.iteritems()):
921 for bmark, n in sorted(marks.iteritems()):
922 current = repo._bookmarkcurrent
922 current = repo._bookmarkcurrent
923 if bmark == current:
923 if bmark == current:
924 prefix, label = '*', 'bookmarks.current'
924 prefix, label = '*', 'bookmarks.current'
925 else:
925 else:
926 prefix, label = ' ', ''
926 prefix, label = ' ', ''
927
927
928 if ui.quiet:
928 if ui.quiet:
929 ui.write("%s\n" % bmark, label=label)
929 ui.write("%s\n" % bmark, label=label)
930 else:
930 else:
931 ui.write(" %s %-25s %d:%s\n" % (
931 ui.write(" %s %-25s %d:%s\n" % (
932 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
932 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
933 label=label)
933 label=label)
934
934
935 @command('branch',
935 @command('branch',
936 [('f', 'force', None,
936 [('f', 'force', None,
937 _('set branch name even if it shadows an existing branch')),
937 _('set branch name even if it shadows an existing branch')),
938 ('C', 'clean', None, _('reset branch name to parent branch name'))],
938 ('C', 'clean', None, _('reset branch name to parent branch name'))],
939 _('[-fC] [NAME]'))
939 _('[-fC] [NAME]'))
940 def branch(ui, repo, label=None, **opts):
940 def branch(ui, repo, label=None, **opts):
941 """set or show the current branch name
941 """set or show the current branch name
942
942
943 .. note::
943 .. note::
944
944
945 Branch names are permanent and global. Use :hg:`bookmark` to create a
945 Branch names are permanent and global. Use :hg:`bookmark` to create a
946 light-weight bookmark instead. See :hg:`help glossary` for more
946 light-weight bookmark instead. See :hg:`help glossary` for more
947 information about named branches and bookmarks.
947 information about named branches and bookmarks.
948
948
949 With no argument, show the current branch name. With one argument,
949 With no argument, show the current branch name. With one argument,
950 set the working directory branch name (the branch will not exist
950 set the working directory branch name (the branch will not exist
951 in the repository until the next commit). Standard practice
951 in the repository until the next commit). Standard practice
952 recommends that primary development take place on the 'default'
952 recommends that primary development take place on the 'default'
953 branch.
953 branch.
954
954
955 Unless -f/--force is specified, branch will not let you set a
955 Unless -f/--force is specified, branch will not let you set a
956 branch name that already exists, even if it's inactive.
956 branch name that already exists, even if it's inactive.
957
957
958 Use -C/--clean to reset the working directory branch to that of
958 Use -C/--clean to reset the working directory branch to that of
959 the parent of the working directory, negating a previous branch
959 the parent of the working directory, negating a previous branch
960 change.
960 change.
961
961
962 Use the command :hg:`update` to switch to an existing branch. Use
962 Use the command :hg:`update` to switch to an existing branch. Use
963 :hg:`commit --close-branch` to mark this branch as closed.
963 :hg:`commit --close-branch` to mark this branch as closed.
964
964
965 Returns 0 on success.
965 Returns 0 on success.
966 """
966 """
967 if label:
967 if label:
968 label = label.strip()
968 label = label.strip()
969
969
970 if not opts.get('clean') and not label:
970 if not opts.get('clean') and not label:
971 ui.write("%s\n" % repo.dirstate.branch())
971 ui.write("%s\n" % repo.dirstate.branch())
972 return
972 return
973
973
974 wlock = repo.wlock()
974 wlock = repo.wlock()
975 try:
975 try:
976 if opts.get('clean'):
976 if opts.get('clean'):
977 label = repo[None].p1().branch()
977 label = repo[None].p1().branch()
978 repo.dirstate.setbranch(label)
978 repo.dirstate.setbranch(label)
979 ui.status(_('reset working directory to branch %s\n') % label)
979 ui.status(_('reset working directory to branch %s\n') % label)
980 elif label:
980 elif label:
981 if not opts.get('force') and label in repo.branchmap():
981 if not opts.get('force') and label in repo.branchmap():
982 if label not in [p.branch() for p in repo.parents()]:
982 if label not in [p.branch() for p in repo.parents()]:
983 raise util.Abort(_('a branch of the same name already'
983 raise util.Abort(_('a branch of the same name already'
984 ' exists'),
984 ' exists'),
985 # i18n: "it" refers to an existing branch
985 # i18n: "it" refers to an existing branch
986 hint=_("use 'hg update' to switch to it"))
986 hint=_("use 'hg update' to switch to it"))
987 scmutil.checknewlabel(repo, label, 'branch')
987 scmutil.checknewlabel(repo, label, 'branch')
988 repo.dirstate.setbranch(label)
988 repo.dirstate.setbranch(label)
989 ui.status(_('marked working directory as branch %s\n') % label)
989 ui.status(_('marked working directory as branch %s\n') % label)
990 ui.status(_('(branches are permanent and global, '
990 ui.status(_('(branches are permanent and global, '
991 'did you want a bookmark?)\n'))
991 'did you want a bookmark?)\n'))
992 finally:
992 finally:
993 wlock.release()
993 wlock.release()
994
994
995 @command('branches',
995 @command('branches',
996 [('a', 'active', False, _('show only branches that have unmerged heads')),
996 [('a', 'active', False, _('show only branches that have unmerged heads')),
997 ('c', 'closed', False, _('show normal and closed branches'))],
997 ('c', 'closed', False, _('show normal and closed branches'))],
998 _('[-ac]'))
998 _('[-ac]'))
999 def branches(ui, repo, active=False, closed=False):
999 def branches(ui, repo, active=False, closed=False):
1000 """list repository named branches
1000 """list repository named branches
1001
1001
1002 List the repository's named branches, indicating which ones are
1002 List the repository's named branches, indicating which ones are
1003 inactive. If -c/--closed is specified, also list branches which have
1003 inactive. If -c/--closed is specified, also list branches which have
1004 been marked closed (see :hg:`commit --close-branch`).
1004 been marked closed (see :hg:`commit --close-branch`).
1005
1005
1006 If -a/--active is specified, only show active branches. A branch
1006 If -a/--active is specified, only show active branches. A branch
1007 is considered active if it contains repository heads.
1007 is considered active if it contains repository heads.
1008
1008
1009 Use the command :hg:`update` to switch to an existing branch.
1009 Use the command :hg:`update` to switch to an existing branch.
1010
1010
1011 Returns 0.
1011 Returns 0.
1012 """
1012 """
1013
1013
1014 hexfunc = ui.debugflag and hex or short
1014 hexfunc = ui.debugflag and hex or short
1015
1015
1016 activebranches = set([repo[n].branch() for n in repo.heads()])
1016 allheads = set(repo.heads())
1017 branches = []
1017 branches = []
1018 for tag, heads in repo.branchmap().iteritems():
1018 for tag, heads in repo.branchmap().iteritems():
1019 for h in reversed(heads):
1019 for h in reversed(heads):
1020 ctx = repo[h]
1020 ctx = repo[h]
1021 isopen = not ctx.closesbranch()
1021 isopen = not ctx.closesbranch()
1022 if isopen:
1022 if isopen:
1023 tip = ctx
1023 tip = ctx
1024 break
1024 break
1025 else:
1025 else:
1026 tip = repo[heads[-1]]
1026 tip = repo[heads[-1]]
1027 isactive = tag in activebranches and isopen
1027 isactive = isopen and bool(set(heads) & allheads)
1028 branches.append((tip, isactive, isopen))
1028 branches.append((tag, tip, isactive, isopen))
1029 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1029 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1030 reverse=True)
1030 reverse=True)
1031
1031
1032 for ctx, isactive, isopen in branches:
1032 for tag, ctx, isactive, isopen in branches:
1033 if (not active) or isactive:
1033 if (not active) or isactive:
1034 if isactive:
1034 if isactive:
1035 label = 'branches.active'
1035 label = 'branches.active'
1036 notice = ''
1036 notice = ''
1037 elif not isopen:
1037 elif not isopen:
1038 if not closed:
1038 if not closed:
1039 continue
1039 continue
1040 label = 'branches.closed'
1040 label = 'branches.closed'
1041 notice = _(' (closed)')
1041 notice = _(' (closed)')
1042 else:
1042 else:
1043 label = 'branches.inactive'
1043 label = 'branches.inactive'
1044 notice = _(' (inactive)')
1044 notice = _(' (inactive)')
1045 if ctx.branch() == repo.dirstate.branch():
1045 if tag == repo.dirstate.branch():
1046 label = 'branches.current'
1046 label = 'branches.current'
1047 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1047 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1048 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1048 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1049 'log.changeset changeset.%s' % ctx.phasestr())
1049 'log.changeset changeset.%s' % ctx.phasestr())
1050 tag = ui.label(ctx.branch(), label)
1050 labeledtag = ui.label(tag, label)
1051 if ui.quiet:
1051 if ui.quiet:
1052 ui.write("%s\n" % tag)
1052 ui.write("%s\n" % labeledtag)
1053 else:
1053 else:
1054 ui.write("%s %s%s\n" % (tag, rev, notice))
1054 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1055
1055
1056 @command('bundle',
1056 @command('bundle',
1057 [('f', 'force', None, _('run even when the destination is unrelated')),
1057 [('f', 'force', None, _('run even when the destination is unrelated')),
1058 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1058 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1059 _('REV')),
1059 _('REV')),
1060 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1060 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1061 _('BRANCH')),
1061 _('BRANCH')),
1062 ('', 'base', [],
1062 ('', 'base', [],
1063 _('a base changeset assumed to be available at the destination'),
1063 _('a base changeset assumed to be available at the destination'),
1064 _('REV')),
1064 _('REV')),
1065 ('a', 'all', None, _('bundle all changesets in the repository')),
1065 ('a', 'all', None, _('bundle all changesets in the repository')),
1066 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1066 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1067 ] + remoteopts,
1067 ] + remoteopts,
1068 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1068 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1069 def bundle(ui, repo, fname, dest=None, **opts):
1069 def bundle(ui, repo, fname, dest=None, **opts):
1070 """create a changegroup file
1070 """create a changegroup file
1071
1071
1072 Generate a compressed changegroup file collecting changesets not
1072 Generate a compressed changegroup file collecting changesets not
1073 known to be in another repository.
1073 known to be in another repository.
1074
1074
1075 If you omit the destination repository, then hg assumes the
1075 If you omit the destination repository, then hg assumes the
1076 destination will have all the nodes you specify with --base
1076 destination will have all the nodes you specify with --base
1077 parameters. To create a bundle containing all changesets, use
1077 parameters. To create a bundle containing all changesets, use
1078 -a/--all (or --base null).
1078 -a/--all (or --base null).
1079
1079
1080 You can change compression method with the -t/--type option.
1080 You can change compression method with the -t/--type option.
1081 The available compression methods are: none, bzip2, and
1081 The available compression methods are: none, bzip2, and
1082 gzip (by default, bundles are compressed using bzip2).
1082 gzip (by default, bundles are compressed using bzip2).
1083
1083
1084 The bundle file can then be transferred using conventional means
1084 The bundle file can then be transferred using conventional means
1085 and applied to another repository with the unbundle or pull
1085 and applied to another repository with the unbundle or pull
1086 command. This is useful when direct push and pull are not
1086 command. This is useful when direct push and pull are not
1087 available or when exporting an entire repository is undesirable.
1087 available or when exporting an entire repository is undesirable.
1088
1088
1089 Applying bundles preserves all changeset contents including
1089 Applying bundles preserves all changeset contents including
1090 permissions, copy/rename information, and revision history.
1090 permissions, copy/rename information, and revision history.
1091
1091
1092 Returns 0 on success, 1 if no changes found.
1092 Returns 0 on success, 1 if no changes found.
1093 """
1093 """
1094 revs = None
1094 revs = None
1095 if 'rev' in opts:
1095 if 'rev' in opts:
1096 revs = scmutil.revrange(repo, opts['rev'])
1096 revs = scmutil.revrange(repo, opts['rev'])
1097
1097
1098 bundletype = opts.get('type', 'bzip2').lower()
1098 bundletype = opts.get('type', 'bzip2').lower()
1099 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1099 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1100 bundletype = btypes.get(bundletype)
1100 bundletype = btypes.get(bundletype)
1101 if bundletype not in changegroup.bundletypes:
1101 if bundletype not in changegroup.bundletypes:
1102 raise util.Abort(_('unknown bundle type specified with --type'))
1102 raise util.Abort(_('unknown bundle type specified with --type'))
1103
1103
1104 if opts.get('all'):
1104 if opts.get('all'):
1105 base = ['null']
1105 base = ['null']
1106 else:
1106 else:
1107 base = scmutil.revrange(repo, opts.get('base'))
1107 base = scmutil.revrange(repo, opts.get('base'))
1108 # TODO: get desired bundlecaps from command line.
1108 # TODO: get desired bundlecaps from command line.
1109 bundlecaps = None
1109 bundlecaps = None
1110 if base:
1110 if base:
1111 if dest:
1111 if dest:
1112 raise util.Abort(_("--base is incompatible with specifying "
1112 raise util.Abort(_("--base is incompatible with specifying "
1113 "a destination"))
1113 "a destination"))
1114 common = [repo.lookup(rev) for rev in base]
1114 common = [repo.lookup(rev) for rev in base]
1115 heads = revs and map(repo.lookup, revs) or revs
1115 heads = revs and map(repo.lookup, revs) or revs
1116 cg = repo.getbundle('bundle', heads=heads, common=common,
1116 cg = repo.getbundle('bundle', heads=heads, common=common,
1117 bundlecaps=bundlecaps)
1117 bundlecaps=bundlecaps)
1118 outgoing = None
1118 outgoing = None
1119 else:
1119 else:
1120 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1120 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1121 dest, branches = hg.parseurl(dest, opts.get('branch'))
1121 dest, branches = hg.parseurl(dest, opts.get('branch'))
1122 other = hg.peer(repo, opts, dest)
1122 other = hg.peer(repo, opts, dest)
1123 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1123 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1124 heads = revs and map(repo.lookup, revs) or revs
1124 heads = revs and map(repo.lookup, revs) or revs
1125 outgoing = discovery.findcommonoutgoing(repo, other,
1125 outgoing = discovery.findcommonoutgoing(repo, other,
1126 onlyheads=heads,
1126 onlyheads=heads,
1127 force=opts.get('force'),
1127 force=opts.get('force'),
1128 portable=True)
1128 portable=True)
1129 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1129 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1130 if not cg:
1130 if not cg:
1131 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1131 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1132 return 1
1132 return 1
1133
1133
1134 changegroup.writebundle(cg, fname, bundletype)
1134 changegroup.writebundle(cg, fname, bundletype)
1135
1135
1136 @command('cat',
1136 @command('cat',
1137 [('o', 'output', '',
1137 [('o', 'output', '',
1138 _('print output to file with formatted name'), _('FORMAT')),
1138 _('print output to file with formatted name'), _('FORMAT')),
1139 ('r', 'rev', '', _('print the given revision'), _('REV')),
1139 ('r', 'rev', '', _('print the given revision'), _('REV')),
1140 ('', 'decode', None, _('apply any matching decode filter')),
1140 ('', 'decode', None, _('apply any matching decode filter')),
1141 ] + walkopts,
1141 ] + walkopts,
1142 _('[OPTION]... FILE...'))
1142 _('[OPTION]... FILE...'))
1143 def cat(ui, repo, file1, *pats, **opts):
1143 def cat(ui, repo, file1, *pats, **opts):
1144 """output the current or given revision of files
1144 """output the current or given revision of files
1145
1145
1146 Print the specified files as they were at the given revision. If
1146 Print the specified files as they were at the given revision. If
1147 no revision is given, the parent of the working directory is used.
1147 no revision is given, the parent of the working directory is used.
1148
1148
1149 Output may be to a file, in which case the name of the file is
1149 Output may be to a file, in which case the name of the file is
1150 given using a format string. The formatting rules are the same as
1150 given using a format string. The formatting rules are the same as
1151 for the export command, with the following additions:
1151 for the export command, with the following additions:
1152
1152
1153 :``%s``: basename of file being printed
1153 :``%s``: basename of file being printed
1154 :``%d``: dirname of file being printed, or '.' if in repository root
1154 :``%d``: dirname of file being printed, or '.' if in repository root
1155 :``%p``: root-relative path name of file being printed
1155 :``%p``: root-relative path name of file being printed
1156
1156
1157 Returns 0 on success.
1157 Returns 0 on success.
1158 """
1158 """
1159 ctx = scmutil.revsingle(repo, opts.get('rev'))
1159 ctx = scmutil.revsingle(repo, opts.get('rev'))
1160 err = 1
1160 err = 1
1161 m = scmutil.match(ctx, (file1,) + pats, opts)
1161 m = scmutil.match(ctx, (file1,) + pats, opts)
1162 for abs in ctx.walk(m):
1162 for abs in ctx.walk(m):
1163 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1163 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1164 pathname=abs)
1164 pathname=abs)
1165 data = ctx[abs].data()
1165 data = ctx[abs].data()
1166 if opts.get('decode'):
1166 if opts.get('decode'):
1167 data = repo.wwritedata(abs, data)
1167 data = repo.wwritedata(abs, data)
1168 fp.write(data)
1168 fp.write(data)
1169 fp.close()
1169 fp.close()
1170 err = 0
1170 err = 0
1171 return err
1171 return err
1172
1172
1173 @command('^clone',
1173 @command('^clone',
1174 [('U', 'noupdate', None,
1174 [('U', 'noupdate', None,
1175 _('the clone will include an empty working copy (only a repository)')),
1175 _('the clone will include an empty working copy (only a repository)')),
1176 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1176 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1177 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1177 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1178 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1178 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1179 ('', 'pull', None, _('use pull protocol to copy metadata')),
1179 ('', 'pull', None, _('use pull protocol to copy metadata')),
1180 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1180 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1181 ] + remoteopts,
1181 ] + remoteopts,
1182 _('[OPTION]... SOURCE [DEST]'))
1182 _('[OPTION]... SOURCE [DEST]'))
1183 def clone(ui, source, dest=None, **opts):
1183 def clone(ui, source, dest=None, **opts):
1184 """make a copy of an existing repository
1184 """make a copy of an existing repository
1185
1185
1186 Create a copy of an existing repository in a new directory.
1186 Create a copy of an existing repository in a new directory.
1187
1187
1188 If no destination directory name is specified, it defaults to the
1188 If no destination directory name is specified, it defaults to the
1189 basename of the source.
1189 basename of the source.
1190
1190
1191 The location of the source is added to the new repository's
1191 The location of the source is added to the new repository's
1192 ``.hg/hgrc`` file, as the default to be used for future pulls.
1192 ``.hg/hgrc`` file, as the default to be used for future pulls.
1193
1193
1194 Only local paths and ``ssh://`` URLs are supported as
1194 Only local paths and ``ssh://`` URLs are supported as
1195 destinations. For ``ssh://`` destinations, no working directory or
1195 destinations. For ``ssh://`` destinations, no working directory or
1196 ``.hg/hgrc`` will be created on the remote side.
1196 ``.hg/hgrc`` will be created on the remote side.
1197
1197
1198 To pull only a subset of changesets, specify one or more revisions
1198 To pull only a subset of changesets, specify one or more revisions
1199 identifiers with -r/--rev or branches with -b/--branch. The
1199 identifiers with -r/--rev or branches with -b/--branch. The
1200 resulting clone will contain only the specified changesets and
1200 resulting clone will contain only the specified changesets and
1201 their ancestors. These options (or 'clone src#rev dest') imply
1201 their ancestors. These options (or 'clone src#rev dest') imply
1202 --pull, even for local source repositories. Note that specifying a
1202 --pull, even for local source repositories. Note that specifying a
1203 tag will include the tagged changeset but not the changeset
1203 tag will include the tagged changeset but not the changeset
1204 containing the tag.
1204 containing the tag.
1205
1205
1206 If the source repository has a bookmark called '@' set, that
1206 If the source repository has a bookmark called '@' set, that
1207 revision will be checked out in the new repository by default.
1207 revision will be checked out in the new repository by default.
1208
1208
1209 To check out a particular version, use -u/--update, or
1209 To check out a particular version, use -u/--update, or
1210 -U/--noupdate to create a clone with no working directory.
1210 -U/--noupdate to create a clone with no working directory.
1211
1211
1212 .. container:: verbose
1212 .. container:: verbose
1213
1213
1214 For efficiency, hardlinks are used for cloning whenever the
1214 For efficiency, hardlinks are used for cloning whenever the
1215 source and destination are on the same filesystem (note this
1215 source and destination are on the same filesystem (note this
1216 applies only to the repository data, not to the working
1216 applies only to the repository data, not to the working
1217 directory). Some filesystems, such as AFS, implement hardlinking
1217 directory). Some filesystems, such as AFS, implement hardlinking
1218 incorrectly, but do not report errors. In these cases, use the
1218 incorrectly, but do not report errors. In these cases, use the
1219 --pull option to avoid hardlinking.
1219 --pull option to avoid hardlinking.
1220
1220
1221 In some cases, you can clone repositories and the working
1221 In some cases, you can clone repositories and the working
1222 directory using full hardlinks with ::
1222 directory using full hardlinks with ::
1223
1223
1224 $ cp -al REPO REPOCLONE
1224 $ cp -al REPO REPOCLONE
1225
1225
1226 This is the fastest way to clone, but it is not always safe. The
1226 This is the fastest way to clone, but it is not always safe. The
1227 operation is not atomic (making sure REPO is not modified during
1227 operation is not atomic (making sure REPO is not modified during
1228 the operation is up to you) and you have to make sure your
1228 the operation is up to you) and you have to make sure your
1229 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1229 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1230 so). Also, this is not compatible with certain extensions that
1230 so). Also, this is not compatible with certain extensions that
1231 place their metadata under the .hg directory, such as mq.
1231 place their metadata under the .hg directory, such as mq.
1232
1232
1233 Mercurial will update the working directory to the first applicable
1233 Mercurial will update the working directory to the first applicable
1234 revision from this list:
1234 revision from this list:
1235
1235
1236 a) null if -U or the source repository has no changesets
1236 a) null if -U or the source repository has no changesets
1237 b) if -u . and the source repository is local, the first parent of
1237 b) if -u . and the source repository is local, the first parent of
1238 the source repository's working directory
1238 the source repository's working directory
1239 c) the changeset specified with -u (if a branch name, this means the
1239 c) the changeset specified with -u (if a branch name, this means the
1240 latest head of that branch)
1240 latest head of that branch)
1241 d) the changeset specified with -r
1241 d) the changeset specified with -r
1242 e) the tipmost head specified with -b
1242 e) the tipmost head specified with -b
1243 f) the tipmost head specified with the url#branch source syntax
1243 f) the tipmost head specified with the url#branch source syntax
1244 g) the revision marked with the '@' bookmark, if present
1244 g) the revision marked with the '@' bookmark, if present
1245 h) the tipmost head of the default branch
1245 h) the tipmost head of the default branch
1246 i) tip
1246 i) tip
1247
1247
1248 Examples:
1248 Examples:
1249
1249
1250 - clone a remote repository to a new directory named hg/::
1250 - clone a remote repository to a new directory named hg/::
1251
1251
1252 hg clone http://selenic.com/hg
1252 hg clone http://selenic.com/hg
1253
1253
1254 - create a lightweight local clone::
1254 - create a lightweight local clone::
1255
1255
1256 hg clone project/ project-feature/
1256 hg clone project/ project-feature/
1257
1257
1258 - clone from an absolute path on an ssh server (note double-slash)::
1258 - clone from an absolute path on an ssh server (note double-slash)::
1259
1259
1260 hg clone ssh://user@server//home/projects/alpha/
1260 hg clone ssh://user@server//home/projects/alpha/
1261
1261
1262 - do a high-speed clone over a LAN while checking out a
1262 - do a high-speed clone over a LAN while checking out a
1263 specified version::
1263 specified version::
1264
1264
1265 hg clone --uncompressed http://server/repo -u 1.5
1265 hg clone --uncompressed http://server/repo -u 1.5
1266
1266
1267 - create a repository without changesets after a particular revision::
1267 - create a repository without changesets after a particular revision::
1268
1268
1269 hg clone -r 04e544 experimental/ good/
1269 hg clone -r 04e544 experimental/ good/
1270
1270
1271 - clone (and track) a particular named branch::
1271 - clone (and track) a particular named branch::
1272
1272
1273 hg clone http://selenic.com/hg#stable
1273 hg clone http://selenic.com/hg#stable
1274
1274
1275 See :hg:`help urls` for details on specifying URLs.
1275 See :hg:`help urls` for details on specifying URLs.
1276
1276
1277 Returns 0 on success.
1277 Returns 0 on success.
1278 """
1278 """
1279 if opts.get('noupdate') and opts.get('updaterev'):
1279 if opts.get('noupdate') and opts.get('updaterev'):
1280 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1280 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1281
1281
1282 r = hg.clone(ui, opts, source, dest,
1282 r = hg.clone(ui, opts, source, dest,
1283 pull=opts.get('pull'),
1283 pull=opts.get('pull'),
1284 stream=opts.get('uncompressed'),
1284 stream=opts.get('uncompressed'),
1285 rev=opts.get('rev'),
1285 rev=opts.get('rev'),
1286 update=opts.get('updaterev') or not opts.get('noupdate'),
1286 update=opts.get('updaterev') or not opts.get('noupdate'),
1287 branch=opts.get('branch'))
1287 branch=opts.get('branch'))
1288
1288
1289 return r is None
1289 return r is None
1290
1290
1291 @command('^commit|ci',
1291 @command('^commit|ci',
1292 [('A', 'addremove', None,
1292 [('A', 'addremove', None,
1293 _('mark new/missing files as added/removed before committing')),
1293 _('mark new/missing files as added/removed before committing')),
1294 ('', 'close-branch', None,
1294 ('', 'close-branch', None,
1295 _('mark a branch as closed, hiding it from the branch list')),
1295 _('mark a branch as closed, hiding it from the branch list')),
1296 ('', 'amend', None, _('amend the parent of the working dir')),
1296 ('', 'amend', None, _('amend the parent of the working dir')),
1297 ('s', 'secret', None, _('use the secret phase for committing')),
1297 ('s', 'secret', None, _('use the secret phase for committing')),
1298 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1298 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1299 _('[OPTION]... [FILE]...'))
1299 _('[OPTION]... [FILE]...'))
1300 def commit(ui, repo, *pats, **opts):
1300 def commit(ui, repo, *pats, **opts):
1301 """commit the specified files or all outstanding changes
1301 """commit the specified files or all outstanding changes
1302
1302
1303 Commit changes to the given files into the repository. Unlike a
1303 Commit changes to the given files into the repository. Unlike a
1304 centralized SCM, this operation is a local operation. See
1304 centralized SCM, this operation is a local operation. See
1305 :hg:`push` for a way to actively distribute your changes.
1305 :hg:`push` for a way to actively distribute your changes.
1306
1306
1307 If a list of files is omitted, all changes reported by :hg:`status`
1307 If a list of files is omitted, all changes reported by :hg:`status`
1308 will be committed.
1308 will be committed.
1309
1309
1310 If you are committing the result of a merge, do not provide any
1310 If you are committing the result of a merge, do not provide any
1311 filenames or -I/-X filters.
1311 filenames or -I/-X filters.
1312
1312
1313 If no commit message is specified, Mercurial starts your
1313 If no commit message is specified, Mercurial starts your
1314 configured editor where you can enter a message. In case your
1314 configured editor where you can enter a message. In case your
1315 commit fails, you will find a backup of your message in
1315 commit fails, you will find a backup of your message in
1316 ``.hg/last-message.txt``.
1316 ``.hg/last-message.txt``.
1317
1317
1318 The --amend flag can be used to amend the parent of the
1318 The --amend flag can be used to amend the parent of the
1319 working directory with a new commit that contains the changes
1319 working directory with a new commit that contains the changes
1320 in the parent in addition to those currently reported by :hg:`status`,
1320 in the parent in addition to those currently reported by :hg:`status`,
1321 if there are any. The old commit is stored in a backup bundle in
1321 if there are any. The old commit is stored in a backup bundle in
1322 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1322 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1323 on how to restore it).
1323 on how to restore it).
1324
1324
1325 Message, user and date are taken from the amended commit unless
1325 Message, user and date are taken from the amended commit unless
1326 specified. When a message isn't specified on the command line,
1326 specified. When a message isn't specified on the command line,
1327 the editor will open with the message of the amended commit.
1327 the editor will open with the message of the amended commit.
1328
1328
1329 It is not possible to amend public changesets (see :hg:`help phases`)
1329 It is not possible to amend public changesets (see :hg:`help phases`)
1330 or changesets that have children.
1330 or changesets that have children.
1331
1331
1332 See :hg:`help dates` for a list of formats valid for -d/--date.
1332 See :hg:`help dates` for a list of formats valid for -d/--date.
1333
1333
1334 Returns 0 on success, 1 if nothing changed.
1334 Returns 0 on success, 1 if nothing changed.
1335 """
1335 """
1336 if opts.get('subrepos'):
1336 if opts.get('subrepos'):
1337 if opts.get('amend'):
1337 if opts.get('amend'):
1338 raise util.Abort(_('cannot amend with --subrepos'))
1338 raise util.Abort(_('cannot amend with --subrepos'))
1339 # Let --subrepos on the command line override config setting.
1339 # Let --subrepos on the command line override config setting.
1340 ui.setconfig('ui', 'commitsubrepos', True)
1340 ui.setconfig('ui', 'commitsubrepos', True)
1341
1341
1342 # Save this for restoring it later
1342 # Save this for restoring it later
1343 oldcommitphase = ui.config('phases', 'new-commit')
1343 oldcommitphase = ui.config('phases', 'new-commit')
1344
1344
1345 cmdutil.checkunfinished(repo, commit=True)
1345 cmdutil.checkunfinished(repo, commit=True)
1346
1346
1347 branch = repo[None].branch()
1347 branch = repo[None].branch()
1348 bheads = repo.branchheads(branch)
1348 bheads = repo.branchheads(branch)
1349
1349
1350 extra = {}
1350 extra = {}
1351 if opts.get('close_branch'):
1351 if opts.get('close_branch'):
1352 extra['close'] = 1
1352 extra['close'] = 1
1353
1353
1354 if not bheads:
1354 if not bheads:
1355 raise util.Abort(_('can only close branch heads'))
1355 raise util.Abort(_('can only close branch heads'))
1356 elif opts.get('amend'):
1356 elif opts.get('amend'):
1357 if repo.parents()[0].p1().branch() != branch and \
1357 if repo.parents()[0].p1().branch() != branch and \
1358 repo.parents()[0].p2().branch() != branch:
1358 repo.parents()[0].p2().branch() != branch:
1359 raise util.Abort(_('can only close branch heads'))
1359 raise util.Abort(_('can only close branch heads'))
1360
1360
1361 if opts.get('amend'):
1361 if opts.get('amend'):
1362 if ui.configbool('ui', 'commitsubrepos'):
1362 if ui.configbool('ui', 'commitsubrepos'):
1363 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1363 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1364
1364
1365 old = repo['.']
1365 old = repo['.']
1366 if old.phase() == phases.public:
1366 if old.phase() == phases.public:
1367 raise util.Abort(_('cannot amend public changesets'))
1367 raise util.Abort(_('cannot amend public changesets'))
1368 if len(repo[None].parents()) > 1:
1368 if len(repo[None].parents()) > 1:
1369 raise util.Abort(_('cannot amend while merging'))
1369 raise util.Abort(_('cannot amend while merging'))
1370 if (not obsolete._enabled) and old.children():
1370 if (not obsolete._enabled) and old.children():
1371 raise util.Abort(_('cannot amend changeset with children'))
1371 raise util.Abort(_('cannot amend changeset with children'))
1372
1372
1373 e = cmdutil.commiteditor
1373 e = cmdutil.commiteditor
1374 if opts.get('force_editor'):
1374 if opts.get('force_editor'):
1375 e = cmdutil.commitforceeditor
1375 e = cmdutil.commitforceeditor
1376
1376
1377 def commitfunc(ui, repo, message, match, opts):
1377 def commitfunc(ui, repo, message, match, opts):
1378 editor = e
1378 editor = e
1379 # message contains text from -m or -l, if it's empty,
1379 # message contains text from -m or -l, if it's empty,
1380 # open the editor with the old message
1380 # open the editor with the old message
1381 if not message:
1381 if not message:
1382 message = old.description()
1382 message = old.description()
1383 editor = cmdutil.commitforceeditor
1383 editor = cmdutil.commitforceeditor
1384 try:
1384 try:
1385 if opts.get('secret'):
1385 if opts.get('secret'):
1386 ui.setconfig('phases', 'new-commit', 'secret')
1386 ui.setconfig('phases', 'new-commit', 'secret')
1387
1387
1388 return repo.commit(message,
1388 return repo.commit(message,
1389 opts.get('user') or old.user(),
1389 opts.get('user') or old.user(),
1390 opts.get('date') or old.date(),
1390 opts.get('date') or old.date(),
1391 match,
1391 match,
1392 editor=editor,
1392 editor=editor,
1393 extra=extra)
1393 extra=extra)
1394 finally:
1394 finally:
1395 ui.setconfig('phases', 'new-commit', oldcommitphase)
1395 ui.setconfig('phases', 'new-commit', oldcommitphase)
1396
1396
1397 current = repo._bookmarkcurrent
1397 current = repo._bookmarkcurrent
1398 marks = old.bookmarks()
1398 marks = old.bookmarks()
1399 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1399 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1400 if node == old.node():
1400 if node == old.node():
1401 ui.status(_("nothing changed\n"))
1401 ui.status(_("nothing changed\n"))
1402 return 1
1402 return 1
1403 elif marks:
1403 elif marks:
1404 ui.debug('moving bookmarks %r from %s to %s\n' %
1404 ui.debug('moving bookmarks %r from %s to %s\n' %
1405 (marks, old.hex(), hex(node)))
1405 (marks, old.hex(), hex(node)))
1406 newmarks = repo._bookmarks
1406 newmarks = repo._bookmarks
1407 for bm in marks:
1407 for bm in marks:
1408 newmarks[bm] = node
1408 newmarks[bm] = node
1409 if bm == current:
1409 if bm == current:
1410 bookmarks.setcurrent(repo, bm)
1410 bookmarks.setcurrent(repo, bm)
1411 newmarks.write()
1411 newmarks.write()
1412 else:
1412 else:
1413 e = cmdutil.commiteditor
1413 e = cmdutil.commiteditor
1414 if opts.get('force_editor'):
1414 if opts.get('force_editor'):
1415 e = cmdutil.commitforceeditor
1415 e = cmdutil.commitforceeditor
1416
1416
1417 def commitfunc(ui, repo, message, match, opts):
1417 def commitfunc(ui, repo, message, match, opts):
1418 try:
1418 try:
1419 if opts.get('secret'):
1419 if opts.get('secret'):
1420 ui.setconfig('phases', 'new-commit', 'secret')
1420 ui.setconfig('phases', 'new-commit', 'secret')
1421
1421
1422 return repo.commit(message, opts.get('user'), opts.get('date'),
1422 return repo.commit(message, opts.get('user'), opts.get('date'),
1423 match, editor=e, extra=extra)
1423 match, editor=e, extra=extra)
1424 finally:
1424 finally:
1425 ui.setconfig('phases', 'new-commit', oldcommitphase)
1425 ui.setconfig('phases', 'new-commit', oldcommitphase)
1426
1426
1427
1427
1428 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1428 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1429
1429
1430 if not node:
1430 if not node:
1431 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1431 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1432 if stat[3]:
1432 if stat[3]:
1433 ui.status(_("nothing changed (%d missing files, see "
1433 ui.status(_("nothing changed (%d missing files, see "
1434 "'hg status')\n") % len(stat[3]))
1434 "'hg status')\n") % len(stat[3]))
1435 else:
1435 else:
1436 ui.status(_("nothing changed\n"))
1436 ui.status(_("nothing changed\n"))
1437 return 1
1437 return 1
1438
1438
1439 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1439 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1440
1440
1441 @command('copy|cp',
1441 @command('copy|cp',
1442 [('A', 'after', None, _('record a copy that has already occurred')),
1442 [('A', 'after', None, _('record a copy that has already occurred')),
1443 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1443 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1444 ] + walkopts + dryrunopts,
1444 ] + walkopts + dryrunopts,
1445 _('[OPTION]... [SOURCE]... DEST'))
1445 _('[OPTION]... [SOURCE]... DEST'))
1446 def copy(ui, repo, *pats, **opts):
1446 def copy(ui, repo, *pats, **opts):
1447 """mark files as copied for the next commit
1447 """mark files as copied for the next commit
1448
1448
1449 Mark dest as having copies of source files. If dest is a
1449 Mark dest as having copies of source files. If dest is a
1450 directory, copies are put in that directory. If dest is a file,
1450 directory, copies are put in that directory. If dest is a file,
1451 the source must be a single file.
1451 the source must be a single file.
1452
1452
1453 By default, this command copies the contents of files as they
1453 By default, this command copies the contents of files as they
1454 exist in the working directory. If invoked with -A/--after, the
1454 exist in the working directory. If invoked with -A/--after, the
1455 operation is recorded, but no copying is performed.
1455 operation is recorded, but no copying is performed.
1456
1456
1457 This command takes effect with the next commit. To undo a copy
1457 This command takes effect with the next commit. To undo a copy
1458 before that, see :hg:`revert`.
1458 before that, see :hg:`revert`.
1459
1459
1460 Returns 0 on success, 1 if errors are encountered.
1460 Returns 0 on success, 1 if errors are encountered.
1461 """
1461 """
1462 wlock = repo.wlock(False)
1462 wlock = repo.wlock(False)
1463 try:
1463 try:
1464 return cmdutil.copy(ui, repo, pats, opts)
1464 return cmdutil.copy(ui, repo, pats, opts)
1465 finally:
1465 finally:
1466 wlock.release()
1466 wlock.release()
1467
1467
1468 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1468 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1469 def debugancestor(ui, repo, *args):
1469 def debugancestor(ui, repo, *args):
1470 """find the ancestor revision of two revisions in a given index"""
1470 """find the ancestor revision of two revisions in a given index"""
1471 if len(args) == 3:
1471 if len(args) == 3:
1472 index, rev1, rev2 = args
1472 index, rev1, rev2 = args
1473 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1473 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1474 lookup = r.lookup
1474 lookup = r.lookup
1475 elif len(args) == 2:
1475 elif len(args) == 2:
1476 if not repo:
1476 if not repo:
1477 raise util.Abort(_("there is no Mercurial repository here "
1477 raise util.Abort(_("there is no Mercurial repository here "
1478 "(.hg not found)"))
1478 "(.hg not found)"))
1479 rev1, rev2 = args
1479 rev1, rev2 = args
1480 r = repo.changelog
1480 r = repo.changelog
1481 lookup = repo.lookup
1481 lookup = repo.lookup
1482 else:
1482 else:
1483 raise util.Abort(_('either two or three arguments required'))
1483 raise util.Abort(_('either two or three arguments required'))
1484 a = r.ancestor(lookup(rev1), lookup(rev2))
1484 a = r.ancestor(lookup(rev1), lookup(rev2))
1485 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1485 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1486
1486
1487 @command('debugbuilddag',
1487 @command('debugbuilddag',
1488 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1488 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1489 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1489 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1490 ('n', 'new-file', None, _('add new file at each rev'))],
1490 ('n', 'new-file', None, _('add new file at each rev'))],
1491 _('[OPTION]... [TEXT]'))
1491 _('[OPTION]... [TEXT]'))
1492 def debugbuilddag(ui, repo, text=None,
1492 def debugbuilddag(ui, repo, text=None,
1493 mergeable_file=False,
1493 mergeable_file=False,
1494 overwritten_file=False,
1494 overwritten_file=False,
1495 new_file=False):
1495 new_file=False):
1496 """builds a repo with a given DAG from scratch in the current empty repo
1496 """builds a repo with a given DAG from scratch in the current empty repo
1497
1497
1498 The description of the DAG is read from stdin if not given on the
1498 The description of the DAG is read from stdin if not given on the
1499 command line.
1499 command line.
1500
1500
1501 Elements:
1501 Elements:
1502
1502
1503 - "+n" is a linear run of n nodes based on the current default parent
1503 - "+n" is a linear run of n nodes based on the current default parent
1504 - "." is a single node based on the current default parent
1504 - "." is a single node based on the current default parent
1505 - "$" resets the default parent to null (implied at the start);
1505 - "$" resets the default parent to null (implied at the start);
1506 otherwise the default parent is always the last node created
1506 otherwise the default parent is always the last node created
1507 - "<p" sets the default parent to the backref p
1507 - "<p" sets the default parent to the backref p
1508 - "*p" is a fork at parent p, which is a backref
1508 - "*p" is a fork at parent p, which is a backref
1509 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1509 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1510 - "/p2" is a merge of the preceding node and p2
1510 - "/p2" is a merge of the preceding node and p2
1511 - ":tag" defines a local tag for the preceding node
1511 - ":tag" defines a local tag for the preceding node
1512 - "@branch" sets the named branch for subsequent nodes
1512 - "@branch" sets the named branch for subsequent nodes
1513 - "#...\\n" is a comment up to the end of the line
1513 - "#...\\n" is a comment up to the end of the line
1514
1514
1515 Whitespace between the above elements is ignored.
1515 Whitespace between the above elements is ignored.
1516
1516
1517 A backref is either
1517 A backref is either
1518
1518
1519 - a number n, which references the node curr-n, where curr is the current
1519 - a number n, which references the node curr-n, where curr is the current
1520 node, or
1520 node, or
1521 - the name of a local tag you placed earlier using ":tag", or
1521 - the name of a local tag you placed earlier using ":tag", or
1522 - empty to denote the default parent.
1522 - empty to denote the default parent.
1523
1523
1524 All string valued-elements are either strictly alphanumeric, or must
1524 All string valued-elements are either strictly alphanumeric, or must
1525 be enclosed in double quotes ("..."), with "\\" as escape character.
1525 be enclosed in double quotes ("..."), with "\\" as escape character.
1526 """
1526 """
1527
1527
1528 if text is None:
1528 if text is None:
1529 ui.status(_("reading DAG from stdin\n"))
1529 ui.status(_("reading DAG from stdin\n"))
1530 text = ui.fin.read()
1530 text = ui.fin.read()
1531
1531
1532 cl = repo.changelog
1532 cl = repo.changelog
1533 if len(cl) > 0:
1533 if len(cl) > 0:
1534 raise util.Abort(_('repository is not empty'))
1534 raise util.Abort(_('repository is not empty'))
1535
1535
1536 # determine number of revs in DAG
1536 # determine number of revs in DAG
1537 total = 0
1537 total = 0
1538 for type, data in dagparser.parsedag(text):
1538 for type, data in dagparser.parsedag(text):
1539 if type == 'n':
1539 if type == 'n':
1540 total += 1
1540 total += 1
1541
1541
1542 if mergeable_file:
1542 if mergeable_file:
1543 linesperrev = 2
1543 linesperrev = 2
1544 # make a file with k lines per rev
1544 # make a file with k lines per rev
1545 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1545 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1546 initialmergedlines.append("")
1546 initialmergedlines.append("")
1547
1547
1548 tags = []
1548 tags = []
1549
1549
1550 lock = tr = None
1550 lock = tr = None
1551 try:
1551 try:
1552 lock = repo.lock()
1552 lock = repo.lock()
1553 tr = repo.transaction("builddag")
1553 tr = repo.transaction("builddag")
1554
1554
1555 at = -1
1555 at = -1
1556 atbranch = 'default'
1556 atbranch = 'default'
1557 nodeids = []
1557 nodeids = []
1558 id = 0
1558 id = 0
1559 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1559 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1560 for type, data in dagparser.parsedag(text):
1560 for type, data in dagparser.parsedag(text):
1561 if type == 'n':
1561 if type == 'n':
1562 ui.note(('node %s\n' % str(data)))
1562 ui.note(('node %s\n' % str(data)))
1563 id, ps = data
1563 id, ps = data
1564
1564
1565 files = []
1565 files = []
1566 fctxs = {}
1566 fctxs = {}
1567
1567
1568 p2 = None
1568 p2 = None
1569 if mergeable_file:
1569 if mergeable_file:
1570 fn = "mf"
1570 fn = "mf"
1571 p1 = repo[ps[0]]
1571 p1 = repo[ps[0]]
1572 if len(ps) > 1:
1572 if len(ps) > 1:
1573 p2 = repo[ps[1]]
1573 p2 = repo[ps[1]]
1574 pa = p1.ancestor(p2)
1574 pa = p1.ancestor(p2)
1575 base, local, other = [x[fn].data() for x in (pa, p1,
1575 base, local, other = [x[fn].data() for x in (pa, p1,
1576 p2)]
1576 p2)]
1577 m3 = simplemerge.Merge3Text(base, local, other)
1577 m3 = simplemerge.Merge3Text(base, local, other)
1578 ml = [l.strip() for l in m3.merge_lines()]
1578 ml = [l.strip() for l in m3.merge_lines()]
1579 ml.append("")
1579 ml.append("")
1580 elif at > 0:
1580 elif at > 0:
1581 ml = p1[fn].data().split("\n")
1581 ml = p1[fn].data().split("\n")
1582 else:
1582 else:
1583 ml = initialmergedlines
1583 ml = initialmergedlines
1584 ml[id * linesperrev] += " r%i" % id
1584 ml[id * linesperrev] += " r%i" % id
1585 mergedtext = "\n".join(ml)
1585 mergedtext = "\n".join(ml)
1586 files.append(fn)
1586 files.append(fn)
1587 fctxs[fn] = context.memfilectx(fn, mergedtext)
1587 fctxs[fn] = context.memfilectx(fn, mergedtext)
1588
1588
1589 if overwritten_file:
1589 if overwritten_file:
1590 fn = "of"
1590 fn = "of"
1591 files.append(fn)
1591 files.append(fn)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1593
1593
1594 if new_file:
1594 if new_file:
1595 fn = "nf%i" % id
1595 fn = "nf%i" % id
1596 files.append(fn)
1596 files.append(fn)
1597 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1597 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1598 if len(ps) > 1:
1598 if len(ps) > 1:
1599 if not p2:
1599 if not p2:
1600 p2 = repo[ps[1]]
1600 p2 = repo[ps[1]]
1601 for fn in p2:
1601 for fn in p2:
1602 if fn.startswith("nf"):
1602 if fn.startswith("nf"):
1603 files.append(fn)
1603 files.append(fn)
1604 fctxs[fn] = p2[fn]
1604 fctxs[fn] = p2[fn]
1605
1605
1606 def fctxfn(repo, cx, path):
1606 def fctxfn(repo, cx, path):
1607 return fctxs.get(path)
1607 return fctxs.get(path)
1608
1608
1609 if len(ps) == 0 or ps[0] < 0:
1609 if len(ps) == 0 or ps[0] < 0:
1610 pars = [None, None]
1610 pars = [None, None]
1611 elif len(ps) == 1:
1611 elif len(ps) == 1:
1612 pars = [nodeids[ps[0]], None]
1612 pars = [nodeids[ps[0]], None]
1613 else:
1613 else:
1614 pars = [nodeids[p] for p in ps]
1614 pars = [nodeids[p] for p in ps]
1615 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1615 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1616 date=(id, 0),
1616 date=(id, 0),
1617 user="debugbuilddag",
1617 user="debugbuilddag",
1618 extra={'branch': atbranch})
1618 extra={'branch': atbranch})
1619 nodeid = repo.commitctx(cx)
1619 nodeid = repo.commitctx(cx)
1620 nodeids.append(nodeid)
1620 nodeids.append(nodeid)
1621 at = id
1621 at = id
1622 elif type == 'l':
1622 elif type == 'l':
1623 id, name = data
1623 id, name = data
1624 ui.note(('tag %s\n' % name))
1624 ui.note(('tag %s\n' % name))
1625 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1625 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1626 elif type == 'a':
1626 elif type == 'a':
1627 ui.note(('branch %s\n' % data))
1627 ui.note(('branch %s\n' % data))
1628 atbranch = data
1628 atbranch = data
1629 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1629 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1630 tr.close()
1630 tr.close()
1631
1631
1632 if tags:
1632 if tags:
1633 repo.opener.write("localtags", "".join(tags))
1633 repo.opener.write("localtags", "".join(tags))
1634 finally:
1634 finally:
1635 ui.progress(_('building'), None)
1635 ui.progress(_('building'), None)
1636 release(tr, lock)
1636 release(tr, lock)
1637
1637
1638 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1638 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1639 def debugbundle(ui, bundlepath, all=None, **opts):
1639 def debugbundle(ui, bundlepath, all=None, **opts):
1640 """lists the contents of a bundle"""
1640 """lists the contents of a bundle"""
1641 f = hg.openpath(ui, bundlepath)
1641 f = hg.openpath(ui, bundlepath)
1642 try:
1642 try:
1643 gen = changegroup.readbundle(f, bundlepath)
1643 gen = changegroup.readbundle(f, bundlepath)
1644 if all:
1644 if all:
1645 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1645 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1646
1646
1647 def showchunks(named):
1647 def showchunks(named):
1648 ui.write("\n%s\n" % named)
1648 ui.write("\n%s\n" % named)
1649 chain = None
1649 chain = None
1650 while True:
1650 while True:
1651 chunkdata = gen.deltachunk(chain)
1651 chunkdata = gen.deltachunk(chain)
1652 if not chunkdata:
1652 if not chunkdata:
1653 break
1653 break
1654 node = chunkdata['node']
1654 node = chunkdata['node']
1655 p1 = chunkdata['p1']
1655 p1 = chunkdata['p1']
1656 p2 = chunkdata['p2']
1656 p2 = chunkdata['p2']
1657 cs = chunkdata['cs']
1657 cs = chunkdata['cs']
1658 deltabase = chunkdata['deltabase']
1658 deltabase = chunkdata['deltabase']
1659 delta = chunkdata['delta']
1659 delta = chunkdata['delta']
1660 ui.write("%s %s %s %s %s %s\n" %
1660 ui.write("%s %s %s %s %s %s\n" %
1661 (hex(node), hex(p1), hex(p2),
1661 (hex(node), hex(p1), hex(p2),
1662 hex(cs), hex(deltabase), len(delta)))
1662 hex(cs), hex(deltabase), len(delta)))
1663 chain = node
1663 chain = node
1664
1664
1665 chunkdata = gen.changelogheader()
1665 chunkdata = gen.changelogheader()
1666 showchunks("changelog")
1666 showchunks("changelog")
1667 chunkdata = gen.manifestheader()
1667 chunkdata = gen.manifestheader()
1668 showchunks("manifest")
1668 showchunks("manifest")
1669 while True:
1669 while True:
1670 chunkdata = gen.filelogheader()
1670 chunkdata = gen.filelogheader()
1671 if not chunkdata:
1671 if not chunkdata:
1672 break
1672 break
1673 fname = chunkdata['filename']
1673 fname = chunkdata['filename']
1674 showchunks(fname)
1674 showchunks(fname)
1675 else:
1675 else:
1676 chunkdata = gen.changelogheader()
1676 chunkdata = gen.changelogheader()
1677 chain = None
1677 chain = None
1678 while True:
1678 while True:
1679 chunkdata = gen.deltachunk(chain)
1679 chunkdata = gen.deltachunk(chain)
1680 if not chunkdata:
1680 if not chunkdata:
1681 break
1681 break
1682 node = chunkdata['node']
1682 node = chunkdata['node']
1683 ui.write("%s\n" % hex(node))
1683 ui.write("%s\n" % hex(node))
1684 chain = node
1684 chain = node
1685 finally:
1685 finally:
1686 f.close()
1686 f.close()
1687
1687
1688 @command('debugcheckstate', [], '')
1688 @command('debugcheckstate', [], '')
1689 def debugcheckstate(ui, repo):
1689 def debugcheckstate(ui, repo):
1690 """validate the correctness of the current dirstate"""
1690 """validate the correctness of the current dirstate"""
1691 parent1, parent2 = repo.dirstate.parents()
1691 parent1, parent2 = repo.dirstate.parents()
1692 m1 = repo[parent1].manifest()
1692 m1 = repo[parent1].manifest()
1693 m2 = repo[parent2].manifest()
1693 m2 = repo[parent2].manifest()
1694 errors = 0
1694 errors = 0
1695 for f in repo.dirstate:
1695 for f in repo.dirstate:
1696 state = repo.dirstate[f]
1696 state = repo.dirstate[f]
1697 if state in "nr" and f not in m1:
1697 if state in "nr" and f not in m1:
1698 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1698 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1699 errors += 1
1699 errors += 1
1700 if state in "a" and f in m1:
1700 if state in "a" and f in m1:
1701 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1701 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1702 errors += 1
1702 errors += 1
1703 if state in "m" and f not in m1 and f not in m2:
1703 if state in "m" and f not in m1 and f not in m2:
1704 ui.warn(_("%s in state %s, but not in either manifest\n") %
1704 ui.warn(_("%s in state %s, but not in either manifest\n") %
1705 (f, state))
1705 (f, state))
1706 errors += 1
1706 errors += 1
1707 for f in m1:
1707 for f in m1:
1708 state = repo.dirstate[f]
1708 state = repo.dirstate[f]
1709 if state not in "nrm":
1709 if state not in "nrm":
1710 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1710 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1711 errors += 1
1711 errors += 1
1712 if errors:
1712 if errors:
1713 error = _(".hg/dirstate inconsistent with current parent's manifest")
1713 error = _(".hg/dirstate inconsistent with current parent's manifest")
1714 raise util.Abort(error)
1714 raise util.Abort(error)
1715
1715
1716 @command('debugcommands', [], _('[COMMAND]'))
1716 @command('debugcommands', [], _('[COMMAND]'))
1717 def debugcommands(ui, cmd='', *args):
1717 def debugcommands(ui, cmd='', *args):
1718 """list all available commands and options"""
1718 """list all available commands and options"""
1719 for cmd, vals in sorted(table.iteritems()):
1719 for cmd, vals in sorted(table.iteritems()):
1720 cmd = cmd.split('|')[0].strip('^')
1720 cmd = cmd.split('|')[0].strip('^')
1721 opts = ', '.join([i[1] for i in vals[1]])
1721 opts = ', '.join([i[1] for i in vals[1]])
1722 ui.write('%s: %s\n' % (cmd, opts))
1722 ui.write('%s: %s\n' % (cmd, opts))
1723
1723
1724 @command('debugcomplete',
1724 @command('debugcomplete',
1725 [('o', 'options', None, _('show the command options'))],
1725 [('o', 'options', None, _('show the command options'))],
1726 _('[-o] CMD'))
1726 _('[-o] CMD'))
1727 def debugcomplete(ui, cmd='', **opts):
1727 def debugcomplete(ui, cmd='', **opts):
1728 """returns the completion list associated with the given command"""
1728 """returns the completion list associated with the given command"""
1729
1729
1730 if opts.get('options'):
1730 if opts.get('options'):
1731 options = []
1731 options = []
1732 otables = [globalopts]
1732 otables = [globalopts]
1733 if cmd:
1733 if cmd:
1734 aliases, entry = cmdutil.findcmd(cmd, table, False)
1734 aliases, entry = cmdutil.findcmd(cmd, table, False)
1735 otables.append(entry[1])
1735 otables.append(entry[1])
1736 for t in otables:
1736 for t in otables:
1737 for o in t:
1737 for o in t:
1738 if "(DEPRECATED)" in o[3]:
1738 if "(DEPRECATED)" in o[3]:
1739 continue
1739 continue
1740 if o[0]:
1740 if o[0]:
1741 options.append('-%s' % o[0])
1741 options.append('-%s' % o[0])
1742 options.append('--%s' % o[1])
1742 options.append('--%s' % o[1])
1743 ui.write("%s\n" % "\n".join(options))
1743 ui.write("%s\n" % "\n".join(options))
1744 return
1744 return
1745
1745
1746 cmdlist = cmdutil.findpossible(cmd, table)
1746 cmdlist = cmdutil.findpossible(cmd, table)
1747 if ui.verbose:
1747 if ui.verbose:
1748 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1748 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1749 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1749 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1750
1750
1751 @command('debugdag',
1751 @command('debugdag',
1752 [('t', 'tags', None, _('use tags as labels')),
1752 [('t', 'tags', None, _('use tags as labels')),
1753 ('b', 'branches', None, _('annotate with branch names')),
1753 ('b', 'branches', None, _('annotate with branch names')),
1754 ('', 'dots', None, _('use dots for runs')),
1754 ('', 'dots', None, _('use dots for runs')),
1755 ('s', 'spaces', None, _('separate elements by spaces'))],
1755 ('s', 'spaces', None, _('separate elements by spaces'))],
1756 _('[OPTION]... [FILE [REV]...]'))
1756 _('[OPTION]... [FILE [REV]...]'))
1757 def debugdag(ui, repo, file_=None, *revs, **opts):
1757 def debugdag(ui, repo, file_=None, *revs, **opts):
1758 """format the changelog or an index DAG as a concise textual description
1758 """format the changelog or an index DAG as a concise textual description
1759
1759
1760 If you pass a revlog index, the revlog's DAG is emitted. If you list
1760 If you pass a revlog index, the revlog's DAG is emitted. If you list
1761 revision numbers, they get labeled in the output as rN.
1761 revision numbers, they get labeled in the output as rN.
1762
1762
1763 Otherwise, the changelog DAG of the current repo is emitted.
1763 Otherwise, the changelog DAG of the current repo is emitted.
1764 """
1764 """
1765 spaces = opts.get('spaces')
1765 spaces = opts.get('spaces')
1766 dots = opts.get('dots')
1766 dots = opts.get('dots')
1767 if file_:
1767 if file_:
1768 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1768 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1769 revs = set((int(r) for r in revs))
1769 revs = set((int(r) for r in revs))
1770 def events():
1770 def events():
1771 for r in rlog:
1771 for r in rlog:
1772 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1772 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1773 if p != -1)))
1773 if p != -1)))
1774 if r in revs:
1774 if r in revs:
1775 yield 'l', (r, "r%i" % r)
1775 yield 'l', (r, "r%i" % r)
1776 elif repo:
1776 elif repo:
1777 cl = repo.changelog
1777 cl = repo.changelog
1778 tags = opts.get('tags')
1778 tags = opts.get('tags')
1779 branches = opts.get('branches')
1779 branches = opts.get('branches')
1780 if tags:
1780 if tags:
1781 labels = {}
1781 labels = {}
1782 for l, n in repo.tags().items():
1782 for l, n in repo.tags().items():
1783 labels.setdefault(cl.rev(n), []).append(l)
1783 labels.setdefault(cl.rev(n), []).append(l)
1784 def events():
1784 def events():
1785 b = "default"
1785 b = "default"
1786 for r in cl:
1786 for r in cl:
1787 if branches:
1787 if branches:
1788 newb = cl.read(cl.node(r))[5]['branch']
1788 newb = cl.read(cl.node(r))[5]['branch']
1789 if newb != b:
1789 if newb != b:
1790 yield 'a', newb
1790 yield 'a', newb
1791 b = newb
1791 b = newb
1792 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1792 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1793 if p != -1)))
1793 if p != -1)))
1794 if tags:
1794 if tags:
1795 ls = labels.get(r)
1795 ls = labels.get(r)
1796 if ls:
1796 if ls:
1797 for l in ls:
1797 for l in ls:
1798 yield 'l', (r, l)
1798 yield 'l', (r, l)
1799 else:
1799 else:
1800 raise util.Abort(_('need repo for changelog dag'))
1800 raise util.Abort(_('need repo for changelog dag'))
1801
1801
1802 for line in dagparser.dagtextlines(events(),
1802 for line in dagparser.dagtextlines(events(),
1803 addspaces=spaces,
1803 addspaces=spaces,
1804 wraplabels=True,
1804 wraplabels=True,
1805 wrapannotations=True,
1805 wrapannotations=True,
1806 wrapnonlinear=dots,
1806 wrapnonlinear=dots,
1807 usedots=dots,
1807 usedots=dots,
1808 maxlinewidth=70):
1808 maxlinewidth=70):
1809 ui.write(line)
1809 ui.write(line)
1810 ui.write("\n")
1810 ui.write("\n")
1811
1811
1812 @command('debugdata',
1812 @command('debugdata',
1813 [('c', 'changelog', False, _('open changelog')),
1813 [('c', 'changelog', False, _('open changelog')),
1814 ('m', 'manifest', False, _('open manifest'))],
1814 ('m', 'manifest', False, _('open manifest'))],
1815 _('-c|-m|FILE REV'))
1815 _('-c|-m|FILE REV'))
1816 def debugdata(ui, repo, file_, rev=None, **opts):
1816 def debugdata(ui, repo, file_, rev=None, **opts):
1817 """dump the contents of a data file revision"""
1817 """dump the contents of a data file revision"""
1818 if opts.get('changelog') or opts.get('manifest'):
1818 if opts.get('changelog') or opts.get('manifest'):
1819 file_, rev = None, file_
1819 file_, rev = None, file_
1820 elif rev is None:
1820 elif rev is None:
1821 raise error.CommandError('debugdata', _('invalid arguments'))
1821 raise error.CommandError('debugdata', _('invalid arguments'))
1822 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1822 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1823 try:
1823 try:
1824 ui.write(r.revision(r.lookup(rev)))
1824 ui.write(r.revision(r.lookup(rev)))
1825 except KeyError:
1825 except KeyError:
1826 raise util.Abort(_('invalid revision identifier %s') % rev)
1826 raise util.Abort(_('invalid revision identifier %s') % rev)
1827
1827
1828 @command('debugdate',
1828 @command('debugdate',
1829 [('e', 'extended', None, _('try extended date formats'))],
1829 [('e', 'extended', None, _('try extended date formats'))],
1830 _('[-e] DATE [RANGE]'))
1830 _('[-e] DATE [RANGE]'))
1831 def debugdate(ui, date, range=None, **opts):
1831 def debugdate(ui, date, range=None, **opts):
1832 """parse and display a date"""
1832 """parse and display a date"""
1833 if opts["extended"]:
1833 if opts["extended"]:
1834 d = util.parsedate(date, util.extendeddateformats)
1834 d = util.parsedate(date, util.extendeddateformats)
1835 else:
1835 else:
1836 d = util.parsedate(date)
1836 d = util.parsedate(date)
1837 ui.write(("internal: %s %s\n") % d)
1837 ui.write(("internal: %s %s\n") % d)
1838 ui.write(("standard: %s\n") % util.datestr(d))
1838 ui.write(("standard: %s\n") % util.datestr(d))
1839 if range:
1839 if range:
1840 m = util.matchdate(range)
1840 m = util.matchdate(range)
1841 ui.write(("match: %s\n") % m(d[0]))
1841 ui.write(("match: %s\n") % m(d[0]))
1842
1842
1843 @command('debugdiscovery',
1843 @command('debugdiscovery',
1844 [('', 'old', None, _('use old-style discovery')),
1844 [('', 'old', None, _('use old-style discovery')),
1845 ('', 'nonheads', None,
1845 ('', 'nonheads', None,
1846 _('use old-style discovery with non-heads included')),
1846 _('use old-style discovery with non-heads included')),
1847 ] + remoteopts,
1847 ] + remoteopts,
1848 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1848 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1849 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1849 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1850 """runs the changeset discovery protocol in isolation"""
1850 """runs the changeset discovery protocol in isolation"""
1851 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1851 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1852 opts.get('branch'))
1852 opts.get('branch'))
1853 remote = hg.peer(repo, opts, remoteurl)
1853 remote = hg.peer(repo, opts, remoteurl)
1854 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1854 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1855
1855
1856 # make sure tests are repeatable
1856 # make sure tests are repeatable
1857 random.seed(12323)
1857 random.seed(12323)
1858
1858
1859 def doit(localheads, remoteheads, remote=remote):
1859 def doit(localheads, remoteheads, remote=remote):
1860 if opts.get('old'):
1860 if opts.get('old'):
1861 if localheads:
1861 if localheads:
1862 raise util.Abort('cannot use localheads with old style '
1862 raise util.Abort('cannot use localheads with old style '
1863 'discovery')
1863 'discovery')
1864 if not util.safehasattr(remote, 'branches'):
1864 if not util.safehasattr(remote, 'branches'):
1865 # enable in-client legacy support
1865 # enable in-client legacy support
1866 remote = localrepo.locallegacypeer(remote.local())
1866 remote = localrepo.locallegacypeer(remote.local())
1867 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1867 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1868 force=True)
1868 force=True)
1869 common = set(common)
1869 common = set(common)
1870 if not opts.get('nonheads'):
1870 if not opts.get('nonheads'):
1871 ui.write(("unpruned common: %s\n") %
1871 ui.write(("unpruned common: %s\n") %
1872 " ".join(sorted(short(n) for n in common)))
1872 " ".join(sorted(short(n) for n in common)))
1873 dag = dagutil.revlogdag(repo.changelog)
1873 dag = dagutil.revlogdag(repo.changelog)
1874 all = dag.ancestorset(dag.internalizeall(common))
1874 all = dag.ancestorset(dag.internalizeall(common))
1875 common = dag.externalizeall(dag.headsetofconnecteds(all))
1875 common = dag.externalizeall(dag.headsetofconnecteds(all))
1876 else:
1876 else:
1877 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1877 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1878 common = set(common)
1878 common = set(common)
1879 rheads = set(hds)
1879 rheads = set(hds)
1880 lheads = set(repo.heads())
1880 lheads = set(repo.heads())
1881 ui.write(("common heads: %s\n") %
1881 ui.write(("common heads: %s\n") %
1882 " ".join(sorted(short(n) for n in common)))
1882 " ".join(sorted(short(n) for n in common)))
1883 if lheads <= common:
1883 if lheads <= common:
1884 ui.write(("local is subset\n"))
1884 ui.write(("local is subset\n"))
1885 elif rheads <= common:
1885 elif rheads <= common:
1886 ui.write(("remote is subset\n"))
1886 ui.write(("remote is subset\n"))
1887
1887
1888 serverlogs = opts.get('serverlog')
1888 serverlogs = opts.get('serverlog')
1889 if serverlogs:
1889 if serverlogs:
1890 for filename in serverlogs:
1890 for filename in serverlogs:
1891 logfile = open(filename, 'r')
1891 logfile = open(filename, 'r')
1892 try:
1892 try:
1893 line = logfile.readline()
1893 line = logfile.readline()
1894 while line:
1894 while line:
1895 parts = line.strip().split(';')
1895 parts = line.strip().split(';')
1896 op = parts[1]
1896 op = parts[1]
1897 if op == 'cg':
1897 if op == 'cg':
1898 pass
1898 pass
1899 elif op == 'cgss':
1899 elif op == 'cgss':
1900 doit(parts[2].split(' '), parts[3].split(' '))
1900 doit(parts[2].split(' '), parts[3].split(' '))
1901 elif op == 'unb':
1901 elif op == 'unb':
1902 doit(parts[3].split(' '), parts[2].split(' '))
1902 doit(parts[3].split(' '), parts[2].split(' '))
1903 line = logfile.readline()
1903 line = logfile.readline()
1904 finally:
1904 finally:
1905 logfile.close()
1905 logfile.close()
1906
1906
1907 else:
1907 else:
1908 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1908 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1909 opts.get('remote_head'))
1909 opts.get('remote_head'))
1910 localrevs = opts.get('local_head')
1910 localrevs = opts.get('local_head')
1911 doit(localrevs, remoterevs)
1911 doit(localrevs, remoterevs)
1912
1912
1913 @command('debugfileset',
1913 @command('debugfileset',
1914 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1914 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1915 _('[-r REV] FILESPEC'))
1915 _('[-r REV] FILESPEC'))
1916 def debugfileset(ui, repo, expr, **opts):
1916 def debugfileset(ui, repo, expr, **opts):
1917 '''parse and apply a fileset specification'''
1917 '''parse and apply a fileset specification'''
1918 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1918 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1919 if ui.verbose:
1919 if ui.verbose:
1920 tree = fileset.parse(expr)[0]
1920 tree = fileset.parse(expr)[0]
1921 ui.note(tree, "\n")
1921 ui.note(tree, "\n")
1922
1922
1923 for f in fileset.getfileset(ctx, expr):
1923 for f in fileset.getfileset(ctx, expr):
1924 ui.write("%s\n" % f)
1924 ui.write("%s\n" % f)
1925
1925
1926 @command('debugfsinfo', [], _('[PATH]'))
1926 @command('debugfsinfo', [], _('[PATH]'))
1927 def debugfsinfo(ui, path="."):
1927 def debugfsinfo(ui, path="."):
1928 """show information detected about current filesystem"""
1928 """show information detected about current filesystem"""
1929 util.writefile('.debugfsinfo', '')
1929 util.writefile('.debugfsinfo', '')
1930 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1930 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1931 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1931 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1932 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1932 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1933 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1933 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1934 and 'yes' or 'no'))
1934 and 'yes' or 'no'))
1935 os.unlink('.debugfsinfo')
1935 os.unlink('.debugfsinfo')
1936
1936
1937 @command('debuggetbundle',
1937 @command('debuggetbundle',
1938 [('H', 'head', [], _('id of head node'), _('ID')),
1938 [('H', 'head', [], _('id of head node'), _('ID')),
1939 ('C', 'common', [], _('id of common node'), _('ID')),
1939 ('C', 'common', [], _('id of common node'), _('ID')),
1940 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1940 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1941 _('REPO FILE [-H|-C ID]...'))
1941 _('REPO FILE [-H|-C ID]...'))
1942 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1942 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1943 """retrieves a bundle from a repo
1943 """retrieves a bundle from a repo
1944
1944
1945 Every ID must be a full-length hex node id string. Saves the bundle to the
1945 Every ID must be a full-length hex node id string. Saves the bundle to the
1946 given file.
1946 given file.
1947 """
1947 """
1948 repo = hg.peer(ui, opts, repopath)
1948 repo = hg.peer(ui, opts, repopath)
1949 if not repo.capable('getbundle'):
1949 if not repo.capable('getbundle'):
1950 raise util.Abort("getbundle() not supported by target repository")
1950 raise util.Abort("getbundle() not supported by target repository")
1951 args = {}
1951 args = {}
1952 if common:
1952 if common:
1953 args['common'] = [bin(s) for s in common]
1953 args['common'] = [bin(s) for s in common]
1954 if head:
1954 if head:
1955 args['heads'] = [bin(s) for s in head]
1955 args['heads'] = [bin(s) for s in head]
1956 # TODO: get desired bundlecaps from command line.
1956 # TODO: get desired bundlecaps from command line.
1957 args['bundlecaps'] = None
1957 args['bundlecaps'] = None
1958 bundle = repo.getbundle('debug', **args)
1958 bundle = repo.getbundle('debug', **args)
1959
1959
1960 bundletype = opts.get('type', 'bzip2').lower()
1960 bundletype = opts.get('type', 'bzip2').lower()
1961 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1961 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1962 bundletype = btypes.get(bundletype)
1962 bundletype = btypes.get(bundletype)
1963 if bundletype not in changegroup.bundletypes:
1963 if bundletype not in changegroup.bundletypes:
1964 raise util.Abort(_('unknown bundle type specified with --type'))
1964 raise util.Abort(_('unknown bundle type specified with --type'))
1965 changegroup.writebundle(bundle, bundlepath, bundletype)
1965 changegroup.writebundle(bundle, bundlepath, bundletype)
1966
1966
1967 @command('debugignore', [], '')
1967 @command('debugignore', [], '')
1968 def debugignore(ui, repo, *values, **opts):
1968 def debugignore(ui, repo, *values, **opts):
1969 """display the combined ignore pattern"""
1969 """display the combined ignore pattern"""
1970 ignore = repo.dirstate._ignore
1970 ignore = repo.dirstate._ignore
1971 includepat = getattr(ignore, 'includepat', None)
1971 includepat = getattr(ignore, 'includepat', None)
1972 if includepat is not None:
1972 if includepat is not None:
1973 ui.write("%s\n" % includepat)
1973 ui.write("%s\n" % includepat)
1974 else:
1974 else:
1975 raise util.Abort(_("no ignore patterns found"))
1975 raise util.Abort(_("no ignore patterns found"))
1976
1976
1977 @command('debugindex',
1977 @command('debugindex',
1978 [('c', 'changelog', False, _('open changelog')),
1978 [('c', 'changelog', False, _('open changelog')),
1979 ('m', 'manifest', False, _('open manifest')),
1979 ('m', 'manifest', False, _('open manifest')),
1980 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1980 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1981 _('[-f FORMAT] -c|-m|FILE'))
1981 _('[-f FORMAT] -c|-m|FILE'))
1982 def debugindex(ui, repo, file_=None, **opts):
1982 def debugindex(ui, repo, file_=None, **opts):
1983 """dump the contents of an index file"""
1983 """dump the contents of an index file"""
1984 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1984 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1985 format = opts.get('format', 0)
1985 format = opts.get('format', 0)
1986 if format not in (0, 1):
1986 if format not in (0, 1):
1987 raise util.Abort(_("unknown format %d") % format)
1987 raise util.Abort(_("unknown format %d") % format)
1988
1988
1989 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1989 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1990 if generaldelta:
1990 if generaldelta:
1991 basehdr = ' delta'
1991 basehdr = ' delta'
1992 else:
1992 else:
1993 basehdr = ' base'
1993 basehdr = ' base'
1994
1994
1995 if format == 0:
1995 if format == 0:
1996 ui.write(" rev offset length " + basehdr + " linkrev"
1996 ui.write(" rev offset length " + basehdr + " linkrev"
1997 " nodeid p1 p2\n")
1997 " nodeid p1 p2\n")
1998 elif format == 1:
1998 elif format == 1:
1999 ui.write(" rev flag offset length"
1999 ui.write(" rev flag offset length"
2000 " size " + basehdr + " link p1 p2"
2000 " size " + basehdr + " link p1 p2"
2001 " nodeid\n")
2001 " nodeid\n")
2002
2002
2003 for i in r:
2003 for i in r:
2004 node = r.node(i)
2004 node = r.node(i)
2005 if generaldelta:
2005 if generaldelta:
2006 base = r.deltaparent(i)
2006 base = r.deltaparent(i)
2007 else:
2007 else:
2008 base = r.chainbase(i)
2008 base = r.chainbase(i)
2009 if format == 0:
2009 if format == 0:
2010 try:
2010 try:
2011 pp = r.parents(node)
2011 pp = r.parents(node)
2012 except Exception:
2012 except Exception:
2013 pp = [nullid, nullid]
2013 pp = [nullid, nullid]
2014 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2014 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2015 i, r.start(i), r.length(i), base, r.linkrev(i),
2015 i, r.start(i), r.length(i), base, r.linkrev(i),
2016 short(node), short(pp[0]), short(pp[1])))
2016 short(node), short(pp[0]), short(pp[1])))
2017 elif format == 1:
2017 elif format == 1:
2018 pr = r.parentrevs(i)
2018 pr = r.parentrevs(i)
2019 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2019 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2020 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2020 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2021 base, r.linkrev(i), pr[0], pr[1], short(node)))
2021 base, r.linkrev(i), pr[0], pr[1], short(node)))
2022
2022
2023 @command('debugindexdot', [], _('FILE'))
2023 @command('debugindexdot', [], _('FILE'))
2024 def debugindexdot(ui, repo, file_):
2024 def debugindexdot(ui, repo, file_):
2025 """dump an index DAG as a graphviz dot file"""
2025 """dump an index DAG as a graphviz dot file"""
2026 r = None
2026 r = None
2027 if repo:
2027 if repo:
2028 filelog = repo.file(file_)
2028 filelog = repo.file(file_)
2029 if len(filelog):
2029 if len(filelog):
2030 r = filelog
2030 r = filelog
2031 if not r:
2031 if not r:
2032 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2032 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2033 ui.write(("digraph G {\n"))
2033 ui.write(("digraph G {\n"))
2034 for i in r:
2034 for i in r:
2035 node = r.node(i)
2035 node = r.node(i)
2036 pp = r.parents(node)
2036 pp = r.parents(node)
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2038 if pp[1] != nullid:
2038 if pp[1] != nullid:
2039 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2039 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2040 ui.write("}\n")
2040 ui.write("}\n")
2041
2041
2042 @command('debuginstall', [], '')
2042 @command('debuginstall', [], '')
2043 def debuginstall(ui):
2043 def debuginstall(ui):
2044 '''test Mercurial installation
2044 '''test Mercurial installation
2045
2045
2046 Returns 0 on success.
2046 Returns 0 on success.
2047 '''
2047 '''
2048
2048
2049 def writetemp(contents):
2049 def writetemp(contents):
2050 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2050 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2051 f = os.fdopen(fd, "wb")
2051 f = os.fdopen(fd, "wb")
2052 f.write(contents)
2052 f.write(contents)
2053 f.close()
2053 f.close()
2054 return name
2054 return name
2055
2055
2056 problems = 0
2056 problems = 0
2057
2057
2058 # encoding
2058 # encoding
2059 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2059 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2060 try:
2060 try:
2061 encoding.fromlocal("test")
2061 encoding.fromlocal("test")
2062 except util.Abort, inst:
2062 except util.Abort, inst:
2063 ui.write(" %s\n" % inst)
2063 ui.write(" %s\n" % inst)
2064 ui.write(_(" (check that your locale is properly set)\n"))
2064 ui.write(_(" (check that your locale is properly set)\n"))
2065 problems += 1
2065 problems += 1
2066
2066
2067 # Python lib
2067 # Python lib
2068 ui.status(_("checking Python lib (%s)...\n")
2068 ui.status(_("checking Python lib (%s)...\n")
2069 % os.path.dirname(os.__file__))
2069 % os.path.dirname(os.__file__))
2070
2070
2071 # compiled modules
2071 # compiled modules
2072 ui.status(_("checking installed modules (%s)...\n")
2072 ui.status(_("checking installed modules (%s)...\n")
2073 % os.path.dirname(__file__))
2073 % os.path.dirname(__file__))
2074 try:
2074 try:
2075 import bdiff, mpatch, base85, osutil
2075 import bdiff, mpatch, base85, osutil
2076 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2076 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2077 except Exception, inst:
2077 except Exception, inst:
2078 ui.write(" %s\n" % inst)
2078 ui.write(" %s\n" % inst)
2079 ui.write(_(" One or more extensions could not be found"))
2079 ui.write(_(" One or more extensions could not be found"))
2080 ui.write(_(" (check that you compiled the extensions)\n"))
2080 ui.write(_(" (check that you compiled the extensions)\n"))
2081 problems += 1
2081 problems += 1
2082
2082
2083 # templates
2083 # templates
2084 import templater
2084 import templater
2085 p = templater.templatepath()
2085 p = templater.templatepath()
2086 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2086 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2087 try:
2087 try:
2088 templater.templater(templater.templatepath("map-cmdline.default"))
2088 templater.templater(templater.templatepath("map-cmdline.default"))
2089 except Exception, inst:
2089 except Exception, inst:
2090 ui.write(" %s\n" % inst)
2090 ui.write(" %s\n" % inst)
2091 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2091 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2092 problems += 1
2092 problems += 1
2093
2093
2094 # editor
2094 # editor
2095 ui.status(_("checking commit editor...\n"))
2095 ui.status(_("checking commit editor...\n"))
2096 editor = ui.geteditor()
2096 editor = ui.geteditor()
2097 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2097 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2098 if not cmdpath:
2098 if not cmdpath:
2099 if editor == 'vi':
2099 if editor == 'vi':
2100 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2100 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2101 ui.write(_(" (specify a commit editor in your configuration"
2101 ui.write(_(" (specify a commit editor in your configuration"
2102 " file)\n"))
2102 " file)\n"))
2103 else:
2103 else:
2104 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2104 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2105 ui.write(_(" (specify a commit editor in your configuration"
2105 ui.write(_(" (specify a commit editor in your configuration"
2106 " file)\n"))
2106 " file)\n"))
2107 problems += 1
2107 problems += 1
2108
2108
2109 # check username
2109 # check username
2110 ui.status(_("checking username...\n"))
2110 ui.status(_("checking username...\n"))
2111 try:
2111 try:
2112 ui.username()
2112 ui.username()
2113 except util.Abort, e:
2113 except util.Abort, e:
2114 ui.write(" %s\n" % e)
2114 ui.write(" %s\n" % e)
2115 ui.write(_(" (specify a username in your configuration file)\n"))
2115 ui.write(_(" (specify a username in your configuration file)\n"))
2116 problems += 1
2116 problems += 1
2117
2117
2118 if not problems:
2118 if not problems:
2119 ui.status(_("no problems detected\n"))
2119 ui.status(_("no problems detected\n"))
2120 else:
2120 else:
2121 ui.write(_("%s problems detected,"
2121 ui.write(_("%s problems detected,"
2122 " please check your install!\n") % problems)
2122 " please check your install!\n") % problems)
2123
2123
2124 return problems
2124 return problems
2125
2125
2126 @command('debugknown', [], _('REPO ID...'))
2126 @command('debugknown', [], _('REPO ID...'))
2127 def debugknown(ui, repopath, *ids, **opts):
2127 def debugknown(ui, repopath, *ids, **opts):
2128 """test whether node ids are known to a repo
2128 """test whether node ids are known to a repo
2129
2129
2130 Every ID must be a full-length hex node id string. Returns a list of 0s
2130 Every ID must be a full-length hex node id string. Returns a list of 0s
2131 and 1s indicating unknown/known.
2131 and 1s indicating unknown/known.
2132 """
2132 """
2133 repo = hg.peer(ui, opts, repopath)
2133 repo = hg.peer(ui, opts, repopath)
2134 if not repo.capable('known'):
2134 if not repo.capable('known'):
2135 raise util.Abort("known() not supported by target repository")
2135 raise util.Abort("known() not supported by target repository")
2136 flags = repo.known([bin(s) for s in ids])
2136 flags = repo.known([bin(s) for s in ids])
2137 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2137 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2138
2138
2139 @command('debuglabelcomplete', [], _('LABEL...'))
2139 @command('debuglabelcomplete', [], _('LABEL...'))
2140 def debuglabelcomplete(ui, repo, *args):
2140 def debuglabelcomplete(ui, repo, *args):
2141 '''complete "labels" - tags, open branch names, bookmark names'''
2141 '''complete "labels" - tags, open branch names, bookmark names'''
2142
2142
2143 labels = set()
2143 labels = set()
2144 labels.update(t[0] for t in repo.tagslist())
2144 labels.update(t[0] for t in repo.tagslist())
2145 labels.update(repo._bookmarks.keys())
2145 labels.update(repo._bookmarks.keys())
2146 for heads in repo.branchmap().itervalues():
2146 for heads in repo.branchmap().itervalues():
2147 for h in heads:
2147 for h in heads:
2148 ctx = repo[h]
2148 ctx = repo[h]
2149 if not ctx.closesbranch():
2149 if not ctx.closesbranch():
2150 labels.add(ctx.branch())
2150 labels.add(ctx.branch())
2151 completions = set()
2151 completions = set()
2152 if not args:
2152 if not args:
2153 args = ['']
2153 args = ['']
2154 for a in args:
2154 for a in args:
2155 completions.update(l for l in labels if l.startswith(a))
2155 completions.update(l for l in labels if l.startswith(a))
2156 ui.write('\n'.join(sorted(completions)))
2156 ui.write('\n'.join(sorted(completions)))
2157 ui.write('\n')
2157 ui.write('\n')
2158
2158
2159 @command('debugobsolete',
2159 @command('debugobsolete',
2160 [('', 'flags', 0, _('markers flag')),
2160 [('', 'flags', 0, _('markers flag')),
2161 ] + commitopts2,
2161 ] + commitopts2,
2162 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2162 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2163 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2163 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2164 """create arbitrary obsolete marker
2164 """create arbitrary obsolete marker
2165
2165
2166 With no arguments, displays the list of obsolescence markers."""
2166 With no arguments, displays the list of obsolescence markers."""
2167 def parsenodeid(s):
2167 def parsenodeid(s):
2168 try:
2168 try:
2169 # We do not use revsingle/revrange functions here to accept
2169 # We do not use revsingle/revrange functions here to accept
2170 # arbitrary node identifiers, possibly not present in the
2170 # arbitrary node identifiers, possibly not present in the
2171 # local repository.
2171 # local repository.
2172 n = bin(s)
2172 n = bin(s)
2173 if len(n) != len(nullid):
2173 if len(n) != len(nullid):
2174 raise TypeError()
2174 raise TypeError()
2175 return n
2175 return n
2176 except TypeError:
2176 except TypeError:
2177 raise util.Abort('changeset references must be full hexadecimal '
2177 raise util.Abort('changeset references must be full hexadecimal '
2178 'node identifiers')
2178 'node identifiers')
2179
2179
2180 if precursor is not None:
2180 if precursor is not None:
2181 metadata = {}
2181 metadata = {}
2182 if 'date' in opts:
2182 if 'date' in opts:
2183 metadata['date'] = opts['date']
2183 metadata['date'] = opts['date']
2184 metadata['user'] = opts['user'] or ui.username()
2184 metadata['user'] = opts['user'] or ui.username()
2185 succs = tuple(parsenodeid(succ) for succ in successors)
2185 succs = tuple(parsenodeid(succ) for succ in successors)
2186 l = repo.lock()
2186 l = repo.lock()
2187 try:
2187 try:
2188 tr = repo.transaction('debugobsolete')
2188 tr = repo.transaction('debugobsolete')
2189 try:
2189 try:
2190 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2190 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2191 opts['flags'], metadata)
2191 opts['flags'], metadata)
2192 tr.close()
2192 tr.close()
2193 finally:
2193 finally:
2194 tr.release()
2194 tr.release()
2195 finally:
2195 finally:
2196 l.release()
2196 l.release()
2197 else:
2197 else:
2198 for m in obsolete.allmarkers(repo):
2198 for m in obsolete.allmarkers(repo):
2199 ui.write(hex(m.precnode()))
2199 ui.write(hex(m.precnode()))
2200 for repl in m.succnodes():
2200 for repl in m.succnodes():
2201 ui.write(' ')
2201 ui.write(' ')
2202 ui.write(hex(repl))
2202 ui.write(hex(repl))
2203 ui.write(' %X ' % m._data[2])
2203 ui.write(' %X ' % m._data[2])
2204 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2204 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2205 sorted(m.metadata().items()))))
2205 sorted(m.metadata().items()))))
2206 ui.write('\n')
2206 ui.write('\n')
2207
2207
2208 @command('debugpathcomplete',
2208 @command('debugpathcomplete',
2209 [('f', 'full', None, _('complete an entire path')),
2209 [('f', 'full', None, _('complete an entire path')),
2210 ('n', 'normal', None, _('show only normal files')),
2210 ('n', 'normal', None, _('show only normal files')),
2211 ('a', 'added', None, _('show only added files')),
2211 ('a', 'added', None, _('show only added files')),
2212 ('r', 'removed', None, _('show only removed files'))],
2212 ('r', 'removed', None, _('show only removed files'))],
2213 _('FILESPEC...'))
2213 _('FILESPEC...'))
2214 def debugpathcomplete(ui, repo, *specs, **opts):
2214 def debugpathcomplete(ui, repo, *specs, **opts):
2215 '''complete part or all of a tracked path
2215 '''complete part or all of a tracked path
2216
2216
2217 This command supports shells that offer path name completion. It
2217 This command supports shells that offer path name completion. It
2218 currently completes only files already known to the dirstate.
2218 currently completes only files already known to the dirstate.
2219
2219
2220 Completion extends only to the next path segment unless
2220 Completion extends only to the next path segment unless
2221 --full is specified, in which case entire paths are used.'''
2221 --full is specified, in which case entire paths are used.'''
2222
2222
2223 def complete(path, acceptable):
2223 def complete(path, acceptable):
2224 dirstate = repo.dirstate
2224 dirstate = repo.dirstate
2225 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2225 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2226 rootdir = repo.root + os.sep
2226 rootdir = repo.root + os.sep
2227 if spec != repo.root and not spec.startswith(rootdir):
2227 if spec != repo.root and not spec.startswith(rootdir):
2228 return [], []
2228 return [], []
2229 if os.path.isdir(spec):
2229 if os.path.isdir(spec):
2230 spec += '/'
2230 spec += '/'
2231 spec = spec[len(rootdir):]
2231 spec = spec[len(rootdir):]
2232 fixpaths = os.sep != '/'
2232 fixpaths = os.sep != '/'
2233 if fixpaths:
2233 if fixpaths:
2234 spec = spec.replace(os.sep, '/')
2234 spec = spec.replace(os.sep, '/')
2235 speclen = len(spec)
2235 speclen = len(spec)
2236 fullpaths = opts['full']
2236 fullpaths = opts['full']
2237 files, dirs = set(), set()
2237 files, dirs = set(), set()
2238 adddir, addfile = dirs.add, files.add
2238 adddir, addfile = dirs.add, files.add
2239 for f, st in dirstate.iteritems():
2239 for f, st in dirstate.iteritems():
2240 if f.startswith(spec) and st[0] in acceptable:
2240 if f.startswith(spec) and st[0] in acceptable:
2241 if fixpaths:
2241 if fixpaths:
2242 f = f.replace('/', os.sep)
2242 f = f.replace('/', os.sep)
2243 if fullpaths:
2243 if fullpaths:
2244 addfile(f)
2244 addfile(f)
2245 continue
2245 continue
2246 s = f.find(os.sep, speclen)
2246 s = f.find(os.sep, speclen)
2247 if s >= 0:
2247 if s >= 0:
2248 adddir(f[:s])
2248 adddir(f[:s])
2249 else:
2249 else:
2250 addfile(f)
2250 addfile(f)
2251 return files, dirs
2251 return files, dirs
2252
2252
2253 acceptable = ''
2253 acceptable = ''
2254 if opts['normal']:
2254 if opts['normal']:
2255 acceptable += 'nm'
2255 acceptable += 'nm'
2256 if opts['added']:
2256 if opts['added']:
2257 acceptable += 'a'
2257 acceptable += 'a'
2258 if opts['removed']:
2258 if opts['removed']:
2259 acceptable += 'r'
2259 acceptable += 'r'
2260 cwd = repo.getcwd()
2260 cwd = repo.getcwd()
2261 if not specs:
2261 if not specs:
2262 specs = ['.']
2262 specs = ['.']
2263
2263
2264 files, dirs = set(), set()
2264 files, dirs = set(), set()
2265 for spec in specs:
2265 for spec in specs:
2266 f, d = complete(spec, acceptable or 'nmar')
2266 f, d = complete(spec, acceptable or 'nmar')
2267 files.update(f)
2267 files.update(f)
2268 dirs.update(d)
2268 dirs.update(d)
2269 files.update(dirs)
2269 files.update(dirs)
2270 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2270 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2271 ui.write('\n')
2271 ui.write('\n')
2272
2272
2273 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2273 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2274 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2274 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2275 '''access the pushkey key/value protocol
2275 '''access the pushkey key/value protocol
2276
2276
2277 With two args, list the keys in the given namespace.
2277 With two args, list the keys in the given namespace.
2278
2278
2279 With five args, set a key to new if it currently is set to old.
2279 With five args, set a key to new if it currently is set to old.
2280 Reports success or failure.
2280 Reports success or failure.
2281 '''
2281 '''
2282
2282
2283 target = hg.peer(ui, {}, repopath)
2283 target = hg.peer(ui, {}, repopath)
2284 if keyinfo:
2284 if keyinfo:
2285 key, old, new = keyinfo
2285 key, old, new = keyinfo
2286 r = target.pushkey(namespace, key, old, new)
2286 r = target.pushkey(namespace, key, old, new)
2287 ui.status(str(r) + '\n')
2287 ui.status(str(r) + '\n')
2288 return not r
2288 return not r
2289 else:
2289 else:
2290 for k, v in sorted(target.listkeys(namespace).iteritems()):
2290 for k, v in sorted(target.listkeys(namespace).iteritems()):
2291 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2291 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2292 v.encode('string-escape')))
2292 v.encode('string-escape')))
2293
2293
2294 @command('debugpvec', [], _('A B'))
2294 @command('debugpvec', [], _('A B'))
2295 def debugpvec(ui, repo, a, b=None):
2295 def debugpvec(ui, repo, a, b=None):
2296 ca = scmutil.revsingle(repo, a)
2296 ca = scmutil.revsingle(repo, a)
2297 cb = scmutil.revsingle(repo, b)
2297 cb = scmutil.revsingle(repo, b)
2298 pa = pvec.ctxpvec(ca)
2298 pa = pvec.ctxpvec(ca)
2299 pb = pvec.ctxpvec(cb)
2299 pb = pvec.ctxpvec(cb)
2300 if pa == pb:
2300 if pa == pb:
2301 rel = "="
2301 rel = "="
2302 elif pa > pb:
2302 elif pa > pb:
2303 rel = ">"
2303 rel = ">"
2304 elif pa < pb:
2304 elif pa < pb:
2305 rel = "<"
2305 rel = "<"
2306 elif pa | pb:
2306 elif pa | pb:
2307 rel = "|"
2307 rel = "|"
2308 ui.write(_("a: %s\n") % pa)
2308 ui.write(_("a: %s\n") % pa)
2309 ui.write(_("b: %s\n") % pb)
2309 ui.write(_("b: %s\n") % pb)
2310 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2310 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2311 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2311 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2312 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2312 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2313 pa.distance(pb), rel))
2313 pa.distance(pb), rel))
2314
2314
2315 @command('debugrebuilddirstate|debugrebuildstate',
2315 @command('debugrebuilddirstate|debugrebuildstate',
2316 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2316 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2317 _('[-r REV]'))
2317 _('[-r REV]'))
2318 def debugrebuilddirstate(ui, repo, rev):
2318 def debugrebuilddirstate(ui, repo, rev):
2319 """rebuild the dirstate as it would look like for the given revision
2319 """rebuild the dirstate as it would look like for the given revision
2320
2320
2321 If no revision is specified the first current parent will be used.
2321 If no revision is specified the first current parent will be used.
2322
2322
2323 The dirstate will be set to the files of the given revision.
2323 The dirstate will be set to the files of the given revision.
2324 The actual working directory content or existing dirstate
2324 The actual working directory content or existing dirstate
2325 information such as adds or removes is not considered.
2325 information such as adds or removes is not considered.
2326
2326
2327 One use of this command is to make the next :hg:`status` invocation
2327 One use of this command is to make the next :hg:`status` invocation
2328 check the actual file content.
2328 check the actual file content.
2329 """
2329 """
2330 ctx = scmutil.revsingle(repo, rev)
2330 ctx = scmutil.revsingle(repo, rev)
2331 wlock = repo.wlock()
2331 wlock = repo.wlock()
2332 try:
2332 try:
2333 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2333 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2334 finally:
2334 finally:
2335 wlock.release()
2335 wlock.release()
2336
2336
2337 @command('debugrename',
2337 @command('debugrename',
2338 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2338 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2339 _('[-r REV] FILE'))
2339 _('[-r REV] FILE'))
2340 def debugrename(ui, repo, file1, *pats, **opts):
2340 def debugrename(ui, repo, file1, *pats, **opts):
2341 """dump rename information"""
2341 """dump rename information"""
2342
2342
2343 ctx = scmutil.revsingle(repo, opts.get('rev'))
2343 ctx = scmutil.revsingle(repo, opts.get('rev'))
2344 m = scmutil.match(ctx, (file1,) + pats, opts)
2344 m = scmutil.match(ctx, (file1,) + pats, opts)
2345 for abs in ctx.walk(m):
2345 for abs in ctx.walk(m):
2346 fctx = ctx[abs]
2346 fctx = ctx[abs]
2347 o = fctx.filelog().renamed(fctx.filenode())
2347 o = fctx.filelog().renamed(fctx.filenode())
2348 rel = m.rel(abs)
2348 rel = m.rel(abs)
2349 if o:
2349 if o:
2350 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2350 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2351 else:
2351 else:
2352 ui.write(_("%s not renamed\n") % rel)
2352 ui.write(_("%s not renamed\n") % rel)
2353
2353
2354 @command('debugrevlog',
2354 @command('debugrevlog',
2355 [('c', 'changelog', False, _('open changelog')),
2355 [('c', 'changelog', False, _('open changelog')),
2356 ('m', 'manifest', False, _('open manifest')),
2356 ('m', 'manifest', False, _('open manifest')),
2357 ('d', 'dump', False, _('dump index data'))],
2357 ('d', 'dump', False, _('dump index data'))],
2358 _('-c|-m|FILE'))
2358 _('-c|-m|FILE'))
2359 def debugrevlog(ui, repo, file_=None, **opts):
2359 def debugrevlog(ui, repo, file_=None, **opts):
2360 """show data and statistics about a revlog"""
2360 """show data and statistics about a revlog"""
2361 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2361 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2362
2362
2363 if opts.get("dump"):
2363 if opts.get("dump"):
2364 numrevs = len(r)
2364 numrevs = len(r)
2365 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2365 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2366 " rawsize totalsize compression heads\n")
2366 " rawsize totalsize compression heads\n")
2367 ts = 0
2367 ts = 0
2368 heads = set()
2368 heads = set()
2369 for rev in xrange(numrevs):
2369 for rev in xrange(numrevs):
2370 dbase = r.deltaparent(rev)
2370 dbase = r.deltaparent(rev)
2371 if dbase == -1:
2371 if dbase == -1:
2372 dbase = rev
2372 dbase = rev
2373 cbase = r.chainbase(rev)
2373 cbase = r.chainbase(rev)
2374 p1, p2 = r.parentrevs(rev)
2374 p1, p2 = r.parentrevs(rev)
2375 rs = r.rawsize(rev)
2375 rs = r.rawsize(rev)
2376 ts = ts + rs
2376 ts = ts + rs
2377 heads -= set(r.parentrevs(rev))
2377 heads -= set(r.parentrevs(rev))
2378 heads.add(rev)
2378 heads.add(rev)
2379 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2379 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2380 (rev, p1, p2, r.start(rev), r.end(rev),
2380 (rev, p1, p2, r.start(rev), r.end(rev),
2381 r.start(dbase), r.start(cbase),
2381 r.start(dbase), r.start(cbase),
2382 r.start(p1), r.start(p2),
2382 r.start(p1), r.start(p2),
2383 rs, ts, ts / r.end(rev), len(heads)))
2383 rs, ts, ts / r.end(rev), len(heads)))
2384 return 0
2384 return 0
2385
2385
2386 v = r.version
2386 v = r.version
2387 format = v & 0xFFFF
2387 format = v & 0xFFFF
2388 flags = []
2388 flags = []
2389 gdelta = False
2389 gdelta = False
2390 if v & revlog.REVLOGNGINLINEDATA:
2390 if v & revlog.REVLOGNGINLINEDATA:
2391 flags.append('inline')
2391 flags.append('inline')
2392 if v & revlog.REVLOGGENERALDELTA:
2392 if v & revlog.REVLOGGENERALDELTA:
2393 gdelta = True
2393 gdelta = True
2394 flags.append('generaldelta')
2394 flags.append('generaldelta')
2395 if not flags:
2395 if not flags:
2396 flags = ['(none)']
2396 flags = ['(none)']
2397
2397
2398 nummerges = 0
2398 nummerges = 0
2399 numfull = 0
2399 numfull = 0
2400 numprev = 0
2400 numprev = 0
2401 nump1 = 0
2401 nump1 = 0
2402 nump2 = 0
2402 nump2 = 0
2403 numother = 0
2403 numother = 0
2404 nump1prev = 0
2404 nump1prev = 0
2405 nump2prev = 0
2405 nump2prev = 0
2406 chainlengths = []
2406 chainlengths = []
2407
2407
2408 datasize = [None, 0, 0L]
2408 datasize = [None, 0, 0L]
2409 fullsize = [None, 0, 0L]
2409 fullsize = [None, 0, 0L]
2410 deltasize = [None, 0, 0L]
2410 deltasize = [None, 0, 0L]
2411
2411
2412 def addsize(size, l):
2412 def addsize(size, l):
2413 if l[0] is None or size < l[0]:
2413 if l[0] is None or size < l[0]:
2414 l[0] = size
2414 l[0] = size
2415 if size > l[1]:
2415 if size > l[1]:
2416 l[1] = size
2416 l[1] = size
2417 l[2] += size
2417 l[2] += size
2418
2418
2419 numrevs = len(r)
2419 numrevs = len(r)
2420 for rev in xrange(numrevs):
2420 for rev in xrange(numrevs):
2421 p1, p2 = r.parentrevs(rev)
2421 p1, p2 = r.parentrevs(rev)
2422 delta = r.deltaparent(rev)
2422 delta = r.deltaparent(rev)
2423 if format > 0:
2423 if format > 0:
2424 addsize(r.rawsize(rev), datasize)
2424 addsize(r.rawsize(rev), datasize)
2425 if p2 != nullrev:
2425 if p2 != nullrev:
2426 nummerges += 1
2426 nummerges += 1
2427 size = r.length(rev)
2427 size = r.length(rev)
2428 if delta == nullrev:
2428 if delta == nullrev:
2429 chainlengths.append(0)
2429 chainlengths.append(0)
2430 numfull += 1
2430 numfull += 1
2431 addsize(size, fullsize)
2431 addsize(size, fullsize)
2432 else:
2432 else:
2433 chainlengths.append(chainlengths[delta] + 1)
2433 chainlengths.append(chainlengths[delta] + 1)
2434 addsize(size, deltasize)
2434 addsize(size, deltasize)
2435 if delta == rev - 1:
2435 if delta == rev - 1:
2436 numprev += 1
2436 numprev += 1
2437 if delta == p1:
2437 if delta == p1:
2438 nump1prev += 1
2438 nump1prev += 1
2439 elif delta == p2:
2439 elif delta == p2:
2440 nump2prev += 1
2440 nump2prev += 1
2441 elif delta == p1:
2441 elif delta == p1:
2442 nump1 += 1
2442 nump1 += 1
2443 elif delta == p2:
2443 elif delta == p2:
2444 nump2 += 1
2444 nump2 += 1
2445 elif delta != nullrev:
2445 elif delta != nullrev:
2446 numother += 1
2446 numother += 1
2447
2447
2448 # Adjust size min value for empty cases
2448 # Adjust size min value for empty cases
2449 for size in (datasize, fullsize, deltasize):
2449 for size in (datasize, fullsize, deltasize):
2450 if size[0] is None:
2450 if size[0] is None:
2451 size[0] = 0
2451 size[0] = 0
2452
2452
2453 numdeltas = numrevs - numfull
2453 numdeltas = numrevs - numfull
2454 numoprev = numprev - nump1prev - nump2prev
2454 numoprev = numprev - nump1prev - nump2prev
2455 totalrawsize = datasize[2]
2455 totalrawsize = datasize[2]
2456 datasize[2] /= numrevs
2456 datasize[2] /= numrevs
2457 fulltotal = fullsize[2]
2457 fulltotal = fullsize[2]
2458 fullsize[2] /= numfull
2458 fullsize[2] /= numfull
2459 deltatotal = deltasize[2]
2459 deltatotal = deltasize[2]
2460 if numrevs - numfull > 0:
2460 if numrevs - numfull > 0:
2461 deltasize[2] /= numrevs - numfull
2461 deltasize[2] /= numrevs - numfull
2462 totalsize = fulltotal + deltatotal
2462 totalsize = fulltotal + deltatotal
2463 avgchainlen = sum(chainlengths) / numrevs
2463 avgchainlen = sum(chainlengths) / numrevs
2464 compratio = totalrawsize / totalsize
2464 compratio = totalrawsize / totalsize
2465
2465
2466 basedfmtstr = '%%%dd\n'
2466 basedfmtstr = '%%%dd\n'
2467 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2467 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2468
2468
2469 def dfmtstr(max):
2469 def dfmtstr(max):
2470 return basedfmtstr % len(str(max))
2470 return basedfmtstr % len(str(max))
2471 def pcfmtstr(max, padding=0):
2471 def pcfmtstr(max, padding=0):
2472 return basepcfmtstr % (len(str(max)), ' ' * padding)
2472 return basepcfmtstr % (len(str(max)), ' ' * padding)
2473
2473
2474 def pcfmt(value, total):
2474 def pcfmt(value, total):
2475 return (value, 100 * float(value) / total)
2475 return (value, 100 * float(value) / total)
2476
2476
2477 ui.write(('format : %d\n') % format)
2477 ui.write(('format : %d\n') % format)
2478 ui.write(('flags : %s\n') % ', '.join(flags))
2478 ui.write(('flags : %s\n') % ', '.join(flags))
2479
2479
2480 ui.write('\n')
2480 ui.write('\n')
2481 fmt = pcfmtstr(totalsize)
2481 fmt = pcfmtstr(totalsize)
2482 fmt2 = dfmtstr(totalsize)
2482 fmt2 = dfmtstr(totalsize)
2483 ui.write(('revisions : ') + fmt2 % numrevs)
2483 ui.write(('revisions : ') + fmt2 % numrevs)
2484 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2484 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2485 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2485 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2486 ui.write(('revisions : ') + fmt2 % numrevs)
2486 ui.write(('revisions : ') + fmt2 % numrevs)
2487 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2487 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2488 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2488 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2489 ui.write(('revision size : ') + fmt2 % totalsize)
2489 ui.write(('revision size : ') + fmt2 % totalsize)
2490 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2490 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2491 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2491 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2492
2492
2493 ui.write('\n')
2493 ui.write('\n')
2494 fmt = dfmtstr(max(avgchainlen, compratio))
2494 fmt = dfmtstr(max(avgchainlen, compratio))
2495 ui.write(('avg chain length : ') + fmt % avgchainlen)
2495 ui.write(('avg chain length : ') + fmt % avgchainlen)
2496 ui.write(('compression ratio : ') + fmt % compratio)
2496 ui.write(('compression ratio : ') + fmt % compratio)
2497
2497
2498 if format > 0:
2498 if format > 0:
2499 ui.write('\n')
2499 ui.write('\n')
2500 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2500 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2501 % tuple(datasize))
2501 % tuple(datasize))
2502 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2502 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2503 % tuple(fullsize))
2503 % tuple(fullsize))
2504 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2504 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2505 % tuple(deltasize))
2505 % tuple(deltasize))
2506
2506
2507 if numdeltas > 0:
2507 if numdeltas > 0:
2508 ui.write('\n')
2508 ui.write('\n')
2509 fmt = pcfmtstr(numdeltas)
2509 fmt = pcfmtstr(numdeltas)
2510 fmt2 = pcfmtstr(numdeltas, 4)
2510 fmt2 = pcfmtstr(numdeltas, 4)
2511 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2511 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2512 if numprev > 0:
2512 if numprev > 0:
2513 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2513 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2514 numprev))
2514 numprev))
2515 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2515 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2516 numprev))
2516 numprev))
2517 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2517 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2518 numprev))
2518 numprev))
2519 if gdelta:
2519 if gdelta:
2520 ui.write(('deltas against p1 : ')
2520 ui.write(('deltas against p1 : ')
2521 + fmt % pcfmt(nump1, numdeltas))
2521 + fmt % pcfmt(nump1, numdeltas))
2522 ui.write(('deltas against p2 : ')
2522 ui.write(('deltas against p2 : ')
2523 + fmt % pcfmt(nump2, numdeltas))
2523 + fmt % pcfmt(nump2, numdeltas))
2524 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2524 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2525 numdeltas))
2525 numdeltas))
2526
2526
2527 @command('debugrevspec', [], ('REVSPEC'))
2527 @command('debugrevspec', [], ('REVSPEC'))
2528 def debugrevspec(ui, repo, expr):
2528 def debugrevspec(ui, repo, expr):
2529 """parse and apply a revision specification
2529 """parse and apply a revision specification
2530
2530
2531 Use --verbose to print the parsed tree before and after aliases
2531 Use --verbose to print the parsed tree before and after aliases
2532 expansion.
2532 expansion.
2533 """
2533 """
2534 if ui.verbose:
2534 if ui.verbose:
2535 tree = revset.parse(expr)[0]
2535 tree = revset.parse(expr)[0]
2536 ui.note(revset.prettyformat(tree), "\n")
2536 ui.note(revset.prettyformat(tree), "\n")
2537 newtree = revset.findaliases(ui, tree)
2537 newtree = revset.findaliases(ui, tree)
2538 if newtree != tree:
2538 if newtree != tree:
2539 ui.note(revset.prettyformat(newtree), "\n")
2539 ui.note(revset.prettyformat(newtree), "\n")
2540 func = revset.match(ui, expr)
2540 func = revset.match(ui, expr)
2541 for c in func(repo, range(len(repo))):
2541 for c in func(repo, range(len(repo))):
2542 ui.write("%s\n" % c)
2542 ui.write("%s\n" % c)
2543
2543
2544 @command('debugsetparents', [], _('REV1 [REV2]'))
2544 @command('debugsetparents', [], _('REV1 [REV2]'))
2545 def debugsetparents(ui, repo, rev1, rev2=None):
2545 def debugsetparents(ui, repo, rev1, rev2=None):
2546 """manually set the parents of the current working directory
2546 """manually set the parents of the current working directory
2547
2547
2548 This is useful for writing repository conversion tools, but should
2548 This is useful for writing repository conversion tools, but should
2549 be used with care.
2549 be used with care.
2550
2550
2551 Returns 0 on success.
2551 Returns 0 on success.
2552 """
2552 """
2553
2553
2554 r1 = scmutil.revsingle(repo, rev1).node()
2554 r1 = scmutil.revsingle(repo, rev1).node()
2555 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2555 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2556
2556
2557 wlock = repo.wlock()
2557 wlock = repo.wlock()
2558 try:
2558 try:
2559 repo.setparents(r1, r2)
2559 repo.setparents(r1, r2)
2560 finally:
2560 finally:
2561 wlock.release()
2561 wlock.release()
2562
2562
2563 @command('debugdirstate|debugstate',
2563 @command('debugdirstate|debugstate',
2564 [('', 'nodates', None, _('do not display the saved mtime')),
2564 [('', 'nodates', None, _('do not display the saved mtime')),
2565 ('', 'datesort', None, _('sort by saved mtime'))],
2565 ('', 'datesort', None, _('sort by saved mtime'))],
2566 _('[OPTION]...'))
2566 _('[OPTION]...'))
2567 def debugstate(ui, repo, nodates=None, datesort=None):
2567 def debugstate(ui, repo, nodates=None, datesort=None):
2568 """show the contents of the current dirstate"""
2568 """show the contents of the current dirstate"""
2569 timestr = ""
2569 timestr = ""
2570 showdate = not nodates
2570 showdate = not nodates
2571 if datesort:
2571 if datesort:
2572 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2572 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2573 else:
2573 else:
2574 keyfunc = None # sort by filename
2574 keyfunc = None # sort by filename
2575 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2575 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2576 if showdate:
2576 if showdate:
2577 if ent[3] == -1:
2577 if ent[3] == -1:
2578 # Pad or slice to locale representation
2578 # Pad or slice to locale representation
2579 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2579 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2580 time.localtime(0)))
2580 time.localtime(0)))
2581 timestr = 'unset'
2581 timestr = 'unset'
2582 timestr = (timestr[:locale_len] +
2582 timestr = (timestr[:locale_len] +
2583 ' ' * (locale_len - len(timestr)))
2583 ' ' * (locale_len - len(timestr)))
2584 else:
2584 else:
2585 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2585 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2586 time.localtime(ent[3]))
2586 time.localtime(ent[3]))
2587 if ent[1] & 020000:
2587 if ent[1] & 020000:
2588 mode = 'lnk'
2588 mode = 'lnk'
2589 else:
2589 else:
2590 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2590 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2591 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2591 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2592 for f in repo.dirstate.copies():
2592 for f in repo.dirstate.copies():
2593 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2593 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2594
2594
2595 @command('debugsub',
2595 @command('debugsub',
2596 [('r', 'rev', '',
2596 [('r', 'rev', '',
2597 _('revision to check'), _('REV'))],
2597 _('revision to check'), _('REV'))],
2598 _('[-r REV] [REV]'))
2598 _('[-r REV] [REV]'))
2599 def debugsub(ui, repo, rev=None):
2599 def debugsub(ui, repo, rev=None):
2600 ctx = scmutil.revsingle(repo, rev, None)
2600 ctx = scmutil.revsingle(repo, rev, None)
2601 for k, v in sorted(ctx.substate.items()):
2601 for k, v in sorted(ctx.substate.items()):
2602 ui.write(('path %s\n') % k)
2602 ui.write(('path %s\n') % k)
2603 ui.write((' source %s\n') % v[0])
2603 ui.write((' source %s\n') % v[0])
2604 ui.write((' revision %s\n') % v[1])
2604 ui.write((' revision %s\n') % v[1])
2605
2605
2606 @command('debugsuccessorssets',
2606 @command('debugsuccessorssets',
2607 [],
2607 [],
2608 _('[REV]'))
2608 _('[REV]'))
2609 def debugsuccessorssets(ui, repo, *revs):
2609 def debugsuccessorssets(ui, repo, *revs):
2610 """show set of successors for revision
2610 """show set of successors for revision
2611
2611
2612 A successors set of changeset A is a consistent group of revisions that
2612 A successors set of changeset A is a consistent group of revisions that
2613 succeed A. It contains non-obsolete changesets only.
2613 succeed A. It contains non-obsolete changesets only.
2614
2614
2615 In most cases a changeset A has a single successors set containing a single
2615 In most cases a changeset A has a single successors set containing a single
2616 successor (changeset A replaced by A').
2616 successor (changeset A replaced by A').
2617
2617
2618 A changeset that is made obsolete with no successors are called "pruned".
2618 A changeset that is made obsolete with no successors are called "pruned".
2619 Such changesets have no successors sets at all.
2619 Such changesets have no successors sets at all.
2620
2620
2621 A changeset that has been "split" will have a successors set containing
2621 A changeset that has been "split" will have a successors set containing
2622 more than one successor.
2622 more than one successor.
2623
2623
2624 A changeset that has been rewritten in multiple different ways is called
2624 A changeset that has been rewritten in multiple different ways is called
2625 "divergent". Such changesets have multiple successor sets (each of which
2625 "divergent". Such changesets have multiple successor sets (each of which
2626 may also be split, i.e. have multiple successors).
2626 may also be split, i.e. have multiple successors).
2627
2627
2628 Results are displayed as follows::
2628 Results are displayed as follows::
2629
2629
2630 <rev1>
2630 <rev1>
2631 <successors-1A>
2631 <successors-1A>
2632 <rev2>
2632 <rev2>
2633 <successors-2A>
2633 <successors-2A>
2634 <successors-2B1> <successors-2B2> <successors-2B3>
2634 <successors-2B1> <successors-2B2> <successors-2B3>
2635
2635
2636 Here rev2 has two possible (i.e. divergent) successors sets. The first
2636 Here rev2 has two possible (i.e. divergent) successors sets. The first
2637 holds one element, whereas the second holds three (i.e. the changeset has
2637 holds one element, whereas the second holds three (i.e. the changeset has
2638 been split).
2638 been split).
2639 """
2639 """
2640 # passed to successorssets caching computation from one call to another
2640 # passed to successorssets caching computation from one call to another
2641 cache = {}
2641 cache = {}
2642 ctx2str = str
2642 ctx2str = str
2643 node2str = short
2643 node2str = short
2644 if ui.debug():
2644 if ui.debug():
2645 def ctx2str(ctx):
2645 def ctx2str(ctx):
2646 return ctx.hex()
2646 return ctx.hex()
2647 node2str = hex
2647 node2str = hex
2648 for rev in scmutil.revrange(repo, revs):
2648 for rev in scmutil.revrange(repo, revs):
2649 ctx = repo[rev]
2649 ctx = repo[rev]
2650 ui.write('%s\n'% ctx2str(ctx))
2650 ui.write('%s\n'% ctx2str(ctx))
2651 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2651 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2652 if succsset:
2652 if succsset:
2653 ui.write(' ')
2653 ui.write(' ')
2654 ui.write(node2str(succsset[0]))
2654 ui.write(node2str(succsset[0]))
2655 for node in succsset[1:]:
2655 for node in succsset[1:]:
2656 ui.write(' ')
2656 ui.write(' ')
2657 ui.write(node2str(node))
2657 ui.write(node2str(node))
2658 ui.write('\n')
2658 ui.write('\n')
2659
2659
2660 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2660 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2661 def debugwalk(ui, repo, *pats, **opts):
2661 def debugwalk(ui, repo, *pats, **opts):
2662 """show how files match on given patterns"""
2662 """show how files match on given patterns"""
2663 m = scmutil.match(repo[None], pats, opts)
2663 m = scmutil.match(repo[None], pats, opts)
2664 items = list(repo.walk(m))
2664 items = list(repo.walk(m))
2665 if not items:
2665 if not items:
2666 return
2666 return
2667 f = lambda fn: fn
2667 f = lambda fn: fn
2668 if ui.configbool('ui', 'slash') and os.sep != '/':
2668 if ui.configbool('ui', 'slash') and os.sep != '/':
2669 f = lambda fn: util.normpath(fn)
2669 f = lambda fn: util.normpath(fn)
2670 fmt = 'f %%-%ds %%-%ds %%s' % (
2670 fmt = 'f %%-%ds %%-%ds %%s' % (
2671 max([len(abs) for abs in items]),
2671 max([len(abs) for abs in items]),
2672 max([len(m.rel(abs)) for abs in items]))
2672 max([len(m.rel(abs)) for abs in items]))
2673 for abs in items:
2673 for abs in items:
2674 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2674 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2675 ui.write("%s\n" % line.rstrip())
2675 ui.write("%s\n" % line.rstrip())
2676
2676
2677 @command('debugwireargs',
2677 @command('debugwireargs',
2678 [('', 'three', '', 'three'),
2678 [('', 'three', '', 'three'),
2679 ('', 'four', '', 'four'),
2679 ('', 'four', '', 'four'),
2680 ('', 'five', '', 'five'),
2680 ('', 'five', '', 'five'),
2681 ] + remoteopts,
2681 ] + remoteopts,
2682 _('REPO [OPTIONS]... [ONE [TWO]]'))
2682 _('REPO [OPTIONS]... [ONE [TWO]]'))
2683 def debugwireargs(ui, repopath, *vals, **opts):
2683 def debugwireargs(ui, repopath, *vals, **opts):
2684 repo = hg.peer(ui, opts, repopath)
2684 repo = hg.peer(ui, opts, repopath)
2685 for opt in remoteopts:
2685 for opt in remoteopts:
2686 del opts[opt[1]]
2686 del opts[opt[1]]
2687 args = {}
2687 args = {}
2688 for k, v in opts.iteritems():
2688 for k, v in opts.iteritems():
2689 if v:
2689 if v:
2690 args[k] = v
2690 args[k] = v
2691 # run twice to check that we don't mess up the stream for the next command
2691 # run twice to check that we don't mess up the stream for the next command
2692 res1 = repo.debugwireargs(*vals, **args)
2692 res1 = repo.debugwireargs(*vals, **args)
2693 res2 = repo.debugwireargs(*vals, **args)
2693 res2 = repo.debugwireargs(*vals, **args)
2694 ui.write("%s\n" % res1)
2694 ui.write("%s\n" % res1)
2695 if res1 != res2:
2695 if res1 != res2:
2696 ui.warn("%s\n" % res2)
2696 ui.warn("%s\n" % res2)
2697
2697
2698 @command('^diff',
2698 @command('^diff',
2699 [('r', 'rev', [], _('revision'), _('REV')),
2699 [('r', 'rev', [], _('revision'), _('REV')),
2700 ('c', 'change', '', _('change made by revision'), _('REV'))
2700 ('c', 'change', '', _('change made by revision'), _('REV'))
2701 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2701 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2702 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2702 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2703 def diff(ui, repo, *pats, **opts):
2703 def diff(ui, repo, *pats, **opts):
2704 """diff repository (or selected files)
2704 """diff repository (or selected files)
2705
2705
2706 Show differences between revisions for the specified files.
2706 Show differences between revisions for the specified files.
2707
2707
2708 Differences between files are shown using the unified diff format.
2708 Differences between files are shown using the unified diff format.
2709
2709
2710 .. note::
2710 .. note::
2711
2711
2712 diff may generate unexpected results for merges, as it will
2712 diff may generate unexpected results for merges, as it will
2713 default to comparing against the working directory's first
2713 default to comparing against the working directory's first
2714 parent changeset if no revisions are specified.
2714 parent changeset if no revisions are specified.
2715
2715
2716 When two revision arguments are given, then changes are shown
2716 When two revision arguments are given, then changes are shown
2717 between those revisions. If only one revision is specified then
2717 between those revisions. If only one revision is specified then
2718 that revision is compared to the working directory, and, when no
2718 that revision is compared to the working directory, and, when no
2719 revisions are specified, the working directory files are compared
2719 revisions are specified, the working directory files are compared
2720 to its parent.
2720 to its parent.
2721
2721
2722 Alternatively you can specify -c/--change with a revision to see
2722 Alternatively you can specify -c/--change with a revision to see
2723 the changes in that changeset relative to its first parent.
2723 the changes in that changeset relative to its first parent.
2724
2724
2725 Without the -a/--text option, diff will avoid generating diffs of
2725 Without the -a/--text option, diff will avoid generating diffs of
2726 files it detects as binary. With -a, diff will generate a diff
2726 files it detects as binary. With -a, diff will generate a diff
2727 anyway, probably with undesirable results.
2727 anyway, probably with undesirable results.
2728
2728
2729 Use the -g/--git option to generate diffs in the git extended diff
2729 Use the -g/--git option to generate diffs in the git extended diff
2730 format. For more information, read :hg:`help diffs`.
2730 format. For more information, read :hg:`help diffs`.
2731
2731
2732 .. container:: verbose
2732 .. container:: verbose
2733
2733
2734 Examples:
2734 Examples:
2735
2735
2736 - compare a file in the current working directory to its parent::
2736 - compare a file in the current working directory to its parent::
2737
2737
2738 hg diff foo.c
2738 hg diff foo.c
2739
2739
2740 - compare two historical versions of a directory, with rename info::
2740 - compare two historical versions of a directory, with rename info::
2741
2741
2742 hg diff --git -r 1.0:1.2 lib/
2742 hg diff --git -r 1.0:1.2 lib/
2743
2743
2744 - get change stats relative to the last change on some date::
2744 - get change stats relative to the last change on some date::
2745
2745
2746 hg diff --stat -r "date('may 2')"
2746 hg diff --stat -r "date('may 2')"
2747
2747
2748 - diff all newly-added files that contain a keyword::
2748 - diff all newly-added files that contain a keyword::
2749
2749
2750 hg diff "set:added() and grep(GNU)"
2750 hg diff "set:added() and grep(GNU)"
2751
2751
2752 - compare a revision and its parents::
2752 - compare a revision and its parents::
2753
2753
2754 hg diff -c 9353 # compare against first parent
2754 hg diff -c 9353 # compare against first parent
2755 hg diff -r 9353^:9353 # same using revset syntax
2755 hg diff -r 9353^:9353 # same using revset syntax
2756 hg diff -r 9353^2:9353 # compare against the second parent
2756 hg diff -r 9353^2:9353 # compare against the second parent
2757
2757
2758 Returns 0 on success.
2758 Returns 0 on success.
2759 """
2759 """
2760
2760
2761 revs = opts.get('rev')
2761 revs = opts.get('rev')
2762 change = opts.get('change')
2762 change = opts.get('change')
2763 stat = opts.get('stat')
2763 stat = opts.get('stat')
2764 reverse = opts.get('reverse')
2764 reverse = opts.get('reverse')
2765
2765
2766 if revs and change:
2766 if revs and change:
2767 msg = _('cannot specify --rev and --change at the same time')
2767 msg = _('cannot specify --rev and --change at the same time')
2768 raise util.Abort(msg)
2768 raise util.Abort(msg)
2769 elif change:
2769 elif change:
2770 node2 = scmutil.revsingle(repo, change, None).node()
2770 node2 = scmutil.revsingle(repo, change, None).node()
2771 node1 = repo[node2].p1().node()
2771 node1 = repo[node2].p1().node()
2772 else:
2772 else:
2773 node1, node2 = scmutil.revpair(repo, revs)
2773 node1, node2 = scmutil.revpair(repo, revs)
2774
2774
2775 if reverse:
2775 if reverse:
2776 node1, node2 = node2, node1
2776 node1, node2 = node2, node1
2777
2777
2778 diffopts = patch.diffopts(ui, opts)
2778 diffopts = patch.diffopts(ui, opts)
2779 m = scmutil.match(repo[node2], pats, opts)
2779 m = scmutil.match(repo[node2], pats, opts)
2780 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2780 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2781 listsubrepos=opts.get('subrepos'))
2781 listsubrepos=opts.get('subrepos'))
2782
2782
2783 @command('^export',
2783 @command('^export',
2784 [('o', 'output', '',
2784 [('o', 'output', '',
2785 _('print output to file with formatted name'), _('FORMAT')),
2785 _('print output to file with formatted name'), _('FORMAT')),
2786 ('', 'switch-parent', None, _('diff against the second parent')),
2786 ('', 'switch-parent', None, _('diff against the second parent')),
2787 ('r', 'rev', [], _('revisions to export'), _('REV')),
2787 ('r', 'rev', [], _('revisions to export'), _('REV')),
2788 ] + diffopts,
2788 ] + diffopts,
2789 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2789 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2790 def export(ui, repo, *changesets, **opts):
2790 def export(ui, repo, *changesets, **opts):
2791 """dump the header and diffs for one or more changesets
2791 """dump the header and diffs for one or more changesets
2792
2792
2793 Print the changeset header and diffs for one or more revisions.
2793 Print the changeset header and diffs for one or more revisions.
2794 If no revision is given, the parent of the working directory is used.
2794 If no revision is given, the parent of the working directory is used.
2795
2795
2796 The information shown in the changeset header is: author, date,
2796 The information shown in the changeset header is: author, date,
2797 branch name (if non-default), changeset hash, parent(s) and commit
2797 branch name (if non-default), changeset hash, parent(s) and commit
2798 comment.
2798 comment.
2799
2799
2800 .. note::
2800 .. note::
2801
2801
2802 export may generate unexpected diff output for merge
2802 export may generate unexpected diff output for merge
2803 changesets, as it will compare the merge changeset against its
2803 changesets, as it will compare the merge changeset against its
2804 first parent only.
2804 first parent only.
2805
2805
2806 Output may be to a file, in which case the name of the file is
2806 Output may be to a file, in which case the name of the file is
2807 given using a format string. The formatting rules are as follows:
2807 given using a format string. The formatting rules are as follows:
2808
2808
2809 :``%%``: literal "%" character
2809 :``%%``: literal "%" character
2810 :``%H``: changeset hash (40 hexadecimal digits)
2810 :``%H``: changeset hash (40 hexadecimal digits)
2811 :``%N``: number of patches being generated
2811 :``%N``: number of patches being generated
2812 :``%R``: changeset revision number
2812 :``%R``: changeset revision number
2813 :``%b``: basename of the exporting repository
2813 :``%b``: basename of the exporting repository
2814 :``%h``: short-form changeset hash (12 hexadecimal digits)
2814 :``%h``: short-form changeset hash (12 hexadecimal digits)
2815 :``%m``: first line of the commit message (only alphanumeric characters)
2815 :``%m``: first line of the commit message (only alphanumeric characters)
2816 :``%n``: zero-padded sequence number, starting at 1
2816 :``%n``: zero-padded sequence number, starting at 1
2817 :``%r``: zero-padded changeset revision number
2817 :``%r``: zero-padded changeset revision number
2818
2818
2819 Without the -a/--text option, export will avoid generating diffs
2819 Without the -a/--text option, export will avoid generating diffs
2820 of files it detects as binary. With -a, export will generate a
2820 of files it detects as binary. With -a, export will generate a
2821 diff anyway, probably with undesirable results.
2821 diff anyway, probably with undesirable results.
2822
2822
2823 Use the -g/--git option to generate diffs in the git extended diff
2823 Use the -g/--git option to generate diffs in the git extended diff
2824 format. See :hg:`help diffs` for more information.
2824 format. See :hg:`help diffs` for more information.
2825
2825
2826 With the --switch-parent option, the diff will be against the
2826 With the --switch-parent option, the diff will be against the
2827 second parent. It can be useful to review a merge.
2827 second parent. It can be useful to review a merge.
2828
2828
2829 .. container:: verbose
2829 .. container:: verbose
2830
2830
2831 Examples:
2831 Examples:
2832
2832
2833 - use export and import to transplant a bugfix to the current
2833 - use export and import to transplant a bugfix to the current
2834 branch::
2834 branch::
2835
2835
2836 hg export -r 9353 | hg import -
2836 hg export -r 9353 | hg import -
2837
2837
2838 - export all the changesets between two revisions to a file with
2838 - export all the changesets between two revisions to a file with
2839 rename information::
2839 rename information::
2840
2840
2841 hg export --git -r 123:150 > changes.txt
2841 hg export --git -r 123:150 > changes.txt
2842
2842
2843 - split outgoing changes into a series of patches with
2843 - split outgoing changes into a series of patches with
2844 descriptive names::
2844 descriptive names::
2845
2845
2846 hg export -r "outgoing()" -o "%n-%m.patch"
2846 hg export -r "outgoing()" -o "%n-%m.patch"
2847
2847
2848 Returns 0 on success.
2848 Returns 0 on success.
2849 """
2849 """
2850 changesets += tuple(opts.get('rev', []))
2850 changesets += tuple(opts.get('rev', []))
2851 if not changesets:
2851 if not changesets:
2852 changesets = ['.']
2852 changesets = ['.']
2853 revs = scmutil.revrange(repo, changesets)
2853 revs = scmutil.revrange(repo, changesets)
2854 if not revs:
2854 if not revs:
2855 raise util.Abort(_("export requires at least one changeset"))
2855 raise util.Abort(_("export requires at least one changeset"))
2856 if len(revs) > 1:
2856 if len(revs) > 1:
2857 ui.note(_('exporting patches:\n'))
2857 ui.note(_('exporting patches:\n'))
2858 else:
2858 else:
2859 ui.note(_('exporting patch:\n'))
2859 ui.note(_('exporting patch:\n'))
2860 cmdutil.export(repo, revs, template=opts.get('output'),
2860 cmdutil.export(repo, revs, template=opts.get('output'),
2861 switch_parent=opts.get('switch_parent'),
2861 switch_parent=opts.get('switch_parent'),
2862 opts=patch.diffopts(ui, opts))
2862 opts=patch.diffopts(ui, opts))
2863
2863
2864 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2864 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2865 def forget(ui, repo, *pats, **opts):
2865 def forget(ui, repo, *pats, **opts):
2866 """forget the specified files on the next commit
2866 """forget the specified files on the next commit
2867
2867
2868 Mark the specified files so they will no longer be tracked
2868 Mark the specified files so they will no longer be tracked
2869 after the next commit.
2869 after the next commit.
2870
2870
2871 This only removes files from the current branch, not from the
2871 This only removes files from the current branch, not from the
2872 entire project history, and it does not delete them from the
2872 entire project history, and it does not delete them from the
2873 working directory.
2873 working directory.
2874
2874
2875 To undo a forget before the next commit, see :hg:`add`.
2875 To undo a forget before the next commit, see :hg:`add`.
2876
2876
2877 .. container:: verbose
2877 .. container:: verbose
2878
2878
2879 Examples:
2879 Examples:
2880
2880
2881 - forget newly-added binary files::
2881 - forget newly-added binary files::
2882
2882
2883 hg forget "set:added() and binary()"
2883 hg forget "set:added() and binary()"
2884
2884
2885 - forget files that would be excluded by .hgignore::
2885 - forget files that would be excluded by .hgignore::
2886
2886
2887 hg forget "set:hgignore()"
2887 hg forget "set:hgignore()"
2888
2888
2889 Returns 0 on success.
2889 Returns 0 on success.
2890 """
2890 """
2891
2891
2892 if not pats:
2892 if not pats:
2893 raise util.Abort(_('no files specified'))
2893 raise util.Abort(_('no files specified'))
2894
2894
2895 m = scmutil.match(repo[None], pats, opts)
2895 m = scmutil.match(repo[None], pats, opts)
2896 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2896 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2897 return rejected and 1 or 0
2897 return rejected and 1 or 0
2898
2898
2899 @command(
2899 @command(
2900 'graft',
2900 'graft',
2901 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2901 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2902 ('c', 'continue', False, _('resume interrupted graft')),
2902 ('c', 'continue', False, _('resume interrupted graft')),
2903 ('e', 'edit', False, _('invoke editor on commit messages')),
2903 ('e', 'edit', False, _('invoke editor on commit messages')),
2904 ('', 'log', None, _('append graft info to log message')),
2904 ('', 'log', None, _('append graft info to log message')),
2905 ('D', 'currentdate', False,
2905 ('D', 'currentdate', False,
2906 _('record the current date as commit date')),
2906 _('record the current date as commit date')),
2907 ('U', 'currentuser', False,
2907 ('U', 'currentuser', False,
2908 _('record the current user as committer'), _('DATE'))]
2908 _('record the current user as committer'), _('DATE'))]
2909 + commitopts2 + mergetoolopts + dryrunopts,
2909 + commitopts2 + mergetoolopts + dryrunopts,
2910 _('[OPTION]... [-r] REV...'))
2910 _('[OPTION]... [-r] REV...'))
2911 def graft(ui, repo, *revs, **opts):
2911 def graft(ui, repo, *revs, **opts):
2912 '''copy changes from other branches onto the current branch
2912 '''copy changes from other branches onto the current branch
2913
2913
2914 This command uses Mercurial's merge logic to copy individual
2914 This command uses Mercurial's merge logic to copy individual
2915 changes from other branches without merging branches in the
2915 changes from other branches without merging branches in the
2916 history graph. This is sometimes known as 'backporting' or
2916 history graph. This is sometimes known as 'backporting' or
2917 'cherry-picking'. By default, graft will copy user, date, and
2917 'cherry-picking'. By default, graft will copy user, date, and
2918 description from the source changesets.
2918 description from the source changesets.
2919
2919
2920 Changesets that are ancestors of the current revision, that have
2920 Changesets that are ancestors of the current revision, that have
2921 already been grafted, or that are merges will be skipped.
2921 already been grafted, or that are merges will be skipped.
2922
2922
2923 If --log is specified, log messages will have a comment appended
2923 If --log is specified, log messages will have a comment appended
2924 of the form::
2924 of the form::
2925
2925
2926 (grafted from CHANGESETHASH)
2926 (grafted from CHANGESETHASH)
2927
2927
2928 If a graft merge results in conflicts, the graft process is
2928 If a graft merge results in conflicts, the graft process is
2929 interrupted so that the current merge can be manually resolved.
2929 interrupted so that the current merge can be manually resolved.
2930 Once all conflicts are addressed, the graft process can be
2930 Once all conflicts are addressed, the graft process can be
2931 continued with the -c/--continue option.
2931 continued with the -c/--continue option.
2932
2932
2933 .. note::
2933 .. note::
2934
2934
2935 The -c/--continue option does not reapply earlier options.
2935 The -c/--continue option does not reapply earlier options.
2936
2936
2937 .. container:: verbose
2937 .. container:: verbose
2938
2938
2939 Examples:
2939 Examples:
2940
2940
2941 - copy a single change to the stable branch and edit its description::
2941 - copy a single change to the stable branch and edit its description::
2942
2942
2943 hg update stable
2943 hg update stable
2944 hg graft --edit 9393
2944 hg graft --edit 9393
2945
2945
2946 - graft a range of changesets with one exception, updating dates::
2946 - graft a range of changesets with one exception, updating dates::
2947
2947
2948 hg graft -D "2085::2093 and not 2091"
2948 hg graft -D "2085::2093 and not 2091"
2949
2949
2950 - continue a graft after resolving conflicts::
2950 - continue a graft after resolving conflicts::
2951
2951
2952 hg graft -c
2952 hg graft -c
2953
2953
2954 - show the source of a grafted changeset::
2954 - show the source of a grafted changeset::
2955
2955
2956 hg log --debug -r .
2956 hg log --debug -r .
2957
2957
2958 Returns 0 on successful completion.
2958 Returns 0 on successful completion.
2959 '''
2959 '''
2960
2960
2961 revs = list(revs)
2961 revs = list(revs)
2962 revs.extend(opts['rev'])
2962 revs.extend(opts['rev'])
2963
2963
2964 if not opts.get('user') and opts.get('currentuser'):
2964 if not opts.get('user') and opts.get('currentuser'):
2965 opts['user'] = ui.username()
2965 opts['user'] = ui.username()
2966 if not opts.get('date') and opts.get('currentdate'):
2966 if not opts.get('date') and opts.get('currentdate'):
2967 opts['date'] = "%d %d" % util.makedate()
2967 opts['date'] = "%d %d" % util.makedate()
2968
2968
2969 editor = None
2969 editor = None
2970 if opts.get('edit'):
2970 if opts.get('edit'):
2971 editor = cmdutil.commitforceeditor
2971 editor = cmdutil.commitforceeditor
2972
2972
2973 cont = False
2973 cont = False
2974 if opts['continue']:
2974 if opts['continue']:
2975 cont = True
2975 cont = True
2976 if revs:
2976 if revs:
2977 raise util.Abort(_("can't specify --continue and revisions"))
2977 raise util.Abort(_("can't specify --continue and revisions"))
2978 # read in unfinished revisions
2978 # read in unfinished revisions
2979 try:
2979 try:
2980 nodes = repo.opener.read('graftstate').splitlines()
2980 nodes = repo.opener.read('graftstate').splitlines()
2981 revs = [repo[node].rev() for node in nodes]
2981 revs = [repo[node].rev() for node in nodes]
2982 except IOError, inst:
2982 except IOError, inst:
2983 if inst.errno != errno.ENOENT:
2983 if inst.errno != errno.ENOENT:
2984 raise
2984 raise
2985 raise util.Abort(_("no graft state found, can't continue"))
2985 raise util.Abort(_("no graft state found, can't continue"))
2986 else:
2986 else:
2987 cmdutil.checkunfinished(repo)
2987 cmdutil.checkunfinished(repo)
2988 cmdutil.bailifchanged(repo)
2988 cmdutil.bailifchanged(repo)
2989 if not revs:
2989 if not revs:
2990 raise util.Abort(_('no revisions specified'))
2990 raise util.Abort(_('no revisions specified'))
2991 revs = scmutil.revrange(repo, revs)
2991 revs = scmutil.revrange(repo, revs)
2992
2992
2993 # check for merges
2993 # check for merges
2994 for rev in repo.revs('%ld and merge()', revs):
2994 for rev in repo.revs('%ld and merge()', revs):
2995 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2995 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2996 revs.remove(rev)
2996 revs.remove(rev)
2997 if not revs:
2997 if not revs:
2998 return -1
2998 return -1
2999
2999
3000 # check for ancestors of dest branch
3000 # check for ancestors of dest branch
3001 crev = repo['.'].rev()
3001 crev = repo['.'].rev()
3002 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3002 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3003 # don't mutate while iterating, create a copy
3003 # don't mutate while iterating, create a copy
3004 for rev in list(revs):
3004 for rev in list(revs):
3005 if rev in ancestors:
3005 if rev in ancestors:
3006 ui.warn(_('skipping ancestor revision %s\n') % rev)
3006 ui.warn(_('skipping ancestor revision %s\n') % rev)
3007 revs.remove(rev)
3007 revs.remove(rev)
3008 if not revs:
3008 if not revs:
3009 return -1
3009 return -1
3010
3010
3011 # analyze revs for earlier grafts
3011 # analyze revs for earlier grafts
3012 ids = {}
3012 ids = {}
3013 for ctx in repo.set("%ld", revs):
3013 for ctx in repo.set("%ld", revs):
3014 ids[ctx.hex()] = ctx.rev()
3014 ids[ctx.hex()] = ctx.rev()
3015 n = ctx.extra().get('source')
3015 n = ctx.extra().get('source')
3016 if n:
3016 if n:
3017 ids[n] = ctx.rev()
3017 ids[n] = ctx.rev()
3018
3018
3019 # check ancestors for earlier grafts
3019 # check ancestors for earlier grafts
3020 ui.debug('scanning for duplicate grafts\n')
3020 ui.debug('scanning for duplicate grafts\n')
3021
3021
3022 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3022 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3023 ctx = repo[rev]
3023 ctx = repo[rev]
3024 n = ctx.extra().get('source')
3024 n = ctx.extra().get('source')
3025 if n in ids:
3025 if n in ids:
3026 r = repo[n].rev()
3026 r = repo[n].rev()
3027 if r in revs:
3027 if r in revs:
3028 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3028 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3029 % (r, rev))
3029 % (r, rev))
3030 revs.remove(r)
3030 revs.remove(r)
3031 elif ids[n] in revs:
3031 elif ids[n] in revs:
3032 ui.warn(_('skipping already grafted revision %s '
3032 ui.warn(_('skipping already grafted revision %s '
3033 '(%s also has origin %d)\n') % (ids[n], rev, r))
3033 '(%s also has origin %d)\n') % (ids[n], rev, r))
3034 revs.remove(ids[n])
3034 revs.remove(ids[n])
3035 elif ctx.hex() in ids:
3035 elif ctx.hex() in ids:
3036 r = ids[ctx.hex()]
3036 r = ids[ctx.hex()]
3037 ui.warn(_('skipping already grafted revision %s '
3037 ui.warn(_('skipping already grafted revision %s '
3038 '(was grafted from %d)\n') % (r, rev))
3038 '(was grafted from %d)\n') % (r, rev))
3039 revs.remove(r)
3039 revs.remove(r)
3040 if not revs:
3040 if not revs:
3041 return -1
3041 return -1
3042
3042
3043 wlock = repo.wlock()
3043 wlock = repo.wlock()
3044 try:
3044 try:
3045 current = repo['.']
3045 current = repo['.']
3046 for pos, ctx in enumerate(repo.set("%ld", revs)):
3046 for pos, ctx in enumerate(repo.set("%ld", revs)):
3047
3047
3048 ui.status(_('grafting revision %s\n') % ctx.rev())
3048 ui.status(_('grafting revision %s\n') % ctx.rev())
3049 if opts.get('dry_run'):
3049 if opts.get('dry_run'):
3050 continue
3050 continue
3051
3051
3052 source = ctx.extra().get('source')
3052 source = ctx.extra().get('source')
3053 if not source:
3053 if not source:
3054 source = ctx.hex()
3054 source = ctx.hex()
3055 extra = {'source': source}
3055 extra = {'source': source}
3056 user = ctx.user()
3056 user = ctx.user()
3057 if opts.get('user'):
3057 if opts.get('user'):
3058 user = opts['user']
3058 user = opts['user']
3059 date = ctx.date()
3059 date = ctx.date()
3060 if opts.get('date'):
3060 if opts.get('date'):
3061 date = opts['date']
3061 date = opts['date']
3062 message = ctx.description()
3062 message = ctx.description()
3063 if opts.get('log'):
3063 if opts.get('log'):
3064 message += '\n(grafted from %s)' % ctx.hex()
3064 message += '\n(grafted from %s)' % ctx.hex()
3065
3065
3066 # we don't merge the first commit when continuing
3066 # we don't merge the first commit when continuing
3067 if not cont:
3067 if not cont:
3068 # perform the graft merge with p1(rev) as 'ancestor'
3068 # perform the graft merge with p1(rev) as 'ancestor'
3069 try:
3069 try:
3070 # ui.forcemerge is an internal variable, do not document
3070 # ui.forcemerge is an internal variable, do not document
3071 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3071 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3072 stats = mergemod.update(repo, ctx.node(), True, True, False,
3072 stats = mergemod.update(repo, ctx.node(), True, True, False,
3073 ctx.p1().node())
3073 ctx.p1().node())
3074 finally:
3074 finally:
3075 repo.ui.setconfig('ui', 'forcemerge', '')
3075 repo.ui.setconfig('ui', 'forcemerge', '')
3076 # report any conflicts
3076 # report any conflicts
3077 if stats and stats[3] > 0:
3077 if stats and stats[3] > 0:
3078 # write out state for --continue
3078 # write out state for --continue
3079 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3079 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3080 repo.opener.write('graftstate', ''.join(nodelines))
3080 repo.opener.write('graftstate', ''.join(nodelines))
3081 raise util.Abort(
3081 raise util.Abort(
3082 _("unresolved conflicts, can't continue"),
3082 _("unresolved conflicts, can't continue"),
3083 hint=_('use hg resolve and hg graft --continue'))
3083 hint=_('use hg resolve and hg graft --continue'))
3084 else:
3084 else:
3085 cont = False
3085 cont = False
3086
3086
3087 # drop the second merge parent
3087 # drop the second merge parent
3088 repo.setparents(current.node(), nullid)
3088 repo.setparents(current.node(), nullid)
3089 repo.dirstate.write()
3089 repo.dirstate.write()
3090 # fix up dirstate for copies and renames
3090 # fix up dirstate for copies and renames
3091 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3091 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3092
3092
3093 # commit
3093 # commit
3094 node = repo.commit(text=message, user=user,
3094 node = repo.commit(text=message, user=user,
3095 date=date, extra=extra, editor=editor)
3095 date=date, extra=extra, editor=editor)
3096 if node is None:
3096 if node is None:
3097 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3097 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3098 else:
3098 else:
3099 current = repo[node]
3099 current = repo[node]
3100 finally:
3100 finally:
3101 wlock.release()
3101 wlock.release()
3102
3102
3103 # remove state when we complete successfully
3103 # remove state when we complete successfully
3104 if not opts.get('dry_run'):
3104 if not opts.get('dry_run'):
3105 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3105 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3106
3106
3107 return 0
3107 return 0
3108
3108
3109 @command('grep',
3109 @command('grep',
3110 [('0', 'print0', None, _('end fields with NUL')),
3110 [('0', 'print0', None, _('end fields with NUL')),
3111 ('', 'all', None, _('print all revisions that match')),
3111 ('', 'all', None, _('print all revisions that match')),
3112 ('a', 'text', None, _('treat all files as text')),
3112 ('a', 'text', None, _('treat all files as text')),
3113 ('f', 'follow', None,
3113 ('f', 'follow', None,
3114 _('follow changeset history,'
3114 _('follow changeset history,'
3115 ' or file history across copies and renames')),
3115 ' or file history across copies and renames')),
3116 ('i', 'ignore-case', None, _('ignore case when matching')),
3116 ('i', 'ignore-case', None, _('ignore case when matching')),
3117 ('l', 'files-with-matches', None,
3117 ('l', 'files-with-matches', None,
3118 _('print only filenames and revisions that match')),
3118 _('print only filenames and revisions that match')),
3119 ('n', 'line-number', None, _('print matching line numbers')),
3119 ('n', 'line-number', None, _('print matching line numbers')),
3120 ('r', 'rev', [],
3120 ('r', 'rev', [],
3121 _('only search files changed within revision range'), _('REV')),
3121 _('only search files changed within revision range'), _('REV')),
3122 ('u', 'user', None, _('list the author (long with -v)')),
3122 ('u', 'user', None, _('list the author (long with -v)')),
3123 ('d', 'date', None, _('list the date (short with -q)')),
3123 ('d', 'date', None, _('list the date (short with -q)')),
3124 ] + walkopts,
3124 ] + walkopts,
3125 _('[OPTION]... PATTERN [FILE]...'))
3125 _('[OPTION]... PATTERN [FILE]...'))
3126 def grep(ui, repo, pattern, *pats, **opts):
3126 def grep(ui, repo, pattern, *pats, **opts):
3127 """search for a pattern in specified files and revisions
3127 """search for a pattern in specified files and revisions
3128
3128
3129 Search revisions of files for a regular expression.
3129 Search revisions of files for a regular expression.
3130
3130
3131 This command behaves differently than Unix grep. It only accepts
3131 This command behaves differently than Unix grep. It only accepts
3132 Python/Perl regexps. It searches repository history, not the
3132 Python/Perl regexps. It searches repository history, not the
3133 working directory. It always prints the revision number in which a
3133 working directory. It always prints the revision number in which a
3134 match appears.
3134 match appears.
3135
3135
3136 By default, grep only prints output for the first revision of a
3136 By default, grep only prints output for the first revision of a
3137 file in which it finds a match. To get it to print every revision
3137 file in which it finds a match. To get it to print every revision
3138 that contains a change in match status ("-" for a match that
3138 that contains a change in match status ("-" for a match that
3139 becomes a non-match, or "+" for a non-match that becomes a match),
3139 becomes a non-match, or "+" for a non-match that becomes a match),
3140 use the --all flag.
3140 use the --all flag.
3141
3141
3142 Returns 0 if a match is found, 1 otherwise.
3142 Returns 0 if a match is found, 1 otherwise.
3143 """
3143 """
3144 reflags = re.M
3144 reflags = re.M
3145 if opts.get('ignore_case'):
3145 if opts.get('ignore_case'):
3146 reflags |= re.I
3146 reflags |= re.I
3147 try:
3147 try:
3148 regexp = util.compilere(pattern, reflags)
3148 regexp = util.compilere(pattern, reflags)
3149 except re.error, inst:
3149 except re.error, inst:
3150 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3150 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3151 return 1
3151 return 1
3152 sep, eol = ':', '\n'
3152 sep, eol = ':', '\n'
3153 if opts.get('print0'):
3153 if opts.get('print0'):
3154 sep = eol = '\0'
3154 sep = eol = '\0'
3155
3155
3156 getfile = util.lrucachefunc(repo.file)
3156 getfile = util.lrucachefunc(repo.file)
3157
3157
3158 def matchlines(body):
3158 def matchlines(body):
3159 begin = 0
3159 begin = 0
3160 linenum = 0
3160 linenum = 0
3161 while begin < len(body):
3161 while begin < len(body):
3162 match = regexp.search(body, begin)
3162 match = regexp.search(body, begin)
3163 if not match:
3163 if not match:
3164 break
3164 break
3165 mstart, mend = match.span()
3165 mstart, mend = match.span()
3166 linenum += body.count('\n', begin, mstart) + 1
3166 linenum += body.count('\n', begin, mstart) + 1
3167 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3167 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3168 begin = body.find('\n', mend) + 1 or len(body) + 1
3168 begin = body.find('\n', mend) + 1 or len(body) + 1
3169 lend = begin - 1
3169 lend = begin - 1
3170 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3170 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3171
3171
3172 class linestate(object):
3172 class linestate(object):
3173 def __init__(self, line, linenum, colstart, colend):
3173 def __init__(self, line, linenum, colstart, colend):
3174 self.line = line
3174 self.line = line
3175 self.linenum = linenum
3175 self.linenum = linenum
3176 self.colstart = colstart
3176 self.colstart = colstart
3177 self.colend = colend
3177 self.colend = colend
3178
3178
3179 def __hash__(self):
3179 def __hash__(self):
3180 return hash((self.linenum, self.line))
3180 return hash((self.linenum, self.line))
3181
3181
3182 def __eq__(self, other):
3182 def __eq__(self, other):
3183 return self.line == other.line
3183 return self.line == other.line
3184
3184
3185 matches = {}
3185 matches = {}
3186 copies = {}
3186 copies = {}
3187 def grepbody(fn, rev, body):
3187 def grepbody(fn, rev, body):
3188 matches[rev].setdefault(fn, [])
3188 matches[rev].setdefault(fn, [])
3189 m = matches[rev][fn]
3189 m = matches[rev][fn]
3190 for lnum, cstart, cend, line in matchlines(body):
3190 for lnum, cstart, cend, line in matchlines(body):
3191 s = linestate(line, lnum, cstart, cend)
3191 s = linestate(line, lnum, cstart, cend)
3192 m.append(s)
3192 m.append(s)
3193
3193
3194 def difflinestates(a, b):
3194 def difflinestates(a, b):
3195 sm = difflib.SequenceMatcher(None, a, b)
3195 sm = difflib.SequenceMatcher(None, a, b)
3196 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3196 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3197 if tag == 'insert':
3197 if tag == 'insert':
3198 for i in xrange(blo, bhi):
3198 for i in xrange(blo, bhi):
3199 yield ('+', b[i])
3199 yield ('+', b[i])
3200 elif tag == 'delete':
3200 elif tag == 'delete':
3201 for i in xrange(alo, ahi):
3201 for i in xrange(alo, ahi):
3202 yield ('-', a[i])
3202 yield ('-', a[i])
3203 elif tag == 'replace':
3203 elif tag == 'replace':
3204 for i in xrange(alo, ahi):
3204 for i in xrange(alo, ahi):
3205 yield ('-', a[i])
3205 yield ('-', a[i])
3206 for i in xrange(blo, bhi):
3206 for i in xrange(blo, bhi):
3207 yield ('+', b[i])
3207 yield ('+', b[i])
3208
3208
3209 def display(fn, ctx, pstates, states):
3209 def display(fn, ctx, pstates, states):
3210 rev = ctx.rev()
3210 rev = ctx.rev()
3211 datefunc = ui.quiet and util.shortdate or util.datestr
3211 datefunc = ui.quiet and util.shortdate or util.datestr
3212 found = False
3212 found = False
3213 filerevmatches = {}
3213 filerevmatches = {}
3214 def binary():
3214 def binary():
3215 flog = getfile(fn)
3215 flog = getfile(fn)
3216 return util.binary(flog.read(ctx.filenode(fn)))
3216 return util.binary(flog.read(ctx.filenode(fn)))
3217
3217
3218 if opts.get('all'):
3218 if opts.get('all'):
3219 iter = difflinestates(pstates, states)
3219 iter = difflinestates(pstates, states)
3220 else:
3220 else:
3221 iter = [('', l) for l in states]
3221 iter = [('', l) for l in states]
3222 for change, l in iter:
3222 for change, l in iter:
3223 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3223 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3224 before, match, after = None, None, None
3224 before, match, after = None, None, None
3225
3225
3226 if opts.get('line_number'):
3226 if opts.get('line_number'):
3227 cols.append((str(l.linenum), 'grep.linenumber'))
3227 cols.append((str(l.linenum), 'grep.linenumber'))
3228 if opts.get('all'):
3228 if opts.get('all'):
3229 cols.append((change, 'grep.change'))
3229 cols.append((change, 'grep.change'))
3230 if opts.get('user'):
3230 if opts.get('user'):
3231 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3231 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3232 if opts.get('date'):
3232 if opts.get('date'):
3233 cols.append((datefunc(ctx.date()), 'grep.date'))
3233 cols.append((datefunc(ctx.date()), 'grep.date'))
3234 if opts.get('files_with_matches'):
3234 if opts.get('files_with_matches'):
3235 c = (fn, rev)
3235 c = (fn, rev)
3236 if c in filerevmatches:
3236 if c in filerevmatches:
3237 continue
3237 continue
3238 filerevmatches[c] = 1
3238 filerevmatches[c] = 1
3239 else:
3239 else:
3240 before = l.line[:l.colstart]
3240 before = l.line[:l.colstart]
3241 match = l.line[l.colstart:l.colend]
3241 match = l.line[l.colstart:l.colend]
3242 after = l.line[l.colend:]
3242 after = l.line[l.colend:]
3243 for col, label in cols[:-1]:
3243 for col, label in cols[:-1]:
3244 ui.write(col, label=label)
3244 ui.write(col, label=label)
3245 ui.write(sep, label='grep.sep')
3245 ui.write(sep, label='grep.sep')
3246 ui.write(cols[-1][0], label=cols[-1][1])
3246 ui.write(cols[-1][0], label=cols[-1][1])
3247 if before is not None:
3247 if before is not None:
3248 ui.write(sep, label='grep.sep')
3248 ui.write(sep, label='grep.sep')
3249 if not opts.get('text') and binary():
3249 if not opts.get('text') and binary():
3250 ui.write(" Binary file matches")
3250 ui.write(" Binary file matches")
3251 else:
3251 else:
3252 ui.write(before)
3252 ui.write(before)
3253 ui.write(match, label='grep.match')
3253 ui.write(match, label='grep.match')
3254 ui.write(after)
3254 ui.write(after)
3255 ui.write(eol)
3255 ui.write(eol)
3256 found = True
3256 found = True
3257 return found
3257 return found
3258
3258
3259 skip = {}
3259 skip = {}
3260 revfiles = {}
3260 revfiles = {}
3261 matchfn = scmutil.match(repo[None], pats, opts)
3261 matchfn = scmutil.match(repo[None], pats, opts)
3262 found = False
3262 found = False
3263 follow = opts.get('follow')
3263 follow = opts.get('follow')
3264
3264
3265 def prep(ctx, fns):
3265 def prep(ctx, fns):
3266 rev = ctx.rev()
3266 rev = ctx.rev()
3267 pctx = ctx.p1()
3267 pctx = ctx.p1()
3268 parent = pctx.rev()
3268 parent = pctx.rev()
3269 matches.setdefault(rev, {})
3269 matches.setdefault(rev, {})
3270 matches.setdefault(parent, {})
3270 matches.setdefault(parent, {})
3271 files = revfiles.setdefault(rev, [])
3271 files = revfiles.setdefault(rev, [])
3272 for fn in fns:
3272 for fn in fns:
3273 flog = getfile(fn)
3273 flog = getfile(fn)
3274 try:
3274 try:
3275 fnode = ctx.filenode(fn)
3275 fnode = ctx.filenode(fn)
3276 except error.LookupError:
3276 except error.LookupError:
3277 continue
3277 continue
3278
3278
3279 copied = flog.renamed(fnode)
3279 copied = flog.renamed(fnode)
3280 copy = follow and copied and copied[0]
3280 copy = follow and copied and copied[0]
3281 if copy:
3281 if copy:
3282 copies.setdefault(rev, {})[fn] = copy
3282 copies.setdefault(rev, {})[fn] = copy
3283 if fn in skip:
3283 if fn in skip:
3284 if copy:
3284 if copy:
3285 skip[copy] = True
3285 skip[copy] = True
3286 continue
3286 continue
3287 files.append(fn)
3287 files.append(fn)
3288
3288
3289 if fn not in matches[rev]:
3289 if fn not in matches[rev]:
3290 grepbody(fn, rev, flog.read(fnode))
3290 grepbody(fn, rev, flog.read(fnode))
3291
3291
3292 pfn = copy or fn
3292 pfn = copy or fn
3293 if pfn not in matches[parent]:
3293 if pfn not in matches[parent]:
3294 try:
3294 try:
3295 fnode = pctx.filenode(pfn)
3295 fnode = pctx.filenode(pfn)
3296 grepbody(pfn, parent, flog.read(fnode))
3296 grepbody(pfn, parent, flog.read(fnode))
3297 except error.LookupError:
3297 except error.LookupError:
3298 pass
3298 pass
3299
3299
3300 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3300 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3301 rev = ctx.rev()
3301 rev = ctx.rev()
3302 parent = ctx.p1().rev()
3302 parent = ctx.p1().rev()
3303 for fn in sorted(revfiles.get(rev, [])):
3303 for fn in sorted(revfiles.get(rev, [])):
3304 states = matches[rev][fn]
3304 states = matches[rev][fn]
3305 copy = copies.get(rev, {}).get(fn)
3305 copy = copies.get(rev, {}).get(fn)
3306 if fn in skip:
3306 if fn in skip:
3307 if copy:
3307 if copy:
3308 skip[copy] = True
3308 skip[copy] = True
3309 continue
3309 continue
3310 pstates = matches.get(parent, {}).get(copy or fn, [])
3310 pstates = matches.get(parent, {}).get(copy or fn, [])
3311 if pstates or states:
3311 if pstates or states:
3312 r = display(fn, ctx, pstates, states)
3312 r = display(fn, ctx, pstates, states)
3313 found = found or r
3313 found = found or r
3314 if r and not opts.get('all'):
3314 if r and not opts.get('all'):
3315 skip[fn] = True
3315 skip[fn] = True
3316 if copy:
3316 if copy:
3317 skip[copy] = True
3317 skip[copy] = True
3318 del matches[rev]
3318 del matches[rev]
3319 del revfiles[rev]
3319 del revfiles[rev]
3320
3320
3321 return not found
3321 return not found
3322
3322
3323 @command('heads',
3323 @command('heads',
3324 [('r', 'rev', '',
3324 [('r', 'rev', '',
3325 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3325 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3326 ('t', 'topo', False, _('show topological heads only')),
3326 ('t', 'topo', False, _('show topological heads only')),
3327 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3327 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3328 ('c', 'closed', False, _('show normal and closed branch heads')),
3328 ('c', 'closed', False, _('show normal and closed branch heads')),
3329 ] + templateopts,
3329 ] + templateopts,
3330 _('[-ct] [-r STARTREV] [REV]...'))
3330 _('[-ct] [-r STARTREV] [REV]...'))
3331 def heads(ui, repo, *branchrevs, **opts):
3331 def heads(ui, repo, *branchrevs, **opts):
3332 """show branch heads
3332 """show branch heads
3333
3333
3334 With no arguments, show all open branch heads in the repository.
3334 With no arguments, show all open branch heads in the repository.
3335 Branch heads are changesets that have no descendants on the
3335 Branch heads are changesets that have no descendants on the
3336 same branch. They are where development generally takes place and
3336 same branch. They are where development generally takes place and
3337 are the usual targets for update and merge operations.
3337 are the usual targets for update and merge operations.
3338
3338
3339 If one or more REVs are given, only open branch heads on the
3339 If one or more REVs are given, only open branch heads on the
3340 branches associated with the specified changesets are shown. This
3340 branches associated with the specified changesets are shown. This
3341 means that you can use :hg:`heads .` to see the heads on the
3341 means that you can use :hg:`heads .` to see the heads on the
3342 currently checked-out branch.
3342 currently checked-out branch.
3343
3343
3344 If -c/--closed is specified, also show branch heads marked closed
3344 If -c/--closed is specified, also show branch heads marked closed
3345 (see :hg:`commit --close-branch`).
3345 (see :hg:`commit --close-branch`).
3346
3346
3347 If STARTREV is specified, only those heads that are descendants of
3347 If STARTREV is specified, only those heads that are descendants of
3348 STARTREV will be displayed.
3348 STARTREV will be displayed.
3349
3349
3350 If -t/--topo is specified, named branch mechanics will be ignored and only
3350 If -t/--topo is specified, named branch mechanics will be ignored and only
3351 topological heads (changesets with no children) will be shown.
3351 topological heads (changesets with no children) will be shown.
3352
3352
3353 Returns 0 if matching heads are found, 1 if not.
3353 Returns 0 if matching heads are found, 1 if not.
3354 """
3354 """
3355
3355
3356 start = None
3356 start = None
3357 if 'rev' in opts:
3357 if 'rev' in opts:
3358 start = scmutil.revsingle(repo, opts['rev'], None).node()
3358 start = scmutil.revsingle(repo, opts['rev'], None).node()
3359
3359
3360 if opts.get('topo'):
3360 if opts.get('topo'):
3361 heads = [repo[h] for h in repo.heads(start)]
3361 heads = [repo[h] for h in repo.heads(start)]
3362 else:
3362 else:
3363 heads = []
3363 heads = []
3364 for branch in repo.branchmap():
3364 for branch in repo.branchmap():
3365 heads += repo.branchheads(branch, start, opts.get('closed'))
3365 heads += repo.branchheads(branch, start, opts.get('closed'))
3366 heads = [repo[h] for h in heads]
3366 heads = [repo[h] for h in heads]
3367
3367
3368 if branchrevs:
3368 if branchrevs:
3369 branches = set(repo[br].branch() for br in branchrevs)
3369 branches = set(repo[br].branch() for br in branchrevs)
3370 heads = [h for h in heads if h.branch() in branches]
3370 heads = [h for h in heads if h.branch() in branches]
3371
3371
3372 if opts.get('active') and branchrevs:
3372 if opts.get('active') and branchrevs:
3373 dagheads = repo.heads(start)
3373 dagheads = repo.heads(start)
3374 heads = [h for h in heads if h.node() in dagheads]
3374 heads = [h for h in heads if h.node() in dagheads]
3375
3375
3376 if branchrevs:
3376 if branchrevs:
3377 haveheads = set(h.branch() for h in heads)
3377 haveheads = set(h.branch() for h in heads)
3378 if branches - haveheads:
3378 if branches - haveheads:
3379 headless = ', '.join(b for b in branches - haveheads)
3379 headless = ', '.join(b for b in branches - haveheads)
3380 msg = _('no open branch heads found on branches %s')
3380 msg = _('no open branch heads found on branches %s')
3381 if opts.get('rev'):
3381 if opts.get('rev'):
3382 msg += _(' (started at %s)') % opts['rev']
3382 msg += _(' (started at %s)') % opts['rev']
3383 ui.warn((msg + '\n') % headless)
3383 ui.warn((msg + '\n') % headless)
3384
3384
3385 if not heads:
3385 if not heads:
3386 return 1
3386 return 1
3387
3387
3388 heads = sorted(heads, key=lambda x: -x.rev())
3388 heads = sorted(heads, key=lambda x: -x.rev())
3389 displayer = cmdutil.show_changeset(ui, repo, opts)
3389 displayer = cmdutil.show_changeset(ui, repo, opts)
3390 for ctx in heads:
3390 for ctx in heads:
3391 displayer.show(ctx)
3391 displayer.show(ctx)
3392 displayer.close()
3392 displayer.close()
3393
3393
3394 @command('help',
3394 @command('help',
3395 [('e', 'extension', None, _('show only help for extensions')),
3395 [('e', 'extension', None, _('show only help for extensions')),
3396 ('c', 'command', None, _('show only help for commands')),
3396 ('c', 'command', None, _('show only help for commands')),
3397 ('k', 'keyword', '', _('show topics matching keyword')),
3397 ('k', 'keyword', '', _('show topics matching keyword')),
3398 ],
3398 ],
3399 _('[-ec] [TOPIC]'))
3399 _('[-ec] [TOPIC]'))
3400 def help_(ui, name=None, **opts):
3400 def help_(ui, name=None, **opts):
3401 """show help for a given topic or a help overview
3401 """show help for a given topic or a help overview
3402
3402
3403 With no arguments, print a list of commands with short help messages.
3403 With no arguments, print a list of commands with short help messages.
3404
3404
3405 Given a topic, extension, or command name, print help for that
3405 Given a topic, extension, or command name, print help for that
3406 topic.
3406 topic.
3407
3407
3408 Returns 0 if successful.
3408 Returns 0 if successful.
3409 """
3409 """
3410
3410
3411 textwidth = min(ui.termwidth(), 80) - 2
3411 textwidth = min(ui.termwidth(), 80) - 2
3412
3412
3413 keep = ui.verbose and ['verbose'] or []
3413 keep = ui.verbose and ['verbose'] or []
3414 text = help.help_(ui, name, **opts)
3414 text = help.help_(ui, name, **opts)
3415
3415
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 if 'verbose' in pruned:
3417 if 'verbose' in pruned:
3418 keep.append('omitted')
3418 keep.append('omitted')
3419 else:
3419 else:
3420 keep.append('notomitted')
3420 keep.append('notomitted')
3421 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3421 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3422 ui.write(formatted)
3422 ui.write(formatted)
3423
3423
3424
3424
3425 @command('identify|id',
3425 @command('identify|id',
3426 [('r', 'rev', '',
3426 [('r', 'rev', '',
3427 _('identify the specified revision'), _('REV')),
3427 _('identify the specified revision'), _('REV')),
3428 ('n', 'num', None, _('show local revision number')),
3428 ('n', 'num', None, _('show local revision number')),
3429 ('i', 'id', None, _('show global revision id')),
3429 ('i', 'id', None, _('show global revision id')),
3430 ('b', 'branch', None, _('show branch')),
3430 ('b', 'branch', None, _('show branch')),
3431 ('t', 'tags', None, _('show tags')),
3431 ('t', 'tags', None, _('show tags')),
3432 ('B', 'bookmarks', None, _('show bookmarks')),
3432 ('B', 'bookmarks', None, _('show bookmarks')),
3433 ] + remoteopts,
3433 ] + remoteopts,
3434 _('[-nibtB] [-r REV] [SOURCE]'))
3434 _('[-nibtB] [-r REV] [SOURCE]'))
3435 def identify(ui, repo, source=None, rev=None,
3435 def identify(ui, repo, source=None, rev=None,
3436 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3436 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3437 """identify the working copy or specified revision
3437 """identify the working copy or specified revision
3438
3438
3439 Print a summary identifying the repository state at REV using one or
3439 Print a summary identifying the repository state at REV using one or
3440 two parent hash identifiers, followed by a "+" if the working
3440 two parent hash identifiers, followed by a "+" if the working
3441 directory has uncommitted changes, the branch name (if not default),
3441 directory has uncommitted changes, the branch name (if not default),
3442 a list of tags, and a list of bookmarks.
3442 a list of tags, and a list of bookmarks.
3443
3443
3444 When REV is not given, print a summary of the current state of the
3444 When REV is not given, print a summary of the current state of the
3445 repository.
3445 repository.
3446
3446
3447 Specifying a path to a repository root or Mercurial bundle will
3447 Specifying a path to a repository root or Mercurial bundle will
3448 cause lookup to operate on that repository/bundle.
3448 cause lookup to operate on that repository/bundle.
3449
3449
3450 .. container:: verbose
3450 .. container:: verbose
3451
3451
3452 Examples:
3452 Examples:
3453
3453
3454 - generate a build identifier for the working directory::
3454 - generate a build identifier for the working directory::
3455
3455
3456 hg id --id > build-id.dat
3456 hg id --id > build-id.dat
3457
3457
3458 - find the revision corresponding to a tag::
3458 - find the revision corresponding to a tag::
3459
3459
3460 hg id -n -r 1.3
3460 hg id -n -r 1.3
3461
3461
3462 - check the most recent revision of a remote repository::
3462 - check the most recent revision of a remote repository::
3463
3463
3464 hg id -r tip http://selenic.com/hg/
3464 hg id -r tip http://selenic.com/hg/
3465
3465
3466 Returns 0 if successful.
3466 Returns 0 if successful.
3467 """
3467 """
3468
3468
3469 if not repo and not source:
3469 if not repo and not source:
3470 raise util.Abort(_("there is no Mercurial repository here "
3470 raise util.Abort(_("there is no Mercurial repository here "
3471 "(.hg not found)"))
3471 "(.hg not found)"))
3472
3472
3473 hexfunc = ui.debugflag and hex or short
3473 hexfunc = ui.debugflag and hex or short
3474 default = not (num or id or branch or tags or bookmarks)
3474 default = not (num or id or branch or tags or bookmarks)
3475 output = []
3475 output = []
3476 revs = []
3476 revs = []
3477
3477
3478 if source:
3478 if source:
3479 source, branches = hg.parseurl(ui.expandpath(source))
3479 source, branches = hg.parseurl(ui.expandpath(source))
3480 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3480 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3481 repo = peer.local()
3481 repo = peer.local()
3482 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3482 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3483
3483
3484 if not repo:
3484 if not repo:
3485 if num or branch or tags:
3485 if num or branch or tags:
3486 raise util.Abort(
3486 raise util.Abort(
3487 _("can't query remote revision number, branch, or tags"))
3487 _("can't query remote revision number, branch, or tags"))
3488 if not rev and revs:
3488 if not rev and revs:
3489 rev = revs[0]
3489 rev = revs[0]
3490 if not rev:
3490 if not rev:
3491 rev = "tip"
3491 rev = "tip"
3492
3492
3493 remoterev = peer.lookup(rev)
3493 remoterev = peer.lookup(rev)
3494 if default or id:
3494 if default or id:
3495 output = [hexfunc(remoterev)]
3495 output = [hexfunc(remoterev)]
3496
3496
3497 def getbms():
3497 def getbms():
3498 bms = []
3498 bms = []
3499
3499
3500 if 'bookmarks' in peer.listkeys('namespaces'):
3500 if 'bookmarks' in peer.listkeys('namespaces'):
3501 hexremoterev = hex(remoterev)
3501 hexremoterev = hex(remoterev)
3502 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3502 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3503 if bmr == hexremoterev]
3503 if bmr == hexremoterev]
3504
3504
3505 return sorted(bms)
3505 return sorted(bms)
3506
3506
3507 if bookmarks:
3507 if bookmarks:
3508 output.extend(getbms())
3508 output.extend(getbms())
3509 elif default and not ui.quiet:
3509 elif default and not ui.quiet:
3510 # multiple bookmarks for a single parent separated by '/'
3510 # multiple bookmarks for a single parent separated by '/'
3511 bm = '/'.join(getbms())
3511 bm = '/'.join(getbms())
3512 if bm:
3512 if bm:
3513 output.append(bm)
3513 output.append(bm)
3514 else:
3514 else:
3515 if not rev:
3515 if not rev:
3516 ctx = repo[None]
3516 ctx = repo[None]
3517 parents = ctx.parents()
3517 parents = ctx.parents()
3518 changed = ""
3518 changed = ""
3519 if default or id or num:
3519 if default or id or num:
3520 if (util.any(repo.status())
3520 if (util.any(repo.status())
3521 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3521 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3522 changed = '+'
3522 changed = '+'
3523 if default or id:
3523 if default or id:
3524 output = ["%s%s" %
3524 output = ["%s%s" %
3525 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3525 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3526 if num:
3526 if num:
3527 output.append("%s%s" %
3527 output.append("%s%s" %
3528 ('+'.join([str(p.rev()) for p in parents]), changed))
3528 ('+'.join([str(p.rev()) for p in parents]), changed))
3529 else:
3529 else:
3530 ctx = scmutil.revsingle(repo, rev)
3530 ctx = scmutil.revsingle(repo, rev)
3531 if default or id:
3531 if default or id:
3532 output = [hexfunc(ctx.node())]
3532 output = [hexfunc(ctx.node())]
3533 if num:
3533 if num:
3534 output.append(str(ctx.rev()))
3534 output.append(str(ctx.rev()))
3535
3535
3536 if default and not ui.quiet:
3536 if default and not ui.quiet:
3537 b = ctx.branch()
3537 b = ctx.branch()
3538 if b != 'default':
3538 if b != 'default':
3539 output.append("(%s)" % b)
3539 output.append("(%s)" % b)
3540
3540
3541 # multiple tags for a single parent separated by '/'
3541 # multiple tags for a single parent separated by '/'
3542 t = '/'.join(ctx.tags())
3542 t = '/'.join(ctx.tags())
3543 if t:
3543 if t:
3544 output.append(t)
3544 output.append(t)
3545
3545
3546 # multiple bookmarks for a single parent separated by '/'
3546 # multiple bookmarks for a single parent separated by '/'
3547 bm = '/'.join(ctx.bookmarks())
3547 bm = '/'.join(ctx.bookmarks())
3548 if bm:
3548 if bm:
3549 output.append(bm)
3549 output.append(bm)
3550 else:
3550 else:
3551 if branch:
3551 if branch:
3552 output.append(ctx.branch())
3552 output.append(ctx.branch())
3553
3553
3554 if tags:
3554 if tags:
3555 output.extend(ctx.tags())
3555 output.extend(ctx.tags())
3556
3556
3557 if bookmarks:
3557 if bookmarks:
3558 output.extend(ctx.bookmarks())
3558 output.extend(ctx.bookmarks())
3559
3559
3560 ui.write("%s\n" % ' '.join(output))
3560 ui.write("%s\n" % ' '.join(output))
3561
3561
3562 @command('import|patch',
3562 @command('import|patch',
3563 [('p', 'strip', 1,
3563 [('p', 'strip', 1,
3564 _('directory strip option for patch. This has the same '
3564 _('directory strip option for patch. This has the same '
3565 'meaning as the corresponding patch option'), _('NUM')),
3565 'meaning as the corresponding patch option'), _('NUM')),
3566 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3566 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3567 ('e', 'edit', False, _('invoke editor on commit messages')),
3567 ('e', 'edit', False, _('invoke editor on commit messages')),
3568 ('f', 'force', None,
3568 ('f', 'force', None,
3569 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3569 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3570 ('', 'no-commit', None,
3570 ('', 'no-commit', None,
3571 _("don't commit, just update the working directory")),
3571 _("don't commit, just update the working directory")),
3572 ('', 'bypass', None,
3572 ('', 'bypass', None,
3573 _("apply patch without touching the working directory")),
3573 _("apply patch without touching the working directory")),
3574 ('', 'exact', None,
3574 ('', 'exact', None,
3575 _('apply patch to the nodes from which it was generated')),
3575 _('apply patch to the nodes from which it was generated')),
3576 ('', 'import-branch', None,
3576 ('', 'import-branch', None,
3577 _('use any branch information in patch (implied by --exact)'))] +
3577 _('use any branch information in patch (implied by --exact)'))] +
3578 commitopts + commitopts2 + similarityopts,
3578 commitopts + commitopts2 + similarityopts,
3579 _('[OPTION]... PATCH...'))
3579 _('[OPTION]... PATCH...'))
3580 def import_(ui, repo, patch1=None, *patches, **opts):
3580 def import_(ui, repo, patch1=None, *patches, **opts):
3581 """import an ordered set of patches
3581 """import an ordered set of patches
3582
3582
3583 Import a list of patches and commit them individually (unless
3583 Import a list of patches and commit them individually (unless
3584 --no-commit is specified).
3584 --no-commit is specified).
3585
3585
3586 Because import first applies changes to the working directory,
3586 Because import first applies changes to the working directory,
3587 import will abort if there are outstanding changes.
3587 import will abort if there are outstanding changes.
3588
3588
3589 You can import a patch straight from a mail message. Even patches
3589 You can import a patch straight from a mail message. Even patches
3590 as attachments work (to use the body part, it must have type
3590 as attachments work (to use the body part, it must have type
3591 text/plain or text/x-patch). From and Subject headers of email
3591 text/plain or text/x-patch). From and Subject headers of email
3592 message are used as default committer and commit message. All
3592 message are used as default committer and commit message. All
3593 text/plain body parts before first diff are added to commit
3593 text/plain body parts before first diff are added to commit
3594 message.
3594 message.
3595
3595
3596 If the imported patch was generated by :hg:`export`, user and
3596 If the imported patch was generated by :hg:`export`, user and
3597 description from patch override values from message headers and
3597 description from patch override values from message headers and
3598 body. Values given on command line with -m/--message and -u/--user
3598 body. Values given on command line with -m/--message and -u/--user
3599 override these.
3599 override these.
3600
3600
3601 If --exact is specified, import will set the working directory to
3601 If --exact is specified, import will set the working directory to
3602 the parent of each patch before applying it, and will abort if the
3602 the parent of each patch before applying it, and will abort if the
3603 resulting changeset has a different ID than the one recorded in
3603 resulting changeset has a different ID than the one recorded in
3604 the patch. This may happen due to character set problems or other
3604 the patch. This may happen due to character set problems or other
3605 deficiencies in the text patch format.
3605 deficiencies in the text patch format.
3606
3606
3607 Use --bypass to apply and commit patches directly to the
3607 Use --bypass to apply and commit patches directly to the
3608 repository, not touching the working directory. Without --exact,
3608 repository, not touching the working directory. Without --exact,
3609 patches will be applied on top of the working directory parent
3609 patches will be applied on top of the working directory parent
3610 revision.
3610 revision.
3611
3611
3612 With -s/--similarity, hg will attempt to discover renames and
3612 With -s/--similarity, hg will attempt to discover renames and
3613 copies in the patch in the same way as :hg:`addremove`.
3613 copies in the patch in the same way as :hg:`addremove`.
3614
3614
3615 To read a patch from standard input, use "-" as the patch name. If
3615 To read a patch from standard input, use "-" as the patch name. If
3616 a URL is specified, the patch will be downloaded from it.
3616 a URL is specified, the patch will be downloaded from it.
3617 See :hg:`help dates` for a list of formats valid for -d/--date.
3617 See :hg:`help dates` for a list of formats valid for -d/--date.
3618
3618
3619 .. container:: verbose
3619 .. container:: verbose
3620
3620
3621 Examples:
3621 Examples:
3622
3622
3623 - import a traditional patch from a website and detect renames::
3623 - import a traditional patch from a website and detect renames::
3624
3624
3625 hg import -s 80 http://example.com/bugfix.patch
3625 hg import -s 80 http://example.com/bugfix.patch
3626
3626
3627 - import a changeset from an hgweb server::
3627 - import a changeset from an hgweb server::
3628
3628
3629 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3629 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3630
3630
3631 - import all the patches in an Unix-style mbox::
3631 - import all the patches in an Unix-style mbox::
3632
3632
3633 hg import incoming-patches.mbox
3633 hg import incoming-patches.mbox
3634
3634
3635 - attempt to exactly restore an exported changeset (not always
3635 - attempt to exactly restore an exported changeset (not always
3636 possible)::
3636 possible)::
3637
3637
3638 hg import --exact proposed-fix.patch
3638 hg import --exact proposed-fix.patch
3639
3639
3640 Returns 0 on success.
3640 Returns 0 on success.
3641 """
3641 """
3642
3642
3643 if not patch1:
3643 if not patch1:
3644 raise util.Abort(_('need at least one patch to import'))
3644 raise util.Abort(_('need at least one patch to import'))
3645
3645
3646 patches = (patch1,) + patches
3646 patches = (patch1,) + patches
3647
3647
3648 date = opts.get('date')
3648 date = opts.get('date')
3649 if date:
3649 if date:
3650 opts['date'] = util.parsedate(date)
3650 opts['date'] = util.parsedate(date)
3651
3651
3652 editor = cmdutil.commiteditor
3652 editor = cmdutil.commiteditor
3653 if opts.get('edit'):
3653 if opts.get('edit'):
3654 editor = cmdutil.commitforceeditor
3654 editor = cmdutil.commitforceeditor
3655
3655
3656 update = not opts.get('bypass')
3656 update = not opts.get('bypass')
3657 if not update and opts.get('no_commit'):
3657 if not update and opts.get('no_commit'):
3658 raise util.Abort(_('cannot use --no-commit with --bypass'))
3658 raise util.Abort(_('cannot use --no-commit with --bypass'))
3659 try:
3659 try:
3660 sim = float(opts.get('similarity') or 0)
3660 sim = float(opts.get('similarity') or 0)
3661 except ValueError:
3661 except ValueError:
3662 raise util.Abort(_('similarity must be a number'))
3662 raise util.Abort(_('similarity must be a number'))
3663 if sim < 0 or sim > 100:
3663 if sim < 0 or sim > 100:
3664 raise util.Abort(_('similarity must be between 0 and 100'))
3664 raise util.Abort(_('similarity must be between 0 and 100'))
3665 if sim and not update:
3665 if sim and not update:
3666 raise util.Abort(_('cannot use --similarity with --bypass'))
3666 raise util.Abort(_('cannot use --similarity with --bypass'))
3667
3667
3668 if update:
3668 if update:
3669 cmdutil.checkunfinished(repo)
3669 cmdutil.checkunfinished(repo)
3670 if (opts.get('exact') or not opts.get('force')) and update:
3670 if (opts.get('exact') or not opts.get('force')) and update:
3671 cmdutil.bailifchanged(repo)
3671 cmdutil.bailifchanged(repo)
3672
3672
3673 base = opts["base"]
3673 base = opts["base"]
3674 strip = opts["strip"]
3674 strip = opts["strip"]
3675 wlock = lock = tr = None
3675 wlock = lock = tr = None
3676 msgs = []
3676 msgs = []
3677
3677
3678 def tryone(ui, hunk, parents):
3678 def tryone(ui, hunk, parents):
3679 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3679 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3680 patch.extract(ui, hunk)
3680 patch.extract(ui, hunk)
3681
3681
3682 if not tmpname:
3682 if not tmpname:
3683 return (None, None)
3683 return (None, None)
3684 msg = _('applied to working directory')
3684 msg = _('applied to working directory')
3685
3685
3686 try:
3686 try:
3687 cmdline_message = cmdutil.logmessage(ui, opts)
3687 cmdline_message = cmdutil.logmessage(ui, opts)
3688 if cmdline_message:
3688 if cmdline_message:
3689 # pickup the cmdline msg
3689 # pickup the cmdline msg
3690 message = cmdline_message
3690 message = cmdline_message
3691 elif message:
3691 elif message:
3692 # pickup the patch msg
3692 # pickup the patch msg
3693 message = message.strip()
3693 message = message.strip()
3694 else:
3694 else:
3695 # launch the editor
3695 # launch the editor
3696 message = None
3696 message = None
3697 ui.debug('message:\n%s\n' % message)
3697 ui.debug('message:\n%s\n' % message)
3698
3698
3699 if len(parents) == 1:
3699 if len(parents) == 1:
3700 parents.append(repo[nullid])
3700 parents.append(repo[nullid])
3701 if opts.get('exact'):
3701 if opts.get('exact'):
3702 if not nodeid or not p1:
3702 if not nodeid or not p1:
3703 raise util.Abort(_('not a Mercurial patch'))
3703 raise util.Abort(_('not a Mercurial patch'))
3704 p1 = repo[p1]
3704 p1 = repo[p1]
3705 p2 = repo[p2 or nullid]
3705 p2 = repo[p2 or nullid]
3706 elif p2:
3706 elif p2:
3707 try:
3707 try:
3708 p1 = repo[p1]
3708 p1 = repo[p1]
3709 p2 = repo[p2]
3709 p2 = repo[p2]
3710 # Without any options, consider p2 only if the
3710 # Without any options, consider p2 only if the
3711 # patch is being applied on top of the recorded
3711 # patch is being applied on top of the recorded
3712 # first parent.
3712 # first parent.
3713 if p1 != parents[0]:
3713 if p1 != parents[0]:
3714 p1 = parents[0]
3714 p1 = parents[0]
3715 p2 = repo[nullid]
3715 p2 = repo[nullid]
3716 except error.RepoError:
3716 except error.RepoError:
3717 p1, p2 = parents
3717 p1, p2 = parents
3718 else:
3718 else:
3719 p1, p2 = parents
3719 p1, p2 = parents
3720
3720
3721 n = None
3721 n = None
3722 if update:
3722 if update:
3723 if p1 != parents[0]:
3723 if p1 != parents[0]:
3724 hg.clean(repo, p1.node())
3724 hg.clean(repo, p1.node())
3725 if p2 != parents[1]:
3725 if p2 != parents[1]:
3726 repo.setparents(p1.node(), p2.node())
3726 repo.setparents(p1.node(), p2.node())
3727
3727
3728 if opts.get('exact') or opts.get('import_branch'):
3728 if opts.get('exact') or opts.get('import_branch'):
3729 repo.dirstate.setbranch(branch or 'default')
3729 repo.dirstate.setbranch(branch or 'default')
3730
3730
3731 files = set()
3731 files = set()
3732 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3732 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3733 eolmode=None, similarity=sim / 100.0)
3733 eolmode=None, similarity=sim / 100.0)
3734 files = list(files)
3734 files = list(files)
3735 if opts.get('no_commit'):
3735 if opts.get('no_commit'):
3736 if message:
3736 if message:
3737 msgs.append(message)
3737 msgs.append(message)
3738 else:
3738 else:
3739 if opts.get('exact') or p2:
3739 if opts.get('exact') or p2:
3740 # If you got here, you either use --force and know what
3740 # If you got here, you either use --force and know what
3741 # you are doing or used --exact or a merge patch while
3741 # you are doing or used --exact or a merge patch while
3742 # being updated to its first parent.
3742 # being updated to its first parent.
3743 m = None
3743 m = None
3744 else:
3744 else:
3745 m = scmutil.matchfiles(repo, files or [])
3745 m = scmutil.matchfiles(repo, files or [])
3746 n = repo.commit(message, opts.get('user') or user,
3746 n = repo.commit(message, opts.get('user') or user,
3747 opts.get('date') or date, match=m,
3747 opts.get('date') or date, match=m,
3748 editor=editor)
3748 editor=editor)
3749 else:
3749 else:
3750 if opts.get('exact') or opts.get('import_branch'):
3750 if opts.get('exact') or opts.get('import_branch'):
3751 branch = branch or 'default'
3751 branch = branch or 'default'
3752 else:
3752 else:
3753 branch = p1.branch()
3753 branch = p1.branch()
3754 store = patch.filestore()
3754 store = patch.filestore()
3755 try:
3755 try:
3756 files = set()
3756 files = set()
3757 try:
3757 try:
3758 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3758 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3759 files, eolmode=None)
3759 files, eolmode=None)
3760 except patch.PatchError, e:
3760 except patch.PatchError, e:
3761 raise util.Abort(str(e))
3761 raise util.Abort(str(e))
3762 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3762 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3763 message,
3763 message,
3764 opts.get('user') or user,
3764 opts.get('user') or user,
3765 opts.get('date') or date,
3765 opts.get('date') or date,
3766 branch, files, store,
3766 branch, files, store,
3767 editor=cmdutil.commiteditor)
3767 editor=cmdutil.commiteditor)
3768 repo.savecommitmessage(memctx.description())
3768 repo.savecommitmessage(memctx.description())
3769 n = memctx.commit()
3769 n = memctx.commit()
3770 finally:
3770 finally:
3771 store.close()
3771 store.close()
3772 if opts.get('exact') and hex(n) != nodeid:
3772 if opts.get('exact') and hex(n) != nodeid:
3773 raise util.Abort(_('patch is damaged or loses information'))
3773 raise util.Abort(_('patch is damaged or loses information'))
3774 if n:
3774 if n:
3775 # i18n: refers to a short changeset id
3775 # i18n: refers to a short changeset id
3776 msg = _('created %s') % short(n)
3776 msg = _('created %s') % short(n)
3777 return (msg, n)
3777 return (msg, n)
3778 finally:
3778 finally:
3779 os.unlink(tmpname)
3779 os.unlink(tmpname)
3780
3780
3781 try:
3781 try:
3782 try:
3782 try:
3783 wlock = repo.wlock()
3783 wlock = repo.wlock()
3784 if not opts.get('no_commit'):
3784 if not opts.get('no_commit'):
3785 lock = repo.lock()
3785 lock = repo.lock()
3786 tr = repo.transaction('import')
3786 tr = repo.transaction('import')
3787 parents = repo.parents()
3787 parents = repo.parents()
3788 for patchurl in patches:
3788 for patchurl in patches:
3789 if patchurl == '-':
3789 if patchurl == '-':
3790 ui.status(_('applying patch from stdin\n'))
3790 ui.status(_('applying patch from stdin\n'))
3791 patchfile = ui.fin
3791 patchfile = ui.fin
3792 patchurl = 'stdin' # for error message
3792 patchurl = 'stdin' # for error message
3793 else:
3793 else:
3794 patchurl = os.path.join(base, patchurl)
3794 patchurl = os.path.join(base, patchurl)
3795 ui.status(_('applying %s\n') % patchurl)
3795 ui.status(_('applying %s\n') % patchurl)
3796 patchfile = hg.openpath(ui, patchurl)
3796 patchfile = hg.openpath(ui, patchurl)
3797
3797
3798 haspatch = False
3798 haspatch = False
3799 for hunk in patch.split(patchfile):
3799 for hunk in patch.split(patchfile):
3800 (msg, node) = tryone(ui, hunk, parents)
3800 (msg, node) = tryone(ui, hunk, parents)
3801 if msg:
3801 if msg:
3802 haspatch = True
3802 haspatch = True
3803 ui.note(msg + '\n')
3803 ui.note(msg + '\n')
3804 if update or opts.get('exact'):
3804 if update or opts.get('exact'):
3805 parents = repo.parents()
3805 parents = repo.parents()
3806 else:
3806 else:
3807 parents = [repo[node]]
3807 parents = [repo[node]]
3808
3808
3809 if not haspatch:
3809 if not haspatch:
3810 raise util.Abort(_('%s: no diffs found') % patchurl)
3810 raise util.Abort(_('%s: no diffs found') % patchurl)
3811
3811
3812 if tr:
3812 if tr:
3813 tr.close()
3813 tr.close()
3814 if msgs:
3814 if msgs:
3815 repo.savecommitmessage('\n* * *\n'.join(msgs))
3815 repo.savecommitmessage('\n* * *\n'.join(msgs))
3816 except: # re-raises
3816 except: # re-raises
3817 # wlock.release() indirectly calls dirstate.write(): since
3817 # wlock.release() indirectly calls dirstate.write(): since
3818 # we're crashing, we do not want to change the working dir
3818 # we're crashing, we do not want to change the working dir
3819 # parent after all, so make sure it writes nothing
3819 # parent after all, so make sure it writes nothing
3820 repo.dirstate.invalidate()
3820 repo.dirstate.invalidate()
3821 raise
3821 raise
3822 finally:
3822 finally:
3823 if tr:
3823 if tr:
3824 tr.release()
3824 tr.release()
3825 release(lock, wlock)
3825 release(lock, wlock)
3826
3826
3827 @command('incoming|in',
3827 @command('incoming|in',
3828 [('f', 'force', None,
3828 [('f', 'force', None,
3829 _('run even if remote repository is unrelated')),
3829 _('run even if remote repository is unrelated')),
3830 ('n', 'newest-first', None, _('show newest record first')),
3830 ('n', 'newest-first', None, _('show newest record first')),
3831 ('', 'bundle', '',
3831 ('', 'bundle', '',
3832 _('file to store the bundles into'), _('FILE')),
3832 _('file to store the bundles into'), _('FILE')),
3833 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3833 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3834 ('B', 'bookmarks', False, _("compare bookmarks")),
3834 ('B', 'bookmarks', False, _("compare bookmarks")),
3835 ('b', 'branch', [],
3835 ('b', 'branch', [],
3836 _('a specific branch you would like to pull'), _('BRANCH')),
3836 _('a specific branch you would like to pull'), _('BRANCH')),
3837 ] + logopts + remoteopts + subrepoopts,
3837 ] + logopts + remoteopts + subrepoopts,
3838 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3838 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3839 def incoming(ui, repo, source="default", **opts):
3839 def incoming(ui, repo, source="default", **opts):
3840 """show new changesets found in source
3840 """show new changesets found in source
3841
3841
3842 Show new changesets found in the specified path/URL or the default
3842 Show new changesets found in the specified path/URL or the default
3843 pull location. These are the changesets that would have been pulled
3843 pull location. These are the changesets that would have been pulled
3844 if a pull at the time you issued this command.
3844 if a pull at the time you issued this command.
3845
3845
3846 For remote repository, using --bundle avoids downloading the
3846 For remote repository, using --bundle avoids downloading the
3847 changesets twice if the incoming is followed by a pull.
3847 changesets twice if the incoming is followed by a pull.
3848
3848
3849 See pull for valid source format details.
3849 See pull for valid source format details.
3850
3850
3851 Returns 0 if there are incoming changes, 1 otherwise.
3851 Returns 0 if there are incoming changes, 1 otherwise.
3852 """
3852 """
3853 if opts.get('graph'):
3853 if opts.get('graph'):
3854 cmdutil.checkunsupportedgraphflags([], opts)
3854 cmdutil.checkunsupportedgraphflags([], opts)
3855 def display(other, chlist, displayer):
3855 def display(other, chlist, displayer):
3856 revdag = cmdutil.graphrevs(other, chlist, opts)
3856 revdag = cmdutil.graphrevs(other, chlist, opts)
3857 showparents = [ctx.node() for ctx in repo[None].parents()]
3857 showparents = [ctx.node() for ctx in repo[None].parents()]
3858 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3858 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3859 graphmod.asciiedges)
3859 graphmod.asciiedges)
3860
3860
3861 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3861 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3862 return 0
3862 return 0
3863
3863
3864 if opts.get('bundle') and opts.get('subrepos'):
3864 if opts.get('bundle') and opts.get('subrepos'):
3865 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3865 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3866
3866
3867 if opts.get('bookmarks'):
3867 if opts.get('bookmarks'):
3868 source, branches = hg.parseurl(ui.expandpath(source),
3868 source, branches = hg.parseurl(ui.expandpath(source),
3869 opts.get('branch'))
3869 opts.get('branch'))
3870 other = hg.peer(repo, opts, source)
3870 other = hg.peer(repo, opts, source)
3871 if 'bookmarks' not in other.listkeys('namespaces'):
3871 if 'bookmarks' not in other.listkeys('namespaces'):
3872 ui.warn(_("remote doesn't support bookmarks\n"))
3872 ui.warn(_("remote doesn't support bookmarks\n"))
3873 return 0
3873 return 0
3874 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3874 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3875 return bookmarks.diff(ui, repo, other)
3875 return bookmarks.diff(ui, repo, other)
3876
3876
3877 repo._subtoppath = ui.expandpath(source)
3877 repo._subtoppath = ui.expandpath(source)
3878 try:
3878 try:
3879 return hg.incoming(ui, repo, source, opts)
3879 return hg.incoming(ui, repo, source, opts)
3880 finally:
3880 finally:
3881 del repo._subtoppath
3881 del repo._subtoppath
3882
3882
3883
3883
3884 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3884 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3885 def init(ui, dest=".", **opts):
3885 def init(ui, dest=".", **opts):
3886 """create a new repository in the given directory
3886 """create a new repository in the given directory
3887
3887
3888 Initialize a new repository in the given directory. If the given
3888 Initialize a new repository in the given directory. If the given
3889 directory does not exist, it will be created.
3889 directory does not exist, it will be created.
3890
3890
3891 If no directory is given, the current directory is used.
3891 If no directory is given, the current directory is used.
3892
3892
3893 It is possible to specify an ``ssh://`` URL as the destination.
3893 It is possible to specify an ``ssh://`` URL as the destination.
3894 See :hg:`help urls` for more information.
3894 See :hg:`help urls` for more information.
3895
3895
3896 Returns 0 on success.
3896 Returns 0 on success.
3897 """
3897 """
3898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3899
3899
3900 @command('locate',
3900 @command('locate',
3901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3904 ] + walkopts,
3904 ] + walkopts,
3905 _('[OPTION]... [PATTERN]...'))
3905 _('[OPTION]... [PATTERN]...'))
3906 def locate(ui, repo, *pats, **opts):
3906 def locate(ui, repo, *pats, **opts):
3907 """locate files matching specific patterns
3907 """locate files matching specific patterns
3908
3908
3909 Print files under Mercurial control in the working directory whose
3909 Print files under Mercurial control in the working directory whose
3910 names match the given patterns.
3910 names match the given patterns.
3911
3911
3912 By default, this command searches all directories in the working
3912 By default, this command searches all directories in the working
3913 directory. To search just the current directory and its
3913 directory. To search just the current directory and its
3914 subdirectories, use "--include .".
3914 subdirectories, use "--include .".
3915
3915
3916 If no patterns are given to match, this command prints the names
3916 If no patterns are given to match, this command prints the names
3917 of all files under Mercurial control in the working directory.
3917 of all files under Mercurial control in the working directory.
3918
3918
3919 If you want to feed the output of this command into the "xargs"
3919 If you want to feed the output of this command into the "xargs"
3920 command, use the -0 option to both this command and "xargs". This
3920 command, use the -0 option to both this command and "xargs". This
3921 will avoid the problem of "xargs" treating single filenames that
3921 will avoid the problem of "xargs" treating single filenames that
3922 contain whitespace as multiple filenames.
3922 contain whitespace as multiple filenames.
3923
3923
3924 Returns 0 if a match is found, 1 otherwise.
3924 Returns 0 if a match is found, 1 otherwise.
3925 """
3925 """
3926 end = opts.get('print0') and '\0' or '\n'
3926 end = opts.get('print0') and '\0' or '\n'
3927 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3927 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3928
3928
3929 ret = 1
3929 ret = 1
3930 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3930 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3931 m.bad = lambda x, y: False
3931 m.bad = lambda x, y: False
3932 for abs in repo[rev].walk(m):
3932 for abs in repo[rev].walk(m):
3933 if not rev and abs not in repo.dirstate:
3933 if not rev and abs not in repo.dirstate:
3934 continue
3934 continue
3935 if opts.get('fullpath'):
3935 if opts.get('fullpath'):
3936 ui.write(repo.wjoin(abs), end)
3936 ui.write(repo.wjoin(abs), end)
3937 else:
3937 else:
3938 ui.write(((pats and m.rel(abs)) or abs), end)
3938 ui.write(((pats and m.rel(abs)) or abs), end)
3939 ret = 0
3939 ret = 0
3940
3940
3941 return ret
3941 return ret
3942
3942
3943 @command('^log|history',
3943 @command('^log|history',
3944 [('f', 'follow', None,
3944 [('f', 'follow', None,
3945 _('follow changeset history, or file history across copies and renames')),
3945 _('follow changeset history, or file history across copies and renames')),
3946 ('', 'follow-first', None,
3946 ('', 'follow-first', None,
3947 _('only follow the first parent of merge changesets (DEPRECATED)')),
3947 _('only follow the first parent of merge changesets (DEPRECATED)')),
3948 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3948 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3949 ('C', 'copies', None, _('show copied files')),
3949 ('C', 'copies', None, _('show copied files')),
3950 ('k', 'keyword', [],
3950 ('k', 'keyword', [],
3951 _('do case-insensitive search for a given text'), _('TEXT')),
3951 _('do case-insensitive search for a given text'), _('TEXT')),
3952 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3952 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3953 ('', 'removed', None, _('include revisions where files were removed')),
3953 ('', 'removed', None, _('include revisions where files were removed')),
3954 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3954 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3955 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3955 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3956 ('', 'only-branch', [],
3956 ('', 'only-branch', [],
3957 _('show only changesets within the given named branch (DEPRECATED)'),
3957 _('show only changesets within the given named branch (DEPRECATED)'),
3958 _('BRANCH')),
3958 _('BRANCH')),
3959 ('b', 'branch', [],
3959 ('b', 'branch', [],
3960 _('show changesets within the given named branch'), _('BRANCH')),
3960 _('show changesets within the given named branch'), _('BRANCH')),
3961 ('P', 'prune', [],
3961 ('P', 'prune', [],
3962 _('do not display revision or any of its ancestors'), _('REV')),
3962 _('do not display revision or any of its ancestors'), _('REV')),
3963 ] + logopts + walkopts,
3963 ] + logopts + walkopts,
3964 _('[OPTION]... [FILE]'))
3964 _('[OPTION]... [FILE]'))
3965 def log(ui, repo, *pats, **opts):
3965 def log(ui, repo, *pats, **opts):
3966 """show revision history of entire repository or files
3966 """show revision history of entire repository or files
3967
3967
3968 Print the revision history of the specified files or the entire
3968 Print the revision history of the specified files or the entire
3969 project.
3969 project.
3970
3970
3971 If no revision range is specified, the default is ``tip:0`` unless
3971 If no revision range is specified, the default is ``tip:0`` unless
3972 --follow is set, in which case the working directory parent is
3972 --follow is set, in which case the working directory parent is
3973 used as the starting revision.
3973 used as the starting revision.
3974
3974
3975 File history is shown without following rename or copy history of
3975 File history is shown without following rename or copy history of
3976 files. Use -f/--follow with a filename to follow history across
3976 files. Use -f/--follow with a filename to follow history across
3977 renames and copies. --follow without a filename will only show
3977 renames and copies. --follow without a filename will only show
3978 ancestors or descendants of the starting revision.
3978 ancestors or descendants of the starting revision.
3979
3979
3980 By default this command prints revision number and changeset id,
3980 By default this command prints revision number and changeset id,
3981 tags, non-trivial parents, user, date and time, and a summary for
3981 tags, non-trivial parents, user, date and time, and a summary for
3982 each commit. When the -v/--verbose switch is used, the list of
3982 each commit. When the -v/--verbose switch is used, the list of
3983 changed files and full commit message are shown.
3983 changed files and full commit message are shown.
3984
3984
3985 .. note::
3985 .. note::
3986
3986
3987 log -p/--patch may generate unexpected diff output for merge
3987 log -p/--patch may generate unexpected diff output for merge
3988 changesets, as it will only compare the merge changeset against
3988 changesets, as it will only compare the merge changeset against
3989 its first parent. Also, only files different from BOTH parents
3989 its first parent. Also, only files different from BOTH parents
3990 will appear in files:.
3990 will appear in files:.
3991
3991
3992 .. note::
3992 .. note::
3993
3993
3994 for performance reasons, log FILE may omit duplicate changes
3994 for performance reasons, log FILE may omit duplicate changes
3995 made on branches and will not show deletions. To see all
3995 made on branches and will not show deletions. To see all
3996 changes including duplicates and deletions, use the --removed
3996 changes including duplicates and deletions, use the --removed
3997 switch.
3997 switch.
3998
3998
3999 .. container:: verbose
3999 .. container:: verbose
4000
4000
4001 Some examples:
4001 Some examples:
4002
4002
4003 - changesets with full descriptions and file lists::
4003 - changesets with full descriptions and file lists::
4004
4004
4005 hg log -v
4005 hg log -v
4006
4006
4007 - changesets ancestral to the working directory::
4007 - changesets ancestral to the working directory::
4008
4008
4009 hg log -f
4009 hg log -f
4010
4010
4011 - last 10 commits on the current branch::
4011 - last 10 commits on the current branch::
4012
4012
4013 hg log -l 10 -b .
4013 hg log -l 10 -b .
4014
4014
4015 - changesets showing all modifications of a file, including removals::
4015 - changesets showing all modifications of a file, including removals::
4016
4016
4017 hg log --removed file.c
4017 hg log --removed file.c
4018
4018
4019 - all changesets that touch a directory, with diffs, excluding merges::
4019 - all changesets that touch a directory, with diffs, excluding merges::
4020
4020
4021 hg log -Mp lib/
4021 hg log -Mp lib/
4022
4022
4023 - all revision numbers that match a keyword::
4023 - all revision numbers that match a keyword::
4024
4024
4025 hg log -k bug --template "{rev}\\n"
4025 hg log -k bug --template "{rev}\\n"
4026
4026
4027 - check if a given changeset is included is a tagged release::
4027 - check if a given changeset is included is a tagged release::
4028
4028
4029 hg log -r "a21ccf and ancestor(1.9)"
4029 hg log -r "a21ccf and ancestor(1.9)"
4030
4030
4031 - find all changesets by some user in a date range::
4031 - find all changesets by some user in a date range::
4032
4032
4033 hg log -k alice -d "may 2008 to jul 2008"
4033 hg log -k alice -d "may 2008 to jul 2008"
4034
4034
4035 - summary of all changesets after the last tag::
4035 - summary of all changesets after the last tag::
4036
4036
4037 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4037 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4038
4038
4039 See :hg:`help dates` for a list of formats valid for -d/--date.
4039 See :hg:`help dates` for a list of formats valid for -d/--date.
4040
4040
4041 See :hg:`help revisions` and :hg:`help revsets` for more about
4041 See :hg:`help revisions` and :hg:`help revsets` for more about
4042 specifying revisions.
4042 specifying revisions.
4043
4043
4044 See :hg:`help templates` for more about pre-packaged styles and
4044 See :hg:`help templates` for more about pre-packaged styles and
4045 specifying custom templates.
4045 specifying custom templates.
4046
4046
4047 Returns 0 on success.
4047 Returns 0 on success.
4048 """
4048 """
4049 if opts.get('graph'):
4049 if opts.get('graph'):
4050 return cmdutil.graphlog(ui, repo, *pats, **opts)
4050 return cmdutil.graphlog(ui, repo, *pats, **opts)
4051
4051
4052 matchfn = scmutil.match(repo[None], pats, opts)
4052 matchfn = scmutil.match(repo[None], pats, opts)
4053 limit = cmdutil.loglimit(opts)
4053 limit = cmdutil.loglimit(opts)
4054 count = 0
4054 count = 0
4055
4055
4056 getrenamed, endrev = None, None
4056 getrenamed, endrev = None, None
4057 if opts.get('copies'):
4057 if opts.get('copies'):
4058 if opts.get('rev'):
4058 if opts.get('rev'):
4059 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4059 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4060 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4060 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4061
4061
4062 df = False
4062 df = False
4063 if opts.get("date"):
4063 if opts.get("date"):
4064 df = util.matchdate(opts["date"])
4064 df = util.matchdate(opts["date"])
4065
4065
4066 branches = opts.get('branch', []) + opts.get('only_branch', [])
4066 branches = opts.get('branch', []) + opts.get('only_branch', [])
4067 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4067 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4068
4068
4069 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4069 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4070 def prep(ctx, fns):
4070 def prep(ctx, fns):
4071 rev = ctx.rev()
4071 rev = ctx.rev()
4072 parents = [p for p in repo.changelog.parentrevs(rev)
4072 parents = [p for p in repo.changelog.parentrevs(rev)
4073 if p != nullrev]
4073 if p != nullrev]
4074 if opts.get('no_merges') and len(parents) == 2:
4074 if opts.get('no_merges') and len(parents) == 2:
4075 return
4075 return
4076 if opts.get('only_merges') and len(parents) != 2:
4076 if opts.get('only_merges') and len(parents) != 2:
4077 return
4077 return
4078 if opts.get('branch') and ctx.branch() not in opts['branch']:
4078 if opts.get('branch') and ctx.branch() not in opts['branch']:
4079 return
4079 return
4080 if df and not df(ctx.date()[0]):
4080 if df and not df(ctx.date()[0]):
4081 return
4081 return
4082
4082
4083 lower = encoding.lower
4083 lower = encoding.lower
4084 if opts.get('user'):
4084 if opts.get('user'):
4085 luser = lower(ctx.user())
4085 luser = lower(ctx.user())
4086 for k in [lower(x) for x in opts['user']]:
4086 for k in [lower(x) for x in opts['user']]:
4087 if (k in luser):
4087 if (k in luser):
4088 break
4088 break
4089 else:
4089 else:
4090 return
4090 return
4091 if opts.get('keyword'):
4091 if opts.get('keyword'):
4092 luser = lower(ctx.user())
4092 luser = lower(ctx.user())
4093 ldesc = lower(ctx.description())
4093 ldesc = lower(ctx.description())
4094 lfiles = lower(" ".join(ctx.files()))
4094 lfiles = lower(" ".join(ctx.files()))
4095 for k in [lower(x) for x in opts['keyword']]:
4095 for k in [lower(x) for x in opts['keyword']]:
4096 if (k in luser or k in ldesc or k in lfiles):
4096 if (k in luser or k in ldesc or k in lfiles):
4097 break
4097 break
4098 else:
4098 else:
4099 return
4099 return
4100
4100
4101 copies = None
4101 copies = None
4102 if getrenamed is not None and rev:
4102 if getrenamed is not None and rev:
4103 copies = []
4103 copies = []
4104 for fn in ctx.files():
4104 for fn in ctx.files():
4105 rename = getrenamed(fn, rev)
4105 rename = getrenamed(fn, rev)
4106 if rename:
4106 if rename:
4107 copies.append((fn, rename[0]))
4107 copies.append((fn, rename[0]))
4108
4108
4109 revmatchfn = None
4109 revmatchfn = None
4110 if opts.get('patch') or opts.get('stat'):
4110 if opts.get('patch') or opts.get('stat'):
4111 if opts.get('follow') or opts.get('follow_first'):
4111 if opts.get('follow') or opts.get('follow_first'):
4112 # note: this might be wrong when following through merges
4112 # note: this might be wrong when following through merges
4113 revmatchfn = scmutil.match(repo[None], fns, default='path')
4113 revmatchfn = scmutil.match(repo[None], fns, default='path')
4114 else:
4114 else:
4115 revmatchfn = matchfn
4115 revmatchfn = matchfn
4116
4116
4117 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4117 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4118
4118
4119 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4119 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4120 if displayer.flush(ctx.rev()):
4120 if displayer.flush(ctx.rev()):
4121 count += 1
4121 count += 1
4122 if count == limit:
4122 if count == limit:
4123 break
4123 break
4124 displayer.close()
4124 displayer.close()
4125
4125
4126 @command('manifest',
4126 @command('manifest',
4127 [('r', 'rev', '', _('revision to display'), _('REV')),
4127 [('r', 'rev', '', _('revision to display'), _('REV')),
4128 ('', 'all', False, _("list files from all revisions"))],
4128 ('', 'all', False, _("list files from all revisions"))],
4129 _('[-r REV]'))
4129 _('[-r REV]'))
4130 def manifest(ui, repo, node=None, rev=None, **opts):
4130 def manifest(ui, repo, node=None, rev=None, **opts):
4131 """output the current or given revision of the project manifest
4131 """output the current or given revision of the project manifest
4132
4132
4133 Print a list of version controlled files for the given revision.
4133 Print a list of version controlled files for the given revision.
4134 If no revision is given, the first parent of the working directory
4134 If no revision is given, the first parent of the working directory
4135 is used, or the null revision if no revision is checked out.
4135 is used, or the null revision if no revision is checked out.
4136
4136
4137 With -v, print file permissions, symlink and executable bits.
4137 With -v, print file permissions, symlink and executable bits.
4138 With --debug, print file revision hashes.
4138 With --debug, print file revision hashes.
4139
4139
4140 If option --all is specified, the list of all files from all revisions
4140 If option --all is specified, the list of all files from all revisions
4141 is printed. This includes deleted and renamed files.
4141 is printed. This includes deleted and renamed files.
4142
4142
4143 Returns 0 on success.
4143 Returns 0 on success.
4144 """
4144 """
4145
4145
4146 fm = ui.formatter('manifest', opts)
4146 fm = ui.formatter('manifest', opts)
4147
4147
4148 if opts.get('all'):
4148 if opts.get('all'):
4149 if rev or node:
4149 if rev or node:
4150 raise util.Abort(_("can't specify a revision with --all"))
4150 raise util.Abort(_("can't specify a revision with --all"))
4151
4151
4152 res = []
4152 res = []
4153 prefix = "data/"
4153 prefix = "data/"
4154 suffix = ".i"
4154 suffix = ".i"
4155 plen = len(prefix)
4155 plen = len(prefix)
4156 slen = len(suffix)
4156 slen = len(suffix)
4157 lock = repo.lock()
4157 lock = repo.lock()
4158 try:
4158 try:
4159 for fn, b, size in repo.store.datafiles():
4159 for fn, b, size in repo.store.datafiles():
4160 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4160 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4161 res.append(fn[plen:-slen])
4161 res.append(fn[plen:-slen])
4162 finally:
4162 finally:
4163 lock.release()
4163 lock.release()
4164 for f in res:
4164 for f in res:
4165 fm.startitem()
4165 fm.startitem()
4166 fm.write("path", '%s\n', f)
4166 fm.write("path", '%s\n', f)
4167 fm.end()
4167 fm.end()
4168 return
4168 return
4169
4169
4170 if rev and node:
4170 if rev and node:
4171 raise util.Abort(_("please specify just one revision"))
4171 raise util.Abort(_("please specify just one revision"))
4172
4172
4173 if not node:
4173 if not node:
4174 node = rev
4174 node = rev
4175
4175
4176 char = {'l': '@', 'x': '*', '': ''}
4176 char = {'l': '@', 'x': '*', '': ''}
4177 mode = {'l': '644', 'x': '755', '': '644'}
4177 mode = {'l': '644', 'x': '755', '': '644'}
4178 ctx = scmutil.revsingle(repo, node)
4178 ctx = scmutil.revsingle(repo, node)
4179 mf = ctx.manifest()
4179 mf = ctx.manifest()
4180 for f in ctx:
4180 for f in ctx:
4181 fm.startitem()
4181 fm.startitem()
4182 fl = ctx[f].flags()
4182 fl = ctx[f].flags()
4183 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4183 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4184 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4184 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4185 fm.write('path', '%s\n', f)
4185 fm.write('path', '%s\n', f)
4186 fm.end()
4186 fm.end()
4187
4187
4188 @command('^merge',
4188 @command('^merge',
4189 [('f', 'force', None,
4189 [('f', 'force', None,
4190 _('force a merge including outstanding changes (DEPRECATED)')),
4190 _('force a merge including outstanding changes (DEPRECATED)')),
4191 ('r', 'rev', '', _('revision to merge'), _('REV')),
4191 ('r', 'rev', '', _('revision to merge'), _('REV')),
4192 ('P', 'preview', None,
4192 ('P', 'preview', None,
4193 _('review revisions to merge (no merge is performed)'))
4193 _('review revisions to merge (no merge is performed)'))
4194 ] + mergetoolopts,
4194 ] + mergetoolopts,
4195 _('[-P] [-f] [[-r] REV]'))
4195 _('[-P] [-f] [[-r] REV]'))
4196 def merge(ui, repo, node=None, **opts):
4196 def merge(ui, repo, node=None, **opts):
4197 """merge working directory with another revision
4197 """merge working directory with another revision
4198
4198
4199 The current working directory is updated with all changes made in
4199 The current working directory is updated with all changes made in
4200 the requested revision since the last common predecessor revision.
4200 the requested revision since the last common predecessor revision.
4201
4201
4202 Files that changed between either parent are marked as changed for
4202 Files that changed between either parent are marked as changed for
4203 the next commit and a commit must be performed before any further
4203 the next commit and a commit must be performed before any further
4204 updates to the repository are allowed. The next commit will have
4204 updates to the repository are allowed. The next commit will have
4205 two parents.
4205 two parents.
4206
4206
4207 ``--tool`` can be used to specify the merge tool used for file
4207 ``--tool`` can be used to specify the merge tool used for file
4208 merges. It overrides the HGMERGE environment variable and your
4208 merges. It overrides the HGMERGE environment variable and your
4209 configuration files. See :hg:`help merge-tools` for options.
4209 configuration files. See :hg:`help merge-tools` for options.
4210
4210
4211 If no revision is specified, the working directory's parent is a
4211 If no revision is specified, the working directory's parent is a
4212 head revision, and the current branch contains exactly one other
4212 head revision, and the current branch contains exactly one other
4213 head, the other head is merged with by default. Otherwise, an
4213 head, the other head is merged with by default. Otherwise, an
4214 explicit revision with which to merge with must be provided.
4214 explicit revision with which to merge with must be provided.
4215
4215
4216 :hg:`resolve` must be used to resolve unresolved files.
4216 :hg:`resolve` must be used to resolve unresolved files.
4217
4217
4218 To undo an uncommitted merge, use :hg:`update --clean .` which
4218 To undo an uncommitted merge, use :hg:`update --clean .` which
4219 will check out a clean copy of the original merge parent, losing
4219 will check out a clean copy of the original merge parent, losing
4220 all changes.
4220 all changes.
4221
4221
4222 Returns 0 on success, 1 if there are unresolved files.
4222 Returns 0 on success, 1 if there are unresolved files.
4223 """
4223 """
4224
4224
4225 if opts.get('rev') and node:
4225 if opts.get('rev') and node:
4226 raise util.Abort(_("please specify just one revision"))
4226 raise util.Abort(_("please specify just one revision"))
4227 if not node:
4227 if not node:
4228 node = opts.get('rev')
4228 node = opts.get('rev')
4229
4229
4230 if node:
4230 if node:
4231 node = scmutil.revsingle(repo, node).node()
4231 node = scmutil.revsingle(repo, node).node()
4232
4232
4233 if not node and repo._bookmarkcurrent:
4233 if not node and repo._bookmarkcurrent:
4234 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4234 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4235 curhead = repo[repo._bookmarkcurrent].node()
4235 curhead = repo[repo._bookmarkcurrent].node()
4236 if len(bmheads) == 2:
4236 if len(bmheads) == 2:
4237 if curhead == bmheads[0]:
4237 if curhead == bmheads[0]:
4238 node = bmheads[1]
4238 node = bmheads[1]
4239 else:
4239 else:
4240 node = bmheads[0]
4240 node = bmheads[0]
4241 elif len(bmheads) > 2:
4241 elif len(bmheads) > 2:
4242 raise util.Abort(_("multiple matching bookmarks to merge - "
4242 raise util.Abort(_("multiple matching bookmarks to merge - "
4243 "please merge with an explicit rev or bookmark"),
4243 "please merge with an explicit rev or bookmark"),
4244 hint=_("run 'hg heads' to see all heads"))
4244 hint=_("run 'hg heads' to see all heads"))
4245 elif len(bmheads) <= 1:
4245 elif len(bmheads) <= 1:
4246 raise util.Abort(_("no matching bookmark to merge - "
4246 raise util.Abort(_("no matching bookmark to merge - "
4247 "please merge with an explicit rev or bookmark"),
4247 "please merge with an explicit rev or bookmark"),
4248 hint=_("run 'hg heads' to see all heads"))
4248 hint=_("run 'hg heads' to see all heads"))
4249
4249
4250 if not node and not repo._bookmarkcurrent:
4250 if not node and not repo._bookmarkcurrent:
4251 branch = repo[None].branch()
4251 branch = repo[None].branch()
4252 bheads = repo.branchheads(branch)
4252 bheads = repo.branchheads(branch)
4253 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4253 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4254
4254
4255 if len(nbhs) > 2:
4255 if len(nbhs) > 2:
4256 raise util.Abort(_("branch '%s' has %d heads - "
4256 raise util.Abort(_("branch '%s' has %d heads - "
4257 "please merge with an explicit rev")
4257 "please merge with an explicit rev")
4258 % (branch, len(bheads)),
4258 % (branch, len(bheads)),
4259 hint=_("run 'hg heads .' to see heads"))
4259 hint=_("run 'hg heads .' to see heads"))
4260
4260
4261 parent = repo.dirstate.p1()
4261 parent = repo.dirstate.p1()
4262 if len(nbhs) <= 1:
4262 if len(nbhs) <= 1:
4263 if len(bheads) > 1:
4263 if len(bheads) > 1:
4264 raise util.Abort(_("heads are bookmarked - "
4264 raise util.Abort(_("heads are bookmarked - "
4265 "please merge with an explicit rev"),
4265 "please merge with an explicit rev"),
4266 hint=_("run 'hg heads' to see all heads"))
4266 hint=_("run 'hg heads' to see all heads"))
4267 if len(repo.heads()) > 1:
4267 if len(repo.heads()) > 1:
4268 raise util.Abort(_("branch '%s' has one head - "
4268 raise util.Abort(_("branch '%s' has one head - "
4269 "please merge with an explicit rev")
4269 "please merge with an explicit rev")
4270 % branch,
4270 % branch,
4271 hint=_("run 'hg heads' to see all heads"))
4271 hint=_("run 'hg heads' to see all heads"))
4272 msg, hint = _('nothing to merge'), None
4272 msg, hint = _('nothing to merge'), None
4273 if parent != repo.lookup(branch):
4273 if parent != repo.lookup(branch):
4274 hint = _("use 'hg update' instead")
4274 hint = _("use 'hg update' instead")
4275 raise util.Abort(msg, hint=hint)
4275 raise util.Abort(msg, hint=hint)
4276
4276
4277 if parent not in bheads:
4277 if parent not in bheads:
4278 raise util.Abort(_('working directory not at a head revision'),
4278 raise util.Abort(_('working directory not at a head revision'),
4279 hint=_("use 'hg update' or merge with an "
4279 hint=_("use 'hg update' or merge with an "
4280 "explicit revision"))
4280 "explicit revision"))
4281 if parent == nbhs[0]:
4281 if parent == nbhs[0]:
4282 node = nbhs[-1]
4282 node = nbhs[-1]
4283 else:
4283 else:
4284 node = nbhs[0]
4284 node = nbhs[0]
4285
4285
4286 if opts.get('preview'):
4286 if opts.get('preview'):
4287 # find nodes that are ancestors of p2 but not of p1
4287 # find nodes that are ancestors of p2 but not of p1
4288 p1 = repo.lookup('.')
4288 p1 = repo.lookup('.')
4289 p2 = repo.lookup(node)
4289 p2 = repo.lookup(node)
4290 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4290 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4291
4291
4292 displayer = cmdutil.show_changeset(ui, repo, opts)
4292 displayer = cmdutil.show_changeset(ui, repo, opts)
4293 for node in nodes:
4293 for node in nodes:
4294 displayer.show(repo[node])
4294 displayer.show(repo[node])
4295 displayer.close()
4295 displayer.close()
4296 return 0
4296 return 0
4297
4297
4298 try:
4298 try:
4299 # ui.forcemerge is an internal variable, do not document
4299 # ui.forcemerge is an internal variable, do not document
4300 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4300 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4301 return hg.merge(repo, node, force=opts.get('force'))
4301 return hg.merge(repo, node, force=opts.get('force'))
4302 finally:
4302 finally:
4303 ui.setconfig('ui', 'forcemerge', '')
4303 ui.setconfig('ui', 'forcemerge', '')
4304
4304
4305 @command('outgoing|out',
4305 @command('outgoing|out',
4306 [('f', 'force', None, _('run even when the destination is unrelated')),
4306 [('f', 'force', None, _('run even when the destination is unrelated')),
4307 ('r', 'rev', [],
4307 ('r', 'rev', [],
4308 _('a changeset intended to be included in the destination'), _('REV')),
4308 _('a changeset intended to be included in the destination'), _('REV')),
4309 ('n', 'newest-first', None, _('show newest record first')),
4309 ('n', 'newest-first', None, _('show newest record first')),
4310 ('B', 'bookmarks', False, _('compare bookmarks')),
4310 ('B', 'bookmarks', False, _('compare bookmarks')),
4311 ('b', 'branch', [], _('a specific branch you would like to push'),
4311 ('b', 'branch', [], _('a specific branch you would like to push'),
4312 _('BRANCH')),
4312 _('BRANCH')),
4313 ] + logopts + remoteopts + subrepoopts,
4313 ] + logopts + remoteopts + subrepoopts,
4314 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4314 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4315 def outgoing(ui, repo, dest=None, **opts):
4315 def outgoing(ui, repo, dest=None, **opts):
4316 """show changesets not found in the destination
4316 """show changesets not found in the destination
4317
4317
4318 Show changesets not found in the specified destination repository
4318 Show changesets not found in the specified destination repository
4319 or the default push location. These are the changesets that would
4319 or the default push location. These are the changesets that would
4320 be pushed if a push was requested.
4320 be pushed if a push was requested.
4321
4321
4322 See pull for details of valid destination formats.
4322 See pull for details of valid destination formats.
4323
4323
4324 Returns 0 if there are outgoing changes, 1 otherwise.
4324 Returns 0 if there are outgoing changes, 1 otherwise.
4325 """
4325 """
4326 if opts.get('graph'):
4326 if opts.get('graph'):
4327 cmdutil.checkunsupportedgraphflags([], opts)
4327 cmdutil.checkunsupportedgraphflags([], opts)
4328 o = hg._outgoing(ui, repo, dest, opts)
4328 o = hg._outgoing(ui, repo, dest, opts)
4329 if o is None:
4329 if o is None:
4330 return
4330 return
4331
4331
4332 revdag = cmdutil.graphrevs(repo, o, opts)
4332 revdag = cmdutil.graphrevs(repo, o, opts)
4333 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4333 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4334 showparents = [ctx.node() for ctx in repo[None].parents()]
4334 showparents = [ctx.node() for ctx in repo[None].parents()]
4335 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4335 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4336 graphmod.asciiedges)
4336 graphmod.asciiedges)
4337 return 0
4337 return 0
4338
4338
4339 if opts.get('bookmarks'):
4339 if opts.get('bookmarks'):
4340 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4340 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4341 dest, branches = hg.parseurl(dest, opts.get('branch'))
4341 dest, branches = hg.parseurl(dest, opts.get('branch'))
4342 other = hg.peer(repo, opts, dest)
4342 other = hg.peer(repo, opts, dest)
4343 if 'bookmarks' not in other.listkeys('namespaces'):
4343 if 'bookmarks' not in other.listkeys('namespaces'):
4344 ui.warn(_("remote doesn't support bookmarks\n"))
4344 ui.warn(_("remote doesn't support bookmarks\n"))
4345 return 0
4345 return 0
4346 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4346 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4347 return bookmarks.diff(ui, other, repo)
4347 return bookmarks.diff(ui, other, repo)
4348
4348
4349 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4349 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4350 try:
4350 try:
4351 return hg.outgoing(ui, repo, dest, opts)
4351 return hg.outgoing(ui, repo, dest, opts)
4352 finally:
4352 finally:
4353 del repo._subtoppath
4353 del repo._subtoppath
4354
4354
4355 @command('parents',
4355 @command('parents',
4356 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4356 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4357 ] + templateopts,
4357 ] + templateopts,
4358 _('[-r REV] [FILE]'))
4358 _('[-r REV] [FILE]'))
4359 def parents(ui, repo, file_=None, **opts):
4359 def parents(ui, repo, file_=None, **opts):
4360 """show the parents of the working directory or revision
4360 """show the parents of the working directory or revision
4361
4361
4362 Print the working directory's parent revisions. If a revision is
4362 Print the working directory's parent revisions. If a revision is
4363 given via -r/--rev, the parent of that revision will be printed.
4363 given via -r/--rev, the parent of that revision will be printed.
4364 If a file argument is given, the revision in which the file was
4364 If a file argument is given, the revision in which the file was
4365 last changed (before the working directory revision or the
4365 last changed (before the working directory revision or the
4366 argument to --rev if given) is printed.
4366 argument to --rev if given) is printed.
4367
4367
4368 Returns 0 on success.
4368 Returns 0 on success.
4369 """
4369 """
4370
4370
4371 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4371 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4372
4372
4373 if file_:
4373 if file_:
4374 m = scmutil.match(ctx, (file_,), opts)
4374 m = scmutil.match(ctx, (file_,), opts)
4375 if m.anypats() or len(m.files()) != 1:
4375 if m.anypats() or len(m.files()) != 1:
4376 raise util.Abort(_('can only specify an explicit filename'))
4376 raise util.Abort(_('can only specify an explicit filename'))
4377 file_ = m.files()[0]
4377 file_ = m.files()[0]
4378 filenodes = []
4378 filenodes = []
4379 for cp in ctx.parents():
4379 for cp in ctx.parents():
4380 if not cp:
4380 if not cp:
4381 continue
4381 continue
4382 try:
4382 try:
4383 filenodes.append(cp.filenode(file_))
4383 filenodes.append(cp.filenode(file_))
4384 except error.LookupError:
4384 except error.LookupError:
4385 pass
4385 pass
4386 if not filenodes:
4386 if not filenodes:
4387 raise util.Abort(_("'%s' not found in manifest!") % file_)
4387 raise util.Abort(_("'%s' not found in manifest!") % file_)
4388 p = []
4388 p = []
4389 for fn in filenodes:
4389 for fn in filenodes:
4390 fctx = repo.filectx(file_, fileid=fn)
4390 fctx = repo.filectx(file_, fileid=fn)
4391 p.append(fctx.node())
4391 p.append(fctx.node())
4392 else:
4392 else:
4393 p = [cp.node() for cp in ctx.parents()]
4393 p = [cp.node() for cp in ctx.parents()]
4394
4394
4395 displayer = cmdutil.show_changeset(ui, repo, opts)
4395 displayer = cmdutil.show_changeset(ui, repo, opts)
4396 for n in p:
4396 for n in p:
4397 if n != nullid:
4397 if n != nullid:
4398 displayer.show(repo[n])
4398 displayer.show(repo[n])
4399 displayer.close()
4399 displayer.close()
4400
4400
4401 @command('paths', [], _('[NAME]'))
4401 @command('paths', [], _('[NAME]'))
4402 def paths(ui, repo, search=None):
4402 def paths(ui, repo, search=None):
4403 """show aliases for remote repositories
4403 """show aliases for remote repositories
4404
4404
4405 Show definition of symbolic path name NAME. If no name is given,
4405 Show definition of symbolic path name NAME. If no name is given,
4406 show definition of all available names.
4406 show definition of all available names.
4407
4407
4408 Option -q/--quiet suppresses all output when searching for NAME
4408 Option -q/--quiet suppresses all output when searching for NAME
4409 and shows only the path names when listing all definitions.
4409 and shows only the path names when listing all definitions.
4410
4410
4411 Path names are defined in the [paths] section of your
4411 Path names are defined in the [paths] section of your
4412 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4412 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4413 repository, ``.hg/hgrc`` is used, too.
4413 repository, ``.hg/hgrc`` is used, too.
4414
4414
4415 The path names ``default`` and ``default-push`` have a special
4415 The path names ``default`` and ``default-push`` have a special
4416 meaning. When performing a push or pull operation, they are used
4416 meaning. When performing a push or pull operation, they are used
4417 as fallbacks if no location is specified on the command-line.
4417 as fallbacks if no location is specified on the command-line.
4418 When ``default-push`` is set, it will be used for push and
4418 When ``default-push`` is set, it will be used for push and
4419 ``default`` will be used for pull; otherwise ``default`` is used
4419 ``default`` will be used for pull; otherwise ``default`` is used
4420 as the fallback for both. When cloning a repository, the clone
4420 as the fallback for both. When cloning a repository, the clone
4421 source is written as ``default`` in ``.hg/hgrc``. Note that
4421 source is written as ``default`` in ``.hg/hgrc``. Note that
4422 ``default`` and ``default-push`` apply to all inbound (e.g.
4422 ``default`` and ``default-push`` apply to all inbound (e.g.
4423 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4423 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4424 :hg:`bundle`) operations.
4424 :hg:`bundle`) operations.
4425
4425
4426 See :hg:`help urls` for more information.
4426 See :hg:`help urls` for more information.
4427
4427
4428 Returns 0 on success.
4428 Returns 0 on success.
4429 """
4429 """
4430 if search:
4430 if search:
4431 for name, path in ui.configitems("paths"):
4431 for name, path in ui.configitems("paths"):
4432 if name == search:
4432 if name == search:
4433 ui.status("%s\n" % util.hidepassword(path))
4433 ui.status("%s\n" % util.hidepassword(path))
4434 return
4434 return
4435 if not ui.quiet:
4435 if not ui.quiet:
4436 ui.warn(_("not found!\n"))
4436 ui.warn(_("not found!\n"))
4437 return 1
4437 return 1
4438 else:
4438 else:
4439 for name, path in ui.configitems("paths"):
4439 for name, path in ui.configitems("paths"):
4440 if ui.quiet:
4440 if ui.quiet:
4441 ui.write("%s\n" % name)
4441 ui.write("%s\n" % name)
4442 else:
4442 else:
4443 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4443 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4444
4444
4445 @command('phase',
4445 @command('phase',
4446 [('p', 'public', False, _('set changeset phase to public')),
4446 [('p', 'public', False, _('set changeset phase to public')),
4447 ('d', 'draft', False, _('set changeset phase to draft')),
4447 ('d', 'draft', False, _('set changeset phase to draft')),
4448 ('s', 'secret', False, _('set changeset phase to secret')),
4448 ('s', 'secret', False, _('set changeset phase to secret')),
4449 ('f', 'force', False, _('allow to move boundary backward')),
4449 ('f', 'force', False, _('allow to move boundary backward')),
4450 ('r', 'rev', [], _('target revision'), _('REV')),
4450 ('r', 'rev', [], _('target revision'), _('REV')),
4451 ],
4451 ],
4452 _('[-p|-d|-s] [-f] [-r] REV...'))
4452 _('[-p|-d|-s] [-f] [-r] REV...'))
4453 def phase(ui, repo, *revs, **opts):
4453 def phase(ui, repo, *revs, **opts):
4454 """set or show the current phase name
4454 """set or show the current phase name
4455
4455
4456 With no argument, show the phase name of specified revisions.
4456 With no argument, show the phase name of specified revisions.
4457
4457
4458 With one of -p/--public, -d/--draft or -s/--secret, change the
4458 With one of -p/--public, -d/--draft or -s/--secret, change the
4459 phase value of the specified revisions.
4459 phase value of the specified revisions.
4460
4460
4461 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4461 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4462 lower phase to an higher phase. Phases are ordered as follows::
4462 lower phase to an higher phase. Phases are ordered as follows::
4463
4463
4464 public < draft < secret
4464 public < draft < secret
4465
4465
4466 Return 0 on success, 1 if no phases were changed or some could not
4466 Return 0 on success, 1 if no phases were changed or some could not
4467 be changed.
4467 be changed.
4468 """
4468 """
4469 # search for a unique phase argument
4469 # search for a unique phase argument
4470 targetphase = None
4470 targetphase = None
4471 for idx, name in enumerate(phases.phasenames):
4471 for idx, name in enumerate(phases.phasenames):
4472 if opts[name]:
4472 if opts[name]:
4473 if targetphase is not None:
4473 if targetphase is not None:
4474 raise util.Abort(_('only one phase can be specified'))
4474 raise util.Abort(_('only one phase can be specified'))
4475 targetphase = idx
4475 targetphase = idx
4476
4476
4477 # look for specified revision
4477 # look for specified revision
4478 revs = list(revs)
4478 revs = list(revs)
4479 revs.extend(opts['rev'])
4479 revs.extend(opts['rev'])
4480 if not revs:
4480 if not revs:
4481 raise util.Abort(_('no revisions specified'))
4481 raise util.Abort(_('no revisions specified'))
4482
4482
4483 revs = scmutil.revrange(repo, revs)
4483 revs = scmutil.revrange(repo, revs)
4484
4484
4485 lock = None
4485 lock = None
4486 ret = 0
4486 ret = 0
4487 if targetphase is None:
4487 if targetphase is None:
4488 # display
4488 # display
4489 for r in revs:
4489 for r in revs:
4490 ctx = repo[r]
4490 ctx = repo[r]
4491 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4491 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4492 else:
4492 else:
4493 lock = repo.lock()
4493 lock = repo.lock()
4494 try:
4494 try:
4495 # set phase
4495 # set phase
4496 if not revs:
4496 if not revs:
4497 raise util.Abort(_('empty revision set'))
4497 raise util.Abort(_('empty revision set'))
4498 nodes = [repo[r].node() for r in revs]
4498 nodes = [repo[r].node() for r in revs]
4499 olddata = repo._phasecache.getphaserevs(repo)[:]
4499 olddata = repo._phasecache.getphaserevs(repo)[:]
4500 phases.advanceboundary(repo, targetphase, nodes)
4500 phases.advanceboundary(repo, targetphase, nodes)
4501 if opts['force']:
4501 if opts['force']:
4502 phases.retractboundary(repo, targetphase, nodes)
4502 phases.retractboundary(repo, targetphase, nodes)
4503 finally:
4503 finally:
4504 lock.release()
4504 lock.release()
4505 # moving revision from public to draft may hide them
4505 # moving revision from public to draft may hide them
4506 # We have to check result on an unfiltered repository
4506 # We have to check result on an unfiltered repository
4507 unfi = repo.unfiltered()
4507 unfi = repo.unfiltered()
4508 newdata = repo._phasecache.getphaserevs(unfi)
4508 newdata = repo._phasecache.getphaserevs(unfi)
4509 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4509 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4510 cl = unfi.changelog
4510 cl = unfi.changelog
4511 rejected = [n for n in nodes
4511 rejected = [n for n in nodes
4512 if newdata[cl.rev(n)] < targetphase]
4512 if newdata[cl.rev(n)] < targetphase]
4513 if rejected:
4513 if rejected:
4514 ui.warn(_('cannot move %i changesets to a higher '
4514 ui.warn(_('cannot move %i changesets to a higher '
4515 'phase, use --force\n') % len(rejected))
4515 'phase, use --force\n') % len(rejected))
4516 ret = 1
4516 ret = 1
4517 if changes:
4517 if changes:
4518 msg = _('phase changed for %i changesets\n') % changes
4518 msg = _('phase changed for %i changesets\n') % changes
4519 if ret:
4519 if ret:
4520 ui.status(msg)
4520 ui.status(msg)
4521 else:
4521 else:
4522 ui.note(msg)
4522 ui.note(msg)
4523 else:
4523 else:
4524 ui.warn(_('no phases changed\n'))
4524 ui.warn(_('no phases changed\n'))
4525 ret = 1
4525 ret = 1
4526 return ret
4526 return ret
4527
4527
4528 def postincoming(ui, repo, modheads, optupdate, checkout):
4528 def postincoming(ui, repo, modheads, optupdate, checkout):
4529 if modheads == 0:
4529 if modheads == 0:
4530 return
4530 return
4531 if optupdate:
4531 if optupdate:
4532 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4532 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4533 try:
4533 try:
4534 ret = hg.update(repo, checkout)
4534 ret = hg.update(repo, checkout)
4535 except util.Abort, inst:
4535 except util.Abort, inst:
4536 ui.warn(_("not updating: %s\n") % str(inst))
4536 ui.warn(_("not updating: %s\n") % str(inst))
4537 if inst.hint:
4537 if inst.hint:
4538 ui.warn(_("(%s)\n") % inst.hint)
4538 ui.warn(_("(%s)\n") % inst.hint)
4539 return 0
4539 return 0
4540 if not ret and not checkout:
4540 if not ret and not checkout:
4541 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4541 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4542 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4542 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4543 return ret
4543 return ret
4544 if modheads > 1:
4544 if modheads > 1:
4545 currentbranchheads = len(repo.branchheads())
4545 currentbranchheads = len(repo.branchheads())
4546 if currentbranchheads == modheads:
4546 if currentbranchheads == modheads:
4547 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4547 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4548 elif currentbranchheads > 1:
4548 elif currentbranchheads > 1:
4549 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4549 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4550 "merge)\n"))
4550 "merge)\n"))
4551 else:
4551 else:
4552 ui.status(_("(run 'hg heads' to see heads)\n"))
4552 ui.status(_("(run 'hg heads' to see heads)\n"))
4553 else:
4553 else:
4554 ui.status(_("(run 'hg update' to get a working copy)\n"))
4554 ui.status(_("(run 'hg update' to get a working copy)\n"))
4555
4555
4556 @command('^pull',
4556 @command('^pull',
4557 [('u', 'update', None,
4557 [('u', 'update', None,
4558 _('update to new branch head if changesets were pulled')),
4558 _('update to new branch head if changesets were pulled')),
4559 ('f', 'force', None, _('run even when remote repository is unrelated')),
4559 ('f', 'force', None, _('run even when remote repository is unrelated')),
4560 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4560 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4561 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4561 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4562 ('b', 'branch', [], _('a specific branch you would like to pull'),
4562 ('b', 'branch', [], _('a specific branch you would like to pull'),
4563 _('BRANCH')),
4563 _('BRANCH')),
4564 ] + remoteopts,
4564 ] + remoteopts,
4565 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4565 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4566 def pull(ui, repo, source="default", **opts):
4566 def pull(ui, repo, source="default", **opts):
4567 """pull changes from the specified source
4567 """pull changes from the specified source
4568
4568
4569 Pull changes from a remote repository to a local one.
4569 Pull changes from a remote repository to a local one.
4570
4570
4571 This finds all changes from the repository at the specified path
4571 This finds all changes from the repository at the specified path
4572 or URL and adds them to a local repository (the current one unless
4572 or URL and adds them to a local repository (the current one unless
4573 -R is specified). By default, this does not update the copy of the
4573 -R is specified). By default, this does not update the copy of the
4574 project in the working directory.
4574 project in the working directory.
4575
4575
4576 Use :hg:`incoming` if you want to see what would have been added
4576 Use :hg:`incoming` if you want to see what would have been added
4577 by a pull at the time you issued this command. If you then decide
4577 by a pull at the time you issued this command. If you then decide
4578 to add those changes to the repository, you should use :hg:`pull
4578 to add those changes to the repository, you should use :hg:`pull
4579 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4579 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4580
4580
4581 If SOURCE is omitted, the 'default' path will be used.
4581 If SOURCE is omitted, the 'default' path will be used.
4582 See :hg:`help urls` for more information.
4582 See :hg:`help urls` for more information.
4583
4583
4584 Returns 0 on success, 1 if an update had unresolved files.
4584 Returns 0 on success, 1 if an update had unresolved files.
4585 """
4585 """
4586 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4586 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4587 other = hg.peer(repo, opts, source)
4587 other = hg.peer(repo, opts, source)
4588 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4588 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4589 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4589 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4590
4590
4591 remotebookmarks = other.listkeys('bookmarks')
4591 remotebookmarks = other.listkeys('bookmarks')
4592
4592
4593 if opts.get('bookmark'):
4593 if opts.get('bookmark'):
4594 if not revs:
4594 if not revs:
4595 revs = []
4595 revs = []
4596 for b in opts['bookmark']:
4596 for b in opts['bookmark']:
4597 if b not in remotebookmarks:
4597 if b not in remotebookmarks:
4598 raise util.Abort(_('remote bookmark %s not found!') % b)
4598 raise util.Abort(_('remote bookmark %s not found!') % b)
4599 revs.append(remotebookmarks[b])
4599 revs.append(remotebookmarks[b])
4600
4600
4601 if revs:
4601 if revs:
4602 try:
4602 try:
4603 revs = [other.lookup(rev) for rev in revs]
4603 revs = [other.lookup(rev) for rev in revs]
4604 except error.CapabilityError:
4604 except error.CapabilityError:
4605 err = _("other repository doesn't support revision lookup, "
4605 err = _("other repository doesn't support revision lookup, "
4606 "so a rev cannot be specified.")
4606 "so a rev cannot be specified.")
4607 raise util.Abort(err)
4607 raise util.Abort(err)
4608
4608
4609 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4609 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4610 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4610 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4611 if checkout:
4611 if checkout:
4612 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4612 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4613 repo._subtoppath = source
4613 repo._subtoppath = source
4614 try:
4614 try:
4615 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4615 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4616
4616
4617 finally:
4617 finally:
4618 del repo._subtoppath
4618 del repo._subtoppath
4619
4619
4620 # update specified bookmarks
4620 # update specified bookmarks
4621 if opts.get('bookmark'):
4621 if opts.get('bookmark'):
4622 marks = repo._bookmarks
4622 marks = repo._bookmarks
4623 for b in opts['bookmark']:
4623 for b in opts['bookmark']:
4624 # explicit pull overrides local bookmark if any
4624 # explicit pull overrides local bookmark if any
4625 ui.status(_("importing bookmark %s\n") % b)
4625 ui.status(_("importing bookmark %s\n") % b)
4626 marks[b] = repo[remotebookmarks[b]].node()
4626 marks[b] = repo[remotebookmarks[b]].node()
4627 marks.write()
4627 marks.write()
4628
4628
4629 return ret
4629 return ret
4630
4630
4631 @command('^push',
4631 @command('^push',
4632 [('f', 'force', None, _('force push')),
4632 [('f', 'force', None, _('force push')),
4633 ('r', 'rev', [],
4633 ('r', 'rev', [],
4634 _('a changeset intended to be included in the destination'),
4634 _('a changeset intended to be included in the destination'),
4635 _('REV')),
4635 _('REV')),
4636 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4636 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4637 ('b', 'branch', [],
4637 ('b', 'branch', [],
4638 _('a specific branch you would like to push'), _('BRANCH')),
4638 _('a specific branch you would like to push'), _('BRANCH')),
4639 ('', 'new-branch', False, _('allow pushing a new branch')),
4639 ('', 'new-branch', False, _('allow pushing a new branch')),
4640 ] + remoteopts,
4640 ] + remoteopts,
4641 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4641 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4642 def push(ui, repo, dest=None, **opts):
4642 def push(ui, repo, dest=None, **opts):
4643 """push changes to the specified destination
4643 """push changes to the specified destination
4644
4644
4645 Push changesets from the local repository to the specified
4645 Push changesets from the local repository to the specified
4646 destination.
4646 destination.
4647
4647
4648 This operation is symmetrical to pull: it is identical to a pull
4648 This operation is symmetrical to pull: it is identical to a pull
4649 in the destination repository from the current one.
4649 in the destination repository from the current one.
4650
4650
4651 By default, push will not allow creation of new heads at the
4651 By default, push will not allow creation of new heads at the
4652 destination, since multiple heads would make it unclear which head
4652 destination, since multiple heads would make it unclear which head
4653 to use. In this situation, it is recommended to pull and merge
4653 to use. In this situation, it is recommended to pull and merge
4654 before pushing.
4654 before pushing.
4655
4655
4656 Use --new-branch if you want to allow push to create a new named
4656 Use --new-branch if you want to allow push to create a new named
4657 branch that is not present at the destination. This allows you to
4657 branch that is not present at the destination. This allows you to
4658 only create a new branch without forcing other changes.
4658 only create a new branch without forcing other changes.
4659
4659
4660 .. note::
4660 .. note::
4661
4661
4662 Extra care should be taken with the -f/--force option,
4662 Extra care should be taken with the -f/--force option,
4663 which will push all new heads on all branches, an action which will
4663 which will push all new heads on all branches, an action which will
4664 almost always cause confusion for collaborators.
4664 almost always cause confusion for collaborators.
4665
4665
4666 If -r/--rev is used, the specified revision and all its ancestors
4666 If -r/--rev is used, the specified revision and all its ancestors
4667 will be pushed to the remote repository.
4667 will be pushed to the remote repository.
4668
4668
4669 If -B/--bookmark is used, the specified bookmarked revision, its
4669 If -B/--bookmark is used, the specified bookmarked revision, its
4670 ancestors, and the bookmark will be pushed to the remote
4670 ancestors, and the bookmark will be pushed to the remote
4671 repository.
4671 repository.
4672
4672
4673 Please see :hg:`help urls` for important details about ``ssh://``
4673 Please see :hg:`help urls` for important details about ``ssh://``
4674 URLs. If DESTINATION is omitted, a default path will be used.
4674 URLs. If DESTINATION is omitted, a default path will be used.
4675
4675
4676 Returns 0 if push was successful, 1 if nothing to push.
4676 Returns 0 if push was successful, 1 if nothing to push.
4677 """
4677 """
4678
4678
4679 if opts.get('bookmark'):
4679 if opts.get('bookmark'):
4680 for b in opts['bookmark']:
4680 for b in opts['bookmark']:
4681 # translate -B options to -r so changesets get pushed
4681 # translate -B options to -r so changesets get pushed
4682 if b in repo._bookmarks:
4682 if b in repo._bookmarks:
4683 opts.setdefault('rev', []).append(b)
4683 opts.setdefault('rev', []).append(b)
4684 else:
4684 else:
4685 # if we try to push a deleted bookmark, translate it to null
4685 # if we try to push a deleted bookmark, translate it to null
4686 # this lets simultaneous -r, -b options continue working
4686 # this lets simultaneous -r, -b options continue working
4687 opts.setdefault('rev', []).append("null")
4687 opts.setdefault('rev', []).append("null")
4688
4688
4689 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4689 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4690 dest, branches = hg.parseurl(dest, opts.get('branch'))
4690 dest, branches = hg.parseurl(dest, opts.get('branch'))
4691 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4691 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4692 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4692 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4693 other = hg.peer(repo, opts, dest)
4693 other = hg.peer(repo, opts, dest)
4694 if revs:
4694 if revs:
4695 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4695 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4696
4696
4697 repo._subtoppath = dest
4697 repo._subtoppath = dest
4698 try:
4698 try:
4699 # push subrepos depth-first for coherent ordering
4699 # push subrepos depth-first for coherent ordering
4700 c = repo['']
4700 c = repo['']
4701 subs = c.substate # only repos that are committed
4701 subs = c.substate # only repos that are committed
4702 for s in sorted(subs):
4702 for s in sorted(subs):
4703 if c.sub(s).push(opts) == 0:
4703 if c.sub(s).push(opts) == 0:
4704 return False
4704 return False
4705 finally:
4705 finally:
4706 del repo._subtoppath
4706 del repo._subtoppath
4707 result = repo.push(other, opts.get('force'), revs=revs,
4707 result = repo.push(other, opts.get('force'), revs=revs,
4708 newbranch=opts.get('new_branch'))
4708 newbranch=opts.get('new_branch'))
4709
4709
4710 result = not result
4710 result = not result
4711
4711
4712 if opts.get('bookmark'):
4712 if opts.get('bookmark'):
4713 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4713 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4714 if bresult == 2:
4714 if bresult == 2:
4715 return 2
4715 return 2
4716 if not result and bresult:
4716 if not result and bresult:
4717 result = 2
4717 result = 2
4718
4718
4719 return result
4719 return result
4720
4720
4721 @command('recover', [])
4721 @command('recover', [])
4722 def recover(ui, repo):
4722 def recover(ui, repo):
4723 """roll back an interrupted transaction
4723 """roll back an interrupted transaction
4724
4724
4725 Recover from an interrupted commit or pull.
4725 Recover from an interrupted commit or pull.
4726
4726
4727 This command tries to fix the repository status after an
4727 This command tries to fix the repository status after an
4728 interrupted operation. It should only be necessary when Mercurial
4728 interrupted operation. It should only be necessary when Mercurial
4729 suggests it.
4729 suggests it.
4730
4730
4731 Returns 0 if successful, 1 if nothing to recover or verify fails.
4731 Returns 0 if successful, 1 if nothing to recover or verify fails.
4732 """
4732 """
4733 if repo.recover():
4733 if repo.recover():
4734 return hg.verify(repo)
4734 return hg.verify(repo)
4735 return 1
4735 return 1
4736
4736
4737 @command('^remove|rm',
4737 @command('^remove|rm',
4738 [('A', 'after', None, _('record delete for missing files')),
4738 [('A', 'after', None, _('record delete for missing files')),
4739 ('f', 'force', None,
4739 ('f', 'force', None,
4740 _('remove (and delete) file even if added or modified')),
4740 _('remove (and delete) file even if added or modified')),
4741 ] + walkopts,
4741 ] + walkopts,
4742 _('[OPTION]... FILE...'))
4742 _('[OPTION]... FILE...'))
4743 def remove(ui, repo, *pats, **opts):
4743 def remove(ui, repo, *pats, **opts):
4744 """remove the specified files on the next commit
4744 """remove the specified files on the next commit
4745
4745
4746 Schedule the indicated files for removal from the current branch.
4746 Schedule the indicated files for removal from the current branch.
4747
4747
4748 This command schedules the files to be removed at the next commit.
4748 This command schedules the files to be removed at the next commit.
4749 To undo a remove before that, see :hg:`revert`. To undo added
4749 To undo a remove before that, see :hg:`revert`. To undo added
4750 files, see :hg:`forget`.
4750 files, see :hg:`forget`.
4751
4751
4752 .. container:: verbose
4752 .. container:: verbose
4753
4753
4754 -A/--after can be used to remove only files that have already
4754 -A/--after can be used to remove only files that have already
4755 been deleted, -f/--force can be used to force deletion, and -Af
4755 been deleted, -f/--force can be used to force deletion, and -Af
4756 can be used to remove files from the next revision without
4756 can be used to remove files from the next revision without
4757 deleting them from the working directory.
4757 deleting them from the working directory.
4758
4758
4759 The following table details the behavior of remove for different
4759 The following table details the behavior of remove for different
4760 file states (columns) and option combinations (rows). The file
4760 file states (columns) and option combinations (rows). The file
4761 states are Added [A], Clean [C], Modified [M] and Missing [!]
4761 states are Added [A], Clean [C], Modified [M] and Missing [!]
4762 (as reported by :hg:`status`). The actions are Warn, Remove
4762 (as reported by :hg:`status`). The actions are Warn, Remove
4763 (from branch) and Delete (from disk):
4763 (from branch) and Delete (from disk):
4764
4764
4765 ========= == == == ==
4765 ========= == == == ==
4766 opt/state A C M !
4766 opt/state A C M !
4767 ========= == == == ==
4767 ========= == == == ==
4768 none W RD W R
4768 none W RD W R
4769 -f R RD RD R
4769 -f R RD RD R
4770 -A W W W R
4770 -A W W W R
4771 -Af R R R R
4771 -Af R R R R
4772 ========= == == == ==
4772 ========= == == == ==
4773
4773
4774 Note that remove never deletes files in Added [A] state from the
4774 Note that remove never deletes files in Added [A] state from the
4775 working directory, not even if option --force is specified.
4775 working directory, not even if option --force is specified.
4776
4776
4777 Returns 0 on success, 1 if any warnings encountered.
4777 Returns 0 on success, 1 if any warnings encountered.
4778 """
4778 """
4779
4779
4780 ret = 0
4780 ret = 0
4781 after, force = opts.get('after'), opts.get('force')
4781 after, force = opts.get('after'), opts.get('force')
4782 if not pats and not after:
4782 if not pats and not after:
4783 raise util.Abort(_('no files specified'))
4783 raise util.Abort(_('no files specified'))
4784
4784
4785 m = scmutil.match(repo[None], pats, opts)
4785 m = scmutil.match(repo[None], pats, opts)
4786 s = repo.status(match=m, clean=True)
4786 s = repo.status(match=m, clean=True)
4787 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4787 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4788
4788
4789 # warn about failure to delete explicit files/dirs
4789 # warn about failure to delete explicit files/dirs
4790 wctx = repo[None]
4790 wctx = repo[None]
4791 for f in m.files():
4791 for f in m.files():
4792 if f in repo.dirstate or f in wctx.dirs():
4792 if f in repo.dirstate or f in wctx.dirs():
4793 continue
4793 continue
4794 if os.path.exists(m.rel(f)):
4794 if os.path.exists(m.rel(f)):
4795 if os.path.isdir(m.rel(f)):
4795 if os.path.isdir(m.rel(f)):
4796 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4796 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4797 else:
4797 else:
4798 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4798 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4799 # missing files will generate a warning elsewhere
4799 # missing files will generate a warning elsewhere
4800 ret = 1
4800 ret = 1
4801
4801
4802 if force:
4802 if force:
4803 list = modified + deleted + clean + added
4803 list = modified + deleted + clean + added
4804 elif after:
4804 elif after:
4805 list = deleted
4805 list = deleted
4806 for f in modified + added + clean:
4806 for f in modified + added + clean:
4807 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4807 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4808 ret = 1
4808 ret = 1
4809 else:
4809 else:
4810 list = deleted + clean
4810 list = deleted + clean
4811 for f in modified:
4811 for f in modified:
4812 ui.warn(_('not removing %s: file is modified (use -f'
4812 ui.warn(_('not removing %s: file is modified (use -f'
4813 ' to force removal)\n') % m.rel(f))
4813 ' to force removal)\n') % m.rel(f))
4814 ret = 1
4814 ret = 1
4815 for f in added:
4815 for f in added:
4816 ui.warn(_('not removing %s: file has been marked for add'
4816 ui.warn(_('not removing %s: file has been marked for add'
4817 ' (use forget to undo)\n') % m.rel(f))
4817 ' (use forget to undo)\n') % m.rel(f))
4818 ret = 1
4818 ret = 1
4819
4819
4820 for f in sorted(list):
4820 for f in sorted(list):
4821 if ui.verbose or not m.exact(f):
4821 if ui.verbose or not m.exact(f):
4822 ui.status(_('removing %s\n') % m.rel(f))
4822 ui.status(_('removing %s\n') % m.rel(f))
4823
4823
4824 wlock = repo.wlock()
4824 wlock = repo.wlock()
4825 try:
4825 try:
4826 if not after:
4826 if not after:
4827 for f in list:
4827 for f in list:
4828 if f in added:
4828 if f in added:
4829 continue # we never unlink added files on remove
4829 continue # we never unlink added files on remove
4830 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4830 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4831 repo[None].forget(list)
4831 repo[None].forget(list)
4832 finally:
4832 finally:
4833 wlock.release()
4833 wlock.release()
4834
4834
4835 return ret
4835 return ret
4836
4836
4837 @command('rename|move|mv',
4837 @command('rename|move|mv',
4838 [('A', 'after', None, _('record a rename that has already occurred')),
4838 [('A', 'after', None, _('record a rename that has already occurred')),
4839 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4839 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4840 ] + walkopts + dryrunopts,
4840 ] + walkopts + dryrunopts,
4841 _('[OPTION]... SOURCE... DEST'))
4841 _('[OPTION]... SOURCE... DEST'))
4842 def rename(ui, repo, *pats, **opts):
4842 def rename(ui, repo, *pats, **opts):
4843 """rename files; equivalent of copy + remove
4843 """rename files; equivalent of copy + remove
4844
4844
4845 Mark dest as copies of sources; mark sources for deletion. If dest
4845 Mark dest as copies of sources; mark sources for deletion. If dest
4846 is a directory, copies are put in that directory. If dest is a
4846 is a directory, copies are put in that directory. If dest is a
4847 file, there can only be one source.
4847 file, there can only be one source.
4848
4848
4849 By default, this command copies the contents of files as they
4849 By default, this command copies the contents of files as they
4850 exist in the working directory. If invoked with -A/--after, the
4850 exist in the working directory. If invoked with -A/--after, the
4851 operation is recorded, but no copying is performed.
4851 operation is recorded, but no copying is performed.
4852
4852
4853 This command takes effect at the next commit. To undo a rename
4853 This command takes effect at the next commit. To undo a rename
4854 before that, see :hg:`revert`.
4854 before that, see :hg:`revert`.
4855
4855
4856 Returns 0 on success, 1 if errors are encountered.
4856 Returns 0 on success, 1 if errors are encountered.
4857 """
4857 """
4858 wlock = repo.wlock(False)
4858 wlock = repo.wlock(False)
4859 try:
4859 try:
4860 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4860 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4861 finally:
4861 finally:
4862 wlock.release()
4862 wlock.release()
4863
4863
4864 @command('resolve',
4864 @command('resolve',
4865 [('a', 'all', None, _('select all unresolved files')),
4865 [('a', 'all', None, _('select all unresolved files')),
4866 ('l', 'list', None, _('list state of files needing merge')),
4866 ('l', 'list', None, _('list state of files needing merge')),
4867 ('m', 'mark', None, _('mark files as resolved')),
4867 ('m', 'mark', None, _('mark files as resolved')),
4868 ('u', 'unmark', None, _('mark files as unresolved')),
4868 ('u', 'unmark', None, _('mark files as unresolved')),
4869 ('n', 'no-status', None, _('hide status prefix'))]
4869 ('n', 'no-status', None, _('hide status prefix'))]
4870 + mergetoolopts + walkopts,
4870 + mergetoolopts + walkopts,
4871 _('[OPTION]... [FILE]...'))
4871 _('[OPTION]... [FILE]...'))
4872 def resolve(ui, repo, *pats, **opts):
4872 def resolve(ui, repo, *pats, **opts):
4873 """redo merges or set/view the merge status of files
4873 """redo merges or set/view the merge status of files
4874
4874
4875 Merges with unresolved conflicts are often the result of
4875 Merges with unresolved conflicts are often the result of
4876 non-interactive merging using the ``internal:merge`` configuration
4876 non-interactive merging using the ``internal:merge`` configuration
4877 setting, or a command-line merge tool like ``diff3``. The resolve
4877 setting, or a command-line merge tool like ``diff3``. The resolve
4878 command is used to manage the files involved in a merge, after
4878 command is used to manage the files involved in a merge, after
4879 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4879 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4880 working directory must have two parents). See :hg:`help
4880 working directory must have two parents). See :hg:`help
4881 merge-tools` for information on configuring merge tools.
4881 merge-tools` for information on configuring merge tools.
4882
4882
4883 The resolve command can be used in the following ways:
4883 The resolve command can be used in the following ways:
4884
4884
4885 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4885 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4886 files, discarding any previous merge attempts. Re-merging is not
4886 files, discarding any previous merge attempts. Re-merging is not
4887 performed for files already marked as resolved. Use ``--all/-a``
4887 performed for files already marked as resolved. Use ``--all/-a``
4888 to select all unresolved files. ``--tool`` can be used to specify
4888 to select all unresolved files. ``--tool`` can be used to specify
4889 the merge tool used for the given files. It overrides the HGMERGE
4889 the merge tool used for the given files. It overrides the HGMERGE
4890 environment variable and your configuration files. Previous file
4890 environment variable and your configuration files. Previous file
4891 contents are saved with a ``.orig`` suffix.
4891 contents are saved with a ``.orig`` suffix.
4892
4892
4893 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4893 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4894 (e.g. after having manually fixed-up the files). The default is
4894 (e.g. after having manually fixed-up the files). The default is
4895 to mark all unresolved files.
4895 to mark all unresolved files.
4896
4896
4897 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4897 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4898 default is to mark all resolved files.
4898 default is to mark all resolved files.
4899
4899
4900 - :hg:`resolve -l`: list files which had or still have conflicts.
4900 - :hg:`resolve -l`: list files which had or still have conflicts.
4901 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4901 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4902
4902
4903 Note that Mercurial will not let you commit files with unresolved
4903 Note that Mercurial will not let you commit files with unresolved
4904 merge conflicts. You must use :hg:`resolve -m ...` before you can
4904 merge conflicts. You must use :hg:`resolve -m ...` before you can
4905 commit after a conflicting merge.
4905 commit after a conflicting merge.
4906
4906
4907 Returns 0 on success, 1 if any files fail a resolve attempt.
4907 Returns 0 on success, 1 if any files fail a resolve attempt.
4908 """
4908 """
4909
4909
4910 all, mark, unmark, show, nostatus = \
4910 all, mark, unmark, show, nostatus = \
4911 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4911 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4912
4912
4913 if (show and (mark or unmark)) or (mark and unmark):
4913 if (show and (mark or unmark)) or (mark and unmark):
4914 raise util.Abort(_("too many options specified"))
4914 raise util.Abort(_("too many options specified"))
4915 if pats and all:
4915 if pats and all:
4916 raise util.Abort(_("can't specify --all and patterns"))
4916 raise util.Abort(_("can't specify --all and patterns"))
4917 if not (all or pats or show or mark or unmark):
4917 if not (all or pats or show or mark or unmark):
4918 raise util.Abort(_('no files or directories specified; '
4918 raise util.Abort(_('no files or directories specified; '
4919 'use --all to remerge all files'))
4919 'use --all to remerge all files'))
4920
4920
4921 ms = mergemod.mergestate(repo)
4921 ms = mergemod.mergestate(repo)
4922 m = scmutil.match(repo[None], pats, opts)
4922 m = scmutil.match(repo[None], pats, opts)
4923 ret = 0
4923 ret = 0
4924
4924
4925 for f in ms:
4925 for f in ms:
4926 if m(f):
4926 if m(f):
4927 if show:
4927 if show:
4928 if nostatus:
4928 if nostatus:
4929 ui.write("%s\n" % f)
4929 ui.write("%s\n" % f)
4930 else:
4930 else:
4931 ui.write("%s %s\n" % (ms[f].upper(), f),
4931 ui.write("%s %s\n" % (ms[f].upper(), f),
4932 label='resolve.' +
4932 label='resolve.' +
4933 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4933 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4934 elif mark:
4934 elif mark:
4935 ms.mark(f, "r")
4935 ms.mark(f, "r")
4936 elif unmark:
4936 elif unmark:
4937 ms.mark(f, "u")
4937 ms.mark(f, "u")
4938 else:
4938 else:
4939 wctx = repo[None]
4939 wctx = repo[None]
4940 mctx = wctx.parents()[-1]
4940 mctx = wctx.parents()[-1]
4941
4941
4942 # backup pre-resolve (merge uses .orig for its own purposes)
4942 # backup pre-resolve (merge uses .orig for its own purposes)
4943 a = repo.wjoin(f)
4943 a = repo.wjoin(f)
4944 util.copyfile(a, a + ".resolve")
4944 util.copyfile(a, a + ".resolve")
4945
4945
4946 try:
4946 try:
4947 # resolve file
4947 # resolve file
4948 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4948 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4949 if ms.resolve(f, wctx, mctx):
4949 if ms.resolve(f, wctx, mctx):
4950 ret = 1
4950 ret = 1
4951 finally:
4951 finally:
4952 ui.setconfig('ui', 'forcemerge', '')
4952 ui.setconfig('ui', 'forcemerge', '')
4953 ms.commit()
4953 ms.commit()
4954
4954
4955 # replace filemerge's .orig file with our resolve file
4955 # replace filemerge's .orig file with our resolve file
4956 util.rename(a + ".resolve", a + ".orig")
4956 util.rename(a + ".resolve", a + ".orig")
4957
4957
4958 ms.commit()
4958 ms.commit()
4959 return ret
4959 return ret
4960
4960
4961 @command('revert',
4961 @command('revert',
4962 [('a', 'all', None, _('revert all changes when no arguments given')),
4962 [('a', 'all', None, _('revert all changes when no arguments given')),
4963 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4963 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4964 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4964 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4965 ('C', 'no-backup', None, _('do not save backup copies of files')),
4965 ('C', 'no-backup', None, _('do not save backup copies of files')),
4966 ] + walkopts + dryrunopts,
4966 ] + walkopts + dryrunopts,
4967 _('[OPTION]... [-r REV] [NAME]...'))
4967 _('[OPTION]... [-r REV] [NAME]...'))
4968 def revert(ui, repo, *pats, **opts):
4968 def revert(ui, repo, *pats, **opts):
4969 """restore files to their checkout state
4969 """restore files to their checkout state
4970
4970
4971 .. note::
4971 .. note::
4972
4972
4973 To check out earlier revisions, you should use :hg:`update REV`.
4973 To check out earlier revisions, you should use :hg:`update REV`.
4974 To cancel an uncommitted merge (and lose your changes),
4974 To cancel an uncommitted merge (and lose your changes),
4975 use :hg:`update --clean .`.
4975 use :hg:`update --clean .`.
4976
4976
4977 With no revision specified, revert the specified files or directories
4977 With no revision specified, revert the specified files or directories
4978 to the contents they had in the parent of the working directory.
4978 to the contents they had in the parent of the working directory.
4979 This restores the contents of files to an unmodified
4979 This restores the contents of files to an unmodified
4980 state and unschedules adds, removes, copies, and renames. If the
4980 state and unschedules adds, removes, copies, and renames. If the
4981 working directory has two parents, you must explicitly specify a
4981 working directory has two parents, you must explicitly specify a
4982 revision.
4982 revision.
4983
4983
4984 Using the -r/--rev or -d/--date options, revert the given files or
4984 Using the -r/--rev or -d/--date options, revert the given files or
4985 directories to their states as of a specific revision. Because
4985 directories to their states as of a specific revision. Because
4986 revert does not change the working directory parents, this will
4986 revert does not change the working directory parents, this will
4987 cause these files to appear modified. This can be helpful to "back
4987 cause these files to appear modified. This can be helpful to "back
4988 out" some or all of an earlier change. See :hg:`backout` for a
4988 out" some or all of an earlier change. See :hg:`backout` for a
4989 related method.
4989 related method.
4990
4990
4991 Modified files are saved with a .orig suffix before reverting.
4991 Modified files are saved with a .orig suffix before reverting.
4992 To disable these backups, use --no-backup.
4992 To disable these backups, use --no-backup.
4993
4993
4994 See :hg:`help dates` for a list of formats valid for -d/--date.
4994 See :hg:`help dates` for a list of formats valid for -d/--date.
4995
4995
4996 Returns 0 on success.
4996 Returns 0 on success.
4997 """
4997 """
4998
4998
4999 if opts.get("date"):
4999 if opts.get("date"):
5000 if opts.get("rev"):
5000 if opts.get("rev"):
5001 raise util.Abort(_("you can't specify a revision and a date"))
5001 raise util.Abort(_("you can't specify a revision and a date"))
5002 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5002 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5003
5003
5004 parent, p2 = repo.dirstate.parents()
5004 parent, p2 = repo.dirstate.parents()
5005 if not opts.get('rev') and p2 != nullid:
5005 if not opts.get('rev') and p2 != nullid:
5006 # revert after merge is a trap for new users (issue2915)
5006 # revert after merge is a trap for new users (issue2915)
5007 raise util.Abort(_('uncommitted merge with no revision specified'),
5007 raise util.Abort(_('uncommitted merge with no revision specified'),
5008 hint=_('use "hg update" or see "hg help revert"'))
5008 hint=_('use "hg update" or see "hg help revert"'))
5009
5009
5010 ctx = scmutil.revsingle(repo, opts.get('rev'))
5010 ctx = scmutil.revsingle(repo, opts.get('rev'))
5011
5011
5012 if not pats and not opts.get('all'):
5012 if not pats and not opts.get('all'):
5013 msg = _("no files or directories specified")
5013 msg = _("no files or directories specified")
5014 if p2 != nullid:
5014 if p2 != nullid:
5015 hint = _("uncommitted merge, use --all to discard all changes,"
5015 hint = _("uncommitted merge, use --all to discard all changes,"
5016 " or 'hg update -C .' to abort the merge")
5016 " or 'hg update -C .' to abort the merge")
5017 raise util.Abort(msg, hint=hint)
5017 raise util.Abort(msg, hint=hint)
5018 dirty = util.any(repo.status())
5018 dirty = util.any(repo.status())
5019 node = ctx.node()
5019 node = ctx.node()
5020 if node != parent:
5020 if node != parent:
5021 if dirty:
5021 if dirty:
5022 hint = _("uncommitted changes, use --all to discard all"
5022 hint = _("uncommitted changes, use --all to discard all"
5023 " changes, or 'hg update %s' to update") % ctx.rev()
5023 " changes, or 'hg update %s' to update") % ctx.rev()
5024 else:
5024 else:
5025 hint = _("use --all to revert all files,"
5025 hint = _("use --all to revert all files,"
5026 " or 'hg update %s' to update") % ctx.rev()
5026 " or 'hg update %s' to update") % ctx.rev()
5027 elif dirty:
5027 elif dirty:
5028 hint = _("uncommitted changes, use --all to discard all changes")
5028 hint = _("uncommitted changes, use --all to discard all changes")
5029 else:
5029 else:
5030 hint = _("use --all to revert all files")
5030 hint = _("use --all to revert all files")
5031 raise util.Abort(msg, hint=hint)
5031 raise util.Abort(msg, hint=hint)
5032
5032
5033 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5033 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5034
5034
5035 @command('rollback', dryrunopts +
5035 @command('rollback', dryrunopts +
5036 [('f', 'force', False, _('ignore safety measures'))])
5036 [('f', 'force', False, _('ignore safety measures'))])
5037 def rollback(ui, repo, **opts):
5037 def rollback(ui, repo, **opts):
5038 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5038 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5039
5039
5040 Please use :hg:`commit --amend` instead of rollback to correct
5040 Please use :hg:`commit --amend` instead of rollback to correct
5041 mistakes in the last commit.
5041 mistakes in the last commit.
5042
5042
5043 This command should be used with care. There is only one level of
5043 This command should be used with care. There is only one level of
5044 rollback, and there is no way to undo a rollback. It will also
5044 rollback, and there is no way to undo a rollback. It will also
5045 restore the dirstate at the time of the last transaction, losing
5045 restore the dirstate at the time of the last transaction, losing
5046 any dirstate changes since that time. This command does not alter
5046 any dirstate changes since that time. This command does not alter
5047 the working directory.
5047 the working directory.
5048
5048
5049 Transactions are used to encapsulate the effects of all commands
5049 Transactions are used to encapsulate the effects of all commands
5050 that create new changesets or propagate existing changesets into a
5050 that create new changesets or propagate existing changesets into a
5051 repository.
5051 repository.
5052
5052
5053 .. container:: verbose
5053 .. container:: verbose
5054
5054
5055 For example, the following commands are transactional, and their
5055 For example, the following commands are transactional, and their
5056 effects can be rolled back:
5056 effects can be rolled back:
5057
5057
5058 - commit
5058 - commit
5059 - import
5059 - import
5060 - pull
5060 - pull
5061 - push (with this repository as the destination)
5061 - push (with this repository as the destination)
5062 - unbundle
5062 - unbundle
5063
5063
5064 To avoid permanent data loss, rollback will refuse to rollback a
5064 To avoid permanent data loss, rollback will refuse to rollback a
5065 commit transaction if it isn't checked out. Use --force to
5065 commit transaction if it isn't checked out. Use --force to
5066 override this protection.
5066 override this protection.
5067
5067
5068 This command is not intended for use on public repositories. Once
5068 This command is not intended for use on public repositories. Once
5069 changes are visible for pull by other users, rolling a transaction
5069 changes are visible for pull by other users, rolling a transaction
5070 back locally is ineffective (someone else may already have pulled
5070 back locally is ineffective (someone else may already have pulled
5071 the changes). Furthermore, a race is possible with readers of the
5071 the changes). Furthermore, a race is possible with readers of the
5072 repository; for example an in-progress pull from the repository
5072 repository; for example an in-progress pull from the repository
5073 may fail if a rollback is performed.
5073 may fail if a rollback is performed.
5074
5074
5075 Returns 0 on success, 1 if no rollback data is available.
5075 Returns 0 on success, 1 if no rollback data is available.
5076 """
5076 """
5077 return repo.rollback(dryrun=opts.get('dry_run'),
5077 return repo.rollback(dryrun=opts.get('dry_run'),
5078 force=opts.get('force'))
5078 force=opts.get('force'))
5079
5079
5080 @command('root', [])
5080 @command('root', [])
5081 def root(ui, repo):
5081 def root(ui, repo):
5082 """print the root (top) of the current working directory
5082 """print the root (top) of the current working directory
5083
5083
5084 Print the root directory of the current repository.
5084 Print the root directory of the current repository.
5085
5085
5086 Returns 0 on success.
5086 Returns 0 on success.
5087 """
5087 """
5088 ui.write(repo.root + "\n")
5088 ui.write(repo.root + "\n")
5089
5089
5090 @command('^serve',
5090 @command('^serve',
5091 [('A', 'accesslog', '', _('name of access log file to write to'),
5091 [('A', 'accesslog', '', _('name of access log file to write to'),
5092 _('FILE')),
5092 _('FILE')),
5093 ('d', 'daemon', None, _('run server in background')),
5093 ('d', 'daemon', None, _('run server in background')),
5094 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5094 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5095 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5095 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5096 # use string type, then we can check if something was passed
5096 # use string type, then we can check if something was passed
5097 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5097 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5098 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5098 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5099 _('ADDR')),
5099 _('ADDR')),
5100 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5100 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5101 _('PREFIX')),
5101 _('PREFIX')),
5102 ('n', 'name', '',
5102 ('n', 'name', '',
5103 _('name to show in web pages (default: working directory)'), _('NAME')),
5103 _('name to show in web pages (default: working directory)'), _('NAME')),
5104 ('', 'web-conf', '',
5104 ('', 'web-conf', '',
5105 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5105 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5106 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5106 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5107 _('FILE')),
5107 _('FILE')),
5108 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5108 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5109 ('', 'stdio', None, _('for remote clients')),
5109 ('', 'stdio', None, _('for remote clients')),
5110 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5110 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5111 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5111 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5112 ('', 'style', '', _('template style to use'), _('STYLE')),
5112 ('', 'style', '', _('template style to use'), _('STYLE')),
5113 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5113 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5114 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5114 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5115 _('[OPTION]...'))
5115 _('[OPTION]...'))
5116 def serve(ui, repo, **opts):
5116 def serve(ui, repo, **opts):
5117 """start stand-alone webserver
5117 """start stand-alone webserver
5118
5118
5119 Start a local HTTP repository browser and pull server. You can use
5119 Start a local HTTP repository browser and pull server. You can use
5120 this for ad-hoc sharing and browsing of repositories. It is
5120 this for ad-hoc sharing and browsing of repositories. It is
5121 recommended to use a real web server to serve a repository for
5121 recommended to use a real web server to serve a repository for
5122 longer periods of time.
5122 longer periods of time.
5123
5123
5124 Please note that the server does not implement access control.
5124 Please note that the server does not implement access control.
5125 This means that, by default, anybody can read from the server and
5125 This means that, by default, anybody can read from the server and
5126 nobody can write to it by default. Set the ``web.allow_push``
5126 nobody can write to it by default. Set the ``web.allow_push``
5127 option to ``*`` to allow everybody to push to the server. You
5127 option to ``*`` to allow everybody to push to the server. You
5128 should use a real web server if you need to authenticate users.
5128 should use a real web server if you need to authenticate users.
5129
5129
5130 By default, the server logs accesses to stdout and errors to
5130 By default, the server logs accesses to stdout and errors to
5131 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5131 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5132 files.
5132 files.
5133
5133
5134 To have the server choose a free port number to listen on, specify
5134 To have the server choose a free port number to listen on, specify
5135 a port number of 0; in this case, the server will print the port
5135 a port number of 0; in this case, the server will print the port
5136 number it uses.
5136 number it uses.
5137
5137
5138 Returns 0 on success.
5138 Returns 0 on success.
5139 """
5139 """
5140
5140
5141 if opts["stdio"] and opts["cmdserver"]:
5141 if opts["stdio"] and opts["cmdserver"]:
5142 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5142 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5143
5143
5144 def checkrepo():
5144 def checkrepo():
5145 if repo is None:
5145 if repo is None:
5146 raise error.RepoError(_("there is no Mercurial repository here"
5146 raise error.RepoError(_("there is no Mercurial repository here"
5147 " (.hg not found)"))
5147 " (.hg not found)"))
5148
5148
5149 if opts["stdio"]:
5149 if opts["stdio"]:
5150 checkrepo()
5150 checkrepo()
5151 s = sshserver.sshserver(ui, repo)
5151 s = sshserver.sshserver(ui, repo)
5152 s.serve_forever()
5152 s.serve_forever()
5153
5153
5154 if opts["cmdserver"]:
5154 if opts["cmdserver"]:
5155 checkrepo()
5155 checkrepo()
5156 s = commandserver.server(ui, repo, opts["cmdserver"])
5156 s = commandserver.server(ui, repo, opts["cmdserver"])
5157 return s.serve()
5157 return s.serve()
5158
5158
5159 # this way we can check if something was given in the command-line
5159 # this way we can check if something was given in the command-line
5160 if opts.get('port'):
5160 if opts.get('port'):
5161 opts['port'] = util.getport(opts.get('port'))
5161 opts['port'] = util.getport(opts.get('port'))
5162
5162
5163 baseui = repo and repo.baseui or ui
5163 baseui = repo and repo.baseui or ui
5164 optlist = ("name templates style address port prefix ipv6"
5164 optlist = ("name templates style address port prefix ipv6"
5165 " accesslog errorlog certificate encoding")
5165 " accesslog errorlog certificate encoding")
5166 for o in optlist.split():
5166 for o in optlist.split():
5167 val = opts.get(o, '')
5167 val = opts.get(o, '')
5168 if val in (None, ''): # should check against default options instead
5168 if val in (None, ''): # should check against default options instead
5169 continue
5169 continue
5170 baseui.setconfig("web", o, val)
5170 baseui.setconfig("web", o, val)
5171 if repo and repo.ui != baseui:
5171 if repo and repo.ui != baseui:
5172 repo.ui.setconfig("web", o, val)
5172 repo.ui.setconfig("web", o, val)
5173
5173
5174 o = opts.get('web_conf') or opts.get('webdir_conf')
5174 o = opts.get('web_conf') or opts.get('webdir_conf')
5175 if not o:
5175 if not o:
5176 if not repo:
5176 if not repo:
5177 raise error.RepoError(_("there is no Mercurial repository"
5177 raise error.RepoError(_("there is no Mercurial repository"
5178 " here (.hg not found)"))
5178 " here (.hg not found)"))
5179 o = repo
5179 o = repo
5180
5180
5181 app = hgweb.hgweb(o, baseui=baseui)
5181 app = hgweb.hgweb(o, baseui=baseui)
5182 service = httpservice(ui, app, opts)
5182 service = httpservice(ui, app, opts)
5183 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5183 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5184
5184
5185 class httpservice(object):
5185 class httpservice(object):
5186 def __init__(self, ui, app, opts):
5186 def __init__(self, ui, app, opts):
5187 self.ui = ui
5187 self.ui = ui
5188 self.app = app
5188 self.app = app
5189 self.opts = opts
5189 self.opts = opts
5190
5190
5191 def init(self):
5191 def init(self):
5192 util.setsignalhandler()
5192 util.setsignalhandler()
5193 self.httpd = hgweb_server.create_server(self.ui, self.app)
5193 self.httpd = hgweb_server.create_server(self.ui, self.app)
5194
5194
5195 if self.opts['port'] and not self.ui.verbose:
5195 if self.opts['port'] and not self.ui.verbose:
5196 return
5196 return
5197
5197
5198 if self.httpd.prefix:
5198 if self.httpd.prefix:
5199 prefix = self.httpd.prefix.strip('/') + '/'
5199 prefix = self.httpd.prefix.strip('/') + '/'
5200 else:
5200 else:
5201 prefix = ''
5201 prefix = ''
5202
5202
5203 port = ':%d' % self.httpd.port
5203 port = ':%d' % self.httpd.port
5204 if port == ':80':
5204 if port == ':80':
5205 port = ''
5205 port = ''
5206
5206
5207 bindaddr = self.httpd.addr
5207 bindaddr = self.httpd.addr
5208 if bindaddr == '0.0.0.0':
5208 if bindaddr == '0.0.0.0':
5209 bindaddr = '*'
5209 bindaddr = '*'
5210 elif ':' in bindaddr: # IPv6
5210 elif ':' in bindaddr: # IPv6
5211 bindaddr = '[%s]' % bindaddr
5211 bindaddr = '[%s]' % bindaddr
5212
5212
5213 fqaddr = self.httpd.fqaddr
5213 fqaddr = self.httpd.fqaddr
5214 if ':' in fqaddr:
5214 if ':' in fqaddr:
5215 fqaddr = '[%s]' % fqaddr
5215 fqaddr = '[%s]' % fqaddr
5216 if self.opts['port']:
5216 if self.opts['port']:
5217 write = self.ui.status
5217 write = self.ui.status
5218 else:
5218 else:
5219 write = self.ui.write
5219 write = self.ui.write
5220 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5220 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5221 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5221 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5222
5222
5223 def run(self):
5223 def run(self):
5224 self.httpd.serve_forever()
5224 self.httpd.serve_forever()
5225
5225
5226
5226
5227 @command('showconfig|debugconfig',
5227 @command('showconfig|debugconfig',
5228 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5228 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5229 _('[-u] [NAME]...'))
5229 _('[-u] [NAME]...'))
5230 def showconfig(ui, repo, *values, **opts):
5230 def showconfig(ui, repo, *values, **opts):
5231 """show combined config settings from all hgrc files
5231 """show combined config settings from all hgrc files
5232
5232
5233 With no arguments, print names and values of all config items.
5233 With no arguments, print names and values of all config items.
5234
5234
5235 With one argument of the form section.name, print just the value
5235 With one argument of the form section.name, print just the value
5236 of that config item.
5236 of that config item.
5237
5237
5238 With multiple arguments, print names and values of all config
5238 With multiple arguments, print names and values of all config
5239 items with matching section names.
5239 items with matching section names.
5240
5240
5241 With --debug, the source (filename and line number) is printed
5241 With --debug, the source (filename and line number) is printed
5242 for each config item.
5242 for each config item.
5243
5243
5244 Returns 0 on success.
5244 Returns 0 on success.
5245 """
5245 """
5246
5246
5247 for f in scmutil.rcpath():
5247 for f in scmutil.rcpath():
5248 ui.debug('read config from: %s\n' % f)
5248 ui.debug('read config from: %s\n' % f)
5249 untrusted = bool(opts.get('untrusted'))
5249 untrusted = bool(opts.get('untrusted'))
5250 if values:
5250 if values:
5251 sections = [v for v in values if '.' not in v]
5251 sections = [v for v in values if '.' not in v]
5252 items = [v for v in values if '.' in v]
5252 items = [v for v in values if '.' in v]
5253 if len(items) > 1 or items and sections:
5253 if len(items) > 1 or items and sections:
5254 raise util.Abort(_('only one config item permitted'))
5254 raise util.Abort(_('only one config item permitted'))
5255 for section, name, value in ui.walkconfig(untrusted=untrusted):
5255 for section, name, value in ui.walkconfig(untrusted=untrusted):
5256 value = str(value).replace('\n', '\\n')
5256 value = str(value).replace('\n', '\\n')
5257 sectname = section + '.' + name
5257 sectname = section + '.' + name
5258 if values:
5258 if values:
5259 for v in values:
5259 for v in values:
5260 if v == section:
5260 if v == section:
5261 ui.debug('%s: ' %
5261 ui.debug('%s: ' %
5262 ui.configsource(section, name, untrusted))
5262 ui.configsource(section, name, untrusted))
5263 ui.write('%s=%s\n' % (sectname, value))
5263 ui.write('%s=%s\n' % (sectname, value))
5264 elif v == sectname:
5264 elif v == sectname:
5265 ui.debug('%s: ' %
5265 ui.debug('%s: ' %
5266 ui.configsource(section, name, untrusted))
5266 ui.configsource(section, name, untrusted))
5267 ui.write(value, '\n')
5267 ui.write(value, '\n')
5268 else:
5268 else:
5269 ui.debug('%s: ' %
5269 ui.debug('%s: ' %
5270 ui.configsource(section, name, untrusted))
5270 ui.configsource(section, name, untrusted))
5271 ui.write('%s=%s\n' % (sectname, value))
5271 ui.write('%s=%s\n' % (sectname, value))
5272
5272
5273 @command('^status|st',
5273 @command('^status|st',
5274 [('A', 'all', None, _('show status of all files')),
5274 [('A', 'all', None, _('show status of all files')),
5275 ('m', 'modified', None, _('show only modified files')),
5275 ('m', 'modified', None, _('show only modified files')),
5276 ('a', 'added', None, _('show only added files')),
5276 ('a', 'added', None, _('show only added files')),
5277 ('r', 'removed', None, _('show only removed files')),
5277 ('r', 'removed', None, _('show only removed files')),
5278 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5278 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5279 ('c', 'clean', None, _('show only files without changes')),
5279 ('c', 'clean', None, _('show only files without changes')),
5280 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5280 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5281 ('i', 'ignored', None, _('show only ignored files')),
5281 ('i', 'ignored', None, _('show only ignored files')),
5282 ('n', 'no-status', None, _('hide status prefix')),
5282 ('n', 'no-status', None, _('hide status prefix')),
5283 ('C', 'copies', None, _('show source of copied files')),
5283 ('C', 'copies', None, _('show source of copied files')),
5284 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5284 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5285 ('', 'rev', [], _('show difference from revision'), _('REV')),
5285 ('', 'rev', [], _('show difference from revision'), _('REV')),
5286 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5286 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5287 ] + walkopts + subrepoopts,
5287 ] + walkopts + subrepoopts,
5288 _('[OPTION]... [FILE]...'))
5288 _('[OPTION]... [FILE]...'))
5289 def status(ui, repo, *pats, **opts):
5289 def status(ui, repo, *pats, **opts):
5290 """show changed files in the working directory
5290 """show changed files in the working directory
5291
5291
5292 Show status of files in the repository. If names are given, only
5292 Show status of files in the repository. If names are given, only
5293 files that match are shown. Files that are clean or ignored or
5293 files that match are shown. Files that are clean or ignored or
5294 the source of a copy/move operation, are not listed unless
5294 the source of a copy/move operation, are not listed unless
5295 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5295 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5296 Unless options described with "show only ..." are given, the
5296 Unless options described with "show only ..." are given, the
5297 options -mardu are used.
5297 options -mardu are used.
5298
5298
5299 Option -q/--quiet hides untracked (unknown and ignored) files
5299 Option -q/--quiet hides untracked (unknown and ignored) files
5300 unless explicitly requested with -u/--unknown or -i/--ignored.
5300 unless explicitly requested with -u/--unknown or -i/--ignored.
5301
5301
5302 .. note::
5302 .. note::
5303
5303
5304 status may appear to disagree with diff if permissions have
5304 status may appear to disagree with diff if permissions have
5305 changed or a merge has occurred. The standard diff format does
5305 changed or a merge has occurred. The standard diff format does
5306 not report permission changes and diff only reports changes
5306 not report permission changes and diff only reports changes
5307 relative to one merge parent.
5307 relative to one merge parent.
5308
5308
5309 If one revision is given, it is used as the base revision.
5309 If one revision is given, it is used as the base revision.
5310 If two revisions are given, the differences between them are
5310 If two revisions are given, the differences between them are
5311 shown. The --change option can also be used as a shortcut to list
5311 shown. The --change option can also be used as a shortcut to list
5312 the changed files of a revision from its first parent.
5312 the changed files of a revision from its first parent.
5313
5313
5314 The codes used to show the status of files are::
5314 The codes used to show the status of files are::
5315
5315
5316 M = modified
5316 M = modified
5317 A = added
5317 A = added
5318 R = removed
5318 R = removed
5319 C = clean
5319 C = clean
5320 ! = missing (deleted by non-hg command, but still tracked)
5320 ! = missing (deleted by non-hg command, but still tracked)
5321 ? = not tracked
5321 ? = not tracked
5322 I = ignored
5322 I = ignored
5323 = origin of the previous file listed as A (added)
5323 = origin of the previous file listed as A (added)
5324
5324
5325 .. container:: verbose
5325 .. container:: verbose
5326
5326
5327 Examples:
5327 Examples:
5328
5328
5329 - show changes in the working directory relative to a
5329 - show changes in the working directory relative to a
5330 changeset::
5330 changeset::
5331
5331
5332 hg status --rev 9353
5332 hg status --rev 9353
5333
5333
5334 - show all changes including copies in an existing changeset::
5334 - show all changes including copies in an existing changeset::
5335
5335
5336 hg status --copies --change 9353
5336 hg status --copies --change 9353
5337
5337
5338 - get a NUL separated list of added files, suitable for xargs::
5338 - get a NUL separated list of added files, suitable for xargs::
5339
5339
5340 hg status -an0
5340 hg status -an0
5341
5341
5342 Returns 0 on success.
5342 Returns 0 on success.
5343 """
5343 """
5344
5344
5345 revs = opts.get('rev')
5345 revs = opts.get('rev')
5346 change = opts.get('change')
5346 change = opts.get('change')
5347
5347
5348 if revs and change:
5348 if revs and change:
5349 msg = _('cannot specify --rev and --change at the same time')
5349 msg = _('cannot specify --rev and --change at the same time')
5350 raise util.Abort(msg)
5350 raise util.Abort(msg)
5351 elif change:
5351 elif change:
5352 node2 = scmutil.revsingle(repo, change, None).node()
5352 node2 = scmutil.revsingle(repo, change, None).node()
5353 node1 = repo[node2].p1().node()
5353 node1 = repo[node2].p1().node()
5354 else:
5354 else:
5355 node1, node2 = scmutil.revpair(repo, revs)
5355 node1, node2 = scmutil.revpair(repo, revs)
5356
5356
5357 cwd = (pats and repo.getcwd()) or ''
5357 cwd = (pats and repo.getcwd()) or ''
5358 end = opts.get('print0') and '\0' or '\n'
5358 end = opts.get('print0') and '\0' or '\n'
5359 copy = {}
5359 copy = {}
5360 states = 'modified added removed deleted unknown ignored clean'.split()
5360 states = 'modified added removed deleted unknown ignored clean'.split()
5361 show = [k for k in states if opts.get(k)]
5361 show = [k for k in states if opts.get(k)]
5362 if opts.get('all'):
5362 if opts.get('all'):
5363 show += ui.quiet and (states[:4] + ['clean']) or states
5363 show += ui.quiet and (states[:4] + ['clean']) or states
5364 if not show:
5364 if not show:
5365 show = ui.quiet and states[:4] or states[:5]
5365 show = ui.quiet and states[:4] or states[:5]
5366
5366
5367 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5367 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5368 'ignored' in show, 'clean' in show, 'unknown' in show,
5368 'ignored' in show, 'clean' in show, 'unknown' in show,
5369 opts.get('subrepos'))
5369 opts.get('subrepos'))
5370 changestates = zip(states, 'MAR!?IC', stat)
5370 changestates = zip(states, 'MAR!?IC', stat)
5371
5371
5372 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5372 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5373 copy = copies.pathcopies(repo[node1], repo[node2])
5373 copy = copies.pathcopies(repo[node1], repo[node2])
5374
5374
5375 fm = ui.formatter('status', opts)
5375 fm = ui.formatter('status', opts)
5376 fmt = '%s' + end
5376 fmt = '%s' + end
5377 showchar = not opts.get('no_status')
5377 showchar = not opts.get('no_status')
5378
5378
5379 for state, char, files in changestates:
5379 for state, char, files in changestates:
5380 if state in show:
5380 if state in show:
5381 label = 'status.' + state
5381 label = 'status.' + state
5382 for f in files:
5382 for f in files:
5383 fm.startitem()
5383 fm.startitem()
5384 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5384 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5385 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5385 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5386 if f in copy:
5386 if f in copy:
5387 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5387 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5388 label='status.copied')
5388 label='status.copied')
5389 fm.end()
5389 fm.end()
5390
5390
5391 @command('^summary|sum',
5391 @command('^summary|sum',
5392 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5392 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5393 def summary(ui, repo, **opts):
5393 def summary(ui, repo, **opts):
5394 """summarize working directory state
5394 """summarize working directory state
5395
5395
5396 This generates a brief summary of the working directory state,
5396 This generates a brief summary of the working directory state,
5397 including parents, branch, commit status, and available updates.
5397 including parents, branch, commit status, and available updates.
5398
5398
5399 With the --remote option, this will check the default paths for
5399 With the --remote option, this will check the default paths for
5400 incoming and outgoing changes. This can be time-consuming.
5400 incoming and outgoing changes. This can be time-consuming.
5401
5401
5402 Returns 0 on success.
5402 Returns 0 on success.
5403 """
5403 """
5404
5404
5405 ctx = repo[None]
5405 ctx = repo[None]
5406 parents = ctx.parents()
5406 parents = ctx.parents()
5407 pnode = parents[0].node()
5407 pnode = parents[0].node()
5408 marks = []
5408 marks = []
5409
5409
5410 for p in parents:
5410 for p in parents:
5411 # label with log.changeset (instead of log.parent) since this
5411 # label with log.changeset (instead of log.parent) since this
5412 # shows a working directory parent *changeset*:
5412 # shows a working directory parent *changeset*:
5413 # i18n: column positioning for "hg summary"
5413 # i18n: column positioning for "hg summary"
5414 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5414 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5415 label='log.changeset changeset.%s' % p.phasestr())
5415 label='log.changeset changeset.%s' % p.phasestr())
5416 ui.write(' '.join(p.tags()), label='log.tag')
5416 ui.write(' '.join(p.tags()), label='log.tag')
5417 if p.bookmarks():
5417 if p.bookmarks():
5418 marks.extend(p.bookmarks())
5418 marks.extend(p.bookmarks())
5419 if p.rev() == -1:
5419 if p.rev() == -1:
5420 if not len(repo):
5420 if not len(repo):
5421 ui.write(_(' (empty repository)'))
5421 ui.write(_(' (empty repository)'))
5422 else:
5422 else:
5423 ui.write(_(' (no revision checked out)'))
5423 ui.write(_(' (no revision checked out)'))
5424 ui.write('\n')
5424 ui.write('\n')
5425 if p.description():
5425 if p.description():
5426 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5426 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5427 label='log.summary')
5427 label='log.summary')
5428
5428
5429 branch = ctx.branch()
5429 branch = ctx.branch()
5430 bheads = repo.branchheads(branch)
5430 bheads = repo.branchheads(branch)
5431 # i18n: column positioning for "hg summary"
5431 # i18n: column positioning for "hg summary"
5432 m = _('branch: %s\n') % branch
5432 m = _('branch: %s\n') % branch
5433 if branch != 'default':
5433 if branch != 'default':
5434 ui.write(m, label='log.branch')
5434 ui.write(m, label='log.branch')
5435 else:
5435 else:
5436 ui.status(m, label='log.branch')
5436 ui.status(m, label='log.branch')
5437
5437
5438 if marks:
5438 if marks:
5439 current = repo._bookmarkcurrent
5439 current = repo._bookmarkcurrent
5440 # i18n: column positioning for "hg summary"
5440 # i18n: column positioning for "hg summary"
5441 ui.write(_('bookmarks:'), label='log.bookmark')
5441 ui.write(_('bookmarks:'), label='log.bookmark')
5442 if current is not None:
5442 if current is not None:
5443 if current in marks:
5443 if current in marks:
5444 ui.write(' *' + current, label='bookmarks.current')
5444 ui.write(' *' + current, label='bookmarks.current')
5445 marks.remove(current)
5445 marks.remove(current)
5446 else:
5446 else:
5447 ui.write(' [%s]' % current, label='bookmarks.current')
5447 ui.write(' [%s]' % current, label='bookmarks.current')
5448 for m in marks:
5448 for m in marks:
5449 ui.write(' ' + m, label='log.bookmark')
5449 ui.write(' ' + m, label='log.bookmark')
5450 ui.write('\n', label='log.bookmark')
5450 ui.write('\n', label='log.bookmark')
5451
5451
5452 st = list(repo.status(unknown=True))[:6]
5452 st = list(repo.status(unknown=True))[:6]
5453
5453
5454 c = repo.dirstate.copies()
5454 c = repo.dirstate.copies()
5455 copied, renamed = [], []
5455 copied, renamed = [], []
5456 for d, s in c.iteritems():
5456 for d, s in c.iteritems():
5457 if s in st[2]:
5457 if s in st[2]:
5458 st[2].remove(s)
5458 st[2].remove(s)
5459 renamed.append(d)
5459 renamed.append(d)
5460 else:
5460 else:
5461 copied.append(d)
5461 copied.append(d)
5462 if d in st[1]:
5462 if d in st[1]:
5463 st[1].remove(d)
5463 st[1].remove(d)
5464 st.insert(3, renamed)
5464 st.insert(3, renamed)
5465 st.insert(4, copied)
5465 st.insert(4, copied)
5466
5466
5467 ms = mergemod.mergestate(repo)
5467 ms = mergemod.mergestate(repo)
5468 st.append([f for f in ms if ms[f] == 'u'])
5468 st.append([f for f in ms if ms[f] == 'u'])
5469
5469
5470 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5470 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5471 st.append(subs)
5471 st.append(subs)
5472
5472
5473 labels = [ui.label(_('%d modified'), 'status.modified'),
5473 labels = [ui.label(_('%d modified'), 'status.modified'),
5474 ui.label(_('%d added'), 'status.added'),
5474 ui.label(_('%d added'), 'status.added'),
5475 ui.label(_('%d removed'), 'status.removed'),
5475 ui.label(_('%d removed'), 'status.removed'),
5476 ui.label(_('%d renamed'), 'status.copied'),
5476 ui.label(_('%d renamed'), 'status.copied'),
5477 ui.label(_('%d copied'), 'status.copied'),
5477 ui.label(_('%d copied'), 'status.copied'),
5478 ui.label(_('%d deleted'), 'status.deleted'),
5478 ui.label(_('%d deleted'), 'status.deleted'),
5479 ui.label(_('%d unknown'), 'status.unknown'),
5479 ui.label(_('%d unknown'), 'status.unknown'),
5480 ui.label(_('%d ignored'), 'status.ignored'),
5480 ui.label(_('%d ignored'), 'status.ignored'),
5481 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5481 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5482 ui.label(_('%d subrepos'), 'status.modified')]
5482 ui.label(_('%d subrepos'), 'status.modified')]
5483 t = []
5483 t = []
5484 for s, l in zip(st, labels):
5484 for s, l in zip(st, labels):
5485 if s:
5485 if s:
5486 t.append(l % len(s))
5486 t.append(l % len(s))
5487
5487
5488 t = ', '.join(t)
5488 t = ', '.join(t)
5489 cleanworkdir = False
5489 cleanworkdir = False
5490
5490
5491 if repo.vfs.exists('updatestate'):
5491 if repo.vfs.exists('updatestate'):
5492 t += _(' (interrupted update)')
5492 t += _(' (interrupted update)')
5493 elif len(parents) > 1:
5493 elif len(parents) > 1:
5494 t += _(' (merge)')
5494 t += _(' (merge)')
5495 elif branch != parents[0].branch():
5495 elif branch != parents[0].branch():
5496 t += _(' (new branch)')
5496 t += _(' (new branch)')
5497 elif (parents[0].closesbranch() and
5497 elif (parents[0].closesbranch() and
5498 pnode in repo.branchheads(branch, closed=True)):
5498 pnode in repo.branchheads(branch, closed=True)):
5499 t += _(' (head closed)')
5499 t += _(' (head closed)')
5500 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5500 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5501 t += _(' (clean)')
5501 t += _(' (clean)')
5502 cleanworkdir = True
5502 cleanworkdir = True
5503 elif pnode not in bheads:
5503 elif pnode not in bheads:
5504 t += _(' (new branch head)')
5504 t += _(' (new branch head)')
5505
5505
5506 if cleanworkdir:
5506 if cleanworkdir:
5507 # i18n: column positioning for "hg summary"
5507 # i18n: column positioning for "hg summary"
5508 ui.status(_('commit: %s\n') % t.strip())
5508 ui.status(_('commit: %s\n') % t.strip())
5509 else:
5509 else:
5510 # i18n: column positioning for "hg summary"
5510 # i18n: column positioning for "hg summary"
5511 ui.write(_('commit: %s\n') % t.strip())
5511 ui.write(_('commit: %s\n') % t.strip())
5512
5512
5513 # all ancestors of branch heads - all ancestors of parent = new csets
5513 # all ancestors of branch heads - all ancestors of parent = new csets
5514 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5514 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5515 bheads))
5515 bheads))
5516
5516
5517 if new == 0:
5517 if new == 0:
5518 # i18n: column positioning for "hg summary"
5518 # i18n: column positioning for "hg summary"
5519 ui.status(_('update: (current)\n'))
5519 ui.status(_('update: (current)\n'))
5520 elif pnode not in bheads:
5520 elif pnode not in bheads:
5521 # i18n: column positioning for "hg summary"
5521 # i18n: column positioning for "hg summary"
5522 ui.write(_('update: %d new changesets (update)\n') % new)
5522 ui.write(_('update: %d new changesets (update)\n') % new)
5523 else:
5523 else:
5524 # i18n: column positioning for "hg summary"
5524 # i18n: column positioning for "hg summary"
5525 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5525 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5526 (new, len(bheads)))
5526 (new, len(bheads)))
5527
5527
5528 cmdutil.summaryhooks(ui, repo)
5528 cmdutil.summaryhooks(ui, repo)
5529
5529
5530 if opts.get('remote'):
5530 if opts.get('remote'):
5531 t = []
5531 t = []
5532 source, branches = hg.parseurl(ui.expandpath('default'))
5532 source, branches = hg.parseurl(ui.expandpath('default'))
5533 sbranch = branches[0]
5533 sbranch = branches[0]
5534 other = hg.peer(repo, {}, source)
5534 other = hg.peer(repo, {}, source)
5535 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5535 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5536 if revs:
5536 if revs:
5537 revs = [other.lookup(rev) for rev in revs]
5537 revs = [other.lookup(rev) for rev in revs]
5538 ui.debug('comparing with %s\n' % util.hidepassword(source))
5538 ui.debug('comparing with %s\n' % util.hidepassword(source))
5539 repo.ui.pushbuffer()
5539 repo.ui.pushbuffer()
5540 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5540 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5541 _common, incoming, _rheads = commoninc
5541 _common, incoming, _rheads = commoninc
5542 repo.ui.popbuffer()
5542 repo.ui.popbuffer()
5543 if incoming:
5543 if incoming:
5544 t.append(_('1 or more incoming'))
5544 t.append(_('1 or more incoming'))
5545
5545
5546 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5546 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5547 dbranch = branches[0]
5547 dbranch = branches[0]
5548 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5548 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5549 if source != dest:
5549 if source != dest:
5550 other = hg.peer(repo, {}, dest)
5550 other = hg.peer(repo, {}, dest)
5551 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5551 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5552 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5552 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5553 commoninc = None
5553 commoninc = None
5554 if revs:
5554 if revs:
5555 revs = [repo.lookup(rev) for rev in revs]
5555 revs = [repo.lookup(rev) for rev in revs]
5556 repo.ui.pushbuffer()
5556 repo.ui.pushbuffer()
5557 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5557 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5558 commoninc=commoninc)
5558 commoninc=commoninc)
5559 repo.ui.popbuffer()
5559 repo.ui.popbuffer()
5560 o = outgoing.missing
5560 o = outgoing.missing
5561 if o:
5561 if o:
5562 t.append(_('%d outgoing') % len(o))
5562 t.append(_('%d outgoing') % len(o))
5563 if 'bookmarks' in other.listkeys('namespaces'):
5563 if 'bookmarks' in other.listkeys('namespaces'):
5564 lmarks = repo.listkeys('bookmarks')
5564 lmarks = repo.listkeys('bookmarks')
5565 rmarks = other.listkeys('bookmarks')
5565 rmarks = other.listkeys('bookmarks')
5566 diff = set(rmarks) - set(lmarks)
5566 diff = set(rmarks) - set(lmarks)
5567 if len(diff) > 0:
5567 if len(diff) > 0:
5568 t.append(_('%d incoming bookmarks') % len(diff))
5568 t.append(_('%d incoming bookmarks') % len(diff))
5569 diff = set(lmarks) - set(rmarks)
5569 diff = set(lmarks) - set(rmarks)
5570 if len(diff) > 0:
5570 if len(diff) > 0:
5571 t.append(_('%d outgoing bookmarks') % len(diff))
5571 t.append(_('%d outgoing bookmarks') % len(diff))
5572
5572
5573 if t:
5573 if t:
5574 # i18n: column positioning for "hg summary"
5574 # i18n: column positioning for "hg summary"
5575 ui.write(_('remote: %s\n') % (', '.join(t)))
5575 ui.write(_('remote: %s\n') % (', '.join(t)))
5576 else:
5576 else:
5577 # i18n: column positioning for "hg summary"
5577 # i18n: column positioning for "hg summary"
5578 ui.status(_('remote: (synced)\n'))
5578 ui.status(_('remote: (synced)\n'))
5579
5579
5580 @command('tag',
5580 @command('tag',
5581 [('f', 'force', None, _('force tag')),
5581 [('f', 'force', None, _('force tag')),
5582 ('l', 'local', None, _('make the tag local')),
5582 ('l', 'local', None, _('make the tag local')),
5583 ('r', 'rev', '', _('revision to tag'), _('REV')),
5583 ('r', 'rev', '', _('revision to tag'), _('REV')),
5584 ('', 'remove', None, _('remove a tag')),
5584 ('', 'remove', None, _('remove a tag')),
5585 # -l/--local is already there, commitopts cannot be used
5585 # -l/--local is already there, commitopts cannot be used
5586 ('e', 'edit', None, _('edit commit message')),
5586 ('e', 'edit', None, _('edit commit message')),
5587 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5587 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5588 ] + commitopts2,
5588 ] + commitopts2,
5589 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5589 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5590 def tag(ui, repo, name1, *names, **opts):
5590 def tag(ui, repo, name1, *names, **opts):
5591 """add one or more tags for the current or given revision
5591 """add one or more tags for the current or given revision
5592
5592
5593 Name a particular revision using <name>.
5593 Name a particular revision using <name>.
5594
5594
5595 Tags are used to name particular revisions of the repository and are
5595 Tags are used to name particular revisions of the repository and are
5596 very useful to compare different revisions, to go back to significant
5596 very useful to compare different revisions, to go back to significant
5597 earlier versions or to mark branch points as releases, etc. Changing
5597 earlier versions or to mark branch points as releases, etc. Changing
5598 an existing tag is normally disallowed; use -f/--force to override.
5598 an existing tag is normally disallowed; use -f/--force to override.
5599
5599
5600 If no revision is given, the parent of the working directory is
5600 If no revision is given, the parent of the working directory is
5601 used.
5601 used.
5602
5602
5603 To facilitate version control, distribution, and merging of tags,
5603 To facilitate version control, distribution, and merging of tags,
5604 they are stored as a file named ".hgtags" which is managed similarly
5604 they are stored as a file named ".hgtags" which is managed similarly
5605 to other project files and can be hand-edited if necessary. This
5605 to other project files and can be hand-edited if necessary. This
5606 also means that tagging creates a new commit. The file
5606 also means that tagging creates a new commit. The file
5607 ".hg/localtags" is used for local tags (not shared among
5607 ".hg/localtags" is used for local tags (not shared among
5608 repositories).
5608 repositories).
5609
5609
5610 Tag commits are usually made at the head of a branch. If the parent
5610 Tag commits are usually made at the head of a branch. If the parent
5611 of the working directory is not a branch head, :hg:`tag` aborts; use
5611 of the working directory is not a branch head, :hg:`tag` aborts; use
5612 -f/--force to force the tag commit to be based on a non-head
5612 -f/--force to force the tag commit to be based on a non-head
5613 changeset.
5613 changeset.
5614
5614
5615 See :hg:`help dates` for a list of formats valid for -d/--date.
5615 See :hg:`help dates` for a list of formats valid for -d/--date.
5616
5616
5617 Since tag names have priority over branch names during revision
5617 Since tag names have priority over branch names during revision
5618 lookup, using an existing branch name as a tag name is discouraged.
5618 lookup, using an existing branch name as a tag name is discouraged.
5619
5619
5620 Returns 0 on success.
5620 Returns 0 on success.
5621 """
5621 """
5622 wlock = lock = None
5622 wlock = lock = None
5623 try:
5623 try:
5624 wlock = repo.wlock()
5624 wlock = repo.wlock()
5625 lock = repo.lock()
5625 lock = repo.lock()
5626 rev_ = "."
5626 rev_ = "."
5627 names = [t.strip() for t in (name1,) + names]
5627 names = [t.strip() for t in (name1,) + names]
5628 if len(names) != len(set(names)):
5628 if len(names) != len(set(names)):
5629 raise util.Abort(_('tag names must be unique'))
5629 raise util.Abort(_('tag names must be unique'))
5630 for n in names:
5630 for n in names:
5631 scmutil.checknewlabel(repo, n, 'tag')
5631 scmutil.checknewlabel(repo, n, 'tag')
5632 if not n:
5632 if not n:
5633 raise util.Abort(_('tag names cannot consist entirely of '
5633 raise util.Abort(_('tag names cannot consist entirely of '
5634 'whitespace'))
5634 'whitespace'))
5635 if opts.get('rev') and opts.get('remove'):
5635 if opts.get('rev') and opts.get('remove'):
5636 raise util.Abort(_("--rev and --remove are incompatible"))
5636 raise util.Abort(_("--rev and --remove are incompatible"))
5637 if opts.get('rev'):
5637 if opts.get('rev'):
5638 rev_ = opts['rev']
5638 rev_ = opts['rev']
5639 message = opts.get('message')
5639 message = opts.get('message')
5640 if opts.get('remove'):
5640 if opts.get('remove'):
5641 expectedtype = opts.get('local') and 'local' or 'global'
5641 expectedtype = opts.get('local') and 'local' or 'global'
5642 for n in names:
5642 for n in names:
5643 if not repo.tagtype(n):
5643 if not repo.tagtype(n):
5644 raise util.Abort(_("tag '%s' does not exist") % n)
5644 raise util.Abort(_("tag '%s' does not exist") % n)
5645 if repo.tagtype(n) != expectedtype:
5645 if repo.tagtype(n) != expectedtype:
5646 if expectedtype == 'global':
5646 if expectedtype == 'global':
5647 raise util.Abort(_("tag '%s' is not a global tag") % n)
5647 raise util.Abort(_("tag '%s' is not a global tag") % n)
5648 else:
5648 else:
5649 raise util.Abort(_("tag '%s' is not a local tag") % n)
5649 raise util.Abort(_("tag '%s' is not a local tag") % n)
5650 rev_ = nullid
5650 rev_ = nullid
5651 if not message:
5651 if not message:
5652 # we don't translate commit messages
5652 # we don't translate commit messages
5653 message = 'Removed tag %s' % ', '.join(names)
5653 message = 'Removed tag %s' % ', '.join(names)
5654 elif not opts.get('force'):
5654 elif not opts.get('force'):
5655 for n in names:
5655 for n in names:
5656 if n in repo.tags():
5656 if n in repo.tags():
5657 raise util.Abort(_("tag '%s' already exists "
5657 raise util.Abort(_("tag '%s' already exists "
5658 "(use -f to force)") % n)
5658 "(use -f to force)") % n)
5659 if not opts.get('local'):
5659 if not opts.get('local'):
5660 p1, p2 = repo.dirstate.parents()
5660 p1, p2 = repo.dirstate.parents()
5661 if p2 != nullid:
5661 if p2 != nullid:
5662 raise util.Abort(_('uncommitted merge'))
5662 raise util.Abort(_('uncommitted merge'))
5663 bheads = repo.branchheads()
5663 bheads = repo.branchheads()
5664 if not opts.get('force') and bheads and p1 not in bheads:
5664 if not opts.get('force') and bheads and p1 not in bheads:
5665 raise util.Abort(_('not at a branch head (use -f to force)'))
5665 raise util.Abort(_('not at a branch head (use -f to force)'))
5666 r = scmutil.revsingle(repo, rev_).node()
5666 r = scmutil.revsingle(repo, rev_).node()
5667
5667
5668 if not message:
5668 if not message:
5669 # we don't translate commit messages
5669 # we don't translate commit messages
5670 message = ('Added tag %s for changeset %s' %
5670 message = ('Added tag %s for changeset %s' %
5671 (', '.join(names), short(r)))
5671 (', '.join(names), short(r)))
5672
5672
5673 date = opts.get('date')
5673 date = opts.get('date')
5674 if date:
5674 if date:
5675 date = util.parsedate(date)
5675 date = util.parsedate(date)
5676
5676
5677 if opts.get('edit'):
5677 if opts.get('edit'):
5678 message = ui.edit(message, ui.username())
5678 message = ui.edit(message, ui.username())
5679
5679
5680 # don't allow tagging the null rev
5680 # don't allow tagging the null rev
5681 if (not opts.get('remove') and
5681 if (not opts.get('remove') and
5682 scmutil.revsingle(repo, rev_).rev() == nullrev):
5682 scmutil.revsingle(repo, rev_).rev() == nullrev):
5683 raise util.Abort(_("cannot tag null revision"))
5683 raise util.Abort(_("cannot tag null revision"))
5684
5684
5685 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5685 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5686 finally:
5686 finally:
5687 release(lock, wlock)
5687 release(lock, wlock)
5688
5688
5689 @command('tags', [], '')
5689 @command('tags', [], '')
5690 def tags(ui, repo, **opts):
5690 def tags(ui, repo, **opts):
5691 """list repository tags
5691 """list repository tags
5692
5692
5693 This lists both regular and local tags. When the -v/--verbose
5693 This lists both regular and local tags. When the -v/--verbose
5694 switch is used, a third column "local" is printed for local tags.
5694 switch is used, a third column "local" is printed for local tags.
5695
5695
5696 Returns 0 on success.
5696 Returns 0 on success.
5697 """
5697 """
5698
5698
5699 fm = ui.formatter('tags', opts)
5699 fm = ui.formatter('tags', opts)
5700 hexfunc = ui.debugflag and hex or short
5700 hexfunc = ui.debugflag and hex or short
5701 tagtype = ""
5701 tagtype = ""
5702
5702
5703 for t, n in reversed(repo.tagslist()):
5703 for t, n in reversed(repo.tagslist()):
5704 hn = hexfunc(n)
5704 hn = hexfunc(n)
5705 label = 'tags.normal'
5705 label = 'tags.normal'
5706 tagtype = ''
5706 tagtype = ''
5707 if repo.tagtype(t) == 'local':
5707 if repo.tagtype(t) == 'local':
5708 label = 'tags.local'
5708 label = 'tags.local'
5709 tagtype = 'local'
5709 tagtype = 'local'
5710
5710
5711 fm.startitem()
5711 fm.startitem()
5712 fm.write('tag', '%s', t, label=label)
5712 fm.write('tag', '%s', t, label=label)
5713 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5713 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5714 fm.condwrite(not ui.quiet, 'rev id', fmt,
5714 fm.condwrite(not ui.quiet, 'rev id', fmt,
5715 repo.changelog.rev(n), hn, label=label)
5715 repo.changelog.rev(n), hn, label=label)
5716 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5716 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5717 tagtype, label=label)
5717 tagtype, label=label)
5718 fm.plain('\n')
5718 fm.plain('\n')
5719 fm.end()
5719 fm.end()
5720
5720
5721 @command('tip',
5721 @command('tip',
5722 [('p', 'patch', None, _('show patch')),
5722 [('p', 'patch', None, _('show patch')),
5723 ('g', 'git', None, _('use git extended diff format')),
5723 ('g', 'git', None, _('use git extended diff format')),
5724 ] + templateopts,
5724 ] + templateopts,
5725 _('[-p] [-g]'))
5725 _('[-p] [-g]'))
5726 def tip(ui, repo, **opts):
5726 def tip(ui, repo, **opts):
5727 """show the tip revision (DEPRECATED)
5727 """show the tip revision (DEPRECATED)
5728
5728
5729 The tip revision (usually just called the tip) is the changeset
5729 The tip revision (usually just called the tip) is the changeset
5730 most recently added to the repository (and therefore the most
5730 most recently added to the repository (and therefore the most
5731 recently changed head).
5731 recently changed head).
5732
5732
5733 If you have just made a commit, that commit will be the tip. If
5733 If you have just made a commit, that commit will be the tip. If
5734 you have just pulled changes from another repository, the tip of
5734 you have just pulled changes from another repository, the tip of
5735 that repository becomes the current tip. The "tip" tag is special
5735 that repository becomes the current tip. The "tip" tag is special
5736 and cannot be renamed or assigned to a different changeset.
5736 and cannot be renamed or assigned to a different changeset.
5737
5737
5738 This command is deprecated, please use :hg:`heads` instead.
5738 This command is deprecated, please use :hg:`heads` instead.
5739
5739
5740 Returns 0 on success.
5740 Returns 0 on success.
5741 """
5741 """
5742 displayer = cmdutil.show_changeset(ui, repo, opts)
5742 displayer = cmdutil.show_changeset(ui, repo, opts)
5743 displayer.show(repo['tip'])
5743 displayer.show(repo['tip'])
5744 displayer.close()
5744 displayer.close()
5745
5745
5746 @command('unbundle',
5746 @command('unbundle',
5747 [('u', 'update', None,
5747 [('u', 'update', None,
5748 _('update to new branch head if changesets were unbundled'))],
5748 _('update to new branch head if changesets were unbundled'))],
5749 _('[-u] FILE...'))
5749 _('[-u] FILE...'))
5750 def unbundle(ui, repo, fname1, *fnames, **opts):
5750 def unbundle(ui, repo, fname1, *fnames, **opts):
5751 """apply one or more changegroup files
5751 """apply one or more changegroup files
5752
5752
5753 Apply one or more compressed changegroup files generated by the
5753 Apply one or more compressed changegroup files generated by the
5754 bundle command.
5754 bundle command.
5755
5755
5756 Returns 0 on success, 1 if an update has unresolved files.
5756 Returns 0 on success, 1 if an update has unresolved files.
5757 """
5757 """
5758 fnames = (fname1,) + fnames
5758 fnames = (fname1,) + fnames
5759
5759
5760 lock = repo.lock()
5760 lock = repo.lock()
5761 wc = repo['.']
5761 wc = repo['.']
5762 try:
5762 try:
5763 for fname in fnames:
5763 for fname in fnames:
5764 f = hg.openpath(ui, fname)
5764 f = hg.openpath(ui, fname)
5765 gen = changegroup.readbundle(f, fname)
5765 gen = changegroup.readbundle(f, fname)
5766 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5766 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5767 finally:
5767 finally:
5768 lock.release()
5768 lock.release()
5769 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5769 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5770 return postincoming(ui, repo, modheads, opts.get('update'), None)
5770 return postincoming(ui, repo, modheads, opts.get('update'), None)
5771
5771
5772 @command('^update|up|checkout|co',
5772 @command('^update|up|checkout|co',
5773 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5773 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5774 ('c', 'check', None,
5774 ('c', 'check', None,
5775 _('update across branches if no uncommitted changes')),
5775 _('update across branches if no uncommitted changes')),
5776 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5776 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5777 ('r', 'rev', '', _('revision'), _('REV'))],
5777 ('r', 'rev', '', _('revision'), _('REV'))],
5778 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5778 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5779 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5779 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5780 """update working directory (or switch revisions)
5780 """update working directory (or switch revisions)
5781
5781
5782 Update the repository's working directory to the specified
5782 Update the repository's working directory to the specified
5783 changeset. If no changeset is specified, update to the tip of the
5783 changeset. If no changeset is specified, update to the tip of the
5784 current named branch and move the current bookmark (see :hg:`help
5784 current named branch and move the current bookmark (see :hg:`help
5785 bookmarks`).
5785 bookmarks`).
5786
5786
5787 Update sets the working directory's parent revision to the specified
5787 Update sets the working directory's parent revision to the specified
5788 changeset (see :hg:`help parents`).
5788 changeset (see :hg:`help parents`).
5789
5789
5790 If the changeset is not a descendant or ancestor of the working
5790 If the changeset is not a descendant or ancestor of the working
5791 directory's parent, the update is aborted. With the -c/--check
5791 directory's parent, the update is aborted. With the -c/--check
5792 option, the working directory is checked for uncommitted changes; if
5792 option, the working directory is checked for uncommitted changes; if
5793 none are found, the working directory is updated to the specified
5793 none are found, the working directory is updated to the specified
5794 changeset.
5794 changeset.
5795
5795
5796 .. container:: verbose
5796 .. container:: verbose
5797
5797
5798 The following rules apply when the working directory contains
5798 The following rules apply when the working directory contains
5799 uncommitted changes:
5799 uncommitted changes:
5800
5800
5801 1. If neither -c/--check nor -C/--clean is specified, and if
5801 1. If neither -c/--check nor -C/--clean is specified, and if
5802 the requested changeset is an ancestor or descendant of
5802 the requested changeset is an ancestor or descendant of
5803 the working directory's parent, the uncommitted changes
5803 the working directory's parent, the uncommitted changes
5804 are merged into the requested changeset and the merged
5804 are merged into the requested changeset and the merged
5805 result is left uncommitted. If the requested changeset is
5805 result is left uncommitted. If the requested changeset is
5806 not an ancestor or descendant (that is, it is on another
5806 not an ancestor or descendant (that is, it is on another
5807 branch), the update is aborted and the uncommitted changes
5807 branch), the update is aborted and the uncommitted changes
5808 are preserved.
5808 are preserved.
5809
5809
5810 2. With the -c/--check option, the update is aborted and the
5810 2. With the -c/--check option, the update is aborted and the
5811 uncommitted changes are preserved.
5811 uncommitted changes are preserved.
5812
5812
5813 3. With the -C/--clean option, uncommitted changes are discarded and
5813 3. With the -C/--clean option, uncommitted changes are discarded and
5814 the working directory is updated to the requested changeset.
5814 the working directory is updated to the requested changeset.
5815
5815
5816 To cancel an uncommitted merge (and lose your changes), use
5816 To cancel an uncommitted merge (and lose your changes), use
5817 :hg:`update --clean .`.
5817 :hg:`update --clean .`.
5818
5818
5819 Use null as the changeset to remove the working directory (like
5819 Use null as the changeset to remove the working directory (like
5820 :hg:`clone -U`).
5820 :hg:`clone -U`).
5821
5821
5822 If you want to revert just one file to an older revision, use
5822 If you want to revert just one file to an older revision, use
5823 :hg:`revert [-r REV] NAME`.
5823 :hg:`revert [-r REV] NAME`.
5824
5824
5825 See :hg:`help dates` for a list of formats valid for -d/--date.
5825 See :hg:`help dates` for a list of formats valid for -d/--date.
5826
5826
5827 Returns 0 on success, 1 if there are unresolved files.
5827 Returns 0 on success, 1 if there are unresolved files.
5828 """
5828 """
5829 if rev and node:
5829 if rev and node:
5830 raise util.Abort(_("please specify just one revision"))
5830 raise util.Abort(_("please specify just one revision"))
5831
5831
5832 if rev is None or rev == '':
5832 if rev is None or rev == '':
5833 rev = node
5833 rev = node
5834
5834
5835 cmdutil.clearunfinished(repo)
5835 cmdutil.clearunfinished(repo)
5836
5836
5837 # with no argument, we also move the current bookmark, if any
5837 # with no argument, we also move the current bookmark, if any
5838 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5838 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5839
5839
5840 # if we defined a bookmark, we have to remember the original bookmark name
5840 # if we defined a bookmark, we have to remember the original bookmark name
5841 brev = rev
5841 brev = rev
5842 rev = scmutil.revsingle(repo, rev, rev).rev()
5842 rev = scmutil.revsingle(repo, rev, rev).rev()
5843
5843
5844 if check and clean:
5844 if check and clean:
5845 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5845 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5846
5846
5847 if date:
5847 if date:
5848 if rev is not None:
5848 if rev is not None:
5849 raise util.Abort(_("you can't specify a revision and a date"))
5849 raise util.Abort(_("you can't specify a revision and a date"))
5850 rev = cmdutil.finddate(ui, repo, date)
5850 rev = cmdutil.finddate(ui, repo, date)
5851
5851
5852 if check:
5852 if check:
5853 c = repo[None]
5853 c = repo[None]
5854 if c.dirty(merge=False, branch=False, missing=True):
5854 if c.dirty(merge=False, branch=False, missing=True):
5855 raise util.Abort(_("uncommitted changes"))
5855 raise util.Abort(_("uncommitted changes"))
5856 if rev is None:
5856 if rev is None:
5857 rev = repo[repo[None].branch()].rev()
5857 rev = repo[repo[None].branch()].rev()
5858 mergemod._checkunknown(repo, repo[None], repo[rev])
5858 mergemod._checkunknown(repo, repo[None], repo[rev])
5859
5859
5860 if clean:
5860 if clean:
5861 ret = hg.clean(repo, rev)
5861 ret = hg.clean(repo, rev)
5862 else:
5862 else:
5863 ret = hg.update(repo, rev)
5863 ret = hg.update(repo, rev)
5864
5864
5865 if not ret and movemarkfrom:
5865 if not ret and movemarkfrom:
5866 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5866 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5867 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5867 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5868 elif brev in repo._bookmarks:
5868 elif brev in repo._bookmarks:
5869 bookmarks.setcurrent(repo, brev)
5869 bookmarks.setcurrent(repo, brev)
5870 elif brev:
5870 elif brev:
5871 bookmarks.unsetcurrent(repo)
5871 bookmarks.unsetcurrent(repo)
5872
5872
5873 return ret
5873 return ret
5874
5874
5875 @command('verify', [])
5875 @command('verify', [])
5876 def verify(ui, repo):
5876 def verify(ui, repo):
5877 """verify the integrity of the repository
5877 """verify the integrity of the repository
5878
5878
5879 Verify the integrity of the current repository.
5879 Verify the integrity of the current repository.
5880
5880
5881 This will perform an extensive check of the repository's
5881 This will perform an extensive check of the repository's
5882 integrity, validating the hashes and checksums of each entry in
5882 integrity, validating the hashes and checksums of each entry in
5883 the changelog, manifest, and tracked files, as well as the
5883 the changelog, manifest, and tracked files, as well as the
5884 integrity of their crosslinks and indices.
5884 integrity of their crosslinks and indices.
5885
5885
5886 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5886 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5887 for more information about recovery from corruption of the
5887 for more information about recovery from corruption of the
5888 repository.
5888 repository.
5889
5889
5890 Returns 0 on success, 1 if errors are encountered.
5890 Returns 0 on success, 1 if errors are encountered.
5891 """
5891 """
5892 return hg.verify(repo)
5892 return hg.verify(repo)
5893
5893
5894 @command('version', [])
5894 @command('version', [])
5895 def version_(ui):
5895 def version_(ui):
5896 """output version and copyright information"""
5896 """output version and copyright information"""
5897 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5897 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5898 % util.version())
5898 % util.version())
5899 ui.status(_(
5899 ui.status(_(
5900 "(see http://mercurial.selenic.com for more information)\n"
5900 "(see http://mercurial.selenic.com for more information)\n"
5901 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5901 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5902 "This is free software; see the source for copying conditions. "
5902 "This is free software; see the source for copying conditions. "
5903 "There is NO\nwarranty; "
5903 "There is NO\nwarranty; "
5904 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5904 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5905 ))
5905 ))
5906
5906
5907 norepo = ("clone init version help debugcommands debugcomplete"
5907 norepo = ("clone init version help debugcommands debugcomplete"
5908 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5908 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5909 " debugknown debuggetbundle debugbundle")
5909 " debugknown debuggetbundle debugbundle")
5910 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5910 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5911 " debugdata debugindex debugindexdot debugrevlog")
5911 " debugdata debugindex debugindexdot debugrevlog")
5912 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5912 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5913 " remove resolve status debugwalk")
5913 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now