##// END OF EJS Templates
branches: quiet option observes other parameters
Travis Herrick -
r16612:726dd0fc default
parent child Browse files
Show More
@@ -1,5724 +1,5724 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 _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil, pvec
19 import random, setdiscovery, treediscovery, dagutil, pvec
20 import phases
20 import phases
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="", explicitonly=False)
176 opts.get('subrepos'), prefix="", explicitonly=False)
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199
199
200 Returns 0 if all files are successfully added.
200 Returns 0 if all files are successfully added.
201 """
201 """
202 try:
202 try:
203 sim = float(opts.get('similarity') or 100)
203 sim = float(opts.get('similarity') or 100)
204 except ValueError:
204 except ValueError:
205 raise util.Abort(_('similarity must be a number'))
205 raise util.Abort(_('similarity must be a number'))
206 if sim < 0 or sim > 100:
206 if sim < 0 or sim > 100:
207 raise util.Abort(_('similarity must be between 0 and 100'))
207 raise util.Abort(_('similarity must be between 0 and 100'))
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209
209
210 @command('^annotate|blame',
210 @command('^annotate|blame',
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 ('', 'follow', None,
212 ('', 'follow', None,
213 _('follow copies/renames and list the filename (DEPRECATED)')),
213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('a', 'text', None, _('treat all files as text')),
215 ('a', 'text', None, _('treat all files as text')),
216 ('u', 'user', None, _('list the author (long with -v)')),
216 ('u', 'user', None, _('list the author (long with -v)')),
217 ('f', 'file', None, _('list the filename')),
217 ('f', 'file', None, _('list the filename')),
218 ('d', 'date', None, _('list the date (short with -q)')),
218 ('d', 'date', None, _('list the date (short with -q)')),
219 ('n', 'number', None, _('list the revision number (default)')),
219 ('n', 'number', None, _('list the revision number (default)')),
220 ('c', 'changeset', None, _('list the changeset')),
220 ('c', 'changeset', None, _('list the changeset')),
221 ('l', 'line-number', None, _('show line number at the first appearance'))
221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ] + diffwsopts + walkopts,
222 ] + diffwsopts + walkopts,
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 def annotate(ui, repo, *pats, **opts):
224 def annotate(ui, repo, *pats, **opts):
225 """show changeset information by line for each file
225 """show changeset information by line for each file
226
226
227 List changes in files, showing the revision id responsible for
227 List changes in files, showing the revision id responsible for
228 each line
228 each line
229
229
230 This command is useful for discovering when a change was made and
230 This command is useful for discovering when a change was made and
231 by whom.
231 by whom.
232
232
233 Without the -a/--text option, annotate will avoid processing files
233 Without the -a/--text option, annotate will avoid processing files
234 it detects as binary. With -a, annotate will annotate the file
234 it detects as binary. With -a, annotate will annotate the file
235 anyway, although the results will probably be neither useful
235 anyway, although the results will probably be neither useful
236 nor desirable.
236 nor desirable.
237
237
238 Returns 0 on success.
238 Returns 0 on success.
239 """
239 """
240 if opts.get('follow'):
240 if opts.get('follow'):
241 # --follow is deprecated and now just an alias for -f/--file
241 # --follow is deprecated and now just an alias for -f/--file
242 # to mimic the behavior of Mercurial before version 1.5
242 # to mimic the behavior of Mercurial before version 1.5
243 opts['file'] = True
243 opts['file'] = True
244
244
245 datefunc = ui.quiet and util.shortdate or util.datestr
245 datefunc = ui.quiet and util.shortdate or util.datestr
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247
247
248 if not pats:
248 if not pats:
249 raise util.Abort(_('at least one filename or pattern is required'))
249 raise util.Abort(_('at least one filename or pattern is required'))
250
250
251 hexfn = ui.debugflag and hex or short
251 hexfn = ui.debugflag and hex or short
252
252
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 ('number', ' ', lambda x: str(x[0].rev())),
254 ('number', ' ', lambda x: str(x[0].rev())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('date', ' ', getdate),
256 ('date', ' ', getdate),
257 ('file', ' ', lambda x: x[0].path()),
257 ('file', ' ', lambda x: x[0].path()),
258 ('line_number', ':', lambda x: str(x[1])),
258 ('line_number', ':', lambda x: str(x[1])),
259 ]
259 ]
260
260
261 if (not opts.get('user') and not opts.get('changeset')
261 if (not opts.get('user') and not opts.get('changeset')
262 and not opts.get('date') and not opts.get('file')):
262 and not opts.get('date') and not opts.get('file')):
263 opts['number'] = True
263 opts['number'] = True
264
264
265 linenumber = opts.get('line_number') is not None
265 linenumber = opts.get('line_number') is not None
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
268
268
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271
271
272 def bad(x, y):
272 def bad(x, y):
273 raise util.Abort("%s: %s" % (x, y))
273 raise util.Abort("%s: %s" % (x, y))
274
274
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 m = scmutil.match(ctx, pats, opts)
276 m = scmutil.match(ctx, pats, opts)
277 m.bad = bad
277 m.bad = bad
278 follow = not opts.get('no_follow')
278 follow = not opts.get('no_follow')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
280 for abs in ctx.walk(m):
280 for abs in ctx.walk(m):
281 fctx = ctx[abs]
281 fctx = ctx[abs]
282 if not opts.get('text') and util.binary(fctx.data()):
282 if not opts.get('text') and util.binary(fctx.data()):
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 continue
284 continue
285
285
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 diffopts=diffopts)
287 diffopts=diffopts)
288 pieces = []
288 pieces = []
289
289
290 for f, sep in funcmap:
290 for f, sep in funcmap:
291 l = [f(n) for n, dummy in lines]
291 l = [f(n) for n, dummy in lines]
292 if l:
292 if l:
293 sized = [(x, encoding.colwidth(x)) for x in l]
293 sized = [(x, encoding.colwidth(x)) for x in l]
294 ml = max([w for x, w in sized])
294 ml = max([w for x, w in sized])
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 for x, w in sized])
296 for x, w in sized])
297
297
298 if pieces:
298 if pieces:
299 for p, l in zip(zip(*pieces), lines):
299 for p, l in zip(zip(*pieces), lines):
300 ui.write("%s: %s" % ("".join(p), l[1]))
300 ui.write("%s: %s" % ("".join(p), l[1]))
301
301
302 if lines and not lines[-1][1].endswith('\n'):
302 if lines and not lines[-1][1].endswith('\n'):
303 ui.write('\n')
303 ui.write('\n')
304
304
305 @command('archive',
305 @command('archive',
306 [('', 'no-decode', None, _('do not pass files through decoders')),
306 [('', 'no-decode', None, _('do not pass files through decoders')),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
308 _('PREFIX')),
308 _('PREFIX')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
311 ] + subrepoopts + walkopts,
311 ] + subrepoopts + walkopts,
312 _('[OPTION]... DEST'))
312 _('[OPTION]... DEST'))
313 def archive(ui, repo, dest, **opts):
313 def archive(ui, repo, dest, **opts):
314 '''create an unversioned archive of a repository revision
314 '''create an unversioned archive of a repository revision
315
315
316 By default, the revision used is the parent of the working
316 By default, the revision used is the parent of the working
317 directory; use -r/--rev to specify a different revision.
317 directory; use -r/--rev to specify a different revision.
318
318
319 The archive type is automatically detected based on file
319 The archive type is automatically detected based on file
320 extension (or override using -t/--type).
320 extension (or override using -t/--type).
321
321
322 .. container:: verbose
322 .. container:: verbose
323
323
324 Examples:
324 Examples:
325
325
326 - create a zip file containing the 1.0 release::
326 - create a zip file containing the 1.0 release::
327
327
328 hg archive -r 1.0 project-1.0.zip
328 hg archive -r 1.0 project-1.0.zip
329
329
330 - create a tarball excluding .hg files::
330 - create a tarball excluding .hg files::
331
331
332 hg archive project.tar.gz -X ".hg*"
332 hg archive project.tar.gz -X ".hg*"
333
333
334 Valid types are:
334 Valid types are:
335
335
336 :``files``: a directory full of files (default)
336 :``files``: a directory full of files (default)
337 :``tar``: tar archive, uncompressed
337 :``tar``: tar archive, uncompressed
338 :``tbz2``: tar archive, compressed using bzip2
338 :``tbz2``: tar archive, compressed using bzip2
339 :``tgz``: tar archive, compressed using gzip
339 :``tgz``: tar archive, compressed using gzip
340 :``uzip``: zip archive, uncompressed
340 :``uzip``: zip archive, uncompressed
341 :``zip``: zip archive, compressed using deflate
341 :``zip``: zip archive, compressed using deflate
342
342
343 The exact name of the destination archive or directory is given
343 The exact name of the destination archive or directory is given
344 using a format string; see :hg:`help export` for details.
344 using a format string; see :hg:`help export` for details.
345
345
346 Each member added to an archive file has a directory prefix
346 Each member added to an archive file has a directory prefix
347 prepended. Use -p/--prefix to specify a format string for the
347 prepended. Use -p/--prefix to specify a format string for the
348 prefix. The default is the basename of the archive, with suffixes
348 prefix. The default is the basename of the archive, with suffixes
349 removed.
349 removed.
350
350
351 Returns 0 on success.
351 Returns 0 on success.
352 '''
352 '''
353
353
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
355 if not ctx:
355 if not ctx:
356 raise util.Abort(_('no working directory: please specify a revision'))
356 raise util.Abort(_('no working directory: please specify a revision'))
357 node = ctx.node()
357 node = ctx.node()
358 dest = cmdutil.makefilename(repo, dest, node)
358 dest = cmdutil.makefilename(repo, dest, node)
359 if os.path.realpath(dest) == repo.root:
359 if os.path.realpath(dest) == repo.root:
360 raise util.Abort(_('repository root cannot be destination'))
360 raise util.Abort(_('repository root cannot be destination'))
361
361
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
363 prefix = opts.get('prefix')
363 prefix = opts.get('prefix')
364
364
365 if dest == '-':
365 if dest == '-':
366 if kind == 'files':
366 if kind == 'files':
367 raise util.Abort(_('cannot archive plain files to stdout'))
367 raise util.Abort(_('cannot archive plain files to stdout'))
368 dest = cmdutil.makefileobj(repo, dest)
368 dest = cmdutil.makefileobj(repo, dest)
369 if not prefix:
369 if not prefix:
370 prefix = os.path.basename(repo.root) + '-%h'
370 prefix = os.path.basename(repo.root) + '-%h'
371
371
372 prefix = cmdutil.makefilename(repo, prefix, node)
372 prefix = cmdutil.makefilename(repo, prefix, node)
373 matchfn = scmutil.match(ctx, [], opts)
373 matchfn = scmutil.match(ctx, [], opts)
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
375 matchfn, prefix, subrepos=opts.get('subrepos'))
375 matchfn, prefix, subrepos=opts.get('subrepos'))
376
376
377 @command('backout',
377 @command('backout',
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
379 ('', 'parent', '',
379 ('', 'parent', '',
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
383 _('[OPTION]... [-r] REV'))
383 _('[OPTION]... [-r] REV'))
384 def backout(ui, repo, node=None, rev=None, **opts):
384 def backout(ui, repo, node=None, rev=None, **opts):
385 '''reverse effect of earlier changeset
385 '''reverse effect of earlier changeset
386
386
387 Prepare a new changeset with the effect of REV undone in the
387 Prepare a new changeset with the effect of REV undone in the
388 current working directory.
388 current working directory.
389
389
390 If REV is the parent of the working directory, then this new changeset
390 If REV is the parent of the working directory, then this new changeset
391 is committed automatically. Otherwise, hg needs to merge the
391 is committed automatically. Otherwise, hg needs to merge the
392 changes and the merged result is left uncommitted.
392 changes and the merged result is left uncommitted.
393
393
394 .. note::
394 .. note::
395 backout cannot be used to fix either an unwanted or
395 backout cannot be used to fix either an unwanted or
396 incorrect merge.
396 incorrect merge.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 By default, the pending changeset will have one parent,
400 By default, the pending changeset will have one parent,
401 maintaining a linear history. With --merge, the pending
401 maintaining a linear history. With --merge, the pending
402 changeset will instead have two parents: the old parent of the
402 changeset will instead have two parents: the old parent of the
403 working directory and a new child of REV that simply undoes REV.
403 working directory and a new child of REV that simply undoes REV.
404
404
405 Before version 1.7, the behavior without --merge was equivalent
405 Before version 1.7, the behavior without --merge was equivalent
406 to specifying --merge followed by :hg:`update --clean .` to
406 to specifying --merge followed by :hg:`update --clean .` to
407 cancel the merge and leave the child of REV as a head to be
407 cancel the merge and leave the child of REV as a head to be
408 merged separately.
408 merged separately.
409
409
410 See :hg:`help dates` for a list of formats valid for -d/--date.
410 See :hg:`help dates` for a list of formats valid for -d/--date.
411
411
412 Returns 0 on success.
412 Returns 0 on success.
413 '''
413 '''
414 if rev and node:
414 if rev and node:
415 raise util.Abort(_("please specify just one revision"))
415 raise util.Abort(_("please specify just one revision"))
416
416
417 if not rev:
417 if not rev:
418 rev = node
418 rev = node
419
419
420 if not rev:
420 if not rev:
421 raise util.Abort(_("please specify a revision to backout"))
421 raise util.Abort(_("please specify a revision to backout"))
422
422
423 date = opts.get('date')
423 date = opts.get('date')
424 if date:
424 if date:
425 opts['date'] = util.parsedate(date)
425 opts['date'] = util.parsedate(date)
426
426
427 cmdutil.bailifchanged(repo)
427 cmdutil.bailifchanged(repo)
428 node = scmutil.revsingle(repo, rev).node()
428 node = scmutil.revsingle(repo, rev).node()
429
429
430 op1, op2 = repo.dirstate.parents()
430 op1, op2 = repo.dirstate.parents()
431 a = repo.changelog.ancestor(op1, node)
431 a = repo.changelog.ancestor(op1, node)
432 if a != node:
432 if a != node:
433 raise util.Abort(_('cannot backout change on a different branch'))
433 raise util.Abort(_('cannot backout change on a different branch'))
434
434
435 p1, p2 = repo.changelog.parents(node)
435 p1, p2 = repo.changelog.parents(node)
436 if p1 == nullid:
436 if p1 == nullid:
437 raise util.Abort(_('cannot backout a change with no parents'))
437 raise util.Abort(_('cannot backout a change with no parents'))
438 if p2 != nullid:
438 if p2 != nullid:
439 if not opts.get('parent'):
439 if not opts.get('parent'):
440 raise util.Abort(_('cannot backout a merge changeset'))
440 raise util.Abort(_('cannot backout a merge changeset'))
441 p = repo.lookup(opts['parent'])
441 p = repo.lookup(opts['parent'])
442 if p not in (p1, p2):
442 if p not in (p1, p2):
443 raise util.Abort(_('%s is not a parent of %s') %
443 raise util.Abort(_('%s is not a parent of %s') %
444 (short(p), short(node)))
444 (short(p), short(node)))
445 parent = p
445 parent = p
446 else:
446 else:
447 if opts.get('parent'):
447 if opts.get('parent'):
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
449 parent = p1
449 parent = p1
450
450
451 # the backout should appear on the same branch
451 # the backout should appear on the same branch
452 wlock = repo.wlock()
452 wlock = repo.wlock()
453 try:
453 try:
454 branch = repo.dirstate.branch()
454 branch = repo.dirstate.branch()
455 hg.clean(repo, node, show_stats=False)
455 hg.clean(repo, node, show_stats=False)
456 repo.dirstate.setbranch(branch)
456 repo.dirstate.setbranch(branch)
457 revert_opts = opts.copy()
457 revert_opts = opts.copy()
458 revert_opts['date'] = None
458 revert_opts['date'] = None
459 revert_opts['all'] = True
459 revert_opts['all'] = True
460 revert_opts['rev'] = hex(parent)
460 revert_opts['rev'] = hex(parent)
461 revert_opts['no_backup'] = None
461 revert_opts['no_backup'] = None
462 revert(ui, repo, **revert_opts)
462 revert(ui, repo, **revert_opts)
463 if not opts.get('merge') and op1 != node:
463 if not opts.get('merge') and op1 != node:
464 try:
464 try:
465 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
465 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 return hg.update(repo, op1)
466 return hg.update(repo, op1)
467 finally:
467 finally:
468 ui.setconfig('ui', 'forcemerge', '')
468 ui.setconfig('ui', 'forcemerge', '')
469
469
470 commit_opts = opts.copy()
470 commit_opts = opts.copy()
471 commit_opts['addremove'] = False
471 commit_opts['addremove'] = False
472 if not commit_opts['message'] and not commit_opts['logfile']:
472 if not commit_opts['message'] and not commit_opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 commit_opts['message'] = "Backed out changeset %s" % short(node)
474 commit_opts['message'] = "Backed out changeset %s" % short(node)
475 commit_opts['force_editor'] = True
475 commit_opts['force_editor'] = True
476 commit(ui, repo, **commit_opts)
476 commit(ui, repo, **commit_opts)
477 def nice(node):
477 def nice(node):
478 return '%d:%s' % (repo.changelog.rev(node), short(node))
478 return '%d:%s' % (repo.changelog.rev(node), short(node))
479 ui.status(_('changeset %s backs out changeset %s\n') %
479 ui.status(_('changeset %s backs out changeset %s\n') %
480 (nice(repo.changelog.tip()), nice(node)))
480 (nice(repo.changelog.tip()), nice(node)))
481 if opts.get('merge') and op1 != node:
481 if opts.get('merge') and op1 != node:
482 hg.clean(repo, op1, show_stats=False)
482 hg.clean(repo, op1, show_stats=False)
483 ui.status(_('merging with changeset %s\n')
483 ui.status(_('merging with changeset %s\n')
484 % nice(repo.changelog.tip()))
484 % nice(repo.changelog.tip()))
485 try:
485 try:
486 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
486 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
487 return hg.merge(repo, hex(repo.changelog.tip()))
487 return hg.merge(repo, hex(repo.changelog.tip()))
488 finally:
488 finally:
489 ui.setconfig('ui', 'forcemerge', '')
489 ui.setconfig('ui', 'forcemerge', '')
490 finally:
490 finally:
491 wlock.release()
491 wlock.release()
492 return 0
492 return 0
493
493
494 @command('bisect',
494 @command('bisect',
495 [('r', 'reset', False, _('reset bisect state')),
495 [('r', 'reset', False, _('reset bisect state')),
496 ('g', 'good', False, _('mark changeset good')),
496 ('g', 'good', False, _('mark changeset good')),
497 ('b', 'bad', False, _('mark changeset bad')),
497 ('b', 'bad', False, _('mark changeset bad')),
498 ('s', 'skip', False, _('skip testing changeset')),
498 ('s', 'skip', False, _('skip testing changeset')),
499 ('e', 'extend', False, _('extend the bisect range')),
499 ('e', 'extend', False, _('extend the bisect range')),
500 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
500 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
501 ('U', 'noupdate', False, _('do not update to target'))],
501 ('U', 'noupdate', False, _('do not update to target'))],
502 _("[-gbsr] [-U] [-c CMD] [REV]"))
502 _("[-gbsr] [-U] [-c CMD] [REV]"))
503 def bisect(ui, repo, rev=None, extra=None, command=None,
503 def bisect(ui, repo, rev=None, extra=None, command=None,
504 reset=None, good=None, bad=None, skip=None, extend=None,
504 reset=None, good=None, bad=None, skip=None, extend=None,
505 noupdate=None):
505 noupdate=None):
506 """subdivision search of changesets
506 """subdivision search of changesets
507
507
508 This command helps to find changesets which introduce problems. To
508 This command helps to find changesets which introduce problems. To
509 use, mark the earliest changeset you know exhibits the problem as
509 use, mark the earliest changeset you know exhibits the problem as
510 bad, then mark the latest changeset which is free from the problem
510 bad, then mark the latest changeset which is free from the problem
511 as good. Bisect will update your working directory to a revision
511 as good. Bisect will update your working directory to a revision
512 for testing (unless the -U/--noupdate option is specified). Once
512 for testing (unless the -U/--noupdate option is specified). Once
513 you have performed tests, mark the working directory as good or
513 you have performed tests, mark the working directory as good or
514 bad, and bisect will either update to another candidate changeset
514 bad, and bisect will either update to another candidate changeset
515 or announce that it has found the bad revision.
515 or announce that it has found the bad revision.
516
516
517 As a shortcut, you can also use the revision argument to mark a
517 As a shortcut, you can also use the revision argument to mark a
518 revision as good or bad without checking it out first.
518 revision as good or bad without checking it out first.
519
519
520 If you supply a command, it will be used for automatic bisection.
520 If you supply a command, it will be used for automatic bisection.
521 Its exit status will be used to mark revisions as good or bad:
521 Its exit status will be used to mark revisions as good or bad:
522 status 0 means good, 125 means to skip the revision, 127
522 status 0 means good, 125 means to skip the revision, 127
523 (command not found) will abort the bisection, and any other
523 (command not found) will abort the bisection, and any other
524 non-zero exit status means the revision is bad.
524 non-zero exit status means the revision is bad.
525
525
526 .. container:: verbose
526 .. container:: verbose
527
527
528 Some examples:
528 Some examples:
529
529
530 - start a bisection with known bad revision 12, and good revision 34::
530 - start a bisection with known bad revision 12, and good revision 34::
531
531
532 hg bisect --bad 34
532 hg bisect --bad 34
533 hg bisect --good 12
533 hg bisect --good 12
534
534
535 - advance the current bisection by marking current revision as good or
535 - advance the current bisection by marking current revision as good or
536 bad::
536 bad::
537
537
538 hg bisect --good
538 hg bisect --good
539 hg bisect --bad
539 hg bisect --bad
540
540
541 - mark the current revision, or a known revision, to be skipped (eg. if
541 - mark the current revision, or a known revision, to be skipped (eg. if
542 that revision is not usable because of another issue)::
542 that revision is not usable because of another issue)::
543
543
544 hg bisect --skip
544 hg bisect --skip
545 hg bisect --skip 23
545 hg bisect --skip 23
546
546
547 - forget the current bisection::
547 - forget the current bisection::
548
548
549 hg bisect --reset
549 hg bisect --reset
550
550
551 - use 'make && make tests' to automatically find the first broken
551 - use 'make && make tests' to automatically find the first broken
552 revision::
552 revision::
553
553
554 hg bisect --reset
554 hg bisect --reset
555 hg bisect --bad 34
555 hg bisect --bad 34
556 hg bisect --good 12
556 hg bisect --good 12
557 hg bisect --command 'make && make tests'
557 hg bisect --command 'make && make tests'
558
558
559 - see all changesets whose states are already known in the current
559 - see all changesets whose states are already known in the current
560 bisection::
560 bisection::
561
561
562 hg log -r "bisect(pruned)"
562 hg log -r "bisect(pruned)"
563
563
564 - see all changesets that took part in the current bisection::
564 - see all changesets that took part in the current bisection::
565
565
566 hg log -r "bisect(range)"
566 hg log -r "bisect(range)"
567
567
568 - with the graphlog extension, you can even get a nice graph::
568 - with the graphlog extension, you can even get a nice graph::
569
569
570 hg log --graph -r "bisect(range)"
570 hg log --graph -r "bisect(range)"
571
571
572 See :hg:`help revsets` for more about the `bisect()` keyword.
572 See :hg:`help revsets` for more about the `bisect()` keyword.
573
573
574 Returns 0 on success.
574 Returns 0 on success.
575 """
575 """
576 def extendbisectrange(nodes, good):
576 def extendbisectrange(nodes, good):
577 # bisect is incomplete when it ends on a merge node and
577 # bisect is incomplete when it ends on a merge node and
578 # one of the parent was not checked.
578 # one of the parent was not checked.
579 parents = repo[nodes[0]].parents()
579 parents = repo[nodes[0]].parents()
580 if len(parents) > 1:
580 if len(parents) > 1:
581 side = good and state['bad'] or state['good']
581 side = good and state['bad'] or state['good']
582 num = len(set(i.node() for i in parents) & set(side))
582 num = len(set(i.node() for i in parents) & set(side))
583 if num == 1:
583 if num == 1:
584 return parents[0].ancestor(parents[1])
584 return parents[0].ancestor(parents[1])
585 return None
585 return None
586
586
587 def print_result(nodes, good):
587 def print_result(nodes, good):
588 displayer = cmdutil.show_changeset(ui, repo, {})
588 displayer = cmdutil.show_changeset(ui, repo, {})
589 if len(nodes) == 1:
589 if len(nodes) == 1:
590 # narrowed it down to a single revision
590 # narrowed it down to a single revision
591 if good:
591 if good:
592 ui.write(_("The first good revision is:\n"))
592 ui.write(_("The first good revision is:\n"))
593 else:
593 else:
594 ui.write(_("The first bad revision is:\n"))
594 ui.write(_("The first bad revision is:\n"))
595 displayer.show(repo[nodes[0]])
595 displayer.show(repo[nodes[0]])
596 extendnode = extendbisectrange(nodes, good)
596 extendnode = extendbisectrange(nodes, good)
597 if extendnode is not None:
597 if extendnode is not None:
598 ui.write(_('Not all ancestors of this changeset have been'
598 ui.write(_('Not all ancestors of this changeset have been'
599 ' checked.\nUse bisect --extend to continue the '
599 ' checked.\nUse bisect --extend to continue the '
600 'bisection from\nthe common ancestor, %s.\n')
600 'bisection from\nthe common ancestor, %s.\n')
601 % extendnode)
601 % extendnode)
602 else:
602 else:
603 # multiple possible revisions
603 # multiple possible revisions
604 if good:
604 if good:
605 ui.write(_("Due to skipped revisions, the first "
605 ui.write(_("Due to skipped revisions, the first "
606 "good revision could be any of:\n"))
606 "good revision could be any of:\n"))
607 else:
607 else:
608 ui.write(_("Due to skipped revisions, the first "
608 ui.write(_("Due to skipped revisions, the first "
609 "bad revision could be any of:\n"))
609 "bad revision could be any of:\n"))
610 for n in nodes:
610 for n in nodes:
611 displayer.show(repo[n])
611 displayer.show(repo[n])
612 displayer.close()
612 displayer.close()
613
613
614 def check_state(state, interactive=True):
614 def check_state(state, interactive=True):
615 if not state['good'] or not state['bad']:
615 if not state['good'] or not state['bad']:
616 if (good or bad or skip or reset) and interactive:
616 if (good or bad or skip or reset) and interactive:
617 return
617 return
618 if not state['good']:
618 if not state['good']:
619 raise util.Abort(_('cannot bisect (no known good revisions)'))
619 raise util.Abort(_('cannot bisect (no known good revisions)'))
620 else:
620 else:
621 raise util.Abort(_('cannot bisect (no known bad revisions)'))
621 raise util.Abort(_('cannot bisect (no known bad revisions)'))
622 return True
622 return True
623
623
624 # backward compatibility
624 # backward compatibility
625 if rev in "good bad reset init".split():
625 if rev in "good bad reset init".split():
626 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
626 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
627 cmd, rev, extra = rev, extra, None
627 cmd, rev, extra = rev, extra, None
628 if cmd == "good":
628 if cmd == "good":
629 good = True
629 good = True
630 elif cmd == "bad":
630 elif cmd == "bad":
631 bad = True
631 bad = True
632 else:
632 else:
633 reset = True
633 reset = True
634 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
634 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
635 raise util.Abort(_('incompatible arguments'))
635 raise util.Abort(_('incompatible arguments'))
636
636
637 if reset:
637 if reset:
638 p = repo.join("bisect.state")
638 p = repo.join("bisect.state")
639 if os.path.exists(p):
639 if os.path.exists(p):
640 os.unlink(p)
640 os.unlink(p)
641 return
641 return
642
642
643 state = hbisect.load_state(repo)
643 state = hbisect.load_state(repo)
644
644
645 if command:
645 if command:
646 changesets = 1
646 changesets = 1
647 try:
647 try:
648 while changesets:
648 while changesets:
649 # update state
649 # update state
650 hbisect.save_state(repo, state)
650 hbisect.save_state(repo, state)
651 status = util.system(command, out=ui.fout)
651 status = util.system(command, out=ui.fout)
652 if status == 125:
652 if status == 125:
653 transition = "skip"
653 transition = "skip"
654 elif status == 0:
654 elif status == 0:
655 transition = "good"
655 transition = "good"
656 # status < 0 means process was killed
656 # status < 0 means process was killed
657 elif status == 127:
657 elif status == 127:
658 raise util.Abort(_("failed to execute %s") % command)
658 raise util.Abort(_("failed to execute %s") % command)
659 elif status < 0:
659 elif status < 0:
660 raise util.Abort(_("%s killed") % command)
660 raise util.Abort(_("%s killed") % command)
661 else:
661 else:
662 transition = "bad"
662 transition = "bad"
663 ctx = scmutil.revsingle(repo, rev)
663 ctx = scmutil.revsingle(repo, rev)
664 rev = None # clear for future iterations
664 rev = None # clear for future iterations
665 state[transition].append(ctx.node())
665 state[transition].append(ctx.node())
666 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
666 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
667 check_state(state, interactive=False)
667 check_state(state, interactive=False)
668 # bisect
668 # bisect
669 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
669 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
670 # update to next check
670 # update to next check
671 cmdutil.bailifchanged(repo)
671 cmdutil.bailifchanged(repo)
672 hg.clean(repo, nodes[0], show_stats=False)
672 hg.clean(repo, nodes[0], show_stats=False)
673 finally:
673 finally:
674 hbisect.save_state(repo, state)
674 hbisect.save_state(repo, state)
675 print_result(nodes, good)
675 print_result(nodes, good)
676 return
676 return
677
677
678 # update state
678 # update state
679
679
680 if rev:
680 if rev:
681 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
681 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
682 else:
682 else:
683 nodes = [repo.lookup('.')]
683 nodes = [repo.lookup('.')]
684
684
685 if good or bad or skip:
685 if good or bad or skip:
686 if good:
686 if good:
687 state['good'] += nodes
687 state['good'] += nodes
688 elif bad:
688 elif bad:
689 state['bad'] += nodes
689 state['bad'] += nodes
690 elif skip:
690 elif skip:
691 state['skip'] += nodes
691 state['skip'] += nodes
692 hbisect.save_state(repo, state)
692 hbisect.save_state(repo, state)
693
693
694 if not check_state(state):
694 if not check_state(state):
695 return
695 return
696
696
697 # actually bisect
697 # actually bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 if extend:
699 if extend:
700 if not changesets:
700 if not changesets:
701 extendnode = extendbisectrange(nodes, good)
701 extendnode = extendbisectrange(nodes, good)
702 if extendnode is not None:
702 if extendnode is not None:
703 ui.write(_("Extending search to changeset %d:%s\n"
703 ui.write(_("Extending search to changeset %d:%s\n"
704 % (extendnode.rev(), extendnode)))
704 % (extendnode.rev(), extendnode)))
705 if noupdate:
705 if noupdate:
706 return
706 return
707 cmdutil.bailifchanged(repo)
707 cmdutil.bailifchanged(repo)
708 return hg.clean(repo, extendnode.node())
708 return hg.clean(repo, extendnode.node())
709 raise util.Abort(_("nothing to extend"))
709 raise util.Abort(_("nothing to extend"))
710
710
711 if changesets == 0:
711 if changesets == 0:
712 print_result(nodes, good)
712 print_result(nodes, good)
713 else:
713 else:
714 assert len(nodes) == 1 # only a single node can be tested next
714 assert len(nodes) == 1 # only a single node can be tested next
715 node = nodes[0]
715 node = nodes[0]
716 # compute the approximate number of remaining tests
716 # compute the approximate number of remaining tests
717 tests, size = 0, 2
717 tests, size = 0, 2
718 while size <= changesets:
718 while size <= changesets:
719 tests, size = tests + 1, size * 2
719 tests, size = tests + 1, size * 2
720 rev = repo.changelog.rev(node)
720 rev = repo.changelog.rev(node)
721 ui.write(_("Testing changeset %d:%s "
721 ui.write(_("Testing changeset %d:%s "
722 "(%d changesets remaining, ~%d tests)\n")
722 "(%d changesets remaining, ~%d tests)\n")
723 % (rev, short(node), changesets, tests))
723 % (rev, short(node), changesets, tests))
724 if not noupdate:
724 if not noupdate:
725 cmdutil.bailifchanged(repo)
725 cmdutil.bailifchanged(repo)
726 return hg.clean(repo, node)
726 return hg.clean(repo, node)
727
727
728 @command('bookmarks',
728 @command('bookmarks',
729 [('f', 'force', False, _('force')),
729 [('f', 'force', False, _('force')),
730 ('r', 'rev', '', _('revision'), _('REV')),
730 ('r', 'rev', '', _('revision'), _('REV')),
731 ('d', 'delete', False, _('delete a given bookmark')),
731 ('d', 'delete', False, _('delete a given bookmark')),
732 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
732 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
733 ('i', 'inactive', False, _('mark a bookmark inactive'))],
733 ('i', 'inactive', False, _('mark a bookmark inactive'))],
734 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
734 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
735 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
735 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
736 rename=None, inactive=False):
736 rename=None, inactive=False):
737 '''track a line of development with movable markers
737 '''track a line of development with movable markers
738
738
739 Bookmarks are pointers to certain commits that move when committing.
739 Bookmarks are pointers to certain commits that move when committing.
740 Bookmarks are local. They can be renamed, copied and deleted. It is
740 Bookmarks are local. They can be renamed, copied and deleted. It is
741 possible to use :hg:`merge NAME` to merge from a given bookmark, and
741 possible to use :hg:`merge NAME` to merge from a given bookmark, and
742 :hg:`update NAME` to update to a given bookmark.
742 :hg:`update NAME` to update to a given bookmark.
743
743
744 You can use :hg:`bookmark NAME` to set a bookmark on the working
744 You can use :hg:`bookmark NAME` to set a bookmark on the working
745 directory's parent revision with the given name. If you specify
745 directory's parent revision with the given name. If you specify
746 a revision using -r REV (where REV may be an existing bookmark),
746 a revision using -r REV (where REV may be an existing bookmark),
747 the bookmark is assigned to that revision.
747 the bookmark is assigned to that revision.
748
748
749 Bookmarks can be pushed and pulled between repositories (see :hg:`help
749 Bookmarks can be pushed and pulled between repositories (see :hg:`help
750 push` and :hg:`help pull`). This requires both the local and remote
750 push` and :hg:`help pull`). This requires both the local and remote
751 repositories to support bookmarks. For versions prior to 1.8, this means
751 repositories to support bookmarks. For versions prior to 1.8, this means
752 the bookmarks extension must be enabled.
752 the bookmarks extension must be enabled.
753
753
754 With -i/--inactive, the new bookmark will not be made the active
754 With -i/--inactive, the new bookmark will not be made the active
755 bookmark. If -r/--rev is given, the new bookmark will not be made
755 bookmark. If -r/--rev is given, the new bookmark will not be made
756 active even if -i/--inactive is not given. If no NAME is given, the
756 active even if -i/--inactive is not given. If no NAME is given, the
757 current active bookmark will be marked inactive.
757 current active bookmark will be marked inactive.
758 '''
758 '''
759 hexfn = ui.debugflag and hex or short
759 hexfn = ui.debugflag and hex or short
760 marks = repo._bookmarks
760 marks = repo._bookmarks
761 cur = repo.changectx('.').node()
761 cur = repo.changectx('.').node()
762
762
763 if delete:
763 if delete:
764 if mark is None:
764 if mark is None:
765 raise util.Abort(_("bookmark name required"))
765 raise util.Abort(_("bookmark name required"))
766 if mark not in marks:
766 if mark not in marks:
767 raise util.Abort(_("bookmark '%s' does not exist") % mark)
767 raise util.Abort(_("bookmark '%s' does not exist") % mark)
768 if mark == repo._bookmarkcurrent:
768 if mark == repo._bookmarkcurrent:
769 bookmarks.setcurrent(repo, None)
769 bookmarks.setcurrent(repo, None)
770 del marks[mark]
770 del marks[mark]
771 bookmarks.write(repo)
771 bookmarks.write(repo)
772 return
772 return
773
773
774 if rename:
774 if rename:
775 if rename not in marks:
775 if rename not in marks:
776 raise util.Abort(_("bookmark '%s' does not exist") % rename)
776 raise util.Abort(_("bookmark '%s' does not exist") % rename)
777 if mark in marks and not force:
777 if mark in marks and not force:
778 raise util.Abort(_("bookmark '%s' already exists "
778 raise util.Abort(_("bookmark '%s' already exists "
779 "(use -f to force)") % mark)
779 "(use -f to force)") % mark)
780 if mark is None:
780 if mark is None:
781 raise util.Abort(_("new bookmark name required"))
781 raise util.Abort(_("new bookmark name required"))
782 marks[mark] = marks[rename]
782 marks[mark] = marks[rename]
783 if repo._bookmarkcurrent == rename and not inactive:
783 if repo._bookmarkcurrent == rename and not inactive:
784 bookmarks.setcurrent(repo, mark)
784 bookmarks.setcurrent(repo, mark)
785 del marks[rename]
785 del marks[rename]
786 bookmarks.write(repo)
786 bookmarks.write(repo)
787 return
787 return
788
788
789 if mark is not None:
789 if mark is not None:
790 if "\n" in mark:
790 if "\n" in mark:
791 raise util.Abort(_("bookmark name cannot contain newlines"))
791 raise util.Abort(_("bookmark name cannot contain newlines"))
792 mark = mark.strip()
792 mark = mark.strip()
793 if not mark:
793 if not mark:
794 raise util.Abort(_("bookmark names cannot consist entirely of "
794 raise util.Abort(_("bookmark names cannot consist entirely of "
795 "whitespace"))
795 "whitespace"))
796 if inactive and mark == repo._bookmarkcurrent:
796 if inactive and mark == repo._bookmarkcurrent:
797 bookmarks.setcurrent(repo, None)
797 bookmarks.setcurrent(repo, None)
798 return
798 return
799 if mark in marks and not force:
799 if mark in marks and not force:
800 raise util.Abort(_("bookmark '%s' already exists "
800 raise util.Abort(_("bookmark '%s' already exists "
801 "(use -f to force)") % mark)
801 "(use -f to force)") % mark)
802 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
802 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
803 and not force):
803 and not force):
804 raise util.Abort(
804 raise util.Abort(
805 _("a bookmark cannot have the name of an existing branch"))
805 _("a bookmark cannot have the name of an existing branch"))
806 if rev:
806 if rev:
807 marks[mark] = repo.lookup(rev)
807 marks[mark] = repo.lookup(rev)
808 else:
808 else:
809 marks[mark] = cur
809 marks[mark] = cur
810 if not inactive and cur == marks[mark]:
810 if not inactive and cur == marks[mark]:
811 bookmarks.setcurrent(repo, mark)
811 bookmarks.setcurrent(repo, mark)
812 bookmarks.write(repo)
812 bookmarks.write(repo)
813 return
813 return
814
814
815 if mark is None:
815 if mark is None:
816 if rev:
816 if rev:
817 raise util.Abort(_("bookmark name required"))
817 raise util.Abort(_("bookmark name required"))
818 if len(marks) == 0:
818 if len(marks) == 0:
819 ui.status(_("no bookmarks set\n"))
819 ui.status(_("no bookmarks set\n"))
820 else:
820 else:
821 for bmark, n in sorted(marks.iteritems()):
821 for bmark, n in sorted(marks.iteritems()):
822 current = repo._bookmarkcurrent
822 current = repo._bookmarkcurrent
823 if bmark == current and n == cur:
823 if bmark == current and n == cur:
824 prefix, label = '*', 'bookmarks.current'
824 prefix, label = '*', 'bookmarks.current'
825 else:
825 else:
826 prefix, label = ' ', ''
826 prefix, label = ' ', ''
827
827
828 if ui.quiet:
828 if ui.quiet:
829 ui.write("%s\n" % bmark, label=label)
829 ui.write("%s\n" % bmark, label=label)
830 else:
830 else:
831 ui.write(" %s %-25s %d:%s\n" % (
831 ui.write(" %s %-25s %d:%s\n" % (
832 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
832 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
833 label=label)
833 label=label)
834 return
834 return
835
835
836 @command('branch',
836 @command('branch',
837 [('f', 'force', None,
837 [('f', 'force', None,
838 _('set branch name even if it shadows an existing branch')),
838 _('set branch name even if it shadows an existing branch')),
839 ('C', 'clean', None, _('reset branch name to parent branch name'))],
839 ('C', 'clean', None, _('reset branch name to parent branch name'))],
840 _('[-fC] [NAME]'))
840 _('[-fC] [NAME]'))
841 def branch(ui, repo, label=None, **opts):
841 def branch(ui, repo, label=None, **opts):
842 """set or show the current branch name
842 """set or show the current branch name
843
843
844 .. note::
844 .. note::
845 Branch names are permanent and global. Use :hg:`bookmark` to create a
845 Branch names are permanent and global. Use :hg:`bookmark` to create a
846 light-weight bookmark instead. See :hg:`help glossary` for more
846 light-weight bookmark instead. See :hg:`help glossary` for more
847 information about named branches and bookmarks.
847 information about named branches and bookmarks.
848
848
849 With no argument, show the current branch name. With one argument,
849 With no argument, show the current branch name. With one argument,
850 set the working directory branch name (the branch will not exist
850 set the working directory branch name (the branch will not exist
851 in the repository until the next commit). Standard practice
851 in the repository until the next commit). Standard practice
852 recommends that primary development take place on the 'default'
852 recommends that primary development take place on the 'default'
853 branch.
853 branch.
854
854
855 Unless -f/--force is specified, branch will not let you set a
855 Unless -f/--force is specified, branch will not let you set a
856 branch name that already exists, even if it's inactive.
856 branch name that already exists, even if it's inactive.
857
857
858 Use -C/--clean to reset the working directory branch to that of
858 Use -C/--clean to reset the working directory branch to that of
859 the parent of the working directory, negating a previous branch
859 the parent of the working directory, negating a previous branch
860 change.
860 change.
861
861
862 Use the command :hg:`update` to switch to an existing branch. Use
862 Use the command :hg:`update` to switch to an existing branch. Use
863 :hg:`commit --close-branch` to mark this branch as closed.
863 :hg:`commit --close-branch` to mark this branch as closed.
864
864
865 Returns 0 on success.
865 Returns 0 on success.
866 """
866 """
867 if not opts.get('clean') and not label:
867 if not opts.get('clean') and not label:
868 ui.write("%s\n" % repo.dirstate.branch())
868 ui.write("%s\n" % repo.dirstate.branch())
869 return
869 return
870
870
871 wlock = repo.wlock()
871 wlock = repo.wlock()
872 try:
872 try:
873 if opts.get('clean'):
873 if opts.get('clean'):
874 label = repo[None].p1().branch()
874 label = repo[None].p1().branch()
875 repo.dirstate.setbranch(label)
875 repo.dirstate.setbranch(label)
876 ui.status(_('reset working directory to branch %s\n') % label)
876 ui.status(_('reset working directory to branch %s\n') % label)
877 elif label:
877 elif label:
878 if not opts.get('force') and label in repo.branchtags():
878 if not opts.get('force') and label in repo.branchtags():
879 if label not in [p.branch() for p in repo.parents()]:
879 if label not in [p.branch() for p in repo.parents()]:
880 raise util.Abort(_('a branch of the same name already'
880 raise util.Abort(_('a branch of the same name already'
881 ' exists'),
881 ' exists'),
882 # i18n: "it" refers to an existing branch
882 # i18n: "it" refers to an existing branch
883 hint=_("use 'hg update' to switch to it"))
883 hint=_("use 'hg update' to switch to it"))
884 repo.dirstate.setbranch(label)
884 repo.dirstate.setbranch(label)
885 ui.status(_('marked working directory as branch %s\n') % label)
885 ui.status(_('marked working directory as branch %s\n') % label)
886 ui.status(_('(branches are permanent and global, '
886 ui.status(_('(branches are permanent and global, '
887 'did you want a bookmark?)\n'))
887 'did you want a bookmark?)\n'))
888 finally:
888 finally:
889 wlock.release()
889 wlock.release()
890
890
891 @command('branches',
891 @command('branches',
892 [('a', 'active', False, _('show only branches that have unmerged heads')),
892 [('a', 'active', False, _('show only branches that have unmerged heads')),
893 ('c', 'closed', False, _('show normal and closed branches'))],
893 ('c', 'closed', False, _('show normal and closed branches'))],
894 _('[-ac]'))
894 _('[-ac]'))
895 def branches(ui, repo, active=False, closed=False):
895 def branches(ui, repo, active=False, closed=False):
896 """list repository named branches
896 """list repository named branches
897
897
898 List the repository's named branches, indicating which ones are
898 List the repository's named branches, indicating which ones are
899 inactive. If -c/--closed is specified, also list branches which have
899 inactive. If -c/--closed is specified, also list branches which have
900 been marked closed (see :hg:`commit --close-branch`).
900 been marked closed (see :hg:`commit --close-branch`).
901
901
902 If -a/--active is specified, only show active branches. A branch
902 If -a/--active is specified, only show active branches. A branch
903 is considered active if it contains repository heads.
903 is considered active if it contains repository heads.
904
904
905 Use the command :hg:`update` to switch to an existing branch.
905 Use the command :hg:`update` to switch to an existing branch.
906
906
907 Returns 0.
907 Returns 0.
908 """
908 """
909
909
910 hexfunc = ui.debugflag and hex or short
910 hexfunc = ui.debugflag and hex or short
911 activebranches = [repo[n].branch() for n in repo.heads()]
911 activebranches = [repo[n].branch() for n in repo.heads()]
912 def testactive(tag, node):
912 def testactive(tag, node):
913 realhead = tag in activebranches
913 realhead = tag in activebranches
914 open = node in repo.branchheads(tag, closed=False)
914 open = node in repo.branchheads(tag, closed=False)
915 return realhead and open
915 return realhead and open
916 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
916 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
917 for tag, node in repo.branchtags().items()],
917 for tag, node in repo.branchtags().items()],
918 reverse=True)
918 reverse=True)
919
919
920 for isactive, node, tag in branches:
920 for isactive, node, tag in branches:
921 if (not active) or isactive:
921 if (not active) or isactive:
922 hn = repo.lookup(node)
923 if isactive:
924 label = 'branches.active'
925 notice = ''
926 elif hn not in repo.branchheads(tag, closed=False):
927 if not closed:
928 continue
929 label = 'branches.closed'
930 notice = _(' (closed)')
931 else:
932 label = 'branches.inactive'
933 notice = _(' (inactive)')
934 if tag == repo.dirstate.branch():
935 label = 'branches.current'
936 rev = str(node).rjust(31 - encoding.colwidth(tag))
937 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
938 tag = ui.label(tag, label)
922 if ui.quiet:
939 if ui.quiet:
923 ui.write("%s\n" % tag)
940 ui.write("%s\n" % tag)
924 else:
941 else:
925 hn = repo.lookup(node)
926 if isactive:
927 label = 'branches.active'
928 notice = ''
929 elif hn not in repo.branchheads(tag, closed=False):
930 if not closed:
931 continue
932 label = 'branches.closed'
933 notice = _(' (closed)')
934 else:
935 label = 'branches.inactive'
936 notice = _(' (inactive)')
937 if tag == repo.dirstate.branch():
938 label = 'branches.current'
939 rev = str(node).rjust(31 - encoding.colwidth(tag))
940 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
941 tag = ui.label(tag, label)
942 ui.write("%s %s%s\n" % (tag, rev, notice))
942 ui.write("%s %s%s\n" % (tag, rev, notice))
943
943
944 @command('bundle',
944 @command('bundle',
945 [('f', 'force', None, _('run even when the destination is unrelated')),
945 [('f', 'force', None, _('run even when the destination is unrelated')),
946 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
946 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
947 _('REV')),
947 _('REV')),
948 ('b', 'branch', [], _('a specific branch you would like to bundle'),
948 ('b', 'branch', [], _('a specific branch you would like to bundle'),
949 _('BRANCH')),
949 _('BRANCH')),
950 ('', 'base', [],
950 ('', 'base', [],
951 _('a base changeset assumed to be available at the destination'),
951 _('a base changeset assumed to be available at the destination'),
952 _('REV')),
952 _('REV')),
953 ('a', 'all', None, _('bundle all changesets in the repository')),
953 ('a', 'all', None, _('bundle all changesets in the repository')),
954 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
954 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
955 ] + remoteopts,
955 ] + remoteopts,
956 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
956 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
957 def bundle(ui, repo, fname, dest=None, **opts):
957 def bundle(ui, repo, fname, dest=None, **opts):
958 """create a changegroup file
958 """create a changegroup file
959
959
960 Generate a compressed changegroup file collecting changesets not
960 Generate a compressed changegroup file collecting changesets not
961 known to be in another repository.
961 known to be in another repository.
962
962
963 If you omit the destination repository, then hg assumes the
963 If you omit the destination repository, then hg assumes the
964 destination will have all the nodes you specify with --base
964 destination will have all the nodes you specify with --base
965 parameters. To create a bundle containing all changesets, use
965 parameters. To create a bundle containing all changesets, use
966 -a/--all (or --base null).
966 -a/--all (or --base null).
967
967
968 You can change compression method with the -t/--type option.
968 You can change compression method with the -t/--type option.
969 The available compression methods are: none, bzip2, and
969 The available compression methods are: none, bzip2, and
970 gzip (by default, bundles are compressed using bzip2).
970 gzip (by default, bundles are compressed using bzip2).
971
971
972 The bundle file can then be transferred using conventional means
972 The bundle file can then be transferred using conventional means
973 and applied to another repository with the unbundle or pull
973 and applied to another repository with the unbundle or pull
974 command. This is useful when direct push and pull are not
974 command. This is useful when direct push and pull are not
975 available or when exporting an entire repository is undesirable.
975 available or when exporting an entire repository is undesirable.
976
976
977 Applying bundles preserves all changeset contents including
977 Applying bundles preserves all changeset contents including
978 permissions, copy/rename information, and revision history.
978 permissions, copy/rename information, and revision history.
979
979
980 Returns 0 on success, 1 if no changes found.
980 Returns 0 on success, 1 if no changes found.
981 """
981 """
982 revs = None
982 revs = None
983 if 'rev' in opts:
983 if 'rev' in opts:
984 revs = scmutil.revrange(repo, opts['rev'])
984 revs = scmutil.revrange(repo, opts['rev'])
985
985
986 bundletype = opts.get('type', 'bzip2').lower()
986 bundletype = opts.get('type', 'bzip2').lower()
987 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
987 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
988 bundletype = btypes.get(bundletype)
988 bundletype = btypes.get(bundletype)
989 if bundletype not in changegroup.bundletypes:
989 if bundletype not in changegroup.bundletypes:
990 raise util.Abort(_('unknown bundle type specified with --type'))
990 raise util.Abort(_('unknown bundle type specified with --type'))
991
991
992 if opts.get('all'):
992 if opts.get('all'):
993 base = ['null']
993 base = ['null']
994 else:
994 else:
995 base = scmutil.revrange(repo, opts.get('base'))
995 base = scmutil.revrange(repo, opts.get('base'))
996 if base:
996 if base:
997 if dest:
997 if dest:
998 raise util.Abort(_("--base is incompatible with specifying "
998 raise util.Abort(_("--base is incompatible with specifying "
999 "a destination"))
999 "a destination"))
1000 common = [repo.lookup(rev) for rev in base]
1000 common = [repo.lookup(rev) for rev in base]
1001 heads = revs and map(repo.lookup, revs) or revs
1001 heads = revs and map(repo.lookup, revs) or revs
1002 cg = repo.getbundle('bundle', heads=heads, common=common)
1002 cg = repo.getbundle('bundle', heads=heads, common=common)
1003 outgoing = None
1003 outgoing = None
1004 else:
1004 else:
1005 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1005 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1006 dest, branches = hg.parseurl(dest, opts.get('branch'))
1006 dest, branches = hg.parseurl(dest, opts.get('branch'))
1007 other = hg.peer(repo, opts, dest)
1007 other = hg.peer(repo, opts, dest)
1008 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1008 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1009 heads = revs and map(repo.lookup, revs) or revs
1009 heads = revs and map(repo.lookup, revs) or revs
1010 outgoing = discovery.findcommonoutgoing(repo, other,
1010 outgoing = discovery.findcommonoutgoing(repo, other,
1011 onlyheads=heads,
1011 onlyheads=heads,
1012 force=opts.get('force'))
1012 force=opts.get('force'))
1013 cg = repo.getlocalbundle('bundle', outgoing)
1013 cg = repo.getlocalbundle('bundle', outgoing)
1014 if not cg:
1014 if not cg:
1015 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1015 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1016 return 1
1016 return 1
1017
1017
1018 changegroup.writebundle(cg, fname, bundletype)
1018 changegroup.writebundle(cg, fname, bundletype)
1019
1019
1020 @command('cat',
1020 @command('cat',
1021 [('o', 'output', '',
1021 [('o', 'output', '',
1022 _('print output to file with formatted name'), _('FORMAT')),
1022 _('print output to file with formatted name'), _('FORMAT')),
1023 ('r', 'rev', '', _('print the given revision'), _('REV')),
1023 ('r', 'rev', '', _('print the given revision'), _('REV')),
1024 ('', 'decode', None, _('apply any matching decode filter')),
1024 ('', 'decode', None, _('apply any matching decode filter')),
1025 ] + walkopts,
1025 ] + walkopts,
1026 _('[OPTION]... FILE...'))
1026 _('[OPTION]... FILE...'))
1027 def cat(ui, repo, file1, *pats, **opts):
1027 def cat(ui, repo, file1, *pats, **opts):
1028 """output the current or given revision of files
1028 """output the current or given revision of files
1029
1029
1030 Print the specified files as they were at the given revision. If
1030 Print the specified files as they were at the given revision. If
1031 no revision is given, the parent of the working directory is used,
1031 no revision is given, the parent of the working directory is used,
1032 or tip if no revision is checked out.
1032 or tip if no revision is checked out.
1033
1033
1034 Output may be to a file, in which case the name of the file is
1034 Output may be to a file, in which case the name of the file is
1035 given using a format string. The formatting rules are the same as
1035 given using a format string. The formatting rules are the same as
1036 for the export command, with the following additions:
1036 for the export command, with the following additions:
1037
1037
1038 :``%s``: basename of file being printed
1038 :``%s``: basename of file being printed
1039 :``%d``: dirname of file being printed, or '.' if in repository root
1039 :``%d``: dirname of file being printed, or '.' if in repository root
1040 :``%p``: root-relative path name of file being printed
1040 :``%p``: root-relative path name of file being printed
1041
1041
1042 Returns 0 on success.
1042 Returns 0 on success.
1043 """
1043 """
1044 ctx = scmutil.revsingle(repo, opts.get('rev'))
1044 ctx = scmutil.revsingle(repo, opts.get('rev'))
1045 err = 1
1045 err = 1
1046 m = scmutil.match(ctx, (file1,) + pats, opts)
1046 m = scmutil.match(ctx, (file1,) + pats, opts)
1047 for abs in ctx.walk(m):
1047 for abs in ctx.walk(m):
1048 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1048 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1049 pathname=abs)
1049 pathname=abs)
1050 data = ctx[abs].data()
1050 data = ctx[abs].data()
1051 if opts.get('decode'):
1051 if opts.get('decode'):
1052 data = repo.wwritedata(abs, data)
1052 data = repo.wwritedata(abs, data)
1053 fp.write(data)
1053 fp.write(data)
1054 fp.close()
1054 fp.close()
1055 err = 0
1055 err = 0
1056 return err
1056 return err
1057
1057
1058 @command('^clone',
1058 @command('^clone',
1059 [('U', 'noupdate', None,
1059 [('U', 'noupdate', None,
1060 _('the clone will include an empty working copy (only a repository)')),
1060 _('the clone will include an empty working copy (only a repository)')),
1061 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1061 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1062 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1062 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1063 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1063 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1064 ('', 'pull', None, _('use pull protocol to copy metadata')),
1064 ('', 'pull', None, _('use pull protocol to copy metadata')),
1065 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1065 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1066 ] + remoteopts,
1066 ] + remoteopts,
1067 _('[OPTION]... SOURCE [DEST]'))
1067 _('[OPTION]... SOURCE [DEST]'))
1068 def clone(ui, source, dest=None, **opts):
1068 def clone(ui, source, dest=None, **opts):
1069 """make a copy of an existing repository
1069 """make a copy of an existing repository
1070
1070
1071 Create a copy of an existing repository in a new directory.
1071 Create a copy of an existing repository in a new directory.
1072
1072
1073 If no destination directory name is specified, it defaults to the
1073 If no destination directory name is specified, it defaults to the
1074 basename of the source.
1074 basename of the source.
1075
1075
1076 The location of the source is added to the new repository's
1076 The location of the source is added to the new repository's
1077 ``.hg/hgrc`` file, as the default to be used for future pulls.
1077 ``.hg/hgrc`` file, as the default to be used for future pulls.
1078
1078
1079 Only local paths and ``ssh://`` URLs are supported as
1079 Only local paths and ``ssh://`` URLs are supported as
1080 destinations. For ``ssh://`` destinations, no working directory or
1080 destinations. For ``ssh://`` destinations, no working directory or
1081 ``.hg/hgrc`` will be created on the remote side.
1081 ``.hg/hgrc`` will be created on the remote side.
1082
1082
1083 To pull only a subset of changesets, specify one or more revisions
1083 To pull only a subset of changesets, specify one or more revisions
1084 identifiers with -r/--rev or branches with -b/--branch. The
1084 identifiers with -r/--rev or branches with -b/--branch. The
1085 resulting clone will contain only the specified changesets and
1085 resulting clone will contain only the specified changesets and
1086 their ancestors. These options (or 'clone src#rev dest') imply
1086 their ancestors. These options (or 'clone src#rev dest') imply
1087 --pull, even for local source repositories. Note that specifying a
1087 --pull, even for local source repositories. Note that specifying a
1088 tag will include the tagged changeset but not the changeset
1088 tag will include the tagged changeset but not the changeset
1089 containing the tag.
1089 containing the tag.
1090
1090
1091 To check out a particular version, use -u/--update, or
1091 To check out a particular version, use -u/--update, or
1092 -U/--noupdate to create a clone with no working directory.
1092 -U/--noupdate to create a clone with no working directory.
1093
1093
1094 .. container:: verbose
1094 .. container:: verbose
1095
1095
1096 For efficiency, hardlinks are used for cloning whenever the
1096 For efficiency, hardlinks are used for cloning whenever the
1097 source and destination are on the same filesystem (note this
1097 source and destination are on the same filesystem (note this
1098 applies only to the repository data, not to the working
1098 applies only to the repository data, not to the working
1099 directory). Some filesystems, such as AFS, implement hardlinking
1099 directory). Some filesystems, such as AFS, implement hardlinking
1100 incorrectly, but do not report errors. In these cases, use the
1100 incorrectly, but do not report errors. In these cases, use the
1101 --pull option to avoid hardlinking.
1101 --pull option to avoid hardlinking.
1102
1102
1103 In some cases, you can clone repositories and the working
1103 In some cases, you can clone repositories and the working
1104 directory using full hardlinks with ::
1104 directory using full hardlinks with ::
1105
1105
1106 $ cp -al REPO REPOCLONE
1106 $ cp -al REPO REPOCLONE
1107
1107
1108 This is the fastest way to clone, but it is not always safe. The
1108 This is the fastest way to clone, but it is not always safe. The
1109 operation is not atomic (making sure REPO is not modified during
1109 operation is not atomic (making sure REPO is not modified during
1110 the operation is up to you) and you have to make sure your
1110 the operation is up to you) and you have to make sure your
1111 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1111 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1112 so). Also, this is not compatible with certain extensions that
1112 so). Also, this is not compatible with certain extensions that
1113 place their metadata under the .hg directory, such as mq.
1113 place their metadata under the .hg directory, such as mq.
1114
1114
1115 Mercurial will update the working directory to the first applicable
1115 Mercurial will update the working directory to the first applicable
1116 revision from this list:
1116 revision from this list:
1117
1117
1118 a) null if -U or the source repository has no changesets
1118 a) null if -U or the source repository has no changesets
1119 b) if -u . and the source repository is local, the first parent of
1119 b) if -u . and the source repository is local, the first parent of
1120 the source repository's working directory
1120 the source repository's working directory
1121 c) the changeset specified with -u (if a branch name, this means the
1121 c) the changeset specified with -u (if a branch name, this means the
1122 latest head of that branch)
1122 latest head of that branch)
1123 d) the changeset specified with -r
1123 d) the changeset specified with -r
1124 e) the tipmost head specified with -b
1124 e) the tipmost head specified with -b
1125 f) the tipmost head specified with the url#branch source syntax
1125 f) the tipmost head specified with the url#branch source syntax
1126 g) the tipmost head of the default branch
1126 g) the tipmost head of the default branch
1127 h) tip
1127 h) tip
1128
1128
1129 Examples:
1129 Examples:
1130
1130
1131 - clone a remote repository to a new directory named hg/::
1131 - clone a remote repository to a new directory named hg/::
1132
1132
1133 hg clone http://selenic.com/hg
1133 hg clone http://selenic.com/hg
1134
1134
1135 - create a lightweight local clone::
1135 - create a lightweight local clone::
1136
1136
1137 hg clone project/ project-feature/
1137 hg clone project/ project-feature/
1138
1138
1139 - clone from an absolute path on an ssh server (note double-slash)::
1139 - clone from an absolute path on an ssh server (note double-slash)::
1140
1140
1141 hg clone ssh://user@server//home/projects/alpha/
1141 hg clone ssh://user@server//home/projects/alpha/
1142
1142
1143 - do a high-speed clone over a LAN while checking out a
1143 - do a high-speed clone over a LAN while checking out a
1144 specified version::
1144 specified version::
1145
1145
1146 hg clone --uncompressed http://server/repo -u 1.5
1146 hg clone --uncompressed http://server/repo -u 1.5
1147
1147
1148 - create a repository without changesets after a particular revision::
1148 - create a repository without changesets after a particular revision::
1149
1149
1150 hg clone -r 04e544 experimental/ good/
1150 hg clone -r 04e544 experimental/ good/
1151
1151
1152 - clone (and track) a particular named branch::
1152 - clone (and track) a particular named branch::
1153
1153
1154 hg clone http://selenic.com/hg#stable
1154 hg clone http://selenic.com/hg#stable
1155
1155
1156 See :hg:`help urls` for details on specifying URLs.
1156 See :hg:`help urls` for details on specifying URLs.
1157
1157
1158 Returns 0 on success.
1158 Returns 0 on success.
1159 """
1159 """
1160 if opts.get('noupdate') and opts.get('updaterev'):
1160 if opts.get('noupdate') and opts.get('updaterev'):
1161 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1161 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1162
1162
1163 r = hg.clone(ui, opts, source, dest,
1163 r = hg.clone(ui, opts, source, dest,
1164 pull=opts.get('pull'),
1164 pull=opts.get('pull'),
1165 stream=opts.get('uncompressed'),
1165 stream=opts.get('uncompressed'),
1166 rev=opts.get('rev'),
1166 rev=opts.get('rev'),
1167 update=opts.get('updaterev') or not opts.get('noupdate'),
1167 update=opts.get('updaterev') or not opts.get('noupdate'),
1168 branch=opts.get('branch'))
1168 branch=opts.get('branch'))
1169
1169
1170 return r is None
1170 return r is None
1171
1171
1172 @command('^commit|ci',
1172 @command('^commit|ci',
1173 [('A', 'addremove', None,
1173 [('A', 'addremove', None,
1174 _('mark new/missing files as added/removed before committing')),
1174 _('mark new/missing files as added/removed before committing')),
1175 ('', 'close-branch', None,
1175 ('', 'close-branch', None,
1176 _('mark a branch as closed, hiding it from the branch list')),
1176 _('mark a branch as closed, hiding it from the branch list')),
1177 ('', 'amend', None, _('amend the parent of the working dir')),
1177 ('', 'amend', None, _('amend the parent of the working dir')),
1178 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1178 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1179 _('[OPTION]... [FILE]...'))
1179 _('[OPTION]... [FILE]...'))
1180 def commit(ui, repo, *pats, **opts):
1180 def commit(ui, repo, *pats, **opts):
1181 """commit the specified files or all outstanding changes
1181 """commit the specified files or all outstanding changes
1182
1182
1183 Commit changes to the given files into the repository. Unlike a
1183 Commit changes to the given files into the repository. Unlike a
1184 centralized SCM, this operation is a local operation. See
1184 centralized SCM, this operation is a local operation. See
1185 :hg:`push` for a way to actively distribute your changes.
1185 :hg:`push` for a way to actively distribute your changes.
1186
1186
1187 If a list of files is omitted, all changes reported by :hg:`status`
1187 If a list of files is omitted, all changes reported by :hg:`status`
1188 will be committed.
1188 will be committed.
1189
1189
1190 If you are committing the result of a merge, do not provide any
1190 If you are committing the result of a merge, do not provide any
1191 filenames or -I/-X filters.
1191 filenames or -I/-X filters.
1192
1192
1193 If no commit message is specified, Mercurial starts your
1193 If no commit message is specified, Mercurial starts your
1194 configured editor where you can enter a message. In case your
1194 configured editor where you can enter a message. In case your
1195 commit fails, you will find a backup of your message in
1195 commit fails, you will find a backup of your message in
1196 ``.hg/last-message.txt``.
1196 ``.hg/last-message.txt``.
1197
1197
1198 The --amend flag can be used to amend the parent of the
1198 The --amend flag can be used to amend the parent of the
1199 working directory with a new commit that contains the changes
1199 working directory with a new commit that contains the changes
1200 in the parent in addition to those currently reported by :hg:`status`,
1200 in the parent in addition to those currently reported by :hg:`status`,
1201 if there are any. The old commit is stored in a backup bundle in
1201 if there are any. The old commit is stored in a backup bundle in
1202 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1202 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1203 on how to restore it).
1203 on how to restore it).
1204
1204
1205 Message, user and date are taken from the amended commit unless
1205 Message, user and date are taken from the amended commit unless
1206 specified. When a message isn't specified on the command line,
1206 specified. When a message isn't specified on the command line,
1207 the editor will open with the message of the amended commit.
1207 the editor will open with the message of the amended commit.
1208
1208
1209 It is not possible to amend public changesets (see :hg:`help phases`)
1209 It is not possible to amend public changesets (see :hg:`help phases`)
1210 or changesets that have children.
1210 or changesets that have children.
1211
1211
1212 See :hg:`help dates` for a list of formats valid for -d/--date.
1212 See :hg:`help dates` for a list of formats valid for -d/--date.
1213
1213
1214 Returns 0 on success, 1 if nothing changed.
1214 Returns 0 on success, 1 if nothing changed.
1215 """
1215 """
1216 if opts.get('subrepos'):
1216 if opts.get('subrepos'):
1217 # Let --subrepos on the command line overide config setting.
1217 # Let --subrepos on the command line overide config setting.
1218 ui.setconfig('ui', 'commitsubrepos', True)
1218 ui.setconfig('ui', 'commitsubrepos', True)
1219
1219
1220 extra = {}
1220 extra = {}
1221 if opts.get('close_branch'):
1221 if opts.get('close_branch'):
1222 if repo['.'].node() not in repo.branchheads():
1222 if repo['.'].node() not in repo.branchheads():
1223 # The topo heads set is included in the branch heads set of the
1223 # The topo heads set is included in the branch heads set of the
1224 # current branch, so it's sufficient to test branchheads
1224 # current branch, so it's sufficient to test branchheads
1225 raise util.Abort(_('can only close branch heads'))
1225 raise util.Abort(_('can only close branch heads'))
1226 extra['close'] = 1
1226 extra['close'] = 1
1227
1227
1228 branch = repo[None].branch()
1228 branch = repo[None].branch()
1229 bheads = repo.branchheads(branch)
1229 bheads = repo.branchheads(branch)
1230
1230
1231 if opts.get('amend'):
1231 if opts.get('amend'):
1232 if ui.configbool('ui', 'commitsubrepos'):
1232 if ui.configbool('ui', 'commitsubrepos'):
1233 raise util.Abort(_('cannot amend recursively'))
1233 raise util.Abort(_('cannot amend recursively'))
1234
1234
1235 old = repo['.']
1235 old = repo['.']
1236 if old.phase() == phases.public:
1236 if old.phase() == phases.public:
1237 raise util.Abort(_('cannot amend public changesets'))
1237 raise util.Abort(_('cannot amend public changesets'))
1238 if len(old.parents()) > 1:
1238 if len(old.parents()) > 1:
1239 raise util.Abort(_('cannot amend merge changesets'))
1239 raise util.Abort(_('cannot amend merge changesets'))
1240 if len(repo[None].parents()) > 1:
1240 if len(repo[None].parents()) > 1:
1241 raise util.Abort(_('cannot amend while merging'))
1241 raise util.Abort(_('cannot amend while merging'))
1242 if old.children():
1242 if old.children():
1243 raise util.Abort(_('cannot amend changeset with children'))
1243 raise util.Abort(_('cannot amend changeset with children'))
1244
1244
1245 e = cmdutil.commiteditor
1245 e = cmdutil.commiteditor
1246 if opts.get('force_editor'):
1246 if opts.get('force_editor'):
1247 e = cmdutil.commitforceeditor
1247 e = cmdutil.commitforceeditor
1248
1248
1249 def commitfunc(ui, repo, message, match, opts):
1249 def commitfunc(ui, repo, message, match, opts):
1250 editor = e
1250 editor = e
1251 # message contains text from -m or -l, if it's empty,
1251 # message contains text from -m or -l, if it's empty,
1252 # open the editor with the old message
1252 # open the editor with the old message
1253 if not message:
1253 if not message:
1254 message = old.description()
1254 message = old.description()
1255 editor = cmdutil.commitforceeditor
1255 editor = cmdutil.commitforceeditor
1256 return repo.commit(message,
1256 return repo.commit(message,
1257 opts.get('user') or old.user(),
1257 opts.get('user') or old.user(),
1258 opts.get('date') or old.date(),
1258 opts.get('date') or old.date(),
1259 match,
1259 match,
1260 editor=editor,
1260 editor=editor,
1261 extra=extra)
1261 extra=extra)
1262
1262
1263 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1263 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1264 if node == old.node():
1264 if node == old.node():
1265 ui.status(_("nothing changed\n"))
1265 ui.status(_("nothing changed\n"))
1266 return 1
1266 return 1
1267 else:
1267 else:
1268 e = cmdutil.commiteditor
1268 e = cmdutil.commiteditor
1269 if opts.get('force_editor'):
1269 if opts.get('force_editor'):
1270 e = cmdutil.commitforceeditor
1270 e = cmdutil.commitforceeditor
1271
1271
1272 def commitfunc(ui, repo, message, match, opts):
1272 def commitfunc(ui, repo, message, match, opts):
1273 return repo.commit(message, opts.get('user'), opts.get('date'),
1273 return repo.commit(message, opts.get('user'), opts.get('date'),
1274 match, editor=e, extra=extra)
1274 match, editor=e, extra=extra)
1275
1275
1276 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1276 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1277
1277
1278 if not node:
1278 if not node:
1279 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1279 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1280 if stat[3]:
1280 if stat[3]:
1281 ui.status(_("nothing changed (%d missing files, see "
1281 ui.status(_("nothing changed (%d missing files, see "
1282 "'hg status')\n") % len(stat[3]))
1282 "'hg status')\n") % len(stat[3]))
1283 else:
1283 else:
1284 ui.status(_("nothing changed\n"))
1284 ui.status(_("nothing changed\n"))
1285 return 1
1285 return 1
1286
1286
1287 ctx = repo[node]
1287 ctx = repo[node]
1288 parents = ctx.parents()
1288 parents = ctx.parents()
1289
1289
1290 if (not opts.get('amend') and bheads and node not in bheads and not
1290 if (not opts.get('amend') and bheads and node not in bheads and not
1291 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1291 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1292 ui.status(_('created new head\n'))
1292 ui.status(_('created new head\n'))
1293 # The message is not printed for initial roots. For the other
1293 # The message is not printed for initial roots. For the other
1294 # changesets, it is printed in the following situations:
1294 # changesets, it is printed in the following situations:
1295 #
1295 #
1296 # Par column: for the 2 parents with ...
1296 # Par column: for the 2 parents with ...
1297 # N: null or no parent
1297 # N: null or no parent
1298 # B: parent is on another named branch
1298 # B: parent is on another named branch
1299 # C: parent is a regular non head changeset
1299 # C: parent is a regular non head changeset
1300 # H: parent was a branch head of the current branch
1300 # H: parent was a branch head of the current branch
1301 # Msg column: whether we print "created new head" message
1301 # Msg column: whether we print "created new head" message
1302 # In the following, it is assumed that there already exists some
1302 # In the following, it is assumed that there already exists some
1303 # initial branch heads of the current branch, otherwise nothing is
1303 # initial branch heads of the current branch, otherwise nothing is
1304 # printed anyway.
1304 # printed anyway.
1305 #
1305 #
1306 # Par Msg Comment
1306 # Par Msg Comment
1307 # NN y additional topo root
1307 # NN y additional topo root
1308 #
1308 #
1309 # BN y additional branch root
1309 # BN y additional branch root
1310 # CN y additional topo head
1310 # CN y additional topo head
1311 # HN n usual case
1311 # HN n usual case
1312 #
1312 #
1313 # BB y weird additional branch root
1313 # BB y weird additional branch root
1314 # CB y branch merge
1314 # CB y branch merge
1315 # HB n merge with named branch
1315 # HB n merge with named branch
1316 #
1316 #
1317 # CC y additional head from merge
1317 # CC y additional head from merge
1318 # CH n merge with a head
1318 # CH n merge with a head
1319 #
1319 #
1320 # HH n head merge: head count decreases
1320 # HH n head merge: head count decreases
1321
1321
1322 if not opts.get('close_branch'):
1322 if not opts.get('close_branch'):
1323 for r in parents:
1323 for r in parents:
1324 if r.extra().get('close') and r.branch() == branch:
1324 if r.extra().get('close') and r.branch() == branch:
1325 ui.status(_('reopening closed branch head %d\n') % r)
1325 ui.status(_('reopening closed branch head %d\n') % r)
1326
1326
1327 if ui.debugflag:
1327 if ui.debugflag:
1328 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1328 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1329 elif ui.verbose:
1329 elif ui.verbose:
1330 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1330 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1331
1331
1332 @command('copy|cp',
1332 @command('copy|cp',
1333 [('A', 'after', None, _('record a copy that has already occurred')),
1333 [('A', 'after', None, _('record a copy that has already occurred')),
1334 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1334 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1335 ] + walkopts + dryrunopts,
1335 ] + walkopts + dryrunopts,
1336 _('[OPTION]... [SOURCE]... DEST'))
1336 _('[OPTION]... [SOURCE]... DEST'))
1337 def copy(ui, repo, *pats, **opts):
1337 def copy(ui, repo, *pats, **opts):
1338 """mark files as copied for the next commit
1338 """mark files as copied for the next commit
1339
1339
1340 Mark dest as having copies of source files. If dest is a
1340 Mark dest as having copies of source files. If dest is a
1341 directory, copies are put in that directory. If dest is a file,
1341 directory, copies are put in that directory. If dest is a file,
1342 the source must be a single file.
1342 the source must be a single file.
1343
1343
1344 By default, this command copies the contents of files as they
1344 By default, this command copies the contents of files as they
1345 exist in the working directory. If invoked with -A/--after, the
1345 exist in the working directory. If invoked with -A/--after, the
1346 operation is recorded, but no copying is performed.
1346 operation is recorded, but no copying is performed.
1347
1347
1348 This command takes effect with the next commit. To undo a copy
1348 This command takes effect with the next commit. To undo a copy
1349 before that, see :hg:`revert`.
1349 before that, see :hg:`revert`.
1350
1350
1351 Returns 0 on success, 1 if errors are encountered.
1351 Returns 0 on success, 1 if errors are encountered.
1352 """
1352 """
1353 wlock = repo.wlock(False)
1353 wlock = repo.wlock(False)
1354 try:
1354 try:
1355 return cmdutil.copy(ui, repo, pats, opts)
1355 return cmdutil.copy(ui, repo, pats, opts)
1356 finally:
1356 finally:
1357 wlock.release()
1357 wlock.release()
1358
1358
1359 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1359 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1360 def debugancestor(ui, repo, *args):
1360 def debugancestor(ui, repo, *args):
1361 """find the ancestor revision of two revisions in a given index"""
1361 """find the ancestor revision of two revisions in a given index"""
1362 if len(args) == 3:
1362 if len(args) == 3:
1363 index, rev1, rev2 = args
1363 index, rev1, rev2 = args
1364 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1364 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1365 lookup = r.lookup
1365 lookup = r.lookup
1366 elif len(args) == 2:
1366 elif len(args) == 2:
1367 if not repo:
1367 if not repo:
1368 raise util.Abort(_("there is no Mercurial repository here "
1368 raise util.Abort(_("there is no Mercurial repository here "
1369 "(.hg not found)"))
1369 "(.hg not found)"))
1370 rev1, rev2 = args
1370 rev1, rev2 = args
1371 r = repo.changelog
1371 r = repo.changelog
1372 lookup = repo.lookup
1372 lookup = repo.lookup
1373 else:
1373 else:
1374 raise util.Abort(_('either two or three arguments required'))
1374 raise util.Abort(_('either two or three arguments required'))
1375 a = r.ancestor(lookup(rev1), lookup(rev2))
1375 a = r.ancestor(lookup(rev1), lookup(rev2))
1376 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1376 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1377
1377
1378 @command('debugbuilddag',
1378 @command('debugbuilddag',
1379 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1379 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1380 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1380 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1381 ('n', 'new-file', None, _('add new file at each rev'))],
1381 ('n', 'new-file', None, _('add new file at each rev'))],
1382 _('[OPTION]... [TEXT]'))
1382 _('[OPTION]... [TEXT]'))
1383 def debugbuilddag(ui, repo, text=None,
1383 def debugbuilddag(ui, repo, text=None,
1384 mergeable_file=False,
1384 mergeable_file=False,
1385 overwritten_file=False,
1385 overwritten_file=False,
1386 new_file=False):
1386 new_file=False):
1387 """builds a repo with a given DAG from scratch in the current empty repo
1387 """builds a repo with a given DAG from scratch in the current empty repo
1388
1388
1389 The description of the DAG is read from stdin if not given on the
1389 The description of the DAG is read from stdin if not given on the
1390 command line.
1390 command line.
1391
1391
1392 Elements:
1392 Elements:
1393
1393
1394 - "+n" is a linear run of n nodes based on the current default parent
1394 - "+n" is a linear run of n nodes based on the current default parent
1395 - "." is a single node based on the current default parent
1395 - "." is a single node based on the current default parent
1396 - "$" resets the default parent to null (implied at the start);
1396 - "$" resets the default parent to null (implied at the start);
1397 otherwise the default parent is always the last node created
1397 otherwise the default parent is always the last node created
1398 - "<p" sets the default parent to the backref p
1398 - "<p" sets the default parent to the backref p
1399 - "*p" is a fork at parent p, which is a backref
1399 - "*p" is a fork at parent p, which is a backref
1400 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1400 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1401 - "/p2" is a merge of the preceding node and p2
1401 - "/p2" is a merge of the preceding node and p2
1402 - ":tag" defines a local tag for the preceding node
1402 - ":tag" defines a local tag for the preceding node
1403 - "@branch" sets the named branch for subsequent nodes
1403 - "@branch" sets the named branch for subsequent nodes
1404 - "#...\\n" is a comment up to the end of the line
1404 - "#...\\n" is a comment up to the end of the line
1405
1405
1406 Whitespace between the above elements is ignored.
1406 Whitespace between the above elements is ignored.
1407
1407
1408 A backref is either
1408 A backref is either
1409
1409
1410 - a number n, which references the node curr-n, where curr is the current
1410 - a number n, which references the node curr-n, where curr is the current
1411 node, or
1411 node, or
1412 - the name of a local tag you placed earlier using ":tag", or
1412 - the name of a local tag you placed earlier using ":tag", or
1413 - empty to denote the default parent.
1413 - empty to denote the default parent.
1414
1414
1415 All string valued-elements are either strictly alphanumeric, or must
1415 All string valued-elements are either strictly alphanumeric, or must
1416 be enclosed in double quotes ("..."), with "\\" as escape character.
1416 be enclosed in double quotes ("..."), with "\\" as escape character.
1417 """
1417 """
1418
1418
1419 if text is None:
1419 if text is None:
1420 ui.status(_("reading DAG from stdin\n"))
1420 ui.status(_("reading DAG from stdin\n"))
1421 text = ui.fin.read()
1421 text = ui.fin.read()
1422
1422
1423 cl = repo.changelog
1423 cl = repo.changelog
1424 if len(cl) > 0:
1424 if len(cl) > 0:
1425 raise util.Abort(_('repository is not empty'))
1425 raise util.Abort(_('repository is not empty'))
1426
1426
1427 # determine number of revs in DAG
1427 # determine number of revs in DAG
1428 total = 0
1428 total = 0
1429 for type, data in dagparser.parsedag(text):
1429 for type, data in dagparser.parsedag(text):
1430 if type == 'n':
1430 if type == 'n':
1431 total += 1
1431 total += 1
1432
1432
1433 if mergeable_file:
1433 if mergeable_file:
1434 linesperrev = 2
1434 linesperrev = 2
1435 # make a file with k lines per rev
1435 # make a file with k lines per rev
1436 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1436 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1437 initialmergedlines.append("")
1437 initialmergedlines.append("")
1438
1438
1439 tags = []
1439 tags = []
1440
1440
1441 lock = tr = None
1441 lock = tr = None
1442 try:
1442 try:
1443 lock = repo.lock()
1443 lock = repo.lock()
1444 tr = repo.transaction("builddag")
1444 tr = repo.transaction("builddag")
1445
1445
1446 at = -1
1446 at = -1
1447 atbranch = 'default'
1447 atbranch = 'default'
1448 nodeids = []
1448 nodeids = []
1449 id = 0
1449 id = 0
1450 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1450 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1451 for type, data in dagparser.parsedag(text):
1451 for type, data in dagparser.parsedag(text):
1452 if type == 'n':
1452 if type == 'n':
1453 ui.note('node %s\n' % str(data))
1453 ui.note('node %s\n' % str(data))
1454 id, ps = data
1454 id, ps = data
1455
1455
1456 files = []
1456 files = []
1457 fctxs = {}
1457 fctxs = {}
1458
1458
1459 p2 = None
1459 p2 = None
1460 if mergeable_file:
1460 if mergeable_file:
1461 fn = "mf"
1461 fn = "mf"
1462 p1 = repo[ps[0]]
1462 p1 = repo[ps[0]]
1463 if len(ps) > 1:
1463 if len(ps) > 1:
1464 p2 = repo[ps[1]]
1464 p2 = repo[ps[1]]
1465 pa = p1.ancestor(p2)
1465 pa = p1.ancestor(p2)
1466 base, local, other = [x[fn].data() for x in pa, p1, p2]
1466 base, local, other = [x[fn].data() for x in pa, p1, p2]
1467 m3 = simplemerge.Merge3Text(base, local, other)
1467 m3 = simplemerge.Merge3Text(base, local, other)
1468 ml = [l.strip() for l in m3.merge_lines()]
1468 ml = [l.strip() for l in m3.merge_lines()]
1469 ml.append("")
1469 ml.append("")
1470 elif at > 0:
1470 elif at > 0:
1471 ml = p1[fn].data().split("\n")
1471 ml = p1[fn].data().split("\n")
1472 else:
1472 else:
1473 ml = initialmergedlines
1473 ml = initialmergedlines
1474 ml[id * linesperrev] += " r%i" % id
1474 ml[id * linesperrev] += " r%i" % id
1475 mergedtext = "\n".join(ml)
1475 mergedtext = "\n".join(ml)
1476 files.append(fn)
1476 files.append(fn)
1477 fctxs[fn] = context.memfilectx(fn, mergedtext)
1477 fctxs[fn] = context.memfilectx(fn, mergedtext)
1478
1478
1479 if overwritten_file:
1479 if overwritten_file:
1480 fn = "of"
1480 fn = "of"
1481 files.append(fn)
1481 files.append(fn)
1482 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1482 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1483
1483
1484 if new_file:
1484 if new_file:
1485 fn = "nf%i" % id
1485 fn = "nf%i" % id
1486 files.append(fn)
1486 files.append(fn)
1487 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1487 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1488 if len(ps) > 1:
1488 if len(ps) > 1:
1489 if not p2:
1489 if not p2:
1490 p2 = repo[ps[1]]
1490 p2 = repo[ps[1]]
1491 for fn in p2:
1491 for fn in p2:
1492 if fn.startswith("nf"):
1492 if fn.startswith("nf"):
1493 files.append(fn)
1493 files.append(fn)
1494 fctxs[fn] = p2[fn]
1494 fctxs[fn] = p2[fn]
1495
1495
1496 def fctxfn(repo, cx, path):
1496 def fctxfn(repo, cx, path):
1497 return fctxs.get(path)
1497 return fctxs.get(path)
1498
1498
1499 if len(ps) == 0 or ps[0] < 0:
1499 if len(ps) == 0 or ps[0] < 0:
1500 pars = [None, None]
1500 pars = [None, None]
1501 elif len(ps) == 1:
1501 elif len(ps) == 1:
1502 pars = [nodeids[ps[0]], None]
1502 pars = [nodeids[ps[0]], None]
1503 else:
1503 else:
1504 pars = [nodeids[p] for p in ps]
1504 pars = [nodeids[p] for p in ps]
1505 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1505 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1506 date=(id, 0),
1506 date=(id, 0),
1507 user="debugbuilddag",
1507 user="debugbuilddag",
1508 extra={'branch': atbranch})
1508 extra={'branch': atbranch})
1509 nodeid = repo.commitctx(cx)
1509 nodeid = repo.commitctx(cx)
1510 nodeids.append(nodeid)
1510 nodeids.append(nodeid)
1511 at = id
1511 at = id
1512 elif type == 'l':
1512 elif type == 'l':
1513 id, name = data
1513 id, name = data
1514 ui.note('tag %s\n' % name)
1514 ui.note('tag %s\n' % name)
1515 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1515 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1516 elif type == 'a':
1516 elif type == 'a':
1517 ui.note('branch %s\n' % data)
1517 ui.note('branch %s\n' % data)
1518 atbranch = data
1518 atbranch = data
1519 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1519 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1520 tr.close()
1520 tr.close()
1521
1521
1522 if tags:
1522 if tags:
1523 repo.opener.write("localtags", "".join(tags))
1523 repo.opener.write("localtags", "".join(tags))
1524 finally:
1524 finally:
1525 ui.progress(_('building'), None)
1525 ui.progress(_('building'), None)
1526 release(tr, lock)
1526 release(tr, lock)
1527
1527
1528 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1528 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1529 def debugbundle(ui, bundlepath, all=None, **opts):
1529 def debugbundle(ui, bundlepath, all=None, **opts):
1530 """lists the contents of a bundle"""
1530 """lists the contents of a bundle"""
1531 f = url.open(ui, bundlepath)
1531 f = url.open(ui, bundlepath)
1532 try:
1532 try:
1533 gen = changegroup.readbundle(f, bundlepath)
1533 gen = changegroup.readbundle(f, bundlepath)
1534 if all:
1534 if all:
1535 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1535 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1536
1536
1537 def showchunks(named):
1537 def showchunks(named):
1538 ui.write("\n%s\n" % named)
1538 ui.write("\n%s\n" % named)
1539 chain = None
1539 chain = None
1540 while True:
1540 while True:
1541 chunkdata = gen.deltachunk(chain)
1541 chunkdata = gen.deltachunk(chain)
1542 if not chunkdata:
1542 if not chunkdata:
1543 break
1543 break
1544 node = chunkdata['node']
1544 node = chunkdata['node']
1545 p1 = chunkdata['p1']
1545 p1 = chunkdata['p1']
1546 p2 = chunkdata['p2']
1546 p2 = chunkdata['p2']
1547 cs = chunkdata['cs']
1547 cs = chunkdata['cs']
1548 deltabase = chunkdata['deltabase']
1548 deltabase = chunkdata['deltabase']
1549 delta = chunkdata['delta']
1549 delta = chunkdata['delta']
1550 ui.write("%s %s %s %s %s %s\n" %
1550 ui.write("%s %s %s %s %s %s\n" %
1551 (hex(node), hex(p1), hex(p2),
1551 (hex(node), hex(p1), hex(p2),
1552 hex(cs), hex(deltabase), len(delta)))
1552 hex(cs), hex(deltabase), len(delta)))
1553 chain = node
1553 chain = node
1554
1554
1555 chunkdata = gen.changelogheader()
1555 chunkdata = gen.changelogheader()
1556 showchunks("changelog")
1556 showchunks("changelog")
1557 chunkdata = gen.manifestheader()
1557 chunkdata = gen.manifestheader()
1558 showchunks("manifest")
1558 showchunks("manifest")
1559 while True:
1559 while True:
1560 chunkdata = gen.filelogheader()
1560 chunkdata = gen.filelogheader()
1561 if not chunkdata:
1561 if not chunkdata:
1562 break
1562 break
1563 fname = chunkdata['filename']
1563 fname = chunkdata['filename']
1564 showchunks(fname)
1564 showchunks(fname)
1565 else:
1565 else:
1566 chunkdata = gen.changelogheader()
1566 chunkdata = gen.changelogheader()
1567 chain = None
1567 chain = None
1568 while True:
1568 while True:
1569 chunkdata = gen.deltachunk(chain)
1569 chunkdata = gen.deltachunk(chain)
1570 if not chunkdata:
1570 if not chunkdata:
1571 break
1571 break
1572 node = chunkdata['node']
1572 node = chunkdata['node']
1573 ui.write("%s\n" % hex(node))
1573 ui.write("%s\n" % hex(node))
1574 chain = node
1574 chain = node
1575 finally:
1575 finally:
1576 f.close()
1576 f.close()
1577
1577
1578 @command('debugcheckstate', [], '')
1578 @command('debugcheckstate', [], '')
1579 def debugcheckstate(ui, repo):
1579 def debugcheckstate(ui, repo):
1580 """validate the correctness of the current dirstate"""
1580 """validate the correctness of the current dirstate"""
1581 parent1, parent2 = repo.dirstate.parents()
1581 parent1, parent2 = repo.dirstate.parents()
1582 m1 = repo[parent1].manifest()
1582 m1 = repo[parent1].manifest()
1583 m2 = repo[parent2].manifest()
1583 m2 = repo[parent2].manifest()
1584 errors = 0
1584 errors = 0
1585 for f in repo.dirstate:
1585 for f in repo.dirstate:
1586 state = repo.dirstate[f]
1586 state = repo.dirstate[f]
1587 if state in "nr" and f not in m1:
1587 if state in "nr" and f not in m1:
1588 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1588 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1589 errors += 1
1589 errors += 1
1590 if state in "a" and f in m1:
1590 if state in "a" and f in m1:
1591 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1591 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1592 errors += 1
1592 errors += 1
1593 if state in "m" and f not in m1 and f not in m2:
1593 if state in "m" and f not in m1 and f not in m2:
1594 ui.warn(_("%s in state %s, but not in either manifest\n") %
1594 ui.warn(_("%s in state %s, but not in either manifest\n") %
1595 (f, state))
1595 (f, state))
1596 errors += 1
1596 errors += 1
1597 for f in m1:
1597 for f in m1:
1598 state = repo.dirstate[f]
1598 state = repo.dirstate[f]
1599 if state not in "nrm":
1599 if state not in "nrm":
1600 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1600 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1601 errors += 1
1601 errors += 1
1602 if errors:
1602 if errors:
1603 error = _(".hg/dirstate inconsistent with current parent's manifest")
1603 error = _(".hg/dirstate inconsistent with current parent's manifest")
1604 raise util.Abort(error)
1604 raise util.Abort(error)
1605
1605
1606 @command('debugcommands', [], _('[COMMAND]'))
1606 @command('debugcommands', [], _('[COMMAND]'))
1607 def debugcommands(ui, cmd='', *args):
1607 def debugcommands(ui, cmd='', *args):
1608 """list all available commands and options"""
1608 """list all available commands and options"""
1609 for cmd, vals in sorted(table.iteritems()):
1609 for cmd, vals in sorted(table.iteritems()):
1610 cmd = cmd.split('|')[0].strip('^')
1610 cmd = cmd.split('|')[0].strip('^')
1611 opts = ', '.join([i[1] for i in vals[1]])
1611 opts = ', '.join([i[1] for i in vals[1]])
1612 ui.write('%s: %s\n' % (cmd, opts))
1612 ui.write('%s: %s\n' % (cmd, opts))
1613
1613
1614 @command('debugcomplete',
1614 @command('debugcomplete',
1615 [('o', 'options', None, _('show the command options'))],
1615 [('o', 'options', None, _('show the command options'))],
1616 _('[-o] CMD'))
1616 _('[-o] CMD'))
1617 def debugcomplete(ui, cmd='', **opts):
1617 def debugcomplete(ui, cmd='', **opts):
1618 """returns the completion list associated with the given command"""
1618 """returns the completion list associated with the given command"""
1619
1619
1620 if opts.get('options'):
1620 if opts.get('options'):
1621 options = []
1621 options = []
1622 otables = [globalopts]
1622 otables = [globalopts]
1623 if cmd:
1623 if cmd:
1624 aliases, entry = cmdutil.findcmd(cmd, table, False)
1624 aliases, entry = cmdutil.findcmd(cmd, table, False)
1625 otables.append(entry[1])
1625 otables.append(entry[1])
1626 for t in otables:
1626 for t in otables:
1627 for o in t:
1627 for o in t:
1628 if "(DEPRECATED)" in o[3]:
1628 if "(DEPRECATED)" in o[3]:
1629 continue
1629 continue
1630 if o[0]:
1630 if o[0]:
1631 options.append('-%s' % o[0])
1631 options.append('-%s' % o[0])
1632 options.append('--%s' % o[1])
1632 options.append('--%s' % o[1])
1633 ui.write("%s\n" % "\n".join(options))
1633 ui.write("%s\n" % "\n".join(options))
1634 return
1634 return
1635
1635
1636 cmdlist = cmdutil.findpossible(cmd, table)
1636 cmdlist = cmdutil.findpossible(cmd, table)
1637 if ui.verbose:
1637 if ui.verbose:
1638 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1638 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1639 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1639 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1640
1640
1641 @command('debugdag',
1641 @command('debugdag',
1642 [('t', 'tags', None, _('use tags as labels')),
1642 [('t', 'tags', None, _('use tags as labels')),
1643 ('b', 'branches', None, _('annotate with branch names')),
1643 ('b', 'branches', None, _('annotate with branch names')),
1644 ('', 'dots', None, _('use dots for runs')),
1644 ('', 'dots', None, _('use dots for runs')),
1645 ('s', 'spaces', None, _('separate elements by spaces'))],
1645 ('s', 'spaces', None, _('separate elements by spaces'))],
1646 _('[OPTION]... [FILE [REV]...]'))
1646 _('[OPTION]... [FILE [REV]...]'))
1647 def debugdag(ui, repo, file_=None, *revs, **opts):
1647 def debugdag(ui, repo, file_=None, *revs, **opts):
1648 """format the changelog or an index DAG as a concise textual description
1648 """format the changelog or an index DAG as a concise textual description
1649
1649
1650 If you pass a revlog index, the revlog's DAG is emitted. If you list
1650 If you pass a revlog index, the revlog's DAG is emitted. If you list
1651 revision numbers, they get labelled in the output as rN.
1651 revision numbers, they get labelled in the output as rN.
1652
1652
1653 Otherwise, the changelog DAG of the current repo is emitted.
1653 Otherwise, the changelog DAG of the current repo is emitted.
1654 """
1654 """
1655 spaces = opts.get('spaces')
1655 spaces = opts.get('spaces')
1656 dots = opts.get('dots')
1656 dots = opts.get('dots')
1657 if file_:
1657 if file_:
1658 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1658 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1659 revs = set((int(r) for r in revs))
1659 revs = set((int(r) for r in revs))
1660 def events():
1660 def events():
1661 for r in rlog:
1661 for r in rlog:
1662 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1662 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1663 if r in revs:
1663 if r in revs:
1664 yield 'l', (r, "r%i" % r)
1664 yield 'l', (r, "r%i" % r)
1665 elif repo:
1665 elif repo:
1666 cl = repo.changelog
1666 cl = repo.changelog
1667 tags = opts.get('tags')
1667 tags = opts.get('tags')
1668 branches = opts.get('branches')
1668 branches = opts.get('branches')
1669 if tags:
1669 if tags:
1670 labels = {}
1670 labels = {}
1671 for l, n in repo.tags().items():
1671 for l, n in repo.tags().items():
1672 labels.setdefault(cl.rev(n), []).append(l)
1672 labels.setdefault(cl.rev(n), []).append(l)
1673 def events():
1673 def events():
1674 b = "default"
1674 b = "default"
1675 for r in cl:
1675 for r in cl:
1676 if branches:
1676 if branches:
1677 newb = cl.read(cl.node(r))[5]['branch']
1677 newb = cl.read(cl.node(r))[5]['branch']
1678 if newb != b:
1678 if newb != b:
1679 yield 'a', newb
1679 yield 'a', newb
1680 b = newb
1680 b = newb
1681 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1681 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1682 if tags:
1682 if tags:
1683 ls = labels.get(r)
1683 ls = labels.get(r)
1684 if ls:
1684 if ls:
1685 for l in ls:
1685 for l in ls:
1686 yield 'l', (r, l)
1686 yield 'l', (r, l)
1687 else:
1687 else:
1688 raise util.Abort(_('need repo for changelog dag'))
1688 raise util.Abort(_('need repo for changelog dag'))
1689
1689
1690 for line in dagparser.dagtextlines(events(),
1690 for line in dagparser.dagtextlines(events(),
1691 addspaces=spaces,
1691 addspaces=spaces,
1692 wraplabels=True,
1692 wraplabels=True,
1693 wrapannotations=True,
1693 wrapannotations=True,
1694 wrapnonlinear=dots,
1694 wrapnonlinear=dots,
1695 usedots=dots,
1695 usedots=dots,
1696 maxlinewidth=70):
1696 maxlinewidth=70):
1697 ui.write(line)
1697 ui.write(line)
1698 ui.write("\n")
1698 ui.write("\n")
1699
1699
1700 @command('debugdata',
1700 @command('debugdata',
1701 [('c', 'changelog', False, _('open changelog')),
1701 [('c', 'changelog', False, _('open changelog')),
1702 ('m', 'manifest', False, _('open manifest'))],
1702 ('m', 'manifest', False, _('open manifest'))],
1703 _('-c|-m|FILE REV'))
1703 _('-c|-m|FILE REV'))
1704 def debugdata(ui, repo, file_, rev = None, **opts):
1704 def debugdata(ui, repo, file_, rev = None, **opts):
1705 """dump the contents of a data file revision"""
1705 """dump the contents of a data file revision"""
1706 if opts.get('changelog') or opts.get('manifest'):
1706 if opts.get('changelog') or opts.get('manifest'):
1707 file_, rev = None, file_
1707 file_, rev = None, file_
1708 elif rev is None:
1708 elif rev is None:
1709 raise error.CommandError('debugdata', _('invalid arguments'))
1709 raise error.CommandError('debugdata', _('invalid arguments'))
1710 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1710 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1711 try:
1711 try:
1712 ui.write(r.revision(r.lookup(rev)))
1712 ui.write(r.revision(r.lookup(rev)))
1713 except KeyError:
1713 except KeyError:
1714 raise util.Abort(_('invalid revision identifier %s') % rev)
1714 raise util.Abort(_('invalid revision identifier %s') % rev)
1715
1715
1716 @command('debugdate',
1716 @command('debugdate',
1717 [('e', 'extended', None, _('try extended date formats'))],
1717 [('e', 'extended', None, _('try extended date formats'))],
1718 _('[-e] DATE [RANGE]'))
1718 _('[-e] DATE [RANGE]'))
1719 def debugdate(ui, date, range=None, **opts):
1719 def debugdate(ui, date, range=None, **opts):
1720 """parse and display a date"""
1720 """parse and display a date"""
1721 if opts["extended"]:
1721 if opts["extended"]:
1722 d = util.parsedate(date, util.extendeddateformats)
1722 d = util.parsedate(date, util.extendeddateformats)
1723 else:
1723 else:
1724 d = util.parsedate(date)
1724 d = util.parsedate(date)
1725 ui.write("internal: %s %s\n" % d)
1725 ui.write("internal: %s %s\n" % d)
1726 ui.write("standard: %s\n" % util.datestr(d))
1726 ui.write("standard: %s\n" % util.datestr(d))
1727 if range:
1727 if range:
1728 m = util.matchdate(range)
1728 m = util.matchdate(range)
1729 ui.write("match: %s\n" % m(d[0]))
1729 ui.write("match: %s\n" % m(d[0]))
1730
1730
1731 @command('debugdiscovery',
1731 @command('debugdiscovery',
1732 [('', 'old', None, _('use old-style discovery')),
1732 [('', 'old', None, _('use old-style discovery')),
1733 ('', 'nonheads', None,
1733 ('', 'nonheads', None,
1734 _('use old-style discovery with non-heads included')),
1734 _('use old-style discovery with non-heads included')),
1735 ] + remoteopts,
1735 ] + remoteopts,
1736 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1736 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1737 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1737 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1738 """runs the changeset discovery protocol in isolation"""
1738 """runs the changeset discovery protocol in isolation"""
1739 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1739 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1740 remote = hg.peer(repo, opts, remoteurl)
1740 remote = hg.peer(repo, opts, remoteurl)
1741 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1741 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1742
1742
1743 # make sure tests are repeatable
1743 # make sure tests are repeatable
1744 random.seed(12323)
1744 random.seed(12323)
1745
1745
1746 def doit(localheads, remoteheads):
1746 def doit(localheads, remoteheads):
1747 if opts.get('old'):
1747 if opts.get('old'):
1748 if localheads:
1748 if localheads:
1749 raise util.Abort('cannot use localheads with old style discovery')
1749 raise util.Abort('cannot use localheads with old style discovery')
1750 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1750 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1751 force=True)
1751 force=True)
1752 common = set(common)
1752 common = set(common)
1753 if not opts.get('nonheads'):
1753 if not opts.get('nonheads'):
1754 ui.write("unpruned common: %s\n" % " ".join([short(n)
1754 ui.write("unpruned common: %s\n" % " ".join([short(n)
1755 for n in common]))
1755 for n in common]))
1756 dag = dagutil.revlogdag(repo.changelog)
1756 dag = dagutil.revlogdag(repo.changelog)
1757 all = dag.ancestorset(dag.internalizeall(common))
1757 all = dag.ancestorset(dag.internalizeall(common))
1758 common = dag.externalizeall(dag.headsetofconnecteds(all))
1758 common = dag.externalizeall(dag.headsetofconnecteds(all))
1759 else:
1759 else:
1760 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1760 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1761 common = set(common)
1761 common = set(common)
1762 rheads = set(hds)
1762 rheads = set(hds)
1763 lheads = set(repo.heads())
1763 lheads = set(repo.heads())
1764 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1764 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1765 if lheads <= common:
1765 if lheads <= common:
1766 ui.write("local is subset\n")
1766 ui.write("local is subset\n")
1767 elif rheads <= common:
1767 elif rheads <= common:
1768 ui.write("remote is subset\n")
1768 ui.write("remote is subset\n")
1769
1769
1770 serverlogs = opts.get('serverlog')
1770 serverlogs = opts.get('serverlog')
1771 if serverlogs:
1771 if serverlogs:
1772 for filename in serverlogs:
1772 for filename in serverlogs:
1773 logfile = open(filename, 'r')
1773 logfile = open(filename, 'r')
1774 try:
1774 try:
1775 line = logfile.readline()
1775 line = logfile.readline()
1776 while line:
1776 while line:
1777 parts = line.strip().split(';')
1777 parts = line.strip().split(';')
1778 op = parts[1]
1778 op = parts[1]
1779 if op == 'cg':
1779 if op == 'cg':
1780 pass
1780 pass
1781 elif op == 'cgss':
1781 elif op == 'cgss':
1782 doit(parts[2].split(' '), parts[3].split(' '))
1782 doit(parts[2].split(' '), parts[3].split(' '))
1783 elif op == 'unb':
1783 elif op == 'unb':
1784 doit(parts[3].split(' '), parts[2].split(' '))
1784 doit(parts[3].split(' '), parts[2].split(' '))
1785 line = logfile.readline()
1785 line = logfile.readline()
1786 finally:
1786 finally:
1787 logfile.close()
1787 logfile.close()
1788
1788
1789 else:
1789 else:
1790 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1790 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1791 opts.get('remote_head'))
1791 opts.get('remote_head'))
1792 localrevs = opts.get('local_head')
1792 localrevs = opts.get('local_head')
1793 doit(localrevs, remoterevs)
1793 doit(localrevs, remoterevs)
1794
1794
1795 @command('debugfileset', [], ('REVSPEC'))
1795 @command('debugfileset', [], ('REVSPEC'))
1796 def debugfileset(ui, repo, expr):
1796 def debugfileset(ui, repo, expr):
1797 '''parse and apply a fileset specification'''
1797 '''parse and apply a fileset specification'''
1798 if ui.verbose:
1798 if ui.verbose:
1799 tree = fileset.parse(expr)[0]
1799 tree = fileset.parse(expr)[0]
1800 ui.note(tree, "\n")
1800 ui.note(tree, "\n")
1801
1801
1802 for f in fileset.getfileset(repo[None], expr):
1802 for f in fileset.getfileset(repo[None], expr):
1803 ui.write("%s\n" % f)
1803 ui.write("%s\n" % f)
1804
1804
1805 @command('debugfsinfo', [], _('[PATH]'))
1805 @command('debugfsinfo', [], _('[PATH]'))
1806 def debugfsinfo(ui, path = "."):
1806 def debugfsinfo(ui, path = "."):
1807 """show information detected about current filesystem"""
1807 """show information detected about current filesystem"""
1808 util.writefile('.debugfsinfo', '')
1808 util.writefile('.debugfsinfo', '')
1809 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1809 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1810 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1810 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1811 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1811 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1812 and 'yes' or 'no'))
1812 and 'yes' or 'no'))
1813 os.unlink('.debugfsinfo')
1813 os.unlink('.debugfsinfo')
1814
1814
1815 @command('debuggetbundle',
1815 @command('debuggetbundle',
1816 [('H', 'head', [], _('id of head node'), _('ID')),
1816 [('H', 'head', [], _('id of head node'), _('ID')),
1817 ('C', 'common', [], _('id of common node'), _('ID')),
1817 ('C', 'common', [], _('id of common node'), _('ID')),
1818 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1818 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1819 _('REPO FILE [-H|-C ID]...'))
1819 _('REPO FILE [-H|-C ID]...'))
1820 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1820 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1821 """retrieves a bundle from a repo
1821 """retrieves a bundle from a repo
1822
1822
1823 Every ID must be a full-length hex node id string. Saves the bundle to the
1823 Every ID must be a full-length hex node id string. Saves the bundle to the
1824 given file.
1824 given file.
1825 """
1825 """
1826 repo = hg.peer(ui, opts, repopath)
1826 repo = hg.peer(ui, opts, repopath)
1827 if not repo.capable('getbundle'):
1827 if not repo.capable('getbundle'):
1828 raise util.Abort("getbundle() not supported by target repository")
1828 raise util.Abort("getbundle() not supported by target repository")
1829 args = {}
1829 args = {}
1830 if common:
1830 if common:
1831 args['common'] = [bin(s) for s in common]
1831 args['common'] = [bin(s) for s in common]
1832 if head:
1832 if head:
1833 args['heads'] = [bin(s) for s in head]
1833 args['heads'] = [bin(s) for s in head]
1834 bundle = repo.getbundle('debug', **args)
1834 bundle = repo.getbundle('debug', **args)
1835
1835
1836 bundletype = opts.get('type', 'bzip2').lower()
1836 bundletype = opts.get('type', 'bzip2').lower()
1837 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1837 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1838 bundletype = btypes.get(bundletype)
1838 bundletype = btypes.get(bundletype)
1839 if bundletype not in changegroup.bundletypes:
1839 if bundletype not in changegroup.bundletypes:
1840 raise util.Abort(_('unknown bundle type specified with --type'))
1840 raise util.Abort(_('unknown bundle type specified with --type'))
1841 changegroup.writebundle(bundle, bundlepath, bundletype)
1841 changegroup.writebundle(bundle, bundlepath, bundletype)
1842
1842
1843 @command('debugignore', [], '')
1843 @command('debugignore', [], '')
1844 def debugignore(ui, repo, *values, **opts):
1844 def debugignore(ui, repo, *values, **opts):
1845 """display the combined ignore pattern"""
1845 """display the combined ignore pattern"""
1846 ignore = repo.dirstate._ignore
1846 ignore = repo.dirstate._ignore
1847 includepat = getattr(ignore, 'includepat', None)
1847 includepat = getattr(ignore, 'includepat', None)
1848 if includepat is not None:
1848 if includepat is not None:
1849 ui.write("%s\n" % includepat)
1849 ui.write("%s\n" % includepat)
1850 else:
1850 else:
1851 raise util.Abort(_("no ignore patterns found"))
1851 raise util.Abort(_("no ignore patterns found"))
1852
1852
1853 @command('debugindex',
1853 @command('debugindex',
1854 [('c', 'changelog', False, _('open changelog')),
1854 [('c', 'changelog', False, _('open changelog')),
1855 ('m', 'manifest', False, _('open manifest')),
1855 ('m', 'manifest', False, _('open manifest')),
1856 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1856 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1857 _('[-f FORMAT] -c|-m|FILE'))
1857 _('[-f FORMAT] -c|-m|FILE'))
1858 def debugindex(ui, repo, file_ = None, **opts):
1858 def debugindex(ui, repo, file_ = None, **opts):
1859 """dump the contents of an index file"""
1859 """dump the contents of an index file"""
1860 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1860 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1861 format = opts.get('format', 0)
1861 format = opts.get('format', 0)
1862 if format not in (0, 1):
1862 if format not in (0, 1):
1863 raise util.Abort(_("unknown format %d") % format)
1863 raise util.Abort(_("unknown format %d") % format)
1864
1864
1865 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1865 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1866 if generaldelta:
1866 if generaldelta:
1867 basehdr = ' delta'
1867 basehdr = ' delta'
1868 else:
1868 else:
1869 basehdr = ' base'
1869 basehdr = ' base'
1870
1870
1871 if format == 0:
1871 if format == 0:
1872 ui.write(" rev offset length " + basehdr + " linkrev"
1872 ui.write(" rev offset length " + basehdr + " linkrev"
1873 " nodeid p1 p2\n")
1873 " nodeid p1 p2\n")
1874 elif format == 1:
1874 elif format == 1:
1875 ui.write(" rev flag offset length"
1875 ui.write(" rev flag offset length"
1876 " size " + basehdr + " link p1 p2 nodeid\n")
1876 " size " + basehdr + " link p1 p2 nodeid\n")
1877
1877
1878 for i in r:
1878 for i in r:
1879 node = r.node(i)
1879 node = r.node(i)
1880 if generaldelta:
1880 if generaldelta:
1881 base = r.deltaparent(i)
1881 base = r.deltaparent(i)
1882 else:
1882 else:
1883 base = r.chainbase(i)
1883 base = r.chainbase(i)
1884 if format == 0:
1884 if format == 0:
1885 try:
1885 try:
1886 pp = r.parents(node)
1886 pp = r.parents(node)
1887 except:
1887 except:
1888 pp = [nullid, nullid]
1888 pp = [nullid, nullid]
1889 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1889 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1890 i, r.start(i), r.length(i), base, r.linkrev(i),
1890 i, r.start(i), r.length(i), base, r.linkrev(i),
1891 short(node), short(pp[0]), short(pp[1])))
1891 short(node), short(pp[0]), short(pp[1])))
1892 elif format == 1:
1892 elif format == 1:
1893 pr = r.parentrevs(i)
1893 pr = r.parentrevs(i)
1894 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1894 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1895 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1895 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1896 base, r.linkrev(i), pr[0], pr[1], short(node)))
1896 base, r.linkrev(i), pr[0], pr[1], short(node)))
1897
1897
1898 @command('debugindexdot', [], _('FILE'))
1898 @command('debugindexdot', [], _('FILE'))
1899 def debugindexdot(ui, repo, file_):
1899 def debugindexdot(ui, repo, file_):
1900 """dump an index DAG as a graphviz dot file"""
1900 """dump an index DAG as a graphviz dot file"""
1901 r = None
1901 r = None
1902 if repo:
1902 if repo:
1903 filelog = repo.file(file_)
1903 filelog = repo.file(file_)
1904 if len(filelog):
1904 if len(filelog):
1905 r = filelog
1905 r = filelog
1906 if not r:
1906 if not r:
1907 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1907 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1908 ui.write("digraph G {\n")
1908 ui.write("digraph G {\n")
1909 for i in r:
1909 for i in r:
1910 node = r.node(i)
1910 node = r.node(i)
1911 pp = r.parents(node)
1911 pp = r.parents(node)
1912 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1912 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1913 if pp[1] != nullid:
1913 if pp[1] != nullid:
1914 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1914 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1915 ui.write("}\n")
1915 ui.write("}\n")
1916
1916
1917 @command('debuginstall', [], '')
1917 @command('debuginstall', [], '')
1918 def debuginstall(ui):
1918 def debuginstall(ui):
1919 '''test Mercurial installation
1919 '''test Mercurial installation
1920
1920
1921 Returns 0 on success.
1921 Returns 0 on success.
1922 '''
1922 '''
1923
1923
1924 def writetemp(contents):
1924 def writetemp(contents):
1925 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1925 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1926 f = os.fdopen(fd, "wb")
1926 f = os.fdopen(fd, "wb")
1927 f.write(contents)
1927 f.write(contents)
1928 f.close()
1928 f.close()
1929 return name
1929 return name
1930
1930
1931 problems = 0
1931 problems = 0
1932
1932
1933 # encoding
1933 # encoding
1934 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1934 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1935 try:
1935 try:
1936 encoding.fromlocal("test")
1936 encoding.fromlocal("test")
1937 except util.Abort, inst:
1937 except util.Abort, inst:
1938 ui.write(" %s\n" % inst)
1938 ui.write(" %s\n" % inst)
1939 ui.write(_(" (check that your locale is properly set)\n"))
1939 ui.write(_(" (check that your locale is properly set)\n"))
1940 problems += 1
1940 problems += 1
1941
1941
1942 # compiled modules
1942 # compiled modules
1943 ui.status(_("Checking installed modules (%s)...\n")
1943 ui.status(_("Checking installed modules (%s)...\n")
1944 % os.path.dirname(__file__))
1944 % os.path.dirname(__file__))
1945 try:
1945 try:
1946 import bdiff, mpatch, base85, osutil
1946 import bdiff, mpatch, base85, osutil
1947 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1947 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1948 except Exception, inst:
1948 except Exception, inst:
1949 ui.write(" %s\n" % inst)
1949 ui.write(" %s\n" % inst)
1950 ui.write(_(" One or more extensions could not be found"))
1950 ui.write(_(" One or more extensions could not be found"))
1951 ui.write(_(" (check that you compiled the extensions)\n"))
1951 ui.write(_(" (check that you compiled the extensions)\n"))
1952 problems += 1
1952 problems += 1
1953
1953
1954 # templates
1954 # templates
1955 import templater
1955 import templater
1956 p = templater.templatepath()
1956 p = templater.templatepath()
1957 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1957 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1958 try:
1958 try:
1959 templater.templater(templater.templatepath("map-cmdline.default"))
1959 templater.templater(templater.templatepath("map-cmdline.default"))
1960 except Exception, inst:
1960 except Exception, inst:
1961 ui.write(" %s\n" % inst)
1961 ui.write(" %s\n" % inst)
1962 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1962 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1963 problems += 1
1963 problems += 1
1964
1964
1965 # editor
1965 # editor
1966 ui.status(_("Checking commit editor...\n"))
1966 ui.status(_("Checking commit editor...\n"))
1967 editor = ui.geteditor()
1967 editor = ui.geteditor()
1968 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1968 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1969 if not cmdpath:
1969 if not cmdpath:
1970 if editor == 'vi':
1970 if editor == 'vi':
1971 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1971 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1972 ui.write(_(" (specify a commit editor in your configuration"
1972 ui.write(_(" (specify a commit editor in your configuration"
1973 " file)\n"))
1973 " file)\n"))
1974 else:
1974 else:
1975 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1975 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1976 ui.write(_(" (specify a commit editor in your configuration"
1976 ui.write(_(" (specify a commit editor in your configuration"
1977 " file)\n"))
1977 " file)\n"))
1978 problems += 1
1978 problems += 1
1979
1979
1980 # check username
1980 # check username
1981 ui.status(_("Checking username...\n"))
1981 ui.status(_("Checking username...\n"))
1982 try:
1982 try:
1983 ui.username()
1983 ui.username()
1984 except util.Abort, e:
1984 except util.Abort, e:
1985 ui.write(" %s\n" % e)
1985 ui.write(" %s\n" % e)
1986 ui.write(_(" (specify a username in your configuration file)\n"))
1986 ui.write(_(" (specify a username in your configuration file)\n"))
1987 problems += 1
1987 problems += 1
1988
1988
1989 if not problems:
1989 if not problems:
1990 ui.status(_("No problems detected\n"))
1990 ui.status(_("No problems detected\n"))
1991 else:
1991 else:
1992 ui.write(_("%s problems detected,"
1992 ui.write(_("%s problems detected,"
1993 " please check your install!\n") % problems)
1993 " please check your install!\n") % problems)
1994
1994
1995 return problems
1995 return problems
1996
1996
1997 @command('debugknown', [], _('REPO ID...'))
1997 @command('debugknown', [], _('REPO ID...'))
1998 def debugknown(ui, repopath, *ids, **opts):
1998 def debugknown(ui, repopath, *ids, **opts):
1999 """test whether node ids are known to a repo
1999 """test whether node ids are known to a repo
2000
2000
2001 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
2001 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
2002 indicating unknown/known.
2002 indicating unknown/known.
2003 """
2003 """
2004 repo = hg.peer(ui, opts, repopath)
2004 repo = hg.peer(ui, opts, repopath)
2005 if not repo.capable('known'):
2005 if not repo.capable('known'):
2006 raise util.Abort("known() not supported by target repository")
2006 raise util.Abort("known() not supported by target repository")
2007 flags = repo.known([bin(s) for s in ids])
2007 flags = repo.known([bin(s) for s in ids])
2008 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2008 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2009
2009
2010 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2010 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2011 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2011 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2012 '''access the pushkey key/value protocol
2012 '''access the pushkey key/value protocol
2013
2013
2014 With two args, list the keys in the given namespace.
2014 With two args, list the keys in the given namespace.
2015
2015
2016 With five args, set a key to new if it currently is set to old.
2016 With five args, set a key to new if it currently is set to old.
2017 Reports success or failure.
2017 Reports success or failure.
2018 '''
2018 '''
2019
2019
2020 target = hg.peer(ui, {}, repopath)
2020 target = hg.peer(ui, {}, repopath)
2021 if keyinfo:
2021 if keyinfo:
2022 key, old, new = keyinfo
2022 key, old, new = keyinfo
2023 r = target.pushkey(namespace, key, old, new)
2023 r = target.pushkey(namespace, key, old, new)
2024 ui.status(str(r) + '\n')
2024 ui.status(str(r) + '\n')
2025 return not r
2025 return not r
2026 else:
2026 else:
2027 for k, v in target.listkeys(namespace).iteritems():
2027 for k, v in target.listkeys(namespace).iteritems():
2028 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2028 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2029 v.encode('string-escape')))
2029 v.encode('string-escape')))
2030
2030
2031 @command('debugpvec', [], _('A B'))
2031 @command('debugpvec', [], _('A B'))
2032 def debugpvec(ui, repo, a, b=None):
2032 def debugpvec(ui, repo, a, b=None):
2033 ca = scmutil.revsingle(repo, a)
2033 ca = scmutil.revsingle(repo, a)
2034 cb = scmutil.revsingle(repo, b)
2034 cb = scmutil.revsingle(repo, b)
2035 pa = pvec.ctxpvec(ca)
2035 pa = pvec.ctxpvec(ca)
2036 pb = pvec.ctxpvec(cb)
2036 pb = pvec.ctxpvec(cb)
2037 if pa == pb:
2037 if pa == pb:
2038 rel = "="
2038 rel = "="
2039 elif pa > pb:
2039 elif pa > pb:
2040 rel = ">"
2040 rel = ">"
2041 elif pa < pb:
2041 elif pa < pb:
2042 rel = "<"
2042 rel = "<"
2043 elif pa | pb:
2043 elif pa | pb:
2044 rel = "|"
2044 rel = "|"
2045 ui.write(_("a: %s\n") % pa)
2045 ui.write(_("a: %s\n") % pa)
2046 ui.write(_("b: %s\n") % pb)
2046 ui.write(_("b: %s\n") % pb)
2047 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2047 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2048 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2048 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2049 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2049 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2050 pa.distance(pb), rel))
2050 pa.distance(pb), rel))
2051
2051
2052 @command('debugrebuildstate',
2052 @command('debugrebuildstate',
2053 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2053 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2054 _('[-r REV] [REV]'))
2054 _('[-r REV] [REV]'))
2055 def debugrebuildstate(ui, repo, rev="tip"):
2055 def debugrebuildstate(ui, repo, rev="tip"):
2056 """rebuild the dirstate as it would look like for the given revision"""
2056 """rebuild the dirstate as it would look like for the given revision"""
2057 ctx = scmutil.revsingle(repo, rev)
2057 ctx = scmutil.revsingle(repo, rev)
2058 wlock = repo.wlock()
2058 wlock = repo.wlock()
2059 try:
2059 try:
2060 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2060 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2061 finally:
2061 finally:
2062 wlock.release()
2062 wlock.release()
2063
2063
2064 @command('debugrename',
2064 @command('debugrename',
2065 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2065 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2066 _('[-r REV] FILE'))
2066 _('[-r REV] FILE'))
2067 def debugrename(ui, repo, file1, *pats, **opts):
2067 def debugrename(ui, repo, file1, *pats, **opts):
2068 """dump rename information"""
2068 """dump rename information"""
2069
2069
2070 ctx = scmutil.revsingle(repo, opts.get('rev'))
2070 ctx = scmutil.revsingle(repo, opts.get('rev'))
2071 m = scmutil.match(ctx, (file1,) + pats, opts)
2071 m = scmutil.match(ctx, (file1,) + pats, opts)
2072 for abs in ctx.walk(m):
2072 for abs in ctx.walk(m):
2073 fctx = ctx[abs]
2073 fctx = ctx[abs]
2074 o = fctx.filelog().renamed(fctx.filenode())
2074 o = fctx.filelog().renamed(fctx.filenode())
2075 rel = m.rel(abs)
2075 rel = m.rel(abs)
2076 if o:
2076 if o:
2077 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2077 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2078 else:
2078 else:
2079 ui.write(_("%s not renamed\n") % rel)
2079 ui.write(_("%s not renamed\n") % rel)
2080
2080
2081 @command('debugrevlog',
2081 @command('debugrevlog',
2082 [('c', 'changelog', False, _('open changelog')),
2082 [('c', 'changelog', False, _('open changelog')),
2083 ('m', 'manifest', False, _('open manifest')),
2083 ('m', 'manifest', False, _('open manifest')),
2084 ('d', 'dump', False, _('dump index data'))],
2084 ('d', 'dump', False, _('dump index data'))],
2085 _('-c|-m|FILE'))
2085 _('-c|-m|FILE'))
2086 def debugrevlog(ui, repo, file_ = None, **opts):
2086 def debugrevlog(ui, repo, file_ = None, **opts):
2087 """show data and statistics about a revlog"""
2087 """show data and statistics about a revlog"""
2088 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2088 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2089
2089
2090 if opts.get("dump"):
2090 if opts.get("dump"):
2091 numrevs = len(r)
2091 numrevs = len(r)
2092 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2092 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2093 " rawsize totalsize compression heads\n")
2093 " rawsize totalsize compression heads\n")
2094 ts = 0
2094 ts = 0
2095 heads = set()
2095 heads = set()
2096 for rev in xrange(numrevs):
2096 for rev in xrange(numrevs):
2097 dbase = r.deltaparent(rev)
2097 dbase = r.deltaparent(rev)
2098 if dbase == -1:
2098 if dbase == -1:
2099 dbase = rev
2099 dbase = rev
2100 cbase = r.chainbase(rev)
2100 cbase = r.chainbase(rev)
2101 p1, p2 = r.parentrevs(rev)
2101 p1, p2 = r.parentrevs(rev)
2102 rs = r.rawsize(rev)
2102 rs = r.rawsize(rev)
2103 ts = ts + rs
2103 ts = ts + rs
2104 heads -= set(r.parentrevs(rev))
2104 heads -= set(r.parentrevs(rev))
2105 heads.add(rev)
2105 heads.add(rev)
2106 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2106 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2107 (rev, p1, p2, r.start(rev), r.end(rev),
2107 (rev, p1, p2, r.start(rev), r.end(rev),
2108 r.start(dbase), r.start(cbase),
2108 r.start(dbase), r.start(cbase),
2109 r.start(p1), r.start(p2),
2109 r.start(p1), r.start(p2),
2110 rs, ts, ts / r.end(rev), len(heads)))
2110 rs, ts, ts / r.end(rev), len(heads)))
2111 return 0
2111 return 0
2112
2112
2113 v = r.version
2113 v = r.version
2114 format = v & 0xFFFF
2114 format = v & 0xFFFF
2115 flags = []
2115 flags = []
2116 gdelta = False
2116 gdelta = False
2117 if v & revlog.REVLOGNGINLINEDATA:
2117 if v & revlog.REVLOGNGINLINEDATA:
2118 flags.append('inline')
2118 flags.append('inline')
2119 if v & revlog.REVLOGGENERALDELTA:
2119 if v & revlog.REVLOGGENERALDELTA:
2120 gdelta = True
2120 gdelta = True
2121 flags.append('generaldelta')
2121 flags.append('generaldelta')
2122 if not flags:
2122 if not flags:
2123 flags = ['(none)']
2123 flags = ['(none)']
2124
2124
2125 nummerges = 0
2125 nummerges = 0
2126 numfull = 0
2126 numfull = 0
2127 numprev = 0
2127 numprev = 0
2128 nump1 = 0
2128 nump1 = 0
2129 nump2 = 0
2129 nump2 = 0
2130 numother = 0
2130 numother = 0
2131 nump1prev = 0
2131 nump1prev = 0
2132 nump2prev = 0
2132 nump2prev = 0
2133 chainlengths = []
2133 chainlengths = []
2134
2134
2135 datasize = [None, 0, 0L]
2135 datasize = [None, 0, 0L]
2136 fullsize = [None, 0, 0L]
2136 fullsize = [None, 0, 0L]
2137 deltasize = [None, 0, 0L]
2137 deltasize = [None, 0, 0L]
2138
2138
2139 def addsize(size, l):
2139 def addsize(size, l):
2140 if l[0] is None or size < l[0]:
2140 if l[0] is None or size < l[0]:
2141 l[0] = size
2141 l[0] = size
2142 if size > l[1]:
2142 if size > l[1]:
2143 l[1] = size
2143 l[1] = size
2144 l[2] += size
2144 l[2] += size
2145
2145
2146 numrevs = len(r)
2146 numrevs = len(r)
2147 for rev in xrange(numrevs):
2147 for rev in xrange(numrevs):
2148 p1, p2 = r.parentrevs(rev)
2148 p1, p2 = r.parentrevs(rev)
2149 delta = r.deltaparent(rev)
2149 delta = r.deltaparent(rev)
2150 if format > 0:
2150 if format > 0:
2151 addsize(r.rawsize(rev), datasize)
2151 addsize(r.rawsize(rev), datasize)
2152 if p2 != nullrev:
2152 if p2 != nullrev:
2153 nummerges += 1
2153 nummerges += 1
2154 size = r.length(rev)
2154 size = r.length(rev)
2155 if delta == nullrev:
2155 if delta == nullrev:
2156 chainlengths.append(0)
2156 chainlengths.append(0)
2157 numfull += 1
2157 numfull += 1
2158 addsize(size, fullsize)
2158 addsize(size, fullsize)
2159 else:
2159 else:
2160 chainlengths.append(chainlengths[delta] + 1)
2160 chainlengths.append(chainlengths[delta] + 1)
2161 addsize(size, deltasize)
2161 addsize(size, deltasize)
2162 if delta == rev - 1:
2162 if delta == rev - 1:
2163 numprev += 1
2163 numprev += 1
2164 if delta == p1:
2164 if delta == p1:
2165 nump1prev += 1
2165 nump1prev += 1
2166 elif delta == p2:
2166 elif delta == p2:
2167 nump2prev += 1
2167 nump2prev += 1
2168 elif delta == p1:
2168 elif delta == p1:
2169 nump1 += 1
2169 nump1 += 1
2170 elif delta == p2:
2170 elif delta == p2:
2171 nump2 += 1
2171 nump2 += 1
2172 elif delta != nullrev:
2172 elif delta != nullrev:
2173 numother += 1
2173 numother += 1
2174
2174
2175 numdeltas = numrevs - numfull
2175 numdeltas = numrevs - numfull
2176 numoprev = numprev - nump1prev - nump2prev
2176 numoprev = numprev - nump1prev - nump2prev
2177 totalrawsize = datasize[2]
2177 totalrawsize = datasize[2]
2178 datasize[2] /= numrevs
2178 datasize[2] /= numrevs
2179 fulltotal = fullsize[2]
2179 fulltotal = fullsize[2]
2180 fullsize[2] /= numfull
2180 fullsize[2] /= numfull
2181 deltatotal = deltasize[2]
2181 deltatotal = deltasize[2]
2182 deltasize[2] /= numrevs - numfull
2182 deltasize[2] /= numrevs - numfull
2183 totalsize = fulltotal + deltatotal
2183 totalsize = fulltotal + deltatotal
2184 avgchainlen = sum(chainlengths) / numrevs
2184 avgchainlen = sum(chainlengths) / numrevs
2185 compratio = totalrawsize / totalsize
2185 compratio = totalrawsize / totalsize
2186
2186
2187 basedfmtstr = '%%%dd\n'
2187 basedfmtstr = '%%%dd\n'
2188 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2188 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2189
2189
2190 def dfmtstr(max):
2190 def dfmtstr(max):
2191 return basedfmtstr % len(str(max))
2191 return basedfmtstr % len(str(max))
2192 def pcfmtstr(max, padding=0):
2192 def pcfmtstr(max, padding=0):
2193 return basepcfmtstr % (len(str(max)), ' ' * padding)
2193 return basepcfmtstr % (len(str(max)), ' ' * padding)
2194
2194
2195 def pcfmt(value, total):
2195 def pcfmt(value, total):
2196 return (value, 100 * float(value) / total)
2196 return (value, 100 * float(value) / total)
2197
2197
2198 ui.write('format : %d\n' % format)
2198 ui.write('format : %d\n' % format)
2199 ui.write('flags : %s\n' % ', '.join(flags))
2199 ui.write('flags : %s\n' % ', '.join(flags))
2200
2200
2201 ui.write('\n')
2201 ui.write('\n')
2202 fmt = pcfmtstr(totalsize)
2202 fmt = pcfmtstr(totalsize)
2203 fmt2 = dfmtstr(totalsize)
2203 fmt2 = dfmtstr(totalsize)
2204 ui.write('revisions : ' + fmt2 % numrevs)
2204 ui.write('revisions : ' + fmt2 % numrevs)
2205 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2205 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2206 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2206 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2207 ui.write('revisions : ' + fmt2 % numrevs)
2207 ui.write('revisions : ' + fmt2 % numrevs)
2208 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2208 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2209 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2209 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2210 ui.write('revision size : ' + fmt2 % totalsize)
2210 ui.write('revision size : ' + fmt2 % totalsize)
2211 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2211 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2212 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2212 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2213
2213
2214 ui.write('\n')
2214 ui.write('\n')
2215 fmt = dfmtstr(max(avgchainlen, compratio))
2215 fmt = dfmtstr(max(avgchainlen, compratio))
2216 ui.write('avg chain length : ' + fmt % avgchainlen)
2216 ui.write('avg chain length : ' + fmt % avgchainlen)
2217 ui.write('compression ratio : ' + fmt % compratio)
2217 ui.write('compression ratio : ' + fmt % compratio)
2218
2218
2219 if format > 0:
2219 if format > 0:
2220 ui.write('\n')
2220 ui.write('\n')
2221 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2221 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2222 % tuple(datasize))
2222 % tuple(datasize))
2223 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2223 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2224 % tuple(fullsize))
2224 % tuple(fullsize))
2225 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2225 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2226 % tuple(deltasize))
2226 % tuple(deltasize))
2227
2227
2228 if numdeltas > 0:
2228 if numdeltas > 0:
2229 ui.write('\n')
2229 ui.write('\n')
2230 fmt = pcfmtstr(numdeltas)
2230 fmt = pcfmtstr(numdeltas)
2231 fmt2 = pcfmtstr(numdeltas, 4)
2231 fmt2 = pcfmtstr(numdeltas, 4)
2232 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2232 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2233 if numprev > 0:
2233 if numprev > 0:
2234 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2234 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2235 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2235 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2236 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2236 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2237 if gdelta:
2237 if gdelta:
2238 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2238 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2239 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2239 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2240 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2240 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2241
2241
2242 @command('debugrevspec', [], ('REVSPEC'))
2242 @command('debugrevspec', [], ('REVSPEC'))
2243 def debugrevspec(ui, repo, expr):
2243 def debugrevspec(ui, repo, expr):
2244 """parse and apply a revision specification
2244 """parse and apply a revision specification
2245
2245
2246 Use --verbose to print the parsed tree before and after aliases
2246 Use --verbose to print the parsed tree before and after aliases
2247 expansion.
2247 expansion.
2248 """
2248 """
2249 if ui.verbose:
2249 if ui.verbose:
2250 tree = revset.parse(expr)[0]
2250 tree = revset.parse(expr)[0]
2251 ui.note(revset.prettyformat(tree), "\n")
2251 ui.note(revset.prettyformat(tree), "\n")
2252 newtree = revset.findaliases(ui, tree)
2252 newtree = revset.findaliases(ui, tree)
2253 if newtree != tree:
2253 if newtree != tree:
2254 ui.note(revset.prettyformat(newtree), "\n")
2254 ui.note(revset.prettyformat(newtree), "\n")
2255 func = revset.match(ui, expr)
2255 func = revset.match(ui, expr)
2256 for c in func(repo, range(len(repo))):
2256 for c in func(repo, range(len(repo))):
2257 ui.write("%s\n" % c)
2257 ui.write("%s\n" % c)
2258
2258
2259 @command('debugsetparents', [], _('REV1 [REV2]'))
2259 @command('debugsetparents', [], _('REV1 [REV2]'))
2260 def debugsetparents(ui, repo, rev1, rev2=None):
2260 def debugsetparents(ui, repo, rev1, rev2=None):
2261 """manually set the parents of the current working directory
2261 """manually set the parents of the current working directory
2262
2262
2263 This is useful for writing repository conversion tools, but should
2263 This is useful for writing repository conversion tools, but should
2264 be used with care.
2264 be used with care.
2265
2265
2266 Returns 0 on success.
2266 Returns 0 on success.
2267 """
2267 """
2268
2268
2269 r1 = scmutil.revsingle(repo, rev1).node()
2269 r1 = scmutil.revsingle(repo, rev1).node()
2270 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2270 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2271
2271
2272 wlock = repo.wlock()
2272 wlock = repo.wlock()
2273 try:
2273 try:
2274 repo.setparents(r1, r2)
2274 repo.setparents(r1, r2)
2275 finally:
2275 finally:
2276 wlock.release()
2276 wlock.release()
2277
2277
2278 @command('debugstate',
2278 @command('debugstate',
2279 [('', 'nodates', None, _('do not display the saved mtime')),
2279 [('', 'nodates', None, _('do not display the saved mtime')),
2280 ('', 'datesort', None, _('sort by saved mtime'))],
2280 ('', 'datesort', None, _('sort by saved mtime'))],
2281 _('[OPTION]...'))
2281 _('[OPTION]...'))
2282 def debugstate(ui, repo, nodates=None, datesort=None):
2282 def debugstate(ui, repo, nodates=None, datesort=None):
2283 """show the contents of the current dirstate"""
2283 """show the contents of the current dirstate"""
2284 timestr = ""
2284 timestr = ""
2285 showdate = not nodates
2285 showdate = not nodates
2286 if datesort:
2286 if datesort:
2287 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2287 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2288 else:
2288 else:
2289 keyfunc = None # sort by filename
2289 keyfunc = None # sort by filename
2290 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2290 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2291 if showdate:
2291 if showdate:
2292 if ent[3] == -1:
2292 if ent[3] == -1:
2293 # Pad or slice to locale representation
2293 # Pad or slice to locale representation
2294 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2294 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2295 time.localtime(0)))
2295 time.localtime(0)))
2296 timestr = 'unset'
2296 timestr = 'unset'
2297 timestr = (timestr[:locale_len] +
2297 timestr = (timestr[:locale_len] +
2298 ' ' * (locale_len - len(timestr)))
2298 ' ' * (locale_len - len(timestr)))
2299 else:
2299 else:
2300 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2300 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2301 time.localtime(ent[3]))
2301 time.localtime(ent[3]))
2302 if ent[1] & 020000:
2302 if ent[1] & 020000:
2303 mode = 'lnk'
2303 mode = 'lnk'
2304 else:
2304 else:
2305 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2305 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2306 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2306 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2307 for f in repo.dirstate.copies():
2307 for f in repo.dirstate.copies():
2308 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2308 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2309
2309
2310 @command('debugsub',
2310 @command('debugsub',
2311 [('r', 'rev', '',
2311 [('r', 'rev', '',
2312 _('revision to check'), _('REV'))],
2312 _('revision to check'), _('REV'))],
2313 _('[-r REV] [REV]'))
2313 _('[-r REV] [REV]'))
2314 def debugsub(ui, repo, rev=None):
2314 def debugsub(ui, repo, rev=None):
2315 ctx = scmutil.revsingle(repo, rev, None)
2315 ctx = scmutil.revsingle(repo, rev, None)
2316 for k, v in sorted(ctx.substate.items()):
2316 for k, v in sorted(ctx.substate.items()):
2317 ui.write('path %s\n' % k)
2317 ui.write('path %s\n' % k)
2318 ui.write(' source %s\n' % v[0])
2318 ui.write(' source %s\n' % v[0])
2319 ui.write(' revision %s\n' % v[1])
2319 ui.write(' revision %s\n' % v[1])
2320
2320
2321 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2321 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2322 def debugwalk(ui, repo, *pats, **opts):
2322 def debugwalk(ui, repo, *pats, **opts):
2323 """show how files match on given patterns"""
2323 """show how files match on given patterns"""
2324 m = scmutil.match(repo[None], pats, opts)
2324 m = scmutil.match(repo[None], pats, opts)
2325 items = list(repo.walk(m))
2325 items = list(repo.walk(m))
2326 if not items:
2326 if not items:
2327 return
2327 return
2328 fmt = 'f %%-%ds %%-%ds %%s' % (
2328 fmt = 'f %%-%ds %%-%ds %%s' % (
2329 max([len(abs) for abs in items]),
2329 max([len(abs) for abs in items]),
2330 max([len(m.rel(abs)) for abs in items]))
2330 max([len(m.rel(abs)) for abs in items]))
2331 for abs in items:
2331 for abs in items:
2332 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2332 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2333 ui.write("%s\n" % line.rstrip())
2333 ui.write("%s\n" % line.rstrip())
2334
2334
2335 @command('debugwireargs',
2335 @command('debugwireargs',
2336 [('', 'three', '', 'three'),
2336 [('', 'three', '', 'three'),
2337 ('', 'four', '', 'four'),
2337 ('', 'four', '', 'four'),
2338 ('', 'five', '', 'five'),
2338 ('', 'five', '', 'five'),
2339 ] + remoteopts,
2339 ] + remoteopts,
2340 _('REPO [OPTIONS]... [ONE [TWO]]'))
2340 _('REPO [OPTIONS]... [ONE [TWO]]'))
2341 def debugwireargs(ui, repopath, *vals, **opts):
2341 def debugwireargs(ui, repopath, *vals, **opts):
2342 repo = hg.peer(ui, opts, repopath)
2342 repo = hg.peer(ui, opts, repopath)
2343 for opt in remoteopts:
2343 for opt in remoteopts:
2344 del opts[opt[1]]
2344 del opts[opt[1]]
2345 args = {}
2345 args = {}
2346 for k, v in opts.iteritems():
2346 for k, v in opts.iteritems():
2347 if v:
2347 if v:
2348 args[k] = v
2348 args[k] = v
2349 # run twice to check that we don't mess up the stream for the next command
2349 # run twice to check that we don't mess up the stream for the next command
2350 res1 = repo.debugwireargs(*vals, **args)
2350 res1 = repo.debugwireargs(*vals, **args)
2351 res2 = repo.debugwireargs(*vals, **args)
2351 res2 = repo.debugwireargs(*vals, **args)
2352 ui.write("%s\n" % res1)
2352 ui.write("%s\n" % res1)
2353 if res1 != res2:
2353 if res1 != res2:
2354 ui.warn("%s\n" % res2)
2354 ui.warn("%s\n" % res2)
2355
2355
2356 @command('^diff',
2356 @command('^diff',
2357 [('r', 'rev', [], _('revision'), _('REV')),
2357 [('r', 'rev', [], _('revision'), _('REV')),
2358 ('c', 'change', '', _('change made by revision'), _('REV'))
2358 ('c', 'change', '', _('change made by revision'), _('REV'))
2359 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2359 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2360 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2360 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2361 def diff(ui, repo, *pats, **opts):
2361 def diff(ui, repo, *pats, **opts):
2362 """diff repository (or selected files)
2362 """diff repository (or selected files)
2363
2363
2364 Show differences between revisions for the specified files.
2364 Show differences between revisions for the specified files.
2365
2365
2366 Differences between files are shown using the unified diff format.
2366 Differences between files are shown using the unified diff format.
2367
2367
2368 .. note::
2368 .. note::
2369 diff may generate unexpected results for merges, as it will
2369 diff may generate unexpected results for merges, as it will
2370 default to comparing against the working directory's first
2370 default to comparing against the working directory's first
2371 parent changeset if no revisions are specified.
2371 parent changeset if no revisions are specified.
2372
2372
2373 When two revision arguments are given, then changes are shown
2373 When two revision arguments are given, then changes are shown
2374 between those revisions. If only one revision is specified then
2374 between those revisions. If only one revision is specified then
2375 that revision is compared to the working directory, and, when no
2375 that revision is compared to the working directory, and, when no
2376 revisions are specified, the working directory files are compared
2376 revisions are specified, the working directory files are compared
2377 to its parent.
2377 to its parent.
2378
2378
2379 Alternatively you can specify -c/--change with a revision to see
2379 Alternatively you can specify -c/--change with a revision to see
2380 the changes in that changeset relative to its first parent.
2380 the changes in that changeset relative to its first parent.
2381
2381
2382 Without the -a/--text option, diff will avoid generating diffs of
2382 Without the -a/--text option, diff will avoid generating diffs of
2383 files it detects as binary. With -a, diff will generate a diff
2383 files it detects as binary. With -a, diff will generate a diff
2384 anyway, probably with undesirable results.
2384 anyway, probably with undesirable results.
2385
2385
2386 Use the -g/--git option to generate diffs in the git extended diff
2386 Use the -g/--git option to generate diffs in the git extended diff
2387 format. For more information, read :hg:`help diffs`.
2387 format. For more information, read :hg:`help diffs`.
2388
2388
2389 .. container:: verbose
2389 .. container:: verbose
2390
2390
2391 Examples:
2391 Examples:
2392
2392
2393 - compare a file in the current working directory to its parent::
2393 - compare a file in the current working directory to its parent::
2394
2394
2395 hg diff foo.c
2395 hg diff foo.c
2396
2396
2397 - compare two historical versions of a directory, with rename info::
2397 - compare two historical versions of a directory, with rename info::
2398
2398
2399 hg diff --git -r 1.0:1.2 lib/
2399 hg diff --git -r 1.0:1.2 lib/
2400
2400
2401 - get change stats relative to the last change on some date::
2401 - get change stats relative to the last change on some date::
2402
2402
2403 hg diff --stat -r "date('may 2')"
2403 hg diff --stat -r "date('may 2')"
2404
2404
2405 - diff all newly-added files that contain a keyword::
2405 - diff all newly-added files that contain a keyword::
2406
2406
2407 hg diff "set:added() and grep(GNU)"
2407 hg diff "set:added() and grep(GNU)"
2408
2408
2409 - compare a revision and its parents::
2409 - compare a revision and its parents::
2410
2410
2411 hg diff -c 9353 # compare against first parent
2411 hg diff -c 9353 # compare against first parent
2412 hg diff -r 9353^:9353 # same using revset syntax
2412 hg diff -r 9353^:9353 # same using revset syntax
2413 hg diff -r 9353^2:9353 # compare against the second parent
2413 hg diff -r 9353^2:9353 # compare against the second parent
2414
2414
2415 Returns 0 on success.
2415 Returns 0 on success.
2416 """
2416 """
2417
2417
2418 revs = opts.get('rev')
2418 revs = opts.get('rev')
2419 change = opts.get('change')
2419 change = opts.get('change')
2420 stat = opts.get('stat')
2420 stat = opts.get('stat')
2421 reverse = opts.get('reverse')
2421 reverse = opts.get('reverse')
2422
2422
2423 if revs and change:
2423 if revs and change:
2424 msg = _('cannot specify --rev and --change at the same time')
2424 msg = _('cannot specify --rev and --change at the same time')
2425 raise util.Abort(msg)
2425 raise util.Abort(msg)
2426 elif change:
2426 elif change:
2427 node2 = scmutil.revsingle(repo, change, None).node()
2427 node2 = scmutil.revsingle(repo, change, None).node()
2428 node1 = repo[node2].p1().node()
2428 node1 = repo[node2].p1().node()
2429 else:
2429 else:
2430 node1, node2 = scmutil.revpair(repo, revs)
2430 node1, node2 = scmutil.revpair(repo, revs)
2431
2431
2432 if reverse:
2432 if reverse:
2433 node1, node2 = node2, node1
2433 node1, node2 = node2, node1
2434
2434
2435 diffopts = patch.diffopts(ui, opts)
2435 diffopts = patch.diffopts(ui, opts)
2436 m = scmutil.match(repo[node2], pats, opts)
2436 m = scmutil.match(repo[node2], pats, opts)
2437 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2437 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2438 listsubrepos=opts.get('subrepos'))
2438 listsubrepos=opts.get('subrepos'))
2439
2439
2440 @command('^export',
2440 @command('^export',
2441 [('o', 'output', '',
2441 [('o', 'output', '',
2442 _('print output to file with formatted name'), _('FORMAT')),
2442 _('print output to file with formatted name'), _('FORMAT')),
2443 ('', 'switch-parent', None, _('diff against the second parent')),
2443 ('', 'switch-parent', None, _('diff against the second parent')),
2444 ('r', 'rev', [], _('revisions to export'), _('REV')),
2444 ('r', 'rev', [], _('revisions to export'), _('REV')),
2445 ] + diffopts,
2445 ] + diffopts,
2446 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2446 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2447 def export(ui, repo, *changesets, **opts):
2447 def export(ui, repo, *changesets, **opts):
2448 """dump the header and diffs for one or more changesets
2448 """dump the header and diffs for one or more changesets
2449
2449
2450 Print the changeset header and diffs for one or more revisions.
2450 Print the changeset header and diffs for one or more revisions.
2451
2451
2452 The information shown in the changeset header is: author, date,
2452 The information shown in the changeset header is: author, date,
2453 branch name (if non-default), changeset hash, parent(s) and commit
2453 branch name (if non-default), changeset hash, parent(s) and commit
2454 comment.
2454 comment.
2455
2455
2456 .. note::
2456 .. note::
2457 export may generate unexpected diff output for merge
2457 export may generate unexpected diff output for merge
2458 changesets, as it will compare the merge changeset against its
2458 changesets, as it will compare the merge changeset against its
2459 first parent only.
2459 first parent only.
2460
2460
2461 Output may be to a file, in which case the name of the file is
2461 Output may be to a file, in which case the name of the file is
2462 given using a format string. The formatting rules are as follows:
2462 given using a format string. The formatting rules are as follows:
2463
2463
2464 :``%%``: literal "%" character
2464 :``%%``: literal "%" character
2465 :``%H``: changeset hash (40 hexadecimal digits)
2465 :``%H``: changeset hash (40 hexadecimal digits)
2466 :``%N``: number of patches being generated
2466 :``%N``: number of patches being generated
2467 :``%R``: changeset revision number
2467 :``%R``: changeset revision number
2468 :``%b``: basename of the exporting repository
2468 :``%b``: basename of the exporting repository
2469 :``%h``: short-form changeset hash (12 hexadecimal digits)
2469 :``%h``: short-form changeset hash (12 hexadecimal digits)
2470 :``%m``: first line of the commit message (only alphanumeric characters)
2470 :``%m``: first line of the commit message (only alphanumeric characters)
2471 :``%n``: zero-padded sequence number, starting at 1
2471 :``%n``: zero-padded sequence number, starting at 1
2472 :``%r``: zero-padded changeset revision number
2472 :``%r``: zero-padded changeset revision number
2473
2473
2474 Without the -a/--text option, export will avoid generating diffs
2474 Without the -a/--text option, export will avoid generating diffs
2475 of files it detects as binary. With -a, export will generate a
2475 of files it detects as binary. With -a, export will generate a
2476 diff anyway, probably with undesirable results.
2476 diff anyway, probably with undesirable results.
2477
2477
2478 Use the -g/--git option to generate diffs in the git extended diff
2478 Use the -g/--git option to generate diffs in the git extended diff
2479 format. See :hg:`help diffs` for more information.
2479 format. See :hg:`help diffs` for more information.
2480
2480
2481 With the --switch-parent option, the diff will be against the
2481 With the --switch-parent option, the diff will be against the
2482 second parent. It can be useful to review a merge.
2482 second parent. It can be useful to review a merge.
2483
2483
2484 .. container:: verbose
2484 .. container:: verbose
2485
2485
2486 Examples:
2486 Examples:
2487
2487
2488 - use export and import to transplant a bugfix to the current
2488 - use export and import to transplant a bugfix to the current
2489 branch::
2489 branch::
2490
2490
2491 hg export -r 9353 | hg import -
2491 hg export -r 9353 | hg import -
2492
2492
2493 - export all the changesets between two revisions to a file with
2493 - export all the changesets between two revisions to a file with
2494 rename information::
2494 rename information::
2495
2495
2496 hg export --git -r 123:150 > changes.txt
2496 hg export --git -r 123:150 > changes.txt
2497
2497
2498 - split outgoing changes into a series of patches with
2498 - split outgoing changes into a series of patches with
2499 descriptive names::
2499 descriptive names::
2500
2500
2501 hg export -r "outgoing()" -o "%n-%m.patch"
2501 hg export -r "outgoing()" -o "%n-%m.patch"
2502
2502
2503 Returns 0 on success.
2503 Returns 0 on success.
2504 """
2504 """
2505 changesets += tuple(opts.get('rev', []))
2505 changesets += tuple(opts.get('rev', []))
2506 revs = scmutil.revrange(repo, changesets)
2506 revs = scmutil.revrange(repo, changesets)
2507 if not revs:
2507 if not revs:
2508 raise util.Abort(_("export requires at least one changeset"))
2508 raise util.Abort(_("export requires at least one changeset"))
2509 if len(revs) > 1:
2509 if len(revs) > 1:
2510 ui.note(_('exporting patches:\n'))
2510 ui.note(_('exporting patches:\n'))
2511 else:
2511 else:
2512 ui.note(_('exporting patch:\n'))
2512 ui.note(_('exporting patch:\n'))
2513 cmdutil.export(repo, revs, template=opts.get('output'),
2513 cmdutil.export(repo, revs, template=opts.get('output'),
2514 switch_parent=opts.get('switch_parent'),
2514 switch_parent=opts.get('switch_parent'),
2515 opts=patch.diffopts(ui, opts))
2515 opts=patch.diffopts(ui, opts))
2516
2516
2517 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2517 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2518 def forget(ui, repo, *pats, **opts):
2518 def forget(ui, repo, *pats, **opts):
2519 """forget the specified files on the next commit
2519 """forget the specified files on the next commit
2520
2520
2521 Mark the specified files so they will no longer be tracked
2521 Mark the specified files so they will no longer be tracked
2522 after the next commit.
2522 after the next commit.
2523
2523
2524 This only removes files from the current branch, not from the
2524 This only removes files from the current branch, not from the
2525 entire project history, and it does not delete them from the
2525 entire project history, and it does not delete them from the
2526 working directory.
2526 working directory.
2527
2527
2528 To undo a forget before the next commit, see :hg:`add`.
2528 To undo a forget before the next commit, see :hg:`add`.
2529
2529
2530 .. container:: verbose
2530 .. container:: verbose
2531
2531
2532 Examples:
2532 Examples:
2533
2533
2534 - forget newly-added binary files::
2534 - forget newly-added binary files::
2535
2535
2536 hg forget "set:added() and binary()"
2536 hg forget "set:added() and binary()"
2537
2537
2538 - forget files that would be excluded by .hgignore::
2538 - forget files that would be excluded by .hgignore::
2539
2539
2540 hg forget "set:hgignore()"
2540 hg forget "set:hgignore()"
2541
2541
2542 Returns 0 on success.
2542 Returns 0 on success.
2543 """
2543 """
2544
2544
2545 if not pats:
2545 if not pats:
2546 raise util.Abort(_('no files specified'))
2546 raise util.Abort(_('no files specified'))
2547
2547
2548 m = scmutil.match(repo[None], pats, opts)
2548 m = scmutil.match(repo[None], pats, opts)
2549 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2549 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2550 return rejected and 1 or 0
2550 return rejected and 1 or 0
2551
2551
2552 @command(
2552 @command(
2553 'graft',
2553 'graft',
2554 [('c', 'continue', False, _('resume interrupted graft')),
2554 [('c', 'continue', False, _('resume interrupted graft')),
2555 ('e', 'edit', False, _('invoke editor on commit messages')),
2555 ('e', 'edit', False, _('invoke editor on commit messages')),
2556 ('D', 'currentdate', False,
2556 ('D', 'currentdate', False,
2557 _('record the current date as commit date')),
2557 _('record the current date as commit date')),
2558 ('U', 'currentuser', False,
2558 ('U', 'currentuser', False,
2559 _('record the current user as committer'), _('DATE'))]
2559 _('record the current user as committer'), _('DATE'))]
2560 + commitopts2 + mergetoolopts + dryrunopts,
2560 + commitopts2 + mergetoolopts + dryrunopts,
2561 _('[OPTION]... REVISION...'))
2561 _('[OPTION]... REVISION...'))
2562 def graft(ui, repo, *revs, **opts):
2562 def graft(ui, repo, *revs, **opts):
2563 '''copy changes from other branches onto the current branch
2563 '''copy changes from other branches onto the current branch
2564
2564
2565 This command uses Mercurial's merge logic to copy individual
2565 This command uses Mercurial's merge logic to copy individual
2566 changes from other branches without merging branches in the
2566 changes from other branches without merging branches in the
2567 history graph. This is sometimes known as 'backporting' or
2567 history graph. This is sometimes known as 'backporting' or
2568 'cherry-picking'. By default, graft will copy user, date, and
2568 'cherry-picking'. By default, graft will copy user, date, and
2569 description from the source changesets.
2569 description from the source changesets.
2570
2570
2571 Changesets that are ancestors of the current revision, that have
2571 Changesets that are ancestors of the current revision, that have
2572 already been grafted, or that are merges will be skipped.
2572 already been grafted, or that are merges will be skipped.
2573
2573
2574 If a graft merge results in conflicts, the graft process is
2574 If a graft merge results in conflicts, the graft process is
2575 interrupted so that the current merge can be manually resolved.
2575 interrupted so that the current merge can be manually resolved.
2576 Once all conflicts are addressed, the graft process can be
2576 Once all conflicts are addressed, the graft process can be
2577 continued with the -c/--continue option.
2577 continued with the -c/--continue option.
2578
2578
2579 .. note::
2579 .. note::
2580 The -c/--continue option does not reapply earlier options.
2580 The -c/--continue option does not reapply earlier options.
2581
2581
2582 .. container:: verbose
2582 .. container:: verbose
2583
2583
2584 Examples:
2584 Examples:
2585
2585
2586 - copy a single change to the stable branch and edit its description::
2586 - copy a single change to the stable branch and edit its description::
2587
2587
2588 hg update stable
2588 hg update stable
2589 hg graft --edit 9393
2589 hg graft --edit 9393
2590
2590
2591 - graft a range of changesets with one exception, updating dates::
2591 - graft a range of changesets with one exception, updating dates::
2592
2592
2593 hg graft -D "2085::2093 and not 2091"
2593 hg graft -D "2085::2093 and not 2091"
2594
2594
2595 - continue a graft after resolving conflicts::
2595 - continue a graft after resolving conflicts::
2596
2596
2597 hg graft -c
2597 hg graft -c
2598
2598
2599 - show the source of a grafted changeset::
2599 - show the source of a grafted changeset::
2600
2600
2601 hg log --debug -r tip
2601 hg log --debug -r tip
2602
2602
2603 Returns 0 on successful completion.
2603 Returns 0 on successful completion.
2604 '''
2604 '''
2605
2605
2606 if not opts.get('user') and opts.get('currentuser'):
2606 if not opts.get('user') and opts.get('currentuser'):
2607 opts['user'] = ui.username()
2607 opts['user'] = ui.username()
2608 if not opts.get('date') and opts.get('currentdate'):
2608 if not opts.get('date') and opts.get('currentdate'):
2609 opts['date'] = "%d %d" % util.makedate()
2609 opts['date'] = "%d %d" % util.makedate()
2610
2610
2611 editor = None
2611 editor = None
2612 if opts.get('edit'):
2612 if opts.get('edit'):
2613 editor = cmdutil.commitforceeditor
2613 editor = cmdutil.commitforceeditor
2614
2614
2615 cont = False
2615 cont = False
2616 if opts['continue']:
2616 if opts['continue']:
2617 cont = True
2617 cont = True
2618 if revs:
2618 if revs:
2619 raise util.Abort(_("can't specify --continue and revisions"))
2619 raise util.Abort(_("can't specify --continue and revisions"))
2620 # read in unfinished revisions
2620 # read in unfinished revisions
2621 try:
2621 try:
2622 nodes = repo.opener.read('graftstate').splitlines()
2622 nodes = repo.opener.read('graftstate').splitlines()
2623 revs = [repo[node].rev() for node in nodes]
2623 revs = [repo[node].rev() for node in nodes]
2624 except IOError, inst:
2624 except IOError, inst:
2625 if inst.errno != errno.ENOENT:
2625 if inst.errno != errno.ENOENT:
2626 raise
2626 raise
2627 raise util.Abort(_("no graft state found, can't continue"))
2627 raise util.Abort(_("no graft state found, can't continue"))
2628 else:
2628 else:
2629 cmdutil.bailifchanged(repo)
2629 cmdutil.bailifchanged(repo)
2630 if not revs:
2630 if not revs:
2631 raise util.Abort(_('no revisions specified'))
2631 raise util.Abort(_('no revisions specified'))
2632 revs = scmutil.revrange(repo, revs)
2632 revs = scmutil.revrange(repo, revs)
2633
2633
2634 # check for merges
2634 # check for merges
2635 for rev in repo.revs('%ld and merge()', revs):
2635 for rev in repo.revs('%ld and merge()', revs):
2636 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2636 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2637 revs.remove(rev)
2637 revs.remove(rev)
2638 if not revs:
2638 if not revs:
2639 return -1
2639 return -1
2640
2640
2641 # check for ancestors of dest branch
2641 # check for ancestors of dest branch
2642 for rev in repo.revs('::. and %ld', revs):
2642 for rev in repo.revs('::. and %ld', revs):
2643 ui.warn(_('skipping ancestor revision %s\n') % rev)
2643 ui.warn(_('skipping ancestor revision %s\n') % rev)
2644 revs.remove(rev)
2644 revs.remove(rev)
2645 if not revs:
2645 if not revs:
2646 return -1
2646 return -1
2647
2647
2648 # analyze revs for earlier grafts
2648 # analyze revs for earlier grafts
2649 ids = {}
2649 ids = {}
2650 for ctx in repo.set("%ld", revs):
2650 for ctx in repo.set("%ld", revs):
2651 ids[ctx.hex()] = ctx.rev()
2651 ids[ctx.hex()] = ctx.rev()
2652 n = ctx.extra().get('source')
2652 n = ctx.extra().get('source')
2653 if n:
2653 if n:
2654 ids[n] = ctx.rev()
2654 ids[n] = ctx.rev()
2655
2655
2656 # check ancestors for earlier grafts
2656 # check ancestors for earlier grafts
2657 ui.debug('scanning for duplicate grafts\n')
2657 ui.debug('scanning for duplicate grafts\n')
2658 for ctx in repo.set("::. - ::%ld", revs):
2658 for ctx in repo.set("::. - ::%ld", revs):
2659 n = ctx.extra().get('source')
2659 n = ctx.extra().get('source')
2660 if n in ids:
2660 if n in ids:
2661 r = repo[n].rev()
2661 r = repo[n].rev()
2662 if r in revs:
2662 if r in revs:
2663 ui.warn(_('skipping already grafted revision %s\n') % r)
2663 ui.warn(_('skipping already grafted revision %s\n') % r)
2664 revs.remove(r)
2664 revs.remove(r)
2665 elif ids[n] in revs:
2665 elif ids[n] in revs:
2666 ui.warn(_('skipping already grafted revision %s '
2666 ui.warn(_('skipping already grafted revision %s '
2667 '(same origin %d)\n') % (ids[n], r))
2667 '(same origin %d)\n') % (ids[n], r))
2668 revs.remove(ids[n])
2668 revs.remove(ids[n])
2669 elif ctx.hex() in ids:
2669 elif ctx.hex() in ids:
2670 r = ids[ctx.hex()]
2670 r = ids[ctx.hex()]
2671 ui.warn(_('skipping already grafted revision %s '
2671 ui.warn(_('skipping already grafted revision %s '
2672 '(was grafted from %d)\n') % (r, ctx.rev()))
2672 '(was grafted from %d)\n') % (r, ctx.rev()))
2673 revs.remove(r)
2673 revs.remove(r)
2674 if not revs:
2674 if not revs:
2675 return -1
2675 return -1
2676
2676
2677 wlock = repo.wlock()
2677 wlock = repo.wlock()
2678 try:
2678 try:
2679 for pos, ctx in enumerate(repo.set("%ld", revs)):
2679 for pos, ctx in enumerate(repo.set("%ld", revs)):
2680 current = repo['.']
2680 current = repo['.']
2681
2681
2682 ui.status(_('grafting revision %s\n') % ctx.rev())
2682 ui.status(_('grafting revision %s\n') % ctx.rev())
2683 if opts.get('dry_run'):
2683 if opts.get('dry_run'):
2684 continue
2684 continue
2685
2685
2686 # we don't merge the first commit when continuing
2686 # we don't merge the first commit when continuing
2687 if not cont:
2687 if not cont:
2688 # perform the graft merge with p1(rev) as 'ancestor'
2688 # perform the graft merge with p1(rev) as 'ancestor'
2689 try:
2689 try:
2690 # ui.forcemerge is an internal variable, do not document
2690 # ui.forcemerge is an internal variable, do not document
2691 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2691 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2692 stats = mergemod.update(repo, ctx.node(), True, True, False,
2692 stats = mergemod.update(repo, ctx.node(), True, True, False,
2693 ctx.p1().node())
2693 ctx.p1().node())
2694 finally:
2694 finally:
2695 ui.setconfig('ui', 'forcemerge', '')
2695 ui.setconfig('ui', 'forcemerge', '')
2696 # drop the second merge parent
2696 # drop the second merge parent
2697 repo.setparents(current.node(), nullid)
2697 repo.setparents(current.node(), nullid)
2698 repo.dirstate.write()
2698 repo.dirstate.write()
2699 # fix up dirstate for copies and renames
2699 # fix up dirstate for copies and renames
2700 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2700 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2701 # report any conflicts
2701 # report any conflicts
2702 if stats and stats[3] > 0:
2702 if stats and stats[3] > 0:
2703 # write out state for --continue
2703 # write out state for --continue
2704 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2704 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2705 repo.opener.write('graftstate', ''.join(nodelines))
2705 repo.opener.write('graftstate', ''.join(nodelines))
2706 raise util.Abort(
2706 raise util.Abort(
2707 _("unresolved conflicts, can't continue"),
2707 _("unresolved conflicts, can't continue"),
2708 hint=_('use hg resolve and hg graft --continue'))
2708 hint=_('use hg resolve and hg graft --continue'))
2709 else:
2709 else:
2710 cont = False
2710 cont = False
2711
2711
2712 # commit
2712 # commit
2713 source = ctx.extra().get('source')
2713 source = ctx.extra().get('source')
2714 if not source:
2714 if not source:
2715 source = ctx.hex()
2715 source = ctx.hex()
2716 extra = {'source': source}
2716 extra = {'source': source}
2717 user = ctx.user()
2717 user = ctx.user()
2718 if opts.get('user'):
2718 if opts.get('user'):
2719 user = opts['user']
2719 user = opts['user']
2720 date = ctx.date()
2720 date = ctx.date()
2721 if opts.get('date'):
2721 if opts.get('date'):
2722 date = opts['date']
2722 date = opts['date']
2723 node = repo.commit(text=ctx.description(), user=user,
2723 node = repo.commit(text=ctx.description(), user=user,
2724 date=date, extra=extra, editor=editor)
2724 date=date, extra=extra, editor=editor)
2725 if node is None:
2725 if node is None:
2726 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2726 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2727 finally:
2727 finally:
2728 wlock.release()
2728 wlock.release()
2729
2729
2730 # remove state when we complete successfully
2730 # remove state when we complete successfully
2731 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2731 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2732 util.unlinkpath(repo.join('graftstate'))
2732 util.unlinkpath(repo.join('graftstate'))
2733
2733
2734 return 0
2734 return 0
2735
2735
2736 @command('grep',
2736 @command('grep',
2737 [('0', 'print0', None, _('end fields with NUL')),
2737 [('0', 'print0', None, _('end fields with NUL')),
2738 ('', 'all', None, _('print all revisions that match')),
2738 ('', 'all', None, _('print all revisions that match')),
2739 ('a', 'text', None, _('treat all files as text')),
2739 ('a', 'text', None, _('treat all files as text')),
2740 ('f', 'follow', None,
2740 ('f', 'follow', None,
2741 _('follow changeset history,'
2741 _('follow changeset history,'
2742 ' or file history across copies and renames')),
2742 ' or file history across copies and renames')),
2743 ('i', 'ignore-case', None, _('ignore case when matching')),
2743 ('i', 'ignore-case', None, _('ignore case when matching')),
2744 ('l', 'files-with-matches', None,
2744 ('l', 'files-with-matches', None,
2745 _('print only filenames and revisions that match')),
2745 _('print only filenames and revisions that match')),
2746 ('n', 'line-number', None, _('print matching line numbers')),
2746 ('n', 'line-number', None, _('print matching line numbers')),
2747 ('r', 'rev', [],
2747 ('r', 'rev', [],
2748 _('only search files changed within revision range'), _('REV')),
2748 _('only search files changed within revision range'), _('REV')),
2749 ('u', 'user', None, _('list the author (long with -v)')),
2749 ('u', 'user', None, _('list the author (long with -v)')),
2750 ('d', 'date', None, _('list the date (short with -q)')),
2750 ('d', 'date', None, _('list the date (short with -q)')),
2751 ] + walkopts,
2751 ] + walkopts,
2752 _('[OPTION]... PATTERN [FILE]...'))
2752 _('[OPTION]... PATTERN [FILE]...'))
2753 def grep(ui, repo, pattern, *pats, **opts):
2753 def grep(ui, repo, pattern, *pats, **opts):
2754 """search for a pattern in specified files and revisions
2754 """search for a pattern in specified files and revisions
2755
2755
2756 Search revisions of files for a regular expression.
2756 Search revisions of files for a regular expression.
2757
2757
2758 This command behaves differently than Unix grep. It only accepts
2758 This command behaves differently than Unix grep. It only accepts
2759 Python/Perl regexps. It searches repository history, not the
2759 Python/Perl regexps. It searches repository history, not the
2760 working directory. It always prints the revision number in which a
2760 working directory. It always prints the revision number in which a
2761 match appears.
2761 match appears.
2762
2762
2763 By default, grep only prints output for the first revision of a
2763 By default, grep only prints output for the first revision of a
2764 file in which it finds a match. To get it to print every revision
2764 file in which it finds a match. To get it to print every revision
2765 that contains a change in match status ("-" for a match that
2765 that contains a change in match status ("-" for a match that
2766 becomes a non-match, or "+" for a non-match that becomes a match),
2766 becomes a non-match, or "+" for a non-match that becomes a match),
2767 use the --all flag.
2767 use the --all flag.
2768
2768
2769 Returns 0 if a match is found, 1 otherwise.
2769 Returns 0 if a match is found, 1 otherwise.
2770 """
2770 """
2771 reflags = re.M
2771 reflags = re.M
2772 if opts.get('ignore_case'):
2772 if opts.get('ignore_case'):
2773 reflags |= re.I
2773 reflags |= re.I
2774 try:
2774 try:
2775 regexp = re.compile(pattern, reflags)
2775 regexp = re.compile(pattern, reflags)
2776 except re.error, inst:
2776 except re.error, inst:
2777 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2777 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2778 return 1
2778 return 1
2779 sep, eol = ':', '\n'
2779 sep, eol = ':', '\n'
2780 if opts.get('print0'):
2780 if opts.get('print0'):
2781 sep = eol = '\0'
2781 sep = eol = '\0'
2782
2782
2783 getfile = util.lrucachefunc(repo.file)
2783 getfile = util.lrucachefunc(repo.file)
2784
2784
2785 def matchlines(body):
2785 def matchlines(body):
2786 begin = 0
2786 begin = 0
2787 linenum = 0
2787 linenum = 0
2788 while True:
2788 while True:
2789 match = regexp.search(body, begin)
2789 match = regexp.search(body, begin)
2790 if not match:
2790 if not match:
2791 break
2791 break
2792 mstart, mend = match.span()
2792 mstart, mend = match.span()
2793 linenum += body.count('\n', begin, mstart) + 1
2793 linenum += body.count('\n', begin, mstart) + 1
2794 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2794 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2795 begin = body.find('\n', mend) + 1 or len(body) + 1
2795 begin = body.find('\n', mend) + 1 or len(body) + 1
2796 lend = begin - 1
2796 lend = begin - 1
2797 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2797 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2798
2798
2799 class linestate(object):
2799 class linestate(object):
2800 def __init__(self, line, linenum, colstart, colend):
2800 def __init__(self, line, linenum, colstart, colend):
2801 self.line = line
2801 self.line = line
2802 self.linenum = linenum
2802 self.linenum = linenum
2803 self.colstart = colstart
2803 self.colstart = colstart
2804 self.colend = colend
2804 self.colend = colend
2805
2805
2806 def __hash__(self):
2806 def __hash__(self):
2807 return hash((self.linenum, self.line))
2807 return hash((self.linenum, self.line))
2808
2808
2809 def __eq__(self, other):
2809 def __eq__(self, other):
2810 return self.line == other.line
2810 return self.line == other.line
2811
2811
2812 matches = {}
2812 matches = {}
2813 copies = {}
2813 copies = {}
2814 def grepbody(fn, rev, body):
2814 def grepbody(fn, rev, body):
2815 matches[rev].setdefault(fn, [])
2815 matches[rev].setdefault(fn, [])
2816 m = matches[rev][fn]
2816 m = matches[rev][fn]
2817 for lnum, cstart, cend, line in matchlines(body):
2817 for lnum, cstart, cend, line in matchlines(body):
2818 s = linestate(line, lnum, cstart, cend)
2818 s = linestate(line, lnum, cstart, cend)
2819 m.append(s)
2819 m.append(s)
2820
2820
2821 def difflinestates(a, b):
2821 def difflinestates(a, b):
2822 sm = difflib.SequenceMatcher(None, a, b)
2822 sm = difflib.SequenceMatcher(None, a, b)
2823 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2823 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2824 if tag == 'insert':
2824 if tag == 'insert':
2825 for i in xrange(blo, bhi):
2825 for i in xrange(blo, bhi):
2826 yield ('+', b[i])
2826 yield ('+', b[i])
2827 elif tag == 'delete':
2827 elif tag == 'delete':
2828 for i in xrange(alo, ahi):
2828 for i in xrange(alo, ahi):
2829 yield ('-', a[i])
2829 yield ('-', a[i])
2830 elif tag == 'replace':
2830 elif tag == 'replace':
2831 for i in xrange(alo, ahi):
2831 for i in xrange(alo, ahi):
2832 yield ('-', a[i])
2832 yield ('-', a[i])
2833 for i in xrange(blo, bhi):
2833 for i in xrange(blo, bhi):
2834 yield ('+', b[i])
2834 yield ('+', b[i])
2835
2835
2836 def display(fn, ctx, pstates, states):
2836 def display(fn, ctx, pstates, states):
2837 rev = ctx.rev()
2837 rev = ctx.rev()
2838 datefunc = ui.quiet and util.shortdate or util.datestr
2838 datefunc = ui.quiet and util.shortdate or util.datestr
2839 found = False
2839 found = False
2840 filerevmatches = {}
2840 filerevmatches = {}
2841 def binary():
2841 def binary():
2842 flog = getfile(fn)
2842 flog = getfile(fn)
2843 return util.binary(flog.read(ctx.filenode(fn)))
2843 return util.binary(flog.read(ctx.filenode(fn)))
2844
2844
2845 if opts.get('all'):
2845 if opts.get('all'):
2846 iter = difflinestates(pstates, states)
2846 iter = difflinestates(pstates, states)
2847 else:
2847 else:
2848 iter = [('', l) for l in states]
2848 iter = [('', l) for l in states]
2849 for change, l in iter:
2849 for change, l in iter:
2850 cols = [fn, str(rev)]
2850 cols = [fn, str(rev)]
2851 before, match, after = None, None, None
2851 before, match, after = None, None, None
2852 if opts.get('line_number'):
2852 if opts.get('line_number'):
2853 cols.append(str(l.linenum))
2853 cols.append(str(l.linenum))
2854 if opts.get('all'):
2854 if opts.get('all'):
2855 cols.append(change)
2855 cols.append(change)
2856 if opts.get('user'):
2856 if opts.get('user'):
2857 cols.append(ui.shortuser(ctx.user()))
2857 cols.append(ui.shortuser(ctx.user()))
2858 if opts.get('date'):
2858 if opts.get('date'):
2859 cols.append(datefunc(ctx.date()))
2859 cols.append(datefunc(ctx.date()))
2860 if opts.get('files_with_matches'):
2860 if opts.get('files_with_matches'):
2861 c = (fn, rev)
2861 c = (fn, rev)
2862 if c in filerevmatches:
2862 if c in filerevmatches:
2863 continue
2863 continue
2864 filerevmatches[c] = 1
2864 filerevmatches[c] = 1
2865 else:
2865 else:
2866 before = l.line[:l.colstart]
2866 before = l.line[:l.colstart]
2867 match = l.line[l.colstart:l.colend]
2867 match = l.line[l.colstart:l.colend]
2868 after = l.line[l.colend:]
2868 after = l.line[l.colend:]
2869 ui.write(sep.join(cols))
2869 ui.write(sep.join(cols))
2870 if before is not None:
2870 if before is not None:
2871 if not opts.get('text') and binary():
2871 if not opts.get('text') and binary():
2872 ui.write(sep + " Binary file matches")
2872 ui.write(sep + " Binary file matches")
2873 else:
2873 else:
2874 ui.write(sep + before)
2874 ui.write(sep + before)
2875 ui.write(match, label='grep.match')
2875 ui.write(match, label='grep.match')
2876 ui.write(after)
2876 ui.write(after)
2877 ui.write(eol)
2877 ui.write(eol)
2878 found = True
2878 found = True
2879 return found
2879 return found
2880
2880
2881 skip = {}
2881 skip = {}
2882 revfiles = {}
2882 revfiles = {}
2883 matchfn = scmutil.match(repo[None], pats, opts)
2883 matchfn = scmutil.match(repo[None], pats, opts)
2884 found = False
2884 found = False
2885 follow = opts.get('follow')
2885 follow = opts.get('follow')
2886
2886
2887 def prep(ctx, fns):
2887 def prep(ctx, fns):
2888 rev = ctx.rev()
2888 rev = ctx.rev()
2889 pctx = ctx.p1()
2889 pctx = ctx.p1()
2890 parent = pctx.rev()
2890 parent = pctx.rev()
2891 matches.setdefault(rev, {})
2891 matches.setdefault(rev, {})
2892 matches.setdefault(parent, {})
2892 matches.setdefault(parent, {})
2893 files = revfiles.setdefault(rev, [])
2893 files = revfiles.setdefault(rev, [])
2894 for fn in fns:
2894 for fn in fns:
2895 flog = getfile(fn)
2895 flog = getfile(fn)
2896 try:
2896 try:
2897 fnode = ctx.filenode(fn)
2897 fnode = ctx.filenode(fn)
2898 except error.LookupError:
2898 except error.LookupError:
2899 continue
2899 continue
2900
2900
2901 copied = flog.renamed(fnode)
2901 copied = flog.renamed(fnode)
2902 copy = follow and copied and copied[0]
2902 copy = follow and copied and copied[0]
2903 if copy:
2903 if copy:
2904 copies.setdefault(rev, {})[fn] = copy
2904 copies.setdefault(rev, {})[fn] = copy
2905 if fn in skip:
2905 if fn in skip:
2906 if copy:
2906 if copy:
2907 skip[copy] = True
2907 skip[copy] = True
2908 continue
2908 continue
2909 files.append(fn)
2909 files.append(fn)
2910
2910
2911 if fn not in matches[rev]:
2911 if fn not in matches[rev]:
2912 grepbody(fn, rev, flog.read(fnode))
2912 grepbody(fn, rev, flog.read(fnode))
2913
2913
2914 pfn = copy or fn
2914 pfn = copy or fn
2915 if pfn not in matches[parent]:
2915 if pfn not in matches[parent]:
2916 try:
2916 try:
2917 fnode = pctx.filenode(pfn)
2917 fnode = pctx.filenode(pfn)
2918 grepbody(pfn, parent, flog.read(fnode))
2918 grepbody(pfn, parent, flog.read(fnode))
2919 except error.LookupError:
2919 except error.LookupError:
2920 pass
2920 pass
2921
2921
2922 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2922 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2923 rev = ctx.rev()
2923 rev = ctx.rev()
2924 parent = ctx.p1().rev()
2924 parent = ctx.p1().rev()
2925 for fn in sorted(revfiles.get(rev, [])):
2925 for fn in sorted(revfiles.get(rev, [])):
2926 states = matches[rev][fn]
2926 states = matches[rev][fn]
2927 copy = copies.get(rev, {}).get(fn)
2927 copy = copies.get(rev, {}).get(fn)
2928 if fn in skip:
2928 if fn in skip:
2929 if copy:
2929 if copy:
2930 skip[copy] = True
2930 skip[copy] = True
2931 continue
2931 continue
2932 pstates = matches.get(parent, {}).get(copy or fn, [])
2932 pstates = matches.get(parent, {}).get(copy or fn, [])
2933 if pstates or states:
2933 if pstates or states:
2934 r = display(fn, ctx, pstates, states)
2934 r = display(fn, ctx, pstates, states)
2935 found = found or r
2935 found = found or r
2936 if r and not opts.get('all'):
2936 if r and not opts.get('all'):
2937 skip[fn] = True
2937 skip[fn] = True
2938 if copy:
2938 if copy:
2939 skip[copy] = True
2939 skip[copy] = True
2940 del matches[rev]
2940 del matches[rev]
2941 del revfiles[rev]
2941 del revfiles[rev]
2942
2942
2943 return not found
2943 return not found
2944
2944
2945 @command('heads',
2945 @command('heads',
2946 [('r', 'rev', '',
2946 [('r', 'rev', '',
2947 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2947 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2948 ('t', 'topo', False, _('show topological heads only')),
2948 ('t', 'topo', False, _('show topological heads only')),
2949 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2949 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2950 ('c', 'closed', False, _('show normal and closed branch heads')),
2950 ('c', 'closed', False, _('show normal and closed branch heads')),
2951 ] + templateopts,
2951 ] + templateopts,
2952 _('[-ac] [-r STARTREV] [REV]...'))
2952 _('[-ac] [-r STARTREV] [REV]...'))
2953 def heads(ui, repo, *branchrevs, **opts):
2953 def heads(ui, repo, *branchrevs, **opts):
2954 """show current repository heads or show branch heads
2954 """show current repository heads or show branch heads
2955
2955
2956 With no arguments, show all repository branch heads.
2956 With no arguments, show all repository branch heads.
2957
2957
2958 Repository "heads" are changesets with no child changesets. They are
2958 Repository "heads" are changesets with no child changesets. They are
2959 where development generally takes place and are the usual targets
2959 where development generally takes place and are the usual targets
2960 for update and merge operations. Branch heads are changesets that have
2960 for update and merge operations. Branch heads are changesets that have
2961 no child changeset on the same branch.
2961 no child changeset on the same branch.
2962
2962
2963 If one or more REVs are given, only branch heads on the branches
2963 If one or more REVs are given, only branch heads on the branches
2964 associated with the specified changesets are shown. This means
2964 associated with the specified changesets are shown. This means
2965 that you can use :hg:`heads foo` to see the heads on a branch
2965 that you can use :hg:`heads foo` to see the heads on a branch
2966 named ``foo``.
2966 named ``foo``.
2967
2967
2968 If -c/--closed is specified, also show branch heads marked closed
2968 If -c/--closed is specified, also show branch heads marked closed
2969 (see :hg:`commit --close-branch`).
2969 (see :hg:`commit --close-branch`).
2970
2970
2971 If STARTREV is specified, only those heads that are descendants of
2971 If STARTREV is specified, only those heads that are descendants of
2972 STARTREV will be displayed.
2972 STARTREV will be displayed.
2973
2973
2974 If -t/--topo is specified, named branch mechanics will be ignored and only
2974 If -t/--topo is specified, named branch mechanics will be ignored and only
2975 changesets without children will be shown.
2975 changesets without children will be shown.
2976
2976
2977 Returns 0 if matching heads are found, 1 if not.
2977 Returns 0 if matching heads are found, 1 if not.
2978 """
2978 """
2979
2979
2980 start = None
2980 start = None
2981 if 'rev' in opts:
2981 if 'rev' in opts:
2982 start = scmutil.revsingle(repo, opts['rev'], None).node()
2982 start = scmutil.revsingle(repo, opts['rev'], None).node()
2983
2983
2984 if opts.get('topo'):
2984 if opts.get('topo'):
2985 heads = [repo[h] for h in repo.heads(start)]
2985 heads = [repo[h] for h in repo.heads(start)]
2986 else:
2986 else:
2987 heads = []
2987 heads = []
2988 for branch in repo.branchmap():
2988 for branch in repo.branchmap():
2989 heads += repo.branchheads(branch, start, opts.get('closed'))
2989 heads += repo.branchheads(branch, start, opts.get('closed'))
2990 heads = [repo[h] for h in heads]
2990 heads = [repo[h] for h in heads]
2991
2991
2992 if branchrevs:
2992 if branchrevs:
2993 branches = set(repo[br].branch() for br in branchrevs)
2993 branches = set(repo[br].branch() for br in branchrevs)
2994 heads = [h for h in heads if h.branch() in branches]
2994 heads = [h for h in heads if h.branch() in branches]
2995
2995
2996 if opts.get('active') and branchrevs:
2996 if opts.get('active') and branchrevs:
2997 dagheads = repo.heads(start)
2997 dagheads = repo.heads(start)
2998 heads = [h for h in heads if h.node() in dagheads]
2998 heads = [h for h in heads if h.node() in dagheads]
2999
2999
3000 if branchrevs:
3000 if branchrevs:
3001 haveheads = set(h.branch() for h in heads)
3001 haveheads = set(h.branch() for h in heads)
3002 if branches - haveheads:
3002 if branches - haveheads:
3003 headless = ', '.join(b for b in branches - haveheads)
3003 headless = ', '.join(b for b in branches - haveheads)
3004 msg = _('no open branch heads found on branches %s')
3004 msg = _('no open branch heads found on branches %s')
3005 if opts.get('rev'):
3005 if opts.get('rev'):
3006 msg += _(' (started at %s)') % opts['rev']
3006 msg += _(' (started at %s)') % opts['rev']
3007 ui.warn((msg + '\n') % headless)
3007 ui.warn((msg + '\n') % headless)
3008
3008
3009 if not heads:
3009 if not heads:
3010 return 1
3010 return 1
3011
3011
3012 heads = sorted(heads, key=lambda x: -x.rev())
3012 heads = sorted(heads, key=lambda x: -x.rev())
3013 displayer = cmdutil.show_changeset(ui, repo, opts)
3013 displayer = cmdutil.show_changeset(ui, repo, opts)
3014 for ctx in heads:
3014 for ctx in heads:
3015 displayer.show(ctx)
3015 displayer.show(ctx)
3016 displayer.close()
3016 displayer.close()
3017
3017
3018 @command('help',
3018 @command('help',
3019 [('e', 'extension', None, _('show only help for extensions')),
3019 [('e', 'extension', None, _('show only help for extensions')),
3020 ('c', 'command', None, _('show only help for commands'))],
3020 ('c', 'command', None, _('show only help for commands'))],
3021 _('[-ec] [TOPIC]'))
3021 _('[-ec] [TOPIC]'))
3022 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3022 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3023 """show help for a given topic or a help overview
3023 """show help for a given topic or a help overview
3024
3024
3025 With no arguments, print a list of commands with short help messages.
3025 With no arguments, print a list of commands with short help messages.
3026
3026
3027 Given a topic, extension, or command name, print help for that
3027 Given a topic, extension, or command name, print help for that
3028 topic.
3028 topic.
3029
3029
3030 Returns 0 if successful.
3030 Returns 0 if successful.
3031 """
3031 """
3032
3032
3033 textwidth = min(ui.termwidth(), 80) - 2
3033 textwidth = min(ui.termwidth(), 80) - 2
3034
3034
3035 def optrst(options):
3035 def optrst(options):
3036 data = []
3036 data = []
3037 multioccur = False
3037 multioccur = False
3038 for option in options:
3038 for option in options:
3039 if len(option) == 5:
3039 if len(option) == 5:
3040 shortopt, longopt, default, desc, optlabel = option
3040 shortopt, longopt, default, desc, optlabel = option
3041 else:
3041 else:
3042 shortopt, longopt, default, desc = option
3042 shortopt, longopt, default, desc = option
3043 optlabel = _("VALUE") # default label
3043 optlabel = _("VALUE") # default label
3044
3044
3045 if _("DEPRECATED") in desc and not ui.verbose:
3045 if _("DEPRECATED") in desc and not ui.verbose:
3046 continue
3046 continue
3047
3047
3048 so = ''
3048 so = ''
3049 if shortopt:
3049 if shortopt:
3050 so = '-' + shortopt
3050 so = '-' + shortopt
3051 lo = '--' + longopt
3051 lo = '--' + longopt
3052 if default:
3052 if default:
3053 desc += _(" (default: %s)") % default
3053 desc += _(" (default: %s)") % default
3054
3054
3055 if isinstance(default, list):
3055 if isinstance(default, list):
3056 lo += " %s [+]" % optlabel
3056 lo += " %s [+]" % optlabel
3057 multioccur = True
3057 multioccur = True
3058 elif (default is not None) and not isinstance(default, bool):
3058 elif (default is not None) and not isinstance(default, bool):
3059 lo += " %s" % optlabel
3059 lo += " %s" % optlabel
3060
3060
3061 data.append((so, lo, desc))
3061 data.append((so, lo, desc))
3062
3062
3063 rst = minirst.maketable(data, 1)
3063 rst = minirst.maketable(data, 1)
3064
3064
3065 if multioccur:
3065 if multioccur:
3066 rst += _("\n[+] marked option can be specified multiple times\n")
3066 rst += _("\n[+] marked option can be specified multiple times\n")
3067
3067
3068 return rst
3068 return rst
3069
3069
3070 # list all option lists
3070 # list all option lists
3071 def opttext(optlist, width):
3071 def opttext(optlist, width):
3072 rst = ''
3072 rst = ''
3073 if not optlist:
3073 if not optlist:
3074 return ''
3074 return ''
3075
3075
3076 for title, options in optlist:
3076 for title, options in optlist:
3077 rst += '\n%s\n' % title
3077 rst += '\n%s\n' % title
3078 if options:
3078 if options:
3079 rst += "\n"
3079 rst += "\n"
3080 rst += optrst(options)
3080 rst += optrst(options)
3081 rst += '\n'
3081 rst += '\n'
3082
3082
3083 return '\n' + minirst.format(rst, width)
3083 return '\n' + minirst.format(rst, width)
3084
3084
3085 def addglobalopts(optlist, aliases):
3085 def addglobalopts(optlist, aliases):
3086 if ui.quiet:
3086 if ui.quiet:
3087 return []
3087 return []
3088
3088
3089 if ui.verbose:
3089 if ui.verbose:
3090 optlist.append((_("global options:"), globalopts))
3090 optlist.append((_("global options:"), globalopts))
3091 if name == 'shortlist':
3091 if name == 'shortlist':
3092 optlist.append((_('use "hg help" for the full list '
3092 optlist.append((_('use "hg help" for the full list '
3093 'of commands'), ()))
3093 'of commands'), ()))
3094 else:
3094 else:
3095 if name == 'shortlist':
3095 if name == 'shortlist':
3096 msg = _('use "hg help" for the full list of commands '
3096 msg = _('use "hg help" for the full list of commands '
3097 'or "hg -v" for details')
3097 'or "hg -v" for details')
3098 elif name and not full:
3098 elif name and not full:
3099 msg = _('use "hg help %s" to show the full help text') % name
3099 msg = _('use "hg help %s" to show the full help text') % name
3100 elif aliases:
3100 elif aliases:
3101 msg = _('use "hg -v help%s" to show builtin aliases and '
3101 msg = _('use "hg -v help%s" to show builtin aliases and '
3102 'global options') % (name and " " + name or "")
3102 'global options') % (name and " " + name or "")
3103 else:
3103 else:
3104 msg = _('use "hg -v help %s" to show more info') % name
3104 msg = _('use "hg -v help %s" to show more info') % name
3105 optlist.append((msg, ()))
3105 optlist.append((msg, ()))
3106
3106
3107 def helpcmd(name):
3107 def helpcmd(name):
3108 try:
3108 try:
3109 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3109 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3110 except error.AmbiguousCommand, inst:
3110 except error.AmbiguousCommand, inst:
3111 # py3k fix: except vars can't be used outside the scope of the
3111 # py3k fix: except vars can't be used outside the scope of the
3112 # except block, nor can be used inside a lambda. python issue4617
3112 # except block, nor can be used inside a lambda. python issue4617
3113 prefix = inst.args[0]
3113 prefix = inst.args[0]
3114 select = lambda c: c.lstrip('^').startswith(prefix)
3114 select = lambda c: c.lstrip('^').startswith(prefix)
3115 helplist(select)
3115 helplist(select)
3116 return
3116 return
3117
3117
3118 # check if it's an invalid alias and display its error if it is
3118 # check if it's an invalid alias and display its error if it is
3119 if getattr(entry[0], 'badalias', False):
3119 if getattr(entry[0], 'badalias', False):
3120 if not unknowncmd:
3120 if not unknowncmd:
3121 entry[0](ui)
3121 entry[0](ui)
3122 return
3122 return
3123
3123
3124 rst = ""
3124 rst = ""
3125
3125
3126 # synopsis
3126 # synopsis
3127 if len(entry) > 2:
3127 if len(entry) > 2:
3128 if entry[2].startswith('hg'):
3128 if entry[2].startswith('hg'):
3129 rst += "%s\n" % entry[2]
3129 rst += "%s\n" % entry[2]
3130 else:
3130 else:
3131 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3131 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3132 else:
3132 else:
3133 rst += 'hg %s\n' % aliases[0]
3133 rst += 'hg %s\n' % aliases[0]
3134
3134
3135 # aliases
3135 # aliases
3136 if full and not ui.quiet and len(aliases) > 1:
3136 if full and not ui.quiet and len(aliases) > 1:
3137 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3137 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3138
3138
3139 # description
3139 # description
3140 doc = gettext(entry[0].__doc__)
3140 doc = gettext(entry[0].__doc__)
3141 if not doc:
3141 if not doc:
3142 doc = _("(no help text available)")
3142 doc = _("(no help text available)")
3143 if util.safehasattr(entry[0], 'definition'): # aliased command
3143 if util.safehasattr(entry[0], 'definition'): # aliased command
3144 if entry[0].definition.startswith('!'): # shell alias
3144 if entry[0].definition.startswith('!'): # shell alias
3145 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3145 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3146 else:
3146 else:
3147 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3147 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3148 if ui.quiet or not full:
3148 if ui.quiet or not full:
3149 doc = doc.splitlines()[0]
3149 doc = doc.splitlines()[0]
3150 rst += "\n" + doc + "\n"
3150 rst += "\n" + doc + "\n"
3151
3151
3152 # check if this command shadows a non-trivial (multi-line)
3152 # check if this command shadows a non-trivial (multi-line)
3153 # extension help text
3153 # extension help text
3154 try:
3154 try:
3155 mod = extensions.find(name)
3155 mod = extensions.find(name)
3156 doc = gettext(mod.__doc__) or ''
3156 doc = gettext(mod.__doc__) or ''
3157 if '\n' in doc.strip():
3157 if '\n' in doc.strip():
3158 msg = _('use "hg help -e %s" to show help for '
3158 msg = _('use "hg help -e %s" to show help for '
3159 'the %s extension') % (name, name)
3159 'the %s extension') % (name, name)
3160 rst += '\n%s\n' % msg
3160 rst += '\n%s\n' % msg
3161 except KeyError:
3161 except KeyError:
3162 pass
3162 pass
3163
3163
3164 # options
3164 # options
3165 if not ui.quiet and entry[1]:
3165 if not ui.quiet and entry[1]:
3166 rst += '\n'
3166 rst += '\n'
3167 rst += _("options:")
3167 rst += _("options:")
3168 rst += '\n\n'
3168 rst += '\n\n'
3169 rst += optrst(entry[1])
3169 rst += optrst(entry[1])
3170
3170
3171 if ui.verbose:
3171 if ui.verbose:
3172 rst += '\n'
3172 rst += '\n'
3173 rst += _("global options:")
3173 rst += _("global options:")
3174 rst += '\n\n'
3174 rst += '\n\n'
3175 rst += optrst(globalopts)
3175 rst += optrst(globalopts)
3176
3176
3177 keep = ui.verbose and ['verbose'] or []
3177 keep = ui.verbose and ['verbose'] or []
3178 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3178 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3179 ui.write(formatted)
3179 ui.write(formatted)
3180
3180
3181 if not ui.verbose:
3181 if not ui.verbose:
3182 if not full:
3182 if not full:
3183 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3183 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3184 % name)
3184 % name)
3185 elif not ui.quiet:
3185 elif not ui.quiet:
3186 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3186 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3187
3187
3188
3188
3189 def helplist(select=None):
3189 def helplist(select=None):
3190 # list of commands
3190 # list of commands
3191 if name == "shortlist":
3191 if name == "shortlist":
3192 header = _('basic commands:\n\n')
3192 header = _('basic commands:\n\n')
3193 else:
3193 else:
3194 header = _('list of commands:\n\n')
3194 header = _('list of commands:\n\n')
3195
3195
3196 h = {}
3196 h = {}
3197 cmds = {}
3197 cmds = {}
3198 for c, e in table.iteritems():
3198 for c, e in table.iteritems():
3199 f = c.split("|", 1)[0]
3199 f = c.split("|", 1)[0]
3200 if select and not select(f):
3200 if select and not select(f):
3201 continue
3201 continue
3202 if (not select and name != 'shortlist' and
3202 if (not select and name != 'shortlist' and
3203 e[0].__module__ != __name__):
3203 e[0].__module__ != __name__):
3204 continue
3204 continue
3205 if name == "shortlist" and not f.startswith("^"):
3205 if name == "shortlist" and not f.startswith("^"):
3206 continue
3206 continue
3207 f = f.lstrip("^")
3207 f = f.lstrip("^")
3208 if not ui.debugflag and f.startswith("debug"):
3208 if not ui.debugflag and f.startswith("debug"):
3209 continue
3209 continue
3210 doc = e[0].__doc__
3210 doc = e[0].__doc__
3211 if doc and 'DEPRECATED' in doc and not ui.verbose:
3211 if doc and 'DEPRECATED' in doc and not ui.verbose:
3212 continue
3212 continue
3213 doc = gettext(doc)
3213 doc = gettext(doc)
3214 if not doc:
3214 if not doc:
3215 doc = _("(no help text available)")
3215 doc = _("(no help text available)")
3216 h[f] = doc.splitlines()[0].rstrip()
3216 h[f] = doc.splitlines()[0].rstrip()
3217 cmds[f] = c.lstrip("^")
3217 cmds[f] = c.lstrip("^")
3218
3218
3219 if not h:
3219 if not h:
3220 ui.status(_('no commands defined\n'))
3220 ui.status(_('no commands defined\n'))
3221 return
3221 return
3222
3222
3223 ui.status(header)
3223 ui.status(header)
3224 fns = sorted(h)
3224 fns = sorted(h)
3225 m = max(map(len, fns))
3225 m = max(map(len, fns))
3226 for f in fns:
3226 for f in fns:
3227 if ui.verbose:
3227 if ui.verbose:
3228 commands = cmds[f].replace("|",", ")
3228 commands = cmds[f].replace("|",", ")
3229 ui.write(" %s:\n %s\n"%(commands, h[f]))
3229 ui.write(" %s:\n %s\n"%(commands, h[f]))
3230 else:
3230 else:
3231 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3231 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3232 initindent=' %-*s ' % (m, f),
3232 initindent=' %-*s ' % (m, f),
3233 hangindent=' ' * (m + 4))))
3233 hangindent=' ' * (m + 4))))
3234
3234
3235 if not name:
3235 if not name:
3236 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3236 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3237 if text:
3237 if text:
3238 ui.write("\n%s" % minirst.format(text, textwidth))
3238 ui.write("\n%s" % minirst.format(text, textwidth))
3239
3239
3240 ui.write(_("\nadditional help topics:\n\n"))
3240 ui.write(_("\nadditional help topics:\n\n"))
3241 topics = []
3241 topics = []
3242 for names, header, doc in help.helptable:
3242 for names, header, doc in help.helptable:
3243 topics.append((sorted(names, key=len, reverse=True)[0], header))
3243 topics.append((sorted(names, key=len, reverse=True)[0], header))
3244 topics_len = max([len(s[0]) for s in topics])
3244 topics_len = max([len(s[0]) for s in topics])
3245 for t, desc in topics:
3245 for t, desc in topics:
3246 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3246 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3247
3247
3248 optlist = []
3248 optlist = []
3249 addglobalopts(optlist, True)
3249 addglobalopts(optlist, True)
3250 ui.write(opttext(optlist, textwidth))
3250 ui.write(opttext(optlist, textwidth))
3251
3251
3252 def helptopic(name):
3252 def helptopic(name):
3253 for names, header, doc in help.helptable:
3253 for names, header, doc in help.helptable:
3254 if name in names:
3254 if name in names:
3255 break
3255 break
3256 else:
3256 else:
3257 raise error.UnknownCommand(name)
3257 raise error.UnknownCommand(name)
3258
3258
3259 # description
3259 # description
3260 if not doc:
3260 if not doc:
3261 doc = _("(no help text available)")
3261 doc = _("(no help text available)")
3262 if util.safehasattr(doc, '__call__'):
3262 if util.safehasattr(doc, '__call__'):
3263 doc = doc()
3263 doc = doc()
3264
3264
3265 ui.write("%s\n\n" % header)
3265 ui.write("%s\n\n" % header)
3266 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3266 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3267 try:
3267 try:
3268 cmdutil.findcmd(name, table)
3268 cmdutil.findcmd(name, table)
3269 ui.write(_('\nuse "hg help -c %s" to see help for '
3269 ui.write(_('\nuse "hg help -c %s" to see help for '
3270 'the %s command\n') % (name, name))
3270 'the %s command\n') % (name, name))
3271 except error.UnknownCommand:
3271 except error.UnknownCommand:
3272 pass
3272 pass
3273
3273
3274 def helpext(name):
3274 def helpext(name):
3275 try:
3275 try:
3276 mod = extensions.find(name)
3276 mod = extensions.find(name)
3277 doc = gettext(mod.__doc__) or _('no help text available')
3277 doc = gettext(mod.__doc__) or _('no help text available')
3278 except KeyError:
3278 except KeyError:
3279 mod = None
3279 mod = None
3280 doc = extensions.disabledext(name)
3280 doc = extensions.disabledext(name)
3281 if not doc:
3281 if not doc:
3282 raise error.UnknownCommand(name)
3282 raise error.UnknownCommand(name)
3283
3283
3284 if '\n' not in doc:
3284 if '\n' not in doc:
3285 head, tail = doc, ""
3285 head, tail = doc, ""
3286 else:
3286 else:
3287 head, tail = doc.split('\n', 1)
3287 head, tail = doc.split('\n', 1)
3288 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3288 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3289 if tail:
3289 if tail:
3290 ui.write(minirst.format(tail, textwidth))
3290 ui.write(minirst.format(tail, textwidth))
3291 ui.status('\n')
3291 ui.status('\n')
3292
3292
3293 if mod:
3293 if mod:
3294 try:
3294 try:
3295 ct = mod.cmdtable
3295 ct = mod.cmdtable
3296 except AttributeError:
3296 except AttributeError:
3297 ct = {}
3297 ct = {}
3298 modcmds = set([c.split('|', 1)[0] for c in ct])
3298 modcmds = set([c.split('|', 1)[0] for c in ct])
3299 helplist(modcmds.__contains__)
3299 helplist(modcmds.__contains__)
3300 else:
3300 else:
3301 ui.write(_('use "hg help extensions" for information on enabling '
3301 ui.write(_('use "hg help extensions" for information on enabling '
3302 'extensions\n'))
3302 'extensions\n'))
3303
3303
3304 def helpextcmd(name):
3304 def helpextcmd(name):
3305 cmd, ext, mod = extensions.disabledcmd(ui, name,
3305 cmd, ext, mod = extensions.disabledcmd(ui, name,
3306 ui.configbool('ui', 'strict'))
3306 ui.configbool('ui', 'strict'))
3307 doc = gettext(mod.__doc__).splitlines()[0]
3307 doc = gettext(mod.__doc__).splitlines()[0]
3308
3308
3309 msg = help.listexts(_("'%s' is provided by the following "
3309 msg = help.listexts(_("'%s' is provided by the following "
3310 "extension:") % cmd, {ext: doc}, indent=4)
3310 "extension:") % cmd, {ext: doc}, indent=4)
3311 ui.write(minirst.format(msg, textwidth))
3311 ui.write(minirst.format(msg, textwidth))
3312 ui.write('\n')
3312 ui.write('\n')
3313 ui.write(_('use "hg help extensions" for information on enabling '
3313 ui.write(_('use "hg help extensions" for information on enabling '
3314 'extensions\n'))
3314 'extensions\n'))
3315
3315
3316 if name and name != 'shortlist':
3316 if name and name != 'shortlist':
3317 i = None
3317 i = None
3318 if unknowncmd:
3318 if unknowncmd:
3319 queries = (helpextcmd,)
3319 queries = (helpextcmd,)
3320 elif opts.get('extension'):
3320 elif opts.get('extension'):
3321 queries = (helpext,)
3321 queries = (helpext,)
3322 elif opts.get('command'):
3322 elif opts.get('command'):
3323 queries = (helpcmd,)
3323 queries = (helpcmd,)
3324 else:
3324 else:
3325 queries = (helptopic, helpcmd, helpext, helpextcmd)
3325 queries = (helptopic, helpcmd, helpext, helpextcmd)
3326 for f in queries:
3326 for f in queries:
3327 try:
3327 try:
3328 f(name)
3328 f(name)
3329 i = None
3329 i = None
3330 break
3330 break
3331 except error.UnknownCommand, inst:
3331 except error.UnknownCommand, inst:
3332 i = inst
3332 i = inst
3333 if i:
3333 if i:
3334 raise i
3334 raise i
3335 else:
3335 else:
3336 # program name
3336 # program name
3337 ui.status(_("Mercurial Distributed SCM\n"))
3337 ui.status(_("Mercurial Distributed SCM\n"))
3338 ui.status('\n')
3338 ui.status('\n')
3339 helplist()
3339 helplist()
3340
3340
3341
3341
3342 @command('identify|id',
3342 @command('identify|id',
3343 [('r', 'rev', '',
3343 [('r', 'rev', '',
3344 _('identify the specified revision'), _('REV')),
3344 _('identify the specified revision'), _('REV')),
3345 ('n', 'num', None, _('show local revision number')),
3345 ('n', 'num', None, _('show local revision number')),
3346 ('i', 'id', None, _('show global revision id')),
3346 ('i', 'id', None, _('show global revision id')),
3347 ('b', 'branch', None, _('show branch')),
3347 ('b', 'branch', None, _('show branch')),
3348 ('t', 'tags', None, _('show tags')),
3348 ('t', 'tags', None, _('show tags')),
3349 ('B', 'bookmarks', None, _('show bookmarks')),
3349 ('B', 'bookmarks', None, _('show bookmarks')),
3350 ] + remoteopts,
3350 ] + remoteopts,
3351 _('[-nibtB] [-r REV] [SOURCE]'))
3351 _('[-nibtB] [-r REV] [SOURCE]'))
3352 def identify(ui, repo, source=None, rev=None,
3352 def identify(ui, repo, source=None, rev=None,
3353 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3353 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3354 """identify the working copy or specified revision
3354 """identify the working copy or specified revision
3355
3355
3356 Print a summary identifying the repository state at REV using one or
3356 Print a summary identifying the repository state at REV using one or
3357 two parent hash identifiers, followed by a "+" if the working
3357 two parent hash identifiers, followed by a "+" if the working
3358 directory has uncommitted changes, the branch name (if not default),
3358 directory has uncommitted changes, the branch name (if not default),
3359 a list of tags, and a list of bookmarks.
3359 a list of tags, and a list of bookmarks.
3360
3360
3361 When REV is not given, print a summary of the current state of the
3361 When REV is not given, print a summary of the current state of the
3362 repository.
3362 repository.
3363
3363
3364 Specifying a path to a repository root or Mercurial bundle will
3364 Specifying a path to a repository root or Mercurial bundle will
3365 cause lookup to operate on that repository/bundle.
3365 cause lookup to operate on that repository/bundle.
3366
3366
3367 .. container:: verbose
3367 .. container:: verbose
3368
3368
3369 Examples:
3369 Examples:
3370
3370
3371 - generate a build identifier for the working directory::
3371 - generate a build identifier for the working directory::
3372
3372
3373 hg id --id > build-id.dat
3373 hg id --id > build-id.dat
3374
3374
3375 - find the revision corresponding to a tag::
3375 - find the revision corresponding to a tag::
3376
3376
3377 hg id -n -r 1.3
3377 hg id -n -r 1.3
3378
3378
3379 - check the most recent revision of a remote repository::
3379 - check the most recent revision of a remote repository::
3380
3380
3381 hg id -r tip http://selenic.com/hg/
3381 hg id -r tip http://selenic.com/hg/
3382
3382
3383 Returns 0 if successful.
3383 Returns 0 if successful.
3384 """
3384 """
3385
3385
3386 if not repo and not source:
3386 if not repo and not source:
3387 raise util.Abort(_("there is no Mercurial repository here "
3387 raise util.Abort(_("there is no Mercurial repository here "
3388 "(.hg not found)"))
3388 "(.hg not found)"))
3389
3389
3390 hexfunc = ui.debugflag and hex or short
3390 hexfunc = ui.debugflag and hex or short
3391 default = not (num or id or branch or tags or bookmarks)
3391 default = not (num or id or branch or tags or bookmarks)
3392 output = []
3392 output = []
3393 revs = []
3393 revs = []
3394
3394
3395 if source:
3395 if source:
3396 source, branches = hg.parseurl(ui.expandpath(source))
3396 source, branches = hg.parseurl(ui.expandpath(source))
3397 repo = hg.peer(ui, opts, source)
3397 repo = hg.peer(ui, opts, source)
3398 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3398 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3399
3399
3400 if not repo.local():
3400 if not repo.local():
3401 if num or branch or tags:
3401 if num or branch or tags:
3402 raise util.Abort(
3402 raise util.Abort(
3403 _("can't query remote revision number, branch, or tags"))
3403 _("can't query remote revision number, branch, or tags"))
3404 if not rev and revs:
3404 if not rev and revs:
3405 rev = revs[0]
3405 rev = revs[0]
3406 if not rev:
3406 if not rev:
3407 rev = "tip"
3407 rev = "tip"
3408
3408
3409 remoterev = repo.lookup(rev)
3409 remoterev = repo.lookup(rev)
3410 if default or id:
3410 if default or id:
3411 output = [hexfunc(remoterev)]
3411 output = [hexfunc(remoterev)]
3412
3412
3413 def getbms():
3413 def getbms():
3414 bms = []
3414 bms = []
3415
3415
3416 if 'bookmarks' in repo.listkeys('namespaces'):
3416 if 'bookmarks' in repo.listkeys('namespaces'):
3417 hexremoterev = hex(remoterev)
3417 hexremoterev = hex(remoterev)
3418 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3418 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3419 if bmr == hexremoterev]
3419 if bmr == hexremoterev]
3420
3420
3421 return bms
3421 return bms
3422
3422
3423 if bookmarks:
3423 if bookmarks:
3424 output.extend(getbms())
3424 output.extend(getbms())
3425 elif default and not ui.quiet:
3425 elif default and not ui.quiet:
3426 # multiple bookmarks for a single parent separated by '/'
3426 # multiple bookmarks for a single parent separated by '/'
3427 bm = '/'.join(getbms())
3427 bm = '/'.join(getbms())
3428 if bm:
3428 if bm:
3429 output.append(bm)
3429 output.append(bm)
3430 else:
3430 else:
3431 if not rev:
3431 if not rev:
3432 ctx = repo[None]
3432 ctx = repo[None]
3433 parents = ctx.parents()
3433 parents = ctx.parents()
3434 changed = ""
3434 changed = ""
3435 if default or id or num:
3435 if default or id or num:
3436 changed = util.any(repo.status()) and "+" or ""
3436 changed = util.any(repo.status()) and "+" or ""
3437 if default or id:
3437 if default or id:
3438 output = ["%s%s" %
3438 output = ["%s%s" %
3439 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3439 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3440 if num:
3440 if num:
3441 output.append("%s%s" %
3441 output.append("%s%s" %
3442 ('+'.join([str(p.rev()) for p in parents]), changed))
3442 ('+'.join([str(p.rev()) for p in parents]), changed))
3443 else:
3443 else:
3444 ctx = scmutil.revsingle(repo, rev)
3444 ctx = scmutil.revsingle(repo, rev)
3445 if default or id:
3445 if default or id:
3446 output = [hexfunc(ctx.node())]
3446 output = [hexfunc(ctx.node())]
3447 if num:
3447 if num:
3448 output.append(str(ctx.rev()))
3448 output.append(str(ctx.rev()))
3449
3449
3450 if default and not ui.quiet:
3450 if default and not ui.quiet:
3451 b = ctx.branch()
3451 b = ctx.branch()
3452 if b != 'default':
3452 if b != 'default':
3453 output.append("(%s)" % b)
3453 output.append("(%s)" % b)
3454
3454
3455 # multiple tags for a single parent separated by '/'
3455 # multiple tags for a single parent separated by '/'
3456 t = '/'.join(ctx.tags())
3456 t = '/'.join(ctx.tags())
3457 if t:
3457 if t:
3458 output.append(t)
3458 output.append(t)
3459
3459
3460 # multiple bookmarks for a single parent separated by '/'
3460 # multiple bookmarks for a single parent separated by '/'
3461 bm = '/'.join(ctx.bookmarks())
3461 bm = '/'.join(ctx.bookmarks())
3462 if bm:
3462 if bm:
3463 output.append(bm)
3463 output.append(bm)
3464 else:
3464 else:
3465 if branch:
3465 if branch:
3466 output.append(ctx.branch())
3466 output.append(ctx.branch())
3467
3467
3468 if tags:
3468 if tags:
3469 output.extend(ctx.tags())
3469 output.extend(ctx.tags())
3470
3470
3471 if bookmarks:
3471 if bookmarks:
3472 output.extend(ctx.bookmarks())
3472 output.extend(ctx.bookmarks())
3473
3473
3474 ui.write("%s\n" % ' '.join(output))
3474 ui.write("%s\n" % ' '.join(output))
3475
3475
3476 @command('import|patch',
3476 @command('import|patch',
3477 [('p', 'strip', 1,
3477 [('p', 'strip', 1,
3478 _('directory strip option for patch. This has the same '
3478 _('directory strip option for patch. This has the same '
3479 'meaning as the corresponding patch option'), _('NUM')),
3479 'meaning as the corresponding patch option'), _('NUM')),
3480 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3480 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3481 ('e', 'edit', False, _('invoke editor on commit messages')),
3481 ('e', 'edit', False, _('invoke editor on commit messages')),
3482 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3482 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3483 ('', 'no-commit', None,
3483 ('', 'no-commit', None,
3484 _("don't commit, just update the working directory")),
3484 _("don't commit, just update the working directory")),
3485 ('', 'bypass', None,
3485 ('', 'bypass', None,
3486 _("apply patch without touching the working directory")),
3486 _("apply patch without touching the working directory")),
3487 ('', 'exact', None,
3487 ('', 'exact', None,
3488 _('apply patch to the nodes from which it was generated')),
3488 _('apply patch to the nodes from which it was generated')),
3489 ('', 'import-branch', None,
3489 ('', 'import-branch', None,
3490 _('use any branch information in patch (implied by --exact)'))] +
3490 _('use any branch information in patch (implied by --exact)'))] +
3491 commitopts + commitopts2 + similarityopts,
3491 commitopts + commitopts2 + similarityopts,
3492 _('[OPTION]... PATCH...'))
3492 _('[OPTION]... PATCH...'))
3493 def import_(ui, repo, patch1=None, *patches, **opts):
3493 def import_(ui, repo, patch1=None, *patches, **opts):
3494 """import an ordered set of patches
3494 """import an ordered set of patches
3495
3495
3496 Import a list of patches and commit them individually (unless
3496 Import a list of patches and commit them individually (unless
3497 --no-commit is specified).
3497 --no-commit is specified).
3498
3498
3499 If there are outstanding changes in the working directory, import
3499 If there are outstanding changes in the working directory, import
3500 will abort unless given the -f/--force flag.
3500 will abort unless given the -f/--force flag.
3501
3501
3502 You can import a patch straight from a mail message. Even patches
3502 You can import a patch straight from a mail message. Even patches
3503 as attachments work (to use the body part, it must have type
3503 as attachments work (to use the body part, it must have type
3504 text/plain or text/x-patch). From and Subject headers of email
3504 text/plain or text/x-patch). From and Subject headers of email
3505 message are used as default committer and commit message. All
3505 message are used as default committer and commit message. All
3506 text/plain body parts before first diff are added to commit
3506 text/plain body parts before first diff are added to commit
3507 message.
3507 message.
3508
3508
3509 If the imported patch was generated by :hg:`export`, user and
3509 If the imported patch was generated by :hg:`export`, user and
3510 description from patch override values from message headers and
3510 description from patch override values from message headers and
3511 body. Values given on command line with -m/--message and -u/--user
3511 body. Values given on command line with -m/--message and -u/--user
3512 override these.
3512 override these.
3513
3513
3514 If --exact is specified, import will set the working directory to
3514 If --exact is specified, import will set the working directory to
3515 the parent of each patch before applying it, and will abort if the
3515 the parent of each patch before applying it, and will abort if the
3516 resulting changeset has a different ID than the one recorded in
3516 resulting changeset has a different ID than the one recorded in
3517 the patch. This may happen due to character set problems or other
3517 the patch. This may happen due to character set problems or other
3518 deficiencies in the text patch format.
3518 deficiencies in the text patch format.
3519
3519
3520 Use --bypass to apply and commit patches directly to the
3520 Use --bypass to apply and commit patches directly to the
3521 repository, not touching the working directory. Without --exact,
3521 repository, not touching the working directory. Without --exact,
3522 patches will be applied on top of the working directory parent
3522 patches will be applied on top of the working directory parent
3523 revision.
3523 revision.
3524
3524
3525 With -s/--similarity, hg will attempt to discover renames and
3525 With -s/--similarity, hg will attempt to discover renames and
3526 copies in the patch in the same way as :hg:`addremove`.
3526 copies in the patch in the same way as :hg:`addremove`.
3527
3527
3528 To read a patch from standard input, use "-" as the patch name. If
3528 To read a patch from standard input, use "-" as the patch name. If
3529 a URL is specified, the patch will be downloaded from it.
3529 a URL is specified, the patch will be downloaded from it.
3530 See :hg:`help dates` for a list of formats valid for -d/--date.
3530 See :hg:`help dates` for a list of formats valid for -d/--date.
3531
3531
3532 .. container:: verbose
3532 .. container:: verbose
3533
3533
3534 Examples:
3534 Examples:
3535
3535
3536 - import a traditional patch from a website and detect renames::
3536 - import a traditional patch from a website and detect renames::
3537
3537
3538 hg import -s 80 http://example.com/bugfix.patch
3538 hg import -s 80 http://example.com/bugfix.patch
3539
3539
3540 - import a changeset from an hgweb server::
3540 - import a changeset from an hgweb server::
3541
3541
3542 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3542 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3543
3543
3544 - import all the patches in an Unix-style mbox::
3544 - import all the patches in an Unix-style mbox::
3545
3545
3546 hg import incoming-patches.mbox
3546 hg import incoming-patches.mbox
3547
3547
3548 - attempt to exactly restore an exported changeset (not always
3548 - attempt to exactly restore an exported changeset (not always
3549 possible)::
3549 possible)::
3550
3550
3551 hg import --exact proposed-fix.patch
3551 hg import --exact proposed-fix.patch
3552
3552
3553 Returns 0 on success.
3553 Returns 0 on success.
3554 """
3554 """
3555
3555
3556 if not patch1:
3556 if not patch1:
3557 raise util.Abort(_('need at least one patch to import'))
3557 raise util.Abort(_('need at least one patch to import'))
3558
3558
3559 patches = (patch1,) + patches
3559 patches = (patch1,) + patches
3560
3560
3561 date = opts.get('date')
3561 date = opts.get('date')
3562 if date:
3562 if date:
3563 opts['date'] = util.parsedate(date)
3563 opts['date'] = util.parsedate(date)
3564
3564
3565 editor = cmdutil.commiteditor
3565 editor = cmdutil.commiteditor
3566 if opts.get('edit'):
3566 if opts.get('edit'):
3567 editor = cmdutil.commitforceeditor
3567 editor = cmdutil.commitforceeditor
3568
3568
3569 update = not opts.get('bypass')
3569 update = not opts.get('bypass')
3570 if not update and opts.get('no_commit'):
3570 if not update and opts.get('no_commit'):
3571 raise util.Abort(_('cannot use --no-commit with --bypass'))
3571 raise util.Abort(_('cannot use --no-commit with --bypass'))
3572 try:
3572 try:
3573 sim = float(opts.get('similarity') or 0)
3573 sim = float(opts.get('similarity') or 0)
3574 except ValueError:
3574 except ValueError:
3575 raise util.Abort(_('similarity must be a number'))
3575 raise util.Abort(_('similarity must be a number'))
3576 if sim < 0 or sim > 100:
3576 if sim < 0 or sim > 100:
3577 raise util.Abort(_('similarity must be between 0 and 100'))
3577 raise util.Abort(_('similarity must be between 0 and 100'))
3578 if sim and not update:
3578 if sim and not update:
3579 raise util.Abort(_('cannot use --similarity with --bypass'))
3579 raise util.Abort(_('cannot use --similarity with --bypass'))
3580
3580
3581 if (opts.get('exact') or not opts.get('force')) and update:
3581 if (opts.get('exact') or not opts.get('force')) and update:
3582 cmdutil.bailifchanged(repo)
3582 cmdutil.bailifchanged(repo)
3583
3583
3584 base = opts["base"]
3584 base = opts["base"]
3585 strip = opts["strip"]
3585 strip = opts["strip"]
3586 wlock = lock = tr = None
3586 wlock = lock = tr = None
3587 msgs = []
3587 msgs = []
3588
3588
3589 def checkexact(repo, n, nodeid):
3589 def checkexact(repo, n, nodeid):
3590 if opts.get('exact') and hex(n) != nodeid:
3590 if opts.get('exact') and hex(n) != nodeid:
3591 repo.rollback()
3591 repo.rollback()
3592 raise util.Abort(_('patch is damaged or loses information'))
3592 raise util.Abort(_('patch is damaged or loses information'))
3593
3593
3594 def tryone(ui, hunk, parents):
3594 def tryone(ui, hunk, parents):
3595 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3595 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3596 patch.extract(ui, hunk)
3596 patch.extract(ui, hunk)
3597
3597
3598 if not tmpname:
3598 if not tmpname:
3599 return (None, None)
3599 return (None, None)
3600 msg = _('applied to working directory')
3600 msg = _('applied to working directory')
3601
3601
3602 try:
3602 try:
3603 cmdline_message = cmdutil.logmessage(ui, opts)
3603 cmdline_message = cmdutil.logmessage(ui, opts)
3604 if cmdline_message:
3604 if cmdline_message:
3605 # pickup the cmdline msg
3605 # pickup the cmdline msg
3606 message = cmdline_message
3606 message = cmdline_message
3607 elif message:
3607 elif message:
3608 # pickup the patch msg
3608 # pickup the patch msg
3609 message = message.strip()
3609 message = message.strip()
3610 else:
3610 else:
3611 # launch the editor
3611 # launch the editor
3612 message = None
3612 message = None
3613 ui.debug('message:\n%s\n' % message)
3613 ui.debug('message:\n%s\n' % message)
3614
3614
3615 if len(parents) == 1:
3615 if len(parents) == 1:
3616 parents.append(repo[nullid])
3616 parents.append(repo[nullid])
3617 if opts.get('exact'):
3617 if opts.get('exact'):
3618 if not nodeid or not p1:
3618 if not nodeid or not p1:
3619 raise util.Abort(_('not a Mercurial patch'))
3619 raise util.Abort(_('not a Mercurial patch'))
3620 p1 = repo[p1]
3620 p1 = repo[p1]
3621 p2 = repo[p2 or nullid]
3621 p2 = repo[p2 or nullid]
3622 elif p2:
3622 elif p2:
3623 try:
3623 try:
3624 p1 = repo[p1]
3624 p1 = repo[p1]
3625 p2 = repo[p2]
3625 p2 = repo[p2]
3626 # Without any options, consider p2 only if the
3626 # Without any options, consider p2 only if the
3627 # patch is being applied on top of the recorded
3627 # patch is being applied on top of the recorded
3628 # first parent.
3628 # first parent.
3629 if p1 != parents[0]:
3629 if p1 != parents[0]:
3630 p1 = parents[0]
3630 p1 = parents[0]
3631 p2 = repo[nullid]
3631 p2 = repo[nullid]
3632 except error.RepoError:
3632 except error.RepoError:
3633 p1, p2 = parents
3633 p1, p2 = parents
3634 else:
3634 else:
3635 p1, p2 = parents
3635 p1, p2 = parents
3636
3636
3637 n = None
3637 n = None
3638 if update:
3638 if update:
3639 if p1 != parents[0]:
3639 if p1 != parents[0]:
3640 hg.clean(repo, p1.node())
3640 hg.clean(repo, p1.node())
3641 if p2 != parents[1]:
3641 if p2 != parents[1]:
3642 repo.setparents(p1.node(), p2.node())
3642 repo.setparents(p1.node(), p2.node())
3643
3643
3644 if opts.get('exact') or opts.get('import_branch'):
3644 if opts.get('exact') or opts.get('import_branch'):
3645 repo.dirstate.setbranch(branch or 'default')
3645 repo.dirstate.setbranch(branch or 'default')
3646
3646
3647 files = set()
3647 files = set()
3648 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3648 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3649 eolmode=None, similarity=sim / 100.0)
3649 eolmode=None, similarity=sim / 100.0)
3650 files = list(files)
3650 files = list(files)
3651 if opts.get('no_commit'):
3651 if opts.get('no_commit'):
3652 if message:
3652 if message:
3653 msgs.append(message)
3653 msgs.append(message)
3654 else:
3654 else:
3655 if opts.get('exact') or p2:
3655 if opts.get('exact') or p2:
3656 # If you got here, you either use --force and know what
3656 # If you got here, you either use --force and know what
3657 # you are doing or used --exact or a merge patch while
3657 # you are doing or used --exact or a merge patch while
3658 # being updated to its first parent.
3658 # being updated to its first parent.
3659 m = None
3659 m = None
3660 else:
3660 else:
3661 m = scmutil.matchfiles(repo, files or [])
3661 m = scmutil.matchfiles(repo, files or [])
3662 n = repo.commit(message, opts.get('user') or user,
3662 n = repo.commit(message, opts.get('user') or user,
3663 opts.get('date') or date, match=m,
3663 opts.get('date') or date, match=m,
3664 editor=editor)
3664 editor=editor)
3665 checkexact(repo, n, nodeid)
3665 checkexact(repo, n, nodeid)
3666 else:
3666 else:
3667 if opts.get('exact') or opts.get('import_branch'):
3667 if opts.get('exact') or opts.get('import_branch'):
3668 branch = branch or 'default'
3668 branch = branch or 'default'
3669 else:
3669 else:
3670 branch = p1.branch()
3670 branch = p1.branch()
3671 store = patch.filestore()
3671 store = patch.filestore()
3672 try:
3672 try:
3673 files = set()
3673 files = set()
3674 try:
3674 try:
3675 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3675 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3676 files, eolmode=None)
3676 files, eolmode=None)
3677 except patch.PatchError, e:
3677 except patch.PatchError, e:
3678 raise util.Abort(str(e))
3678 raise util.Abort(str(e))
3679 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3679 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3680 message,
3680 message,
3681 opts.get('user') or user,
3681 opts.get('user') or user,
3682 opts.get('date') or date,
3682 opts.get('date') or date,
3683 branch, files, store,
3683 branch, files, store,
3684 editor=cmdutil.commiteditor)
3684 editor=cmdutil.commiteditor)
3685 repo.savecommitmessage(memctx.description())
3685 repo.savecommitmessage(memctx.description())
3686 n = memctx.commit()
3686 n = memctx.commit()
3687 checkexact(repo, n, nodeid)
3687 checkexact(repo, n, nodeid)
3688 finally:
3688 finally:
3689 store.close()
3689 store.close()
3690 if n:
3690 if n:
3691 # i18n: refers to a short changeset id
3691 # i18n: refers to a short changeset id
3692 msg = _('created %s') % short(n)
3692 msg = _('created %s') % short(n)
3693 return (msg, n)
3693 return (msg, n)
3694 finally:
3694 finally:
3695 os.unlink(tmpname)
3695 os.unlink(tmpname)
3696
3696
3697 try:
3697 try:
3698 try:
3698 try:
3699 wlock = repo.wlock()
3699 wlock = repo.wlock()
3700 if not opts.get('no_commit'):
3700 if not opts.get('no_commit'):
3701 lock = repo.lock()
3701 lock = repo.lock()
3702 tr = repo.transaction('import')
3702 tr = repo.transaction('import')
3703 parents = repo.parents()
3703 parents = repo.parents()
3704 for patchurl in patches:
3704 for patchurl in patches:
3705 if patchurl == '-':
3705 if patchurl == '-':
3706 ui.status(_('applying patch from stdin\n'))
3706 ui.status(_('applying patch from stdin\n'))
3707 patchfile = ui.fin
3707 patchfile = ui.fin
3708 patchurl = 'stdin' # for error message
3708 patchurl = 'stdin' # for error message
3709 else:
3709 else:
3710 patchurl = os.path.join(base, patchurl)
3710 patchurl = os.path.join(base, patchurl)
3711 ui.status(_('applying %s\n') % patchurl)
3711 ui.status(_('applying %s\n') % patchurl)
3712 patchfile = url.open(ui, patchurl)
3712 patchfile = url.open(ui, patchurl)
3713
3713
3714 haspatch = False
3714 haspatch = False
3715 for hunk in patch.split(patchfile):
3715 for hunk in patch.split(patchfile):
3716 (msg, node) = tryone(ui, hunk, parents)
3716 (msg, node) = tryone(ui, hunk, parents)
3717 if msg:
3717 if msg:
3718 haspatch = True
3718 haspatch = True
3719 ui.note(msg + '\n')
3719 ui.note(msg + '\n')
3720 if update or opts.get('exact'):
3720 if update or opts.get('exact'):
3721 parents = repo.parents()
3721 parents = repo.parents()
3722 else:
3722 else:
3723 parents = [repo[node]]
3723 parents = [repo[node]]
3724
3724
3725 if not haspatch:
3725 if not haspatch:
3726 raise util.Abort(_('%s: no diffs found') % patchurl)
3726 raise util.Abort(_('%s: no diffs found') % patchurl)
3727
3727
3728 if tr:
3728 if tr:
3729 tr.close()
3729 tr.close()
3730 if msgs:
3730 if msgs:
3731 repo.savecommitmessage('\n* * *\n'.join(msgs))
3731 repo.savecommitmessage('\n* * *\n'.join(msgs))
3732 except:
3732 except:
3733 # wlock.release() indirectly calls dirstate.write(): since
3733 # wlock.release() indirectly calls dirstate.write(): since
3734 # we're crashing, we do not want to change the working dir
3734 # we're crashing, we do not want to change the working dir
3735 # parent after all, so make sure it writes nothing
3735 # parent after all, so make sure it writes nothing
3736 repo.dirstate.invalidate()
3736 repo.dirstate.invalidate()
3737 raise
3737 raise
3738 finally:
3738 finally:
3739 if tr:
3739 if tr:
3740 tr.release()
3740 tr.release()
3741 release(lock, wlock)
3741 release(lock, wlock)
3742
3742
3743 @command('incoming|in',
3743 @command('incoming|in',
3744 [('f', 'force', None,
3744 [('f', 'force', None,
3745 _('run even if remote repository is unrelated')),
3745 _('run even if remote repository is unrelated')),
3746 ('n', 'newest-first', None, _('show newest record first')),
3746 ('n', 'newest-first', None, _('show newest record first')),
3747 ('', 'bundle', '',
3747 ('', 'bundle', '',
3748 _('file to store the bundles into'), _('FILE')),
3748 _('file to store the bundles into'), _('FILE')),
3749 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3749 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3750 ('B', 'bookmarks', False, _("compare bookmarks")),
3750 ('B', 'bookmarks', False, _("compare bookmarks")),
3751 ('b', 'branch', [],
3751 ('b', 'branch', [],
3752 _('a specific branch you would like to pull'), _('BRANCH')),
3752 _('a specific branch you would like to pull'), _('BRANCH')),
3753 ] + logopts + remoteopts + subrepoopts,
3753 ] + logopts + remoteopts + subrepoopts,
3754 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3754 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3755 def incoming(ui, repo, source="default", **opts):
3755 def incoming(ui, repo, source="default", **opts):
3756 """show new changesets found in source
3756 """show new changesets found in source
3757
3757
3758 Show new changesets found in the specified path/URL or the default
3758 Show new changesets found in the specified path/URL or the default
3759 pull location. These are the changesets that would have been pulled
3759 pull location. These are the changesets that would have been pulled
3760 if a pull at the time you issued this command.
3760 if a pull at the time you issued this command.
3761
3761
3762 For remote repository, using --bundle avoids downloading the
3762 For remote repository, using --bundle avoids downloading the
3763 changesets twice if the incoming is followed by a pull.
3763 changesets twice if the incoming is followed by a pull.
3764
3764
3765 See pull for valid source format details.
3765 See pull for valid source format details.
3766
3766
3767 Returns 0 if there are incoming changes, 1 otherwise.
3767 Returns 0 if there are incoming changes, 1 otherwise.
3768 """
3768 """
3769 if opts.get('bundle') and opts.get('subrepos'):
3769 if opts.get('bundle') and opts.get('subrepos'):
3770 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3770 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3771
3771
3772 if opts.get('bookmarks'):
3772 if opts.get('bookmarks'):
3773 source, branches = hg.parseurl(ui.expandpath(source),
3773 source, branches = hg.parseurl(ui.expandpath(source),
3774 opts.get('branch'))
3774 opts.get('branch'))
3775 other = hg.peer(repo, opts, source)
3775 other = hg.peer(repo, opts, source)
3776 if 'bookmarks' not in other.listkeys('namespaces'):
3776 if 'bookmarks' not in other.listkeys('namespaces'):
3777 ui.warn(_("remote doesn't support bookmarks\n"))
3777 ui.warn(_("remote doesn't support bookmarks\n"))
3778 return 0
3778 return 0
3779 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3779 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3780 return bookmarks.diff(ui, repo, other)
3780 return bookmarks.diff(ui, repo, other)
3781
3781
3782 repo._subtoppath = ui.expandpath(source)
3782 repo._subtoppath = ui.expandpath(source)
3783 try:
3783 try:
3784 return hg.incoming(ui, repo, source, opts)
3784 return hg.incoming(ui, repo, source, opts)
3785 finally:
3785 finally:
3786 del repo._subtoppath
3786 del repo._subtoppath
3787
3787
3788
3788
3789 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3789 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3790 def init(ui, dest=".", **opts):
3790 def init(ui, dest=".", **opts):
3791 """create a new repository in the given directory
3791 """create a new repository in the given directory
3792
3792
3793 Initialize a new repository in the given directory. If the given
3793 Initialize a new repository in the given directory. If the given
3794 directory does not exist, it will be created.
3794 directory does not exist, it will be created.
3795
3795
3796 If no directory is given, the current directory is used.
3796 If no directory is given, the current directory is used.
3797
3797
3798 It is possible to specify an ``ssh://`` URL as the destination.
3798 It is possible to specify an ``ssh://`` URL as the destination.
3799 See :hg:`help urls` for more information.
3799 See :hg:`help urls` for more information.
3800
3800
3801 Returns 0 on success.
3801 Returns 0 on success.
3802 """
3802 """
3803 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3803 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3804
3804
3805 @command('locate',
3805 @command('locate',
3806 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3806 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3807 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3807 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3808 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3808 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3809 ] + walkopts,
3809 ] + walkopts,
3810 _('[OPTION]... [PATTERN]...'))
3810 _('[OPTION]... [PATTERN]...'))
3811 def locate(ui, repo, *pats, **opts):
3811 def locate(ui, repo, *pats, **opts):
3812 """locate files matching specific patterns
3812 """locate files matching specific patterns
3813
3813
3814 Print files under Mercurial control in the working directory whose
3814 Print files under Mercurial control in the working directory whose
3815 names match the given patterns.
3815 names match the given patterns.
3816
3816
3817 By default, this command searches all directories in the working
3817 By default, this command searches all directories in the working
3818 directory. To search just the current directory and its
3818 directory. To search just the current directory and its
3819 subdirectories, use "--include .".
3819 subdirectories, use "--include .".
3820
3820
3821 If no patterns are given to match, this command prints the names
3821 If no patterns are given to match, this command prints the names
3822 of all files under Mercurial control in the working directory.
3822 of all files under Mercurial control in the working directory.
3823
3823
3824 If you want to feed the output of this command into the "xargs"
3824 If you want to feed the output of this command into the "xargs"
3825 command, use the -0 option to both this command and "xargs". This
3825 command, use the -0 option to both this command and "xargs". This
3826 will avoid the problem of "xargs" treating single filenames that
3826 will avoid the problem of "xargs" treating single filenames that
3827 contain whitespace as multiple filenames.
3827 contain whitespace as multiple filenames.
3828
3828
3829 Returns 0 if a match is found, 1 otherwise.
3829 Returns 0 if a match is found, 1 otherwise.
3830 """
3830 """
3831 end = opts.get('print0') and '\0' or '\n'
3831 end = opts.get('print0') and '\0' or '\n'
3832 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3832 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3833
3833
3834 ret = 1
3834 ret = 1
3835 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3835 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3836 m.bad = lambda x, y: False
3836 m.bad = lambda x, y: False
3837 for abs in repo[rev].walk(m):
3837 for abs in repo[rev].walk(m):
3838 if not rev and abs not in repo.dirstate:
3838 if not rev and abs not in repo.dirstate:
3839 continue
3839 continue
3840 if opts.get('fullpath'):
3840 if opts.get('fullpath'):
3841 ui.write(repo.wjoin(abs), end)
3841 ui.write(repo.wjoin(abs), end)
3842 else:
3842 else:
3843 ui.write(((pats and m.rel(abs)) or abs), end)
3843 ui.write(((pats and m.rel(abs)) or abs), end)
3844 ret = 0
3844 ret = 0
3845
3845
3846 return ret
3846 return ret
3847
3847
3848 @command('^log|history',
3848 @command('^log|history',
3849 [('f', 'follow', None,
3849 [('f', 'follow', None,
3850 _('follow changeset history, or file history across copies and renames')),
3850 _('follow changeset history, or file history across copies and renames')),
3851 ('', 'follow-first', None,
3851 ('', 'follow-first', None,
3852 _('only follow the first parent of merge changesets (DEPRECATED)')),
3852 _('only follow the first parent of merge changesets (DEPRECATED)')),
3853 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3853 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3854 ('C', 'copies', None, _('show copied files')),
3854 ('C', 'copies', None, _('show copied files')),
3855 ('k', 'keyword', [],
3855 ('k', 'keyword', [],
3856 _('do case-insensitive search for a given text'), _('TEXT')),
3856 _('do case-insensitive search for a given text'), _('TEXT')),
3857 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3857 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3858 ('', 'removed', None, _('include revisions where files were removed')),
3858 ('', 'removed', None, _('include revisions where files were removed')),
3859 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3859 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3860 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3860 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3861 ('', 'only-branch', [],
3861 ('', 'only-branch', [],
3862 _('show only changesets within the given named branch (DEPRECATED)'),
3862 _('show only changesets within the given named branch (DEPRECATED)'),
3863 _('BRANCH')),
3863 _('BRANCH')),
3864 ('b', 'branch', [],
3864 ('b', 'branch', [],
3865 _('show changesets within the given named branch'), _('BRANCH')),
3865 _('show changesets within the given named branch'), _('BRANCH')),
3866 ('P', 'prune', [],
3866 ('P', 'prune', [],
3867 _('do not display revision or any of its ancestors'), _('REV')),
3867 _('do not display revision or any of its ancestors'), _('REV')),
3868 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3868 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3869 ] + logopts + walkopts,
3869 ] + logopts + walkopts,
3870 _('[OPTION]... [FILE]'))
3870 _('[OPTION]... [FILE]'))
3871 def log(ui, repo, *pats, **opts):
3871 def log(ui, repo, *pats, **opts):
3872 """show revision history of entire repository or files
3872 """show revision history of entire repository or files
3873
3873
3874 Print the revision history of the specified files or the entire
3874 Print the revision history of the specified files or the entire
3875 project.
3875 project.
3876
3876
3877 If no revision range is specified, the default is ``tip:0`` unless
3877 If no revision range is specified, the default is ``tip:0`` unless
3878 --follow is set, in which case the working directory parent is
3878 --follow is set, in which case the working directory parent is
3879 used as the starting revision.
3879 used as the starting revision.
3880
3880
3881 File history is shown without following rename or copy history of
3881 File history is shown without following rename or copy history of
3882 files. Use -f/--follow with a filename to follow history across
3882 files. Use -f/--follow with a filename to follow history across
3883 renames and copies. --follow without a filename will only show
3883 renames and copies. --follow without a filename will only show
3884 ancestors or descendants of the starting revision.
3884 ancestors or descendants of the starting revision.
3885
3885
3886 By default this command prints revision number and changeset id,
3886 By default this command prints revision number and changeset id,
3887 tags, non-trivial parents, user, date and time, and a summary for
3887 tags, non-trivial parents, user, date and time, and a summary for
3888 each commit. When the -v/--verbose switch is used, the list of
3888 each commit. When the -v/--verbose switch is used, the list of
3889 changed files and full commit message are shown.
3889 changed files and full commit message are shown.
3890
3890
3891 .. note::
3891 .. note::
3892 log -p/--patch may generate unexpected diff output for merge
3892 log -p/--patch may generate unexpected diff output for merge
3893 changesets, as it will only compare the merge changeset against
3893 changesets, as it will only compare the merge changeset against
3894 its first parent. Also, only files different from BOTH parents
3894 its first parent. Also, only files different from BOTH parents
3895 will appear in files:.
3895 will appear in files:.
3896
3896
3897 .. note::
3897 .. note::
3898 for performance reasons, log FILE may omit duplicate changes
3898 for performance reasons, log FILE may omit duplicate changes
3899 made on branches and will not show deletions. To see all
3899 made on branches and will not show deletions. To see all
3900 changes including duplicates and deletions, use the --removed
3900 changes including duplicates and deletions, use the --removed
3901 switch.
3901 switch.
3902
3902
3903 .. container:: verbose
3903 .. container:: verbose
3904
3904
3905 Some examples:
3905 Some examples:
3906
3906
3907 - changesets with full descriptions and file lists::
3907 - changesets with full descriptions and file lists::
3908
3908
3909 hg log -v
3909 hg log -v
3910
3910
3911 - changesets ancestral to the working directory::
3911 - changesets ancestral to the working directory::
3912
3912
3913 hg log -f
3913 hg log -f
3914
3914
3915 - last 10 commits on the current branch::
3915 - last 10 commits on the current branch::
3916
3916
3917 hg log -l 10 -b .
3917 hg log -l 10 -b .
3918
3918
3919 - changesets showing all modifications of a file, including removals::
3919 - changesets showing all modifications of a file, including removals::
3920
3920
3921 hg log --removed file.c
3921 hg log --removed file.c
3922
3922
3923 - all changesets that touch a directory, with diffs, excluding merges::
3923 - all changesets that touch a directory, with diffs, excluding merges::
3924
3924
3925 hg log -Mp lib/
3925 hg log -Mp lib/
3926
3926
3927 - all revision numbers that match a keyword::
3927 - all revision numbers that match a keyword::
3928
3928
3929 hg log -k bug --template "{rev}\\n"
3929 hg log -k bug --template "{rev}\\n"
3930
3930
3931 - check if a given changeset is included is a tagged release::
3931 - check if a given changeset is included is a tagged release::
3932
3932
3933 hg log -r "a21ccf and ancestor(1.9)"
3933 hg log -r "a21ccf and ancestor(1.9)"
3934
3934
3935 - find all changesets by some user in a date range::
3935 - find all changesets by some user in a date range::
3936
3936
3937 hg log -k alice -d "may 2008 to jul 2008"
3937 hg log -k alice -d "may 2008 to jul 2008"
3938
3938
3939 - summary of all changesets after the last tag::
3939 - summary of all changesets after the last tag::
3940
3940
3941 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3941 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3942
3942
3943 See :hg:`help dates` for a list of formats valid for -d/--date.
3943 See :hg:`help dates` for a list of formats valid for -d/--date.
3944
3944
3945 See :hg:`help revisions` and :hg:`help revsets` for more about
3945 See :hg:`help revisions` and :hg:`help revsets` for more about
3946 specifying revisions.
3946 specifying revisions.
3947
3947
3948 See :hg:`help templates` for more about pre-packaged styles and
3948 See :hg:`help templates` for more about pre-packaged styles and
3949 specifying custom templates.
3949 specifying custom templates.
3950
3950
3951 Returns 0 on success.
3951 Returns 0 on success.
3952 """
3952 """
3953
3953
3954 matchfn = scmutil.match(repo[None], pats, opts)
3954 matchfn = scmutil.match(repo[None], pats, opts)
3955 limit = cmdutil.loglimit(opts)
3955 limit = cmdutil.loglimit(opts)
3956 count = 0
3956 count = 0
3957
3957
3958 getrenamed, endrev = None, None
3958 getrenamed, endrev = None, None
3959 if opts.get('copies'):
3959 if opts.get('copies'):
3960 if opts.get('rev'):
3960 if opts.get('rev'):
3961 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3961 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3962 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3962 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3963
3963
3964 df = False
3964 df = False
3965 if opts["date"]:
3965 if opts["date"]:
3966 df = util.matchdate(opts["date"])
3966 df = util.matchdate(opts["date"])
3967
3967
3968 branches = opts.get('branch', []) + opts.get('only_branch', [])
3968 branches = opts.get('branch', []) + opts.get('only_branch', [])
3969 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3969 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3970
3970
3971 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3971 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3972 def prep(ctx, fns):
3972 def prep(ctx, fns):
3973 rev = ctx.rev()
3973 rev = ctx.rev()
3974 parents = [p for p in repo.changelog.parentrevs(rev)
3974 parents = [p for p in repo.changelog.parentrevs(rev)
3975 if p != nullrev]
3975 if p != nullrev]
3976 if opts.get('no_merges') and len(parents) == 2:
3976 if opts.get('no_merges') and len(parents) == 2:
3977 return
3977 return
3978 if opts.get('only_merges') and len(parents) != 2:
3978 if opts.get('only_merges') and len(parents) != 2:
3979 return
3979 return
3980 if opts.get('branch') and ctx.branch() not in opts['branch']:
3980 if opts.get('branch') and ctx.branch() not in opts['branch']:
3981 return
3981 return
3982 if not opts.get('hidden') and ctx.hidden():
3982 if not opts.get('hidden') and ctx.hidden():
3983 return
3983 return
3984 if df and not df(ctx.date()[0]):
3984 if df and not df(ctx.date()[0]):
3985 return
3985 return
3986
3986
3987 lower = encoding.lower
3987 lower = encoding.lower
3988 if opts.get('user'):
3988 if opts.get('user'):
3989 luser = lower(ctx.user())
3989 luser = lower(ctx.user())
3990 for k in [lower(x) for x in opts['user']]:
3990 for k in [lower(x) for x in opts['user']]:
3991 if (k in luser):
3991 if (k in luser):
3992 break
3992 break
3993 else:
3993 else:
3994 return
3994 return
3995 if opts.get('keyword'):
3995 if opts.get('keyword'):
3996 luser = lower(ctx.user())
3996 luser = lower(ctx.user())
3997 ldesc = lower(ctx.description())
3997 ldesc = lower(ctx.description())
3998 lfiles = lower(" ".join(ctx.files()))
3998 lfiles = lower(" ".join(ctx.files()))
3999 for k in [lower(x) for x in opts['keyword']]:
3999 for k in [lower(x) for x in opts['keyword']]:
4000 if (k in luser or k in ldesc or k in lfiles):
4000 if (k in luser or k in ldesc or k in lfiles):
4001 break
4001 break
4002 else:
4002 else:
4003 return
4003 return
4004
4004
4005 copies = None
4005 copies = None
4006 if getrenamed is not None and rev:
4006 if getrenamed is not None and rev:
4007 copies = []
4007 copies = []
4008 for fn in ctx.files():
4008 for fn in ctx.files():
4009 rename = getrenamed(fn, rev)
4009 rename = getrenamed(fn, rev)
4010 if rename:
4010 if rename:
4011 copies.append((fn, rename[0]))
4011 copies.append((fn, rename[0]))
4012
4012
4013 revmatchfn = None
4013 revmatchfn = None
4014 if opts.get('patch') or opts.get('stat'):
4014 if opts.get('patch') or opts.get('stat'):
4015 if opts.get('follow') or opts.get('follow_first'):
4015 if opts.get('follow') or opts.get('follow_first'):
4016 # note: this might be wrong when following through merges
4016 # note: this might be wrong when following through merges
4017 revmatchfn = scmutil.match(repo[None], fns, default='path')
4017 revmatchfn = scmutil.match(repo[None], fns, default='path')
4018 else:
4018 else:
4019 revmatchfn = matchfn
4019 revmatchfn = matchfn
4020
4020
4021 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4021 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4022
4022
4023 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4023 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4024 if count == limit:
4024 if count == limit:
4025 break
4025 break
4026 if displayer.flush(ctx.rev()):
4026 if displayer.flush(ctx.rev()):
4027 count += 1
4027 count += 1
4028 displayer.close()
4028 displayer.close()
4029
4029
4030 @command('manifest',
4030 @command('manifest',
4031 [('r', 'rev', '', _('revision to display'), _('REV')),
4031 [('r', 'rev', '', _('revision to display'), _('REV')),
4032 ('', 'all', False, _("list files from all revisions"))],
4032 ('', 'all', False, _("list files from all revisions"))],
4033 _('[-r REV]'))
4033 _('[-r REV]'))
4034 def manifest(ui, repo, node=None, rev=None, **opts):
4034 def manifest(ui, repo, node=None, rev=None, **opts):
4035 """output the current or given revision of the project manifest
4035 """output the current or given revision of the project manifest
4036
4036
4037 Print a list of version controlled files for the given revision.
4037 Print a list of version controlled files for the given revision.
4038 If no revision is given, the first parent of the working directory
4038 If no revision is given, the first parent of the working directory
4039 is used, or the null revision if no revision is checked out.
4039 is used, or the null revision if no revision is checked out.
4040
4040
4041 With -v, print file permissions, symlink and executable bits.
4041 With -v, print file permissions, symlink and executable bits.
4042 With --debug, print file revision hashes.
4042 With --debug, print file revision hashes.
4043
4043
4044 If option --all is specified, the list of all files from all revisions
4044 If option --all is specified, the list of all files from all revisions
4045 is printed. This includes deleted and renamed files.
4045 is printed. This includes deleted and renamed files.
4046
4046
4047 Returns 0 on success.
4047 Returns 0 on success.
4048 """
4048 """
4049 if opts.get('all'):
4049 if opts.get('all'):
4050 if rev or node:
4050 if rev or node:
4051 raise util.Abort(_("can't specify a revision with --all"))
4051 raise util.Abort(_("can't specify a revision with --all"))
4052
4052
4053 res = []
4053 res = []
4054 prefix = "data/"
4054 prefix = "data/"
4055 suffix = ".i"
4055 suffix = ".i"
4056 plen = len(prefix)
4056 plen = len(prefix)
4057 slen = len(suffix)
4057 slen = len(suffix)
4058 lock = repo.lock()
4058 lock = repo.lock()
4059 try:
4059 try:
4060 for fn, b, size in repo.store.datafiles():
4060 for fn, b, size in repo.store.datafiles():
4061 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4061 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4062 res.append(fn[plen:-slen])
4062 res.append(fn[plen:-slen])
4063 finally:
4063 finally:
4064 lock.release()
4064 lock.release()
4065 for f in sorted(res):
4065 for f in sorted(res):
4066 ui.write("%s\n" % f)
4066 ui.write("%s\n" % f)
4067 return
4067 return
4068
4068
4069 if rev and node:
4069 if rev and node:
4070 raise util.Abort(_("please specify just one revision"))
4070 raise util.Abort(_("please specify just one revision"))
4071
4071
4072 if not node:
4072 if not node:
4073 node = rev
4073 node = rev
4074
4074
4075 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4075 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4076 ctx = scmutil.revsingle(repo, node)
4076 ctx = scmutil.revsingle(repo, node)
4077 for f in ctx:
4077 for f in ctx:
4078 if ui.debugflag:
4078 if ui.debugflag:
4079 ui.write("%40s " % hex(ctx.manifest()[f]))
4079 ui.write("%40s " % hex(ctx.manifest()[f]))
4080 if ui.verbose:
4080 if ui.verbose:
4081 ui.write(decor[ctx.flags(f)])
4081 ui.write(decor[ctx.flags(f)])
4082 ui.write("%s\n" % f)
4082 ui.write("%s\n" % f)
4083
4083
4084 @command('^merge',
4084 @command('^merge',
4085 [('f', 'force', None, _('force a merge with outstanding changes')),
4085 [('f', 'force', None, _('force a merge with outstanding changes')),
4086 ('r', 'rev', '', _('revision to merge'), _('REV')),
4086 ('r', 'rev', '', _('revision to merge'), _('REV')),
4087 ('P', 'preview', None,
4087 ('P', 'preview', None,
4088 _('review revisions to merge (no merge is performed)'))
4088 _('review revisions to merge (no merge is performed)'))
4089 ] + mergetoolopts,
4089 ] + mergetoolopts,
4090 _('[-P] [-f] [[-r] REV]'))
4090 _('[-P] [-f] [[-r] REV]'))
4091 def merge(ui, repo, node=None, **opts):
4091 def merge(ui, repo, node=None, **opts):
4092 """merge working directory with another revision
4092 """merge working directory with another revision
4093
4093
4094 The current working directory is updated with all changes made in
4094 The current working directory is updated with all changes made in
4095 the requested revision since the last common predecessor revision.
4095 the requested revision since the last common predecessor revision.
4096
4096
4097 Files that changed between either parent are marked as changed for
4097 Files that changed between either parent are marked as changed for
4098 the next commit and a commit must be performed before any further
4098 the next commit and a commit must be performed before any further
4099 updates to the repository are allowed. The next commit will have
4099 updates to the repository are allowed. The next commit will have
4100 two parents.
4100 two parents.
4101
4101
4102 ``--tool`` can be used to specify the merge tool used for file
4102 ``--tool`` can be used to specify the merge tool used for file
4103 merges. It overrides the HGMERGE environment variable and your
4103 merges. It overrides the HGMERGE environment variable and your
4104 configuration files. See :hg:`help merge-tools` for options.
4104 configuration files. See :hg:`help merge-tools` for options.
4105
4105
4106 If no revision is specified, the working directory's parent is a
4106 If no revision is specified, the working directory's parent is a
4107 head revision, and the current branch contains exactly one other
4107 head revision, and the current branch contains exactly one other
4108 head, the other head is merged with by default. Otherwise, an
4108 head, the other head is merged with by default. Otherwise, an
4109 explicit revision with which to merge with must be provided.
4109 explicit revision with which to merge with must be provided.
4110
4110
4111 :hg:`resolve` must be used to resolve unresolved files.
4111 :hg:`resolve` must be used to resolve unresolved files.
4112
4112
4113 To undo an uncommitted merge, use :hg:`update --clean .` which
4113 To undo an uncommitted merge, use :hg:`update --clean .` which
4114 will check out a clean copy of the original merge parent, losing
4114 will check out a clean copy of the original merge parent, losing
4115 all changes.
4115 all changes.
4116
4116
4117 Returns 0 on success, 1 if there are unresolved files.
4117 Returns 0 on success, 1 if there are unresolved files.
4118 """
4118 """
4119
4119
4120 if opts.get('rev') and node:
4120 if opts.get('rev') and node:
4121 raise util.Abort(_("please specify just one revision"))
4121 raise util.Abort(_("please specify just one revision"))
4122 if not node:
4122 if not node:
4123 node = opts.get('rev')
4123 node = opts.get('rev')
4124
4124
4125 if not node:
4125 if not node:
4126 branch = repo[None].branch()
4126 branch = repo[None].branch()
4127 bheads = repo.branchheads(branch)
4127 bheads = repo.branchheads(branch)
4128 if len(bheads) > 2:
4128 if len(bheads) > 2:
4129 raise util.Abort(_("branch '%s' has %d heads - "
4129 raise util.Abort(_("branch '%s' has %d heads - "
4130 "please merge with an explicit rev")
4130 "please merge with an explicit rev")
4131 % (branch, len(bheads)),
4131 % (branch, len(bheads)),
4132 hint=_("run 'hg heads .' to see heads"))
4132 hint=_("run 'hg heads .' to see heads"))
4133
4133
4134 parent = repo.dirstate.p1()
4134 parent = repo.dirstate.p1()
4135 if len(bheads) == 1:
4135 if len(bheads) == 1:
4136 if len(repo.heads()) > 1:
4136 if len(repo.heads()) > 1:
4137 raise util.Abort(_("branch '%s' has one head - "
4137 raise util.Abort(_("branch '%s' has one head - "
4138 "please merge with an explicit rev")
4138 "please merge with an explicit rev")
4139 % branch,
4139 % branch,
4140 hint=_("run 'hg heads' to see all heads"))
4140 hint=_("run 'hg heads' to see all heads"))
4141 msg, hint = _('nothing to merge'), None
4141 msg, hint = _('nothing to merge'), None
4142 if parent != repo.lookup(branch):
4142 if parent != repo.lookup(branch):
4143 hint = _("use 'hg update' instead")
4143 hint = _("use 'hg update' instead")
4144 raise util.Abort(msg, hint=hint)
4144 raise util.Abort(msg, hint=hint)
4145
4145
4146 if parent not in bheads:
4146 if parent not in bheads:
4147 raise util.Abort(_('working directory not at a head revision'),
4147 raise util.Abort(_('working directory not at a head revision'),
4148 hint=_("use 'hg update' or merge with an "
4148 hint=_("use 'hg update' or merge with an "
4149 "explicit revision"))
4149 "explicit revision"))
4150 node = parent == bheads[0] and bheads[-1] or bheads[0]
4150 node = parent == bheads[0] and bheads[-1] or bheads[0]
4151 else:
4151 else:
4152 node = scmutil.revsingle(repo, node).node()
4152 node = scmutil.revsingle(repo, node).node()
4153
4153
4154 if opts.get('preview'):
4154 if opts.get('preview'):
4155 # find nodes that are ancestors of p2 but not of p1
4155 # find nodes that are ancestors of p2 but not of p1
4156 p1 = repo.lookup('.')
4156 p1 = repo.lookup('.')
4157 p2 = repo.lookup(node)
4157 p2 = repo.lookup(node)
4158 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4158 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4159
4159
4160 displayer = cmdutil.show_changeset(ui, repo, opts)
4160 displayer = cmdutil.show_changeset(ui, repo, opts)
4161 for node in nodes:
4161 for node in nodes:
4162 displayer.show(repo[node])
4162 displayer.show(repo[node])
4163 displayer.close()
4163 displayer.close()
4164 return 0
4164 return 0
4165
4165
4166 try:
4166 try:
4167 # ui.forcemerge is an internal variable, do not document
4167 # ui.forcemerge is an internal variable, do not document
4168 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4168 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4169 return hg.merge(repo, node, force=opts.get('force'))
4169 return hg.merge(repo, node, force=opts.get('force'))
4170 finally:
4170 finally:
4171 ui.setconfig('ui', 'forcemerge', '')
4171 ui.setconfig('ui', 'forcemerge', '')
4172
4172
4173 @command('outgoing|out',
4173 @command('outgoing|out',
4174 [('f', 'force', None, _('run even when the destination is unrelated')),
4174 [('f', 'force', None, _('run even when the destination is unrelated')),
4175 ('r', 'rev', [],
4175 ('r', 'rev', [],
4176 _('a changeset intended to be included in the destination'), _('REV')),
4176 _('a changeset intended to be included in the destination'), _('REV')),
4177 ('n', 'newest-first', None, _('show newest record first')),
4177 ('n', 'newest-first', None, _('show newest record first')),
4178 ('B', 'bookmarks', False, _('compare bookmarks')),
4178 ('B', 'bookmarks', False, _('compare bookmarks')),
4179 ('b', 'branch', [], _('a specific branch you would like to push'),
4179 ('b', 'branch', [], _('a specific branch you would like to push'),
4180 _('BRANCH')),
4180 _('BRANCH')),
4181 ] + logopts + remoteopts + subrepoopts,
4181 ] + logopts + remoteopts + subrepoopts,
4182 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4182 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4183 def outgoing(ui, repo, dest=None, **opts):
4183 def outgoing(ui, repo, dest=None, **opts):
4184 """show changesets not found in the destination
4184 """show changesets not found in the destination
4185
4185
4186 Show changesets not found in the specified destination repository
4186 Show changesets not found in the specified destination repository
4187 or the default push location. These are the changesets that would
4187 or the default push location. These are the changesets that would
4188 be pushed if a push was requested.
4188 be pushed if a push was requested.
4189
4189
4190 See pull for details of valid destination formats.
4190 See pull for details of valid destination formats.
4191
4191
4192 Returns 0 if there are outgoing changes, 1 otherwise.
4192 Returns 0 if there are outgoing changes, 1 otherwise.
4193 """
4193 """
4194
4194
4195 if opts.get('bookmarks'):
4195 if opts.get('bookmarks'):
4196 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4196 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4197 dest, branches = hg.parseurl(dest, opts.get('branch'))
4197 dest, branches = hg.parseurl(dest, opts.get('branch'))
4198 other = hg.peer(repo, opts, dest)
4198 other = hg.peer(repo, opts, dest)
4199 if 'bookmarks' not in other.listkeys('namespaces'):
4199 if 'bookmarks' not in other.listkeys('namespaces'):
4200 ui.warn(_("remote doesn't support bookmarks\n"))
4200 ui.warn(_("remote doesn't support bookmarks\n"))
4201 return 0
4201 return 0
4202 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4202 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4203 return bookmarks.diff(ui, other, repo)
4203 return bookmarks.diff(ui, other, repo)
4204
4204
4205 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4205 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4206 try:
4206 try:
4207 return hg.outgoing(ui, repo, dest, opts)
4207 return hg.outgoing(ui, repo, dest, opts)
4208 finally:
4208 finally:
4209 del repo._subtoppath
4209 del repo._subtoppath
4210
4210
4211 @command('parents',
4211 @command('parents',
4212 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4212 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4213 ] + templateopts,
4213 ] + templateopts,
4214 _('[-r REV] [FILE]'))
4214 _('[-r REV] [FILE]'))
4215 def parents(ui, repo, file_=None, **opts):
4215 def parents(ui, repo, file_=None, **opts):
4216 """show the parents of the working directory or revision
4216 """show the parents of the working directory or revision
4217
4217
4218 Print the working directory's parent revisions. If a revision is
4218 Print the working directory's parent revisions. If a revision is
4219 given via -r/--rev, the parent of that revision will be printed.
4219 given via -r/--rev, the parent of that revision will be printed.
4220 If a file argument is given, the revision in which the file was
4220 If a file argument is given, the revision in which the file was
4221 last changed (before the working directory revision or the
4221 last changed (before the working directory revision or the
4222 argument to --rev if given) is printed.
4222 argument to --rev if given) is printed.
4223
4223
4224 Returns 0 on success.
4224 Returns 0 on success.
4225 """
4225 """
4226
4226
4227 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4227 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4228
4228
4229 if file_:
4229 if file_:
4230 m = scmutil.match(ctx, (file_,), opts)
4230 m = scmutil.match(ctx, (file_,), opts)
4231 if m.anypats() or len(m.files()) != 1:
4231 if m.anypats() or len(m.files()) != 1:
4232 raise util.Abort(_('can only specify an explicit filename'))
4232 raise util.Abort(_('can only specify an explicit filename'))
4233 file_ = m.files()[0]
4233 file_ = m.files()[0]
4234 filenodes = []
4234 filenodes = []
4235 for cp in ctx.parents():
4235 for cp in ctx.parents():
4236 if not cp:
4236 if not cp:
4237 continue
4237 continue
4238 try:
4238 try:
4239 filenodes.append(cp.filenode(file_))
4239 filenodes.append(cp.filenode(file_))
4240 except error.LookupError:
4240 except error.LookupError:
4241 pass
4241 pass
4242 if not filenodes:
4242 if not filenodes:
4243 raise util.Abort(_("'%s' not found in manifest!") % file_)
4243 raise util.Abort(_("'%s' not found in manifest!") % file_)
4244 fl = repo.file(file_)
4244 fl = repo.file(file_)
4245 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4245 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4246 else:
4246 else:
4247 p = [cp.node() for cp in ctx.parents()]
4247 p = [cp.node() for cp in ctx.parents()]
4248
4248
4249 displayer = cmdutil.show_changeset(ui, repo, opts)
4249 displayer = cmdutil.show_changeset(ui, repo, opts)
4250 for n in p:
4250 for n in p:
4251 if n != nullid:
4251 if n != nullid:
4252 displayer.show(repo[n])
4252 displayer.show(repo[n])
4253 displayer.close()
4253 displayer.close()
4254
4254
4255 @command('paths', [], _('[NAME]'))
4255 @command('paths', [], _('[NAME]'))
4256 def paths(ui, repo, search=None):
4256 def paths(ui, repo, search=None):
4257 """show aliases for remote repositories
4257 """show aliases for remote repositories
4258
4258
4259 Show definition of symbolic path name NAME. If no name is given,
4259 Show definition of symbolic path name NAME. If no name is given,
4260 show definition of all available names.
4260 show definition of all available names.
4261
4261
4262 Option -q/--quiet suppresses all output when searching for NAME
4262 Option -q/--quiet suppresses all output when searching for NAME
4263 and shows only the path names when listing all definitions.
4263 and shows only the path names when listing all definitions.
4264
4264
4265 Path names are defined in the [paths] section of your
4265 Path names are defined in the [paths] section of your
4266 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4266 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4267 repository, ``.hg/hgrc`` is used, too.
4267 repository, ``.hg/hgrc`` is used, too.
4268
4268
4269 The path names ``default`` and ``default-push`` have a special
4269 The path names ``default`` and ``default-push`` have a special
4270 meaning. When performing a push or pull operation, they are used
4270 meaning. When performing a push or pull operation, they are used
4271 as fallbacks if no location is specified on the command-line.
4271 as fallbacks if no location is specified on the command-line.
4272 When ``default-push`` is set, it will be used for push and
4272 When ``default-push`` is set, it will be used for push and
4273 ``default`` will be used for pull; otherwise ``default`` is used
4273 ``default`` will be used for pull; otherwise ``default`` is used
4274 as the fallback for both. When cloning a repository, the clone
4274 as the fallback for both. When cloning a repository, the clone
4275 source is written as ``default`` in ``.hg/hgrc``. Note that
4275 source is written as ``default`` in ``.hg/hgrc``. Note that
4276 ``default`` and ``default-push`` apply to all inbound (e.g.
4276 ``default`` and ``default-push`` apply to all inbound (e.g.
4277 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4277 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4278 :hg:`bundle`) operations.
4278 :hg:`bundle`) operations.
4279
4279
4280 See :hg:`help urls` for more information.
4280 See :hg:`help urls` for more information.
4281
4281
4282 Returns 0 on success.
4282 Returns 0 on success.
4283 """
4283 """
4284 if search:
4284 if search:
4285 for name, path in ui.configitems("paths"):
4285 for name, path in ui.configitems("paths"):
4286 if name == search:
4286 if name == search:
4287 ui.status("%s\n" % util.hidepassword(path))
4287 ui.status("%s\n" % util.hidepassword(path))
4288 return
4288 return
4289 if not ui.quiet:
4289 if not ui.quiet:
4290 ui.warn(_("not found!\n"))
4290 ui.warn(_("not found!\n"))
4291 return 1
4291 return 1
4292 else:
4292 else:
4293 for name, path in ui.configitems("paths"):
4293 for name, path in ui.configitems("paths"):
4294 if ui.quiet:
4294 if ui.quiet:
4295 ui.write("%s\n" % name)
4295 ui.write("%s\n" % name)
4296 else:
4296 else:
4297 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4297 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4298
4298
4299 @command('^phase',
4299 @command('^phase',
4300 [('p', 'public', False, _('set changeset phase to public')),
4300 [('p', 'public', False, _('set changeset phase to public')),
4301 ('d', 'draft', False, _('set changeset phase to draft')),
4301 ('d', 'draft', False, _('set changeset phase to draft')),
4302 ('s', 'secret', False, _('set changeset phase to secret')),
4302 ('s', 'secret', False, _('set changeset phase to secret')),
4303 ('f', 'force', False, _('allow to move boundary backward')),
4303 ('f', 'force', False, _('allow to move boundary backward')),
4304 ('r', 'rev', [], _('target revision'), _('REV')),
4304 ('r', 'rev', [], _('target revision'), _('REV')),
4305 ],
4305 ],
4306 _('[-p|-d|-s] [-f] [-r] REV...'))
4306 _('[-p|-d|-s] [-f] [-r] REV...'))
4307 def phase(ui, repo, *revs, **opts):
4307 def phase(ui, repo, *revs, **opts):
4308 """set or show the current phase name
4308 """set or show the current phase name
4309
4309
4310 With no argument, show the phase name of specified revisions.
4310 With no argument, show the phase name of specified revisions.
4311
4311
4312 With one of -p/--public, -d/--draft or -s/--secret, change the
4312 With one of -p/--public, -d/--draft or -s/--secret, change the
4313 phase value of the specified revisions.
4313 phase value of the specified revisions.
4314
4314
4315 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4315 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4316 lower phase to an higher phase. Phases are ordered as follows::
4316 lower phase to an higher phase. Phases are ordered as follows::
4317
4317
4318 public < draft < secret
4318 public < draft < secret
4319
4319
4320 Return 0 on success, 1 if no phases were changed or some could not
4320 Return 0 on success, 1 if no phases were changed or some could not
4321 be changed.
4321 be changed.
4322 """
4322 """
4323 # search for a unique phase argument
4323 # search for a unique phase argument
4324 targetphase = None
4324 targetphase = None
4325 for idx, name in enumerate(phases.phasenames):
4325 for idx, name in enumerate(phases.phasenames):
4326 if opts[name]:
4326 if opts[name]:
4327 if targetphase is not None:
4327 if targetphase is not None:
4328 raise util.Abort(_('only one phase can be specified'))
4328 raise util.Abort(_('only one phase can be specified'))
4329 targetphase = idx
4329 targetphase = idx
4330
4330
4331 # look for specified revision
4331 # look for specified revision
4332 revs = list(revs)
4332 revs = list(revs)
4333 revs.extend(opts['rev'])
4333 revs.extend(opts['rev'])
4334 if not revs:
4334 if not revs:
4335 raise util.Abort(_('no revisions specified'))
4335 raise util.Abort(_('no revisions specified'))
4336
4336
4337 revs = scmutil.revrange(repo, revs)
4337 revs = scmutil.revrange(repo, revs)
4338
4338
4339 lock = None
4339 lock = None
4340 ret = 0
4340 ret = 0
4341 if targetphase is None:
4341 if targetphase is None:
4342 # display
4342 # display
4343 for r in revs:
4343 for r in revs:
4344 ctx = repo[r]
4344 ctx = repo[r]
4345 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4345 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4346 else:
4346 else:
4347 lock = repo.lock()
4347 lock = repo.lock()
4348 try:
4348 try:
4349 # set phase
4349 # set phase
4350 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4350 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4351 if not nodes:
4351 if not nodes:
4352 raise util.Abort(_('empty revision set'))
4352 raise util.Abort(_('empty revision set'))
4353 olddata = repo._phaserev[:]
4353 olddata = repo._phaserev[:]
4354 phases.advanceboundary(repo, targetphase, nodes)
4354 phases.advanceboundary(repo, targetphase, nodes)
4355 if opts['force']:
4355 if opts['force']:
4356 phases.retractboundary(repo, targetphase, nodes)
4356 phases.retractboundary(repo, targetphase, nodes)
4357 finally:
4357 finally:
4358 lock.release()
4358 lock.release()
4359 if olddata is not None:
4359 if olddata is not None:
4360 changes = 0
4360 changes = 0
4361 newdata = repo._phaserev
4361 newdata = repo._phaserev
4362 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4362 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4363 rejected = [n for n in nodes
4363 rejected = [n for n in nodes
4364 if newdata[repo[n].rev()] < targetphase]
4364 if newdata[repo[n].rev()] < targetphase]
4365 if rejected:
4365 if rejected:
4366 ui.warn(_('cannot move %i changesets to a more permissive '
4366 ui.warn(_('cannot move %i changesets to a more permissive '
4367 'phase, use --force\n') % len(rejected))
4367 'phase, use --force\n') % len(rejected))
4368 ret = 1
4368 ret = 1
4369 if changes:
4369 if changes:
4370 msg = _('phase changed for %i changesets\n') % changes
4370 msg = _('phase changed for %i changesets\n') % changes
4371 if ret:
4371 if ret:
4372 ui.status(msg)
4372 ui.status(msg)
4373 else:
4373 else:
4374 ui.note(msg)
4374 ui.note(msg)
4375 else:
4375 else:
4376 ui.warn(_('no phases changed\n'))
4376 ui.warn(_('no phases changed\n'))
4377 ret = 1
4377 ret = 1
4378 return ret
4378 return ret
4379
4379
4380 def postincoming(ui, repo, modheads, optupdate, checkout):
4380 def postincoming(ui, repo, modheads, optupdate, checkout):
4381 if modheads == 0:
4381 if modheads == 0:
4382 return
4382 return
4383 if optupdate:
4383 if optupdate:
4384 movemarkfrom = repo['.'].node()
4384 movemarkfrom = repo['.'].node()
4385 try:
4385 try:
4386 ret = hg.update(repo, checkout)
4386 ret = hg.update(repo, checkout)
4387 except util.Abort, inst:
4387 except util.Abort, inst:
4388 ui.warn(_("not updating: %s\n") % str(inst))
4388 ui.warn(_("not updating: %s\n") % str(inst))
4389 return 0
4389 return 0
4390 if not ret and not checkout:
4390 if not ret and not checkout:
4391 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4391 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4392 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4392 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4393 return ret
4393 return ret
4394 if modheads > 1:
4394 if modheads > 1:
4395 currentbranchheads = len(repo.branchheads())
4395 currentbranchheads = len(repo.branchheads())
4396 if currentbranchheads == modheads:
4396 if currentbranchheads == modheads:
4397 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4397 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4398 elif currentbranchheads > 1:
4398 elif currentbranchheads > 1:
4399 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4399 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4400 else:
4400 else:
4401 ui.status(_("(run 'hg heads' to see heads)\n"))
4401 ui.status(_("(run 'hg heads' to see heads)\n"))
4402 else:
4402 else:
4403 ui.status(_("(run 'hg update' to get a working copy)\n"))
4403 ui.status(_("(run 'hg update' to get a working copy)\n"))
4404
4404
4405 @command('^pull',
4405 @command('^pull',
4406 [('u', 'update', None,
4406 [('u', 'update', None,
4407 _('update to new branch head if changesets were pulled')),
4407 _('update to new branch head if changesets were pulled')),
4408 ('f', 'force', None, _('run even when remote repository is unrelated')),
4408 ('f', 'force', None, _('run even when remote repository is unrelated')),
4409 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4409 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4410 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4410 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4411 ('b', 'branch', [], _('a specific branch you would like to pull'),
4411 ('b', 'branch', [], _('a specific branch you would like to pull'),
4412 _('BRANCH')),
4412 _('BRANCH')),
4413 ] + remoteopts,
4413 ] + remoteopts,
4414 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4414 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4415 def pull(ui, repo, source="default", **opts):
4415 def pull(ui, repo, source="default", **opts):
4416 """pull changes from the specified source
4416 """pull changes from the specified source
4417
4417
4418 Pull changes from a remote repository to a local one.
4418 Pull changes from a remote repository to a local one.
4419
4419
4420 This finds all changes from the repository at the specified path
4420 This finds all changes from the repository at the specified path
4421 or URL and adds them to a local repository (the current one unless
4421 or URL and adds them to a local repository (the current one unless
4422 -R is specified). By default, this does not update the copy of the
4422 -R is specified). By default, this does not update the copy of the
4423 project in the working directory.
4423 project in the working directory.
4424
4424
4425 Use :hg:`incoming` if you want to see what would have been added
4425 Use :hg:`incoming` if you want to see what would have been added
4426 by a pull at the time you issued this command. If you then decide
4426 by a pull at the time you issued this command. If you then decide
4427 to add those changes to the repository, you should use :hg:`pull
4427 to add those changes to the repository, you should use :hg:`pull
4428 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4428 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4429
4429
4430 If SOURCE is omitted, the 'default' path will be used.
4430 If SOURCE is omitted, the 'default' path will be used.
4431 See :hg:`help urls` for more information.
4431 See :hg:`help urls` for more information.
4432
4432
4433 Returns 0 on success, 1 if an update had unresolved files.
4433 Returns 0 on success, 1 if an update had unresolved files.
4434 """
4434 """
4435 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4435 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4436 other = hg.peer(repo, opts, source)
4436 other = hg.peer(repo, opts, source)
4437 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4437 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4438 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4438 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4439
4439
4440 if opts.get('bookmark'):
4440 if opts.get('bookmark'):
4441 if not revs:
4441 if not revs:
4442 revs = []
4442 revs = []
4443 rb = other.listkeys('bookmarks')
4443 rb = other.listkeys('bookmarks')
4444 for b in opts['bookmark']:
4444 for b in opts['bookmark']:
4445 if b not in rb:
4445 if b not in rb:
4446 raise util.Abort(_('remote bookmark %s not found!') % b)
4446 raise util.Abort(_('remote bookmark %s not found!') % b)
4447 revs.append(rb[b])
4447 revs.append(rb[b])
4448
4448
4449 if revs:
4449 if revs:
4450 try:
4450 try:
4451 revs = [other.lookup(rev) for rev in revs]
4451 revs = [other.lookup(rev) for rev in revs]
4452 except error.CapabilityError:
4452 except error.CapabilityError:
4453 err = _("other repository doesn't support revision lookup, "
4453 err = _("other repository doesn't support revision lookup, "
4454 "so a rev cannot be specified.")
4454 "so a rev cannot be specified.")
4455 raise util.Abort(err)
4455 raise util.Abort(err)
4456
4456
4457 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4457 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4458 bookmarks.updatefromremote(ui, repo, other, source)
4458 bookmarks.updatefromremote(ui, repo, other, source)
4459 if checkout:
4459 if checkout:
4460 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4460 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4461 repo._subtoppath = source
4461 repo._subtoppath = source
4462 try:
4462 try:
4463 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4463 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4464
4464
4465 finally:
4465 finally:
4466 del repo._subtoppath
4466 del repo._subtoppath
4467
4467
4468 # update specified bookmarks
4468 # update specified bookmarks
4469 if opts.get('bookmark'):
4469 if opts.get('bookmark'):
4470 for b in opts['bookmark']:
4470 for b in opts['bookmark']:
4471 # explicit pull overrides local bookmark if any
4471 # explicit pull overrides local bookmark if any
4472 ui.status(_("importing bookmark %s\n") % b)
4472 ui.status(_("importing bookmark %s\n") % b)
4473 repo._bookmarks[b] = repo[rb[b]].node()
4473 repo._bookmarks[b] = repo[rb[b]].node()
4474 bookmarks.write(repo)
4474 bookmarks.write(repo)
4475
4475
4476 return ret
4476 return ret
4477
4477
4478 @command('^push',
4478 @command('^push',
4479 [('f', 'force', None, _('force push')),
4479 [('f', 'force', None, _('force push')),
4480 ('r', 'rev', [],
4480 ('r', 'rev', [],
4481 _('a changeset intended to be included in the destination'),
4481 _('a changeset intended to be included in the destination'),
4482 _('REV')),
4482 _('REV')),
4483 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4483 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4484 ('b', 'branch', [],
4484 ('b', 'branch', [],
4485 _('a specific branch you would like to push'), _('BRANCH')),
4485 _('a specific branch you would like to push'), _('BRANCH')),
4486 ('', 'new-branch', False, _('allow pushing a new branch')),
4486 ('', 'new-branch', False, _('allow pushing a new branch')),
4487 ] + remoteopts,
4487 ] + remoteopts,
4488 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4488 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4489 def push(ui, repo, dest=None, **opts):
4489 def push(ui, repo, dest=None, **opts):
4490 """push changes to the specified destination
4490 """push changes to the specified destination
4491
4491
4492 Push changesets from the local repository to the specified
4492 Push changesets from the local repository to the specified
4493 destination.
4493 destination.
4494
4494
4495 This operation is symmetrical to pull: it is identical to a pull
4495 This operation is symmetrical to pull: it is identical to a pull
4496 in the destination repository from the current one.
4496 in the destination repository from the current one.
4497
4497
4498 By default, push will not allow creation of new heads at the
4498 By default, push will not allow creation of new heads at the
4499 destination, since multiple heads would make it unclear which head
4499 destination, since multiple heads would make it unclear which head
4500 to use. In this situation, it is recommended to pull and merge
4500 to use. In this situation, it is recommended to pull and merge
4501 before pushing.
4501 before pushing.
4502
4502
4503 Use --new-branch if you want to allow push to create a new named
4503 Use --new-branch if you want to allow push to create a new named
4504 branch that is not present at the destination. This allows you to
4504 branch that is not present at the destination. This allows you to
4505 only create a new branch without forcing other changes.
4505 only create a new branch without forcing other changes.
4506
4506
4507 Use -f/--force to override the default behavior and push all
4507 Use -f/--force to override the default behavior and push all
4508 changesets on all branches.
4508 changesets on all branches.
4509
4509
4510 If -r/--rev is used, the specified revision and all its ancestors
4510 If -r/--rev is used, the specified revision and all its ancestors
4511 will be pushed to the remote repository.
4511 will be pushed to the remote repository.
4512
4512
4513 Please see :hg:`help urls` for important details about ``ssh://``
4513 Please see :hg:`help urls` for important details about ``ssh://``
4514 URLs. If DESTINATION is omitted, a default path will be used.
4514 URLs. If DESTINATION is omitted, a default path will be used.
4515
4515
4516 Returns 0 if push was successful, 1 if nothing to push.
4516 Returns 0 if push was successful, 1 if nothing to push.
4517 """
4517 """
4518
4518
4519 if opts.get('bookmark'):
4519 if opts.get('bookmark'):
4520 for b in opts['bookmark']:
4520 for b in opts['bookmark']:
4521 # translate -B options to -r so changesets get pushed
4521 # translate -B options to -r so changesets get pushed
4522 if b in repo._bookmarks:
4522 if b in repo._bookmarks:
4523 opts.setdefault('rev', []).append(b)
4523 opts.setdefault('rev', []).append(b)
4524 else:
4524 else:
4525 # if we try to push a deleted bookmark, translate it to null
4525 # if we try to push a deleted bookmark, translate it to null
4526 # this lets simultaneous -r, -b options continue working
4526 # this lets simultaneous -r, -b options continue working
4527 opts.setdefault('rev', []).append("null")
4527 opts.setdefault('rev', []).append("null")
4528
4528
4529 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4529 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4530 dest, branches = hg.parseurl(dest, opts.get('branch'))
4530 dest, branches = hg.parseurl(dest, opts.get('branch'))
4531 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4531 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4532 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4532 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4533 other = hg.peer(repo, opts, dest)
4533 other = hg.peer(repo, opts, dest)
4534 if revs:
4534 if revs:
4535 revs = [repo.lookup(rev) for rev in revs]
4535 revs = [repo.lookup(rev) for rev in revs]
4536
4536
4537 repo._subtoppath = dest
4537 repo._subtoppath = dest
4538 try:
4538 try:
4539 # push subrepos depth-first for coherent ordering
4539 # push subrepos depth-first for coherent ordering
4540 c = repo['']
4540 c = repo['']
4541 subs = c.substate # only repos that are committed
4541 subs = c.substate # only repos that are committed
4542 for s in sorted(subs):
4542 for s in sorted(subs):
4543 if c.sub(s).push(opts) == 0:
4543 if c.sub(s).push(opts) == 0:
4544 return False
4544 return False
4545 finally:
4545 finally:
4546 del repo._subtoppath
4546 del repo._subtoppath
4547 result = repo.push(other, opts.get('force'), revs=revs,
4547 result = repo.push(other, opts.get('force'), revs=revs,
4548 newbranch=opts.get('new_branch'))
4548 newbranch=opts.get('new_branch'))
4549
4549
4550 result = not result
4550 result = not result
4551
4551
4552 if opts.get('bookmark'):
4552 if opts.get('bookmark'):
4553 rb = other.listkeys('bookmarks')
4553 rb = other.listkeys('bookmarks')
4554 for b in opts['bookmark']:
4554 for b in opts['bookmark']:
4555 # explicit push overrides remote bookmark if any
4555 # explicit push overrides remote bookmark if any
4556 if b in repo._bookmarks:
4556 if b in repo._bookmarks:
4557 ui.status(_("exporting bookmark %s\n") % b)
4557 ui.status(_("exporting bookmark %s\n") % b)
4558 new = repo[b].hex()
4558 new = repo[b].hex()
4559 elif b in rb:
4559 elif b in rb:
4560 ui.status(_("deleting remote bookmark %s\n") % b)
4560 ui.status(_("deleting remote bookmark %s\n") % b)
4561 new = '' # delete
4561 new = '' # delete
4562 else:
4562 else:
4563 ui.warn(_('bookmark %s does not exist on the local '
4563 ui.warn(_('bookmark %s does not exist on the local '
4564 'or remote repository!\n') % b)
4564 'or remote repository!\n') % b)
4565 return 2
4565 return 2
4566 old = rb.get(b, '')
4566 old = rb.get(b, '')
4567 r = other.pushkey('bookmarks', b, old, new)
4567 r = other.pushkey('bookmarks', b, old, new)
4568 if not r:
4568 if not r:
4569 ui.warn(_('updating bookmark %s failed!\n') % b)
4569 ui.warn(_('updating bookmark %s failed!\n') % b)
4570 if not result:
4570 if not result:
4571 result = 2
4571 result = 2
4572
4572
4573 return result
4573 return result
4574
4574
4575 @command('recover', [])
4575 @command('recover', [])
4576 def recover(ui, repo):
4576 def recover(ui, repo):
4577 """roll back an interrupted transaction
4577 """roll back an interrupted transaction
4578
4578
4579 Recover from an interrupted commit or pull.
4579 Recover from an interrupted commit or pull.
4580
4580
4581 This command tries to fix the repository status after an
4581 This command tries to fix the repository status after an
4582 interrupted operation. It should only be necessary when Mercurial
4582 interrupted operation. It should only be necessary when Mercurial
4583 suggests it.
4583 suggests it.
4584
4584
4585 Returns 0 if successful, 1 if nothing to recover or verify fails.
4585 Returns 0 if successful, 1 if nothing to recover or verify fails.
4586 """
4586 """
4587 if repo.recover():
4587 if repo.recover():
4588 return hg.verify(repo)
4588 return hg.verify(repo)
4589 return 1
4589 return 1
4590
4590
4591 @command('^remove|rm',
4591 @command('^remove|rm',
4592 [('A', 'after', None, _('record delete for missing files')),
4592 [('A', 'after', None, _('record delete for missing files')),
4593 ('f', 'force', None,
4593 ('f', 'force', None,
4594 _('remove (and delete) file even if added or modified')),
4594 _('remove (and delete) file even if added or modified')),
4595 ] + walkopts,
4595 ] + walkopts,
4596 _('[OPTION]... FILE...'))
4596 _('[OPTION]... FILE...'))
4597 def remove(ui, repo, *pats, **opts):
4597 def remove(ui, repo, *pats, **opts):
4598 """remove the specified files on the next commit
4598 """remove the specified files on the next commit
4599
4599
4600 Schedule the indicated files for removal from the current branch.
4600 Schedule the indicated files for removal from the current branch.
4601
4601
4602 This command schedules the files to be removed at the next commit.
4602 This command schedules the files to be removed at the next commit.
4603 To undo a remove before that, see :hg:`revert`. To undo added
4603 To undo a remove before that, see :hg:`revert`. To undo added
4604 files, see :hg:`forget`.
4604 files, see :hg:`forget`.
4605
4605
4606 .. container:: verbose
4606 .. container:: verbose
4607
4607
4608 -A/--after can be used to remove only files that have already
4608 -A/--after can be used to remove only files that have already
4609 been deleted, -f/--force can be used to force deletion, and -Af
4609 been deleted, -f/--force can be used to force deletion, and -Af
4610 can be used to remove files from the next revision without
4610 can be used to remove files from the next revision without
4611 deleting them from the working directory.
4611 deleting them from the working directory.
4612
4612
4613 The following table details the behavior of remove for different
4613 The following table details the behavior of remove for different
4614 file states (columns) and option combinations (rows). The file
4614 file states (columns) and option combinations (rows). The file
4615 states are Added [A], Clean [C], Modified [M] and Missing [!]
4615 states are Added [A], Clean [C], Modified [M] and Missing [!]
4616 (as reported by :hg:`status`). The actions are Warn, Remove
4616 (as reported by :hg:`status`). The actions are Warn, Remove
4617 (from branch) and Delete (from disk):
4617 (from branch) and Delete (from disk):
4618
4618
4619 ======= == == == ==
4619 ======= == == == ==
4620 A C M !
4620 A C M !
4621 ======= == == == ==
4621 ======= == == == ==
4622 none W RD W R
4622 none W RD W R
4623 -f R RD RD R
4623 -f R RD RD R
4624 -A W W W R
4624 -A W W W R
4625 -Af R R R R
4625 -Af R R R R
4626 ======= == == == ==
4626 ======= == == == ==
4627
4627
4628 Note that remove never deletes files in Added [A] state from the
4628 Note that remove never deletes files in Added [A] state from the
4629 working directory, not even if option --force is specified.
4629 working directory, not even if option --force is specified.
4630
4630
4631 Returns 0 on success, 1 if any warnings encountered.
4631 Returns 0 on success, 1 if any warnings encountered.
4632 """
4632 """
4633
4633
4634 ret = 0
4634 ret = 0
4635 after, force = opts.get('after'), opts.get('force')
4635 after, force = opts.get('after'), opts.get('force')
4636 if not pats and not after:
4636 if not pats and not after:
4637 raise util.Abort(_('no files specified'))
4637 raise util.Abort(_('no files specified'))
4638
4638
4639 m = scmutil.match(repo[None], pats, opts)
4639 m = scmutil.match(repo[None], pats, opts)
4640 s = repo.status(match=m, clean=True)
4640 s = repo.status(match=m, clean=True)
4641 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4641 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4642
4642
4643 for f in m.files():
4643 for f in m.files():
4644 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4644 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4645 if os.path.exists(m.rel(f)):
4645 if os.path.exists(m.rel(f)):
4646 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4646 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4647 ret = 1
4647 ret = 1
4648
4648
4649 if force:
4649 if force:
4650 list = modified + deleted + clean + added
4650 list = modified + deleted + clean + added
4651 elif after:
4651 elif after:
4652 list = deleted
4652 list = deleted
4653 for f in modified + added + clean:
4653 for f in modified + added + clean:
4654 ui.warn(_('not removing %s: file still exists (use -f'
4654 ui.warn(_('not removing %s: file still exists (use -f'
4655 ' to force removal)\n') % m.rel(f))
4655 ' to force removal)\n') % m.rel(f))
4656 ret = 1
4656 ret = 1
4657 else:
4657 else:
4658 list = deleted + clean
4658 list = deleted + clean
4659 for f in modified:
4659 for f in modified:
4660 ui.warn(_('not removing %s: file is modified (use -f'
4660 ui.warn(_('not removing %s: file is modified (use -f'
4661 ' to force removal)\n') % m.rel(f))
4661 ' to force removal)\n') % m.rel(f))
4662 ret = 1
4662 ret = 1
4663 for f in added:
4663 for f in added:
4664 ui.warn(_('not removing %s: file has been marked for add'
4664 ui.warn(_('not removing %s: file has been marked for add'
4665 ' (use forget to undo)\n') % m.rel(f))
4665 ' (use forget to undo)\n') % m.rel(f))
4666 ret = 1
4666 ret = 1
4667
4667
4668 for f in sorted(list):
4668 for f in sorted(list):
4669 if ui.verbose or not m.exact(f):
4669 if ui.verbose or not m.exact(f):
4670 ui.status(_('removing %s\n') % m.rel(f))
4670 ui.status(_('removing %s\n') % m.rel(f))
4671
4671
4672 wlock = repo.wlock()
4672 wlock = repo.wlock()
4673 try:
4673 try:
4674 if not after:
4674 if not after:
4675 for f in list:
4675 for f in list:
4676 if f in added:
4676 if f in added:
4677 continue # we never unlink added files on remove
4677 continue # we never unlink added files on remove
4678 try:
4678 try:
4679 util.unlinkpath(repo.wjoin(f))
4679 util.unlinkpath(repo.wjoin(f))
4680 except OSError, inst:
4680 except OSError, inst:
4681 if inst.errno != errno.ENOENT:
4681 if inst.errno != errno.ENOENT:
4682 raise
4682 raise
4683 repo[None].forget(list)
4683 repo[None].forget(list)
4684 finally:
4684 finally:
4685 wlock.release()
4685 wlock.release()
4686
4686
4687 return ret
4687 return ret
4688
4688
4689 @command('rename|move|mv',
4689 @command('rename|move|mv',
4690 [('A', 'after', None, _('record a rename that has already occurred')),
4690 [('A', 'after', None, _('record a rename that has already occurred')),
4691 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4691 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4692 ] + walkopts + dryrunopts,
4692 ] + walkopts + dryrunopts,
4693 _('[OPTION]... SOURCE... DEST'))
4693 _('[OPTION]... SOURCE... DEST'))
4694 def rename(ui, repo, *pats, **opts):
4694 def rename(ui, repo, *pats, **opts):
4695 """rename files; equivalent of copy + remove
4695 """rename files; equivalent of copy + remove
4696
4696
4697 Mark dest as copies of sources; mark sources for deletion. If dest
4697 Mark dest as copies of sources; mark sources for deletion. If dest
4698 is a directory, copies are put in that directory. If dest is a
4698 is a directory, copies are put in that directory. If dest is a
4699 file, there can only be one source.
4699 file, there can only be one source.
4700
4700
4701 By default, this command copies the contents of files as they
4701 By default, this command copies the contents of files as they
4702 exist in the working directory. If invoked with -A/--after, the
4702 exist in the working directory. If invoked with -A/--after, the
4703 operation is recorded, but no copying is performed.
4703 operation is recorded, but no copying is performed.
4704
4704
4705 This command takes effect at the next commit. To undo a rename
4705 This command takes effect at the next commit. To undo a rename
4706 before that, see :hg:`revert`.
4706 before that, see :hg:`revert`.
4707
4707
4708 Returns 0 on success, 1 if errors are encountered.
4708 Returns 0 on success, 1 if errors are encountered.
4709 """
4709 """
4710 wlock = repo.wlock(False)
4710 wlock = repo.wlock(False)
4711 try:
4711 try:
4712 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4712 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4713 finally:
4713 finally:
4714 wlock.release()
4714 wlock.release()
4715
4715
4716 @command('resolve',
4716 @command('resolve',
4717 [('a', 'all', None, _('select all unresolved files')),
4717 [('a', 'all', None, _('select all unresolved files')),
4718 ('l', 'list', None, _('list state of files needing merge')),
4718 ('l', 'list', None, _('list state of files needing merge')),
4719 ('m', 'mark', None, _('mark files as resolved')),
4719 ('m', 'mark', None, _('mark files as resolved')),
4720 ('u', 'unmark', None, _('mark files as unresolved')),
4720 ('u', 'unmark', None, _('mark files as unresolved')),
4721 ('n', 'no-status', None, _('hide status prefix'))]
4721 ('n', 'no-status', None, _('hide status prefix'))]
4722 + mergetoolopts + walkopts,
4722 + mergetoolopts + walkopts,
4723 _('[OPTION]... [FILE]...'))
4723 _('[OPTION]... [FILE]...'))
4724 def resolve(ui, repo, *pats, **opts):
4724 def resolve(ui, repo, *pats, **opts):
4725 """redo merges or set/view the merge status of files
4725 """redo merges or set/view the merge status of files
4726
4726
4727 Merges with unresolved conflicts are often the result of
4727 Merges with unresolved conflicts are often the result of
4728 non-interactive merging using the ``internal:merge`` configuration
4728 non-interactive merging using the ``internal:merge`` configuration
4729 setting, or a command-line merge tool like ``diff3``. The resolve
4729 setting, or a command-line merge tool like ``diff3``. The resolve
4730 command is used to manage the files involved in a merge, after
4730 command is used to manage the files involved in a merge, after
4731 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4731 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4732 working directory must have two parents). See :hg:`help
4732 working directory must have two parents). See :hg:`help
4733 merge-tools` for information on configuring merge tools.
4733 merge-tools` for information on configuring merge tools.
4734
4734
4735 The resolve command can be used in the following ways:
4735 The resolve command can be used in the following ways:
4736
4736
4737 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4737 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4738 files, discarding any previous merge attempts. Re-merging is not
4738 files, discarding any previous merge attempts. Re-merging is not
4739 performed for files already marked as resolved. Use ``--all/-a``
4739 performed for files already marked as resolved. Use ``--all/-a``
4740 to select all unresolved files. ``--tool`` can be used to specify
4740 to select all unresolved files. ``--tool`` can be used to specify
4741 the merge tool used for the given files. It overrides the HGMERGE
4741 the merge tool used for the given files. It overrides the HGMERGE
4742 environment variable and your configuration files. Previous file
4742 environment variable and your configuration files. Previous file
4743 contents are saved with a ``.orig`` suffix.
4743 contents are saved with a ``.orig`` suffix.
4744
4744
4745 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4745 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4746 (e.g. after having manually fixed-up the files). The default is
4746 (e.g. after having manually fixed-up the files). The default is
4747 to mark all unresolved files.
4747 to mark all unresolved files.
4748
4748
4749 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4749 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4750 default is to mark all resolved files.
4750 default is to mark all resolved files.
4751
4751
4752 - :hg:`resolve -l`: list files which had or still have conflicts.
4752 - :hg:`resolve -l`: list files which had or still have conflicts.
4753 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4753 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4754
4754
4755 Note that Mercurial will not let you commit files with unresolved
4755 Note that Mercurial will not let you commit files with unresolved
4756 merge conflicts. You must use :hg:`resolve -m ...` before you can
4756 merge conflicts. You must use :hg:`resolve -m ...` before you can
4757 commit after a conflicting merge.
4757 commit after a conflicting merge.
4758
4758
4759 Returns 0 on success, 1 if any files fail a resolve attempt.
4759 Returns 0 on success, 1 if any files fail a resolve attempt.
4760 """
4760 """
4761
4761
4762 all, mark, unmark, show, nostatus = \
4762 all, mark, unmark, show, nostatus = \
4763 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4763 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4764
4764
4765 if (show and (mark or unmark)) or (mark and unmark):
4765 if (show and (mark or unmark)) or (mark and unmark):
4766 raise util.Abort(_("too many options specified"))
4766 raise util.Abort(_("too many options specified"))
4767 if pats and all:
4767 if pats and all:
4768 raise util.Abort(_("can't specify --all and patterns"))
4768 raise util.Abort(_("can't specify --all and patterns"))
4769 if not (all or pats or show or mark or unmark):
4769 if not (all or pats or show or mark or unmark):
4770 raise util.Abort(_('no files or directories specified; '
4770 raise util.Abort(_('no files or directories specified; '
4771 'use --all to remerge all files'))
4771 'use --all to remerge all files'))
4772
4772
4773 ms = mergemod.mergestate(repo)
4773 ms = mergemod.mergestate(repo)
4774 m = scmutil.match(repo[None], pats, opts)
4774 m = scmutil.match(repo[None], pats, opts)
4775 ret = 0
4775 ret = 0
4776
4776
4777 for f in ms:
4777 for f in ms:
4778 if m(f):
4778 if m(f):
4779 if show:
4779 if show:
4780 if nostatus:
4780 if nostatus:
4781 ui.write("%s\n" % f)
4781 ui.write("%s\n" % f)
4782 else:
4782 else:
4783 ui.write("%s %s\n" % (ms[f].upper(), f),
4783 ui.write("%s %s\n" % (ms[f].upper(), f),
4784 label='resolve.' +
4784 label='resolve.' +
4785 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4785 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4786 elif mark:
4786 elif mark:
4787 ms.mark(f, "r")
4787 ms.mark(f, "r")
4788 elif unmark:
4788 elif unmark:
4789 ms.mark(f, "u")
4789 ms.mark(f, "u")
4790 else:
4790 else:
4791 wctx = repo[None]
4791 wctx = repo[None]
4792 mctx = wctx.parents()[-1]
4792 mctx = wctx.parents()[-1]
4793
4793
4794 # backup pre-resolve (merge uses .orig for its own purposes)
4794 # backup pre-resolve (merge uses .orig for its own purposes)
4795 a = repo.wjoin(f)
4795 a = repo.wjoin(f)
4796 util.copyfile(a, a + ".resolve")
4796 util.copyfile(a, a + ".resolve")
4797
4797
4798 try:
4798 try:
4799 # resolve file
4799 # resolve file
4800 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4800 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4801 if ms.resolve(f, wctx, mctx):
4801 if ms.resolve(f, wctx, mctx):
4802 ret = 1
4802 ret = 1
4803 finally:
4803 finally:
4804 ui.setconfig('ui', 'forcemerge', '')
4804 ui.setconfig('ui', 'forcemerge', '')
4805
4805
4806 # replace filemerge's .orig file with our resolve file
4806 # replace filemerge's .orig file with our resolve file
4807 util.rename(a + ".resolve", a + ".orig")
4807 util.rename(a + ".resolve", a + ".orig")
4808
4808
4809 ms.commit()
4809 ms.commit()
4810 return ret
4810 return ret
4811
4811
4812 @command('revert',
4812 @command('revert',
4813 [('a', 'all', None, _('revert all changes when no arguments given')),
4813 [('a', 'all', None, _('revert all changes when no arguments given')),
4814 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4814 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4815 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4815 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4816 ('C', 'no-backup', None, _('do not save backup copies of files')),
4816 ('C', 'no-backup', None, _('do not save backup copies of files')),
4817 ] + walkopts + dryrunopts,
4817 ] + walkopts + dryrunopts,
4818 _('[OPTION]... [-r REV] [NAME]...'))
4818 _('[OPTION]... [-r REV] [NAME]...'))
4819 def revert(ui, repo, *pats, **opts):
4819 def revert(ui, repo, *pats, **opts):
4820 """restore files to their checkout state
4820 """restore files to their checkout state
4821
4821
4822 .. note::
4822 .. note::
4823 To check out earlier revisions, you should use :hg:`update REV`.
4823 To check out earlier revisions, you should use :hg:`update REV`.
4824 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4824 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4825
4825
4826 With no revision specified, revert the specified files or directories
4826 With no revision specified, revert the specified files or directories
4827 to the contents they had in the parent of the working directory.
4827 to the contents they had in the parent of the working directory.
4828 This restores the contents of files to an unmodified
4828 This restores the contents of files to an unmodified
4829 state and unschedules adds, removes, copies, and renames. If the
4829 state and unschedules adds, removes, copies, and renames. If the
4830 working directory has two parents, you must explicitly specify a
4830 working directory has two parents, you must explicitly specify a
4831 revision.
4831 revision.
4832
4832
4833 Using the -r/--rev or -d/--date options, revert the given files or
4833 Using the -r/--rev or -d/--date options, revert the given files or
4834 directories to their states as of a specific revision. Because
4834 directories to their states as of a specific revision. Because
4835 revert does not change the working directory parents, this will
4835 revert does not change the working directory parents, this will
4836 cause these files to appear modified. This can be helpful to "back
4836 cause these files to appear modified. This can be helpful to "back
4837 out" some or all of an earlier change. See :hg:`backout` for a
4837 out" some or all of an earlier change. See :hg:`backout` for a
4838 related method.
4838 related method.
4839
4839
4840 Modified files are saved with a .orig suffix before reverting.
4840 Modified files are saved with a .orig suffix before reverting.
4841 To disable these backups, use --no-backup.
4841 To disable these backups, use --no-backup.
4842
4842
4843 See :hg:`help dates` for a list of formats valid for -d/--date.
4843 See :hg:`help dates` for a list of formats valid for -d/--date.
4844
4844
4845 Returns 0 on success.
4845 Returns 0 on success.
4846 """
4846 """
4847
4847
4848 if opts.get("date"):
4848 if opts.get("date"):
4849 if opts.get("rev"):
4849 if opts.get("rev"):
4850 raise util.Abort(_("you can't specify a revision and a date"))
4850 raise util.Abort(_("you can't specify a revision and a date"))
4851 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4851 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4852
4852
4853 parent, p2 = repo.dirstate.parents()
4853 parent, p2 = repo.dirstate.parents()
4854 if not opts.get('rev') and p2 != nullid:
4854 if not opts.get('rev') and p2 != nullid:
4855 # revert after merge is a trap for new users (issue2915)
4855 # revert after merge is a trap for new users (issue2915)
4856 raise util.Abort(_('uncommitted merge with no revision specified'),
4856 raise util.Abort(_('uncommitted merge with no revision specified'),
4857 hint=_('use "hg update" or see "hg help revert"'))
4857 hint=_('use "hg update" or see "hg help revert"'))
4858
4858
4859 ctx = scmutil.revsingle(repo, opts.get('rev'))
4859 ctx = scmutil.revsingle(repo, opts.get('rev'))
4860
4860
4861 if not pats and not opts.get('all'):
4861 if not pats and not opts.get('all'):
4862 msg = _("no files or directories specified")
4862 msg = _("no files or directories specified")
4863 if p2 != nullid:
4863 if p2 != nullid:
4864 hint = _("uncommitted merge, use --all to discard all changes,"
4864 hint = _("uncommitted merge, use --all to discard all changes,"
4865 " or 'hg update -C .' to abort the merge")
4865 " or 'hg update -C .' to abort the merge")
4866 raise util.Abort(msg, hint=hint)
4866 raise util.Abort(msg, hint=hint)
4867 dirty = util.any(repo.status())
4867 dirty = util.any(repo.status())
4868 node = ctx.node()
4868 node = ctx.node()
4869 if node != parent:
4869 if node != parent:
4870 if dirty:
4870 if dirty:
4871 hint = _("uncommitted changes, use --all to discard all"
4871 hint = _("uncommitted changes, use --all to discard all"
4872 " changes, or 'hg update %s' to update") % ctx.rev()
4872 " changes, or 'hg update %s' to update") % ctx.rev()
4873 else:
4873 else:
4874 hint = _("use --all to revert all files,"
4874 hint = _("use --all to revert all files,"
4875 " or 'hg update %s' to update") % ctx.rev()
4875 " or 'hg update %s' to update") % ctx.rev()
4876 elif dirty:
4876 elif dirty:
4877 hint = _("uncommitted changes, use --all to discard all changes")
4877 hint = _("uncommitted changes, use --all to discard all changes")
4878 else:
4878 else:
4879 hint = _("use --all to revert all files")
4879 hint = _("use --all to revert all files")
4880 raise util.Abort(msg, hint=hint)
4880 raise util.Abort(msg, hint=hint)
4881
4881
4882 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4882 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4883
4883
4884 @command('rollback', dryrunopts +
4884 @command('rollback', dryrunopts +
4885 [('f', 'force', False, _('ignore safety measures'))])
4885 [('f', 'force', False, _('ignore safety measures'))])
4886 def rollback(ui, repo, **opts):
4886 def rollback(ui, repo, **opts):
4887 """roll back the last transaction (dangerous)
4887 """roll back the last transaction (dangerous)
4888
4888
4889 This command should be used with care. There is only one level of
4889 This command should be used with care. There is only one level of
4890 rollback, and there is no way to undo a rollback. It will also
4890 rollback, and there is no way to undo a rollback. It will also
4891 restore the dirstate at the time of the last transaction, losing
4891 restore the dirstate at the time of the last transaction, losing
4892 any dirstate changes since that time. This command does not alter
4892 any dirstate changes since that time. This command does not alter
4893 the working directory.
4893 the working directory.
4894
4894
4895 Transactions are used to encapsulate the effects of all commands
4895 Transactions are used to encapsulate the effects of all commands
4896 that create new changesets or propagate existing changesets into a
4896 that create new changesets or propagate existing changesets into a
4897 repository. For example, the following commands are transactional,
4897 repository. For example, the following commands are transactional,
4898 and their effects can be rolled back:
4898 and their effects can be rolled back:
4899
4899
4900 - commit
4900 - commit
4901 - import
4901 - import
4902 - pull
4902 - pull
4903 - push (with this repository as the destination)
4903 - push (with this repository as the destination)
4904 - unbundle
4904 - unbundle
4905
4905
4906 To avoid permanent data loss, rollback will refuse to rollback a
4906 To avoid permanent data loss, rollback will refuse to rollback a
4907 commit transaction if it isn't checked out. Use --force to
4907 commit transaction if it isn't checked out. Use --force to
4908 override this protection.
4908 override this protection.
4909
4909
4910 This command is not intended for use on public repositories. Once
4910 This command is not intended for use on public repositories. Once
4911 changes are visible for pull by other users, rolling a transaction
4911 changes are visible for pull by other users, rolling a transaction
4912 back locally is ineffective (someone else may already have pulled
4912 back locally is ineffective (someone else may already have pulled
4913 the changes). Furthermore, a race is possible with readers of the
4913 the changes). Furthermore, a race is possible with readers of the
4914 repository; for example an in-progress pull from the repository
4914 repository; for example an in-progress pull from the repository
4915 may fail if a rollback is performed.
4915 may fail if a rollback is performed.
4916
4916
4917 Returns 0 on success, 1 if no rollback data is available.
4917 Returns 0 on success, 1 if no rollback data is available.
4918 """
4918 """
4919 return repo.rollback(dryrun=opts.get('dry_run'),
4919 return repo.rollback(dryrun=opts.get('dry_run'),
4920 force=opts.get('force'))
4920 force=opts.get('force'))
4921
4921
4922 @command('root', [])
4922 @command('root', [])
4923 def root(ui, repo):
4923 def root(ui, repo):
4924 """print the root (top) of the current working directory
4924 """print the root (top) of the current working directory
4925
4925
4926 Print the root directory of the current repository.
4926 Print the root directory of the current repository.
4927
4927
4928 Returns 0 on success.
4928 Returns 0 on success.
4929 """
4929 """
4930 ui.write(repo.root + "\n")
4930 ui.write(repo.root + "\n")
4931
4931
4932 @command('^serve',
4932 @command('^serve',
4933 [('A', 'accesslog', '', _('name of access log file to write to'),
4933 [('A', 'accesslog', '', _('name of access log file to write to'),
4934 _('FILE')),
4934 _('FILE')),
4935 ('d', 'daemon', None, _('run server in background')),
4935 ('d', 'daemon', None, _('run server in background')),
4936 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4936 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4937 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4937 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4938 # use string type, then we can check if something was passed
4938 # use string type, then we can check if something was passed
4939 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4939 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4940 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4940 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4941 _('ADDR')),
4941 _('ADDR')),
4942 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4942 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4943 _('PREFIX')),
4943 _('PREFIX')),
4944 ('n', 'name', '',
4944 ('n', 'name', '',
4945 _('name to show in web pages (default: working directory)'), _('NAME')),
4945 _('name to show in web pages (default: working directory)'), _('NAME')),
4946 ('', 'web-conf', '',
4946 ('', 'web-conf', '',
4947 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4947 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4948 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4948 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4949 _('FILE')),
4949 _('FILE')),
4950 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4950 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4951 ('', 'stdio', None, _('for remote clients')),
4951 ('', 'stdio', None, _('for remote clients')),
4952 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4952 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4953 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4953 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4954 ('', 'style', '', _('template style to use'), _('STYLE')),
4954 ('', 'style', '', _('template style to use'), _('STYLE')),
4955 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4955 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4956 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4956 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4957 _('[OPTION]...'))
4957 _('[OPTION]...'))
4958 def serve(ui, repo, **opts):
4958 def serve(ui, repo, **opts):
4959 """start stand-alone webserver
4959 """start stand-alone webserver
4960
4960
4961 Start a local HTTP repository browser and pull server. You can use
4961 Start a local HTTP repository browser and pull server. You can use
4962 this for ad-hoc sharing and browsing of repositories. It is
4962 this for ad-hoc sharing and browsing of repositories. It is
4963 recommended to use a real web server to serve a repository for
4963 recommended to use a real web server to serve a repository for
4964 longer periods of time.
4964 longer periods of time.
4965
4965
4966 Please note that the server does not implement access control.
4966 Please note that the server does not implement access control.
4967 This means that, by default, anybody can read from the server and
4967 This means that, by default, anybody can read from the server and
4968 nobody can write to it by default. Set the ``web.allow_push``
4968 nobody can write to it by default. Set the ``web.allow_push``
4969 option to ``*`` to allow everybody to push to the server. You
4969 option to ``*`` to allow everybody to push to the server. You
4970 should use a real web server if you need to authenticate users.
4970 should use a real web server if you need to authenticate users.
4971
4971
4972 By default, the server logs accesses to stdout and errors to
4972 By default, the server logs accesses to stdout and errors to
4973 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4973 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4974 files.
4974 files.
4975
4975
4976 To have the server choose a free port number to listen on, specify
4976 To have the server choose a free port number to listen on, specify
4977 a port number of 0; in this case, the server will print the port
4977 a port number of 0; in this case, the server will print the port
4978 number it uses.
4978 number it uses.
4979
4979
4980 Returns 0 on success.
4980 Returns 0 on success.
4981 """
4981 """
4982
4982
4983 if opts["stdio"] and opts["cmdserver"]:
4983 if opts["stdio"] and opts["cmdserver"]:
4984 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4984 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4985
4985
4986 def checkrepo():
4986 def checkrepo():
4987 if repo is None:
4987 if repo is None:
4988 raise error.RepoError(_("There is no Mercurial repository here"
4988 raise error.RepoError(_("There is no Mercurial repository here"
4989 " (.hg not found)"))
4989 " (.hg not found)"))
4990
4990
4991 if opts["stdio"]:
4991 if opts["stdio"]:
4992 checkrepo()
4992 checkrepo()
4993 s = sshserver.sshserver(ui, repo)
4993 s = sshserver.sshserver(ui, repo)
4994 s.serve_forever()
4994 s.serve_forever()
4995
4995
4996 if opts["cmdserver"]:
4996 if opts["cmdserver"]:
4997 checkrepo()
4997 checkrepo()
4998 s = commandserver.server(ui, repo, opts["cmdserver"])
4998 s = commandserver.server(ui, repo, opts["cmdserver"])
4999 return s.serve()
4999 return s.serve()
5000
5000
5001 # this way we can check if something was given in the command-line
5001 # this way we can check if something was given in the command-line
5002 if opts.get('port'):
5002 if opts.get('port'):
5003 opts['port'] = util.getport(opts.get('port'))
5003 opts['port'] = util.getport(opts.get('port'))
5004
5004
5005 baseui = repo and repo.baseui or ui
5005 baseui = repo and repo.baseui or ui
5006 optlist = ("name templates style address port prefix ipv6"
5006 optlist = ("name templates style address port prefix ipv6"
5007 " accesslog errorlog certificate encoding")
5007 " accesslog errorlog certificate encoding")
5008 for o in optlist.split():
5008 for o in optlist.split():
5009 val = opts.get(o, '')
5009 val = opts.get(o, '')
5010 if val in (None, ''): # should check against default options instead
5010 if val in (None, ''): # should check against default options instead
5011 continue
5011 continue
5012 baseui.setconfig("web", o, val)
5012 baseui.setconfig("web", o, val)
5013 if repo and repo.ui != baseui:
5013 if repo and repo.ui != baseui:
5014 repo.ui.setconfig("web", o, val)
5014 repo.ui.setconfig("web", o, val)
5015
5015
5016 o = opts.get('web_conf') or opts.get('webdir_conf')
5016 o = opts.get('web_conf') or opts.get('webdir_conf')
5017 if not o:
5017 if not o:
5018 if not repo:
5018 if not repo:
5019 raise error.RepoError(_("There is no Mercurial repository"
5019 raise error.RepoError(_("There is no Mercurial repository"
5020 " here (.hg not found)"))
5020 " here (.hg not found)"))
5021 o = repo.root
5021 o = repo.root
5022
5022
5023 app = hgweb.hgweb(o, baseui=ui)
5023 app = hgweb.hgweb(o, baseui=ui)
5024
5024
5025 class service(object):
5025 class service(object):
5026 def init(self):
5026 def init(self):
5027 util.setsignalhandler()
5027 util.setsignalhandler()
5028 self.httpd = hgweb.server.create_server(ui, app)
5028 self.httpd = hgweb.server.create_server(ui, app)
5029
5029
5030 if opts['port'] and not ui.verbose:
5030 if opts['port'] and not ui.verbose:
5031 return
5031 return
5032
5032
5033 if self.httpd.prefix:
5033 if self.httpd.prefix:
5034 prefix = self.httpd.prefix.strip('/') + '/'
5034 prefix = self.httpd.prefix.strip('/') + '/'
5035 else:
5035 else:
5036 prefix = ''
5036 prefix = ''
5037
5037
5038 port = ':%d' % self.httpd.port
5038 port = ':%d' % self.httpd.port
5039 if port == ':80':
5039 if port == ':80':
5040 port = ''
5040 port = ''
5041
5041
5042 bindaddr = self.httpd.addr
5042 bindaddr = self.httpd.addr
5043 if bindaddr == '0.0.0.0':
5043 if bindaddr == '0.0.0.0':
5044 bindaddr = '*'
5044 bindaddr = '*'
5045 elif ':' in bindaddr: # IPv6
5045 elif ':' in bindaddr: # IPv6
5046 bindaddr = '[%s]' % bindaddr
5046 bindaddr = '[%s]' % bindaddr
5047
5047
5048 fqaddr = self.httpd.fqaddr
5048 fqaddr = self.httpd.fqaddr
5049 if ':' in fqaddr:
5049 if ':' in fqaddr:
5050 fqaddr = '[%s]' % fqaddr
5050 fqaddr = '[%s]' % fqaddr
5051 if opts['port']:
5051 if opts['port']:
5052 write = ui.status
5052 write = ui.status
5053 else:
5053 else:
5054 write = ui.write
5054 write = ui.write
5055 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5055 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5056 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5056 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5057
5057
5058 def run(self):
5058 def run(self):
5059 self.httpd.serve_forever()
5059 self.httpd.serve_forever()
5060
5060
5061 service = service()
5061 service = service()
5062
5062
5063 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5063 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5064
5064
5065 @command('showconfig|debugconfig',
5065 @command('showconfig|debugconfig',
5066 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5066 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5067 _('[-u] [NAME]...'))
5067 _('[-u] [NAME]...'))
5068 def showconfig(ui, repo, *values, **opts):
5068 def showconfig(ui, repo, *values, **opts):
5069 """show combined config settings from all hgrc files
5069 """show combined config settings from all hgrc files
5070
5070
5071 With no arguments, print names and values of all config items.
5071 With no arguments, print names and values of all config items.
5072
5072
5073 With one argument of the form section.name, print just the value
5073 With one argument of the form section.name, print just the value
5074 of that config item.
5074 of that config item.
5075
5075
5076 With multiple arguments, print names and values of all config
5076 With multiple arguments, print names and values of all config
5077 items with matching section names.
5077 items with matching section names.
5078
5078
5079 With --debug, the source (filename and line number) is printed
5079 With --debug, the source (filename and line number) is printed
5080 for each config item.
5080 for each config item.
5081
5081
5082 Returns 0 on success.
5082 Returns 0 on success.
5083 """
5083 """
5084
5084
5085 for f in scmutil.rcpath():
5085 for f in scmutil.rcpath():
5086 ui.debug('read config from: %s\n' % f)
5086 ui.debug('read config from: %s\n' % f)
5087 untrusted = bool(opts.get('untrusted'))
5087 untrusted = bool(opts.get('untrusted'))
5088 if values:
5088 if values:
5089 sections = [v for v in values if '.' not in v]
5089 sections = [v for v in values if '.' not in v]
5090 items = [v for v in values if '.' in v]
5090 items = [v for v in values if '.' in v]
5091 if len(items) > 1 or items and sections:
5091 if len(items) > 1 or items and sections:
5092 raise util.Abort(_('only one config item permitted'))
5092 raise util.Abort(_('only one config item permitted'))
5093 for section, name, value in ui.walkconfig(untrusted=untrusted):
5093 for section, name, value in ui.walkconfig(untrusted=untrusted):
5094 value = str(value).replace('\n', '\\n')
5094 value = str(value).replace('\n', '\\n')
5095 sectname = section + '.' + name
5095 sectname = section + '.' + name
5096 if values:
5096 if values:
5097 for v in values:
5097 for v in values:
5098 if v == section:
5098 if v == section:
5099 ui.debug('%s: ' %
5099 ui.debug('%s: ' %
5100 ui.configsource(section, name, untrusted))
5100 ui.configsource(section, name, untrusted))
5101 ui.write('%s=%s\n' % (sectname, value))
5101 ui.write('%s=%s\n' % (sectname, value))
5102 elif v == sectname:
5102 elif v == sectname:
5103 ui.debug('%s: ' %
5103 ui.debug('%s: ' %
5104 ui.configsource(section, name, untrusted))
5104 ui.configsource(section, name, untrusted))
5105 ui.write(value, '\n')
5105 ui.write(value, '\n')
5106 else:
5106 else:
5107 ui.debug('%s: ' %
5107 ui.debug('%s: ' %
5108 ui.configsource(section, name, untrusted))
5108 ui.configsource(section, name, untrusted))
5109 ui.write('%s=%s\n' % (sectname, value))
5109 ui.write('%s=%s\n' % (sectname, value))
5110
5110
5111 @command('^status|st',
5111 @command('^status|st',
5112 [('A', 'all', None, _('show status of all files')),
5112 [('A', 'all', None, _('show status of all files')),
5113 ('m', 'modified', None, _('show only modified files')),
5113 ('m', 'modified', None, _('show only modified files')),
5114 ('a', 'added', None, _('show only added files')),
5114 ('a', 'added', None, _('show only added files')),
5115 ('r', 'removed', None, _('show only removed files')),
5115 ('r', 'removed', None, _('show only removed files')),
5116 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5116 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5117 ('c', 'clean', None, _('show only files without changes')),
5117 ('c', 'clean', None, _('show only files without changes')),
5118 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5118 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5119 ('i', 'ignored', None, _('show only ignored files')),
5119 ('i', 'ignored', None, _('show only ignored files')),
5120 ('n', 'no-status', None, _('hide status prefix')),
5120 ('n', 'no-status', None, _('hide status prefix')),
5121 ('C', 'copies', None, _('show source of copied files')),
5121 ('C', 'copies', None, _('show source of copied files')),
5122 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5122 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5123 ('', 'rev', [], _('show difference from revision'), _('REV')),
5123 ('', 'rev', [], _('show difference from revision'), _('REV')),
5124 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5124 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5125 ] + walkopts + subrepoopts,
5125 ] + walkopts + subrepoopts,
5126 _('[OPTION]... [FILE]...'))
5126 _('[OPTION]... [FILE]...'))
5127 def status(ui, repo, *pats, **opts):
5127 def status(ui, repo, *pats, **opts):
5128 """show changed files in the working directory
5128 """show changed files in the working directory
5129
5129
5130 Show status of files in the repository. If names are given, only
5130 Show status of files in the repository. If names are given, only
5131 files that match are shown. Files that are clean or ignored or
5131 files that match are shown. Files that are clean or ignored or
5132 the source of a copy/move operation, are not listed unless
5132 the source of a copy/move operation, are not listed unless
5133 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5133 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5134 Unless options described with "show only ..." are given, the
5134 Unless options described with "show only ..." are given, the
5135 options -mardu are used.
5135 options -mardu are used.
5136
5136
5137 Option -q/--quiet hides untracked (unknown and ignored) files
5137 Option -q/--quiet hides untracked (unknown and ignored) files
5138 unless explicitly requested with -u/--unknown or -i/--ignored.
5138 unless explicitly requested with -u/--unknown or -i/--ignored.
5139
5139
5140 .. note::
5140 .. note::
5141 status may appear to disagree with diff if permissions have
5141 status may appear to disagree with diff if permissions have
5142 changed or a merge has occurred. The standard diff format does
5142 changed or a merge has occurred. The standard diff format does
5143 not report permission changes and diff only reports changes
5143 not report permission changes and diff only reports changes
5144 relative to one merge parent.
5144 relative to one merge parent.
5145
5145
5146 If one revision is given, it is used as the base revision.
5146 If one revision is given, it is used as the base revision.
5147 If two revisions are given, the differences between them are
5147 If two revisions are given, the differences between them are
5148 shown. The --change option can also be used as a shortcut to list
5148 shown. The --change option can also be used as a shortcut to list
5149 the changed files of a revision from its first parent.
5149 the changed files of a revision from its first parent.
5150
5150
5151 The codes used to show the status of files are::
5151 The codes used to show the status of files are::
5152
5152
5153 M = modified
5153 M = modified
5154 A = added
5154 A = added
5155 R = removed
5155 R = removed
5156 C = clean
5156 C = clean
5157 ! = missing (deleted by non-hg command, but still tracked)
5157 ! = missing (deleted by non-hg command, but still tracked)
5158 ? = not tracked
5158 ? = not tracked
5159 I = ignored
5159 I = ignored
5160 = origin of the previous file listed as A (added)
5160 = origin of the previous file listed as A (added)
5161
5161
5162 .. container:: verbose
5162 .. container:: verbose
5163
5163
5164 Examples:
5164 Examples:
5165
5165
5166 - show changes in the working directory relative to a
5166 - show changes in the working directory relative to a
5167 changeset::
5167 changeset::
5168
5168
5169 hg status --rev 9353
5169 hg status --rev 9353
5170
5170
5171 - show all changes including copies in an existing changeset::
5171 - show all changes including copies in an existing changeset::
5172
5172
5173 hg status --copies --change 9353
5173 hg status --copies --change 9353
5174
5174
5175 - get a NUL separated list of added files, suitable for xargs::
5175 - get a NUL separated list of added files, suitable for xargs::
5176
5176
5177 hg status -an0
5177 hg status -an0
5178
5178
5179 Returns 0 on success.
5179 Returns 0 on success.
5180 """
5180 """
5181
5181
5182 revs = opts.get('rev')
5182 revs = opts.get('rev')
5183 change = opts.get('change')
5183 change = opts.get('change')
5184
5184
5185 if revs and change:
5185 if revs and change:
5186 msg = _('cannot specify --rev and --change at the same time')
5186 msg = _('cannot specify --rev and --change at the same time')
5187 raise util.Abort(msg)
5187 raise util.Abort(msg)
5188 elif change:
5188 elif change:
5189 node2 = scmutil.revsingle(repo, change, None).node()
5189 node2 = scmutil.revsingle(repo, change, None).node()
5190 node1 = repo[node2].p1().node()
5190 node1 = repo[node2].p1().node()
5191 else:
5191 else:
5192 node1, node2 = scmutil.revpair(repo, revs)
5192 node1, node2 = scmutil.revpair(repo, revs)
5193
5193
5194 cwd = (pats and repo.getcwd()) or ''
5194 cwd = (pats and repo.getcwd()) or ''
5195 end = opts.get('print0') and '\0' or '\n'
5195 end = opts.get('print0') and '\0' or '\n'
5196 copy = {}
5196 copy = {}
5197 states = 'modified added removed deleted unknown ignored clean'.split()
5197 states = 'modified added removed deleted unknown ignored clean'.split()
5198 show = [k for k in states if opts.get(k)]
5198 show = [k for k in states if opts.get(k)]
5199 if opts.get('all'):
5199 if opts.get('all'):
5200 show += ui.quiet and (states[:4] + ['clean']) or states
5200 show += ui.quiet and (states[:4] + ['clean']) or states
5201 if not show:
5201 if not show:
5202 show = ui.quiet and states[:4] or states[:5]
5202 show = ui.quiet and states[:4] or states[:5]
5203
5203
5204 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5204 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5205 'ignored' in show, 'clean' in show, 'unknown' in show,
5205 'ignored' in show, 'clean' in show, 'unknown' in show,
5206 opts.get('subrepos'))
5206 opts.get('subrepos'))
5207 changestates = zip(states, 'MAR!?IC', stat)
5207 changestates = zip(states, 'MAR!?IC', stat)
5208
5208
5209 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5209 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5210 copy = copies.pathcopies(repo[node1], repo[node2])
5210 copy = copies.pathcopies(repo[node1], repo[node2])
5211
5211
5212 fm = ui.formatter('status', opts)
5212 fm = ui.formatter('status', opts)
5213 format = '%s %s' + end
5213 format = '%s %s' + end
5214 if opts.get('no_status'):
5214 if opts.get('no_status'):
5215 format = '%.0s%s' + end
5215 format = '%.0s%s' + end
5216
5216
5217 for state, char, files in changestates:
5217 for state, char, files in changestates:
5218 if state in show:
5218 if state in show:
5219 label = 'status.' + state
5219 label = 'status.' + state
5220 for f in files:
5220 for f in files:
5221 fm.startitem()
5221 fm.startitem()
5222 fm.write("status path", format, char,
5222 fm.write("status path", format, char,
5223 repo.pathto(f, cwd), label=label)
5223 repo.pathto(f, cwd), label=label)
5224 if f in copy:
5224 if f in copy:
5225 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5225 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5226 label='status.copied')
5226 label='status.copied')
5227 fm.end()
5227 fm.end()
5228
5228
5229 @command('^summary|sum',
5229 @command('^summary|sum',
5230 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5230 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5231 def summary(ui, repo, **opts):
5231 def summary(ui, repo, **opts):
5232 """summarize working directory state
5232 """summarize working directory state
5233
5233
5234 This generates a brief summary of the working directory state,
5234 This generates a brief summary of the working directory state,
5235 including parents, branch, commit status, and available updates.
5235 including parents, branch, commit status, and available updates.
5236
5236
5237 With the --remote option, this will check the default paths for
5237 With the --remote option, this will check the default paths for
5238 incoming and outgoing changes. This can be time-consuming.
5238 incoming and outgoing changes. This can be time-consuming.
5239
5239
5240 Returns 0 on success.
5240 Returns 0 on success.
5241 """
5241 """
5242
5242
5243 ctx = repo[None]
5243 ctx = repo[None]
5244 parents = ctx.parents()
5244 parents = ctx.parents()
5245 pnode = parents[0].node()
5245 pnode = parents[0].node()
5246 marks = []
5246 marks = []
5247
5247
5248 for p in parents:
5248 for p in parents:
5249 # label with log.changeset (instead of log.parent) since this
5249 # label with log.changeset (instead of log.parent) since this
5250 # shows a working directory parent *changeset*:
5250 # shows a working directory parent *changeset*:
5251 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5251 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5252 label='log.changeset')
5252 label='log.changeset')
5253 ui.write(' '.join(p.tags()), label='log.tag')
5253 ui.write(' '.join(p.tags()), label='log.tag')
5254 if p.bookmarks():
5254 if p.bookmarks():
5255 marks.extend(p.bookmarks())
5255 marks.extend(p.bookmarks())
5256 if p.rev() == -1:
5256 if p.rev() == -1:
5257 if not len(repo):
5257 if not len(repo):
5258 ui.write(_(' (empty repository)'))
5258 ui.write(_(' (empty repository)'))
5259 else:
5259 else:
5260 ui.write(_(' (no revision checked out)'))
5260 ui.write(_(' (no revision checked out)'))
5261 ui.write('\n')
5261 ui.write('\n')
5262 if p.description():
5262 if p.description():
5263 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5263 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5264 label='log.summary')
5264 label='log.summary')
5265
5265
5266 branch = ctx.branch()
5266 branch = ctx.branch()
5267 bheads = repo.branchheads(branch)
5267 bheads = repo.branchheads(branch)
5268 m = _('branch: %s\n') % branch
5268 m = _('branch: %s\n') % branch
5269 if branch != 'default':
5269 if branch != 'default':
5270 ui.write(m, label='log.branch')
5270 ui.write(m, label='log.branch')
5271 else:
5271 else:
5272 ui.status(m, label='log.branch')
5272 ui.status(m, label='log.branch')
5273
5273
5274 if marks:
5274 if marks:
5275 current = repo._bookmarkcurrent
5275 current = repo._bookmarkcurrent
5276 ui.write(_('bookmarks:'), label='log.bookmark')
5276 ui.write(_('bookmarks:'), label='log.bookmark')
5277 if current is not None:
5277 if current is not None:
5278 try:
5278 try:
5279 marks.remove(current)
5279 marks.remove(current)
5280 ui.write(' *' + current, label='bookmarks.current')
5280 ui.write(' *' + current, label='bookmarks.current')
5281 except ValueError:
5281 except ValueError:
5282 # current bookmark not in parent ctx marks
5282 # current bookmark not in parent ctx marks
5283 pass
5283 pass
5284 for m in marks:
5284 for m in marks:
5285 ui.write(' ' + m, label='log.bookmark')
5285 ui.write(' ' + m, label='log.bookmark')
5286 ui.write('\n', label='log.bookmark')
5286 ui.write('\n', label='log.bookmark')
5287
5287
5288 st = list(repo.status(unknown=True))[:6]
5288 st = list(repo.status(unknown=True))[:6]
5289
5289
5290 c = repo.dirstate.copies()
5290 c = repo.dirstate.copies()
5291 copied, renamed = [], []
5291 copied, renamed = [], []
5292 for d, s in c.iteritems():
5292 for d, s in c.iteritems():
5293 if s in st[2]:
5293 if s in st[2]:
5294 st[2].remove(s)
5294 st[2].remove(s)
5295 renamed.append(d)
5295 renamed.append(d)
5296 else:
5296 else:
5297 copied.append(d)
5297 copied.append(d)
5298 if d in st[1]:
5298 if d in st[1]:
5299 st[1].remove(d)
5299 st[1].remove(d)
5300 st.insert(3, renamed)
5300 st.insert(3, renamed)
5301 st.insert(4, copied)
5301 st.insert(4, copied)
5302
5302
5303 ms = mergemod.mergestate(repo)
5303 ms = mergemod.mergestate(repo)
5304 st.append([f for f in ms if ms[f] == 'u'])
5304 st.append([f for f in ms if ms[f] == 'u'])
5305
5305
5306 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5306 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5307 st.append(subs)
5307 st.append(subs)
5308
5308
5309 labels = [ui.label(_('%d modified'), 'status.modified'),
5309 labels = [ui.label(_('%d modified'), 'status.modified'),
5310 ui.label(_('%d added'), 'status.added'),
5310 ui.label(_('%d added'), 'status.added'),
5311 ui.label(_('%d removed'), 'status.removed'),
5311 ui.label(_('%d removed'), 'status.removed'),
5312 ui.label(_('%d renamed'), 'status.copied'),
5312 ui.label(_('%d renamed'), 'status.copied'),
5313 ui.label(_('%d copied'), 'status.copied'),
5313 ui.label(_('%d copied'), 'status.copied'),
5314 ui.label(_('%d deleted'), 'status.deleted'),
5314 ui.label(_('%d deleted'), 'status.deleted'),
5315 ui.label(_('%d unknown'), 'status.unknown'),
5315 ui.label(_('%d unknown'), 'status.unknown'),
5316 ui.label(_('%d ignored'), 'status.ignored'),
5316 ui.label(_('%d ignored'), 'status.ignored'),
5317 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5317 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5318 ui.label(_('%d subrepos'), 'status.modified')]
5318 ui.label(_('%d subrepos'), 'status.modified')]
5319 t = []
5319 t = []
5320 for s, l in zip(st, labels):
5320 for s, l in zip(st, labels):
5321 if s:
5321 if s:
5322 t.append(l % len(s))
5322 t.append(l % len(s))
5323
5323
5324 t = ', '.join(t)
5324 t = ', '.join(t)
5325 cleanworkdir = False
5325 cleanworkdir = False
5326
5326
5327 if len(parents) > 1:
5327 if len(parents) > 1:
5328 t += _(' (merge)')
5328 t += _(' (merge)')
5329 elif branch != parents[0].branch():
5329 elif branch != parents[0].branch():
5330 t += _(' (new branch)')
5330 t += _(' (new branch)')
5331 elif (parents[0].extra().get('close') and
5331 elif (parents[0].extra().get('close') and
5332 pnode in repo.branchheads(branch, closed=True)):
5332 pnode in repo.branchheads(branch, closed=True)):
5333 t += _(' (head closed)')
5333 t += _(' (head closed)')
5334 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5334 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5335 t += _(' (clean)')
5335 t += _(' (clean)')
5336 cleanworkdir = True
5336 cleanworkdir = True
5337 elif pnode not in bheads:
5337 elif pnode not in bheads:
5338 t += _(' (new branch head)')
5338 t += _(' (new branch head)')
5339
5339
5340 if cleanworkdir:
5340 if cleanworkdir:
5341 ui.status(_('commit: %s\n') % t.strip())
5341 ui.status(_('commit: %s\n') % t.strip())
5342 else:
5342 else:
5343 ui.write(_('commit: %s\n') % t.strip())
5343 ui.write(_('commit: %s\n') % t.strip())
5344
5344
5345 # all ancestors of branch heads - all ancestors of parent = new csets
5345 # all ancestors of branch heads - all ancestors of parent = new csets
5346 new = [0] * len(repo)
5346 new = [0] * len(repo)
5347 cl = repo.changelog
5347 cl = repo.changelog
5348 for a in [cl.rev(n) for n in bheads]:
5348 for a in [cl.rev(n) for n in bheads]:
5349 new[a] = 1
5349 new[a] = 1
5350 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5350 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5351 new[a] = 1
5351 new[a] = 1
5352 for a in [p.rev() for p in parents]:
5352 for a in [p.rev() for p in parents]:
5353 if a >= 0:
5353 if a >= 0:
5354 new[a] = 0
5354 new[a] = 0
5355 for a in cl.ancestors(*[p.rev() for p in parents]):
5355 for a in cl.ancestors(*[p.rev() for p in parents]):
5356 new[a] = 0
5356 new[a] = 0
5357 new = sum(new)
5357 new = sum(new)
5358
5358
5359 if new == 0:
5359 if new == 0:
5360 ui.status(_('update: (current)\n'))
5360 ui.status(_('update: (current)\n'))
5361 elif pnode not in bheads:
5361 elif pnode not in bheads:
5362 ui.write(_('update: %d new changesets (update)\n') % new)
5362 ui.write(_('update: %d new changesets (update)\n') % new)
5363 else:
5363 else:
5364 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5364 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5365 (new, len(bheads)))
5365 (new, len(bheads)))
5366
5366
5367 if opts.get('remote'):
5367 if opts.get('remote'):
5368 t = []
5368 t = []
5369 source, branches = hg.parseurl(ui.expandpath('default'))
5369 source, branches = hg.parseurl(ui.expandpath('default'))
5370 other = hg.peer(repo, {}, source)
5370 other = hg.peer(repo, {}, source)
5371 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5371 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5372 ui.debug('comparing with %s\n' % util.hidepassword(source))
5372 ui.debug('comparing with %s\n' % util.hidepassword(source))
5373 repo.ui.pushbuffer()
5373 repo.ui.pushbuffer()
5374 commoninc = discovery.findcommonincoming(repo, other)
5374 commoninc = discovery.findcommonincoming(repo, other)
5375 _common, incoming, _rheads = commoninc
5375 _common, incoming, _rheads = commoninc
5376 repo.ui.popbuffer()
5376 repo.ui.popbuffer()
5377 if incoming:
5377 if incoming:
5378 t.append(_('1 or more incoming'))
5378 t.append(_('1 or more incoming'))
5379
5379
5380 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5380 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5381 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5381 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5382 if source != dest:
5382 if source != dest:
5383 other = hg.peer(repo, {}, dest)
5383 other = hg.peer(repo, {}, dest)
5384 commoninc = None
5384 commoninc = None
5385 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5385 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5386 repo.ui.pushbuffer()
5386 repo.ui.pushbuffer()
5387 outgoing = discovery.findcommonoutgoing(repo, other,
5387 outgoing = discovery.findcommonoutgoing(repo, other,
5388 commoninc=commoninc)
5388 commoninc=commoninc)
5389 repo.ui.popbuffer()
5389 repo.ui.popbuffer()
5390 o = outgoing.missing
5390 o = outgoing.missing
5391 if o:
5391 if o:
5392 t.append(_('%d outgoing') % len(o))
5392 t.append(_('%d outgoing') % len(o))
5393 if 'bookmarks' in other.listkeys('namespaces'):
5393 if 'bookmarks' in other.listkeys('namespaces'):
5394 lmarks = repo.listkeys('bookmarks')
5394 lmarks = repo.listkeys('bookmarks')
5395 rmarks = other.listkeys('bookmarks')
5395 rmarks = other.listkeys('bookmarks')
5396 diff = set(rmarks) - set(lmarks)
5396 diff = set(rmarks) - set(lmarks)
5397 if len(diff) > 0:
5397 if len(diff) > 0:
5398 t.append(_('%d incoming bookmarks') % len(diff))
5398 t.append(_('%d incoming bookmarks') % len(diff))
5399 diff = set(lmarks) - set(rmarks)
5399 diff = set(lmarks) - set(rmarks)
5400 if len(diff) > 0:
5400 if len(diff) > 0:
5401 t.append(_('%d outgoing bookmarks') % len(diff))
5401 t.append(_('%d outgoing bookmarks') % len(diff))
5402
5402
5403 if t:
5403 if t:
5404 ui.write(_('remote: %s\n') % (', '.join(t)))
5404 ui.write(_('remote: %s\n') % (', '.join(t)))
5405 else:
5405 else:
5406 ui.status(_('remote: (synced)\n'))
5406 ui.status(_('remote: (synced)\n'))
5407
5407
5408 @command('tag',
5408 @command('tag',
5409 [('f', 'force', None, _('force tag')),
5409 [('f', 'force', None, _('force tag')),
5410 ('l', 'local', None, _('make the tag local')),
5410 ('l', 'local', None, _('make the tag local')),
5411 ('r', 'rev', '', _('revision to tag'), _('REV')),
5411 ('r', 'rev', '', _('revision to tag'), _('REV')),
5412 ('', 'remove', None, _('remove a tag')),
5412 ('', 'remove', None, _('remove a tag')),
5413 # -l/--local is already there, commitopts cannot be used
5413 # -l/--local is already there, commitopts cannot be used
5414 ('e', 'edit', None, _('edit commit message')),
5414 ('e', 'edit', None, _('edit commit message')),
5415 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5415 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5416 ] + commitopts2,
5416 ] + commitopts2,
5417 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5417 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5418 def tag(ui, repo, name1, *names, **opts):
5418 def tag(ui, repo, name1, *names, **opts):
5419 """add one or more tags for the current or given revision
5419 """add one or more tags for the current or given revision
5420
5420
5421 Name a particular revision using <name>.
5421 Name a particular revision using <name>.
5422
5422
5423 Tags are used to name particular revisions of the repository and are
5423 Tags are used to name particular revisions of the repository and are
5424 very useful to compare different revisions, to go back to significant
5424 very useful to compare different revisions, to go back to significant
5425 earlier versions or to mark branch points as releases, etc. Changing
5425 earlier versions or to mark branch points as releases, etc. Changing
5426 an existing tag is normally disallowed; use -f/--force to override.
5426 an existing tag is normally disallowed; use -f/--force to override.
5427
5427
5428 If no revision is given, the parent of the working directory is
5428 If no revision is given, the parent of the working directory is
5429 used, or tip if no revision is checked out.
5429 used, or tip if no revision is checked out.
5430
5430
5431 To facilitate version control, distribution, and merging of tags,
5431 To facilitate version control, distribution, and merging of tags,
5432 they are stored as a file named ".hgtags" which is managed similarly
5432 they are stored as a file named ".hgtags" which is managed similarly
5433 to other project files and can be hand-edited if necessary. This
5433 to other project files and can be hand-edited if necessary. This
5434 also means that tagging creates a new commit. The file
5434 also means that tagging creates a new commit. The file
5435 ".hg/localtags" is used for local tags (not shared among
5435 ".hg/localtags" is used for local tags (not shared among
5436 repositories).
5436 repositories).
5437
5437
5438 Tag commits are usually made at the head of a branch. If the parent
5438 Tag commits are usually made at the head of a branch. If the parent
5439 of the working directory is not a branch head, :hg:`tag` aborts; use
5439 of the working directory is not a branch head, :hg:`tag` aborts; use
5440 -f/--force to force the tag commit to be based on a non-head
5440 -f/--force to force the tag commit to be based on a non-head
5441 changeset.
5441 changeset.
5442
5442
5443 See :hg:`help dates` for a list of formats valid for -d/--date.
5443 See :hg:`help dates` for a list of formats valid for -d/--date.
5444
5444
5445 Since tag names have priority over branch names during revision
5445 Since tag names have priority over branch names during revision
5446 lookup, using an existing branch name as a tag name is discouraged.
5446 lookup, using an existing branch name as a tag name is discouraged.
5447
5447
5448 Returns 0 on success.
5448 Returns 0 on success.
5449 """
5449 """
5450 wlock = lock = None
5450 wlock = lock = None
5451 try:
5451 try:
5452 wlock = repo.wlock()
5452 wlock = repo.wlock()
5453 lock = repo.lock()
5453 lock = repo.lock()
5454 rev_ = "."
5454 rev_ = "."
5455 names = [t.strip() for t in (name1,) + names]
5455 names = [t.strip() for t in (name1,) + names]
5456 if len(names) != len(set(names)):
5456 if len(names) != len(set(names)):
5457 raise util.Abort(_('tag names must be unique'))
5457 raise util.Abort(_('tag names must be unique'))
5458 for n in names:
5458 for n in names:
5459 if n in ['tip', '.', 'null']:
5459 if n in ['tip', '.', 'null']:
5460 raise util.Abort(_("the name '%s' is reserved") % n)
5460 raise util.Abort(_("the name '%s' is reserved") % n)
5461 if not n:
5461 if not n:
5462 raise util.Abort(_('tag names cannot consist entirely of '
5462 raise util.Abort(_('tag names cannot consist entirely of '
5463 'whitespace'))
5463 'whitespace'))
5464 if opts.get('rev') and opts.get('remove'):
5464 if opts.get('rev') and opts.get('remove'):
5465 raise util.Abort(_("--rev and --remove are incompatible"))
5465 raise util.Abort(_("--rev and --remove are incompatible"))
5466 if opts.get('rev'):
5466 if opts.get('rev'):
5467 rev_ = opts['rev']
5467 rev_ = opts['rev']
5468 message = opts.get('message')
5468 message = opts.get('message')
5469 if opts.get('remove'):
5469 if opts.get('remove'):
5470 expectedtype = opts.get('local') and 'local' or 'global'
5470 expectedtype = opts.get('local') and 'local' or 'global'
5471 for n in names:
5471 for n in names:
5472 if not repo.tagtype(n):
5472 if not repo.tagtype(n):
5473 raise util.Abort(_("tag '%s' does not exist") % n)
5473 raise util.Abort(_("tag '%s' does not exist") % n)
5474 if repo.tagtype(n) != expectedtype:
5474 if repo.tagtype(n) != expectedtype:
5475 if expectedtype == 'global':
5475 if expectedtype == 'global':
5476 raise util.Abort(_("tag '%s' is not a global tag") % n)
5476 raise util.Abort(_("tag '%s' is not a global tag") % n)
5477 else:
5477 else:
5478 raise util.Abort(_("tag '%s' is not a local tag") % n)
5478 raise util.Abort(_("tag '%s' is not a local tag") % n)
5479 rev_ = nullid
5479 rev_ = nullid
5480 if not message:
5480 if not message:
5481 # we don't translate commit messages
5481 # we don't translate commit messages
5482 message = 'Removed tag %s' % ', '.join(names)
5482 message = 'Removed tag %s' % ', '.join(names)
5483 elif not opts.get('force'):
5483 elif not opts.get('force'):
5484 for n in names:
5484 for n in names:
5485 if n in repo.tags():
5485 if n in repo.tags():
5486 raise util.Abort(_("tag '%s' already exists "
5486 raise util.Abort(_("tag '%s' already exists "
5487 "(use -f to force)") % n)
5487 "(use -f to force)") % n)
5488 if not opts.get('local'):
5488 if not opts.get('local'):
5489 p1, p2 = repo.dirstate.parents()
5489 p1, p2 = repo.dirstate.parents()
5490 if p2 != nullid:
5490 if p2 != nullid:
5491 raise util.Abort(_('uncommitted merge'))
5491 raise util.Abort(_('uncommitted merge'))
5492 bheads = repo.branchheads()
5492 bheads = repo.branchheads()
5493 if not opts.get('force') and bheads and p1 not in bheads:
5493 if not opts.get('force') and bheads and p1 not in bheads:
5494 raise util.Abort(_('not at a branch head (use -f to force)'))
5494 raise util.Abort(_('not at a branch head (use -f to force)'))
5495 r = scmutil.revsingle(repo, rev_).node()
5495 r = scmutil.revsingle(repo, rev_).node()
5496
5496
5497 if not message:
5497 if not message:
5498 # we don't translate commit messages
5498 # we don't translate commit messages
5499 message = ('Added tag %s for changeset %s' %
5499 message = ('Added tag %s for changeset %s' %
5500 (', '.join(names), short(r)))
5500 (', '.join(names), short(r)))
5501
5501
5502 date = opts.get('date')
5502 date = opts.get('date')
5503 if date:
5503 if date:
5504 date = util.parsedate(date)
5504 date = util.parsedate(date)
5505
5505
5506 if opts.get('edit'):
5506 if opts.get('edit'):
5507 message = ui.edit(message, ui.username())
5507 message = ui.edit(message, ui.username())
5508
5508
5509 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5509 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5510 finally:
5510 finally:
5511 release(lock, wlock)
5511 release(lock, wlock)
5512
5512
5513 @command('tags', [], '')
5513 @command('tags', [], '')
5514 def tags(ui, repo):
5514 def tags(ui, repo):
5515 """list repository tags
5515 """list repository tags
5516
5516
5517 This lists both regular and local tags. When the -v/--verbose
5517 This lists both regular and local tags. When the -v/--verbose
5518 switch is used, a third column "local" is printed for local tags.
5518 switch is used, a third column "local" is printed for local tags.
5519
5519
5520 Returns 0 on success.
5520 Returns 0 on success.
5521 """
5521 """
5522
5522
5523 hexfunc = ui.debugflag and hex or short
5523 hexfunc = ui.debugflag and hex or short
5524 tagtype = ""
5524 tagtype = ""
5525
5525
5526 for t, n in reversed(repo.tagslist()):
5526 for t, n in reversed(repo.tagslist()):
5527 if ui.quiet:
5527 if ui.quiet:
5528 ui.write("%s\n" % t, label='tags.normal')
5528 ui.write("%s\n" % t, label='tags.normal')
5529 continue
5529 continue
5530
5530
5531 hn = hexfunc(n)
5531 hn = hexfunc(n)
5532 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5532 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5533 rev = ui.label(r, 'log.changeset')
5533 rev = ui.label(r, 'log.changeset')
5534 spaces = " " * (30 - encoding.colwidth(t))
5534 spaces = " " * (30 - encoding.colwidth(t))
5535
5535
5536 tag = ui.label(t, 'tags.normal')
5536 tag = ui.label(t, 'tags.normal')
5537 if ui.verbose:
5537 if ui.verbose:
5538 if repo.tagtype(t) == 'local':
5538 if repo.tagtype(t) == 'local':
5539 tagtype = " local"
5539 tagtype = " local"
5540 tag = ui.label(t, 'tags.local')
5540 tag = ui.label(t, 'tags.local')
5541 else:
5541 else:
5542 tagtype = ""
5542 tagtype = ""
5543 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5543 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5544
5544
5545 @command('tip',
5545 @command('tip',
5546 [('p', 'patch', None, _('show patch')),
5546 [('p', 'patch', None, _('show patch')),
5547 ('g', 'git', None, _('use git extended diff format')),
5547 ('g', 'git', None, _('use git extended diff format')),
5548 ] + templateopts,
5548 ] + templateopts,
5549 _('[-p] [-g]'))
5549 _('[-p] [-g]'))
5550 def tip(ui, repo, **opts):
5550 def tip(ui, repo, **opts):
5551 """show the tip revision
5551 """show the tip revision
5552
5552
5553 The tip revision (usually just called the tip) is the changeset
5553 The tip revision (usually just called the tip) is the changeset
5554 most recently added to the repository (and therefore the most
5554 most recently added to the repository (and therefore the most
5555 recently changed head).
5555 recently changed head).
5556
5556
5557 If you have just made a commit, that commit will be the tip. If
5557 If you have just made a commit, that commit will be the tip. If
5558 you have just pulled changes from another repository, the tip of
5558 you have just pulled changes from another repository, the tip of
5559 that repository becomes the current tip. The "tip" tag is special
5559 that repository becomes the current tip. The "tip" tag is special
5560 and cannot be renamed or assigned to a different changeset.
5560 and cannot be renamed or assigned to a different changeset.
5561
5561
5562 Returns 0 on success.
5562 Returns 0 on success.
5563 """
5563 """
5564 displayer = cmdutil.show_changeset(ui, repo, opts)
5564 displayer = cmdutil.show_changeset(ui, repo, opts)
5565 displayer.show(repo[len(repo) - 1])
5565 displayer.show(repo[len(repo) - 1])
5566 displayer.close()
5566 displayer.close()
5567
5567
5568 @command('unbundle',
5568 @command('unbundle',
5569 [('u', 'update', None,
5569 [('u', 'update', None,
5570 _('update to new branch head if changesets were unbundled'))],
5570 _('update to new branch head if changesets were unbundled'))],
5571 _('[-u] FILE...'))
5571 _('[-u] FILE...'))
5572 def unbundle(ui, repo, fname1, *fnames, **opts):
5572 def unbundle(ui, repo, fname1, *fnames, **opts):
5573 """apply one or more changegroup files
5573 """apply one or more changegroup files
5574
5574
5575 Apply one or more compressed changegroup files generated by the
5575 Apply one or more compressed changegroup files generated by the
5576 bundle command.
5576 bundle command.
5577
5577
5578 Returns 0 on success, 1 if an update has unresolved files.
5578 Returns 0 on success, 1 if an update has unresolved files.
5579 """
5579 """
5580 fnames = (fname1,) + fnames
5580 fnames = (fname1,) + fnames
5581
5581
5582 lock = repo.lock()
5582 lock = repo.lock()
5583 wc = repo['.']
5583 wc = repo['.']
5584 try:
5584 try:
5585 for fname in fnames:
5585 for fname in fnames:
5586 f = url.open(ui, fname)
5586 f = url.open(ui, fname)
5587 gen = changegroup.readbundle(f, fname)
5587 gen = changegroup.readbundle(f, fname)
5588 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5588 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5589 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5589 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5590 finally:
5590 finally:
5591 lock.release()
5591 lock.release()
5592 return postincoming(ui, repo, modheads, opts.get('update'), None)
5592 return postincoming(ui, repo, modheads, opts.get('update'), None)
5593
5593
5594 @command('^update|up|checkout|co',
5594 @command('^update|up|checkout|co',
5595 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5595 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5596 ('c', 'check', None,
5596 ('c', 'check', None,
5597 _('update across branches if no uncommitted changes')),
5597 _('update across branches if no uncommitted changes')),
5598 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5598 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5599 ('r', 'rev', '', _('revision'), _('REV'))],
5599 ('r', 'rev', '', _('revision'), _('REV'))],
5600 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5600 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5601 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5601 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5602 """update working directory (or switch revisions)
5602 """update working directory (or switch revisions)
5603
5603
5604 Update the repository's working directory to the specified
5604 Update the repository's working directory to the specified
5605 changeset. If no changeset is specified, update to the tip of the
5605 changeset. If no changeset is specified, update to the tip of the
5606 current named branch and move the current bookmark (see :hg:`help
5606 current named branch and move the current bookmark (see :hg:`help
5607 bookmarks`).
5607 bookmarks`).
5608
5608
5609 If the changeset is not a descendant of the working directory's
5609 If the changeset is not a descendant of the working directory's
5610 parent, the update is aborted. With the -c/--check option, the
5610 parent, the update is aborted. With the -c/--check option, the
5611 working directory is checked for uncommitted changes; if none are
5611 working directory is checked for uncommitted changes; if none are
5612 found, the working directory is updated to the specified
5612 found, the working directory is updated to the specified
5613 changeset.
5613 changeset.
5614
5614
5615 Update sets the working directory's parent revison to the specified
5615 Update sets the working directory's parent revison to the specified
5616 changeset (see :hg:`help parents`).
5616 changeset (see :hg:`help parents`).
5617
5617
5618 The following rules apply when the working directory contains
5618 The following rules apply when the working directory contains
5619 uncommitted changes:
5619 uncommitted changes:
5620
5620
5621 1. If neither -c/--check nor -C/--clean is specified, and if
5621 1. If neither -c/--check nor -C/--clean is specified, and if
5622 the requested changeset is an ancestor or descendant of
5622 the requested changeset is an ancestor or descendant of
5623 the working directory's parent, the uncommitted changes
5623 the working directory's parent, the uncommitted changes
5624 are merged into the requested changeset and the merged
5624 are merged into the requested changeset and the merged
5625 result is left uncommitted. If the requested changeset is
5625 result is left uncommitted. If the requested changeset is
5626 not an ancestor or descendant (that is, it is on another
5626 not an ancestor or descendant (that is, it is on another
5627 branch), the update is aborted and the uncommitted changes
5627 branch), the update is aborted and the uncommitted changes
5628 are preserved.
5628 are preserved.
5629
5629
5630 2. With the -c/--check option, the update is aborted and the
5630 2. With the -c/--check option, the update is aborted and the
5631 uncommitted changes are preserved.
5631 uncommitted changes are preserved.
5632
5632
5633 3. With the -C/--clean option, uncommitted changes are discarded and
5633 3. With the -C/--clean option, uncommitted changes are discarded and
5634 the working directory is updated to the requested changeset.
5634 the working directory is updated to the requested changeset.
5635
5635
5636 Use null as the changeset to remove the working directory (like
5636 Use null as the changeset to remove the working directory (like
5637 :hg:`clone -U`).
5637 :hg:`clone -U`).
5638
5638
5639 If you want to revert just one file to an older revision, use
5639 If you want to revert just one file to an older revision, use
5640 :hg:`revert [-r REV] NAME`.
5640 :hg:`revert [-r REV] NAME`.
5641
5641
5642 See :hg:`help dates` for a list of formats valid for -d/--date.
5642 See :hg:`help dates` for a list of formats valid for -d/--date.
5643
5643
5644 Returns 0 on success, 1 if there are unresolved files.
5644 Returns 0 on success, 1 if there are unresolved files.
5645 """
5645 """
5646 if rev and node:
5646 if rev and node:
5647 raise util.Abort(_("please specify just one revision"))
5647 raise util.Abort(_("please specify just one revision"))
5648
5648
5649 if rev is None or rev == '':
5649 if rev is None or rev == '':
5650 rev = node
5650 rev = node
5651
5651
5652 # with no argument, we also move the current bookmark, if any
5652 # with no argument, we also move the current bookmark, if any
5653 movemarkfrom = None
5653 movemarkfrom = None
5654 if rev is None or node == '':
5654 if rev is None or node == '':
5655 movemarkfrom = repo['.'].node()
5655 movemarkfrom = repo['.'].node()
5656
5656
5657 # if we defined a bookmark, we have to remember the original bookmark name
5657 # if we defined a bookmark, we have to remember the original bookmark name
5658 brev = rev
5658 brev = rev
5659 rev = scmutil.revsingle(repo, rev, rev).rev()
5659 rev = scmutil.revsingle(repo, rev, rev).rev()
5660
5660
5661 if check and clean:
5661 if check and clean:
5662 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5662 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5663
5663
5664 if date:
5664 if date:
5665 if rev is not None:
5665 if rev is not None:
5666 raise util.Abort(_("you can't specify a revision and a date"))
5666 raise util.Abort(_("you can't specify a revision and a date"))
5667 rev = cmdutil.finddate(ui, repo, date)
5667 rev = cmdutil.finddate(ui, repo, date)
5668
5668
5669 if check:
5669 if check:
5670 c = repo[None]
5670 c = repo[None]
5671 if c.dirty(merge=False, branch=False):
5671 if c.dirty(merge=False, branch=False):
5672 raise util.Abort(_("uncommitted local changes"))
5672 raise util.Abort(_("uncommitted local changes"))
5673 if rev is None:
5673 if rev is None:
5674 rev = repo[repo[None].branch()].rev()
5674 rev = repo[repo[None].branch()].rev()
5675 mergemod._checkunknown(repo, repo[None], repo[rev])
5675 mergemod._checkunknown(repo, repo[None], repo[rev])
5676
5676
5677 if clean:
5677 if clean:
5678 ret = hg.clean(repo, rev)
5678 ret = hg.clean(repo, rev)
5679 else:
5679 else:
5680 ret = hg.update(repo, rev)
5680 ret = hg.update(repo, rev)
5681
5681
5682 if not ret and movemarkfrom:
5682 if not ret and movemarkfrom:
5683 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5683 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5684 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5684 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5685 elif brev in repo._bookmarks:
5685 elif brev in repo._bookmarks:
5686 bookmarks.setcurrent(repo, brev)
5686 bookmarks.setcurrent(repo, brev)
5687 elif brev:
5687 elif brev:
5688 bookmarks.unsetcurrent(repo)
5688 bookmarks.unsetcurrent(repo)
5689
5689
5690 return ret
5690 return ret
5691
5691
5692 @command('verify', [])
5692 @command('verify', [])
5693 def verify(ui, repo):
5693 def verify(ui, repo):
5694 """verify the integrity of the repository
5694 """verify the integrity of the repository
5695
5695
5696 Verify the integrity of the current repository.
5696 Verify the integrity of the current repository.
5697
5697
5698 This will perform an extensive check of the repository's
5698 This will perform an extensive check of the repository's
5699 integrity, validating the hashes and checksums of each entry in
5699 integrity, validating the hashes and checksums of each entry in
5700 the changelog, manifest, and tracked files, as well as the
5700 the changelog, manifest, and tracked files, as well as the
5701 integrity of their crosslinks and indices.
5701 integrity of their crosslinks and indices.
5702
5702
5703 Returns 0 on success, 1 if errors are encountered.
5703 Returns 0 on success, 1 if errors are encountered.
5704 """
5704 """
5705 return hg.verify(repo)
5705 return hg.verify(repo)
5706
5706
5707 @command('version', [])
5707 @command('version', [])
5708 def version_(ui):
5708 def version_(ui):
5709 """output version and copyright information"""
5709 """output version and copyright information"""
5710 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5710 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5711 % util.version())
5711 % util.version())
5712 ui.status(_(
5712 ui.status(_(
5713 "(see http://mercurial.selenic.com for more information)\n"
5713 "(see http://mercurial.selenic.com for more information)\n"
5714 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5714 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5715 "This is free software; see the source for copying conditions. "
5715 "This is free software; see the source for copying conditions. "
5716 "There is NO\nwarranty; "
5716 "There is NO\nwarranty; "
5717 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5717 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5718 ))
5718 ))
5719
5719
5720 norepo = ("clone init version help debugcommands debugcomplete"
5720 norepo = ("clone init version help debugcommands debugcomplete"
5721 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5721 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5722 " debugknown debuggetbundle debugbundle")
5722 " debugknown debuggetbundle debugbundle")
5723 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5723 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5724 " debugdata debugindex debugindexdot debugrevlog")
5724 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,405 +1,410 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo 'root' >root
3 $ echo 'root' >root
4 $ hg add root
4 $ hg add root
5 $ hg commit -d '0 0' -m "Adding root node"
5 $ hg commit -d '0 0' -m "Adding root node"
6
6
7 $ echo 'a' >a
7 $ echo 'a' >a
8 $ hg add a
8 $ hg add a
9 $ hg branch a
9 $ hg branch a
10 marked working directory as branch a
10 marked working directory as branch a
11 (branches are permanent and global, did you want a bookmark?)
11 (branches are permanent and global, did you want a bookmark?)
12 $ hg commit -d '1 0' -m "Adding a branch"
12 $ hg commit -d '1 0' -m "Adding a branch"
13
13
14 $ hg branch q
14 $ hg branch q
15 marked working directory as branch q
15 marked working directory as branch q
16 (branches are permanent and global, did you want a bookmark?)
16 (branches are permanent and global, did you want a bookmark?)
17 $ echo 'aa' >a
17 $ echo 'aa' >a
18 $ hg branch -C
18 $ hg branch -C
19 reset working directory to branch a
19 reset working directory to branch a
20 $ hg commit -d '2 0' -m "Adding to a branch"
20 $ hg commit -d '2 0' -m "Adding to a branch"
21
21
22 $ hg update -C 0
22 $ hg update -C 0
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 $ echo 'b' >b
24 $ echo 'b' >b
25 $ hg add b
25 $ hg add b
26 $ hg branch b
26 $ hg branch b
27 marked working directory as branch b
27 marked working directory as branch b
28 (branches are permanent and global, did you want a bookmark?)
28 (branches are permanent and global, did you want a bookmark?)
29 $ hg commit -d '2 0' -m "Adding b branch"
29 $ hg commit -d '2 0' -m "Adding b branch"
30
30
31 $ echo 'bh1' >bh1
31 $ echo 'bh1' >bh1
32 $ hg add bh1
32 $ hg add bh1
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
34
34
35 $ hg update -C 2
35 $ hg update -C 2
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
37 $ echo 'bh2' >bh2
37 $ echo 'bh2' >bh2
38 $ hg add bh2
38 $ hg add bh2
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
40
40
41 $ echo 'c' >c
41 $ echo 'c' >c
42 $ hg add c
42 $ hg add c
43 $ hg branch c
43 $ hg branch c
44 marked working directory as branch c
44 marked working directory as branch c
45 (branches are permanent and global, did you want a bookmark?)
45 (branches are permanent and global, did you want a bookmark?)
46 $ hg commit -d '5 0' -m "Adding c branch"
46 $ hg commit -d '5 0' -m "Adding c branch"
47
47
48 $ hg branch tip
48 $ hg branch tip
49 abort: the name 'tip' is reserved
49 abort: the name 'tip' is reserved
50 [255]
50 [255]
51 $ hg branch null
51 $ hg branch null
52 abort: the name 'null' is reserved
52 abort: the name 'null' is reserved
53 [255]
53 [255]
54 $ hg branch .
54 $ hg branch .
55 abort: the name '.' is reserved
55 abort: the name '.' is reserved
56 [255]
56 [255]
57
57
58 $ echo 'd' >d
58 $ echo 'd' >d
59 $ hg add d
59 $ hg add d
60 $ hg branch 'a branch name much longer than the default justification used by branches'
60 $ hg branch 'a branch name much longer than the default justification used by branches'
61 marked working directory as branch a branch name much longer than the default justification used by branches
61 marked working directory as branch a branch name much longer than the default justification used by branches
62 (branches are permanent and global, did you want a bookmark?)
62 (branches are permanent and global, did you want a bookmark?)
63 $ hg commit -d '6 0' -m "Adding d branch"
63 $ hg commit -d '6 0' -m "Adding d branch"
64
64
65 $ hg branches
65 $ hg branches
66 a branch name much longer than the default justification used by branches 7:10ff5895aa57
66 a branch name much longer than the default justification used by branches 7:10ff5895aa57
67 b 4:aee39cd168d0
67 b 4:aee39cd168d0
68 c 6:589736a22561 (inactive)
68 c 6:589736a22561 (inactive)
69 a 5:d8cbc61dbaa6 (inactive)
69 a 5:d8cbc61dbaa6 (inactive)
70 default 0:19709c5a4e75 (inactive)
70 default 0:19709c5a4e75 (inactive)
71
71
72 -------
72 -------
73
73
74 $ hg branches -a
74 $ hg branches -a
75 a branch name much longer than the default justification used by branches 7:10ff5895aa57
75 a branch name much longer than the default justification used by branches 7:10ff5895aa57
76 b 4:aee39cd168d0
76 b 4:aee39cd168d0
77
77
78 --- Branch a
78 --- Branch a
79
79
80 $ hg log -b a
80 $ hg log -b a
81 changeset: 5:d8cbc61dbaa6
81 changeset: 5:d8cbc61dbaa6
82 branch: a
82 branch: a
83 parent: 2:881fe2b92ad0
83 parent: 2:881fe2b92ad0
84 user: test
84 user: test
85 date: Thu Jan 01 00:00:04 1970 +0000
85 date: Thu Jan 01 00:00:04 1970 +0000
86 summary: Adding b branch head 2
86 summary: Adding b branch head 2
87
87
88 changeset: 2:881fe2b92ad0
88 changeset: 2:881fe2b92ad0
89 branch: a
89 branch: a
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:02 1970 +0000
91 date: Thu Jan 01 00:00:02 1970 +0000
92 summary: Adding to a branch
92 summary: Adding to a branch
93
93
94 changeset: 1:dd6b440dd85a
94 changeset: 1:dd6b440dd85a
95 branch: a
95 branch: a
96 user: test
96 user: test
97 date: Thu Jan 01 00:00:01 1970 +0000
97 date: Thu Jan 01 00:00:01 1970 +0000
98 summary: Adding a branch
98 summary: Adding a branch
99
99
100
100
101 ---- Branch b
101 ---- Branch b
102
102
103 $ hg log -b b
103 $ hg log -b b
104 changeset: 4:aee39cd168d0
104 changeset: 4:aee39cd168d0
105 branch: b
105 branch: b
106 user: test
106 user: test
107 date: Thu Jan 01 00:00:03 1970 +0000
107 date: Thu Jan 01 00:00:03 1970 +0000
108 summary: Adding b branch head 1
108 summary: Adding b branch head 1
109
109
110 changeset: 3:ac22033332d1
110 changeset: 3:ac22033332d1
111 branch: b
111 branch: b
112 parent: 0:19709c5a4e75
112 parent: 0:19709c5a4e75
113 user: test
113 user: test
114 date: Thu Jan 01 00:00:02 1970 +0000
114 date: Thu Jan 01 00:00:02 1970 +0000
115 summary: Adding b branch
115 summary: Adding b branch
116
116
117
117
118 ---- going to test branch closing
118 ---- going to test branch closing
119
119
120 $ hg branches
120 $ hg branches
121 a branch name much longer than the default justification used by branches 7:10ff5895aa57
121 a branch name much longer than the default justification used by branches 7:10ff5895aa57
122 b 4:aee39cd168d0
122 b 4:aee39cd168d0
123 c 6:589736a22561 (inactive)
123 c 6:589736a22561 (inactive)
124 a 5:d8cbc61dbaa6 (inactive)
124 a 5:d8cbc61dbaa6 (inactive)
125 default 0:19709c5a4e75 (inactive)
125 default 0:19709c5a4e75 (inactive)
126 $ hg up -C b
126 $ hg up -C b
127 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
127 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
128 $ echo 'xxx1' >> b
128 $ echo 'xxx1' >> b
129 $ hg commit -d '7 0' -m 'adding cset to branch b'
129 $ hg commit -d '7 0' -m 'adding cset to branch b'
130 $ hg up -C aee39cd168d0
130 $ hg up -C aee39cd168d0
131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
132 $ echo 'xxx2' >> b
132 $ echo 'xxx2' >> b
133 $ hg commit -d '8 0' -m 'adding head to branch b'
133 $ hg commit -d '8 0' -m 'adding head to branch b'
134 created new head
134 created new head
135 $ echo 'xxx3' >> b
135 $ echo 'xxx3' >> b
136 $ hg commit -d '9 0' -m 'adding another cset to branch b'
136 $ hg commit -d '9 0' -m 'adding another cset to branch b'
137 $ hg branches
137 $ hg branches
138 b 10:bfbe841b666e
138 b 10:bfbe841b666e
139 a branch name much longer than the default justification used by branches 7:10ff5895aa57
139 a branch name much longer than the default justification used by branches 7:10ff5895aa57
140 c 6:589736a22561 (inactive)
140 c 6:589736a22561 (inactive)
141 a 5:d8cbc61dbaa6 (inactive)
141 a 5:d8cbc61dbaa6 (inactive)
142 default 0:19709c5a4e75 (inactive)
142 default 0:19709c5a4e75 (inactive)
143 $ hg heads --closed
143 $ hg heads --closed
144 changeset: 10:bfbe841b666e
144 changeset: 10:bfbe841b666e
145 branch: b
145 branch: b
146 tag: tip
146 tag: tip
147 user: test
147 user: test
148 date: Thu Jan 01 00:00:09 1970 +0000
148 date: Thu Jan 01 00:00:09 1970 +0000
149 summary: adding another cset to branch b
149 summary: adding another cset to branch b
150
150
151 changeset: 8:eebb944467c9
151 changeset: 8:eebb944467c9
152 branch: b
152 branch: b
153 parent: 4:aee39cd168d0
153 parent: 4:aee39cd168d0
154 user: test
154 user: test
155 date: Thu Jan 01 00:00:07 1970 +0000
155 date: Thu Jan 01 00:00:07 1970 +0000
156 summary: adding cset to branch b
156 summary: adding cset to branch b
157
157
158 changeset: 7:10ff5895aa57
158 changeset: 7:10ff5895aa57
159 branch: a branch name much longer than the default justification used by branches
159 branch: a branch name much longer than the default justification used by branches
160 user: test
160 user: test
161 date: Thu Jan 01 00:00:06 1970 +0000
161 date: Thu Jan 01 00:00:06 1970 +0000
162 summary: Adding d branch
162 summary: Adding d branch
163
163
164 changeset: 6:589736a22561
164 changeset: 6:589736a22561
165 branch: c
165 branch: c
166 user: test
166 user: test
167 date: Thu Jan 01 00:00:05 1970 +0000
167 date: Thu Jan 01 00:00:05 1970 +0000
168 summary: Adding c branch
168 summary: Adding c branch
169
169
170 changeset: 5:d8cbc61dbaa6
170 changeset: 5:d8cbc61dbaa6
171 branch: a
171 branch: a
172 parent: 2:881fe2b92ad0
172 parent: 2:881fe2b92ad0
173 user: test
173 user: test
174 date: Thu Jan 01 00:00:04 1970 +0000
174 date: Thu Jan 01 00:00:04 1970 +0000
175 summary: Adding b branch head 2
175 summary: Adding b branch head 2
176
176
177 changeset: 0:19709c5a4e75
177 changeset: 0:19709c5a4e75
178 user: test
178 user: test
179 date: Thu Jan 01 00:00:00 1970 +0000
179 date: Thu Jan 01 00:00:00 1970 +0000
180 summary: Adding root node
180 summary: Adding root node
181
181
182 $ hg heads
182 $ hg heads
183 changeset: 10:bfbe841b666e
183 changeset: 10:bfbe841b666e
184 branch: b
184 branch: b
185 tag: tip
185 tag: tip
186 user: test
186 user: test
187 date: Thu Jan 01 00:00:09 1970 +0000
187 date: Thu Jan 01 00:00:09 1970 +0000
188 summary: adding another cset to branch b
188 summary: adding another cset to branch b
189
189
190 changeset: 8:eebb944467c9
190 changeset: 8:eebb944467c9
191 branch: b
191 branch: b
192 parent: 4:aee39cd168d0
192 parent: 4:aee39cd168d0
193 user: test
193 user: test
194 date: Thu Jan 01 00:00:07 1970 +0000
194 date: Thu Jan 01 00:00:07 1970 +0000
195 summary: adding cset to branch b
195 summary: adding cset to branch b
196
196
197 changeset: 7:10ff5895aa57
197 changeset: 7:10ff5895aa57
198 branch: a branch name much longer than the default justification used by branches
198 branch: a branch name much longer than the default justification used by branches
199 user: test
199 user: test
200 date: Thu Jan 01 00:00:06 1970 +0000
200 date: Thu Jan 01 00:00:06 1970 +0000
201 summary: Adding d branch
201 summary: Adding d branch
202
202
203 changeset: 6:589736a22561
203 changeset: 6:589736a22561
204 branch: c
204 branch: c
205 user: test
205 user: test
206 date: Thu Jan 01 00:00:05 1970 +0000
206 date: Thu Jan 01 00:00:05 1970 +0000
207 summary: Adding c branch
207 summary: Adding c branch
208
208
209 changeset: 5:d8cbc61dbaa6
209 changeset: 5:d8cbc61dbaa6
210 branch: a
210 branch: a
211 parent: 2:881fe2b92ad0
211 parent: 2:881fe2b92ad0
212 user: test
212 user: test
213 date: Thu Jan 01 00:00:04 1970 +0000
213 date: Thu Jan 01 00:00:04 1970 +0000
214 summary: Adding b branch head 2
214 summary: Adding b branch head 2
215
215
216 changeset: 0:19709c5a4e75
216 changeset: 0:19709c5a4e75
217 user: test
217 user: test
218 date: Thu Jan 01 00:00:00 1970 +0000
218 date: Thu Jan 01 00:00:00 1970 +0000
219 summary: Adding root node
219 summary: Adding root node
220
220
221 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
221 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
222 $ hg branches -a
222 $ hg branches -a
223 b 8:eebb944467c9
223 b 8:eebb944467c9
224 a branch name much longer than the default justification used by branches 7:10ff5895aa57
224 a branch name much longer than the default justification used by branches 7:10ff5895aa57
225 $ hg up -C b
225 $ hg up -C b
226 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
227 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
228
228
229 --- b branch should be inactive
229 --- b branch should be inactive
230
230
231 $ hg branches
231 $ hg branches
232 a branch name much longer than the default justification used by branches 7:10ff5895aa57
232 a branch name much longer than the default justification used by branches 7:10ff5895aa57
233 c 6:589736a22561 (inactive)
233 c 6:589736a22561 (inactive)
234 a 5:d8cbc61dbaa6 (inactive)
234 a 5:d8cbc61dbaa6 (inactive)
235 default 0:19709c5a4e75 (inactive)
235 default 0:19709c5a4e75 (inactive)
236 $ hg branches -c
236 $ hg branches -c
237 a branch name much longer than the default justification used by branches 7:10ff5895aa57
237 a branch name much longer than the default justification used by branches 7:10ff5895aa57
238 b 12:e3d49c0575d8 (closed)
238 b 12:e3d49c0575d8 (closed)
239 c 6:589736a22561 (inactive)
239 c 6:589736a22561 (inactive)
240 a 5:d8cbc61dbaa6 (inactive)
240 a 5:d8cbc61dbaa6 (inactive)
241 default 0:19709c5a4e75 (inactive)
241 default 0:19709c5a4e75 (inactive)
242 $ hg branches -a
242 $ hg branches -a
243 a branch name much longer than the default justification used by branches 7:10ff5895aa57
243 a branch name much longer than the default justification used by branches 7:10ff5895aa57
244 $ hg branches -q
245 a branch name much longer than the default justification used by branches
246 c
247 a
248 default
244 $ hg heads b
249 $ hg heads b
245 no open branch heads found on branches b
250 no open branch heads found on branches b
246 [1]
251 [1]
247 $ hg heads --closed b
252 $ hg heads --closed b
248 changeset: 12:e3d49c0575d8
253 changeset: 12:e3d49c0575d8
249 branch: b
254 branch: b
250 tag: tip
255 tag: tip
251 parent: 8:eebb944467c9
256 parent: 8:eebb944467c9
252 user: test
257 user: test
253 date: Thu Jan 01 00:00:09 1970 +0000
258 date: Thu Jan 01 00:00:09 1970 +0000
254 summary: close this part branch too
259 summary: close this part branch too
255
260
256 changeset: 11:d3f163457ebf
261 changeset: 11:d3f163457ebf
257 branch: b
262 branch: b
258 user: test
263 user: test
259 date: Thu Jan 01 00:00:09 1970 +0000
264 date: Thu Jan 01 00:00:09 1970 +0000
260 summary: prune bad branch
265 summary: prune bad branch
261
266
262 $ echo 'xxx4' >> b
267 $ echo 'xxx4' >> b
263 $ hg commit -d '9 0' -m 'reopen branch with a change'
268 $ hg commit -d '9 0' -m 'reopen branch with a change'
264 reopening closed branch head 12
269 reopening closed branch head 12
265
270
266 --- branch b is back in action
271 --- branch b is back in action
267
272
268 $ hg branches -a
273 $ hg branches -a
269 b 13:e23b5505d1ad
274 b 13:e23b5505d1ad
270 a branch name much longer than the default justification used by branches 7:10ff5895aa57
275 a branch name much longer than the default justification used by branches 7:10ff5895aa57
271
276
272 ---- test heads listings
277 ---- test heads listings
273
278
274 $ hg heads
279 $ hg heads
275 changeset: 13:e23b5505d1ad
280 changeset: 13:e23b5505d1ad
276 branch: b
281 branch: b
277 tag: tip
282 tag: tip
278 user: test
283 user: test
279 date: Thu Jan 01 00:00:09 1970 +0000
284 date: Thu Jan 01 00:00:09 1970 +0000
280 summary: reopen branch with a change
285 summary: reopen branch with a change
281
286
282 changeset: 7:10ff5895aa57
287 changeset: 7:10ff5895aa57
283 branch: a branch name much longer than the default justification used by branches
288 branch: a branch name much longer than the default justification used by branches
284 user: test
289 user: test
285 date: Thu Jan 01 00:00:06 1970 +0000
290 date: Thu Jan 01 00:00:06 1970 +0000
286 summary: Adding d branch
291 summary: Adding d branch
287
292
288 changeset: 6:589736a22561
293 changeset: 6:589736a22561
289 branch: c
294 branch: c
290 user: test
295 user: test
291 date: Thu Jan 01 00:00:05 1970 +0000
296 date: Thu Jan 01 00:00:05 1970 +0000
292 summary: Adding c branch
297 summary: Adding c branch
293
298
294 changeset: 5:d8cbc61dbaa6
299 changeset: 5:d8cbc61dbaa6
295 branch: a
300 branch: a
296 parent: 2:881fe2b92ad0
301 parent: 2:881fe2b92ad0
297 user: test
302 user: test
298 date: Thu Jan 01 00:00:04 1970 +0000
303 date: Thu Jan 01 00:00:04 1970 +0000
299 summary: Adding b branch head 2
304 summary: Adding b branch head 2
300
305
301 changeset: 0:19709c5a4e75
306 changeset: 0:19709c5a4e75
302 user: test
307 user: test
303 date: Thu Jan 01 00:00:00 1970 +0000
308 date: Thu Jan 01 00:00:00 1970 +0000
304 summary: Adding root node
309 summary: Adding root node
305
310
306
311
307 branch default
312 branch default
308
313
309 $ hg heads default
314 $ hg heads default
310 changeset: 0:19709c5a4e75
315 changeset: 0:19709c5a4e75
311 user: test
316 user: test
312 date: Thu Jan 01 00:00:00 1970 +0000
317 date: Thu Jan 01 00:00:00 1970 +0000
313 summary: Adding root node
318 summary: Adding root node
314
319
315
320
316 branch a
321 branch a
317
322
318 $ hg heads a
323 $ hg heads a
319 changeset: 5:d8cbc61dbaa6
324 changeset: 5:d8cbc61dbaa6
320 branch: a
325 branch: a
321 parent: 2:881fe2b92ad0
326 parent: 2:881fe2b92ad0
322 user: test
327 user: test
323 date: Thu Jan 01 00:00:04 1970 +0000
328 date: Thu Jan 01 00:00:04 1970 +0000
324 summary: Adding b branch head 2
329 summary: Adding b branch head 2
325
330
326 $ hg heads --active a
331 $ hg heads --active a
327 no open branch heads found on branches a
332 no open branch heads found on branches a
328 [1]
333 [1]
329
334
330 branch b
335 branch b
331
336
332 $ hg heads b
337 $ hg heads b
333 changeset: 13:e23b5505d1ad
338 changeset: 13:e23b5505d1ad
334 branch: b
339 branch: b
335 tag: tip
340 tag: tip
336 user: test
341 user: test
337 date: Thu Jan 01 00:00:09 1970 +0000
342 date: Thu Jan 01 00:00:09 1970 +0000
338 summary: reopen branch with a change
343 summary: reopen branch with a change
339
344
340 $ hg heads --closed b
345 $ hg heads --closed b
341 changeset: 13:e23b5505d1ad
346 changeset: 13:e23b5505d1ad
342 branch: b
347 branch: b
343 tag: tip
348 tag: tip
344 user: test
349 user: test
345 date: Thu Jan 01 00:00:09 1970 +0000
350 date: Thu Jan 01 00:00:09 1970 +0000
346 summary: reopen branch with a change
351 summary: reopen branch with a change
347
352
348 changeset: 11:d3f163457ebf
353 changeset: 11:d3f163457ebf
349 branch: b
354 branch: b
350 user: test
355 user: test
351 date: Thu Jan 01 00:00:09 1970 +0000
356 date: Thu Jan 01 00:00:09 1970 +0000
352 summary: prune bad branch
357 summary: prune bad branch
353
358
354 default branch colors:
359 default branch colors:
355
360
356 $ echo "[extensions]" >> $HGRCPATH
361 $ echo "[extensions]" >> $HGRCPATH
357 $ echo "color =" >> $HGRCPATH
362 $ echo "color =" >> $HGRCPATH
358 $ echo "[color]" >> $HGRCPATH
363 $ echo "[color]" >> $HGRCPATH
359 $ echo "mode = ansi" >> $HGRCPATH
364 $ echo "mode = ansi" >> $HGRCPATH
360
365
361 $ hg up -C c
366 $ hg up -C c
362 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
367 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
363 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
368 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
364 $ hg up -C b
369 $ hg up -C b
365 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
370 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
366 $ hg branches --color=always
371 $ hg branches --color=always
367 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
372 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
368 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
373 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
369 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
374 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
370 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
375 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
371
376
372 default closed branch color:
377 default closed branch color:
373
378
374 $ hg branches --color=always --closed
379 $ hg branches --color=always --closed
375 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
380 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
376 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
381 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
377 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
382 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
378 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
383 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
379 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
384 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
380
385
381 $ echo "[extensions]" >> $HGRCPATH
386 $ echo "[extensions]" >> $HGRCPATH
382 $ echo "color =" >> $HGRCPATH
387 $ echo "color =" >> $HGRCPATH
383 $ echo "[color]" >> $HGRCPATH
388 $ echo "[color]" >> $HGRCPATH
384 $ echo "branches.active = green" >> $HGRCPATH
389 $ echo "branches.active = green" >> $HGRCPATH
385 $ echo "branches.closed = blue" >> $HGRCPATH
390 $ echo "branches.closed = blue" >> $HGRCPATH
386 $ echo "branches.current = red" >> $HGRCPATH
391 $ echo "branches.current = red" >> $HGRCPATH
387 $ echo "branches.inactive = magenta" >> $HGRCPATH
392 $ echo "branches.inactive = magenta" >> $HGRCPATH
388 $ echo "log.changeset = cyan" >> $HGRCPATH
393 $ echo "log.changeset = cyan" >> $HGRCPATH
389
394
390 custom branch colors:
395 custom branch colors:
391
396
392 $ hg branches --color=always
397 $ hg branches --color=always
393 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
398 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
394 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
399 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
395 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
400 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
396 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
401 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
397
402
398 custom closed branch color:
403 custom closed branch color:
399
404
400 $ hg branches --color=always --closed
405 $ hg branches --color=always --closed
401 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
406 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
402 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
407 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
403 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
408 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
404 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
409 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
405 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
410 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
General Comments 0
You need to be logged in to leave comments. Login now