##// END OF EJS Templates
commands: refactor 'serve', extract the http service class
Mads Kiilerich -
r19919:e48c7045 default
parent child Browse files
Show More
@@ -1,5912 +1,5916 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, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import phases, obsolete
21 import phases, obsolete
22
22
23 table = {}
23 table = {}
24
24
25 command = cmdutil.command(table)
25 command = cmdutil.command(table)
26
26
27 # common command options
27 # common command options
28
28
29 globalopts = [
29 globalopts = [
30 ('R', 'repository', '',
30 ('R', 'repository', '',
31 _('repository root directory or name of overlay bundle file'),
31 _('repository root directory or name of overlay bundle file'),
32 _('REPO')),
32 _('REPO')),
33 ('', 'cwd', '',
33 ('', 'cwd', '',
34 _('change working directory'), _('DIR')),
34 _('change working directory'), _('DIR')),
35 ('y', 'noninteractive', None,
35 ('y', 'noninteractive', None,
36 _('do not prompt, automatically pick the first choice for all prompts')),
36 _('do not prompt, automatically pick the first choice for all prompts')),
37 ('q', 'quiet', None, _('suppress output')),
37 ('q', 'quiet', None, _('suppress output')),
38 ('v', 'verbose', None, _('enable additional output')),
38 ('v', 'verbose', None, _('enable additional output')),
39 ('', 'config', [],
39 ('', 'config', [],
40 _('set/override config option (use \'section.name=value\')'),
40 _('set/override config option (use \'section.name=value\')'),
41 _('CONFIG')),
41 _('CONFIG')),
42 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debugger', None, _('start debugger')),
43 ('', 'debugger', None, _('start debugger')),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 _('ENCODE')),
45 _('ENCODE')),
46 ('', 'encodingmode', encoding.encodingmode,
46 ('', 'encodingmode', encoding.encodingmode,
47 _('set the charset encoding mode'), _('MODE')),
47 _('set the charset encoding mode'), _('MODE')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'time', None, _('time how long the command takes')),
49 ('', 'time', None, _('time how long the command takes')),
50 ('', 'profile', None, _('print command execution profile')),
50 ('', 'profile', None, _('print command execution profile')),
51 ('', 'version', None, _('output version information and exit')),
51 ('', 'version', None, _('output version information and exit')),
52 ('h', 'help', None, _('display help and exit')),
52 ('h', 'help', None, _('display help and exit')),
53 ('', 'hidden', False, _('consider hidden changesets')),
53 ('', 'hidden', False, _('consider hidden changesets')),
54 ]
54 ]
55
55
56 dryrunopts = [('n', 'dry-run', None,
56 dryrunopts = [('n', 'dry-run', None,
57 _('do not perform actions, just print output'))]
57 _('do not perform actions, just print output'))]
58
58
59 remoteopts = [
59 remoteopts = [
60 ('e', 'ssh', '',
60 ('e', 'ssh', '',
61 _('specify ssh command to use'), _('CMD')),
61 _('specify ssh command to use'), _('CMD')),
62 ('', 'remotecmd', '',
62 ('', 'remotecmd', '',
63 _('specify hg command to run on the remote side'), _('CMD')),
63 _('specify hg command to run on the remote side'), _('CMD')),
64 ('', 'insecure', None,
64 ('', 'insecure', None,
65 _('do not verify server certificate (ignoring web.cacerts config)')),
65 _('do not verify server certificate (ignoring web.cacerts config)')),
66 ]
66 ]
67
67
68 walkopts = [
68 walkopts = [
69 ('I', 'include', [],
69 ('I', 'include', [],
70 _('include names matching the given patterns'), _('PATTERN')),
70 _('include names matching the given patterns'), _('PATTERN')),
71 ('X', 'exclude', [],
71 ('X', 'exclude', [],
72 _('exclude names matching the given patterns'), _('PATTERN')),
72 _('exclude names matching the given patterns'), _('PATTERN')),
73 ]
73 ]
74
74
75 commitopts = [
75 commitopts = [
76 ('m', 'message', '',
76 ('m', 'message', '',
77 _('use text as commit message'), _('TEXT')),
77 _('use text as commit message'), _('TEXT')),
78 ('l', 'logfile', '',
78 ('l', 'logfile', '',
79 _('read commit message from file'), _('FILE')),
79 _('read commit message from file'), _('FILE')),
80 ]
80 ]
81
81
82 commitopts2 = [
82 commitopts2 = [
83 ('d', 'date', '',
83 ('d', 'date', '',
84 _('record the specified date as commit date'), _('DATE')),
84 _('record the specified date as commit date'), _('DATE')),
85 ('u', 'user', '',
85 ('u', 'user', '',
86 _('record the specified user as committer'), _('USER')),
86 _('record the specified user as committer'), _('USER')),
87 ]
87 ]
88
88
89 templateopts = [
89 templateopts = [
90 ('', 'style', '',
90 ('', 'style', '',
91 _('display using template map file'), _('STYLE')),
91 _('display using template map file'), _('STYLE')),
92 ('', 'template', '',
92 ('', 'template', '',
93 _('display with template'), _('TEMPLATE')),
93 _('display with template'), _('TEMPLATE')),
94 ]
94 ]
95
95
96 logopts = [
96 logopts = [
97 ('p', 'patch', None, _('show patch')),
97 ('p', 'patch', None, _('show patch')),
98 ('g', 'git', None, _('use git extended diff format')),
98 ('g', 'git', None, _('use git extended diff format')),
99 ('l', 'limit', '',
99 ('l', 'limit', '',
100 _('limit number of changes displayed'), _('NUM')),
100 _('limit number of changes displayed'), _('NUM')),
101 ('M', 'no-merges', None, _('do not show merges')),
101 ('M', 'no-merges', None, _('do not show merges')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('G', 'graph', None, _("show the revision DAG")),
103 ('G', 'graph', None, _("show the revision DAG")),
104 ] + templateopts
104 ] + templateopts
105
105
106 diffopts = [
106 diffopts = [
107 ('a', 'text', None, _('treat all files as text')),
107 ('a', 'text', None, _('treat all files as text')),
108 ('g', 'git', None, _('use git extended diff format')),
108 ('g', 'git', None, _('use git extended diff format')),
109 ('', 'nodates', None, _('omit dates from diff headers'))
109 ('', 'nodates', None, _('omit dates from diff headers'))
110 ]
110 ]
111
111
112 diffwsopts = [
112 diffwsopts = [
113 ('w', 'ignore-all-space', None,
113 ('w', 'ignore-all-space', None,
114 _('ignore white space when comparing lines')),
114 _('ignore white space when comparing lines')),
115 ('b', 'ignore-space-change', None,
115 ('b', 'ignore-space-change', None,
116 _('ignore changes in the amount of white space')),
116 _('ignore changes in the amount of white space')),
117 ('B', 'ignore-blank-lines', None,
117 ('B', 'ignore-blank-lines', None,
118 _('ignore changes whose lines are all blank')),
118 _('ignore changes whose lines are all blank')),
119 ]
119 ]
120
120
121 diffopts2 = [
121 diffopts2 = [
122 ('p', 'show-function', None, _('show which function each change is in')),
122 ('p', 'show-function', None, _('show which function each change is in')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ] + diffwsopts + [
124 ] + diffwsopts + [
125 ('U', 'unified', '',
125 ('U', 'unified', '',
126 _('number of lines of context to show'), _('NUM')),
126 _('number of lines of context to show'), _('NUM')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ]
128 ]
129
129
130 mergetoolopts = [
130 mergetoolopts = [
131 ('t', 'tool', '', _('specify merge tool')),
131 ('t', 'tool', '', _('specify merge tool')),
132 ]
132 ]
133
133
134 similarityopts = [
134 similarityopts = [
135 ('s', 'similarity', '',
135 ('s', 'similarity', '',
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 ]
137 ]
138
138
139 subrepoopts = [
139 subrepoopts = [
140 ('S', 'subrepos', None,
140 ('S', 'subrepos', None,
141 _('recurse into subrepositories'))
141 _('recurse into subrepositories'))
142 ]
142 ]
143
143
144 # Commands start here, listed alphabetically
144 # Commands start here, listed alphabetically
145
145
146 @command('^add',
146 @command('^add',
147 walkopts + subrepoopts + dryrunopts,
147 walkopts + subrepoopts + dryrunopts,
148 _('[OPTION]... [FILE]...'))
148 _('[OPTION]... [FILE]...'))
149 def add(ui, repo, *pats, **opts):
149 def add(ui, repo, *pats, **opts):
150 """add the specified files on the next commit
150 """add the specified files on the next commit
151
151
152 Schedule files to be version controlled and added to the
152 Schedule files to be version controlled and added to the
153 repository.
153 repository.
154
154
155 The files will be added to the repository at the next commit. To
155 The files will be added to the repository at the next commit. To
156 undo an add before that, see :hg:`forget`.
156 undo an add before that, see :hg:`forget`.
157
157
158 If no names are given, add all files to the repository.
158 If no names are given, add all files to the repository.
159
159
160 .. container:: verbose
160 .. container:: verbose
161
161
162 An example showing how new (unknown) files are added
162 An example showing how new (unknown) files are added
163 automatically by :hg:`add`::
163 automatically by :hg:`add`::
164
164
165 $ ls
165 $ ls
166 foo.c
166 foo.c
167 $ hg status
167 $ hg status
168 ? foo.c
168 ? foo.c
169 $ hg add
169 $ hg add
170 adding foo.c
170 adding foo.c
171 $ hg status
171 $ hg status
172 A foo.c
172 A foo.c
173
173
174 Returns 0 if all files are successfully added.
174 Returns 0 if all files are successfully added.
175 """
175 """
176
176
177 m = scmutil.match(repo[None], pats, opts)
177 m = scmutil.match(repo[None], pats, opts)
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 opts.get('subrepos'), prefix="", explicitonly=False)
179 opts.get('subrepos'), prefix="", explicitonly=False)
180 return rejected and 1 or 0
180 return rejected and 1 or 0
181
181
182 @command('addremove',
182 @command('addremove',
183 similarityopts + walkopts + dryrunopts,
183 similarityopts + walkopts + dryrunopts,
184 _('[OPTION]... [FILE]...'))
184 _('[OPTION]... [FILE]...'))
185 def addremove(ui, repo, *pats, **opts):
185 def addremove(ui, repo, *pats, **opts):
186 """add all new files, delete all missing files
186 """add all new files, delete all missing files
187
187
188 Add all new files and remove all missing files from the
188 Add all new files and remove all missing files from the
189 repository.
189 repository.
190
190
191 New files are ignored if they match any of the patterns in
191 New files are ignored if they match any of the patterns in
192 ``.hgignore``. As with add, these changes take effect at the next
192 ``.hgignore``. As with add, these changes take effect at the next
193 commit.
193 commit.
194
194
195 Use the -s/--similarity option to detect renamed files. This
195 Use the -s/--similarity option to detect renamed files. This
196 option takes a percentage between 0 (disabled) and 100 (files must
196 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. With a parameter greater than 0,
197 be identical) as its parameter. With a parameter greater than 0,
198 this compares every removed file with every added file and records
198 this compares every removed file with every added file and records
199 those similar enough as renames. Detecting renamed files this way
199 those similar enough as renames. Detecting renamed files this way
200 can be expensive. After using this option, :hg:`status -C` can be
200 can be expensive. After using this option, :hg:`status -C` can be
201 used to check which files were identified as moved or renamed. If
201 used to check which files were identified as moved or renamed. If
202 not specified, -s/--similarity defaults to 100 and only renames of
202 not specified, -s/--similarity defaults to 100 and only renames of
203 identical files are detected.
203 identical files are detected.
204
204
205 Returns 0 if all files are successfully added.
205 Returns 0 if all files are successfully added.
206 """
206 """
207 try:
207 try:
208 sim = float(opts.get('similarity') or 100)
208 sim = float(opts.get('similarity') or 100)
209 except ValueError:
209 except ValueError:
210 raise util.Abort(_('similarity must be a number'))
210 raise util.Abort(_('similarity must be a number'))
211 if sim < 0 or sim > 100:
211 if sim < 0 or sim > 100:
212 raise util.Abort(_('similarity must be between 0 and 100'))
212 raise util.Abort(_('similarity must be between 0 and 100'))
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214
214
215 @command('^annotate|blame',
215 @command('^annotate|blame',
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 ('', 'follow', None,
217 ('', 'follow', None,
218 _('follow copies/renames and list the filename (DEPRECATED)')),
218 _('follow copies/renames and list the filename (DEPRECATED)')),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('a', 'text', None, _('treat all files as text')),
220 ('a', 'text', None, _('treat all files as text')),
221 ('u', 'user', None, _('list the author (long with -v)')),
221 ('u', 'user', None, _('list the author (long with -v)')),
222 ('f', 'file', None, _('list the filename')),
222 ('f', 'file', None, _('list the filename')),
223 ('d', 'date', None, _('list the date (short with -q)')),
223 ('d', 'date', None, _('list the date (short with -q)')),
224 ('n', 'number', None, _('list the revision number (default)')),
224 ('n', 'number', None, _('list the revision number (default)')),
225 ('c', 'changeset', None, _('list the changeset')),
225 ('c', 'changeset', None, _('list the changeset')),
226 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ] + diffwsopts + walkopts,
227 ] + diffwsopts + walkopts,
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 def annotate(ui, repo, *pats, **opts):
229 def annotate(ui, repo, *pats, **opts):
230 """show changeset information by line for each file
230 """show changeset information by line for each file
231
231
232 List changes in files, showing the revision id responsible for
232 List changes in files, showing the revision id responsible for
233 each line
233 each line
234
234
235 This command is useful for discovering when a change was made and
235 This command is useful for discovering when a change was made and
236 by whom.
236 by whom.
237
237
238 Without the -a/--text option, annotate will avoid processing files
238 Without the -a/--text option, annotate will avoid processing files
239 it detects as binary. With -a, annotate will annotate the file
239 it detects as binary. With -a, annotate will annotate the file
240 anyway, although the results will probably be neither useful
240 anyway, although the results will probably be neither useful
241 nor desirable.
241 nor desirable.
242
242
243 Returns 0 on success.
243 Returns 0 on success.
244 """
244 """
245 if opts.get('follow'):
245 if opts.get('follow'):
246 # --follow is deprecated and now just an alias for -f/--file
246 # --follow is deprecated and now just an alias for -f/--file
247 # to mimic the behavior of Mercurial before version 1.5
247 # to mimic the behavior of Mercurial before version 1.5
248 opts['file'] = True
248 opts['file'] = True
249
249
250 datefunc = ui.quiet and util.shortdate or util.datestr
250 datefunc = ui.quiet and util.shortdate or util.datestr
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252
252
253 if not pats:
253 if not pats:
254 raise util.Abort(_('at least one filename or pattern is required'))
254 raise util.Abort(_('at least one filename or pattern is required'))
255
255
256 hexfn = ui.debugflag and hex or short
256 hexfn = ui.debugflag and hex or short
257
257
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 ('number', ' ', lambda x: str(x[0].rev())),
259 ('number', ' ', lambda x: str(x[0].rev())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('date', ' ', getdate),
261 ('date', ' ', getdate),
262 ('file', ' ', lambda x: x[0].path()),
262 ('file', ' ', lambda x: x[0].path()),
263 ('line_number', ':', lambda x: str(x[1])),
263 ('line_number', ':', lambda x: str(x[1])),
264 ]
264 ]
265
265
266 if (not opts.get('user') and not opts.get('changeset')
266 if (not opts.get('user') and not opts.get('changeset')
267 and not opts.get('date') and not opts.get('file')):
267 and not opts.get('date') and not opts.get('file')):
268 opts['number'] = True
268 opts['number'] = True
269
269
270 linenumber = opts.get('line_number') is not None
270 linenumber = opts.get('line_number') is not None
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
273
273
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276
276
277 def bad(x, y):
277 def bad(x, y):
278 raise util.Abort("%s: %s" % (x, y))
278 raise util.Abort("%s: %s" % (x, y))
279
279
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 m = scmutil.match(ctx, pats, opts)
281 m = scmutil.match(ctx, pats, opts)
282 m.bad = bad
282 m.bad = bad
283 follow = not opts.get('no_follow')
283 follow = not opts.get('no_follow')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
285 for abs in ctx.walk(m):
285 for abs in ctx.walk(m):
286 fctx = ctx[abs]
286 fctx = ctx[abs]
287 if not opts.get('text') and util.binary(fctx.data()):
287 if not opts.get('text') and util.binary(fctx.data()):
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 continue
289 continue
290
290
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 diffopts=diffopts)
292 diffopts=diffopts)
293 pieces = []
293 pieces = []
294
294
295 for f, sep in funcmap:
295 for f, sep in funcmap:
296 l = [f(n) for n, dummy in lines]
296 l = [f(n) for n, dummy in lines]
297 if l:
297 if l:
298 sized = [(x, encoding.colwidth(x)) for x in l]
298 sized = [(x, encoding.colwidth(x)) for x in l]
299 ml = max([w for x, w in sized])
299 ml = max([w for x, w in sized])
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 for x, w in sized])
301 for x, w in sized])
302
302
303 if pieces:
303 if pieces:
304 for p, l in zip(zip(*pieces), lines):
304 for p, l in zip(zip(*pieces), lines):
305 ui.write("%s: %s" % ("".join(p), l[1]))
305 ui.write("%s: %s" % ("".join(p), l[1]))
306
306
307 if lines and not lines[-1][1].endswith('\n'):
307 if lines and not lines[-1][1].endswith('\n'):
308 ui.write('\n')
308 ui.write('\n')
309
309
310 @command('archive',
310 @command('archive',
311 [('', 'no-decode', None, _('do not pass files through decoders')),
311 [('', 'no-decode', None, _('do not pass files through decoders')),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 _('PREFIX')),
313 _('PREFIX')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ] + subrepoopts + walkopts,
316 ] + subrepoopts + walkopts,
317 _('[OPTION]... DEST'))
317 _('[OPTION]... DEST'))
318 def archive(ui, repo, dest, **opts):
318 def archive(ui, repo, dest, **opts):
319 '''create an unversioned archive of a repository revision
319 '''create an unversioned archive of a repository revision
320
320
321 By default, the revision used is the parent of the working
321 By default, the revision used is the parent of the working
322 directory; use -r/--rev to specify a different revision.
322 directory; use -r/--rev to specify a different revision.
323
323
324 The archive type is automatically detected based on file
324 The archive type is automatically detected based on file
325 extension (or override using -t/--type).
325 extension (or override using -t/--type).
326
326
327 .. container:: verbose
327 .. container:: verbose
328
328
329 Examples:
329 Examples:
330
330
331 - create a zip file containing the 1.0 release::
331 - create a zip file containing the 1.0 release::
332
332
333 hg archive -r 1.0 project-1.0.zip
333 hg archive -r 1.0 project-1.0.zip
334
334
335 - create a tarball excluding .hg files::
335 - create a tarball excluding .hg files::
336
336
337 hg archive project.tar.gz -X ".hg*"
337 hg archive project.tar.gz -X ".hg*"
338
338
339 Valid types are:
339 Valid types are:
340
340
341 :``files``: a directory full of files (default)
341 :``files``: a directory full of files (default)
342 :``tar``: tar archive, uncompressed
342 :``tar``: tar archive, uncompressed
343 :``tbz2``: tar archive, compressed using bzip2
343 :``tbz2``: tar archive, compressed using bzip2
344 :``tgz``: tar archive, compressed using gzip
344 :``tgz``: tar archive, compressed using gzip
345 :``uzip``: zip archive, uncompressed
345 :``uzip``: zip archive, uncompressed
346 :``zip``: zip archive, compressed using deflate
346 :``zip``: zip archive, compressed using deflate
347
347
348 The exact name of the destination archive or directory is given
348 The exact name of the destination archive or directory is given
349 using a format string; see :hg:`help export` for details.
349 using a format string; see :hg:`help export` for details.
350
350
351 Each member added to an archive file has a directory prefix
351 Each member added to an archive file has a directory prefix
352 prepended. Use -p/--prefix to specify a format string for the
352 prepended. Use -p/--prefix to specify a format string for the
353 prefix. The default is the basename of the archive, with suffixes
353 prefix. The default is the basename of the archive, with suffixes
354 removed.
354 removed.
355
355
356 Returns 0 on success.
356 Returns 0 on success.
357 '''
357 '''
358
358
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 if not ctx:
360 if not ctx:
361 raise util.Abort(_('no working directory: please specify a revision'))
361 raise util.Abort(_('no working directory: please specify a revision'))
362 node = ctx.node()
362 node = ctx.node()
363 dest = cmdutil.makefilename(repo, dest, node)
363 dest = cmdutil.makefilename(repo, dest, node)
364 if os.path.realpath(dest) == repo.root:
364 if os.path.realpath(dest) == repo.root:
365 raise util.Abort(_('repository root cannot be destination'))
365 raise util.Abort(_('repository root cannot be destination'))
366
366
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 prefix = opts.get('prefix')
368 prefix = opts.get('prefix')
369
369
370 if dest == '-':
370 if dest == '-':
371 if kind == 'files':
371 if kind == 'files':
372 raise util.Abort(_('cannot archive plain files to stdout'))
372 raise util.Abort(_('cannot archive plain files to stdout'))
373 dest = cmdutil.makefileobj(repo, dest)
373 dest = cmdutil.makefileobj(repo, dest)
374 if not prefix:
374 if not prefix:
375 prefix = os.path.basename(repo.root) + '-%h'
375 prefix = os.path.basename(repo.root) + '-%h'
376
376
377 prefix = cmdutil.makefilename(repo, prefix, node)
377 prefix = cmdutil.makefilename(repo, prefix, node)
378 matchfn = scmutil.match(ctx, [], opts)
378 matchfn = scmutil.match(ctx, [], opts)
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 matchfn, prefix, subrepos=opts.get('subrepos'))
380 matchfn, prefix, subrepos=opts.get('subrepos'))
381
381
382 @command('backout',
382 @command('backout',
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 ('', 'parent', '',
384 ('', 'parent', '',
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 _('[OPTION]... [-r] REV'))
388 _('[OPTION]... [-r] REV'))
389 def backout(ui, repo, node=None, rev=None, **opts):
389 def backout(ui, repo, node=None, rev=None, **opts):
390 '''reverse effect of earlier changeset
390 '''reverse effect of earlier changeset
391
391
392 Prepare a new changeset with the effect of REV undone in the
392 Prepare a new changeset with the effect of REV undone in the
393 current working directory.
393 current working directory.
394
394
395 If REV is the parent of the working directory, then this new changeset
395 If REV is the parent of the working directory, then this new changeset
396 is committed automatically. Otherwise, hg needs to merge the
396 is committed automatically. Otherwise, hg needs to merge the
397 changes and the merged result is left uncommitted.
397 changes and the merged result is left uncommitted.
398
398
399 .. note::
399 .. note::
400 backout cannot be used to fix either an unwanted or
400 backout cannot be used to fix either an unwanted or
401 incorrect merge.
401 incorrect merge.
402
402
403 .. container:: verbose
403 .. container:: verbose
404
404
405 By default, the pending changeset will have one parent,
405 By default, the pending changeset will have one parent,
406 maintaining a linear history. With --merge, the pending
406 maintaining a linear history. With --merge, the pending
407 changeset will instead have two parents: the old parent of the
407 changeset will instead have two parents: the old parent of the
408 working directory and a new child of REV that simply undoes REV.
408 working directory and a new child of REV that simply undoes REV.
409
409
410 Before version 1.7, the behavior without --merge was equivalent
410 Before version 1.7, the behavior without --merge was equivalent
411 to specifying --merge followed by :hg:`update --clean .` to
411 to specifying --merge followed by :hg:`update --clean .` to
412 cancel the merge and leave the child of REV as a head to be
412 cancel the merge and leave the child of REV as a head to be
413 merged separately.
413 merged separately.
414
414
415 See :hg:`help dates` for a list of formats valid for -d/--date.
415 See :hg:`help dates` for a list of formats valid for -d/--date.
416
416
417 Returns 0 on success.
417 Returns 0 on success.
418 '''
418 '''
419 if rev and node:
419 if rev and node:
420 raise util.Abort(_("please specify just one revision"))
420 raise util.Abort(_("please specify just one revision"))
421
421
422 if not rev:
422 if not rev:
423 rev = node
423 rev = node
424
424
425 if not rev:
425 if not rev:
426 raise util.Abort(_("please specify a revision to backout"))
426 raise util.Abort(_("please specify a revision to backout"))
427
427
428 date = opts.get('date')
428 date = opts.get('date')
429 if date:
429 if date:
430 opts['date'] = util.parsedate(date)
430 opts['date'] = util.parsedate(date)
431
431
432 cmdutil.checkunfinished(repo)
432 cmdutil.checkunfinished(repo)
433 cmdutil.bailifchanged(repo)
433 cmdutil.bailifchanged(repo)
434 node = scmutil.revsingle(repo, rev).node()
434 node = scmutil.revsingle(repo, rev).node()
435
435
436 op1, op2 = repo.dirstate.parents()
436 op1, op2 = repo.dirstate.parents()
437 a = repo.changelog.ancestor(op1, node)
437 a = repo.changelog.ancestor(op1, node)
438 if a != node:
438 if a != node:
439 raise util.Abort(_('cannot backout change on a different branch'))
439 raise util.Abort(_('cannot backout change on a different branch'))
440
440
441 p1, p2 = repo.changelog.parents(node)
441 p1, p2 = repo.changelog.parents(node)
442 if p1 == nullid:
442 if p1 == nullid:
443 raise util.Abort(_('cannot backout a change with no parents'))
443 raise util.Abort(_('cannot backout a change with no parents'))
444 if p2 != nullid:
444 if p2 != nullid:
445 if not opts.get('parent'):
445 if not opts.get('parent'):
446 raise util.Abort(_('cannot backout a merge changeset'))
446 raise util.Abort(_('cannot backout a merge changeset'))
447 p = repo.lookup(opts['parent'])
447 p = repo.lookup(opts['parent'])
448 if p not in (p1, p2):
448 if p not in (p1, p2):
449 raise util.Abort(_('%s is not a parent of %s') %
449 raise util.Abort(_('%s is not a parent of %s') %
450 (short(p), short(node)))
450 (short(p), short(node)))
451 parent = p
451 parent = p
452 else:
452 else:
453 if opts.get('parent'):
453 if opts.get('parent'):
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
455 parent = p1
455 parent = p1
456
456
457 # the backout should appear on the same branch
457 # the backout should appear on the same branch
458 wlock = repo.wlock()
458 wlock = repo.wlock()
459 try:
459 try:
460 branch = repo.dirstate.branch()
460 branch = repo.dirstate.branch()
461 bheads = repo.branchheads(branch)
461 bheads = repo.branchheads(branch)
462 hg.clean(repo, node, show_stats=False)
462 hg.clean(repo, node, show_stats=False)
463 repo.dirstate.setbranch(branch)
463 repo.dirstate.setbranch(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 e = cmdutil.commiteditor
473 e = cmdutil.commiteditor
474 if not opts['message'] and not opts['logfile']:
474 if not opts['message'] and not opts['logfile']:
475 # we don't translate commit messages
475 # we don't translate commit messages
476 opts['message'] = "Backed out changeset %s" % short(node)
476 opts['message'] = "Backed out changeset %s" % short(node)
477 e = cmdutil.commitforceeditor
477 e = cmdutil.commitforceeditor
478
478
479 def commitfunc(ui, repo, message, match, opts):
479 def commitfunc(ui, repo, message, match, opts):
480 return repo.commit(message, opts.get('user'), opts.get('date'),
480 return repo.commit(message, opts.get('user'), opts.get('date'),
481 match, editor=e)
481 match, editor=e)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
484
484
485 def nice(node):
485 def nice(node):
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
487 ui.status(_('changeset %s backs out changeset %s\n') %
487 ui.status(_('changeset %s backs out changeset %s\n') %
488 (nice(repo.changelog.tip()), nice(node)))
488 (nice(repo.changelog.tip()), nice(node)))
489 if opts.get('merge') and op1 != node:
489 if opts.get('merge') and op1 != node:
490 hg.clean(repo, op1, show_stats=False)
490 hg.clean(repo, op1, show_stats=False)
491 ui.status(_('merging with changeset %s\n')
491 ui.status(_('merging with changeset %s\n')
492 % nice(repo.changelog.tip()))
492 % nice(repo.changelog.tip()))
493 try:
493 try:
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
495 return hg.merge(repo, hex(repo.changelog.tip()))
495 return hg.merge(repo, hex(repo.changelog.tip()))
496 finally:
496 finally:
497 ui.setconfig('ui', 'forcemerge', '')
497 ui.setconfig('ui', 'forcemerge', '')
498 finally:
498 finally:
499 wlock.release()
499 wlock.release()
500 return 0
500 return 0
501
501
502 @command('bisect',
502 @command('bisect',
503 [('r', 'reset', False, _('reset bisect state')),
503 [('r', 'reset', False, _('reset bisect state')),
504 ('g', 'good', False, _('mark changeset good')),
504 ('g', 'good', False, _('mark changeset good')),
505 ('b', 'bad', False, _('mark changeset bad')),
505 ('b', 'bad', False, _('mark changeset bad')),
506 ('s', 'skip', False, _('skip testing changeset')),
506 ('s', 'skip', False, _('skip testing changeset')),
507 ('e', 'extend', False, _('extend the bisect range')),
507 ('e', 'extend', False, _('extend the bisect range')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
509 ('U', 'noupdate', False, _('do not update to target'))],
509 ('U', 'noupdate', False, _('do not update to target'))],
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
511 def bisect(ui, repo, rev=None, extra=None, command=None,
511 def bisect(ui, repo, rev=None, extra=None, command=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
513 noupdate=None):
513 noupdate=None):
514 """subdivision search of changesets
514 """subdivision search of changesets
515
515
516 This command helps to find changesets which introduce problems. To
516 This command helps to find changesets which introduce problems. To
517 use, mark the earliest changeset you know exhibits the problem as
517 use, mark the earliest changeset you know exhibits the problem as
518 bad, then mark the latest changeset which is free from the problem
518 bad, then mark the latest changeset which is free from the problem
519 as good. Bisect will update your working directory to a revision
519 as good. Bisect will update your working directory to a revision
520 for testing (unless the -U/--noupdate option is specified). Once
520 for testing (unless the -U/--noupdate option is specified). Once
521 you have performed tests, mark the working directory as good or
521 you have performed tests, mark the working directory as good or
522 bad, and bisect will either update to another candidate changeset
522 bad, and bisect will either update to another candidate changeset
523 or announce that it has found the bad revision.
523 or announce that it has found the bad revision.
524
524
525 As a shortcut, you can also use the revision argument to mark a
525 As a shortcut, you can also use the revision argument to mark a
526 revision as good or bad without checking it out first.
526 revision as good or bad without checking it out first.
527
527
528 If you supply a command, it will be used for automatic bisection.
528 If you supply a command, it will be used for automatic bisection.
529 The environment variable HG_NODE will contain the ID of the
529 The environment variable HG_NODE will contain the ID of the
530 changeset being tested. The exit status of the command will be
530 changeset being tested. The exit status of the command will be
531 used to mark revisions as good or bad: status 0 means good, 125
531 used to mark revisions as good or bad: status 0 means good, 125
532 means to skip the revision, 127 (command not found) will abort the
532 means to skip the revision, 127 (command not found) will abort the
533 bisection, and any other non-zero exit status means the revision
533 bisection, and any other non-zero exit status means the revision
534 is bad.
534 is bad.
535
535
536 .. container:: verbose
536 .. container:: verbose
537
537
538 Some examples:
538 Some examples:
539
539
540 - start a bisection with known bad revision 12, and good revision 34::
540 - start a bisection with known bad revision 12, and good revision 34::
541
541
542 hg bisect --bad 34
542 hg bisect --bad 34
543 hg bisect --good 12
543 hg bisect --good 12
544
544
545 - advance the current bisection by marking current revision as good or
545 - advance the current bisection by marking current revision as good or
546 bad::
546 bad::
547
547
548 hg bisect --good
548 hg bisect --good
549 hg bisect --bad
549 hg bisect --bad
550
550
551 - mark the current revision, or a known revision, to be skipped (e.g. if
551 - mark the current revision, or a known revision, to be skipped (e.g. if
552 that revision is not usable because of another issue)::
552 that revision is not usable because of another issue)::
553
553
554 hg bisect --skip
554 hg bisect --skip
555 hg bisect --skip 23
555 hg bisect --skip 23
556
556
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
558
558
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
560
560
561 - forget the current bisection::
561 - forget the current bisection::
562
562
563 hg bisect --reset
563 hg bisect --reset
564
564
565 - use 'make && make tests' to automatically find the first broken
565 - use 'make && make tests' to automatically find the first broken
566 revision::
566 revision::
567
567
568 hg bisect --reset
568 hg bisect --reset
569 hg bisect --bad 34
569 hg bisect --bad 34
570 hg bisect --good 12
570 hg bisect --good 12
571 hg bisect --command 'make && make tests'
571 hg bisect --command 'make && make tests'
572
572
573 - see all changesets whose states are already known in the current
573 - see all changesets whose states are already known in the current
574 bisection::
574 bisection::
575
575
576 hg log -r "bisect(pruned)"
576 hg log -r "bisect(pruned)"
577
577
578 - see the changeset currently being bisected (especially useful
578 - see the changeset currently being bisected (especially useful
579 if running with -U/--noupdate)::
579 if running with -U/--noupdate)::
580
580
581 hg log -r "bisect(current)"
581 hg log -r "bisect(current)"
582
582
583 - see all changesets that took part in the current bisection::
583 - see all changesets that took part in the current bisection::
584
584
585 hg log -r "bisect(range)"
585 hg log -r "bisect(range)"
586
586
587 - with the graphlog extension, you can even get a nice graph::
587 - with the graphlog extension, you can even get a nice graph::
588
588
589 hg log --graph -r "bisect(range)"
589 hg log --graph -r "bisect(range)"
590
590
591 See :hg:`help revsets` for more about the `bisect()` keyword.
591 See :hg:`help revsets` for more about the `bisect()` keyword.
592
592
593 Returns 0 on success.
593 Returns 0 on success.
594 """
594 """
595 def extendbisectrange(nodes, good):
595 def extendbisectrange(nodes, good):
596 # bisect is incomplete when it ends on a merge node and
596 # bisect is incomplete when it ends on a merge node and
597 # one of the parent was not checked.
597 # one of the parent was not checked.
598 parents = repo[nodes[0]].parents()
598 parents = repo[nodes[0]].parents()
599 if len(parents) > 1:
599 if len(parents) > 1:
600 side = good and state['bad'] or state['good']
600 side = good and state['bad'] or state['good']
601 num = len(set(i.node() for i in parents) & set(side))
601 num = len(set(i.node() for i in parents) & set(side))
602 if num == 1:
602 if num == 1:
603 return parents[0].ancestor(parents[1])
603 return parents[0].ancestor(parents[1])
604 return None
604 return None
605
605
606 def print_result(nodes, good):
606 def print_result(nodes, good):
607 displayer = cmdutil.show_changeset(ui, repo, {})
607 displayer = cmdutil.show_changeset(ui, repo, {})
608 if len(nodes) == 1:
608 if len(nodes) == 1:
609 # narrowed it down to a single revision
609 # narrowed it down to a single revision
610 if good:
610 if good:
611 ui.write(_("The first good revision is:\n"))
611 ui.write(_("The first good revision is:\n"))
612 else:
612 else:
613 ui.write(_("The first bad revision is:\n"))
613 ui.write(_("The first bad revision is:\n"))
614 displayer.show(repo[nodes[0]])
614 displayer.show(repo[nodes[0]])
615 extendnode = extendbisectrange(nodes, good)
615 extendnode = extendbisectrange(nodes, good)
616 if extendnode is not None:
616 if extendnode is not None:
617 ui.write(_('Not all ancestors of this changeset have been'
617 ui.write(_('Not all ancestors of this changeset have been'
618 ' checked.\nUse bisect --extend to continue the '
618 ' checked.\nUse bisect --extend to continue the '
619 'bisection from\nthe common ancestor, %s.\n')
619 'bisection from\nthe common ancestor, %s.\n')
620 % extendnode)
620 % extendnode)
621 else:
621 else:
622 # multiple possible revisions
622 # multiple possible revisions
623 if good:
623 if good:
624 ui.write(_("Due to skipped revisions, the first "
624 ui.write(_("Due to skipped revisions, the first "
625 "good revision could be any of:\n"))
625 "good revision could be any of:\n"))
626 else:
626 else:
627 ui.write(_("Due to skipped revisions, the first "
627 ui.write(_("Due to skipped revisions, the first "
628 "bad revision could be any of:\n"))
628 "bad revision could be any of:\n"))
629 for n in nodes:
629 for n in nodes:
630 displayer.show(repo[n])
630 displayer.show(repo[n])
631 displayer.close()
631 displayer.close()
632
632
633 def check_state(state, interactive=True):
633 def check_state(state, interactive=True):
634 if not state['good'] or not state['bad']:
634 if not state['good'] or not state['bad']:
635 if (good or bad or skip or reset) and interactive:
635 if (good or bad or skip or reset) and interactive:
636 return
636 return
637 if not state['good']:
637 if not state['good']:
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
639 else:
639 else:
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
641 return True
641 return True
642
642
643 # backward compatibility
643 # backward compatibility
644 if rev in "good bad reset init".split():
644 if rev in "good bad reset init".split():
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
646 cmd, rev, extra = rev, extra, None
646 cmd, rev, extra = rev, extra, None
647 if cmd == "good":
647 if cmd == "good":
648 good = True
648 good = True
649 elif cmd == "bad":
649 elif cmd == "bad":
650 bad = True
650 bad = True
651 else:
651 else:
652 reset = True
652 reset = True
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
654 raise util.Abort(_('incompatible arguments'))
654 raise util.Abort(_('incompatible arguments'))
655
655
656 cmdutil.checkunfinished(repo)
656 cmdutil.checkunfinished(repo)
657
657
658 if reset:
658 if reset:
659 p = repo.join("bisect.state")
659 p = repo.join("bisect.state")
660 if os.path.exists(p):
660 if os.path.exists(p):
661 os.unlink(p)
661 os.unlink(p)
662 return
662 return
663
663
664 state = hbisect.load_state(repo)
664 state = hbisect.load_state(repo)
665
665
666 if command:
666 if command:
667 changesets = 1
667 changesets = 1
668 try:
668 try:
669 node = state['current'][0]
669 node = state['current'][0]
670 except LookupError:
670 except LookupError:
671 if noupdate:
671 if noupdate:
672 raise util.Abort(_('current bisect revision is unknown - '
672 raise util.Abort(_('current bisect revision is unknown - '
673 'start a new bisect to fix'))
673 'start a new bisect to fix'))
674 node, p2 = repo.dirstate.parents()
674 node, p2 = repo.dirstate.parents()
675 if p2 != nullid:
675 if p2 != nullid:
676 raise util.Abort(_('current bisect revision is a merge'))
676 raise util.Abort(_('current bisect revision is a merge'))
677 try:
677 try:
678 while changesets:
678 while changesets:
679 # update state
679 # update state
680 state['current'] = [node]
680 state['current'] = [node]
681 hbisect.save_state(repo, state)
681 hbisect.save_state(repo, state)
682 status = util.system(command,
682 status = util.system(command,
683 environ={'HG_NODE': hex(node)},
683 environ={'HG_NODE': hex(node)},
684 out=ui.fout)
684 out=ui.fout)
685 if status == 125:
685 if status == 125:
686 transition = "skip"
686 transition = "skip"
687 elif status == 0:
687 elif status == 0:
688 transition = "good"
688 transition = "good"
689 # status < 0 means process was killed
689 # status < 0 means process was killed
690 elif status == 127:
690 elif status == 127:
691 raise util.Abort(_("failed to execute %s") % command)
691 raise util.Abort(_("failed to execute %s") % command)
692 elif status < 0:
692 elif status < 0:
693 raise util.Abort(_("%s killed") % command)
693 raise util.Abort(_("%s killed") % command)
694 else:
694 else:
695 transition = "bad"
695 transition = "bad"
696 ctx = scmutil.revsingle(repo, rev, node)
696 ctx = scmutil.revsingle(repo, rev, node)
697 rev = None # clear for future iterations
697 rev = None # clear for future iterations
698 state[transition].append(ctx.node())
698 state[transition].append(ctx.node())
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
700 check_state(state, interactive=False)
700 check_state(state, interactive=False)
701 # bisect
701 # bisect
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
703 # update to next check
703 # update to next check
704 node = nodes[0]
704 node = nodes[0]
705 if not noupdate:
705 if not noupdate:
706 cmdutil.bailifchanged(repo)
706 cmdutil.bailifchanged(repo)
707 hg.clean(repo, node, show_stats=False)
707 hg.clean(repo, node, show_stats=False)
708 finally:
708 finally:
709 state['current'] = [node]
709 state['current'] = [node]
710 hbisect.save_state(repo, state)
710 hbisect.save_state(repo, state)
711 print_result(nodes, good)
711 print_result(nodes, good)
712 return
712 return
713
713
714 # update state
714 # update state
715
715
716 if rev:
716 if rev:
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
718 else:
718 else:
719 nodes = [repo.lookup('.')]
719 nodes = [repo.lookup('.')]
720
720
721 if good or bad or skip:
721 if good or bad or skip:
722 if good:
722 if good:
723 state['good'] += nodes
723 state['good'] += nodes
724 elif bad:
724 elif bad:
725 state['bad'] += nodes
725 state['bad'] += nodes
726 elif skip:
726 elif skip:
727 state['skip'] += nodes
727 state['skip'] += nodes
728 hbisect.save_state(repo, state)
728 hbisect.save_state(repo, state)
729
729
730 if not check_state(state):
730 if not check_state(state):
731 return
731 return
732
732
733 # actually bisect
733 # actually bisect
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
735 if extend:
735 if extend:
736 if not changesets:
736 if not changesets:
737 extendnode = extendbisectrange(nodes, good)
737 extendnode = extendbisectrange(nodes, good)
738 if extendnode is not None:
738 if extendnode is not None:
739 ui.write(_("Extending search to changeset %d:%s\n"
739 ui.write(_("Extending search to changeset %d:%s\n"
740 % (extendnode.rev(), extendnode)))
740 % (extendnode.rev(), extendnode)))
741 state['current'] = [extendnode.node()]
741 state['current'] = [extendnode.node()]
742 hbisect.save_state(repo, state)
742 hbisect.save_state(repo, state)
743 if noupdate:
743 if noupdate:
744 return
744 return
745 cmdutil.bailifchanged(repo)
745 cmdutil.bailifchanged(repo)
746 return hg.clean(repo, extendnode.node())
746 return hg.clean(repo, extendnode.node())
747 raise util.Abort(_("nothing to extend"))
747 raise util.Abort(_("nothing to extend"))
748
748
749 if changesets == 0:
749 if changesets == 0:
750 print_result(nodes, good)
750 print_result(nodes, good)
751 else:
751 else:
752 assert len(nodes) == 1 # only a single node can be tested next
752 assert len(nodes) == 1 # only a single node can be tested next
753 node = nodes[0]
753 node = nodes[0]
754 # compute the approximate number of remaining tests
754 # compute the approximate number of remaining tests
755 tests, size = 0, 2
755 tests, size = 0, 2
756 while size <= changesets:
756 while size <= changesets:
757 tests, size = tests + 1, size * 2
757 tests, size = tests + 1, size * 2
758 rev = repo.changelog.rev(node)
758 rev = repo.changelog.rev(node)
759 ui.write(_("Testing changeset %d:%s "
759 ui.write(_("Testing changeset %d:%s "
760 "(%d changesets remaining, ~%d tests)\n")
760 "(%d changesets remaining, ~%d tests)\n")
761 % (rev, short(node), changesets, tests))
761 % (rev, short(node), changesets, tests))
762 state['current'] = [node]
762 state['current'] = [node]
763 hbisect.save_state(repo, state)
763 hbisect.save_state(repo, state)
764 if not noupdate:
764 if not noupdate:
765 cmdutil.bailifchanged(repo)
765 cmdutil.bailifchanged(repo)
766 return hg.clean(repo, node)
766 return hg.clean(repo, node)
767
767
768 @command('bookmarks|bookmark',
768 @command('bookmarks|bookmark',
769 [('f', 'force', False, _('force')),
769 [('f', 'force', False, _('force')),
770 ('r', 'rev', '', _('revision'), _('REV')),
770 ('r', 'rev', '', _('revision'), _('REV')),
771 ('d', 'delete', False, _('delete a given bookmark')),
771 ('d', 'delete', False, _('delete a given bookmark')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
775 def bookmark(ui, repo, *names, **opts):
775 def bookmark(ui, repo, *names, **opts):
776 '''track a line of development with movable markers
776 '''track a line of development with movable markers
777
777
778 Bookmarks are pointers to certain commits that move when committing.
778 Bookmarks are pointers to certain commits that move when committing.
779 Bookmarks are local. They can be renamed, copied and deleted. It is
779 Bookmarks are local. They can be renamed, copied and deleted. It is
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
781 :hg:`update NAME` to update to a given bookmark.
781 :hg:`update NAME` to update to a given bookmark.
782
782
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
784 directory's parent revision with the given name. If you specify
784 directory's parent revision with the given name. If you specify
785 a revision using -r REV (where REV may be an existing bookmark),
785 a revision using -r REV (where REV may be an existing bookmark),
786 the bookmark is assigned to that revision.
786 the bookmark is assigned to that revision.
787
787
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
789 push` and :hg:`help pull`). This requires both the local and remote
789 push` and :hg:`help pull`). This requires both the local and remote
790 repositories to support bookmarks. For versions prior to 1.8, this means
790 repositories to support bookmarks. For versions prior to 1.8, this means
791 the bookmarks extension must be enabled.
791 the bookmarks extension must be enabled.
792
792
793 If you set a bookmark called '@', new clones of the repository will
793 If you set a bookmark called '@', new clones of the repository will
794 have that revision checked out (and the bookmark made active) by
794 have that revision checked out (and the bookmark made active) by
795 default.
795 default.
796
796
797 With -i/--inactive, the new bookmark will not be made the active
797 With -i/--inactive, the new bookmark will not be made the active
798 bookmark. If -r/--rev is given, the new bookmark will not be made
798 bookmark. If -r/--rev is given, the new bookmark will not be made
799 active even if -i/--inactive is not given. If no NAME is given, the
799 active even if -i/--inactive is not given. If no NAME is given, the
800 current active bookmark will be marked inactive.
800 current active bookmark will be marked inactive.
801 '''
801 '''
802 force = opts.get('force')
802 force = opts.get('force')
803 rev = opts.get('rev')
803 rev = opts.get('rev')
804 delete = opts.get('delete')
804 delete = opts.get('delete')
805 rename = opts.get('rename')
805 rename = opts.get('rename')
806 inactive = opts.get('inactive')
806 inactive = opts.get('inactive')
807
807
808 hexfn = ui.debugflag and hex or short
808 hexfn = ui.debugflag and hex or short
809 marks = repo._bookmarks
809 marks = repo._bookmarks
810 cur = repo.changectx('.').node()
810 cur = repo.changectx('.').node()
811
811
812 def checkformat(mark):
812 def checkformat(mark):
813 mark = mark.strip()
813 mark = mark.strip()
814 if not mark:
814 if not mark:
815 raise util.Abort(_("bookmark names cannot consist entirely of "
815 raise util.Abort(_("bookmark names cannot consist entirely of "
816 "whitespace"))
816 "whitespace"))
817 scmutil.checknewlabel(repo, mark, 'bookmark')
817 scmutil.checknewlabel(repo, mark, 'bookmark')
818 return mark
818 return mark
819
819
820 def checkconflict(repo, mark, force=False, target=None):
820 def checkconflict(repo, mark, force=False, target=None):
821 if mark in marks and not force:
821 if mark in marks and not force:
822 if target:
822 if target:
823 if marks[mark] == target and target == cur:
823 if marks[mark] == target and target == cur:
824 # re-activating a bookmark
824 # re-activating a bookmark
825 return
825 return
826 anc = repo.changelog.ancestors([repo[target].rev()])
826 anc = repo.changelog.ancestors([repo[target].rev()])
827 bmctx = repo[marks[mark]]
827 bmctx = repo[marks[mark]]
828 divs = [repo[b].node() for b in marks
828 divs = [repo[b].node() for b in marks
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
830
830
831 # allow resolving a single divergent bookmark even if moving
831 # allow resolving a single divergent bookmark even if moving
832 # the bookmark across branches when a revision is specified
832 # the bookmark across branches when a revision is specified
833 # that contains a divergent bookmark
833 # that contains a divergent bookmark
834 if bmctx.rev() not in anc and target in divs:
834 if bmctx.rev() not in anc and target in divs:
835 bookmarks.deletedivergent(repo, [target], mark)
835 bookmarks.deletedivergent(repo, [target], mark)
836 return
836 return
837
837
838 deletefrom = [b for b in divs
838 deletefrom = [b for b in divs
839 if repo[b].rev() in anc or b == target]
839 if repo[b].rev() in anc or b == target]
840 bookmarks.deletedivergent(repo, deletefrom, mark)
840 bookmarks.deletedivergent(repo, deletefrom, mark)
841 if bmctx.rev() in anc:
841 if bmctx.rev() in anc:
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
843 (mark, short(bmctx.node())))
843 (mark, short(bmctx.node())))
844 return
844 return
845 raise util.Abort(_("bookmark '%s' already exists "
845 raise util.Abort(_("bookmark '%s' already exists "
846 "(use -f to force)") % mark)
846 "(use -f to force)") % mark)
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
848 and not force):
848 and not force):
849 raise util.Abort(
849 raise util.Abort(
850 _("a bookmark cannot have the name of an existing branch"))
850 _("a bookmark cannot have the name of an existing branch"))
851
851
852 if delete and rename:
852 if delete and rename:
853 raise util.Abort(_("--delete and --rename are incompatible"))
853 raise util.Abort(_("--delete and --rename are incompatible"))
854 if delete and rev:
854 if delete and rev:
855 raise util.Abort(_("--rev is incompatible with --delete"))
855 raise util.Abort(_("--rev is incompatible with --delete"))
856 if rename and rev:
856 if rename and rev:
857 raise util.Abort(_("--rev is incompatible with --rename"))
857 raise util.Abort(_("--rev is incompatible with --rename"))
858 if not names and (delete or rev):
858 if not names and (delete or rev):
859 raise util.Abort(_("bookmark name required"))
859 raise util.Abort(_("bookmark name required"))
860
860
861 if delete:
861 if delete:
862 for mark in names:
862 for mark in names:
863 if mark not in marks:
863 if mark not in marks:
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
865 if mark == repo._bookmarkcurrent:
865 if mark == repo._bookmarkcurrent:
866 bookmarks.setcurrent(repo, None)
866 bookmarks.setcurrent(repo, None)
867 del marks[mark]
867 del marks[mark]
868 marks.write()
868 marks.write()
869
869
870 elif rename:
870 elif rename:
871 if not names:
871 if not names:
872 raise util.Abort(_("new bookmark name required"))
872 raise util.Abort(_("new bookmark name required"))
873 elif len(names) > 1:
873 elif len(names) > 1:
874 raise util.Abort(_("only one new bookmark name allowed"))
874 raise util.Abort(_("only one new bookmark name allowed"))
875 mark = checkformat(names[0])
875 mark = checkformat(names[0])
876 if rename not in marks:
876 if rename not in marks:
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
878 checkconflict(repo, mark, force)
878 checkconflict(repo, mark, force)
879 marks[mark] = marks[rename]
879 marks[mark] = marks[rename]
880 if repo._bookmarkcurrent == rename and not inactive:
880 if repo._bookmarkcurrent == rename and not inactive:
881 bookmarks.setcurrent(repo, mark)
881 bookmarks.setcurrent(repo, mark)
882 del marks[rename]
882 del marks[rename]
883 marks.write()
883 marks.write()
884
884
885 elif names:
885 elif names:
886 newact = None
886 newact = None
887 for mark in names:
887 for mark in names:
888 mark = checkformat(mark)
888 mark = checkformat(mark)
889 if newact is None:
889 if newact is None:
890 newact = mark
890 newact = mark
891 if inactive and mark == repo._bookmarkcurrent:
891 if inactive and mark == repo._bookmarkcurrent:
892 bookmarks.setcurrent(repo, None)
892 bookmarks.setcurrent(repo, None)
893 return
893 return
894 tgt = cur
894 tgt = cur
895 if rev:
895 if rev:
896 tgt = scmutil.revsingle(repo, rev).node()
896 tgt = scmutil.revsingle(repo, rev).node()
897 checkconflict(repo, mark, force, tgt)
897 checkconflict(repo, mark, force, tgt)
898 marks[mark] = tgt
898 marks[mark] = tgt
899 if not inactive and cur == marks[newact] and not rev:
899 if not inactive and cur == marks[newact] and not rev:
900 bookmarks.setcurrent(repo, newact)
900 bookmarks.setcurrent(repo, newact)
901 elif cur != tgt and newact == repo._bookmarkcurrent:
901 elif cur != tgt and newact == repo._bookmarkcurrent:
902 bookmarks.setcurrent(repo, None)
902 bookmarks.setcurrent(repo, None)
903 marks.write()
903 marks.write()
904
904
905 # Same message whether trying to deactivate the current bookmark (-i
905 # Same message whether trying to deactivate the current bookmark (-i
906 # with no NAME) or listing bookmarks
906 # with no NAME) or listing bookmarks
907 elif len(marks) == 0:
907 elif len(marks) == 0:
908 ui.status(_("no bookmarks set\n"))
908 ui.status(_("no bookmarks set\n"))
909
909
910 elif inactive:
910 elif inactive:
911 if not repo._bookmarkcurrent:
911 if not repo._bookmarkcurrent:
912 ui.status(_("no active bookmark\n"))
912 ui.status(_("no active bookmark\n"))
913 else:
913 else:
914 bookmarks.setcurrent(repo, None)
914 bookmarks.setcurrent(repo, None)
915
915
916 else: # show bookmarks
916 else: # show bookmarks
917 for bmark, n in sorted(marks.iteritems()):
917 for bmark, n in sorted(marks.iteritems()):
918 current = repo._bookmarkcurrent
918 current = repo._bookmarkcurrent
919 if bmark == current:
919 if bmark == current:
920 prefix, label = '*', 'bookmarks.current'
920 prefix, label = '*', 'bookmarks.current'
921 else:
921 else:
922 prefix, label = ' ', ''
922 prefix, label = ' ', ''
923
923
924 if ui.quiet:
924 if ui.quiet:
925 ui.write("%s\n" % bmark, label=label)
925 ui.write("%s\n" % bmark, label=label)
926 else:
926 else:
927 ui.write(" %s %-25s %d:%s\n" % (
927 ui.write(" %s %-25s %d:%s\n" % (
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
929 label=label)
929 label=label)
930
930
931 @command('branch',
931 @command('branch',
932 [('f', 'force', None,
932 [('f', 'force', None,
933 _('set branch name even if it shadows an existing branch')),
933 _('set branch name even if it shadows an existing branch')),
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
935 _('[-fC] [NAME]'))
935 _('[-fC] [NAME]'))
936 def branch(ui, repo, label=None, **opts):
936 def branch(ui, repo, label=None, **opts):
937 """set or show the current branch name
937 """set or show the current branch name
938
938
939 .. note::
939 .. note::
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
941 light-weight bookmark instead. See :hg:`help glossary` for more
941 light-weight bookmark instead. See :hg:`help glossary` for more
942 information about named branches and bookmarks.
942 information about named branches and bookmarks.
943
943
944 With no argument, show the current branch name. With one argument,
944 With no argument, show the current branch name. With one argument,
945 set the working directory branch name (the branch will not exist
945 set the working directory branch name (the branch will not exist
946 in the repository until the next commit). Standard practice
946 in the repository until the next commit). Standard practice
947 recommends that primary development take place on the 'default'
947 recommends that primary development take place on the 'default'
948 branch.
948 branch.
949
949
950 Unless -f/--force is specified, branch will not let you set a
950 Unless -f/--force is specified, branch will not let you set a
951 branch name that already exists, even if it's inactive.
951 branch name that already exists, even if it's inactive.
952
952
953 Use -C/--clean to reset the working directory branch to that of
953 Use -C/--clean to reset the working directory branch to that of
954 the parent of the working directory, negating a previous branch
954 the parent of the working directory, negating a previous branch
955 change.
955 change.
956
956
957 Use the command :hg:`update` to switch to an existing branch. Use
957 Use the command :hg:`update` to switch to an existing branch. Use
958 :hg:`commit --close-branch` to mark this branch as closed.
958 :hg:`commit --close-branch` to mark this branch as closed.
959
959
960 Returns 0 on success.
960 Returns 0 on success.
961 """
961 """
962 if label:
962 if label:
963 label = label.strip()
963 label = label.strip()
964
964
965 if not opts.get('clean') and not label:
965 if not opts.get('clean') and not label:
966 ui.write("%s\n" % repo.dirstate.branch())
966 ui.write("%s\n" % repo.dirstate.branch())
967 return
967 return
968
968
969 wlock = repo.wlock()
969 wlock = repo.wlock()
970 try:
970 try:
971 if opts.get('clean'):
971 if opts.get('clean'):
972 label = repo[None].p1().branch()
972 label = repo[None].p1().branch()
973 repo.dirstate.setbranch(label)
973 repo.dirstate.setbranch(label)
974 ui.status(_('reset working directory to branch %s\n') % label)
974 ui.status(_('reset working directory to branch %s\n') % label)
975 elif label:
975 elif label:
976 if not opts.get('force') and label in repo.branchmap():
976 if not opts.get('force') and label in repo.branchmap():
977 if label not in [p.branch() for p in repo.parents()]:
977 if label not in [p.branch() for p in repo.parents()]:
978 raise util.Abort(_('a branch of the same name already'
978 raise util.Abort(_('a branch of the same name already'
979 ' exists'),
979 ' exists'),
980 # i18n: "it" refers to an existing branch
980 # i18n: "it" refers to an existing branch
981 hint=_("use 'hg update' to switch to it"))
981 hint=_("use 'hg update' to switch to it"))
982 scmutil.checknewlabel(repo, label, 'branch')
982 scmutil.checknewlabel(repo, label, 'branch')
983 repo.dirstate.setbranch(label)
983 repo.dirstate.setbranch(label)
984 ui.status(_('marked working directory as branch %s\n') % label)
984 ui.status(_('marked working directory as branch %s\n') % label)
985 ui.status(_('(branches are permanent and global, '
985 ui.status(_('(branches are permanent and global, '
986 'did you want a bookmark?)\n'))
986 'did you want a bookmark?)\n'))
987 finally:
987 finally:
988 wlock.release()
988 wlock.release()
989
989
990 @command('branches',
990 @command('branches',
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
992 ('c', 'closed', False, _('show normal and closed branches'))],
992 ('c', 'closed', False, _('show normal and closed branches'))],
993 _('[-ac]'))
993 _('[-ac]'))
994 def branches(ui, repo, active=False, closed=False):
994 def branches(ui, repo, active=False, closed=False):
995 """list repository named branches
995 """list repository named branches
996
996
997 List the repository's named branches, indicating which ones are
997 List the repository's named branches, indicating which ones are
998 inactive. If -c/--closed is specified, also list branches which have
998 inactive. If -c/--closed is specified, also list branches which have
999 been marked closed (see :hg:`commit --close-branch`).
999 been marked closed (see :hg:`commit --close-branch`).
1000
1000
1001 If -a/--active is specified, only show active branches. A branch
1001 If -a/--active is specified, only show active branches. A branch
1002 is considered active if it contains repository heads.
1002 is considered active if it contains repository heads.
1003
1003
1004 Use the command :hg:`update` to switch to an existing branch.
1004 Use the command :hg:`update` to switch to an existing branch.
1005
1005
1006 Returns 0.
1006 Returns 0.
1007 """
1007 """
1008
1008
1009 hexfunc = ui.debugflag and hex or short
1009 hexfunc = ui.debugflag and hex or short
1010
1010
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1012 branches = []
1012 branches = []
1013 for tag, heads in repo.branchmap().iteritems():
1013 for tag, heads in repo.branchmap().iteritems():
1014 for h in reversed(heads):
1014 for h in reversed(heads):
1015 ctx = repo[h]
1015 ctx = repo[h]
1016 isopen = not ctx.closesbranch()
1016 isopen = not ctx.closesbranch()
1017 if isopen:
1017 if isopen:
1018 tip = ctx
1018 tip = ctx
1019 break
1019 break
1020 else:
1020 else:
1021 tip = repo[heads[-1]]
1021 tip = repo[heads[-1]]
1022 isactive = tag in activebranches and isopen
1022 isactive = tag in activebranches and isopen
1023 branches.append((tip, isactive, isopen))
1023 branches.append((tip, isactive, isopen))
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1025 reverse=True)
1025 reverse=True)
1026
1026
1027 for ctx, isactive, isopen in branches:
1027 for ctx, isactive, isopen in branches:
1028 if (not active) or isactive:
1028 if (not active) or isactive:
1029 if isactive:
1029 if isactive:
1030 label = 'branches.active'
1030 label = 'branches.active'
1031 notice = ''
1031 notice = ''
1032 elif not isopen:
1032 elif not isopen:
1033 if not closed:
1033 if not closed:
1034 continue
1034 continue
1035 label = 'branches.closed'
1035 label = 'branches.closed'
1036 notice = _(' (closed)')
1036 notice = _(' (closed)')
1037 else:
1037 else:
1038 label = 'branches.inactive'
1038 label = 'branches.inactive'
1039 notice = _(' (inactive)')
1039 notice = _(' (inactive)')
1040 if ctx.branch() == repo.dirstate.branch():
1040 if ctx.branch() == repo.dirstate.branch():
1041 label = 'branches.current'
1041 label = 'branches.current'
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1044 'log.changeset changeset.%s' % ctx.phasestr())
1044 'log.changeset changeset.%s' % ctx.phasestr())
1045 tag = ui.label(ctx.branch(), label)
1045 tag = ui.label(ctx.branch(), label)
1046 if ui.quiet:
1046 if ui.quiet:
1047 ui.write("%s\n" % tag)
1047 ui.write("%s\n" % tag)
1048 else:
1048 else:
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1050
1050
1051 @command('bundle',
1051 @command('bundle',
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1054 _('REV')),
1054 _('REV')),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1056 _('BRANCH')),
1056 _('BRANCH')),
1057 ('', 'base', [],
1057 ('', 'base', [],
1058 _('a base changeset assumed to be available at the destination'),
1058 _('a base changeset assumed to be available at the destination'),
1059 _('REV')),
1059 _('REV')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1062 ] + remoteopts,
1062 ] + remoteopts,
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1064 def bundle(ui, repo, fname, dest=None, **opts):
1064 def bundle(ui, repo, fname, dest=None, **opts):
1065 """create a changegroup file
1065 """create a changegroup file
1066
1066
1067 Generate a compressed changegroup file collecting changesets not
1067 Generate a compressed changegroup file collecting changesets not
1068 known to be in another repository.
1068 known to be in another repository.
1069
1069
1070 If you omit the destination repository, then hg assumes the
1070 If you omit the destination repository, then hg assumes the
1071 destination will have all the nodes you specify with --base
1071 destination will have all the nodes you specify with --base
1072 parameters. To create a bundle containing all changesets, use
1072 parameters. To create a bundle containing all changesets, use
1073 -a/--all (or --base null).
1073 -a/--all (or --base null).
1074
1074
1075 You can change compression method with the -t/--type option.
1075 You can change compression method with the -t/--type option.
1076 The available compression methods are: none, bzip2, and
1076 The available compression methods are: none, bzip2, and
1077 gzip (by default, bundles are compressed using bzip2).
1077 gzip (by default, bundles are compressed using bzip2).
1078
1078
1079 The bundle file can then be transferred using conventional means
1079 The bundle file can then be transferred using conventional means
1080 and applied to another repository with the unbundle or pull
1080 and applied to another repository with the unbundle or pull
1081 command. This is useful when direct push and pull are not
1081 command. This is useful when direct push and pull are not
1082 available or when exporting an entire repository is undesirable.
1082 available or when exporting an entire repository is undesirable.
1083
1083
1084 Applying bundles preserves all changeset contents including
1084 Applying bundles preserves all changeset contents including
1085 permissions, copy/rename information, and revision history.
1085 permissions, copy/rename information, and revision history.
1086
1086
1087 Returns 0 on success, 1 if no changes found.
1087 Returns 0 on success, 1 if no changes found.
1088 """
1088 """
1089 revs = None
1089 revs = None
1090 if 'rev' in opts:
1090 if 'rev' in opts:
1091 revs = scmutil.revrange(repo, opts['rev'])
1091 revs = scmutil.revrange(repo, opts['rev'])
1092
1092
1093 bundletype = opts.get('type', 'bzip2').lower()
1093 bundletype = opts.get('type', 'bzip2').lower()
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1095 bundletype = btypes.get(bundletype)
1095 bundletype = btypes.get(bundletype)
1096 if bundletype not in changegroup.bundletypes:
1096 if bundletype not in changegroup.bundletypes:
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1098
1098
1099 if opts.get('all'):
1099 if opts.get('all'):
1100 base = ['null']
1100 base = ['null']
1101 else:
1101 else:
1102 base = scmutil.revrange(repo, opts.get('base'))
1102 base = scmutil.revrange(repo, opts.get('base'))
1103 # TODO: get desired bundlecaps from command line.
1103 # TODO: get desired bundlecaps from command line.
1104 bundlecaps = None
1104 bundlecaps = None
1105 if base:
1105 if base:
1106 if dest:
1106 if dest:
1107 raise util.Abort(_("--base is incompatible with specifying "
1107 raise util.Abort(_("--base is incompatible with specifying "
1108 "a destination"))
1108 "a destination"))
1109 common = [repo.lookup(rev) for rev in base]
1109 common = [repo.lookup(rev) for rev in base]
1110 heads = revs and map(repo.lookup, revs) or revs
1110 heads = revs and map(repo.lookup, revs) or revs
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1112 bundlecaps=bundlecaps)
1112 bundlecaps=bundlecaps)
1113 outgoing = None
1113 outgoing = None
1114 else:
1114 else:
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1117 other = hg.peer(repo, opts, dest)
1117 other = hg.peer(repo, opts, dest)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1119 heads = revs and map(repo.lookup, revs) or revs
1119 heads = revs and map(repo.lookup, revs) or revs
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1121 onlyheads=heads,
1121 onlyheads=heads,
1122 force=opts.get('force'),
1122 force=opts.get('force'),
1123 portable=True)
1123 portable=True)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1125 if not cg:
1125 if not cg:
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1127 return 1
1127 return 1
1128
1128
1129 changegroup.writebundle(cg, fname, bundletype)
1129 changegroup.writebundle(cg, fname, bundletype)
1130
1130
1131 @command('cat',
1131 @command('cat',
1132 [('o', 'output', '',
1132 [('o', 'output', '',
1133 _('print output to file with formatted name'), _('FORMAT')),
1133 _('print output to file with formatted name'), _('FORMAT')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1136 ] + walkopts,
1136 ] + walkopts,
1137 _('[OPTION]... FILE...'))
1137 _('[OPTION]... FILE...'))
1138 def cat(ui, repo, file1, *pats, **opts):
1138 def cat(ui, repo, file1, *pats, **opts):
1139 """output the current or given revision of files
1139 """output the current or given revision of files
1140
1140
1141 Print the specified files as they were at the given revision. If
1141 Print the specified files as they were at the given revision. If
1142 no revision is given, the parent of the working directory is used.
1142 no revision is given, the parent of the working directory is used.
1143
1143
1144 Output may be to a file, in which case the name of the file is
1144 Output may be to a file, in which case the name of the file is
1145 given using a format string. The formatting rules are the same as
1145 given using a format string. The formatting rules are the same as
1146 for the export command, with the following additions:
1146 for the export command, with the following additions:
1147
1147
1148 :``%s``: basename of file being printed
1148 :``%s``: basename of file being printed
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1150 :``%p``: root-relative path name of file being printed
1150 :``%p``: root-relative path name of file being printed
1151
1151
1152 Returns 0 on success.
1152 Returns 0 on success.
1153 """
1153 """
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1155 err = 1
1155 err = 1
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1157 for abs in ctx.walk(m):
1157 for abs in ctx.walk(m):
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1159 pathname=abs)
1159 pathname=abs)
1160 data = ctx[abs].data()
1160 data = ctx[abs].data()
1161 if opts.get('decode'):
1161 if opts.get('decode'):
1162 data = repo.wwritedata(abs, data)
1162 data = repo.wwritedata(abs, data)
1163 fp.write(data)
1163 fp.write(data)
1164 fp.close()
1164 fp.close()
1165 err = 0
1165 err = 0
1166 return err
1166 return err
1167
1167
1168 @command('^clone',
1168 @command('^clone',
1169 [('U', 'noupdate', None,
1169 [('U', 'noupdate', None,
1170 _('the clone will include an empty working copy (only a repository)')),
1170 _('the clone will include an empty working copy (only a repository)')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1176 ] + remoteopts,
1176 ] + remoteopts,
1177 _('[OPTION]... SOURCE [DEST]'))
1177 _('[OPTION]... SOURCE [DEST]'))
1178 def clone(ui, source, dest=None, **opts):
1178 def clone(ui, source, dest=None, **opts):
1179 """make a copy of an existing repository
1179 """make a copy of an existing repository
1180
1180
1181 Create a copy of an existing repository in a new directory.
1181 Create a copy of an existing repository in a new directory.
1182
1182
1183 If no destination directory name is specified, it defaults to the
1183 If no destination directory name is specified, it defaults to the
1184 basename of the source.
1184 basename of the source.
1185
1185
1186 The location of the source is added to the new repository's
1186 The location of the source is added to the new repository's
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1188
1188
1189 Only local paths and ``ssh://`` URLs are supported as
1189 Only local paths and ``ssh://`` URLs are supported as
1190 destinations. For ``ssh://`` destinations, no working directory or
1190 destinations. For ``ssh://`` destinations, no working directory or
1191 ``.hg/hgrc`` will be created on the remote side.
1191 ``.hg/hgrc`` will be created on the remote side.
1192
1192
1193 To pull only a subset of changesets, specify one or more revisions
1193 To pull only a subset of changesets, specify one or more revisions
1194 identifiers with -r/--rev or branches with -b/--branch. The
1194 identifiers with -r/--rev or branches with -b/--branch. The
1195 resulting clone will contain only the specified changesets and
1195 resulting clone will contain only the specified changesets and
1196 their ancestors. These options (or 'clone src#rev dest') imply
1196 their ancestors. These options (or 'clone src#rev dest') imply
1197 --pull, even for local source repositories. Note that specifying a
1197 --pull, even for local source repositories. Note that specifying a
1198 tag will include the tagged changeset but not the changeset
1198 tag will include the tagged changeset but not the changeset
1199 containing the tag.
1199 containing the tag.
1200
1200
1201 If the source repository has a bookmark called '@' set, that
1201 If the source repository has a bookmark called '@' set, that
1202 revision will be checked out in the new repository by default.
1202 revision will be checked out in the new repository by default.
1203
1203
1204 To check out a particular version, use -u/--update, or
1204 To check out a particular version, use -u/--update, or
1205 -U/--noupdate to create a clone with no working directory.
1205 -U/--noupdate to create a clone with no working directory.
1206
1206
1207 .. container:: verbose
1207 .. container:: verbose
1208
1208
1209 For efficiency, hardlinks are used for cloning whenever the
1209 For efficiency, hardlinks are used for cloning whenever the
1210 source and destination are on the same filesystem (note this
1210 source and destination are on the same filesystem (note this
1211 applies only to the repository data, not to the working
1211 applies only to the repository data, not to the working
1212 directory). Some filesystems, such as AFS, implement hardlinking
1212 directory). Some filesystems, such as AFS, implement hardlinking
1213 incorrectly, but do not report errors. In these cases, use the
1213 incorrectly, but do not report errors. In these cases, use the
1214 --pull option to avoid hardlinking.
1214 --pull option to avoid hardlinking.
1215
1215
1216 In some cases, you can clone repositories and the working
1216 In some cases, you can clone repositories and the working
1217 directory using full hardlinks with ::
1217 directory using full hardlinks with ::
1218
1218
1219 $ cp -al REPO REPOCLONE
1219 $ cp -al REPO REPOCLONE
1220
1220
1221 This is the fastest way to clone, but it is not always safe. The
1221 This is the fastest way to clone, but it is not always safe. The
1222 operation is not atomic (making sure REPO is not modified during
1222 operation is not atomic (making sure REPO is not modified during
1223 the operation is up to you) and you have to make sure your
1223 the operation is up to you) and you have to make sure your
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1225 so). Also, this is not compatible with certain extensions that
1225 so). Also, this is not compatible with certain extensions that
1226 place their metadata under the .hg directory, such as mq.
1226 place their metadata under the .hg directory, such as mq.
1227
1227
1228 Mercurial will update the working directory to the first applicable
1228 Mercurial will update the working directory to the first applicable
1229 revision from this list:
1229 revision from this list:
1230
1230
1231 a) null if -U or the source repository has no changesets
1231 a) null if -U or the source repository has no changesets
1232 b) if -u . and the source repository is local, the first parent of
1232 b) if -u . and the source repository is local, the first parent of
1233 the source repository's working directory
1233 the source repository's working directory
1234 c) the changeset specified with -u (if a branch name, this means the
1234 c) the changeset specified with -u (if a branch name, this means the
1235 latest head of that branch)
1235 latest head of that branch)
1236 d) the changeset specified with -r
1236 d) the changeset specified with -r
1237 e) the tipmost head specified with -b
1237 e) the tipmost head specified with -b
1238 f) the tipmost head specified with the url#branch source syntax
1238 f) the tipmost head specified with the url#branch source syntax
1239 g) the revision marked with the '@' bookmark, if present
1239 g) the revision marked with the '@' bookmark, if present
1240 h) the tipmost head of the default branch
1240 h) the tipmost head of the default branch
1241 i) tip
1241 i) tip
1242
1242
1243 Examples:
1243 Examples:
1244
1244
1245 - clone a remote repository to a new directory named hg/::
1245 - clone a remote repository to a new directory named hg/::
1246
1246
1247 hg clone http://selenic.com/hg
1247 hg clone http://selenic.com/hg
1248
1248
1249 - create a lightweight local clone::
1249 - create a lightweight local clone::
1250
1250
1251 hg clone project/ project-feature/
1251 hg clone project/ project-feature/
1252
1252
1253 - clone from an absolute path on an ssh server (note double-slash)::
1253 - clone from an absolute path on an ssh server (note double-slash)::
1254
1254
1255 hg clone ssh://user@server//home/projects/alpha/
1255 hg clone ssh://user@server//home/projects/alpha/
1256
1256
1257 - do a high-speed clone over a LAN while checking out a
1257 - do a high-speed clone over a LAN while checking out a
1258 specified version::
1258 specified version::
1259
1259
1260 hg clone --uncompressed http://server/repo -u 1.5
1260 hg clone --uncompressed http://server/repo -u 1.5
1261
1261
1262 - create a repository without changesets after a particular revision::
1262 - create a repository without changesets after a particular revision::
1263
1263
1264 hg clone -r 04e544 experimental/ good/
1264 hg clone -r 04e544 experimental/ good/
1265
1265
1266 - clone (and track) a particular named branch::
1266 - clone (and track) a particular named branch::
1267
1267
1268 hg clone http://selenic.com/hg#stable
1268 hg clone http://selenic.com/hg#stable
1269
1269
1270 See :hg:`help urls` for details on specifying URLs.
1270 See :hg:`help urls` for details on specifying URLs.
1271
1271
1272 Returns 0 on success.
1272 Returns 0 on success.
1273 """
1273 """
1274 if opts.get('noupdate') and opts.get('updaterev'):
1274 if opts.get('noupdate') and opts.get('updaterev'):
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1276
1276
1277 r = hg.clone(ui, opts, source, dest,
1277 r = hg.clone(ui, opts, source, dest,
1278 pull=opts.get('pull'),
1278 pull=opts.get('pull'),
1279 stream=opts.get('uncompressed'),
1279 stream=opts.get('uncompressed'),
1280 rev=opts.get('rev'),
1280 rev=opts.get('rev'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1282 branch=opts.get('branch'))
1282 branch=opts.get('branch'))
1283
1283
1284 return r is None
1284 return r is None
1285
1285
1286 @command('^commit|ci',
1286 @command('^commit|ci',
1287 [('A', 'addremove', None,
1287 [('A', 'addremove', None,
1288 _('mark new/missing files as added/removed before committing')),
1288 _('mark new/missing files as added/removed before committing')),
1289 ('', 'close-branch', None,
1289 ('', 'close-branch', None,
1290 _('mark a branch as closed, hiding it from the branch list')),
1290 _('mark a branch as closed, hiding it from the branch list')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1294 _('[OPTION]... [FILE]...'))
1294 _('[OPTION]... [FILE]...'))
1295 def commit(ui, repo, *pats, **opts):
1295 def commit(ui, repo, *pats, **opts):
1296 """commit the specified files or all outstanding changes
1296 """commit the specified files or all outstanding changes
1297
1297
1298 Commit changes to the given files into the repository. Unlike a
1298 Commit changes to the given files into the repository. Unlike a
1299 centralized SCM, this operation is a local operation. See
1299 centralized SCM, this operation is a local operation. See
1300 :hg:`push` for a way to actively distribute your changes.
1300 :hg:`push` for a way to actively distribute your changes.
1301
1301
1302 If a list of files is omitted, all changes reported by :hg:`status`
1302 If a list of files is omitted, all changes reported by :hg:`status`
1303 will be committed.
1303 will be committed.
1304
1304
1305 If you are committing the result of a merge, do not provide any
1305 If you are committing the result of a merge, do not provide any
1306 filenames or -I/-X filters.
1306 filenames or -I/-X filters.
1307
1307
1308 If no commit message is specified, Mercurial starts your
1308 If no commit message is specified, Mercurial starts your
1309 configured editor where you can enter a message. In case your
1309 configured editor where you can enter a message. In case your
1310 commit fails, you will find a backup of your message in
1310 commit fails, you will find a backup of your message in
1311 ``.hg/last-message.txt``.
1311 ``.hg/last-message.txt``.
1312
1312
1313 The --amend flag can be used to amend the parent of the
1313 The --amend flag can be used to amend the parent of the
1314 working directory with a new commit that contains the changes
1314 working directory with a new commit that contains the changes
1315 in the parent in addition to those currently reported by :hg:`status`,
1315 in the parent in addition to those currently reported by :hg:`status`,
1316 if there are any. The old commit is stored in a backup bundle in
1316 if there are any. The old commit is stored in a backup bundle in
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1318 on how to restore it).
1318 on how to restore it).
1319
1319
1320 Message, user and date are taken from the amended commit unless
1320 Message, user and date are taken from the amended commit unless
1321 specified. When a message isn't specified on the command line,
1321 specified. When a message isn't specified on the command line,
1322 the editor will open with the message of the amended commit.
1322 the editor will open with the message of the amended commit.
1323
1323
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1325 or changesets that have children.
1325 or changesets that have children.
1326
1326
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1328
1328
1329 Returns 0 on success, 1 if nothing changed.
1329 Returns 0 on success, 1 if nothing changed.
1330 """
1330 """
1331 if opts.get('subrepos'):
1331 if opts.get('subrepos'):
1332 if opts.get('amend'):
1332 if opts.get('amend'):
1333 raise util.Abort(_('cannot amend with --subrepos'))
1333 raise util.Abort(_('cannot amend with --subrepos'))
1334 # Let --subrepos on the command line override config setting.
1334 # Let --subrepos on the command line override config setting.
1335 ui.setconfig('ui', 'commitsubrepos', True)
1335 ui.setconfig('ui', 'commitsubrepos', True)
1336
1336
1337 # Save this for restoring it later
1337 # Save this for restoring it later
1338 oldcommitphase = ui.config('phases', 'new-commit')
1338 oldcommitphase = ui.config('phases', 'new-commit')
1339
1339
1340 cmdutil.checkunfinished(repo, commit=True)
1340 cmdutil.checkunfinished(repo, commit=True)
1341
1341
1342 branch = repo[None].branch()
1342 branch = repo[None].branch()
1343 bheads = repo.branchheads(branch)
1343 bheads = repo.branchheads(branch)
1344
1344
1345 extra = {}
1345 extra = {}
1346 if opts.get('close_branch'):
1346 if opts.get('close_branch'):
1347 extra['close'] = 1
1347 extra['close'] = 1
1348
1348
1349 if not bheads:
1349 if not bheads:
1350 raise util.Abort(_('can only close branch heads'))
1350 raise util.Abort(_('can only close branch heads'))
1351 elif opts.get('amend'):
1351 elif opts.get('amend'):
1352 if repo.parents()[0].p1().branch() != branch and \
1352 if repo.parents()[0].p1().branch() != branch and \
1353 repo.parents()[0].p2().branch() != branch:
1353 repo.parents()[0].p2().branch() != branch:
1354 raise util.Abort(_('can only close branch heads'))
1354 raise util.Abort(_('can only close branch heads'))
1355
1355
1356 if opts.get('amend'):
1356 if opts.get('amend'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1359
1359
1360 old = repo['.']
1360 old = repo['.']
1361 if old.phase() == phases.public:
1361 if old.phase() == phases.public:
1362 raise util.Abort(_('cannot amend public changesets'))
1362 raise util.Abort(_('cannot amend public changesets'))
1363 if len(repo[None].parents()) > 1:
1363 if len(repo[None].parents()) > 1:
1364 raise util.Abort(_('cannot amend while merging'))
1364 raise util.Abort(_('cannot amend while merging'))
1365 if (not obsolete._enabled) and old.children():
1365 if (not obsolete._enabled) and old.children():
1366 raise util.Abort(_('cannot amend changeset with children'))
1366 raise util.Abort(_('cannot amend changeset with children'))
1367
1367
1368 e = cmdutil.commiteditor
1368 e = cmdutil.commiteditor
1369 if opts.get('force_editor'):
1369 if opts.get('force_editor'):
1370 e = cmdutil.commitforceeditor
1370 e = cmdutil.commitforceeditor
1371
1371
1372 def commitfunc(ui, repo, message, match, opts):
1372 def commitfunc(ui, repo, message, match, opts):
1373 editor = e
1373 editor = e
1374 # message contains text from -m or -l, if it's empty,
1374 # message contains text from -m or -l, if it's empty,
1375 # open the editor with the old message
1375 # open the editor with the old message
1376 if not message:
1376 if not message:
1377 message = old.description()
1377 message = old.description()
1378 editor = cmdutil.commitforceeditor
1378 editor = cmdutil.commitforceeditor
1379 try:
1379 try:
1380 if opts.get('secret'):
1380 if opts.get('secret'):
1381 ui.setconfig('phases', 'new-commit', 'secret')
1381 ui.setconfig('phases', 'new-commit', 'secret')
1382
1382
1383 return repo.commit(message,
1383 return repo.commit(message,
1384 opts.get('user') or old.user(),
1384 opts.get('user') or old.user(),
1385 opts.get('date') or old.date(),
1385 opts.get('date') or old.date(),
1386 match,
1386 match,
1387 editor=editor,
1387 editor=editor,
1388 extra=extra)
1388 extra=extra)
1389 finally:
1389 finally:
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1391
1391
1392 current = repo._bookmarkcurrent
1392 current = repo._bookmarkcurrent
1393 marks = old.bookmarks()
1393 marks = old.bookmarks()
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1395 if node == old.node():
1395 if node == old.node():
1396 ui.status(_("nothing changed\n"))
1396 ui.status(_("nothing changed\n"))
1397 return 1
1397 return 1
1398 elif marks:
1398 elif marks:
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1400 (marks, old.hex(), hex(node)))
1400 (marks, old.hex(), hex(node)))
1401 newmarks = repo._bookmarks
1401 newmarks = repo._bookmarks
1402 for bm in marks:
1402 for bm in marks:
1403 newmarks[bm] = node
1403 newmarks[bm] = node
1404 if bm == current:
1404 if bm == current:
1405 bookmarks.setcurrent(repo, bm)
1405 bookmarks.setcurrent(repo, bm)
1406 newmarks.write()
1406 newmarks.write()
1407 else:
1407 else:
1408 e = cmdutil.commiteditor
1408 e = cmdutil.commiteditor
1409 if opts.get('force_editor'):
1409 if opts.get('force_editor'):
1410 e = cmdutil.commitforceeditor
1410 e = cmdutil.commitforceeditor
1411
1411
1412 def commitfunc(ui, repo, message, match, opts):
1412 def commitfunc(ui, repo, message, match, opts):
1413 try:
1413 try:
1414 if opts.get('secret'):
1414 if opts.get('secret'):
1415 ui.setconfig('phases', 'new-commit', 'secret')
1415 ui.setconfig('phases', 'new-commit', 'secret')
1416
1416
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1418 match, editor=e, extra=extra)
1418 match, editor=e, extra=extra)
1419 finally:
1419 finally:
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1421
1421
1422
1422
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1424
1424
1425 if not node:
1425 if not node:
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1427 if stat[3]:
1427 if stat[3]:
1428 ui.status(_("nothing changed (%d missing files, see "
1428 ui.status(_("nothing changed (%d missing files, see "
1429 "'hg status')\n") % len(stat[3]))
1429 "'hg status')\n") % len(stat[3]))
1430 else:
1430 else:
1431 ui.status(_("nothing changed\n"))
1431 ui.status(_("nothing changed\n"))
1432 return 1
1432 return 1
1433
1433
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1435
1435
1436 @command('copy|cp',
1436 @command('copy|cp',
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1439 ] + walkopts + dryrunopts,
1439 ] + walkopts + dryrunopts,
1440 _('[OPTION]... [SOURCE]... DEST'))
1440 _('[OPTION]... [SOURCE]... DEST'))
1441 def copy(ui, repo, *pats, **opts):
1441 def copy(ui, repo, *pats, **opts):
1442 """mark files as copied for the next commit
1442 """mark files as copied for the next commit
1443
1443
1444 Mark dest as having copies of source files. If dest is a
1444 Mark dest as having copies of source files. If dest is a
1445 directory, copies are put in that directory. If dest is a file,
1445 directory, copies are put in that directory. If dest is a file,
1446 the source must be a single file.
1446 the source must be a single file.
1447
1447
1448 By default, this command copies the contents of files as they
1448 By default, this command copies the contents of files as they
1449 exist in the working directory. If invoked with -A/--after, the
1449 exist in the working directory. If invoked with -A/--after, the
1450 operation is recorded, but no copying is performed.
1450 operation is recorded, but no copying is performed.
1451
1451
1452 This command takes effect with the next commit. To undo a copy
1452 This command takes effect with the next commit. To undo a copy
1453 before that, see :hg:`revert`.
1453 before that, see :hg:`revert`.
1454
1454
1455 Returns 0 on success, 1 if errors are encountered.
1455 Returns 0 on success, 1 if errors are encountered.
1456 """
1456 """
1457 wlock = repo.wlock(False)
1457 wlock = repo.wlock(False)
1458 try:
1458 try:
1459 return cmdutil.copy(ui, repo, pats, opts)
1459 return cmdutil.copy(ui, repo, pats, opts)
1460 finally:
1460 finally:
1461 wlock.release()
1461 wlock.release()
1462
1462
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1464 def debugancestor(ui, repo, *args):
1464 def debugancestor(ui, repo, *args):
1465 """find the ancestor revision of two revisions in a given index"""
1465 """find the ancestor revision of two revisions in a given index"""
1466 if len(args) == 3:
1466 if len(args) == 3:
1467 index, rev1, rev2 = args
1467 index, rev1, rev2 = args
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1469 lookup = r.lookup
1469 lookup = r.lookup
1470 elif len(args) == 2:
1470 elif len(args) == 2:
1471 if not repo:
1471 if not repo:
1472 raise util.Abort(_("there is no Mercurial repository here "
1472 raise util.Abort(_("there is no Mercurial repository here "
1473 "(.hg not found)"))
1473 "(.hg not found)"))
1474 rev1, rev2 = args
1474 rev1, rev2 = args
1475 r = repo.changelog
1475 r = repo.changelog
1476 lookup = repo.lookup
1476 lookup = repo.lookup
1477 else:
1477 else:
1478 raise util.Abort(_('either two or three arguments required'))
1478 raise util.Abort(_('either two or three arguments required'))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1481
1481
1482 @command('debugbuilddag',
1482 @command('debugbuilddag',
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1486 _('[OPTION]... [TEXT]'))
1486 _('[OPTION]... [TEXT]'))
1487 def debugbuilddag(ui, repo, text=None,
1487 def debugbuilddag(ui, repo, text=None,
1488 mergeable_file=False,
1488 mergeable_file=False,
1489 overwritten_file=False,
1489 overwritten_file=False,
1490 new_file=False):
1490 new_file=False):
1491 """builds a repo with a given DAG from scratch in the current empty repo
1491 """builds a repo with a given DAG from scratch in the current empty repo
1492
1492
1493 The description of the DAG is read from stdin if not given on the
1493 The description of the DAG is read from stdin if not given on the
1494 command line.
1494 command line.
1495
1495
1496 Elements:
1496 Elements:
1497
1497
1498 - "+n" is a linear run of n nodes based on the current default parent
1498 - "+n" is a linear run of n nodes based on the current default parent
1499 - "." is a single node based on the current default parent
1499 - "." is a single node based on the current default parent
1500 - "$" resets the default parent to null (implied at the start);
1500 - "$" resets the default parent to null (implied at the start);
1501 otherwise the default parent is always the last node created
1501 otherwise the default parent is always the last node created
1502 - "<p" sets the default parent to the backref p
1502 - "<p" sets the default parent to the backref p
1503 - "*p" is a fork at parent p, which is a backref
1503 - "*p" is a fork at parent p, which is a backref
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1505 - "/p2" is a merge of the preceding node and p2
1505 - "/p2" is a merge of the preceding node and p2
1506 - ":tag" defines a local tag for the preceding node
1506 - ":tag" defines a local tag for the preceding node
1507 - "@branch" sets the named branch for subsequent nodes
1507 - "@branch" sets the named branch for subsequent nodes
1508 - "#...\\n" is a comment up to the end of the line
1508 - "#...\\n" is a comment up to the end of the line
1509
1509
1510 Whitespace between the above elements is ignored.
1510 Whitespace between the above elements is ignored.
1511
1511
1512 A backref is either
1512 A backref is either
1513
1513
1514 - a number n, which references the node curr-n, where curr is the current
1514 - a number n, which references the node curr-n, where curr is the current
1515 node, or
1515 node, or
1516 - the name of a local tag you placed earlier using ":tag", or
1516 - the name of a local tag you placed earlier using ":tag", or
1517 - empty to denote the default parent.
1517 - empty to denote the default parent.
1518
1518
1519 All string valued-elements are either strictly alphanumeric, or must
1519 All string valued-elements are either strictly alphanumeric, or must
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1521 """
1521 """
1522
1522
1523 if text is None:
1523 if text is None:
1524 ui.status(_("reading DAG from stdin\n"))
1524 ui.status(_("reading DAG from stdin\n"))
1525 text = ui.fin.read()
1525 text = ui.fin.read()
1526
1526
1527 cl = repo.changelog
1527 cl = repo.changelog
1528 if len(cl) > 0:
1528 if len(cl) > 0:
1529 raise util.Abort(_('repository is not empty'))
1529 raise util.Abort(_('repository is not empty'))
1530
1530
1531 # determine number of revs in DAG
1531 # determine number of revs in DAG
1532 total = 0
1532 total = 0
1533 for type, data in dagparser.parsedag(text):
1533 for type, data in dagparser.parsedag(text):
1534 if type == 'n':
1534 if type == 'n':
1535 total += 1
1535 total += 1
1536
1536
1537 if mergeable_file:
1537 if mergeable_file:
1538 linesperrev = 2
1538 linesperrev = 2
1539 # make a file with k lines per rev
1539 # make a file with k lines per rev
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1541 initialmergedlines.append("")
1541 initialmergedlines.append("")
1542
1542
1543 tags = []
1543 tags = []
1544
1544
1545 lock = tr = None
1545 lock = tr = None
1546 try:
1546 try:
1547 lock = repo.lock()
1547 lock = repo.lock()
1548 tr = repo.transaction("builddag")
1548 tr = repo.transaction("builddag")
1549
1549
1550 at = -1
1550 at = -1
1551 atbranch = 'default'
1551 atbranch = 'default'
1552 nodeids = []
1552 nodeids = []
1553 id = 0
1553 id = 0
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1555 for type, data in dagparser.parsedag(text):
1555 for type, data in dagparser.parsedag(text):
1556 if type == 'n':
1556 if type == 'n':
1557 ui.note(('node %s\n' % str(data)))
1557 ui.note(('node %s\n' % str(data)))
1558 id, ps = data
1558 id, ps = data
1559
1559
1560 files = []
1560 files = []
1561 fctxs = {}
1561 fctxs = {}
1562
1562
1563 p2 = None
1563 p2 = None
1564 if mergeable_file:
1564 if mergeable_file:
1565 fn = "mf"
1565 fn = "mf"
1566 p1 = repo[ps[0]]
1566 p1 = repo[ps[0]]
1567 if len(ps) > 1:
1567 if len(ps) > 1:
1568 p2 = repo[ps[1]]
1568 p2 = repo[ps[1]]
1569 pa = p1.ancestor(p2)
1569 pa = p1.ancestor(p2)
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1571 p2)]
1571 p2)]
1572 m3 = simplemerge.Merge3Text(base, local, other)
1572 m3 = simplemerge.Merge3Text(base, local, other)
1573 ml = [l.strip() for l in m3.merge_lines()]
1573 ml = [l.strip() for l in m3.merge_lines()]
1574 ml.append("")
1574 ml.append("")
1575 elif at > 0:
1575 elif at > 0:
1576 ml = p1[fn].data().split("\n")
1576 ml = p1[fn].data().split("\n")
1577 else:
1577 else:
1578 ml = initialmergedlines
1578 ml = initialmergedlines
1579 ml[id * linesperrev] += " r%i" % id
1579 ml[id * linesperrev] += " r%i" % id
1580 mergedtext = "\n".join(ml)
1580 mergedtext = "\n".join(ml)
1581 files.append(fn)
1581 files.append(fn)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1583
1583
1584 if overwritten_file:
1584 if overwritten_file:
1585 fn = "of"
1585 fn = "of"
1586 files.append(fn)
1586 files.append(fn)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1588
1588
1589 if new_file:
1589 if new_file:
1590 fn = "nf%i" % id
1590 fn = "nf%i" % id
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 if len(ps) > 1:
1593 if len(ps) > 1:
1594 if not p2:
1594 if not p2:
1595 p2 = repo[ps[1]]
1595 p2 = repo[ps[1]]
1596 for fn in p2:
1596 for fn in p2:
1597 if fn.startswith("nf"):
1597 if fn.startswith("nf"):
1598 files.append(fn)
1598 files.append(fn)
1599 fctxs[fn] = p2[fn]
1599 fctxs[fn] = p2[fn]
1600
1600
1601 def fctxfn(repo, cx, path):
1601 def fctxfn(repo, cx, path):
1602 return fctxs.get(path)
1602 return fctxs.get(path)
1603
1603
1604 if len(ps) == 0 or ps[0] < 0:
1604 if len(ps) == 0 or ps[0] < 0:
1605 pars = [None, None]
1605 pars = [None, None]
1606 elif len(ps) == 1:
1606 elif len(ps) == 1:
1607 pars = [nodeids[ps[0]], None]
1607 pars = [nodeids[ps[0]], None]
1608 else:
1608 else:
1609 pars = [nodeids[p] for p in ps]
1609 pars = [nodeids[p] for p in ps]
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1611 date=(id, 0),
1611 date=(id, 0),
1612 user="debugbuilddag",
1612 user="debugbuilddag",
1613 extra={'branch': atbranch})
1613 extra={'branch': atbranch})
1614 nodeid = repo.commitctx(cx)
1614 nodeid = repo.commitctx(cx)
1615 nodeids.append(nodeid)
1615 nodeids.append(nodeid)
1616 at = id
1616 at = id
1617 elif type == 'l':
1617 elif type == 'l':
1618 id, name = data
1618 id, name = data
1619 ui.note(('tag %s\n' % name))
1619 ui.note(('tag %s\n' % name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1621 elif type == 'a':
1621 elif type == 'a':
1622 ui.note(('branch %s\n' % data))
1622 ui.note(('branch %s\n' % data))
1623 atbranch = data
1623 atbranch = data
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1625 tr.close()
1625 tr.close()
1626
1626
1627 if tags:
1627 if tags:
1628 repo.opener.write("localtags", "".join(tags))
1628 repo.opener.write("localtags", "".join(tags))
1629 finally:
1629 finally:
1630 ui.progress(_('building'), None)
1630 ui.progress(_('building'), None)
1631 release(tr, lock)
1631 release(tr, lock)
1632
1632
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1635 """lists the contents of a bundle"""
1635 """lists the contents of a bundle"""
1636 f = hg.openpath(ui, bundlepath)
1636 f = hg.openpath(ui, bundlepath)
1637 try:
1637 try:
1638 gen = changegroup.readbundle(f, bundlepath)
1638 gen = changegroup.readbundle(f, bundlepath)
1639 if all:
1639 if all:
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1641
1641
1642 def showchunks(named):
1642 def showchunks(named):
1643 ui.write("\n%s\n" % named)
1643 ui.write("\n%s\n" % named)
1644 chain = None
1644 chain = None
1645 while True:
1645 while True:
1646 chunkdata = gen.deltachunk(chain)
1646 chunkdata = gen.deltachunk(chain)
1647 if not chunkdata:
1647 if not chunkdata:
1648 break
1648 break
1649 node = chunkdata['node']
1649 node = chunkdata['node']
1650 p1 = chunkdata['p1']
1650 p1 = chunkdata['p1']
1651 p2 = chunkdata['p2']
1651 p2 = chunkdata['p2']
1652 cs = chunkdata['cs']
1652 cs = chunkdata['cs']
1653 deltabase = chunkdata['deltabase']
1653 deltabase = chunkdata['deltabase']
1654 delta = chunkdata['delta']
1654 delta = chunkdata['delta']
1655 ui.write("%s %s %s %s %s %s\n" %
1655 ui.write("%s %s %s %s %s %s\n" %
1656 (hex(node), hex(p1), hex(p2),
1656 (hex(node), hex(p1), hex(p2),
1657 hex(cs), hex(deltabase), len(delta)))
1657 hex(cs), hex(deltabase), len(delta)))
1658 chain = node
1658 chain = node
1659
1659
1660 chunkdata = gen.changelogheader()
1660 chunkdata = gen.changelogheader()
1661 showchunks("changelog")
1661 showchunks("changelog")
1662 chunkdata = gen.manifestheader()
1662 chunkdata = gen.manifestheader()
1663 showchunks("manifest")
1663 showchunks("manifest")
1664 while True:
1664 while True:
1665 chunkdata = gen.filelogheader()
1665 chunkdata = gen.filelogheader()
1666 if not chunkdata:
1666 if not chunkdata:
1667 break
1667 break
1668 fname = chunkdata['filename']
1668 fname = chunkdata['filename']
1669 showchunks(fname)
1669 showchunks(fname)
1670 else:
1670 else:
1671 chunkdata = gen.changelogheader()
1671 chunkdata = gen.changelogheader()
1672 chain = None
1672 chain = None
1673 while True:
1673 while True:
1674 chunkdata = gen.deltachunk(chain)
1674 chunkdata = gen.deltachunk(chain)
1675 if not chunkdata:
1675 if not chunkdata:
1676 break
1676 break
1677 node = chunkdata['node']
1677 node = chunkdata['node']
1678 ui.write("%s\n" % hex(node))
1678 ui.write("%s\n" % hex(node))
1679 chain = node
1679 chain = node
1680 finally:
1680 finally:
1681 f.close()
1681 f.close()
1682
1682
1683 @command('debugcheckstate', [], '')
1683 @command('debugcheckstate', [], '')
1684 def debugcheckstate(ui, repo):
1684 def debugcheckstate(ui, repo):
1685 """validate the correctness of the current dirstate"""
1685 """validate the correctness of the current dirstate"""
1686 parent1, parent2 = repo.dirstate.parents()
1686 parent1, parent2 = repo.dirstate.parents()
1687 m1 = repo[parent1].manifest()
1687 m1 = repo[parent1].manifest()
1688 m2 = repo[parent2].manifest()
1688 m2 = repo[parent2].manifest()
1689 errors = 0
1689 errors = 0
1690 for f in repo.dirstate:
1690 for f in repo.dirstate:
1691 state = repo.dirstate[f]
1691 state = repo.dirstate[f]
1692 if state in "nr" and f not in m1:
1692 if state in "nr" and f not in m1:
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1694 errors += 1
1694 errors += 1
1695 if state in "a" and f in m1:
1695 if state in "a" and f in m1:
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1697 errors += 1
1697 errors += 1
1698 if state in "m" and f not in m1 and f not in m2:
1698 if state in "m" and f not in m1 and f not in m2:
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1700 (f, state))
1700 (f, state))
1701 errors += 1
1701 errors += 1
1702 for f in m1:
1702 for f in m1:
1703 state = repo.dirstate[f]
1703 state = repo.dirstate[f]
1704 if state not in "nrm":
1704 if state not in "nrm":
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1706 errors += 1
1706 errors += 1
1707 if errors:
1707 if errors:
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1709 raise util.Abort(error)
1709 raise util.Abort(error)
1710
1710
1711 @command('debugcommands', [], _('[COMMAND]'))
1711 @command('debugcommands', [], _('[COMMAND]'))
1712 def debugcommands(ui, cmd='', *args):
1712 def debugcommands(ui, cmd='', *args):
1713 """list all available commands and options"""
1713 """list all available commands and options"""
1714 for cmd, vals in sorted(table.iteritems()):
1714 for cmd, vals in sorted(table.iteritems()):
1715 cmd = cmd.split('|')[0].strip('^')
1715 cmd = cmd.split('|')[0].strip('^')
1716 opts = ', '.join([i[1] for i in vals[1]])
1716 opts = ', '.join([i[1] for i in vals[1]])
1717 ui.write('%s: %s\n' % (cmd, opts))
1717 ui.write('%s: %s\n' % (cmd, opts))
1718
1718
1719 @command('debugcomplete',
1719 @command('debugcomplete',
1720 [('o', 'options', None, _('show the command options'))],
1720 [('o', 'options', None, _('show the command options'))],
1721 _('[-o] CMD'))
1721 _('[-o] CMD'))
1722 def debugcomplete(ui, cmd='', **opts):
1722 def debugcomplete(ui, cmd='', **opts):
1723 """returns the completion list associated with the given command"""
1723 """returns the completion list associated with the given command"""
1724
1724
1725 if opts.get('options'):
1725 if opts.get('options'):
1726 options = []
1726 options = []
1727 otables = [globalopts]
1727 otables = [globalopts]
1728 if cmd:
1728 if cmd:
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1730 otables.append(entry[1])
1730 otables.append(entry[1])
1731 for t in otables:
1731 for t in otables:
1732 for o in t:
1732 for o in t:
1733 if "(DEPRECATED)" in o[3]:
1733 if "(DEPRECATED)" in o[3]:
1734 continue
1734 continue
1735 if o[0]:
1735 if o[0]:
1736 options.append('-%s' % o[0])
1736 options.append('-%s' % o[0])
1737 options.append('--%s' % o[1])
1737 options.append('--%s' % o[1])
1738 ui.write("%s\n" % "\n".join(options))
1738 ui.write("%s\n" % "\n".join(options))
1739 return
1739 return
1740
1740
1741 cmdlist = cmdutil.findpossible(cmd, table)
1741 cmdlist = cmdutil.findpossible(cmd, table)
1742 if ui.verbose:
1742 if ui.verbose:
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1745
1745
1746 @command('debugdag',
1746 @command('debugdag',
1747 [('t', 'tags', None, _('use tags as labels')),
1747 [('t', 'tags', None, _('use tags as labels')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1749 ('', 'dots', None, _('use dots for runs')),
1749 ('', 'dots', None, _('use dots for runs')),
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1751 _('[OPTION]... [FILE [REV]...]'))
1751 _('[OPTION]... [FILE [REV]...]'))
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1753 """format the changelog or an index DAG as a concise textual description
1753 """format the changelog or an index DAG as a concise textual description
1754
1754
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1756 revision numbers, they get labeled in the output as rN.
1756 revision numbers, they get labeled in the output as rN.
1757
1757
1758 Otherwise, the changelog DAG of the current repo is emitted.
1758 Otherwise, the changelog DAG of the current repo is emitted.
1759 """
1759 """
1760 spaces = opts.get('spaces')
1760 spaces = opts.get('spaces')
1761 dots = opts.get('dots')
1761 dots = opts.get('dots')
1762 if file_:
1762 if file_:
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1764 revs = set((int(r) for r in revs))
1764 revs = set((int(r) for r in revs))
1765 def events():
1765 def events():
1766 for r in rlog:
1766 for r in rlog:
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1768 if p != -1)))
1768 if p != -1)))
1769 if r in revs:
1769 if r in revs:
1770 yield 'l', (r, "r%i" % r)
1770 yield 'l', (r, "r%i" % r)
1771 elif repo:
1771 elif repo:
1772 cl = repo.changelog
1772 cl = repo.changelog
1773 tags = opts.get('tags')
1773 tags = opts.get('tags')
1774 branches = opts.get('branches')
1774 branches = opts.get('branches')
1775 if tags:
1775 if tags:
1776 labels = {}
1776 labels = {}
1777 for l, n in repo.tags().items():
1777 for l, n in repo.tags().items():
1778 labels.setdefault(cl.rev(n), []).append(l)
1778 labels.setdefault(cl.rev(n), []).append(l)
1779 def events():
1779 def events():
1780 b = "default"
1780 b = "default"
1781 for r in cl:
1781 for r in cl:
1782 if branches:
1782 if branches:
1783 newb = cl.read(cl.node(r))[5]['branch']
1783 newb = cl.read(cl.node(r))[5]['branch']
1784 if newb != b:
1784 if newb != b:
1785 yield 'a', newb
1785 yield 'a', newb
1786 b = newb
1786 b = newb
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1788 if p != -1)))
1788 if p != -1)))
1789 if tags:
1789 if tags:
1790 ls = labels.get(r)
1790 ls = labels.get(r)
1791 if ls:
1791 if ls:
1792 for l in ls:
1792 for l in ls:
1793 yield 'l', (r, l)
1793 yield 'l', (r, l)
1794 else:
1794 else:
1795 raise util.Abort(_('need repo for changelog dag'))
1795 raise util.Abort(_('need repo for changelog dag'))
1796
1796
1797 for line in dagparser.dagtextlines(events(),
1797 for line in dagparser.dagtextlines(events(),
1798 addspaces=spaces,
1798 addspaces=spaces,
1799 wraplabels=True,
1799 wraplabels=True,
1800 wrapannotations=True,
1800 wrapannotations=True,
1801 wrapnonlinear=dots,
1801 wrapnonlinear=dots,
1802 usedots=dots,
1802 usedots=dots,
1803 maxlinewidth=70):
1803 maxlinewidth=70):
1804 ui.write(line)
1804 ui.write(line)
1805 ui.write("\n")
1805 ui.write("\n")
1806
1806
1807 @command('debugdata',
1807 @command('debugdata',
1808 [('c', 'changelog', False, _('open changelog')),
1808 [('c', 'changelog', False, _('open changelog')),
1809 ('m', 'manifest', False, _('open manifest'))],
1809 ('m', 'manifest', False, _('open manifest'))],
1810 _('-c|-m|FILE REV'))
1810 _('-c|-m|FILE REV'))
1811 def debugdata(ui, repo, file_, rev=None, **opts):
1811 def debugdata(ui, repo, file_, rev=None, **opts):
1812 """dump the contents of a data file revision"""
1812 """dump the contents of a data file revision"""
1813 if opts.get('changelog') or opts.get('manifest'):
1813 if opts.get('changelog') or opts.get('manifest'):
1814 file_, rev = None, file_
1814 file_, rev = None, file_
1815 elif rev is None:
1815 elif rev is None:
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1818 try:
1818 try:
1819 ui.write(r.revision(r.lookup(rev)))
1819 ui.write(r.revision(r.lookup(rev)))
1820 except KeyError:
1820 except KeyError:
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1822
1822
1823 @command('debugdate',
1823 @command('debugdate',
1824 [('e', 'extended', None, _('try extended date formats'))],
1824 [('e', 'extended', None, _('try extended date formats'))],
1825 _('[-e] DATE [RANGE]'))
1825 _('[-e] DATE [RANGE]'))
1826 def debugdate(ui, date, range=None, **opts):
1826 def debugdate(ui, date, range=None, **opts):
1827 """parse and display a date"""
1827 """parse and display a date"""
1828 if opts["extended"]:
1828 if opts["extended"]:
1829 d = util.parsedate(date, util.extendeddateformats)
1829 d = util.parsedate(date, util.extendeddateformats)
1830 else:
1830 else:
1831 d = util.parsedate(date)
1831 d = util.parsedate(date)
1832 ui.write(("internal: %s %s\n") % d)
1832 ui.write(("internal: %s %s\n") % d)
1833 ui.write(("standard: %s\n") % util.datestr(d))
1833 ui.write(("standard: %s\n") % util.datestr(d))
1834 if range:
1834 if range:
1835 m = util.matchdate(range)
1835 m = util.matchdate(range)
1836 ui.write(("match: %s\n") % m(d[0]))
1836 ui.write(("match: %s\n") % m(d[0]))
1837
1837
1838 @command('debugdiscovery',
1838 @command('debugdiscovery',
1839 [('', 'old', None, _('use old-style discovery')),
1839 [('', 'old', None, _('use old-style discovery')),
1840 ('', 'nonheads', None,
1840 ('', 'nonheads', None,
1841 _('use old-style discovery with non-heads included')),
1841 _('use old-style discovery with non-heads included')),
1842 ] + remoteopts,
1842 ] + remoteopts,
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1845 """runs the changeset discovery protocol in isolation"""
1845 """runs the changeset discovery protocol in isolation"""
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1847 opts.get('branch'))
1847 opts.get('branch'))
1848 remote = hg.peer(repo, opts, remoteurl)
1848 remote = hg.peer(repo, opts, remoteurl)
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1850
1850
1851 # make sure tests are repeatable
1851 # make sure tests are repeatable
1852 random.seed(12323)
1852 random.seed(12323)
1853
1853
1854 def doit(localheads, remoteheads, remote=remote):
1854 def doit(localheads, remoteheads, remote=remote):
1855 if opts.get('old'):
1855 if opts.get('old'):
1856 if localheads:
1856 if localheads:
1857 raise util.Abort('cannot use localheads with old style '
1857 raise util.Abort('cannot use localheads with old style '
1858 'discovery')
1858 'discovery')
1859 if not util.safehasattr(remote, 'branches'):
1859 if not util.safehasattr(remote, 'branches'):
1860 # enable in-client legacy support
1860 # enable in-client legacy support
1861 remote = localrepo.locallegacypeer(remote.local())
1861 remote = localrepo.locallegacypeer(remote.local())
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1863 force=True)
1863 force=True)
1864 common = set(common)
1864 common = set(common)
1865 if not opts.get('nonheads'):
1865 if not opts.get('nonheads'):
1866 ui.write(("unpruned common: %s\n") %
1866 ui.write(("unpruned common: %s\n") %
1867 " ".join(sorted(short(n) for n in common)))
1867 " ".join(sorted(short(n) for n in common)))
1868 dag = dagutil.revlogdag(repo.changelog)
1868 dag = dagutil.revlogdag(repo.changelog)
1869 all = dag.ancestorset(dag.internalizeall(common))
1869 all = dag.ancestorset(dag.internalizeall(common))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1871 else:
1871 else:
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1873 common = set(common)
1873 common = set(common)
1874 rheads = set(hds)
1874 rheads = set(hds)
1875 lheads = set(repo.heads())
1875 lheads = set(repo.heads())
1876 ui.write(("common heads: %s\n") %
1876 ui.write(("common heads: %s\n") %
1877 " ".join(sorted(short(n) for n in common)))
1877 " ".join(sorted(short(n) for n in common)))
1878 if lheads <= common:
1878 if lheads <= common:
1879 ui.write(("local is subset\n"))
1879 ui.write(("local is subset\n"))
1880 elif rheads <= common:
1880 elif rheads <= common:
1881 ui.write(("remote is subset\n"))
1881 ui.write(("remote is subset\n"))
1882
1882
1883 serverlogs = opts.get('serverlog')
1883 serverlogs = opts.get('serverlog')
1884 if serverlogs:
1884 if serverlogs:
1885 for filename in serverlogs:
1885 for filename in serverlogs:
1886 logfile = open(filename, 'r')
1886 logfile = open(filename, 'r')
1887 try:
1887 try:
1888 line = logfile.readline()
1888 line = logfile.readline()
1889 while line:
1889 while line:
1890 parts = line.strip().split(';')
1890 parts = line.strip().split(';')
1891 op = parts[1]
1891 op = parts[1]
1892 if op == 'cg':
1892 if op == 'cg':
1893 pass
1893 pass
1894 elif op == 'cgss':
1894 elif op == 'cgss':
1895 doit(parts[2].split(' '), parts[3].split(' '))
1895 doit(parts[2].split(' '), parts[3].split(' '))
1896 elif op == 'unb':
1896 elif op == 'unb':
1897 doit(parts[3].split(' '), parts[2].split(' '))
1897 doit(parts[3].split(' '), parts[2].split(' '))
1898 line = logfile.readline()
1898 line = logfile.readline()
1899 finally:
1899 finally:
1900 logfile.close()
1900 logfile.close()
1901
1901
1902 else:
1902 else:
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1904 opts.get('remote_head'))
1904 opts.get('remote_head'))
1905 localrevs = opts.get('local_head')
1905 localrevs = opts.get('local_head')
1906 doit(localrevs, remoterevs)
1906 doit(localrevs, remoterevs)
1907
1907
1908 @command('debugfileset',
1908 @command('debugfileset',
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1910 _('[-r REV] FILESPEC'))
1910 _('[-r REV] FILESPEC'))
1911 def debugfileset(ui, repo, expr, **opts):
1911 def debugfileset(ui, repo, expr, **opts):
1912 '''parse and apply a fileset specification'''
1912 '''parse and apply a fileset specification'''
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1914 if ui.verbose:
1914 if ui.verbose:
1915 tree = fileset.parse(expr)[0]
1915 tree = fileset.parse(expr)[0]
1916 ui.note(tree, "\n")
1916 ui.note(tree, "\n")
1917
1917
1918 for f in fileset.getfileset(ctx, expr):
1918 for f in fileset.getfileset(ctx, expr):
1919 ui.write("%s\n" % f)
1919 ui.write("%s\n" % f)
1920
1920
1921 @command('debugfsinfo', [], _('[PATH]'))
1921 @command('debugfsinfo', [], _('[PATH]'))
1922 def debugfsinfo(ui, path="."):
1922 def debugfsinfo(ui, path="."):
1923 """show information detected about current filesystem"""
1923 """show information detected about current filesystem"""
1924 util.writefile('.debugfsinfo', '')
1924 util.writefile('.debugfsinfo', '')
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1929 and 'yes' or 'no'))
1929 and 'yes' or 'no'))
1930 os.unlink('.debugfsinfo')
1930 os.unlink('.debugfsinfo')
1931
1931
1932 @command('debuggetbundle',
1932 @command('debuggetbundle',
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1936 _('REPO FILE [-H|-C ID]...'))
1936 _('REPO FILE [-H|-C ID]...'))
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1938 """retrieves a bundle from a repo
1938 """retrieves a bundle from a repo
1939
1939
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1941 given file.
1941 given file.
1942 """
1942 """
1943 repo = hg.peer(ui, opts, repopath)
1943 repo = hg.peer(ui, opts, repopath)
1944 if not repo.capable('getbundle'):
1944 if not repo.capable('getbundle'):
1945 raise util.Abort("getbundle() not supported by target repository")
1945 raise util.Abort("getbundle() not supported by target repository")
1946 args = {}
1946 args = {}
1947 if common:
1947 if common:
1948 args['common'] = [bin(s) for s in common]
1948 args['common'] = [bin(s) for s in common]
1949 if head:
1949 if head:
1950 args['heads'] = [bin(s) for s in head]
1950 args['heads'] = [bin(s) for s in head]
1951 # TODO: get desired bundlecaps from command line.
1951 # TODO: get desired bundlecaps from command line.
1952 args['bundlecaps'] = None
1952 args['bundlecaps'] = None
1953 bundle = repo.getbundle('debug', **args)
1953 bundle = repo.getbundle('debug', **args)
1954
1954
1955 bundletype = opts.get('type', 'bzip2').lower()
1955 bundletype = opts.get('type', 'bzip2').lower()
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1957 bundletype = btypes.get(bundletype)
1957 bundletype = btypes.get(bundletype)
1958 if bundletype not in changegroup.bundletypes:
1958 if bundletype not in changegroup.bundletypes:
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1961
1961
1962 @command('debugignore', [], '')
1962 @command('debugignore', [], '')
1963 def debugignore(ui, repo, *values, **opts):
1963 def debugignore(ui, repo, *values, **opts):
1964 """display the combined ignore pattern"""
1964 """display the combined ignore pattern"""
1965 ignore = repo.dirstate._ignore
1965 ignore = repo.dirstate._ignore
1966 includepat = getattr(ignore, 'includepat', None)
1966 includepat = getattr(ignore, 'includepat', None)
1967 if includepat is not None:
1967 if includepat is not None:
1968 ui.write("%s\n" % includepat)
1968 ui.write("%s\n" % includepat)
1969 else:
1969 else:
1970 raise util.Abort(_("no ignore patterns found"))
1970 raise util.Abort(_("no ignore patterns found"))
1971
1971
1972 @command('debugindex',
1972 @command('debugindex',
1973 [('c', 'changelog', False, _('open changelog')),
1973 [('c', 'changelog', False, _('open changelog')),
1974 ('m', 'manifest', False, _('open manifest')),
1974 ('m', 'manifest', False, _('open manifest')),
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1976 _('[-f FORMAT] -c|-m|FILE'))
1976 _('[-f FORMAT] -c|-m|FILE'))
1977 def debugindex(ui, repo, file_=None, **opts):
1977 def debugindex(ui, repo, file_=None, **opts):
1978 """dump the contents of an index file"""
1978 """dump the contents of an index file"""
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1980 format = opts.get('format', 0)
1980 format = opts.get('format', 0)
1981 if format not in (0, 1):
1981 if format not in (0, 1):
1982 raise util.Abort(_("unknown format %d") % format)
1982 raise util.Abort(_("unknown format %d") % format)
1983
1983
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1985 if generaldelta:
1985 if generaldelta:
1986 basehdr = ' delta'
1986 basehdr = ' delta'
1987 else:
1987 else:
1988 basehdr = ' base'
1988 basehdr = ' base'
1989
1989
1990 if format == 0:
1990 if format == 0:
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1992 " nodeid p1 p2\n")
1992 " nodeid p1 p2\n")
1993 elif format == 1:
1993 elif format == 1:
1994 ui.write(" rev flag offset length"
1994 ui.write(" rev flag offset length"
1995 " size " + basehdr + " link p1 p2"
1995 " size " + basehdr + " link p1 p2"
1996 " nodeid\n")
1996 " nodeid\n")
1997
1997
1998 for i in r:
1998 for i in r:
1999 node = r.node(i)
1999 node = r.node(i)
2000 if generaldelta:
2000 if generaldelta:
2001 base = r.deltaparent(i)
2001 base = r.deltaparent(i)
2002 else:
2002 else:
2003 base = r.chainbase(i)
2003 base = r.chainbase(i)
2004 if format == 0:
2004 if format == 0:
2005 try:
2005 try:
2006 pp = r.parents(node)
2006 pp = r.parents(node)
2007 except Exception:
2007 except Exception:
2008 pp = [nullid, nullid]
2008 pp = [nullid, nullid]
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2011 short(node), short(pp[0]), short(pp[1])))
2011 short(node), short(pp[0]), short(pp[1])))
2012 elif format == 1:
2012 elif format == 1:
2013 pr = r.parentrevs(i)
2013 pr = r.parentrevs(i)
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2017
2017
2018 @command('debugindexdot', [], _('FILE'))
2018 @command('debugindexdot', [], _('FILE'))
2019 def debugindexdot(ui, repo, file_):
2019 def debugindexdot(ui, repo, file_):
2020 """dump an index DAG as a graphviz dot file"""
2020 """dump an index DAG as a graphviz dot file"""
2021 r = None
2021 r = None
2022 if repo:
2022 if repo:
2023 filelog = repo.file(file_)
2023 filelog = repo.file(file_)
2024 if len(filelog):
2024 if len(filelog):
2025 r = filelog
2025 r = filelog
2026 if not r:
2026 if not r:
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2028 ui.write(("digraph G {\n"))
2028 ui.write(("digraph G {\n"))
2029 for i in r:
2029 for i in r:
2030 node = r.node(i)
2030 node = r.node(i)
2031 pp = r.parents(node)
2031 pp = r.parents(node)
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2033 if pp[1] != nullid:
2033 if pp[1] != nullid:
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2035 ui.write("}\n")
2035 ui.write("}\n")
2036
2036
2037 @command('debuginstall', [], '')
2037 @command('debuginstall', [], '')
2038 def debuginstall(ui):
2038 def debuginstall(ui):
2039 '''test Mercurial installation
2039 '''test Mercurial installation
2040
2040
2041 Returns 0 on success.
2041 Returns 0 on success.
2042 '''
2042 '''
2043
2043
2044 def writetemp(contents):
2044 def writetemp(contents):
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2046 f = os.fdopen(fd, "wb")
2046 f = os.fdopen(fd, "wb")
2047 f.write(contents)
2047 f.write(contents)
2048 f.close()
2048 f.close()
2049 return name
2049 return name
2050
2050
2051 problems = 0
2051 problems = 0
2052
2052
2053 # encoding
2053 # encoding
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2055 try:
2055 try:
2056 encoding.fromlocal("test")
2056 encoding.fromlocal("test")
2057 except util.Abort, inst:
2057 except util.Abort, inst:
2058 ui.write(" %s\n" % inst)
2058 ui.write(" %s\n" % inst)
2059 ui.write(_(" (check that your locale is properly set)\n"))
2059 ui.write(_(" (check that your locale is properly set)\n"))
2060 problems += 1
2060 problems += 1
2061
2061
2062 # Python lib
2062 # Python lib
2063 ui.status(_("checking Python lib (%s)...\n")
2063 ui.status(_("checking Python lib (%s)...\n")
2064 % os.path.dirname(os.__file__))
2064 % os.path.dirname(os.__file__))
2065
2065
2066 # compiled modules
2066 # compiled modules
2067 ui.status(_("checking installed modules (%s)...\n")
2067 ui.status(_("checking installed modules (%s)...\n")
2068 % os.path.dirname(__file__))
2068 % os.path.dirname(__file__))
2069 try:
2069 try:
2070 import bdiff, mpatch, base85, osutil
2070 import bdiff, mpatch, base85, osutil
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2072 except Exception, inst:
2072 except Exception, inst:
2073 ui.write(" %s\n" % inst)
2073 ui.write(" %s\n" % inst)
2074 ui.write(_(" One or more extensions could not be found"))
2074 ui.write(_(" One or more extensions could not be found"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2076 problems += 1
2076 problems += 1
2077
2077
2078 # templates
2078 # templates
2079 import templater
2079 import templater
2080 p = templater.templatepath()
2080 p = templater.templatepath()
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2082 try:
2082 try:
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2084 except Exception, inst:
2084 except Exception, inst:
2085 ui.write(" %s\n" % inst)
2085 ui.write(" %s\n" % inst)
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2087 problems += 1
2087 problems += 1
2088
2088
2089 # editor
2089 # editor
2090 ui.status(_("checking commit editor...\n"))
2090 ui.status(_("checking commit editor...\n"))
2091 editor = ui.geteditor()
2091 editor = ui.geteditor()
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2093 if not cmdpath:
2093 if not cmdpath:
2094 if editor == 'vi':
2094 if editor == 'vi':
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2096 ui.write(_(" (specify a commit editor in your configuration"
2096 ui.write(_(" (specify a commit editor in your configuration"
2097 " file)\n"))
2097 " file)\n"))
2098 else:
2098 else:
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2100 ui.write(_(" (specify a commit editor in your configuration"
2100 ui.write(_(" (specify a commit editor in your configuration"
2101 " file)\n"))
2101 " file)\n"))
2102 problems += 1
2102 problems += 1
2103
2103
2104 # check username
2104 # check username
2105 ui.status(_("checking username...\n"))
2105 ui.status(_("checking username...\n"))
2106 try:
2106 try:
2107 ui.username()
2107 ui.username()
2108 except util.Abort, e:
2108 except util.Abort, e:
2109 ui.write(" %s\n" % e)
2109 ui.write(" %s\n" % e)
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2111 problems += 1
2111 problems += 1
2112
2112
2113 if not problems:
2113 if not problems:
2114 ui.status(_("no problems detected\n"))
2114 ui.status(_("no problems detected\n"))
2115 else:
2115 else:
2116 ui.write(_("%s problems detected,"
2116 ui.write(_("%s problems detected,"
2117 " please check your install!\n") % problems)
2117 " please check your install!\n") % problems)
2118
2118
2119 return problems
2119 return problems
2120
2120
2121 @command('debugknown', [], _('REPO ID...'))
2121 @command('debugknown', [], _('REPO ID...'))
2122 def debugknown(ui, repopath, *ids, **opts):
2122 def debugknown(ui, repopath, *ids, **opts):
2123 """test whether node ids are known to a repo
2123 """test whether node ids are known to a repo
2124
2124
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2126 and 1s indicating unknown/known.
2126 and 1s indicating unknown/known.
2127 """
2127 """
2128 repo = hg.peer(ui, opts, repopath)
2128 repo = hg.peer(ui, opts, repopath)
2129 if not repo.capable('known'):
2129 if not repo.capable('known'):
2130 raise util.Abort("known() not supported by target repository")
2130 raise util.Abort("known() not supported by target repository")
2131 flags = repo.known([bin(s) for s in ids])
2131 flags = repo.known([bin(s) for s in ids])
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2133
2133
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2135 def debuglabelcomplete(ui, repo, *args):
2135 def debuglabelcomplete(ui, repo, *args):
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2137
2137
2138 labels = set()
2138 labels = set()
2139 labels.update(t[0] for t in repo.tagslist())
2139 labels.update(t[0] for t in repo.tagslist())
2140 labels.update(repo._bookmarks.keys())
2140 labels.update(repo._bookmarks.keys())
2141 for heads in repo.branchmap().itervalues():
2141 for heads in repo.branchmap().itervalues():
2142 for h in heads:
2142 for h in heads:
2143 ctx = repo[h]
2143 ctx = repo[h]
2144 if not ctx.closesbranch():
2144 if not ctx.closesbranch():
2145 labels.add(ctx.branch())
2145 labels.add(ctx.branch())
2146 completions = set()
2146 completions = set()
2147 if not args:
2147 if not args:
2148 args = ['']
2148 args = ['']
2149 for a in args:
2149 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2150 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2151 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2152 ui.write('\n')
2153
2153
2154 @command('debugobsolete',
2154 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2155 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2156 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2159 """create arbitrary obsolete marker
2160
2160
2161 With no arguments, displays the list of obsolescence markers."""
2161 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2162 def parsenodeid(s):
2163 try:
2163 try:
2164 # We do not use revsingle/revrange functions here to accept
2164 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2165 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2166 # local repository.
2167 n = bin(s)
2167 n = bin(s)
2168 if len(n) != len(nullid):
2168 if len(n) != len(nullid):
2169 raise TypeError()
2169 raise TypeError()
2170 return n
2170 return n
2171 except TypeError:
2171 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2172 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2173 'node identifiers')
2174
2174
2175 if precursor is not None:
2175 if precursor is not None:
2176 metadata = {}
2176 metadata = {}
2177 if 'date' in opts:
2177 if 'date' in opts:
2178 metadata['date'] = opts['date']
2178 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2179 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2181 l = repo.lock()
2182 try:
2182 try:
2183 tr = repo.transaction('debugobsolete')
2183 tr = repo.transaction('debugobsolete')
2184 try:
2184 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2186 opts['flags'], metadata)
2187 tr.close()
2187 tr.close()
2188 finally:
2188 finally:
2189 tr.release()
2189 tr.release()
2190 finally:
2190 finally:
2191 l.release()
2191 l.release()
2192 else:
2192 else:
2193 for m in obsolete.allmarkers(repo):
2193 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2194 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2195 for repl in m.succnodes():
2196 ui.write(' ')
2196 ui.write(' ')
2197 ui.write(hex(repl))
2197 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2198 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2200 sorted(m.metadata().items()))))
2201 ui.write('\n')
2201 ui.write('\n')
2202
2202
2203 @command('debugpathcomplete',
2203 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2204 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2205 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2206 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2207 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2208 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2210 '''complete part or all of a tracked path
2211
2211
2212 This command supports shells that offer path name completion. It
2212 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2213 currently completes only files already known to the dirstate.
2214
2214
2215 Completion extends only to the next path segment unless
2215 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2216 --full is specified, in which case entire paths are used.'''
2217
2217
2218 def complete(path, acceptable):
2218 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2219 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2221 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2222 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2223 return [], []
2224 if os.path.isdir(spec):
2224 if os.path.isdir(spec):
2225 spec += '/'
2225 spec += '/'
2226 spec = spec[len(rootdir):]
2226 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2227 fixpaths = os.sep != '/'
2228 if fixpaths:
2228 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2229 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2230 speclen = len(spec)
2231 fullpaths = opts['full']
2231 fullpaths = opts['full']
2232 files, dirs = set(), set()
2232 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2233 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2234 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2235 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2236 if fixpaths:
2237 f = f.replace('/', os.sep)
2237 f = f.replace('/', os.sep)
2238 if fullpaths:
2238 if fullpaths:
2239 addfile(f)
2239 addfile(f)
2240 continue
2240 continue
2241 s = f.find(os.sep, speclen)
2241 s = f.find(os.sep, speclen)
2242 if s >= 0:
2242 if s >= 0:
2243 adddir(f[:s + 1])
2243 adddir(f[:s + 1])
2244 else:
2244 else:
2245 addfile(f)
2245 addfile(f)
2246 return files, dirs
2246 return files, dirs
2247
2247
2248 acceptable = ''
2248 acceptable = ''
2249 if opts['normal']:
2249 if opts['normal']:
2250 acceptable += 'nm'
2250 acceptable += 'nm'
2251 if opts['added']:
2251 if opts['added']:
2252 acceptable += 'a'
2252 acceptable += 'a'
2253 if opts['removed']:
2253 if opts['removed']:
2254 acceptable += 'r'
2254 acceptable += 'r'
2255 cwd = repo.getcwd()
2255 cwd = repo.getcwd()
2256 if not specs:
2256 if not specs:
2257 specs = ['.']
2257 specs = ['.']
2258
2258
2259 files, dirs = set(), set()
2259 files, dirs = set(), set()
2260 for spec in specs:
2260 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2261 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2262 files.update(f)
2263 dirs.update(d)
2263 dirs.update(d)
2264 if not files and len(dirs) == 1:
2264 if not files and len(dirs) == 1:
2265 # force the shell to consider a completion that matches one
2265 # force the shell to consider a completion that matches one
2266 # directory and zero files to be ambiguous
2266 # directory and zero files to be ambiguous
2267 dirs.add(iter(dirs).next() + '.')
2267 dirs.add(iter(dirs).next() + '.')
2268 files.update(dirs)
2268 files.update(dirs)
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2270 ui.write('\n')
2270 ui.write('\n')
2271
2271
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2274 '''access the pushkey key/value protocol
2274 '''access the pushkey key/value protocol
2275
2275
2276 With two args, list the keys in the given namespace.
2276 With two args, list the keys in the given namespace.
2277
2277
2278 With five args, set a key to new if it currently is set to old.
2278 With five args, set a key to new if it currently is set to old.
2279 Reports success or failure.
2279 Reports success or failure.
2280 '''
2280 '''
2281
2281
2282 target = hg.peer(ui, {}, repopath)
2282 target = hg.peer(ui, {}, repopath)
2283 if keyinfo:
2283 if keyinfo:
2284 key, old, new = keyinfo
2284 key, old, new = keyinfo
2285 r = target.pushkey(namespace, key, old, new)
2285 r = target.pushkey(namespace, key, old, new)
2286 ui.status(str(r) + '\n')
2286 ui.status(str(r) + '\n')
2287 return not r
2287 return not r
2288 else:
2288 else:
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2291 v.encode('string-escape')))
2291 v.encode('string-escape')))
2292
2292
2293 @command('debugpvec', [], _('A B'))
2293 @command('debugpvec', [], _('A B'))
2294 def debugpvec(ui, repo, a, b=None):
2294 def debugpvec(ui, repo, a, b=None):
2295 ca = scmutil.revsingle(repo, a)
2295 ca = scmutil.revsingle(repo, a)
2296 cb = scmutil.revsingle(repo, b)
2296 cb = scmutil.revsingle(repo, b)
2297 pa = pvec.ctxpvec(ca)
2297 pa = pvec.ctxpvec(ca)
2298 pb = pvec.ctxpvec(cb)
2298 pb = pvec.ctxpvec(cb)
2299 if pa == pb:
2299 if pa == pb:
2300 rel = "="
2300 rel = "="
2301 elif pa > pb:
2301 elif pa > pb:
2302 rel = ">"
2302 rel = ">"
2303 elif pa < pb:
2303 elif pa < pb:
2304 rel = "<"
2304 rel = "<"
2305 elif pa | pb:
2305 elif pa | pb:
2306 rel = "|"
2306 rel = "|"
2307 ui.write(_("a: %s\n") % pa)
2307 ui.write(_("a: %s\n") % pa)
2308 ui.write(_("b: %s\n") % pb)
2308 ui.write(_("b: %s\n") % pb)
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2312 pa.distance(pb), rel))
2312 pa.distance(pb), rel))
2313
2313
2314 @command('debugrebuilddirstate|debugrebuildstate',
2314 @command('debugrebuilddirstate|debugrebuildstate',
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2316 _('[-r REV]'))
2316 _('[-r REV]'))
2317 def debugrebuilddirstate(ui, repo, rev):
2317 def debugrebuilddirstate(ui, repo, rev):
2318 """rebuild the dirstate as it would look like for the given revision
2318 """rebuild the dirstate as it would look like for the given revision
2319
2319
2320 If no revision is specified the first current parent will be used.
2320 If no revision is specified the first current parent will be used.
2321
2321
2322 The dirstate will be set to the files of the given revision.
2322 The dirstate will be set to the files of the given revision.
2323 The actual working directory content or existing dirstate
2323 The actual working directory content or existing dirstate
2324 information such as adds or removes is not considered.
2324 information such as adds or removes is not considered.
2325
2325
2326 One use of this command is to make the next :hg:`status` invocation
2326 One use of this command is to make the next :hg:`status` invocation
2327 check the actual file content.
2327 check the actual file content.
2328 """
2328 """
2329 ctx = scmutil.revsingle(repo, rev)
2329 ctx = scmutil.revsingle(repo, rev)
2330 wlock = repo.wlock()
2330 wlock = repo.wlock()
2331 try:
2331 try:
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2333 finally:
2333 finally:
2334 wlock.release()
2334 wlock.release()
2335
2335
2336 @command('debugrename',
2336 @command('debugrename',
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2338 _('[-r REV] FILE'))
2338 _('[-r REV] FILE'))
2339 def debugrename(ui, repo, file1, *pats, **opts):
2339 def debugrename(ui, repo, file1, *pats, **opts):
2340 """dump rename information"""
2340 """dump rename information"""
2341
2341
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2344 for abs in ctx.walk(m):
2344 for abs in ctx.walk(m):
2345 fctx = ctx[abs]
2345 fctx = ctx[abs]
2346 o = fctx.filelog().renamed(fctx.filenode())
2346 o = fctx.filelog().renamed(fctx.filenode())
2347 rel = m.rel(abs)
2347 rel = m.rel(abs)
2348 if o:
2348 if o:
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2350 else:
2350 else:
2351 ui.write(_("%s not renamed\n") % rel)
2351 ui.write(_("%s not renamed\n") % rel)
2352
2352
2353 @command('debugrevlog',
2353 @command('debugrevlog',
2354 [('c', 'changelog', False, _('open changelog')),
2354 [('c', 'changelog', False, _('open changelog')),
2355 ('m', 'manifest', False, _('open manifest')),
2355 ('m', 'manifest', False, _('open manifest')),
2356 ('d', 'dump', False, _('dump index data'))],
2356 ('d', 'dump', False, _('dump index data'))],
2357 _('-c|-m|FILE'))
2357 _('-c|-m|FILE'))
2358 def debugrevlog(ui, repo, file_=None, **opts):
2358 def debugrevlog(ui, repo, file_=None, **opts):
2359 """show data and statistics about a revlog"""
2359 """show data and statistics about a revlog"""
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2361
2361
2362 if opts.get("dump"):
2362 if opts.get("dump"):
2363 numrevs = len(r)
2363 numrevs = len(r)
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2365 " rawsize totalsize compression heads\n")
2365 " rawsize totalsize compression heads\n")
2366 ts = 0
2366 ts = 0
2367 heads = set()
2367 heads = set()
2368 for rev in xrange(numrevs):
2368 for rev in xrange(numrevs):
2369 dbase = r.deltaparent(rev)
2369 dbase = r.deltaparent(rev)
2370 if dbase == -1:
2370 if dbase == -1:
2371 dbase = rev
2371 dbase = rev
2372 cbase = r.chainbase(rev)
2372 cbase = r.chainbase(rev)
2373 p1, p2 = r.parentrevs(rev)
2373 p1, p2 = r.parentrevs(rev)
2374 rs = r.rawsize(rev)
2374 rs = r.rawsize(rev)
2375 ts = ts + rs
2375 ts = ts + rs
2376 heads -= set(r.parentrevs(rev))
2376 heads -= set(r.parentrevs(rev))
2377 heads.add(rev)
2377 heads.add(rev)
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2380 r.start(dbase), r.start(cbase),
2380 r.start(dbase), r.start(cbase),
2381 r.start(p1), r.start(p2),
2381 r.start(p1), r.start(p2),
2382 rs, ts, ts / r.end(rev), len(heads)))
2382 rs, ts, ts / r.end(rev), len(heads)))
2383 return 0
2383 return 0
2384
2384
2385 v = r.version
2385 v = r.version
2386 format = v & 0xFFFF
2386 format = v & 0xFFFF
2387 flags = []
2387 flags = []
2388 gdelta = False
2388 gdelta = False
2389 if v & revlog.REVLOGNGINLINEDATA:
2389 if v & revlog.REVLOGNGINLINEDATA:
2390 flags.append('inline')
2390 flags.append('inline')
2391 if v & revlog.REVLOGGENERALDELTA:
2391 if v & revlog.REVLOGGENERALDELTA:
2392 gdelta = True
2392 gdelta = True
2393 flags.append('generaldelta')
2393 flags.append('generaldelta')
2394 if not flags:
2394 if not flags:
2395 flags = ['(none)']
2395 flags = ['(none)']
2396
2396
2397 nummerges = 0
2397 nummerges = 0
2398 numfull = 0
2398 numfull = 0
2399 numprev = 0
2399 numprev = 0
2400 nump1 = 0
2400 nump1 = 0
2401 nump2 = 0
2401 nump2 = 0
2402 numother = 0
2402 numother = 0
2403 nump1prev = 0
2403 nump1prev = 0
2404 nump2prev = 0
2404 nump2prev = 0
2405 chainlengths = []
2405 chainlengths = []
2406
2406
2407 datasize = [None, 0, 0L]
2407 datasize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2410
2410
2411 def addsize(size, l):
2411 def addsize(size, l):
2412 if l[0] is None or size < l[0]:
2412 if l[0] is None or size < l[0]:
2413 l[0] = size
2413 l[0] = size
2414 if size > l[1]:
2414 if size > l[1]:
2415 l[1] = size
2415 l[1] = size
2416 l[2] += size
2416 l[2] += size
2417
2417
2418 numrevs = len(r)
2418 numrevs = len(r)
2419 for rev in xrange(numrevs):
2419 for rev in xrange(numrevs):
2420 p1, p2 = r.parentrevs(rev)
2420 p1, p2 = r.parentrevs(rev)
2421 delta = r.deltaparent(rev)
2421 delta = r.deltaparent(rev)
2422 if format > 0:
2422 if format > 0:
2423 addsize(r.rawsize(rev), datasize)
2423 addsize(r.rawsize(rev), datasize)
2424 if p2 != nullrev:
2424 if p2 != nullrev:
2425 nummerges += 1
2425 nummerges += 1
2426 size = r.length(rev)
2426 size = r.length(rev)
2427 if delta == nullrev:
2427 if delta == nullrev:
2428 chainlengths.append(0)
2428 chainlengths.append(0)
2429 numfull += 1
2429 numfull += 1
2430 addsize(size, fullsize)
2430 addsize(size, fullsize)
2431 else:
2431 else:
2432 chainlengths.append(chainlengths[delta] + 1)
2432 chainlengths.append(chainlengths[delta] + 1)
2433 addsize(size, deltasize)
2433 addsize(size, deltasize)
2434 if delta == rev - 1:
2434 if delta == rev - 1:
2435 numprev += 1
2435 numprev += 1
2436 if delta == p1:
2436 if delta == p1:
2437 nump1prev += 1
2437 nump1prev += 1
2438 elif delta == p2:
2438 elif delta == p2:
2439 nump2prev += 1
2439 nump2prev += 1
2440 elif delta == p1:
2440 elif delta == p1:
2441 nump1 += 1
2441 nump1 += 1
2442 elif delta == p2:
2442 elif delta == p2:
2443 nump2 += 1
2443 nump2 += 1
2444 elif delta != nullrev:
2444 elif delta != nullrev:
2445 numother += 1
2445 numother += 1
2446
2446
2447 # Adjust size min value for empty cases
2447 # Adjust size min value for empty cases
2448 for size in (datasize, fullsize, deltasize):
2448 for size in (datasize, fullsize, deltasize):
2449 if size[0] is None:
2449 if size[0] is None:
2450 size[0] = 0
2450 size[0] = 0
2451
2451
2452 numdeltas = numrevs - numfull
2452 numdeltas = numrevs - numfull
2453 numoprev = numprev - nump1prev - nump2prev
2453 numoprev = numprev - nump1prev - nump2prev
2454 totalrawsize = datasize[2]
2454 totalrawsize = datasize[2]
2455 datasize[2] /= numrevs
2455 datasize[2] /= numrevs
2456 fulltotal = fullsize[2]
2456 fulltotal = fullsize[2]
2457 fullsize[2] /= numfull
2457 fullsize[2] /= numfull
2458 deltatotal = deltasize[2]
2458 deltatotal = deltasize[2]
2459 if numrevs - numfull > 0:
2459 if numrevs - numfull > 0:
2460 deltasize[2] /= numrevs - numfull
2460 deltasize[2] /= numrevs - numfull
2461 totalsize = fulltotal + deltatotal
2461 totalsize = fulltotal + deltatotal
2462 avgchainlen = sum(chainlengths) / numrevs
2462 avgchainlen = sum(chainlengths) / numrevs
2463 compratio = totalrawsize / totalsize
2463 compratio = totalrawsize / totalsize
2464
2464
2465 basedfmtstr = '%%%dd\n'
2465 basedfmtstr = '%%%dd\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2467
2467
2468 def dfmtstr(max):
2468 def dfmtstr(max):
2469 return basedfmtstr % len(str(max))
2469 return basedfmtstr % len(str(max))
2470 def pcfmtstr(max, padding=0):
2470 def pcfmtstr(max, padding=0):
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2472
2472
2473 def pcfmt(value, total):
2473 def pcfmt(value, total):
2474 return (value, 100 * float(value) / total)
2474 return (value, 100 * float(value) / total)
2475
2475
2476 ui.write(('format : %d\n') % format)
2476 ui.write(('format : %d\n') % format)
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2478
2478
2479 ui.write('\n')
2479 ui.write('\n')
2480 fmt = pcfmtstr(totalsize)
2480 fmt = pcfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2491
2491
2492 ui.write('\n')
2492 ui.write('\n')
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2496
2496
2497 if format > 0:
2497 if format > 0:
2498 ui.write('\n')
2498 ui.write('\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(datasize))
2500 % tuple(datasize))
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2502 % tuple(fullsize))
2502 % tuple(fullsize))
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2504 % tuple(deltasize))
2504 % tuple(deltasize))
2505
2505
2506 if numdeltas > 0:
2506 if numdeltas > 0:
2507 ui.write('\n')
2507 ui.write('\n')
2508 fmt = pcfmtstr(numdeltas)
2508 fmt = pcfmtstr(numdeltas)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2511 if numprev > 0:
2511 if numprev > 0:
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2513 numprev))
2513 numprev))
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2515 numprev))
2515 numprev))
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2517 numprev))
2517 numprev))
2518 if gdelta:
2518 if gdelta:
2519 ui.write(('deltas against p1 : ')
2519 ui.write(('deltas against p1 : ')
2520 + fmt % pcfmt(nump1, numdeltas))
2520 + fmt % pcfmt(nump1, numdeltas))
2521 ui.write(('deltas against p2 : ')
2521 ui.write(('deltas against p2 : ')
2522 + fmt % pcfmt(nump2, numdeltas))
2522 + fmt % pcfmt(nump2, numdeltas))
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2524 numdeltas))
2524 numdeltas))
2525
2525
2526 @command('debugrevspec', [], ('REVSPEC'))
2526 @command('debugrevspec', [], ('REVSPEC'))
2527 def debugrevspec(ui, repo, expr):
2527 def debugrevspec(ui, repo, expr):
2528 """parse and apply a revision specification
2528 """parse and apply a revision specification
2529
2529
2530 Use --verbose to print the parsed tree before and after aliases
2530 Use --verbose to print the parsed tree before and after aliases
2531 expansion.
2531 expansion.
2532 """
2532 """
2533 if ui.verbose:
2533 if ui.verbose:
2534 tree = revset.parse(expr)[0]
2534 tree = revset.parse(expr)[0]
2535 ui.note(revset.prettyformat(tree), "\n")
2535 ui.note(revset.prettyformat(tree), "\n")
2536 newtree = revset.findaliases(ui, tree)
2536 newtree = revset.findaliases(ui, tree)
2537 if newtree != tree:
2537 if newtree != tree:
2538 ui.note(revset.prettyformat(newtree), "\n")
2538 ui.note(revset.prettyformat(newtree), "\n")
2539 func = revset.match(ui, expr)
2539 func = revset.match(ui, expr)
2540 for c in func(repo, range(len(repo))):
2540 for c in func(repo, range(len(repo))):
2541 ui.write("%s\n" % c)
2541 ui.write("%s\n" % c)
2542
2542
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2545 """manually set the parents of the current working directory
2545 """manually set the parents of the current working directory
2546
2546
2547 This is useful for writing repository conversion tools, but should
2547 This is useful for writing repository conversion tools, but should
2548 be used with care.
2548 be used with care.
2549
2549
2550 Returns 0 on success.
2550 Returns 0 on success.
2551 """
2551 """
2552
2552
2553 r1 = scmutil.revsingle(repo, rev1).node()
2553 r1 = scmutil.revsingle(repo, rev1).node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2555
2555
2556 wlock = repo.wlock()
2556 wlock = repo.wlock()
2557 try:
2557 try:
2558 repo.setparents(r1, r2)
2558 repo.setparents(r1, r2)
2559 finally:
2559 finally:
2560 wlock.release()
2560 wlock.release()
2561
2561
2562 @command('debugdirstate|debugstate',
2562 @command('debugdirstate|debugstate',
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2565 _('[OPTION]...'))
2565 _('[OPTION]...'))
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2567 """show the contents of the current dirstate"""
2567 """show the contents of the current dirstate"""
2568 timestr = ""
2568 timestr = ""
2569 showdate = not nodates
2569 showdate = not nodates
2570 if datesort:
2570 if datesort:
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2572 else:
2572 else:
2573 keyfunc = None # sort by filename
2573 keyfunc = None # sort by filename
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2575 if showdate:
2575 if showdate:
2576 if ent[3] == -1:
2576 if ent[3] == -1:
2577 # Pad or slice to locale representation
2577 # Pad or slice to locale representation
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2579 time.localtime(0)))
2579 time.localtime(0)))
2580 timestr = 'unset'
2580 timestr = 'unset'
2581 timestr = (timestr[:locale_len] +
2581 timestr = (timestr[:locale_len] +
2582 ' ' * (locale_len - len(timestr)))
2582 ' ' * (locale_len - len(timestr)))
2583 else:
2583 else:
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2585 time.localtime(ent[3]))
2585 time.localtime(ent[3]))
2586 if ent[1] & 020000:
2586 if ent[1] & 020000:
2587 mode = 'lnk'
2587 mode = 'lnk'
2588 else:
2588 else:
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2591 for f in repo.dirstate.copies():
2591 for f in repo.dirstate.copies():
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2593
2593
2594 @command('debugsub',
2594 @command('debugsub',
2595 [('r', 'rev', '',
2595 [('r', 'rev', '',
2596 _('revision to check'), _('REV'))],
2596 _('revision to check'), _('REV'))],
2597 _('[-r REV] [REV]'))
2597 _('[-r REV] [REV]'))
2598 def debugsub(ui, repo, rev=None):
2598 def debugsub(ui, repo, rev=None):
2599 ctx = scmutil.revsingle(repo, rev, None)
2599 ctx = scmutil.revsingle(repo, rev, None)
2600 for k, v in sorted(ctx.substate.items()):
2600 for k, v in sorted(ctx.substate.items()):
2601 ui.write(('path %s\n') % k)
2601 ui.write(('path %s\n') % k)
2602 ui.write((' source %s\n') % v[0])
2602 ui.write((' source %s\n') % v[0])
2603 ui.write((' revision %s\n') % v[1])
2603 ui.write((' revision %s\n') % v[1])
2604
2604
2605 @command('debugsuccessorssets',
2605 @command('debugsuccessorssets',
2606 [],
2606 [],
2607 _('[REV]'))
2607 _('[REV]'))
2608 def debugsuccessorssets(ui, repo, *revs):
2608 def debugsuccessorssets(ui, repo, *revs):
2609 """show set of successors for revision
2609 """show set of successors for revision
2610
2610
2611 A successors set of changeset A is a consistent group of revisions that
2611 A successors set of changeset A is a consistent group of revisions that
2612 succeed A. It contains non-obsolete changesets only.
2612 succeed A. It contains non-obsolete changesets only.
2613
2613
2614 In most cases a changeset A has a single successors set containing a single
2614 In most cases a changeset A has a single successors set containing a single
2615 successor (changeset A replaced by A').
2615 successor (changeset A replaced by A').
2616
2616
2617 A changeset that is made obsolete with no successors are called "pruned".
2617 A changeset that is made obsolete with no successors are called "pruned".
2618 Such changesets have no successors sets at all.
2618 Such changesets have no successors sets at all.
2619
2619
2620 A changeset that has been "split" will have a successors set containing
2620 A changeset that has been "split" will have a successors set containing
2621 more than one successor.
2621 more than one successor.
2622
2622
2623 A changeset that has been rewritten in multiple different ways is called
2623 A changeset that has been rewritten in multiple different ways is called
2624 "divergent". Such changesets have multiple successor sets (each of which
2624 "divergent". Such changesets have multiple successor sets (each of which
2625 may also be split, i.e. have multiple successors).
2625 may also be split, i.e. have multiple successors).
2626
2626
2627 Results are displayed as follows::
2627 Results are displayed as follows::
2628
2628
2629 <rev1>
2629 <rev1>
2630 <successors-1A>
2630 <successors-1A>
2631 <rev2>
2631 <rev2>
2632 <successors-2A>
2632 <successors-2A>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2634
2634
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2636 holds one element, whereas the second holds three (i.e. the changeset has
2636 holds one element, whereas the second holds three (i.e. the changeset has
2637 been split).
2637 been split).
2638 """
2638 """
2639 # passed to successorssets caching computation from one call to another
2639 # passed to successorssets caching computation from one call to another
2640 cache = {}
2640 cache = {}
2641 ctx2str = str
2641 ctx2str = str
2642 node2str = short
2642 node2str = short
2643 if ui.debug():
2643 if ui.debug():
2644 def ctx2str(ctx):
2644 def ctx2str(ctx):
2645 return ctx.hex()
2645 return ctx.hex()
2646 node2str = hex
2646 node2str = hex
2647 for rev in scmutil.revrange(repo, revs):
2647 for rev in scmutil.revrange(repo, revs):
2648 ctx = repo[rev]
2648 ctx = repo[rev]
2649 ui.write('%s\n'% ctx2str(ctx))
2649 ui.write('%s\n'% ctx2str(ctx))
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2651 if succsset:
2651 if succsset:
2652 ui.write(' ')
2652 ui.write(' ')
2653 ui.write(node2str(succsset[0]))
2653 ui.write(node2str(succsset[0]))
2654 for node in succsset[1:]:
2654 for node in succsset[1:]:
2655 ui.write(' ')
2655 ui.write(' ')
2656 ui.write(node2str(node))
2656 ui.write(node2str(node))
2657 ui.write('\n')
2657 ui.write('\n')
2658
2658
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2660 def debugwalk(ui, repo, *pats, **opts):
2660 def debugwalk(ui, repo, *pats, **opts):
2661 """show how files match on given patterns"""
2661 """show how files match on given patterns"""
2662 m = scmutil.match(repo[None], pats, opts)
2662 m = scmutil.match(repo[None], pats, opts)
2663 items = list(repo.walk(m))
2663 items = list(repo.walk(m))
2664 if not items:
2664 if not items:
2665 return
2665 return
2666 f = lambda fn: fn
2666 f = lambda fn: fn
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2668 f = lambda fn: util.normpath(fn)
2668 f = lambda fn: util.normpath(fn)
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2670 max([len(abs) for abs in items]),
2670 max([len(abs) for abs in items]),
2671 max([len(m.rel(abs)) for abs in items]))
2671 max([len(m.rel(abs)) for abs in items]))
2672 for abs in items:
2672 for abs in items:
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2674 ui.write("%s\n" % line.rstrip())
2674 ui.write("%s\n" % line.rstrip())
2675
2675
2676 @command('debugwireargs',
2676 @command('debugwireargs',
2677 [('', 'three', '', 'three'),
2677 [('', 'three', '', 'three'),
2678 ('', 'four', '', 'four'),
2678 ('', 'four', '', 'four'),
2679 ('', 'five', '', 'five'),
2679 ('', 'five', '', 'five'),
2680 ] + remoteopts,
2680 ] + remoteopts,
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2682 def debugwireargs(ui, repopath, *vals, **opts):
2682 def debugwireargs(ui, repopath, *vals, **opts):
2683 repo = hg.peer(ui, opts, repopath)
2683 repo = hg.peer(ui, opts, repopath)
2684 for opt in remoteopts:
2684 for opt in remoteopts:
2685 del opts[opt[1]]
2685 del opts[opt[1]]
2686 args = {}
2686 args = {}
2687 for k, v in opts.iteritems():
2687 for k, v in opts.iteritems():
2688 if v:
2688 if v:
2689 args[k] = v
2689 args[k] = v
2690 # run twice to check that we don't mess up the stream for the next command
2690 # run twice to check that we don't mess up the stream for the next command
2691 res1 = repo.debugwireargs(*vals, **args)
2691 res1 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2693 ui.write("%s\n" % res1)
2693 ui.write("%s\n" % res1)
2694 if res1 != res2:
2694 if res1 != res2:
2695 ui.warn("%s\n" % res2)
2695 ui.warn("%s\n" % res2)
2696
2696
2697 @command('^diff',
2697 @command('^diff',
2698 [('r', 'rev', [], _('revision'), _('REV')),
2698 [('r', 'rev', [], _('revision'), _('REV')),
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2702 def diff(ui, repo, *pats, **opts):
2702 def diff(ui, repo, *pats, **opts):
2703 """diff repository (or selected files)
2703 """diff repository (or selected files)
2704
2704
2705 Show differences between revisions for the specified files.
2705 Show differences between revisions for the specified files.
2706
2706
2707 Differences between files are shown using the unified diff format.
2707 Differences between files are shown using the unified diff format.
2708
2708
2709 .. note::
2709 .. note::
2710 diff may generate unexpected results for merges, as it will
2710 diff may generate unexpected results for merges, as it will
2711 default to comparing against the working directory's first
2711 default to comparing against the working directory's first
2712 parent changeset if no revisions are specified.
2712 parent changeset if no revisions are specified.
2713
2713
2714 When two revision arguments are given, then changes are shown
2714 When two revision arguments are given, then changes are shown
2715 between those revisions. If only one revision is specified then
2715 between those revisions. If only one revision is specified then
2716 that revision is compared to the working directory, and, when no
2716 that revision is compared to the working directory, and, when no
2717 revisions are specified, the working directory files are compared
2717 revisions are specified, the working directory files are compared
2718 to its parent.
2718 to its parent.
2719
2719
2720 Alternatively you can specify -c/--change with a revision to see
2720 Alternatively you can specify -c/--change with a revision to see
2721 the changes in that changeset relative to its first parent.
2721 the changes in that changeset relative to its first parent.
2722
2722
2723 Without the -a/--text option, diff will avoid generating diffs of
2723 Without the -a/--text option, diff will avoid generating diffs of
2724 files it detects as binary. With -a, diff will generate a diff
2724 files it detects as binary. With -a, diff will generate a diff
2725 anyway, probably with undesirable results.
2725 anyway, probably with undesirable results.
2726
2726
2727 Use the -g/--git option to generate diffs in the git extended diff
2727 Use the -g/--git option to generate diffs in the git extended diff
2728 format. For more information, read :hg:`help diffs`.
2728 format. For more information, read :hg:`help diffs`.
2729
2729
2730 .. container:: verbose
2730 .. container:: verbose
2731
2731
2732 Examples:
2732 Examples:
2733
2733
2734 - compare a file in the current working directory to its parent::
2734 - compare a file in the current working directory to its parent::
2735
2735
2736 hg diff foo.c
2736 hg diff foo.c
2737
2737
2738 - compare two historical versions of a directory, with rename info::
2738 - compare two historical versions of a directory, with rename info::
2739
2739
2740 hg diff --git -r 1.0:1.2 lib/
2740 hg diff --git -r 1.0:1.2 lib/
2741
2741
2742 - get change stats relative to the last change on some date::
2742 - get change stats relative to the last change on some date::
2743
2743
2744 hg diff --stat -r "date('may 2')"
2744 hg diff --stat -r "date('may 2')"
2745
2745
2746 - diff all newly-added files that contain a keyword::
2746 - diff all newly-added files that contain a keyword::
2747
2747
2748 hg diff "set:added() and grep(GNU)"
2748 hg diff "set:added() and grep(GNU)"
2749
2749
2750 - compare a revision and its parents::
2750 - compare a revision and its parents::
2751
2751
2752 hg diff -c 9353 # compare against first parent
2752 hg diff -c 9353 # compare against first parent
2753 hg diff -r 9353^:9353 # same using revset syntax
2753 hg diff -r 9353^:9353 # same using revset syntax
2754 hg diff -r 9353^2:9353 # compare against the second parent
2754 hg diff -r 9353^2:9353 # compare against the second parent
2755
2755
2756 Returns 0 on success.
2756 Returns 0 on success.
2757 """
2757 """
2758
2758
2759 revs = opts.get('rev')
2759 revs = opts.get('rev')
2760 change = opts.get('change')
2760 change = opts.get('change')
2761 stat = opts.get('stat')
2761 stat = opts.get('stat')
2762 reverse = opts.get('reverse')
2762 reverse = opts.get('reverse')
2763
2763
2764 if revs and change:
2764 if revs and change:
2765 msg = _('cannot specify --rev and --change at the same time')
2765 msg = _('cannot specify --rev and --change at the same time')
2766 raise util.Abort(msg)
2766 raise util.Abort(msg)
2767 elif change:
2767 elif change:
2768 node2 = scmutil.revsingle(repo, change, None).node()
2768 node2 = scmutil.revsingle(repo, change, None).node()
2769 node1 = repo[node2].p1().node()
2769 node1 = repo[node2].p1().node()
2770 else:
2770 else:
2771 node1, node2 = scmutil.revpair(repo, revs)
2771 node1, node2 = scmutil.revpair(repo, revs)
2772
2772
2773 if reverse:
2773 if reverse:
2774 node1, node2 = node2, node1
2774 node1, node2 = node2, node1
2775
2775
2776 diffopts = patch.diffopts(ui, opts)
2776 diffopts = patch.diffopts(ui, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2779 listsubrepos=opts.get('subrepos'))
2779 listsubrepos=opts.get('subrepos'))
2780
2780
2781 @command('^export',
2781 @command('^export',
2782 [('o', 'output', '',
2782 [('o', 'output', '',
2783 _('print output to file with formatted name'), _('FORMAT')),
2783 _('print output to file with formatted name'), _('FORMAT')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2786 ] + diffopts,
2786 ] + diffopts,
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2788 def export(ui, repo, *changesets, **opts):
2788 def export(ui, repo, *changesets, **opts):
2789 """dump the header and diffs for one or more changesets
2789 """dump the header and diffs for one or more changesets
2790
2790
2791 Print the changeset header and diffs for one or more revisions.
2791 Print the changeset header and diffs for one or more revisions.
2792 If no revision is given, the parent of the working directory is used.
2792 If no revision is given, the parent of the working directory is used.
2793
2793
2794 The information shown in the changeset header is: author, date,
2794 The information shown in the changeset header is: author, date,
2795 branch name (if non-default), changeset hash, parent(s) and commit
2795 branch name (if non-default), changeset hash, parent(s) and commit
2796 comment.
2796 comment.
2797
2797
2798 .. note::
2798 .. note::
2799 export may generate unexpected diff output for merge
2799 export may generate unexpected diff output for merge
2800 changesets, as it will compare the merge changeset against its
2800 changesets, as it will compare the merge changeset against its
2801 first parent only.
2801 first parent only.
2802
2802
2803 Output may be to a file, in which case the name of the file is
2803 Output may be to a file, in which case the name of the file is
2804 given using a format string. The formatting rules are as follows:
2804 given using a format string. The formatting rules are as follows:
2805
2805
2806 :``%%``: literal "%" character
2806 :``%%``: literal "%" character
2807 :``%H``: changeset hash (40 hexadecimal digits)
2807 :``%H``: changeset hash (40 hexadecimal digits)
2808 :``%N``: number of patches being generated
2808 :``%N``: number of patches being generated
2809 :``%R``: changeset revision number
2809 :``%R``: changeset revision number
2810 :``%b``: basename of the exporting repository
2810 :``%b``: basename of the exporting repository
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2813 :``%n``: zero-padded sequence number, starting at 1
2813 :``%n``: zero-padded sequence number, starting at 1
2814 :``%r``: zero-padded changeset revision number
2814 :``%r``: zero-padded changeset revision number
2815
2815
2816 Without the -a/--text option, export will avoid generating diffs
2816 Without the -a/--text option, export will avoid generating diffs
2817 of files it detects as binary. With -a, export will generate a
2817 of files it detects as binary. With -a, export will generate a
2818 diff anyway, probably with undesirable results.
2818 diff anyway, probably with undesirable results.
2819
2819
2820 Use the -g/--git option to generate diffs in the git extended diff
2820 Use the -g/--git option to generate diffs in the git extended diff
2821 format. See :hg:`help diffs` for more information.
2821 format. See :hg:`help diffs` for more information.
2822
2822
2823 With the --switch-parent option, the diff will be against the
2823 With the --switch-parent option, the diff will be against the
2824 second parent. It can be useful to review a merge.
2824 second parent. It can be useful to review a merge.
2825
2825
2826 .. container:: verbose
2826 .. container:: verbose
2827
2827
2828 Examples:
2828 Examples:
2829
2829
2830 - use export and import to transplant a bugfix to the current
2830 - use export and import to transplant a bugfix to the current
2831 branch::
2831 branch::
2832
2832
2833 hg export -r 9353 | hg import -
2833 hg export -r 9353 | hg import -
2834
2834
2835 - export all the changesets between two revisions to a file with
2835 - export all the changesets between two revisions to a file with
2836 rename information::
2836 rename information::
2837
2837
2838 hg export --git -r 123:150 > changes.txt
2838 hg export --git -r 123:150 > changes.txt
2839
2839
2840 - split outgoing changes into a series of patches with
2840 - split outgoing changes into a series of patches with
2841 descriptive names::
2841 descriptive names::
2842
2842
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2844
2844
2845 Returns 0 on success.
2845 Returns 0 on success.
2846 """
2846 """
2847 changesets += tuple(opts.get('rev', []))
2847 changesets += tuple(opts.get('rev', []))
2848 if not changesets:
2848 if not changesets:
2849 changesets = ['.']
2849 changesets = ['.']
2850 revs = scmutil.revrange(repo, changesets)
2850 revs = scmutil.revrange(repo, changesets)
2851 if not revs:
2851 if not revs:
2852 raise util.Abort(_("export requires at least one changeset"))
2852 raise util.Abort(_("export requires at least one changeset"))
2853 if len(revs) > 1:
2853 if len(revs) > 1:
2854 ui.note(_('exporting patches:\n'))
2854 ui.note(_('exporting patches:\n'))
2855 else:
2855 else:
2856 ui.note(_('exporting patch:\n'))
2856 ui.note(_('exporting patch:\n'))
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2858 switch_parent=opts.get('switch_parent'),
2858 switch_parent=opts.get('switch_parent'),
2859 opts=patch.diffopts(ui, opts))
2859 opts=patch.diffopts(ui, opts))
2860
2860
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2862 def forget(ui, repo, *pats, **opts):
2862 def forget(ui, repo, *pats, **opts):
2863 """forget the specified files on the next commit
2863 """forget the specified files on the next commit
2864
2864
2865 Mark the specified files so they will no longer be tracked
2865 Mark the specified files so they will no longer be tracked
2866 after the next commit.
2866 after the next commit.
2867
2867
2868 This only removes files from the current branch, not from the
2868 This only removes files from the current branch, not from the
2869 entire project history, and it does not delete them from the
2869 entire project history, and it does not delete them from the
2870 working directory.
2870 working directory.
2871
2871
2872 To undo a forget before the next commit, see :hg:`add`.
2872 To undo a forget before the next commit, see :hg:`add`.
2873
2873
2874 .. container:: verbose
2874 .. container:: verbose
2875
2875
2876 Examples:
2876 Examples:
2877
2877
2878 - forget newly-added binary files::
2878 - forget newly-added binary files::
2879
2879
2880 hg forget "set:added() and binary()"
2880 hg forget "set:added() and binary()"
2881
2881
2882 - forget files that would be excluded by .hgignore::
2882 - forget files that would be excluded by .hgignore::
2883
2883
2884 hg forget "set:hgignore()"
2884 hg forget "set:hgignore()"
2885
2885
2886 Returns 0 on success.
2886 Returns 0 on success.
2887 """
2887 """
2888
2888
2889 if not pats:
2889 if not pats:
2890 raise util.Abort(_('no files specified'))
2890 raise util.Abort(_('no files specified'))
2891
2891
2892 m = scmutil.match(repo[None], pats, opts)
2892 m = scmutil.match(repo[None], pats, opts)
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2894 return rejected and 1 or 0
2894 return rejected and 1 or 0
2895
2895
2896 @command(
2896 @command(
2897 'graft',
2897 'graft',
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2901 ('', 'log', None, _('append graft info to log message')),
2901 ('', 'log', None, _('append graft info to log message')),
2902 ('D', 'currentdate', False,
2902 ('D', 'currentdate', False,
2903 _('record the current date as commit date')),
2903 _('record the current date as commit date')),
2904 ('U', 'currentuser', False,
2904 ('U', 'currentuser', False,
2905 _('record the current user as committer'), _('DATE'))]
2905 _('record the current user as committer'), _('DATE'))]
2906 + commitopts2 + mergetoolopts + dryrunopts,
2906 + commitopts2 + mergetoolopts + dryrunopts,
2907 _('[OPTION]... [-r] REV...'))
2907 _('[OPTION]... [-r] REV...'))
2908 def graft(ui, repo, *revs, **opts):
2908 def graft(ui, repo, *revs, **opts):
2909 '''copy changes from other branches onto the current branch
2909 '''copy changes from other branches onto the current branch
2910
2910
2911 This command uses Mercurial's merge logic to copy individual
2911 This command uses Mercurial's merge logic to copy individual
2912 changes from other branches without merging branches in the
2912 changes from other branches without merging branches in the
2913 history graph. This is sometimes known as 'backporting' or
2913 history graph. This is sometimes known as 'backporting' or
2914 'cherry-picking'. By default, graft will copy user, date, and
2914 'cherry-picking'. By default, graft will copy user, date, and
2915 description from the source changesets.
2915 description from the source changesets.
2916
2916
2917 Changesets that are ancestors of the current revision, that have
2917 Changesets that are ancestors of the current revision, that have
2918 already been grafted, or that are merges will be skipped.
2918 already been grafted, or that are merges will be skipped.
2919
2919
2920 If --log is specified, log messages will have a comment appended
2920 If --log is specified, log messages will have a comment appended
2921 of the form::
2921 of the form::
2922
2922
2923 (grafted from CHANGESETHASH)
2923 (grafted from CHANGESETHASH)
2924
2924
2925 If a graft merge results in conflicts, the graft process is
2925 If a graft merge results in conflicts, the graft process is
2926 interrupted so that the current merge can be manually resolved.
2926 interrupted so that the current merge can be manually resolved.
2927 Once all conflicts are addressed, the graft process can be
2927 Once all conflicts are addressed, the graft process can be
2928 continued with the -c/--continue option.
2928 continued with the -c/--continue option.
2929
2929
2930 .. note::
2930 .. note::
2931 The -c/--continue option does not reapply earlier options.
2931 The -c/--continue option does not reapply earlier options.
2932
2932
2933 .. container:: verbose
2933 .. container:: verbose
2934
2934
2935 Examples:
2935 Examples:
2936
2936
2937 - copy a single change to the stable branch and edit its description::
2937 - copy a single change to the stable branch and edit its description::
2938
2938
2939 hg update stable
2939 hg update stable
2940 hg graft --edit 9393
2940 hg graft --edit 9393
2941
2941
2942 - graft a range of changesets with one exception, updating dates::
2942 - graft a range of changesets with one exception, updating dates::
2943
2943
2944 hg graft -D "2085::2093 and not 2091"
2944 hg graft -D "2085::2093 and not 2091"
2945
2945
2946 - continue a graft after resolving conflicts::
2946 - continue a graft after resolving conflicts::
2947
2947
2948 hg graft -c
2948 hg graft -c
2949
2949
2950 - show the source of a grafted changeset::
2950 - show the source of a grafted changeset::
2951
2951
2952 hg log --debug -r .
2952 hg log --debug -r .
2953
2953
2954 Returns 0 on successful completion.
2954 Returns 0 on successful completion.
2955 '''
2955 '''
2956
2956
2957 revs = list(revs)
2957 revs = list(revs)
2958 revs.extend(opts['rev'])
2958 revs.extend(opts['rev'])
2959
2959
2960 if not opts.get('user') and opts.get('currentuser'):
2960 if not opts.get('user') and opts.get('currentuser'):
2961 opts['user'] = ui.username()
2961 opts['user'] = ui.username()
2962 if not opts.get('date') and opts.get('currentdate'):
2962 if not opts.get('date') and opts.get('currentdate'):
2963 opts['date'] = "%d %d" % util.makedate()
2963 opts['date'] = "%d %d" % util.makedate()
2964
2964
2965 editor = None
2965 editor = None
2966 if opts.get('edit'):
2966 if opts.get('edit'):
2967 editor = cmdutil.commitforceeditor
2967 editor = cmdutil.commitforceeditor
2968
2968
2969 cont = False
2969 cont = False
2970 if opts['continue']:
2970 if opts['continue']:
2971 cont = True
2971 cont = True
2972 if revs:
2972 if revs:
2973 raise util.Abort(_("can't specify --continue and revisions"))
2973 raise util.Abort(_("can't specify --continue and revisions"))
2974 # read in unfinished revisions
2974 # read in unfinished revisions
2975 try:
2975 try:
2976 nodes = repo.opener.read('graftstate').splitlines()
2976 nodes = repo.opener.read('graftstate').splitlines()
2977 revs = [repo[node].rev() for node in nodes]
2977 revs = [repo[node].rev() for node in nodes]
2978 except IOError, inst:
2978 except IOError, inst:
2979 if inst.errno != errno.ENOENT:
2979 if inst.errno != errno.ENOENT:
2980 raise
2980 raise
2981 raise util.Abort(_("no graft state found, can't continue"))
2981 raise util.Abort(_("no graft state found, can't continue"))
2982 else:
2982 else:
2983 cmdutil.checkunfinished(repo)
2983 cmdutil.checkunfinished(repo)
2984 cmdutil.bailifchanged(repo)
2984 cmdutil.bailifchanged(repo)
2985 if not revs:
2985 if not revs:
2986 raise util.Abort(_('no revisions specified'))
2986 raise util.Abort(_('no revisions specified'))
2987 revs = scmutil.revrange(repo, revs)
2987 revs = scmutil.revrange(repo, revs)
2988
2988
2989 # check for merges
2989 # check for merges
2990 for rev in repo.revs('%ld and merge()', revs):
2990 for rev in repo.revs('%ld and merge()', revs):
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2992 revs.remove(rev)
2992 revs.remove(rev)
2993 if not revs:
2993 if not revs:
2994 return -1
2994 return -1
2995
2995
2996 # check for ancestors of dest branch
2996 # check for ancestors of dest branch
2997 crev = repo['.'].rev()
2997 crev = repo['.'].rev()
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2999 # don't mutate while iterating, create a copy
2999 # don't mutate while iterating, create a copy
3000 for rev in list(revs):
3000 for rev in list(revs):
3001 if rev in ancestors:
3001 if rev in ancestors:
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3003 revs.remove(rev)
3003 revs.remove(rev)
3004 if not revs:
3004 if not revs:
3005 return -1
3005 return -1
3006
3006
3007 # analyze revs for earlier grafts
3007 # analyze revs for earlier grafts
3008 ids = {}
3008 ids = {}
3009 for ctx in repo.set("%ld", revs):
3009 for ctx in repo.set("%ld", revs):
3010 ids[ctx.hex()] = ctx.rev()
3010 ids[ctx.hex()] = ctx.rev()
3011 n = ctx.extra().get('source')
3011 n = ctx.extra().get('source')
3012 if n:
3012 if n:
3013 ids[n] = ctx.rev()
3013 ids[n] = ctx.rev()
3014
3014
3015 # check ancestors for earlier grafts
3015 # check ancestors for earlier grafts
3016 ui.debug('scanning for duplicate grafts\n')
3016 ui.debug('scanning for duplicate grafts\n')
3017
3017
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3019 ctx = repo[rev]
3019 ctx = repo[rev]
3020 n = ctx.extra().get('source')
3020 n = ctx.extra().get('source')
3021 if n in ids:
3021 if n in ids:
3022 r = repo[n].rev()
3022 r = repo[n].rev()
3023 if r in revs:
3023 if r in revs:
3024 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3024 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3025 % (r, rev))
3025 % (r, rev))
3026 revs.remove(r)
3026 revs.remove(r)
3027 elif ids[n] in revs:
3027 elif ids[n] in revs:
3028 ui.warn(_('skipping already grafted revision %s '
3028 ui.warn(_('skipping already grafted revision %s '
3029 '(%s also has origin %d)\n') % (ids[n], rev, r))
3029 '(%s also has origin %d)\n') % (ids[n], rev, r))
3030 revs.remove(ids[n])
3030 revs.remove(ids[n])
3031 elif ctx.hex() in ids:
3031 elif ctx.hex() in ids:
3032 r = ids[ctx.hex()]
3032 r = ids[ctx.hex()]
3033 ui.warn(_('skipping already grafted revision %s '
3033 ui.warn(_('skipping already grafted revision %s '
3034 '(was grafted from %d)\n') % (r, rev))
3034 '(was grafted from %d)\n') % (r, rev))
3035 revs.remove(r)
3035 revs.remove(r)
3036 if not revs:
3036 if not revs:
3037 return -1
3037 return -1
3038
3038
3039 wlock = repo.wlock()
3039 wlock = repo.wlock()
3040 try:
3040 try:
3041 current = repo['.']
3041 current = repo['.']
3042 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042 for pos, ctx in enumerate(repo.set("%ld", revs)):
3043
3043
3044 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 ui.status(_('grafting revision %s\n') % ctx.rev())
3045 if opts.get('dry_run'):
3045 if opts.get('dry_run'):
3046 continue
3046 continue
3047
3047
3048 source = ctx.extra().get('source')
3048 source = ctx.extra().get('source')
3049 if not source:
3049 if not source:
3050 source = ctx.hex()
3050 source = ctx.hex()
3051 extra = {'source': source}
3051 extra = {'source': source}
3052 user = ctx.user()
3052 user = ctx.user()
3053 if opts.get('user'):
3053 if opts.get('user'):
3054 user = opts['user']
3054 user = opts['user']
3055 date = ctx.date()
3055 date = ctx.date()
3056 if opts.get('date'):
3056 if opts.get('date'):
3057 date = opts['date']
3057 date = opts['date']
3058 message = ctx.description()
3058 message = ctx.description()
3059 if opts.get('log'):
3059 if opts.get('log'):
3060 message += '\n(grafted from %s)' % ctx.hex()
3060 message += '\n(grafted from %s)' % ctx.hex()
3061
3061
3062 # we don't merge the first commit when continuing
3062 # we don't merge the first commit when continuing
3063 if not cont:
3063 if not cont:
3064 # perform the graft merge with p1(rev) as 'ancestor'
3064 # perform the graft merge with p1(rev) as 'ancestor'
3065 try:
3065 try:
3066 # ui.forcemerge is an internal variable, do not document
3066 # ui.forcemerge is an internal variable, do not document
3067 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3068 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 stats = mergemod.update(repo, ctx.node(), True, True, False,
3069 ctx.p1().node())
3069 ctx.p1().node())
3070 finally:
3070 finally:
3071 repo.ui.setconfig('ui', 'forcemerge', '')
3071 repo.ui.setconfig('ui', 'forcemerge', '')
3072 # report any conflicts
3072 # report any conflicts
3073 if stats and stats[3] > 0:
3073 if stats and stats[3] > 0:
3074 # write out state for --continue
3074 # write out state for --continue
3075 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3076 repo.opener.write('graftstate', ''.join(nodelines))
3076 repo.opener.write('graftstate', ''.join(nodelines))
3077 raise util.Abort(
3077 raise util.Abort(
3078 _("unresolved conflicts, can't continue"),
3078 _("unresolved conflicts, can't continue"),
3079 hint=_('use hg resolve and hg graft --continue'))
3079 hint=_('use hg resolve and hg graft --continue'))
3080 else:
3080 else:
3081 cont = False
3081 cont = False
3082
3082
3083 # drop the second merge parent
3083 # drop the second merge parent
3084 repo.setparents(current.node(), nullid)
3084 repo.setparents(current.node(), nullid)
3085 repo.dirstate.write()
3085 repo.dirstate.write()
3086 # fix up dirstate for copies and renames
3086 # fix up dirstate for copies and renames
3087 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3088
3088
3089 # commit
3089 # commit
3090 node = repo.commit(text=message, user=user,
3090 node = repo.commit(text=message, user=user,
3091 date=date, extra=extra, editor=editor)
3091 date=date, extra=extra, editor=editor)
3092 if node is None:
3092 if node is None:
3093 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3094 else:
3094 else:
3095 current = repo[node]
3095 current = repo[node]
3096 finally:
3096 finally:
3097 wlock.release()
3097 wlock.release()
3098
3098
3099 # remove state when we complete successfully
3099 # remove state when we complete successfully
3100 if not opts.get('dry_run'):
3100 if not opts.get('dry_run'):
3101 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3102
3102
3103 return 0
3103 return 0
3104
3104
3105 @command('grep',
3105 @command('grep',
3106 [('0', 'print0', None, _('end fields with NUL')),
3106 [('0', 'print0', None, _('end fields with NUL')),
3107 ('', 'all', None, _('print all revisions that match')),
3107 ('', 'all', None, _('print all revisions that match')),
3108 ('a', 'text', None, _('treat all files as text')),
3108 ('a', 'text', None, _('treat all files as text')),
3109 ('f', 'follow', None,
3109 ('f', 'follow', None,
3110 _('follow changeset history,'
3110 _('follow changeset history,'
3111 ' or file history across copies and renames')),
3111 ' or file history across copies and renames')),
3112 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('i', 'ignore-case', None, _('ignore case when matching')),
3113 ('l', 'files-with-matches', None,
3113 ('l', 'files-with-matches', None,
3114 _('print only filenames and revisions that match')),
3114 _('print only filenames and revisions that match')),
3115 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('n', 'line-number', None, _('print matching line numbers')),
3116 ('r', 'rev', [],
3116 ('r', 'rev', [],
3117 _('only search files changed within revision range'), _('REV')),
3117 _('only search files changed within revision range'), _('REV')),
3118 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('u', 'user', None, _('list the author (long with -v)')),
3119 ('d', 'date', None, _('list the date (short with -q)')),
3119 ('d', 'date', None, _('list the date (short with -q)')),
3120 ] + walkopts,
3120 ] + walkopts,
3121 _('[OPTION]... PATTERN [FILE]...'))
3121 _('[OPTION]... PATTERN [FILE]...'))
3122 def grep(ui, repo, pattern, *pats, **opts):
3122 def grep(ui, repo, pattern, *pats, **opts):
3123 """search for a pattern in specified files and revisions
3123 """search for a pattern in specified files and revisions
3124
3124
3125 Search revisions of files for a regular expression.
3125 Search revisions of files for a regular expression.
3126
3126
3127 This command behaves differently than Unix grep. It only accepts
3127 This command behaves differently than Unix grep. It only accepts
3128 Python/Perl regexps. It searches repository history, not the
3128 Python/Perl regexps. It searches repository history, not the
3129 working directory. It always prints the revision number in which a
3129 working directory. It always prints the revision number in which a
3130 match appears.
3130 match appears.
3131
3131
3132 By default, grep only prints output for the first revision of a
3132 By default, grep only prints output for the first revision of a
3133 file in which it finds a match. To get it to print every revision
3133 file in which it finds a match. To get it to print every revision
3134 that contains a change in match status ("-" for a match that
3134 that contains a change in match status ("-" for a match that
3135 becomes a non-match, or "+" for a non-match that becomes a match),
3135 becomes a non-match, or "+" for a non-match that becomes a match),
3136 use the --all flag.
3136 use the --all flag.
3137
3137
3138 Returns 0 if a match is found, 1 otherwise.
3138 Returns 0 if a match is found, 1 otherwise.
3139 """
3139 """
3140 reflags = re.M
3140 reflags = re.M
3141 if opts.get('ignore_case'):
3141 if opts.get('ignore_case'):
3142 reflags |= re.I
3142 reflags |= re.I
3143 try:
3143 try:
3144 regexp = util.compilere(pattern, reflags)
3144 regexp = util.compilere(pattern, reflags)
3145 except re.error, inst:
3145 except re.error, inst:
3146 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3147 return 1
3147 return 1
3148 sep, eol = ':', '\n'
3148 sep, eol = ':', '\n'
3149 if opts.get('print0'):
3149 if opts.get('print0'):
3150 sep = eol = '\0'
3150 sep = eol = '\0'
3151
3151
3152 getfile = util.lrucachefunc(repo.file)
3152 getfile = util.lrucachefunc(repo.file)
3153
3153
3154 def matchlines(body):
3154 def matchlines(body):
3155 begin = 0
3155 begin = 0
3156 linenum = 0
3156 linenum = 0
3157 while begin < len(body):
3157 while begin < len(body):
3158 match = regexp.search(body, begin)
3158 match = regexp.search(body, begin)
3159 if not match:
3159 if not match:
3160 break
3160 break
3161 mstart, mend = match.span()
3161 mstart, mend = match.span()
3162 linenum += body.count('\n', begin, mstart) + 1
3162 linenum += body.count('\n', begin, mstart) + 1
3163 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3164 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 begin = body.find('\n', mend) + 1 or len(body) + 1
3165 lend = begin - 1
3165 lend = begin - 1
3166 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3167
3167
3168 class linestate(object):
3168 class linestate(object):
3169 def __init__(self, line, linenum, colstart, colend):
3169 def __init__(self, line, linenum, colstart, colend):
3170 self.line = line
3170 self.line = line
3171 self.linenum = linenum
3171 self.linenum = linenum
3172 self.colstart = colstart
3172 self.colstart = colstart
3173 self.colend = colend
3173 self.colend = colend
3174
3174
3175 def __hash__(self):
3175 def __hash__(self):
3176 return hash((self.linenum, self.line))
3176 return hash((self.linenum, self.line))
3177
3177
3178 def __eq__(self, other):
3178 def __eq__(self, other):
3179 return self.line == other.line
3179 return self.line == other.line
3180
3180
3181 matches = {}
3181 matches = {}
3182 copies = {}
3182 copies = {}
3183 def grepbody(fn, rev, body):
3183 def grepbody(fn, rev, body):
3184 matches[rev].setdefault(fn, [])
3184 matches[rev].setdefault(fn, [])
3185 m = matches[rev][fn]
3185 m = matches[rev][fn]
3186 for lnum, cstart, cend, line in matchlines(body):
3186 for lnum, cstart, cend, line in matchlines(body):
3187 s = linestate(line, lnum, cstart, cend)
3187 s = linestate(line, lnum, cstart, cend)
3188 m.append(s)
3188 m.append(s)
3189
3189
3190 def difflinestates(a, b):
3190 def difflinestates(a, b):
3191 sm = difflib.SequenceMatcher(None, a, b)
3191 sm = difflib.SequenceMatcher(None, a, b)
3192 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3193 if tag == 'insert':
3193 if tag == 'insert':
3194 for i in xrange(blo, bhi):
3194 for i in xrange(blo, bhi):
3195 yield ('+', b[i])
3195 yield ('+', b[i])
3196 elif tag == 'delete':
3196 elif tag == 'delete':
3197 for i in xrange(alo, ahi):
3197 for i in xrange(alo, ahi):
3198 yield ('-', a[i])
3198 yield ('-', a[i])
3199 elif tag == 'replace':
3199 elif tag == 'replace':
3200 for i in xrange(alo, ahi):
3200 for i in xrange(alo, ahi):
3201 yield ('-', a[i])
3201 yield ('-', a[i])
3202 for i in xrange(blo, bhi):
3202 for i in xrange(blo, bhi):
3203 yield ('+', b[i])
3203 yield ('+', b[i])
3204
3204
3205 def display(fn, ctx, pstates, states):
3205 def display(fn, ctx, pstates, states):
3206 rev = ctx.rev()
3206 rev = ctx.rev()
3207 datefunc = ui.quiet and util.shortdate or util.datestr
3207 datefunc = ui.quiet and util.shortdate or util.datestr
3208 found = False
3208 found = False
3209 filerevmatches = {}
3209 filerevmatches = {}
3210 def binary():
3210 def binary():
3211 flog = getfile(fn)
3211 flog = getfile(fn)
3212 return util.binary(flog.read(ctx.filenode(fn)))
3212 return util.binary(flog.read(ctx.filenode(fn)))
3213
3213
3214 if opts.get('all'):
3214 if opts.get('all'):
3215 iter = difflinestates(pstates, states)
3215 iter = difflinestates(pstates, states)
3216 else:
3216 else:
3217 iter = [('', l) for l in states]
3217 iter = [('', l) for l in states]
3218 for change, l in iter:
3218 for change, l in iter:
3219 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3220 before, match, after = None, None, None
3220 before, match, after = None, None, None
3221
3221
3222 if opts.get('line_number'):
3222 if opts.get('line_number'):
3223 cols.append((str(l.linenum), 'grep.linenumber'))
3223 cols.append((str(l.linenum), 'grep.linenumber'))
3224 if opts.get('all'):
3224 if opts.get('all'):
3225 cols.append((change, 'grep.change'))
3225 cols.append((change, 'grep.change'))
3226 if opts.get('user'):
3226 if opts.get('user'):
3227 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3228 if opts.get('date'):
3228 if opts.get('date'):
3229 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 cols.append((datefunc(ctx.date()), 'grep.date'))
3230 if opts.get('files_with_matches'):
3230 if opts.get('files_with_matches'):
3231 c = (fn, rev)
3231 c = (fn, rev)
3232 if c in filerevmatches:
3232 if c in filerevmatches:
3233 continue
3233 continue
3234 filerevmatches[c] = 1
3234 filerevmatches[c] = 1
3235 else:
3235 else:
3236 before = l.line[:l.colstart]
3236 before = l.line[:l.colstart]
3237 match = l.line[l.colstart:l.colend]
3237 match = l.line[l.colstart:l.colend]
3238 after = l.line[l.colend:]
3238 after = l.line[l.colend:]
3239 for col, label in cols[:-1]:
3239 for col, label in cols[:-1]:
3240 ui.write(col, label=label)
3240 ui.write(col, label=label)
3241 ui.write(sep, label='grep.sep')
3241 ui.write(sep, label='grep.sep')
3242 ui.write(cols[-1][0], label=cols[-1][1])
3242 ui.write(cols[-1][0], label=cols[-1][1])
3243 if before is not None:
3243 if before is not None:
3244 ui.write(sep, label='grep.sep')
3244 ui.write(sep, label='grep.sep')
3245 if not opts.get('text') and binary():
3245 if not opts.get('text') and binary():
3246 ui.write(" Binary file matches")
3246 ui.write(" Binary file matches")
3247 else:
3247 else:
3248 ui.write(before)
3248 ui.write(before)
3249 ui.write(match, label='grep.match')
3249 ui.write(match, label='grep.match')
3250 ui.write(after)
3250 ui.write(after)
3251 ui.write(eol)
3251 ui.write(eol)
3252 found = True
3252 found = True
3253 return found
3253 return found
3254
3254
3255 skip = {}
3255 skip = {}
3256 revfiles = {}
3256 revfiles = {}
3257 matchfn = scmutil.match(repo[None], pats, opts)
3257 matchfn = scmutil.match(repo[None], pats, opts)
3258 found = False
3258 found = False
3259 follow = opts.get('follow')
3259 follow = opts.get('follow')
3260
3260
3261 def prep(ctx, fns):
3261 def prep(ctx, fns):
3262 rev = ctx.rev()
3262 rev = ctx.rev()
3263 pctx = ctx.p1()
3263 pctx = ctx.p1()
3264 parent = pctx.rev()
3264 parent = pctx.rev()
3265 matches.setdefault(rev, {})
3265 matches.setdefault(rev, {})
3266 matches.setdefault(parent, {})
3266 matches.setdefault(parent, {})
3267 files = revfiles.setdefault(rev, [])
3267 files = revfiles.setdefault(rev, [])
3268 for fn in fns:
3268 for fn in fns:
3269 flog = getfile(fn)
3269 flog = getfile(fn)
3270 try:
3270 try:
3271 fnode = ctx.filenode(fn)
3271 fnode = ctx.filenode(fn)
3272 except error.LookupError:
3272 except error.LookupError:
3273 continue
3273 continue
3274
3274
3275 copied = flog.renamed(fnode)
3275 copied = flog.renamed(fnode)
3276 copy = follow and copied and copied[0]
3276 copy = follow and copied and copied[0]
3277 if copy:
3277 if copy:
3278 copies.setdefault(rev, {})[fn] = copy
3278 copies.setdefault(rev, {})[fn] = copy
3279 if fn in skip:
3279 if fn in skip:
3280 if copy:
3280 if copy:
3281 skip[copy] = True
3281 skip[copy] = True
3282 continue
3282 continue
3283 files.append(fn)
3283 files.append(fn)
3284
3284
3285 if fn not in matches[rev]:
3285 if fn not in matches[rev]:
3286 grepbody(fn, rev, flog.read(fnode))
3286 grepbody(fn, rev, flog.read(fnode))
3287
3287
3288 pfn = copy or fn
3288 pfn = copy or fn
3289 if pfn not in matches[parent]:
3289 if pfn not in matches[parent]:
3290 try:
3290 try:
3291 fnode = pctx.filenode(pfn)
3291 fnode = pctx.filenode(pfn)
3292 grepbody(pfn, parent, flog.read(fnode))
3292 grepbody(pfn, parent, flog.read(fnode))
3293 except error.LookupError:
3293 except error.LookupError:
3294 pass
3294 pass
3295
3295
3296 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3297 rev = ctx.rev()
3297 rev = ctx.rev()
3298 parent = ctx.p1().rev()
3298 parent = ctx.p1().rev()
3299 for fn in sorted(revfiles.get(rev, [])):
3299 for fn in sorted(revfiles.get(rev, [])):
3300 states = matches[rev][fn]
3300 states = matches[rev][fn]
3301 copy = copies.get(rev, {}).get(fn)
3301 copy = copies.get(rev, {}).get(fn)
3302 if fn in skip:
3302 if fn in skip:
3303 if copy:
3303 if copy:
3304 skip[copy] = True
3304 skip[copy] = True
3305 continue
3305 continue
3306 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 pstates = matches.get(parent, {}).get(copy or fn, [])
3307 if pstates or states:
3307 if pstates or states:
3308 r = display(fn, ctx, pstates, states)
3308 r = display(fn, ctx, pstates, states)
3309 found = found or r
3309 found = found or r
3310 if r and not opts.get('all'):
3310 if r and not opts.get('all'):
3311 skip[fn] = True
3311 skip[fn] = True
3312 if copy:
3312 if copy:
3313 skip[copy] = True
3313 skip[copy] = True
3314 del matches[rev]
3314 del matches[rev]
3315 del revfiles[rev]
3315 del revfiles[rev]
3316
3316
3317 return not found
3317 return not found
3318
3318
3319 @command('heads',
3319 @command('heads',
3320 [('r', 'rev', '',
3320 [('r', 'rev', '',
3321 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3322 ('t', 'topo', False, _('show topological heads only')),
3322 ('t', 'topo', False, _('show topological heads only')),
3323 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3324 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ('c', 'closed', False, _('show normal and closed branch heads')),
3325 ] + templateopts,
3325 ] + templateopts,
3326 _('[-ct] [-r STARTREV] [REV]...'))
3326 _('[-ct] [-r STARTREV] [REV]...'))
3327 def heads(ui, repo, *branchrevs, **opts):
3327 def heads(ui, repo, *branchrevs, **opts):
3328 """show branch heads
3328 """show branch heads
3329
3329
3330 With no arguments, show all open branch heads in the repository.
3330 With no arguments, show all open branch heads in the repository.
3331 Branch heads are changesets that have no descendants on the
3331 Branch heads are changesets that have no descendants on the
3332 same branch. They are where development generally takes place and
3332 same branch. They are where development generally takes place and
3333 are the usual targets for update and merge operations.
3333 are the usual targets for update and merge operations.
3334
3334
3335 If one or more REVs are given, only open branch heads on the
3335 If one or more REVs are given, only open branch heads on the
3336 branches associated with the specified changesets are shown. This
3336 branches associated with the specified changesets are shown. This
3337 means that you can use :hg:`heads .` to see the heads on the
3337 means that you can use :hg:`heads .` to see the heads on the
3338 currently checked-out branch.
3338 currently checked-out branch.
3339
3339
3340 If -c/--closed is specified, also show branch heads marked closed
3340 If -c/--closed is specified, also show branch heads marked closed
3341 (see :hg:`commit --close-branch`).
3341 (see :hg:`commit --close-branch`).
3342
3342
3343 If STARTREV is specified, only those heads that are descendants of
3343 If STARTREV is specified, only those heads that are descendants of
3344 STARTREV will be displayed.
3344 STARTREV will be displayed.
3345
3345
3346 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 If -t/--topo is specified, named branch mechanics will be ignored and only
3347 topological heads (changesets with no children) will be shown.
3347 topological heads (changesets with no children) will be shown.
3348
3348
3349 Returns 0 if matching heads are found, 1 if not.
3349 Returns 0 if matching heads are found, 1 if not.
3350 """
3350 """
3351
3351
3352 start = None
3352 start = None
3353 if 'rev' in opts:
3353 if 'rev' in opts:
3354 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354 start = scmutil.revsingle(repo, opts['rev'], None).node()
3355
3355
3356 if opts.get('topo'):
3356 if opts.get('topo'):
3357 heads = [repo[h] for h in repo.heads(start)]
3357 heads = [repo[h] for h in repo.heads(start)]
3358 else:
3358 else:
3359 heads = []
3359 heads = []
3360 for branch in repo.branchmap():
3360 for branch in repo.branchmap():
3361 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads += repo.branchheads(branch, start, opts.get('closed'))
3362 heads = [repo[h] for h in heads]
3362 heads = [repo[h] for h in heads]
3363
3363
3364 if branchrevs:
3364 if branchrevs:
3365 branches = set(repo[br].branch() for br in branchrevs)
3365 branches = set(repo[br].branch() for br in branchrevs)
3366 heads = [h for h in heads if h.branch() in branches]
3366 heads = [h for h in heads if h.branch() in branches]
3367
3367
3368 if opts.get('active') and branchrevs:
3368 if opts.get('active') and branchrevs:
3369 dagheads = repo.heads(start)
3369 dagheads = repo.heads(start)
3370 heads = [h for h in heads if h.node() in dagheads]
3370 heads = [h for h in heads if h.node() in dagheads]
3371
3371
3372 if branchrevs:
3372 if branchrevs:
3373 haveheads = set(h.branch() for h in heads)
3373 haveheads = set(h.branch() for h in heads)
3374 if branches - haveheads:
3374 if branches - haveheads:
3375 headless = ', '.join(b for b in branches - haveheads)
3375 headless = ', '.join(b for b in branches - haveheads)
3376 msg = _('no open branch heads found on branches %s')
3376 msg = _('no open branch heads found on branches %s')
3377 if opts.get('rev'):
3377 if opts.get('rev'):
3378 msg += _(' (started at %s)') % opts['rev']
3378 msg += _(' (started at %s)') % opts['rev']
3379 ui.warn((msg + '\n') % headless)
3379 ui.warn((msg + '\n') % headless)
3380
3380
3381 if not heads:
3381 if not heads:
3382 return 1
3382 return 1
3383
3383
3384 heads = sorted(heads, key=lambda x: -x.rev())
3384 heads = sorted(heads, key=lambda x: -x.rev())
3385 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 displayer = cmdutil.show_changeset(ui, repo, opts)
3386 for ctx in heads:
3386 for ctx in heads:
3387 displayer.show(ctx)
3387 displayer.show(ctx)
3388 displayer.close()
3388 displayer.close()
3389
3389
3390 @command('help',
3390 @command('help',
3391 [('e', 'extension', None, _('show only help for extensions')),
3391 [('e', 'extension', None, _('show only help for extensions')),
3392 ('c', 'command', None, _('show only help for commands')),
3392 ('c', 'command', None, _('show only help for commands')),
3393 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ('k', 'keyword', '', _('show topics matching keyword')),
3394 ],
3394 ],
3395 _('[-ec] [TOPIC]'))
3395 _('[-ec] [TOPIC]'))
3396 def help_(ui, name=None, **opts):
3396 def help_(ui, name=None, **opts):
3397 """show help for a given topic or a help overview
3397 """show help for a given topic or a help overview
3398
3398
3399 With no arguments, print a list of commands with short help messages.
3399 With no arguments, print a list of commands with short help messages.
3400
3400
3401 Given a topic, extension, or command name, print help for that
3401 Given a topic, extension, or command name, print help for that
3402 topic.
3402 topic.
3403
3403
3404 Returns 0 if successful.
3404 Returns 0 if successful.
3405 """
3405 """
3406
3406
3407 textwidth = min(ui.termwidth(), 80) - 2
3407 textwidth = min(ui.termwidth(), 80) - 2
3408
3408
3409 keep = ui.verbose and ['verbose'] or []
3409 keep = ui.verbose and ['verbose'] or []
3410 text = help.help_(ui, name, **opts)
3410 text = help.help_(ui, name, **opts)
3411
3411
3412 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3413 if 'verbose' in pruned:
3413 if 'verbose' in pruned:
3414 keep.append('omitted')
3414 keep.append('omitted')
3415 else:
3415 else:
3416 keep.append('notomitted')
3416 keep.append('notomitted')
3417 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3418 ui.write(formatted)
3418 ui.write(formatted)
3419
3419
3420
3420
3421 @command('identify|id',
3421 @command('identify|id',
3422 [('r', 'rev', '',
3422 [('r', 'rev', '',
3423 _('identify the specified revision'), _('REV')),
3423 _('identify the specified revision'), _('REV')),
3424 ('n', 'num', None, _('show local revision number')),
3424 ('n', 'num', None, _('show local revision number')),
3425 ('i', 'id', None, _('show global revision id')),
3425 ('i', 'id', None, _('show global revision id')),
3426 ('b', 'branch', None, _('show branch')),
3426 ('b', 'branch', None, _('show branch')),
3427 ('t', 'tags', None, _('show tags')),
3427 ('t', 'tags', None, _('show tags')),
3428 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ('B', 'bookmarks', None, _('show bookmarks')),
3429 ] + remoteopts,
3429 ] + remoteopts,
3430 _('[-nibtB] [-r REV] [SOURCE]'))
3430 _('[-nibtB] [-r REV] [SOURCE]'))
3431 def identify(ui, repo, source=None, rev=None,
3431 def identify(ui, repo, source=None, rev=None,
3432 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3433 """identify the working copy or specified revision
3433 """identify the working copy or specified revision
3434
3434
3435 Print a summary identifying the repository state at REV using one or
3435 Print a summary identifying the repository state at REV using one or
3436 two parent hash identifiers, followed by a "+" if the working
3436 two parent hash identifiers, followed by a "+" if the working
3437 directory has uncommitted changes, the branch name (if not default),
3437 directory has uncommitted changes, the branch name (if not default),
3438 a list of tags, and a list of bookmarks.
3438 a list of tags, and a list of bookmarks.
3439
3439
3440 When REV is not given, print a summary of the current state of the
3440 When REV is not given, print a summary of the current state of the
3441 repository.
3441 repository.
3442
3442
3443 Specifying a path to a repository root or Mercurial bundle will
3443 Specifying a path to a repository root or Mercurial bundle will
3444 cause lookup to operate on that repository/bundle.
3444 cause lookup to operate on that repository/bundle.
3445
3445
3446 .. container:: verbose
3446 .. container:: verbose
3447
3447
3448 Examples:
3448 Examples:
3449
3449
3450 - generate a build identifier for the working directory::
3450 - generate a build identifier for the working directory::
3451
3451
3452 hg id --id > build-id.dat
3452 hg id --id > build-id.dat
3453
3453
3454 - find the revision corresponding to a tag::
3454 - find the revision corresponding to a tag::
3455
3455
3456 hg id -n -r 1.3
3456 hg id -n -r 1.3
3457
3457
3458 - check the most recent revision of a remote repository::
3458 - check the most recent revision of a remote repository::
3459
3459
3460 hg id -r tip http://selenic.com/hg/
3460 hg id -r tip http://selenic.com/hg/
3461
3461
3462 Returns 0 if successful.
3462 Returns 0 if successful.
3463 """
3463 """
3464
3464
3465 if not repo and not source:
3465 if not repo and not source:
3466 raise util.Abort(_("there is no Mercurial repository here "
3466 raise util.Abort(_("there is no Mercurial repository here "
3467 "(.hg not found)"))
3467 "(.hg not found)"))
3468
3468
3469 hexfunc = ui.debugflag and hex or short
3469 hexfunc = ui.debugflag and hex or short
3470 default = not (num or id or branch or tags or bookmarks)
3470 default = not (num or id or branch or tags or bookmarks)
3471 output = []
3471 output = []
3472 revs = []
3472 revs = []
3473
3473
3474 if source:
3474 if source:
3475 source, branches = hg.parseurl(ui.expandpath(source))
3475 source, branches = hg.parseurl(ui.expandpath(source))
3476 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3477 repo = peer.local()
3477 repo = peer.local()
3478 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3479
3479
3480 if not repo:
3480 if not repo:
3481 if num or branch or tags:
3481 if num or branch or tags:
3482 raise util.Abort(
3482 raise util.Abort(
3483 _("can't query remote revision number, branch, or tags"))
3483 _("can't query remote revision number, branch, or tags"))
3484 if not rev and revs:
3484 if not rev and revs:
3485 rev = revs[0]
3485 rev = revs[0]
3486 if not rev:
3486 if not rev:
3487 rev = "tip"
3487 rev = "tip"
3488
3488
3489 remoterev = peer.lookup(rev)
3489 remoterev = peer.lookup(rev)
3490 if default or id:
3490 if default or id:
3491 output = [hexfunc(remoterev)]
3491 output = [hexfunc(remoterev)]
3492
3492
3493 def getbms():
3493 def getbms():
3494 bms = []
3494 bms = []
3495
3495
3496 if 'bookmarks' in peer.listkeys('namespaces'):
3496 if 'bookmarks' in peer.listkeys('namespaces'):
3497 hexremoterev = hex(remoterev)
3497 hexremoterev = hex(remoterev)
3498 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3499 if bmr == hexremoterev]
3499 if bmr == hexremoterev]
3500
3500
3501 return sorted(bms)
3501 return sorted(bms)
3502
3502
3503 if bookmarks:
3503 if bookmarks:
3504 output.extend(getbms())
3504 output.extend(getbms())
3505 elif default and not ui.quiet:
3505 elif default and not ui.quiet:
3506 # multiple bookmarks for a single parent separated by '/'
3506 # multiple bookmarks for a single parent separated by '/'
3507 bm = '/'.join(getbms())
3507 bm = '/'.join(getbms())
3508 if bm:
3508 if bm:
3509 output.append(bm)
3509 output.append(bm)
3510 else:
3510 else:
3511 if not rev:
3511 if not rev:
3512 ctx = repo[None]
3512 ctx = repo[None]
3513 parents = ctx.parents()
3513 parents = ctx.parents()
3514 changed = ""
3514 changed = ""
3515 if default or id or num:
3515 if default or id or num:
3516 if (util.any(repo.status())
3516 if (util.any(repo.status())
3517 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3518 changed = '+'
3518 changed = '+'
3519 if default or id:
3519 if default or id:
3520 output = ["%s%s" %
3520 output = ["%s%s" %
3521 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3522 if num:
3522 if num:
3523 output.append("%s%s" %
3523 output.append("%s%s" %
3524 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 ('+'.join([str(p.rev()) for p in parents]), changed))
3525 else:
3525 else:
3526 ctx = scmutil.revsingle(repo, rev)
3526 ctx = scmutil.revsingle(repo, rev)
3527 if default or id:
3527 if default or id:
3528 output = [hexfunc(ctx.node())]
3528 output = [hexfunc(ctx.node())]
3529 if num:
3529 if num:
3530 output.append(str(ctx.rev()))
3530 output.append(str(ctx.rev()))
3531
3531
3532 if default and not ui.quiet:
3532 if default and not ui.quiet:
3533 b = ctx.branch()
3533 b = ctx.branch()
3534 if b != 'default':
3534 if b != 'default':
3535 output.append("(%s)" % b)
3535 output.append("(%s)" % b)
3536
3536
3537 # multiple tags for a single parent separated by '/'
3537 # multiple tags for a single parent separated by '/'
3538 t = '/'.join(ctx.tags())
3538 t = '/'.join(ctx.tags())
3539 if t:
3539 if t:
3540 output.append(t)
3540 output.append(t)
3541
3541
3542 # multiple bookmarks for a single parent separated by '/'
3542 # multiple bookmarks for a single parent separated by '/'
3543 bm = '/'.join(ctx.bookmarks())
3543 bm = '/'.join(ctx.bookmarks())
3544 if bm:
3544 if bm:
3545 output.append(bm)
3545 output.append(bm)
3546 else:
3546 else:
3547 if branch:
3547 if branch:
3548 output.append(ctx.branch())
3548 output.append(ctx.branch())
3549
3549
3550 if tags:
3550 if tags:
3551 output.extend(ctx.tags())
3551 output.extend(ctx.tags())
3552
3552
3553 if bookmarks:
3553 if bookmarks:
3554 output.extend(ctx.bookmarks())
3554 output.extend(ctx.bookmarks())
3555
3555
3556 ui.write("%s\n" % ' '.join(output))
3556 ui.write("%s\n" % ' '.join(output))
3557
3557
3558 @command('import|patch',
3558 @command('import|patch',
3559 [('p', 'strip', 1,
3559 [('p', 'strip', 1,
3560 _('directory strip option for patch. This has the same '
3560 _('directory strip option for patch. This has the same '
3561 'meaning as the corresponding patch option'), _('NUM')),
3561 'meaning as the corresponding patch option'), _('NUM')),
3562 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3563 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('e', 'edit', False, _('invoke editor on commit messages')),
3564 ('f', 'force', None,
3564 ('f', 'force', None,
3565 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3566 ('', 'no-commit', None,
3566 ('', 'no-commit', None,
3567 _("don't commit, just update the working directory")),
3567 _("don't commit, just update the working directory")),
3568 ('', 'bypass', None,
3568 ('', 'bypass', None,
3569 _("apply patch without touching the working directory")),
3569 _("apply patch without touching the working directory")),
3570 ('', 'exact', None,
3570 ('', 'exact', None,
3571 _('apply patch to the nodes from which it was generated')),
3571 _('apply patch to the nodes from which it was generated')),
3572 ('', 'import-branch', None,
3572 ('', 'import-branch', None,
3573 _('use any branch information in patch (implied by --exact)'))] +
3573 _('use any branch information in patch (implied by --exact)'))] +
3574 commitopts + commitopts2 + similarityopts,
3574 commitopts + commitopts2 + similarityopts,
3575 _('[OPTION]... PATCH...'))
3575 _('[OPTION]... PATCH...'))
3576 def import_(ui, repo, patch1=None, *patches, **opts):
3576 def import_(ui, repo, patch1=None, *patches, **opts):
3577 """import an ordered set of patches
3577 """import an ordered set of patches
3578
3578
3579 Import a list of patches and commit them individually (unless
3579 Import a list of patches and commit them individually (unless
3580 --no-commit is specified).
3580 --no-commit is specified).
3581
3581
3582 Because import first applies changes to the working directory,
3582 Because import first applies changes to the working directory,
3583 import will abort if there are outstanding changes.
3583 import will abort if there are outstanding changes.
3584
3584
3585 You can import a patch straight from a mail message. Even patches
3585 You can import a patch straight from a mail message. Even patches
3586 as attachments work (to use the body part, it must have type
3586 as attachments work (to use the body part, it must have type
3587 text/plain or text/x-patch). From and Subject headers of email
3587 text/plain or text/x-patch). From and Subject headers of email
3588 message are used as default committer and commit message. All
3588 message are used as default committer and commit message. All
3589 text/plain body parts before first diff are added to commit
3589 text/plain body parts before first diff are added to commit
3590 message.
3590 message.
3591
3591
3592 If the imported patch was generated by :hg:`export`, user and
3592 If the imported patch was generated by :hg:`export`, user and
3593 description from patch override values from message headers and
3593 description from patch override values from message headers and
3594 body. Values given on command line with -m/--message and -u/--user
3594 body. Values given on command line with -m/--message and -u/--user
3595 override these.
3595 override these.
3596
3596
3597 If --exact is specified, import will set the working directory to
3597 If --exact is specified, import will set the working directory to
3598 the parent of each patch before applying it, and will abort if the
3598 the parent of each patch before applying it, and will abort if the
3599 resulting changeset has a different ID than the one recorded in
3599 resulting changeset has a different ID than the one recorded in
3600 the patch. This may happen due to character set problems or other
3600 the patch. This may happen due to character set problems or other
3601 deficiencies in the text patch format.
3601 deficiencies in the text patch format.
3602
3602
3603 Use --bypass to apply and commit patches directly to the
3603 Use --bypass to apply and commit patches directly to the
3604 repository, not touching the working directory. Without --exact,
3604 repository, not touching the working directory. Without --exact,
3605 patches will be applied on top of the working directory parent
3605 patches will be applied on top of the working directory parent
3606 revision.
3606 revision.
3607
3607
3608 With -s/--similarity, hg will attempt to discover renames and
3608 With -s/--similarity, hg will attempt to discover renames and
3609 copies in the patch in the same way as :hg:`addremove`.
3609 copies in the patch in the same way as :hg:`addremove`.
3610
3610
3611 To read a patch from standard input, use "-" as the patch name. If
3611 To read a patch from standard input, use "-" as the patch name. If
3612 a URL is specified, the patch will be downloaded from it.
3612 a URL is specified, the patch will be downloaded from it.
3613 See :hg:`help dates` for a list of formats valid for -d/--date.
3613 See :hg:`help dates` for a list of formats valid for -d/--date.
3614
3614
3615 .. container:: verbose
3615 .. container:: verbose
3616
3616
3617 Examples:
3617 Examples:
3618
3618
3619 - import a traditional patch from a website and detect renames::
3619 - import a traditional patch from a website and detect renames::
3620
3620
3621 hg import -s 80 http://example.com/bugfix.patch
3621 hg import -s 80 http://example.com/bugfix.patch
3622
3622
3623 - import a changeset from an hgweb server::
3623 - import a changeset from an hgweb server::
3624
3624
3625 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3626
3626
3627 - import all the patches in an Unix-style mbox::
3627 - import all the patches in an Unix-style mbox::
3628
3628
3629 hg import incoming-patches.mbox
3629 hg import incoming-patches.mbox
3630
3630
3631 - attempt to exactly restore an exported changeset (not always
3631 - attempt to exactly restore an exported changeset (not always
3632 possible)::
3632 possible)::
3633
3633
3634 hg import --exact proposed-fix.patch
3634 hg import --exact proposed-fix.patch
3635
3635
3636 Returns 0 on success.
3636 Returns 0 on success.
3637 """
3637 """
3638
3638
3639 if not patch1:
3639 if not patch1:
3640 raise util.Abort(_('need at least one patch to import'))
3640 raise util.Abort(_('need at least one patch to import'))
3641
3641
3642 patches = (patch1,) + patches
3642 patches = (patch1,) + patches
3643
3643
3644 date = opts.get('date')
3644 date = opts.get('date')
3645 if date:
3645 if date:
3646 opts['date'] = util.parsedate(date)
3646 opts['date'] = util.parsedate(date)
3647
3647
3648 editor = cmdutil.commiteditor
3648 editor = cmdutil.commiteditor
3649 if opts.get('edit'):
3649 if opts.get('edit'):
3650 editor = cmdutil.commitforceeditor
3650 editor = cmdutil.commitforceeditor
3651
3651
3652 update = not opts.get('bypass')
3652 update = not opts.get('bypass')
3653 if not update and opts.get('no_commit'):
3653 if not update and opts.get('no_commit'):
3654 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 raise util.Abort(_('cannot use --no-commit with --bypass'))
3655 try:
3655 try:
3656 sim = float(opts.get('similarity') or 0)
3656 sim = float(opts.get('similarity') or 0)
3657 except ValueError:
3657 except ValueError:
3658 raise util.Abort(_('similarity must be a number'))
3658 raise util.Abort(_('similarity must be a number'))
3659 if sim < 0 or sim > 100:
3659 if sim < 0 or sim > 100:
3660 raise util.Abort(_('similarity must be between 0 and 100'))
3660 raise util.Abort(_('similarity must be between 0 and 100'))
3661 if sim and not update:
3661 if sim and not update:
3662 raise util.Abort(_('cannot use --similarity with --bypass'))
3662 raise util.Abort(_('cannot use --similarity with --bypass'))
3663
3663
3664 if update:
3664 if update:
3665 cmdutil.checkunfinished(repo)
3665 cmdutil.checkunfinished(repo)
3666 if (opts.get('exact') or not opts.get('force')) and update:
3666 if (opts.get('exact') or not opts.get('force')) and update:
3667 cmdutil.bailifchanged(repo)
3667 cmdutil.bailifchanged(repo)
3668
3668
3669 base = opts["base"]
3669 base = opts["base"]
3670 strip = opts["strip"]
3670 strip = opts["strip"]
3671 wlock = lock = tr = None
3671 wlock = lock = tr = None
3672 msgs = []
3672 msgs = []
3673
3673
3674 def tryone(ui, hunk, parents):
3674 def tryone(ui, hunk, parents):
3675 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3676 patch.extract(ui, hunk)
3676 patch.extract(ui, hunk)
3677
3677
3678 if not tmpname:
3678 if not tmpname:
3679 return (None, None)
3679 return (None, None)
3680 msg = _('applied to working directory')
3680 msg = _('applied to working directory')
3681
3681
3682 try:
3682 try:
3683 cmdline_message = cmdutil.logmessage(ui, opts)
3683 cmdline_message = cmdutil.logmessage(ui, opts)
3684 if cmdline_message:
3684 if cmdline_message:
3685 # pickup the cmdline msg
3685 # pickup the cmdline msg
3686 message = cmdline_message
3686 message = cmdline_message
3687 elif message:
3687 elif message:
3688 # pickup the patch msg
3688 # pickup the patch msg
3689 message = message.strip()
3689 message = message.strip()
3690 else:
3690 else:
3691 # launch the editor
3691 # launch the editor
3692 message = None
3692 message = None
3693 ui.debug('message:\n%s\n' % message)
3693 ui.debug('message:\n%s\n' % message)
3694
3694
3695 if len(parents) == 1:
3695 if len(parents) == 1:
3696 parents.append(repo[nullid])
3696 parents.append(repo[nullid])
3697 if opts.get('exact'):
3697 if opts.get('exact'):
3698 if not nodeid or not p1:
3698 if not nodeid or not p1:
3699 raise util.Abort(_('not a Mercurial patch'))
3699 raise util.Abort(_('not a Mercurial patch'))
3700 p1 = repo[p1]
3700 p1 = repo[p1]
3701 p2 = repo[p2 or nullid]
3701 p2 = repo[p2 or nullid]
3702 elif p2:
3702 elif p2:
3703 try:
3703 try:
3704 p1 = repo[p1]
3704 p1 = repo[p1]
3705 p2 = repo[p2]
3705 p2 = repo[p2]
3706 # Without any options, consider p2 only if the
3706 # Without any options, consider p2 only if the
3707 # patch is being applied on top of the recorded
3707 # patch is being applied on top of the recorded
3708 # first parent.
3708 # first parent.
3709 if p1 != parents[0]:
3709 if p1 != parents[0]:
3710 p1 = parents[0]
3710 p1 = parents[0]
3711 p2 = repo[nullid]
3711 p2 = repo[nullid]
3712 except error.RepoError:
3712 except error.RepoError:
3713 p1, p2 = parents
3713 p1, p2 = parents
3714 else:
3714 else:
3715 p1, p2 = parents
3715 p1, p2 = parents
3716
3716
3717 n = None
3717 n = None
3718 if update:
3718 if update:
3719 if p1 != parents[0]:
3719 if p1 != parents[0]:
3720 hg.clean(repo, p1.node())
3720 hg.clean(repo, p1.node())
3721 if p2 != parents[1]:
3721 if p2 != parents[1]:
3722 repo.setparents(p1.node(), p2.node())
3722 repo.setparents(p1.node(), p2.node())
3723
3723
3724 if opts.get('exact') or opts.get('import_branch'):
3724 if opts.get('exact') or opts.get('import_branch'):
3725 repo.dirstate.setbranch(branch or 'default')
3725 repo.dirstate.setbranch(branch or 'default')
3726
3726
3727 files = set()
3727 files = set()
3728 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3729 eolmode=None, similarity=sim / 100.0)
3729 eolmode=None, similarity=sim / 100.0)
3730 files = list(files)
3730 files = list(files)
3731 if opts.get('no_commit'):
3731 if opts.get('no_commit'):
3732 if message:
3732 if message:
3733 msgs.append(message)
3733 msgs.append(message)
3734 else:
3734 else:
3735 if opts.get('exact') or p2:
3735 if opts.get('exact') or p2:
3736 # If you got here, you either use --force and know what
3736 # If you got here, you either use --force and know what
3737 # you are doing or used --exact or a merge patch while
3737 # you are doing or used --exact or a merge patch while
3738 # being updated to its first parent.
3738 # being updated to its first parent.
3739 m = None
3739 m = None
3740 else:
3740 else:
3741 m = scmutil.matchfiles(repo, files or [])
3741 m = scmutil.matchfiles(repo, files or [])
3742 n = repo.commit(message, opts.get('user') or user,
3742 n = repo.commit(message, opts.get('user') or user,
3743 opts.get('date') or date, match=m,
3743 opts.get('date') or date, match=m,
3744 editor=editor)
3744 editor=editor)
3745 else:
3745 else:
3746 if opts.get('exact') or opts.get('import_branch'):
3746 if opts.get('exact') or opts.get('import_branch'):
3747 branch = branch or 'default'
3747 branch = branch or 'default'
3748 else:
3748 else:
3749 branch = p1.branch()
3749 branch = p1.branch()
3750 store = patch.filestore()
3750 store = patch.filestore()
3751 try:
3751 try:
3752 files = set()
3752 files = set()
3753 try:
3753 try:
3754 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3755 files, eolmode=None)
3755 files, eolmode=None)
3756 except patch.PatchError, e:
3756 except patch.PatchError, e:
3757 raise util.Abort(str(e))
3757 raise util.Abort(str(e))
3758 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3758 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3759 message,
3759 message,
3760 opts.get('user') or user,
3760 opts.get('user') or user,
3761 opts.get('date') or date,
3761 opts.get('date') or date,
3762 branch, files, store,
3762 branch, files, store,
3763 editor=cmdutil.commiteditor)
3763 editor=cmdutil.commiteditor)
3764 repo.savecommitmessage(memctx.description())
3764 repo.savecommitmessage(memctx.description())
3765 n = memctx.commit()
3765 n = memctx.commit()
3766 finally:
3766 finally:
3767 store.close()
3767 store.close()
3768 if opts.get('exact') and hex(n) != nodeid:
3768 if opts.get('exact') and hex(n) != nodeid:
3769 raise util.Abort(_('patch is damaged or loses information'))
3769 raise util.Abort(_('patch is damaged or loses information'))
3770 if n:
3770 if n:
3771 # i18n: refers to a short changeset id
3771 # i18n: refers to a short changeset id
3772 msg = _('created %s') % short(n)
3772 msg = _('created %s') % short(n)
3773 return (msg, n)
3773 return (msg, n)
3774 finally:
3774 finally:
3775 os.unlink(tmpname)
3775 os.unlink(tmpname)
3776
3776
3777 try:
3777 try:
3778 try:
3778 try:
3779 wlock = repo.wlock()
3779 wlock = repo.wlock()
3780 if not opts.get('no_commit'):
3780 if not opts.get('no_commit'):
3781 lock = repo.lock()
3781 lock = repo.lock()
3782 tr = repo.transaction('import')
3782 tr = repo.transaction('import')
3783 parents = repo.parents()
3783 parents = repo.parents()
3784 for patchurl in patches:
3784 for patchurl in patches:
3785 if patchurl == '-':
3785 if patchurl == '-':
3786 ui.status(_('applying patch from stdin\n'))
3786 ui.status(_('applying patch from stdin\n'))
3787 patchfile = ui.fin
3787 patchfile = ui.fin
3788 patchurl = 'stdin' # for error message
3788 patchurl = 'stdin' # for error message
3789 else:
3789 else:
3790 patchurl = os.path.join(base, patchurl)
3790 patchurl = os.path.join(base, patchurl)
3791 ui.status(_('applying %s\n') % patchurl)
3791 ui.status(_('applying %s\n') % patchurl)
3792 patchfile = hg.openpath(ui, patchurl)
3792 patchfile = hg.openpath(ui, patchurl)
3793
3793
3794 haspatch = False
3794 haspatch = False
3795 for hunk in patch.split(patchfile):
3795 for hunk in patch.split(patchfile):
3796 (msg, node) = tryone(ui, hunk, parents)
3796 (msg, node) = tryone(ui, hunk, parents)
3797 if msg:
3797 if msg:
3798 haspatch = True
3798 haspatch = True
3799 ui.note(msg + '\n')
3799 ui.note(msg + '\n')
3800 if update or opts.get('exact'):
3800 if update or opts.get('exact'):
3801 parents = repo.parents()
3801 parents = repo.parents()
3802 else:
3802 else:
3803 parents = [repo[node]]
3803 parents = [repo[node]]
3804
3804
3805 if not haspatch:
3805 if not haspatch:
3806 raise util.Abort(_('%s: no diffs found') % patchurl)
3806 raise util.Abort(_('%s: no diffs found') % patchurl)
3807
3807
3808 if tr:
3808 if tr:
3809 tr.close()
3809 tr.close()
3810 if msgs:
3810 if msgs:
3811 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 repo.savecommitmessage('\n* * *\n'.join(msgs))
3812 except: # re-raises
3812 except: # re-raises
3813 # wlock.release() indirectly calls dirstate.write(): since
3813 # wlock.release() indirectly calls dirstate.write(): since
3814 # we're crashing, we do not want to change the working dir
3814 # we're crashing, we do not want to change the working dir
3815 # parent after all, so make sure it writes nothing
3815 # parent after all, so make sure it writes nothing
3816 repo.dirstate.invalidate()
3816 repo.dirstate.invalidate()
3817 raise
3817 raise
3818 finally:
3818 finally:
3819 if tr:
3819 if tr:
3820 tr.release()
3820 tr.release()
3821 release(lock, wlock)
3821 release(lock, wlock)
3822
3822
3823 @command('incoming|in',
3823 @command('incoming|in',
3824 [('f', 'force', None,
3824 [('f', 'force', None,
3825 _('run even if remote repository is unrelated')),
3825 _('run even if remote repository is unrelated')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3827 ('', 'bundle', '',
3827 ('', 'bundle', '',
3828 _('file to store the bundles into'), _('FILE')),
3828 _('file to store the bundles into'), _('FILE')),
3829 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3830 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('B', 'bookmarks', False, _("compare bookmarks")),
3831 ('b', 'branch', [],
3831 ('b', 'branch', [],
3832 _('a specific branch you would like to pull'), _('BRANCH')),
3832 _('a specific branch you would like to pull'), _('BRANCH')),
3833 ] + logopts + remoteopts + subrepoopts,
3833 ] + logopts + remoteopts + subrepoopts,
3834 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3835 def incoming(ui, repo, source="default", **opts):
3835 def incoming(ui, repo, source="default", **opts):
3836 """show new changesets found in source
3836 """show new changesets found in source
3837
3837
3838 Show new changesets found in the specified path/URL or the default
3838 Show new changesets found in the specified path/URL or the default
3839 pull location. These are the changesets that would have been pulled
3839 pull location. These are the changesets that would have been pulled
3840 if a pull at the time you issued this command.
3840 if a pull at the time you issued this command.
3841
3841
3842 For remote repository, using --bundle avoids downloading the
3842 For remote repository, using --bundle avoids downloading the
3843 changesets twice if the incoming is followed by a pull.
3843 changesets twice if the incoming is followed by a pull.
3844
3844
3845 See pull for valid source format details.
3845 See pull for valid source format details.
3846
3846
3847 Returns 0 if there are incoming changes, 1 otherwise.
3847 Returns 0 if there are incoming changes, 1 otherwise.
3848 """
3848 """
3849 if opts.get('graph'):
3849 if opts.get('graph'):
3850 cmdutil.checkunsupportedgraphflags([], opts)
3850 cmdutil.checkunsupportedgraphflags([], opts)
3851 def display(other, chlist, displayer):
3851 def display(other, chlist, displayer):
3852 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 revdag = cmdutil.graphrevs(other, chlist, opts)
3853 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 showparents = [ctx.node() for ctx in repo[None].parents()]
3854 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3855 graphmod.asciiedges)
3855 graphmod.asciiedges)
3856
3856
3857 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3858 return 0
3858 return 0
3859
3859
3860 if opts.get('bundle') and opts.get('subrepos'):
3860 if opts.get('bundle') and opts.get('subrepos'):
3861 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3862
3862
3863 if opts.get('bookmarks'):
3863 if opts.get('bookmarks'):
3864 source, branches = hg.parseurl(ui.expandpath(source),
3864 source, branches = hg.parseurl(ui.expandpath(source),
3865 opts.get('branch'))
3865 opts.get('branch'))
3866 other = hg.peer(repo, opts, source)
3866 other = hg.peer(repo, opts, source)
3867 if 'bookmarks' not in other.listkeys('namespaces'):
3867 if 'bookmarks' not in other.listkeys('namespaces'):
3868 ui.warn(_("remote doesn't support bookmarks\n"))
3868 ui.warn(_("remote doesn't support bookmarks\n"))
3869 return 0
3869 return 0
3870 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3871 return bookmarks.diff(ui, repo, other)
3871 return bookmarks.diff(ui, repo, other)
3872
3872
3873 repo._subtoppath = ui.expandpath(source)
3873 repo._subtoppath = ui.expandpath(source)
3874 try:
3874 try:
3875 return hg.incoming(ui, repo, source, opts)
3875 return hg.incoming(ui, repo, source, opts)
3876 finally:
3876 finally:
3877 del repo._subtoppath
3877 del repo._subtoppath
3878
3878
3879
3879
3880 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3881 def init(ui, dest=".", **opts):
3881 def init(ui, dest=".", **opts):
3882 """create a new repository in the given directory
3882 """create a new repository in the given directory
3883
3883
3884 Initialize a new repository in the given directory. If the given
3884 Initialize a new repository in the given directory. If the given
3885 directory does not exist, it will be created.
3885 directory does not exist, it will be created.
3886
3886
3887 If no directory is given, the current directory is used.
3887 If no directory is given, the current directory is used.
3888
3888
3889 It is possible to specify an ``ssh://`` URL as the destination.
3889 It is possible to specify an ``ssh://`` URL as the destination.
3890 See :hg:`help urls` for more information.
3890 See :hg:`help urls` for more information.
3891
3891
3892 Returns 0 on success.
3892 Returns 0 on success.
3893 """
3893 """
3894 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3895
3895
3896 @command('locate',
3896 @command('locate',
3897 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3898 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3899 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3900 ] + walkopts,
3900 ] + walkopts,
3901 _('[OPTION]... [PATTERN]...'))
3901 _('[OPTION]... [PATTERN]...'))
3902 def locate(ui, repo, *pats, **opts):
3902 def locate(ui, repo, *pats, **opts):
3903 """locate files matching specific patterns
3903 """locate files matching specific patterns
3904
3904
3905 Print files under Mercurial control in the working directory whose
3905 Print files under Mercurial control in the working directory whose
3906 names match the given patterns.
3906 names match the given patterns.
3907
3907
3908 By default, this command searches all directories in the working
3908 By default, this command searches all directories in the working
3909 directory. To search just the current directory and its
3909 directory. To search just the current directory and its
3910 subdirectories, use "--include .".
3910 subdirectories, use "--include .".
3911
3911
3912 If no patterns are given to match, this command prints the names
3912 If no patterns are given to match, this command prints the names
3913 of all files under Mercurial control in the working directory.
3913 of all files under Mercurial control in the working directory.
3914
3914
3915 If you want to feed the output of this command into the "xargs"
3915 If you want to feed the output of this command into the "xargs"
3916 command, use the -0 option to both this command and "xargs". This
3916 command, use the -0 option to both this command and "xargs". This
3917 will avoid the problem of "xargs" treating single filenames that
3917 will avoid the problem of "xargs" treating single filenames that
3918 contain whitespace as multiple filenames.
3918 contain whitespace as multiple filenames.
3919
3919
3920 Returns 0 if a match is found, 1 otherwise.
3920 Returns 0 if a match is found, 1 otherwise.
3921 """
3921 """
3922 end = opts.get('print0') and '\0' or '\n'
3922 end = opts.get('print0') and '\0' or '\n'
3923 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3924
3924
3925 ret = 1
3925 ret = 1
3926 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3927 m.bad = lambda x, y: False
3927 m.bad = lambda x, y: False
3928 for abs in repo[rev].walk(m):
3928 for abs in repo[rev].walk(m):
3929 if not rev and abs not in repo.dirstate:
3929 if not rev and abs not in repo.dirstate:
3930 continue
3930 continue
3931 if opts.get('fullpath'):
3931 if opts.get('fullpath'):
3932 ui.write(repo.wjoin(abs), end)
3932 ui.write(repo.wjoin(abs), end)
3933 else:
3933 else:
3934 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ui.write(((pats and m.rel(abs)) or abs), end)
3935 ret = 0
3935 ret = 0
3936
3936
3937 return ret
3937 return ret
3938
3938
3939 @command('^log|history',
3939 @command('^log|history',
3940 [('f', 'follow', None,
3940 [('f', 'follow', None,
3941 _('follow changeset history, or file history across copies and renames')),
3941 _('follow changeset history, or file history across copies and renames')),
3942 ('', 'follow-first', None,
3942 ('', 'follow-first', None,
3943 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 _('only follow the first parent of merge changesets (DEPRECATED)')),
3944 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3945 ('C', 'copies', None, _('show copied files')),
3945 ('C', 'copies', None, _('show copied files')),
3946 ('k', 'keyword', [],
3946 ('k', 'keyword', [],
3947 _('do case-insensitive search for a given text'), _('TEXT')),
3947 _('do case-insensitive search for a given text'), _('TEXT')),
3948 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3949 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('', 'removed', None, _('include revisions where files were removed')),
3950 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3951 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3952 ('', 'only-branch', [],
3952 ('', 'only-branch', [],
3953 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('show only changesets within the given named branch (DEPRECATED)'),
3954 _('BRANCH')),
3954 _('BRANCH')),
3955 ('b', 'branch', [],
3955 ('b', 'branch', [],
3956 _('show changesets within the given named branch'), _('BRANCH')),
3956 _('show changesets within the given named branch'), _('BRANCH')),
3957 ('P', 'prune', [],
3957 ('P', 'prune', [],
3958 _('do not display revision or any of its ancestors'), _('REV')),
3958 _('do not display revision or any of its ancestors'), _('REV')),
3959 ] + logopts + walkopts,
3959 ] + logopts + walkopts,
3960 _('[OPTION]... [FILE]'))
3960 _('[OPTION]... [FILE]'))
3961 def log(ui, repo, *pats, **opts):
3961 def log(ui, repo, *pats, **opts):
3962 """show revision history of entire repository or files
3962 """show revision history of entire repository or files
3963
3963
3964 Print the revision history of the specified files or the entire
3964 Print the revision history of the specified files or the entire
3965 project.
3965 project.
3966
3966
3967 If no revision range is specified, the default is ``tip:0`` unless
3967 If no revision range is specified, the default is ``tip:0`` unless
3968 --follow is set, in which case the working directory parent is
3968 --follow is set, in which case the working directory parent is
3969 used as the starting revision.
3969 used as the starting revision.
3970
3970
3971 File history is shown without following rename or copy history of
3971 File history is shown without following rename or copy history of
3972 files. Use -f/--follow with a filename to follow history across
3972 files. Use -f/--follow with a filename to follow history across
3973 renames and copies. --follow without a filename will only show
3973 renames and copies. --follow without a filename will only show
3974 ancestors or descendants of the starting revision.
3974 ancestors or descendants of the starting revision.
3975
3975
3976 By default this command prints revision number and changeset id,
3976 By default this command prints revision number and changeset id,
3977 tags, non-trivial parents, user, date and time, and a summary for
3977 tags, non-trivial parents, user, date and time, and a summary for
3978 each commit. When the -v/--verbose switch is used, the list of
3978 each commit. When the -v/--verbose switch is used, the list of
3979 changed files and full commit message are shown.
3979 changed files and full commit message are shown.
3980
3980
3981 .. note::
3981 .. note::
3982 log -p/--patch may generate unexpected diff output for merge
3982 log -p/--patch may generate unexpected diff output for merge
3983 changesets, as it will only compare the merge changeset against
3983 changesets, as it will only compare the merge changeset against
3984 its first parent. Also, only files different from BOTH parents
3984 its first parent. Also, only files different from BOTH parents
3985 will appear in files:.
3985 will appear in files:.
3986
3986
3987 .. note::
3987 .. note::
3988 for performance reasons, log FILE may omit duplicate changes
3988 for performance reasons, log FILE may omit duplicate changes
3989 made on branches and will not show deletions. To see all
3989 made on branches and will not show deletions. To see all
3990 changes including duplicates and deletions, use the --removed
3990 changes including duplicates and deletions, use the --removed
3991 switch.
3991 switch.
3992
3992
3993 .. container:: verbose
3993 .. container:: verbose
3994
3994
3995 Some examples:
3995 Some examples:
3996
3996
3997 - changesets with full descriptions and file lists::
3997 - changesets with full descriptions and file lists::
3998
3998
3999 hg log -v
3999 hg log -v
4000
4000
4001 - changesets ancestral to the working directory::
4001 - changesets ancestral to the working directory::
4002
4002
4003 hg log -f
4003 hg log -f
4004
4004
4005 - last 10 commits on the current branch::
4005 - last 10 commits on the current branch::
4006
4006
4007 hg log -l 10 -b .
4007 hg log -l 10 -b .
4008
4008
4009 - changesets showing all modifications of a file, including removals::
4009 - changesets showing all modifications of a file, including removals::
4010
4010
4011 hg log --removed file.c
4011 hg log --removed file.c
4012
4012
4013 - all changesets that touch a directory, with diffs, excluding merges::
4013 - all changesets that touch a directory, with diffs, excluding merges::
4014
4014
4015 hg log -Mp lib/
4015 hg log -Mp lib/
4016
4016
4017 - all revision numbers that match a keyword::
4017 - all revision numbers that match a keyword::
4018
4018
4019 hg log -k bug --template "{rev}\\n"
4019 hg log -k bug --template "{rev}\\n"
4020
4020
4021 - check if a given changeset is included is a tagged release::
4021 - check if a given changeset is included is a tagged release::
4022
4022
4023 hg log -r "a21ccf and ancestor(1.9)"
4023 hg log -r "a21ccf and ancestor(1.9)"
4024
4024
4025 - find all changesets by some user in a date range::
4025 - find all changesets by some user in a date range::
4026
4026
4027 hg log -k alice -d "may 2008 to jul 2008"
4027 hg log -k alice -d "may 2008 to jul 2008"
4028
4028
4029 - summary of all changesets after the last tag::
4029 - summary of all changesets after the last tag::
4030
4030
4031 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4031 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4032
4032
4033 See :hg:`help dates` for a list of formats valid for -d/--date.
4033 See :hg:`help dates` for a list of formats valid for -d/--date.
4034
4034
4035 See :hg:`help revisions` and :hg:`help revsets` for more about
4035 See :hg:`help revisions` and :hg:`help revsets` for more about
4036 specifying revisions.
4036 specifying revisions.
4037
4037
4038 See :hg:`help templates` for more about pre-packaged styles and
4038 See :hg:`help templates` for more about pre-packaged styles and
4039 specifying custom templates.
4039 specifying custom templates.
4040
4040
4041 Returns 0 on success.
4041 Returns 0 on success.
4042 """
4042 """
4043 if opts.get('graph'):
4043 if opts.get('graph'):
4044 return cmdutil.graphlog(ui, repo, *pats, **opts)
4044 return cmdutil.graphlog(ui, repo, *pats, **opts)
4045
4045
4046 matchfn = scmutil.match(repo[None], pats, opts)
4046 matchfn = scmutil.match(repo[None], pats, opts)
4047 limit = cmdutil.loglimit(opts)
4047 limit = cmdutil.loglimit(opts)
4048 count = 0
4048 count = 0
4049
4049
4050 getrenamed, endrev = None, None
4050 getrenamed, endrev = None, None
4051 if opts.get('copies'):
4051 if opts.get('copies'):
4052 if opts.get('rev'):
4052 if opts.get('rev'):
4053 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4053 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4054 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4054 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4055
4055
4056 df = False
4056 df = False
4057 if opts.get("date"):
4057 if opts.get("date"):
4058 df = util.matchdate(opts["date"])
4058 df = util.matchdate(opts["date"])
4059
4059
4060 branches = opts.get('branch', []) + opts.get('only_branch', [])
4060 branches = opts.get('branch', []) + opts.get('only_branch', [])
4061 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4061 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4062
4062
4063 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4063 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4064 def prep(ctx, fns):
4064 def prep(ctx, fns):
4065 rev = ctx.rev()
4065 rev = ctx.rev()
4066 parents = [p for p in repo.changelog.parentrevs(rev)
4066 parents = [p for p in repo.changelog.parentrevs(rev)
4067 if p != nullrev]
4067 if p != nullrev]
4068 if opts.get('no_merges') and len(parents) == 2:
4068 if opts.get('no_merges') and len(parents) == 2:
4069 return
4069 return
4070 if opts.get('only_merges') and len(parents) != 2:
4070 if opts.get('only_merges') and len(parents) != 2:
4071 return
4071 return
4072 if opts.get('branch') and ctx.branch() not in opts['branch']:
4072 if opts.get('branch') and ctx.branch() not in opts['branch']:
4073 return
4073 return
4074 if df and not df(ctx.date()[0]):
4074 if df and not df(ctx.date()[0]):
4075 return
4075 return
4076
4076
4077 lower = encoding.lower
4077 lower = encoding.lower
4078 if opts.get('user'):
4078 if opts.get('user'):
4079 luser = lower(ctx.user())
4079 luser = lower(ctx.user())
4080 for k in [lower(x) for x in opts['user']]:
4080 for k in [lower(x) for x in opts['user']]:
4081 if (k in luser):
4081 if (k in luser):
4082 break
4082 break
4083 else:
4083 else:
4084 return
4084 return
4085 if opts.get('keyword'):
4085 if opts.get('keyword'):
4086 luser = lower(ctx.user())
4086 luser = lower(ctx.user())
4087 ldesc = lower(ctx.description())
4087 ldesc = lower(ctx.description())
4088 lfiles = lower(" ".join(ctx.files()))
4088 lfiles = lower(" ".join(ctx.files()))
4089 for k in [lower(x) for x in opts['keyword']]:
4089 for k in [lower(x) for x in opts['keyword']]:
4090 if (k in luser or k in ldesc or k in lfiles):
4090 if (k in luser or k in ldesc or k in lfiles):
4091 break
4091 break
4092 else:
4092 else:
4093 return
4093 return
4094
4094
4095 copies = None
4095 copies = None
4096 if getrenamed is not None and rev:
4096 if getrenamed is not None and rev:
4097 copies = []
4097 copies = []
4098 for fn in ctx.files():
4098 for fn in ctx.files():
4099 rename = getrenamed(fn, rev)
4099 rename = getrenamed(fn, rev)
4100 if rename:
4100 if rename:
4101 copies.append((fn, rename[0]))
4101 copies.append((fn, rename[0]))
4102
4102
4103 revmatchfn = None
4103 revmatchfn = None
4104 if opts.get('patch') or opts.get('stat'):
4104 if opts.get('patch') or opts.get('stat'):
4105 if opts.get('follow') or opts.get('follow_first'):
4105 if opts.get('follow') or opts.get('follow_first'):
4106 # note: this might be wrong when following through merges
4106 # note: this might be wrong when following through merges
4107 revmatchfn = scmutil.match(repo[None], fns, default='path')
4107 revmatchfn = scmutil.match(repo[None], fns, default='path')
4108 else:
4108 else:
4109 revmatchfn = matchfn
4109 revmatchfn = matchfn
4110
4110
4111 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4111 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4112
4112
4113 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4113 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4114 if displayer.flush(ctx.rev()):
4114 if displayer.flush(ctx.rev()):
4115 count += 1
4115 count += 1
4116 if count == limit:
4116 if count == limit:
4117 break
4117 break
4118 displayer.close()
4118 displayer.close()
4119
4119
4120 @command('manifest',
4120 @command('manifest',
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4122 ('', 'all', False, _("list files from all revisions"))],
4122 ('', 'all', False, _("list files from all revisions"))],
4123 _('[-r REV]'))
4123 _('[-r REV]'))
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4125 """output the current or given revision of the project manifest
4125 """output the current or given revision of the project manifest
4126
4126
4127 Print a list of version controlled files for the given revision.
4127 Print a list of version controlled files for the given revision.
4128 If no revision is given, the first parent of the working directory
4128 If no revision is given, the first parent of the working directory
4129 is used, or the null revision if no revision is checked out.
4129 is used, or the null revision if no revision is checked out.
4130
4130
4131 With -v, print file permissions, symlink and executable bits.
4131 With -v, print file permissions, symlink and executable bits.
4132 With --debug, print file revision hashes.
4132 With --debug, print file revision hashes.
4133
4133
4134 If option --all is specified, the list of all files from all revisions
4134 If option --all is specified, the list of all files from all revisions
4135 is printed. This includes deleted and renamed files.
4135 is printed. This includes deleted and renamed files.
4136
4136
4137 Returns 0 on success.
4137 Returns 0 on success.
4138 """
4138 """
4139
4139
4140 fm = ui.formatter('manifest', opts)
4140 fm = ui.formatter('manifest', opts)
4141
4141
4142 if opts.get('all'):
4142 if opts.get('all'):
4143 if rev or node:
4143 if rev or node:
4144 raise util.Abort(_("can't specify a revision with --all"))
4144 raise util.Abort(_("can't specify a revision with --all"))
4145
4145
4146 res = []
4146 res = []
4147 prefix = "data/"
4147 prefix = "data/"
4148 suffix = ".i"
4148 suffix = ".i"
4149 plen = len(prefix)
4149 plen = len(prefix)
4150 slen = len(suffix)
4150 slen = len(suffix)
4151 lock = repo.lock()
4151 lock = repo.lock()
4152 try:
4152 try:
4153 for fn, b, size in repo.store.datafiles():
4153 for fn, b, size in repo.store.datafiles():
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4155 res.append(fn[plen:-slen])
4155 res.append(fn[plen:-slen])
4156 finally:
4156 finally:
4157 lock.release()
4157 lock.release()
4158 for f in res:
4158 for f in res:
4159 fm.startitem()
4159 fm.startitem()
4160 fm.write("path", '%s\n', f)
4160 fm.write("path", '%s\n', f)
4161 fm.end()
4161 fm.end()
4162 return
4162 return
4163
4163
4164 if rev and node:
4164 if rev and node:
4165 raise util.Abort(_("please specify just one revision"))
4165 raise util.Abort(_("please specify just one revision"))
4166
4166
4167 if not node:
4167 if not node:
4168 node = rev
4168 node = rev
4169
4169
4170 char = {'l': '@', 'x': '*', '': ''}
4170 char = {'l': '@', 'x': '*', '': ''}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4172 ctx = scmutil.revsingle(repo, node)
4172 ctx = scmutil.revsingle(repo, node)
4173 mf = ctx.manifest()
4173 mf = ctx.manifest()
4174 for f in ctx:
4174 for f in ctx:
4175 fm.startitem()
4175 fm.startitem()
4176 fl = ctx[f].flags()
4176 fl = ctx[f].flags()
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4179 fm.write('path', '%s\n', f)
4179 fm.write('path', '%s\n', f)
4180 fm.end()
4180 fm.end()
4181
4181
4182 @command('^merge',
4182 @command('^merge',
4183 [('f', 'force', None,
4183 [('f', 'force', None,
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4186 ('P', 'preview', None,
4186 ('P', 'preview', None,
4187 _('review revisions to merge (no merge is performed)'))
4187 _('review revisions to merge (no merge is performed)'))
4188 ] + mergetoolopts,
4188 ] + mergetoolopts,
4189 _('[-P] [-f] [[-r] REV]'))
4189 _('[-P] [-f] [[-r] REV]'))
4190 def merge(ui, repo, node=None, **opts):
4190 def merge(ui, repo, node=None, **opts):
4191 """merge working directory with another revision
4191 """merge working directory with another revision
4192
4192
4193 The current working directory is updated with all changes made in
4193 The current working directory is updated with all changes made in
4194 the requested revision since the last common predecessor revision.
4194 the requested revision since the last common predecessor revision.
4195
4195
4196 Files that changed between either parent are marked as changed for
4196 Files that changed between either parent are marked as changed for
4197 the next commit and a commit must be performed before any further
4197 the next commit and a commit must be performed before any further
4198 updates to the repository are allowed. The next commit will have
4198 updates to the repository are allowed. The next commit will have
4199 two parents.
4199 two parents.
4200
4200
4201 ``--tool`` can be used to specify the merge tool used for file
4201 ``--tool`` can be used to specify the merge tool used for file
4202 merges. It overrides the HGMERGE environment variable and your
4202 merges. It overrides the HGMERGE environment variable and your
4203 configuration files. See :hg:`help merge-tools` for options.
4203 configuration files. See :hg:`help merge-tools` for options.
4204
4204
4205 If no revision is specified, the working directory's parent is a
4205 If no revision is specified, the working directory's parent is a
4206 head revision, and the current branch contains exactly one other
4206 head revision, and the current branch contains exactly one other
4207 head, the other head is merged with by default. Otherwise, an
4207 head, the other head is merged with by default. Otherwise, an
4208 explicit revision with which to merge with must be provided.
4208 explicit revision with which to merge with must be provided.
4209
4209
4210 :hg:`resolve` must be used to resolve unresolved files.
4210 :hg:`resolve` must be used to resolve unresolved files.
4211
4211
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4213 will check out a clean copy of the original merge parent, losing
4213 will check out a clean copy of the original merge parent, losing
4214 all changes.
4214 all changes.
4215
4215
4216 Returns 0 on success, 1 if there are unresolved files.
4216 Returns 0 on success, 1 if there are unresolved files.
4217 """
4217 """
4218
4218
4219 if opts.get('rev') and node:
4219 if opts.get('rev') and node:
4220 raise util.Abort(_("please specify just one revision"))
4220 raise util.Abort(_("please specify just one revision"))
4221 if not node:
4221 if not node:
4222 node = opts.get('rev')
4222 node = opts.get('rev')
4223
4223
4224 if node:
4224 if node:
4225 node = scmutil.revsingle(repo, node).node()
4225 node = scmutil.revsingle(repo, node).node()
4226
4226
4227 if not node and repo._bookmarkcurrent:
4227 if not node and repo._bookmarkcurrent:
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4229 curhead = repo[repo._bookmarkcurrent].node()
4229 curhead = repo[repo._bookmarkcurrent].node()
4230 if len(bmheads) == 2:
4230 if len(bmheads) == 2:
4231 if curhead == bmheads[0]:
4231 if curhead == bmheads[0]:
4232 node = bmheads[1]
4232 node = bmheads[1]
4233 else:
4233 else:
4234 node = bmheads[0]
4234 node = bmheads[0]
4235 elif len(bmheads) > 2:
4235 elif len(bmheads) > 2:
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4237 "please merge with an explicit rev or bookmark"),
4237 "please merge with an explicit rev or bookmark"),
4238 hint=_("run 'hg heads' to see all heads"))
4238 hint=_("run 'hg heads' to see all heads"))
4239 elif len(bmheads) <= 1:
4239 elif len(bmheads) <= 1:
4240 raise util.Abort(_("no matching bookmark to merge - "
4240 raise util.Abort(_("no matching bookmark to merge - "
4241 "please merge with an explicit rev or bookmark"),
4241 "please merge with an explicit rev or bookmark"),
4242 hint=_("run 'hg heads' to see all heads"))
4242 hint=_("run 'hg heads' to see all heads"))
4243
4243
4244 if not node and not repo._bookmarkcurrent:
4244 if not node and not repo._bookmarkcurrent:
4245 branch = repo[None].branch()
4245 branch = repo[None].branch()
4246 bheads = repo.branchheads(branch)
4246 bheads = repo.branchheads(branch)
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4248
4248
4249 if len(nbhs) > 2:
4249 if len(nbhs) > 2:
4250 raise util.Abort(_("branch '%s' has %d heads - "
4250 raise util.Abort(_("branch '%s' has %d heads - "
4251 "please merge with an explicit rev")
4251 "please merge with an explicit rev")
4252 % (branch, len(bheads)),
4252 % (branch, len(bheads)),
4253 hint=_("run 'hg heads .' to see heads"))
4253 hint=_("run 'hg heads .' to see heads"))
4254
4254
4255 parent = repo.dirstate.p1()
4255 parent = repo.dirstate.p1()
4256 if len(nbhs) <= 1:
4256 if len(nbhs) <= 1:
4257 if len(bheads) > 1:
4257 if len(bheads) > 1:
4258 raise util.Abort(_("heads are bookmarked - "
4258 raise util.Abort(_("heads are bookmarked - "
4259 "please merge with an explicit rev"),
4259 "please merge with an explicit rev"),
4260 hint=_("run 'hg heads' to see all heads"))
4260 hint=_("run 'hg heads' to see all heads"))
4261 if len(repo.heads()) > 1:
4261 if len(repo.heads()) > 1:
4262 raise util.Abort(_("branch '%s' has one head - "
4262 raise util.Abort(_("branch '%s' has one head - "
4263 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4264 % branch,
4264 % branch,
4265 hint=_("run 'hg heads' to see all heads"))
4265 hint=_("run 'hg heads' to see all heads"))
4266 msg, hint = _('nothing to merge'), None
4266 msg, hint = _('nothing to merge'), None
4267 if parent != repo.lookup(branch):
4267 if parent != repo.lookup(branch):
4268 hint = _("use 'hg update' instead")
4268 hint = _("use 'hg update' instead")
4269 raise util.Abort(msg, hint=hint)
4269 raise util.Abort(msg, hint=hint)
4270
4270
4271 if parent not in bheads:
4271 if parent not in bheads:
4272 raise util.Abort(_('working directory not at a head revision'),
4272 raise util.Abort(_('working directory not at a head revision'),
4273 hint=_("use 'hg update' or merge with an "
4273 hint=_("use 'hg update' or merge with an "
4274 "explicit revision"))
4274 "explicit revision"))
4275 if parent == nbhs[0]:
4275 if parent == nbhs[0]:
4276 node = nbhs[-1]
4276 node = nbhs[-1]
4277 else:
4277 else:
4278 node = nbhs[0]
4278 node = nbhs[0]
4279
4279
4280 if opts.get('preview'):
4280 if opts.get('preview'):
4281 # find nodes that are ancestors of p2 but not of p1
4281 # find nodes that are ancestors of p2 but not of p1
4282 p1 = repo.lookup('.')
4282 p1 = repo.lookup('.')
4283 p2 = repo.lookup(node)
4283 p2 = repo.lookup(node)
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4285
4285
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4287 for node in nodes:
4287 for node in nodes:
4288 displayer.show(repo[node])
4288 displayer.show(repo[node])
4289 displayer.close()
4289 displayer.close()
4290 return 0
4290 return 0
4291
4291
4292 try:
4292 try:
4293 # ui.forcemerge is an internal variable, do not document
4293 # ui.forcemerge is an internal variable, do not document
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4295 return hg.merge(repo, node, force=opts.get('force'))
4295 return hg.merge(repo, node, force=opts.get('force'))
4296 finally:
4296 finally:
4297 ui.setconfig('ui', 'forcemerge', '')
4297 ui.setconfig('ui', 'forcemerge', '')
4298
4298
4299 @command('outgoing|out',
4299 @command('outgoing|out',
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4301 ('r', 'rev', [],
4301 ('r', 'rev', [],
4302 _('a changeset intended to be included in the destination'), _('REV')),
4302 _('a changeset intended to be included in the destination'), _('REV')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4306 _('BRANCH')),
4306 _('BRANCH')),
4307 ] + logopts + remoteopts + subrepoopts,
4307 ] + logopts + remoteopts + subrepoopts,
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4309 def outgoing(ui, repo, dest=None, **opts):
4309 def outgoing(ui, repo, dest=None, **opts):
4310 """show changesets not found in the destination
4310 """show changesets not found in the destination
4311
4311
4312 Show changesets not found in the specified destination repository
4312 Show changesets not found in the specified destination repository
4313 or the default push location. These are the changesets that would
4313 or the default push location. These are the changesets that would
4314 be pushed if a push was requested.
4314 be pushed if a push was requested.
4315
4315
4316 See pull for details of valid destination formats.
4316 See pull for details of valid destination formats.
4317
4317
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4319 """
4319 """
4320 if opts.get('graph'):
4320 if opts.get('graph'):
4321 cmdutil.checkunsupportedgraphflags([], opts)
4321 cmdutil.checkunsupportedgraphflags([], opts)
4322 o = hg._outgoing(ui, repo, dest, opts)
4322 o = hg._outgoing(ui, repo, dest, opts)
4323 if o is None:
4323 if o is None:
4324 return
4324 return
4325
4325
4326 revdag = cmdutil.graphrevs(repo, o, opts)
4326 revdag = cmdutil.graphrevs(repo, o, opts)
4327 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4328 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 showparents = [ctx.node() for ctx in repo[None].parents()]
4329 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4330 graphmod.asciiedges)
4330 graphmod.asciiedges)
4331 return 0
4331 return 0
4332
4332
4333 if opts.get('bookmarks'):
4333 if opts.get('bookmarks'):
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4336 other = hg.peer(repo, opts, dest)
4336 other = hg.peer(repo, opts, dest)
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4339 return 0
4339 return 0
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4341 return bookmarks.diff(ui, other, repo)
4341 return bookmarks.diff(ui, other, repo)
4342
4342
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4344 try:
4344 try:
4345 return hg.outgoing(ui, repo, dest, opts)
4345 return hg.outgoing(ui, repo, dest, opts)
4346 finally:
4346 finally:
4347 del repo._subtoppath
4347 del repo._subtoppath
4348
4348
4349 @command('parents',
4349 @command('parents',
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4351 ] + templateopts,
4351 ] + templateopts,
4352 _('[-r REV] [FILE]'))
4352 _('[-r REV] [FILE]'))
4353 def parents(ui, repo, file_=None, **opts):
4353 def parents(ui, repo, file_=None, **opts):
4354 """show the parents of the working directory or revision
4354 """show the parents of the working directory or revision
4355
4355
4356 Print the working directory's parent revisions. If a revision is
4356 Print the working directory's parent revisions. If a revision is
4357 given via -r/--rev, the parent of that revision will be printed.
4357 given via -r/--rev, the parent of that revision will be printed.
4358 If a file argument is given, the revision in which the file was
4358 If a file argument is given, the revision in which the file was
4359 last changed (before the working directory revision or the
4359 last changed (before the working directory revision or the
4360 argument to --rev if given) is printed.
4360 argument to --rev if given) is printed.
4361
4361
4362 Returns 0 on success.
4362 Returns 0 on success.
4363 """
4363 """
4364
4364
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4366
4366
4367 if file_:
4367 if file_:
4368 m = scmutil.match(ctx, (file_,), opts)
4368 m = scmutil.match(ctx, (file_,), opts)
4369 if m.anypats() or len(m.files()) != 1:
4369 if m.anypats() or len(m.files()) != 1:
4370 raise util.Abort(_('can only specify an explicit filename'))
4370 raise util.Abort(_('can only specify an explicit filename'))
4371 file_ = m.files()[0]
4371 file_ = m.files()[0]
4372 filenodes = []
4372 filenodes = []
4373 for cp in ctx.parents():
4373 for cp in ctx.parents():
4374 if not cp:
4374 if not cp:
4375 continue
4375 continue
4376 try:
4376 try:
4377 filenodes.append(cp.filenode(file_))
4377 filenodes.append(cp.filenode(file_))
4378 except error.LookupError:
4378 except error.LookupError:
4379 pass
4379 pass
4380 if not filenodes:
4380 if not filenodes:
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4382 p = []
4382 p = []
4383 for fn in filenodes:
4383 for fn in filenodes:
4384 fctx = repo.filectx(file_, fileid=fn)
4384 fctx = repo.filectx(file_, fileid=fn)
4385 p.append(fctx.node())
4385 p.append(fctx.node())
4386 else:
4386 else:
4387 p = [cp.node() for cp in ctx.parents()]
4387 p = [cp.node() for cp in ctx.parents()]
4388
4388
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4390 for n in p:
4390 for n in p:
4391 if n != nullid:
4391 if n != nullid:
4392 displayer.show(repo[n])
4392 displayer.show(repo[n])
4393 displayer.close()
4393 displayer.close()
4394
4394
4395 @command('paths', [], _('[NAME]'))
4395 @command('paths', [], _('[NAME]'))
4396 def paths(ui, repo, search=None):
4396 def paths(ui, repo, search=None):
4397 """show aliases for remote repositories
4397 """show aliases for remote repositories
4398
4398
4399 Show definition of symbolic path name NAME. If no name is given,
4399 Show definition of symbolic path name NAME. If no name is given,
4400 show definition of all available names.
4400 show definition of all available names.
4401
4401
4402 Option -q/--quiet suppresses all output when searching for NAME
4402 Option -q/--quiet suppresses all output when searching for NAME
4403 and shows only the path names when listing all definitions.
4403 and shows only the path names when listing all definitions.
4404
4404
4405 Path names are defined in the [paths] section of your
4405 Path names are defined in the [paths] section of your
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4407 repository, ``.hg/hgrc`` is used, too.
4407 repository, ``.hg/hgrc`` is used, too.
4408
4408
4409 The path names ``default`` and ``default-push`` have a special
4409 The path names ``default`` and ``default-push`` have a special
4410 meaning. When performing a push or pull operation, they are used
4410 meaning. When performing a push or pull operation, they are used
4411 as fallbacks if no location is specified on the command-line.
4411 as fallbacks if no location is specified on the command-line.
4412 When ``default-push`` is set, it will be used for push and
4412 When ``default-push`` is set, it will be used for push and
4413 ``default`` will be used for pull; otherwise ``default`` is used
4413 ``default`` will be used for pull; otherwise ``default`` is used
4414 as the fallback for both. When cloning a repository, the clone
4414 as the fallback for both. When cloning a repository, the clone
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4418 :hg:`bundle`) operations.
4418 :hg:`bundle`) operations.
4419
4419
4420 See :hg:`help urls` for more information.
4420 See :hg:`help urls` for more information.
4421
4421
4422 Returns 0 on success.
4422 Returns 0 on success.
4423 """
4423 """
4424 if search:
4424 if search:
4425 for name, path in ui.configitems("paths"):
4425 for name, path in ui.configitems("paths"):
4426 if name == search:
4426 if name == search:
4427 ui.status("%s\n" % util.hidepassword(path))
4427 ui.status("%s\n" % util.hidepassword(path))
4428 return
4428 return
4429 if not ui.quiet:
4429 if not ui.quiet:
4430 ui.warn(_("not found!\n"))
4430 ui.warn(_("not found!\n"))
4431 return 1
4431 return 1
4432 else:
4432 else:
4433 for name, path in ui.configitems("paths"):
4433 for name, path in ui.configitems("paths"):
4434 if ui.quiet:
4434 if ui.quiet:
4435 ui.write("%s\n" % name)
4435 ui.write("%s\n" % name)
4436 else:
4436 else:
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4438
4438
4439 @command('phase',
4439 @command('phase',
4440 [('p', 'public', False, _('set changeset phase to public')),
4440 [('p', 'public', False, _('set changeset phase to public')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4445 ],
4445 ],
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4447 def phase(ui, repo, *revs, **opts):
4447 def phase(ui, repo, *revs, **opts):
4448 """set or show the current phase name
4448 """set or show the current phase name
4449
4449
4450 With no argument, show the phase name of specified revisions.
4450 With no argument, show the phase name of specified revisions.
4451
4451
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4453 phase value of the specified revisions.
4453 phase value of the specified revisions.
4454
4454
4455 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4456 lower phase to an higher phase. Phases are ordered as follows::
4456 lower phase to an higher phase. Phases are ordered as follows::
4457
4457
4458 public < draft < secret
4458 public < draft < secret
4459
4459
4460 Return 0 on success, 1 if no phases were changed or some could not
4460 Return 0 on success, 1 if no phases were changed or some could not
4461 be changed.
4461 be changed.
4462 """
4462 """
4463 # search for a unique phase argument
4463 # search for a unique phase argument
4464 targetphase = None
4464 targetphase = None
4465 for idx, name in enumerate(phases.phasenames):
4465 for idx, name in enumerate(phases.phasenames):
4466 if opts[name]:
4466 if opts[name]:
4467 if targetphase is not None:
4467 if targetphase is not None:
4468 raise util.Abort(_('only one phase can be specified'))
4468 raise util.Abort(_('only one phase can be specified'))
4469 targetphase = idx
4469 targetphase = idx
4470
4470
4471 # look for specified revision
4471 # look for specified revision
4472 revs = list(revs)
4472 revs = list(revs)
4473 revs.extend(opts['rev'])
4473 revs.extend(opts['rev'])
4474 if not revs:
4474 if not revs:
4475 raise util.Abort(_('no revisions specified'))
4475 raise util.Abort(_('no revisions specified'))
4476
4476
4477 revs = scmutil.revrange(repo, revs)
4477 revs = scmutil.revrange(repo, revs)
4478
4478
4479 lock = None
4479 lock = None
4480 ret = 0
4480 ret = 0
4481 if targetphase is None:
4481 if targetphase is None:
4482 # display
4482 # display
4483 for r in revs:
4483 for r in revs:
4484 ctx = repo[r]
4484 ctx = repo[r]
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4486 else:
4486 else:
4487 lock = repo.lock()
4487 lock = repo.lock()
4488 try:
4488 try:
4489 # set phase
4489 # set phase
4490 if not revs:
4490 if not revs:
4491 raise util.Abort(_('empty revision set'))
4491 raise util.Abort(_('empty revision set'))
4492 nodes = [repo[r].node() for r in revs]
4492 nodes = [repo[r].node() for r in revs]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4494 phases.advanceboundary(repo, targetphase, nodes)
4494 phases.advanceboundary(repo, targetphase, nodes)
4495 if opts['force']:
4495 if opts['force']:
4496 phases.retractboundary(repo, targetphase, nodes)
4496 phases.retractboundary(repo, targetphase, nodes)
4497 finally:
4497 finally:
4498 lock.release()
4498 lock.release()
4499 # moving revision from public to draft may hide them
4499 # moving revision from public to draft may hide them
4500 # We have to check result on an unfiltered repository
4500 # We have to check result on an unfiltered repository
4501 unfi = repo.unfiltered()
4501 unfi = repo.unfiltered()
4502 newdata = repo._phasecache.getphaserevs(unfi)
4502 newdata = repo._phasecache.getphaserevs(unfi)
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4504 cl = unfi.changelog
4504 cl = unfi.changelog
4505 rejected = [n for n in nodes
4505 rejected = [n for n in nodes
4506 if newdata[cl.rev(n)] < targetphase]
4506 if newdata[cl.rev(n)] < targetphase]
4507 if rejected:
4507 if rejected:
4508 ui.warn(_('cannot move %i changesets to a more permissive '
4508 ui.warn(_('cannot move %i changesets to a more permissive '
4509 'phase, use --force\n') % len(rejected))
4509 'phase, use --force\n') % len(rejected))
4510 ret = 1
4510 ret = 1
4511 if changes:
4511 if changes:
4512 msg = _('phase changed for %i changesets\n') % changes
4512 msg = _('phase changed for %i changesets\n') % changes
4513 if ret:
4513 if ret:
4514 ui.status(msg)
4514 ui.status(msg)
4515 else:
4515 else:
4516 ui.note(msg)
4516 ui.note(msg)
4517 else:
4517 else:
4518 ui.warn(_('no phases changed\n'))
4518 ui.warn(_('no phases changed\n'))
4519 ret = 1
4519 ret = 1
4520 return ret
4520 return ret
4521
4521
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4523 if modheads == 0:
4523 if modheads == 0:
4524 return
4524 return
4525 if optupdate:
4525 if optupdate:
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4527 try:
4527 try:
4528 ret = hg.update(repo, checkout)
4528 ret = hg.update(repo, checkout)
4529 except util.Abort, inst:
4529 except util.Abort, inst:
4530 ui.warn(_("not updating: %s\n") % str(inst))
4530 ui.warn(_("not updating: %s\n") % str(inst))
4531 if inst.hint:
4531 if inst.hint:
4532 ui.warn(_("(%s)\n") % inst.hint)
4532 ui.warn(_("(%s)\n") % inst.hint)
4533 return 0
4533 return 0
4534 if not ret and not checkout:
4534 if not ret and not checkout:
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4537 return ret
4537 return ret
4538 if modheads > 1:
4538 if modheads > 1:
4539 currentbranchheads = len(repo.branchheads())
4539 currentbranchheads = len(repo.branchheads())
4540 if currentbranchheads == modheads:
4540 if currentbranchheads == modheads:
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4542 elif currentbranchheads > 1:
4542 elif currentbranchheads > 1:
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4544 "merge)\n"))
4544 "merge)\n"))
4545 else:
4545 else:
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4547 else:
4547 else:
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4549
4549
4550 @command('^pull',
4550 @command('^pull',
4551 [('u', 'update', None,
4551 [('u', 'update', None,
4552 _('update to new branch head if changesets were pulled')),
4552 _('update to new branch head if changesets were pulled')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4557 _('BRANCH')),
4557 _('BRANCH')),
4558 ] + remoteopts,
4558 ] + remoteopts,
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4560 def pull(ui, repo, source="default", **opts):
4560 def pull(ui, repo, source="default", **opts):
4561 """pull changes from the specified source
4561 """pull changes from the specified source
4562
4562
4563 Pull changes from a remote repository to a local one.
4563 Pull changes from a remote repository to a local one.
4564
4564
4565 This finds all changes from the repository at the specified path
4565 This finds all changes from the repository at the specified path
4566 or URL and adds them to a local repository (the current one unless
4566 or URL and adds them to a local repository (the current one unless
4567 -R is specified). By default, this does not update the copy of the
4567 -R is specified). By default, this does not update the copy of the
4568 project in the working directory.
4568 project in the working directory.
4569
4569
4570 Use :hg:`incoming` if you want to see what would have been added
4570 Use :hg:`incoming` if you want to see what would have been added
4571 by a pull at the time you issued this command. If you then decide
4571 by a pull at the time you issued this command. If you then decide
4572 to add those changes to the repository, you should use :hg:`pull
4572 to add those changes to the repository, you should use :hg:`pull
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4574
4574
4575 If SOURCE is omitted, the 'default' path will be used.
4575 If SOURCE is omitted, the 'default' path will be used.
4576 See :hg:`help urls` for more information.
4576 See :hg:`help urls` for more information.
4577
4577
4578 Returns 0 on success, 1 if an update had unresolved files.
4578 Returns 0 on success, 1 if an update had unresolved files.
4579 """
4579 """
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4581 other = hg.peer(repo, opts, source)
4581 other = hg.peer(repo, opts, source)
4582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4583 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4583 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4584
4584
4585 remotebookmarks = other.listkeys('bookmarks')
4585 remotebookmarks = other.listkeys('bookmarks')
4586
4586
4587 if opts.get('bookmark'):
4587 if opts.get('bookmark'):
4588 if not revs:
4588 if not revs:
4589 revs = []
4589 revs = []
4590 for b in opts['bookmark']:
4590 for b in opts['bookmark']:
4591 if b not in remotebookmarks:
4591 if b not in remotebookmarks:
4592 raise util.Abort(_('remote bookmark %s not found!') % b)
4592 raise util.Abort(_('remote bookmark %s not found!') % b)
4593 revs.append(remotebookmarks[b])
4593 revs.append(remotebookmarks[b])
4594
4594
4595 if revs:
4595 if revs:
4596 try:
4596 try:
4597 revs = [other.lookup(rev) for rev in revs]
4597 revs = [other.lookup(rev) for rev in revs]
4598 except error.CapabilityError:
4598 except error.CapabilityError:
4599 err = _("other repository doesn't support revision lookup, "
4599 err = _("other repository doesn't support revision lookup, "
4600 "so a rev cannot be specified.")
4600 "so a rev cannot be specified.")
4601 raise util.Abort(err)
4601 raise util.Abort(err)
4602
4602
4603 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4603 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4604 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4604 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4605 if checkout:
4605 if checkout:
4606 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4606 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4607 repo._subtoppath = source
4607 repo._subtoppath = source
4608 try:
4608 try:
4609 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4609 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4610
4610
4611 finally:
4611 finally:
4612 del repo._subtoppath
4612 del repo._subtoppath
4613
4613
4614 # update specified bookmarks
4614 # update specified bookmarks
4615 if opts.get('bookmark'):
4615 if opts.get('bookmark'):
4616 marks = repo._bookmarks
4616 marks = repo._bookmarks
4617 for b in opts['bookmark']:
4617 for b in opts['bookmark']:
4618 # explicit pull overrides local bookmark if any
4618 # explicit pull overrides local bookmark if any
4619 ui.status(_("importing bookmark %s\n") % b)
4619 ui.status(_("importing bookmark %s\n") % b)
4620 marks[b] = repo[remotebookmarks[b]].node()
4620 marks[b] = repo[remotebookmarks[b]].node()
4621 marks.write()
4621 marks.write()
4622
4622
4623 return ret
4623 return ret
4624
4624
4625 @command('^push',
4625 @command('^push',
4626 [('f', 'force', None, _('force push')),
4626 [('f', 'force', None, _('force push')),
4627 ('r', 'rev', [],
4627 ('r', 'rev', [],
4628 _('a changeset intended to be included in the destination'),
4628 _('a changeset intended to be included in the destination'),
4629 _('REV')),
4629 _('REV')),
4630 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4630 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4631 ('b', 'branch', [],
4631 ('b', 'branch', [],
4632 _('a specific branch you would like to push'), _('BRANCH')),
4632 _('a specific branch you would like to push'), _('BRANCH')),
4633 ('', 'new-branch', False, _('allow pushing a new branch')),
4633 ('', 'new-branch', False, _('allow pushing a new branch')),
4634 ] + remoteopts,
4634 ] + remoteopts,
4635 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4635 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4636 def push(ui, repo, dest=None, **opts):
4636 def push(ui, repo, dest=None, **opts):
4637 """push changes to the specified destination
4637 """push changes to the specified destination
4638
4638
4639 Push changesets from the local repository to the specified
4639 Push changesets from the local repository to the specified
4640 destination.
4640 destination.
4641
4641
4642 This operation is symmetrical to pull: it is identical to a pull
4642 This operation is symmetrical to pull: it is identical to a pull
4643 in the destination repository from the current one.
4643 in the destination repository from the current one.
4644
4644
4645 By default, push will not allow creation of new heads at the
4645 By default, push will not allow creation of new heads at the
4646 destination, since multiple heads would make it unclear which head
4646 destination, since multiple heads would make it unclear which head
4647 to use. In this situation, it is recommended to pull and merge
4647 to use. In this situation, it is recommended to pull and merge
4648 before pushing.
4648 before pushing.
4649
4649
4650 Use --new-branch if you want to allow push to create a new named
4650 Use --new-branch if you want to allow push to create a new named
4651 branch that is not present at the destination. This allows you to
4651 branch that is not present at the destination. This allows you to
4652 only create a new branch without forcing other changes.
4652 only create a new branch without forcing other changes.
4653
4653
4654 Use -f/--force to override the default behavior and push all
4654 Use -f/--force to override the default behavior and push all
4655 changesets on all branches.
4655 changesets on all branches.
4656
4656
4657 If -r/--rev is used, the specified revision and all its ancestors
4657 If -r/--rev is used, the specified revision and all its ancestors
4658 will be pushed to the remote repository.
4658 will be pushed to the remote repository.
4659
4659
4660 If -B/--bookmark is used, the specified bookmarked revision, its
4660 If -B/--bookmark is used, the specified bookmarked revision, its
4661 ancestors, and the bookmark will be pushed to the remote
4661 ancestors, and the bookmark will be pushed to the remote
4662 repository.
4662 repository.
4663
4663
4664 Please see :hg:`help urls` for important details about ``ssh://``
4664 Please see :hg:`help urls` for important details about ``ssh://``
4665 URLs. If DESTINATION is omitted, a default path will be used.
4665 URLs. If DESTINATION is omitted, a default path will be used.
4666
4666
4667 Returns 0 if push was successful, 1 if nothing to push.
4667 Returns 0 if push was successful, 1 if nothing to push.
4668 """
4668 """
4669
4669
4670 if opts.get('bookmark'):
4670 if opts.get('bookmark'):
4671 for b in opts['bookmark']:
4671 for b in opts['bookmark']:
4672 # translate -B options to -r so changesets get pushed
4672 # translate -B options to -r so changesets get pushed
4673 if b in repo._bookmarks:
4673 if b in repo._bookmarks:
4674 opts.setdefault('rev', []).append(b)
4674 opts.setdefault('rev', []).append(b)
4675 else:
4675 else:
4676 # if we try to push a deleted bookmark, translate it to null
4676 # if we try to push a deleted bookmark, translate it to null
4677 # this lets simultaneous -r, -b options continue working
4677 # this lets simultaneous -r, -b options continue working
4678 opts.setdefault('rev', []).append("null")
4678 opts.setdefault('rev', []).append("null")
4679
4679
4680 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4680 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4681 dest, branches = hg.parseurl(dest, opts.get('branch'))
4681 dest, branches = hg.parseurl(dest, opts.get('branch'))
4682 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4682 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4683 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4683 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4684 other = hg.peer(repo, opts, dest)
4684 other = hg.peer(repo, opts, dest)
4685 if revs:
4685 if revs:
4686 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4686 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4687
4687
4688 repo._subtoppath = dest
4688 repo._subtoppath = dest
4689 try:
4689 try:
4690 # push subrepos depth-first for coherent ordering
4690 # push subrepos depth-first for coherent ordering
4691 c = repo['']
4691 c = repo['']
4692 subs = c.substate # only repos that are committed
4692 subs = c.substate # only repos that are committed
4693 for s in sorted(subs):
4693 for s in sorted(subs):
4694 if c.sub(s).push(opts) == 0:
4694 if c.sub(s).push(opts) == 0:
4695 return False
4695 return False
4696 finally:
4696 finally:
4697 del repo._subtoppath
4697 del repo._subtoppath
4698 result = repo.push(other, opts.get('force'), revs=revs,
4698 result = repo.push(other, opts.get('force'), revs=revs,
4699 newbranch=opts.get('new_branch'))
4699 newbranch=opts.get('new_branch'))
4700
4700
4701 result = not result
4701 result = not result
4702
4702
4703 if opts.get('bookmark'):
4703 if opts.get('bookmark'):
4704 rb = other.listkeys('bookmarks')
4704 rb = other.listkeys('bookmarks')
4705 for b in opts['bookmark']:
4705 for b in opts['bookmark']:
4706 # explicit push overrides remote bookmark if any
4706 # explicit push overrides remote bookmark if any
4707 if b in repo._bookmarks:
4707 if b in repo._bookmarks:
4708 ui.status(_("exporting bookmark %s\n") % b)
4708 ui.status(_("exporting bookmark %s\n") % b)
4709 new = repo[b].hex()
4709 new = repo[b].hex()
4710 elif b in rb:
4710 elif b in rb:
4711 ui.status(_("deleting remote bookmark %s\n") % b)
4711 ui.status(_("deleting remote bookmark %s\n") % b)
4712 new = '' # delete
4712 new = '' # delete
4713 else:
4713 else:
4714 ui.warn(_('bookmark %s does not exist on the local '
4714 ui.warn(_('bookmark %s does not exist on the local '
4715 'or remote repository!\n') % b)
4715 'or remote repository!\n') % b)
4716 return 2
4716 return 2
4717 old = rb.get(b, '')
4717 old = rb.get(b, '')
4718 r = other.pushkey('bookmarks', b, old, new)
4718 r = other.pushkey('bookmarks', b, old, new)
4719 if not r:
4719 if not r:
4720 ui.warn(_('updating bookmark %s failed!\n') % b)
4720 ui.warn(_('updating bookmark %s failed!\n') % b)
4721 if not result:
4721 if not result:
4722 result = 2
4722 result = 2
4723
4723
4724 return result
4724 return result
4725
4725
4726 @command('recover', [])
4726 @command('recover', [])
4727 def recover(ui, repo):
4727 def recover(ui, repo):
4728 """roll back an interrupted transaction
4728 """roll back an interrupted transaction
4729
4729
4730 Recover from an interrupted commit or pull.
4730 Recover from an interrupted commit or pull.
4731
4731
4732 This command tries to fix the repository status after an
4732 This command tries to fix the repository status after an
4733 interrupted operation. It should only be necessary when Mercurial
4733 interrupted operation. It should only be necessary when Mercurial
4734 suggests it.
4734 suggests it.
4735
4735
4736 Returns 0 if successful, 1 if nothing to recover or verify fails.
4736 Returns 0 if successful, 1 if nothing to recover or verify fails.
4737 """
4737 """
4738 if repo.recover():
4738 if repo.recover():
4739 return hg.verify(repo)
4739 return hg.verify(repo)
4740 return 1
4740 return 1
4741
4741
4742 @command('^remove|rm',
4742 @command('^remove|rm',
4743 [('A', 'after', None, _('record delete for missing files')),
4743 [('A', 'after', None, _('record delete for missing files')),
4744 ('f', 'force', None,
4744 ('f', 'force', None,
4745 _('remove (and delete) file even if added or modified')),
4745 _('remove (and delete) file even if added or modified')),
4746 ] + walkopts,
4746 ] + walkopts,
4747 _('[OPTION]... FILE...'))
4747 _('[OPTION]... FILE...'))
4748 def remove(ui, repo, *pats, **opts):
4748 def remove(ui, repo, *pats, **opts):
4749 """remove the specified files on the next commit
4749 """remove the specified files on the next commit
4750
4750
4751 Schedule the indicated files for removal from the current branch.
4751 Schedule the indicated files for removal from the current branch.
4752
4752
4753 This command schedules the files to be removed at the next commit.
4753 This command schedules the files to be removed at the next commit.
4754 To undo a remove before that, see :hg:`revert`. To undo added
4754 To undo a remove before that, see :hg:`revert`. To undo added
4755 files, see :hg:`forget`.
4755 files, see :hg:`forget`.
4756
4756
4757 .. container:: verbose
4757 .. container:: verbose
4758
4758
4759 -A/--after can be used to remove only files that have already
4759 -A/--after can be used to remove only files that have already
4760 been deleted, -f/--force can be used to force deletion, and -Af
4760 been deleted, -f/--force can be used to force deletion, and -Af
4761 can be used to remove files from the next revision without
4761 can be used to remove files from the next revision without
4762 deleting them from the working directory.
4762 deleting them from the working directory.
4763
4763
4764 The following table details the behavior of remove for different
4764 The following table details the behavior of remove for different
4765 file states (columns) and option combinations (rows). The file
4765 file states (columns) and option combinations (rows). The file
4766 states are Added [A], Clean [C], Modified [M] and Missing [!]
4766 states are Added [A], Clean [C], Modified [M] and Missing [!]
4767 (as reported by :hg:`status`). The actions are Warn, Remove
4767 (as reported by :hg:`status`). The actions are Warn, Remove
4768 (from branch) and Delete (from disk):
4768 (from branch) and Delete (from disk):
4769
4769
4770 ======= == == == ==
4770 ======= == == == ==
4771 A C M !
4771 A C M !
4772 ======= == == == ==
4772 ======= == == == ==
4773 none W RD W R
4773 none W RD W R
4774 -f R RD RD R
4774 -f R RD RD R
4775 -A W W W R
4775 -A W W W R
4776 -Af R R R R
4776 -Af R R R R
4777 ======= == == == ==
4777 ======= == == == ==
4778
4778
4779 Note that remove never deletes files in Added [A] state from the
4779 Note that remove never deletes files in Added [A] state from the
4780 working directory, not even if option --force is specified.
4780 working directory, not even if option --force is specified.
4781
4781
4782 Returns 0 on success, 1 if any warnings encountered.
4782 Returns 0 on success, 1 if any warnings encountered.
4783 """
4783 """
4784
4784
4785 ret = 0
4785 ret = 0
4786 after, force = opts.get('after'), opts.get('force')
4786 after, force = opts.get('after'), opts.get('force')
4787 if not pats and not after:
4787 if not pats and not after:
4788 raise util.Abort(_('no files specified'))
4788 raise util.Abort(_('no files specified'))
4789
4789
4790 m = scmutil.match(repo[None], pats, opts)
4790 m = scmutil.match(repo[None], pats, opts)
4791 s = repo.status(match=m, clean=True)
4791 s = repo.status(match=m, clean=True)
4792 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4792 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4793
4793
4794 # warn about failure to delete explicit files/dirs
4794 # warn about failure to delete explicit files/dirs
4795 wctx = repo[None]
4795 wctx = repo[None]
4796 for f in m.files():
4796 for f in m.files():
4797 if f in repo.dirstate or f in wctx.dirs():
4797 if f in repo.dirstate or f in wctx.dirs():
4798 continue
4798 continue
4799 if os.path.exists(m.rel(f)):
4799 if os.path.exists(m.rel(f)):
4800 if os.path.isdir(m.rel(f)):
4800 if os.path.isdir(m.rel(f)):
4801 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4801 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4802 else:
4802 else:
4803 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4803 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4804 # missing files will generate a warning elsewhere
4804 # missing files will generate a warning elsewhere
4805 ret = 1
4805 ret = 1
4806
4806
4807 if force:
4807 if force:
4808 list = modified + deleted + clean + added
4808 list = modified + deleted + clean + added
4809 elif after:
4809 elif after:
4810 list = deleted
4810 list = deleted
4811 for f in modified + added + clean:
4811 for f in modified + added + clean:
4812 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4812 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4813 ret = 1
4813 ret = 1
4814 else:
4814 else:
4815 list = deleted + clean
4815 list = deleted + clean
4816 for f in modified:
4816 for f in modified:
4817 ui.warn(_('not removing %s: file is modified (use -f'
4817 ui.warn(_('not removing %s: file is modified (use -f'
4818 ' to force removal)\n') % m.rel(f))
4818 ' to force removal)\n') % m.rel(f))
4819 ret = 1
4819 ret = 1
4820 for f in added:
4820 for f in added:
4821 ui.warn(_('not removing %s: file has been marked for add'
4821 ui.warn(_('not removing %s: file has been marked for add'
4822 ' (use forget to undo)\n') % m.rel(f))
4822 ' (use forget to undo)\n') % m.rel(f))
4823 ret = 1
4823 ret = 1
4824
4824
4825 for f in sorted(list):
4825 for f in sorted(list):
4826 if ui.verbose or not m.exact(f):
4826 if ui.verbose or not m.exact(f):
4827 ui.status(_('removing %s\n') % m.rel(f))
4827 ui.status(_('removing %s\n') % m.rel(f))
4828
4828
4829 wlock = repo.wlock()
4829 wlock = repo.wlock()
4830 try:
4830 try:
4831 if not after:
4831 if not after:
4832 for f in list:
4832 for f in list:
4833 if f in added:
4833 if f in added:
4834 continue # we never unlink added files on remove
4834 continue # we never unlink added files on remove
4835 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4835 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4836 repo[None].forget(list)
4836 repo[None].forget(list)
4837 finally:
4837 finally:
4838 wlock.release()
4838 wlock.release()
4839
4839
4840 return ret
4840 return ret
4841
4841
4842 @command('rename|move|mv',
4842 @command('rename|move|mv',
4843 [('A', 'after', None, _('record a rename that has already occurred')),
4843 [('A', 'after', None, _('record a rename that has already occurred')),
4844 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4844 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4845 ] + walkopts + dryrunopts,
4845 ] + walkopts + dryrunopts,
4846 _('[OPTION]... SOURCE... DEST'))
4846 _('[OPTION]... SOURCE... DEST'))
4847 def rename(ui, repo, *pats, **opts):
4847 def rename(ui, repo, *pats, **opts):
4848 """rename files; equivalent of copy + remove
4848 """rename files; equivalent of copy + remove
4849
4849
4850 Mark dest as copies of sources; mark sources for deletion. If dest
4850 Mark dest as copies of sources; mark sources for deletion. If dest
4851 is a directory, copies are put in that directory. If dest is a
4851 is a directory, copies are put in that directory. If dest is a
4852 file, there can only be one source.
4852 file, there can only be one source.
4853
4853
4854 By default, this command copies the contents of files as they
4854 By default, this command copies the contents of files as they
4855 exist in the working directory. If invoked with -A/--after, the
4855 exist in the working directory. If invoked with -A/--after, the
4856 operation is recorded, but no copying is performed.
4856 operation is recorded, but no copying is performed.
4857
4857
4858 This command takes effect at the next commit. To undo a rename
4858 This command takes effect at the next commit. To undo a rename
4859 before that, see :hg:`revert`.
4859 before that, see :hg:`revert`.
4860
4860
4861 Returns 0 on success, 1 if errors are encountered.
4861 Returns 0 on success, 1 if errors are encountered.
4862 """
4862 """
4863 wlock = repo.wlock(False)
4863 wlock = repo.wlock(False)
4864 try:
4864 try:
4865 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4865 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4866 finally:
4866 finally:
4867 wlock.release()
4867 wlock.release()
4868
4868
4869 @command('resolve',
4869 @command('resolve',
4870 [('a', 'all', None, _('select all unresolved files')),
4870 [('a', 'all', None, _('select all unresolved files')),
4871 ('l', 'list', None, _('list state of files needing merge')),
4871 ('l', 'list', None, _('list state of files needing merge')),
4872 ('m', 'mark', None, _('mark files as resolved')),
4872 ('m', 'mark', None, _('mark files as resolved')),
4873 ('u', 'unmark', None, _('mark files as unresolved')),
4873 ('u', 'unmark', None, _('mark files as unresolved')),
4874 ('n', 'no-status', None, _('hide status prefix'))]
4874 ('n', 'no-status', None, _('hide status prefix'))]
4875 + mergetoolopts + walkopts,
4875 + mergetoolopts + walkopts,
4876 _('[OPTION]... [FILE]...'))
4876 _('[OPTION]... [FILE]...'))
4877 def resolve(ui, repo, *pats, **opts):
4877 def resolve(ui, repo, *pats, **opts):
4878 """redo merges or set/view the merge status of files
4878 """redo merges or set/view the merge status of files
4879
4879
4880 Merges with unresolved conflicts are often the result of
4880 Merges with unresolved conflicts are often the result of
4881 non-interactive merging using the ``internal:merge`` configuration
4881 non-interactive merging using the ``internal:merge`` configuration
4882 setting, or a command-line merge tool like ``diff3``. The resolve
4882 setting, or a command-line merge tool like ``diff3``. The resolve
4883 command is used to manage the files involved in a merge, after
4883 command is used to manage the files involved in a merge, after
4884 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4884 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4885 working directory must have two parents). See :hg:`help
4885 working directory must have two parents). See :hg:`help
4886 merge-tools` for information on configuring merge tools.
4886 merge-tools` for information on configuring merge tools.
4887
4887
4888 The resolve command can be used in the following ways:
4888 The resolve command can be used in the following ways:
4889
4889
4890 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4890 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4891 files, discarding any previous merge attempts. Re-merging is not
4891 files, discarding any previous merge attempts. Re-merging is not
4892 performed for files already marked as resolved. Use ``--all/-a``
4892 performed for files already marked as resolved. Use ``--all/-a``
4893 to select all unresolved files. ``--tool`` can be used to specify
4893 to select all unresolved files. ``--tool`` can be used to specify
4894 the merge tool used for the given files. It overrides the HGMERGE
4894 the merge tool used for the given files. It overrides the HGMERGE
4895 environment variable and your configuration files. Previous file
4895 environment variable and your configuration files. Previous file
4896 contents are saved with a ``.orig`` suffix.
4896 contents are saved with a ``.orig`` suffix.
4897
4897
4898 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4898 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4899 (e.g. after having manually fixed-up the files). The default is
4899 (e.g. after having manually fixed-up the files). The default is
4900 to mark all unresolved files.
4900 to mark all unresolved files.
4901
4901
4902 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4902 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4903 default is to mark all resolved files.
4903 default is to mark all resolved files.
4904
4904
4905 - :hg:`resolve -l`: list files which had or still have conflicts.
4905 - :hg:`resolve -l`: list files which had or still have conflicts.
4906 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4906 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4907
4907
4908 Note that Mercurial will not let you commit files with unresolved
4908 Note that Mercurial will not let you commit files with unresolved
4909 merge conflicts. You must use :hg:`resolve -m ...` before you can
4909 merge conflicts. You must use :hg:`resolve -m ...` before you can
4910 commit after a conflicting merge.
4910 commit after a conflicting merge.
4911
4911
4912 Returns 0 on success, 1 if any files fail a resolve attempt.
4912 Returns 0 on success, 1 if any files fail a resolve attempt.
4913 """
4913 """
4914
4914
4915 all, mark, unmark, show, nostatus = \
4915 all, mark, unmark, show, nostatus = \
4916 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4916 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4917
4917
4918 if (show and (mark or unmark)) or (mark and unmark):
4918 if (show and (mark or unmark)) or (mark and unmark):
4919 raise util.Abort(_("too many options specified"))
4919 raise util.Abort(_("too many options specified"))
4920 if pats and all:
4920 if pats and all:
4921 raise util.Abort(_("can't specify --all and patterns"))
4921 raise util.Abort(_("can't specify --all and patterns"))
4922 if not (all or pats or show or mark or unmark):
4922 if not (all or pats or show or mark or unmark):
4923 raise util.Abort(_('no files or directories specified; '
4923 raise util.Abort(_('no files or directories specified; '
4924 'use --all to remerge all files'))
4924 'use --all to remerge all files'))
4925
4925
4926 ms = mergemod.mergestate(repo)
4926 ms = mergemod.mergestate(repo)
4927 m = scmutil.match(repo[None], pats, opts)
4927 m = scmutil.match(repo[None], pats, opts)
4928 ret = 0
4928 ret = 0
4929
4929
4930 for f in ms:
4930 for f in ms:
4931 if m(f):
4931 if m(f):
4932 if show:
4932 if show:
4933 if nostatus:
4933 if nostatus:
4934 ui.write("%s\n" % f)
4934 ui.write("%s\n" % f)
4935 else:
4935 else:
4936 ui.write("%s %s\n" % (ms[f].upper(), f),
4936 ui.write("%s %s\n" % (ms[f].upper(), f),
4937 label='resolve.' +
4937 label='resolve.' +
4938 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4938 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4939 elif mark:
4939 elif mark:
4940 ms.mark(f, "r")
4940 ms.mark(f, "r")
4941 elif unmark:
4941 elif unmark:
4942 ms.mark(f, "u")
4942 ms.mark(f, "u")
4943 else:
4943 else:
4944 wctx = repo[None]
4944 wctx = repo[None]
4945 mctx = wctx.parents()[-1]
4945 mctx = wctx.parents()[-1]
4946
4946
4947 # backup pre-resolve (merge uses .orig for its own purposes)
4947 # backup pre-resolve (merge uses .orig for its own purposes)
4948 a = repo.wjoin(f)
4948 a = repo.wjoin(f)
4949 util.copyfile(a, a + ".resolve")
4949 util.copyfile(a, a + ".resolve")
4950
4950
4951 try:
4951 try:
4952 # resolve file
4952 # resolve file
4953 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4953 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4954 if ms.resolve(f, wctx, mctx):
4954 if ms.resolve(f, wctx, mctx):
4955 ret = 1
4955 ret = 1
4956 finally:
4956 finally:
4957 ui.setconfig('ui', 'forcemerge', '')
4957 ui.setconfig('ui', 'forcemerge', '')
4958 ms.commit()
4958 ms.commit()
4959
4959
4960 # replace filemerge's .orig file with our resolve file
4960 # replace filemerge's .orig file with our resolve file
4961 util.rename(a + ".resolve", a + ".orig")
4961 util.rename(a + ".resolve", a + ".orig")
4962
4962
4963 ms.commit()
4963 ms.commit()
4964 return ret
4964 return ret
4965
4965
4966 @command('revert',
4966 @command('revert',
4967 [('a', 'all', None, _('revert all changes when no arguments given')),
4967 [('a', 'all', None, _('revert all changes when no arguments given')),
4968 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4968 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4969 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4969 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4970 ('C', 'no-backup', None, _('do not save backup copies of files')),
4970 ('C', 'no-backup', None, _('do not save backup copies of files')),
4971 ] + walkopts + dryrunopts,
4971 ] + walkopts + dryrunopts,
4972 _('[OPTION]... [-r REV] [NAME]...'))
4972 _('[OPTION]... [-r REV] [NAME]...'))
4973 def revert(ui, repo, *pats, **opts):
4973 def revert(ui, repo, *pats, **opts):
4974 """restore files to their checkout state
4974 """restore files to their checkout state
4975
4975
4976 .. note::
4976 .. note::
4977 To check out earlier revisions, you should use :hg:`update REV`.
4977 To check out earlier revisions, you should use :hg:`update REV`.
4978 To cancel an uncommitted merge (and lose your changes),
4978 To cancel an uncommitted merge (and lose your changes),
4979 use :hg:`update --clean .`.
4979 use :hg:`update --clean .`.
4980
4980
4981 With no revision specified, revert the specified files or directories
4981 With no revision specified, revert the specified files or directories
4982 to the contents they had in the parent of the working directory.
4982 to the contents they had in the parent of the working directory.
4983 This restores the contents of files to an unmodified
4983 This restores the contents of files to an unmodified
4984 state and unschedules adds, removes, copies, and renames. If the
4984 state and unschedules adds, removes, copies, and renames. If the
4985 working directory has two parents, you must explicitly specify a
4985 working directory has two parents, you must explicitly specify a
4986 revision.
4986 revision.
4987
4987
4988 Using the -r/--rev or -d/--date options, revert the given files or
4988 Using the -r/--rev or -d/--date options, revert the given files or
4989 directories to their states as of a specific revision. Because
4989 directories to their states as of a specific revision. Because
4990 revert does not change the working directory parents, this will
4990 revert does not change the working directory parents, this will
4991 cause these files to appear modified. This can be helpful to "back
4991 cause these files to appear modified. This can be helpful to "back
4992 out" some or all of an earlier change. See :hg:`backout` for a
4992 out" some or all of an earlier change. See :hg:`backout` for a
4993 related method.
4993 related method.
4994
4994
4995 Modified files are saved with a .orig suffix before reverting.
4995 Modified files are saved with a .orig suffix before reverting.
4996 To disable these backups, use --no-backup.
4996 To disable these backups, use --no-backup.
4997
4997
4998 See :hg:`help dates` for a list of formats valid for -d/--date.
4998 See :hg:`help dates` for a list of formats valid for -d/--date.
4999
4999
5000 Returns 0 on success.
5000 Returns 0 on success.
5001 """
5001 """
5002
5002
5003 if opts.get("date"):
5003 if opts.get("date"):
5004 if opts.get("rev"):
5004 if opts.get("rev"):
5005 raise util.Abort(_("you can't specify a revision and a date"))
5005 raise util.Abort(_("you can't specify a revision and a date"))
5006 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5006 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5007
5007
5008 parent, p2 = repo.dirstate.parents()
5008 parent, p2 = repo.dirstate.parents()
5009 if not opts.get('rev') and p2 != nullid:
5009 if not opts.get('rev') and p2 != nullid:
5010 # revert after merge is a trap for new users (issue2915)
5010 # revert after merge is a trap for new users (issue2915)
5011 raise util.Abort(_('uncommitted merge with no revision specified'),
5011 raise util.Abort(_('uncommitted merge with no revision specified'),
5012 hint=_('use "hg update" or see "hg help revert"'))
5012 hint=_('use "hg update" or see "hg help revert"'))
5013
5013
5014 ctx = scmutil.revsingle(repo, opts.get('rev'))
5014 ctx = scmutil.revsingle(repo, opts.get('rev'))
5015
5015
5016 if not pats and not opts.get('all'):
5016 if not pats and not opts.get('all'):
5017 msg = _("no files or directories specified")
5017 msg = _("no files or directories specified")
5018 if p2 != nullid:
5018 if p2 != nullid:
5019 hint = _("uncommitted merge, use --all to discard all changes,"
5019 hint = _("uncommitted merge, use --all to discard all changes,"
5020 " or 'hg update -C .' to abort the merge")
5020 " or 'hg update -C .' to abort the merge")
5021 raise util.Abort(msg, hint=hint)
5021 raise util.Abort(msg, hint=hint)
5022 dirty = util.any(repo.status())
5022 dirty = util.any(repo.status())
5023 node = ctx.node()
5023 node = ctx.node()
5024 if node != parent:
5024 if node != parent:
5025 if dirty:
5025 if dirty:
5026 hint = _("uncommitted changes, use --all to discard all"
5026 hint = _("uncommitted changes, use --all to discard all"
5027 " changes, or 'hg update %s' to update") % ctx.rev()
5027 " changes, or 'hg update %s' to update") % ctx.rev()
5028 else:
5028 else:
5029 hint = _("use --all to revert all files,"
5029 hint = _("use --all to revert all files,"
5030 " or 'hg update %s' to update") % ctx.rev()
5030 " or 'hg update %s' to update") % ctx.rev()
5031 elif dirty:
5031 elif dirty:
5032 hint = _("uncommitted changes, use --all to discard all changes")
5032 hint = _("uncommitted changes, use --all to discard all changes")
5033 else:
5033 else:
5034 hint = _("use --all to revert all files")
5034 hint = _("use --all to revert all files")
5035 raise util.Abort(msg, hint=hint)
5035 raise util.Abort(msg, hint=hint)
5036
5036
5037 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5037 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5038
5038
5039 @command('rollback', dryrunopts +
5039 @command('rollback', dryrunopts +
5040 [('f', 'force', False, _('ignore safety measures'))])
5040 [('f', 'force', False, _('ignore safety measures'))])
5041 def rollback(ui, repo, **opts):
5041 def rollback(ui, repo, **opts):
5042 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5042 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5043
5043
5044 Please use :hg:`commit --amend` instead of rollback to correct
5044 Please use :hg:`commit --amend` instead of rollback to correct
5045 mistakes in the last commit.
5045 mistakes in the last commit.
5046
5046
5047 This command should be used with care. There is only one level of
5047 This command should be used with care. There is only one level of
5048 rollback, and there is no way to undo a rollback. It will also
5048 rollback, and there is no way to undo a rollback. It will also
5049 restore the dirstate at the time of the last transaction, losing
5049 restore the dirstate at the time of the last transaction, losing
5050 any dirstate changes since that time. This command does not alter
5050 any dirstate changes since that time. This command does not alter
5051 the working directory.
5051 the working directory.
5052
5052
5053 Transactions are used to encapsulate the effects of all commands
5053 Transactions are used to encapsulate the effects of all commands
5054 that create new changesets or propagate existing changesets into a
5054 that create new changesets or propagate existing changesets into a
5055 repository.
5055 repository.
5056
5056
5057 .. container:: verbose
5057 .. container:: verbose
5058
5058
5059 For example, the following commands are transactional, and their
5059 For example, the following commands are transactional, and their
5060 effects can be rolled back:
5060 effects can be rolled back:
5061
5061
5062 - commit
5062 - commit
5063 - import
5063 - import
5064 - pull
5064 - pull
5065 - push (with this repository as the destination)
5065 - push (with this repository as the destination)
5066 - unbundle
5066 - unbundle
5067
5067
5068 To avoid permanent data loss, rollback will refuse to rollback a
5068 To avoid permanent data loss, rollback will refuse to rollback a
5069 commit transaction if it isn't checked out. Use --force to
5069 commit transaction if it isn't checked out. Use --force to
5070 override this protection.
5070 override this protection.
5071
5071
5072 This command is not intended for use on public repositories. Once
5072 This command is not intended for use on public repositories. Once
5073 changes are visible for pull by other users, rolling a transaction
5073 changes are visible for pull by other users, rolling a transaction
5074 back locally is ineffective (someone else may already have pulled
5074 back locally is ineffective (someone else may already have pulled
5075 the changes). Furthermore, a race is possible with readers of the
5075 the changes). Furthermore, a race is possible with readers of the
5076 repository; for example an in-progress pull from the repository
5076 repository; for example an in-progress pull from the repository
5077 may fail if a rollback is performed.
5077 may fail if a rollback is performed.
5078
5078
5079 Returns 0 on success, 1 if no rollback data is available.
5079 Returns 0 on success, 1 if no rollback data is available.
5080 """
5080 """
5081 return repo.rollback(dryrun=opts.get('dry_run'),
5081 return repo.rollback(dryrun=opts.get('dry_run'),
5082 force=opts.get('force'))
5082 force=opts.get('force'))
5083
5083
5084 @command('root', [])
5084 @command('root', [])
5085 def root(ui, repo):
5085 def root(ui, repo):
5086 """print the root (top) of the current working directory
5086 """print the root (top) of the current working directory
5087
5087
5088 Print the root directory of the current repository.
5088 Print the root directory of the current repository.
5089
5089
5090 Returns 0 on success.
5090 Returns 0 on success.
5091 """
5091 """
5092 ui.write(repo.root + "\n")
5092 ui.write(repo.root + "\n")
5093
5093
5094 @command('^serve',
5094 @command('^serve',
5095 [('A', 'accesslog', '', _('name of access log file to write to'),
5095 [('A', 'accesslog', '', _('name of access log file to write to'),
5096 _('FILE')),
5096 _('FILE')),
5097 ('d', 'daemon', None, _('run server in background')),
5097 ('d', 'daemon', None, _('run server in background')),
5098 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5098 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5099 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5099 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5100 # use string type, then we can check if something was passed
5100 # use string type, then we can check if something was passed
5101 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5101 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5102 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5102 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5103 _('ADDR')),
5103 _('ADDR')),
5104 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5104 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5105 _('PREFIX')),
5105 _('PREFIX')),
5106 ('n', 'name', '',
5106 ('n', 'name', '',
5107 _('name to show in web pages (default: working directory)'), _('NAME')),
5107 _('name to show in web pages (default: working directory)'), _('NAME')),
5108 ('', 'web-conf', '',
5108 ('', 'web-conf', '',
5109 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5109 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5110 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5110 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5111 _('FILE')),
5111 _('FILE')),
5112 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5112 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5113 ('', 'stdio', None, _('for remote clients')),
5113 ('', 'stdio', None, _('for remote clients')),
5114 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5114 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5115 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5115 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5116 ('', 'style', '', _('template style to use'), _('STYLE')),
5116 ('', 'style', '', _('template style to use'), _('STYLE')),
5117 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5117 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5118 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5118 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5119 _('[OPTION]...'))
5119 _('[OPTION]...'))
5120 def serve(ui, repo, **opts):
5120 def serve(ui, repo, **opts):
5121 """start stand-alone webserver
5121 """start stand-alone webserver
5122
5122
5123 Start a local HTTP repository browser and pull server. You can use
5123 Start a local HTTP repository browser and pull server. You can use
5124 this for ad-hoc sharing and browsing of repositories. It is
5124 this for ad-hoc sharing and browsing of repositories. It is
5125 recommended to use a real web server to serve a repository for
5125 recommended to use a real web server to serve a repository for
5126 longer periods of time.
5126 longer periods of time.
5127
5127
5128 Please note that the server does not implement access control.
5128 Please note that the server does not implement access control.
5129 This means that, by default, anybody can read from the server and
5129 This means that, by default, anybody can read from the server and
5130 nobody can write to it by default. Set the ``web.allow_push``
5130 nobody can write to it by default. Set the ``web.allow_push``
5131 option to ``*`` to allow everybody to push to the server. You
5131 option to ``*`` to allow everybody to push to the server. You
5132 should use a real web server if you need to authenticate users.
5132 should use a real web server if you need to authenticate users.
5133
5133
5134 By default, the server logs accesses to stdout and errors to
5134 By default, the server logs accesses to stdout and errors to
5135 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5135 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5136 files.
5136 files.
5137
5137
5138 To have the server choose a free port number to listen on, specify
5138 To have the server choose a free port number to listen on, specify
5139 a port number of 0; in this case, the server will print the port
5139 a port number of 0; in this case, the server will print the port
5140 number it uses.
5140 number it uses.
5141
5141
5142 Returns 0 on success.
5142 Returns 0 on success.
5143 """
5143 """
5144
5144
5145 if opts["stdio"] and opts["cmdserver"]:
5145 if opts["stdio"] and opts["cmdserver"]:
5146 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5146 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5147
5147
5148 def checkrepo():
5148 def checkrepo():
5149 if repo is None:
5149 if repo is None:
5150 raise error.RepoError(_("there is no Mercurial repository here"
5150 raise error.RepoError(_("there is no Mercurial repository here"
5151 " (.hg not found)"))
5151 " (.hg not found)"))
5152
5152
5153 if opts["stdio"]:
5153 if opts["stdio"]:
5154 checkrepo()
5154 checkrepo()
5155 s = sshserver.sshserver(ui, repo)
5155 s = sshserver.sshserver(ui, repo)
5156 s.serve_forever()
5156 s.serve_forever()
5157
5157
5158 if opts["cmdserver"]:
5158 if opts["cmdserver"]:
5159 checkrepo()
5159 checkrepo()
5160 s = commandserver.server(ui, repo, opts["cmdserver"])
5160 s = commandserver.server(ui, repo, opts["cmdserver"])
5161 return s.serve()
5161 return s.serve()
5162
5162
5163 # this way we can check if something was given in the command-line
5163 # this way we can check if something was given in the command-line
5164 if opts.get('port'):
5164 if opts.get('port'):
5165 opts['port'] = util.getport(opts.get('port'))
5165 opts['port'] = util.getport(opts.get('port'))
5166
5166
5167 baseui = repo and repo.baseui or ui
5167 baseui = repo and repo.baseui or ui
5168 optlist = ("name templates style address port prefix ipv6"
5168 optlist = ("name templates style address port prefix ipv6"
5169 " accesslog errorlog certificate encoding")
5169 " accesslog errorlog certificate encoding")
5170 for o in optlist.split():
5170 for o in optlist.split():
5171 val = opts.get(o, '')
5171 val = opts.get(o, '')
5172 if val in (None, ''): # should check against default options instead
5172 if val in (None, ''): # should check against default options instead
5173 continue
5173 continue
5174 baseui.setconfig("web", o, val)
5174 baseui.setconfig("web", o, val)
5175 if repo and repo.ui != baseui:
5175 if repo and repo.ui != baseui:
5176 repo.ui.setconfig("web", o, val)
5176 repo.ui.setconfig("web", o, val)
5177
5177
5178 o = opts.get('web_conf') or opts.get('webdir_conf')
5178 o = opts.get('web_conf') or opts.get('webdir_conf')
5179 if not o:
5179 if not o:
5180 if not repo:
5180 if not repo:
5181 raise error.RepoError(_("there is no Mercurial repository"
5181 raise error.RepoError(_("there is no Mercurial repository"
5182 " here (.hg not found)"))
5182 " here (.hg not found)"))
5183 o = repo
5183 o = repo
5184
5184
5185 app = hgweb.hgweb(o, baseui=baseui)
5185 app = hgweb.hgweb(o, baseui=baseui)
5186
5186 service = httpservice(ui, app, opts)
5187 class service(object):
5188 def init(self):
5189 util.setsignalhandler()
5190 self.httpd = hgweb_server.create_server(ui, app)
5191
5192 if opts['port'] and not ui.verbose:
5193 return
5194
5195 if self.httpd.prefix:
5196 prefix = self.httpd.prefix.strip('/') + '/'
5197 else:
5198 prefix = ''
5199
5200 port = ':%d' % self.httpd.port
5201 if port == ':80':
5202 port = ''
5203
5204 bindaddr = self.httpd.addr
5205 if bindaddr == '0.0.0.0':
5206 bindaddr = '*'
5207 elif ':' in bindaddr: # IPv6
5208 bindaddr = '[%s]' % bindaddr
5209
5210 fqaddr = self.httpd.fqaddr
5211 if ':' in fqaddr:
5212 fqaddr = '[%s]' % fqaddr
5213 if opts['port']:
5214 write = ui.status
5215 else:
5216 write = ui.write
5217 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5218 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5219
5220 def run(self):
5221 self.httpd.serve_forever()
5222
5223 service = service()
5224
5225 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5187 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5226
5188
5189 class httpservice(object):
5190 def __init__(self, ui, app, opts):
5191 self.ui = ui
5192 self.app = app
5193 self.opts = opts
5194
5195 def init(self):
5196 util.setsignalhandler()
5197 self.httpd = hgweb_server.create_server(self.ui, self.app)
5198
5199 if self.opts['port'] and not self.ui.verbose:
5200 return
5201
5202 if self.httpd.prefix:
5203 prefix = self.httpd.prefix.strip('/') + '/'
5204 else:
5205 prefix = ''
5206
5207 port = ':%d' % self.httpd.port
5208 if port == ':80':
5209 port = ''
5210
5211 bindaddr = self.httpd.addr
5212 if bindaddr == '0.0.0.0':
5213 bindaddr = '*'
5214 elif ':' in bindaddr: # IPv6
5215 bindaddr = '[%s]' % bindaddr
5216
5217 fqaddr = self.httpd.fqaddr
5218 if ':' in fqaddr:
5219 fqaddr = '[%s]' % fqaddr
5220 if self.opts['port']:
5221 write = self.ui.status
5222 else:
5223 write = self.ui.write
5224 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5225 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5226
5227 def run(self):
5228 self.httpd.serve_forever()
5229
5230
5227 @command('showconfig|debugconfig',
5231 @command('showconfig|debugconfig',
5228 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5232 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5229 _('[-u] [NAME]...'))
5233 _('[-u] [NAME]...'))
5230 def showconfig(ui, repo, *values, **opts):
5234 def showconfig(ui, repo, *values, **opts):
5231 """show combined config settings from all hgrc files
5235 """show combined config settings from all hgrc files
5232
5236
5233 With no arguments, print names and values of all config items.
5237 With no arguments, print names and values of all config items.
5234
5238
5235 With one argument of the form section.name, print just the value
5239 With one argument of the form section.name, print just the value
5236 of that config item.
5240 of that config item.
5237
5241
5238 With multiple arguments, print names and values of all config
5242 With multiple arguments, print names and values of all config
5239 items with matching section names.
5243 items with matching section names.
5240
5244
5241 With --debug, the source (filename and line number) is printed
5245 With --debug, the source (filename and line number) is printed
5242 for each config item.
5246 for each config item.
5243
5247
5244 Returns 0 on success.
5248 Returns 0 on success.
5245 """
5249 """
5246
5250
5247 for f in scmutil.rcpath():
5251 for f in scmutil.rcpath():
5248 ui.debug('read config from: %s\n' % f)
5252 ui.debug('read config from: %s\n' % f)
5249 untrusted = bool(opts.get('untrusted'))
5253 untrusted = bool(opts.get('untrusted'))
5250 if values:
5254 if values:
5251 sections = [v for v in values if '.' not in v]
5255 sections = [v for v in values if '.' not in v]
5252 items = [v for v in values if '.' in v]
5256 items = [v for v in values if '.' in v]
5253 if len(items) > 1 or items and sections:
5257 if len(items) > 1 or items and sections:
5254 raise util.Abort(_('only one config item permitted'))
5258 raise util.Abort(_('only one config item permitted'))
5255 for section, name, value in ui.walkconfig(untrusted=untrusted):
5259 for section, name, value in ui.walkconfig(untrusted=untrusted):
5256 value = str(value).replace('\n', '\\n')
5260 value = str(value).replace('\n', '\\n')
5257 sectname = section + '.' + name
5261 sectname = section + '.' + name
5258 if values:
5262 if values:
5259 for v in values:
5263 for v in values:
5260 if v == section:
5264 if v == section:
5261 ui.debug('%s: ' %
5265 ui.debug('%s: ' %
5262 ui.configsource(section, name, untrusted))
5266 ui.configsource(section, name, untrusted))
5263 ui.write('%s=%s\n' % (sectname, value))
5267 ui.write('%s=%s\n' % (sectname, value))
5264 elif v == sectname:
5268 elif v == sectname:
5265 ui.debug('%s: ' %
5269 ui.debug('%s: ' %
5266 ui.configsource(section, name, untrusted))
5270 ui.configsource(section, name, untrusted))
5267 ui.write(value, '\n')
5271 ui.write(value, '\n')
5268 else:
5272 else:
5269 ui.debug('%s: ' %
5273 ui.debug('%s: ' %
5270 ui.configsource(section, name, untrusted))
5274 ui.configsource(section, name, untrusted))
5271 ui.write('%s=%s\n' % (sectname, value))
5275 ui.write('%s=%s\n' % (sectname, value))
5272
5276
5273 @command('^status|st',
5277 @command('^status|st',
5274 [('A', 'all', None, _('show status of all files')),
5278 [('A', 'all', None, _('show status of all files')),
5275 ('m', 'modified', None, _('show only modified files')),
5279 ('m', 'modified', None, _('show only modified files')),
5276 ('a', 'added', None, _('show only added files')),
5280 ('a', 'added', None, _('show only added files')),
5277 ('r', 'removed', None, _('show only removed files')),
5281 ('r', 'removed', None, _('show only removed files')),
5278 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5282 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5279 ('c', 'clean', None, _('show only files without changes')),
5283 ('c', 'clean', None, _('show only files without changes')),
5280 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5284 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5281 ('i', 'ignored', None, _('show only ignored files')),
5285 ('i', 'ignored', None, _('show only ignored files')),
5282 ('n', 'no-status', None, _('hide status prefix')),
5286 ('n', 'no-status', None, _('hide status prefix')),
5283 ('C', 'copies', None, _('show source of copied files')),
5287 ('C', 'copies', None, _('show source of copied files')),
5284 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5288 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5285 ('', 'rev', [], _('show difference from revision'), _('REV')),
5289 ('', 'rev', [], _('show difference from revision'), _('REV')),
5286 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5290 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5287 ] + walkopts + subrepoopts,
5291 ] + walkopts + subrepoopts,
5288 _('[OPTION]... [FILE]...'))
5292 _('[OPTION]... [FILE]...'))
5289 def status(ui, repo, *pats, **opts):
5293 def status(ui, repo, *pats, **opts):
5290 """show changed files in the working directory
5294 """show changed files in the working directory
5291
5295
5292 Show status of files in the repository. If names are given, only
5296 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
5297 files that match are shown. Files that are clean or ignored or
5294 the source of a copy/move operation, are not listed unless
5298 the source of a copy/move operation, are not listed unless
5295 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5299 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5296 Unless options described with "show only ..." are given, the
5300 Unless options described with "show only ..." are given, the
5297 options -mardu are used.
5301 options -mardu are used.
5298
5302
5299 Option -q/--quiet hides untracked (unknown and ignored) files
5303 Option -q/--quiet hides untracked (unknown and ignored) files
5300 unless explicitly requested with -u/--unknown or -i/--ignored.
5304 unless explicitly requested with -u/--unknown or -i/--ignored.
5301
5305
5302 .. note::
5306 .. note::
5303 status may appear to disagree with diff if permissions have
5307 status may appear to disagree with diff if permissions have
5304 changed or a merge has occurred. The standard diff format does
5308 changed or a merge has occurred. The standard diff format does
5305 not report permission changes and diff only reports changes
5309 not report permission changes and diff only reports changes
5306 relative to one merge parent.
5310 relative to one merge parent.
5307
5311
5308 If one revision is given, it is used as the base revision.
5312 If one revision is given, it is used as the base revision.
5309 If two revisions are given, the differences between them are
5313 If two revisions are given, the differences between them are
5310 shown. The --change option can also be used as a shortcut to list
5314 shown. The --change option can also be used as a shortcut to list
5311 the changed files of a revision from its first parent.
5315 the changed files of a revision from its first parent.
5312
5316
5313 The codes used to show the status of files are::
5317 The codes used to show the status of files are::
5314
5318
5315 M = modified
5319 M = modified
5316 A = added
5320 A = added
5317 R = removed
5321 R = removed
5318 C = clean
5322 C = clean
5319 ! = missing (deleted by non-hg command, but still tracked)
5323 ! = missing (deleted by non-hg command, but still tracked)
5320 ? = not tracked
5324 ? = not tracked
5321 I = ignored
5325 I = ignored
5322 = origin of the previous file listed as A (added)
5326 = origin of the previous file listed as A (added)
5323
5327
5324 .. container:: verbose
5328 .. container:: verbose
5325
5329
5326 Examples:
5330 Examples:
5327
5331
5328 - show changes in the working directory relative to a
5332 - show changes in the working directory relative to a
5329 changeset::
5333 changeset::
5330
5334
5331 hg status --rev 9353
5335 hg status --rev 9353
5332
5336
5333 - show all changes including copies in an existing changeset::
5337 - show all changes including copies in an existing changeset::
5334
5338
5335 hg status --copies --change 9353
5339 hg status --copies --change 9353
5336
5340
5337 - get a NUL separated list of added files, suitable for xargs::
5341 - get a NUL separated list of added files, suitable for xargs::
5338
5342
5339 hg status -an0
5343 hg status -an0
5340
5344
5341 Returns 0 on success.
5345 Returns 0 on success.
5342 """
5346 """
5343
5347
5344 revs = opts.get('rev')
5348 revs = opts.get('rev')
5345 change = opts.get('change')
5349 change = opts.get('change')
5346
5350
5347 if revs and change:
5351 if revs and change:
5348 msg = _('cannot specify --rev and --change at the same time')
5352 msg = _('cannot specify --rev and --change at the same time')
5349 raise util.Abort(msg)
5353 raise util.Abort(msg)
5350 elif change:
5354 elif change:
5351 node2 = scmutil.revsingle(repo, change, None).node()
5355 node2 = scmutil.revsingle(repo, change, None).node()
5352 node1 = repo[node2].p1().node()
5356 node1 = repo[node2].p1().node()
5353 else:
5357 else:
5354 node1, node2 = scmutil.revpair(repo, revs)
5358 node1, node2 = scmutil.revpair(repo, revs)
5355
5359
5356 cwd = (pats and repo.getcwd()) or ''
5360 cwd = (pats and repo.getcwd()) or ''
5357 end = opts.get('print0') and '\0' or '\n'
5361 end = opts.get('print0') and '\0' or '\n'
5358 copy = {}
5362 copy = {}
5359 states = 'modified added removed deleted unknown ignored clean'.split()
5363 states = 'modified added removed deleted unknown ignored clean'.split()
5360 show = [k for k in states if opts.get(k)]
5364 show = [k for k in states if opts.get(k)]
5361 if opts.get('all'):
5365 if opts.get('all'):
5362 show += ui.quiet and (states[:4] + ['clean']) or states
5366 show += ui.quiet and (states[:4] + ['clean']) or states
5363 if not show:
5367 if not show:
5364 show = ui.quiet and states[:4] or states[:5]
5368 show = ui.quiet and states[:4] or states[:5]
5365
5369
5366 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5370 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5367 'ignored' in show, 'clean' in show, 'unknown' in show,
5371 'ignored' in show, 'clean' in show, 'unknown' in show,
5368 opts.get('subrepos'))
5372 opts.get('subrepos'))
5369 changestates = zip(states, 'MAR!?IC', stat)
5373 changestates = zip(states, 'MAR!?IC', stat)
5370
5374
5371 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5375 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5372 copy = copies.pathcopies(repo[node1], repo[node2])
5376 copy = copies.pathcopies(repo[node1], repo[node2])
5373
5377
5374 fm = ui.formatter('status', opts)
5378 fm = ui.formatter('status', opts)
5375 fmt = '%s' + end
5379 fmt = '%s' + end
5376 showchar = not opts.get('no_status')
5380 showchar = not opts.get('no_status')
5377
5381
5378 for state, char, files in changestates:
5382 for state, char, files in changestates:
5379 if state in show:
5383 if state in show:
5380 label = 'status.' + state
5384 label = 'status.' + state
5381 for f in files:
5385 for f in files:
5382 fm.startitem()
5386 fm.startitem()
5383 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5387 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5384 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5388 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5385 if f in copy:
5389 if f in copy:
5386 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5390 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5387 label='status.copied')
5391 label='status.copied')
5388 fm.end()
5392 fm.end()
5389
5393
5390 @command('^summary|sum',
5394 @command('^summary|sum',
5391 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5395 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5392 def summary(ui, repo, **opts):
5396 def summary(ui, repo, **opts):
5393 """summarize working directory state
5397 """summarize working directory state
5394
5398
5395 This generates a brief summary of the working directory state,
5399 This generates a brief summary of the working directory state,
5396 including parents, branch, commit status, and available updates.
5400 including parents, branch, commit status, and available updates.
5397
5401
5398 With the --remote option, this will check the default paths for
5402 With the --remote option, this will check the default paths for
5399 incoming and outgoing changes. This can be time-consuming.
5403 incoming and outgoing changes. This can be time-consuming.
5400
5404
5401 Returns 0 on success.
5405 Returns 0 on success.
5402 """
5406 """
5403
5407
5404 ctx = repo[None]
5408 ctx = repo[None]
5405 parents = ctx.parents()
5409 parents = ctx.parents()
5406 pnode = parents[0].node()
5410 pnode = parents[0].node()
5407 marks = []
5411 marks = []
5408
5412
5409 for p in parents:
5413 for p in parents:
5410 # label with log.changeset (instead of log.parent) since this
5414 # label with log.changeset (instead of log.parent) since this
5411 # shows a working directory parent *changeset*:
5415 # shows a working directory parent *changeset*:
5412 # i18n: column positioning for "hg summary"
5416 # i18n: column positioning for "hg summary"
5413 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5417 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5414 label='log.changeset changeset.%s' % p.phasestr())
5418 label='log.changeset changeset.%s' % p.phasestr())
5415 ui.write(' '.join(p.tags()), label='log.tag')
5419 ui.write(' '.join(p.tags()), label='log.tag')
5416 if p.bookmarks():
5420 if p.bookmarks():
5417 marks.extend(p.bookmarks())
5421 marks.extend(p.bookmarks())
5418 if p.rev() == -1:
5422 if p.rev() == -1:
5419 if not len(repo):
5423 if not len(repo):
5420 ui.write(_(' (empty repository)'))
5424 ui.write(_(' (empty repository)'))
5421 else:
5425 else:
5422 ui.write(_(' (no revision checked out)'))
5426 ui.write(_(' (no revision checked out)'))
5423 ui.write('\n')
5427 ui.write('\n')
5424 if p.description():
5428 if p.description():
5425 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5429 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5426 label='log.summary')
5430 label='log.summary')
5427
5431
5428 branch = ctx.branch()
5432 branch = ctx.branch()
5429 bheads = repo.branchheads(branch)
5433 bheads = repo.branchheads(branch)
5430 # i18n: column positioning for "hg summary"
5434 # i18n: column positioning for "hg summary"
5431 m = _('branch: %s\n') % branch
5435 m = _('branch: %s\n') % branch
5432 if branch != 'default':
5436 if branch != 'default':
5433 ui.write(m, label='log.branch')
5437 ui.write(m, label='log.branch')
5434 else:
5438 else:
5435 ui.status(m, label='log.branch')
5439 ui.status(m, label='log.branch')
5436
5440
5437 if marks:
5441 if marks:
5438 current = repo._bookmarkcurrent
5442 current = repo._bookmarkcurrent
5439 # i18n: column positioning for "hg summary"
5443 # i18n: column positioning for "hg summary"
5440 ui.write(_('bookmarks:'), label='log.bookmark')
5444 ui.write(_('bookmarks:'), label='log.bookmark')
5441 if current is not None:
5445 if current is not None:
5442 if current in marks:
5446 if current in marks:
5443 ui.write(' *' + current, label='bookmarks.current')
5447 ui.write(' *' + current, label='bookmarks.current')
5444 marks.remove(current)
5448 marks.remove(current)
5445 else:
5449 else:
5446 ui.write(' [%s]' % current, label='bookmarks.current')
5450 ui.write(' [%s]' % current, label='bookmarks.current')
5447 for m in marks:
5451 for m in marks:
5448 ui.write(' ' + m, label='log.bookmark')
5452 ui.write(' ' + m, label='log.bookmark')
5449 ui.write('\n', label='log.bookmark')
5453 ui.write('\n', label='log.bookmark')
5450
5454
5451 st = list(repo.status(unknown=True))[:6]
5455 st = list(repo.status(unknown=True))[:6]
5452
5456
5453 c = repo.dirstate.copies()
5457 c = repo.dirstate.copies()
5454 copied, renamed = [], []
5458 copied, renamed = [], []
5455 for d, s in c.iteritems():
5459 for d, s in c.iteritems():
5456 if s in st[2]:
5460 if s in st[2]:
5457 st[2].remove(s)
5461 st[2].remove(s)
5458 renamed.append(d)
5462 renamed.append(d)
5459 else:
5463 else:
5460 copied.append(d)
5464 copied.append(d)
5461 if d in st[1]:
5465 if d in st[1]:
5462 st[1].remove(d)
5466 st[1].remove(d)
5463 st.insert(3, renamed)
5467 st.insert(3, renamed)
5464 st.insert(4, copied)
5468 st.insert(4, copied)
5465
5469
5466 ms = mergemod.mergestate(repo)
5470 ms = mergemod.mergestate(repo)
5467 st.append([f for f in ms if ms[f] == 'u'])
5471 st.append([f for f in ms if ms[f] == 'u'])
5468
5472
5469 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5473 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5470 st.append(subs)
5474 st.append(subs)
5471
5475
5472 labels = [ui.label(_('%d modified'), 'status.modified'),
5476 labels = [ui.label(_('%d modified'), 'status.modified'),
5473 ui.label(_('%d added'), 'status.added'),
5477 ui.label(_('%d added'), 'status.added'),
5474 ui.label(_('%d removed'), 'status.removed'),
5478 ui.label(_('%d removed'), 'status.removed'),
5475 ui.label(_('%d renamed'), 'status.copied'),
5479 ui.label(_('%d renamed'), 'status.copied'),
5476 ui.label(_('%d copied'), 'status.copied'),
5480 ui.label(_('%d copied'), 'status.copied'),
5477 ui.label(_('%d deleted'), 'status.deleted'),
5481 ui.label(_('%d deleted'), 'status.deleted'),
5478 ui.label(_('%d unknown'), 'status.unknown'),
5482 ui.label(_('%d unknown'), 'status.unknown'),
5479 ui.label(_('%d ignored'), 'status.ignored'),
5483 ui.label(_('%d ignored'), 'status.ignored'),
5480 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5484 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5481 ui.label(_('%d subrepos'), 'status.modified')]
5485 ui.label(_('%d subrepos'), 'status.modified')]
5482 t = []
5486 t = []
5483 for s, l in zip(st, labels):
5487 for s, l in zip(st, labels):
5484 if s:
5488 if s:
5485 t.append(l % len(s))
5489 t.append(l % len(s))
5486
5490
5487 t = ', '.join(t)
5491 t = ', '.join(t)
5488 cleanworkdir = False
5492 cleanworkdir = False
5489
5493
5490 if repo.vfs.exists('updatestate'):
5494 if repo.vfs.exists('updatestate'):
5491 t += _(' (interrupted update)')
5495 t += _(' (interrupted update)')
5492 elif len(parents) > 1:
5496 elif len(parents) > 1:
5493 t += _(' (merge)')
5497 t += _(' (merge)')
5494 elif branch != parents[0].branch():
5498 elif branch != parents[0].branch():
5495 t += _(' (new branch)')
5499 t += _(' (new branch)')
5496 elif (parents[0].closesbranch() and
5500 elif (parents[0].closesbranch() and
5497 pnode in repo.branchheads(branch, closed=True)):
5501 pnode in repo.branchheads(branch, closed=True)):
5498 t += _(' (head closed)')
5502 t += _(' (head closed)')
5499 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5503 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5500 t += _(' (clean)')
5504 t += _(' (clean)')
5501 cleanworkdir = True
5505 cleanworkdir = True
5502 elif pnode not in bheads:
5506 elif pnode not in bheads:
5503 t += _(' (new branch head)')
5507 t += _(' (new branch head)')
5504
5508
5505 if cleanworkdir:
5509 if cleanworkdir:
5506 # i18n: column positioning for "hg summary"
5510 # i18n: column positioning for "hg summary"
5507 ui.status(_('commit: %s\n') % t.strip())
5511 ui.status(_('commit: %s\n') % t.strip())
5508 else:
5512 else:
5509 # i18n: column positioning for "hg summary"
5513 # i18n: column positioning for "hg summary"
5510 ui.write(_('commit: %s\n') % t.strip())
5514 ui.write(_('commit: %s\n') % t.strip())
5511
5515
5512 # all ancestors of branch heads - all ancestors of parent = new csets
5516 # all ancestors of branch heads - all ancestors of parent = new csets
5513 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5517 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5514 bheads))
5518 bheads))
5515
5519
5516 if new == 0:
5520 if new == 0:
5517 # i18n: column positioning for "hg summary"
5521 # i18n: column positioning for "hg summary"
5518 ui.status(_('update: (current)\n'))
5522 ui.status(_('update: (current)\n'))
5519 elif pnode not in bheads:
5523 elif pnode not in bheads:
5520 # i18n: column positioning for "hg summary"
5524 # i18n: column positioning for "hg summary"
5521 ui.write(_('update: %d new changesets (update)\n') % new)
5525 ui.write(_('update: %d new changesets (update)\n') % new)
5522 else:
5526 else:
5523 # i18n: column positioning for "hg summary"
5527 # i18n: column positioning for "hg summary"
5524 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5528 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5525 (new, len(bheads)))
5529 (new, len(bheads)))
5526
5530
5527 cmdutil.summaryhooks(ui, repo)
5531 cmdutil.summaryhooks(ui, repo)
5528
5532
5529 if opts.get('remote'):
5533 if opts.get('remote'):
5530 t = []
5534 t = []
5531 source, branches = hg.parseurl(ui.expandpath('default'))
5535 source, branches = hg.parseurl(ui.expandpath('default'))
5532 sbranch = branches[0]
5536 sbranch = branches[0]
5533 other = hg.peer(repo, {}, source)
5537 other = hg.peer(repo, {}, source)
5534 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5538 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5535 if revs:
5539 if revs:
5536 revs = [other.lookup(rev) for rev in revs]
5540 revs = [other.lookup(rev) for rev in revs]
5537 ui.debug('comparing with %s\n' % util.hidepassword(source))
5541 ui.debug('comparing with %s\n' % util.hidepassword(source))
5538 repo.ui.pushbuffer()
5542 repo.ui.pushbuffer()
5539 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5543 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5540 _common, incoming, _rheads = commoninc
5544 _common, incoming, _rheads = commoninc
5541 repo.ui.popbuffer()
5545 repo.ui.popbuffer()
5542 if incoming:
5546 if incoming:
5543 t.append(_('1 or more incoming'))
5547 t.append(_('1 or more incoming'))
5544
5548
5545 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5549 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5546 dbranch = branches[0]
5550 dbranch = branches[0]
5547 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5551 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5548 if source != dest:
5552 if source != dest:
5549 other = hg.peer(repo, {}, dest)
5553 other = hg.peer(repo, {}, dest)
5550 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5554 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5551 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5555 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5552 commoninc = None
5556 commoninc = None
5553 if revs:
5557 if revs:
5554 revs = [repo.lookup(rev) for rev in revs]
5558 revs = [repo.lookup(rev) for rev in revs]
5555 repo.ui.pushbuffer()
5559 repo.ui.pushbuffer()
5556 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5560 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5557 commoninc=commoninc)
5561 commoninc=commoninc)
5558 repo.ui.popbuffer()
5562 repo.ui.popbuffer()
5559 o = outgoing.missing
5563 o = outgoing.missing
5560 if o:
5564 if o:
5561 t.append(_('%d outgoing') % len(o))
5565 t.append(_('%d outgoing') % len(o))
5562 if 'bookmarks' in other.listkeys('namespaces'):
5566 if 'bookmarks' in other.listkeys('namespaces'):
5563 lmarks = repo.listkeys('bookmarks')
5567 lmarks = repo.listkeys('bookmarks')
5564 rmarks = other.listkeys('bookmarks')
5568 rmarks = other.listkeys('bookmarks')
5565 diff = set(rmarks) - set(lmarks)
5569 diff = set(rmarks) - set(lmarks)
5566 if len(diff) > 0:
5570 if len(diff) > 0:
5567 t.append(_('%d incoming bookmarks') % len(diff))
5571 t.append(_('%d incoming bookmarks') % len(diff))
5568 diff = set(lmarks) - set(rmarks)
5572 diff = set(lmarks) - set(rmarks)
5569 if len(diff) > 0:
5573 if len(diff) > 0:
5570 t.append(_('%d outgoing bookmarks') % len(diff))
5574 t.append(_('%d outgoing bookmarks') % len(diff))
5571
5575
5572 if t:
5576 if t:
5573 # i18n: column positioning for "hg summary"
5577 # i18n: column positioning for "hg summary"
5574 ui.write(_('remote: %s\n') % (', '.join(t)))
5578 ui.write(_('remote: %s\n') % (', '.join(t)))
5575 else:
5579 else:
5576 # i18n: column positioning for "hg summary"
5580 # i18n: column positioning for "hg summary"
5577 ui.status(_('remote: (synced)\n'))
5581 ui.status(_('remote: (synced)\n'))
5578
5582
5579 @command('tag',
5583 @command('tag',
5580 [('f', 'force', None, _('force tag')),
5584 [('f', 'force', None, _('force tag')),
5581 ('l', 'local', None, _('make the tag local')),
5585 ('l', 'local', None, _('make the tag local')),
5582 ('r', 'rev', '', _('revision to tag'), _('REV')),
5586 ('r', 'rev', '', _('revision to tag'), _('REV')),
5583 ('', 'remove', None, _('remove a tag')),
5587 ('', 'remove', None, _('remove a tag')),
5584 # -l/--local is already there, commitopts cannot be used
5588 # -l/--local is already there, commitopts cannot be used
5585 ('e', 'edit', None, _('edit commit message')),
5589 ('e', 'edit', None, _('edit commit message')),
5586 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5590 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5587 ] + commitopts2,
5591 ] + commitopts2,
5588 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5592 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5589 def tag(ui, repo, name1, *names, **opts):
5593 def tag(ui, repo, name1, *names, **opts):
5590 """add one or more tags for the current or given revision
5594 """add one or more tags for the current or given revision
5591
5595
5592 Name a particular revision using <name>.
5596 Name a particular revision using <name>.
5593
5597
5594 Tags are used to name particular revisions of the repository and are
5598 Tags are used to name particular revisions of the repository and are
5595 very useful to compare different revisions, to go back to significant
5599 very useful to compare different revisions, to go back to significant
5596 earlier versions or to mark branch points as releases, etc. Changing
5600 earlier versions or to mark branch points as releases, etc. Changing
5597 an existing tag is normally disallowed; use -f/--force to override.
5601 an existing tag is normally disallowed; use -f/--force to override.
5598
5602
5599 If no revision is given, the parent of the working directory is
5603 If no revision is given, the parent of the working directory is
5600 used.
5604 used.
5601
5605
5602 To facilitate version control, distribution, and merging of tags,
5606 To facilitate version control, distribution, and merging of tags,
5603 they are stored as a file named ".hgtags" which is managed similarly
5607 they are stored as a file named ".hgtags" which is managed similarly
5604 to other project files and can be hand-edited if necessary. This
5608 to other project files and can be hand-edited if necessary. This
5605 also means that tagging creates a new commit. The file
5609 also means that tagging creates a new commit. The file
5606 ".hg/localtags" is used for local tags (not shared among
5610 ".hg/localtags" is used for local tags (not shared among
5607 repositories).
5611 repositories).
5608
5612
5609 Tag commits are usually made at the head of a branch. If the parent
5613 Tag commits are usually made at the head of a branch. If the parent
5610 of the working directory is not a branch head, :hg:`tag` aborts; use
5614 of the working directory is not a branch head, :hg:`tag` aborts; use
5611 -f/--force to force the tag commit to be based on a non-head
5615 -f/--force to force the tag commit to be based on a non-head
5612 changeset.
5616 changeset.
5613
5617
5614 See :hg:`help dates` for a list of formats valid for -d/--date.
5618 See :hg:`help dates` for a list of formats valid for -d/--date.
5615
5619
5616 Since tag names have priority over branch names during revision
5620 Since tag names have priority over branch names during revision
5617 lookup, using an existing branch name as a tag name is discouraged.
5621 lookup, using an existing branch name as a tag name is discouraged.
5618
5622
5619 Returns 0 on success.
5623 Returns 0 on success.
5620 """
5624 """
5621 wlock = lock = None
5625 wlock = lock = None
5622 try:
5626 try:
5623 wlock = repo.wlock()
5627 wlock = repo.wlock()
5624 lock = repo.lock()
5628 lock = repo.lock()
5625 rev_ = "."
5629 rev_ = "."
5626 names = [t.strip() for t in (name1,) + names]
5630 names = [t.strip() for t in (name1,) + names]
5627 if len(names) != len(set(names)):
5631 if len(names) != len(set(names)):
5628 raise util.Abort(_('tag names must be unique'))
5632 raise util.Abort(_('tag names must be unique'))
5629 for n in names:
5633 for n in names:
5630 scmutil.checknewlabel(repo, n, 'tag')
5634 scmutil.checknewlabel(repo, n, 'tag')
5631 if not n:
5635 if not n:
5632 raise util.Abort(_('tag names cannot consist entirely of '
5636 raise util.Abort(_('tag names cannot consist entirely of '
5633 'whitespace'))
5637 'whitespace'))
5634 if opts.get('rev') and opts.get('remove'):
5638 if opts.get('rev') and opts.get('remove'):
5635 raise util.Abort(_("--rev and --remove are incompatible"))
5639 raise util.Abort(_("--rev and --remove are incompatible"))
5636 if opts.get('rev'):
5640 if opts.get('rev'):
5637 rev_ = opts['rev']
5641 rev_ = opts['rev']
5638 message = opts.get('message')
5642 message = opts.get('message')
5639 if opts.get('remove'):
5643 if opts.get('remove'):
5640 expectedtype = opts.get('local') and 'local' or 'global'
5644 expectedtype = opts.get('local') and 'local' or 'global'
5641 for n in names:
5645 for n in names:
5642 if not repo.tagtype(n):
5646 if not repo.tagtype(n):
5643 raise util.Abort(_("tag '%s' does not exist") % n)
5647 raise util.Abort(_("tag '%s' does not exist") % n)
5644 if repo.tagtype(n) != expectedtype:
5648 if repo.tagtype(n) != expectedtype:
5645 if expectedtype == 'global':
5649 if expectedtype == 'global':
5646 raise util.Abort(_("tag '%s' is not a global tag") % n)
5650 raise util.Abort(_("tag '%s' is not a global tag") % n)
5647 else:
5651 else:
5648 raise util.Abort(_("tag '%s' is not a local tag") % n)
5652 raise util.Abort(_("tag '%s' is not a local tag") % n)
5649 rev_ = nullid
5653 rev_ = nullid
5650 if not message:
5654 if not message:
5651 # we don't translate commit messages
5655 # we don't translate commit messages
5652 message = 'Removed tag %s' % ', '.join(names)
5656 message = 'Removed tag %s' % ', '.join(names)
5653 elif not opts.get('force'):
5657 elif not opts.get('force'):
5654 for n in names:
5658 for n in names:
5655 if n in repo.tags():
5659 if n in repo.tags():
5656 raise util.Abort(_("tag '%s' already exists "
5660 raise util.Abort(_("tag '%s' already exists "
5657 "(use -f to force)") % n)
5661 "(use -f to force)") % n)
5658 if not opts.get('local'):
5662 if not opts.get('local'):
5659 p1, p2 = repo.dirstate.parents()
5663 p1, p2 = repo.dirstate.parents()
5660 if p2 != nullid:
5664 if p2 != nullid:
5661 raise util.Abort(_('uncommitted merge'))
5665 raise util.Abort(_('uncommitted merge'))
5662 bheads = repo.branchheads()
5666 bheads = repo.branchheads()
5663 if not opts.get('force') and bheads and p1 not in bheads:
5667 if not opts.get('force') and bheads and p1 not in bheads:
5664 raise util.Abort(_('not at a branch head (use -f to force)'))
5668 raise util.Abort(_('not at a branch head (use -f to force)'))
5665 r = scmutil.revsingle(repo, rev_).node()
5669 r = scmutil.revsingle(repo, rev_).node()
5666
5670
5667 if not message:
5671 if not message:
5668 # we don't translate commit messages
5672 # we don't translate commit messages
5669 message = ('Added tag %s for changeset %s' %
5673 message = ('Added tag %s for changeset %s' %
5670 (', '.join(names), short(r)))
5674 (', '.join(names), short(r)))
5671
5675
5672 date = opts.get('date')
5676 date = opts.get('date')
5673 if date:
5677 if date:
5674 date = util.parsedate(date)
5678 date = util.parsedate(date)
5675
5679
5676 if opts.get('edit'):
5680 if opts.get('edit'):
5677 message = ui.edit(message, ui.username())
5681 message = ui.edit(message, ui.username())
5678
5682
5679 # don't allow tagging the null rev
5683 # don't allow tagging the null rev
5680 if (not opts.get('remove') and
5684 if (not opts.get('remove') and
5681 scmutil.revsingle(repo, rev_).rev() == nullrev):
5685 scmutil.revsingle(repo, rev_).rev() == nullrev):
5682 raise util.Abort(_("cannot tag null revision"))
5686 raise util.Abort(_("cannot tag null revision"))
5683
5687
5684 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5688 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5685 finally:
5689 finally:
5686 release(lock, wlock)
5690 release(lock, wlock)
5687
5691
5688 @command('tags', [], '')
5692 @command('tags', [], '')
5689 def tags(ui, repo, **opts):
5693 def tags(ui, repo, **opts):
5690 """list repository tags
5694 """list repository tags
5691
5695
5692 This lists both regular and local tags. When the -v/--verbose
5696 This lists both regular and local tags. When the -v/--verbose
5693 switch is used, a third column "local" is printed for local tags.
5697 switch is used, a third column "local" is printed for local tags.
5694
5698
5695 Returns 0 on success.
5699 Returns 0 on success.
5696 """
5700 """
5697
5701
5698 fm = ui.formatter('tags', opts)
5702 fm = ui.formatter('tags', opts)
5699 hexfunc = ui.debugflag and hex or short
5703 hexfunc = ui.debugflag and hex or short
5700 tagtype = ""
5704 tagtype = ""
5701
5705
5702 for t, n in reversed(repo.tagslist()):
5706 for t, n in reversed(repo.tagslist()):
5703 hn = hexfunc(n)
5707 hn = hexfunc(n)
5704 label = 'tags.normal'
5708 label = 'tags.normal'
5705 tagtype = ''
5709 tagtype = ''
5706 if repo.tagtype(t) == 'local':
5710 if repo.tagtype(t) == 'local':
5707 label = 'tags.local'
5711 label = 'tags.local'
5708 tagtype = 'local'
5712 tagtype = 'local'
5709
5713
5710 fm.startitem()
5714 fm.startitem()
5711 fm.write('tag', '%s', t, label=label)
5715 fm.write('tag', '%s', t, label=label)
5712 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5716 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5713 fm.condwrite(not ui.quiet, 'rev id', fmt,
5717 fm.condwrite(not ui.quiet, 'rev id', fmt,
5714 repo.changelog.rev(n), hn, label=label)
5718 repo.changelog.rev(n), hn, label=label)
5715 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5719 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5716 tagtype, label=label)
5720 tagtype, label=label)
5717 fm.plain('\n')
5721 fm.plain('\n')
5718 fm.end()
5722 fm.end()
5719
5723
5720 @command('tip',
5724 @command('tip',
5721 [('p', 'patch', None, _('show patch')),
5725 [('p', 'patch', None, _('show patch')),
5722 ('g', 'git', None, _('use git extended diff format')),
5726 ('g', 'git', None, _('use git extended diff format')),
5723 ] + templateopts,
5727 ] + templateopts,
5724 _('[-p] [-g]'))
5728 _('[-p] [-g]'))
5725 def tip(ui, repo, **opts):
5729 def tip(ui, repo, **opts):
5726 """show the tip revision (DEPRECATED)
5730 """show the tip revision (DEPRECATED)
5727
5731
5728 The tip revision (usually just called the tip) is the changeset
5732 The tip revision (usually just called the tip) is the changeset
5729 most recently added to the repository (and therefore the most
5733 most recently added to the repository (and therefore the most
5730 recently changed head).
5734 recently changed head).
5731
5735
5732 If you have just made a commit, that commit will be the tip. If
5736 If you have just made a commit, that commit will be the tip. If
5733 you have just pulled changes from another repository, the tip of
5737 you have just pulled changes from another repository, the tip of
5734 that repository becomes the current tip. The "tip" tag is special
5738 that repository becomes the current tip. The "tip" tag is special
5735 and cannot be renamed or assigned to a different changeset.
5739 and cannot be renamed or assigned to a different changeset.
5736
5740
5737 This command is deprecated, please use :hg:`heads` instead.
5741 This command is deprecated, please use :hg:`heads` instead.
5738
5742
5739 Returns 0 on success.
5743 Returns 0 on success.
5740 """
5744 """
5741 displayer = cmdutil.show_changeset(ui, repo, opts)
5745 displayer = cmdutil.show_changeset(ui, repo, opts)
5742 displayer.show(repo['tip'])
5746 displayer.show(repo['tip'])
5743 displayer.close()
5747 displayer.close()
5744
5748
5745 @command('unbundle',
5749 @command('unbundle',
5746 [('u', 'update', None,
5750 [('u', 'update', None,
5747 _('update to new branch head if changesets were unbundled'))],
5751 _('update to new branch head if changesets were unbundled'))],
5748 _('[-u] FILE...'))
5752 _('[-u] FILE...'))
5749 def unbundle(ui, repo, fname1, *fnames, **opts):
5753 def unbundle(ui, repo, fname1, *fnames, **opts):
5750 """apply one or more changegroup files
5754 """apply one or more changegroup files
5751
5755
5752 Apply one or more compressed changegroup files generated by the
5756 Apply one or more compressed changegroup files generated by the
5753 bundle command.
5757 bundle command.
5754
5758
5755 Returns 0 on success, 1 if an update has unresolved files.
5759 Returns 0 on success, 1 if an update has unresolved files.
5756 """
5760 """
5757 fnames = (fname1,) + fnames
5761 fnames = (fname1,) + fnames
5758
5762
5759 lock = repo.lock()
5763 lock = repo.lock()
5760 wc = repo['.']
5764 wc = repo['.']
5761 try:
5765 try:
5762 for fname in fnames:
5766 for fname in fnames:
5763 f = hg.openpath(ui, fname)
5767 f = hg.openpath(ui, fname)
5764 gen = changegroup.readbundle(f, fname)
5768 gen = changegroup.readbundle(f, fname)
5765 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5769 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5766 finally:
5770 finally:
5767 lock.release()
5771 lock.release()
5768 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5772 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5769 return postincoming(ui, repo, modheads, opts.get('update'), None)
5773 return postincoming(ui, repo, modheads, opts.get('update'), None)
5770
5774
5771 @command('^update|up|checkout|co',
5775 @command('^update|up|checkout|co',
5772 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5776 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5773 ('c', 'check', None,
5777 ('c', 'check', None,
5774 _('update across branches if no uncommitted changes')),
5778 _('update across branches if no uncommitted changes')),
5775 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5779 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5776 ('r', 'rev', '', _('revision'), _('REV'))],
5780 ('r', 'rev', '', _('revision'), _('REV'))],
5777 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5781 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5778 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5782 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5779 """update working directory (or switch revisions)
5783 """update working directory (or switch revisions)
5780
5784
5781 Update the repository's working directory to the specified
5785 Update the repository's working directory to the specified
5782 changeset. If no changeset is specified, update to the tip of the
5786 changeset. If no changeset is specified, update to the tip of the
5783 current named branch and move the current bookmark (see :hg:`help
5787 current named branch and move the current bookmark (see :hg:`help
5784 bookmarks`).
5788 bookmarks`).
5785
5789
5786 Update sets the working directory's parent revision to the specified
5790 Update sets the working directory's parent revision to the specified
5787 changeset (see :hg:`help parents`).
5791 changeset (see :hg:`help parents`).
5788
5792
5789 If the changeset is not a descendant or ancestor of the working
5793 If the changeset is not a descendant or ancestor of the working
5790 directory's parent, the update is aborted. With the -c/--check
5794 directory's parent, the update is aborted. With the -c/--check
5791 option, the working directory is checked for uncommitted changes; if
5795 option, the working directory is checked for uncommitted changes; if
5792 none are found, the working directory is updated to the specified
5796 none are found, the working directory is updated to the specified
5793 changeset.
5797 changeset.
5794
5798
5795 .. container:: verbose
5799 .. container:: verbose
5796
5800
5797 The following rules apply when the working directory contains
5801 The following rules apply when the working directory contains
5798 uncommitted changes:
5802 uncommitted changes:
5799
5803
5800 1. If neither -c/--check nor -C/--clean is specified, and if
5804 1. If neither -c/--check nor -C/--clean is specified, and if
5801 the requested changeset is an ancestor or descendant of
5805 the requested changeset is an ancestor or descendant of
5802 the working directory's parent, the uncommitted changes
5806 the working directory's parent, the uncommitted changes
5803 are merged into the requested changeset and the merged
5807 are merged into the requested changeset and the merged
5804 result is left uncommitted. If the requested changeset is
5808 result is left uncommitted. If the requested changeset is
5805 not an ancestor or descendant (that is, it is on another
5809 not an ancestor or descendant (that is, it is on another
5806 branch), the update is aborted and the uncommitted changes
5810 branch), the update is aborted and the uncommitted changes
5807 are preserved.
5811 are preserved.
5808
5812
5809 2. With the -c/--check option, the update is aborted and the
5813 2. With the -c/--check option, the update is aborted and the
5810 uncommitted changes are preserved.
5814 uncommitted changes are preserved.
5811
5815
5812 3. With the -C/--clean option, uncommitted changes are discarded and
5816 3. With the -C/--clean option, uncommitted changes are discarded and
5813 the working directory is updated to the requested changeset.
5817 the working directory is updated to the requested changeset.
5814
5818
5815 To cancel an uncommitted merge (and lose your changes), use
5819 To cancel an uncommitted merge (and lose your changes), use
5816 :hg:`update --clean .`.
5820 :hg:`update --clean .`.
5817
5821
5818 Use null as the changeset to remove the working directory (like
5822 Use null as the changeset to remove the working directory (like
5819 :hg:`clone -U`).
5823 :hg:`clone -U`).
5820
5824
5821 If you want to revert just one file to an older revision, use
5825 If you want to revert just one file to an older revision, use
5822 :hg:`revert [-r REV] NAME`.
5826 :hg:`revert [-r REV] NAME`.
5823
5827
5824 See :hg:`help dates` for a list of formats valid for -d/--date.
5828 See :hg:`help dates` for a list of formats valid for -d/--date.
5825
5829
5826 Returns 0 on success, 1 if there are unresolved files.
5830 Returns 0 on success, 1 if there are unresolved files.
5827 """
5831 """
5828 if rev and node:
5832 if rev and node:
5829 raise util.Abort(_("please specify just one revision"))
5833 raise util.Abort(_("please specify just one revision"))
5830
5834
5831 if rev is None or rev == '':
5835 if rev is None or rev == '':
5832 rev = node
5836 rev = node
5833
5837
5834 cmdutil.clearunfinished(repo)
5838 cmdutil.clearunfinished(repo)
5835
5839
5836 # with no argument, we also move the current bookmark, if any
5840 # with no argument, we also move the current bookmark, if any
5837 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5841 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5838
5842
5839 # if we defined a bookmark, we have to remember the original bookmark name
5843 # if we defined a bookmark, we have to remember the original bookmark name
5840 brev = rev
5844 brev = rev
5841 rev = scmutil.revsingle(repo, rev, rev).rev()
5845 rev = scmutil.revsingle(repo, rev, rev).rev()
5842
5846
5843 if check and clean:
5847 if check and clean:
5844 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5848 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5845
5849
5846 if date:
5850 if date:
5847 if rev is not None:
5851 if rev is not None:
5848 raise util.Abort(_("you can't specify a revision and a date"))
5852 raise util.Abort(_("you can't specify a revision and a date"))
5849 rev = cmdutil.finddate(ui, repo, date)
5853 rev = cmdutil.finddate(ui, repo, date)
5850
5854
5851 if check:
5855 if check:
5852 c = repo[None]
5856 c = repo[None]
5853 if c.dirty(merge=False, branch=False, missing=True):
5857 if c.dirty(merge=False, branch=False, missing=True):
5854 raise util.Abort(_("uncommitted changes"))
5858 raise util.Abort(_("uncommitted changes"))
5855 if rev is None:
5859 if rev is None:
5856 rev = repo[repo[None].branch()].rev()
5860 rev = repo[repo[None].branch()].rev()
5857 mergemod._checkunknown(repo, repo[None], repo[rev])
5861 mergemod._checkunknown(repo, repo[None], repo[rev])
5858
5862
5859 if clean:
5863 if clean:
5860 ret = hg.clean(repo, rev)
5864 ret = hg.clean(repo, rev)
5861 else:
5865 else:
5862 ret = hg.update(repo, rev)
5866 ret = hg.update(repo, rev)
5863
5867
5864 if not ret and movemarkfrom:
5868 if not ret and movemarkfrom:
5865 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5869 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5866 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5870 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5867 elif brev in repo._bookmarks:
5871 elif brev in repo._bookmarks:
5868 bookmarks.setcurrent(repo, brev)
5872 bookmarks.setcurrent(repo, brev)
5869 elif brev:
5873 elif brev:
5870 bookmarks.unsetcurrent(repo)
5874 bookmarks.unsetcurrent(repo)
5871
5875
5872 return ret
5876 return ret
5873
5877
5874 @command('verify', [])
5878 @command('verify', [])
5875 def verify(ui, repo):
5879 def verify(ui, repo):
5876 """verify the integrity of the repository
5880 """verify the integrity of the repository
5877
5881
5878 Verify the integrity of the current repository.
5882 Verify the integrity of the current repository.
5879
5883
5880 This will perform an extensive check of the repository's
5884 This will perform an extensive check of the repository's
5881 integrity, validating the hashes and checksums of each entry in
5885 integrity, validating the hashes and checksums of each entry in
5882 the changelog, manifest, and tracked files, as well as the
5886 the changelog, manifest, and tracked files, as well as the
5883 integrity of their crosslinks and indices.
5887 integrity of their crosslinks and indices.
5884
5888
5885 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5889 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5886 for more information about recovery from corruption of the
5890 for more information about recovery from corruption of the
5887 repository.
5891 repository.
5888
5892
5889 Returns 0 on success, 1 if errors are encountered.
5893 Returns 0 on success, 1 if errors are encountered.
5890 """
5894 """
5891 return hg.verify(repo)
5895 return hg.verify(repo)
5892
5896
5893 @command('version', [])
5897 @command('version', [])
5894 def version_(ui):
5898 def version_(ui):
5895 """output version and copyright information"""
5899 """output version and copyright information"""
5896 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5900 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5897 % util.version())
5901 % util.version())
5898 ui.status(_(
5902 ui.status(_(
5899 "(see http://mercurial.selenic.com for more information)\n"
5903 "(see http://mercurial.selenic.com for more information)\n"
5900 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5904 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5901 "This is free software; see the source for copying conditions. "
5905 "This is free software; see the source for copying conditions. "
5902 "There is NO\nwarranty; "
5906 "There is NO\nwarranty; "
5903 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5907 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5904 ))
5908 ))
5905
5909
5906 norepo = ("clone init version help debugcommands debugcomplete"
5910 norepo = ("clone init version help debugcommands debugcomplete"
5907 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5911 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5908 " debugknown debuggetbundle debugbundle")
5912 " debugknown debuggetbundle debugbundle")
5909 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5913 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5910 " debugdata debugindex debugindexdot debugrevlog")
5914 " debugdata debugindex debugindexdot debugrevlog")
5911 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5915 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5912 " remove resolve status debugwalk")
5916 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now