##// END OF EJS Templates
config: mention edit options and config topic in help
Matt Mackall -
r20783:43054dc8 default
parent child Browse files
Show More
@@ -1,5899 +1,5906 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 from hgweb import server as hgweb_server
17 from hgweb import server as hgweb_server
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod
20 import dagparser, context, simplemerge, graphmod
21 import random
21 import random
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import phases, obsolete
23 import phases, obsolete
24
24
25 table = {}
25 table = {}
26
26
27 command = cmdutil.command(table)
27 command = cmdutil.command(table)
28
28
29 # common command options
29 # common command options
30
30
31 globalopts = [
31 globalopts = [
32 ('R', 'repository', '',
32 ('R', 'repository', '',
33 _('repository root directory or name of overlay bundle file'),
33 _('repository root directory or name of overlay bundle file'),
34 _('REPO')),
34 _('REPO')),
35 ('', 'cwd', '',
35 ('', 'cwd', '',
36 _('change working directory'), _('DIR')),
36 _('change working directory'), _('DIR')),
37 ('y', 'noninteractive', None,
37 ('y', 'noninteractive', None,
38 _('do not prompt, automatically pick the first choice for all prompts')),
38 _('do not prompt, automatically pick the first choice for all prompts')),
39 ('q', 'quiet', None, _('suppress output')),
39 ('q', 'quiet', None, _('suppress output')),
40 ('v', 'verbose', None, _('enable additional output')),
40 ('v', 'verbose', None, _('enable additional output')),
41 ('', 'config', [],
41 ('', 'config', [],
42 _('set/override config option (use \'section.name=value\')'),
42 _('set/override config option (use \'section.name=value\')'),
43 _('CONFIG')),
43 _('CONFIG')),
44 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debug', None, _('enable debugging output')),
45 ('', 'debugger', None, _('start debugger')),
45 ('', 'debugger', None, _('start debugger')),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
47 _('ENCODE')),
47 _('ENCODE')),
48 ('', 'encodingmode', encoding.encodingmode,
48 ('', 'encodingmode', encoding.encodingmode,
49 _('set the charset encoding mode'), _('MODE')),
49 _('set the charset encoding mode'), _('MODE')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
51 ('', 'time', None, _('time how long the command takes')),
51 ('', 'time', None, _('time how long the command takes')),
52 ('', 'profile', None, _('print command execution profile')),
52 ('', 'profile', None, _('print command execution profile')),
53 ('', 'version', None, _('output version information and exit')),
53 ('', 'version', None, _('output version information and exit')),
54 ('h', 'help', None, _('display help and exit')),
54 ('h', 'help', None, _('display help and exit')),
55 ('', 'hidden', False, _('consider hidden changesets')),
55 ('', 'hidden', False, _('consider hidden changesets')),
56 ]
56 ]
57
57
58 dryrunopts = [('n', 'dry-run', None,
58 dryrunopts = [('n', 'dry-run', None,
59 _('do not perform actions, just print output'))]
59 _('do not perform actions, just print output'))]
60
60
61 remoteopts = [
61 remoteopts = [
62 ('e', 'ssh', '',
62 ('e', 'ssh', '',
63 _('specify ssh command to use'), _('CMD')),
63 _('specify ssh command to use'), _('CMD')),
64 ('', 'remotecmd', '',
64 ('', 'remotecmd', '',
65 _('specify hg command to run on the remote side'), _('CMD')),
65 _('specify hg command to run on the remote side'), _('CMD')),
66 ('', 'insecure', None,
66 ('', 'insecure', None,
67 _('do not verify server certificate (ignoring web.cacerts config)')),
67 _('do not verify server certificate (ignoring web.cacerts config)')),
68 ]
68 ]
69
69
70 walkopts = [
70 walkopts = [
71 ('I', 'include', [],
71 ('I', 'include', [],
72 _('include names matching the given patterns'), _('PATTERN')),
72 _('include names matching the given patterns'), _('PATTERN')),
73 ('X', 'exclude', [],
73 ('X', 'exclude', [],
74 _('exclude names matching the given patterns'), _('PATTERN')),
74 _('exclude names matching the given patterns'), _('PATTERN')),
75 ]
75 ]
76
76
77 commitopts = [
77 commitopts = [
78 ('m', 'message', '',
78 ('m', 'message', '',
79 _('use text as commit message'), _('TEXT')),
79 _('use text as commit message'), _('TEXT')),
80 ('l', 'logfile', '',
80 ('l', 'logfile', '',
81 _('read commit message from file'), _('FILE')),
81 _('read commit message from file'), _('FILE')),
82 ]
82 ]
83
83
84 commitopts2 = [
84 commitopts2 = [
85 ('d', 'date', '',
85 ('d', 'date', '',
86 _('record the specified date as commit date'), _('DATE')),
86 _('record the specified date as commit date'), _('DATE')),
87 ('u', 'user', '',
87 ('u', 'user', '',
88 _('record the specified user as committer'), _('USER')),
88 _('record the specified user as committer'), _('USER')),
89 ]
89 ]
90
90
91 templateopts = [
91 templateopts = [
92 ('', 'style', '',
92 ('', 'style', '',
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
94 ('T', 'template', '',
94 ('T', 'template', '',
95 _('display with template'), _('TEMPLATE')),
95 _('display with template'), _('TEMPLATE')),
96 ]
96 ]
97
97
98 logopts = [
98 logopts = [
99 ('p', 'patch', None, _('show patch')),
99 ('p', 'patch', None, _('show patch')),
100 ('g', 'git', None, _('use git extended diff format')),
100 ('g', 'git', None, _('use git extended diff format')),
101 ('l', 'limit', '',
101 ('l', 'limit', '',
102 _('limit number of changes displayed'), _('NUM')),
102 _('limit number of changes displayed'), _('NUM')),
103 ('M', 'no-merges', None, _('do not show merges')),
103 ('M', 'no-merges', None, _('do not show merges')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
105 ('G', 'graph', None, _("show the revision DAG")),
105 ('G', 'graph', None, _("show the revision DAG")),
106 ] + templateopts
106 ] + templateopts
107
107
108 diffopts = [
108 diffopts = [
109 ('a', 'text', None, _('treat all files as text')),
109 ('a', 'text', None, _('treat all files as text')),
110 ('g', 'git', None, _('use git extended diff format')),
110 ('g', 'git', None, _('use git extended diff format')),
111 ('', 'nodates', None, _('omit dates from diff headers'))
111 ('', 'nodates', None, _('omit dates from diff headers'))
112 ]
112 ]
113
113
114 diffwsopts = [
114 diffwsopts = [
115 ('w', 'ignore-all-space', None,
115 ('w', 'ignore-all-space', None,
116 _('ignore white space when comparing lines')),
116 _('ignore white space when comparing lines')),
117 ('b', 'ignore-space-change', None,
117 ('b', 'ignore-space-change', None,
118 _('ignore changes in the amount of white space')),
118 _('ignore changes in the amount of white space')),
119 ('B', 'ignore-blank-lines', None,
119 ('B', 'ignore-blank-lines', None,
120 _('ignore changes whose lines are all blank')),
120 _('ignore changes whose lines are all blank')),
121 ]
121 ]
122
122
123 diffopts2 = [
123 diffopts2 = [
124 ('p', 'show-function', None, _('show which function each change is in')),
124 ('p', 'show-function', None, _('show which function each change is in')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
126 ] + diffwsopts + [
126 ] + diffwsopts + [
127 ('U', 'unified', '',
127 ('U', 'unified', '',
128 _('number of lines of context to show'), _('NUM')),
128 _('number of lines of context to show'), _('NUM')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
130 ]
130 ]
131
131
132 mergetoolopts = [
132 mergetoolopts = [
133 ('t', 'tool', '', _('specify merge tool')),
133 ('t', 'tool', '', _('specify merge tool')),
134 ]
134 ]
135
135
136 similarityopts = [
136 similarityopts = [
137 ('s', 'similarity', '',
137 ('s', 'similarity', '',
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
139 ]
139 ]
140
140
141 subrepoopts = [
141 subrepoopts = [
142 ('S', 'subrepos', None,
142 ('S', 'subrepos', None,
143 _('recurse into subrepositories'))
143 _('recurse into subrepositories'))
144 ]
144 ]
145
145
146 # Commands start here, listed alphabetically
146 # Commands start here, listed alphabetically
147
147
148 @command('^add',
148 @command('^add',
149 walkopts + subrepoopts + dryrunopts,
149 walkopts + subrepoopts + dryrunopts,
150 _('[OPTION]... [FILE]...'))
150 _('[OPTION]... [FILE]...'))
151 def add(ui, repo, *pats, **opts):
151 def add(ui, repo, *pats, **opts):
152 """add the specified files on the next commit
152 """add the specified files on the next commit
153
153
154 Schedule files to be version controlled and added to the
154 Schedule files to be version controlled and added to the
155 repository.
155 repository.
156
156
157 The files will be added to the repository at the next commit. To
157 The files will be added to the repository at the next commit. To
158 undo an add before that, see :hg:`forget`.
158 undo an add before that, see :hg:`forget`.
159
159
160 If no names are given, add all files to the repository.
160 If no names are given, add all files to the repository.
161
161
162 .. container:: verbose
162 .. container:: verbose
163
163
164 An example showing how new (unknown) files are added
164 An example showing how new (unknown) files are added
165 automatically by :hg:`add`::
165 automatically by :hg:`add`::
166
166
167 $ ls
167 $ ls
168 foo.c
168 foo.c
169 $ hg status
169 $ hg status
170 ? foo.c
170 ? foo.c
171 $ hg add
171 $ hg add
172 adding foo.c
172 adding foo.c
173 $ hg status
173 $ hg status
174 A foo.c
174 A foo.c
175
175
176 Returns 0 if all files are successfully added.
176 Returns 0 if all files are successfully added.
177 """
177 """
178
178
179 m = scmutil.match(repo[None], pats, opts)
179 m = scmutil.match(repo[None], pats, opts)
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
181 opts.get('subrepos'), prefix="", explicitonly=False)
181 opts.get('subrepos'), prefix="", explicitonly=False)
182 return rejected and 1 or 0
182 return rejected and 1 or 0
183
183
184 @command('addremove',
184 @command('addremove',
185 similarityopts + walkopts + dryrunopts,
185 similarityopts + walkopts + dryrunopts,
186 _('[OPTION]... [FILE]...'))
186 _('[OPTION]... [FILE]...'))
187 def addremove(ui, repo, *pats, **opts):
187 def addremove(ui, repo, *pats, **opts):
188 """add all new files, delete all missing files
188 """add all new files, delete all missing files
189
189
190 Add all new files and remove all missing files from the
190 Add all new files and remove all missing files from the
191 repository.
191 repository.
192
192
193 New files are ignored if they match any of the patterns in
193 New files are ignored if they match any of the patterns in
194 ``.hgignore``. As with add, these changes take effect at the next
194 ``.hgignore``. As with add, these changes take effect at the next
195 commit.
195 commit.
196
196
197 Use the -s/--similarity option to detect renamed files. This
197 Use the -s/--similarity option to detect renamed files. This
198 option takes a percentage between 0 (disabled) and 100 (files must
198 option takes a percentage between 0 (disabled) and 100 (files must
199 be identical) as its parameter. With a parameter greater than 0,
199 be identical) as its parameter. With a parameter greater than 0,
200 this compares every removed file with every added file and records
200 this compares every removed file with every added file and records
201 those similar enough as renames. Detecting renamed files this way
201 those similar enough as renames. Detecting renamed files this way
202 can be expensive. After using this option, :hg:`status -C` can be
202 can be expensive. After using this option, :hg:`status -C` can be
203 used to check which files were identified as moved or renamed. If
203 used to check which files were identified as moved or renamed. If
204 not specified, -s/--similarity defaults to 100 and only renames of
204 not specified, -s/--similarity defaults to 100 and only renames of
205 identical files are detected.
205 identical files are detected.
206
206
207 Returns 0 if all files are successfully added.
207 Returns 0 if all files are successfully added.
208 """
208 """
209 try:
209 try:
210 sim = float(opts.get('similarity') or 100)
210 sim = float(opts.get('similarity') or 100)
211 except ValueError:
211 except ValueError:
212 raise util.Abort(_('similarity must be a number'))
212 raise util.Abort(_('similarity must be a number'))
213 if sim < 0 or sim > 100:
213 if sim < 0 or sim > 100:
214 raise util.Abort(_('similarity must be between 0 and 100'))
214 raise util.Abort(_('similarity must be between 0 and 100'))
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
216
216
217 @command('^annotate|blame',
217 @command('^annotate|blame',
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
219 ('', 'follow', None,
219 ('', 'follow', None,
220 _('follow copies/renames and list the filename (DEPRECATED)')),
220 _('follow copies/renames and list the filename (DEPRECATED)')),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
222 ('a', 'text', None, _('treat all files as text')),
222 ('a', 'text', None, _('treat all files as text')),
223 ('u', 'user', None, _('list the author (long with -v)')),
223 ('u', 'user', None, _('list the author (long with -v)')),
224 ('f', 'file', None, _('list the filename')),
224 ('f', 'file', None, _('list the filename')),
225 ('d', 'date', None, _('list the date (short with -q)')),
225 ('d', 'date', None, _('list the date (short with -q)')),
226 ('n', 'number', None, _('list the revision number (default)')),
226 ('n', 'number', None, _('list the revision number (default)')),
227 ('c', 'changeset', None, _('list the changeset')),
227 ('c', 'changeset', None, _('list the changeset')),
228 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ('l', 'line-number', None, _('show line number at the first appearance'))
229 ] + diffwsopts + walkopts,
229 ] + diffwsopts + walkopts,
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
231 def annotate(ui, repo, *pats, **opts):
231 def annotate(ui, repo, *pats, **opts):
232 """show changeset information by line for each file
232 """show changeset information by line for each file
233
233
234 List changes in files, showing the revision id responsible for
234 List changes in files, showing the revision id responsible for
235 each line
235 each line
236
236
237 This command is useful for discovering when a change was made and
237 This command is useful for discovering when a change was made and
238 by whom.
238 by whom.
239
239
240 Without the -a/--text option, annotate will avoid processing files
240 Without the -a/--text option, annotate will avoid processing files
241 it detects as binary. With -a, annotate will annotate the file
241 it detects as binary. With -a, annotate will annotate the file
242 anyway, although the results will probably be neither useful
242 anyway, although the results will probably be neither useful
243 nor desirable.
243 nor desirable.
244
244
245 Returns 0 on success.
245 Returns 0 on success.
246 """
246 """
247 if opts.get('follow'):
247 if opts.get('follow'):
248 # --follow is deprecated and now just an alias for -f/--file
248 # --follow is deprecated and now just an alias for -f/--file
249 # to mimic the behavior of Mercurial before version 1.5
249 # to mimic the behavior of Mercurial before version 1.5
250 opts['file'] = True
250 opts['file'] = True
251
251
252 datefunc = ui.quiet and util.shortdate or util.datestr
252 datefunc = ui.quiet and util.shortdate or util.datestr
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
254
254
255 if not pats:
255 if not pats:
256 raise util.Abort(_('at least one filename or pattern is required'))
256 raise util.Abort(_('at least one filename or pattern is required'))
257
257
258 hexfn = ui.debugflag and hex or short
258 hexfn = ui.debugflag and hex or short
259
259
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
261 ('number', ' ', lambda x: str(x[0].rev())),
261 ('number', ' ', lambda x: str(x[0].rev())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
263 ('date', ' ', getdate),
263 ('date', ' ', getdate),
264 ('file', ' ', lambda x: x[0].path()),
264 ('file', ' ', lambda x: x[0].path()),
265 ('line_number', ':', lambda x: str(x[1])),
265 ('line_number', ':', lambda x: str(x[1])),
266 ]
266 ]
267
267
268 if (not opts.get('user') and not opts.get('changeset')
268 if (not opts.get('user') and not opts.get('changeset')
269 and not opts.get('date') and not opts.get('file')):
269 and not opts.get('date') and not opts.get('file')):
270 opts['number'] = True
270 opts['number'] = True
271
271
272 linenumber = opts.get('line_number') is not None
272 linenumber = opts.get('line_number') is not None
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
275
275
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
278
278
279 def bad(x, y):
279 def bad(x, y):
280 raise util.Abort("%s: %s" % (x, y))
280 raise util.Abort("%s: %s" % (x, y))
281
281
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 m = scmutil.match(ctx, pats, opts)
283 m = scmutil.match(ctx, pats, opts)
284 m.bad = bad
284 m.bad = bad
285 follow = not opts.get('no_follow')
285 follow = not opts.get('no_follow')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
287 for abs in ctx.walk(m):
287 for abs in ctx.walk(m):
288 fctx = ctx[abs]
288 fctx = ctx[abs]
289 if not opts.get('text') and util.binary(fctx.data()):
289 if not opts.get('text') and util.binary(fctx.data()):
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
291 continue
291 continue
292
292
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
294 diffopts=diffopts)
294 diffopts=diffopts)
295 pieces = []
295 pieces = []
296
296
297 for f, sep in funcmap:
297 for f, sep in funcmap:
298 l = [f(n) for n, dummy in lines]
298 l = [f(n) for n, dummy in lines]
299 if l:
299 if l:
300 sized = [(x, encoding.colwidth(x)) for x in l]
300 sized = [(x, encoding.colwidth(x)) for x in l]
301 ml = max([w for x, w in sized])
301 ml = max([w for x, w in sized])
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
303 for x, w in sized])
303 for x, w in sized])
304
304
305 if pieces:
305 if pieces:
306 for p, l in zip(zip(*pieces), lines):
306 for p, l in zip(zip(*pieces), lines):
307 ui.write("%s: %s" % ("".join(p), l[1]))
307 ui.write("%s: %s" % ("".join(p), l[1]))
308
308
309 if lines and not lines[-1][1].endswith('\n'):
309 if lines and not lines[-1][1].endswith('\n'):
310 ui.write('\n')
310 ui.write('\n')
311
311
312 @command('archive',
312 @command('archive',
313 [('', 'no-decode', None, _('do not pass files through decoders')),
313 [('', 'no-decode', None, _('do not pass files through decoders')),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
315 _('PREFIX')),
315 _('PREFIX')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
318 ] + subrepoopts + walkopts,
318 ] + subrepoopts + walkopts,
319 _('[OPTION]... DEST'))
319 _('[OPTION]... DEST'))
320 def archive(ui, repo, dest, **opts):
320 def archive(ui, repo, dest, **opts):
321 '''create an unversioned archive of a repository revision
321 '''create an unversioned archive of a repository revision
322
322
323 By default, the revision used is the parent of the working
323 By default, the revision used is the parent of the working
324 directory; use -r/--rev to specify a different revision.
324 directory; use -r/--rev to specify a different revision.
325
325
326 The archive type is automatically detected based on file
326 The archive type is automatically detected based on file
327 extension (or override using -t/--type).
327 extension (or override using -t/--type).
328
328
329 .. container:: verbose
329 .. container:: verbose
330
330
331 Examples:
331 Examples:
332
332
333 - create a zip file containing the 1.0 release::
333 - create a zip file containing the 1.0 release::
334
334
335 hg archive -r 1.0 project-1.0.zip
335 hg archive -r 1.0 project-1.0.zip
336
336
337 - create a tarball excluding .hg files::
337 - create a tarball excluding .hg files::
338
338
339 hg archive project.tar.gz -X ".hg*"
339 hg archive project.tar.gz -X ".hg*"
340
340
341 Valid types are:
341 Valid types are:
342
342
343 :``files``: a directory full of files (default)
343 :``files``: a directory full of files (default)
344 :``tar``: tar archive, uncompressed
344 :``tar``: tar archive, uncompressed
345 :``tbz2``: tar archive, compressed using bzip2
345 :``tbz2``: tar archive, compressed using bzip2
346 :``tgz``: tar archive, compressed using gzip
346 :``tgz``: tar archive, compressed using gzip
347 :``uzip``: zip archive, uncompressed
347 :``uzip``: zip archive, uncompressed
348 :``zip``: zip archive, compressed using deflate
348 :``zip``: zip archive, compressed using deflate
349
349
350 The exact name of the destination archive or directory is given
350 The exact name of the destination archive or directory is given
351 using a format string; see :hg:`help export` for details.
351 using a format string; see :hg:`help export` for details.
352
352
353 Each member added to an archive file has a directory prefix
353 Each member added to an archive file has a directory prefix
354 prepended. Use -p/--prefix to specify a format string for the
354 prepended. Use -p/--prefix to specify a format string for the
355 prefix. The default is the basename of the archive, with suffixes
355 prefix. The default is the basename of the archive, with suffixes
356 removed.
356 removed.
357
357
358 Returns 0 on success.
358 Returns 0 on success.
359 '''
359 '''
360
360
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
362 if not ctx:
362 if not ctx:
363 raise util.Abort(_('no working directory: please specify a revision'))
363 raise util.Abort(_('no working directory: please specify a revision'))
364 node = ctx.node()
364 node = ctx.node()
365 dest = cmdutil.makefilename(repo, dest, node)
365 dest = cmdutil.makefilename(repo, dest, node)
366 if os.path.realpath(dest) == repo.root:
366 if os.path.realpath(dest) == repo.root:
367 raise util.Abort(_('repository root cannot be destination'))
367 raise util.Abort(_('repository root cannot be destination'))
368
368
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
370 prefix = opts.get('prefix')
370 prefix = opts.get('prefix')
371
371
372 if dest == '-':
372 if dest == '-':
373 if kind == 'files':
373 if kind == 'files':
374 raise util.Abort(_('cannot archive plain files to stdout'))
374 raise util.Abort(_('cannot archive plain files to stdout'))
375 dest = cmdutil.makefileobj(repo, dest)
375 dest = cmdutil.makefileobj(repo, dest)
376 if not prefix:
376 if not prefix:
377 prefix = os.path.basename(repo.root) + '-%h'
377 prefix = os.path.basename(repo.root) + '-%h'
378
378
379 prefix = cmdutil.makefilename(repo, prefix, node)
379 prefix = cmdutil.makefilename(repo, prefix, node)
380 matchfn = scmutil.match(ctx, [], opts)
380 matchfn = scmutil.match(ctx, [], opts)
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
382 matchfn, prefix, subrepos=opts.get('subrepos'))
382 matchfn, prefix, subrepos=opts.get('subrepos'))
383
383
384 @command('backout',
384 @command('backout',
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
386 ('', 'parent', '',
386 ('', 'parent', '',
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
390 _('[OPTION]... [-r] REV'))
390 _('[OPTION]... [-r] REV'))
391 def backout(ui, repo, node=None, rev=None, **opts):
391 def backout(ui, repo, node=None, rev=None, **opts):
392 '''reverse effect of earlier changeset
392 '''reverse effect of earlier changeset
393
393
394 Prepare a new changeset with the effect of REV undone in the
394 Prepare a new changeset with the effect of REV undone in the
395 current working directory.
395 current working directory.
396
396
397 If REV is the parent of the working directory, then this new changeset
397 If REV is the parent of the working directory, then this new changeset
398 is committed automatically. Otherwise, hg needs to merge the
398 is committed automatically. Otherwise, hg needs to merge the
399 changes and the merged result is left uncommitted.
399 changes and the merged result is left uncommitted.
400
400
401 .. note::
401 .. note::
402
402
403 backout cannot be used to fix either an unwanted or
403 backout cannot be used to fix either an unwanted or
404 incorrect merge.
404 incorrect merge.
405
405
406 .. container:: verbose
406 .. container:: verbose
407
407
408 By default, the pending changeset will have one parent,
408 By default, the pending changeset will have one parent,
409 maintaining a linear history. With --merge, the pending
409 maintaining a linear history. With --merge, the pending
410 changeset will instead have two parents: the old parent of the
410 changeset will instead have two parents: the old parent of the
411 working directory and a new child of REV that simply undoes REV.
411 working directory and a new child of REV that simply undoes REV.
412
412
413 Before version 1.7, the behavior without --merge was equivalent
413 Before version 1.7, the behavior without --merge was equivalent
414 to specifying --merge followed by :hg:`update --clean .` to
414 to specifying --merge followed by :hg:`update --clean .` to
415 cancel the merge and leave the child of REV as a head to be
415 cancel the merge and leave the child of REV as a head to be
416 merged separately.
416 merged separately.
417
417
418 See :hg:`help dates` for a list of formats valid for -d/--date.
418 See :hg:`help dates` for a list of formats valid for -d/--date.
419
419
420 Returns 0 on success.
420 Returns 0 on success.
421 '''
421 '''
422 if rev and node:
422 if rev and node:
423 raise util.Abort(_("please specify just one revision"))
423 raise util.Abort(_("please specify just one revision"))
424
424
425 if not rev:
425 if not rev:
426 rev = node
426 rev = node
427
427
428 if not rev:
428 if not rev:
429 raise util.Abort(_("please specify a revision to backout"))
429 raise util.Abort(_("please specify a revision to backout"))
430
430
431 date = opts.get('date')
431 date = opts.get('date')
432 if date:
432 if date:
433 opts['date'] = util.parsedate(date)
433 opts['date'] = util.parsedate(date)
434
434
435 cmdutil.checkunfinished(repo)
435 cmdutil.checkunfinished(repo)
436 cmdutil.bailifchanged(repo)
436 cmdutil.bailifchanged(repo)
437 node = scmutil.revsingle(repo, rev).node()
437 node = scmutil.revsingle(repo, rev).node()
438
438
439 op1, op2 = repo.dirstate.parents()
439 op1, op2 = repo.dirstate.parents()
440 a = repo.changelog.ancestor(op1, node)
440 a = repo.changelog.ancestor(op1, node)
441 if a != node:
441 if a != node:
442 raise util.Abort(_('cannot backout change on a different branch'))
442 raise util.Abort(_('cannot backout change on a different branch'))
443
443
444 p1, p2 = repo.changelog.parents(node)
444 p1, p2 = repo.changelog.parents(node)
445 if p1 == nullid:
445 if p1 == nullid:
446 raise util.Abort(_('cannot backout a change with no parents'))
446 raise util.Abort(_('cannot backout a change with no parents'))
447 if p2 != nullid:
447 if p2 != nullid:
448 if not opts.get('parent'):
448 if not opts.get('parent'):
449 raise util.Abort(_('cannot backout a merge changeset'))
449 raise util.Abort(_('cannot backout a merge changeset'))
450 p = repo.lookup(opts['parent'])
450 p = repo.lookup(opts['parent'])
451 if p not in (p1, p2):
451 if p not in (p1, p2):
452 raise util.Abort(_('%s is not a parent of %s') %
452 raise util.Abort(_('%s is not a parent of %s') %
453 (short(p), short(node)))
453 (short(p), short(node)))
454 parent = p
454 parent = p
455 else:
455 else:
456 if opts.get('parent'):
456 if opts.get('parent'):
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
458 parent = p1
458 parent = p1
459
459
460 # the backout should appear on the same branch
460 # the backout should appear on the same branch
461 wlock = repo.wlock()
461 wlock = repo.wlock()
462 try:
462 try:
463 branch = repo.dirstate.branch()
463 branch = repo.dirstate.branch()
464 bheads = repo.branchheads(branch)
464 bheads = repo.branchheads(branch)
465 rctx = scmutil.revsingle(repo, hex(parent))
465 rctx = scmutil.revsingle(repo, hex(parent))
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 stats = mergemod.update(repo, parent, True, True, False,
469 stats = mergemod.update(repo, parent, True, True, False,
470 node, False)
470 node, False)
471 repo.setparents(op1, op2)
471 repo.setparents(op1, op2)
472 hg._showstats(repo, stats)
472 hg._showstats(repo, stats)
473 if stats[3]:
473 if stats[3]:
474 repo.ui.status(_("use 'hg resolve' to retry unresolved "
474 repo.ui.status(_("use 'hg resolve' to retry unresolved "
475 "file merges\n"))
475 "file merges\n"))
476 else:
476 else:
477 msg = _("changeset %s backed out, "
477 msg = _("changeset %s backed out, "
478 "don't forget to commit.\n")
478 "don't forget to commit.\n")
479 ui.status(msg % short(node))
479 ui.status(msg % short(node))
480 return stats[3] > 0
480 return stats[3] > 0
481 finally:
481 finally:
482 ui.setconfig('ui', 'forcemerge', '')
482 ui.setconfig('ui', 'forcemerge', '')
483 else:
483 else:
484 hg.clean(repo, node, show_stats=False)
484 hg.clean(repo, node, show_stats=False)
485 repo.dirstate.setbranch(branch)
485 repo.dirstate.setbranch(branch)
486 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
486 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
487
487
488
488
489 e = cmdutil.commiteditor
489 e = cmdutil.commiteditor
490 if not opts['message'] and not opts['logfile']:
490 if not opts['message'] and not opts['logfile']:
491 # we don't translate commit messages
491 # we don't translate commit messages
492 opts['message'] = "Backed out changeset %s" % short(node)
492 opts['message'] = "Backed out changeset %s" % short(node)
493 e = cmdutil.commitforceeditor
493 e = cmdutil.commitforceeditor
494
494
495 def commitfunc(ui, repo, message, match, opts):
495 def commitfunc(ui, repo, message, match, opts):
496 return repo.commit(message, opts.get('user'), opts.get('date'),
496 return repo.commit(message, opts.get('user'), opts.get('date'),
497 match, editor=e)
497 match, editor=e)
498 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
498 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 cmdutil.commitstatus(repo, newnode, branch, bheads)
499 cmdutil.commitstatus(repo, newnode, branch, bheads)
500
500
501 def nice(node):
501 def nice(node):
502 return '%d:%s' % (repo.changelog.rev(node), short(node))
502 return '%d:%s' % (repo.changelog.rev(node), short(node))
503 ui.status(_('changeset %s backs out changeset %s\n') %
503 ui.status(_('changeset %s backs out changeset %s\n') %
504 (nice(repo.changelog.tip()), nice(node)))
504 (nice(repo.changelog.tip()), nice(node)))
505 if opts.get('merge') and op1 != node:
505 if opts.get('merge') and op1 != node:
506 hg.clean(repo, op1, show_stats=False)
506 hg.clean(repo, op1, show_stats=False)
507 ui.status(_('merging with changeset %s\n')
507 ui.status(_('merging with changeset %s\n')
508 % nice(repo.changelog.tip()))
508 % nice(repo.changelog.tip()))
509 try:
509 try:
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
511 return hg.merge(repo, hex(repo.changelog.tip()))
511 return hg.merge(repo, hex(repo.changelog.tip()))
512 finally:
512 finally:
513 ui.setconfig('ui', 'forcemerge', '')
513 ui.setconfig('ui', 'forcemerge', '')
514 finally:
514 finally:
515 wlock.release()
515 wlock.release()
516 return 0
516 return 0
517
517
518 @command('bisect',
518 @command('bisect',
519 [('r', 'reset', False, _('reset bisect state')),
519 [('r', 'reset', False, _('reset bisect state')),
520 ('g', 'good', False, _('mark changeset good')),
520 ('g', 'good', False, _('mark changeset good')),
521 ('b', 'bad', False, _('mark changeset bad')),
521 ('b', 'bad', False, _('mark changeset bad')),
522 ('s', 'skip', False, _('skip testing changeset')),
522 ('s', 'skip', False, _('skip testing changeset')),
523 ('e', 'extend', False, _('extend the bisect range')),
523 ('e', 'extend', False, _('extend the bisect range')),
524 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
524 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
525 ('U', 'noupdate', False, _('do not update to target'))],
525 ('U', 'noupdate', False, _('do not update to target'))],
526 _("[-gbsr] [-U] [-c CMD] [REV]"))
526 _("[-gbsr] [-U] [-c CMD] [REV]"))
527 def bisect(ui, repo, rev=None, extra=None, command=None,
527 def bisect(ui, repo, rev=None, extra=None, command=None,
528 reset=None, good=None, bad=None, skip=None, extend=None,
528 reset=None, good=None, bad=None, skip=None, extend=None,
529 noupdate=None):
529 noupdate=None):
530 """subdivision search of changesets
530 """subdivision search of changesets
531
531
532 This command helps to find changesets which introduce problems. To
532 This command helps to find changesets which introduce problems. To
533 use, mark the earliest changeset you know exhibits the problem as
533 use, mark the earliest changeset you know exhibits the problem as
534 bad, then mark the latest changeset which is free from the problem
534 bad, then mark the latest changeset which is free from the problem
535 as good. Bisect will update your working directory to a revision
535 as good. Bisect will update your working directory to a revision
536 for testing (unless the -U/--noupdate option is specified). Once
536 for testing (unless the -U/--noupdate option is specified). Once
537 you have performed tests, mark the working directory as good or
537 you have performed tests, mark the working directory as good or
538 bad, and bisect will either update to another candidate changeset
538 bad, and bisect will either update to another candidate changeset
539 or announce that it has found the bad revision.
539 or announce that it has found the bad revision.
540
540
541 As a shortcut, you can also use the revision argument to mark a
541 As a shortcut, you can also use the revision argument to mark a
542 revision as good or bad without checking it out first.
542 revision as good or bad without checking it out first.
543
543
544 If you supply a command, it will be used for automatic bisection.
544 If you supply a command, it will be used for automatic bisection.
545 The environment variable HG_NODE will contain the ID of the
545 The environment variable HG_NODE will contain the ID of the
546 changeset being tested. The exit status of the command will be
546 changeset being tested. The exit status of the command will be
547 used to mark revisions as good or bad: status 0 means good, 125
547 used to mark revisions as good or bad: status 0 means good, 125
548 means to skip the revision, 127 (command not found) will abort the
548 means to skip the revision, 127 (command not found) will abort the
549 bisection, and any other non-zero exit status means the revision
549 bisection, and any other non-zero exit status means the revision
550 is bad.
550 is bad.
551
551
552 .. container:: verbose
552 .. container:: verbose
553
553
554 Some examples:
554 Some examples:
555
555
556 - start a bisection with known bad revision 34, and good revision 12::
556 - start a bisection with known bad revision 34, and good revision 12::
557
557
558 hg bisect --bad 34
558 hg bisect --bad 34
559 hg bisect --good 12
559 hg bisect --good 12
560
560
561 - advance the current bisection by marking current revision as good or
561 - advance the current bisection by marking current revision as good or
562 bad::
562 bad::
563
563
564 hg bisect --good
564 hg bisect --good
565 hg bisect --bad
565 hg bisect --bad
566
566
567 - mark the current revision, or a known revision, to be skipped (e.g. if
567 - mark the current revision, or a known revision, to be skipped (e.g. if
568 that revision is not usable because of another issue)::
568 that revision is not usable because of another issue)::
569
569
570 hg bisect --skip
570 hg bisect --skip
571 hg bisect --skip 23
571 hg bisect --skip 23
572
572
573 - skip all revisions that do not touch directories ``foo`` or ``bar``::
573 - skip all revisions that do not touch directories ``foo`` or ``bar``::
574
574
575 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
575 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
576
576
577 - forget the current bisection::
577 - forget the current bisection::
578
578
579 hg bisect --reset
579 hg bisect --reset
580
580
581 - use 'make && make tests' to automatically find the first broken
581 - use 'make && make tests' to automatically find the first broken
582 revision::
582 revision::
583
583
584 hg bisect --reset
584 hg bisect --reset
585 hg bisect --bad 34
585 hg bisect --bad 34
586 hg bisect --good 12
586 hg bisect --good 12
587 hg bisect --command "make && make tests"
587 hg bisect --command "make && make tests"
588
588
589 - see all changesets whose states are already known in the current
589 - see all changesets whose states are already known in the current
590 bisection::
590 bisection::
591
591
592 hg log -r "bisect(pruned)"
592 hg log -r "bisect(pruned)"
593
593
594 - see the changeset currently being bisected (especially useful
594 - see the changeset currently being bisected (especially useful
595 if running with -U/--noupdate)::
595 if running with -U/--noupdate)::
596
596
597 hg log -r "bisect(current)"
597 hg log -r "bisect(current)"
598
598
599 - see all changesets that took part in the current bisection::
599 - see all changesets that took part in the current bisection::
600
600
601 hg log -r "bisect(range)"
601 hg log -r "bisect(range)"
602
602
603 - you can even get a nice graph::
603 - you can even get a nice graph::
604
604
605 hg log --graph -r "bisect(range)"
605 hg log --graph -r "bisect(range)"
606
606
607 See :hg:`help revsets` for more about the `bisect()` keyword.
607 See :hg:`help revsets` for more about the `bisect()` keyword.
608
608
609 Returns 0 on success.
609 Returns 0 on success.
610 """
610 """
611 def extendbisectrange(nodes, good):
611 def extendbisectrange(nodes, good):
612 # bisect is incomplete when it ends on a merge node and
612 # bisect is incomplete when it ends on a merge node and
613 # one of the parent was not checked.
613 # one of the parent was not checked.
614 parents = repo[nodes[0]].parents()
614 parents = repo[nodes[0]].parents()
615 if len(parents) > 1:
615 if len(parents) > 1:
616 side = good and state['bad'] or state['good']
616 side = good and state['bad'] or state['good']
617 num = len(set(i.node() for i in parents) & set(side))
617 num = len(set(i.node() for i in parents) & set(side))
618 if num == 1:
618 if num == 1:
619 return parents[0].ancestor(parents[1])
619 return parents[0].ancestor(parents[1])
620 return None
620 return None
621
621
622 def print_result(nodes, good):
622 def print_result(nodes, good):
623 displayer = cmdutil.show_changeset(ui, repo, {})
623 displayer = cmdutil.show_changeset(ui, repo, {})
624 if len(nodes) == 1:
624 if len(nodes) == 1:
625 # narrowed it down to a single revision
625 # narrowed it down to a single revision
626 if good:
626 if good:
627 ui.write(_("The first good revision is:\n"))
627 ui.write(_("The first good revision is:\n"))
628 else:
628 else:
629 ui.write(_("The first bad revision is:\n"))
629 ui.write(_("The first bad revision is:\n"))
630 displayer.show(repo[nodes[0]])
630 displayer.show(repo[nodes[0]])
631 extendnode = extendbisectrange(nodes, good)
631 extendnode = extendbisectrange(nodes, good)
632 if extendnode is not None:
632 if extendnode is not None:
633 ui.write(_('Not all ancestors of this changeset have been'
633 ui.write(_('Not all ancestors of this changeset have been'
634 ' checked.\nUse bisect --extend to continue the '
634 ' checked.\nUse bisect --extend to continue the '
635 'bisection from\nthe common ancestor, %s.\n')
635 'bisection from\nthe common ancestor, %s.\n')
636 % extendnode)
636 % extendnode)
637 else:
637 else:
638 # multiple possible revisions
638 # multiple possible revisions
639 if good:
639 if good:
640 ui.write(_("Due to skipped revisions, the first "
640 ui.write(_("Due to skipped revisions, the first "
641 "good revision could be any of:\n"))
641 "good revision could be any of:\n"))
642 else:
642 else:
643 ui.write(_("Due to skipped revisions, the first "
643 ui.write(_("Due to skipped revisions, the first "
644 "bad revision could be any of:\n"))
644 "bad revision could be any of:\n"))
645 for n in nodes:
645 for n in nodes:
646 displayer.show(repo[n])
646 displayer.show(repo[n])
647 displayer.close()
647 displayer.close()
648
648
649 def check_state(state, interactive=True):
649 def check_state(state, interactive=True):
650 if not state['good'] or not state['bad']:
650 if not state['good'] or not state['bad']:
651 if (good or bad or skip or reset) and interactive:
651 if (good or bad or skip or reset) and interactive:
652 return
652 return
653 if not state['good']:
653 if not state['good']:
654 raise util.Abort(_('cannot bisect (no known good revisions)'))
654 raise util.Abort(_('cannot bisect (no known good revisions)'))
655 else:
655 else:
656 raise util.Abort(_('cannot bisect (no known bad revisions)'))
656 raise util.Abort(_('cannot bisect (no known bad revisions)'))
657 return True
657 return True
658
658
659 # backward compatibility
659 # backward compatibility
660 if rev in "good bad reset init".split():
660 if rev in "good bad reset init".split():
661 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
661 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
662 cmd, rev, extra = rev, extra, None
662 cmd, rev, extra = rev, extra, None
663 if cmd == "good":
663 if cmd == "good":
664 good = True
664 good = True
665 elif cmd == "bad":
665 elif cmd == "bad":
666 bad = True
666 bad = True
667 else:
667 else:
668 reset = True
668 reset = True
669 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
669 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
670 raise util.Abort(_('incompatible arguments'))
670 raise util.Abort(_('incompatible arguments'))
671
671
672 cmdutil.checkunfinished(repo)
672 cmdutil.checkunfinished(repo)
673
673
674 if reset:
674 if reset:
675 p = repo.join("bisect.state")
675 p = repo.join("bisect.state")
676 if os.path.exists(p):
676 if os.path.exists(p):
677 os.unlink(p)
677 os.unlink(p)
678 return
678 return
679
679
680 state = hbisect.load_state(repo)
680 state = hbisect.load_state(repo)
681
681
682 if command:
682 if command:
683 changesets = 1
683 changesets = 1
684 if noupdate:
684 if noupdate:
685 try:
685 try:
686 node = state['current'][0]
686 node = state['current'][0]
687 except LookupError:
687 except LookupError:
688 raise util.Abort(_('current bisect revision is unknown - '
688 raise util.Abort(_('current bisect revision is unknown - '
689 'start a new bisect to fix'))
689 'start a new bisect to fix'))
690 else:
690 else:
691 node, p2 = repo.dirstate.parents()
691 node, p2 = repo.dirstate.parents()
692 if p2 != nullid:
692 if p2 != nullid:
693 raise util.Abort(_('current bisect revision is a merge'))
693 raise util.Abort(_('current bisect revision is a merge'))
694 try:
694 try:
695 while changesets:
695 while changesets:
696 # update state
696 # update state
697 state['current'] = [node]
697 state['current'] = [node]
698 hbisect.save_state(repo, state)
698 hbisect.save_state(repo, state)
699 status = util.system(command,
699 status = util.system(command,
700 environ={'HG_NODE': hex(node)},
700 environ={'HG_NODE': hex(node)},
701 out=ui.fout)
701 out=ui.fout)
702 if status == 125:
702 if status == 125:
703 transition = "skip"
703 transition = "skip"
704 elif status == 0:
704 elif status == 0:
705 transition = "good"
705 transition = "good"
706 # status < 0 means process was killed
706 # status < 0 means process was killed
707 elif status == 127:
707 elif status == 127:
708 raise util.Abort(_("failed to execute %s") % command)
708 raise util.Abort(_("failed to execute %s") % command)
709 elif status < 0:
709 elif status < 0:
710 raise util.Abort(_("%s killed") % command)
710 raise util.Abort(_("%s killed") % command)
711 else:
711 else:
712 transition = "bad"
712 transition = "bad"
713 ctx = scmutil.revsingle(repo, rev, node)
713 ctx = scmutil.revsingle(repo, rev, node)
714 rev = None # clear for future iterations
714 rev = None # clear for future iterations
715 state[transition].append(ctx.node())
715 state[transition].append(ctx.node())
716 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
716 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
717 check_state(state, interactive=False)
717 check_state(state, interactive=False)
718 # bisect
718 # bisect
719 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
719 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
720 # update to next check
720 # update to next check
721 node = nodes[0]
721 node = nodes[0]
722 if not noupdate:
722 if not noupdate:
723 cmdutil.bailifchanged(repo)
723 cmdutil.bailifchanged(repo)
724 hg.clean(repo, node, show_stats=False)
724 hg.clean(repo, node, show_stats=False)
725 finally:
725 finally:
726 state['current'] = [node]
726 state['current'] = [node]
727 hbisect.save_state(repo, state)
727 hbisect.save_state(repo, state)
728 print_result(nodes, bgood)
728 print_result(nodes, bgood)
729 return
729 return
730
730
731 # update state
731 # update state
732
732
733 if rev:
733 if rev:
734 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
734 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
735 else:
735 else:
736 nodes = [repo.lookup('.')]
736 nodes = [repo.lookup('.')]
737
737
738 if good or bad or skip:
738 if good or bad or skip:
739 if good:
739 if good:
740 state['good'] += nodes
740 state['good'] += nodes
741 elif bad:
741 elif bad:
742 state['bad'] += nodes
742 state['bad'] += nodes
743 elif skip:
743 elif skip:
744 state['skip'] += nodes
744 state['skip'] += nodes
745 hbisect.save_state(repo, state)
745 hbisect.save_state(repo, state)
746
746
747 if not check_state(state):
747 if not check_state(state):
748 return
748 return
749
749
750 # actually bisect
750 # actually bisect
751 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
751 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
752 if extend:
752 if extend:
753 if not changesets:
753 if not changesets:
754 extendnode = extendbisectrange(nodes, good)
754 extendnode = extendbisectrange(nodes, good)
755 if extendnode is not None:
755 if extendnode is not None:
756 ui.write(_("Extending search to changeset %d:%s\n"
756 ui.write(_("Extending search to changeset %d:%s\n"
757 % (extendnode.rev(), extendnode)))
757 % (extendnode.rev(), extendnode)))
758 state['current'] = [extendnode.node()]
758 state['current'] = [extendnode.node()]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if noupdate:
760 if noupdate:
761 return
761 return
762 cmdutil.bailifchanged(repo)
762 cmdutil.bailifchanged(repo)
763 return hg.clean(repo, extendnode.node())
763 return hg.clean(repo, extendnode.node())
764 raise util.Abort(_("nothing to extend"))
764 raise util.Abort(_("nothing to extend"))
765
765
766 if changesets == 0:
766 if changesets == 0:
767 print_result(nodes, good)
767 print_result(nodes, good)
768 else:
768 else:
769 assert len(nodes) == 1 # only a single node can be tested next
769 assert len(nodes) == 1 # only a single node can be tested next
770 node = nodes[0]
770 node = nodes[0]
771 # compute the approximate number of remaining tests
771 # compute the approximate number of remaining tests
772 tests, size = 0, 2
772 tests, size = 0, 2
773 while size <= changesets:
773 while size <= changesets:
774 tests, size = tests + 1, size * 2
774 tests, size = tests + 1, size * 2
775 rev = repo.changelog.rev(node)
775 rev = repo.changelog.rev(node)
776 ui.write(_("Testing changeset %d:%s "
776 ui.write(_("Testing changeset %d:%s "
777 "(%d changesets remaining, ~%d tests)\n")
777 "(%d changesets remaining, ~%d tests)\n")
778 % (rev, short(node), changesets, tests))
778 % (rev, short(node), changesets, tests))
779 state['current'] = [node]
779 state['current'] = [node]
780 hbisect.save_state(repo, state)
780 hbisect.save_state(repo, state)
781 if not noupdate:
781 if not noupdate:
782 cmdutil.bailifchanged(repo)
782 cmdutil.bailifchanged(repo)
783 return hg.clean(repo, node)
783 return hg.clean(repo, node)
784
784
785 @command('bookmarks|bookmark',
785 @command('bookmarks|bookmark',
786 [('f', 'force', False, _('force')),
786 [('f', 'force', False, _('force')),
787 ('r', 'rev', '', _('revision'), _('REV')),
787 ('r', 'rev', '', _('revision'), _('REV')),
788 ('d', 'delete', False, _('delete a given bookmark')),
788 ('d', 'delete', False, _('delete a given bookmark')),
789 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
789 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
790 ('i', 'inactive', False, _('mark a bookmark inactive'))],
790 ('i', 'inactive', False, _('mark a bookmark inactive'))],
791 _('hg bookmarks [OPTIONS]... [NAME]...'))
791 _('hg bookmarks [OPTIONS]... [NAME]...'))
792 def bookmark(ui, repo, *names, **opts):
792 def bookmark(ui, repo, *names, **opts):
793 '''track a line of development with movable markers
793 '''track a line of development with movable markers
794
794
795 Bookmarks are pointers to certain commits that move when committing.
795 Bookmarks are pointers to certain commits that move when committing.
796 Bookmarks are local. They can be renamed, copied and deleted. It is
796 Bookmarks are local. They can be renamed, copied and deleted. It is
797 possible to use :hg:`merge NAME` to merge from a given bookmark, and
797 possible to use :hg:`merge NAME` to merge from a given bookmark, and
798 :hg:`update NAME` to update to a given bookmark.
798 :hg:`update NAME` to update to a given bookmark.
799
799
800 You can use :hg:`bookmark NAME` to set a bookmark on the working
800 You can use :hg:`bookmark NAME` to set a bookmark on the working
801 directory's parent revision with the given name. If you specify
801 directory's parent revision with the given name. If you specify
802 a revision using -r REV (where REV may be an existing bookmark),
802 a revision using -r REV (where REV may be an existing bookmark),
803 the bookmark is assigned to that revision.
803 the bookmark is assigned to that revision.
804
804
805 Bookmarks can be pushed and pulled between repositories (see :hg:`help
805 Bookmarks can be pushed and pulled between repositories (see :hg:`help
806 push` and :hg:`help pull`). This requires both the local and remote
806 push` and :hg:`help pull`). This requires both the local and remote
807 repositories to support bookmarks. For versions prior to 1.8, this means
807 repositories to support bookmarks. For versions prior to 1.8, this means
808 the bookmarks extension must be enabled.
808 the bookmarks extension must be enabled.
809
809
810 If you set a bookmark called '@', new clones of the repository will
810 If you set a bookmark called '@', new clones of the repository will
811 have that revision checked out (and the bookmark made active) by
811 have that revision checked out (and the bookmark made active) by
812 default.
812 default.
813
813
814 With -i/--inactive, the new bookmark will not be made the active
814 With -i/--inactive, the new bookmark will not be made the active
815 bookmark. If -r/--rev is given, the new bookmark will not be made
815 bookmark. If -r/--rev is given, the new bookmark will not be made
816 active even if -i/--inactive is not given. If no NAME is given, the
816 active even if -i/--inactive is not given. If no NAME is given, the
817 current active bookmark will be marked inactive.
817 current active bookmark will be marked inactive.
818 '''
818 '''
819 force = opts.get('force')
819 force = opts.get('force')
820 rev = opts.get('rev')
820 rev = opts.get('rev')
821 delete = opts.get('delete')
821 delete = opts.get('delete')
822 rename = opts.get('rename')
822 rename = opts.get('rename')
823 inactive = opts.get('inactive')
823 inactive = opts.get('inactive')
824
824
825 def checkformat(mark):
825 def checkformat(mark):
826 mark = mark.strip()
826 mark = mark.strip()
827 if not mark:
827 if not mark:
828 raise util.Abort(_("bookmark names cannot consist entirely of "
828 raise util.Abort(_("bookmark names cannot consist entirely of "
829 "whitespace"))
829 "whitespace"))
830 scmutil.checknewlabel(repo, mark, 'bookmark')
830 scmutil.checknewlabel(repo, mark, 'bookmark')
831 return mark
831 return mark
832
832
833 def checkconflict(repo, mark, cur, force=False, target=None):
833 def checkconflict(repo, mark, cur, force=False, target=None):
834 if mark in marks and not force:
834 if mark in marks and not force:
835 if target:
835 if target:
836 if marks[mark] == target and target == cur:
836 if marks[mark] == target and target == cur:
837 # re-activating a bookmark
837 # re-activating a bookmark
838 return
838 return
839 anc = repo.changelog.ancestors([repo[target].rev()])
839 anc = repo.changelog.ancestors([repo[target].rev()])
840 bmctx = repo[marks[mark]]
840 bmctx = repo[marks[mark]]
841 divs = [repo[b].node() for b in marks
841 divs = [repo[b].node() for b in marks
842 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
842 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
843
843
844 # allow resolving a single divergent bookmark even if moving
844 # allow resolving a single divergent bookmark even if moving
845 # the bookmark across branches when a revision is specified
845 # the bookmark across branches when a revision is specified
846 # that contains a divergent bookmark
846 # that contains a divergent bookmark
847 if bmctx.rev() not in anc and target in divs:
847 if bmctx.rev() not in anc and target in divs:
848 bookmarks.deletedivergent(repo, [target], mark)
848 bookmarks.deletedivergent(repo, [target], mark)
849 return
849 return
850
850
851 deletefrom = [b for b in divs
851 deletefrom = [b for b in divs
852 if repo[b].rev() in anc or b == target]
852 if repo[b].rev() in anc or b == target]
853 bookmarks.deletedivergent(repo, deletefrom, mark)
853 bookmarks.deletedivergent(repo, deletefrom, mark)
854 if bookmarks.validdest(repo, bmctx, repo[target]):
854 if bookmarks.validdest(repo, bmctx, repo[target]):
855 ui.status(_("moving bookmark '%s' forward from %s\n") %
855 ui.status(_("moving bookmark '%s' forward from %s\n") %
856 (mark, short(bmctx.node())))
856 (mark, short(bmctx.node())))
857 return
857 return
858 raise util.Abort(_("bookmark '%s' already exists "
858 raise util.Abort(_("bookmark '%s' already exists "
859 "(use -f to force)") % mark)
859 "(use -f to force)") % mark)
860 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
860 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
861 and not force):
861 and not force):
862 raise util.Abort(
862 raise util.Abort(
863 _("a bookmark cannot have the name of an existing branch"))
863 _("a bookmark cannot have the name of an existing branch"))
864
864
865 if delete and rename:
865 if delete and rename:
866 raise util.Abort(_("--delete and --rename are incompatible"))
866 raise util.Abort(_("--delete and --rename are incompatible"))
867 if delete and rev:
867 if delete and rev:
868 raise util.Abort(_("--rev is incompatible with --delete"))
868 raise util.Abort(_("--rev is incompatible with --delete"))
869 if rename and rev:
869 if rename and rev:
870 raise util.Abort(_("--rev is incompatible with --rename"))
870 raise util.Abort(_("--rev is incompatible with --rename"))
871 if not names and (delete or rev):
871 if not names and (delete or rev):
872 raise util.Abort(_("bookmark name required"))
872 raise util.Abort(_("bookmark name required"))
873
873
874 if delete or rename or names or inactive:
874 if delete or rename or names or inactive:
875 wlock = repo.wlock()
875 wlock = repo.wlock()
876 try:
876 try:
877 cur = repo.changectx('.').node()
877 cur = repo.changectx('.').node()
878 marks = repo._bookmarks
878 marks = repo._bookmarks
879 if delete:
879 if delete:
880 for mark in names:
880 for mark in names:
881 if mark not in marks:
881 if mark not in marks:
882 raise util.Abort(_("bookmark '%s' does not exist") %
882 raise util.Abort(_("bookmark '%s' does not exist") %
883 mark)
883 mark)
884 if mark == repo._bookmarkcurrent:
884 if mark == repo._bookmarkcurrent:
885 bookmarks.unsetcurrent(repo)
885 bookmarks.unsetcurrent(repo)
886 del marks[mark]
886 del marks[mark]
887 marks.write()
887 marks.write()
888
888
889 elif rename:
889 elif rename:
890 if not names:
890 if not names:
891 raise util.Abort(_("new bookmark name required"))
891 raise util.Abort(_("new bookmark name required"))
892 elif len(names) > 1:
892 elif len(names) > 1:
893 raise util.Abort(_("only one new bookmark name allowed"))
893 raise util.Abort(_("only one new bookmark name allowed"))
894 mark = checkformat(names[0])
894 mark = checkformat(names[0])
895 if rename not in marks:
895 if rename not in marks:
896 raise util.Abort(_("bookmark '%s' does not exist") % rename)
896 raise util.Abort(_("bookmark '%s' does not exist") % rename)
897 checkconflict(repo, mark, cur, force)
897 checkconflict(repo, mark, cur, force)
898 marks[mark] = marks[rename]
898 marks[mark] = marks[rename]
899 if repo._bookmarkcurrent == rename and not inactive:
899 if repo._bookmarkcurrent == rename and not inactive:
900 bookmarks.setcurrent(repo, mark)
900 bookmarks.setcurrent(repo, mark)
901 del marks[rename]
901 del marks[rename]
902 marks.write()
902 marks.write()
903
903
904 elif names:
904 elif names:
905 newact = None
905 newact = None
906 for mark in names:
906 for mark in names:
907 mark = checkformat(mark)
907 mark = checkformat(mark)
908 if newact is None:
908 if newact is None:
909 newact = mark
909 newact = mark
910 if inactive and mark == repo._bookmarkcurrent:
910 if inactive and mark == repo._bookmarkcurrent:
911 bookmarks.unsetcurrent(repo)
911 bookmarks.unsetcurrent(repo)
912 return
912 return
913 tgt = cur
913 tgt = cur
914 if rev:
914 if rev:
915 tgt = scmutil.revsingle(repo, rev).node()
915 tgt = scmutil.revsingle(repo, rev).node()
916 checkconflict(repo, mark, cur, force, tgt)
916 checkconflict(repo, mark, cur, force, tgt)
917 marks[mark] = tgt
917 marks[mark] = tgt
918 if not inactive and cur == marks[newact] and not rev:
918 if not inactive and cur == marks[newact] and not rev:
919 bookmarks.setcurrent(repo, newact)
919 bookmarks.setcurrent(repo, newact)
920 elif cur != tgt and newact == repo._bookmarkcurrent:
920 elif cur != tgt and newact == repo._bookmarkcurrent:
921 bookmarks.unsetcurrent(repo)
921 bookmarks.unsetcurrent(repo)
922 marks.write()
922 marks.write()
923
923
924 elif inactive:
924 elif inactive:
925 if len(marks) == 0:
925 if len(marks) == 0:
926 ui.status(_("no bookmarks set\n"))
926 ui.status(_("no bookmarks set\n"))
927 elif not repo._bookmarkcurrent:
927 elif not repo._bookmarkcurrent:
928 ui.status(_("no active bookmark\n"))
928 ui.status(_("no active bookmark\n"))
929 else:
929 else:
930 bookmarks.unsetcurrent(repo)
930 bookmarks.unsetcurrent(repo)
931 finally:
931 finally:
932 wlock.release()
932 wlock.release()
933 else: # show bookmarks
933 else: # show bookmarks
934 hexfn = ui.debugflag and hex or short
934 hexfn = ui.debugflag and hex or short
935 marks = repo._bookmarks
935 marks = repo._bookmarks
936 if len(marks) == 0:
936 if len(marks) == 0:
937 ui.status(_("no bookmarks set\n"))
937 ui.status(_("no bookmarks set\n"))
938 else:
938 else:
939 for bmark, n in sorted(marks.iteritems()):
939 for bmark, n in sorted(marks.iteritems()):
940 current = repo._bookmarkcurrent
940 current = repo._bookmarkcurrent
941 if bmark == current:
941 if bmark == current:
942 prefix, label = '*', 'bookmarks.current'
942 prefix, label = '*', 'bookmarks.current'
943 else:
943 else:
944 prefix, label = ' ', ''
944 prefix, label = ' ', ''
945
945
946 if ui.quiet:
946 if ui.quiet:
947 ui.write("%s\n" % bmark, label=label)
947 ui.write("%s\n" % bmark, label=label)
948 else:
948 else:
949 ui.write(" %s %-25s %d:%s\n" % (
949 ui.write(" %s %-25s %d:%s\n" % (
950 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
950 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
951 label=label)
951 label=label)
952
952
953 @command('branch',
953 @command('branch',
954 [('f', 'force', None,
954 [('f', 'force', None,
955 _('set branch name even if it shadows an existing branch')),
955 _('set branch name even if it shadows an existing branch')),
956 ('C', 'clean', None, _('reset branch name to parent branch name'))],
956 ('C', 'clean', None, _('reset branch name to parent branch name'))],
957 _('[-fC] [NAME]'))
957 _('[-fC] [NAME]'))
958 def branch(ui, repo, label=None, **opts):
958 def branch(ui, repo, label=None, **opts):
959 """set or show the current branch name
959 """set or show the current branch name
960
960
961 .. note::
961 .. note::
962
962
963 Branch names are permanent and global. Use :hg:`bookmark` to create a
963 Branch names are permanent and global. Use :hg:`bookmark` to create a
964 light-weight bookmark instead. See :hg:`help glossary` for more
964 light-weight bookmark instead. See :hg:`help glossary` for more
965 information about named branches and bookmarks.
965 information about named branches and bookmarks.
966
966
967 With no argument, show the current branch name. With one argument,
967 With no argument, show the current branch name. With one argument,
968 set the working directory branch name (the branch will not exist
968 set the working directory branch name (the branch will not exist
969 in the repository until the next commit). Standard practice
969 in the repository until the next commit). Standard practice
970 recommends that primary development take place on the 'default'
970 recommends that primary development take place on the 'default'
971 branch.
971 branch.
972
972
973 Unless -f/--force is specified, branch will not let you set a
973 Unless -f/--force is specified, branch will not let you set a
974 branch name that already exists, even if it's inactive.
974 branch name that already exists, even if it's inactive.
975
975
976 Use -C/--clean to reset the working directory branch to that of
976 Use -C/--clean to reset the working directory branch to that of
977 the parent of the working directory, negating a previous branch
977 the parent of the working directory, negating a previous branch
978 change.
978 change.
979
979
980 Use the command :hg:`update` to switch to an existing branch. Use
980 Use the command :hg:`update` to switch to an existing branch. Use
981 :hg:`commit --close-branch` to mark this branch as closed.
981 :hg:`commit --close-branch` to mark this branch as closed.
982
982
983 Returns 0 on success.
983 Returns 0 on success.
984 """
984 """
985 if label:
985 if label:
986 label = label.strip()
986 label = label.strip()
987
987
988 if not opts.get('clean') and not label:
988 if not opts.get('clean') and not label:
989 ui.write("%s\n" % repo.dirstate.branch())
989 ui.write("%s\n" % repo.dirstate.branch())
990 return
990 return
991
991
992 wlock = repo.wlock()
992 wlock = repo.wlock()
993 try:
993 try:
994 if opts.get('clean'):
994 if opts.get('clean'):
995 label = repo[None].p1().branch()
995 label = repo[None].p1().branch()
996 repo.dirstate.setbranch(label)
996 repo.dirstate.setbranch(label)
997 ui.status(_('reset working directory to branch %s\n') % label)
997 ui.status(_('reset working directory to branch %s\n') % label)
998 elif label:
998 elif label:
999 if not opts.get('force') and label in repo.branchmap():
999 if not opts.get('force') and label in repo.branchmap():
1000 if label not in [p.branch() for p in repo.parents()]:
1000 if label not in [p.branch() for p in repo.parents()]:
1001 raise util.Abort(_('a branch of the same name already'
1001 raise util.Abort(_('a branch of the same name already'
1002 ' exists'),
1002 ' exists'),
1003 # i18n: "it" refers to an existing branch
1003 # i18n: "it" refers to an existing branch
1004 hint=_("use 'hg update' to switch to it"))
1004 hint=_("use 'hg update' to switch to it"))
1005 scmutil.checknewlabel(repo, label, 'branch')
1005 scmutil.checknewlabel(repo, label, 'branch')
1006 repo.dirstate.setbranch(label)
1006 repo.dirstate.setbranch(label)
1007 ui.status(_('marked working directory as branch %s\n') % label)
1007 ui.status(_('marked working directory as branch %s\n') % label)
1008 ui.status(_('(branches are permanent and global, '
1008 ui.status(_('(branches are permanent and global, '
1009 'did you want a bookmark?)\n'))
1009 'did you want a bookmark?)\n'))
1010 finally:
1010 finally:
1011 wlock.release()
1011 wlock.release()
1012
1012
1013 @command('branches',
1013 @command('branches',
1014 [('a', 'active', False, _('show only branches that have unmerged heads')),
1014 [('a', 'active', False, _('show only branches that have unmerged heads')),
1015 ('c', 'closed', False, _('show normal and closed branches'))],
1015 ('c', 'closed', False, _('show normal and closed branches'))],
1016 _('[-ac]'))
1016 _('[-ac]'))
1017 def branches(ui, repo, active=False, closed=False):
1017 def branches(ui, repo, active=False, closed=False):
1018 """list repository named branches
1018 """list repository named branches
1019
1019
1020 List the repository's named branches, indicating which ones are
1020 List the repository's named branches, indicating which ones are
1021 inactive. If -c/--closed is specified, also list branches which have
1021 inactive. If -c/--closed is specified, also list branches which have
1022 been marked closed (see :hg:`commit --close-branch`).
1022 been marked closed (see :hg:`commit --close-branch`).
1023
1023
1024 If -a/--active is specified, only show active branches. A branch
1024 If -a/--active is specified, only show active branches. A branch
1025 is considered active if it contains repository heads.
1025 is considered active if it contains repository heads.
1026
1026
1027 Use the command :hg:`update` to switch to an existing branch.
1027 Use the command :hg:`update` to switch to an existing branch.
1028
1028
1029 Returns 0.
1029 Returns 0.
1030 """
1030 """
1031
1031
1032 hexfunc = ui.debugflag and hex or short
1032 hexfunc = ui.debugflag and hex or short
1033
1033
1034 allheads = set(repo.heads())
1034 allheads = set(repo.heads())
1035 branches = []
1035 branches = []
1036 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1036 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1037 isactive = not isclosed and bool(set(heads) & allheads)
1037 isactive = not isclosed and bool(set(heads) & allheads)
1038 branches.append((tag, repo[tip], isactive, not isclosed))
1038 branches.append((tag, repo[tip], isactive, not isclosed))
1039 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1039 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1040 reverse=True)
1040 reverse=True)
1041
1041
1042 for tag, ctx, isactive, isopen in branches:
1042 for tag, ctx, isactive, isopen in branches:
1043 if (not active) or isactive:
1043 if (not active) or isactive:
1044 if isactive:
1044 if isactive:
1045 label = 'branches.active'
1045 label = 'branches.active'
1046 notice = ''
1046 notice = ''
1047 elif not isopen:
1047 elif not isopen:
1048 if not closed:
1048 if not closed:
1049 continue
1049 continue
1050 label = 'branches.closed'
1050 label = 'branches.closed'
1051 notice = _(' (closed)')
1051 notice = _(' (closed)')
1052 else:
1052 else:
1053 label = 'branches.inactive'
1053 label = 'branches.inactive'
1054 notice = _(' (inactive)')
1054 notice = _(' (inactive)')
1055 if tag == repo.dirstate.branch():
1055 if tag == repo.dirstate.branch():
1056 label = 'branches.current'
1056 label = 'branches.current'
1057 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1057 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1058 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1058 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1059 'log.changeset changeset.%s' % ctx.phasestr())
1059 'log.changeset changeset.%s' % ctx.phasestr())
1060 labeledtag = ui.label(tag, label)
1060 labeledtag = ui.label(tag, label)
1061 if ui.quiet:
1061 if ui.quiet:
1062 ui.write("%s\n" % labeledtag)
1062 ui.write("%s\n" % labeledtag)
1063 else:
1063 else:
1064 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1064 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1065
1065
1066 @command('bundle',
1066 @command('bundle',
1067 [('f', 'force', None, _('run even when the destination is unrelated')),
1067 [('f', 'force', None, _('run even when the destination is unrelated')),
1068 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1068 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1069 _('REV')),
1069 _('REV')),
1070 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1070 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1071 _('BRANCH')),
1071 _('BRANCH')),
1072 ('', 'base', [],
1072 ('', 'base', [],
1073 _('a base changeset assumed to be available at the destination'),
1073 _('a base changeset assumed to be available at the destination'),
1074 _('REV')),
1074 _('REV')),
1075 ('a', 'all', None, _('bundle all changesets in the repository')),
1075 ('a', 'all', None, _('bundle all changesets in the repository')),
1076 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1076 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1077 ] + remoteopts,
1077 ] + remoteopts,
1078 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1078 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1079 def bundle(ui, repo, fname, dest=None, **opts):
1079 def bundle(ui, repo, fname, dest=None, **opts):
1080 """create a changegroup file
1080 """create a changegroup file
1081
1081
1082 Generate a compressed changegroup file collecting changesets not
1082 Generate a compressed changegroup file collecting changesets not
1083 known to be in another repository.
1083 known to be in another repository.
1084
1084
1085 If you omit the destination repository, then hg assumes the
1085 If you omit the destination repository, then hg assumes the
1086 destination will have all the nodes you specify with --base
1086 destination will have all the nodes you specify with --base
1087 parameters. To create a bundle containing all changesets, use
1087 parameters. To create a bundle containing all changesets, use
1088 -a/--all (or --base null).
1088 -a/--all (or --base null).
1089
1089
1090 You can change compression method with the -t/--type option.
1090 You can change compression method with the -t/--type option.
1091 The available compression methods are: none, bzip2, and
1091 The available compression methods are: none, bzip2, and
1092 gzip (by default, bundles are compressed using bzip2).
1092 gzip (by default, bundles are compressed using bzip2).
1093
1093
1094 The bundle file can then be transferred using conventional means
1094 The bundle file can then be transferred using conventional means
1095 and applied to another repository with the unbundle or pull
1095 and applied to another repository with the unbundle or pull
1096 command. This is useful when direct push and pull are not
1096 command. This is useful when direct push and pull are not
1097 available or when exporting an entire repository is undesirable.
1097 available or when exporting an entire repository is undesirable.
1098
1098
1099 Applying bundles preserves all changeset contents including
1099 Applying bundles preserves all changeset contents including
1100 permissions, copy/rename information, and revision history.
1100 permissions, copy/rename information, and revision history.
1101
1101
1102 Returns 0 on success, 1 if no changes found.
1102 Returns 0 on success, 1 if no changes found.
1103 """
1103 """
1104 revs = None
1104 revs = None
1105 if 'rev' in opts:
1105 if 'rev' in opts:
1106 revs = scmutil.revrange(repo, opts['rev'])
1106 revs = scmutil.revrange(repo, opts['rev'])
1107
1107
1108 bundletype = opts.get('type', 'bzip2').lower()
1108 bundletype = opts.get('type', 'bzip2').lower()
1109 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1109 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1110 bundletype = btypes.get(bundletype)
1110 bundletype = btypes.get(bundletype)
1111 if bundletype not in changegroup.bundletypes:
1111 if bundletype not in changegroup.bundletypes:
1112 raise util.Abort(_('unknown bundle type specified with --type'))
1112 raise util.Abort(_('unknown bundle type specified with --type'))
1113
1113
1114 if opts.get('all'):
1114 if opts.get('all'):
1115 base = ['null']
1115 base = ['null']
1116 else:
1116 else:
1117 base = scmutil.revrange(repo, opts.get('base'))
1117 base = scmutil.revrange(repo, opts.get('base'))
1118 # TODO: get desired bundlecaps from command line.
1118 # TODO: get desired bundlecaps from command line.
1119 bundlecaps = None
1119 bundlecaps = None
1120 if base:
1120 if base:
1121 if dest:
1121 if dest:
1122 raise util.Abort(_("--base is incompatible with specifying "
1122 raise util.Abort(_("--base is incompatible with specifying "
1123 "a destination"))
1123 "a destination"))
1124 common = [repo.lookup(rev) for rev in base]
1124 common = [repo.lookup(rev) for rev in base]
1125 heads = revs and map(repo.lookup, revs) or revs
1125 heads = revs and map(repo.lookup, revs) or revs
1126 cg = repo.getbundle('bundle', heads=heads, common=common,
1126 cg = repo.getbundle('bundle', heads=heads, common=common,
1127 bundlecaps=bundlecaps)
1127 bundlecaps=bundlecaps)
1128 outgoing = None
1128 outgoing = None
1129 else:
1129 else:
1130 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1130 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1131 dest, branches = hg.parseurl(dest, opts.get('branch'))
1131 dest, branches = hg.parseurl(dest, opts.get('branch'))
1132 other = hg.peer(repo, opts, dest)
1132 other = hg.peer(repo, opts, dest)
1133 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1133 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1134 heads = revs and map(repo.lookup, revs) or revs
1134 heads = revs and map(repo.lookup, revs) or revs
1135 outgoing = discovery.findcommonoutgoing(repo, other,
1135 outgoing = discovery.findcommonoutgoing(repo, other,
1136 onlyheads=heads,
1136 onlyheads=heads,
1137 force=opts.get('force'),
1137 force=opts.get('force'),
1138 portable=True)
1138 portable=True)
1139 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1139 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1140 if not cg:
1140 if not cg:
1141 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1141 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1142 return 1
1142 return 1
1143
1143
1144 changegroup.writebundle(cg, fname, bundletype)
1144 changegroup.writebundle(cg, fname, bundletype)
1145
1145
1146 @command('cat',
1146 @command('cat',
1147 [('o', 'output', '',
1147 [('o', 'output', '',
1148 _('print output to file with formatted name'), _('FORMAT')),
1148 _('print output to file with formatted name'), _('FORMAT')),
1149 ('r', 'rev', '', _('print the given revision'), _('REV')),
1149 ('r', 'rev', '', _('print the given revision'), _('REV')),
1150 ('', 'decode', None, _('apply any matching decode filter')),
1150 ('', 'decode', None, _('apply any matching decode filter')),
1151 ] + walkopts,
1151 ] + walkopts,
1152 _('[OPTION]... FILE...'))
1152 _('[OPTION]... FILE...'))
1153 def cat(ui, repo, file1, *pats, **opts):
1153 def cat(ui, repo, file1, *pats, **opts):
1154 """output the current or given revision of files
1154 """output the current or given revision of files
1155
1155
1156 Print the specified files as they were at the given revision. If
1156 Print the specified files as they were at the given revision. If
1157 no revision is given, the parent of the working directory is used.
1157 no revision is given, the parent of the working directory is used.
1158
1158
1159 Output may be to a file, in which case the name of the file is
1159 Output may be to a file, in which case the name of the file is
1160 given using a format string. The formatting rules are the same as
1160 given using a format string. The formatting rules are the same as
1161 for the export command, with the following additions:
1161 for the export command, with the following additions:
1162
1162
1163 :``%s``: basename of file being printed
1163 :``%s``: basename of file being printed
1164 :``%d``: dirname of file being printed, or '.' if in repository root
1164 :``%d``: dirname of file being printed, or '.' if in repository root
1165 :``%p``: root-relative path name of file being printed
1165 :``%p``: root-relative path name of file being printed
1166
1166
1167 Returns 0 on success.
1167 Returns 0 on success.
1168 """
1168 """
1169 ctx = scmutil.revsingle(repo, opts.get('rev'))
1169 ctx = scmutil.revsingle(repo, opts.get('rev'))
1170 err = 1
1170 err = 1
1171 m = scmutil.match(ctx, (file1,) + pats, opts)
1171 m = scmutil.match(ctx, (file1,) + pats, opts)
1172
1172
1173 def write(path):
1173 def write(path):
1174 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1174 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1175 pathname=path)
1175 pathname=path)
1176 data = ctx[path].data()
1176 data = ctx[path].data()
1177 if opts.get('decode'):
1177 if opts.get('decode'):
1178 data = repo.wwritedata(path, data)
1178 data = repo.wwritedata(path, data)
1179 fp.write(data)
1179 fp.write(data)
1180 fp.close()
1180 fp.close()
1181
1181
1182 # Automation often uses hg cat on single files, so special case it
1182 # Automation often uses hg cat on single files, so special case it
1183 # for performance to avoid the cost of parsing the manifest.
1183 # for performance to avoid the cost of parsing the manifest.
1184 if len(m.files()) == 1 and not m.anypats():
1184 if len(m.files()) == 1 and not m.anypats():
1185 file = m.files()[0]
1185 file = m.files()[0]
1186 mf = repo.manifest
1186 mf = repo.manifest
1187 mfnode = ctx._changeset[0]
1187 mfnode = ctx._changeset[0]
1188 if mf.find(mfnode, file)[0]:
1188 if mf.find(mfnode, file)[0]:
1189 write(file)
1189 write(file)
1190 return 0
1190 return 0
1191
1191
1192 for abs in ctx.walk(m):
1192 for abs in ctx.walk(m):
1193 write(abs)
1193 write(abs)
1194 err = 0
1194 err = 0
1195 return err
1195 return err
1196
1196
1197 @command('^clone',
1197 @command('^clone',
1198 [('U', 'noupdate', None,
1198 [('U', 'noupdate', None,
1199 _('the clone will include an empty working copy (only a repository)')),
1199 _('the clone will include an empty working copy (only a repository)')),
1200 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1200 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1201 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1201 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1202 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1202 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1203 ('', 'pull', None, _('use pull protocol to copy metadata')),
1203 ('', 'pull', None, _('use pull protocol to copy metadata')),
1204 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1204 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1205 ] + remoteopts,
1205 ] + remoteopts,
1206 _('[OPTION]... SOURCE [DEST]'))
1206 _('[OPTION]... SOURCE [DEST]'))
1207 def clone(ui, source, dest=None, **opts):
1207 def clone(ui, source, dest=None, **opts):
1208 """make a copy of an existing repository
1208 """make a copy of an existing repository
1209
1209
1210 Create a copy of an existing repository in a new directory.
1210 Create a copy of an existing repository in a new directory.
1211
1211
1212 If no destination directory name is specified, it defaults to the
1212 If no destination directory name is specified, it defaults to the
1213 basename of the source.
1213 basename of the source.
1214
1214
1215 The location of the source is added to the new repository's
1215 The location of the source is added to the new repository's
1216 ``.hg/hgrc`` file, as the default to be used for future pulls.
1216 ``.hg/hgrc`` file, as the default to be used for future pulls.
1217
1217
1218 Only local paths and ``ssh://`` URLs are supported as
1218 Only local paths and ``ssh://`` URLs are supported as
1219 destinations. For ``ssh://`` destinations, no working directory or
1219 destinations. For ``ssh://`` destinations, no working directory or
1220 ``.hg/hgrc`` will be created on the remote side.
1220 ``.hg/hgrc`` will be created on the remote side.
1221
1221
1222 To pull only a subset of changesets, specify one or more revisions
1222 To pull only a subset of changesets, specify one or more revisions
1223 identifiers with -r/--rev or branches with -b/--branch. The
1223 identifiers with -r/--rev or branches with -b/--branch. The
1224 resulting clone will contain only the specified changesets and
1224 resulting clone will contain only the specified changesets and
1225 their ancestors. These options (or 'clone src#rev dest') imply
1225 their ancestors. These options (or 'clone src#rev dest') imply
1226 --pull, even for local source repositories. Note that specifying a
1226 --pull, even for local source repositories. Note that specifying a
1227 tag will include the tagged changeset but not the changeset
1227 tag will include the tagged changeset but not the changeset
1228 containing the tag.
1228 containing the tag.
1229
1229
1230 If the source repository has a bookmark called '@' set, that
1230 If the source repository has a bookmark called '@' set, that
1231 revision will be checked out in the new repository by default.
1231 revision will be checked out in the new repository by default.
1232
1232
1233 To check out a particular version, use -u/--update, or
1233 To check out a particular version, use -u/--update, or
1234 -U/--noupdate to create a clone with no working directory.
1234 -U/--noupdate to create a clone with no working directory.
1235
1235
1236 .. container:: verbose
1236 .. container:: verbose
1237
1237
1238 For efficiency, hardlinks are used for cloning whenever the
1238 For efficiency, hardlinks are used for cloning whenever the
1239 source and destination are on the same filesystem (note this
1239 source and destination are on the same filesystem (note this
1240 applies only to the repository data, not to the working
1240 applies only to the repository data, not to the working
1241 directory). Some filesystems, such as AFS, implement hardlinking
1241 directory). Some filesystems, such as AFS, implement hardlinking
1242 incorrectly, but do not report errors. In these cases, use the
1242 incorrectly, but do not report errors. In these cases, use the
1243 --pull option to avoid hardlinking.
1243 --pull option to avoid hardlinking.
1244
1244
1245 In some cases, you can clone repositories and the working
1245 In some cases, you can clone repositories and the working
1246 directory using full hardlinks with ::
1246 directory using full hardlinks with ::
1247
1247
1248 $ cp -al REPO REPOCLONE
1248 $ cp -al REPO REPOCLONE
1249
1249
1250 This is the fastest way to clone, but it is not always safe. The
1250 This is the fastest way to clone, but it is not always safe. The
1251 operation is not atomic (making sure REPO is not modified during
1251 operation is not atomic (making sure REPO is not modified during
1252 the operation is up to you) and you have to make sure your
1252 the operation is up to you) and you have to make sure your
1253 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1253 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1254 so). Also, this is not compatible with certain extensions that
1254 so). Also, this is not compatible with certain extensions that
1255 place their metadata under the .hg directory, such as mq.
1255 place their metadata under the .hg directory, such as mq.
1256
1256
1257 Mercurial will update the working directory to the first applicable
1257 Mercurial will update the working directory to the first applicable
1258 revision from this list:
1258 revision from this list:
1259
1259
1260 a) null if -U or the source repository has no changesets
1260 a) null if -U or the source repository has no changesets
1261 b) if -u . and the source repository is local, the first parent of
1261 b) if -u . and the source repository is local, the first parent of
1262 the source repository's working directory
1262 the source repository's working directory
1263 c) the changeset specified with -u (if a branch name, this means the
1263 c) the changeset specified with -u (if a branch name, this means the
1264 latest head of that branch)
1264 latest head of that branch)
1265 d) the changeset specified with -r
1265 d) the changeset specified with -r
1266 e) the tipmost head specified with -b
1266 e) the tipmost head specified with -b
1267 f) the tipmost head specified with the url#branch source syntax
1267 f) the tipmost head specified with the url#branch source syntax
1268 g) the revision marked with the '@' bookmark, if present
1268 g) the revision marked with the '@' bookmark, if present
1269 h) the tipmost head of the default branch
1269 h) the tipmost head of the default branch
1270 i) tip
1270 i) tip
1271
1271
1272 Examples:
1272 Examples:
1273
1273
1274 - clone a remote repository to a new directory named hg/::
1274 - clone a remote repository to a new directory named hg/::
1275
1275
1276 hg clone http://selenic.com/hg
1276 hg clone http://selenic.com/hg
1277
1277
1278 - create a lightweight local clone::
1278 - create a lightweight local clone::
1279
1279
1280 hg clone project/ project-feature/
1280 hg clone project/ project-feature/
1281
1281
1282 - clone from an absolute path on an ssh server (note double-slash)::
1282 - clone from an absolute path on an ssh server (note double-slash)::
1283
1283
1284 hg clone ssh://user@server//home/projects/alpha/
1284 hg clone ssh://user@server//home/projects/alpha/
1285
1285
1286 - do a high-speed clone over a LAN while checking out a
1286 - do a high-speed clone over a LAN while checking out a
1287 specified version::
1287 specified version::
1288
1288
1289 hg clone --uncompressed http://server/repo -u 1.5
1289 hg clone --uncompressed http://server/repo -u 1.5
1290
1290
1291 - create a repository without changesets after a particular revision::
1291 - create a repository without changesets after a particular revision::
1292
1292
1293 hg clone -r 04e544 experimental/ good/
1293 hg clone -r 04e544 experimental/ good/
1294
1294
1295 - clone (and track) a particular named branch::
1295 - clone (and track) a particular named branch::
1296
1296
1297 hg clone http://selenic.com/hg#stable
1297 hg clone http://selenic.com/hg#stable
1298
1298
1299 See :hg:`help urls` for details on specifying URLs.
1299 See :hg:`help urls` for details on specifying URLs.
1300
1300
1301 Returns 0 on success.
1301 Returns 0 on success.
1302 """
1302 """
1303 if opts.get('noupdate') and opts.get('updaterev'):
1303 if opts.get('noupdate') and opts.get('updaterev'):
1304 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1304 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1305
1305
1306 r = hg.clone(ui, opts, source, dest,
1306 r = hg.clone(ui, opts, source, dest,
1307 pull=opts.get('pull'),
1307 pull=opts.get('pull'),
1308 stream=opts.get('uncompressed'),
1308 stream=opts.get('uncompressed'),
1309 rev=opts.get('rev'),
1309 rev=opts.get('rev'),
1310 update=opts.get('updaterev') or not opts.get('noupdate'),
1310 update=opts.get('updaterev') or not opts.get('noupdate'),
1311 branch=opts.get('branch'))
1311 branch=opts.get('branch'))
1312
1312
1313 return r is None
1313 return r is None
1314
1314
1315 @command('^commit|ci',
1315 @command('^commit|ci',
1316 [('A', 'addremove', None,
1316 [('A', 'addremove', None,
1317 _('mark new/missing files as added/removed before committing')),
1317 _('mark new/missing files as added/removed before committing')),
1318 ('', 'close-branch', None,
1318 ('', 'close-branch', None,
1319 _('mark a branch as closed, hiding it from the branch list')),
1319 _('mark a branch as closed, hiding it from the branch list')),
1320 ('', 'amend', None, _('amend the parent of the working dir')),
1320 ('', 'amend', None, _('amend the parent of the working dir')),
1321 ('s', 'secret', None, _('use the secret phase for committing')),
1321 ('s', 'secret', None, _('use the secret phase for committing')),
1322 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1322 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1323 _('[OPTION]... [FILE]...'))
1323 _('[OPTION]... [FILE]...'))
1324 def commit(ui, repo, *pats, **opts):
1324 def commit(ui, repo, *pats, **opts):
1325 """commit the specified files or all outstanding changes
1325 """commit the specified files or all outstanding changes
1326
1326
1327 Commit changes to the given files into the repository. Unlike a
1327 Commit changes to the given files into the repository. Unlike a
1328 centralized SCM, this operation is a local operation. See
1328 centralized SCM, this operation is a local operation. See
1329 :hg:`push` for a way to actively distribute your changes.
1329 :hg:`push` for a way to actively distribute your changes.
1330
1330
1331 If a list of files is omitted, all changes reported by :hg:`status`
1331 If a list of files is omitted, all changes reported by :hg:`status`
1332 will be committed.
1332 will be committed.
1333
1333
1334 If you are committing the result of a merge, do not provide any
1334 If you are committing the result of a merge, do not provide any
1335 filenames or -I/-X filters.
1335 filenames or -I/-X filters.
1336
1336
1337 If no commit message is specified, Mercurial starts your
1337 If no commit message is specified, Mercurial starts your
1338 configured editor where you can enter a message. In case your
1338 configured editor where you can enter a message. In case your
1339 commit fails, you will find a backup of your message in
1339 commit fails, you will find a backup of your message in
1340 ``.hg/last-message.txt``.
1340 ``.hg/last-message.txt``.
1341
1341
1342 The --amend flag can be used to amend the parent of the
1342 The --amend flag can be used to amend the parent of the
1343 working directory with a new commit that contains the changes
1343 working directory with a new commit that contains the changes
1344 in the parent in addition to those currently reported by :hg:`status`,
1344 in the parent in addition to those currently reported by :hg:`status`,
1345 if there are any. The old commit is stored in a backup bundle in
1345 if there are any. The old commit is stored in a backup bundle in
1346 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1346 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1347 on how to restore it).
1347 on how to restore it).
1348
1348
1349 Message, user and date are taken from the amended commit unless
1349 Message, user and date are taken from the amended commit unless
1350 specified. When a message isn't specified on the command line,
1350 specified. When a message isn't specified on the command line,
1351 the editor will open with the message of the amended commit.
1351 the editor will open with the message of the amended commit.
1352
1352
1353 It is not possible to amend public changesets (see :hg:`help phases`)
1353 It is not possible to amend public changesets (see :hg:`help phases`)
1354 or changesets that have children.
1354 or changesets that have children.
1355
1355
1356 See :hg:`help dates` for a list of formats valid for -d/--date.
1356 See :hg:`help dates` for a list of formats valid for -d/--date.
1357
1357
1358 Returns 0 on success, 1 if nothing changed.
1358 Returns 0 on success, 1 if nothing changed.
1359 """
1359 """
1360 if opts.get('subrepos'):
1360 if opts.get('subrepos'):
1361 if opts.get('amend'):
1361 if opts.get('amend'):
1362 raise util.Abort(_('cannot amend with --subrepos'))
1362 raise util.Abort(_('cannot amend with --subrepos'))
1363 # Let --subrepos on the command line override config setting.
1363 # Let --subrepos on the command line override config setting.
1364 ui.setconfig('ui', 'commitsubrepos', True)
1364 ui.setconfig('ui', 'commitsubrepos', True)
1365
1365
1366 # Save this for restoring it later
1366 # Save this for restoring it later
1367 oldcommitphase = ui.config('phases', 'new-commit')
1367 oldcommitphase = ui.config('phases', 'new-commit')
1368
1368
1369 cmdutil.checkunfinished(repo, commit=True)
1369 cmdutil.checkunfinished(repo, commit=True)
1370
1370
1371 branch = repo[None].branch()
1371 branch = repo[None].branch()
1372 bheads = repo.branchheads(branch)
1372 bheads = repo.branchheads(branch)
1373
1373
1374 extra = {}
1374 extra = {}
1375 if opts.get('close_branch'):
1375 if opts.get('close_branch'):
1376 extra['close'] = 1
1376 extra['close'] = 1
1377
1377
1378 if not bheads:
1378 if not bheads:
1379 raise util.Abort(_('can only close branch heads'))
1379 raise util.Abort(_('can only close branch heads'))
1380 elif opts.get('amend'):
1380 elif opts.get('amend'):
1381 if repo.parents()[0].p1().branch() != branch and \
1381 if repo.parents()[0].p1().branch() != branch and \
1382 repo.parents()[0].p2().branch() != branch:
1382 repo.parents()[0].p2().branch() != branch:
1383 raise util.Abort(_('can only close branch heads'))
1383 raise util.Abort(_('can only close branch heads'))
1384
1384
1385 if opts.get('amend'):
1385 if opts.get('amend'):
1386 if ui.configbool('ui', 'commitsubrepos'):
1386 if ui.configbool('ui', 'commitsubrepos'):
1387 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1387 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1388
1388
1389 old = repo['.']
1389 old = repo['.']
1390 if old.phase() == phases.public:
1390 if old.phase() == phases.public:
1391 raise util.Abort(_('cannot amend public changesets'))
1391 raise util.Abort(_('cannot amend public changesets'))
1392 if len(repo[None].parents()) > 1:
1392 if len(repo[None].parents()) > 1:
1393 raise util.Abort(_('cannot amend while merging'))
1393 raise util.Abort(_('cannot amend while merging'))
1394 if (not obsolete._enabled) and old.children():
1394 if (not obsolete._enabled) and old.children():
1395 raise util.Abort(_('cannot amend changeset with children'))
1395 raise util.Abort(_('cannot amend changeset with children'))
1396
1396
1397 e = cmdutil.commiteditor
1397 e = cmdutil.commiteditor
1398 if opts.get('force_editor'):
1398 if opts.get('force_editor'):
1399 e = cmdutil.commitforceeditor
1399 e = cmdutil.commitforceeditor
1400
1400
1401 # commitfunc is used only for temporary amend commit by cmdutil.amend
1401 # commitfunc is used only for temporary amend commit by cmdutil.amend
1402 def commitfunc(ui, repo, message, match, opts):
1402 def commitfunc(ui, repo, message, match, opts):
1403 editor = e
1403 editor = e
1404 # message contains text from -m or -l, if it's empty,
1404 # message contains text from -m or -l, if it's empty,
1405 # open the editor with the old message
1405 # open the editor with the old message
1406 if not message:
1406 if not message:
1407 message = old.description()
1407 message = old.description()
1408 editor = cmdutil.commitforceeditor
1408 editor = cmdutil.commitforceeditor
1409 return repo.commit(message,
1409 return repo.commit(message,
1410 opts.get('user') or old.user(),
1410 opts.get('user') or old.user(),
1411 opts.get('date') or old.date(),
1411 opts.get('date') or old.date(),
1412 match,
1412 match,
1413 editor=editor,
1413 editor=editor,
1414 extra=extra)
1414 extra=extra)
1415
1415
1416 current = repo._bookmarkcurrent
1416 current = repo._bookmarkcurrent
1417 marks = old.bookmarks()
1417 marks = old.bookmarks()
1418 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1418 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1419 if node == old.node():
1419 if node == old.node():
1420 ui.status(_("nothing changed\n"))
1420 ui.status(_("nothing changed\n"))
1421 return 1
1421 return 1
1422 elif marks:
1422 elif marks:
1423 ui.debug('moving bookmarks %r from %s to %s\n' %
1423 ui.debug('moving bookmarks %r from %s to %s\n' %
1424 (marks, old.hex(), hex(node)))
1424 (marks, old.hex(), hex(node)))
1425 newmarks = repo._bookmarks
1425 newmarks = repo._bookmarks
1426 for bm in marks:
1426 for bm in marks:
1427 newmarks[bm] = node
1427 newmarks[bm] = node
1428 if bm == current:
1428 if bm == current:
1429 bookmarks.setcurrent(repo, bm)
1429 bookmarks.setcurrent(repo, bm)
1430 newmarks.write()
1430 newmarks.write()
1431 else:
1431 else:
1432 e = cmdutil.commiteditor
1432 e = cmdutil.commiteditor
1433 if opts.get('force_editor'):
1433 if opts.get('force_editor'):
1434 e = cmdutil.commitforceeditor
1434 e = cmdutil.commitforceeditor
1435
1435
1436 def commitfunc(ui, repo, message, match, opts):
1436 def commitfunc(ui, repo, message, match, opts):
1437 try:
1437 try:
1438 if opts.get('secret'):
1438 if opts.get('secret'):
1439 ui.setconfig('phases', 'new-commit', 'secret')
1439 ui.setconfig('phases', 'new-commit', 'secret')
1440 # Propagate to subrepos
1440 # Propagate to subrepos
1441 repo.baseui.setconfig('phases', 'new-commit', 'secret')
1441 repo.baseui.setconfig('phases', 'new-commit', 'secret')
1442
1442
1443 return repo.commit(message, opts.get('user'), opts.get('date'),
1443 return repo.commit(message, opts.get('user'), opts.get('date'),
1444 match, editor=e, extra=extra)
1444 match, editor=e, extra=extra)
1445 finally:
1445 finally:
1446 ui.setconfig('phases', 'new-commit', oldcommitphase)
1446 ui.setconfig('phases', 'new-commit', oldcommitphase)
1447 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase)
1447 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase)
1448
1448
1449
1449
1450 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1450 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1451
1451
1452 if not node:
1452 if not node:
1453 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1453 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1454 if stat[3]:
1454 if stat[3]:
1455 ui.status(_("nothing changed (%d missing files, see "
1455 ui.status(_("nothing changed (%d missing files, see "
1456 "'hg status')\n") % len(stat[3]))
1456 "'hg status')\n") % len(stat[3]))
1457 else:
1457 else:
1458 ui.status(_("nothing changed\n"))
1458 ui.status(_("nothing changed\n"))
1459 return 1
1459 return 1
1460
1460
1461 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1461 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1462
1462
1463 @command('config|showconfig|debugconfig',
1463 @command('config|showconfig|debugconfig',
1464 [('u', 'untrusted', None, _('show untrusted configuration options')),
1464 [('u', 'untrusted', None, _('show untrusted configuration options')),
1465 ('e', 'edit', None, _('edit user config')),
1465 ('e', 'edit', None, _('edit user config')),
1466 ('l', 'local', None, _('edit repository config')),
1466 ('l', 'local', None, _('edit repository config')),
1467 ('g', 'global', None, _('edit global config'))],
1467 ('g', 'global', None, _('edit global config'))],
1468 _('[-u] [NAME]...'))
1468 _('[-u] [NAME]...'))
1469 def config(ui, repo, *values, **opts):
1469 def config(ui, repo, *values, **opts):
1470 """show combined config settings from all hgrc files
1470 """show combined config settings from all hgrc files
1471
1471
1472 With no arguments, print names and values of all config items.
1472 With no arguments, print names and values of all config items.
1473
1473
1474 With one argument of the form section.name, print just the value
1474 With one argument of the form section.name, print just the value
1475 of that config item.
1475 of that config item.
1476
1476
1477 With multiple arguments, print names and values of all config
1477 With multiple arguments, print names and values of all config
1478 items with matching section names.
1478 items with matching section names.
1479
1479
1480 With --edit, start an editor on the user-level config file. With
1481 --global, edit the system-wide config file. With --local, edit the
1482 repository-level config file.
1483
1480 With --debug, the source (filename and line number) is printed
1484 With --debug, the source (filename and line number) is printed
1481 for each config item.
1485 for each config item.
1482
1486
1487 See :hg:`help config` for more information about config files.
1488
1483 Returns 0 on success.
1489 Returns 0 on success.
1490
1484 """
1491 """
1485
1492
1486 if opts.get('edit') or opts.get('local') or opts.get('global'):
1493 if opts.get('edit') or opts.get('local') or opts.get('global'):
1487 if opts.get('local') and opts.get('global'):
1494 if opts.get('local') and opts.get('global'):
1488 raise util.Abort(_("can't use --local and --global together"))
1495 raise util.Abort(_("can't use --local and --global together"))
1489
1496
1490 if opts.get('local'):
1497 if opts.get('local'):
1491 if not repo:
1498 if not repo:
1492 raise util.Abort(_("can't use --local outside a repository"))
1499 raise util.Abort(_("can't use --local outside a repository"))
1493 paths = [repo.join('hgrc')]
1500 paths = [repo.join('hgrc')]
1494 elif opts.get('global'):
1501 elif opts.get('global'):
1495 paths = scmutil.systemrcpath()
1502 paths = scmutil.systemrcpath()
1496 else:
1503 else:
1497 paths = scmutil.userrcpath()
1504 paths = scmutil.userrcpath()
1498
1505
1499 for f in paths:
1506 for f in paths:
1500 if os.path.exists(f):
1507 if os.path.exists(f):
1501 break
1508 break
1502 else:
1509 else:
1503 f = paths[0]
1510 f = paths[0]
1504 fp = open(f, "w")
1511 fp = open(f, "w")
1505 fp.write(
1512 fp.write(
1506 '# example config (see "hg help config" for more info)\n'
1513 '# example config (see "hg help config" for more info)\n'
1507 '\n'
1514 '\n'
1508 '[ui]\n'
1515 '[ui]\n'
1509 '# name and email, e.g.\n'
1516 '# name and email, e.g.\n'
1510 '# username = Jane Doe <jdoe@example.com>\n'
1517 '# username = Jane Doe <jdoe@example.com>\n'
1511 'username =\n'
1518 'username =\n'
1512 '\n'
1519 '\n'
1513 '[extensions]\n'
1520 '[extensions]\n'
1514 '# uncomment these lines to enable some popular extensions\n'
1521 '# uncomment these lines to enable some popular extensions\n'
1515 '# (see "hg help extensions" for more info)\n'
1522 '# (see "hg help extensions" for more info)\n'
1516 '# pager =\n'
1523 '# pager =\n'
1517 '# progress =\n'
1524 '# progress =\n'
1518 '# color =\n')
1525 '# color =\n')
1519 fp.close()
1526 fp.close()
1520
1527
1521 editor = ui.geteditor()
1528 editor = ui.geteditor()
1522 util.system("%s \"%s\"" % (editor, f),
1529 util.system("%s \"%s\"" % (editor, f),
1523 onerr=util.Abort, errprefix=_("edit failed"),
1530 onerr=util.Abort, errprefix=_("edit failed"),
1524 out=ui.fout)
1531 out=ui.fout)
1525 return
1532 return
1526
1533
1527 for f in scmutil.rcpath():
1534 for f in scmutil.rcpath():
1528 ui.debug('read config from: %s\n' % f)
1535 ui.debug('read config from: %s\n' % f)
1529 untrusted = bool(opts.get('untrusted'))
1536 untrusted = bool(opts.get('untrusted'))
1530 if values:
1537 if values:
1531 sections = [v for v in values if '.' not in v]
1538 sections = [v for v in values if '.' not in v]
1532 items = [v for v in values if '.' in v]
1539 items = [v for v in values if '.' in v]
1533 if len(items) > 1 or items and sections:
1540 if len(items) > 1 or items and sections:
1534 raise util.Abort(_('only one config item permitted'))
1541 raise util.Abort(_('only one config item permitted'))
1535 for section, name, value in ui.walkconfig(untrusted=untrusted):
1542 for section, name, value in ui.walkconfig(untrusted=untrusted):
1536 value = str(value).replace('\n', '\\n')
1543 value = str(value).replace('\n', '\\n')
1537 sectname = section + '.' + name
1544 sectname = section + '.' + name
1538 if values:
1545 if values:
1539 for v in values:
1546 for v in values:
1540 if v == section:
1547 if v == section:
1541 ui.debug('%s: ' %
1548 ui.debug('%s: ' %
1542 ui.configsource(section, name, untrusted))
1549 ui.configsource(section, name, untrusted))
1543 ui.write('%s=%s\n' % (sectname, value))
1550 ui.write('%s=%s\n' % (sectname, value))
1544 elif v == sectname:
1551 elif v == sectname:
1545 ui.debug('%s: ' %
1552 ui.debug('%s: ' %
1546 ui.configsource(section, name, untrusted))
1553 ui.configsource(section, name, untrusted))
1547 ui.write(value, '\n')
1554 ui.write(value, '\n')
1548 else:
1555 else:
1549 ui.debug('%s: ' %
1556 ui.debug('%s: ' %
1550 ui.configsource(section, name, untrusted))
1557 ui.configsource(section, name, untrusted))
1551 ui.write('%s=%s\n' % (sectname, value))
1558 ui.write('%s=%s\n' % (sectname, value))
1552
1559
1553 @command('copy|cp',
1560 @command('copy|cp',
1554 [('A', 'after', None, _('record a copy that has already occurred')),
1561 [('A', 'after', None, _('record a copy that has already occurred')),
1555 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1562 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1556 ] + walkopts + dryrunopts,
1563 ] + walkopts + dryrunopts,
1557 _('[OPTION]... [SOURCE]... DEST'))
1564 _('[OPTION]... [SOURCE]... DEST'))
1558 def copy(ui, repo, *pats, **opts):
1565 def copy(ui, repo, *pats, **opts):
1559 """mark files as copied for the next commit
1566 """mark files as copied for the next commit
1560
1567
1561 Mark dest as having copies of source files. If dest is a
1568 Mark dest as having copies of source files. If dest is a
1562 directory, copies are put in that directory. If dest is a file,
1569 directory, copies are put in that directory. If dest is a file,
1563 the source must be a single file.
1570 the source must be a single file.
1564
1571
1565 By default, this command copies the contents of files as they
1572 By default, this command copies the contents of files as they
1566 exist in the working directory. If invoked with -A/--after, the
1573 exist in the working directory. If invoked with -A/--after, the
1567 operation is recorded, but no copying is performed.
1574 operation is recorded, but no copying is performed.
1568
1575
1569 This command takes effect with the next commit. To undo a copy
1576 This command takes effect with the next commit. To undo a copy
1570 before that, see :hg:`revert`.
1577 before that, see :hg:`revert`.
1571
1578
1572 Returns 0 on success, 1 if errors are encountered.
1579 Returns 0 on success, 1 if errors are encountered.
1573 """
1580 """
1574 wlock = repo.wlock(False)
1581 wlock = repo.wlock(False)
1575 try:
1582 try:
1576 return cmdutil.copy(ui, repo, pats, opts)
1583 return cmdutil.copy(ui, repo, pats, opts)
1577 finally:
1584 finally:
1578 wlock.release()
1585 wlock.release()
1579
1586
1580 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1587 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1581 def debugancestor(ui, repo, *args):
1588 def debugancestor(ui, repo, *args):
1582 """find the ancestor revision of two revisions in a given index"""
1589 """find the ancestor revision of two revisions in a given index"""
1583 if len(args) == 3:
1590 if len(args) == 3:
1584 index, rev1, rev2 = args
1591 index, rev1, rev2 = args
1585 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1592 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1586 lookup = r.lookup
1593 lookup = r.lookup
1587 elif len(args) == 2:
1594 elif len(args) == 2:
1588 if not repo:
1595 if not repo:
1589 raise util.Abort(_("there is no Mercurial repository here "
1596 raise util.Abort(_("there is no Mercurial repository here "
1590 "(.hg not found)"))
1597 "(.hg not found)"))
1591 rev1, rev2 = args
1598 rev1, rev2 = args
1592 r = repo.changelog
1599 r = repo.changelog
1593 lookup = repo.lookup
1600 lookup = repo.lookup
1594 else:
1601 else:
1595 raise util.Abort(_('either two or three arguments required'))
1602 raise util.Abort(_('either two or three arguments required'))
1596 a = r.ancestor(lookup(rev1), lookup(rev2))
1603 a = r.ancestor(lookup(rev1), lookup(rev2))
1597 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1604 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1598
1605
1599 @command('debugbuilddag',
1606 @command('debugbuilddag',
1600 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1607 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1601 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1608 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1602 ('n', 'new-file', None, _('add new file at each rev'))],
1609 ('n', 'new-file', None, _('add new file at each rev'))],
1603 _('[OPTION]... [TEXT]'))
1610 _('[OPTION]... [TEXT]'))
1604 def debugbuilddag(ui, repo, text=None,
1611 def debugbuilddag(ui, repo, text=None,
1605 mergeable_file=False,
1612 mergeable_file=False,
1606 overwritten_file=False,
1613 overwritten_file=False,
1607 new_file=False):
1614 new_file=False):
1608 """builds a repo with a given DAG from scratch in the current empty repo
1615 """builds a repo with a given DAG from scratch in the current empty repo
1609
1616
1610 The description of the DAG is read from stdin if not given on the
1617 The description of the DAG is read from stdin if not given on the
1611 command line.
1618 command line.
1612
1619
1613 Elements:
1620 Elements:
1614
1621
1615 - "+n" is a linear run of n nodes based on the current default parent
1622 - "+n" is a linear run of n nodes based on the current default parent
1616 - "." is a single node based on the current default parent
1623 - "." is a single node based on the current default parent
1617 - "$" resets the default parent to null (implied at the start);
1624 - "$" resets the default parent to null (implied at the start);
1618 otherwise the default parent is always the last node created
1625 otherwise the default parent is always the last node created
1619 - "<p" sets the default parent to the backref p
1626 - "<p" sets the default parent to the backref p
1620 - "*p" is a fork at parent p, which is a backref
1627 - "*p" is a fork at parent p, which is a backref
1621 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1628 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1622 - "/p2" is a merge of the preceding node and p2
1629 - "/p2" is a merge of the preceding node and p2
1623 - ":tag" defines a local tag for the preceding node
1630 - ":tag" defines a local tag for the preceding node
1624 - "@branch" sets the named branch for subsequent nodes
1631 - "@branch" sets the named branch for subsequent nodes
1625 - "#...\\n" is a comment up to the end of the line
1632 - "#...\\n" is a comment up to the end of the line
1626
1633
1627 Whitespace between the above elements is ignored.
1634 Whitespace between the above elements is ignored.
1628
1635
1629 A backref is either
1636 A backref is either
1630
1637
1631 - a number n, which references the node curr-n, where curr is the current
1638 - a number n, which references the node curr-n, where curr is the current
1632 node, or
1639 node, or
1633 - the name of a local tag you placed earlier using ":tag", or
1640 - the name of a local tag you placed earlier using ":tag", or
1634 - empty to denote the default parent.
1641 - empty to denote the default parent.
1635
1642
1636 All string valued-elements are either strictly alphanumeric, or must
1643 All string valued-elements are either strictly alphanumeric, or must
1637 be enclosed in double quotes ("..."), with "\\" as escape character.
1644 be enclosed in double quotes ("..."), with "\\" as escape character.
1638 """
1645 """
1639
1646
1640 if text is None:
1647 if text is None:
1641 ui.status(_("reading DAG from stdin\n"))
1648 ui.status(_("reading DAG from stdin\n"))
1642 text = ui.fin.read()
1649 text = ui.fin.read()
1643
1650
1644 cl = repo.changelog
1651 cl = repo.changelog
1645 if len(cl) > 0:
1652 if len(cl) > 0:
1646 raise util.Abort(_('repository is not empty'))
1653 raise util.Abort(_('repository is not empty'))
1647
1654
1648 # determine number of revs in DAG
1655 # determine number of revs in DAG
1649 total = 0
1656 total = 0
1650 for type, data in dagparser.parsedag(text):
1657 for type, data in dagparser.parsedag(text):
1651 if type == 'n':
1658 if type == 'n':
1652 total += 1
1659 total += 1
1653
1660
1654 if mergeable_file:
1661 if mergeable_file:
1655 linesperrev = 2
1662 linesperrev = 2
1656 # make a file with k lines per rev
1663 # make a file with k lines per rev
1657 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1664 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1658 initialmergedlines.append("")
1665 initialmergedlines.append("")
1659
1666
1660 tags = []
1667 tags = []
1661
1668
1662 lock = tr = None
1669 lock = tr = None
1663 try:
1670 try:
1664 lock = repo.lock()
1671 lock = repo.lock()
1665 tr = repo.transaction("builddag")
1672 tr = repo.transaction("builddag")
1666
1673
1667 at = -1
1674 at = -1
1668 atbranch = 'default'
1675 atbranch = 'default'
1669 nodeids = []
1676 nodeids = []
1670 id = 0
1677 id = 0
1671 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1678 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1672 for type, data in dagparser.parsedag(text):
1679 for type, data in dagparser.parsedag(text):
1673 if type == 'n':
1680 if type == 'n':
1674 ui.note(('node %s\n' % str(data)))
1681 ui.note(('node %s\n' % str(data)))
1675 id, ps = data
1682 id, ps = data
1676
1683
1677 files = []
1684 files = []
1678 fctxs = {}
1685 fctxs = {}
1679
1686
1680 p2 = None
1687 p2 = None
1681 if mergeable_file:
1688 if mergeable_file:
1682 fn = "mf"
1689 fn = "mf"
1683 p1 = repo[ps[0]]
1690 p1 = repo[ps[0]]
1684 if len(ps) > 1:
1691 if len(ps) > 1:
1685 p2 = repo[ps[1]]
1692 p2 = repo[ps[1]]
1686 pa = p1.ancestor(p2)
1693 pa = p1.ancestor(p2)
1687 base, local, other = [x[fn].data() for x in (pa, p1,
1694 base, local, other = [x[fn].data() for x in (pa, p1,
1688 p2)]
1695 p2)]
1689 m3 = simplemerge.Merge3Text(base, local, other)
1696 m3 = simplemerge.Merge3Text(base, local, other)
1690 ml = [l.strip() for l in m3.merge_lines()]
1697 ml = [l.strip() for l in m3.merge_lines()]
1691 ml.append("")
1698 ml.append("")
1692 elif at > 0:
1699 elif at > 0:
1693 ml = p1[fn].data().split("\n")
1700 ml = p1[fn].data().split("\n")
1694 else:
1701 else:
1695 ml = initialmergedlines
1702 ml = initialmergedlines
1696 ml[id * linesperrev] += " r%i" % id
1703 ml[id * linesperrev] += " r%i" % id
1697 mergedtext = "\n".join(ml)
1704 mergedtext = "\n".join(ml)
1698 files.append(fn)
1705 files.append(fn)
1699 fctxs[fn] = context.memfilectx(fn, mergedtext)
1706 fctxs[fn] = context.memfilectx(fn, mergedtext)
1700
1707
1701 if overwritten_file:
1708 if overwritten_file:
1702 fn = "of"
1709 fn = "of"
1703 files.append(fn)
1710 files.append(fn)
1704 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1711 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1705
1712
1706 if new_file:
1713 if new_file:
1707 fn = "nf%i" % id
1714 fn = "nf%i" % id
1708 files.append(fn)
1715 files.append(fn)
1709 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1716 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1710 if len(ps) > 1:
1717 if len(ps) > 1:
1711 if not p2:
1718 if not p2:
1712 p2 = repo[ps[1]]
1719 p2 = repo[ps[1]]
1713 for fn in p2:
1720 for fn in p2:
1714 if fn.startswith("nf"):
1721 if fn.startswith("nf"):
1715 files.append(fn)
1722 files.append(fn)
1716 fctxs[fn] = p2[fn]
1723 fctxs[fn] = p2[fn]
1717
1724
1718 def fctxfn(repo, cx, path):
1725 def fctxfn(repo, cx, path):
1719 return fctxs.get(path)
1726 return fctxs.get(path)
1720
1727
1721 if len(ps) == 0 or ps[0] < 0:
1728 if len(ps) == 0 or ps[0] < 0:
1722 pars = [None, None]
1729 pars = [None, None]
1723 elif len(ps) == 1:
1730 elif len(ps) == 1:
1724 pars = [nodeids[ps[0]], None]
1731 pars = [nodeids[ps[0]], None]
1725 else:
1732 else:
1726 pars = [nodeids[p] for p in ps]
1733 pars = [nodeids[p] for p in ps]
1727 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1734 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1728 date=(id, 0),
1735 date=(id, 0),
1729 user="debugbuilddag",
1736 user="debugbuilddag",
1730 extra={'branch': atbranch})
1737 extra={'branch': atbranch})
1731 nodeid = repo.commitctx(cx)
1738 nodeid = repo.commitctx(cx)
1732 nodeids.append(nodeid)
1739 nodeids.append(nodeid)
1733 at = id
1740 at = id
1734 elif type == 'l':
1741 elif type == 'l':
1735 id, name = data
1742 id, name = data
1736 ui.note(('tag %s\n' % name))
1743 ui.note(('tag %s\n' % name))
1737 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1744 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1738 elif type == 'a':
1745 elif type == 'a':
1739 ui.note(('branch %s\n' % data))
1746 ui.note(('branch %s\n' % data))
1740 atbranch = data
1747 atbranch = data
1741 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1748 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1742 tr.close()
1749 tr.close()
1743
1750
1744 if tags:
1751 if tags:
1745 repo.opener.write("localtags", "".join(tags))
1752 repo.opener.write("localtags", "".join(tags))
1746 finally:
1753 finally:
1747 ui.progress(_('building'), None)
1754 ui.progress(_('building'), None)
1748 release(tr, lock)
1755 release(tr, lock)
1749
1756
1750 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1757 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1751 def debugbundle(ui, bundlepath, all=None, **opts):
1758 def debugbundle(ui, bundlepath, all=None, **opts):
1752 """lists the contents of a bundle"""
1759 """lists the contents of a bundle"""
1753 f = hg.openpath(ui, bundlepath)
1760 f = hg.openpath(ui, bundlepath)
1754 try:
1761 try:
1755 gen = changegroup.readbundle(f, bundlepath)
1762 gen = changegroup.readbundle(f, bundlepath)
1756 if all:
1763 if all:
1757 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1764 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1758
1765
1759 def showchunks(named):
1766 def showchunks(named):
1760 ui.write("\n%s\n" % named)
1767 ui.write("\n%s\n" % named)
1761 chain = None
1768 chain = None
1762 while True:
1769 while True:
1763 chunkdata = gen.deltachunk(chain)
1770 chunkdata = gen.deltachunk(chain)
1764 if not chunkdata:
1771 if not chunkdata:
1765 break
1772 break
1766 node = chunkdata['node']
1773 node = chunkdata['node']
1767 p1 = chunkdata['p1']
1774 p1 = chunkdata['p1']
1768 p2 = chunkdata['p2']
1775 p2 = chunkdata['p2']
1769 cs = chunkdata['cs']
1776 cs = chunkdata['cs']
1770 deltabase = chunkdata['deltabase']
1777 deltabase = chunkdata['deltabase']
1771 delta = chunkdata['delta']
1778 delta = chunkdata['delta']
1772 ui.write("%s %s %s %s %s %s\n" %
1779 ui.write("%s %s %s %s %s %s\n" %
1773 (hex(node), hex(p1), hex(p2),
1780 (hex(node), hex(p1), hex(p2),
1774 hex(cs), hex(deltabase), len(delta)))
1781 hex(cs), hex(deltabase), len(delta)))
1775 chain = node
1782 chain = node
1776
1783
1777 chunkdata = gen.changelogheader()
1784 chunkdata = gen.changelogheader()
1778 showchunks("changelog")
1785 showchunks("changelog")
1779 chunkdata = gen.manifestheader()
1786 chunkdata = gen.manifestheader()
1780 showchunks("manifest")
1787 showchunks("manifest")
1781 while True:
1788 while True:
1782 chunkdata = gen.filelogheader()
1789 chunkdata = gen.filelogheader()
1783 if not chunkdata:
1790 if not chunkdata:
1784 break
1791 break
1785 fname = chunkdata['filename']
1792 fname = chunkdata['filename']
1786 showchunks(fname)
1793 showchunks(fname)
1787 else:
1794 else:
1788 chunkdata = gen.changelogheader()
1795 chunkdata = gen.changelogheader()
1789 chain = None
1796 chain = None
1790 while True:
1797 while True:
1791 chunkdata = gen.deltachunk(chain)
1798 chunkdata = gen.deltachunk(chain)
1792 if not chunkdata:
1799 if not chunkdata:
1793 break
1800 break
1794 node = chunkdata['node']
1801 node = chunkdata['node']
1795 ui.write("%s\n" % hex(node))
1802 ui.write("%s\n" % hex(node))
1796 chain = node
1803 chain = node
1797 finally:
1804 finally:
1798 f.close()
1805 f.close()
1799
1806
1800 @command('debugcheckstate', [], '')
1807 @command('debugcheckstate', [], '')
1801 def debugcheckstate(ui, repo):
1808 def debugcheckstate(ui, repo):
1802 """validate the correctness of the current dirstate"""
1809 """validate the correctness of the current dirstate"""
1803 parent1, parent2 = repo.dirstate.parents()
1810 parent1, parent2 = repo.dirstate.parents()
1804 m1 = repo[parent1].manifest()
1811 m1 = repo[parent1].manifest()
1805 m2 = repo[parent2].manifest()
1812 m2 = repo[parent2].manifest()
1806 errors = 0
1813 errors = 0
1807 for f in repo.dirstate:
1814 for f in repo.dirstate:
1808 state = repo.dirstate[f]
1815 state = repo.dirstate[f]
1809 if state in "nr" and f not in m1:
1816 if state in "nr" and f not in m1:
1810 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1817 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1811 errors += 1
1818 errors += 1
1812 if state in "a" and f in m1:
1819 if state in "a" and f in m1:
1813 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1820 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1814 errors += 1
1821 errors += 1
1815 if state in "m" and f not in m1 and f not in m2:
1822 if state in "m" and f not in m1 and f not in m2:
1816 ui.warn(_("%s in state %s, but not in either manifest\n") %
1823 ui.warn(_("%s in state %s, but not in either manifest\n") %
1817 (f, state))
1824 (f, state))
1818 errors += 1
1825 errors += 1
1819 for f in m1:
1826 for f in m1:
1820 state = repo.dirstate[f]
1827 state = repo.dirstate[f]
1821 if state not in "nrm":
1828 if state not in "nrm":
1822 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1829 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1823 errors += 1
1830 errors += 1
1824 if errors:
1831 if errors:
1825 error = _(".hg/dirstate inconsistent with current parent's manifest")
1832 error = _(".hg/dirstate inconsistent with current parent's manifest")
1826 raise util.Abort(error)
1833 raise util.Abort(error)
1827
1834
1828 @command('debugcommands', [], _('[COMMAND]'))
1835 @command('debugcommands', [], _('[COMMAND]'))
1829 def debugcommands(ui, cmd='', *args):
1836 def debugcommands(ui, cmd='', *args):
1830 """list all available commands and options"""
1837 """list all available commands and options"""
1831 for cmd, vals in sorted(table.iteritems()):
1838 for cmd, vals in sorted(table.iteritems()):
1832 cmd = cmd.split('|')[0].strip('^')
1839 cmd = cmd.split('|')[0].strip('^')
1833 opts = ', '.join([i[1] for i in vals[1]])
1840 opts = ', '.join([i[1] for i in vals[1]])
1834 ui.write('%s: %s\n' % (cmd, opts))
1841 ui.write('%s: %s\n' % (cmd, opts))
1835
1842
1836 @command('debugcomplete',
1843 @command('debugcomplete',
1837 [('o', 'options', None, _('show the command options'))],
1844 [('o', 'options', None, _('show the command options'))],
1838 _('[-o] CMD'))
1845 _('[-o] CMD'))
1839 def debugcomplete(ui, cmd='', **opts):
1846 def debugcomplete(ui, cmd='', **opts):
1840 """returns the completion list associated with the given command"""
1847 """returns the completion list associated with the given command"""
1841
1848
1842 if opts.get('options'):
1849 if opts.get('options'):
1843 options = []
1850 options = []
1844 otables = [globalopts]
1851 otables = [globalopts]
1845 if cmd:
1852 if cmd:
1846 aliases, entry = cmdutil.findcmd(cmd, table, False)
1853 aliases, entry = cmdutil.findcmd(cmd, table, False)
1847 otables.append(entry[1])
1854 otables.append(entry[1])
1848 for t in otables:
1855 for t in otables:
1849 for o in t:
1856 for o in t:
1850 if "(DEPRECATED)" in o[3]:
1857 if "(DEPRECATED)" in o[3]:
1851 continue
1858 continue
1852 if o[0]:
1859 if o[0]:
1853 options.append('-%s' % o[0])
1860 options.append('-%s' % o[0])
1854 options.append('--%s' % o[1])
1861 options.append('--%s' % o[1])
1855 ui.write("%s\n" % "\n".join(options))
1862 ui.write("%s\n" % "\n".join(options))
1856 return
1863 return
1857
1864
1858 cmdlist = cmdutil.findpossible(cmd, table)
1865 cmdlist = cmdutil.findpossible(cmd, table)
1859 if ui.verbose:
1866 if ui.verbose:
1860 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1867 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1861 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1868 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1862
1869
1863 @command('debugdag',
1870 @command('debugdag',
1864 [('t', 'tags', None, _('use tags as labels')),
1871 [('t', 'tags', None, _('use tags as labels')),
1865 ('b', 'branches', None, _('annotate with branch names')),
1872 ('b', 'branches', None, _('annotate with branch names')),
1866 ('', 'dots', None, _('use dots for runs')),
1873 ('', 'dots', None, _('use dots for runs')),
1867 ('s', 'spaces', None, _('separate elements by spaces'))],
1874 ('s', 'spaces', None, _('separate elements by spaces'))],
1868 _('[OPTION]... [FILE [REV]...]'))
1875 _('[OPTION]... [FILE [REV]...]'))
1869 def debugdag(ui, repo, file_=None, *revs, **opts):
1876 def debugdag(ui, repo, file_=None, *revs, **opts):
1870 """format the changelog or an index DAG as a concise textual description
1877 """format the changelog or an index DAG as a concise textual description
1871
1878
1872 If you pass a revlog index, the revlog's DAG is emitted. If you list
1879 If you pass a revlog index, the revlog's DAG is emitted. If you list
1873 revision numbers, they get labeled in the output as rN.
1880 revision numbers, they get labeled in the output as rN.
1874
1881
1875 Otherwise, the changelog DAG of the current repo is emitted.
1882 Otherwise, the changelog DAG of the current repo is emitted.
1876 """
1883 """
1877 spaces = opts.get('spaces')
1884 spaces = opts.get('spaces')
1878 dots = opts.get('dots')
1885 dots = opts.get('dots')
1879 if file_:
1886 if file_:
1880 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1887 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1881 revs = set((int(r) for r in revs))
1888 revs = set((int(r) for r in revs))
1882 def events():
1889 def events():
1883 for r in rlog:
1890 for r in rlog:
1884 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1891 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1885 if p != -1)))
1892 if p != -1)))
1886 if r in revs:
1893 if r in revs:
1887 yield 'l', (r, "r%i" % r)
1894 yield 'l', (r, "r%i" % r)
1888 elif repo:
1895 elif repo:
1889 cl = repo.changelog
1896 cl = repo.changelog
1890 tags = opts.get('tags')
1897 tags = opts.get('tags')
1891 branches = opts.get('branches')
1898 branches = opts.get('branches')
1892 if tags:
1899 if tags:
1893 labels = {}
1900 labels = {}
1894 for l, n in repo.tags().items():
1901 for l, n in repo.tags().items():
1895 labels.setdefault(cl.rev(n), []).append(l)
1902 labels.setdefault(cl.rev(n), []).append(l)
1896 def events():
1903 def events():
1897 b = "default"
1904 b = "default"
1898 for r in cl:
1905 for r in cl:
1899 if branches:
1906 if branches:
1900 newb = cl.read(cl.node(r))[5]['branch']
1907 newb = cl.read(cl.node(r))[5]['branch']
1901 if newb != b:
1908 if newb != b:
1902 yield 'a', newb
1909 yield 'a', newb
1903 b = newb
1910 b = newb
1904 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1911 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1905 if p != -1)))
1912 if p != -1)))
1906 if tags:
1913 if tags:
1907 ls = labels.get(r)
1914 ls = labels.get(r)
1908 if ls:
1915 if ls:
1909 for l in ls:
1916 for l in ls:
1910 yield 'l', (r, l)
1917 yield 'l', (r, l)
1911 else:
1918 else:
1912 raise util.Abort(_('need repo for changelog dag'))
1919 raise util.Abort(_('need repo for changelog dag'))
1913
1920
1914 for line in dagparser.dagtextlines(events(),
1921 for line in dagparser.dagtextlines(events(),
1915 addspaces=spaces,
1922 addspaces=spaces,
1916 wraplabels=True,
1923 wraplabels=True,
1917 wrapannotations=True,
1924 wrapannotations=True,
1918 wrapnonlinear=dots,
1925 wrapnonlinear=dots,
1919 usedots=dots,
1926 usedots=dots,
1920 maxlinewidth=70):
1927 maxlinewidth=70):
1921 ui.write(line)
1928 ui.write(line)
1922 ui.write("\n")
1929 ui.write("\n")
1923
1930
1924 @command('debugdata',
1931 @command('debugdata',
1925 [('c', 'changelog', False, _('open changelog')),
1932 [('c', 'changelog', False, _('open changelog')),
1926 ('m', 'manifest', False, _('open manifest'))],
1933 ('m', 'manifest', False, _('open manifest'))],
1927 _('-c|-m|FILE REV'))
1934 _('-c|-m|FILE REV'))
1928 def debugdata(ui, repo, file_, rev=None, **opts):
1935 def debugdata(ui, repo, file_, rev=None, **opts):
1929 """dump the contents of a data file revision"""
1936 """dump the contents of a data file revision"""
1930 if opts.get('changelog') or opts.get('manifest'):
1937 if opts.get('changelog') or opts.get('manifest'):
1931 file_, rev = None, file_
1938 file_, rev = None, file_
1932 elif rev is None:
1939 elif rev is None:
1933 raise error.CommandError('debugdata', _('invalid arguments'))
1940 raise error.CommandError('debugdata', _('invalid arguments'))
1934 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1941 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1935 try:
1942 try:
1936 ui.write(r.revision(r.lookup(rev)))
1943 ui.write(r.revision(r.lookup(rev)))
1937 except KeyError:
1944 except KeyError:
1938 raise util.Abort(_('invalid revision identifier %s') % rev)
1945 raise util.Abort(_('invalid revision identifier %s') % rev)
1939
1946
1940 @command('debugdate',
1947 @command('debugdate',
1941 [('e', 'extended', None, _('try extended date formats'))],
1948 [('e', 'extended', None, _('try extended date formats'))],
1942 _('[-e] DATE [RANGE]'))
1949 _('[-e] DATE [RANGE]'))
1943 def debugdate(ui, date, range=None, **opts):
1950 def debugdate(ui, date, range=None, **opts):
1944 """parse and display a date"""
1951 """parse and display a date"""
1945 if opts["extended"]:
1952 if opts["extended"]:
1946 d = util.parsedate(date, util.extendeddateformats)
1953 d = util.parsedate(date, util.extendeddateformats)
1947 else:
1954 else:
1948 d = util.parsedate(date)
1955 d = util.parsedate(date)
1949 ui.write(("internal: %s %s\n") % d)
1956 ui.write(("internal: %s %s\n") % d)
1950 ui.write(("standard: %s\n") % util.datestr(d))
1957 ui.write(("standard: %s\n") % util.datestr(d))
1951 if range:
1958 if range:
1952 m = util.matchdate(range)
1959 m = util.matchdate(range)
1953 ui.write(("match: %s\n") % m(d[0]))
1960 ui.write(("match: %s\n") % m(d[0]))
1954
1961
1955 @command('debugdiscovery',
1962 @command('debugdiscovery',
1956 [('', 'old', None, _('use old-style discovery')),
1963 [('', 'old', None, _('use old-style discovery')),
1957 ('', 'nonheads', None,
1964 ('', 'nonheads', None,
1958 _('use old-style discovery with non-heads included')),
1965 _('use old-style discovery with non-heads included')),
1959 ] + remoteopts,
1966 ] + remoteopts,
1960 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1967 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1961 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1968 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1962 """runs the changeset discovery protocol in isolation"""
1969 """runs the changeset discovery protocol in isolation"""
1963 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1970 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1964 opts.get('branch'))
1971 opts.get('branch'))
1965 remote = hg.peer(repo, opts, remoteurl)
1972 remote = hg.peer(repo, opts, remoteurl)
1966 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1973 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1967
1974
1968 # make sure tests are repeatable
1975 # make sure tests are repeatable
1969 random.seed(12323)
1976 random.seed(12323)
1970
1977
1971 def doit(localheads, remoteheads, remote=remote):
1978 def doit(localheads, remoteheads, remote=remote):
1972 if opts.get('old'):
1979 if opts.get('old'):
1973 if localheads:
1980 if localheads:
1974 raise util.Abort('cannot use localheads with old style '
1981 raise util.Abort('cannot use localheads with old style '
1975 'discovery')
1982 'discovery')
1976 if not util.safehasattr(remote, 'branches'):
1983 if not util.safehasattr(remote, 'branches'):
1977 # enable in-client legacy support
1984 # enable in-client legacy support
1978 remote = localrepo.locallegacypeer(remote.local())
1985 remote = localrepo.locallegacypeer(remote.local())
1979 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1986 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1980 force=True)
1987 force=True)
1981 common = set(common)
1988 common = set(common)
1982 if not opts.get('nonheads'):
1989 if not opts.get('nonheads'):
1983 ui.write(("unpruned common: %s\n") %
1990 ui.write(("unpruned common: %s\n") %
1984 " ".join(sorted(short(n) for n in common)))
1991 " ".join(sorted(short(n) for n in common)))
1985 dag = dagutil.revlogdag(repo.changelog)
1992 dag = dagutil.revlogdag(repo.changelog)
1986 all = dag.ancestorset(dag.internalizeall(common))
1993 all = dag.ancestorset(dag.internalizeall(common))
1987 common = dag.externalizeall(dag.headsetofconnecteds(all))
1994 common = dag.externalizeall(dag.headsetofconnecteds(all))
1988 else:
1995 else:
1989 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1996 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1990 common = set(common)
1997 common = set(common)
1991 rheads = set(hds)
1998 rheads = set(hds)
1992 lheads = set(repo.heads())
1999 lheads = set(repo.heads())
1993 ui.write(("common heads: %s\n") %
2000 ui.write(("common heads: %s\n") %
1994 " ".join(sorted(short(n) for n in common)))
2001 " ".join(sorted(short(n) for n in common)))
1995 if lheads <= common:
2002 if lheads <= common:
1996 ui.write(("local is subset\n"))
2003 ui.write(("local is subset\n"))
1997 elif rheads <= common:
2004 elif rheads <= common:
1998 ui.write(("remote is subset\n"))
2005 ui.write(("remote is subset\n"))
1999
2006
2000 serverlogs = opts.get('serverlog')
2007 serverlogs = opts.get('serverlog')
2001 if serverlogs:
2008 if serverlogs:
2002 for filename in serverlogs:
2009 for filename in serverlogs:
2003 logfile = open(filename, 'r')
2010 logfile = open(filename, 'r')
2004 try:
2011 try:
2005 line = logfile.readline()
2012 line = logfile.readline()
2006 while line:
2013 while line:
2007 parts = line.strip().split(';')
2014 parts = line.strip().split(';')
2008 op = parts[1]
2015 op = parts[1]
2009 if op == 'cg':
2016 if op == 'cg':
2010 pass
2017 pass
2011 elif op == 'cgss':
2018 elif op == 'cgss':
2012 doit(parts[2].split(' '), parts[3].split(' '))
2019 doit(parts[2].split(' '), parts[3].split(' '))
2013 elif op == 'unb':
2020 elif op == 'unb':
2014 doit(parts[3].split(' '), parts[2].split(' '))
2021 doit(parts[3].split(' '), parts[2].split(' '))
2015 line = logfile.readline()
2022 line = logfile.readline()
2016 finally:
2023 finally:
2017 logfile.close()
2024 logfile.close()
2018
2025
2019 else:
2026 else:
2020 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2027 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2021 opts.get('remote_head'))
2028 opts.get('remote_head'))
2022 localrevs = opts.get('local_head')
2029 localrevs = opts.get('local_head')
2023 doit(localrevs, remoterevs)
2030 doit(localrevs, remoterevs)
2024
2031
2025 @command('debugfileset',
2032 @command('debugfileset',
2026 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2033 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2027 _('[-r REV] FILESPEC'))
2034 _('[-r REV] FILESPEC'))
2028 def debugfileset(ui, repo, expr, **opts):
2035 def debugfileset(ui, repo, expr, **opts):
2029 '''parse and apply a fileset specification'''
2036 '''parse and apply a fileset specification'''
2030 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2037 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2031 if ui.verbose:
2038 if ui.verbose:
2032 tree = fileset.parse(expr)[0]
2039 tree = fileset.parse(expr)[0]
2033 ui.note(tree, "\n")
2040 ui.note(tree, "\n")
2034
2041
2035 for f in ctx.getfileset(expr):
2042 for f in ctx.getfileset(expr):
2036 ui.write("%s\n" % f)
2043 ui.write("%s\n" % f)
2037
2044
2038 @command('debugfsinfo', [], _('[PATH]'))
2045 @command('debugfsinfo', [], _('[PATH]'))
2039 def debugfsinfo(ui, path="."):
2046 def debugfsinfo(ui, path="."):
2040 """show information detected about current filesystem"""
2047 """show information detected about current filesystem"""
2041 util.writefile('.debugfsinfo', '')
2048 util.writefile('.debugfsinfo', '')
2042 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2049 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2043 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2050 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2044 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2051 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2045 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2052 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2046 and 'yes' or 'no'))
2053 and 'yes' or 'no'))
2047 os.unlink('.debugfsinfo')
2054 os.unlink('.debugfsinfo')
2048
2055
2049 @command('debuggetbundle',
2056 @command('debuggetbundle',
2050 [('H', 'head', [], _('id of head node'), _('ID')),
2057 [('H', 'head', [], _('id of head node'), _('ID')),
2051 ('C', 'common', [], _('id of common node'), _('ID')),
2058 ('C', 'common', [], _('id of common node'), _('ID')),
2052 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2059 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2053 _('REPO FILE [-H|-C ID]...'))
2060 _('REPO FILE [-H|-C ID]...'))
2054 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2061 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2055 """retrieves a bundle from a repo
2062 """retrieves a bundle from a repo
2056
2063
2057 Every ID must be a full-length hex node id string. Saves the bundle to the
2064 Every ID must be a full-length hex node id string. Saves the bundle to the
2058 given file.
2065 given file.
2059 """
2066 """
2060 repo = hg.peer(ui, opts, repopath)
2067 repo = hg.peer(ui, opts, repopath)
2061 if not repo.capable('getbundle'):
2068 if not repo.capable('getbundle'):
2062 raise util.Abort("getbundle() not supported by target repository")
2069 raise util.Abort("getbundle() not supported by target repository")
2063 args = {}
2070 args = {}
2064 if common:
2071 if common:
2065 args['common'] = [bin(s) for s in common]
2072 args['common'] = [bin(s) for s in common]
2066 if head:
2073 if head:
2067 args['heads'] = [bin(s) for s in head]
2074 args['heads'] = [bin(s) for s in head]
2068 # TODO: get desired bundlecaps from command line.
2075 # TODO: get desired bundlecaps from command line.
2069 args['bundlecaps'] = None
2076 args['bundlecaps'] = None
2070 bundle = repo.getbundle('debug', **args)
2077 bundle = repo.getbundle('debug', **args)
2071
2078
2072 bundletype = opts.get('type', 'bzip2').lower()
2079 bundletype = opts.get('type', 'bzip2').lower()
2073 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2080 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2074 bundletype = btypes.get(bundletype)
2081 bundletype = btypes.get(bundletype)
2075 if bundletype not in changegroup.bundletypes:
2082 if bundletype not in changegroup.bundletypes:
2076 raise util.Abort(_('unknown bundle type specified with --type'))
2083 raise util.Abort(_('unknown bundle type specified with --type'))
2077 changegroup.writebundle(bundle, bundlepath, bundletype)
2084 changegroup.writebundle(bundle, bundlepath, bundletype)
2078
2085
2079 @command('debugignore', [], '')
2086 @command('debugignore', [], '')
2080 def debugignore(ui, repo, *values, **opts):
2087 def debugignore(ui, repo, *values, **opts):
2081 """display the combined ignore pattern"""
2088 """display the combined ignore pattern"""
2082 ignore = repo.dirstate._ignore
2089 ignore = repo.dirstate._ignore
2083 includepat = getattr(ignore, 'includepat', None)
2090 includepat = getattr(ignore, 'includepat', None)
2084 if includepat is not None:
2091 if includepat is not None:
2085 ui.write("%s\n" % includepat)
2092 ui.write("%s\n" % includepat)
2086 else:
2093 else:
2087 raise util.Abort(_("no ignore patterns found"))
2094 raise util.Abort(_("no ignore patterns found"))
2088
2095
2089 @command('debugindex',
2096 @command('debugindex',
2090 [('c', 'changelog', False, _('open changelog')),
2097 [('c', 'changelog', False, _('open changelog')),
2091 ('m', 'manifest', False, _('open manifest')),
2098 ('m', 'manifest', False, _('open manifest')),
2092 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2099 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2093 _('[-f FORMAT] -c|-m|FILE'))
2100 _('[-f FORMAT] -c|-m|FILE'))
2094 def debugindex(ui, repo, file_=None, **opts):
2101 def debugindex(ui, repo, file_=None, **opts):
2095 """dump the contents of an index file"""
2102 """dump the contents of an index file"""
2096 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2103 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2097 format = opts.get('format', 0)
2104 format = opts.get('format', 0)
2098 if format not in (0, 1):
2105 if format not in (0, 1):
2099 raise util.Abort(_("unknown format %d") % format)
2106 raise util.Abort(_("unknown format %d") % format)
2100
2107
2101 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2108 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2102 if generaldelta:
2109 if generaldelta:
2103 basehdr = ' delta'
2110 basehdr = ' delta'
2104 else:
2111 else:
2105 basehdr = ' base'
2112 basehdr = ' base'
2106
2113
2107 if format == 0:
2114 if format == 0:
2108 ui.write(" rev offset length " + basehdr + " linkrev"
2115 ui.write(" rev offset length " + basehdr + " linkrev"
2109 " nodeid p1 p2\n")
2116 " nodeid p1 p2\n")
2110 elif format == 1:
2117 elif format == 1:
2111 ui.write(" rev flag offset length"
2118 ui.write(" rev flag offset length"
2112 " size " + basehdr + " link p1 p2"
2119 " size " + basehdr + " link p1 p2"
2113 " nodeid\n")
2120 " nodeid\n")
2114
2121
2115 for i in r:
2122 for i in r:
2116 node = r.node(i)
2123 node = r.node(i)
2117 if generaldelta:
2124 if generaldelta:
2118 base = r.deltaparent(i)
2125 base = r.deltaparent(i)
2119 else:
2126 else:
2120 base = r.chainbase(i)
2127 base = r.chainbase(i)
2121 if format == 0:
2128 if format == 0:
2122 try:
2129 try:
2123 pp = r.parents(node)
2130 pp = r.parents(node)
2124 except Exception:
2131 except Exception:
2125 pp = [nullid, nullid]
2132 pp = [nullid, nullid]
2126 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2133 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2127 i, r.start(i), r.length(i), base, r.linkrev(i),
2134 i, r.start(i), r.length(i), base, r.linkrev(i),
2128 short(node), short(pp[0]), short(pp[1])))
2135 short(node), short(pp[0]), short(pp[1])))
2129 elif format == 1:
2136 elif format == 1:
2130 pr = r.parentrevs(i)
2137 pr = r.parentrevs(i)
2131 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2138 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2132 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2139 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2133 base, r.linkrev(i), pr[0], pr[1], short(node)))
2140 base, r.linkrev(i), pr[0], pr[1], short(node)))
2134
2141
2135 @command('debugindexdot', [], _('FILE'))
2142 @command('debugindexdot', [], _('FILE'))
2136 def debugindexdot(ui, repo, file_):
2143 def debugindexdot(ui, repo, file_):
2137 """dump an index DAG as a graphviz dot file"""
2144 """dump an index DAG as a graphviz dot file"""
2138 r = None
2145 r = None
2139 if repo:
2146 if repo:
2140 filelog = repo.file(file_)
2147 filelog = repo.file(file_)
2141 if len(filelog):
2148 if len(filelog):
2142 r = filelog
2149 r = filelog
2143 if not r:
2150 if not r:
2144 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2151 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2145 ui.write(("digraph G {\n"))
2152 ui.write(("digraph G {\n"))
2146 for i in r:
2153 for i in r:
2147 node = r.node(i)
2154 node = r.node(i)
2148 pp = r.parents(node)
2155 pp = r.parents(node)
2149 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2156 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2150 if pp[1] != nullid:
2157 if pp[1] != nullid:
2151 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2158 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2152 ui.write("}\n")
2159 ui.write("}\n")
2153
2160
2154 @command('debuginstall', [], '')
2161 @command('debuginstall', [], '')
2155 def debuginstall(ui):
2162 def debuginstall(ui):
2156 '''test Mercurial installation
2163 '''test Mercurial installation
2157
2164
2158 Returns 0 on success.
2165 Returns 0 on success.
2159 '''
2166 '''
2160
2167
2161 def writetemp(contents):
2168 def writetemp(contents):
2162 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2169 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2163 f = os.fdopen(fd, "wb")
2170 f = os.fdopen(fd, "wb")
2164 f.write(contents)
2171 f.write(contents)
2165 f.close()
2172 f.close()
2166 return name
2173 return name
2167
2174
2168 problems = 0
2175 problems = 0
2169
2176
2170 # encoding
2177 # encoding
2171 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2178 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2172 try:
2179 try:
2173 encoding.fromlocal("test")
2180 encoding.fromlocal("test")
2174 except util.Abort, inst:
2181 except util.Abort, inst:
2175 ui.write(" %s\n" % inst)
2182 ui.write(" %s\n" % inst)
2176 ui.write(_(" (check that your locale is properly set)\n"))
2183 ui.write(_(" (check that your locale is properly set)\n"))
2177 problems += 1
2184 problems += 1
2178
2185
2179 # Python
2186 # Python
2180 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2187 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2181 ui.status(_("checking Python version (%s)\n")
2188 ui.status(_("checking Python version (%s)\n")
2182 % ("%s.%s.%s" % sys.version_info[:3]))
2189 % ("%s.%s.%s" % sys.version_info[:3]))
2183 ui.status(_("checking Python lib (%s)...\n")
2190 ui.status(_("checking Python lib (%s)...\n")
2184 % os.path.dirname(os.__file__))
2191 % os.path.dirname(os.__file__))
2185
2192
2186 # compiled modules
2193 # compiled modules
2187 ui.status(_("checking installed modules (%s)...\n")
2194 ui.status(_("checking installed modules (%s)...\n")
2188 % os.path.dirname(__file__))
2195 % os.path.dirname(__file__))
2189 try:
2196 try:
2190 import bdiff, mpatch, base85, osutil
2197 import bdiff, mpatch, base85, osutil
2191 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2198 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2192 except Exception, inst:
2199 except Exception, inst:
2193 ui.write(" %s\n" % inst)
2200 ui.write(" %s\n" % inst)
2194 ui.write(_(" One or more extensions could not be found"))
2201 ui.write(_(" One or more extensions could not be found"))
2195 ui.write(_(" (check that you compiled the extensions)\n"))
2202 ui.write(_(" (check that you compiled the extensions)\n"))
2196 problems += 1
2203 problems += 1
2197
2204
2198 # templates
2205 # templates
2199 import templater
2206 import templater
2200 p = templater.templatepath()
2207 p = templater.templatepath()
2201 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2208 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2202 if p:
2209 if p:
2203 m = templater.templatepath("map-cmdline.default")
2210 m = templater.templatepath("map-cmdline.default")
2204 if m:
2211 if m:
2205 # template found, check if it is working
2212 # template found, check if it is working
2206 try:
2213 try:
2207 templater.templater(m)
2214 templater.templater(m)
2208 except Exception, inst:
2215 except Exception, inst:
2209 ui.write(" %s\n" % inst)
2216 ui.write(" %s\n" % inst)
2210 p = None
2217 p = None
2211 else:
2218 else:
2212 ui.write(_(" template 'default' not found\n"))
2219 ui.write(_(" template 'default' not found\n"))
2213 p = None
2220 p = None
2214 else:
2221 else:
2215 ui.write(_(" no template directories found\n"))
2222 ui.write(_(" no template directories found\n"))
2216 if not p:
2223 if not p:
2217 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2224 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2218 problems += 1
2225 problems += 1
2219
2226
2220 # editor
2227 # editor
2221 ui.status(_("checking commit editor...\n"))
2228 ui.status(_("checking commit editor...\n"))
2222 editor = ui.geteditor()
2229 editor = ui.geteditor()
2223 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2230 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2224 if not cmdpath:
2231 if not cmdpath:
2225 if editor == 'vi':
2232 if editor == 'vi':
2226 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2233 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2227 ui.write(_(" (specify a commit editor in your configuration"
2234 ui.write(_(" (specify a commit editor in your configuration"
2228 " file)\n"))
2235 " file)\n"))
2229 else:
2236 else:
2230 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2237 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2231 ui.write(_(" (specify a commit editor in your configuration"
2238 ui.write(_(" (specify a commit editor in your configuration"
2232 " file)\n"))
2239 " file)\n"))
2233 problems += 1
2240 problems += 1
2234
2241
2235 # check username
2242 # check username
2236 ui.status(_("checking username...\n"))
2243 ui.status(_("checking username...\n"))
2237 try:
2244 try:
2238 ui.username()
2245 ui.username()
2239 except util.Abort, e:
2246 except util.Abort, e:
2240 ui.write(" %s\n" % e)
2247 ui.write(" %s\n" % e)
2241 ui.write(_(" (specify a username in your configuration file)\n"))
2248 ui.write(_(" (specify a username in your configuration file)\n"))
2242 problems += 1
2249 problems += 1
2243
2250
2244 if not problems:
2251 if not problems:
2245 ui.status(_("no problems detected\n"))
2252 ui.status(_("no problems detected\n"))
2246 else:
2253 else:
2247 ui.write(_("%s problems detected,"
2254 ui.write(_("%s problems detected,"
2248 " please check your install!\n") % problems)
2255 " please check your install!\n") % problems)
2249
2256
2250 return problems
2257 return problems
2251
2258
2252 @command('debugknown', [], _('REPO ID...'))
2259 @command('debugknown', [], _('REPO ID...'))
2253 def debugknown(ui, repopath, *ids, **opts):
2260 def debugknown(ui, repopath, *ids, **opts):
2254 """test whether node ids are known to a repo
2261 """test whether node ids are known to a repo
2255
2262
2256 Every ID must be a full-length hex node id string. Returns a list of 0s
2263 Every ID must be a full-length hex node id string. Returns a list of 0s
2257 and 1s indicating unknown/known.
2264 and 1s indicating unknown/known.
2258 """
2265 """
2259 repo = hg.peer(ui, opts, repopath)
2266 repo = hg.peer(ui, opts, repopath)
2260 if not repo.capable('known'):
2267 if not repo.capable('known'):
2261 raise util.Abort("known() not supported by target repository")
2268 raise util.Abort("known() not supported by target repository")
2262 flags = repo.known([bin(s) for s in ids])
2269 flags = repo.known([bin(s) for s in ids])
2263 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2270 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2264
2271
2265 @command('debuglabelcomplete', [], _('LABEL...'))
2272 @command('debuglabelcomplete', [], _('LABEL...'))
2266 def debuglabelcomplete(ui, repo, *args):
2273 def debuglabelcomplete(ui, repo, *args):
2267 '''complete "labels" - tags, open branch names, bookmark names'''
2274 '''complete "labels" - tags, open branch names, bookmark names'''
2268
2275
2269 labels = set()
2276 labels = set()
2270 labels.update(t[0] for t in repo.tagslist())
2277 labels.update(t[0] for t in repo.tagslist())
2271 labels.update(repo._bookmarks.keys())
2278 labels.update(repo._bookmarks.keys())
2272 labels.update(tag for (tag, heads, tip, closed)
2279 labels.update(tag for (tag, heads, tip, closed)
2273 in repo.branchmap().iterbranches() if not closed)
2280 in repo.branchmap().iterbranches() if not closed)
2274 completions = set()
2281 completions = set()
2275 if not args:
2282 if not args:
2276 args = ['']
2283 args = ['']
2277 for a in args:
2284 for a in args:
2278 completions.update(l for l in labels if l.startswith(a))
2285 completions.update(l for l in labels if l.startswith(a))
2279 ui.write('\n'.join(sorted(completions)))
2286 ui.write('\n'.join(sorted(completions)))
2280 ui.write('\n')
2287 ui.write('\n')
2281
2288
2282 @command('debugobsolete',
2289 @command('debugobsolete',
2283 [('', 'flags', 0, _('markers flag')),
2290 [('', 'flags', 0, _('markers flag')),
2284 ] + commitopts2,
2291 ] + commitopts2,
2285 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2292 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2286 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2293 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2287 """create arbitrary obsolete marker
2294 """create arbitrary obsolete marker
2288
2295
2289 With no arguments, displays the list of obsolescence markers."""
2296 With no arguments, displays the list of obsolescence markers."""
2290 def parsenodeid(s):
2297 def parsenodeid(s):
2291 try:
2298 try:
2292 # We do not use revsingle/revrange functions here to accept
2299 # We do not use revsingle/revrange functions here to accept
2293 # arbitrary node identifiers, possibly not present in the
2300 # arbitrary node identifiers, possibly not present in the
2294 # local repository.
2301 # local repository.
2295 n = bin(s)
2302 n = bin(s)
2296 if len(n) != len(nullid):
2303 if len(n) != len(nullid):
2297 raise TypeError()
2304 raise TypeError()
2298 return n
2305 return n
2299 except TypeError:
2306 except TypeError:
2300 raise util.Abort('changeset references must be full hexadecimal '
2307 raise util.Abort('changeset references must be full hexadecimal '
2301 'node identifiers')
2308 'node identifiers')
2302
2309
2303 if precursor is not None:
2310 if precursor is not None:
2304 metadata = {}
2311 metadata = {}
2305 if 'date' in opts:
2312 if 'date' in opts:
2306 metadata['date'] = opts['date']
2313 metadata['date'] = opts['date']
2307 metadata['user'] = opts['user'] or ui.username()
2314 metadata['user'] = opts['user'] or ui.username()
2308 succs = tuple(parsenodeid(succ) for succ in successors)
2315 succs = tuple(parsenodeid(succ) for succ in successors)
2309 l = repo.lock()
2316 l = repo.lock()
2310 try:
2317 try:
2311 tr = repo.transaction('debugobsolete')
2318 tr = repo.transaction('debugobsolete')
2312 try:
2319 try:
2313 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2320 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2314 opts['flags'], metadata)
2321 opts['flags'], metadata)
2315 tr.close()
2322 tr.close()
2316 finally:
2323 finally:
2317 tr.release()
2324 tr.release()
2318 finally:
2325 finally:
2319 l.release()
2326 l.release()
2320 else:
2327 else:
2321 for m in obsolete.allmarkers(repo):
2328 for m in obsolete.allmarkers(repo):
2322 cmdutil.showmarker(ui, m)
2329 cmdutil.showmarker(ui, m)
2323
2330
2324 @command('debugpathcomplete',
2331 @command('debugpathcomplete',
2325 [('f', 'full', None, _('complete an entire path')),
2332 [('f', 'full', None, _('complete an entire path')),
2326 ('n', 'normal', None, _('show only normal files')),
2333 ('n', 'normal', None, _('show only normal files')),
2327 ('a', 'added', None, _('show only added files')),
2334 ('a', 'added', None, _('show only added files')),
2328 ('r', 'removed', None, _('show only removed files'))],
2335 ('r', 'removed', None, _('show only removed files'))],
2329 _('FILESPEC...'))
2336 _('FILESPEC...'))
2330 def debugpathcomplete(ui, repo, *specs, **opts):
2337 def debugpathcomplete(ui, repo, *specs, **opts):
2331 '''complete part or all of a tracked path
2338 '''complete part or all of a tracked path
2332
2339
2333 This command supports shells that offer path name completion. It
2340 This command supports shells that offer path name completion. It
2334 currently completes only files already known to the dirstate.
2341 currently completes only files already known to the dirstate.
2335
2342
2336 Completion extends only to the next path segment unless
2343 Completion extends only to the next path segment unless
2337 --full is specified, in which case entire paths are used.'''
2344 --full is specified, in which case entire paths are used.'''
2338
2345
2339 def complete(path, acceptable):
2346 def complete(path, acceptable):
2340 dirstate = repo.dirstate
2347 dirstate = repo.dirstate
2341 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2348 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2342 rootdir = repo.root + os.sep
2349 rootdir = repo.root + os.sep
2343 if spec != repo.root and not spec.startswith(rootdir):
2350 if spec != repo.root and not spec.startswith(rootdir):
2344 return [], []
2351 return [], []
2345 if os.path.isdir(spec):
2352 if os.path.isdir(spec):
2346 spec += '/'
2353 spec += '/'
2347 spec = spec[len(rootdir):]
2354 spec = spec[len(rootdir):]
2348 fixpaths = os.sep != '/'
2355 fixpaths = os.sep != '/'
2349 if fixpaths:
2356 if fixpaths:
2350 spec = spec.replace(os.sep, '/')
2357 spec = spec.replace(os.sep, '/')
2351 speclen = len(spec)
2358 speclen = len(spec)
2352 fullpaths = opts['full']
2359 fullpaths = opts['full']
2353 files, dirs = set(), set()
2360 files, dirs = set(), set()
2354 adddir, addfile = dirs.add, files.add
2361 adddir, addfile = dirs.add, files.add
2355 for f, st in dirstate.iteritems():
2362 for f, st in dirstate.iteritems():
2356 if f.startswith(spec) and st[0] in acceptable:
2363 if f.startswith(spec) and st[0] in acceptable:
2357 if fixpaths:
2364 if fixpaths:
2358 f = f.replace('/', os.sep)
2365 f = f.replace('/', os.sep)
2359 if fullpaths:
2366 if fullpaths:
2360 addfile(f)
2367 addfile(f)
2361 continue
2368 continue
2362 s = f.find(os.sep, speclen)
2369 s = f.find(os.sep, speclen)
2363 if s >= 0:
2370 if s >= 0:
2364 adddir(f[:s])
2371 adddir(f[:s])
2365 else:
2372 else:
2366 addfile(f)
2373 addfile(f)
2367 return files, dirs
2374 return files, dirs
2368
2375
2369 acceptable = ''
2376 acceptable = ''
2370 if opts['normal']:
2377 if opts['normal']:
2371 acceptable += 'nm'
2378 acceptable += 'nm'
2372 if opts['added']:
2379 if opts['added']:
2373 acceptable += 'a'
2380 acceptable += 'a'
2374 if opts['removed']:
2381 if opts['removed']:
2375 acceptable += 'r'
2382 acceptable += 'r'
2376 cwd = repo.getcwd()
2383 cwd = repo.getcwd()
2377 if not specs:
2384 if not specs:
2378 specs = ['.']
2385 specs = ['.']
2379
2386
2380 files, dirs = set(), set()
2387 files, dirs = set(), set()
2381 for spec in specs:
2388 for spec in specs:
2382 f, d = complete(spec, acceptable or 'nmar')
2389 f, d = complete(spec, acceptable or 'nmar')
2383 files.update(f)
2390 files.update(f)
2384 dirs.update(d)
2391 dirs.update(d)
2385 files.update(dirs)
2392 files.update(dirs)
2386 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2393 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2387 ui.write('\n')
2394 ui.write('\n')
2388
2395
2389 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2396 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2390 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2397 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2391 '''access the pushkey key/value protocol
2398 '''access the pushkey key/value protocol
2392
2399
2393 With two args, list the keys in the given namespace.
2400 With two args, list the keys in the given namespace.
2394
2401
2395 With five args, set a key to new if it currently is set to old.
2402 With five args, set a key to new if it currently is set to old.
2396 Reports success or failure.
2403 Reports success or failure.
2397 '''
2404 '''
2398
2405
2399 target = hg.peer(ui, {}, repopath)
2406 target = hg.peer(ui, {}, repopath)
2400 if keyinfo:
2407 if keyinfo:
2401 key, old, new = keyinfo
2408 key, old, new = keyinfo
2402 r = target.pushkey(namespace, key, old, new)
2409 r = target.pushkey(namespace, key, old, new)
2403 ui.status(str(r) + '\n')
2410 ui.status(str(r) + '\n')
2404 return not r
2411 return not r
2405 else:
2412 else:
2406 for k, v in sorted(target.listkeys(namespace).iteritems()):
2413 for k, v in sorted(target.listkeys(namespace).iteritems()):
2407 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2414 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2408 v.encode('string-escape')))
2415 v.encode('string-escape')))
2409
2416
2410 @command('debugpvec', [], _('A B'))
2417 @command('debugpvec', [], _('A B'))
2411 def debugpvec(ui, repo, a, b=None):
2418 def debugpvec(ui, repo, a, b=None):
2412 ca = scmutil.revsingle(repo, a)
2419 ca = scmutil.revsingle(repo, a)
2413 cb = scmutil.revsingle(repo, b)
2420 cb = scmutil.revsingle(repo, b)
2414 pa = pvec.ctxpvec(ca)
2421 pa = pvec.ctxpvec(ca)
2415 pb = pvec.ctxpvec(cb)
2422 pb = pvec.ctxpvec(cb)
2416 if pa == pb:
2423 if pa == pb:
2417 rel = "="
2424 rel = "="
2418 elif pa > pb:
2425 elif pa > pb:
2419 rel = ">"
2426 rel = ">"
2420 elif pa < pb:
2427 elif pa < pb:
2421 rel = "<"
2428 rel = "<"
2422 elif pa | pb:
2429 elif pa | pb:
2423 rel = "|"
2430 rel = "|"
2424 ui.write(_("a: %s\n") % pa)
2431 ui.write(_("a: %s\n") % pa)
2425 ui.write(_("b: %s\n") % pb)
2432 ui.write(_("b: %s\n") % pb)
2426 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2433 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2427 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2434 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2428 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2435 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2429 pa.distance(pb), rel))
2436 pa.distance(pb), rel))
2430
2437
2431 @command('debugrebuilddirstate|debugrebuildstate',
2438 @command('debugrebuilddirstate|debugrebuildstate',
2432 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2439 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2433 _('[-r REV]'))
2440 _('[-r REV]'))
2434 def debugrebuilddirstate(ui, repo, rev):
2441 def debugrebuilddirstate(ui, repo, rev):
2435 """rebuild the dirstate as it would look like for the given revision
2442 """rebuild the dirstate as it would look like for the given revision
2436
2443
2437 If no revision is specified the first current parent will be used.
2444 If no revision is specified the first current parent will be used.
2438
2445
2439 The dirstate will be set to the files of the given revision.
2446 The dirstate will be set to the files of the given revision.
2440 The actual working directory content or existing dirstate
2447 The actual working directory content or existing dirstate
2441 information such as adds or removes is not considered.
2448 information such as adds or removes is not considered.
2442
2449
2443 One use of this command is to make the next :hg:`status` invocation
2450 One use of this command is to make the next :hg:`status` invocation
2444 check the actual file content.
2451 check the actual file content.
2445 """
2452 """
2446 ctx = scmutil.revsingle(repo, rev)
2453 ctx = scmutil.revsingle(repo, rev)
2447 wlock = repo.wlock()
2454 wlock = repo.wlock()
2448 try:
2455 try:
2449 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2456 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2450 finally:
2457 finally:
2451 wlock.release()
2458 wlock.release()
2452
2459
2453 @command('debugrename',
2460 @command('debugrename',
2454 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2461 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2455 _('[-r REV] FILE'))
2462 _('[-r REV] FILE'))
2456 def debugrename(ui, repo, file1, *pats, **opts):
2463 def debugrename(ui, repo, file1, *pats, **opts):
2457 """dump rename information"""
2464 """dump rename information"""
2458
2465
2459 ctx = scmutil.revsingle(repo, opts.get('rev'))
2466 ctx = scmutil.revsingle(repo, opts.get('rev'))
2460 m = scmutil.match(ctx, (file1,) + pats, opts)
2467 m = scmutil.match(ctx, (file1,) + pats, opts)
2461 for abs in ctx.walk(m):
2468 for abs in ctx.walk(m):
2462 fctx = ctx[abs]
2469 fctx = ctx[abs]
2463 o = fctx.filelog().renamed(fctx.filenode())
2470 o = fctx.filelog().renamed(fctx.filenode())
2464 rel = m.rel(abs)
2471 rel = m.rel(abs)
2465 if o:
2472 if o:
2466 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2473 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2467 else:
2474 else:
2468 ui.write(_("%s not renamed\n") % rel)
2475 ui.write(_("%s not renamed\n") % rel)
2469
2476
2470 @command('debugrevlog',
2477 @command('debugrevlog',
2471 [('c', 'changelog', False, _('open changelog')),
2478 [('c', 'changelog', False, _('open changelog')),
2472 ('m', 'manifest', False, _('open manifest')),
2479 ('m', 'manifest', False, _('open manifest')),
2473 ('d', 'dump', False, _('dump index data'))],
2480 ('d', 'dump', False, _('dump index data'))],
2474 _('-c|-m|FILE'))
2481 _('-c|-m|FILE'))
2475 def debugrevlog(ui, repo, file_=None, **opts):
2482 def debugrevlog(ui, repo, file_=None, **opts):
2476 """show data and statistics about a revlog"""
2483 """show data and statistics about a revlog"""
2477 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2484 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2478
2485
2479 if opts.get("dump"):
2486 if opts.get("dump"):
2480 numrevs = len(r)
2487 numrevs = len(r)
2481 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2488 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2482 " rawsize totalsize compression heads\n")
2489 " rawsize totalsize compression heads\n")
2483 ts = 0
2490 ts = 0
2484 heads = set()
2491 heads = set()
2485 for rev in xrange(numrevs):
2492 for rev in xrange(numrevs):
2486 dbase = r.deltaparent(rev)
2493 dbase = r.deltaparent(rev)
2487 if dbase == -1:
2494 if dbase == -1:
2488 dbase = rev
2495 dbase = rev
2489 cbase = r.chainbase(rev)
2496 cbase = r.chainbase(rev)
2490 p1, p2 = r.parentrevs(rev)
2497 p1, p2 = r.parentrevs(rev)
2491 rs = r.rawsize(rev)
2498 rs = r.rawsize(rev)
2492 ts = ts + rs
2499 ts = ts + rs
2493 heads -= set(r.parentrevs(rev))
2500 heads -= set(r.parentrevs(rev))
2494 heads.add(rev)
2501 heads.add(rev)
2495 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2502 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2496 (rev, p1, p2, r.start(rev), r.end(rev),
2503 (rev, p1, p2, r.start(rev), r.end(rev),
2497 r.start(dbase), r.start(cbase),
2504 r.start(dbase), r.start(cbase),
2498 r.start(p1), r.start(p2),
2505 r.start(p1), r.start(p2),
2499 rs, ts, ts / r.end(rev), len(heads)))
2506 rs, ts, ts / r.end(rev), len(heads)))
2500 return 0
2507 return 0
2501
2508
2502 v = r.version
2509 v = r.version
2503 format = v & 0xFFFF
2510 format = v & 0xFFFF
2504 flags = []
2511 flags = []
2505 gdelta = False
2512 gdelta = False
2506 if v & revlog.REVLOGNGINLINEDATA:
2513 if v & revlog.REVLOGNGINLINEDATA:
2507 flags.append('inline')
2514 flags.append('inline')
2508 if v & revlog.REVLOGGENERALDELTA:
2515 if v & revlog.REVLOGGENERALDELTA:
2509 gdelta = True
2516 gdelta = True
2510 flags.append('generaldelta')
2517 flags.append('generaldelta')
2511 if not flags:
2518 if not flags:
2512 flags = ['(none)']
2519 flags = ['(none)']
2513
2520
2514 nummerges = 0
2521 nummerges = 0
2515 numfull = 0
2522 numfull = 0
2516 numprev = 0
2523 numprev = 0
2517 nump1 = 0
2524 nump1 = 0
2518 nump2 = 0
2525 nump2 = 0
2519 numother = 0
2526 numother = 0
2520 nump1prev = 0
2527 nump1prev = 0
2521 nump2prev = 0
2528 nump2prev = 0
2522 chainlengths = []
2529 chainlengths = []
2523
2530
2524 datasize = [None, 0, 0L]
2531 datasize = [None, 0, 0L]
2525 fullsize = [None, 0, 0L]
2532 fullsize = [None, 0, 0L]
2526 deltasize = [None, 0, 0L]
2533 deltasize = [None, 0, 0L]
2527
2534
2528 def addsize(size, l):
2535 def addsize(size, l):
2529 if l[0] is None or size < l[0]:
2536 if l[0] is None or size < l[0]:
2530 l[0] = size
2537 l[0] = size
2531 if size > l[1]:
2538 if size > l[1]:
2532 l[1] = size
2539 l[1] = size
2533 l[2] += size
2540 l[2] += size
2534
2541
2535 numrevs = len(r)
2542 numrevs = len(r)
2536 for rev in xrange(numrevs):
2543 for rev in xrange(numrevs):
2537 p1, p2 = r.parentrevs(rev)
2544 p1, p2 = r.parentrevs(rev)
2538 delta = r.deltaparent(rev)
2545 delta = r.deltaparent(rev)
2539 if format > 0:
2546 if format > 0:
2540 addsize(r.rawsize(rev), datasize)
2547 addsize(r.rawsize(rev), datasize)
2541 if p2 != nullrev:
2548 if p2 != nullrev:
2542 nummerges += 1
2549 nummerges += 1
2543 size = r.length(rev)
2550 size = r.length(rev)
2544 if delta == nullrev:
2551 if delta == nullrev:
2545 chainlengths.append(0)
2552 chainlengths.append(0)
2546 numfull += 1
2553 numfull += 1
2547 addsize(size, fullsize)
2554 addsize(size, fullsize)
2548 else:
2555 else:
2549 chainlengths.append(chainlengths[delta] + 1)
2556 chainlengths.append(chainlengths[delta] + 1)
2550 addsize(size, deltasize)
2557 addsize(size, deltasize)
2551 if delta == rev - 1:
2558 if delta == rev - 1:
2552 numprev += 1
2559 numprev += 1
2553 if delta == p1:
2560 if delta == p1:
2554 nump1prev += 1
2561 nump1prev += 1
2555 elif delta == p2:
2562 elif delta == p2:
2556 nump2prev += 1
2563 nump2prev += 1
2557 elif delta == p1:
2564 elif delta == p1:
2558 nump1 += 1
2565 nump1 += 1
2559 elif delta == p2:
2566 elif delta == p2:
2560 nump2 += 1
2567 nump2 += 1
2561 elif delta != nullrev:
2568 elif delta != nullrev:
2562 numother += 1
2569 numother += 1
2563
2570
2564 # Adjust size min value for empty cases
2571 # Adjust size min value for empty cases
2565 for size in (datasize, fullsize, deltasize):
2572 for size in (datasize, fullsize, deltasize):
2566 if size[0] is None:
2573 if size[0] is None:
2567 size[0] = 0
2574 size[0] = 0
2568
2575
2569 numdeltas = numrevs - numfull
2576 numdeltas = numrevs - numfull
2570 numoprev = numprev - nump1prev - nump2prev
2577 numoprev = numprev - nump1prev - nump2prev
2571 totalrawsize = datasize[2]
2578 totalrawsize = datasize[2]
2572 datasize[2] /= numrevs
2579 datasize[2] /= numrevs
2573 fulltotal = fullsize[2]
2580 fulltotal = fullsize[2]
2574 fullsize[2] /= numfull
2581 fullsize[2] /= numfull
2575 deltatotal = deltasize[2]
2582 deltatotal = deltasize[2]
2576 if numrevs - numfull > 0:
2583 if numrevs - numfull > 0:
2577 deltasize[2] /= numrevs - numfull
2584 deltasize[2] /= numrevs - numfull
2578 totalsize = fulltotal + deltatotal
2585 totalsize = fulltotal + deltatotal
2579 avgchainlen = sum(chainlengths) / numrevs
2586 avgchainlen = sum(chainlengths) / numrevs
2580 compratio = totalrawsize / totalsize
2587 compratio = totalrawsize / totalsize
2581
2588
2582 basedfmtstr = '%%%dd\n'
2589 basedfmtstr = '%%%dd\n'
2583 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2590 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2584
2591
2585 def dfmtstr(max):
2592 def dfmtstr(max):
2586 return basedfmtstr % len(str(max))
2593 return basedfmtstr % len(str(max))
2587 def pcfmtstr(max, padding=0):
2594 def pcfmtstr(max, padding=0):
2588 return basepcfmtstr % (len(str(max)), ' ' * padding)
2595 return basepcfmtstr % (len(str(max)), ' ' * padding)
2589
2596
2590 def pcfmt(value, total):
2597 def pcfmt(value, total):
2591 return (value, 100 * float(value) / total)
2598 return (value, 100 * float(value) / total)
2592
2599
2593 ui.write(('format : %d\n') % format)
2600 ui.write(('format : %d\n') % format)
2594 ui.write(('flags : %s\n') % ', '.join(flags))
2601 ui.write(('flags : %s\n') % ', '.join(flags))
2595
2602
2596 ui.write('\n')
2603 ui.write('\n')
2597 fmt = pcfmtstr(totalsize)
2604 fmt = pcfmtstr(totalsize)
2598 fmt2 = dfmtstr(totalsize)
2605 fmt2 = dfmtstr(totalsize)
2599 ui.write(('revisions : ') + fmt2 % numrevs)
2606 ui.write(('revisions : ') + fmt2 % numrevs)
2600 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2607 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2601 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2608 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2602 ui.write(('revisions : ') + fmt2 % numrevs)
2609 ui.write(('revisions : ') + fmt2 % numrevs)
2603 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2610 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2604 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2611 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2605 ui.write(('revision size : ') + fmt2 % totalsize)
2612 ui.write(('revision size : ') + fmt2 % totalsize)
2606 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2613 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2607 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2614 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2608
2615
2609 ui.write('\n')
2616 ui.write('\n')
2610 fmt = dfmtstr(max(avgchainlen, compratio))
2617 fmt = dfmtstr(max(avgchainlen, compratio))
2611 ui.write(('avg chain length : ') + fmt % avgchainlen)
2618 ui.write(('avg chain length : ') + fmt % avgchainlen)
2612 ui.write(('compression ratio : ') + fmt % compratio)
2619 ui.write(('compression ratio : ') + fmt % compratio)
2613
2620
2614 if format > 0:
2621 if format > 0:
2615 ui.write('\n')
2622 ui.write('\n')
2616 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2623 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2617 % tuple(datasize))
2624 % tuple(datasize))
2618 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2625 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2619 % tuple(fullsize))
2626 % tuple(fullsize))
2620 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2627 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2621 % tuple(deltasize))
2628 % tuple(deltasize))
2622
2629
2623 if numdeltas > 0:
2630 if numdeltas > 0:
2624 ui.write('\n')
2631 ui.write('\n')
2625 fmt = pcfmtstr(numdeltas)
2632 fmt = pcfmtstr(numdeltas)
2626 fmt2 = pcfmtstr(numdeltas, 4)
2633 fmt2 = pcfmtstr(numdeltas, 4)
2627 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2634 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2628 if numprev > 0:
2635 if numprev > 0:
2629 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2636 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2630 numprev))
2637 numprev))
2631 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2638 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2632 numprev))
2639 numprev))
2633 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2640 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2634 numprev))
2641 numprev))
2635 if gdelta:
2642 if gdelta:
2636 ui.write(('deltas against p1 : ')
2643 ui.write(('deltas against p1 : ')
2637 + fmt % pcfmt(nump1, numdeltas))
2644 + fmt % pcfmt(nump1, numdeltas))
2638 ui.write(('deltas against p2 : ')
2645 ui.write(('deltas against p2 : ')
2639 + fmt % pcfmt(nump2, numdeltas))
2646 + fmt % pcfmt(nump2, numdeltas))
2640 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2647 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2641 numdeltas))
2648 numdeltas))
2642
2649
2643 @command('debugrevspec',
2650 @command('debugrevspec',
2644 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2651 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2645 ('REVSPEC'))
2652 ('REVSPEC'))
2646 def debugrevspec(ui, repo, expr, **opts):
2653 def debugrevspec(ui, repo, expr, **opts):
2647 """parse and apply a revision specification
2654 """parse and apply a revision specification
2648
2655
2649 Use --verbose to print the parsed tree before and after aliases
2656 Use --verbose to print the parsed tree before and after aliases
2650 expansion.
2657 expansion.
2651 """
2658 """
2652 if ui.verbose:
2659 if ui.verbose:
2653 tree = revset.parse(expr)[0]
2660 tree = revset.parse(expr)[0]
2654 ui.note(revset.prettyformat(tree), "\n")
2661 ui.note(revset.prettyformat(tree), "\n")
2655 newtree = revset.findaliases(ui, tree)
2662 newtree = revset.findaliases(ui, tree)
2656 if newtree != tree:
2663 if newtree != tree:
2657 ui.note(revset.prettyformat(newtree), "\n")
2664 ui.note(revset.prettyformat(newtree), "\n")
2658 if opts["optimize"]:
2665 if opts["optimize"]:
2659 weight, optimizedtree = revset.optimize(newtree, True)
2666 weight, optimizedtree = revset.optimize(newtree, True)
2660 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2667 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2661 func = revset.match(ui, expr)
2668 func = revset.match(ui, expr)
2662 for c in func(repo, revset.spanset(repo)):
2669 for c in func(repo, revset.spanset(repo)):
2663 ui.write("%s\n" % c)
2670 ui.write("%s\n" % c)
2664
2671
2665 @command('debugsetparents', [], _('REV1 [REV2]'))
2672 @command('debugsetparents', [], _('REV1 [REV2]'))
2666 def debugsetparents(ui, repo, rev1, rev2=None):
2673 def debugsetparents(ui, repo, rev1, rev2=None):
2667 """manually set the parents of the current working directory
2674 """manually set the parents of the current working directory
2668
2675
2669 This is useful for writing repository conversion tools, but should
2676 This is useful for writing repository conversion tools, but should
2670 be used with care.
2677 be used with care.
2671
2678
2672 Returns 0 on success.
2679 Returns 0 on success.
2673 """
2680 """
2674
2681
2675 r1 = scmutil.revsingle(repo, rev1).node()
2682 r1 = scmutil.revsingle(repo, rev1).node()
2676 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2683 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2677
2684
2678 wlock = repo.wlock()
2685 wlock = repo.wlock()
2679 try:
2686 try:
2680 repo.setparents(r1, r2)
2687 repo.setparents(r1, r2)
2681 finally:
2688 finally:
2682 wlock.release()
2689 wlock.release()
2683
2690
2684 @command('debugdirstate|debugstate',
2691 @command('debugdirstate|debugstate',
2685 [('', 'nodates', None, _('do not display the saved mtime')),
2692 [('', 'nodates', None, _('do not display the saved mtime')),
2686 ('', 'datesort', None, _('sort by saved mtime'))],
2693 ('', 'datesort', None, _('sort by saved mtime'))],
2687 _('[OPTION]...'))
2694 _('[OPTION]...'))
2688 def debugstate(ui, repo, nodates=None, datesort=None):
2695 def debugstate(ui, repo, nodates=None, datesort=None):
2689 """show the contents of the current dirstate"""
2696 """show the contents of the current dirstate"""
2690 timestr = ""
2697 timestr = ""
2691 showdate = not nodates
2698 showdate = not nodates
2692 if datesort:
2699 if datesort:
2693 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2700 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2694 else:
2701 else:
2695 keyfunc = None # sort by filename
2702 keyfunc = None # sort by filename
2696 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2703 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2697 if showdate:
2704 if showdate:
2698 if ent[3] == -1:
2705 if ent[3] == -1:
2699 # Pad or slice to locale representation
2706 # Pad or slice to locale representation
2700 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2707 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2701 time.localtime(0)))
2708 time.localtime(0)))
2702 timestr = 'unset'
2709 timestr = 'unset'
2703 timestr = (timestr[:locale_len] +
2710 timestr = (timestr[:locale_len] +
2704 ' ' * (locale_len - len(timestr)))
2711 ' ' * (locale_len - len(timestr)))
2705 else:
2712 else:
2706 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2713 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2707 time.localtime(ent[3]))
2714 time.localtime(ent[3]))
2708 if ent[1] & 020000:
2715 if ent[1] & 020000:
2709 mode = 'lnk'
2716 mode = 'lnk'
2710 else:
2717 else:
2711 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2718 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2712 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2719 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2713 for f in repo.dirstate.copies():
2720 for f in repo.dirstate.copies():
2714 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2721 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2715
2722
2716 @command('debugsub',
2723 @command('debugsub',
2717 [('r', 'rev', '',
2724 [('r', 'rev', '',
2718 _('revision to check'), _('REV'))],
2725 _('revision to check'), _('REV'))],
2719 _('[-r REV] [REV]'))
2726 _('[-r REV] [REV]'))
2720 def debugsub(ui, repo, rev=None):
2727 def debugsub(ui, repo, rev=None):
2721 ctx = scmutil.revsingle(repo, rev, None)
2728 ctx = scmutil.revsingle(repo, rev, None)
2722 for k, v in sorted(ctx.substate.items()):
2729 for k, v in sorted(ctx.substate.items()):
2723 ui.write(('path %s\n') % k)
2730 ui.write(('path %s\n') % k)
2724 ui.write((' source %s\n') % v[0])
2731 ui.write((' source %s\n') % v[0])
2725 ui.write((' revision %s\n') % v[1])
2732 ui.write((' revision %s\n') % v[1])
2726
2733
2727 @command('debugsuccessorssets',
2734 @command('debugsuccessorssets',
2728 [],
2735 [],
2729 _('[REV]'))
2736 _('[REV]'))
2730 def debugsuccessorssets(ui, repo, *revs):
2737 def debugsuccessorssets(ui, repo, *revs):
2731 """show set of successors for revision
2738 """show set of successors for revision
2732
2739
2733 A successors set of changeset A is a consistent group of revisions that
2740 A successors set of changeset A is a consistent group of revisions that
2734 succeed A. It contains non-obsolete changesets only.
2741 succeed A. It contains non-obsolete changesets only.
2735
2742
2736 In most cases a changeset A has a single successors set containing a single
2743 In most cases a changeset A has a single successors set containing a single
2737 successor (changeset A replaced by A').
2744 successor (changeset A replaced by A').
2738
2745
2739 A changeset that is made obsolete with no successors are called "pruned".
2746 A changeset that is made obsolete with no successors are called "pruned".
2740 Such changesets have no successors sets at all.
2747 Such changesets have no successors sets at all.
2741
2748
2742 A changeset that has been "split" will have a successors set containing
2749 A changeset that has been "split" will have a successors set containing
2743 more than one successor.
2750 more than one successor.
2744
2751
2745 A changeset that has been rewritten in multiple different ways is called
2752 A changeset that has been rewritten in multiple different ways is called
2746 "divergent". Such changesets have multiple successor sets (each of which
2753 "divergent". Such changesets have multiple successor sets (each of which
2747 may also be split, i.e. have multiple successors).
2754 may also be split, i.e. have multiple successors).
2748
2755
2749 Results are displayed as follows::
2756 Results are displayed as follows::
2750
2757
2751 <rev1>
2758 <rev1>
2752 <successors-1A>
2759 <successors-1A>
2753 <rev2>
2760 <rev2>
2754 <successors-2A>
2761 <successors-2A>
2755 <successors-2B1> <successors-2B2> <successors-2B3>
2762 <successors-2B1> <successors-2B2> <successors-2B3>
2756
2763
2757 Here rev2 has two possible (i.e. divergent) successors sets. The first
2764 Here rev2 has two possible (i.e. divergent) successors sets. The first
2758 holds one element, whereas the second holds three (i.e. the changeset has
2765 holds one element, whereas the second holds three (i.e. the changeset has
2759 been split).
2766 been split).
2760 """
2767 """
2761 # passed to successorssets caching computation from one call to another
2768 # passed to successorssets caching computation from one call to another
2762 cache = {}
2769 cache = {}
2763 ctx2str = str
2770 ctx2str = str
2764 node2str = short
2771 node2str = short
2765 if ui.debug():
2772 if ui.debug():
2766 def ctx2str(ctx):
2773 def ctx2str(ctx):
2767 return ctx.hex()
2774 return ctx.hex()
2768 node2str = hex
2775 node2str = hex
2769 for rev in scmutil.revrange(repo, revs):
2776 for rev in scmutil.revrange(repo, revs):
2770 ctx = repo[rev]
2777 ctx = repo[rev]
2771 ui.write('%s\n'% ctx2str(ctx))
2778 ui.write('%s\n'% ctx2str(ctx))
2772 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2779 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2773 if succsset:
2780 if succsset:
2774 ui.write(' ')
2781 ui.write(' ')
2775 ui.write(node2str(succsset[0]))
2782 ui.write(node2str(succsset[0]))
2776 for node in succsset[1:]:
2783 for node in succsset[1:]:
2777 ui.write(' ')
2784 ui.write(' ')
2778 ui.write(node2str(node))
2785 ui.write(node2str(node))
2779 ui.write('\n')
2786 ui.write('\n')
2780
2787
2781 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2788 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2782 def debugwalk(ui, repo, *pats, **opts):
2789 def debugwalk(ui, repo, *pats, **opts):
2783 """show how files match on given patterns"""
2790 """show how files match on given patterns"""
2784 m = scmutil.match(repo[None], pats, opts)
2791 m = scmutil.match(repo[None], pats, opts)
2785 items = list(repo.walk(m))
2792 items = list(repo.walk(m))
2786 if not items:
2793 if not items:
2787 return
2794 return
2788 f = lambda fn: fn
2795 f = lambda fn: fn
2789 if ui.configbool('ui', 'slash') and os.sep != '/':
2796 if ui.configbool('ui', 'slash') and os.sep != '/':
2790 f = lambda fn: util.normpath(fn)
2797 f = lambda fn: util.normpath(fn)
2791 fmt = 'f %%-%ds %%-%ds %%s' % (
2798 fmt = 'f %%-%ds %%-%ds %%s' % (
2792 max([len(abs) for abs in items]),
2799 max([len(abs) for abs in items]),
2793 max([len(m.rel(abs)) for abs in items]))
2800 max([len(m.rel(abs)) for abs in items]))
2794 for abs in items:
2801 for abs in items:
2795 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2802 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2796 ui.write("%s\n" % line.rstrip())
2803 ui.write("%s\n" % line.rstrip())
2797
2804
2798 @command('debugwireargs',
2805 @command('debugwireargs',
2799 [('', 'three', '', 'three'),
2806 [('', 'three', '', 'three'),
2800 ('', 'four', '', 'four'),
2807 ('', 'four', '', 'four'),
2801 ('', 'five', '', 'five'),
2808 ('', 'five', '', 'five'),
2802 ] + remoteopts,
2809 ] + remoteopts,
2803 _('REPO [OPTIONS]... [ONE [TWO]]'))
2810 _('REPO [OPTIONS]... [ONE [TWO]]'))
2804 def debugwireargs(ui, repopath, *vals, **opts):
2811 def debugwireargs(ui, repopath, *vals, **opts):
2805 repo = hg.peer(ui, opts, repopath)
2812 repo = hg.peer(ui, opts, repopath)
2806 for opt in remoteopts:
2813 for opt in remoteopts:
2807 del opts[opt[1]]
2814 del opts[opt[1]]
2808 args = {}
2815 args = {}
2809 for k, v in opts.iteritems():
2816 for k, v in opts.iteritems():
2810 if v:
2817 if v:
2811 args[k] = v
2818 args[k] = v
2812 # run twice to check that we don't mess up the stream for the next command
2819 # run twice to check that we don't mess up the stream for the next command
2813 res1 = repo.debugwireargs(*vals, **args)
2820 res1 = repo.debugwireargs(*vals, **args)
2814 res2 = repo.debugwireargs(*vals, **args)
2821 res2 = repo.debugwireargs(*vals, **args)
2815 ui.write("%s\n" % res1)
2822 ui.write("%s\n" % res1)
2816 if res1 != res2:
2823 if res1 != res2:
2817 ui.warn("%s\n" % res2)
2824 ui.warn("%s\n" % res2)
2818
2825
2819 @command('^diff',
2826 @command('^diff',
2820 [('r', 'rev', [], _('revision'), _('REV')),
2827 [('r', 'rev', [], _('revision'), _('REV')),
2821 ('c', 'change', '', _('change made by revision'), _('REV'))
2828 ('c', 'change', '', _('change made by revision'), _('REV'))
2822 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2829 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2823 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2830 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2824 def diff(ui, repo, *pats, **opts):
2831 def diff(ui, repo, *pats, **opts):
2825 """diff repository (or selected files)
2832 """diff repository (or selected files)
2826
2833
2827 Show differences between revisions for the specified files.
2834 Show differences between revisions for the specified files.
2828
2835
2829 Differences between files are shown using the unified diff format.
2836 Differences between files are shown using the unified diff format.
2830
2837
2831 .. note::
2838 .. note::
2832
2839
2833 diff may generate unexpected results for merges, as it will
2840 diff may generate unexpected results for merges, as it will
2834 default to comparing against the working directory's first
2841 default to comparing against the working directory's first
2835 parent changeset if no revisions are specified.
2842 parent changeset if no revisions are specified.
2836
2843
2837 When two revision arguments are given, then changes are shown
2844 When two revision arguments are given, then changes are shown
2838 between those revisions. If only one revision is specified then
2845 between those revisions. If only one revision is specified then
2839 that revision is compared to the working directory, and, when no
2846 that revision is compared to the working directory, and, when no
2840 revisions are specified, the working directory files are compared
2847 revisions are specified, the working directory files are compared
2841 to its parent.
2848 to its parent.
2842
2849
2843 Alternatively you can specify -c/--change with a revision to see
2850 Alternatively you can specify -c/--change with a revision to see
2844 the changes in that changeset relative to its first parent.
2851 the changes in that changeset relative to its first parent.
2845
2852
2846 Without the -a/--text option, diff will avoid generating diffs of
2853 Without the -a/--text option, diff will avoid generating diffs of
2847 files it detects as binary. With -a, diff will generate a diff
2854 files it detects as binary. With -a, diff will generate a diff
2848 anyway, probably with undesirable results.
2855 anyway, probably with undesirable results.
2849
2856
2850 Use the -g/--git option to generate diffs in the git extended diff
2857 Use the -g/--git option to generate diffs in the git extended diff
2851 format. For more information, read :hg:`help diffs`.
2858 format. For more information, read :hg:`help diffs`.
2852
2859
2853 .. container:: verbose
2860 .. container:: verbose
2854
2861
2855 Examples:
2862 Examples:
2856
2863
2857 - compare a file in the current working directory to its parent::
2864 - compare a file in the current working directory to its parent::
2858
2865
2859 hg diff foo.c
2866 hg diff foo.c
2860
2867
2861 - compare two historical versions of a directory, with rename info::
2868 - compare two historical versions of a directory, with rename info::
2862
2869
2863 hg diff --git -r 1.0:1.2 lib/
2870 hg diff --git -r 1.0:1.2 lib/
2864
2871
2865 - get change stats relative to the last change on some date::
2872 - get change stats relative to the last change on some date::
2866
2873
2867 hg diff --stat -r "date('may 2')"
2874 hg diff --stat -r "date('may 2')"
2868
2875
2869 - diff all newly-added files that contain a keyword::
2876 - diff all newly-added files that contain a keyword::
2870
2877
2871 hg diff "set:added() and grep(GNU)"
2878 hg diff "set:added() and grep(GNU)"
2872
2879
2873 - compare a revision and its parents::
2880 - compare a revision and its parents::
2874
2881
2875 hg diff -c 9353 # compare against first parent
2882 hg diff -c 9353 # compare against first parent
2876 hg diff -r 9353^:9353 # same using revset syntax
2883 hg diff -r 9353^:9353 # same using revset syntax
2877 hg diff -r 9353^2:9353 # compare against the second parent
2884 hg diff -r 9353^2:9353 # compare against the second parent
2878
2885
2879 Returns 0 on success.
2886 Returns 0 on success.
2880 """
2887 """
2881
2888
2882 revs = opts.get('rev')
2889 revs = opts.get('rev')
2883 change = opts.get('change')
2890 change = opts.get('change')
2884 stat = opts.get('stat')
2891 stat = opts.get('stat')
2885 reverse = opts.get('reverse')
2892 reverse = opts.get('reverse')
2886
2893
2887 if revs and change:
2894 if revs and change:
2888 msg = _('cannot specify --rev and --change at the same time')
2895 msg = _('cannot specify --rev and --change at the same time')
2889 raise util.Abort(msg)
2896 raise util.Abort(msg)
2890 elif change:
2897 elif change:
2891 node2 = scmutil.revsingle(repo, change, None).node()
2898 node2 = scmutil.revsingle(repo, change, None).node()
2892 node1 = repo[node2].p1().node()
2899 node1 = repo[node2].p1().node()
2893 else:
2900 else:
2894 node1, node2 = scmutil.revpair(repo, revs)
2901 node1, node2 = scmutil.revpair(repo, revs)
2895
2902
2896 if reverse:
2903 if reverse:
2897 node1, node2 = node2, node1
2904 node1, node2 = node2, node1
2898
2905
2899 diffopts = patch.diffopts(ui, opts)
2906 diffopts = patch.diffopts(ui, opts)
2900 m = scmutil.match(repo[node2], pats, opts)
2907 m = scmutil.match(repo[node2], pats, opts)
2901 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2908 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2902 listsubrepos=opts.get('subrepos'))
2909 listsubrepos=opts.get('subrepos'))
2903
2910
2904 @command('^export',
2911 @command('^export',
2905 [('o', 'output', '',
2912 [('o', 'output', '',
2906 _('print output to file with formatted name'), _('FORMAT')),
2913 _('print output to file with formatted name'), _('FORMAT')),
2907 ('', 'switch-parent', None, _('diff against the second parent')),
2914 ('', 'switch-parent', None, _('diff against the second parent')),
2908 ('r', 'rev', [], _('revisions to export'), _('REV')),
2915 ('r', 'rev', [], _('revisions to export'), _('REV')),
2909 ] + diffopts,
2916 ] + diffopts,
2910 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2917 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2911 def export(ui, repo, *changesets, **opts):
2918 def export(ui, repo, *changesets, **opts):
2912 """dump the header and diffs for one or more changesets
2919 """dump the header and diffs for one or more changesets
2913
2920
2914 Print the changeset header and diffs for one or more revisions.
2921 Print the changeset header and diffs for one or more revisions.
2915 If no revision is given, the parent of the working directory is used.
2922 If no revision is given, the parent of the working directory is used.
2916
2923
2917 The information shown in the changeset header is: author, date,
2924 The information shown in the changeset header is: author, date,
2918 branch name (if non-default), changeset hash, parent(s) and commit
2925 branch name (if non-default), changeset hash, parent(s) and commit
2919 comment.
2926 comment.
2920
2927
2921 .. note::
2928 .. note::
2922
2929
2923 export may generate unexpected diff output for merge
2930 export may generate unexpected diff output for merge
2924 changesets, as it will compare the merge changeset against its
2931 changesets, as it will compare the merge changeset against its
2925 first parent only.
2932 first parent only.
2926
2933
2927 Output may be to a file, in which case the name of the file is
2934 Output may be to a file, in which case the name of the file is
2928 given using a format string. The formatting rules are as follows:
2935 given using a format string. The formatting rules are as follows:
2929
2936
2930 :``%%``: literal "%" character
2937 :``%%``: literal "%" character
2931 :``%H``: changeset hash (40 hexadecimal digits)
2938 :``%H``: changeset hash (40 hexadecimal digits)
2932 :``%N``: number of patches being generated
2939 :``%N``: number of patches being generated
2933 :``%R``: changeset revision number
2940 :``%R``: changeset revision number
2934 :``%b``: basename of the exporting repository
2941 :``%b``: basename of the exporting repository
2935 :``%h``: short-form changeset hash (12 hexadecimal digits)
2942 :``%h``: short-form changeset hash (12 hexadecimal digits)
2936 :``%m``: first line of the commit message (only alphanumeric characters)
2943 :``%m``: first line of the commit message (only alphanumeric characters)
2937 :``%n``: zero-padded sequence number, starting at 1
2944 :``%n``: zero-padded sequence number, starting at 1
2938 :``%r``: zero-padded changeset revision number
2945 :``%r``: zero-padded changeset revision number
2939
2946
2940 Without the -a/--text option, export will avoid generating diffs
2947 Without the -a/--text option, export will avoid generating diffs
2941 of files it detects as binary. With -a, export will generate a
2948 of files it detects as binary. With -a, export will generate a
2942 diff anyway, probably with undesirable results.
2949 diff anyway, probably with undesirable results.
2943
2950
2944 Use the -g/--git option to generate diffs in the git extended diff
2951 Use the -g/--git option to generate diffs in the git extended diff
2945 format. See :hg:`help diffs` for more information.
2952 format. See :hg:`help diffs` for more information.
2946
2953
2947 With the --switch-parent option, the diff will be against the
2954 With the --switch-parent option, the diff will be against the
2948 second parent. It can be useful to review a merge.
2955 second parent. It can be useful to review a merge.
2949
2956
2950 .. container:: verbose
2957 .. container:: verbose
2951
2958
2952 Examples:
2959 Examples:
2953
2960
2954 - use export and import to transplant a bugfix to the current
2961 - use export and import to transplant a bugfix to the current
2955 branch::
2962 branch::
2956
2963
2957 hg export -r 9353 | hg import -
2964 hg export -r 9353 | hg import -
2958
2965
2959 - export all the changesets between two revisions to a file with
2966 - export all the changesets between two revisions to a file with
2960 rename information::
2967 rename information::
2961
2968
2962 hg export --git -r 123:150 > changes.txt
2969 hg export --git -r 123:150 > changes.txt
2963
2970
2964 - split outgoing changes into a series of patches with
2971 - split outgoing changes into a series of patches with
2965 descriptive names::
2972 descriptive names::
2966
2973
2967 hg export -r "outgoing()" -o "%n-%m.patch"
2974 hg export -r "outgoing()" -o "%n-%m.patch"
2968
2975
2969 Returns 0 on success.
2976 Returns 0 on success.
2970 """
2977 """
2971 changesets += tuple(opts.get('rev', []))
2978 changesets += tuple(opts.get('rev', []))
2972 if not changesets:
2979 if not changesets:
2973 changesets = ['.']
2980 changesets = ['.']
2974 revs = scmutil.revrange(repo, changesets)
2981 revs = scmutil.revrange(repo, changesets)
2975 if not revs:
2982 if not revs:
2976 raise util.Abort(_("export requires at least one changeset"))
2983 raise util.Abort(_("export requires at least one changeset"))
2977 if len(revs) > 1:
2984 if len(revs) > 1:
2978 ui.note(_('exporting patches:\n'))
2985 ui.note(_('exporting patches:\n'))
2979 else:
2986 else:
2980 ui.note(_('exporting patch:\n'))
2987 ui.note(_('exporting patch:\n'))
2981 cmdutil.export(repo, revs, template=opts.get('output'),
2988 cmdutil.export(repo, revs, template=opts.get('output'),
2982 switch_parent=opts.get('switch_parent'),
2989 switch_parent=opts.get('switch_parent'),
2983 opts=patch.diffopts(ui, opts))
2990 opts=patch.diffopts(ui, opts))
2984
2991
2985 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2992 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2986 def forget(ui, repo, *pats, **opts):
2993 def forget(ui, repo, *pats, **opts):
2987 """forget the specified files on the next commit
2994 """forget the specified files on the next commit
2988
2995
2989 Mark the specified files so they will no longer be tracked
2996 Mark the specified files so they will no longer be tracked
2990 after the next commit.
2997 after the next commit.
2991
2998
2992 This only removes files from the current branch, not from the
2999 This only removes files from the current branch, not from the
2993 entire project history, and it does not delete them from the
3000 entire project history, and it does not delete them from the
2994 working directory.
3001 working directory.
2995
3002
2996 To undo a forget before the next commit, see :hg:`add`.
3003 To undo a forget before the next commit, see :hg:`add`.
2997
3004
2998 .. container:: verbose
3005 .. container:: verbose
2999
3006
3000 Examples:
3007 Examples:
3001
3008
3002 - forget newly-added binary files::
3009 - forget newly-added binary files::
3003
3010
3004 hg forget "set:added() and binary()"
3011 hg forget "set:added() and binary()"
3005
3012
3006 - forget files that would be excluded by .hgignore::
3013 - forget files that would be excluded by .hgignore::
3007
3014
3008 hg forget "set:hgignore()"
3015 hg forget "set:hgignore()"
3009
3016
3010 Returns 0 on success.
3017 Returns 0 on success.
3011 """
3018 """
3012
3019
3013 if not pats:
3020 if not pats:
3014 raise util.Abort(_('no files specified'))
3021 raise util.Abort(_('no files specified'))
3015
3022
3016 m = scmutil.match(repo[None], pats, opts)
3023 m = scmutil.match(repo[None], pats, opts)
3017 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3024 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3018 return rejected and 1 or 0
3025 return rejected and 1 or 0
3019
3026
3020 @command(
3027 @command(
3021 'graft',
3028 'graft',
3022 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3029 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3023 ('c', 'continue', False, _('resume interrupted graft')),
3030 ('c', 'continue', False, _('resume interrupted graft')),
3024 ('e', 'edit', False, _('invoke editor on commit messages')),
3031 ('e', 'edit', False, _('invoke editor on commit messages')),
3025 ('', 'log', None, _('append graft info to log message')),
3032 ('', 'log', None, _('append graft info to log message')),
3026 ('D', 'currentdate', False,
3033 ('D', 'currentdate', False,
3027 _('record the current date as commit date')),
3034 _('record the current date as commit date')),
3028 ('U', 'currentuser', False,
3035 ('U', 'currentuser', False,
3029 _('record the current user as committer'), _('DATE'))]
3036 _('record the current user as committer'), _('DATE'))]
3030 + commitopts2 + mergetoolopts + dryrunopts,
3037 + commitopts2 + mergetoolopts + dryrunopts,
3031 _('[OPTION]... [-r] REV...'))
3038 _('[OPTION]... [-r] REV...'))
3032 def graft(ui, repo, *revs, **opts):
3039 def graft(ui, repo, *revs, **opts):
3033 '''copy changes from other branches onto the current branch
3040 '''copy changes from other branches onto the current branch
3034
3041
3035 This command uses Mercurial's merge logic to copy individual
3042 This command uses Mercurial's merge logic to copy individual
3036 changes from other branches without merging branches in the
3043 changes from other branches without merging branches in the
3037 history graph. This is sometimes known as 'backporting' or
3044 history graph. This is sometimes known as 'backporting' or
3038 'cherry-picking'. By default, graft will copy user, date, and
3045 'cherry-picking'. By default, graft will copy user, date, and
3039 description from the source changesets.
3046 description from the source changesets.
3040
3047
3041 Changesets that are ancestors of the current revision, that have
3048 Changesets that are ancestors of the current revision, that have
3042 already been grafted, or that are merges will be skipped.
3049 already been grafted, or that are merges will be skipped.
3043
3050
3044 If --log is specified, log messages will have a comment appended
3051 If --log is specified, log messages will have a comment appended
3045 of the form::
3052 of the form::
3046
3053
3047 (grafted from CHANGESETHASH)
3054 (grafted from CHANGESETHASH)
3048
3055
3049 If a graft merge results in conflicts, the graft process is
3056 If a graft merge results in conflicts, the graft process is
3050 interrupted so that the current merge can be manually resolved.
3057 interrupted so that the current merge can be manually resolved.
3051 Once all conflicts are addressed, the graft process can be
3058 Once all conflicts are addressed, the graft process can be
3052 continued with the -c/--continue option.
3059 continued with the -c/--continue option.
3053
3060
3054 .. note::
3061 .. note::
3055
3062
3056 The -c/--continue option does not reapply earlier options.
3063 The -c/--continue option does not reapply earlier options.
3057
3064
3058 .. container:: verbose
3065 .. container:: verbose
3059
3066
3060 Examples:
3067 Examples:
3061
3068
3062 - copy a single change to the stable branch and edit its description::
3069 - copy a single change to the stable branch and edit its description::
3063
3070
3064 hg update stable
3071 hg update stable
3065 hg graft --edit 9393
3072 hg graft --edit 9393
3066
3073
3067 - graft a range of changesets with one exception, updating dates::
3074 - graft a range of changesets with one exception, updating dates::
3068
3075
3069 hg graft -D "2085::2093 and not 2091"
3076 hg graft -D "2085::2093 and not 2091"
3070
3077
3071 - continue a graft after resolving conflicts::
3078 - continue a graft after resolving conflicts::
3072
3079
3073 hg graft -c
3080 hg graft -c
3074
3081
3075 - show the source of a grafted changeset::
3082 - show the source of a grafted changeset::
3076
3083
3077 hg log --debug -r .
3084 hg log --debug -r .
3078
3085
3079 Returns 0 on successful completion.
3086 Returns 0 on successful completion.
3080 '''
3087 '''
3081
3088
3082 revs = list(revs)
3089 revs = list(revs)
3083 revs.extend(opts['rev'])
3090 revs.extend(opts['rev'])
3084
3091
3085 if not opts.get('user') and opts.get('currentuser'):
3092 if not opts.get('user') and opts.get('currentuser'):
3086 opts['user'] = ui.username()
3093 opts['user'] = ui.username()
3087 if not opts.get('date') and opts.get('currentdate'):
3094 if not opts.get('date') and opts.get('currentdate'):
3088 opts['date'] = "%d %d" % util.makedate()
3095 opts['date'] = "%d %d" % util.makedate()
3089
3096
3090 editor = None
3097 editor = None
3091 if opts.get('edit'):
3098 if opts.get('edit'):
3092 editor = cmdutil.commitforceeditor
3099 editor = cmdutil.commitforceeditor
3093
3100
3094 cont = False
3101 cont = False
3095 if opts['continue']:
3102 if opts['continue']:
3096 cont = True
3103 cont = True
3097 if revs:
3104 if revs:
3098 raise util.Abort(_("can't specify --continue and revisions"))
3105 raise util.Abort(_("can't specify --continue and revisions"))
3099 # read in unfinished revisions
3106 # read in unfinished revisions
3100 try:
3107 try:
3101 nodes = repo.opener.read('graftstate').splitlines()
3108 nodes = repo.opener.read('graftstate').splitlines()
3102 revs = [repo[node].rev() for node in nodes]
3109 revs = [repo[node].rev() for node in nodes]
3103 except IOError, inst:
3110 except IOError, inst:
3104 if inst.errno != errno.ENOENT:
3111 if inst.errno != errno.ENOENT:
3105 raise
3112 raise
3106 raise util.Abort(_("no graft state found, can't continue"))
3113 raise util.Abort(_("no graft state found, can't continue"))
3107 else:
3114 else:
3108 cmdutil.checkunfinished(repo)
3115 cmdutil.checkunfinished(repo)
3109 cmdutil.bailifchanged(repo)
3116 cmdutil.bailifchanged(repo)
3110 if not revs:
3117 if not revs:
3111 raise util.Abort(_('no revisions specified'))
3118 raise util.Abort(_('no revisions specified'))
3112 revs = scmutil.revrange(repo, revs)
3119 revs = scmutil.revrange(repo, revs)
3113
3120
3114 # check for merges
3121 # check for merges
3115 for rev in repo.revs('%ld and merge()', revs):
3122 for rev in repo.revs('%ld and merge()', revs):
3116 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3123 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3117 revs.remove(rev)
3124 revs.remove(rev)
3118 if not revs:
3125 if not revs:
3119 return -1
3126 return -1
3120
3127
3121 # check for ancestors of dest branch
3128 # check for ancestors of dest branch
3122 crev = repo['.'].rev()
3129 crev = repo['.'].rev()
3123 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3130 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3124 # don't mutate while iterating, create a copy
3131 # don't mutate while iterating, create a copy
3125 for rev in list(revs):
3132 for rev in list(revs):
3126 if rev in ancestors:
3133 if rev in ancestors:
3127 ui.warn(_('skipping ancestor revision %s\n') % rev)
3134 ui.warn(_('skipping ancestor revision %s\n') % rev)
3128 revs.remove(rev)
3135 revs.remove(rev)
3129 if not revs:
3136 if not revs:
3130 return -1
3137 return -1
3131
3138
3132 # analyze revs for earlier grafts
3139 # analyze revs for earlier grafts
3133 ids = {}
3140 ids = {}
3134 for ctx in repo.set("%ld", revs):
3141 for ctx in repo.set("%ld", revs):
3135 ids[ctx.hex()] = ctx.rev()
3142 ids[ctx.hex()] = ctx.rev()
3136 n = ctx.extra().get('source')
3143 n = ctx.extra().get('source')
3137 if n:
3144 if n:
3138 ids[n] = ctx.rev()
3145 ids[n] = ctx.rev()
3139
3146
3140 # check ancestors for earlier grafts
3147 # check ancestors for earlier grafts
3141 ui.debug('scanning for duplicate grafts\n')
3148 ui.debug('scanning for duplicate grafts\n')
3142
3149
3143 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3150 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3144 ctx = repo[rev]
3151 ctx = repo[rev]
3145 n = ctx.extra().get('source')
3152 n = ctx.extra().get('source')
3146 if n in ids:
3153 if n in ids:
3147 r = repo[n].rev()
3154 r = repo[n].rev()
3148 if r in revs:
3155 if r in revs:
3149 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3156 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3150 % (r, rev))
3157 % (r, rev))
3151 revs.remove(r)
3158 revs.remove(r)
3152 elif ids[n] in revs:
3159 elif ids[n] in revs:
3153 ui.warn(_('skipping already grafted revision %s '
3160 ui.warn(_('skipping already grafted revision %s '
3154 '(%s also has origin %d)\n') % (ids[n], rev, r))
3161 '(%s also has origin %d)\n') % (ids[n], rev, r))
3155 revs.remove(ids[n])
3162 revs.remove(ids[n])
3156 elif ctx.hex() in ids:
3163 elif ctx.hex() in ids:
3157 r = ids[ctx.hex()]
3164 r = ids[ctx.hex()]
3158 ui.warn(_('skipping already grafted revision %s '
3165 ui.warn(_('skipping already grafted revision %s '
3159 '(was grafted from %d)\n') % (r, rev))
3166 '(was grafted from %d)\n') % (r, rev))
3160 revs.remove(r)
3167 revs.remove(r)
3161 if not revs:
3168 if not revs:
3162 return -1
3169 return -1
3163
3170
3164 wlock = repo.wlock()
3171 wlock = repo.wlock()
3165 try:
3172 try:
3166 current = repo['.']
3173 current = repo['.']
3167 for pos, ctx in enumerate(repo.set("%ld", revs)):
3174 for pos, ctx in enumerate(repo.set("%ld", revs)):
3168
3175
3169 ui.status(_('grafting revision %s\n') % ctx.rev())
3176 ui.status(_('grafting revision %s\n') % ctx.rev())
3170 if opts.get('dry_run'):
3177 if opts.get('dry_run'):
3171 continue
3178 continue
3172
3179
3173 source = ctx.extra().get('source')
3180 source = ctx.extra().get('source')
3174 if not source:
3181 if not source:
3175 source = ctx.hex()
3182 source = ctx.hex()
3176 extra = {'source': source}
3183 extra = {'source': source}
3177 user = ctx.user()
3184 user = ctx.user()
3178 if opts.get('user'):
3185 if opts.get('user'):
3179 user = opts['user']
3186 user = opts['user']
3180 date = ctx.date()
3187 date = ctx.date()
3181 if opts.get('date'):
3188 if opts.get('date'):
3182 date = opts['date']
3189 date = opts['date']
3183 message = ctx.description()
3190 message = ctx.description()
3184 if opts.get('log'):
3191 if opts.get('log'):
3185 message += '\n(grafted from %s)' % ctx.hex()
3192 message += '\n(grafted from %s)' % ctx.hex()
3186
3193
3187 # we don't merge the first commit when continuing
3194 # we don't merge the first commit when continuing
3188 if not cont:
3195 if not cont:
3189 # perform the graft merge with p1(rev) as 'ancestor'
3196 # perform the graft merge with p1(rev) as 'ancestor'
3190 try:
3197 try:
3191 # ui.forcemerge is an internal variable, do not document
3198 # ui.forcemerge is an internal variable, do not document
3192 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3199 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3193 stats = mergemod.update(repo, ctx.node(), True, True, False,
3200 stats = mergemod.update(repo, ctx.node(), True, True, False,
3194 ctx.p1().node())
3201 ctx.p1().node())
3195 finally:
3202 finally:
3196 repo.ui.setconfig('ui', 'forcemerge', '')
3203 repo.ui.setconfig('ui', 'forcemerge', '')
3197 # report any conflicts
3204 # report any conflicts
3198 if stats and stats[3] > 0:
3205 if stats and stats[3] > 0:
3199 # write out state for --continue
3206 # write out state for --continue
3200 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3207 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3201 repo.opener.write('graftstate', ''.join(nodelines))
3208 repo.opener.write('graftstate', ''.join(nodelines))
3202 raise util.Abort(
3209 raise util.Abort(
3203 _("unresolved conflicts, can't continue"),
3210 _("unresolved conflicts, can't continue"),
3204 hint=_('use hg resolve and hg graft --continue'))
3211 hint=_('use hg resolve and hg graft --continue'))
3205 else:
3212 else:
3206 cont = False
3213 cont = False
3207
3214
3208 # drop the second merge parent
3215 # drop the second merge parent
3209 repo.setparents(current.node(), nullid)
3216 repo.setparents(current.node(), nullid)
3210 repo.dirstate.write()
3217 repo.dirstate.write()
3211 # fix up dirstate for copies and renames
3218 # fix up dirstate for copies and renames
3212 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3219 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3213
3220
3214 # commit
3221 # commit
3215 node = repo.commit(text=message, user=user,
3222 node = repo.commit(text=message, user=user,
3216 date=date, extra=extra, editor=editor)
3223 date=date, extra=extra, editor=editor)
3217 if node is None:
3224 if node is None:
3218 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3225 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3219 else:
3226 else:
3220 current = repo[node]
3227 current = repo[node]
3221 finally:
3228 finally:
3222 wlock.release()
3229 wlock.release()
3223
3230
3224 # remove state when we complete successfully
3231 # remove state when we complete successfully
3225 if not opts.get('dry_run'):
3232 if not opts.get('dry_run'):
3226 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3233 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3227
3234
3228 return 0
3235 return 0
3229
3236
3230 @command('grep',
3237 @command('grep',
3231 [('0', 'print0', None, _('end fields with NUL')),
3238 [('0', 'print0', None, _('end fields with NUL')),
3232 ('', 'all', None, _('print all revisions that match')),
3239 ('', 'all', None, _('print all revisions that match')),
3233 ('a', 'text', None, _('treat all files as text')),
3240 ('a', 'text', None, _('treat all files as text')),
3234 ('f', 'follow', None,
3241 ('f', 'follow', None,
3235 _('follow changeset history,'
3242 _('follow changeset history,'
3236 ' or file history across copies and renames')),
3243 ' or file history across copies and renames')),
3237 ('i', 'ignore-case', None, _('ignore case when matching')),
3244 ('i', 'ignore-case', None, _('ignore case when matching')),
3238 ('l', 'files-with-matches', None,
3245 ('l', 'files-with-matches', None,
3239 _('print only filenames and revisions that match')),
3246 _('print only filenames and revisions that match')),
3240 ('n', 'line-number', None, _('print matching line numbers')),
3247 ('n', 'line-number', None, _('print matching line numbers')),
3241 ('r', 'rev', [],
3248 ('r', 'rev', [],
3242 _('only search files changed within revision range'), _('REV')),
3249 _('only search files changed within revision range'), _('REV')),
3243 ('u', 'user', None, _('list the author (long with -v)')),
3250 ('u', 'user', None, _('list the author (long with -v)')),
3244 ('d', 'date', None, _('list the date (short with -q)')),
3251 ('d', 'date', None, _('list the date (short with -q)')),
3245 ] + walkopts,
3252 ] + walkopts,
3246 _('[OPTION]... PATTERN [FILE]...'))
3253 _('[OPTION]... PATTERN [FILE]...'))
3247 def grep(ui, repo, pattern, *pats, **opts):
3254 def grep(ui, repo, pattern, *pats, **opts):
3248 """search for a pattern in specified files and revisions
3255 """search for a pattern in specified files and revisions
3249
3256
3250 Search revisions of files for a regular expression.
3257 Search revisions of files for a regular expression.
3251
3258
3252 This command behaves differently than Unix grep. It only accepts
3259 This command behaves differently than Unix grep. It only accepts
3253 Python/Perl regexps. It searches repository history, not the
3260 Python/Perl regexps. It searches repository history, not the
3254 working directory. It always prints the revision number in which a
3261 working directory. It always prints the revision number in which a
3255 match appears.
3262 match appears.
3256
3263
3257 By default, grep only prints output for the first revision of a
3264 By default, grep only prints output for the first revision of a
3258 file in which it finds a match. To get it to print every revision
3265 file in which it finds a match. To get it to print every revision
3259 that contains a change in match status ("-" for a match that
3266 that contains a change in match status ("-" for a match that
3260 becomes a non-match, or "+" for a non-match that becomes a match),
3267 becomes a non-match, or "+" for a non-match that becomes a match),
3261 use the --all flag.
3268 use the --all flag.
3262
3269
3263 Returns 0 if a match is found, 1 otherwise.
3270 Returns 0 if a match is found, 1 otherwise.
3264 """
3271 """
3265 reflags = re.M
3272 reflags = re.M
3266 if opts.get('ignore_case'):
3273 if opts.get('ignore_case'):
3267 reflags |= re.I
3274 reflags |= re.I
3268 try:
3275 try:
3269 regexp = util.compilere(pattern, reflags)
3276 regexp = util.compilere(pattern, reflags)
3270 except re.error, inst:
3277 except re.error, inst:
3271 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3278 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3272 return 1
3279 return 1
3273 sep, eol = ':', '\n'
3280 sep, eol = ':', '\n'
3274 if opts.get('print0'):
3281 if opts.get('print0'):
3275 sep = eol = '\0'
3282 sep = eol = '\0'
3276
3283
3277 getfile = util.lrucachefunc(repo.file)
3284 getfile = util.lrucachefunc(repo.file)
3278
3285
3279 def matchlines(body):
3286 def matchlines(body):
3280 begin = 0
3287 begin = 0
3281 linenum = 0
3288 linenum = 0
3282 while begin < len(body):
3289 while begin < len(body):
3283 match = regexp.search(body, begin)
3290 match = regexp.search(body, begin)
3284 if not match:
3291 if not match:
3285 break
3292 break
3286 mstart, mend = match.span()
3293 mstart, mend = match.span()
3287 linenum += body.count('\n', begin, mstart) + 1
3294 linenum += body.count('\n', begin, mstart) + 1
3288 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3295 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3289 begin = body.find('\n', mend) + 1 or len(body) + 1
3296 begin = body.find('\n', mend) + 1 or len(body) + 1
3290 lend = begin - 1
3297 lend = begin - 1
3291 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3298 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3292
3299
3293 class linestate(object):
3300 class linestate(object):
3294 def __init__(self, line, linenum, colstart, colend):
3301 def __init__(self, line, linenum, colstart, colend):
3295 self.line = line
3302 self.line = line
3296 self.linenum = linenum
3303 self.linenum = linenum
3297 self.colstart = colstart
3304 self.colstart = colstart
3298 self.colend = colend
3305 self.colend = colend
3299
3306
3300 def __hash__(self):
3307 def __hash__(self):
3301 return hash((self.linenum, self.line))
3308 return hash((self.linenum, self.line))
3302
3309
3303 def __eq__(self, other):
3310 def __eq__(self, other):
3304 return self.line == other.line
3311 return self.line == other.line
3305
3312
3306 matches = {}
3313 matches = {}
3307 copies = {}
3314 copies = {}
3308 def grepbody(fn, rev, body):
3315 def grepbody(fn, rev, body):
3309 matches[rev].setdefault(fn, [])
3316 matches[rev].setdefault(fn, [])
3310 m = matches[rev][fn]
3317 m = matches[rev][fn]
3311 for lnum, cstart, cend, line in matchlines(body):
3318 for lnum, cstart, cend, line in matchlines(body):
3312 s = linestate(line, lnum, cstart, cend)
3319 s = linestate(line, lnum, cstart, cend)
3313 m.append(s)
3320 m.append(s)
3314
3321
3315 def difflinestates(a, b):
3322 def difflinestates(a, b):
3316 sm = difflib.SequenceMatcher(None, a, b)
3323 sm = difflib.SequenceMatcher(None, a, b)
3317 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3324 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3318 if tag == 'insert':
3325 if tag == 'insert':
3319 for i in xrange(blo, bhi):
3326 for i in xrange(blo, bhi):
3320 yield ('+', b[i])
3327 yield ('+', b[i])
3321 elif tag == 'delete':
3328 elif tag == 'delete':
3322 for i in xrange(alo, ahi):
3329 for i in xrange(alo, ahi):
3323 yield ('-', a[i])
3330 yield ('-', a[i])
3324 elif tag == 'replace':
3331 elif tag == 'replace':
3325 for i in xrange(alo, ahi):
3332 for i in xrange(alo, ahi):
3326 yield ('-', a[i])
3333 yield ('-', a[i])
3327 for i in xrange(blo, bhi):
3334 for i in xrange(blo, bhi):
3328 yield ('+', b[i])
3335 yield ('+', b[i])
3329
3336
3330 def display(fn, ctx, pstates, states):
3337 def display(fn, ctx, pstates, states):
3331 rev = ctx.rev()
3338 rev = ctx.rev()
3332 datefunc = ui.quiet and util.shortdate or util.datestr
3339 datefunc = ui.quiet and util.shortdate or util.datestr
3333 found = False
3340 found = False
3334 filerevmatches = {}
3341 filerevmatches = {}
3335 def binary():
3342 def binary():
3336 flog = getfile(fn)
3343 flog = getfile(fn)
3337 return util.binary(flog.read(ctx.filenode(fn)))
3344 return util.binary(flog.read(ctx.filenode(fn)))
3338
3345
3339 if opts.get('all'):
3346 if opts.get('all'):
3340 iter = difflinestates(pstates, states)
3347 iter = difflinestates(pstates, states)
3341 else:
3348 else:
3342 iter = [('', l) for l in states]
3349 iter = [('', l) for l in states]
3343 for change, l in iter:
3350 for change, l in iter:
3344 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3351 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3345 before, match, after = None, None, None
3352 before, match, after = None, None, None
3346
3353
3347 if opts.get('line_number'):
3354 if opts.get('line_number'):
3348 cols.append((str(l.linenum), 'grep.linenumber'))
3355 cols.append((str(l.linenum), 'grep.linenumber'))
3349 if opts.get('all'):
3356 if opts.get('all'):
3350 cols.append((change, 'grep.change'))
3357 cols.append((change, 'grep.change'))
3351 if opts.get('user'):
3358 if opts.get('user'):
3352 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3359 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3353 if opts.get('date'):
3360 if opts.get('date'):
3354 cols.append((datefunc(ctx.date()), 'grep.date'))
3361 cols.append((datefunc(ctx.date()), 'grep.date'))
3355 if opts.get('files_with_matches'):
3362 if opts.get('files_with_matches'):
3356 c = (fn, rev)
3363 c = (fn, rev)
3357 if c in filerevmatches:
3364 if c in filerevmatches:
3358 continue
3365 continue
3359 filerevmatches[c] = 1
3366 filerevmatches[c] = 1
3360 else:
3367 else:
3361 before = l.line[:l.colstart]
3368 before = l.line[:l.colstart]
3362 match = l.line[l.colstart:l.colend]
3369 match = l.line[l.colstart:l.colend]
3363 after = l.line[l.colend:]
3370 after = l.line[l.colend:]
3364 for col, label in cols[:-1]:
3371 for col, label in cols[:-1]:
3365 ui.write(col, label=label)
3372 ui.write(col, label=label)
3366 ui.write(sep, label='grep.sep')
3373 ui.write(sep, label='grep.sep')
3367 ui.write(cols[-1][0], label=cols[-1][1])
3374 ui.write(cols[-1][0], label=cols[-1][1])
3368 if before is not None:
3375 if before is not None:
3369 ui.write(sep, label='grep.sep')
3376 ui.write(sep, label='grep.sep')
3370 if not opts.get('text') and binary():
3377 if not opts.get('text') and binary():
3371 ui.write(" Binary file matches")
3378 ui.write(" Binary file matches")
3372 else:
3379 else:
3373 ui.write(before)
3380 ui.write(before)
3374 ui.write(match, label='grep.match')
3381 ui.write(match, label='grep.match')
3375 ui.write(after)
3382 ui.write(after)
3376 ui.write(eol)
3383 ui.write(eol)
3377 found = True
3384 found = True
3378 return found
3385 return found
3379
3386
3380 skip = {}
3387 skip = {}
3381 revfiles = {}
3388 revfiles = {}
3382 matchfn = scmutil.match(repo[None], pats, opts)
3389 matchfn = scmutil.match(repo[None], pats, opts)
3383 found = False
3390 found = False
3384 follow = opts.get('follow')
3391 follow = opts.get('follow')
3385
3392
3386 def prep(ctx, fns):
3393 def prep(ctx, fns):
3387 rev = ctx.rev()
3394 rev = ctx.rev()
3388 pctx = ctx.p1()
3395 pctx = ctx.p1()
3389 parent = pctx.rev()
3396 parent = pctx.rev()
3390 matches.setdefault(rev, {})
3397 matches.setdefault(rev, {})
3391 matches.setdefault(parent, {})
3398 matches.setdefault(parent, {})
3392 files = revfiles.setdefault(rev, [])
3399 files = revfiles.setdefault(rev, [])
3393 for fn in fns:
3400 for fn in fns:
3394 flog = getfile(fn)
3401 flog = getfile(fn)
3395 try:
3402 try:
3396 fnode = ctx.filenode(fn)
3403 fnode = ctx.filenode(fn)
3397 except error.LookupError:
3404 except error.LookupError:
3398 continue
3405 continue
3399
3406
3400 copied = flog.renamed(fnode)
3407 copied = flog.renamed(fnode)
3401 copy = follow and copied and copied[0]
3408 copy = follow and copied and copied[0]
3402 if copy:
3409 if copy:
3403 copies.setdefault(rev, {})[fn] = copy
3410 copies.setdefault(rev, {})[fn] = copy
3404 if fn in skip:
3411 if fn in skip:
3405 if copy:
3412 if copy:
3406 skip[copy] = True
3413 skip[copy] = True
3407 continue
3414 continue
3408 files.append(fn)
3415 files.append(fn)
3409
3416
3410 if fn not in matches[rev]:
3417 if fn not in matches[rev]:
3411 grepbody(fn, rev, flog.read(fnode))
3418 grepbody(fn, rev, flog.read(fnode))
3412
3419
3413 pfn = copy or fn
3420 pfn = copy or fn
3414 if pfn not in matches[parent]:
3421 if pfn not in matches[parent]:
3415 try:
3422 try:
3416 fnode = pctx.filenode(pfn)
3423 fnode = pctx.filenode(pfn)
3417 grepbody(pfn, parent, flog.read(fnode))
3424 grepbody(pfn, parent, flog.read(fnode))
3418 except error.LookupError:
3425 except error.LookupError:
3419 pass
3426 pass
3420
3427
3421 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3428 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3422 rev = ctx.rev()
3429 rev = ctx.rev()
3423 parent = ctx.p1().rev()
3430 parent = ctx.p1().rev()
3424 for fn in sorted(revfiles.get(rev, [])):
3431 for fn in sorted(revfiles.get(rev, [])):
3425 states = matches[rev][fn]
3432 states = matches[rev][fn]
3426 copy = copies.get(rev, {}).get(fn)
3433 copy = copies.get(rev, {}).get(fn)
3427 if fn in skip:
3434 if fn in skip:
3428 if copy:
3435 if copy:
3429 skip[copy] = True
3436 skip[copy] = True
3430 continue
3437 continue
3431 pstates = matches.get(parent, {}).get(copy or fn, [])
3438 pstates = matches.get(parent, {}).get(copy or fn, [])
3432 if pstates or states:
3439 if pstates or states:
3433 r = display(fn, ctx, pstates, states)
3440 r = display(fn, ctx, pstates, states)
3434 found = found or r
3441 found = found or r
3435 if r and not opts.get('all'):
3442 if r and not opts.get('all'):
3436 skip[fn] = True
3443 skip[fn] = True
3437 if copy:
3444 if copy:
3438 skip[copy] = True
3445 skip[copy] = True
3439 del matches[rev]
3446 del matches[rev]
3440 del revfiles[rev]
3447 del revfiles[rev]
3441
3448
3442 return not found
3449 return not found
3443
3450
3444 @command('heads',
3451 @command('heads',
3445 [('r', 'rev', '',
3452 [('r', 'rev', '',
3446 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3453 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3447 ('t', 'topo', False, _('show topological heads only')),
3454 ('t', 'topo', False, _('show topological heads only')),
3448 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3455 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3449 ('c', 'closed', False, _('show normal and closed branch heads')),
3456 ('c', 'closed', False, _('show normal and closed branch heads')),
3450 ] + templateopts,
3457 ] + templateopts,
3451 _('[-ct] [-r STARTREV] [REV]...'))
3458 _('[-ct] [-r STARTREV] [REV]...'))
3452 def heads(ui, repo, *branchrevs, **opts):
3459 def heads(ui, repo, *branchrevs, **opts):
3453 """show branch heads
3460 """show branch heads
3454
3461
3455 With no arguments, show all open branch heads in the repository.
3462 With no arguments, show all open branch heads in the repository.
3456 Branch heads are changesets that have no descendants on the
3463 Branch heads are changesets that have no descendants on the
3457 same branch. They are where development generally takes place and
3464 same branch. They are where development generally takes place and
3458 are the usual targets for update and merge operations.
3465 are the usual targets for update and merge operations.
3459
3466
3460 If one or more REVs are given, only open branch heads on the
3467 If one or more REVs are given, only open branch heads on the
3461 branches associated with the specified changesets are shown. This
3468 branches associated with the specified changesets are shown. This
3462 means that you can use :hg:`heads .` to see the heads on the
3469 means that you can use :hg:`heads .` to see the heads on the
3463 currently checked-out branch.
3470 currently checked-out branch.
3464
3471
3465 If -c/--closed is specified, also show branch heads marked closed
3472 If -c/--closed is specified, also show branch heads marked closed
3466 (see :hg:`commit --close-branch`).
3473 (see :hg:`commit --close-branch`).
3467
3474
3468 If STARTREV is specified, only those heads that are descendants of
3475 If STARTREV is specified, only those heads that are descendants of
3469 STARTREV will be displayed.
3476 STARTREV will be displayed.
3470
3477
3471 If -t/--topo is specified, named branch mechanics will be ignored and only
3478 If -t/--topo is specified, named branch mechanics will be ignored and only
3472 topological heads (changesets with no children) will be shown.
3479 topological heads (changesets with no children) will be shown.
3473
3480
3474 Returns 0 if matching heads are found, 1 if not.
3481 Returns 0 if matching heads are found, 1 if not.
3475 """
3482 """
3476
3483
3477 start = None
3484 start = None
3478 if 'rev' in opts:
3485 if 'rev' in opts:
3479 start = scmutil.revsingle(repo, opts['rev'], None).node()
3486 start = scmutil.revsingle(repo, opts['rev'], None).node()
3480
3487
3481 if opts.get('topo'):
3488 if opts.get('topo'):
3482 heads = [repo[h] for h in repo.heads(start)]
3489 heads = [repo[h] for h in repo.heads(start)]
3483 else:
3490 else:
3484 heads = []
3491 heads = []
3485 for branch in repo.branchmap():
3492 for branch in repo.branchmap():
3486 heads += repo.branchheads(branch, start, opts.get('closed'))
3493 heads += repo.branchheads(branch, start, opts.get('closed'))
3487 heads = [repo[h] for h in heads]
3494 heads = [repo[h] for h in heads]
3488
3495
3489 if branchrevs:
3496 if branchrevs:
3490 branches = set(repo[br].branch() for br in branchrevs)
3497 branches = set(repo[br].branch() for br in branchrevs)
3491 heads = [h for h in heads if h.branch() in branches]
3498 heads = [h for h in heads if h.branch() in branches]
3492
3499
3493 if opts.get('active') and branchrevs:
3500 if opts.get('active') and branchrevs:
3494 dagheads = repo.heads(start)
3501 dagheads = repo.heads(start)
3495 heads = [h for h in heads if h.node() in dagheads]
3502 heads = [h for h in heads if h.node() in dagheads]
3496
3503
3497 if branchrevs:
3504 if branchrevs:
3498 haveheads = set(h.branch() for h in heads)
3505 haveheads = set(h.branch() for h in heads)
3499 if branches - haveheads:
3506 if branches - haveheads:
3500 headless = ', '.join(b for b in branches - haveheads)
3507 headless = ', '.join(b for b in branches - haveheads)
3501 msg = _('no open branch heads found on branches %s')
3508 msg = _('no open branch heads found on branches %s')
3502 if opts.get('rev'):
3509 if opts.get('rev'):
3503 msg += _(' (started at %s)') % opts['rev']
3510 msg += _(' (started at %s)') % opts['rev']
3504 ui.warn((msg + '\n') % headless)
3511 ui.warn((msg + '\n') % headless)
3505
3512
3506 if not heads:
3513 if not heads:
3507 return 1
3514 return 1
3508
3515
3509 heads = sorted(heads, key=lambda x: -x.rev())
3516 heads = sorted(heads, key=lambda x: -x.rev())
3510 displayer = cmdutil.show_changeset(ui, repo, opts)
3517 displayer = cmdutil.show_changeset(ui, repo, opts)
3511 for ctx in heads:
3518 for ctx in heads:
3512 displayer.show(ctx)
3519 displayer.show(ctx)
3513 displayer.close()
3520 displayer.close()
3514
3521
3515 @command('help',
3522 @command('help',
3516 [('e', 'extension', None, _('show only help for extensions')),
3523 [('e', 'extension', None, _('show only help for extensions')),
3517 ('c', 'command', None, _('show only help for commands')),
3524 ('c', 'command', None, _('show only help for commands')),
3518 ('k', 'keyword', '', _('show topics matching keyword')),
3525 ('k', 'keyword', '', _('show topics matching keyword')),
3519 ],
3526 ],
3520 _('[-ec] [TOPIC]'))
3527 _('[-ec] [TOPIC]'))
3521 def help_(ui, name=None, **opts):
3528 def help_(ui, name=None, **opts):
3522 """show help for a given topic or a help overview
3529 """show help for a given topic or a help overview
3523
3530
3524 With no arguments, print a list of commands with short help messages.
3531 With no arguments, print a list of commands with short help messages.
3525
3532
3526 Given a topic, extension, or command name, print help for that
3533 Given a topic, extension, or command name, print help for that
3527 topic.
3534 topic.
3528
3535
3529 Returns 0 if successful.
3536 Returns 0 if successful.
3530 """
3537 """
3531
3538
3532 textwidth = min(ui.termwidth(), 80) - 2
3539 textwidth = min(ui.termwidth(), 80) - 2
3533
3540
3534 keep = ui.verbose and ['verbose'] or []
3541 keep = ui.verbose and ['verbose'] or []
3535 text = help.help_(ui, name, **opts)
3542 text = help.help_(ui, name, **opts)
3536
3543
3537 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3544 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3538 if 'verbose' in pruned:
3545 if 'verbose' in pruned:
3539 keep.append('omitted')
3546 keep.append('omitted')
3540 else:
3547 else:
3541 keep.append('notomitted')
3548 keep.append('notomitted')
3542 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3549 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3543 ui.write(formatted)
3550 ui.write(formatted)
3544
3551
3545
3552
3546 @command('identify|id',
3553 @command('identify|id',
3547 [('r', 'rev', '',
3554 [('r', 'rev', '',
3548 _('identify the specified revision'), _('REV')),
3555 _('identify the specified revision'), _('REV')),
3549 ('n', 'num', None, _('show local revision number')),
3556 ('n', 'num', None, _('show local revision number')),
3550 ('i', 'id', None, _('show global revision id')),
3557 ('i', 'id', None, _('show global revision id')),
3551 ('b', 'branch', None, _('show branch')),
3558 ('b', 'branch', None, _('show branch')),
3552 ('t', 'tags', None, _('show tags')),
3559 ('t', 'tags', None, _('show tags')),
3553 ('B', 'bookmarks', None, _('show bookmarks')),
3560 ('B', 'bookmarks', None, _('show bookmarks')),
3554 ] + remoteopts,
3561 ] + remoteopts,
3555 _('[-nibtB] [-r REV] [SOURCE]'))
3562 _('[-nibtB] [-r REV] [SOURCE]'))
3556 def identify(ui, repo, source=None, rev=None,
3563 def identify(ui, repo, source=None, rev=None,
3557 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3564 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3558 """identify the working copy or specified revision
3565 """identify the working copy or specified revision
3559
3566
3560 Print a summary identifying the repository state at REV using one or
3567 Print a summary identifying the repository state at REV using one or
3561 two parent hash identifiers, followed by a "+" if the working
3568 two parent hash identifiers, followed by a "+" if the working
3562 directory has uncommitted changes, the branch name (if not default),
3569 directory has uncommitted changes, the branch name (if not default),
3563 a list of tags, and a list of bookmarks.
3570 a list of tags, and a list of bookmarks.
3564
3571
3565 When REV is not given, print a summary of the current state of the
3572 When REV is not given, print a summary of the current state of the
3566 repository.
3573 repository.
3567
3574
3568 Specifying a path to a repository root or Mercurial bundle will
3575 Specifying a path to a repository root or Mercurial bundle will
3569 cause lookup to operate on that repository/bundle.
3576 cause lookup to operate on that repository/bundle.
3570
3577
3571 .. container:: verbose
3578 .. container:: verbose
3572
3579
3573 Examples:
3580 Examples:
3574
3581
3575 - generate a build identifier for the working directory::
3582 - generate a build identifier for the working directory::
3576
3583
3577 hg id --id > build-id.dat
3584 hg id --id > build-id.dat
3578
3585
3579 - find the revision corresponding to a tag::
3586 - find the revision corresponding to a tag::
3580
3587
3581 hg id -n -r 1.3
3588 hg id -n -r 1.3
3582
3589
3583 - check the most recent revision of a remote repository::
3590 - check the most recent revision of a remote repository::
3584
3591
3585 hg id -r tip http://selenic.com/hg/
3592 hg id -r tip http://selenic.com/hg/
3586
3593
3587 Returns 0 if successful.
3594 Returns 0 if successful.
3588 """
3595 """
3589
3596
3590 if not repo and not source:
3597 if not repo and not source:
3591 raise util.Abort(_("there is no Mercurial repository here "
3598 raise util.Abort(_("there is no Mercurial repository here "
3592 "(.hg not found)"))
3599 "(.hg not found)"))
3593
3600
3594 hexfunc = ui.debugflag and hex or short
3601 hexfunc = ui.debugflag and hex or short
3595 default = not (num or id or branch or tags or bookmarks)
3602 default = not (num or id or branch or tags or bookmarks)
3596 output = []
3603 output = []
3597 revs = []
3604 revs = []
3598
3605
3599 if source:
3606 if source:
3600 source, branches = hg.parseurl(ui.expandpath(source))
3607 source, branches = hg.parseurl(ui.expandpath(source))
3601 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3608 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3602 repo = peer.local()
3609 repo = peer.local()
3603 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3610 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3604
3611
3605 if not repo:
3612 if not repo:
3606 if num or branch or tags:
3613 if num or branch or tags:
3607 raise util.Abort(
3614 raise util.Abort(
3608 _("can't query remote revision number, branch, or tags"))
3615 _("can't query remote revision number, branch, or tags"))
3609 if not rev and revs:
3616 if not rev and revs:
3610 rev = revs[0]
3617 rev = revs[0]
3611 if not rev:
3618 if not rev:
3612 rev = "tip"
3619 rev = "tip"
3613
3620
3614 remoterev = peer.lookup(rev)
3621 remoterev = peer.lookup(rev)
3615 if default or id:
3622 if default or id:
3616 output = [hexfunc(remoterev)]
3623 output = [hexfunc(remoterev)]
3617
3624
3618 def getbms():
3625 def getbms():
3619 bms = []
3626 bms = []
3620
3627
3621 if 'bookmarks' in peer.listkeys('namespaces'):
3628 if 'bookmarks' in peer.listkeys('namespaces'):
3622 hexremoterev = hex(remoterev)
3629 hexremoterev = hex(remoterev)
3623 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3630 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3624 if bmr == hexremoterev]
3631 if bmr == hexremoterev]
3625
3632
3626 return sorted(bms)
3633 return sorted(bms)
3627
3634
3628 if bookmarks:
3635 if bookmarks:
3629 output.extend(getbms())
3636 output.extend(getbms())
3630 elif default and not ui.quiet:
3637 elif default and not ui.quiet:
3631 # multiple bookmarks for a single parent separated by '/'
3638 # multiple bookmarks for a single parent separated by '/'
3632 bm = '/'.join(getbms())
3639 bm = '/'.join(getbms())
3633 if bm:
3640 if bm:
3634 output.append(bm)
3641 output.append(bm)
3635 else:
3642 else:
3636 if not rev:
3643 if not rev:
3637 ctx = repo[None]
3644 ctx = repo[None]
3638 parents = ctx.parents()
3645 parents = ctx.parents()
3639 changed = ""
3646 changed = ""
3640 if default or id or num:
3647 if default or id or num:
3641 if (util.any(repo.status())
3648 if (util.any(repo.status())
3642 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3649 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3643 changed = '+'
3650 changed = '+'
3644 if default or id:
3651 if default or id:
3645 output = ["%s%s" %
3652 output = ["%s%s" %
3646 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3653 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3647 if num:
3654 if num:
3648 output.append("%s%s" %
3655 output.append("%s%s" %
3649 ('+'.join([str(p.rev()) for p in parents]), changed))
3656 ('+'.join([str(p.rev()) for p in parents]), changed))
3650 else:
3657 else:
3651 ctx = scmutil.revsingle(repo, rev)
3658 ctx = scmutil.revsingle(repo, rev)
3652 if default or id:
3659 if default or id:
3653 output = [hexfunc(ctx.node())]
3660 output = [hexfunc(ctx.node())]
3654 if num:
3661 if num:
3655 output.append(str(ctx.rev()))
3662 output.append(str(ctx.rev()))
3656
3663
3657 if default and not ui.quiet:
3664 if default and not ui.quiet:
3658 b = ctx.branch()
3665 b = ctx.branch()
3659 if b != 'default':
3666 if b != 'default':
3660 output.append("(%s)" % b)
3667 output.append("(%s)" % b)
3661
3668
3662 # multiple tags for a single parent separated by '/'
3669 # multiple tags for a single parent separated by '/'
3663 t = '/'.join(ctx.tags())
3670 t = '/'.join(ctx.tags())
3664 if t:
3671 if t:
3665 output.append(t)
3672 output.append(t)
3666
3673
3667 # multiple bookmarks for a single parent separated by '/'
3674 # multiple bookmarks for a single parent separated by '/'
3668 bm = '/'.join(ctx.bookmarks())
3675 bm = '/'.join(ctx.bookmarks())
3669 if bm:
3676 if bm:
3670 output.append(bm)
3677 output.append(bm)
3671 else:
3678 else:
3672 if branch:
3679 if branch:
3673 output.append(ctx.branch())
3680 output.append(ctx.branch())
3674
3681
3675 if tags:
3682 if tags:
3676 output.extend(ctx.tags())
3683 output.extend(ctx.tags())
3677
3684
3678 if bookmarks:
3685 if bookmarks:
3679 output.extend(ctx.bookmarks())
3686 output.extend(ctx.bookmarks())
3680
3687
3681 ui.write("%s\n" % ' '.join(output))
3688 ui.write("%s\n" % ' '.join(output))
3682
3689
3683 @command('import|patch',
3690 @command('import|patch',
3684 [('p', 'strip', 1,
3691 [('p', 'strip', 1,
3685 _('directory strip option for patch. This has the same '
3692 _('directory strip option for patch. This has the same '
3686 'meaning as the corresponding patch option'), _('NUM')),
3693 'meaning as the corresponding patch option'), _('NUM')),
3687 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3694 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3688 ('e', 'edit', False, _('invoke editor on commit messages')),
3695 ('e', 'edit', False, _('invoke editor on commit messages')),
3689 ('f', 'force', None,
3696 ('f', 'force', None,
3690 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3697 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3691 ('', 'no-commit', None,
3698 ('', 'no-commit', None,
3692 _("don't commit, just update the working directory")),
3699 _("don't commit, just update the working directory")),
3693 ('', 'bypass', None,
3700 ('', 'bypass', None,
3694 _("apply patch without touching the working directory")),
3701 _("apply patch without touching the working directory")),
3695 ('', 'exact', None,
3702 ('', 'exact', None,
3696 _('apply patch to the nodes from which it was generated')),
3703 _('apply patch to the nodes from which it was generated')),
3697 ('', 'import-branch', None,
3704 ('', 'import-branch', None,
3698 _('use any branch information in patch (implied by --exact)'))] +
3705 _('use any branch information in patch (implied by --exact)'))] +
3699 commitopts + commitopts2 + similarityopts,
3706 commitopts + commitopts2 + similarityopts,
3700 _('[OPTION]... PATCH...'))
3707 _('[OPTION]... PATCH...'))
3701 def import_(ui, repo, patch1=None, *patches, **opts):
3708 def import_(ui, repo, patch1=None, *patches, **opts):
3702 """import an ordered set of patches
3709 """import an ordered set of patches
3703
3710
3704 Import a list of patches and commit them individually (unless
3711 Import a list of patches and commit them individually (unless
3705 --no-commit is specified).
3712 --no-commit is specified).
3706
3713
3707 Because import first applies changes to the working directory,
3714 Because import first applies changes to the working directory,
3708 import will abort if there are outstanding changes.
3715 import will abort if there are outstanding changes.
3709
3716
3710 You can import a patch straight from a mail message. Even patches
3717 You can import a patch straight from a mail message. Even patches
3711 as attachments work (to use the body part, it must have type
3718 as attachments work (to use the body part, it must have type
3712 text/plain or text/x-patch). From and Subject headers of email
3719 text/plain or text/x-patch). From and Subject headers of email
3713 message are used as default committer and commit message. All
3720 message are used as default committer and commit message. All
3714 text/plain body parts before first diff are added to commit
3721 text/plain body parts before first diff are added to commit
3715 message.
3722 message.
3716
3723
3717 If the imported patch was generated by :hg:`export`, user and
3724 If the imported patch was generated by :hg:`export`, user and
3718 description from patch override values from message headers and
3725 description from patch override values from message headers and
3719 body. Values given on command line with -m/--message and -u/--user
3726 body. Values given on command line with -m/--message and -u/--user
3720 override these.
3727 override these.
3721
3728
3722 If --exact is specified, import will set the working directory to
3729 If --exact is specified, import will set the working directory to
3723 the parent of each patch before applying it, and will abort if the
3730 the parent of each patch before applying it, and will abort if the
3724 resulting changeset has a different ID than the one recorded in
3731 resulting changeset has a different ID than the one recorded in
3725 the patch. This may happen due to character set problems or other
3732 the patch. This may happen due to character set problems or other
3726 deficiencies in the text patch format.
3733 deficiencies in the text patch format.
3727
3734
3728 Use --bypass to apply and commit patches directly to the
3735 Use --bypass to apply and commit patches directly to the
3729 repository, not touching the working directory. Without --exact,
3736 repository, not touching the working directory. Without --exact,
3730 patches will be applied on top of the working directory parent
3737 patches will be applied on top of the working directory parent
3731 revision.
3738 revision.
3732
3739
3733 With -s/--similarity, hg will attempt to discover renames and
3740 With -s/--similarity, hg will attempt to discover renames and
3734 copies in the patch in the same way as :hg:`addremove`.
3741 copies in the patch in the same way as :hg:`addremove`.
3735
3742
3736 To read a patch from standard input, use "-" as the patch name. If
3743 To read a patch from standard input, use "-" as the patch name. If
3737 a URL is specified, the patch will be downloaded from it.
3744 a URL is specified, the patch will be downloaded from it.
3738 See :hg:`help dates` for a list of formats valid for -d/--date.
3745 See :hg:`help dates` for a list of formats valid for -d/--date.
3739
3746
3740 .. container:: verbose
3747 .. container:: verbose
3741
3748
3742 Examples:
3749 Examples:
3743
3750
3744 - import a traditional patch from a website and detect renames::
3751 - import a traditional patch from a website and detect renames::
3745
3752
3746 hg import -s 80 http://example.com/bugfix.patch
3753 hg import -s 80 http://example.com/bugfix.patch
3747
3754
3748 - import a changeset from an hgweb server::
3755 - import a changeset from an hgweb server::
3749
3756
3750 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3757 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3751
3758
3752 - import all the patches in an Unix-style mbox::
3759 - import all the patches in an Unix-style mbox::
3753
3760
3754 hg import incoming-patches.mbox
3761 hg import incoming-patches.mbox
3755
3762
3756 - attempt to exactly restore an exported changeset (not always
3763 - attempt to exactly restore an exported changeset (not always
3757 possible)::
3764 possible)::
3758
3765
3759 hg import --exact proposed-fix.patch
3766 hg import --exact proposed-fix.patch
3760
3767
3761 Returns 0 on success.
3768 Returns 0 on success.
3762 """
3769 """
3763
3770
3764 if not patch1:
3771 if not patch1:
3765 raise util.Abort(_('need at least one patch to import'))
3772 raise util.Abort(_('need at least one patch to import'))
3766
3773
3767 patches = (patch1,) + patches
3774 patches = (patch1,) + patches
3768
3775
3769 date = opts.get('date')
3776 date = opts.get('date')
3770 if date:
3777 if date:
3771 opts['date'] = util.parsedate(date)
3778 opts['date'] = util.parsedate(date)
3772
3779
3773 update = not opts.get('bypass')
3780 update = not opts.get('bypass')
3774 if not update and opts.get('no_commit'):
3781 if not update and opts.get('no_commit'):
3775 raise util.Abort(_('cannot use --no-commit with --bypass'))
3782 raise util.Abort(_('cannot use --no-commit with --bypass'))
3776 try:
3783 try:
3777 sim = float(opts.get('similarity') or 0)
3784 sim = float(opts.get('similarity') or 0)
3778 except ValueError:
3785 except ValueError:
3779 raise util.Abort(_('similarity must be a number'))
3786 raise util.Abort(_('similarity must be a number'))
3780 if sim < 0 or sim > 100:
3787 if sim < 0 or sim > 100:
3781 raise util.Abort(_('similarity must be between 0 and 100'))
3788 raise util.Abort(_('similarity must be between 0 and 100'))
3782 if sim and not update:
3789 if sim and not update:
3783 raise util.Abort(_('cannot use --similarity with --bypass'))
3790 raise util.Abort(_('cannot use --similarity with --bypass'))
3784
3791
3785 if update:
3792 if update:
3786 cmdutil.checkunfinished(repo)
3793 cmdutil.checkunfinished(repo)
3787 if (opts.get('exact') or not opts.get('force')) and update:
3794 if (opts.get('exact') or not opts.get('force')) and update:
3788 cmdutil.bailifchanged(repo)
3795 cmdutil.bailifchanged(repo)
3789
3796
3790 base = opts["base"]
3797 base = opts["base"]
3791 wlock = lock = tr = None
3798 wlock = lock = tr = None
3792 msgs = []
3799 msgs = []
3793
3800
3794
3801
3795 try:
3802 try:
3796 try:
3803 try:
3797 wlock = repo.wlock()
3804 wlock = repo.wlock()
3798 if not opts.get('no_commit'):
3805 if not opts.get('no_commit'):
3799 lock = repo.lock()
3806 lock = repo.lock()
3800 tr = repo.transaction('import')
3807 tr = repo.transaction('import')
3801 parents = repo.parents()
3808 parents = repo.parents()
3802 for patchurl in patches:
3809 for patchurl in patches:
3803 if patchurl == '-':
3810 if patchurl == '-':
3804 ui.status(_('applying patch from stdin\n'))
3811 ui.status(_('applying patch from stdin\n'))
3805 patchfile = ui.fin
3812 patchfile = ui.fin
3806 patchurl = 'stdin' # for error message
3813 patchurl = 'stdin' # for error message
3807 else:
3814 else:
3808 patchurl = os.path.join(base, patchurl)
3815 patchurl = os.path.join(base, patchurl)
3809 ui.status(_('applying %s\n') % patchurl)
3816 ui.status(_('applying %s\n') % patchurl)
3810 patchfile = hg.openpath(ui, patchurl)
3817 patchfile = hg.openpath(ui, patchurl)
3811
3818
3812 haspatch = False
3819 haspatch = False
3813 for hunk in patch.split(patchfile):
3820 for hunk in patch.split(patchfile):
3814 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3821 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3815 opts, msgs, hg.clean)
3822 opts, msgs, hg.clean)
3816 if msg:
3823 if msg:
3817 haspatch = True
3824 haspatch = True
3818 ui.note(msg + '\n')
3825 ui.note(msg + '\n')
3819 if update or opts.get('exact'):
3826 if update or opts.get('exact'):
3820 parents = repo.parents()
3827 parents = repo.parents()
3821 else:
3828 else:
3822 parents = [repo[node]]
3829 parents = [repo[node]]
3823
3830
3824 if not haspatch:
3831 if not haspatch:
3825 raise util.Abort(_('%s: no diffs found') % patchurl)
3832 raise util.Abort(_('%s: no diffs found') % patchurl)
3826
3833
3827 if tr:
3834 if tr:
3828 tr.close()
3835 tr.close()
3829 if msgs:
3836 if msgs:
3830 repo.savecommitmessage('\n* * *\n'.join(msgs))
3837 repo.savecommitmessage('\n* * *\n'.join(msgs))
3831 except: # re-raises
3838 except: # re-raises
3832 # wlock.release() indirectly calls dirstate.write(): since
3839 # wlock.release() indirectly calls dirstate.write(): since
3833 # we're crashing, we do not want to change the working dir
3840 # we're crashing, we do not want to change the working dir
3834 # parent after all, so make sure it writes nothing
3841 # parent after all, so make sure it writes nothing
3835 repo.dirstate.invalidate()
3842 repo.dirstate.invalidate()
3836 raise
3843 raise
3837 finally:
3844 finally:
3838 if tr:
3845 if tr:
3839 tr.release()
3846 tr.release()
3840 release(lock, wlock)
3847 release(lock, wlock)
3841
3848
3842 @command('incoming|in',
3849 @command('incoming|in',
3843 [('f', 'force', None,
3850 [('f', 'force', None,
3844 _('run even if remote repository is unrelated')),
3851 _('run even if remote repository is unrelated')),
3845 ('n', 'newest-first', None, _('show newest record first')),
3852 ('n', 'newest-first', None, _('show newest record first')),
3846 ('', 'bundle', '',
3853 ('', 'bundle', '',
3847 _('file to store the bundles into'), _('FILE')),
3854 _('file to store the bundles into'), _('FILE')),
3848 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3855 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3849 ('B', 'bookmarks', False, _("compare bookmarks")),
3856 ('B', 'bookmarks', False, _("compare bookmarks")),
3850 ('b', 'branch', [],
3857 ('b', 'branch', [],
3851 _('a specific branch you would like to pull'), _('BRANCH')),
3858 _('a specific branch you would like to pull'), _('BRANCH')),
3852 ] + logopts + remoteopts + subrepoopts,
3859 ] + logopts + remoteopts + subrepoopts,
3853 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3860 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3854 def incoming(ui, repo, source="default", **opts):
3861 def incoming(ui, repo, source="default", **opts):
3855 """show new changesets found in source
3862 """show new changesets found in source
3856
3863
3857 Show new changesets found in the specified path/URL or the default
3864 Show new changesets found in the specified path/URL or the default
3858 pull location. These are the changesets that would have been pulled
3865 pull location. These are the changesets that would have been pulled
3859 if a pull at the time you issued this command.
3866 if a pull at the time you issued this command.
3860
3867
3861 For remote repository, using --bundle avoids downloading the
3868 For remote repository, using --bundle avoids downloading the
3862 changesets twice if the incoming is followed by a pull.
3869 changesets twice if the incoming is followed by a pull.
3863
3870
3864 See pull for valid source format details.
3871 See pull for valid source format details.
3865
3872
3866 Returns 0 if there are incoming changes, 1 otherwise.
3873 Returns 0 if there are incoming changes, 1 otherwise.
3867 """
3874 """
3868 if opts.get('graph'):
3875 if opts.get('graph'):
3869 cmdutil.checkunsupportedgraphflags([], opts)
3876 cmdutil.checkunsupportedgraphflags([], opts)
3870 def display(other, chlist, displayer):
3877 def display(other, chlist, displayer):
3871 revdag = cmdutil.graphrevs(other, chlist, opts)
3878 revdag = cmdutil.graphrevs(other, chlist, opts)
3872 showparents = [ctx.node() for ctx in repo[None].parents()]
3879 showparents = [ctx.node() for ctx in repo[None].parents()]
3873 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3880 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3874 graphmod.asciiedges)
3881 graphmod.asciiedges)
3875
3882
3876 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3883 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3877 return 0
3884 return 0
3878
3885
3879 if opts.get('bundle') and opts.get('subrepos'):
3886 if opts.get('bundle') and opts.get('subrepos'):
3880 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3887 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3881
3888
3882 if opts.get('bookmarks'):
3889 if opts.get('bookmarks'):
3883 source, branches = hg.parseurl(ui.expandpath(source),
3890 source, branches = hg.parseurl(ui.expandpath(source),
3884 opts.get('branch'))
3891 opts.get('branch'))
3885 other = hg.peer(repo, opts, source)
3892 other = hg.peer(repo, opts, source)
3886 if 'bookmarks' not in other.listkeys('namespaces'):
3893 if 'bookmarks' not in other.listkeys('namespaces'):
3887 ui.warn(_("remote doesn't support bookmarks\n"))
3894 ui.warn(_("remote doesn't support bookmarks\n"))
3888 return 0
3895 return 0
3889 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3896 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3890 return bookmarks.diff(ui, repo, other)
3897 return bookmarks.diff(ui, repo, other)
3891
3898
3892 repo._subtoppath = ui.expandpath(source)
3899 repo._subtoppath = ui.expandpath(source)
3893 try:
3900 try:
3894 return hg.incoming(ui, repo, source, opts)
3901 return hg.incoming(ui, repo, source, opts)
3895 finally:
3902 finally:
3896 del repo._subtoppath
3903 del repo._subtoppath
3897
3904
3898
3905
3899 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3906 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3900 def init(ui, dest=".", **opts):
3907 def init(ui, dest=".", **opts):
3901 """create a new repository in the given directory
3908 """create a new repository in the given directory
3902
3909
3903 Initialize a new repository in the given directory. If the given
3910 Initialize a new repository in the given directory. If the given
3904 directory does not exist, it will be created.
3911 directory does not exist, it will be created.
3905
3912
3906 If no directory is given, the current directory is used.
3913 If no directory is given, the current directory is used.
3907
3914
3908 It is possible to specify an ``ssh://`` URL as the destination.
3915 It is possible to specify an ``ssh://`` URL as the destination.
3909 See :hg:`help urls` for more information.
3916 See :hg:`help urls` for more information.
3910
3917
3911 Returns 0 on success.
3918 Returns 0 on success.
3912 """
3919 """
3913 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3920 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3914
3921
3915 @command('locate',
3922 @command('locate',
3916 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3923 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3917 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3924 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3918 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3925 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3919 ] + walkopts,
3926 ] + walkopts,
3920 _('[OPTION]... [PATTERN]...'))
3927 _('[OPTION]... [PATTERN]...'))
3921 def locate(ui, repo, *pats, **opts):
3928 def locate(ui, repo, *pats, **opts):
3922 """locate files matching specific patterns
3929 """locate files matching specific patterns
3923
3930
3924 Print files under Mercurial control in the working directory whose
3931 Print files under Mercurial control in the working directory whose
3925 names match the given patterns.
3932 names match the given patterns.
3926
3933
3927 By default, this command searches all directories in the working
3934 By default, this command searches all directories in the working
3928 directory. To search just the current directory and its
3935 directory. To search just the current directory and its
3929 subdirectories, use "--include .".
3936 subdirectories, use "--include .".
3930
3937
3931 If no patterns are given to match, this command prints the names
3938 If no patterns are given to match, this command prints the names
3932 of all files under Mercurial control in the working directory.
3939 of all files under Mercurial control in the working directory.
3933
3940
3934 If you want to feed the output of this command into the "xargs"
3941 If you want to feed the output of this command into the "xargs"
3935 command, use the -0 option to both this command and "xargs". This
3942 command, use the -0 option to both this command and "xargs". This
3936 will avoid the problem of "xargs" treating single filenames that
3943 will avoid the problem of "xargs" treating single filenames that
3937 contain whitespace as multiple filenames.
3944 contain whitespace as multiple filenames.
3938
3945
3939 Returns 0 if a match is found, 1 otherwise.
3946 Returns 0 if a match is found, 1 otherwise.
3940 """
3947 """
3941 end = opts.get('print0') and '\0' or '\n'
3948 end = opts.get('print0') and '\0' or '\n'
3942 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3949 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3943
3950
3944 ret = 1
3951 ret = 1
3945 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3952 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3946 m.bad = lambda x, y: False
3953 m.bad = lambda x, y: False
3947 for abs in repo[rev].walk(m):
3954 for abs in repo[rev].walk(m):
3948 if not rev and abs not in repo.dirstate:
3955 if not rev and abs not in repo.dirstate:
3949 continue
3956 continue
3950 if opts.get('fullpath'):
3957 if opts.get('fullpath'):
3951 ui.write(repo.wjoin(abs), end)
3958 ui.write(repo.wjoin(abs), end)
3952 else:
3959 else:
3953 ui.write(((pats and m.rel(abs)) or abs), end)
3960 ui.write(((pats and m.rel(abs)) or abs), end)
3954 ret = 0
3961 ret = 0
3955
3962
3956 return ret
3963 return ret
3957
3964
3958 @command('^log|history',
3965 @command('^log|history',
3959 [('f', 'follow', None,
3966 [('f', 'follow', None,
3960 _('follow changeset history, or file history across copies and renames')),
3967 _('follow changeset history, or file history across copies and renames')),
3961 ('', 'follow-first', None,
3968 ('', 'follow-first', None,
3962 _('only follow the first parent of merge changesets (DEPRECATED)')),
3969 _('only follow the first parent of merge changesets (DEPRECATED)')),
3963 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3970 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3964 ('C', 'copies', None, _('show copied files')),
3971 ('C', 'copies', None, _('show copied files')),
3965 ('k', 'keyword', [],
3972 ('k', 'keyword', [],
3966 _('do case-insensitive search for a given text'), _('TEXT')),
3973 _('do case-insensitive search for a given text'), _('TEXT')),
3967 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3974 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3968 ('', 'removed', None, _('include revisions where files were removed')),
3975 ('', 'removed', None, _('include revisions where files were removed')),
3969 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3976 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3970 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3977 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3971 ('', 'only-branch', [],
3978 ('', 'only-branch', [],
3972 _('show only changesets within the given named branch (DEPRECATED)'),
3979 _('show only changesets within the given named branch (DEPRECATED)'),
3973 _('BRANCH')),
3980 _('BRANCH')),
3974 ('b', 'branch', [],
3981 ('b', 'branch', [],
3975 _('show changesets within the given named branch'), _('BRANCH')),
3982 _('show changesets within the given named branch'), _('BRANCH')),
3976 ('P', 'prune', [],
3983 ('P', 'prune', [],
3977 _('do not display revision or any of its ancestors'), _('REV')),
3984 _('do not display revision or any of its ancestors'), _('REV')),
3978 ] + logopts + walkopts,
3985 ] + logopts + walkopts,
3979 _('[OPTION]... [FILE]'))
3986 _('[OPTION]... [FILE]'))
3980 def log(ui, repo, *pats, **opts):
3987 def log(ui, repo, *pats, **opts):
3981 """show revision history of entire repository or files
3988 """show revision history of entire repository or files
3982
3989
3983 Print the revision history of the specified files or the entire
3990 Print the revision history of the specified files or the entire
3984 project.
3991 project.
3985
3992
3986 If no revision range is specified, the default is ``tip:0`` unless
3993 If no revision range is specified, the default is ``tip:0`` unless
3987 --follow is set, in which case the working directory parent is
3994 --follow is set, in which case the working directory parent is
3988 used as the starting revision.
3995 used as the starting revision.
3989
3996
3990 File history is shown without following rename or copy history of
3997 File history is shown without following rename or copy history of
3991 files. Use -f/--follow with a filename to follow history across
3998 files. Use -f/--follow with a filename to follow history across
3992 renames and copies. --follow without a filename will only show
3999 renames and copies. --follow without a filename will only show
3993 ancestors or descendants of the starting revision.
4000 ancestors or descendants of the starting revision.
3994
4001
3995 By default this command prints revision number and changeset id,
4002 By default this command prints revision number and changeset id,
3996 tags, non-trivial parents, user, date and time, and a summary for
4003 tags, non-trivial parents, user, date and time, and a summary for
3997 each commit. When the -v/--verbose switch is used, the list of
4004 each commit. When the -v/--verbose switch is used, the list of
3998 changed files and full commit message are shown.
4005 changed files and full commit message are shown.
3999
4006
4000 With --graph the revisions are shown as an ASCII art DAG with the most
4007 With --graph the revisions are shown as an ASCII art DAG with the most
4001 recent changeset at the top.
4008 recent changeset at the top.
4002 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4009 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4003 and '+' represents a fork where the changeset from the lines below is a
4010 and '+' represents a fork where the changeset from the lines below is a
4004 parent of the 'o' merge on the same same line.
4011 parent of the 'o' merge on the same same line.
4005
4012
4006 .. note::
4013 .. note::
4007
4014
4008 log -p/--patch may generate unexpected diff output for merge
4015 log -p/--patch may generate unexpected diff output for merge
4009 changesets, as it will only compare the merge changeset against
4016 changesets, as it will only compare the merge changeset against
4010 its first parent. Also, only files different from BOTH parents
4017 its first parent. Also, only files different from BOTH parents
4011 will appear in files:.
4018 will appear in files:.
4012
4019
4013 .. note::
4020 .. note::
4014
4021
4015 for performance reasons, log FILE may omit duplicate changes
4022 for performance reasons, log FILE may omit duplicate changes
4016 made on branches and will not show deletions. To see all
4023 made on branches and will not show deletions. To see all
4017 changes including duplicates and deletions, use the --removed
4024 changes including duplicates and deletions, use the --removed
4018 switch.
4025 switch.
4019
4026
4020 .. container:: verbose
4027 .. container:: verbose
4021
4028
4022 Some examples:
4029 Some examples:
4023
4030
4024 - changesets with full descriptions and file lists::
4031 - changesets with full descriptions and file lists::
4025
4032
4026 hg log -v
4033 hg log -v
4027
4034
4028 - changesets ancestral to the working directory::
4035 - changesets ancestral to the working directory::
4029
4036
4030 hg log -f
4037 hg log -f
4031
4038
4032 - last 10 commits on the current branch::
4039 - last 10 commits on the current branch::
4033
4040
4034 hg log -l 10 -b .
4041 hg log -l 10 -b .
4035
4042
4036 - changesets showing all modifications of a file, including removals::
4043 - changesets showing all modifications of a file, including removals::
4037
4044
4038 hg log --removed file.c
4045 hg log --removed file.c
4039
4046
4040 - all changesets that touch a directory, with diffs, excluding merges::
4047 - all changesets that touch a directory, with diffs, excluding merges::
4041
4048
4042 hg log -Mp lib/
4049 hg log -Mp lib/
4043
4050
4044 - all revision numbers that match a keyword::
4051 - all revision numbers that match a keyword::
4045
4052
4046 hg log -k bug --template "{rev}\\n"
4053 hg log -k bug --template "{rev}\\n"
4047
4054
4048 - check if a given changeset is included is a tagged release::
4055 - check if a given changeset is included is a tagged release::
4049
4056
4050 hg log -r "a21ccf and ancestor(1.9)"
4057 hg log -r "a21ccf and ancestor(1.9)"
4051
4058
4052 - find all changesets by some user in a date range::
4059 - find all changesets by some user in a date range::
4053
4060
4054 hg log -k alice -d "may 2008 to jul 2008"
4061 hg log -k alice -d "may 2008 to jul 2008"
4055
4062
4056 - summary of all changesets after the last tag::
4063 - summary of all changesets after the last tag::
4057
4064
4058 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4065 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4059
4066
4060 See :hg:`help dates` for a list of formats valid for -d/--date.
4067 See :hg:`help dates` for a list of formats valid for -d/--date.
4061
4068
4062 See :hg:`help revisions` and :hg:`help revsets` for more about
4069 See :hg:`help revisions` and :hg:`help revsets` for more about
4063 specifying revisions.
4070 specifying revisions.
4064
4071
4065 See :hg:`help templates` for more about pre-packaged styles and
4072 See :hg:`help templates` for more about pre-packaged styles and
4066 specifying custom templates.
4073 specifying custom templates.
4067
4074
4068 Returns 0 on success.
4075 Returns 0 on success.
4069 """
4076 """
4070 if opts.get('graph'):
4077 if opts.get('graph'):
4071 return cmdutil.graphlog(ui, repo, *pats, **opts)
4078 return cmdutil.graphlog(ui, repo, *pats, **opts)
4072
4079
4073 matchfn = scmutil.match(repo[None], pats, opts)
4080 matchfn = scmutil.match(repo[None], pats, opts)
4074 limit = cmdutil.loglimit(opts)
4081 limit = cmdutil.loglimit(opts)
4075 count = 0
4082 count = 0
4076
4083
4077 getrenamed, endrev = None, None
4084 getrenamed, endrev = None, None
4078 if opts.get('copies'):
4085 if opts.get('copies'):
4079 if opts.get('rev'):
4086 if opts.get('rev'):
4080 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4087 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4081 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4088 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4082
4089
4083 df = False
4090 df = False
4084 if opts.get("date"):
4091 if opts.get("date"):
4085 df = util.matchdate(opts["date"])
4092 df = util.matchdate(opts["date"])
4086
4093
4087 branches = opts.get('branch', []) + opts.get('only_branch', [])
4094 branches = opts.get('branch', []) + opts.get('only_branch', [])
4088 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4095 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4089
4096
4090 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4097 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4091 def prep(ctx, fns):
4098 def prep(ctx, fns):
4092 rev = ctx.rev()
4099 rev = ctx.rev()
4093 parents = [p for p in repo.changelog.parentrevs(rev)
4100 parents = [p for p in repo.changelog.parentrevs(rev)
4094 if p != nullrev]
4101 if p != nullrev]
4095 if opts.get('no_merges') and len(parents) == 2:
4102 if opts.get('no_merges') and len(parents) == 2:
4096 return
4103 return
4097 if opts.get('only_merges') and len(parents) != 2:
4104 if opts.get('only_merges') and len(parents) != 2:
4098 return
4105 return
4099 if opts.get('branch') and ctx.branch() not in opts['branch']:
4106 if opts.get('branch') and ctx.branch() not in opts['branch']:
4100 return
4107 return
4101 if df and not df(ctx.date()[0]):
4108 if df and not df(ctx.date()[0]):
4102 return
4109 return
4103
4110
4104 lower = encoding.lower
4111 lower = encoding.lower
4105 if opts.get('user'):
4112 if opts.get('user'):
4106 luser = lower(ctx.user())
4113 luser = lower(ctx.user())
4107 for k in [lower(x) for x in opts['user']]:
4114 for k in [lower(x) for x in opts['user']]:
4108 if (k in luser):
4115 if (k in luser):
4109 break
4116 break
4110 else:
4117 else:
4111 return
4118 return
4112 if opts.get('keyword'):
4119 if opts.get('keyword'):
4113 luser = lower(ctx.user())
4120 luser = lower(ctx.user())
4114 ldesc = lower(ctx.description())
4121 ldesc = lower(ctx.description())
4115 lfiles = lower(" ".join(ctx.files()))
4122 lfiles = lower(" ".join(ctx.files()))
4116 for k in [lower(x) for x in opts['keyword']]:
4123 for k in [lower(x) for x in opts['keyword']]:
4117 if (k in luser or k in ldesc or k in lfiles):
4124 if (k in luser or k in ldesc or k in lfiles):
4118 break
4125 break
4119 else:
4126 else:
4120 return
4127 return
4121
4128
4122 copies = None
4129 copies = None
4123 if getrenamed is not None and rev:
4130 if getrenamed is not None and rev:
4124 copies = []
4131 copies = []
4125 for fn in ctx.files():
4132 for fn in ctx.files():
4126 rename = getrenamed(fn, rev)
4133 rename = getrenamed(fn, rev)
4127 if rename:
4134 if rename:
4128 copies.append((fn, rename[0]))
4135 copies.append((fn, rename[0]))
4129
4136
4130 revmatchfn = None
4137 revmatchfn = None
4131 if opts.get('patch') or opts.get('stat'):
4138 if opts.get('patch') or opts.get('stat'):
4132 if opts.get('follow') or opts.get('follow_first'):
4139 if opts.get('follow') or opts.get('follow_first'):
4133 # note: this might be wrong when following through merges
4140 # note: this might be wrong when following through merges
4134 revmatchfn = scmutil.match(repo[None], fns, default='path')
4141 revmatchfn = scmutil.match(repo[None], fns, default='path')
4135 else:
4142 else:
4136 revmatchfn = matchfn
4143 revmatchfn = matchfn
4137
4144
4138 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4145 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4139
4146
4140 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4147 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4141 if displayer.flush(ctx.rev()):
4148 if displayer.flush(ctx.rev()):
4142 count += 1
4149 count += 1
4143 if count == limit:
4150 if count == limit:
4144 break
4151 break
4145 displayer.close()
4152 displayer.close()
4146
4153
4147 @command('manifest',
4154 @command('manifest',
4148 [('r', 'rev', '', _('revision to display'), _('REV')),
4155 [('r', 'rev', '', _('revision to display'), _('REV')),
4149 ('', 'all', False, _("list files from all revisions"))],
4156 ('', 'all', False, _("list files from all revisions"))],
4150 _('[-r REV]'))
4157 _('[-r REV]'))
4151 def manifest(ui, repo, node=None, rev=None, **opts):
4158 def manifest(ui, repo, node=None, rev=None, **opts):
4152 """output the current or given revision of the project manifest
4159 """output the current or given revision of the project manifest
4153
4160
4154 Print a list of version controlled files for the given revision.
4161 Print a list of version controlled files for the given revision.
4155 If no revision is given, the first parent of the working directory
4162 If no revision is given, the first parent of the working directory
4156 is used, or the null revision if no revision is checked out.
4163 is used, or the null revision if no revision is checked out.
4157
4164
4158 With -v, print file permissions, symlink and executable bits.
4165 With -v, print file permissions, symlink and executable bits.
4159 With --debug, print file revision hashes.
4166 With --debug, print file revision hashes.
4160
4167
4161 If option --all is specified, the list of all files from all revisions
4168 If option --all is specified, the list of all files from all revisions
4162 is printed. This includes deleted and renamed files.
4169 is printed. This includes deleted and renamed files.
4163
4170
4164 Returns 0 on success.
4171 Returns 0 on success.
4165 """
4172 """
4166
4173
4167 fm = ui.formatter('manifest', opts)
4174 fm = ui.formatter('manifest', opts)
4168
4175
4169 if opts.get('all'):
4176 if opts.get('all'):
4170 if rev or node:
4177 if rev or node:
4171 raise util.Abort(_("can't specify a revision with --all"))
4178 raise util.Abort(_("can't specify a revision with --all"))
4172
4179
4173 res = []
4180 res = []
4174 prefix = "data/"
4181 prefix = "data/"
4175 suffix = ".i"
4182 suffix = ".i"
4176 plen = len(prefix)
4183 plen = len(prefix)
4177 slen = len(suffix)
4184 slen = len(suffix)
4178 lock = repo.lock()
4185 lock = repo.lock()
4179 try:
4186 try:
4180 for fn, b, size in repo.store.datafiles():
4187 for fn, b, size in repo.store.datafiles():
4181 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4188 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4182 res.append(fn[plen:-slen])
4189 res.append(fn[plen:-slen])
4183 finally:
4190 finally:
4184 lock.release()
4191 lock.release()
4185 for f in res:
4192 for f in res:
4186 fm.startitem()
4193 fm.startitem()
4187 fm.write("path", '%s\n', f)
4194 fm.write("path", '%s\n', f)
4188 fm.end()
4195 fm.end()
4189 return
4196 return
4190
4197
4191 if rev and node:
4198 if rev and node:
4192 raise util.Abort(_("please specify just one revision"))
4199 raise util.Abort(_("please specify just one revision"))
4193
4200
4194 if not node:
4201 if not node:
4195 node = rev
4202 node = rev
4196
4203
4197 char = {'l': '@', 'x': '*', '': ''}
4204 char = {'l': '@', 'x': '*', '': ''}
4198 mode = {'l': '644', 'x': '755', '': '644'}
4205 mode = {'l': '644', 'x': '755', '': '644'}
4199 ctx = scmutil.revsingle(repo, node)
4206 ctx = scmutil.revsingle(repo, node)
4200 mf = ctx.manifest()
4207 mf = ctx.manifest()
4201 for f in ctx:
4208 for f in ctx:
4202 fm.startitem()
4209 fm.startitem()
4203 fl = ctx[f].flags()
4210 fl = ctx[f].flags()
4204 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4211 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4205 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4212 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4206 fm.write('path', '%s\n', f)
4213 fm.write('path', '%s\n', f)
4207 fm.end()
4214 fm.end()
4208
4215
4209 @command('^merge',
4216 @command('^merge',
4210 [('f', 'force', None,
4217 [('f', 'force', None,
4211 _('force a merge including outstanding changes (DEPRECATED)')),
4218 _('force a merge including outstanding changes (DEPRECATED)')),
4212 ('r', 'rev', '', _('revision to merge'), _('REV')),
4219 ('r', 'rev', '', _('revision to merge'), _('REV')),
4213 ('P', 'preview', None,
4220 ('P', 'preview', None,
4214 _('review revisions to merge (no merge is performed)'))
4221 _('review revisions to merge (no merge is performed)'))
4215 ] + mergetoolopts,
4222 ] + mergetoolopts,
4216 _('[-P] [-f] [[-r] REV]'))
4223 _('[-P] [-f] [[-r] REV]'))
4217 def merge(ui, repo, node=None, **opts):
4224 def merge(ui, repo, node=None, **opts):
4218 """merge working directory with another revision
4225 """merge working directory with another revision
4219
4226
4220 The current working directory is updated with all changes made in
4227 The current working directory is updated with all changes made in
4221 the requested revision since the last common predecessor revision.
4228 the requested revision since the last common predecessor revision.
4222
4229
4223 Files that changed between either parent are marked as changed for
4230 Files that changed between either parent are marked as changed for
4224 the next commit and a commit must be performed before any further
4231 the next commit and a commit must be performed before any further
4225 updates to the repository are allowed. The next commit will have
4232 updates to the repository are allowed. The next commit will have
4226 two parents.
4233 two parents.
4227
4234
4228 ``--tool`` can be used to specify the merge tool used for file
4235 ``--tool`` can be used to specify the merge tool used for file
4229 merges. It overrides the HGMERGE environment variable and your
4236 merges. It overrides the HGMERGE environment variable and your
4230 configuration files. See :hg:`help merge-tools` for options.
4237 configuration files. See :hg:`help merge-tools` for options.
4231
4238
4232 If no revision is specified, the working directory's parent is a
4239 If no revision is specified, the working directory's parent is a
4233 head revision, and the current branch contains exactly one other
4240 head revision, and the current branch contains exactly one other
4234 head, the other head is merged with by default. Otherwise, an
4241 head, the other head is merged with by default. Otherwise, an
4235 explicit revision with which to merge with must be provided.
4242 explicit revision with which to merge with must be provided.
4236
4243
4237 :hg:`resolve` must be used to resolve unresolved files.
4244 :hg:`resolve` must be used to resolve unresolved files.
4238
4245
4239 To undo an uncommitted merge, use :hg:`update --clean .` which
4246 To undo an uncommitted merge, use :hg:`update --clean .` which
4240 will check out a clean copy of the original merge parent, losing
4247 will check out a clean copy of the original merge parent, losing
4241 all changes.
4248 all changes.
4242
4249
4243 Returns 0 on success, 1 if there are unresolved files.
4250 Returns 0 on success, 1 if there are unresolved files.
4244 """
4251 """
4245
4252
4246 if opts.get('rev') and node:
4253 if opts.get('rev') and node:
4247 raise util.Abort(_("please specify just one revision"))
4254 raise util.Abort(_("please specify just one revision"))
4248 if not node:
4255 if not node:
4249 node = opts.get('rev')
4256 node = opts.get('rev')
4250
4257
4251 if node:
4258 if node:
4252 node = scmutil.revsingle(repo, node).node()
4259 node = scmutil.revsingle(repo, node).node()
4253
4260
4254 if not node and repo._bookmarkcurrent:
4261 if not node and repo._bookmarkcurrent:
4255 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4262 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4256 curhead = repo[repo._bookmarkcurrent].node()
4263 curhead = repo[repo._bookmarkcurrent].node()
4257 if len(bmheads) == 2:
4264 if len(bmheads) == 2:
4258 if curhead == bmheads[0]:
4265 if curhead == bmheads[0]:
4259 node = bmheads[1]
4266 node = bmheads[1]
4260 else:
4267 else:
4261 node = bmheads[0]
4268 node = bmheads[0]
4262 elif len(bmheads) > 2:
4269 elif len(bmheads) > 2:
4263 raise util.Abort(_("multiple matching bookmarks to merge - "
4270 raise util.Abort(_("multiple matching bookmarks to merge - "
4264 "please merge with an explicit rev or bookmark"),
4271 "please merge with an explicit rev or bookmark"),
4265 hint=_("run 'hg heads' to see all heads"))
4272 hint=_("run 'hg heads' to see all heads"))
4266 elif len(bmheads) <= 1:
4273 elif len(bmheads) <= 1:
4267 raise util.Abort(_("no matching bookmark to merge - "
4274 raise util.Abort(_("no matching bookmark to merge - "
4268 "please merge with an explicit rev or bookmark"),
4275 "please merge with an explicit rev or bookmark"),
4269 hint=_("run 'hg heads' to see all heads"))
4276 hint=_("run 'hg heads' to see all heads"))
4270
4277
4271 if not node and not repo._bookmarkcurrent:
4278 if not node and not repo._bookmarkcurrent:
4272 branch = repo[None].branch()
4279 branch = repo[None].branch()
4273 bheads = repo.branchheads(branch)
4280 bheads = repo.branchheads(branch)
4274 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4281 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4275
4282
4276 if len(nbhs) > 2:
4283 if len(nbhs) > 2:
4277 raise util.Abort(_("branch '%s' has %d heads - "
4284 raise util.Abort(_("branch '%s' has %d heads - "
4278 "please merge with an explicit rev")
4285 "please merge with an explicit rev")
4279 % (branch, len(bheads)),
4286 % (branch, len(bheads)),
4280 hint=_("run 'hg heads .' to see heads"))
4287 hint=_("run 'hg heads .' to see heads"))
4281
4288
4282 parent = repo.dirstate.p1()
4289 parent = repo.dirstate.p1()
4283 if len(nbhs) <= 1:
4290 if len(nbhs) <= 1:
4284 if len(bheads) > 1:
4291 if len(bheads) > 1:
4285 raise util.Abort(_("heads are bookmarked - "
4292 raise util.Abort(_("heads are bookmarked - "
4286 "please merge with an explicit rev"),
4293 "please merge with an explicit rev"),
4287 hint=_("run 'hg heads' to see all heads"))
4294 hint=_("run 'hg heads' to see all heads"))
4288 if len(repo.heads()) > 1:
4295 if len(repo.heads()) > 1:
4289 raise util.Abort(_("branch '%s' has one head - "
4296 raise util.Abort(_("branch '%s' has one head - "
4290 "please merge with an explicit rev")
4297 "please merge with an explicit rev")
4291 % branch,
4298 % branch,
4292 hint=_("run 'hg heads' to see all heads"))
4299 hint=_("run 'hg heads' to see all heads"))
4293 msg, hint = _('nothing to merge'), None
4300 msg, hint = _('nothing to merge'), None
4294 if parent != repo.lookup(branch):
4301 if parent != repo.lookup(branch):
4295 hint = _("use 'hg update' instead")
4302 hint = _("use 'hg update' instead")
4296 raise util.Abort(msg, hint=hint)
4303 raise util.Abort(msg, hint=hint)
4297
4304
4298 if parent not in bheads:
4305 if parent not in bheads:
4299 raise util.Abort(_('working directory not at a head revision'),
4306 raise util.Abort(_('working directory not at a head revision'),
4300 hint=_("use 'hg update' or merge with an "
4307 hint=_("use 'hg update' or merge with an "
4301 "explicit revision"))
4308 "explicit revision"))
4302 if parent == nbhs[0]:
4309 if parent == nbhs[0]:
4303 node = nbhs[-1]
4310 node = nbhs[-1]
4304 else:
4311 else:
4305 node = nbhs[0]
4312 node = nbhs[0]
4306
4313
4307 if opts.get('preview'):
4314 if opts.get('preview'):
4308 # find nodes that are ancestors of p2 but not of p1
4315 # find nodes that are ancestors of p2 but not of p1
4309 p1 = repo.lookup('.')
4316 p1 = repo.lookup('.')
4310 p2 = repo.lookup(node)
4317 p2 = repo.lookup(node)
4311 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4318 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4312
4319
4313 displayer = cmdutil.show_changeset(ui, repo, opts)
4320 displayer = cmdutil.show_changeset(ui, repo, opts)
4314 for node in nodes:
4321 for node in nodes:
4315 displayer.show(repo[node])
4322 displayer.show(repo[node])
4316 displayer.close()
4323 displayer.close()
4317 return 0
4324 return 0
4318
4325
4319 try:
4326 try:
4320 # ui.forcemerge is an internal variable, do not document
4327 # ui.forcemerge is an internal variable, do not document
4321 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4328 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4322 return hg.merge(repo, node, force=opts.get('force'))
4329 return hg.merge(repo, node, force=opts.get('force'))
4323 finally:
4330 finally:
4324 ui.setconfig('ui', 'forcemerge', '')
4331 ui.setconfig('ui', 'forcemerge', '')
4325
4332
4326 @command('outgoing|out',
4333 @command('outgoing|out',
4327 [('f', 'force', None, _('run even when the destination is unrelated')),
4334 [('f', 'force', None, _('run even when the destination is unrelated')),
4328 ('r', 'rev', [],
4335 ('r', 'rev', [],
4329 _('a changeset intended to be included in the destination'), _('REV')),
4336 _('a changeset intended to be included in the destination'), _('REV')),
4330 ('n', 'newest-first', None, _('show newest record first')),
4337 ('n', 'newest-first', None, _('show newest record first')),
4331 ('B', 'bookmarks', False, _('compare bookmarks')),
4338 ('B', 'bookmarks', False, _('compare bookmarks')),
4332 ('b', 'branch', [], _('a specific branch you would like to push'),
4339 ('b', 'branch', [], _('a specific branch you would like to push'),
4333 _('BRANCH')),
4340 _('BRANCH')),
4334 ] + logopts + remoteopts + subrepoopts,
4341 ] + logopts + remoteopts + subrepoopts,
4335 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4342 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4336 def outgoing(ui, repo, dest=None, **opts):
4343 def outgoing(ui, repo, dest=None, **opts):
4337 """show changesets not found in the destination
4344 """show changesets not found in the destination
4338
4345
4339 Show changesets not found in the specified destination repository
4346 Show changesets not found in the specified destination repository
4340 or the default push location. These are the changesets that would
4347 or the default push location. These are the changesets that would
4341 be pushed if a push was requested.
4348 be pushed if a push was requested.
4342
4349
4343 See pull for details of valid destination formats.
4350 See pull for details of valid destination formats.
4344
4351
4345 Returns 0 if there are outgoing changes, 1 otherwise.
4352 Returns 0 if there are outgoing changes, 1 otherwise.
4346 """
4353 """
4347 if opts.get('graph'):
4354 if opts.get('graph'):
4348 cmdutil.checkunsupportedgraphflags([], opts)
4355 cmdutil.checkunsupportedgraphflags([], opts)
4349 o = hg._outgoing(ui, repo, dest, opts)
4356 o = hg._outgoing(ui, repo, dest, opts)
4350 if o is None:
4357 if o is None:
4351 return
4358 return
4352
4359
4353 revdag = cmdutil.graphrevs(repo, o, opts)
4360 revdag = cmdutil.graphrevs(repo, o, opts)
4354 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4361 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4355 showparents = [ctx.node() for ctx in repo[None].parents()]
4362 showparents = [ctx.node() for ctx in repo[None].parents()]
4356 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4363 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4357 graphmod.asciiedges)
4364 graphmod.asciiedges)
4358 return 0
4365 return 0
4359
4366
4360 if opts.get('bookmarks'):
4367 if opts.get('bookmarks'):
4361 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4368 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4362 dest, branches = hg.parseurl(dest, opts.get('branch'))
4369 dest, branches = hg.parseurl(dest, opts.get('branch'))
4363 other = hg.peer(repo, opts, dest)
4370 other = hg.peer(repo, opts, dest)
4364 if 'bookmarks' not in other.listkeys('namespaces'):
4371 if 'bookmarks' not in other.listkeys('namespaces'):
4365 ui.warn(_("remote doesn't support bookmarks\n"))
4372 ui.warn(_("remote doesn't support bookmarks\n"))
4366 return 0
4373 return 0
4367 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4374 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4368 return bookmarks.diff(ui, other, repo)
4375 return bookmarks.diff(ui, other, repo)
4369
4376
4370 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4377 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4371 try:
4378 try:
4372 return hg.outgoing(ui, repo, dest, opts)
4379 return hg.outgoing(ui, repo, dest, opts)
4373 finally:
4380 finally:
4374 del repo._subtoppath
4381 del repo._subtoppath
4375
4382
4376 @command('parents',
4383 @command('parents',
4377 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4384 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4378 ] + templateopts,
4385 ] + templateopts,
4379 _('[-r REV] [FILE]'))
4386 _('[-r REV] [FILE]'))
4380 def parents(ui, repo, file_=None, **opts):
4387 def parents(ui, repo, file_=None, **opts):
4381 """show the parents of the working directory or revision
4388 """show the parents of the working directory or revision
4382
4389
4383 Print the working directory's parent revisions. If a revision is
4390 Print the working directory's parent revisions. If a revision is
4384 given via -r/--rev, the parent of that revision will be printed.
4391 given via -r/--rev, the parent of that revision will be printed.
4385 If a file argument is given, the revision in which the file was
4392 If a file argument is given, the revision in which the file was
4386 last changed (before the working directory revision or the
4393 last changed (before the working directory revision or the
4387 argument to --rev if given) is printed.
4394 argument to --rev if given) is printed.
4388
4395
4389 Returns 0 on success.
4396 Returns 0 on success.
4390 """
4397 """
4391
4398
4392 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4399 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4393
4400
4394 if file_:
4401 if file_:
4395 m = scmutil.match(ctx, (file_,), opts)
4402 m = scmutil.match(ctx, (file_,), opts)
4396 if m.anypats() or len(m.files()) != 1:
4403 if m.anypats() or len(m.files()) != 1:
4397 raise util.Abort(_('can only specify an explicit filename'))
4404 raise util.Abort(_('can only specify an explicit filename'))
4398 file_ = m.files()[0]
4405 file_ = m.files()[0]
4399 filenodes = []
4406 filenodes = []
4400 for cp in ctx.parents():
4407 for cp in ctx.parents():
4401 if not cp:
4408 if not cp:
4402 continue
4409 continue
4403 try:
4410 try:
4404 filenodes.append(cp.filenode(file_))
4411 filenodes.append(cp.filenode(file_))
4405 except error.LookupError:
4412 except error.LookupError:
4406 pass
4413 pass
4407 if not filenodes:
4414 if not filenodes:
4408 raise util.Abort(_("'%s' not found in manifest!") % file_)
4415 raise util.Abort(_("'%s' not found in manifest!") % file_)
4409 p = []
4416 p = []
4410 for fn in filenodes:
4417 for fn in filenodes:
4411 fctx = repo.filectx(file_, fileid=fn)
4418 fctx = repo.filectx(file_, fileid=fn)
4412 p.append(fctx.node())
4419 p.append(fctx.node())
4413 else:
4420 else:
4414 p = [cp.node() for cp in ctx.parents()]
4421 p = [cp.node() for cp in ctx.parents()]
4415
4422
4416 displayer = cmdutil.show_changeset(ui, repo, opts)
4423 displayer = cmdutil.show_changeset(ui, repo, opts)
4417 for n in p:
4424 for n in p:
4418 if n != nullid:
4425 if n != nullid:
4419 displayer.show(repo[n])
4426 displayer.show(repo[n])
4420 displayer.close()
4427 displayer.close()
4421
4428
4422 @command('paths', [], _('[NAME]'))
4429 @command('paths', [], _('[NAME]'))
4423 def paths(ui, repo, search=None):
4430 def paths(ui, repo, search=None):
4424 """show aliases for remote repositories
4431 """show aliases for remote repositories
4425
4432
4426 Show definition of symbolic path name NAME. If no name is given,
4433 Show definition of symbolic path name NAME. If no name is given,
4427 show definition of all available names.
4434 show definition of all available names.
4428
4435
4429 Option -q/--quiet suppresses all output when searching for NAME
4436 Option -q/--quiet suppresses all output when searching for NAME
4430 and shows only the path names when listing all definitions.
4437 and shows only the path names when listing all definitions.
4431
4438
4432 Path names are defined in the [paths] section of your
4439 Path names are defined in the [paths] section of your
4433 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4440 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4434 repository, ``.hg/hgrc`` is used, too.
4441 repository, ``.hg/hgrc`` is used, too.
4435
4442
4436 The path names ``default`` and ``default-push`` have a special
4443 The path names ``default`` and ``default-push`` have a special
4437 meaning. When performing a push or pull operation, they are used
4444 meaning. When performing a push or pull operation, they are used
4438 as fallbacks if no location is specified on the command-line.
4445 as fallbacks if no location is specified on the command-line.
4439 When ``default-push`` is set, it will be used for push and
4446 When ``default-push`` is set, it will be used for push and
4440 ``default`` will be used for pull; otherwise ``default`` is used
4447 ``default`` will be used for pull; otherwise ``default`` is used
4441 as the fallback for both. When cloning a repository, the clone
4448 as the fallback for both. When cloning a repository, the clone
4442 source is written as ``default`` in ``.hg/hgrc``. Note that
4449 source is written as ``default`` in ``.hg/hgrc``. Note that
4443 ``default`` and ``default-push`` apply to all inbound (e.g.
4450 ``default`` and ``default-push`` apply to all inbound (e.g.
4444 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4451 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4445 :hg:`bundle`) operations.
4452 :hg:`bundle`) operations.
4446
4453
4447 See :hg:`help urls` for more information.
4454 See :hg:`help urls` for more information.
4448
4455
4449 Returns 0 on success.
4456 Returns 0 on success.
4450 """
4457 """
4451 if search:
4458 if search:
4452 for name, path in ui.configitems("paths"):
4459 for name, path in ui.configitems("paths"):
4453 if name == search:
4460 if name == search:
4454 ui.status("%s\n" % util.hidepassword(path))
4461 ui.status("%s\n" % util.hidepassword(path))
4455 return
4462 return
4456 if not ui.quiet:
4463 if not ui.quiet:
4457 ui.warn(_("not found!\n"))
4464 ui.warn(_("not found!\n"))
4458 return 1
4465 return 1
4459 else:
4466 else:
4460 for name, path in ui.configitems("paths"):
4467 for name, path in ui.configitems("paths"):
4461 if ui.quiet:
4468 if ui.quiet:
4462 ui.write("%s\n" % name)
4469 ui.write("%s\n" % name)
4463 else:
4470 else:
4464 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4471 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4465
4472
4466 @command('phase',
4473 @command('phase',
4467 [('p', 'public', False, _('set changeset phase to public')),
4474 [('p', 'public', False, _('set changeset phase to public')),
4468 ('d', 'draft', False, _('set changeset phase to draft')),
4475 ('d', 'draft', False, _('set changeset phase to draft')),
4469 ('s', 'secret', False, _('set changeset phase to secret')),
4476 ('s', 'secret', False, _('set changeset phase to secret')),
4470 ('f', 'force', False, _('allow to move boundary backward')),
4477 ('f', 'force', False, _('allow to move boundary backward')),
4471 ('r', 'rev', [], _('target revision'), _('REV')),
4478 ('r', 'rev', [], _('target revision'), _('REV')),
4472 ],
4479 ],
4473 _('[-p|-d|-s] [-f] [-r] REV...'))
4480 _('[-p|-d|-s] [-f] [-r] REV...'))
4474 def phase(ui, repo, *revs, **opts):
4481 def phase(ui, repo, *revs, **opts):
4475 """set or show the current phase name
4482 """set or show the current phase name
4476
4483
4477 With no argument, show the phase name of specified revisions.
4484 With no argument, show the phase name of specified revisions.
4478
4485
4479 With one of -p/--public, -d/--draft or -s/--secret, change the
4486 With one of -p/--public, -d/--draft or -s/--secret, change the
4480 phase value of the specified revisions.
4487 phase value of the specified revisions.
4481
4488
4482 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4489 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4483 lower phase to an higher phase. Phases are ordered as follows::
4490 lower phase to an higher phase. Phases are ordered as follows::
4484
4491
4485 public < draft < secret
4492 public < draft < secret
4486
4493
4487 Returns 0 on success, 1 if no phases were changed or some could not
4494 Returns 0 on success, 1 if no phases were changed or some could not
4488 be changed.
4495 be changed.
4489 """
4496 """
4490 # search for a unique phase argument
4497 # search for a unique phase argument
4491 targetphase = None
4498 targetphase = None
4492 for idx, name in enumerate(phases.phasenames):
4499 for idx, name in enumerate(phases.phasenames):
4493 if opts[name]:
4500 if opts[name]:
4494 if targetphase is not None:
4501 if targetphase is not None:
4495 raise util.Abort(_('only one phase can be specified'))
4502 raise util.Abort(_('only one phase can be specified'))
4496 targetphase = idx
4503 targetphase = idx
4497
4504
4498 # look for specified revision
4505 # look for specified revision
4499 revs = list(revs)
4506 revs = list(revs)
4500 revs.extend(opts['rev'])
4507 revs.extend(opts['rev'])
4501 if not revs:
4508 if not revs:
4502 raise util.Abort(_('no revisions specified'))
4509 raise util.Abort(_('no revisions specified'))
4503
4510
4504 revs = scmutil.revrange(repo, revs)
4511 revs = scmutil.revrange(repo, revs)
4505
4512
4506 lock = None
4513 lock = None
4507 ret = 0
4514 ret = 0
4508 if targetphase is None:
4515 if targetphase is None:
4509 # display
4516 # display
4510 for r in revs:
4517 for r in revs:
4511 ctx = repo[r]
4518 ctx = repo[r]
4512 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4519 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4513 else:
4520 else:
4514 lock = repo.lock()
4521 lock = repo.lock()
4515 try:
4522 try:
4516 # set phase
4523 # set phase
4517 if not revs:
4524 if not revs:
4518 raise util.Abort(_('empty revision set'))
4525 raise util.Abort(_('empty revision set'))
4519 nodes = [repo[r].node() for r in revs]
4526 nodes = [repo[r].node() for r in revs]
4520 olddata = repo._phasecache.getphaserevs(repo)[:]
4527 olddata = repo._phasecache.getphaserevs(repo)[:]
4521 phases.advanceboundary(repo, targetphase, nodes)
4528 phases.advanceboundary(repo, targetphase, nodes)
4522 if opts['force']:
4529 if opts['force']:
4523 phases.retractboundary(repo, targetphase, nodes)
4530 phases.retractboundary(repo, targetphase, nodes)
4524 finally:
4531 finally:
4525 lock.release()
4532 lock.release()
4526 # moving revision from public to draft may hide them
4533 # moving revision from public to draft may hide them
4527 # We have to check result on an unfiltered repository
4534 # We have to check result on an unfiltered repository
4528 unfi = repo.unfiltered()
4535 unfi = repo.unfiltered()
4529 newdata = repo._phasecache.getphaserevs(unfi)
4536 newdata = repo._phasecache.getphaserevs(unfi)
4530 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4537 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4531 cl = unfi.changelog
4538 cl = unfi.changelog
4532 rejected = [n for n in nodes
4539 rejected = [n for n in nodes
4533 if newdata[cl.rev(n)] < targetphase]
4540 if newdata[cl.rev(n)] < targetphase]
4534 if rejected:
4541 if rejected:
4535 ui.warn(_('cannot move %i changesets to a higher '
4542 ui.warn(_('cannot move %i changesets to a higher '
4536 'phase, use --force\n') % len(rejected))
4543 'phase, use --force\n') % len(rejected))
4537 ret = 1
4544 ret = 1
4538 if changes:
4545 if changes:
4539 msg = _('phase changed for %i changesets\n') % changes
4546 msg = _('phase changed for %i changesets\n') % changes
4540 if ret:
4547 if ret:
4541 ui.status(msg)
4548 ui.status(msg)
4542 else:
4549 else:
4543 ui.note(msg)
4550 ui.note(msg)
4544 else:
4551 else:
4545 ui.warn(_('no phases changed\n'))
4552 ui.warn(_('no phases changed\n'))
4546 ret = 1
4553 ret = 1
4547 return ret
4554 return ret
4548
4555
4549 def postincoming(ui, repo, modheads, optupdate, checkout):
4556 def postincoming(ui, repo, modheads, optupdate, checkout):
4550 if modheads == 0:
4557 if modheads == 0:
4551 return
4558 return
4552 if optupdate:
4559 if optupdate:
4553 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4560 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4554 try:
4561 try:
4555 ret = hg.update(repo, checkout)
4562 ret = hg.update(repo, checkout)
4556 except util.Abort, inst:
4563 except util.Abort, inst:
4557 ui.warn(_("not updating: %s\n") % str(inst))
4564 ui.warn(_("not updating: %s\n") % str(inst))
4558 if inst.hint:
4565 if inst.hint:
4559 ui.warn(_("(%s)\n") % inst.hint)
4566 ui.warn(_("(%s)\n") % inst.hint)
4560 return 0
4567 return 0
4561 if not ret and not checkout:
4568 if not ret and not checkout:
4562 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4569 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4563 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4570 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4564 return ret
4571 return ret
4565 if modheads > 1:
4572 if modheads > 1:
4566 currentbranchheads = len(repo.branchheads())
4573 currentbranchheads = len(repo.branchheads())
4567 if currentbranchheads == modheads:
4574 if currentbranchheads == modheads:
4568 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4575 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4569 elif currentbranchheads > 1:
4576 elif currentbranchheads > 1:
4570 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4577 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4571 "merge)\n"))
4578 "merge)\n"))
4572 else:
4579 else:
4573 ui.status(_("(run 'hg heads' to see heads)\n"))
4580 ui.status(_("(run 'hg heads' to see heads)\n"))
4574 else:
4581 else:
4575 ui.status(_("(run 'hg update' to get a working copy)\n"))
4582 ui.status(_("(run 'hg update' to get a working copy)\n"))
4576
4583
4577 @command('^pull',
4584 @command('^pull',
4578 [('u', 'update', None,
4585 [('u', 'update', None,
4579 _('update to new branch head if changesets were pulled')),
4586 _('update to new branch head if changesets were pulled')),
4580 ('f', 'force', None, _('run even when remote repository is unrelated')),
4587 ('f', 'force', None, _('run even when remote repository is unrelated')),
4581 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4588 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4582 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4589 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4583 ('b', 'branch', [], _('a specific branch you would like to pull'),
4590 ('b', 'branch', [], _('a specific branch you would like to pull'),
4584 _('BRANCH')),
4591 _('BRANCH')),
4585 ] + remoteopts,
4592 ] + remoteopts,
4586 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4593 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4587 def pull(ui, repo, source="default", **opts):
4594 def pull(ui, repo, source="default", **opts):
4588 """pull changes from the specified source
4595 """pull changes from the specified source
4589
4596
4590 Pull changes from a remote repository to a local one.
4597 Pull changes from a remote repository to a local one.
4591
4598
4592 This finds all changes from the repository at the specified path
4599 This finds all changes from the repository at the specified path
4593 or URL and adds them to a local repository (the current one unless
4600 or URL and adds them to a local repository (the current one unless
4594 -R is specified). By default, this does not update the copy of the
4601 -R is specified). By default, this does not update the copy of the
4595 project in the working directory.
4602 project in the working directory.
4596
4603
4597 Use :hg:`incoming` if you want to see what would have been added
4604 Use :hg:`incoming` if you want to see what would have been added
4598 by a pull at the time you issued this command. If you then decide
4605 by a pull at the time you issued this command. If you then decide
4599 to add those changes to the repository, you should use :hg:`pull
4606 to add those changes to the repository, you should use :hg:`pull
4600 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4607 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4601
4608
4602 If SOURCE is omitted, the 'default' path will be used.
4609 If SOURCE is omitted, the 'default' path will be used.
4603 See :hg:`help urls` for more information.
4610 See :hg:`help urls` for more information.
4604
4611
4605 Returns 0 on success, 1 if an update had unresolved files.
4612 Returns 0 on success, 1 if an update had unresolved files.
4606 """
4613 """
4607 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4614 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4608 other = hg.peer(repo, opts, source)
4615 other = hg.peer(repo, opts, source)
4609 try:
4616 try:
4610 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4617 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4611 revs, checkout = hg.addbranchrevs(repo, other, branches,
4618 revs, checkout = hg.addbranchrevs(repo, other, branches,
4612 opts.get('rev'))
4619 opts.get('rev'))
4613
4620
4614 remotebookmarks = other.listkeys('bookmarks')
4621 remotebookmarks = other.listkeys('bookmarks')
4615
4622
4616 if opts.get('bookmark'):
4623 if opts.get('bookmark'):
4617 if not revs:
4624 if not revs:
4618 revs = []
4625 revs = []
4619 for b in opts['bookmark']:
4626 for b in opts['bookmark']:
4620 if b not in remotebookmarks:
4627 if b not in remotebookmarks:
4621 raise util.Abort(_('remote bookmark %s not found!') % b)
4628 raise util.Abort(_('remote bookmark %s not found!') % b)
4622 revs.append(remotebookmarks[b])
4629 revs.append(remotebookmarks[b])
4623
4630
4624 if revs:
4631 if revs:
4625 try:
4632 try:
4626 revs = [other.lookup(rev) for rev in revs]
4633 revs = [other.lookup(rev) for rev in revs]
4627 except error.CapabilityError:
4634 except error.CapabilityError:
4628 err = _("other repository doesn't support revision lookup, "
4635 err = _("other repository doesn't support revision lookup, "
4629 "so a rev cannot be specified.")
4636 "so a rev cannot be specified.")
4630 raise util.Abort(err)
4637 raise util.Abort(err)
4631
4638
4632 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4639 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4633 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4640 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4634 if checkout:
4641 if checkout:
4635 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4642 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4636 repo._subtoppath = source
4643 repo._subtoppath = source
4637 try:
4644 try:
4638 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4645 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4639
4646
4640 finally:
4647 finally:
4641 del repo._subtoppath
4648 del repo._subtoppath
4642
4649
4643 # update specified bookmarks
4650 # update specified bookmarks
4644 if opts.get('bookmark'):
4651 if opts.get('bookmark'):
4645 marks = repo._bookmarks
4652 marks = repo._bookmarks
4646 for b in opts['bookmark']:
4653 for b in opts['bookmark']:
4647 # explicit pull overrides local bookmark if any
4654 # explicit pull overrides local bookmark if any
4648 ui.status(_("importing bookmark %s\n") % b)
4655 ui.status(_("importing bookmark %s\n") % b)
4649 marks[b] = repo[remotebookmarks[b]].node()
4656 marks[b] = repo[remotebookmarks[b]].node()
4650 marks.write()
4657 marks.write()
4651 finally:
4658 finally:
4652 other.close()
4659 other.close()
4653 return ret
4660 return ret
4654
4661
4655 @command('^push',
4662 @command('^push',
4656 [('f', 'force', None, _('force push')),
4663 [('f', 'force', None, _('force push')),
4657 ('r', 'rev', [],
4664 ('r', 'rev', [],
4658 _('a changeset intended to be included in the destination'),
4665 _('a changeset intended to be included in the destination'),
4659 _('REV')),
4666 _('REV')),
4660 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4667 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4661 ('b', 'branch', [],
4668 ('b', 'branch', [],
4662 _('a specific branch you would like to push'), _('BRANCH')),
4669 _('a specific branch you would like to push'), _('BRANCH')),
4663 ('', 'new-branch', False, _('allow pushing a new branch')),
4670 ('', 'new-branch', False, _('allow pushing a new branch')),
4664 ] + remoteopts,
4671 ] + remoteopts,
4665 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4672 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4666 def push(ui, repo, dest=None, **opts):
4673 def push(ui, repo, dest=None, **opts):
4667 """push changes to the specified destination
4674 """push changes to the specified destination
4668
4675
4669 Push changesets from the local repository to the specified
4676 Push changesets from the local repository to the specified
4670 destination.
4677 destination.
4671
4678
4672 This operation is symmetrical to pull: it is identical to a pull
4679 This operation is symmetrical to pull: it is identical to a pull
4673 in the destination repository from the current one.
4680 in the destination repository from the current one.
4674
4681
4675 By default, push will not allow creation of new heads at the
4682 By default, push will not allow creation of new heads at the
4676 destination, since multiple heads would make it unclear which head
4683 destination, since multiple heads would make it unclear which head
4677 to use. In this situation, it is recommended to pull and merge
4684 to use. In this situation, it is recommended to pull and merge
4678 before pushing.
4685 before pushing.
4679
4686
4680 Use --new-branch if you want to allow push to create a new named
4687 Use --new-branch if you want to allow push to create a new named
4681 branch that is not present at the destination. This allows you to
4688 branch that is not present at the destination. This allows you to
4682 only create a new branch without forcing other changes.
4689 only create a new branch without forcing other changes.
4683
4690
4684 .. note::
4691 .. note::
4685
4692
4686 Extra care should be taken with the -f/--force option,
4693 Extra care should be taken with the -f/--force option,
4687 which will push all new heads on all branches, an action which will
4694 which will push all new heads on all branches, an action which will
4688 almost always cause confusion for collaborators.
4695 almost always cause confusion for collaborators.
4689
4696
4690 If -r/--rev is used, the specified revision and all its ancestors
4697 If -r/--rev is used, the specified revision and all its ancestors
4691 will be pushed to the remote repository.
4698 will be pushed to the remote repository.
4692
4699
4693 If -B/--bookmark is used, the specified bookmarked revision, its
4700 If -B/--bookmark is used, the specified bookmarked revision, its
4694 ancestors, and the bookmark will be pushed to the remote
4701 ancestors, and the bookmark will be pushed to the remote
4695 repository.
4702 repository.
4696
4703
4697 Please see :hg:`help urls` for important details about ``ssh://``
4704 Please see :hg:`help urls` for important details about ``ssh://``
4698 URLs. If DESTINATION is omitted, a default path will be used.
4705 URLs. If DESTINATION is omitted, a default path will be used.
4699
4706
4700 Returns 0 if push was successful, 1 if nothing to push.
4707 Returns 0 if push was successful, 1 if nothing to push.
4701 """
4708 """
4702
4709
4703 if opts.get('bookmark'):
4710 if opts.get('bookmark'):
4704 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4711 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4705 for b in opts['bookmark']:
4712 for b in opts['bookmark']:
4706 # translate -B options to -r so changesets get pushed
4713 # translate -B options to -r so changesets get pushed
4707 if b in repo._bookmarks:
4714 if b in repo._bookmarks:
4708 opts.setdefault('rev', []).append(b)
4715 opts.setdefault('rev', []).append(b)
4709 else:
4716 else:
4710 # if we try to push a deleted bookmark, translate it to null
4717 # if we try to push a deleted bookmark, translate it to null
4711 # this lets simultaneous -r, -b options continue working
4718 # this lets simultaneous -r, -b options continue working
4712 opts.setdefault('rev', []).append("null")
4719 opts.setdefault('rev', []).append("null")
4713
4720
4714 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4721 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4715 dest, branches = hg.parseurl(dest, opts.get('branch'))
4722 dest, branches = hg.parseurl(dest, opts.get('branch'))
4716 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4723 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4717 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4724 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4718 try:
4725 try:
4719 other = hg.peer(repo, opts, dest)
4726 other = hg.peer(repo, opts, dest)
4720 except error.RepoError:
4727 except error.RepoError:
4721 if dest == "default-push":
4728 if dest == "default-push":
4722 raise util.Abort(_("default repository not configured!"),
4729 raise util.Abort(_("default repository not configured!"),
4723 hint=_('see the "path" section in "hg help config"'))
4730 hint=_('see the "path" section in "hg help config"'))
4724 else:
4731 else:
4725 raise
4732 raise
4726
4733
4727 if revs:
4734 if revs:
4728 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4735 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4729
4736
4730 repo._subtoppath = dest
4737 repo._subtoppath = dest
4731 try:
4738 try:
4732 # push subrepos depth-first for coherent ordering
4739 # push subrepos depth-first for coherent ordering
4733 c = repo['']
4740 c = repo['']
4734 subs = c.substate # only repos that are committed
4741 subs = c.substate # only repos that are committed
4735 for s in sorted(subs):
4742 for s in sorted(subs):
4736 if c.sub(s).push(opts) == 0:
4743 if c.sub(s).push(opts) == 0:
4737 return False
4744 return False
4738 finally:
4745 finally:
4739 del repo._subtoppath
4746 del repo._subtoppath
4740 result = repo.push(other, opts.get('force'), revs=revs,
4747 result = repo.push(other, opts.get('force'), revs=revs,
4741 newbranch=opts.get('new_branch'))
4748 newbranch=opts.get('new_branch'))
4742
4749
4743 result = not result
4750 result = not result
4744
4751
4745 if opts.get('bookmark'):
4752 if opts.get('bookmark'):
4746 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4753 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4747 if bresult == 2:
4754 if bresult == 2:
4748 return 2
4755 return 2
4749 if not result and bresult:
4756 if not result and bresult:
4750 result = 2
4757 result = 2
4751
4758
4752 return result
4759 return result
4753
4760
4754 @command('recover', [])
4761 @command('recover', [])
4755 def recover(ui, repo):
4762 def recover(ui, repo):
4756 """roll back an interrupted transaction
4763 """roll back an interrupted transaction
4757
4764
4758 Recover from an interrupted commit or pull.
4765 Recover from an interrupted commit or pull.
4759
4766
4760 This command tries to fix the repository status after an
4767 This command tries to fix the repository status after an
4761 interrupted operation. It should only be necessary when Mercurial
4768 interrupted operation. It should only be necessary when Mercurial
4762 suggests it.
4769 suggests it.
4763
4770
4764 Returns 0 if successful, 1 if nothing to recover or verify fails.
4771 Returns 0 if successful, 1 if nothing to recover or verify fails.
4765 """
4772 """
4766 if repo.recover():
4773 if repo.recover():
4767 return hg.verify(repo)
4774 return hg.verify(repo)
4768 return 1
4775 return 1
4769
4776
4770 @command('^remove|rm',
4777 @command('^remove|rm',
4771 [('A', 'after', None, _('record delete for missing files')),
4778 [('A', 'after', None, _('record delete for missing files')),
4772 ('f', 'force', None,
4779 ('f', 'force', None,
4773 _('remove (and delete) file even if added or modified')),
4780 _('remove (and delete) file even if added or modified')),
4774 ] + walkopts,
4781 ] + walkopts,
4775 _('[OPTION]... FILE...'))
4782 _('[OPTION]... FILE...'))
4776 def remove(ui, repo, *pats, **opts):
4783 def remove(ui, repo, *pats, **opts):
4777 """remove the specified files on the next commit
4784 """remove the specified files on the next commit
4778
4785
4779 Schedule the indicated files for removal from the current branch.
4786 Schedule the indicated files for removal from the current branch.
4780
4787
4781 This command schedules the files to be removed at the next commit.
4788 This command schedules the files to be removed at the next commit.
4782 To undo a remove before that, see :hg:`revert`. To undo added
4789 To undo a remove before that, see :hg:`revert`. To undo added
4783 files, see :hg:`forget`.
4790 files, see :hg:`forget`.
4784
4791
4785 .. container:: verbose
4792 .. container:: verbose
4786
4793
4787 -A/--after can be used to remove only files that have already
4794 -A/--after can be used to remove only files that have already
4788 been deleted, -f/--force can be used to force deletion, and -Af
4795 been deleted, -f/--force can be used to force deletion, and -Af
4789 can be used to remove files from the next revision without
4796 can be used to remove files from the next revision without
4790 deleting them from the working directory.
4797 deleting them from the working directory.
4791
4798
4792 The following table details the behavior of remove for different
4799 The following table details the behavior of remove for different
4793 file states (columns) and option combinations (rows). The file
4800 file states (columns) and option combinations (rows). The file
4794 states are Added [A], Clean [C], Modified [M] and Missing [!]
4801 states are Added [A], Clean [C], Modified [M] and Missing [!]
4795 (as reported by :hg:`status`). The actions are Warn, Remove
4802 (as reported by :hg:`status`). The actions are Warn, Remove
4796 (from branch) and Delete (from disk):
4803 (from branch) and Delete (from disk):
4797
4804
4798 ========= == == == ==
4805 ========= == == == ==
4799 opt/state A C M !
4806 opt/state A C M !
4800 ========= == == == ==
4807 ========= == == == ==
4801 none W RD W R
4808 none W RD W R
4802 -f R RD RD R
4809 -f R RD RD R
4803 -A W W W R
4810 -A W W W R
4804 -Af R R R R
4811 -Af R R R R
4805 ========= == == == ==
4812 ========= == == == ==
4806
4813
4807 Note that remove never deletes files in Added [A] state from the
4814 Note that remove never deletes files in Added [A] state from the
4808 working directory, not even if option --force is specified.
4815 working directory, not even if option --force is specified.
4809
4816
4810 Returns 0 on success, 1 if any warnings encountered.
4817 Returns 0 on success, 1 if any warnings encountered.
4811 """
4818 """
4812
4819
4813 ret = 0
4820 ret = 0
4814 after, force = opts.get('after'), opts.get('force')
4821 after, force = opts.get('after'), opts.get('force')
4815 if not pats and not after:
4822 if not pats and not after:
4816 raise util.Abort(_('no files specified'))
4823 raise util.Abort(_('no files specified'))
4817
4824
4818 m = scmutil.match(repo[None], pats, opts)
4825 m = scmutil.match(repo[None], pats, opts)
4819 s = repo.status(match=m, clean=True)
4826 s = repo.status(match=m, clean=True)
4820 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4827 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4821
4828
4822 # warn about failure to delete explicit files/dirs
4829 # warn about failure to delete explicit files/dirs
4823 wctx = repo[None]
4830 wctx = repo[None]
4824 for f in m.files():
4831 for f in m.files():
4825 if f in repo.dirstate or f in wctx.dirs():
4832 if f in repo.dirstate or f in wctx.dirs():
4826 continue
4833 continue
4827 if os.path.exists(m.rel(f)):
4834 if os.path.exists(m.rel(f)):
4828 if os.path.isdir(m.rel(f)):
4835 if os.path.isdir(m.rel(f)):
4829 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4836 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4830 else:
4837 else:
4831 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4838 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4832 # missing files will generate a warning elsewhere
4839 # missing files will generate a warning elsewhere
4833 ret = 1
4840 ret = 1
4834
4841
4835 if force:
4842 if force:
4836 list = modified + deleted + clean + added
4843 list = modified + deleted + clean + added
4837 elif after:
4844 elif after:
4838 list = deleted
4845 list = deleted
4839 for f in modified + added + clean:
4846 for f in modified + added + clean:
4840 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4847 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4841 ret = 1
4848 ret = 1
4842 else:
4849 else:
4843 list = deleted + clean
4850 list = deleted + clean
4844 for f in modified:
4851 for f in modified:
4845 ui.warn(_('not removing %s: file is modified (use -f'
4852 ui.warn(_('not removing %s: file is modified (use -f'
4846 ' to force removal)\n') % m.rel(f))
4853 ' to force removal)\n') % m.rel(f))
4847 ret = 1
4854 ret = 1
4848 for f in added:
4855 for f in added:
4849 ui.warn(_('not removing %s: file has been marked for add'
4856 ui.warn(_('not removing %s: file has been marked for add'
4850 ' (use forget to undo)\n') % m.rel(f))
4857 ' (use forget to undo)\n') % m.rel(f))
4851 ret = 1
4858 ret = 1
4852
4859
4853 for f in sorted(list):
4860 for f in sorted(list):
4854 if ui.verbose or not m.exact(f):
4861 if ui.verbose or not m.exact(f):
4855 ui.status(_('removing %s\n') % m.rel(f))
4862 ui.status(_('removing %s\n') % m.rel(f))
4856
4863
4857 wlock = repo.wlock()
4864 wlock = repo.wlock()
4858 try:
4865 try:
4859 if not after:
4866 if not after:
4860 for f in list:
4867 for f in list:
4861 if f in added:
4868 if f in added:
4862 continue # we never unlink added files on remove
4869 continue # we never unlink added files on remove
4863 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4870 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4864 repo[None].forget(list)
4871 repo[None].forget(list)
4865 finally:
4872 finally:
4866 wlock.release()
4873 wlock.release()
4867
4874
4868 return ret
4875 return ret
4869
4876
4870 @command('rename|move|mv',
4877 @command('rename|move|mv',
4871 [('A', 'after', None, _('record a rename that has already occurred')),
4878 [('A', 'after', None, _('record a rename that has already occurred')),
4872 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4879 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4873 ] + walkopts + dryrunopts,
4880 ] + walkopts + dryrunopts,
4874 _('[OPTION]... SOURCE... DEST'))
4881 _('[OPTION]... SOURCE... DEST'))
4875 def rename(ui, repo, *pats, **opts):
4882 def rename(ui, repo, *pats, **opts):
4876 """rename files; equivalent of copy + remove
4883 """rename files; equivalent of copy + remove
4877
4884
4878 Mark dest as copies of sources; mark sources for deletion. If dest
4885 Mark dest as copies of sources; mark sources for deletion. If dest
4879 is a directory, copies are put in that directory. If dest is a
4886 is a directory, copies are put in that directory. If dest is a
4880 file, there can only be one source.
4887 file, there can only be one source.
4881
4888
4882 By default, this command copies the contents of files as they
4889 By default, this command copies the contents of files as they
4883 exist in the working directory. If invoked with -A/--after, the
4890 exist in the working directory. If invoked with -A/--after, the
4884 operation is recorded, but no copying is performed.
4891 operation is recorded, but no copying is performed.
4885
4892
4886 This command takes effect at the next commit. To undo a rename
4893 This command takes effect at the next commit. To undo a rename
4887 before that, see :hg:`revert`.
4894 before that, see :hg:`revert`.
4888
4895
4889 Returns 0 on success, 1 if errors are encountered.
4896 Returns 0 on success, 1 if errors are encountered.
4890 """
4897 """
4891 wlock = repo.wlock(False)
4898 wlock = repo.wlock(False)
4892 try:
4899 try:
4893 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4900 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4894 finally:
4901 finally:
4895 wlock.release()
4902 wlock.release()
4896
4903
4897 @command('resolve',
4904 @command('resolve',
4898 [('a', 'all', None, _('select all unresolved files')),
4905 [('a', 'all', None, _('select all unresolved files')),
4899 ('l', 'list', None, _('list state of files needing merge')),
4906 ('l', 'list', None, _('list state of files needing merge')),
4900 ('m', 'mark', None, _('mark files as resolved')),
4907 ('m', 'mark', None, _('mark files as resolved')),
4901 ('u', 'unmark', None, _('mark files as unresolved')),
4908 ('u', 'unmark', None, _('mark files as unresolved')),
4902 ('n', 'no-status', None, _('hide status prefix'))]
4909 ('n', 'no-status', None, _('hide status prefix'))]
4903 + mergetoolopts + walkopts,
4910 + mergetoolopts + walkopts,
4904 _('[OPTION]... [FILE]...'))
4911 _('[OPTION]... [FILE]...'))
4905 def resolve(ui, repo, *pats, **opts):
4912 def resolve(ui, repo, *pats, **opts):
4906 """redo merges or set/view the merge status of files
4913 """redo merges or set/view the merge status of files
4907
4914
4908 Merges with unresolved conflicts are often the result of
4915 Merges with unresolved conflicts are often the result of
4909 non-interactive merging using the ``internal:merge`` configuration
4916 non-interactive merging using the ``internal:merge`` configuration
4910 setting, or a command-line merge tool like ``diff3``. The resolve
4917 setting, or a command-line merge tool like ``diff3``. The resolve
4911 command is used to manage the files involved in a merge, after
4918 command is used to manage the files involved in a merge, after
4912 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4919 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4913 working directory must have two parents). See :hg:`help
4920 working directory must have two parents). See :hg:`help
4914 merge-tools` for information on configuring merge tools.
4921 merge-tools` for information on configuring merge tools.
4915
4922
4916 The resolve command can be used in the following ways:
4923 The resolve command can be used in the following ways:
4917
4924
4918 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4925 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4919 files, discarding any previous merge attempts. Re-merging is not
4926 files, discarding any previous merge attempts. Re-merging is not
4920 performed for files already marked as resolved. Use ``--all/-a``
4927 performed for files already marked as resolved. Use ``--all/-a``
4921 to select all unresolved files. ``--tool`` can be used to specify
4928 to select all unresolved files. ``--tool`` can be used to specify
4922 the merge tool used for the given files. It overrides the HGMERGE
4929 the merge tool used for the given files. It overrides the HGMERGE
4923 environment variable and your configuration files. Previous file
4930 environment variable and your configuration files. Previous file
4924 contents are saved with a ``.orig`` suffix.
4931 contents are saved with a ``.orig`` suffix.
4925
4932
4926 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4933 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4927 (e.g. after having manually fixed-up the files). The default is
4934 (e.g. after having manually fixed-up the files). The default is
4928 to mark all unresolved files.
4935 to mark all unresolved files.
4929
4936
4930 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4937 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4931 default is to mark all resolved files.
4938 default is to mark all resolved files.
4932
4939
4933 - :hg:`resolve -l`: list files which had or still have conflicts.
4940 - :hg:`resolve -l`: list files which had or still have conflicts.
4934 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4941 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4935
4942
4936 Note that Mercurial will not let you commit files with unresolved
4943 Note that Mercurial will not let you commit files with unresolved
4937 merge conflicts. You must use :hg:`resolve -m ...` before you can
4944 merge conflicts. You must use :hg:`resolve -m ...` before you can
4938 commit after a conflicting merge.
4945 commit after a conflicting merge.
4939
4946
4940 Returns 0 on success, 1 if any files fail a resolve attempt.
4947 Returns 0 on success, 1 if any files fail a resolve attempt.
4941 """
4948 """
4942
4949
4943 all, mark, unmark, show, nostatus = \
4950 all, mark, unmark, show, nostatus = \
4944 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4951 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4945
4952
4946 if (show and (mark or unmark)) or (mark and unmark):
4953 if (show and (mark or unmark)) or (mark and unmark):
4947 raise util.Abort(_("too many options specified"))
4954 raise util.Abort(_("too many options specified"))
4948 if pats and all:
4955 if pats and all:
4949 raise util.Abort(_("can't specify --all and patterns"))
4956 raise util.Abort(_("can't specify --all and patterns"))
4950 if not (all or pats or show or mark or unmark):
4957 if not (all or pats or show or mark or unmark):
4951 raise util.Abort(_('no files or directories specified; '
4958 raise util.Abort(_('no files or directories specified; '
4952 'use --all to remerge all files'))
4959 'use --all to remerge all files'))
4953
4960
4954 ms = mergemod.mergestate(repo)
4961 ms = mergemod.mergestate(repo)
4955 m = scmutil.match(repo[None], pats, opts)
4962 m = scmutil.match(repo[None], pats, opts)
4956 ret = 0
4963 ret = 0
4957
4964
4958 for f in ms:
4965 for f in ms:
4959 if m(f):
4966 if m(f):
4960 if show:
4967 if show:
4961 if nostatus:
4968 if nostatus:
4962 ui.write("%s\n" % f)
4969 ui.write("%s\n" % f)
4963 else:
4970 else:
4964 ui.write("%s %s\n" % (ms[f].upper(), f),
4971 ui.write("%s %s\n" % (ms[f].upper(), f),
4965 label='resolve.' +
4972 label='resolve.' +
4966 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4973 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4967 elif mark:
4974 elif mark:
4968 ms.mark(f, "r")
4975 ms.mark(f, "r")
4969 elif unmark:
4976 elif unmark:
4970 ms.mark(f, "u")
4977 ms.mark(f, "u")
4971 else:
4978 else:
4972 wctx = repo[None]
4979 wctx = repo[None]
4973
4980
4974 # backup pre-resolve (merge uses .orig for its own purposes)
4981 # backup pre-resolve (merge uses .orig for its own purposes)
4975 a = repo.wjoin(f)
4982 a = repo.wjoin(f)
4976 util.copyfile(a, a + ".resolve")
4983 util.copyfile(a, a + ".resolve")
4977
4984
4978 try:
4985 try:
4979 # resolve file
4986 # resolve file
4980 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4987 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4981 if ms.resolve(f, wctx):
4988 if ms.resolve(f, wctx):
4982 ret = 1
4989 ret = 1
4983 finally:
4990 finally:
4984 ui.setconfig('ui', 'forcemerge', '')
4991 ui.setconfig('ui', 'forcemerge', '')
4985 ms.commit()
4992 ms.commit()
4986
4993
4987 # replace filemerge's .orig file with our resolve file
4994 # replace filemerge's .orig file with our resolve file
4988 util.rename(a + ".resolve", a + ".orig")
4995 util.rename(a + ".resolve", a + ".orig")
4989
4996
4990 ms.commit()
4997 ms.commit()
4991 return ret
4998 return ret
4992
4999
4993 @command('revert',
5000 @command('revert',
4994 [('a', 'all', None, _('revert all changes when no arguments given')),
5001 [('a', 'all', None, _('revert all changes when no arguments given')),
4995 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5002 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4996 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5003 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4997 ('C', 'no-backup', None, _('do not save backup copies of files')),
5004 ('C', 'no-backup', None, _('do not save backup copies of files')),
4998 ] + walkopts + dryrunopts,
5005 ] + walkopts + dryrunopts,
4999 _('[OPTION]... [-r REV] [NAME]...'))
5006 _('[OPTION]... [-r REV] [NAME]...'))
5000 def revert(ui, repo, *pats, **opts):
5007 def revert(ui, repo, *pats, **opts):
5001 """restore files to their checkout state
5008 """restore files to their checkout state
5002
5009
5003 .. note::
5010 .. note::
5004
5011
5005 To check out earlier revisions, you should use :hg:`update REV`.
5012 To check out earlier revisions, you should use :hg:`update REV`.
5006 To cancel an uncommitted merge (and lose your changes),
5013 To cancel an uncommitted merge (and lose your changes),
5007 use :hg:`update --clean .`.
5014 use :hg:`update --clean .`.
5008
5015
5009 With no revision specified, revert the specified files or directories
5016 With no revision specified, revert the specified files or directories
5010 to the contents they had in the parent of the working directory.
5017 to the contents they had in the parent of the working directory.
5011 This restores the contents of files to an unmodified
5018 This restores the contents of files to an unmodified
5012 state and unschedules adds, removes, copies, and renames. If the
5019 state and unschedules adds, removes, copies, and renames. If the
5013 working directory has two parents, you must explicitly specify a
5020 working directory has two parents, you must explicitly specify a
5014 revision.
5021 revision.
5015
5022
5016 Using the -r/--rev or -d/--date options, revert the given files or
5023 Using the -r/--rev or -d/--date options, revert the given files or
5017 directories to their states as of a specific revision. Because
5024 directories to their states as of a specific revision. Because
5018 revert does not change the working directory parents, this will
5025 revert does not change the working directory parents, this will
5019 cause these files to appear modified. This can be helpful to "back
5026 cause these files to appear modified. This can be helpful to "back
5020 out" some or all of an earlier change. See :hg:`backout` for a
5027 out" some or all of an earlier change. See :hg:`backout` for a
5021 related method.
5028 related method.
5022
5029
5023 Modified files are saved with a .orig suffix before reverting.
5030 Modified files are saved with a .orig suffix before reverting.
5024 To disable these backups, use --no-backup.
5031 To disable these backups, use --no-backup.
5025
5032
5026 See :hg:`help dates` for a list of formats valid for -d/--date.
5033 See :hg:`help dates` for a list of formats valid for -d/--date.
5027
5034
5028 Returns 0 on success.
5035 Returns 0 on success.
5029 """
5036 """
5030
5037
5031 if opts.get("date"):
5038 if opts.get("date"):
5032 if opts.get("rev"):
5039 if opts.get("rev"):
5033 raise util.Abort(_("you can't specify a revision and a date"))
5040 raise util.Abort(_("you can't specify a revision and a date"))
5034 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5041 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5035
5042
5036 parent, p2 = repo.dirstate.parents()
5043 parent, p2 = repo.dirstate.parents()
5037 if not opts.get('rev') and p2 != nullid:
5044 if not opts.get('rev') and p2 != nullid:
5038 # revert after merge is a trap for new users (issue2915)
5045 # revert after merge is a trap for new users (issue2915)
5039 raise util.Abort(_('uncommitted merge with no revision specified'),
5046 raise util.Abort(_('uncommitted merge with no revision specified'),
5040 hint=_('use "hg update" or see "hg help revert"'))
5047 hint=_('use "hg update" or see "hg help revert"'))
5041
5048
5042 ctx = scmutil.revsingle(repo, opts.get('rev'))
5049 ctx = scmutil.revsingle(repo, opts.get('rev'))
5043
5050
5044 if not pats and not opts.get('all'):
5051 if not pats and not opts.get('all'):
5045 msg = _("no files or directories specified")
5052 msg = _("no files or directories specified")
5046 if p2 != nullid:
5053 if p2 != nullid:
5047 hint = _("uncommitted merge, use --all to discard all changes,"
5054 hint = _("uncommitted merge, use --all to discard all changes,"
5048 " or 'hg update -C .' to abort the merge")
5055 " or 'hg update -C .' to abort the merge")
5049 raise util.Abort(msg, hint=hint)
5056 raise util.Abort(msg, hint=hint)
5050 dirty = util.any(repo.status())
5057 dirty = util.any(repo.status())
5051 node = ctx.node()
5058 node = ctx.node()
5052 if node != parent:
5059 if node != parent:
5053 if dirty:
5060 if dirty:
5054 hint = _("uncommitted changes, use --all to discard all"
5061 hint = _("uncommitted changes, use --all to discard all"
5055 " changes, or 'hg update %s' to update") % ctx.rev()
5062 " changes, or 'hg update %s' to update") % ctx.rev()
5056 else:
5063 else:
5057 hint = _("use --all to revert all files,"
5064 hint = _("use --all to revert all files,"
5058 " or 'hg update %s' to update") % ctx.rev()
5065 " or 'hg update %s' to update") % ctx.rev()
5059 elif dirty:
5066 elif dirty:
5060 hint = _("uncommitted changes, use --all to discard all changes")
5067 hint = _("uncommitted changes, use --all to discard all changes")
5061 else:
5068 else:
5062 hint = _("use --all to revert all files")
5069 hint = _("use --all to revert all files")
5063 raise util.Abort(msg, hint=hint)
5070 raise util.Abort(msg, hint=hint)
5064
5071
5065 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5072 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5066
5073
5067 @command('rollback', dryrunopts +
5074 @command('rollback', dryrunopts +
5068 [('f', 'force', False, _('ignore safety measures'))])
5075 [('f', 'force', False, _('ignore safety measures'))])
5069 def rollback(ui, repo, **opts):
5076 def rollback(ui, repo, **opts):
5070 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5077 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5071
5078
5072 Please use :hg:`commit --amend` instead of rollback to correct
5079 Please use :hg:`commit --amend` instead of rollback to correct
5073 mistakes in the last commit.
5080 mistakes in the last commit.
5074
5081
5075 This command should be used with care. There is only one level of
5082 This command should be used with care. There is only one level of
5076 rollback, and there is no way to undo a rollback. It will also
5083 rollback, and there is no way to undo a rollback. It will also
5077 restore the dirstate at the time of the last transaction, losing
5084 restore the dirstate at the time of the last transaction, losing
5078 any dirstate changes since that time. This command does not alter
5085 any dirstate changes since that time. This command does not alter
5079 the working directory.
5086 the working directory.
5080
5087
5081 Transactions are used to encapsulate the effects of all commands
5088 Transactions are used to encapsulate the effects of all commands
5082 that create new changesets or propagate existing changesets into a
5089 that create new changesets or propagate existing changesets into a
5083 repository.
5090 repository.
5084
5091
5085 .. container:: verbose
5092 .. container:: verbose
5086
5093
5087 For example, the following commands are transactional, and their
5094 For example, the following commands are transactional, and their
5088 effects can be rolled back:
5095 effects can be rolled back:
5089
5096
5090 - commit
5097 - commit
5091 - import
5098 - import
5092 - pull
5099 - pull
5093 - push (with this repository as the destination)
5100 - push (with this repository as the destination)
5094 - unbundle
5101 - unbundle
5095
5102
5096 To avoid permanent data loss, rollback will refuse to rollback a
5103 To avoid permanent data loss, rollback will refuse to rollback a
5097 commit transaction if it isn't checked out. Use --force to
5104 commit transaction if it isn't checked out. Use --force to
5098 override this protection.
5105 override this protection.
5099
5106
5100 This command is not intended for use on public repositories. Once
5107 This command is not intended for use on public repositories. Once
5101 changes are visible for pull by other users, rolling a transaction
5108 changes are visible for pull by other users, rolling a transaction
5102 back locally is ineffective (someone else may already have pulled
5109 back locally is ineffective (someone else may already have pulled
5103 the changes). Furthermore, a race is possible with readers of the
5110 the changes). Furthermore, a race is possible with readers of the
5104 repository; for example an in-progress pull from the repository
5111 repository; for example an in-progress pull from the repository
5105 may fail if a rollback is performed.
5112 may fail if a rollback is performed.
5106
5113
5107 Returns 0 on success, 1 if no rollback data is available.
5114 Returns 0 on success, 1 if no rollback data is available.
5108 """
5115 """
5109 return repo.rollback(dryrun=opts.get('dry_run'),
5116 return repo.rollback(dryrun=opts.get('dry_run'),
5110 force=opts.get('force'))
5117 force=opts.get('force'))
5111
5118
5112 @command('root', [])
5119 @command('root', [])
5113 def root(ui, repo):
5120 def root(ui, repo):
5114 """print the root (top) of the current working directory
5121 """print the root (top) of the current working directory
5115
5122
5116 Print the root directory of the current repository.
5123 Print the root directory of the current repository.
5117
5124
5118 Returns 0 on success.
5125 Returns 0 on success.
5119 """
5126 """
5120 ui.write(repo.root + "\n")
5127 ui.write(repo.root + "\n")
5121
5128
5122 @command('^serve',
5129 @command('^serve',
5123 [('A', 'accesslog', '', _('name of access log file to write to'),
5130 [('A', 'accesslog', '', _('name of access log file to write to'),
5124 _('FILE')),
5131 _('FILE')),
5125 ('d', 'daemon', None, _('run server in background')),
5132 ('d', 'daemon', None, _('run server in background')),
5126 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5133 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5127 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5134 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5128 # use string type, then we can check if something was passed
5135 # use string type, then we can check if something was passed
5129 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5136 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5130 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5137 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5131 _('ADDR')),
5138 _('ADDR')),
5132 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5139 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5133 _('PREFIX')),
5140 _('PREFIX')),
5134 ('n', 'name', '',
5141 ('n', 'name', '',
5135 _('name to show in web pages (default: working directory)'), _('NAME')),
5142 _('name to show in web pages (default: working directory)'), _('NAME')),
5136 ('', 'web-conf', '',
5143 ('', 'web-conf', '',
5137 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5144 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5138 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5145 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5139 _('FILE')),
5146 _('FILE')),
5140 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5147 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5141 ('', 'stdio', None, _('for remote clients')),
5148 ('', 'stdio', None, _('for remote clients')),
5142 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5149 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5143 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5150 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5144 ('', 'style', '', _('template style to use'), _('STYLE')),
5151 ('', 'style', '', _('template style to use'), _('STYLE')),
5145 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5152 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5146 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5153 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5147 _('[OPTION]...'))
5154 _('[OPTION]...'))
5148 def serve(ui, repo, **opts):
5155 def serve(ui, repo, **opts):
5149 """start stand-alone webserver
5156 """start stand-alone webserver
5150
5157
5151 Start a local HTTP repository browser and pull server. You can use
5158 Start a local HTTP repository browser and pull server. You can use
5152 this for ad-hoc sharing and browsing of repositories. It is
5159 this for ad-hoc sharing and browsing of repositories. It is
5153 recommended to use a real web server to serve a repository for
5160 recommended to use a real web server to serve a repository for
5154 longer periods of time.
5161 longer periods of time.
5155
5162
5156 Please note that the server does not implement access control.
5163 Please note that the server does not implement access control.
5157 This means that, by default, anybody can read from the server and
5164 This means that, by default, anybody can read from the server and
5158 nobody can write to it by default. Set the ``web.allow_push``
5165 nobody can write to it by default. Set the ``web.allow_push``
5159 option to ``*`` to allow everybody to push to the server. You
5166 option to ``*`` to allow everybody to push to the server. You
5160 should use a real web server if you need to authenticate users.
5167 should use a real web server if you need to authenticate users.
5161
5168
5162 By default, the server logs accesses to stdout and errors to
5169 By default, the server logs accesses to stdout and errors to
5163 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5170 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5164 files.
5171 files.
5165
5172
5166 To have the server choose a free port number to listen on, specify
5173 To have the server choose a free port number to listen on, specify
5167 a port number of 0; in this case, the server will print the port
5174 a port number of 0; in this case, the server will print the port
5168 number it uses.
5175 number it uses.
5169
5176
5170 Returns 0 on success.
5177 Returns 0 on success.
5171 """
5178 """
5172
5179
5173 if opts["stdio"] and opts["cmdserver"]:
5180 if opts["stdio"] and opts["cmdserver"]:
5174 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5181 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5175
5182
5176 def checkrepo():
5183 def checkrepo():
5177 if repo is None:
5184 if repo is None:
5178 raise error.RepoError(_("there is no Mercurial repository here"
5185 raise error.RepoError(_("there is no Mercurial repository here"
5179 " (.hg not found)"))
5186 " (.hg not found)"))
5180
5187
5181 if opts["stdio"]:
5188 if opts["stdio"]:
5182 checkrepo()
5189 checkrepo()
5183 s = sshserver.sshserver(ui, repo)
5190 s = sshserver.sshserver(ui, repo)
5184 s.serve_forever()
5191 s.serve_forever()
5185
5192
5186 if opts["cmdserver"]:
5193 if opts["cmdserver"]:
5187 s = commandserver.server(ui, repo, opts["cmdserver"])
5194 s = commandserver.server(ui, repo, opts["cmdserver"])
5188 return s.serve()
5195 return s.serve()
5189
5196
5190 # this way we can check if something was given in the command-line
5197 # this way we can check if something was given in the command-line
5191 if opts.get('port'):
5198 if opts.get('port'):
5192 opts['port'] = util.getport(opts.get('port'))
5199 opts['port'] = util.getport(opts.get('port'))
5193
5200
5194 baseui = repo and repo.baseui or ui
5201 baseui = repo and repo.baseui or ui
5195 optlist = ("name templates style address port prefix ipv6"
5202 optlist = ("name templates style address port prefix ipv6"
5196 " accesslog errorlog certificate encoding")
5203 " accesslog errorlog certificate encoding")
5197 for o in optlist.split():
5204 for o in optlist.split():
5198 val = opts.get(o, '')
5205 val = opts.get(o, '')
5199 if val in (None, ''): # should check against default options instead
5206 if val in (None, ''): # should check against default options instead
5200 continue
5207 continue
5201 baseui.setconfig("web", o, val)
5208 baseui.setconfig("web", o, val)
5202 if repo and repo.ui != baseui:
5209 if repo and repo.ui != baseui:
5203 repo.ui.setconfig("web", o, val)
5210 repo.ui.setconfig("web", o, val)
5204
5211
5205 o = opts.get('web_conf') or opts.get('webdir_conf')
5212 o = opts.get('web_conf') or opts.get('webdir_conf')
5206 if not o:
5213 if not o:
5207 if not repo:
5214 if not repo:
5208 raise error.RepoError(_("there is no Mercurial repository"
5215 raise error.RepoError(_("there is no Mercurial repository"
5209 " here (.hg not found)"))
5216 " here (.hg not found)"))
5210 o = repo
5217 o = repo
5211
5218
5212 app = hgweb.hgweb(o, baseui=baseui)
5219 app = hgweb.hgweb(o, baseui=baseui)
5213 service = httpservice(ui, app, opts)
5220 service = httpservice(ui, app, opts)
5214 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5221 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5215
5222
5216 class httpservice(object):
5223 class httpservice(object):
5217 def __init__(self, ui, app, opts):
5224 def __init__(self, ui, app, opts):
5218 self.ui = ui
5225 self.ui = ui
5219 self.app = app
5226 self.app = app
5220 self.opts = opts
5227 self.opts = opts
5221
5228
5222 def init(self):
5229 def init(self):
5223 util.setsignalhandler()
5230 util.setsignalhandler()
5224 self.httpd = hgweb_server.create_server(self.ui, self.app)
5231 self.httpd = hgweb_server.create_server(self.ui, self.app)
5225
5232
5226 if self.opts['port'] and not self.ui.verbose:
5233 if self.opts['port'] and not self.ui.verbose:
5227 return
5234 return
5228
5235
5229 if self.httpd.prefix:
5236 if self.httpd.prefix:
5230 prefix = self.httpd.prefix.strip('/') + '/'
5237 prefix = self.httpd.prefix.strip('/') + '/'
5231 else:
5238 else:
5232 prefix = ''
5239 prefix = ''
5233
5240
5234 port = ':%d' % self.httpd.port
5241 port = ':%d' % self.httpd.port
5235 if port == ':80':
5242 if port == ':80':
5236 port = ''
5243 port = ''
5237
5244
5238 bindaddr = self.httpd.addr
5245 bindaddr = self.httpd.addr
5239 if bindaddr == '0.0.0.0':
5246 if bindaddr == '0.0.0.0':
5240 bindaddr = '*'
5247 bindaddr = '*'
5241 elif ':' in bindaddr: # IPv6
5248 elif ':' in bindaddr: # IPv6
5242 bindaddr = '[%s]' % bindaddr
5249 bindaddr = '[%s]' % bindaddr
5243
5250
5244 fqaddr = self.httpd.fqaddr
5251 fqaddr = self.httpd.fqaddr
5245 if ':' in fqaddr:
5252 if ':' in fqaddr:
5246 fqaddr = '[%s]' % fqaddr
5253 fqaddr = '[%s]' % fqaddr
5247 if self.opts['port']:
5254 if self.opts['port']:
5248 write = self.ui.status
5255 write = self.ui.status
5249 else:
5256 else:
5250 write = self.ui.write
5257 write = self.ui.write
5251 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5258 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5252 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5259 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5253
5260
5254 def run(self):
5261 def run(self):
5255 self.httpd.serve_forever()
5262 self.httpd.serve_forever()
5256
5263
5257
5264
5258 @command('^status|st',
5265 @command('^status|st',
5259 [('A', 'all', None, _('show status of all files')),
5266 [('A', 'all', None, _('show status of all files')),
5260 ('m', 'modified', None, _('show only modified files')),
5267 ('m', 'modified', None, _('show only modified files')),
5261 ('a', 'added', None, _('show only added files')),
5268 ('a', 'added', None, _('show only added files')),
5262 ('r', 'removed', None, _('show only removed files')),
5269 ('r', 'removed', None, _('show only removed files')),
5263 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5270 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5264 ('c', 'clean', None, _('show only files without changes')),
5271 ('c', 'clean', None, _('show only files without changes')),
5265 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5272 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5266 ('i', 'ignored', None, _('show only ignored files')),
5273 ('i', 'ignored', None, _('show only ignored files')),
5267 ('n', 'no-status', None, _('hide status prefix')),
5274 ('n', 'no-status', None, _('hide status prefix')),
5268 ('C', 'copies', None, _('show source of copied files')),
5275 ('C', 'copies', None, _('show source of copied files')),
5269 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5276 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5270 ('', 'rev', [], _('show difference from revision'), _('REV')),
5277 ('', 'rev', [], _('show difference from revision'), _('REV')),
5271 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5278 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5272 ] + walkopts + subrepoopts,
5279 ] + walkopts + subrepoopts,
5273 _('[OPTION]... [FILE]...'))
5280 _('[OPTION]... [FILE]...'))
5274 def status(ui, repo, *pats, **opts):
5281 def status(ui, repo, *pats, **opts):
5275 """show changed files in the working directory
5282 """show changed files in the working directory
5276
5283
5277 Show status of files in the repository. If names are given, only
5284 Show status of files in the repository. If names are given, only
5278 files that match are shown. Files that are clean or ignored or
5285 files that match are shown. Files that are clean or ignored or
5279 the source of a copy/move operation, are not listed unless
5286 the source of a copy/move operation, are not listed unless
5280 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5287 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5281 Unless options described with "show only ..." are given, the
5288 Unless options described with "show only ..." are given, the
5282 options -mardu are used.
5289 options -mardu are used.
5283
5290
5284 Option -q/--quiet hides untracked (unknown and ignored) files
5291 Option -q/--quiet hides untracked (unknown and ignored) files
5285 unless explicitly requested with -u/--unknown or -i/--ignored.
5292 unless explicitly requested with -u/--unknown or -i/--ignored.
5286
5293
5287 .. note::
5294 .. note::
5288
5295
5289 status may appear to disagree with diff if permissions have
5296 status may appear to disagree with diff if permissions have
5290 changed or a merge has occurred. The standard diff format does
5297 changed or a merge has occurred. The standard diff format does
5291 not report permission changes and diff only reports changes
5298 not report permission changes and diff only reports changes
5292 relative to one merge parent.
5299 relative to one merge parent.
5293
5300
5294 If one revision is given, it is used as the base revision.
5301 If one revision is given, it is used as the base revision.
5295 If two revisions are given, the differences between them are
5302 If two revisions are given, the differences between them are
5296 shown. The --change option can also be used as a shortcut to list
5303 shown. The --change option can also be used as a shortcut to list
5297 the changed files of a revision from its first parent.
5304 the changed files of a revision from its first parent.
5298
5305
5299 The codes used to show the status of files are::
5306 The codes used to show the status of files are::
5300
5307
5301 M = modified
5308 M = modified
5302 A = added
5309 A = added
5303 R = removed
5310 R = removed
5304 C = clean
5311 C = clean
5305 ! = missing (deleted by non-hg command, but still tracked)
5312 ! = missing (deleted by non-hg command, but still tracked)
5306 ? = not tracked
5313 ? = not tracked
5307 I = ignored
5314 I = ignored
5308 = origin of the previous file (with --copies)
5315 = origin of the previous file (with --copies)
5309
5316
5310 .. container:: verbose
5317 .. container:: verbose
5311
5318
5312 Examples:
5319 Examples:
5313
5320
5314 - show changes in the working directory relative to a
5321 - show changes in the working directory relative to a
5315 changeset::
5322 changeset::
5316
5323
5317 hg status --rev 9353
5324 hg status --rev 9353
5318
5325
5319 - show all changes including copies in an existing changeset::
5326 - show all changes including copies in an existing changeset::
5320
5327
5321 hg status --copies --change 9353
5328 hg status --copies --change 9353
5322
5329
5323 - get a NUL separated list of added files, suitable for xargs::
5330 - get a NUL separated list of added files, suitable for xargs::
5324
5331
5325 hg status -an0
5332 hg status -an0
5326
5333
5327 Returns 0 on success.
5334 Returns 0 on success.
5328 """
5335 """
5329
5336
5330 revs = opts.get('rev')
5337 revs = opts.get('rev')
5331 change = opts.get('change')
5338 change = opts.get('change')
5332
5339
5333 if revs and change:
5340 if revs and change:
5334 msg = _('cannot specify --rev and --change at the same time')
5341 msg = _('cannot specify --rev and --change at the same time')
5335 raise util.Abort(msg)
5342 raise util.Abort(msg)
5336 elif change:
5343 elif change:
5337 node2 = scmutil.revsingle(repo, change, None).node()
5344 node2 = scmutil.revsingle(repo, change, None).node()
5338 node1 = repo[node2].p1().node()
5345 node1 = repo[node2].p1().node()
5339 else:
5346 else:
5340 node1, node2 = scmutil.revpair(repo, revs)
5347 node1, node2 = scmutil.revpair(repo, revs)
5341
5348
5342 cwd = (pats and repo.getcwd()) or ''
5349 cwd = (pats and repo.getcwd()) or ''
5343 end = opts.get('print0') and '\0' or '\n'
5350 end = opts.get('print0') and '\0' or '\n'
5344 copy = {}
5351 copy = {}
5345 states = 'modified added removed deleted unknown ignored clean'.split()
5352 states = 'modified added removed deleted unknown ignored clean'.split()
5346 show = [k for k in states if opts.get(k)]
5353 show = [k for k in states if opts.get(k)]
5347 if opts.get('all'):
5354 if opts.get('all'):
5348 show += ui.quiet and (states[:4] + ['clean']) or states
5355 show += ui.quiet and (states[:4] + ['clean']) or states
5349 if not show:
5356 if not show:
5350 show = ui.quiet and states[:4] or states[:5]
5357 show = ui.quiet and states[:4] or states[:5]
5351
5358
5352 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5359 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5353 'ignored' in show, 'clean' in show, 'unknown' in show,
5360 'ignored' in show, 'clean' in show, 'unknown' in show,
5354 opts.get('subrepos'))
5361 opts.get('subrepos'))
5355 changestates = zip(states, 'MAR!?IC', stat)
5362 changestates = zip(states, 'MAR!?IC', stat)
5356
5363
5357 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5364 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5358 copy = copies.pathcopies(repo[node1], repo[node2])
5365 copy = copies.pathcopies(repo[node1], repo[node2])
5359
5366
5360 fm = ui.formatter('status', opts)
5367 fm = ui.formatter('status', opts)
5361 fmt = '%s' + end
5368 fmt = '%s' + end
5362 showchar = not opts.get('no_status')
5369 showchar = not opts.get('no_status')
5363
5370
5364 for state, char, files in changestates:
5371 for state, char, files in changestates:
5365 if state in show:
5372 if state in show:
5366 label = 'status.' + state
5373 label = 'status.' + state
5367 for f in files:
5374 for f in files:
5368 fm.startitem()
5375 fm.startitem()
5369 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5376 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5370 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5377 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5371 if f in copy:
5378 if f in copy:
5372 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5379 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5373 label='status.copied')
5380 label='status.copied')
5374 fm.end()
5381 fm.end()
5375
5382
5376 @command('^summary|sum',
5383 @command('^summary|sum',
5377 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5384 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5378 def summary(ui, repo, **opts):
5385 def summary(ui, repo, **opts):
5379 """summarize working directory state
5386 """summarize working directory state
5380
5387
5381 This generates a brief summary of the working directory state,
5388 This generates a brief summary of the working directory state,
5382 including parents, branch, commit status, and available updates.
5389 including parents, branch, commit status, and available updates.
5383
5390
5384 With the --remote option, this will check the default paths for
5391 With the --remote option, this will check the default paths for
5385 incoming and outgoing changes. This can be time-consuming.
5392 incoming and outgoing changes. This can be time-consuming.
5386
5393
5387 Returns 0 on success.
5394 Returns 0 on success.
5388 """
5395 """
5389
5396
5390 ctx = repo[None]
5397 ctx = repo[None]
5391 parents = ctx.parents()
5398 parents = ctx.parents()
5392 pnode = parents[0].node()
5399 pnode = parents[0].node()
5393 marks = []
5400 marks = []
5394
5401
5395 for p in parents:
5402 for p in parents:
5396 # label with log.changeset (instead of log.parent) since this
5403 # label with log.changeset (instead of log.parent) since this
5397 # shows a working directory parent *changeset*:
5404 # shows a working directory parent *changeset*:
5398 # i18n: column positioning for "hg summary"
5405 # i18n: column positioning for "hg summary"
5399 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5406 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5400 label='log.changeset changeset.%s' % p.phasestr())
5407 label='log.changeset changeset.%s' % p.phasestr())
5401 ui.write(' '.join(p.tags()), label='log.tag')
5408 ui.write(' '.join(p.tags()), label='log.tag')
5402 if p.bookmarks():
5409 if p.bookmarks():
5403 marks.extend(p.bookmarks())
5410 marks.extend(p.bookmarks())
5404 if p.rev() == -1:
5411 if p.rev() == -1:
5405 if not len(repo):
5412 if not len(repo):
5406 ui.write(_(' (empty repository)'))
5413 ui.write(_(' (empty repository)'))
5407 else:
5414 else:
5408 ui.write(_(' (no revision checked out)'))
5415 ui.write(_(' (no revision checked out)'))
5409 ui.write('\n')
5416 ui.write('\n')
5410 if p.description():
5417 if p.description():
5411 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5418 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5412 label='log.summary')
5419 label='log.summary')
5413
5420
5414 branch = ctx.branch()
5421 branch = ctx.branch()
5415 bheads = repo.branchheads(branch)
5422 bheads = repo.branchheads(branch)
5416 # i18n: column positioning for "hg summary"
5423 # i18n: column positioning for "hg summary"
5417 m = _('branch: %s\n') % branch
5424 m = _('branch: %s\n') % branch
5418 if branch != 'default':
5425 if branch != 'default':
5419 ui.write(m, label='log.branch')
5426 ui.write(m, label='log.branch')
5420 else:
5427 else:
5421 ui.status(m, label='log.branch')
5428 ui.status(m, label='log.branch')
5422
5429
5423 if marks:
5430 if marks:
5424 current = repo._bookmarkcurrent
5431 current = repo._bookmarkcurrent
5425 # i18n: column positioning for "hg summary"
5432 # i18n: column positioning for "hg summary"
5426 ui.write(_('bookmarks:'), label='log.bookmark')
5433 ui.write(_('bookmarks:'), label='log.bookmark')
5427 if current is not None:
5434 if current is not None:
5428 if current in marks:
5435 if current in marks:
5429 ui.write(' *' + current, label='bookmarks.current')
5436 ui.write(' *' + current, label='bookmarks.current')
5430 marks.remove(current)
5437 marks.remove(current)
5431 else:
5438 else:
5432 ui.write(' [%s]' % current, label='bookmarks.current')
5439 ui.write(' [%s]' % current, label='bookmarks.current')
5433 for m in marks:
5440 for m in marks:
5434 ui.write(' ' + m, label='log.bookmark')
5441 ui.write(' ' + m, label='log.bookmark')
5435 ui.write('\n', label='log.bookmark')
5442 ui.write('\n', label='log.bookmark')
5436
5443
5437 st = list(repo.status(unknown=True))[:6]
5444 st = list(repo.status(unknown=True))[:6]
5438
5445
5439 c = repo.dirstate.copies()
5446 c = repo.dirstate.copies()
5440 copied, renamed = [], []
5447 copied, renamed = [], []
5441 for d, s in c.iteritems():
5448 for d, s in c.iteritems():
5442 if s in st[2]:
5449 if s in st[2]:
5443 st[2].remove(s)
5450 st[2].remove(s)
5444 renamed.append(d)
5451 renamed.append(d)
5445 else:
5452 else:
5446 copied.append(d)
5453 copied.append(d)
5447 if d in st[1]:
5454 if d in st[1]:
5448 st[1].remove(d)
5455 st[1].remove(d)
5449 st.insert(3, renamed)
5456 st.insert(3, renamed)
5450 st.insert(4, copied)
5457 st.insert(4, copied)
5451
5458
5452 ms = mergemod.mergestate(repo)
5459 ms = mergemod.mergestate(repo)
5453 st.append([f for f in ms if ms[f] == 'u'])
5460 st.append([f for f in ms if ms[f] == 'u'])
5454
5461
5455 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5462 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5456 st.append(subs)
5463 st.append(subs)
5457
5464
5458 labels = [ui.label(_('%d modified'), 'status.modified'),
5465 labels = [ui.label(_('%d modified'), 'status.modified'),
5459 ui.label(_('%d added'), 'status.added'),
5466 ui.label(_('%d added'), 'status.added'),
5460 ui.label(_('%d removed'), 'status.removed'),
5467 ui.label(_('%d removed'), 'status.removed'),
5461 ui.label(_('%d renamed'), 'status.copied'),
5468 ui.label(_('%d renamed'), 'status.copied'),
5462 ui.label(_('%d copied'), 'status.copied'),
5469 ui.label(_('%d copied'), 'status.copied'),
5463 ui.label(_('%d deleted'), 'status.deleted'),
5470 ui.label(_('%d deleted'), 'status.deleted'),
5464 ui.label(_('%d unknown'), 'status.unknown'),
5471 ui.label(_('%d unknown'), 'status.unknown'),
5465 ui.label(_('%d ignored'), 'status.ignored'),
5472 ui.label(_('%d ignored'), 'status.ignored'),
5466 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5473 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5467 ui.label(_('%d subrepos'), 'status.modified')]
5474 ui.label(_('%d subrepos'), 'status.modified')]
5468 t = []
5475 t = []
5469 for s, l in zip(st, labels):
5476 for s, l in zip(st, labels):
5470 if s:
5477 if s:
5471 t.append(l % len(s))
5478 t.append(l % len(s))
5472
5479
5473 t = ', '.join(t)
5480 t = ', '.join(t)
5474 cleanworkdir = False
5481 cleanworkdir = False
5475
5482
5476 if repo.vfs.exists('updatestate'):
5483 if repo.vfs.exists('updatestate'):
5477 t += _(' (interrupted update)')
5484 t += _(' (interrupted update)')
5478 elif len(parents) > 1:
5485 elif len(parents) > 1:
5479 t += _(' (merge)')
5486 t += _(' (merge)')
5480 elif branch != parents[0].branch():
5487 elif branch != parents[0].branch():
5481 t += _(' (new branch)')
5488 t += _(' (new branch)')
5482 elif (parents[0].closesbranch() and
5489 elif (parents[0].closesbranch() and
5483 pnode in repo.branchheads(branch, closed=True)):
5490 pnode in repo.branchheads(branch, closed=True)):
5484 t += _(' (head closed)')
5491 t += _(' (head closed)')
5485 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5492 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5486 t += _(' (clean)')
5493 t += _(' (clean)')
5487 cleanworkdir = True
5494 cleanworkdir = True
5488 elif pnode not in bheads:
5495 elif pnode not in bheads:
5489 t += _(' (new branch head)')
5496 t += _(' (new branch head)')
5490
5497
5491 if cleanworkdir:
5498 if cleanworkdir:
5492 # i18n: column positioning for "hg summary"
5499 # i18n: column positioning for "hg summary"
5493 ui.status(_('commit: %s\n') % t.strip())
5500 ui.status(_('commit: %s\n') % t.strip())
5494 else:
5501 else:
5495 # i18n: column positioning for "hg summary"
5502 # i18n: column positioning for "hg summary"
5496 ui.write(_('commit: %s\n') % t.strip())
5503 ui.write(_('commit: %s\n') % t.strip())
5497
5504
5498 # all ancestors of branch heads - all ancestors of parent = new csets
5505 # all ancestors of branch heads - all ancestors of parent = new csets
5499 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5506 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5500 bheads))
5507 bheads))
5501
5508
5502 if new == 0:
5509 if new == 0:
5503 # i18n: column positioning for "hg summary"
5510 # i18n: column positioning for "hg summary"
5504 ui.status(_('update: (current)\n'))
5511 ui.status(_('update: (current)\n'))
5505 elif pnode not in bheads:
5512 elif pnode not in bheads:
5506 # i18n: column positioning for "hg summary"
5513 # i18n: column positioning for "hg summary"
5507 ui.write(_('update: %d new changesets (update)\n') % new)
5514 ui.write(_('update: %d new changesets (update)\n') % new)
5508 else:
5515 else:
5509 # i18n: column positioning for "hg summary"
5516 # i18n: column positioning for "hg summary"
5510 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5517 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5511 (new, len(bheads)))
5518 (new, len(bheads)))
5512
5519
5513 cmdutil.summaryhooks(ui, repo)
5520 cmdutil.summaryhooks(ui, repo)
5514
5521
5515 if opts.get('remote'):
5522 if opts.get('remote'):
5516 t = []
5523 t = []
5517 source, branches = hg.parseurl(ui.expandpath('default'))
5524 source, branches = hg.parseurl(ui.expandpath('default'))
5518 sbranch = branches[0]
5525 sbranch = branches[0]
5519 other = hg.peer(repo, {}, source)
5526 other = hg.peer(repo, {}, source)
5520 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5527 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5521 if revs:
5528 if revs:
5522 revs = [other.lookup(rev) for rev in revs]
5529 revs = [other.lookup(rev) for rev in revs]
5523 ui.debug('comparing with %s\n' % util.hidepassword(source))
5530 ui.debug('comparing with %s\n' % util.hidepassword(source))
5524 repo.ui.pushbuffer()
5531 repo.ui.pushbuffer()
5525 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5532 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5526 _common, incoming, _rheads = commoninc
5533 _common, incoming, _rheads = commoninc
5527 repo.ui.popbuffer()
5534 repo.ui.popbuffer()
5528 if incoming:
5535 if incoming:
5529 t.append(_('1 or more incoming'))
5536 t.append(_('1 or more incoming'))
5530
5537
5531 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5538 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5532 dbranch = branches[0]
5539 dbranch = branches[0]
5533 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5540 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5534 if source != dest:
5541 if source != dest:
5535 other = hg.peer(repo, {}, dest)
5542 other = hg.peer(repo, {}, dest)
5536 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5543 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5537 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5544 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5538 commoninc = None
5545 commoninc = None
5539 if revs:
5546 if revs:
5540 revs = [repo.lookup(rev) for rev in revs]
5547 revs = [repo.lookup(rev) for rev in revs]
5541 repo.ui.pushbuffer()
5548 repo.ui.pushbuffer()
5542 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5549 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5543 commoninc=commoninc)
5550 commoninc=commoninc)
5544 repo.ui.popbuffer()
5551 repo.ui.popbuffer()
5545 o = outgoing.missing
5552 o = outgoing.missing
5546 if o:
5553 if o:
5547 t.append(_('%d outgoing') % len(o))
5554 t.append(_('%d outgoing') % len(o))
5548 if 'bookmarks' in other.listkeys('namespaces'):
5555 if 'bookmarks' in other.listkeys('namespaces'):
5549 lmarks = repo.listkeys('bookmarks')
5556 lmarks = repo.listkeys('bookmarks')
5550 rmarks = other.listkeys('bookmarks')
5557 rmarks = other.listkeys('bookmarks')
5551 diff = set(rmarks) - set(lmarks)
5558 diff = set(rmarks) - set(lmarks)
5552 if len(diff) > 0:
5559 if len(diff) > 0:
5553 t.append(_('%d incoming bookmarks') % len(diff))
5560 t.append(_('%d incoming bookmarks') % len(diff))
5554 diff = set(lmarks) - set(rmarks)
5561 diff = set(lmarks) - set(rmarks)
5555 if len(diff) > 0:
5562 if len(diff) > 0:
5556 t.append(_('%d outgoing bookmarks') % len(diff))
5563 t.append(_('%d outgoing bookmarks') % len(diff))
5557
5564
5558 if t:
5565 if t:
5559 # i18n: column positioning for "hg summary"
5566 # i18n: column positioning for "hg summary"
5560 ui.write(_('remote: %s\n') % (', '.join(t)))
5567 ui.write(_('remote: %s\n') % (', '.join(t)))
5561 else:
5568 else:
5562 # i18n: column positioning for "hg summary"
5569 # i18n: column positioning for "hg summary"
5563 ui.status(_('remote: (synced)\n'))
5570 ui.status(_('remote: (synced)\n'))
5564
5571
5565 @command('tag',
5572 @command('tag',
5566 [('f', 'force', None, _('force tag')),
5573 [('f', 'force', None, _('force tag')),
5567 ('l', 'local', None, _('make the tag local')),
5574 ('l', 'local', None, _('make the tag local')),
5568 ('r', 'rev', '', _('revision to tag'), _('REV')),
5575 ('r', 'rev', '', _('revision to tag'), _('REV')),
5569 ('', 'remove', None, _('remove a tag')),
5576 ('', 'remove', None, _('remove a tag')),
5570 # -l/--local is already there, commitopts cannot be used
5577 # -l/--local is already there, commitopts cannot be used
5571 ('e', 'edit', None, _('edit commit message')),
5578 ('e', 'edit', None, _('edit commit message')),
5572 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5579 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5573 ] + commitopts2,
5580 ] + commitopts2,
5574 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5581 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5575 def tag(ui, repo, name1, *names, **opts):
5582 def tag(ui, repo, name1, *names, **opts):
5576 """add one or more tags for the current or given revision
5583 """add one or more tags for the current or given revision
5577
5584
5578 Name a particular revision using <name>.
5585 Name a particular revision using <name>.
5579
5586
5580 Tags are used to name particular revisions of the repository and are
5587 Tags are used to name particular revisions of the repository and are
5581 very useful to compare different revisions, to go back to significant
5588 very useful to compare different revisions, to go back to significant
5582 earlier versions or to mark branch points as releases, etc. Changing
5589 earlier versions or to mark branch points as releases, etc. Changing
5583 an existing tag is normally disallowed; use -f/--force to override.
5590 an existing tag is normally disallowed; use -f/--force to override.
5584
5591
5585 If no revision is given, the parent of the working directory is
5592 If no revision is given, the parent of the working directory is
5586 used.
5593 used.
5587
5594
5588 To facilitate version control, distribution, and merging of tags,
5595 To facilitate version control, distribution, and merging of tags,
5589 they are stored as a file named ".hgtags" which is managed similarly
5596 they are stored as a file named ".hgtags" which is managed similarly
5590 to other project files and can be hand-edited if necessary. This
5597 to other project files and can be hand-edited if necessary. This
5591 also means that tagging creates a new commit. The file
5598 also means that tagging creates a new commit. The file
5592 ".hg/localtags" is used for local tags (not shared among
5599 ".hg/localtags" is used for local tags (not shared among
5593 repositories).
5600 repositories).
5594
5601
5595 Tag commits are usually made at the head of a branch. If the parent
5602 Tag commits are usually made at the head of a branch. If the parent
5596 of the working directory is not a branch head, :hg:`tag` aborts; use
5603 of the working directory is not a branch head, :hg:`tag` aborts; use
5597 -f/--force to force the tag commit to be based on a non-head
5604 -f/--force to force the tag commit to be based on a non-head
5598 changeset.
5605 changeset.
5599
5606
5600 See :hg:`help dates` for a list of formats valid for -d/--date.
5607 See :hg:`help dates` for a list of formats valid for -d/--date.
5601
5608
5602 Since tag names have priority over branch names during revision
5609 Since tag names have priority over branch names during revision
5603 lookup, using an existing branch name as a tag name is discouraged.
5610 lookup, using an existing branch name as a tag name is discouraged.
5604
5611
5605 Returns 0 on success.
5612 Returns 0 on success.
5606 """
5613 """
5607 wlock = lock = None
5614 wlock = lock = None
5608 try:
5615 try:
5609 wlock = repo.wlock()
5616 wlock = repo.wlock()
5610 lock = repo.lock()
5617 lock = repo.lock()
5611 rev_ = "."
5618 rev_ = "."
5612 names = [t.strip() for t in (name1,) + names]
5619 names = [t.strip() for t in (name1,) + names]
5613 if len(names) != len(set(names)):
5620 if len(names) != len(set(names)):
5614 raise util.Abort(_('tag names must be unique'))
5621 raise util.Abort(_('tag names must be unique'))
5615 for n in names:
5622 for n in names:
5616 scmutil.checknewlabel(repo, n, 'tag')
5623 scmutil.checknewlabel(repo, n, 'tag')
5617 if not n:
5624 if not n:
5618 raise util.Abort(_('tag names cannot consist entirely of '
5625 raise util.Abort(_('tag names cannot consist entirely of '
5619 'whitespace'))
5626 'whitespace'))
5620 if opts.get('rev') and opts.get('remove'):
5627 if opts.get('rev') and opts.get('remove'):
5621 raise util.Abort(_("--rev and --remove are incompatible"))
5628 raise util.Abort(_("--rev and --remove are incompatible"))
5622 if opts.get('rev'):
5629 if opts.get('rev'):
5623 rev_ = opts['rev']
5630 rev_ = opts['rev']
5624 message = opts.get('message')
5631 message = opts.get('message')
5625 if opts.get('remove'):
5632 if opts.get('remove'):
5626 expectedtype = opts.get('local') and 'local' or 'global'
5633 expectedtype = opts.get('local') and 'local' or 'global'
5627 for n in names:
5634 for n in names:
5628 if not repo.tagtype(n):
5635 if not repo.tagtype(n):
5629 raise util.Abort(_("tag '%s' does not exist") % n)
5636 raise util.Abort(_("tag '%s' does not exist") % n)
5630 if repo.tagtype(n) != expectedtype:
5637 if repo.tagtype(n) != expectedtype:
5631 if expectedtype == 'global':
5638 if expectedtype == 'global':
5632 raise util.Abort(_("tag '%s' is not a global tag") % n)
5639 raise util.Abort(_("tag '%s' is not a global tag") % n)
5633 else:
5640 else:
5634 raise util.Abort(_("tag '%s' is not a local tag") % n)
5641 raise util.Abort(_("tag '%s' is not a local tag") % n)
5635 rev_ = nullid
5642 rev_ = nullid
5636 if not message:
5643 if not message:
5637 # we don't translate commit messages
5644 # we don't translate commit messages
5638 message = 'Removed tag %s' % ', '.join(names)
5645 message = 'Removed tag %s' % ', '.join(names)
5639 elif not opts.get('force'):
5646 elif not opts.get('force'):
5640 for n in names:
5647 for n in names:
5641 if n in repo.tags():
5648 if n in repo.tags():
5642 raise util.Abort(_("tag '%s' already exists "
5649 raise util.Abort(_("tag '%s' already exists "
5643 "(use -f to force)") % n)
5650 "(use -f to force)") % n)
5644 if not opts.get('local'):
5651 if not opts.get('local'):
5645 p1, p2 = repo.dirstate.parents()
5652 p1, p2 = repo.dirstate.parents()
5646 if p2 != nullid:
5653 if p2 != nullid:
5647 raise util.Abort(_('uncommitted merge'))
5654 raise util.Abort(_('uncommitted merge'))
5648 bheads = repo.branchheads()
5655 bheads = repo.branchheads()
5649 if not opts.get('force') and bheads and p1 not in bheads:
5656 if not opts.get('force') and bheads and p1 not in bheads:
5650 raise util.Abort(_('not at a branch head (use -f to force)'))
5657 raise util.Abort(_('not at a branch head (use -f to force)'))
5651 r = scmutil.revsingle(repo, rev_).node()
5658 r = scmutil.revsingle(repo, rev_).node()
5652
5659
5653 if not message:
5660 if not message:
5654 # we don't translate commit messages
5661 # we don't translate commit messages
5655 message = ('Added tag %s for changeset %s' %
5662 message = ('Added tag %s for changeset %s' %
5656 (', '.join(names), short(r)))
5663 (', '.join(names), short(r)))
5657
5664
5658 date = opts.get('date')
5665 date = opts.get('date')
5659 if date:
5666 if date:
5660 date = util.parsedate(date)
5667 date = util.parsedate(date)
5661
5668
5662 if opts.get('edit'):
5669 if opts.get('edit'):
5663 message = ui.edit(message, ui.username())
5670 message = ui.edit(message, ui.username())
5664 repo.savecommitmessage(message)
5671 repo.savecommitmessage(message)
5665
5672
5666 # don't allow tagging the null rev
5673 # don't allow tagging the null rev
5667 if (not opts.get('remove') and
5674 if (not opts.get('remove') and
5668 scmutil.revsingle(repo, rev_).rev() == nullrev):
5675 scmutil.revsingle(repo, rev_).rev() == nullrev):
5669 raise util.Abort(_("cannot tag null revision"))
5676 raise util.Abort(_("cannot tag null revision"))
5670
5677
5671 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5678 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5672 finally:
5679 finally:
5673 release(lock, wlock)
5680 release(lock, wlock)
5674
5681
5675 @command('tags', [], '')
5682 @command('tags', [], '')
5676 def tags(ui, repo, **opts):
5683 def tags(ui, repo, **opts):
5677 """list repository tags
5684 """list repository tags
5678
5685
5679 This lists both regular and local tags. When the -v/--verbose
5686 This lists both regular and local tags. When the -v/--verbose
5680 switch is used, a third column "local" is printed for local tags.
5687 switch is used, a third column "local" is printed for local tags.
5681
5688
5682 Returns 0 on success.
5689 Returns 0 on success.
5683 """
5690 """
5684
5691
5685 fm = ui.formatter('tags', opts)
5692 fm = ui.formatter('tags', opts)
5686 hexfunc = ui.debugflag and hex or short
5693 hexfunc = ui.debugflag and hex or short
5687 tagtype = ""
5694 tagtype = ""
5688
5695
5689 for t, n in reversed(repo.tagslist()):
5696 for t, n in reversed(repo.tagslist()):
5690 hn = hexfunc(n)
5697 hn = hexfunc(n)
5691 label = 'tags.normal'
5698 label = 'tags.normal'
5692 tagtype = ''
5699 tagtype = ''
5693 if repo.tagtype(t) == 'local':
5700 if repo.tagtype(t) == 'local':
5694 label = 'tags.local'
5701 label = 'tags.local'
5695 tagtype = 'local'
5702 tagtype = 'local'
5696
5703
5697 fm.startitem()
5704 fm.startitem()
5698 fm.write('tag', '%s', t, label=label)
5705 fm.write('tag', '%s', t, label=label)
5699 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5706 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5700 fm.condwrite(not ui.quiet, 'rev id', fmt,
5707 fm.condwrite(not ui.quiet, 'rev id', fmt,
5701 repo.changelog.rev(n), hn, label=label)
5708 repo.changelog.rev(n), hn, label=label)
5702 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5709 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5703 tagtype, label=label)
5710 tagtype, label=label)
5704 fm.plain('\n')
5711 fm.plain('\n')
5705 fm.end()
5712 fm.end()
5706
5713
5707 @command('tip',
5714 @command('tip',
5708 [('p', 'patch', None, _('show patch')),
5715 [('p', 'patch', None, _('show patch')),
5709 ('g', 'git', None, _('use git extended diff format')),
5716 ('g', 'git', None, _('use git extended diff format')),
5710 ] + templateopts,
5717 ] + templateopts,
5711 _('[-p] [-g]'))
5718 _('[-p] [-g]'))
5712 def tip(ui, repo, **opts):
5719 def tip(ui, repo, **opts):
5713 """show the tip revision (DEPRECATED)
5720 """show the tip revision (DEPRECATED)
5714
5721
5715 The tip revision (usually just called the tip) is the changeset
5722 The tip revision (usually just called the tip) is the changeset
5716 most recently added to the repository (and therefore the most
5723 most recently added to the repository (and therefore the most
5717 recently changed head).
5724 recently changed head).
5718
5725
5719 If you have just made a commit, that commit will be the tip. If
5726 If you have just made a commit, that commit will be the tip. If
5720 you have just pulled changes from another repository, the tip of
5727 you have just pulled changes from another repository, the tip of
5721 that repository becomes the current tip. The "tip" tag is special
5728 that repository becomes the current tip. The "tip" tag is special
5722 and cannot be renamed or assigned to a different changeset.
5729 and cannot be renamed or assigned to a different changeset.
5723
5730
5724 This command is deprecated, please use :hg:`heads` instead.
5731 This command is deprecated, please use :hg:`heads` instead.
5725
5732
5726 Returns 0 on success.
5733 Returns 0 on success.
5727 """
5734 """
5728 displayer = cmdutil.show_changeset(ui, repo, opts)
5735 displayer = cmdutil.show_changeset(ui, repo, opts)
5729 displayer.show(repo['tip'])
5736 displayer.show(repo['tip'])
5730 displayer.close()
5737 displayer.close()
5731
5738
5732 @command('unbundle',
5739 @command('unbundle',
5733 [('u', 'update', None,
5740 [('u', 'update', None,
5734 _('update to new branch head if changesets were unbundled'))],
5741 _('update to new branch head if changesets were unbundled'))],
5735 _('[-u] FILE...'))
5742 _('[-u] FILE...'))
5736 def unbundle(ui, repo, fname1, *fnames, **opts):
5743 def unbundle(ui, repo, fname1, *fnames, **opts):
5737 """apply one or more changegroup files
5744 """apply one or more changegroup files
5738
5745
5739 Apply one or more compressed changegroup files generated by the
5746 Apply one or more compressed changegroup files generated by the
5740 bundle command.
5747 bundle command.
5741
5748
5742 Returns 0 on success, 1 if an update has unresolved files.
5749 Returns 0 on success, 1 if an update has unresolved files.
5743 """
5750 """
5744 fnames = (fname1,) + fnames
5751 fnames = (fname1,) + fnames
5745
5752
5746 lock = repo.lock()
5753 lock = repo.lock()
5747 wc = repo['.']
5754 wc = repo['.']
5748 try:
5755 try:
5749 for fname in fnames:
5756 for fname in fnames:
5750 f = hg.openpath(ui, fname)
5757 f = hg.openpath(ui, fname)
5751 gen = changegroup.readbundle(f, fname)
5758 gen = changegroup.readbundle(f, fname)
5752 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5759 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5753 finally:
5760 finally:
5754 lock.release()
5761 lock.release()
5755 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5762 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5756 return postincoming(ui, repo, modheads, opts.get('update'), None)
5763 return postincoming(ui, repo, modheads, opts.get('update'), None)
5757
5764
5758 @command('^update|up|checkout|co',
5765 @command('^update|up|checkout|co',
5759 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5766 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5760 ('c', 'check', None,
5767 ('c', 'check', None,
5761 _('update across branches if no uncommitted changes')),
5768 _('update across branches if no uncommitted changes')),
5762 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5769 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5763 ('r', 'rev', '', _('revision'), _('REV'))],
5770 ('r', 'rev', '', _('revision'), _('REV'))],
5764 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5771 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5765 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5772 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5766 """update working directory (or switch revisions)
5773 """update working directory (or switch revisions)
5767
5774
5768 Update the repository's working directory to the specified
5775 Update the repository's working directory to the specified
5769 changeset. If no changeset is specified, update to the tip of the
5776 changeset. If no changeset is specified, update to the tip of the
5770 current named branch and move the current bookmark (see :hg:`help
5777 current named branch and move the current bookmark (see :hg:`help
5771 bookmarks`).
5778 bookmarks`).
5772
5779
5773 Update sets the working directory's parent revision to the specified
5780 Update sets the working directory's parent revision to the specified
5774 changeset (see :hg:`help parents`).
5781 changeset (see :hg:`help parents`).
5775
5782
5776 If the changeset is not a descendant or ancestor of the working
5783 If the changeset is not a descendant or ancestor of the working
5777 directory's parent, the update is aborted. With the -c/--check
5784 directory's parent, the update is aborted. With the -c/--check
5778 option, the working directory is checked for uncommitted changes; if
5785 option, the working directory is checked for uncommitted changes; if
5779 none are found, the working directory is updated to the specified
5786 none are found, the working directory is updated to the specified
5780 changeset.
5787 changeset.
5781
5788
5782 .. container:: verbose
5789 .. container:: verbose
5783
5790
5784 The following rules apply when the working directory contains
5791 The following rules apply when the working directory contains
5785 uncommitted changes:
5792 uncommitted changes:
5786
5793
5787 1. If neither -c/--check nor -C/--clean is specified, and if
5794 1. If neither -c/--check nor -C/--clean is specified, and if
5788 the requested changeset is an ancestor or descendant of
5795 the requested changeset is an ancestor or descendant of
5789 the working directory's parent, the uncommitted changes
5796 the working directory's parent, the uncommitted changes
5790 are merged into the requested changeset and the merged
5797 are merged into the requested changeset and the merged
5791 result is left uncommitted. If the requested changeset is
5798 result is left uncommitted. If the requested changeset is
5792 not an ancestor or descendant (that is, it is on another
5799 not an ancestor or descendant (that is, it is on another
5793 branch), the update is aborted and the uncommitted changes
5800 branch), the update is aborted and the uncommitted changes
5794 are preserved.
5801 are preserved.
5795
5802
5796 2. With the -c/--check option, the update is aborted and the
5803 2. With the -c/--check option, the update is aborted and the
5797 uncommitted changes are preserved.
5804 uncommitted changes are preserved.
5798
5805
5799 3. With the -C/--clean option, uncommitted changes are discarded and
5806 3. With the -C/--clean option, uncommitted changes are discarded and
5800 the working directory is updated to the requested changeset.
5807 the working directory is updated to the requested changeset.
5801
5808
5802 To cancel an uncommitted merge (and lose your changes), use
5809 To cancel an uncommitted merge (and lose your changes), use
5803 :hg:`update --clean .`.
5810 :hg:`update --clean .`.
5804
5811
5805 Use null as the changeset to remove the working directory (like
5812 Use null as the changeset to remove the working directory (like
5806 :hg:`clone -U`).
5813 :hg:`clone -U`).
5807
5814
5808 If you want to revert just one file to an older revision, use
5815 If you want to revert just one file to an older revision, use
5809 :hg:`revert [-r REV] NAME`.
5816 :hg:`revert [-r REV] NAME`.
5810
5817
5811 See :hg:`help dates` for a list of formats valid for -d/--date.
5818 See :hg:`help dates` for a list of formats valid for -d/--date.
5812
5819
5813 Returns 0 on success, 1 if there are unresolved files.
5820 Returns 0 on success, 1 if there are unresolved files.
5814 """
5821 """
5815 if rev and node:
5822 if rev and node:
5816 raise util.Abort(_("please specify just one revision"))
5823 raise util.Abort(_("please specify just one revision"))
5817
5824
5818 if rev is None or rev == '':
5825 if rev is None or rev == '':
5819 rev = node
5826 rev = node
5820
5827
5821 cmdutil.clearunfinished(repo)
5828 cmdutil.clearunfinished(repo)
5822
5829
5823 # with no argument, we also move the current bookmark, if any
5830 # with no argument, we also move the current bookmark, if any
5824 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5831 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5825
5832
5826 # if we defined a bookmark, we have to remember the original bookmark name
5833 # if we defined a bookmark, we have to remember the original bookmark name
5827 brev = rev
5834 brev = rev
5828 rev = scmutil.revsingle(repo, rev, rev).rev()
5835 rev = scmutil.revsingle(repo, rev, rev).rev()
5829
5836
5830 if check and clean:
5837 if check and clean:
5831 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5838 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5832
5839
5833 if date:
5840 if date:
5834 if rev is not None:
5841 if rev is not None:
5835 raise util.Abort(_("you can't specify a revision and a date"))
5842 raise util.Abort(_("you can't specify a revision and a date"))
5836 rev = cmdutil.finddate(ui, repo, date)
5843 rev = cmdutil.finddate(ui, repo, date)
5837
5844
5838 if check:
5845 if check:
5839 c = repo[None]
5846 c = repo[None]
5840 if c.dirty(merge=False, branch=False, missing=True):
5847 if c.dirty(merge=False, branch=False, missing=True):
5841 raise util.Abort(_("uncommitted changes"))
5848 raise util.Abort(_("uncommitted changes"))
5842 if rev is None:
5849 if rev is None:
5843 rev = repo[repo[None].branch()].rev()
5850 rev = repo[repo[None].branch()].rev()
5844 mergemod._checkunknown(repo, repo[None], repo[rev])
5851 mergemod._checkunknown(repo, repo[None], repo[rev])
5845
5852
5846 if clean:
5853 if clean:
5847 ret = hg.clean(repo, rev)
5854 ret = hg.clean(repo, rev)
5848 else:
5855 else:
5849 ret = hg.update(repo, rev)
5856 ret = hg.update(repo, rev)
5850
5857
5851 if not ret and movemarkfrom:
5858 if not ret and movemarkfrom:
5852 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5859 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5853 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5860 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5854 elif brev in repo._bookmarks:
5861 elif brev in repo._bookmarks:
5855 bookmarks.setcurrent(repo, brev)
5862 bookmarks.setcurrent(repo, brev)
5856 elif brev:
5863 elif brev:
5857 bookmarks.unsetcurrent(repo)
5864 bookmarks.unsetcurrent(repo)
5858
5865
5859 return ret
5866 return ret
5860
5867
5861 @command('verify', [])
5868 @command('verify', [])
5862 def verify(ui, repo):
5869 def verify(ui, repo):
5863 """verify the integrity of the repository
5870 """verify the integrity of the repository
5864
5871
5865 Verify the integrity of the current repository.
5872 Verify the integrity of the current repository.
5866
5873
5867 This will perform an extensive check of the repository's
5874 This will perform an extensive check of the repository's
5868 integrity, validating the hashes and checksums of each entry in
5875 integrity, validating the hashes and checksums of each entry in
5869 the changelog, manifest, and tracked files, as well as the
5876 the changelog, manifest, and tracked files, as well as the
5870 integrity of their crosslinks and indices.
5877 integrity of their crosslinks and indices.
5871
5878
5872 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5879 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5873 for more information about recovery from corruption of the
5880 for more information about recovery from corruption of the
5874 repository.
5881 repository.
5875
5882
5876 Returns 0 on success, 1 if errors are encountered.
5883 Returns 0 on success, 1 if errors are encountered.
5877 """
5884 """
5878 return hg.verify(repo)
5885 return hg.verify(repo)
5879
5886
5880 @command('version', [])
5887 @command('version', [])
5881 def version_(ui):
5888 def version_(ui):
5882 """output version and copyright information"""
5889 """output version and copyright information"""
5883 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5890 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5884 % util.version())
5891 % util.version())
5885 ui.status(_(
5892 ui.status(_(
5886 "(see http://mercurial.selenic.com for more information)\n"
5893 "(see http://mercurial.selenic.com for more information)\n"
5887 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5894 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5888 "This is free software; see the source for copying conditions. "
5895 "This is free software; see the source for copying conditions. "
5889 "There is NO\nwarranty; "
5896 "There is NO\nwarranty; "
5890 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5897 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5891 ))
5898 ))
5892
5899
5893 norepo = ("clone init version help debugcommands debugcomplete"
5900 norepo = ("clone init version help debugcommands debugcomplete"
5894 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5901 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5895 " debugknown debuggetbundle debugbundle")
5902 " debugknown debuggetbundle debugbundle")
5896 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5903 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5897 " debugdata debugindex debugindexdot debugrevlog")
5904 " debugdata debugindex debugindexdot debugrevlog")
5898 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5905 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5899 " remove resolve status debugwalk")
5906 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now