##// END OF EJS Templates
bookmarks: allow moving a bookmark forward to a descendant...
Kevin Bullock -
r18773:56dd55da default
parent child Browse files
Show More
@@ -1,5729 +1,5736 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
814 anc = repo.changelog.ancestors([repo[target].rev()])
815 bmctx = repo[marks[mark]]
816 if bmctx.rev() in anc:
817 ui.status(_("moving bookmark '%s' forward from %s\n") %
818 (mark, short(bmctx.node())))
819 return
813 raise util.Abort(_("bookmark '%s' already exists "
820 raise util.Abort(_("bookmark '%s' already exists "
814 "(use -f to force)") % mark)
821 "(use -f to force)") % mark)
815 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
822 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
816 and not force):
823 and not force):
817 raise util.Abort(
824 raise util.Abort(
818 _("a bookmark cannot have the name of an existing branch"))
825 _("a bookmark cannot have the name of an existing branch"))
819
826
820 if delete and rename:
827 if delete and rename:
821 raise util.Abort(_("--delete and --rename are incompatible"))
828 raise util.Abort(_("--delete and --rename are incompatible"))
822 if delete and rev:
829 if delete and rev:
823 raise util.Abort(_("--rev is incompatible with --delete"))
830 raise util.Abort(_("--rev is incompatible with --delete"))
824 if rename and rev:
831 if rename and rev:
825 raise util.Abort(_("--rev is incompatible with --rename"))
832 raise util.Abort(_("--rev is incompatible with --rename"))
826 if mark is None and (delete or rev):
833 if mark is None and (delete or rev):
827 raise util.Abort(_("bookmark name required"))
834 raise util.Abort(_("bookmark name required"))
828
835
829 if delete:
836 if delete:
830 if mark not in marks:
837 if mark not in marks:
831 raise util.Abort(_("bookmark '%s' does not exist") % mark)
838 raise util.Abort(_("bookmark '%s' does not exist") % mark)
832 if mark == repo._bookmarkcurrent:
839 if mark == repo._bookmarkcurrent:
833 bookmarks.setcurrent(repo, None)
840 bookmarks.setcurrent(repo, None)
834 del marks[mark]
841 del marks[mark]
835 marks.write()
842 marks.write()
836
843
837 elif rename:
844 elif rename:
838 if mark is None:
845 if mark is None:
839 raise util.Abort(_("new bookmark name required"))
846 raise util.Abort(_("new bookmark name required"))
840 mark = checkformat(mark)
847 mark = checkformat(mark)
841 if rename not in marks:
848 if rename not in marks:
842 raise util.Abort(_("bookmark '%s' does not exist") % rename)
849 raise util.Abort(_("bookmark '%s' does not exist") % rename)
843 checkconflict(repo, mark, force)
850 checkconflict(repo, mark, force)
844 marks[mark] = marks[rename]
851 marks[mark] = marks[rename]
845 if repo._bookmarkcurrent == rename and not inactive:
852 if repo._bookmarkcurrent == rename and not inactive:
846 bookmarks.setcurrent(repo, mark)
853 bookmarks.setcurrent(repo, mark)
847 del marks[rename]
854 del marks[rename]
848 marks.write()
855 marks.write()
849
856
850 elif mark is not None:
857 elif mark is not None:
851 mark = checkformat(mark)
858 mark = checkformat(mark)
852 if inactive and mark == repo._bookmarkcurrent:
859 if inactive and mark == repo._bookmarkcurrent:
853 bookmarks.setcurrent(repo, None)
860 bookmarks.setcurrent(repo, None)
854 return
861 return
855 checkconflict(repo, mark, force)
862 tgt = cur
856 if rev:
863 if rev:
857 marks[mark] = scmutil.revsingle(repo, rev).node()
864 tgt = scmutil.revsingle(repo, rev).node()
858 else:
865 checkconflict(repo, mark, force, tgt)
859 marks[mark] = cur
866 marks[mark] = tgt
860 if not inactive and cur == marks[mark]:
867 if not inactive and cur == marks[mark]:
861 bookmarks.setcurrent(repo, mark)
868 bookmarks.setcurrent(repo, mark)
862 marks.write()
869 marks.write()
863
870
864 # Same message whether trying to deactivate the current bookmark (-i
871 # Same message whether trying to deactivate the current bookmark (-i
865 # with no NAME) or listing bookmarks
872 # with no NAME) or listing bookmarks
866 elif len(marks) == 0:
873 elif len(marks) == 0:
867 ui.status(_("no bookmarks set\n"))
874 ui.status(_("no bookmarks set\n"))
868
875
869 elif inactive:
876 elif inactive:
870 if not repo._bookmarkcurrent:
877 if not repo._bookmarkcurrent:
871 ui.status(_("no active bookmark\n"))
878 ui.status(_("no active bookmark\n"))
872 else:
879 else:
873 bookmarks.setcurrent(repo, None)
880 bookmarks.setcurrent(repo, None)
874
881
875 else: # show bookmarks
882 else: # show bookmarks
876 for bmark, n in sorted(marks.iteritems()):
883 for bmark, n in sorted(marks.iteritems()):
877 current = repo._bookmarkcurrent
884 current = repo._bookmarkcurrent
878 if bmark == current:
885 if bmark == current:
879 prefix, label = '*', 'bookmarks.current'
886 prefix, label = '*', 'bookmarks.current'
880 else:
887 else:
881 prefix, label = ' ', ''
888 prefix, label = ' ', ''
882
889
883 if ui.quiet:
890 if ui.quiet:
884 ui.write("%s\n" % bmark, label=label)
891 ui.write("%s\n" % bmark, label=label)
885 else:
892 else:
886 ui.write(" %s %-25s %d:%s\n" % (
893 ui.write(" %s %-25s %d:%s\n" % (
887 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
894 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
888 label=label)
895 label=label)
889
896
890 @command('branch',
897 @command('branch',
891 [('f', 'force', None,
898 [('f', 'force', None,
892 _('set branch name even if it shadows an existing branch')),
899 _('set branch name even if it shadows an existing branch')),
893 ('C', 'clean', None, _('reset branch name to parent branch name'))],
900 ('C', 'clean', None, _('reset branch name to parent branch name'))],
894 _('[-fC] [NAME]'))
901 _('[-fC] [NAME]'))
895 def branch(ui, repo, label=None, **opts):
902 def branch(ui, repo, label=None, **opts):
896 """set or show the current branch name
903 """set or show the current branch name
897
904
898 .. note::
905 .. note::
899 Branch names are permanent and global. Use :hg:`bookmark` to create a
906 Branch names are permanent and global. Use :hg:`bookmark` to create a
900 light-weight bookmark instead. See :hg:`help glossary` for more
907 light-weight bookmark instead. See :hg:`help glossary` for more
901 information about named branches and bookmarks.
908 information about named branches and bookmarks.
902
909
903 With no argument, show the current branch name. With one argument,
910 With no argument, show the current branch name. With one argument,
904 set the working directory branch name (the branch will not exist
911 set the working directory branch name (the branch will not exist
905 in the repository until the next commit). Standard practice
912 in the repository until the next commit). Standard practice
906 recommends that primary development take place on the 'default'
913 recommends that primary development take place on the 'default'
907 branch.
914 branch.
908
915
909 Unless -f/--force is specified, branch will not let you set a
916 Unless -f/--force is specified, branch will not let you set a
910 branch name that already exists, even if it's inactive.
917 branch name that already exists, even if it's inactive.
911
918
912 Use -C/--clean to reset the working directory branch to that of
919 Use -C/--clean to reset the working directory branch to that of
913 the parent of the working directory, negating a previous branch
920 the parent of the working directory, negating a previous branch
914 change.
921 change.
915
922
916 Use the command :hg:`update` to switch to an existing branch. Use
923 Use the command :hg:`update` to switch to an existing branch. Use
917 :hg:`commit --close-branch` to mark this branch as closed.
924 :hg:`commit --close-branch` to mark this branch as closed.
918
925
919 Returns 0 on success.
926 Returns 0 on success.
920 """
927 """
921 if not opts.get('clean') and not label:
928 if not opts.get('clean') and not label:
922 ui.write("%s\n" % repo.dirstate.branch())
929 ui.write("%s\n" % repo.dirstate.branch())
923 return
930 return
924
931
925 wlock = repo.wlock()
932 wlock = repo.wlock()
926 try:
933 try:
927 if opts.get('clean'):
934 if opts.get('clean'):
928 label = repo[None].p1().branch()
935 label = repo[None].p1().branch()
929 repo.dirstate.setbranch(label)
936 repo.dirstate.setbranch(label)
930 ui.status(_('reset working directory to branch %s\n') % label)
937 ui.status(_('reset working directory to branch %s\n') % label)
931 elif label:
938 elif label:
932 if not opts.get('force') and label in repo.branchmap():
939 if not opts.get('force') and label in repo.branchmap():
933 if label not in [p.branch() for p in repo.parents()]:
940 if label not in [p.branch() for p in repo.parents()]:
934 raise util.Abort(_('a branch of the same name already'
941 raise util.Abort(_('a branch of the same name already'
935 ' exists'),
942 ' exists'),
936 # i18n: "it" refers to an existing branch
943 # i18n: "it" refers to an existing branch
937 hint=_("use 'hg update' to switch to it"))
944 hint=_("use 'hg update' to switch to it"))
938 scmutil.checknewlabel(repo, label, 'branch')
945 scmutil.checknewlabel(repo, label, 'branch')
939 repo.dirstate.setbranch(label)
946 repo.dirstate.setbranch(label)
940 ui.status(_('marked working directory as branch %s\n') % label)
947 ui.status(_('marked working directory as branch %s\n') % label)
941 ui.status(_('(branches are permanent and global, '
948 ui.status(_('(branches are permanent and global, '
942 'did you want a bookmark?)\n'))
949 'did you want a bookmark?)\n'))
943 finally:
950 finally:
944 wlock.release()
951 wlock.release()
945
952
946 @command('branches',
953 @command('branches',
947 [('a', 'active', False, _('show only branches that have unmerged heads')),
954 [('a', 'active', False, _('show only branches that have unmerged heads')),
948 ('c', 'closed', False, _('show normal and closed branches'))],
955 ('c', 'closed', False, _('show normal and closed branches'))],
949 _('[-ac]'))
956 _('[-ac]'))
950 def branches(ui, repo, active=False, closed=False):
957 def branches(ui, repo, active=False, closed=False):
951 """list repository named branches
958 """list repository named branches
952
959
953 List the repository's named branches, indicating which ones are
960 List the repository's named branches, indicating which ones are
954 inactive. If -c/--closed is specified, also list branches which have
961 inactive. If -c/--closed is specified, also list branches which have
955 been marked closed (see :hg:`commit --close-branch`).
962 been marked closed (see :hg:`commit --close-branch`).
956
963
957 If -a/--active is specified, only show active branches. A branch
964 If -a/--active is specified, only show active branches. A branch
958 is considered active if it contains repository heads.
965 is considered active if it contains repository heads.
959
966
960 Use the command :hg:`update` to switch to an existing branch.
967 Use the command :hg:`update` to switch to an existing branch.
961
968
962 Returns 0.
969 Returns 0.
963 """
970 """
964
971
965 hexfunc = ui.debugflag and hex or short
972 hexfunc = ui.debugflag and hex or short
966
973
967 activebranches = set([repo[n].branch() for n in repo.heads()])
974 activebranches = set([repo[n].branch() for n in repo.heads()])
968 branches = []
975 branches = []
969 for tag, heads in repo.branchmap().iteritems():
976 for tag, heads in repo.branchmap().iteritems():
970 for h in reversed(heads):
977 for h in reversed(heads):
971 ctx = repo[h]
978 ctx = repo[h]
972 isopen = not ctx.closesbranch()
979 isopen = not ctx.closesbranch()
973 if isopen:
980 if isopen:
974 tip = ctx
981 tip = ctx
975 break
982 break
976 else:
983 else:
977 tip = repo[heads[-1]]
984 tip = repo[heads[-1]]
978 isactive = tag in activebranches and isopen
985 isactive = tag in activebranches and isopen
979 branches.append((tip, isactive, isopen))
986 branches.append((tip, isactive, isopen))
980 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
987 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
981 reverse=True)
988 reverse=True)
982
989
983 for ctx, isactive, isopen in branches:
990 for ctx, isactive, isopen in branches:
984 if (not active) or isactive:
991 if (not active) or isactive:
985 if isactive:
992 if isactive:
986 label = 'branches.active'
993 label = 'branches.active'
987 notice = ''
994 notice = ''
988 elif not isopen:
995 elif not isopen:
989 if not closed:
996 if not closed:
990 continue
997 continue
991 label = 'branches.closed'
998 label = 'branches.closed'
992 notice = _(' (closed)')
999 notice = _(' (closed)')
993 else:
1000 else:
994 label = 'branches.inactive'
1001 label = 'branches.inactive'
995 notice = _(' (inactive)')
1002 notice = _(' (inactive)')
996 if ctx.branch() == repo.dirstate.branch():
1003 if ctx.branch() == repo.dirstate.branch():
997 label = 'branches.current'
1004 label = 'branches.current'
998 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1005 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
999 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1006 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1000 'log.changeset changeset.%s' % ctx.phasestr())
1007 'log.changeset changeset.%s' % ctx.phasestr())
1001 tag = ui.label(ctx.branch(), label)
1008 tag = ui.label(ctx.branch(), label)
1002 if ui.quiet:
1009 if ui.quiet:
1003 ui.write("%s\n" % tag)
1010 ui.write("%s\n" % tag)
1004 else:
1011 else:
1005 ui.write("%s %s%s\n" % (tag, rev, notice))
1012 ui.write("%s %s%s\n" % (tag, rev, notice))
1006
1013
1007 @command('bundle',
1014 @command('bundle',
1008 [('f', 'force', None, _('run even when the destination is unrelated')),
1015 [('f', 'force', None, _('run even when the destination is unrelated')),
1009 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1016 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1010 _('REV')),
1017 _('REV')),
1011 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1018 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1012 _('BRANCH')),
1019 _('BRANCH')),
1013 ('', 'base', [],
1020 ('', 'base', [],
1014 _('a base changeset assumed to be available at the destination'),
1021 _('a base changeset assumed to be available at the destination'),
1015 _('REV')),
1022 _('REV')),
1016 ('a', 'all', None, _('bundle all changesets in the repository')),
1023 ('a', 'all', None, _('bundle all changesets in the repository')),
1017 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1024 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1018 ] + remoteopts,
1025 ] + remoteopts,
1019 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1026 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1020 def bundle(ui, repo, fname, dest=None, **opts):
1027 def bundle(ui, repo, fname, dest=None, **opts):
1021 """create a changegroup file
1028 """create a changegroup file
1022
1029
1023 Generate a compressed changegroup file collecting changesets not
1030 Generate a compressed changegroup file collecting changesets not
1024 known to be in another repository.
1031 known to be in another repository.
1025
1032
1026 If you omit the destination repository, then hg assumes the
1033 If you omit the destination repository, then hg assumes the
1027 destination will have all the nodes you specify with --base
1034 destination will have all the nodes you specify with --base
1028 parameters. To create a bundle containing all changesets, use
1035 parameters. To create a bundle containing all changesets, use
1029 -a/--all (or --base null).
1036 -a/--all (or --base null).
1030
1037
1031 You can change compression method with the -t/--type option.
1038 You can change compression method with the -t/--type option.
1032 The available compression methods are: none, bzip2, and
1039 The available compression methods are: none, bzip2, and
1033 gzip (by default, bundles are compressed using bzip2).
1040 gzip (by default, bundles are compressed using bzip2).
1034
1041
1035 The bundle file can then be transferred using conventional means
1042 The bundle file can then be transferred using conventional means
1036 and applied to another repository with the unbundle or pull
1043 and applied to another repository with the unbundle or pull
1037 command. This is useful when direct push and pull are not
1044 command. This is useful when direct push and pull are not
1038 available or when exporting an entire repository is undesirable.
1045 available or when exporting an entire repository is undesirable.
1039
1046
1040 Applying bundles preserves all changeset contents including
1047 Applying bundles preserves all changeset contents including
1041 permissions, copy/rename information, and revision history.
1048 permissions, copy/rename information, and revision history.
1042
1049
1043 Returns 0 on success, 1 if no changes found.
1050 Returns 0 on success, 1 if no changes found.
1044 """
1051 """
1045 revs = None
1052 revs = None
1046 if 'rev' in opts:
1053 if 'rev' in opts:
1047 revs = scmutil.revrange(repo, opts['rev'])
1054 revs = scmutil.revrange(repo, opts['rev'])
1048
1055
1049 bundletype = opts.get('type', 'bzip2').lower()
1056 bundletype = opts.get('type', 'bzip2').lower()
1050 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1057 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1051 bundletype = btypes.get(bundletype)
1058 bundletype = btypes.get(bundletype)
1052 if bundletype not in changegroup.bundletypes:
1059 if bundletype not in changegroup.bundletypes:
1053 raise util.Abort(_('unknown bundle type specified with --type'))
1060 raise util.Abort(_('unknown bundle type specified with --type'))
1054
1061
1055 if opts.get('all'):
1062 if opts.get('all'):
1056 base = ['null']
1063 base = ['null']
1057 else:
1064 else:
1058 base = scmutil.revrange(repo, opts.get('base'))
1065 base = scmutil.revrange(repo, opts.get('base'))
1059 if base:
1066 if base:
1060 if dest:
1067 if dest:
1061 raise util.Abort(_("--base is incompatible with specifying "
1068 raise util.Abort(_("--base is incompatible with specifying "
1062 "a destination"))
1069 "a destination"))
1063 common = [repo.lookup(rev) for rev in base]
1070 common = [repo.lookup(rev) for rev in base]
1064 heads = revs and map(repo.lookup, revs) or revs
1071 heads = revs and map(repo.lookup, revs) or revs
1065 cg = repo.getbundle('bundle', heads=heads, common=common)
1072 cg = repo.getbundle('bundle', heads=heads, common=common)
1066 outgoing = None
1073 outgoing = None
1067 else:
1074 else:
1068 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1075 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1069 dest, branches = hg.parseurl(dest, opts.get('branch'))
1076 dest, branches = hg.parseurl(dest, opts.get('branch'))
1070 other = hg.peer(repo, opts, dest)
1077 other = hg.peer(repo, opts, dest)
1071 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1078 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1072 heads = revs and map(repo.lookup, revs) or revs
1079 heads = revs and map(repo.lookup, revs) or revs
1073 outgoing = discovery.findcommonoutgoing(repo, other,
1080 outgoing = discovery.findcommonoutgoing(repo, other,
1074 onlyheads=heads,
1081 onlyheads=heads,
1075 force=opts.get('force'),
1082 force=opts.get('force'),
1076 portable=True)
1083 portable=True)
1077 cg = repo.getlocalbundle('bundle', outgoing)
1084 cg = repo.getlocalbundle('bundle', outgoing)
1078 if not cg:
1085 if not cg:
1079 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1086 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1080 return 1
1087 return 1
1081
1088
1082 changegroup.writebundle(cg, fname, bundletype)
1089 changegroup.writebundle(cg, fname, bundletype)
1083
1090
1084 @command('cat',
1091 @command('cat',
1085 [('o', 'output', '',
1092 [('o', 'output', '',
1086 _('print output to file with formatted name'), _('FORMAT')),
1093 _('print output to file with formatted name'), _('FORMAT')),
1087 ('r', 'rev', '', _('print the given revision'), _('REV')),
1094 ('r', 'rev', '', _('print the given revision'), _('REV')),
1088 ('', 'decode', None, _('apply any matching decode filter')),
1095 ('', 'decode', None, _('apply any matching decode filter')),
1089 ] + walkopts,
1096 ] + walkopts,
1090 _('[OPTION]... FILE...'))
1097 _('[OPTION]... FILE...'))
1091 def cat(ui, repo, file1, *pats, **opts):
1098 def cat(ui, repo, file1, *pats, **opts):
1092 """output the current or given revision of files
1099 """output the current or given revision of files
1093
1100
1094 Print the specified files as they were at the given revision. If
1101 Print the specified files as they were at the given revision. If
1095 no revision is given, the parent of the working directory is used,
1102 no revision is given, the parent of the working directory is used,
1096 or tip if no revision is checked out.
1103 or tip if no revision is checked out.
1097
1104
1098 Output may be to a file, in which case the name of the file is
1105 Output may be to a file, in which case the name of the file is
1099 given using a format string. The formatting rules are the same as
1106 given using a format string. The formatting rules are the same as
1100 for the export command, with the following additions:
1107 for the export command, with the following additions:
1101
1108
1102 :``%s``: basename of file being printed
1109 :``%s``: basename of file being printed
1103 :``%d``: dirname of file being printed, or '.' if in repository root
1110 :``%d``: dirname of file being printed, or '.' if in repository root
1104 :``%p``: root-relative path name of file being printed
1111 :``%p``: root-relative path name of file being printed
1105
1112
1106 Returns 0 on success.
1113 Returns 0 on success.
1107 """
1114 """
1108 ctx = scmutil.revsingle(repo, opts.get('rev'))
1115 ctx = scmutil.revsingle(repo, opts.get('rev'))
1109 err = 1
1116 err = 1
1110 m = scmutil.match(ctx, (file1,) + pats, opts)
1117 m = scmutil.match(ctx, (file1,) + pats, opts)
1111 for abs in ctx.walk(m):
1118 for abs in ctx.walk(m):
1112 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1119 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1113 pathname=abs)
1120 pathname=abs)
1114 data = ctx[abs].data()
1121 data = ctx[abs].data()
1115 if opts.get('decode'):
1122 if opts.get('decode'):
1116 data = repo.wwritedata(abs, data)
1123 data = repo.wwritedata(abs, data)
1117 fp.write(data)
1124 fp.write(data)
1118 fp.close()
1125 fp.close()
1119 err = 0
1126 err = 0
1120 return err
1127 return err
1121
1128
1122 @command('^clone',
1129 @command('^clone',
1123 [('U', 'noupdate', None,
1130 [('U', 'noupdate', None,
1124 _('the clone will include an empty working copy (only a repository)')),
1131 _('the clone will include an empty working copy (only a repository)')),
1125 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1132 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1126 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1133 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1127 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1134 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1128 ('', 'pull', None, _('use pull protocol to copy metadata')),
1135 ('', 'pull', None, _('use pull protocol to copy metadata')),
1129 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1136 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1130 ] + remoteopts,
1137 ] + remoteopts,
1131 _('[OPTION]... SOURCE [DEST]'))
1138 _('[OPTION]... SOURCE [DEST]'))
1132 def clone(ui, source, dest=None, **opts):
1139 def clone(ui, source, dest=None, **opts):
1133 """make a copy of an existing repository
1140 """make a copy of an existing repository
1134
1141
1135 Create a copy of an existing repository in a new directory.
1142 Create a copy of an existing repository in a new directory.
1136
1143
1137 If no destination directory name is specified, it defaults to the
1144 If no destination directory name is specified, it defaults to the
1138 basename of the source.
1145 basename of the source.
1139
1146
1140 The location of the source is added to the new repository's
1147 The location of the source is added to the new repository's
1141 ``.hg/hgrc`` file, as the default to be used for future pulls.
1148 ``.hg/hgrc`` file, as the default to be used for future pulls.
1142
1149
1143 Only local paths and ``ssh://`` URLs are supported as
1150 Only local paths and ``ssh://`` URLs are supported as
1144 destinations. For ``ssh://`` destinations, no working directory or
1151 destinations. For ``ssh://`` destinations, no working directory or
1145 ``.hg/hgrc`` will be created on the remote side.
1152 ``.hg/hgrc`` will be created on the remote side.
1146
1153
1147 To pull only a subset of changesets, specify one or more revisions
1154 To pull only a subset of changesets, specify one or more revisions
1148 identifiers with -r/--rev or branches with -b/--branch. The
1155 identifiers with -r/--rev or branches with -b/--branch. The
1149 resulting clone will contain only the specified changesets and
1156 resulting clone will contain only the specified changesets and
1150 their ancestors. These options (or 'clone src#rev dest') imply
1157 their ancestors. These options (or 'clone src#rev dest') imply
1151 --pull, even for local source repositories. Note that specifying a
1158 --pull, even for local source repositories. Note that specifying a
1152 tag will include the tagged changeset but not the changeset
1159 tag will include the tagged changeset but not the changeset
1153 containing the tag.
1160 containing the tag.
1154
1161
1155 If the source repository has a bookmark called '@' set, that
1162 If the source repository has a bookmark called '@' set, that
1156 revision will be checked out in the new repository by default.
1163 revision will be checked out in the new repository by default.
1157
1164
1158 To check out a particular version, use -u/--update, or
1165 To check out a particular version, use -u/--update, or
1159 -U/--noupdate to create a clone with no working directory.
1166 -U/--noupdate to create a clone with no working directory.
1160
1167
1161 .. container:: verbose
1168 .. container:: verbose
1162
1169
1163 For efficiency, hardlinks are used for cloning whenever the
1170 For efficiency, hardlinks are used for cloning whenever the
1164 source and destination are on the same filesystem (note this
1171 source and destination are on the same filesystem (note this
1165 applies only to the repository data, not to the working
1172 applies only to the repository data, not to the working
1166 directory). Some filesystems, such as AFS, implement hardlinking
1173 directory). Some filesystems, such as AFS, implement hardlinking
1167 incorrectly, but do not report errors. In these cases, use the
1174 incorrectly, but do not report errors. In these cases, use the
1168 --pull option to avoid hardlinking.
1175 --pull option to avoid hardlinking.
1169
1176
1170 In some cases, you can clone repositories and the working
1177 In some cases, you can clone repositories and the working
1171 directory using full hardlinks with ::
1178 directory using full hardlinks with ::
1172
1179
1173 $ cp -al REPO REPOCLONE
1180 $ cp -al REPO REPOCLONE
1174
1181
1175 This is the fastest way to clone, but it is not always safe. The
1182 This is the fastest way to clone, but it is not always safe. The
1176 operation is not atomic (making sure REPO is not modified during
1183 operation is not atomic (making sure REPO is not modified during
1177 the operation is up to you) and you have to make sure your
1184 the operation is up to you) and you have to make sure your
1178 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1185 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1179 so). Also, this is not compatible with certain extensions that
1186 so). Also, this is not compatible with certain extensions that
1180 place their metadata under the .hg directory, such as mq.
1187 place their metadata under the .hg directory, such as mq.
1181
1188
1182 Mercurial will update the working directory to the first applicable
1189 Mercurial will update the working directory to the first applicable
1183 revision from this list:
1190 revision from this list:
1184
1191
1185 a) null if -U or the source repository has no changesets
1192 a) null if -U or the source repository has no changesets
1186 b) if -u . and the source repository is local, the first parent of
1193 b) if -u . and the source repository is local, the first parent of
1187 the source repository's working directory
1194 the source repository's working directory
1188 c) the changeset specified with -u (if a branch name, this means the
1195 c) the changeset specified with -u (if a branch name, this means the
1189 latest head of that branch)
1196 latest head of that branch)
1190 d) the changeset specified with -r
1197 d) the changeset specified with -r
1191 e) the tipmost head specified with -b
1198 e) the tipmost head specified with -b
1192 f) the tipmost head specified with the url#branch source syntax
1199 f) the tipmost head specified with the url#branch source syntax
1193 g) the revision marked with the '@' bookmark, if present
1200 g) the revision marked with the '@' bookmark, if present
1194 h) the tipmost head of the default branch
1201 h) the tipmost head of the default branch
1195 i) tip
1202 i) tip
1196
1203
1197 Examples:
1204 Examples:
1198
1205
1199 - clone a remote repository to a new directory named hg/::
1206 - clone a remote repository to a new directory named hg/::
1200
1207
1201 hg clone http://selenic.com/hg
1208 hg clone http://selenic.com/hg
1202
1209
1203 - create a lightweight local clone::
1210 - create a lightweight local clone::
1204
1211
1205 hg clone project/ project-feature/
1212 hg clone project/ project-feature/
1206
1213
1207 - clone from an absolute path on an ssh server (note double-slash)::
1214 - clone from an absolute path on an ssh server (note double-slash)::
1208
1215
1209 hg clone ssh://user@server//home/projects/alpha/
1216 hg clone ssh://user@server//home/projects/alpha/
1210
1217
1211 - do a high-speed clone over a LAN while checking out a
1218 - do a high-speed clone over a LAN while checking out a
1212 specified version::
1219 specified version::
1213
1220
1214 hg clone --uncompressed http://server/repo -u 1.5
1221 hg clone --uncompressed http://server/repo -u 1.5
1215
1222
1216 - create a repository without changesets after a particular revision::
1223 - create a repository without changesets after a particular revision::
1217
1224
1218 hg clone -r 04e544 experimental/ good/
1225 hg clone -r 04e544 experimental/ good/
1219
1226
1220 - clone (and track) a particular named branch::
1227 - clone (and track) a particular named branch::
1221
1228
1222 hg clone http://selenic.com/hg#stable
1229 hg clone http://selenic.com/hg#stable
1223
1230
1224 See :hg:`help urls` for details on specifying URLs.
1231 See :hg:`help urls` for details on specifying URLs.
1225
1232
1226 Returns 0 on success.
1233 Returns 0 on success.
1227 """
1234 """
1228 if opts.get('noupdate') and opts.get('updaterev'):
1235 if opts.get('noupdate') and opts.get('updaterev'):
1229 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1236 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1230
1237
1231 r = hg.clone(ui, opts, source, dest,
1238 r = hg.clone(ui, opts, source, dest,
1232 pull=opts.get('pull'),
1239 pull=opts.get('pull'),
1233 stream=opts.get('uncompressed'),
1240 stream=opts.get('uncompressed'),
1234 rev=opts.get('rev'),
1241 rev=opts.get('rev'),
1235 update=opts.get('updaterev') or not opts.get('noupdate'),
1242 update=opts.get('updaterev') or not opts.get('noupdate'),
1236 branch=opts.get('branch'))
1243 branch=opts.get('branch'))
1237
1244
1238 return r is None
1245 return r is None
1239
1246
1240 @command('^commit|ci',
1247 @command('^commit|ci',
1241 [('A', 'addremove', None,
1248 [('A', 'addremove', None,
1242 _('mark new/missing files as added/removed before committing')),
1249 _('mark new/missing files as added/removed before committing')),
1243 ('', 'close-branch', None,
1250 ('', 'close-branch', None,
1244 _('mark a branch as closed, hiding it from the branch list')),
1251 _('mark a branch as closed, hiding it from the branch list')),
1245 ('', 'amend', None, _('amend the parent of the working dir')),
1252 ('', 'amend', None, _('amend the parent of the working dir')),
1246 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1253 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1247 _('[OPTION]... [FILE]...'))
1254 _('[OPTION]... [FILE]...'))
1248 def commit(ui, repo, *pats, **opts):
1255 def commit(ui, repo, *pats, **opts):
1249 """commit the specified files or all outstanding changes
1256 """commit the specified files or all outstanding changes
1250
1257
1251 Commit changes to the given files into the repository. Unlike a
1258 Commit changes to the given files into the repository. Unlike a
1252 centralized SCM, this operation is a local operation. See
1259 centralized SCM, this operation is a local operation. See
1253 :hg:`push` for a way to actively distribute your changes.
1260 :hg:`push` for a way to actively distribute your changes.
1254
1261
1255 If a list of files is omitted, all changes reported by :hg:`status`
1262 If a list of files is omitted, all changes reported by :hg:`status`
1256 will be committed.
1263 will be committed.
1257
1264
1258 If you are committing the result of a merge, do not provide any
1265 If you are committing the result of a merge, do not provide any
1259 filenames or -I/-X filters.
1266 filenames or -I/-X filters.
1260
1267
1261 If no commit message is specified, Mercurial starts your
1268 If no commit message is specified, Mercurial starts your
1262 configured editor where you can enter a message. In case your
1269 configured editor where you can enter a message. In case your
1263 commit fails, you will find a backup of your message in
1270 commit fails, you will find a backup of your message in
1264 ``.hg/last-message.txt``.
1271 ``.hg/last-message.txt``.
1265
1272
1266 The --amend flag can be used to amend the parent of the
1273 The --amend flag can be used to amend the parent of the
1267 working directory with a new commit that contains the changes
1274 working directory with a new commit that contains the changes
1268 in the parent in addition to those currently reported by :hg:`status`,
1275 in the parent in addition to those currently reported by :hg:`status`,
1269 if there are any. The old commit is stored in a backup bundle in
1276 if there are any. The old commit is stored in a backup bundle in
1270 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1277 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1271 on how to restore it).
1278 on how to restore it).
1272
1279
1273 Message, user and date are taken from the amended commit unless
1280 Message, user and date are taken from the amended commit unless
1274 specified. When a message isn't specified on the command line,
1281 specified. When a message isn't specified on the command line,
1275 the editor will open with the message of the amended commit.
1282 the editor will open with the message of the amended commit.
1276
1283
1277 It is not possible to amend public changesets (see :hg:`help phases`)
1284 It is not possible to amend public changesets (see :hg:`help phases`)
1278 or changesets that have children.
1285 or changesets that have children.
1279
1286
1280 See :hg:`help dates` for a list of formats valid for -d/--date.
1287 See :hg:`help dates` for a list of formats valid for -d/--date.
1281
1288
1282 Returns 0 on success, 1 if nothing changed.
1289 Returns 0 on success, 1 if nothing changed.
1283 """
1290 """
1284 if opts.get('subrepos'):
1291 if opts.get('subrepos'):
1285 # Let --subrepos on the command line override config setting.
1292 # Let --subrepos on the command line override config setting.
1286 ui.setconfig('ui', 'commitsubrepos', True)
1293 ui.setconfig('ui', 'commitsubrepos', True)
1287
1294
1288 extra = {}
1295 extra = {}
1289 if opts.get('close_branch'):
1296 if opts.get('close_branch'):
1290 if repo['.'].node() not in repo.branchheads():
1297 if repo['.'].node() not in repo.branchheads():
1291 # The topo heads set is included in the branch heads set of the
1298 # The topo heads set is included in the branch heads set of the
1292 # current branch, so it's sufficient to test branchheads
1299 # current branch, so it's sufficient to test branchheads
1293 raise util.Abort(_('can only close branch heads'))
1300 raise util.Abort(_('can only close branch heads'))
1294 extra['close'] = 1
1301 extra['close'] = 1
1295
1302
1296 branch = repo[None].branch()
1303 branch = repo[None].branch()
1297 bheads = repo.branchheads(branch)
1304 bheads = repo.branchheads(branch)
1298
1305
1299 if opts.get('amend'):
1306 if opts.get('amend'):
1300 if ui.configbool('ui', 'commitsubrepos'):
1307 if ui.configbool('ui', 'commitsubrepos'):
1301 raise util.Abort(_('cannot amend recursively'))
1308 raise util.Abort(_('cannot amend recursively'))
1302
1309
1303 old = repo['.']
1310 old = repo['.']
1304 if old.phase() == phases.public:
1311 if old.phase() == phases.public:
1305 raise util.Abort(_('cannot amend public changesets'))
1312 raise util.Abort(_('cannot amend public changesets'))
1306 if len(old.parents()) > 1:
1313 if len(old.parents()) > 1:
1307 raise util.Abort(_('cannot amend merge changesets'))
1314 raise util.Abort(_('cannot amend merge changesets'))
1308 if len(repo[None].parents()) > 1:
1315 if len(repo[None].parents()) > 1:
1309 raise util.Abort(_('cannot amend while merging'))
1316 raise util.Abort(_('cannot amend while merging'))
1310 if (not obsolete._enabled) and old.children():
1317 if (not obsolete._enabled) and old.children():
1311 raise util.Abort(_('cannot amend changeset with children'))
1318 raise util.Abort(_('cannot amend changeset with children'))
1312
1319
1313 e = cmdutil.commiteditor
1320 e = cmdutil.commiteditor
1314 if opts.get('force_editor'):
1321 if opts.get('force_editor'):
1315 e = cmdutil.commitforceeditor
1322 e = cmdutil.commitforceeditor
1316
1323
1317 def commitfunc(ui, repo, message, match, opts):
1324 def commitfunc(ui, repo, message, match, opts):
1318 editor = e
1325 editor = e
1319 # message contains text from -m or -l, if it's empty,
1326 # message contains text from -m or -l, if it's empty,
1320 # open the editor with the old message
1327 # open the editor with the old message
1321 if not message:
1328 if not message:
1322 message = old.description()
1329 message = old.description()
1323 editor = cmdutil.commitforceeditor
1330 editor = cmdutil.commitforceeditor
1324 return repo.commit(message,
1331 return repo.commit(message,
1325 opts.get('user') or old.user(),
1332 opts.get('user') or old.user(),
1326 opts.get('date') or old.date(),
1333 opts.get('date') or old.date(),
1327 match,
1334 match,
1328 editor=editor,
1335 editor=editor,
1329 extra=extra)
1336 extra=extra)
1330
1337
1331 current = repo._bookmarkcurrent
1338 current = repo._bookmarkcurrent
1332 marks = old.bookmarks()
1339 marks = old.bookmarks()
1333 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1340 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1334 if node == old.node():
1341 if node == old.node():
1335 ui.status(_("nothing changed\n"))
1342 ui.status(_("nothing changed\n"))
1336 return 1
1343 return 1
1337 elif marks:
1344 elif marks:
1338 ui.debug('moving bookmarks %r from %s to %s\n' %
1345 ui.debug('moving bookmarks %r from %s to %s\n' %
1339 (marks, old.hex(), hex(node)))
1346 (marks, old.hex(), hex(node)))
1340 newmarks = repo._bookmarks
1347 newmarks = repo._bookmarks
1341 for bm in marks:
1348 for bm in marks:
1342 newmarks[bm] = node
1349 newmarks[bm] = node
1343 if bm == current:
1350 if bm == current:
1344 bookmarks.setcurrent(repo, bm)
1351 bookmarks.setcurrent(repo, bm)
1345 newmarks.write()
1352 newmarks.write()
1346 else:
1353 else:
1347 e = cmdutil.commiteditor
1354 e = cmdutil.commiteditor
1348 if opts.get('force_editor'):
1355 if opts.get('force_editor'):
1349 e = cmdutil.commitforceeditor
1356 e = cmdutil.commitforceeditor
1350
1357
1351 def commitfunc(ui, repo, message, match, opts):
1358 def commitfunc(ui, repo, message, match, opts):
1352 return repo.commit(message, opts.get('user'), opts.get('date'),
1359 return repo.commit(message, opts.get('user'), opts.get('date'),
1353 match, editor=e, extra=extra)
1360 match, editor=e, extra=extra)
1354
1361
1355 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1362 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1356
1363
1357 if not node:
1364 if not node:
1358 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1365 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1359 if stat[3]:
1366 if stat[3]:
1360 ui.status(_("nothing changed (%d missing files, see "
1367 ui.status(_("nothing changed (%d missing files, see "
1361 "'hg status')\n") % len(stat[3]))
1368 "'hg status')\n") % len(stat[3]))
1362 else:
1369 else:
1363 ui.status(_("nothing changed\n"))
1370 ui.status(_("nothing changed\n"))
1364 return 1
1371 return 1
1365
1372
1366 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1373 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1367
1374
1368 @command('copy|cp',
1375 @command('copy|cp',
1369 [('A', 'after', None, _('record a copy that has already occurred')),
1376 [('A', 'after', None, _('record a copy that has already occurred')),
1370 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1377 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1371 ] + walkopts + dryrunopts,
1378 ] + walkopts + dryrunopts,
1372 _('[OPTION]... [SOURCE]... DEST'))
1379 _('[OPTION]... [SOURCE]... DEST'))
1373 def copy(ui, repo, *pats, **opts):
1380 def copy(ui, repo, *pats, **opts):
1374 """mark files as copied for the next commit
1381 """mark files as copied for the next commit
1375
1382
1376 Mark dest as having copies of source files. If dest is a
1383 Mark dest as having copies of source files. If dest is a
1377 directory, copies are put in that directory. If dest is a file,
1384 directory, copies are put in that directory. If dest is a file,
1378 the source must be a single file.
1385 the source must be a single file.
1379
1386
1380 By default, this command copies the contents of files as they
1387 By default, this command copies the contents of files as they
1381 exist in the working directory. If invoked with -A/--after, the
1388 exist in the working directory. If invoked with -A/--after, the
1382 operation is recorded, but no copying is performed.
1389 operation is recorded, but no copying is performed.
1383
1390
1384 This command takes effect with the next commit. To undo a copy
1391 This command takes effect with the next commit. To undo a copy
1385 before that, see :hg:`revert`.
1392 before that, see :hg:`revert`.
1386
1393
1387 Returns 0 on success, 1 if errors are encountered.
1394 Returns 0 on success, 1 if errors are encountered.
1388 """
1395 """
1389 wlock = repo.wlock(False)
1396 wlock = repo.wlock(False)
1390 try:
1397 try:
1391 return cmdutil.copy(ui, repo, pats, opts)
1398 return cmdutil.copy(ui, repo, pats, opts)
1392 finally:
1399 finally:
1393 wlock.release()
1400 wlock.release()
1394
1401
1395 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1402 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1396 def debugancestor(ui, repo, *args):
1403 def debugancestor(ui, repo, *args):
1397 """find the ancestor revision of two revisions in a given index"""
1404 """find the ancestor revision of two revisions in a given index"""
1398 if len(args) == 3:
1405 if len(args) == 3:
1399 index, rev1, rev2 = args
1406 index, rev1, rev2 = args
1400 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1407 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1401 lookup = r.lookup
1408 lookup = r.lookup
1402 elif len(args) == 2:
1409 elif len(args) == 2:
1403 if not repo:
1410 if not repo:
1404 raise util.Abort(_("there is no Mercurial repository here "
1411 raise util.Abort(_("there is no Mercurial repository here "
1405 "(.hg not found)"))
1412 "(.hg not found)"))
1406 rev1, rev2 = args
1413 rev1, rev2 = args
1407 r = repo.changelog
1414 r = repo.changelog
1408 lookup = repo.lookup
1415 lookup = repo.lookup
1409 else:
1416 else:
1410 raise util.Abort(_('either two or three arguments required'))
1417 raise util.Abort(_('either two or three arguments required'))
1411 a = r.ancestor(lookup(rev1), lookup(rev2))
1418 a = r.ancestor(lookup(rev1), lookup(rev2))
1412 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1419 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1413
1420
1414 @command('debugbuilddag',
1421 @command('debugbuilddag',
1415 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1422 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1416 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1423 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1417 ('n', 'new-file', None, _('add new file at each rev'))],
1424 ('n', 'new-file', None, _('add new file at each rev'))],
1418 _('[OPTION]... [TEXT]'))
1425 _('[OPTION]... [TEXT]'))
1419 def debugbuilddag(ui, repo, text=None,
1426 def debugbuilddag(ui, repo, text=None,
1420 mergeable_file=False,
1427 mergeable_file=False,
1421 overwritten_file=False,
1428 overwritten_file=False,
1422 new_file=False):
1429 new_file=False):
1423 """builds a repo with a given DAG from scratch in the current empty repo
1430 """builds a repo with a given DAG from scratch in the current empty repo
1424
1431
1425 The description of the DAG is read from stdin if not given on the
1432 The description of the DAG is read from stdin if not given on the
1426 command line.
1433 command line.
1427
1434
1428 Elements:
1435 Elements:
1429
1436
1430 - "+n" is a linear run of n nodes based on the current default parent
1437 - "+n" is a linear run of n nodes based on the current default parent
1431 - "." is a single node based on the current default parent
1438 - "." is a single node based on the current default parent
1432 - "$" resets the default parent to null (implied at the start);
1439 - "$" resets the default parent to null (implied at the start);
1433 otherwise the default parent is always the last node created
1440 otherwise the default parent is always the last node created
1434 - "<p" sets the default parent to the backref p
1441 - "<p" sets the default parent to the backref p
1435 - "*p" is a fork at parent p, which is a backref
1442 - "*p" is a fork at parent p, which is a backref
1436 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1443 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1437 - "/p2" is a merge of the preceding node and p2
1444 - "/p2" is a merge of the preceding node and p2
1438 - ":tag" defines a local tag for the preceding node
1445 - ":tag" defines a local tag for the preceding node
1439 - "@branch" sets the named branch for subsequent nodes
1446 - "@branch" sets the named branch for subsequent nodes
1440 - "#...\\n" is a comment up to the end of the line
1447 - "#...\\n" is a comment up to the end of the line
1441
1448
1442 Whitespace between the above elements is ignored.
1449 Whitespace between the above elements is ignored.
1443
1450
1444 A backref is either
1451 A backref is either
1445
1452
1446 - a number n, which references the node curr-n, where curr is the current
1453 - a number n, which references the node curr-n, where curr is the current
1447 node, or
1454 node, or
1448 - the name of a local tag you placed earlier using ":tag", or
1455 - the name of a local tag you placed earlier using ":tag", or
1449 - empty to denote the default parent.
1456 - empty to denote the default parent.
1450
1457
1451 All string valued-elements are either strictly alphanumeric, or must
1458 All string valued-elements are either strictly alphanumeric, or must
1452 be enclosed in double quotes ("..."), with "\\" as escape character.
1459 be enclosed in double quotes ("..."), with "\\" as escape character.
1453 """
1460 """
1454
1461
1455 if text is None:
1462 if text is None:
1456 ui.status(_("reading DAG from stdin\n"))
1463 ui.status(_("reading DAG from stdin\n"))
1457 text = ui.fin.read()
1464 text = ui.fin.read()
1458
1465
1459 cl = repo.changelog
1466 cl = repo.changelog
1460 if len(cl) > 0:
1467 if len(cl) > 0:
1461 raise util.Abort(_('repository is not empty'))
1468 raise util.Abort(_('repository is not empty'))
1462
1469
1463 # determine number of revs in DAG
1470 # determine number of revs in DAG
1464 total = 0
1471 total = 0
1465 for type, data in dagparser.parsedag(text):
1472 for type, data in dagparser.parsedag(text):
1466 if type == 'n':
1473 if type == 'n':
1467 total += 1
1474 total += 1
1468
1475
1469 if mergeable_file:
1476 if mergeable_file:
1470 linesperrev = 2
1477 linesperrev = 2
1471 # make a file with k lines per rev
1478 # make a file with k lines per rev
1472 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1479 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1473 initialmergedlines.append("")
1480 initialmergedlines.append("")
1474
1481
1475 tags = []
1482 tags = []
1476
1483
1477 lock = tr = None
1484 lock = tr = None
1478 try:
1485 try:
1479 lock = repo.lock()
1486 lock = repo.lock()
1480 tr = repo.transaction("builddag")
1487 tr = repo.transaction("builddag")
1481
1488
1482 at = -1
1489 at = -1
1483 atbranch = 'default'
1490 atbranch = 'default'
1484 nodeids = []
1491 nodeids = []
1485 id = 0
1492 id = 0
1486 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1493 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1487 for type, data in dagparser.parsedag(text):
1494 for type, data in dagparser.parsedag(text):
1488 if type == 'n':
1495 if type == 'n':
1489 ui.note(('node %s\n' % str(data)))
1496 ui.note(('node %s\n' % str(data)))
1490 id, ps = data
1497 id, ps = data
1491
1498
1492 files = []
1499 files = []
1493 fctxs = {}
1500 fctxs = {}
1494
1501
1495 p2 = None
1502 p2 = None
1496 if mergeable_file:
1503 if mergeable_file:
1497 fn = "mf"
1504 fn = "mf"
1498 p1 = repo[ps[0]]
1505 p1 = repo[ps[0]]
1499 if len(ps) > 1:
1506 if len(ps) > 1:
1500 p2 = repo[ps[1]]
1507 p2 = repo[ps[1]]
1501 pa = p1.ancestor(p2)
1508 pa = p1.ancestor(p2)
1502 base, local, other = [x[fn].data() for x in (pa, p1,
1509 base, local, other = [x[fn].data() for x in (pa, p1,
1503 p2)]
1510 p2)]
1504 m3 = simplemerge.Merge3Text(base, local, other)
1511 m3 = simplemerge.Merge3Text(base, local, other)
1505 ml = [l.strip() for l in m3.merge_lines()]
1512 ml = [l.strip() for l in m3.merge_lines()]
1506 ml.append("")
1513 ml.append("")
1507 elif at > 0:
1514 elif at > 0:
1508 ml = p1[fn].data().split("\n")
1515 ml = p1[fn].data().split("\n")
1509 else:
1516 else:
1510 ml = initialmergedlines
1517 ml = initialmergedlines
1511 ml[id * linesperrev] += " r%i" % id
1518 ml[id * linesperrev] += " r%i" % id
1512 mergedtext = "\n".join(ml)
1519 mergedtext = "\n".join(ml)
1513 files.append(fn)
1520 files.append(fn)
1514 fctxs[fn] = context.memfilectx(fn, mergedtext)
1521 fctxs[fn] = context.memfilectx(fn, mergedtext)
1515
1522
1516 if overwritten_file:
1523 if overwritten_file:
1517 fn = "of"
1524 fn = "of"
1518 files.append(fn)
1525 files.append(fn)
1519 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1526 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1520
1527
1521 if new_file:
1528 if new_file:
1522 fn = "nf%i" % id
1529 fn = "nf%i" % id
1523 files.append(fn)
1530 files.append(fn)
1524 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1525 if len(ps) > 1:
1532 if len(ps) > 1:
1526 if not p2:
1533 if not p2:
1527 p2 = repo[ps[1]]
1534 p2 = repo[ps[1]]
1528 for fn in p2:
1535 for fn in p2:
1529 if fn.startswith("nf"):
1536 if fn.startswith("nf"):
1530 files.append(fn)
1537 files.append(fn)
1531 fctxs[fn] = p2[fn]
1538 fctxs[fn] = p2[fn]
1532
1539
1533 def fctxfn(repo, cx, path):
1540 def fctxfn(repo, cx, path):
1534 return fctxs.get(path)
1541 return fctxs.get(path)
1535
1542
1536 if len(ps) == 0 or ps[0] < 0:
1543 if len(ps) == 0 or ps[0] < 0:
1537 pars = [None, None]
1544 pars = [None, None]
1538 elif len(ps) == 1:
1545 elif len(ps) == 1:
1539 pars = [nodeids[ps[0]], None]
1546 pars = [nodeids[ps[0]], None]
1540 else:
1547 else:
1541 pars = [nodeids[p] for p in ps]
1548 pars = [nodeids[p] for p in ps]
1542 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1549 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1543 date=(id, 0),
1550 date=(id, 0),
1544 user="debugbuilddag",
1551 user="debugbuilddag",
1545 extra={'branch': atbranch})
1552 extra={'branch': atbranch})
1546 nodeid = repo.commitctx(cx)
1553 nodeid = repo.commitctx(cx)
1547 nodeids.append(nodeid)
1554 nodeids.append(nodeid)
1548 at = id
1555 at = id
1549 elif type == 'l':
1556 elif type == 'l':
1550 id, name = data
1557 id, name = data
1551 ui.note(('tag %s\n' % name))
1558 ui.note(('tag %s\n' % name))
1552 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1559 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1553 elif type == 'a':
1560 elif type == 'a':
1554 ui.note(('branch %s\n' % data))
1561 ui.note(('branch %s\n' % data))
1555 atbranch = data
1562 atbranch = data
1556 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1563 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1557 tr.close()
1564 tr.close()
1558
1565
1559 if tags:
1566 if tags:
1560 repo.opener.write("localtags", "".join(tags))
1567 repo.opener.write("localtags", "".join(tags))
1561 finally:
1568 finally:
1562 ui.progress(_('building'), None)
1569 ui.progress(_('building'), None)
1563 release(tr, lock)
1570 release(tr, lock)
1564
1571
1565 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1572 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1566 def debugbundle(ui, bundlepath, all=None, **opts):
1573 def debugbundle(ui, bundlepath, all=None, **opts):
1567 """lists the contents of a bundle"""
1574 """lists the contents of a bundle"""
1568 f = hg.openpath(ui, bundlepath)
1575 f = hg.openpath(ui, bundlepath)
1569 try:
1576 try:
1570 gen = changegroup.readbundle(f, bundlepath)
1577 gen = changegroup.readbundle(f, bundlepath)
1571 if all:
1578 if all:
1572 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1579 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1573
1580
1574 def showchunks(named):
1581 def showchunks(named):
1575 ui.write("\n%s\n" % named)
1582 ui.write("\n%s\n" % named)
1576 chain = None
1583 chain = None
1577 while True:
1584 while True:
1578 chunkdata = gen.deltachunk(chain)
1585 chunkdata = gen.deltachunk(chain)
1579 if not chunkdata:
1586 if not chunkdata:
1580 break
1587 break
1581 node = chunkdata['node']
1588 node = chunkdata['node']
1582 p1 = chunkdata['p1']
1589 p1 = chunkdata['p1']
1583 p2 = chunkdata['p2']
1590 p2 = chunkdata['p2']
1584 cs = chunkdata['cs']
1591 cs = chunkdata['cs']
1585 deltabase = chunkdata['deltabase']
1592 deltabase = chunkdata['deltabase']
1586 delta = chunkdata['delta']
1593 delta = chunkdata['delta']
1587 ui.write("%s %s %s %s %s %s\n" %
1594 ui.write("%s %s %s %s %s %s\n" %
1588 (hex(node), hex(p1), hex(p2),
1595 (hex(node), hex(p1), hex(p2),
1589 hex(cs), hex(deltabase), len(delta)))
1596 hex(cs), hex(deltabase), len(delta)))
1590 chain = node
1597 chain = node
1591
1598
1592 chunkdata = gen.changelogheader()
1599 chunkdata = gen.changelogheader()
1593 showchunks("changelog")
1600 showchunks("changelog")
1594 chunkdata = gen.manifestheader()
1601 chunkdata = gen.manifestheader()
1595 showchunks("manifest")
1602 showchunks("manifest")
1596 while True:
1603 while True:
1597 chunkdata = gen.filelogheader()
1604 chunkdata = gen.filelogheader()
1598 if not chunkdata:
1605 if not chunkdata:
1599 break
1606 break
1600 fname = chunkdata['filename']
1607 fname = chunkdata['filename']
1601 showchunks(fname)
1608 showchunks(fname)
1602 else:
1609 else:
1603 chunkdata = gen.changelogheader()
1610 chunkdata = gen.changelogheader()
1604 chain = None
1611 chain = None
1605 while True:
1612 while True:
1606 chunkdata = gen.deltachunk(chain)
1613 chunkdata = gen.deltachunk(chain)
1607 if not chunkdata:
1614 if not chunkdata:
1608 break
1615 break
1609 node = chunkdata['node']
1616 node = chunkdata['node']
1610 ui.write("%s\n" % hex(node))
1617 ui.write("%s\n" % hex(node))
1611 chain = node
1618 chain = node
1612 finally:
1619 finally:
1613 f.close()
1620 f.close()
1614
1621
1615 @command('debugcheckstate', [], '')
1622 @command('debugcheckstate', [], '')
1616 def debugcheckstate(ui, repo):
1623 def debugcheckstate(ui, repo):
1617 """validate the correctness of the current dirstate"""
1624 """validate the correctness of the current dirstate"""
1618 parent1, parent2 = repo.dirstate.parents()
1625 parent1, parent2 = repo.dirstate.parents()
1619 m1 = repo[parent1].manifest()
1626 m1 = repo[parent1].manifest()
1620 m2 = repo[parent2].manifest()
1627 m2 = repo[parent2].manifest()
1621 errors = 0
1628 errors = 0
1622 for f in repo.dirstate:
1629 for f in repo.dirstate:
1623 state = repo.dirstate[f]
1630 state = repo.dirstate[f]
1624 if state in "nr" and f not in m1:
1631 if state in "nr" and f not in m1:
1625 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1632 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1626 errors += 1
1633 errors += 1
1627 if state in "a" and f in m1:
1634 if state in "a" and f in m1:
1628 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1635 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1629 errors += 1
1636 errors += 1
1630 if state in "m" and f not in m1 and f not in m2:
1637 if state in "m" and f not in m1 and f not in m2:
1631 ui.warn(_("%s in state %s, but not in either manifest\n") %
1638 ui.warn(_("%s in state %s, but not in either manifest\n") %
1632 (f, state))
1639 (f, state))
1633 errors += 1
1640 errors += 1
1634 for f in m1:
1641 for f in m1:
1635 state = repo.dirstate[f]
1642 state = repo.dirstate[f]
1636 if state not in "nrm":
1643 if state not in "nrm":
1637 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1644 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1638 errors += 1
1645 errors += 1
1639 if errors:
1646 if errors:
1640 error = _(".hg/dirstate inconsistent with current parent's manifest")
1647 error = _(".hg/dirstate inconsistent with current parent's manifest")
1641 raise util.Abort(error)
1648 raise util.Abort(error)
1642
1649
1643 @command('debugcommands', [], _('[COMMAND]'))
1650 @command('debugcommands', [], _('[COMMAND]'))
1644 def debugcommands(ui, cmd='', *args):
1651 def debugcommands(ui, cmd='', *args):
1645 """list all available commands and options"""
1652 """list all available commands and options"""
1646 for cmd, vals in sorted(table.iteritems()):
1653 for cmd, vals in sorted(table.iteritems()):
1647 cmd = cmd.split('|')[0].strip('^')
1654 cmd = cmd.split('|')[0].strip('^')
1648 opts = ', '.join([i[1] for i in vals[1]])
1655 opts = ', '.join([i[1] for i in vals[1]])
1649 ui.write('%s: %s\n' % (cmd, opts))
1656 ui.write('%s: %s\n' % (cmd, opts))
1650
1657
1651 @command('debugcomplete',
1658 @command('debugcomplete',
1652 [('o', 'options', None, _('show the command options'))],
1659 [('o', 'options', None, _('show the command options'))],
1653 _('[-o] CMD'))
1660 _('[-o] CMD'))
1654 def debugcomplete(ui, cmd='', **opts):
1661 def debugcomplete(ui, cmd='', **opts):
1655 """returns the completion list associated with the given command"""
1662 """returns the completion list associated with the given command"""
1656
1663
1657 if opts.get('options'):
1664 if opts.get('options'):
1658 options = []
1665 options = []
1659 otables = [globalopts]
1666 otables = [globalopts]
1660 if cmd:
1667 if cmd:
1661 aliases, entry = cmdutil.findcmd(cmd, table, False)
1668 aliases, entry = cmdutil.findcmd(cmd, table, False)
1662 otables.append(entry[1])
1669 otables.append(entry[1])
1663 for t in otables:
1670 for t in otables:
1664 for o in t:
1671 for o in t:
1665 if "(DEPRECATED)" in o[3]:
1672 if "(DEPRECATED)" in o[3]:
1666 continue
1673 continue
1667 if o[0]:
1674 if o[0]:
1668 options.append('-%s' % o[0])
1675 options.append('-%s' % o[0])
1669 options.append('--%s' % o[1])
1676 options.append('--%s' % o[1])
1670 ui.write("%s\n" % "\n".join(options))
1677 ui.write("%s\n" % "\n".join(options))
1671 return
1678 return
1672
1679
1673 cmdlist = cmdutil.findpossible(cmd, table)
1680 cmdlist = cmdutil.findpossible(cmd, table)
1674 if ui.verbose:
1681 if ui.verbose:
1675 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1682 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1676 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1683 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1677
1684
1678 @command('debugdag',
1685 @command('debugdag',
1679 [('t', 'tags', None, _('use tags as labels')),
1686 [('t', 'tags', None, _('use tags as labels')),
1680 ('b', 'branches', None, _('annotate with branch names')),
1687 ('b', 'branches', None, _('annotate with branch names')),
1681 ('', 'dots', None, _('use dots for runs')),
1688 ('', 'dots', None, _('use dots for runs')),
1682 ('s', 'spaces', None, _('separate elements by spaces'))],
1689 ('s', 'spaces', None, _('separate elements by spaces'))],
1683 _('[OPTION]... [FILE [REV]...]'))
1690 _('[OPTION]... [FILE [REV]...]'))
1684 def debugdag(ui, repo, file_=None, *revs, **opts):
1691 def debugdag(ui, repo, file_=None, *revs, **opts):
1685 """format the changelog or an index DAG as a concise textual description
1692 """format the changelog or an index DAG as a concise textual description
1686
1693
1687 If you pass a revlog index, the revlog's DAG is emitted. If you list
1694 If you pass a revlog index, the revlog's DAG is emitted. If you list
1688 revision numbers, they get labeled in the output as rN.
1695 revision numbers, they get labeled in the output as rN.
1689
1696
1690 Otherwise, the changelog DAG of the current repo is emitted.
1697 Otherwise, the changelog DAG of the current repo is emitted.
1691 """
1698 """
1692 spaces = opts.get('spaces')
1699 spaces = opts.get('spaces')
1693 dots = opts.get('dots')
1700 dots = opts.get('dots')
1694 if file_:
1701 if file_:
1695 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1702 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1696 revs = set((int(r) for r in revs))
1703 revs = set((int(r) for r in revs))
1697 def events():
1704 def events():
1698 for r in rlog:
1705 for r in rlog:
1699 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1706 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1700 if p != -1)))
1707 if p != -1)))
1701 if r in revs:
1708 if r in revs:
1702 yield 'l', (r, "r%i" % r)
1709 yield 'l', (r, "r%i" % r)
1703 elif repo:
1710 elif repo:
1704 cl = repo.changelog
1711 cl = repo.changelog
1705 tags = opts.get('tags')
1712 tags = opts.get('tags')
1706 branches = opts.get('branches')
1713 branches = opts.get('branches')
1707 if tags:
1714 if tags:
1708 labels = {}
1715 labels = {}
1709 for l, n in repo.tags().items():
1716 for l, n in repo.tags().items():
1710 labels.setdefault(cl.rev(n), []).append(l)
1717 labels.setdefault(cl.rev(n), []).append(l)
1711 def events():
1718 def events():
1712 b = "default"
1719 b = "default"
1713 for r in cl:
1720 for r in cl:
1714 if branches:
1721 if branches:
1715 newb = cl.read(cl.node(r))[5]['branch']
1722 newb = cl.read(cl.node(r))[5]['branch']
1716 if newb != b:
1723 if newb != b:
1717 yield 'a', newb
1724 yield 'a', newb
1718 b = newb
1725 b = newb
1719 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1726 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1720 if p != -1)))
1727 if p != -1)))
1721 if tags:
1728 if tags:
1722 ls = labels.get(r)
1729 ls = labels.get(r)
1723 if ls:
1730 if ls:
1724 for l in ls:
1731 for l in ls:
1725 yield 'l', (r, l)
1732 yield 'l', (r, l)
1726 else:
1733 else:
1727 raise util.Abort(_('need repo for changelog dag'))
1734 raise util.Abort(_('need repo for changelog dag'))
1728
1735
1729 for line in dagparser.dagtextlines(events(),
1736 for line in dagparser.dagtextlines(events(),
1730 addspaces=spaces,
1737 addspaces=spaces,
1731 wraplabels=True,
1738 wraplabels=True,
1732 wrapannotations=True,
1739 wrapannotations=True,
1733 wrapnonlinear=dots,
1740 wrapnonlinear=dots,
1734 usedots=dots,
1741 usedots=dots,
1735 maxlinewidth=70):
1742 maxlinewidth=70):
1736 ui.write(line)
1743 ui.write(line)
1737 ui.write("\n")
1744 ui.write("\n")
1738
1745
1739 @command('debugdata',
1746 @command('debugdata',
1740 [('c', 'changelog', False, _('open changelog')),
1747 [('c', 'changelog', False, _('open changelog')),
1741 ('m', 'manifest', False, _('open manifest'))],
1748 ('m', 'manifest', False, _('open manifest'))],
1742 _('-c|-m|FILE REV'))
1749 _('-c|-m|FILE REV'))
1743 def debugdata(ui, repo, file_, rev = None, **opts):
1750 def debugdata(ui, repo, file_, rev = None, **opts):
1744 """dump the contents of a data file revision"""
1751 """dump the contents of a data file revision"""
1745 if opts.get('changelog') or opts.get('manifest'):
1752 if opts.get('changelog') or opts.get('manifest'):
1746 file_, rev = None, file_
1753 file_, rev = None, file_
1747 elif rev is None:
1754 elif rev is None:
1748 raise error.CommandError('debugdata', _('invalid arguments'))
1755 raise error.CommandError('debugdata', _('invalid arguments'))
1749 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1756 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1750 try:
1757 try:
1751 ui.write(r.revision(r.lookup(rev)))
1758 ui.write(r.revision(r.lookup(rev)))
1752 except KeyError:
1759 except KeyError:
1753 raise util.Abort(_('invalid revision identifier %s') % rev)
1760 raise util.Abort(_('invalid revision identifier %s') % rev)
1754
1761
1755 @command('debugdate',
1762 @command('debugdate',
1756 [('e', 'extended', None, _('try extended date formats'))],
1763 [('e', 'extended', None, _('try extended date formats'))],
1757 _('[-e] DATE [RANGE]'))
1764 _('[-e] DATE [RANGE]'))
1758 def debugdate(ui, date, range=None, **opts):
1765 def debugdate(ui, date, range=None, **opts):
1759 """parse and display a date"""
1766 """parse and display a date"""
1760 if opts["extended"]:
1767 if opts["extended"]:
1761 d = util.parsedate(date, util.extendeddateformats)
1768 d = util.parsedate(date, util.extendeddateformats)
1762 else:
1769 else:
1763 d = util.parsedate(date)
1770 d = util.parsedate(date)
1764 ui.write(("internal: %s %s\n") % d)
1771 ui.write(("internal: %s %s\n") % d)
1765 ui.write(("standard: %s\n") % util.datestr(d))
1772 ui.write(("standard: %s\n") % util.datestr(d))
1766 if range:
1773 if range:
1767 m = util.matchdate(range)
1774 m = util.matchdate(range)
1768 ui.write(("match: %s\n") % m(d[0]))
1775 ui.write(("match: %s\n") % m(d[0]))
1769
1776
1770 @command('debugdiscovery',
1777 @command('debugdiscovery',
1771 [('', 'old', None, _('use old-style discovery')),
1778 [('', 'old', None, _('use old-style discovery')),
1772 ('', 'nonheads', None,
1779 ('', 'nonheads', None,
1773 _('use old-style discovery with non-heads included')),
1780 _('use old-style discovery with non-heads included')),
1774 ] + remoteopts,
1781 ] + remoteopts,
1775 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1782 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1776 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1783 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1777 """runs the changeset discovery protocol in isolation"""
1784 """runs the changeset discovery protocol in isolation"""
1778 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1785 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1779 opts.get('branch'))
1786 opts.get('branch'))
1780 remote = hg.peer(repo, opts, remoteurl)
1787 remote = hg.peer(repo, opts, remoteurl)
1781 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1788 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1782
1789
1783 # make sure tests are repeatable
1790 # make sure tests are repeatable
1784 random.seed(12323)
1791 random.seed(12323)
1785
1792
1786 def doit(localheads, remoteheads, remote=remote):
1793 def doit(localheads, remoteheads, remote=remote):
1787 if opts.get('old'):
1794 if opts.get('old'):
1788 if localheads:
1795 if localheads:
1789 raise util.Abort('cannot use localheads with old style '
1796 raise util.Abort('cannot use localheads with old style '
1790 'discovery')
1797 'discovery')
1791 if not util.safehasattr(remote, 'branches'):
1798 if not util.safehasattr(remote, 'branches'):
1792 # enable in-client legacy support
1799 # enable in-client legacy support
1793 remote = localrepo.locallegacypeer(remote.local())
1800 remote = localrepo.locallegacypeer(remote.local())
1794 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1801 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1795 force=True)
1802 force=True)
1796 common = set(common)
1803 common = set(common)
1797 if not opts.get('nonheads'):
1804 if not opts.get('nonheads'):
1798 ui.write(("unpruned common: %s\n") %
1805 ui.write(("unpruned common: %s\n") %
1799 " ".join(sorted(short(n) for n in common)))
1806 " ".join(sorted(short(n) for n in common)))
1800 dag = dagutil.revlogdag(repo.changelog)
1807 dag = dagutil.revlogdag(repo.changelog)
1801 all = dag.ancestorset(dag.internalizeall(common))
1808 all = dag.ancestorset(dag.internalizeall(common))
1802 common = dag.externalizeall(dag.headsetofconnecteds(all))
1809 common = dag.externalizeall(dag.headsetofconnecteds(all))
1803 else:
1810 else:
1804 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1811 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1805 common = set(common)
1812 common = set(common)
1806 rheads = set(hds)
1813 rheads = set(hds)
1807 lheads = set(repo.heads())
1814 lheads = set(repo.heads())
1808 ui.write(("common heads: %s\n") %
1815 ui.write(("common heads: %s\n") %
1809 " ".join(sorted(short(n) for n in common)))
1816 " ".join(sorted(short(n) for n in common)))
1810 if lheads <= common:
1817 if lheads <= common:
1811 ui.write(("local is subset\n"))
1818 ui.write(("local is subset\n"))
1812 elif rheads <= common:
1819 elif rheads <= common:
1813 ui.write(("remote is subset\n"))
1820 ui.write(("remote is subset\n"))
1814
1821
1815 serverlogs = opts.get('serverlog')
1822 serverlogs = opts.get('serverlog')
1816 if serverlogs:
1823 if serverlogs:
1817 for filename in serverlogs:
1824 for filename in serverlogs:
1818 logfile = open(filename, 'r')
1825 logfile = open(filename, 'r')
1819 try:
1826 try:
1820 line = logfile.readline()
1827 line = logfile.readline()
1821 while line:
1828 while line:
1822 parts = line.strip().split(';')
1829 parts = line.strip().split(';')
1823 op = parts[1]
1830 op = parts[1]
1824 if op == 'cg':
1831 if op == 'cg':
1825 pass
1832 pass
1826 elif op == 'cgss':
1833 elif op == 'cgss':
1827 doit(parts[2].split(' '), parts[3].split(' '))
1834 doit(parts[2].split(' '), parts[3].split(' '))
1828 elif op == 'unb':
1835 elif op == 'unb':
1829 doit(parts[3].split(' '), parts[2].split(' '))
1836 doit(parts[3].split(' '), parts[2].split(' '))
1830 line = logfile.readline()
1837 line = logfile.readline()
1831 finally:
1838 finally:
1832 logfile.close()
1839 logfile.close()
1833
1840
1834 else:
1841 else:
1835 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1842 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1836 opts.get('remote_head'))
1843 opts.get('remote_head'))
1837 localrevs = opts.get('local_head')
1844 localrevs = opts.get('local_head')
1838 doit(localrevs, remoterevs)
1845 doit(localrevs, remoterevs)
1839
1846
1840 @command('debugfileset',
1847 @command('debugfileset',
1841 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1848 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1842 _('[-r REV] FILESPEC'))
1849 _('[-r REV] FILESPEC'))
1843 def debugfileset(ui, repo, expr, **opts):
1850 def debugfileset(ui, repo, expr, **opts):
1844 '''parse and apply a fileset specification'''
1851 '''parse and apply a fileset specification'''
1845 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1852 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1846 if ui.verbose:
1853 if ui.verbose:
1847 tree = fileset.parse(expr)[0]
1854 tree = fileset.parse(expr)[0]
1848 ui.note(tree, "\n")
1855 ui.note(tree, "\n")
1849
1856
1850 for f in fileset.getfileset(ctx, expr):
1857 for f in fileset.getfileset(ctx, expr):
1851 ui.write("%s\n" % f)
1858 ui.write("%s\n" % f)
1852
1859
1853 @command('debugfsinfo', [], _('[PATH]'))
1860 @command('debugfsinfo', [], _('[PATH]'))
1854 def debugfsinfo(ui, path = "."):
1861 def debugfsinfo(ui, path = "."):
1855 """show information detected about current filesystem"""
1862 """show information detected about current filesystem"""
1856 util.writefile('.debugfsinfo', '')
1863 util.writefile('.debugfsinfo', '')
1857 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1858 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1859 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1866 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1860 and 'yes' or 'no'))
1867 and 'yes' or 'no'))
1861 os.unlink('.debugfsinfo')
1868 os.unlink('.debugfsinfo')
1862
1869
1863 @command('debuggetbundle',
1870 @command('debuggetbundle',
1864 [('H', 'head', [], _('id of head node'), _('ID')),
1871 [('H', 'head', [], _('id of head node'), _('ID')),
1865 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('C', 'common', [], _('id of common node'), _('ID')),
1866 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1867 _('REPO FILE [-H|-C ID]...'))
1874 _('REPO FILE [-H|-C ID]...'))
1868 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1869 """retrieves a bundle from a repo
1876 """retrieves a bundle from a repo
1870
1877
1871 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 Every ID must be a full-length hex node id string. Saves the bundle to the
1872 given file.
1879 given file.
1873 """
1880 """
1874 repo = hg.peer(ui, opts, repopath)
1881 repo = hg.peer(ui, opts, repopath)
1875 if not repo.capable('getbundle'):
1882 if not repo.capable('getbundle'):
1876 raise util.Abort("getbundle() not supported by target repository")
1883 raise util.Abort("getbundle() not supported by target repository")
1877 args = {}
1884 args = {}
1878 if common:
1885 if common:
1879 args['common'] = [bin(s) for s in common]
1886 args['common'] = [bin(s) for s in common]
1880 if head:
1887 if head:
1881 args['heads'] = [bin(s) for s in head]
1888 args['heads'] = [bin(s) for s in head]
1882 bundle = repo.getbundle('debug', **args)
1889 bundle = repo.getbundle('debug', **args)
1883
1890
1884 bundletype = opts.get('type', 'bzip2').lower()
1891 bundletype = opts.get('type', 'bzip2').lower()
1885 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1886 bundletype = btypes.get(bundletype)
1893 bundletype = btypes.get(bundletype)
1887 if bundletype not in changegroup.bundletypes:
1894 if bundletype not in changegroup.bundletypes:
1888 raise util.Abort(_('unknown bundle type specified with --type'))
1895 raise util.Abort(_('unknown bundle type specified with --type'))
1889 changegroup.writebundle(bundle, bundlepath, bundletype)
1896 changegroup.writebundle(bundle, bundlepath, bundletype)
1890
1897
1891 @command('debugignore', [], '')
1898 @command('debugignore', [], '')
1892 def debugignore(ui, repo, *values, **opts):
1899 def debugignore(ui, repo, *values, **opts):
1893 """display the combined ignore pattern"""
1900 """display the combined ignore pattern"""
1894 ignore = repo.dirstate._ignore
1901 ignore = repo.dirstate._ignore
1895 includepat = getattr(ignore, 'includepat', None)
1902 includepat = getattr(ignore, 'includepat', None)
1896 if includepat is not None:
1903 if includepat is not None:
1897 ui.write("%s\n" % includepat)
1904 ui.write("%s\n" % includepat)
1898 else:
1905 else:
1899 raise util.Abort(_("no ignore patterns found"))
1906 raise util.Abort(_("no ignore patterns found"))
1900
1907
1901 @command('debugindex',
1908 @command('debugindex',
1902 [('c', 'changelog', False, _('open changelog')),
1909 [('c', 'changelog', False, _('open changelog')),
1903 ('m', 'manifest', False, _('open manifest')),
1910 ('m', 'manifest', False, _('open manifest')),
1904 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1905 _('[-f FORMAT] -c|-m|FILE'))
1912 _('[-f FORMAT] -c|-m|FILE'))
1906 def debugindex(ui, repo, file_ = None, **opts):
1913 def debugindex(ui, repo, file_ = None, **opts):
1907 """dump the contents of an index file"""
1914 """dump the contents of an index file"""
1908 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1909 format = opts.get('format', 0)
1916 format = opts.get('format', 0)
1910 if format not in (0, 1):
1917 if format not in (0, 1):
1911 raise util.Abort(_("unknown format %d") % format)
1918 raise util.Abort(_("unknown format %d") % format)
1912
1919
1913 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1914 if generaldelta:
1921 if generaldelta:
1915 basehdr = ' delta'
1922 basehdr = ' delta'
1916 else:
1923 else:
1917 basehdr = ' base'
1924 basehdr = ' base'
1918
1925
1919 if format == 0:
1926 if format == 0:
1920 ui.write(" rev offset length " + basehdr + " linkrev"
1927 ui.write(" rev offset length " + basehdr + " linkrev"
1921 " nodeid p1 p2\n")
1928 " nodeid p1 p2\n")
1922 elif format == 1:
1929 elif format == 1:
1923 ui.write(" rev flag offset length"
1930 ui.write(" rev flag offset length"
1924 " size " + basehdr + " link p1 p2"
1931 " size " + basehdr + " link p1 p2"
1925 " nodeid\n")
1932 " nodeid\n")
1926
1933
1927 for i in r:
1934 for i in r:
1928 node = r.node(i)
1935 node = r.node(i)
1929 if generaldelta:
1936 if generaldelta:
1930 base = r.deltaparent(i)
1937 base = r.deltaparent(i)
1931 else:
1938 else:
1932 base = r.chainbase(i)
1939 base = r.chainbase(i)
1933 if format == 0:
1940 if format == 0:
1934 try:
1941 try:
1935 pp = r.parents(node)
1942 pp = r.parents(node)
1936 except Exception:
1943 except Exception:
1937 pp = [nullid, nullid]
1944 pp = [nullid, nullid]
1938 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1939 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 i, r.start(i), r.length(i), base, r.linkrev(i),
1940 short(node), short(pp[0]), short(pp[1])))
1947 short(node), short(pp[0]), short(pp[1])))
1941 elif format == 1:
1948 elif format == 1:
1942 pr = r.parentrevs(i)
1949 pr = r.parentrevs(i)
1943 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1944 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1945 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952 base, r.linkrev(i), pr[0], pr[1], short(node)))
1946
1953
1947 @command('debugindexdot', [], _('FILE'))
1954 @command('debugindexdot', [], _('FILE'))
1948 def debugindexdot(ui, repo, file_):
1955 def debugindexdot(ui, repo, file_):
1949 """dump an index DAG as a graphviz dot file"""
1956 """dump an index DAG as a graphviz dot file"""
1950 r = None
1957 r = None
1951 if repo:
1958 if repo:
1952 filelog = repo.file(file_)
1959 filelog = repo.file(file_)
1953 if len(filelog):
1960 if len(filelog):
1954 r = filelog
1961 r = filelog
1955 if not r:
1962 if not r:
1956 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1957 ui.write(("digraph G {\n"))
1964 ui.write(("digraph G {\n"))
1958 for i in r:
1965 for i in r:
1959 node = r.node(i)
1966 node = r.node(i)
1960 pp = r.parents(node)
1967 pp = r.parents(node)
1961 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1962 if pp[1] != nullid:
1969 if pp[1] != nullid:
1963 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1964 ui.write("}\n")
1971 ui.write("}\n")
1965
1972
1966 @command('debuginstall', [], '')
1973 @command('debuginstall', [], '')
1967 def debuginstall(ui):
1974 def debuginstall(ui):
1968 '''test Mercurial installation
1975 '''test Mercurial installation
1969
1976
1970 Returns 0 on success.
1977 Returns 0 on success.
1971 '''
1978 '''
1972
1979
1973 def writetemp(contents):
1980 def writetemp(contents):
1974 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1975 f = os.fdopen(fd, "wb")
1982 f = os.fdopen(fd, "wb")
1976 f.write(contents)
1983 f.write(contents)
1977 f.close()
1984 f.close()
1978 return name
1985 return name
1979
1986
1980 problems = 0
1987 problems = 0
1981
1988
1982 # encoding
1989 # encoding
1983 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1984 try:
1991 try:
1985 encoding.fromlocal("test")
1992 encoding.fromlocal("test")
1986 except util.Abort, inst:
1993 except util.Abort, inst:
1987 ui.write(" %s\n" % inst)
1994 ui.write(" %s\n" % inst)
1988 ui.write(_(" (check that your locale is properly set)\n"))
1995 ui.write(_(" (check that your locale is properly set)\n"))
1989 problems += 1
1996 problems += 1
1990
1997
1991 # Python lib
1998 # Python lib
1992 ui.status(_("checking Python lib (%s)...\n")
1999 ui.status(_("checking Python lib (%s)...\n")
1993 % os.path.dirname(os.__file__))
2000 % os.path.dirname(os.__file__))
1994
2001
1995 # compiled modules
2002 # compiled modules
1996 ui.status(_("checking installed modules (%s)...\n")
2003 ui.status(_("checking installed modules (%s)...\n")
1997 % os.path.dirname(__file__))
2004 % os.path.dirname(__file__))
1998 try:
2005 try:
1999 import bdiff, mpatch, base85, osutil
2006 import bdiff, mpatch, base85, osutil
2000 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2007 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2001 except Exception, inst:
2008 except Exception, inst:
2002 ui.write(" %s\n" % inst)
2009 ui.write(" %s\n" % inst)
2003 ui.write(_(" One or more extensions could not be found"))
2010 ui.write(_(" One or more extensions could not be found"))
2004 ui.write(_(" (check that you compiled the extensions)\n"))
2011 ui.write(_(" (check that you compiled the extensions)\n"))
2005 problems += 1
2012 problems += 1
2006
2013
2007 # templates
2014 # templates
2008 import templater
2015 import templater
2009 p = templater.templatepath()
2016 p = templater.templatepath()
2010 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2017 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2011 try:
2018 try:
2012 templater.templater(templater.templatepath("map-cmdline.default"))
2019 templater.templater(templater.templatepath("map-cmdline.default"))
2013 except Exception, inst:
2020 except Exception, inst:
2014 ui.write(" %s\n" % inst)
2021 ui.write(" %s\n" % inst)
2015 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2022 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2016 problems += 1
2023 problems += 1
2017
2024
2018 # editor
2025 # editor
2019 ui.status(_("checking commit editor...\n"))
2026 ui.status(_("checking commit editor...\n"))
2020 editor = ui.geteditor()
2027 editor = ui.geteditor()
2021 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2028 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2022 if not cmdpath:
2029 if not cmdpath:
2023 if editor == 'vi':
2030 if editor == 'vi':
2024 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2031 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2025 ui.write(_(" (specify a commit editor in your configuration"
2032 ui.write(_(" (specify a commit editor in your configuration"
2026 " file)\n"))
2033 " file)\n"))
2027 else:
2034 else:
2028 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2035 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2029 ui.write(_(" (specify a commit editor in your configuration"
2036 ui.write(_(" (specify a commit editor in your configuration"
2030 " file)\n"))
2037 " file)\n"))
2031 problems += 1
2038 problems += 1
2032
2039
2033 # check username
2040 # check username
2034 ui.status(_("checking username...\n"))
2041 ui.status(_("checking username...\n"))
2035 try:
2042 try:
2036 ui.username()
2043 ui.username()
2037 except util.Abort, e:
2044 except util.Abort, e:
2038 ui.write(" %s\n" % e)
2045 ui.write(" %s\n" % e)
2039 ui.write(_(" (specify a username in your configuration file)\n"))
2046 ui.write(_(" (specify a username in your configuration file)\n"))
2040 problems += 1
2047 problems += 1
2041
2048
2042 if not problems:
2049 if not problems:
2043 ui.status(_("no problems detected\n"))
2050 ui.status(_("no problems detected\n"))
2044 else:
2051 else:
2045 ui.write(_("%s problems detected,"
2052 ui.write(_("%s problems detected,"
2046 " please check your install!\n") % problems)
2053 " please check your install!\n") % problems)
2047
2054
2048 return problems
2055 return problems
2049
2056
2050 @command('debugknown', [], _('REPO ID...'))
2057 @command('debugknown', [], _('REPO ID...'))
2051 def debugknown(ui, repopath, *ids, **opts):
2058 def debugknown(ui, repopath, *ids, **opts):
2052 """test whether node ids are known to a repo
2059 """test whether node ids are known to a repo
2053
2060
2054 Every ID must be a full-length hex node id string. Returns a list of 0s
2061 Every ID must be a full-length hex node id string. Returns a list of 0s
2055 and 1s indicating unknown/known.
2062 and 1s indicating unknown/known.
2056 """
2063 """
2057 repo = hg.peer(ui, opts, repopath)
2064 repo = hg.peer(ui, opts, repopath)
2058 if not repo.capable('known'):
2065 if not repo.capable('known'):
2059 raise util.Abort("known() not supported by target repository")
2066 raise util.Abort("known() not supported by target repository")
2060 flags = repo.known([bin(s) for s in ids])
2067 flags = repo.known([bin(s) for s in ids])
2061 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2068 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2062
2069
2063 @command('debugobsolete',
2070 @command('debugobsolete',
2064 [('', 'flags', 0, _('markers flag')),
2071 [('', 'flags', 0, _('markers flag')),
2065 ] + commitopts2,
2072 ] + commitopts2,
2066 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2073 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2067 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2074 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2068 """create arbitrary obsolete marker
2075 """create arbitrary obsolete marker
2069
2076
2070 With no arguments it it display the list obsolescence marker."""
2077 With no arguments it it display the list obsolescence marker."""
2071 def parsenodeid(s):
2078 def parsenodeid(s):
2072 try:
2079 try:
2073 # We do not use revsingle/revrange functions here to accept
2080 # We do not use revsingle/revrange functions here to accept
2074 # arbitrary node identifiers, possibly not present in the
2081 # arbitrary node identifiers, possibly not present in the
2075 # local repository.
2082 # local repository.
2076 n = bin(s)
2083 n = bin(s)
2077 if len(n) != len(nullid):
2084 if len(n) != len(nullid):
2078 raise TypeError()
2085 raise TypeError()
2079 return n
2086 return n
2080 except TypeError:
2087 except TypeError:
2081 raise util.Abort('changeset references must be full hexadecimal '
2088 raise util.Abort('changeset references must be full hexadecimal '
2082 'node identifiers')
2089 'node identifiers')
2083
2090
2084 if precursor is not None:
2091 if precursor is not None:
2085 metadata = {}
2092 metadata = {}
2086 if 'date' in opts:
2093 if 'date' in opts:
2087 metadata['date'] = opts['date']
2094 metadata['date'] = opts['date']
2088 metadata['user'] = opts['user'] or ui.username()
2095 metadata['user'] = opts['user'] or ui.username()
2089 succs = tuple(parsenodeid(succ) for succ in successors)
2096 succs = tuple(parsenodeid(succ) for succ in successors)
2090 l = repo.lock()
2097 l = repo.lock()
2091 try:
2098 try:
2092 tr = repo.transaction('debugobsolete')
2099 tr = repo.transaction('debugobsolete')
2093 try:
2100 try:
2094 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2101 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2095 opts['flags'], metadata)
2102 opts['flags'], metadata)
2096 tr.close()
2103 tr.close()
2097 finally:
2104 finally:
2098 tr.release()
2105 tr.release()
2099 finally:
2106 finally:
2100 l.release()
2107 l.release()
2101 else:
2108 else:
2102 for m in obsolete.allmarkers(repo):
2109 for m in obsolete.allmarkers(repo):
2103 ui.write(hex(m.precnode()))
2110 ui.write(hex(m.precnode()))
2104 for repl in m.succnodes():
2111 for repl in m.succnodes():
2105 ui.write(' ')
2112 ui.write(' ')
2106 ui.write(hex(repl))
2113 ui.write(hex(repl))
2107 ui.write(' %X ' % m._data[2])
2114 ui.write(' %X ' % m._data[2])
2108 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2115 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2109 sorted(m.metadata().items()))))
2116 sorted(m.metadata().items()))))
2110 ui.write('\n')
2117 ui.write('\n')
2111
2118
2112 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2119 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2113 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2120 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2114 '''access the pushkey key/value protocol
2121 '''access the pushkey key/value protocol
2115
2122
2116 With two args, list the keys in the given namespace.
2123 With two args, list the keys in the given namespace.
2117
2124
2118 With five args, set a key to new if it currently is set to old.
2125 With five args, set a key to new if it currently is set to old.
2119 Reports success or failure.
2126 Reports success or failure.
2120 '''
2127 '''
2121
2128
2122 target = hg.peer(ui, {}, repopath)
2129 target = hg.peer(ui, {}, repopath)
2123 if keyinfo:
2130 if keyinfo:
2124 key, old, new = keyinfo
2131 key, old, new = keyinfo
2125 r = target.pushkey(namespace, key, old, new)
2132 r = target.pushkey(namespace, key, old, new)
2126 ui.status(str(r) + '\n')
2133 ui.status(str(r) + '\n')
2127 return not r
2134 return not r
2128 else:
2135 else:
2129 for k, v in sorted(target.listkeys(namespace).iteritems()):
2136 for k, v in sorted(target.listkeys(namespace).iteritems()):
2130 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2137 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2131 v.encode('string-escape')))
2138 v.encode('string-escape')))
2132
2139
2133 @command('debugpvec', [], _('A B'))
2140 @command('debugpvec', [], _('A B'))
2134 def debugpvec(ui, repo, a, b=None):
2141 def debugpvec(ui, repo, a, b=None):
2135 ca = scmutil.revsingle(repo, a)
2142 ca = scmutil.revsingle(repo, a)
2136 cb = scmutil.revsingle(repo, b)
2143 cb = scmutil.revsingle(repo, b)
2137 pa = pvec.ctxpvec(ca)
2144 pa = pvec.ctxpvec(ca)
2138 pb = pvec.ctxpvec(cb)
2145 pb = pvec.ctxpvec(cb)
2139 if pa == pb:
2146 if pa == pb:
2140 rel = "="
2147 rel = "="
2141 elif pa > pb:
2148 elif pa > pb:
2142 rel = ">"
2149 rel = ">"
2143 elif pa < pb:
2150 elif pa < pb:
2144 rel = "<"
2151 rel = "<"
2145 elif pa | pb:
2152 elif pa | pb:
2146 rel = "|"
2153 rel = "|"
2147 ui.write(_("a: %s\n") % pa)
2154 ui.write(_("a: %s\n") % pa)
2148 ui.write(_("b: %s\n") % pb)
2155 ui.write(_("b: %s\n") % pb)
2149 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2156 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2150 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2157 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2151 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2158 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2152 pa.distance(pb), rel))
2159 pa.distance(pb), rel))
2153
2160
2154 @command('debugrebuildstate',
2161 @command('debugrebuildstate',
2155 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2162 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2156 _('[-r REV] [REV]'))
2163 _('[-r REV] [REV]'))
2157 def debugrebuildstate(ui, repo, rev="tip"):
2164 def debugrebuildstate(ui, repo, rev="tip"):
2158 """rebuild the dirstate as it would look like for the given revision"""
2165 """rebuild the dirstate as it would look like for the given revision"""
2159 ctx = scmutil.revsingle(repo, rev)
2166 ctx = scmutil.revsingle(repo, rev)
2160 wlock = repo.wlock()
2167 wlock = repo.wlock()
2161 try:
2168 try:
2162 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2169 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2163 finally:
2170 finally:
2164 wlock.release()
2171 wlock.release()
2165
2172
2166 @command('debugrename',
2173 @command('debugrename',
2167 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2174 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2168 _('[-r REV] FILE'))
2175 _('[-r REV] FILE'))
2169 def debugrename(ui, repo, file1, *pats, **opts):
2176 def debugrename(ui, repo, file1, *pats, **opts):
2170 """dump rename information"""
2177 """dump rename information"""
2171
2178
2172 ctx = scmutil.revsingle(repo, opts.get('rev'))
2179 ctx = scmutil.revsingle(repo, opts.get('rev'))
2173 m = scmutil.match(ctx, (file1,) + pats, opts)
2180 m = scmutil.match(ctx, (file1,) + pats, opts)
2174 for abs in ctx.walk(m):
2181 for abs in ctx.walk(m):
2175 fctx = ctx[abs]
2182 fctx = ctx[abs]
2176 o = fctx.filelog().renamed(fctx.filenode())
2183 o = fctx.filelog().renamed(fctx.filenode())
2177 rel = m.rel(abs)
2184 rel = m.rel(abs)
2178 if o:
2185 if o:
2179 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2186 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2180 else:
2187 else:
2181 ui.write(_("%s not renamed\n") % rel)
2188 ui.write(_("%s not renamed\n") % rel)
2182
2189
2183 @command('debugrevlog',
2190 @command('debugrevlog',
2184 [('c', 'changelog', False, _('open changelog')),
2191 [('c', 'changelog', False, _('open changelog')),
2185 ('m', 'manifest', False, _('open manifest')),
2192 ('m', 'manifest', False, _('open manifest')),
2186 ('d', 'dump', False, _('dump index data'))],
2193 ('d', 'dump', False, _('dump index data'))],
2187 _('-c|-m|FILE'))
2194 _('-c|-m|FILE'))
2188 def debugrevlog(ui, repo, file_ = None, **opts):
2195 def debugrevlog(ui, repo, file_ = None, **opts):
2189 """show data and statistics about a revlog"""
2196 """show data and statistics about a revlog"""
2190 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2197 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2191
2198
2192 if opts.get("dump"):
2199 if opts.get("dump"):
2193 numrevs = len(r)
2200 numrevs = len(r)
2194 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2201 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2195 " rawsize totalsize compression heads\n")
2202 " rawsize totalsize compression heads\n")
2196 ts = 0
2203 ts = 0
2197 heads = set()
2204 heads = set()
2198 for rev in xrange(numrevs):
2205 for rev in xrange(numrevs):
2199 dbase = r.deltaparent(rev)
2206 dbase = r.deltaparent(rev)
2200 if dbase == -1:
2207 if dbase == -1:
2201 dbase = rev
2208 dbase = rev
2202 cbase = r.chainbase(rev)
2209 cbase = r.chainbase(rev)
2203 p1, p2 = r.parentrevs(rev)
2210 p1, p2 = r.parentrevs(rev)
2204 rs = r.rawsize(rev)
2211 rs = r.rawsize(rev)
2205 ts = ts + rs
2212 ts = ts + rs
2206 heads -= set(r.parentrevs(rev))
2213 heads -= set(r.parentrevs(rev))
2207 heads.add(rev)
2214 heads.add(rev)
2208 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2215 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2209 (rev, p1, p2, r.start(rev), r.end(rev),
2216 (rev, p1, p2, r.start(rev), r.end(rev),
2210 r.start(dbase), r.start(cbase),
2217 r.start(dbase), r.start(cbase),
2211 r.start(p1), r.start(p2),
2218 r.start(p1), r.start(p2),
2212 rs, ts, ts / r.end(rev), len(heads)))
2219 rs, ts, ts / r.end(rev), len(heads)))
2213 return 0
2220 return 0
2214
2221
2215 v = r.version
2222 v = r.version
2216 format = v & 0xFFFF
2223 format = v & 0xFFFF
2217 flags = []
2224 flags = []
2218 gdelta = False
2225 gdelta = False
2219 if v & revlog.REVLOGNGINLINEDATA:
2226 if v & revlog.REVLOGNGINLINEDATA:
2220 flags.append('inline')
2227 flags.append('inline')
2221 if v & revlog.REVLOGGENERALDELTA:
2228 if v & revlog.REVLOGGENERALDELTA:
2222 gdelta = True
2229 gdelta = True
2223 flags.append('generaldelta')
2230 flags.append('generaldelta')
2224 if not flags:
2231 if not flags:
2225 flags = ['(none)']
2232 flags = ['(none)']
2226
2233
2227 nummerges = 0
2234 nummerges = 0
2228 numfull = 0
2235 numfull = 0
2229 numprev = 0
2236 numprev = 0
2230 nump1 = 0
2237 nump1 = 0
2231 nump2 = 0
2238 nump2 = 0
2232 numother = 0
2239 numother = 0
2233 nump1prev = 0
2240 nump1prev = 0
2234 nump2prev = 0
2241 nump2prev = 0
2235 chainlengths = []
2242 chainlengths = []
2236
2243
2237 datasize = [None, 0, 0L]
2244 datasize = [None, 0, 0L]
2238 fullsize = [None, 0, 0L]
2245 fullsize = [None, 0, 0L]
2239 deltasize = [None, 0, 0L]
2246 deltasize = [None, 0, 0L]
2240
2247
2241 def addsize(size, l):
2248 def addsize(size, l):
2242 if l[0] is None or size < l[0]:
2249 if l[0] is None or size < l[0]:
2243 l[0] = size
2250 l[0] = size
2244 if size > l[1]:
2251 if size > l[1]:
2245 l[1] = size
2252 l[1] = size
2246 l[2] += size
2253 l[2] += size
2247
2254
2248 numrevs = len(r)
2255 numrevs = len(r)
2249 for rev in xrange(numrevs):
2256 for rev in xrange(numrevs):
2250 p1, p2 = r.parentrevs(rev)
2257 p1, p2 = r.parentrevs(rev)
2251 delta = r.deltaparent(rev)
2258 delta = r.deltaparent(rev)
2252 if format > 0:
2259 if format > 0:
2253 addsize(r.rawsize(rev), datasize)
2260 addsize(r.rawsize(rev), datasize)
2254 if p2 != nullrev:
2261 if p2 != nullrev:
2255 nummerges += 1
2262 nummerges += 1
2256 size = r.length(rev)
2263 size = r.length(rev)
2257 if delta == nullrev:
2264 if delta == nullrev:
2258 chainlengths.append(0)
2265 chainlengths.append(0)
2259 numfull += 1
2266 numfull += 1
2260 addsize(size, fullsize)
2267 addsize(size, fullsize)
2261 else:
2268 else:
2262 chainlengths.append(chainlengths[delta] + 1)
2269 chainlengths.append(chainlengths[delta] + 1)
2263 addsize(size, deltasize)
2270 addsize(size, deltasize)
2264 if delta == rev - 1:
2271 if delta == rev - 1:
2265 numprev += 1
2272 numprev += 1
2266 if delta == p1:
2273 if delta == p1:
2267 nump1prev += 1
2274 nump1prev += 1
2268 elif delta == p2:
2275 elif delta == p2:
2269 nump2prev += 1
2276 nump2prev += 1
2270 elif delta == p1:
2277 elif delta == p1:
2271 nump1 += 1
2278 nump1 += 1
2272 elif delta == p2:
2279 elif delta == p2:
2273 nump2 += 1
2280 nump2 += 1
2274 elif delta != nullrev:
2281 elif delta != nullrev:
2275 numother += 1
2282 numother += 1
2276
2283
2277 # Adjust size min value for empty cases
2284 # Adjust size min value for empty cases
2278 for size in (datasize, fullsize, deltasize):
2285 for size in (datasize, fullsize, deltasize):
2279 if size[0] is None:
2286 if size[0] is None:
2280 size[0] = 0
2287 size[0] = 0
2281
2288
2282 numdeltas = numrevs - numfull
2289 numdeltas = numrevs - numfull
2283 numoprev = numprev - nump1prev - nump2prev
2290 numoprev = numprev - nump1prev - nump2prev
2284 totalrawsize = datasize[2]
2291 totalrawsize = datasize[2]
2285 datasize[2] /= numrevs
2292 datasize[2] /= numrevs
2286 fulltotal = fullsize[2]
2293 fulltotal = fullsize[2]
2287 fullsize[2] /= numfull
2294 fullsize[2] /= numfull
2288 deltatotal = deltasize[2]
2295 deltatotal = deltasize[2]
2289 if numrevs - numfull > 0:
2296 if numrevs - numfull > 0:
2290 deltasize[2] /= numrevs - numfull
2297 deltasize[2] /= numrevs - numfull
2291 totalsize = fulltotal + deltatotal
2298 totalsize = fulltotal + deltatotal
2292 avgchainlen = sum(chainlengths) / numrevs
2299 avgchainlen = sum(chainlengths) / numrevs
2293 compratio = totalrawsize / totalsize
2300 compratio = totalrawsize / totalsize
2294
2301
2295 basedfmtstr = '%%%dd\n'
2302 basedfmtstr = '%%%dd\n'
2296 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2303 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2297
2304
2298 def dfmtstr(max):
2305 def dfmtstr(max):
2299 return basedfmtstr % len(str(max))
2306 return basedfmtstr % len(str(max))
2300 def pcfmtstr(max, padding=0):
2307 def pcfmtstr(max, padding=0):
2301 return basepcfmtstr % (len(str(max)), ' ' * padding)
2308 return basepcfmtstr % (len(str(max)), ' ' * padding)
2302
2309
2303 def pcfmt(value, total):
2310 def pcfmt(value, total):
2304 return (value, 100 * float(value) / total)
2311 return (value, 100 * float(value) / total)
2305
2312
2306 ui.write(('format : %d\n') % format)
2313 ui.write(('format : %d\n') % format)
2307 ui.write(('flags : %s\n') % ', '.join(flags))
2314 ui.write(('flags : %s\n') % ', '.join(flags))
2308
2315
2309 ui.write('\n')
2316 ui.write('\n')
2310 fmt = pcfmtstr(totalsize)
2317 fmt = pcfmtstr(totalsize)
2311 fmt2 = dfmtstr(totalsize)
2318 fmt2 = dfmtstr(totalsize)
2312 ui.write(('revisions : ') + fmt2 % numrevs)
2319 ui.write(('revisions : ') + fmt2 % numrevs)
2313 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2320 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2314 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2321 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2315 ui.write(('revisions : ') + fmt2 % numrevs)
2322 ui.write(('revisions : ') + fmt2 % numrevs)
2316 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2323 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2317 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2324 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2318 ui.write(('revision size : ') + fmt2 % totalsize)
2325 ui.write(('revision size : ') + fmt2 % totalsize)
2319 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2326 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2320 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2327 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2321
2328
2322 ui.write('\n')
2329 ui.write('\n')
2323 fmt = dfmtstr(max(avgchainlen, compratio))
2330 fmt = dfmtstr(max(avgchainlen, compratio))
2324 ui.write(('avg chain length : ') + fmt % avgchainlen)
2331 ui.write(('avg chain length : ') + fmt % avgchainlen)
2325 ui.write(('compression ratio : ') + fmt % compratio)
2332 ui.write(('compression ratio : ') + fmt % compratio)
2326
2333
2327 if format > 0:
2334 if format > 0:
2328 ui.write('\n')
2335 ui.write('\n')
2329 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2336 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2330 % tuple(datasize))
2337 % tuple(datasize))
2331 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2338 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2332 % tuple(fullsize))
2339 % tuple(fullsize))
2333 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2340 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2334 % tuple(deltasize))
2341 % tuple(deltasize))
2335
2342
2336 if numdeltas > 0:
2343 if numdeltas > 0:
2337 ui.write('\n')
2344 ui.write('\n')
2338 fmt = pcfmtstr(numdeltas)
2345 fmt = pcfmtstr(numdeltas)
2339 fmt2 = pcfmtstr(numdeltas, 4)
2346 fmt2 = pcfmtstr(numdeltas, 4)
2340 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2347 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2341 if numprev > 0:
2348 if numprev > 0:
2342 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2349 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2343 numprev))
2350 numprev))
2344 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2351 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2345 numprev))
2352 numprev))
2346 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2353 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2347 numprev))
2354 numprev))
2348 if gdelta:
2355 if gdelta:
2349 ui.write(('deltas against p1 : ')
2356 ui.write(('deltas against p1 : ')
2350 + fmt % pcfmt(nump1, numdeltas))
2357 + fmt % pcfmt(nump1, numdeltas))
2351 ui.write(('deltas against p2 : ')
2358 ui.write(('deltas against p2 : ')
2352 + fmt % pcfmt(nump2, numdeltas))
2359 + fmt % pcfmt(nump2, numdeltas))
2353 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2360 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2354 numdeltas))
2361 numdeltas))
2355
2362
2356 @command('debugrevspec', [], ('REVSPEC'))
2363 @command('debugrevspec', [], ('REVSPEC'))
2357 def debugrevspec(ui, repo, expr):
2364 def debugrevspec(ui, repo, expr):
2358 """parse and apply a revision specification
2365 """parse and apply a revision specification
2359
2366
2360 Use --verbose to print the parsed tree before and after aliases
2367 Use --verbose to print the parsed tree before and after aliases
2361 expansion.
2368 expansion.
2362 """
2369 """
2363 if ui.verbose:
2370 if ui.verbose:
2364 tree = revset.parse(expr)[0]
2371 tree = revset.parse(expr)[0]
2365 ui.note(revset.prettyformat(tree), "\n")
2372 ui.note(revset.prettyformat(tree), "\n")
2366 newtree = revset.findaliases(ui, tree)
2373 newtree = revset.findaliases(ui, tree)
2367 if newtree != tree:
2374 if newtree != tree:
2368 ui.note(revset.prettyformat(newtree), "\n")
2375 ui.note(revset.prettyformat(newtree), "\n")
2369 func = revset.match(ui, expr)
2376 func = revset.match(ui, expr)
2370 for c in func(repo, range(len(repo))):
2377 for c in func(repo, range(len(repo))):
2371 ui.write("%s\n" % c)
2378 ui.write("%s\n" % c)
2372
2379
2373 @command('debugsetparents', [], _('REV1 [REV2]'))
2380 @command('debugsetparents', [], _('REV1 [REV2]'))
2374 def debugsetparents(ui, repo, rev1, rev2=None):
2381 def debugsetparents(ui, repo, rev1, rev2=None):
2375 """manually set the parents of the current working directory
2382 """manually set the parents of the current working directory
2376
2383
2377 This is useful for writing repository conversion tools, but should
2384 This is useful for writing repository conversion tools, but should
2378 be used with care.
2385 be used with care.
2379
2386
2380 Returns 0 on success.
2387 Returns 0 on success.
2381 """
2388 """
2382
2389
2383 r1 = scmutil.revsingle(repo, rev1).node()
2390 r1 = scmutil.revsingle(repo, rev1).node()
2384 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2391 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2385
2392
2386 wlock = repo.wlock()
2393 wlock = repo.wlock()
2387 try:
2394 try:
2388 repo.setparents(r1, r2)
2395 repo.setparents(r1, r2)
2389 finally:
2396 finally:
2390 wlock.release()
2397 wlock.release()
2391
2398
2392 @command('debugstate',
2399 @command('debugstate',
2393 [('', 'nodates', None, _('do not display the saved mtime')),
2400 [('', 'nodates', None, _('do not display the saved mtime')),
2394 ('', 'datesort', None, _('sort by saved mtime'))],
2401 ('', 'datesort', None, _('sort by saved mtime'))],
2395 _('[OPTION]...'))
2402 _('[OPTION]...'))
2396 def debugstate(ui, repo, nodates=None, datesort=None):
2403 def debugstate(ui, repo, nodates=None, datesort=None):
2397 """show the contents of the current dirstate"""
2404 """show the contents of the current dirstate"""
2398 timestr = ""
2405 timestr = ""
2399 showdate = not nodates
2406 showdate = not nodates
2400 if datesort:
2407 if datesort:
2401 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2408 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2402 else:
2409 else:
2403 keyfunc = None # sort by filename
2410 keyfunc = None # sort by filename
2404 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2411 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2405 if showdate:
2412 if showdate:
2406 if ent[3] == -1:
2413 if ent[3] == -1:
2407 # Pad or slice to locale representation
2414 # Pad or slice to locale representation
2408 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2415 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2409 time.localtime(0)))
2416 time.localtime(0)))
2410 timestr = 'unset'
2417 timestr = 'unset'
2411 timestr = (timestr[:locale_len] +
2418 timestr = (timestr[:locale_len] +
2412 ' ' * (locale_len - len(timestr)))
2419 ' ' * (locale_len - len(timestr)))
2413 else:
2420 else:
2414 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2421 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2415 time.localtime(ent[3]))
2422 time.localtime(ent[3]))
2416 if ent[1] & 020000:
2423 if ent[1] & 020000:
2417 mode = 'lnk'
2424 mode = 'lnk'
2418 else:
2425 else:
2419 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2426 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2420 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2427 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2421 for f in repo.dirstate.copies():
2428 for f in repo.dirstate.copies():
2422 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2429 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2423
2430
2424 @command('debugsub',
2431 @command('debugsub',
2425 [('r', 'rev', '',
2432 [('r', 'rev', '',
2426 _('revision to check'), _('REV'))],
2433 _('revision to check'), _('REV'))],
2427 _('[-r REV] [REV]'))
2434 _('[-r REV] [REV]'))
2428 def debugsub(ui, repo, rev=None):
2435 def debugsub(ui, repo, rev=None):
2429 ctx = scmutil.revsingle(repo, rev, None)
2436 ctx = scmutil.revsingle(repo, rev, None)
2430 for k, v in sorted(ctx.substate.items()):
2437 for k, v in sorted(ctx.substate.items()):
2431 ui.write(('path %s\n') % k)
2438 ui.write(('path %s\n') % k)
2432 ui.write((' source %s\n') % v[0])
2439 ui.write((' source %s\n') % v[0])
2433 ui.write((' revision %s\n') % v[1])
2440 ui.write((' revision %s\n') % v[1])
2434
2441
2435 @command('debugsuccessorssets',
2442 @command('debugsuccessorssets',
2436 [],
2443 [],
2437 _('[REV]'))
2444 _('[REV]'))
2438 def debugsuccessorssets(ui, repo, *revs):
2445 def debugsuccessorssets(ui, repo, *revs):
2439 """show set of successors for revision
2446 """show set of successors for revision
2440
2447
2441 A successors set of changeset A is a consistent group of revisions that
2448 A successors set of changeset A is a consistent group of revisions that
2442 succeed A. It contains non-obsolete changesets only.
2449 succeed A. It contains non-obsolete changesets only.
2443
2450
2444 In most cases a changeset A has a single successors set containing a single
2451 In most cases a changeset A has a single successors set containing a single
2445 successor (changeset A replaced by A').
2452 successor (changeset A replaced by A').
2446
2453
2447 A changeset that is made obsolete with no successors are called "pruned".
2454 A changeset that is made obsolete with no successors are called "pruned".
2448 Such changesets have no successors sets at all.
2455 Such changesets have no successors sets at all.
2449
2456
2450 A changeset that has been "split" will have a successors set containing
2457 A changeset that has been "split" will have a successors set containing
2451 more than one successor.
2458 more than one successor.
2452
2459
2453 A changeset that has been rewritten in multiple different ways is called
2460 A changeset that has been rewritten in multiple different ways is called
2454 "divergent". Such changesets have multiple successor sets (each of which
2461 "divergent". Such changesets have multiple successor sets (each of which
2455 may also be split, i.e. have multiple successors).
2462 may also be split, i.e. have multiple successors).
2456
2463
2457 Results are displayed as follows::
2464 Results are displayed as follows::
2458
2465
2459 <rev1>
2466 <rev1>
2460 <successors-1A>
2467 <successors-1A>
2461 <rev2>
2468 <rev2>
2462 <successors-2A>
2469 <successors-2A>
2463 <successors-2B1> <successors-2B2> <successors-2B3>
2470 <successors-2B1> <successors-2B2> <successors-2B3>
2464
2471
2465 Here rev2 has two possible (i.e. divergent) successors sets. The first
2472 Here rev2 has two possible (i.e. divergent) successors sets. The first
2466 holds one element, whereas the second holds three (i.e. the changeset has
2473 holds one element, whereas the second holds three (i.e. the changeset has
2467 been split).
2474 been split).
2468 """
2475 """
2469 # passed to successorssets caching computation from one call to another
2476 # passed to successorssets caching computation from one call to another
2470 cache = {}
2477 cache = {}
2471 ctx2str = str
2478 ctx2str = str
2472 node2str = short
2479 node2str = short
2473 if ui.debug():
2480 if ui.debug():
2474 def ctx2str(ctx):
2481 def ctx2str(ctx):
2475 return ctx.hex()
2482 return ctx.hex()
2476 node2str = hex
2483 node2str = hex
2477 for rev in scmutil.revrange(repo, revs):
2484 for rev in scmutil.revrange(repo, revs):
2478 ctx = repo[rev]
2485 ctx = repo[rev]
2479 ui.write('%s\n'% ctx2str(ctx))
2486 ui.write('%s\n'% ctx2str(ctx))
2480 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2487 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2481 if succsset:
2488 if succsset:
2482 ui.write(' ')
2489 ui.write(' ')
2483 ui.write(node2str(succsset[0]))
2490 ui.write(node2str(succsset[0]))
2484 for node in succsset[1:]:
2491 for node in succsset[1:]:
2485 ui.write(' ')
2492 ui.write(' ')
2486 ui.write(node2str(node))
2493 ui.write(node2str(node))
2487 ui.write('\n')
2494 ui.write('\n')
2488
2495
2489 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2496 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2490 def debugwalk(ui, repo, *pats, **opts):
2497 def debugwalk(ui, repo, *pats, **opts):
2491 """show how files match on given patterns"""
2498 """show how files match on given patterns"""
2492 m = scmutil.match(repo[None], pats, opts)
2499 m = scmutil.match(repo[None], pats, opts)
2493 items = list(repo.walk(m))
2500 items = list(repo.walk(m))
2494 if not items:
2501 if not items:
2495 return
2502 return
2496 f = lambda fn: fn
2503 f = lambda fn: fn
2497 if ui.configbool('ui', 'slash') and os.sep != '/':
2504 if ui.configbool('ui', 'slash') and os.sep != '/':
2498 f = lambda fn: util.normpath(fn)
2505 f = lambda fn: util.normpath(fn)
2499 fmt = 'f %%-%ds %%-%ds %%s' % (
2506 fmt = 'f %%-%ds %%-%ds %%s' % (
2500 max([len(abs) for abs in items]),
2507 max([len(abs) for abs in items]),
2501 max([len(m.rel(abs)) for abs in items]))
2508 max([len(m.rel(abs)) for abs in items]))
2502 for abs in items:
2509 for abs in items:
2503 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2510 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2504 ui.write("%s\n" % line.rstrip())
2511 ui.write("%s\n" % line.rstrip())
2505
2512
2506 @command('debugwireargs',
2513 @command('debugwireargs',
2507 [('', 'three', '', 'three'),
2514 [('', 'three', '', 'three'),
2508 ('', 'four', '', 'four'),
2515 ('', 'four', '', 'four'),
2509 ('', 'five', '', 'five'),
2516 ('', 'five', '', 'five'),
2510 ] + remoteopts,
2517 ] + remoteopts,
2511 _('REPO [OPTIONS]... [ONE [TWO]]'))
2518 _('REPO [OPTIONS]... [ONE [TWO]]'))
2512 def debugwireargs(ui, repopath, *vals, **opts):
2519 def debugwireargs(ui, repopath, *vals, **opts):
2513 repo = hg.peer(ui, opts, repopath)
2520 repo = hg.peer(ui, opts, repopath)
2514 for opt in remoteopts:
2521 for opt in remoteopts:
2515 del opts[opt[1]]
2522 del opts[opt[1]]
2516 args = {}
2523 args = {}
2517 for k, v in opts.iteritems():
2524 for k, v in opts.iteritems():
2518 if v:
2525 if v:
2519 args[k] = v
2526 args[k] = v
2520 # run twice to check that we don't mess up the stream for the next command
2527 # run twice to check that we don't mess up the stream for the next command
2521 res1 = repo.debugwireargs(*vals, **args)
2528 res1 = repo.debugwireargs(*vals, **args)
2522 res2 = repo.debugwireargs(*vals, **args)
2529 res2 = repo.debugwireargs(*vals, **args)
2523 ui.write("%s\n" % res1)
2530 ui.write("%s\n" % res1)
2524 if res1 != res2:
2531 if res1 != res2:
2525 ui.warn("%s\n" % res2)
2532 ui.warn("%s\n" % res2)
2526
2533
2527 @command('^diff',
2534 @command('^diff',
2528 [('r', 'rev', [], _('revision'), _('REV')),
2535 [('r', 'rev', [], _('revision'), _('REV')),
2529 ('c', 'change', '', _('change made by revision'), _('REV'))
2536 ('c', 'change', '', _('change made by revision'), _('REV'))
2530 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2537 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2531 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2538 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2532 def diff(ui, repo, *pats, **opts):
2539 def diff(ui, repo, *pats, **opts):
2533 """diff repository (or selected files)
2540 """diff repository (or selected files)
2534
2541
2535 Show differences between revisions for the specified files.
2542 Show differences between revisions for the specified files.
2536
2543
2537 Differences between files are shown using the unified diff format.
2544 Differences between files are shown using the unified diff format.
2538
2545
2539 .. note::
2546 .. note::
2540 diff may generate unexpected results for merges, as it will
2547 diff may generate unexpected results for merges, as it will
2541 default to comparing against the working directory's first
2548 default to comparing against the working directory's first
2542 parent changeset if no revisions are specified.
2549 parent changeset if no revisions are specified.
2543
2550
2544 When two revision arguments are given, then changes are shown
2551 When two revision arguments are given, then changes are shown
2545 between those revisions. If only one revision is specified then
2552 between those revisions. If only one revision is specified then
2546 that revision is compared to the working directory, and, when no
2553 that revision is compared to the working directory, and, when no
2547 revisions are specified, the working directory files are compared
2554 revisions are specified, the working directory files are compared
2548 to its parent.
2555 to its parent.
2549
2556
2550 Alternatively you can specify -c/--change with a revision to see
2557 Alternatively you can specify -c/--change with a revision to see
2551 the changes in that changeset relative to its first parent.
2558 the changes in that changeset relative to its first parent.
2552
2559
2553 Without the -a/--text option, diff will avoid generating diffs of
2560 Without the -a/--text option, diff will avoid generating diffs of
2554 files it detects as binary. With -a, diff will generate a diff
2561 files it detects as binary. With -a, diff will generate a diff
2555 anyway, probably with undesirable results.
2562 anyway, probably with undesirable results.
2556
2563
2557 Use the -g/--git option to generate diffs in the git extended diff
2564 Use the -g/--git option to generate diffs in the git extended diff
2558 format. For more information, read :hg:`help diffs`.
2565 format. For more information, read :hg:`help diffs`.
2559
2566
2560 .. container:: verbose
2567 .. container:: verbose
2561
2568
2562 Examples:
2569 Examples:
2563
2570
2564 - compare a file in the current working directory to its parent::
2571 - compare a file in the current working directory to its parent::
2565
2572
2566 hg diff foo.c
2573 hg diff foo.c
2567
2574
2568 - compare two historical versions of a directory, with rename info::
2575 - compare two historical versions of a directory, with rename info::
2569
2576
2570 hg diff --git -r 1.0:1.2 lib/
2577 hg diff --git -r 1.0:1.2 lib/
2571
2578
2572 - get change stats relative to the last change on some date::
2579 - get change stats relative to the last change on some date::
2573
2580
2574 hg diff --stat -r "date('may 2')"
2581 hg diff --stat -r "date('may 2')"
2575
2582
2576 - diff all newly-added files that contain a keyword::
2583 - diff all newly-added files that contain a keyword::
2577
2584
2578 hg diff "set:added() and grep(GNU)"
2585 hg diff "set:added() and grep(GNU)"
2579
2586
2580 - compare a revision and its parents::
2587 - compare a revision and its parents::
2581
2588
2582 hg diff -c 9353 # compare against first parent
2589 hg diff -c 9353 # compare against first parent
2583 hg diff -r 9353^:9353 # same using revset syntax
2590 hg diff -r 9353^:9353 # same using revset syntax
2584 hg diff -r 9353^2:9353 # compare against the second parent
2591 hg diff -r 9353^2:9353 # compare against the second parent
2585
2592
2586 Returns 0 on success.
2593 Returns 0 on success.
2587 """
2594 """
2588
2595
2589 revs = opts.get('rev')
2596 revs = opts.get('rev')
2590 change = opts.get('change')
2597 change = opts.get('change')
2591 stat = opts.get('stat')
2598 stat = opts.get('stat')
2592 reverse = opts.get('reverse')
2599 reverse = opts.get('reverse')
2593
2600
2594 if revs and change:
2601 if revs and change:
2595 msg = _('cannot specify --rev and --change at the same time')
2602 msg = _('cannot specify --rev and --change at the same time')
2596 raise util.Abort(msg)
2603 raise util.Abort(msg)
2597 elif change:
2604 elif change:
2598 node2 = scmutil.revsingle(repo, change, None).node()
2605 node2 = scmutil.revsingle(repo, change, None).node()
2599 node1 = repo[node2].p1().node()
2606 node1 = repo[node2].p1().node()
2600 else:
2607 else:
2601 node1, node2 = scmutil.revpair(repo, revs)
2608 node1, node2 = scmutil.revpair(repo, revs)
2602
2609
2603 if reverse:
2610 if reverse:
2604 node1, node2 = node2, node1
2611 node1, node2 = node2, node1
2605
2612
2606 diffopts = patch.diffopts(ui, opts)
2613 diffopts = patch.diffopts(ui, opts)
2607 m = scmutil.match(repo[node2], pats, opts)
2614 m = scmutil.match(repo[node2], pats, opts)
2608 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2615 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2609 listsubrepos=opts.get('subrepos'))
2616 listsubrepos=opts.get('subrepos'))
2610
2617
2611 @command('^export',
2618 @command('^export',
2612 [('o', 'output', '',
2619 [('o', 'output', '',
2613 _('print output to file with formatted name'), _('FORMAT')),
2620 _('print output to file with formatted name'), _('FORMAT')),
2614 ('', 'switch-parent', None, _('diff against the second parent')),
2621 ('', 'switch-parent', None, _('diff against the second parent')),
2615 ('r', 'rev', [], _('revisions to export'), _('REV')),
2622 ('r', 'rev', [], _('revisions to export'), _('REV')),
2616 ] + diffopts,
2623 ] + diffopts,
2617 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2624 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2618 def export(ui, repo, *changesets, **opts):
2625 def export(ui, repo, *changesets, **opts):
2619 """dump the header and diffs for one or more changesets
2626 """dump the header and diffs for one or more changesets
2620
2627
2621 Print the changeset header and diffs for one or more revisions.
2628 Print the changeset header and diffs for one or more revisions.
2622
2629
2623 The information shown in the changeset header is: author, date,
2630 The information shown in the changeset header is: author, date,
2624 branch name (if non-default), changeset hash, parent(s) and commit
2631 branch name (if non-default), changeset hash, parent(s) and commit
2625 comment.
2632 comment.
2626
2633
2627 .. note::
2634 .. note::
2628 export may generate unexpected diff output for merge
2635 export may generate unexpected diff output for merge
2629 changesets, as it will compare the merge changeset against its
2636 changesets, as it will compare the merge changeset against its
2630 first parent only.
2637 first parent only.
2631
2638
2632 Output may be to a file, in which case the name of the file is
2639 Output may be to a file, in which case the name of the file is
2633 given using a format string. The formatting rules are as follows:
2640 given using a format string. The formatting rules are as follows:
2634
2641
2635 :``%%``: literal "%" character
2642 :``%%``: literal "%" character
2636 :``%H``: changeset hash (40 hexadecimal digits)
2643 :``%H``: changeset hash (40 hexadecimal digits)
2637 :``%N``: number of patches being generated
2644 :``%N``: number of patches being generated
2638 :``%R``: changeset revision number
2645 :``%R``: changeset revision number
2639 :``%b``: basename of the exporting repository
2646 :``%b``: basename of the exporting repository
2640 :``%h``: short-form changeset hash (12 hexadecimal digits)
2647 :``%h``: short-form changeset hash (12 hexadecimal digits)
2641 :``%m``: first line of the commit message (only alphanumeric characters)
2648 :``%m``: first line of the commit message (only alphanumeric characters)
2642 :``%n``: zero-padded sequence number, starting at 1
2649 :``%n``: zero-padded sequence number, starting at 1
2643 :``%r``: zero-padded changeset revision number
2650 :``%r``: zero-padded changeset revision number
2644
2651
2645 Without the -a/--text option, export will avoid generating diffs
2652 Without the -a/--text option, export will avoid generating diffs
2646 of files it detects as binary. With -a, export will generate a
2653 of files it detects as binary. With -a, export will generate a
2647 diff anyway, probably with undesirable results.
2654 diff anyway, probably with undesirable results.
2648
2655
2649 Use the -g/--git option to generate diffs in the git extended diff
2656 Use the -g/--git option to generate diffs in the git extended diff
2650 format. See :hg:`help diffs` for more information.
2657 format. See :hg:`help diffs` for more information.
2651
2658
2652 With the --switch-parent option, the diff will be against the
2659 With the --switch-parent option, the diff will be against the
2653 second parent. It can be useful to review a merge.
2660 second parent. It can be useful to review a merge.
2654
2661
2655 .. container:: verbose
2662 .. container:: verbose
2656
2663
2657 Examples:
2664 Examples:
2658
2665
2659 - use export and import to transplant a bugfix to the current
2666 - use export and import to transplant a bugfix to the current
2660 branch::
2667 branch::
2661
2668
2662 hg export -r 9353 | hg import -
2669 hg export -r 9353 | hg import -
2663
2670
2664 - export all the changesets between two revisions to a file with
2671 - export all the changesets between two revisions to a file with
2665 rename information::
2672 rename information::
2666
2673
2667 hg export --git -r 123:150 > changes.txt
2674 hg export --git -r 123:150 > changes.txt
2668
2675
2669 - split outgoing changes into a series of patches with
2676 - split outgoing changes into a series of patches with
2670 descriptive names::
2677 descriptive names::
2671
2678
2672 hg export -r "outgoing()" -o "%n-%m.patch"
2679 hg export -r "outgoing()" -o "%n-%m.patch"
2673
2680
2674 Returns 0 on success.
2681 Returns 0 on success.
2675 """
2682 """
2676 changesets += tuple(opts.get('rev', []))
2683 changesets += tuple(opts.get('rev', []))
2677 revs = scmutil.revrange(repo, changesets)
2684 revs = scmutil.revrange(repo, changesets)
2678 if not revs:
2685 if not revs:
2679 raise util.Abort(_("export requires at least one changeset"))
2686 raise util.Abort(_("export requires at least one changeset"))
2680 if len(revs) > 1:
2687 if len(revs) > 1:
2681 ui.note(_('exporting patches:\n'))
2688 ui.note(_('exporting patches:\n'))
2682 else:
2689 else:
2683 ui.note(_('exporting patch:\n'))
2690 ui.note(_('exporting patch:\n'))
2684 cmdutil.export(repo, revs, template=opts.get('output'),
2691 cmdutil.export(repo, revs, template=opts.get('output'),
2685 switch_parent=opts.get('switch_parent'),
2692 switch_parent=opts.get('switch_parent'),
2686 opts=patch.diffopts(ui, opts))
2693 opts=patch.diffopts(ui, opts))
2687
2694
2688 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2695 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2689 def forget(ui, repo, *pats, **opts):
2696 def forget(ui, repo, *pats, **opts):
2690 """forget the specified files on the next commit
2697 """forget the specified files on the next commit
2691
2698
2692 Mark the specified files so they will no longer be tracked
2699 Mark the specified files so they will no longer be tracked
2693 after the next commit.
2700 after the next commit.
2694
2701
2695 This only removes files from the current branch, not from the
2702 This only removes files from the current branch, not from the
2696 entire project history, and it does not delete them from the
2703 entire project history, and it does not delete them from the
2697 working directory.
2704 working directory.
2698
2705
2699 To undo a forget before the next commit, see :hg:`add`.
2706 To undo a forget before the next commit, see :hg:`add`.
2700
2707
2701 .. container:: verbose
2708 .. container:: verbose
2702
2709
2703 Examples:
2710 Examples:
2704
2711
2705 - forget newly-added binary files::
2712 - forget newly-added binary files::
2706
2713
2707 hg forget "set:added() and binary()"
2714 hg forget "set:added() and binary()"
2708
2715
2709 - forget files that would be excluded by .hgignore::
2716 - forget files that would be excluded by .hgignore::
2710
2717
2711 hg forget "set:hgignore()"
2718 hg forget "set:hgignore()"
2712
2719
2713 Returns 0 on success.
2720 Returns 0 on success.
2714 """
2721 """
2715
2722
2716 if not pats:
2723 if not pats:
2717 raise util.Abort(_('no files specified'))
2724 raise util.Abort(_('no files specified'))
2718
2725
2719 m = scmutil.match(repo[None], pats, opts)
2726 m = scmutil.match(repo[None], pats, opts)
2720 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2727 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2721 return rejected and 1 or 0
2728 return rejected and 1 or 0
2722
2729
2723 @command(
2730 @command(
2724 'graft',
2731 'graft',
2725 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2732 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2726 ('c', 'continue', False, _('resume interrupted graft')),
2733 ('c', 'continue', False, _('resume interrupted graft')),
2727 ('e', 'edit', False, _('invoke editor on commit messages')),
2734 ('e', 'edit', False, _('invoke editor on commit messages')),
2728 ('', 'log', None, _('append graft info to log message')),
2735 ('', 'log', None, _('append graft info to log message')),
2729 ('D', 'currentdate', False,
2736 ('D', 'currentdate', False,
2730 _('record the current date as commit date')),
2737 _('record the current date as commit date')),
2731 ('U', 'currentuser', False,
2738 ('U', 'currentuser', False,
2732 _('record the current user as committer'), _('DATE'))]
2739 _('record the current user as committer'), _('DATE'))]
2733 + commitopts2 + mergetoolopts + dryrunopts,
2740 + commitopts2 + mergetoolopts + dryrunopts,
2734 _('[OPTION]... [-r] REV...'))
2741 _('[OPTION]... [-r] REV...'))
2735 def graft(ui, repo, *revs, **opts):
2742 def graft(ui, repo, *revs, **opts):
2736 '''copy changes from other branches onto the current branch
2743 '''copy changes from other branches onto the current branch
2737
2744
2738 This command uses Mercurial's merge logic to copy individual
2745 This command uses Mercurial's merge logic to copy individual
2739 changes from other branches without merging branches in the
2746 changes from other branches without merging branches in the
2740 history graph. This is sometimes known as 'backporting' or
2747 history graph. This is sometimes known as 'backporting' or
2741 'cherry-picking'. By default, graft will copy user, date, and
2748 'cherry-picking'. By default, graft will copy user, date, and
2742 description from the source changesets.
2749 description from the source changesets.
2743
2750
2744 Changesets that are ancestors of the current revision, that have
2751 Changesets that are ancestors of the current revision, that have
2745 already been grafted, or that are merges will be skipped.
2752 already been grafted, or that are merges will be skipped.
2746
2753
2747 If --log is specified, log messages will have a comment appended
2754 If --log is specified, log messages will have a comment appended
2748 of the form::
2755 of the form::
2749
2756
2750 (grafted from CHANGESETHASH)
2757 (grafted from CHANGESETHASH)
2751
2758
2752 If a graft merge results in conflicts, the graft process is
2759 If a graft merge results in conflicts, the graft process is
2753 interrupted so that the current merge can be manually resolved.
2760 interrupted so that the current merge can be manually resolved.
2754 Once all conflicts are addressed, the graft process can be
2761 Once all conflicts are addressed, the graft process can be
2755 continued with the -c/--continue option.
2762 continued with the -c/--continue option.
2756
2763
2757 .. note::
2764 .. note::
2758 The -c/--continue option does not reapply earlier options.
2765 The -c/--continue option does not reapply earlier options.
2759
2766
2760 .. container:: verbose
2767 .. container:: verbose
2761
2768
2762 Examples:
2769 Examples:
2763
2770
2764 - copy a single change to the stable branch and edit its description::
2771 - copy a single change to the stable branch and edit its description::
2765
2772
2766 hg update stable
2773 hg update stable
2767 hg graft --edit 9393
2774 hg graft --edit 9393
2768
2775
2769 - graft a range of changesets with one exception, updating dates::
2776 - graft a range of changesets with one exception, updating dates::
2770
2777
2771 hg graft -D "2085::2093 and not 2091"
2778 hg graft -D "2085::2093 and not 2091"
2772
2779
2773 - continue a graft after resolving conflicts::
2780 - continue a graft after resolving conflicts::
2774
2781
2775 hg graft -c
2782 hg graft -c
2776
2783
2777 - show the source of a grafted changeset::
2784 - show the source of a grafted changeset::
2778
2785
2779 hg log --debug -r tip
2786 hg log --debug -r tip
2780
2787
2781 Returns 0 on successful completion.
2788 Returns 0 on successful completion.
2782 '''
2789 '''
2783
2790
2784 revs = list(revs)
2791 revs = list(revs)
2785 revs.extend(opts['rev'])
2792 revs.extend(opts['rev'])
2786
2793
2787 if not opts.get('user') and opts.get('currentuser'):
2794 if not opts.get('user') and opts.get('currentuser'):
2788 opts['user'] = ui.username()
2795 opts['user'] = ui.username()
2789 if not opts.get('date') and opts.get('currentdate'):
2796 if not opts.get('date') and opts.get('currentdate'):
2790 opts['date'] = "%d %d" % util.makedate()
2797 opts['date'] = "%d %d" % util.makedate()
2791
2798
2792 editor = None
2799 editor = None
2793 if opts.get('edit'):
2800 if opts.get('edit'):
2794 editor = cmdutil.commitforceeditor
2801 editor = cmdutil.commitforceeditor
2795
2802
2796 cont = False
2803 cont = False
2797 if opts['continue']:
2804 if opts['continue']:
2798 cont = True
2805 cont = True
2799 if revs:
2806 if revs:
2800 raise util.Abort(_("can't specify --continue and revisions"))
2807 raise util.Abort(_("can't specify --continue and revisions"))
2801 # read in unfinished revisions
2808 # read in unfinished revisions
2802 try:
2809 try:
2803 nodes = repo.opener.read('graftstate').splitlines()
2810 nodes = repo.opener.read('graftstate').splitlines()
2804 revs = [repo[node].rev() for node in nodes]
2811 revs = [repo[node].rev() for node in nodes]
2805 except IOError, inst:
2812 except IOError, inst:
2806 if inst.errno != errno.ENOENT:
2813 if inst.errno != errno.ENOENT:
2807 raise
2814 raise
2808 raise util.Abort(_("no graft state found, can't continue"))
2815 raise util.Abort(_("no graft state found, can't continue"))
2809 else:
2816 else:
2810 cmdutil.bailifchanged(repo)
2817 cmdutil.bailifchanged(repo)
2811 if not revs:
2818 if not revs:
2812 raise util.Abort(_('no revisions specified'))
2819 raise util.Abort(_('no revisions specified'))
2813 revs = scmutil.revrange(repo, revs)
2820 revs = scmutil.revrange(repo, revs)
2814
2821
2815 # check for merges
2822 # check for merges
2816 for rev in repo.revs('%ld and merge()', revs):
2823 for rev in repo.revs('%ld and merge()', revs):
2817 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2824 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2818 revs.remove(rev)
2825 revs.remove(rev)
2819 if not revs:
2826 if not revs:
2820 return -1
2827 return -1
2821
2828
2822 # check for ancestors of dest branch
2829 # check for ancestors of dest branch
2823 for rev in repo.revs('::. and %ld', revs):
2830 for rev in repo.revs('::. and %ld', revs):
2824 ui.warn(_('skipping ancestor revision %s\n') % rev)
2831 ui.warn(_('skipping ancestor revision %s\n') % rev)
2825 revs.remove(rev)
2832 revs.remove(rev)
2826 if not revs:
2833 if not revs:
2827 return -1
2834 return -1
2828
2835
2829 # analyze revs for earlier grafts
2836 # analyze revs for earlier grafts
2830 ids = {}
2837 ids = {}
2831 for ctx in repo.set("%ld", revs):
2838 for ctx in repo.set("%ld", revs):
2832 ids[ctx.hex()] = ctx.rev()
2839 ids[ctx.hex()] = ctx.rev()
2833 n = ctx.extra().get('source')
2840 n = ctx.extra().get('source')
2834 if n:
2841 if n:
2835 ids[n] = ctx.rev()
2842 ids[n] = ctx.rev()
2836
2843
2837 # check ancestors for earlier grafts
2844 # check ancestors for earlier grafts
2838 ui.debug('scanning for duplicate grafts\n')
2845 ui.debug('scanning for duplicate grafts\n')
2839 for ctx in repo.set("::. - ::%ld", revs):
2846 for ctx in repo.set("::. - ::%ld", revs):
2840 n = ctx.extra().get('source')
2847 n = ctx.extra().get('source')
2841 if n in ids:
2848 if n in ids:
2842 r = repo[n].rev()
2849 r = repo[n].rev()
2843 if r in revs:
2850 if r in revs:
2844 ui.warn(_('skipping already grafted revision %s\n') % r)
2851 ui.warn(_('skipping already grafted revision %s\n') % r)
2845 revs.remove(r)
2852 revs.remove(r)
2846 elif ids[n] in revs:
2853 elif ids[n] in revs:
2847 ui.warn(_('skipping already grafted revision %s '
2854 ui.warn(_('skipping already grafted revision %s '
2848 '(same origin %d)\n') % (ids[n], r))
2855 '(same origin %d)\n') % (ids[n], r))
2849 revs.remove(ids[n])
2856 revs.remove(ids[n])
2850 elif ctx.hex() in ids:
2857 elif ctx.hex() in ids:
2851 r = ids[ctx.hex()]
2858 r = ids[ctx.hex()]
2852 ui.warn(_('skipping already grafted revision %s '
2859 ui.warn(_('skipping already grafted revision %s '
2853 '(was grafted from %d)\n') % (r, ctx.rev()))
2860 '(was grafted from %d)\n') % (r, ctx.rev()))
2854 revs.remove(r)
2861 revs.remove(r)
2855 if not revs:
2862 if not revs:
2856 return -1
2863 return -1
2857
2864
2858 wlock = repo.wlock()
2865 wlock = repo.wlock()
2859 try:
2866 try:
2860 current = repo['.']
2867 current = repo['.']
2861 for pos, ctx in enumerate(repo.set("%ld", revs)):
2868 for pos, ctx in enumerate(repo.set("%ld", revs)):
2862
2869
2863 ui.status(_('grafting revision %s\n') % ctx.rev())
2870 ui.status(_('grafting revision %s\n') % ctx.rev())
2864 if opts.get('dry_run'):
2871 if opts.get('dry_run'):
2865 continue
2872 continue
2866
2873
2867 source = ctx.extra().get('source')
2874 source = ctx.extra().get('source')
2868 if not source:
2875 if not source:
2869 source = ctx.hex()
2876 source = ctx.hex()
2870 extra = {'source': source}
2877 extra = {'source': source}
2871 user = ctx.user()
2878 user = ctx.user()
2872 if opts.get('user'):
2879 if opts.get('user'):
2873 user = opts['user']
2880 user = opts['user']
2874 date = ctx.date()
2881 date = ctx.date()
2875 if opts.get('date'):
2882 if opts.get('date'):
2876 date = opts['date']
2883 date = opts['date']
2877 message = ctx.description()
2884 message = ctx.description()
2878 if opts.get('log'):
2885 if opts.get('log'):
2879 message += '\n(grafted from %s)' % ctx.hex()
2886 message += '\n(grafted from %s)' % ctx.hex()
2880
2887
2881 # we don't merge the first commit when continuing
2888 # we don't merge the first commit when continuing
2882 if not cont:
2889 if not cont:
2883 # perform the graft merge with p1(rev) as 'ancestor'
2890 # perform the graft merge with p1(rev) as 'ancestor'
2884 try:
2891 try:
2885 # ui.forcemerge is an internal variable, do not document
2892 # ui.forcemerge is an internal variable, do not document
2886 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2893 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2887 stats = mergemod.update(repo, ctx.node(), True, True, False,
2894 stats = mergemod.update(repo, ctx.node(), True, True, False,
2888 ctx.p1().node())
2895 ctx.p1().node())
2889 finally:
2896 finally:
2890 repo.ui.setconfig('ui', 'forcemerge', '')
2897 repo.ui.setconfig('ui', 'forcemerge', '')
2891 # report any conflicts
2898 # report any conflicts
2892 if stats and stats[3] > 0:
2899 if stats and stats[3] > 0:
2893 # write out state for --continue
2900 # write out state for --continue
2894 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2901 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2895 repo.opener.write('graftstate', ''.join(nodelines))
2902 repo.opener.write('graftstate', ''.join(nodelines))
2896 raise util.Abort(
2903 raise util.Abort(
2897 _("unresolved conflicts, can't continue"),
2904 _("unresolved conflicts, can't continue"),
2898 hint=_('use hg resolve and hg graft --continue'))
2905 hint=_('use hg resolve and hg graft --continue'))
2899 else:
2906 else:
2900 cont = False
2907 cont = False
2901
2908
2902 # drop the second merge parent
2909 # drop the second merge parent
2903 repo.setparents(current.node(), nullid)
2910 repo.setparents(current.node(), nullid)
2904 repo.dirstate.write()
2911 repo.dirstate.write()
2905 # fix up dirstate for copies and renames
2912 # fix up dirstate for copies and renames
2906 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2913 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2907
2914
2908 # commit
2915 # commit
2909 node = repo.commit(text=message, user=user,
2916 node = repo.commit(text=message, user=user,
2910 date=date, extra=extra, editor=editor)
2917 date=date, extra=extra, editor=editor)
2911 if node is None:
2918 if node is None:
2912 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2919 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2913 else:
2920 else:
2914 current = repo[node]
2921 current = repo[node]
2915 finally:
2922 finally:
2916 wlock.release()
2923 wlock.release()
2917
2924
2918 # remove state when we complete successfully
2925 # remove state when we complete successfully
2919 if not opts.get('dry_run'):
2926 if not opts.get('dry_run'):
2920 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2927 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2921
2928
2922 return 0
2929 return 0
2923
2930
2924 @command('grep',
2931 @command('grep',
2925 [('0', 'print0', None, _('end fields with NUL')),
2932 [('0', 'print0', None, _('end fields with NUL')),
2926 ('', 'all', None, _('print all revisions that match')),
2933 ('', 'all', None, _('print all revisions that match')),
2927 ('a', 'text', None, _('treat all files as text')),
2934 ('a', 'text', None, _('treat all files as text')),
2928 ('f', 'follow', None,
2935 ('f', 'follow', None,
2929 _('follow changeset history,'
2936 _('follow changeset history,'
2930 ' or file history across copies and renames')),
2937 ' or file history across copies and renames')),
2931 ('i', 'ignore-case', None, _('ignore case when matching')),
2938 ('i', 'ignore-case', None, _('ignore case when matching')),
2932 ('l', 'files-with-matches', None,
2939 ('l', 'files-with-matches', None,
2933 _('print only filenames and revisions that match')),
2940 _('print only filenames and revisions that match')),
2934 ('n', 'line-number', None, _('print matching line numbers')),
2941 ('n', 'line-number', None, _('print matching line numbers')),
2935 ('r', 'rev', [],
2942 ('r', 'rev', [],
2936 _('only search files changed within revision range'), _('REV')),
2943 _('only search files changed within revision range'), _('REV')),
2937 ('u', 'user', None, _('list the author (long with -v)')),
2944 ('u', 'user', None, _('list the author (long with -v)')),
2938 ('d', 'date', None, _('list the date (short with -q)')),
2945 ('d', 'date', None, _('list the date (short with -q)')),
2939 ] + walkopts,
2946 ] + walkopts,
2940 _('[OPTION]... PATTERN [FILE]...'))
2947 _('[OPTION]... PATTERN [FILE]...'))
2941 def grep(ui, repo, pattern, *pats, **opts):
2948 def grep(ui, repo, pattern, *pats, **opts):
2942 """search for a pattern in specified files and revisions
2949 """search for a pattern in specified files and revisions
2943
2950
2944 Search revisions of files for a regular expression.
2951 Search revisions of files for a regular expression.
2945
2952
2946 This command behaves differently than Unix grep. It only accepts
2953 This command behaves differently than Unix grep. It only accepts
2947 Python/Perl regexps. It searches repository history, not the
2954 Python/Perl regexps. It searches repository history, not the
2948 working directory. It always prints the revision number in which a
2955 working directory. It always prints the revision number in which a
2949 match appears.
2956 match appears.
2950
2957
2951 By default, grep only prints output for the first revision of a
2958 By default, grep only prints output for the first revision of a
2952 file in which it finds a match. To get it to print every revision
2959 file in which it finds a match. To get it to print every revision
2953 that contains a change in match status ("-" for a match that
2960 that contains a change in match status ("-" for a match that
2954 becomes a non-match, or "+" for a non-match that becomes a match),
2961 becomes a non-match, or "+" for a non-match that becomes a match),
2955 use the --all flag.
2962 use the --all flag.
2956
2963
2957 Returns 0 if a match is found, 1 otherwise.
2964 Returns 0 if a match is found, 1 otherwise.
2958 """
2965 """
2959 reflags = re.M
2966 reflags = re.M
2960 if opts.get('ignore_case'):
2967 if opts.get('ignore_case'):
2961 reflags |= re.I
2968 reflags |= re.I
2962 try:
2969 try:
2963 regexp = re.compile(pattern, reflags)
2970 regexp = re.compile(pattern, reflags)
2964 except re.error, inst:
2971 except re.error, inst:
2965 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2972 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2966 return 1
2973 return 1
2967 sep, eol = ':', '\n'
2974 sep, eol = ':', '\n'
2968 if opts.get('print0'):
2975 if opts.get('print0'):
2969 sep = eol = '\0'
2976 sep = eol = '\0'
2970
2977
2971 getfile = util.lrucachefunc(repo.file)
2978 getfile = util.lrucachefunc(repo.file)
2972
2979
2973 def matchlines(body):
2980 def matchlines(body):
2974 begin = 0
2981 begin = 0
2975 linenum = 0
2982 linenum = 0
2976 while begin < len(body):
2983 while begin < len(body):
2977 match = regexp.search(body, begin)
2984 match = regexp.search(body, begin)
2978 if not match:
2985 if not match:
2979 break
2986 break
2980 mstart, mend = match.span()
2987 mstart, mend = match.span()
2981 linenum += body.count('\n', begin, mstart) + 1
2988 linenum += body.count('\n', begin, mstart) + 1
2982 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2989 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2983 begin = body.find('\n', mend) + 1 or len(body) + 1
2990 begin = body.find('\n', mend) + 1 or len(body) + 1
2984 lend = begin - 1
2991 lend = begin - 1
2985 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2992 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2986
2993
2987 class linestate(object):
2994 class linestate(object):
2988 def __init__(self, line, linenum, colstart, colend):
2995 def __init__(self, line, linenum, colstart, colend):
2989 self.line = line
2996 self.line = line
2990 self.linenum = linenum
2997 self.linenum = linenum
2991 self.colstart = colstart
2998 self.colstart = colstart
2992 self.colend = colend
2999 self.colend = colend
2993
3000
2994 def __hash__(self):
3001 def __hash__(self):
2995 return hash((self.linenum, self.line))
3002 return hash((self.linenum, self.line))
2996
3003
2997 def __eq__(self, other):
3004 def __eq__(self, other):
2998 return self.line == other.line
3005 return self.line == other.line
2999
3006
3000 matches = {}
3007 matches = {}
3001 copies = {}
3008 copies = {}
3002 def grepbody(fn, rev, body):
3009 def grepbody(fn, rev, body):
3003 matches[rev].setdefault(fn, [])
3010 matches[rev].setdefault(fn, [])
3004 m = matches[rev][fn]
3011 m = matches[rev][fn]
3005 for lnum, cstart, cend, line in matchlines(body):
3012 for lnum, cstart, cend, line in matchlines(body):
3006 s = linestate(line, lnum, cstart, cend)
3013 s = linestate(line, lnum, cstart, cend)
3007 m.append(s)
3014 m.append(s)
3008
3015
3009 def difflinestates(a, b):
3016 def difflinestates(a, b):
3010 sm = difflib.SequenceMatcher(None, a, b)
3017 sm = difflib.SequenceMatcher(None, a, b)
3011 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3018 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3012 if tag == 'insert':
3019 if tag == 'insert':
3013 for i in xrange(blo, bhi):
3020 for i in xrange(blo, bhi):
3014 yield ('+', b[i])
3021 yield ('+', b[i])
3015 elif tag == 'delete':
3022 elif tag == 'delete':
3016 for i in xrange(alo, ahi):
3023 for i in xrange(alo, ahi):
3017 yield ('-', a[i])
3024 yield ('-', a[i])
3018 elif tag == 'replace':
3025 elif tag == 'replace':
3019 for i in xrange(alo, ahi):
3026 for i in xrange(alo, ahi):
3020 yield ('-', a[i])
3027 yield ('-', a[i])
3021 for i in xrange(blo, bhi):
3028 for i in xrange(blo, bhi):
3022 yield ('+', b[i])
3029 yield ('+', b[i])
3023
3030
3024 def display(fn, ctx, pstates, states):
3031 def display(fn, ctx, pstates, states):
3025 rev = ctx.rev()
3032 rev = ctx.rev()
3026 datefunc = ui.quiet and util.shortdate or util.datestr
3033 datefunc = ui.quiet and util.shortdate or util.datestr
3027 found = False
3034 found = False
3028 filerevmatches = {}
3035 filerevmatches = {}
3029 def binary():
3036 def binary():
3030 flog = getfile(fn)
3037 flog = getfile(fn)
3031 return util.binary(flog.read(ctx.filenode(fn)))
3038 return util.binary(flog.read(ctx.filenode(fn)))
3032
3039
3033 if opts.get('all'):
3040 if opts.get('all'):
3034 iter = difflinestates(pstates, states)
3041 iter = difflinestates(pstates, states)
3035 else:
3042 else:
3036 iter = [('', l) for l in states]
3043 iter = [('', l) for l in states]
3037 for change, l in iter:
3044 for change, l in iter:
3038 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3045 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3039 before, match, after = None, None, None
3046 before, match, after = None, None, None
3040
3047
3041 if opts.get('line_number'):
3048 if opts.get('line_number'):
3042 cols.append((str(l.linenum), 'grep.linenumber'))
3049 cols.append((str(l.linenum), 'grep.linenumber'))
3043 if opts.get('all'):
3050 if opts.get('all'):
3044 cols.append((change, 'grep.change'))
3051 cols.append((change, 'grep.change'))
3045 if opts.get('user'):
3052 if opts.get('user'):
3046 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3053 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3047 if opts.get('date'):
3054 if opts.get('date'):
3048 cols.append((datefunc(ctx.date()), 'grep.date'))
3055 cols.append((datefunc(ctx.date()), 'grep.date'))
3049 if opts.get('files_with_matches'):
3056 if opts.get('files_with_matches'):
3050 c = (fn, rev)
3057 c = (fn, rev)
3051 if c in filerevmatches:
3058 if c in filerevmatches:
3052 continue
3059 continue
3053 filerevmatches[c] = 1
3060 filerevmatches[c] = 1
3054 else:
3061 else:
3055 before = l.line[:l.colstart]
3062 before = l.line[:l.colstart]
3056 match = l.line[l.colstart:l.colend]
3063 match = l.line[l.colstart:l.colend]
3057 after = l.line[l.colend:]
3064 after = l.line[l.colend:]
3058 for col, label in cols[:-1]:
3065 for col, label in cols[:-1]:
3059 ui.write(col, label=label)
3066 ui.write(col, label=label)
3060 ui.write(sep, label='grep.sep')
3067 ui.write(sep, label='grep.sep')
3061 ui.write(cols[-1][0], label=cols[-1][1])
3068 ui.write(cols[-1][0], label=cols[-1][1])
3062 if before is not None:
3069 if before is not None:
3063 ui.write(sep, label='grep.sep')
3070 ui.write(sep, label='grep.sep')
3064 if not opts.get('text') and binary():
3071 if not opts.get('text') and binary():
3065 ui.write(" Binary file matches")
3072 ui.write(" Binary file matches")
3066 else:
3073 else:
3067 ui.write(before)
3074 ui.write(before)
3068 ui.write(match, label='grep.match')
3075 ui.write(match, label='grep.match')
3069 ui.write(after)
3076 ui.write(after)
3070 ui.write(eol)
3077 ui.write(eol)
3071 found = True
3078 found = True
3072 return found
3079 return found
3073
3080
3074 skip = {}
3081 skip = {}
3075 revfiles = {}
3082 revfiles = {}
3076 matchfn = scmutil.match(repo[None], pats, opts)
3083 matchfn = scmutil.match(repo[None], pats, opts)
3077 found = False
3084 found = False
3078 follow = opts.get('follow')
3085 follow = opts.get('follow')
3079
3086
3080 def prep(ctx, fns):
3087 def prep(ctx, fns):
3081 rev = ctx.rev()
3088 rev = ctx.rev()
3082 pctx = ctx.p1()
3089 pctx = ctx.p1()
3083 parent = pctx.rev()
3090 parent = pctx.rev()
3084 matches.setdefault(rev, {})
3091 matches.setdefault(rev, {})
3085 matches.setdefault(parent, {})
3092 matches.setdefault(parent, {})
3086 files = revfiles.setdefault(rev, [])
3093 files = revfiles.setdefault(rev, [])
3087 for fn in fns:
3094 for fn in fns:
3088 flog = getfile(fn)
3095 flog = getfile(fn)
3089 try:
3096 try:
3090 fnode = ctx.filenode(fn)
3097 fnode = ctx.filenode(fn)
3091 except error.LookupError:
3098 except error.LookupError:
3092 continue
3099 continue
3093
3100
3094 copied = flog.renamed(fnode)
3101 copied = flog.renamed(fnode)
3095 copy = follow and copied and copied[0]
3102 copy = follow and copied and copied[0]
3096 if copy:
3103 if copy:
3097 copies.setdefault(rev, {})[fn] = copy
3104 copies.setdefault(rev, {})[fn] = copy
3098 if fn in skip:
3105 if fn in skip:
3099 if copy:
3106 if copy:
3100 skip[copy] = True
3107 skip[copy] = True
3101 continue
3108 continue
3102 files.append(fn)
3109 files.append(fn)
3103
3110
3104 if fn not in matches[rev]:
3111 if fn not in matches[rev]:
3105 grepbody(fn, rev, flog.read(fnode))
3112 grepbody(fn, rev, flog.read(fnode))
3106
3113
3107 pfn = copy or fn
3114 pfn = copy or fn
3108 if pfn not in matches[parent]:
3115 if pfn not in matches[parent]:
3109 try:
3116 try:
3110 fnode = pctx.filenode(pfn)
3117 fnode = pctx.filenode(pfn)
3111 grepbody(pfn, parent, flog.read(fnode))
3118 grepbody(pfn, parent, flog.read(fnode))
3112 except error.LookupError:
3119 except error.LookupError:
3113 pass
3120 pass
3114
3121
3115 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3122 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3116 rev = ctx.rev()
3123 rev = ctx.rev()
3117 parent = ctx.p1().rev()
3124 parent = ctx.p1().rev()
3118 for fn in sorted(revfiles.get(rev, [])):
3125 for fn in sorted(revfiles.get(rev, [])):
3119 states = matches[rev][fn]
3126 states = matches[rev][fn]
3120 copy = copies.get(rev, {}).get(fn)
3127 copy = copies.get(rev, {}).get(fn)
3121 if fn in skip:
3128 if fn in skip:
3122 if copy:
3129 if copy:
3123 skip[copy] = True
3130 skip[copy] = True
3124 continue
3131 continue
3125 pstates = matches.get(parent, {}).get(copy or fn, [])
3132 pstates = matches.get(parent, {}).get(copy or fn, [])
3126 if pstates or states:
3133 if pstates or states:
3127 r = display(fn, ctx, pstates, states)
3134 r = display(fn, ctx, pstates, states)
3128 found = found or r
3135 found = found or r
3129 if r and not opts.get('all'):
3136 if r and not opts.get('all'):
3130 skip[fn] = True
3137 skip[fn] = True
3131 if copy:
3138 if copy:
3132 skip[copy] = True
3139 skip[copy] = True
3133 del matches[rev]
3140 del matches[rev]
3134 del revfiles[rev]
3141 del revfiles[rev]
3135
3142
3136 return not found
3143 return not found
3137
3144
3138 @command('heads',
3145 @command('heads',
3139 [('r', 'rev', '',
3146 [('r', 'rev', '',
3140 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3147 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3141 ('t', 'topo', False, _('show topological heads only')),
3148 ('t', 'topo', False, _('show topological heads only')),
3142 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3149 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3143 ('c', 'closed', False, _('show normal and closed branch heads')),
3150 ('c', 'closed', False, _('show normal and closed branch heads')),
3144 ] + templateopts,
3151 ] + templateopts,
3145 _('[-ct] [-r STARTREV] [REV]...'))
3152 _('[-ct] [-r STARTREV] [REV]...'))
3146 def heads(ui, repo, *branchrevs, **opts):
3153 def heads(ui, repo, *branchrevs, **opts):
3147 """show current repository heads or show branch heads
3154 """show current repository heads or show branch heads
3148
3155
3149 With no arguments, show all repository branch heads.
3156 With no arguments, show all repository branch heads.
3150
3157
3151 Repository "heads" are changesets with no child changesets. They are
3158 Repository "heads" are changesets with no child changesets. They are
3152 where development generally takes place and are the usual targets
3159 where development generally takes place and are the usual targets
3153 for update and merge operations. Branch heads are changesets that have
3160 for update and merge operations. Branch heads are changesets that have
3154 no child changeset on the same branch.
3161 no child changeset on the same branch.
3155
3162
3156 If one or more REVs are given, only branch heads on the branches
3163 If one or more REVs are given, only branch heads on the branches
3157 associated with the specified changesets are shown. This means
3164 associated with the specified changesets are shown. This means
3158 that you can use :hg:`heads foo` to see the heads on a branch
3165 that you can use :hg:`heads foo` to see the heads on a branch
3159 named ``foo``.
3166 named ``foo``.
3160
3167
3161 If -c/--closed is specified, also show branch heads marked closed
3168 If -c/--closed is specified, also show branch heads marked closed
3162 (see :hg:`commit --close-branch`).
3169 (see :hg:`commit --close-branch`).
3163
3170
3164 If STARTREV is specified, only those heads that are descendants of
3171 If STARTREV is specified, only those heads that are descendants of
3165 STARTREV will be displayed.
3172 STARTREV will be displayed.
3166
3173
3167 If -t/--topo is specified, named branch mechanics will be ignored and only
3174 If -t/--topo is specified, named branch mechanics will be ignored and only
3168 changesets without children will be shown.
3175 changesets without children will be shown.
3169
3176
3170 Returns 0 if matching heads are found, 1 if not.
3177 Returns 0 if matching heads are found, 1 if not.
3171 """
3178 """
3172
3179
3173 start = None
3180 start = None
3174 if 'rev' in opts:
3181 if 'rev' in opts:
3175 start = scmutil.revsingle(repo, opts['rev'], None).node()
3182 start = scmutil.revsingle(repo, opts['rev'], None).node()
3176
3183
3177 if opts.get('topo'):
3184 if opts.get('topo'):
3178 heads = [repo[h] for h in repo.heads(start)]
3185 heads = [repo[h] for h in repo.heads(start)]
3179 else:
3186 else:
3180 heads = []
3187 heads = []
3181 for branch in repo.branchmap():
3188 for branch in repo.branchmap():
3182 heads += repo.branchheads(branch, start, opts.get('closed'))
3189 heads += repo.branchheads(branch, start, opts.get('closed'))
3183 heads = [repo[h] for h in heads]
3190 heads = [repo[h] for h in heads]
3184
3191
3185 if branchrevs:
3192 if branchrevs:
3186 branches = set(repo[br].branch() for br in branchrevs)
3193 branches = set(repo[br].branch() for br in branchrevs)
3187 heads = [h for h in heads if h.branch() in branches]
3194 heads = [h for h in heads if h.branch() in branches]
3188
3195
3189 if opts.get('active') and branchrevs:
3196 if opts.get('active') and branchrevs:
3190 dagheads = repo.heads(start)
3197 dagheads = repo.heads(start)
3191 heads = [h for h in heads if h.node() in dagheads]
3198 heads = [h for h in heads if h.node() in dagheads]
3192
3199
3193 if branchrevs:
3200 if branchrevs:
3194 haveheads = set(h.branch() for h in heads)
3201 haveheads = set(h.branch() for h in heads)
3195 if branches - haveheads:
3202 if branches - haveheads:
3196 headless = ', '.join(b for b in branches - haveheads)
3203 headless = ', '.join(b for b in branches - haveheads)
3197 msg = _('no open branch heads found on branches %s')
3204 msg = _('no open branch heads found on branches %s')
3198 if opts.get('rev'):
3205 if opts.get('rev'):
3199 msg += _(' (started at %s)') % opts['rev']
3206 msg += _(' (started at %s)') % opts['rev']
3200 ui.warn((msg + '\n') % headless)
3207 ui.warn((msg + '\n') % headless)
3201
3208
3202 if not heads:
3209 if not heads:
3203 return 1
3210 return 1
3204
3211
3205 heads = sorted(heads, key=lambda x: -x.rev())
3212 heads = sorted(heads, key=lambda x: -x.rev())
3206 displayer = cmdutil.show_changeset(ui, repo, opts)
3213 displayer = cmdutil.show_changeset(ui, repo, opts)
3207 for ctx in heads:
3214 for ctx in heads:
3208 displayer.show(ctx)
3215 displayer.show(ctx)
3209 displayer.close()
3216 displayer.close()
3210
3217
3211 @command('help',
3218 @command('help',
3212 [('e', 'extension', None, _('show only help for extensions')),
3219 [('e', 'extension', None, _('show only help for extensions')),
3213 ('c', 'command', None, _('show only help for commands')),
3220 ('c', 'command', None, _('show only help for commands')),
3214 ('k', 'keyword', '', _('show topics matching keyword')),
3221 ('k', 'keyword', '', _('show topics matching keyword')),
3215 ],
3222 ],
3216 _('[-ec] [TOPIC]'))
3223 _('[-ec] [TOPIC]'))
3217 def help_(ui, name=None, **opts):
3224 def help_(ui, name=None, **opts):
3218 """show help for a given topic or a help overview
3225 """show help for a given topic or a help overview
3219
3226
3220 With no arguments, print a list of commands with short help messages.
3227 With no arguments, print a list of commands with short help messages.
3221
3228
3222 Given a topic, extension, or command name, print help for that
3229 Given a topic, extension, or command name, print help for that
3223 topic.
3230 topic.
3224
3231
3225 Returns 0 if successful.
3232 Returns 0 if successful.
3226 """
3233 """
3227
3234
3228 textwidth = min(ui.termwidth(), 80) - 2
3235 textwidth = min(ui.termwidth(), 80) - 2
3229
3236
3230 keep = ui.verbose and ['verbose'] or []
3237 keep = ui.verbose and ['verbose'] or []
3231 text = help.help_(ui, name, **opts)
3238 text = help.help_(ui, name, **opts)
3232
3239
3233 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3240 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3234 if 'verbose' in pruned:
3241 if 'verbose' in pruned:
3235 keep.append('omitted')
3242 keep.append('omitted')
3236 else:
3243 else:
3237 keep.append('notomitted')
3244 keep.append('notomitted')
3238 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3245 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3239 ui.write(formatted)
3246 ui.write(formatted)
3240
3247
3241
3248
3242 @command('identify|id',
3249 @command('identify|id',
3243 [('r', 'rev', '',
3250 [('r', 'rev', '',
3244 _('identify the specified revision'), _('REV')),
3251 _('identify the specified revision'), _('REV')),
3245 ('n', 'num', None, _('show local revision number')),
3252 ('n', 'num', None, _('show local revision number')),
3246 ('i', 'id', None, _('show global revision id')),
3253 ('i', 'id', None, _('show global revision id')),
3247 ('b', 'branch', None, _('show branch')),
3254 ('b', 'branch', None, _('show branch')),
3248 ('t', 'tags', None, _('show tags')),
3255 ('t', 'tags', None, _('show tags')),
3249 ('B', 'bookmarks', None, _('show bookmarks')),
3256 ('B', 'bookmarks', None, _('show bookmarks')),
3250 ] + remoteopts,
3257 ] + remoteopts,
3251 _('[-nibtB] [-r REV] [SOURCE]'))
3258 _('[-nibtB] [-r REV] [SOURCE]'))
3252 def identify(ui, repo, source=None, rev=None,
3259 def identify(ui, repo, source=None, rev=None,
3253 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3260 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3254 """identify the working copy or specified revision
3261 """identify the working copy or specified revision
3255
3262
3256 Print a summary identifying the repository state at REV using one or
3263 Print a summary identifying the repository state at REV using one or
3257 two parent hash identifiers, followed by a "+" if the working
3264 two parent hash identifiers, followed by a "+" if the working
3258 directory has uncommitted changes, the branch name (if not default),
3265 directory has uncommitted changes, the branch name (if not default),
3259 a list of tags, and a list of bookmarks.
3266 a list of tags, and a list of bookmarks.
3260
3267
3261 When REV is not given, print a summary of the current state of the
3268 When REV is not given, print a summary of the current state of the
3262 repository.
3269 repository.
3263
3270
3264 Specifying a path to a repository root or Mercurial bundle will
3271 Specifying a path to a repository root or Mercurial bundle will
3265 cause lookup to operate on that repository/bundle.
3272 cause lookup to operate on that repository/bundle.
3266
3273
3267 .. container:: verbose
3274 .. container:: verbose
3268
3275
3269 Examples:
3276 Examples:
3270
3277
3271 - generate a build identifier for the working directory::
3278 - generate a build identifier for the working directory::
3272
3279
3273 hg id --id > build-id.dat
3280 hg id --id > build-id.dat
3274
3281
3275 - find the revision corresponding to a tag::
3282 - find the revision corresponding to a tag::
3276
3283
3277 hg id -n -r 1.3
3284 hg id -n -r 1.3
3278
3285
3279 - check the most recent revision of a remote repository::
3286 - check the most recent revision of a remote repository::
3280
3287
3281 hg id -r tip http://selenic.com/hg/
3288 hg id -r tip http://selenic.com/hg/
3282
3289
3283 Returns 0 if successful.
3290 Returns 0 if successful.
3284 """
3291 """
3285
3292
3286 if not repo and not source:
3293 if not repo and not source:
3287 raise util.Abort(_("there is no Mercurial repository here "
3294 raise util.Abort(_("there is no Mercurial repository here "
3288 "(.hg not found)"))
3295 "(.hg not found)"))
3289
3296
3290 hexfunc = ui.debugflag and hex or short
3297 hexfunc = ui.debugflag and hex or short
3291 default = not (num or id or branch or tags or bookmarks)
3298 default = not (num or id or branch or tags or bookmarks)
3292 output = []
3299 output = []
3293 revs = []
3300 revs = []
3294
3301
3295 if source:
3302 if source:
3296 source, branches = hg.parseurl(ui.expandpath(source))
3303 source, branches = hg.parseurl(ui.expandpath(source))
3297 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3304 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3298 repo = peer.local()
3305 repo = peer.local()
3299 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3306 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3300
3307
3301 if not repo:
3308 if not repo:
3302 if num or branch or tags:
3309 if num or branch or tags:
3303 raise util.Abort(
3310 raise util.Abort(
3304 _("can't query remote revision number, branch, or tags"))
3311 _("can't query remote revision number, branch, or tags"))
3305 if not rev and revs:
3312 if not rev and revs:
3306 rev = revs[0]
3313 rev = revs[0]
3307 if not rev:
3314 if not rev:
3308 rev = "tip"
3315 rev = "tip"
3309
3316
3310 remoterev = peer.lookup(rev)
3317 remoterev = peer.lookup(rev)
3311 if default or id:
3318 if default or id:
3312 output = [hexfunc(remoterev)]
3319 output = [hexfunc(remoterev)]
3313
3320
3314 def getbms():
3321 def getbms():
3315 bms = []
3322 bms = []
3316
3323
3317 if 'bookmarks' in peer.listkeys('namespaces'):
3324 if 'bookmarks' in peer.listkeys('namespaces'):
3318 hexremoterev = hex(remoterev)
3325 hexremoterev = hex(remoterev)
3319 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3326 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3320 if bmr == hexremoterev]
3327 if bmr == hexremoterev]
3321
3328
3322 return sorted(bms)
3329 return sorted(bms)
3323
3330
3324 if bookmarks:
3331 if bookmarks:
3325 output.extend(getbms())
3332 output.extend(getbms())
3326 elif default and not ui.quiet:
3333 elif default and not ui.quiet:
3327 # multiple bookmarks for a single parent separated by '/'
3334 # multiple bookmarks for a single parent separated by '/'
3328 bm = '/'.join(getbms())
3335 bm = '/'.join(getbms())
3329 if bm:
3336 if bm:
3330 output.append(bm)
3337 output.append(bm)
3331 else:
3338 else:
3332 if not rev:
3339 if not rev:
3333 ctx = repo[None]
3340 ctx = repo[None]
3334 parents = ctx.parents()
3341 parents = ctx.parents()
3335 changed = ""
3342 changed = ""
3336 if default or id or num:
3343 if default or id or num:
3337 if (util.any(repo.status())
3344 if (util.any(repo.status())
3338 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3345 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3339 changed = '+'
3346 changed = '+'
3340 if default or id:
3347 if default or id:
3341 output = ["%s%s" %
3348 output = ["%s%s" %
3342 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3349 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3343 if num:
3350 if num:
3344 output.append("%s%s" %
3351 output.append("%s%s" %
3345 ('+'.join([str(p.rev()) for p in parents]), changed))
3352 ('+'.join([str(p.rev()) for p in parents]), changed))
3346 else:
3353 else:
3347 ctx = scmutil.revsingle(repo, rev)
3354 ctx = scmutil.revsingle(repo, rev)
3348 if default or id:
3355 if default or id:
3349 output = [hexfunc(ctx.node())]
3356 output = [hexfunc(ctx.node())]
3350 if num:
3357 if num:
3351 output.append(str(ctx.rev()))
3358 output.append(str(ctx.rev()))
3352
3359
3353 if default and not ui.quiet:
3360 if default and not ui.quiet:
3354 b = ctx.branch()
3361 b = ctx.branch()
3355 if b != 'default':
3362 if b != 'default':
3356 output.append("(%s)" % b)
3363 output.append("(%s)" % b)
3357
3364
3358 # multiple tags for a single parent separated by '/'
3365 # multiple tags for a single parent separated by '/'
3359 t = '/'.join(ctx.tags())
3366 t = '/'.join(ctx.tags())
3360 if t:
3367 if t:
3361 output.append(t)
3368 output.append(t)
3362
3369
3363 # multiple bookmarks for a single parent separated by '/'
3370 # multiple bookmarks for a single parent separated by '/'
3364 bm = '/'.join(ctx.bookmarks())
3371 bm = '/'.join(ctx.bookmarks())
3365 if bm:
3372 if bm:
3366 output.append(bm)
3373 output.append(bm)
3367 else:
3374 else:
3368 if branch:
3375 if branch:
3369 output.append(ctx.branch())
3376 output.append(ctx.branch())
3370
3377
3371 if tags:
3378 if tags:
3372 output.extend(ctx.tags())
3379 output.extend(ctx.tags())
3373
3380
3374 if bookmarks:
3381 if bookmarks:
3375 output.extend(ctx.bookmarks())
3382 output.extend(ctx.bookmarks())
3376
3383
3377 ui.write("%s\n" % ' '.join(output))
3384 ui.write("%s\n" % ' '.join(output))
3378
3385
3379 @command('import|patch',
3386 @command('import|patch',
3380 [('p', 'strip', 1,
3387 [('p', 'strip', 1,
3381 _('directory strip option for patch. This has the same '
3388 _('directory strip option for patch. This has the same '
3382 'meaning as the corresponding patch option'), _('NUM')),
3389 'meaning as the corresponding patch option'), _('NUM')),
3383 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3390 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3384 ('e', 'edit', False, _('invoke editor on commit messages')),
3391 ('e', 'edit', False, _('invoke editor on commit messages')),
3385 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3392 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3386 ('', 'no-commit', None,
3393 ('', 'no-commit', None,
3387 _("don't commit, just update the working directory")),
3394 _("don't commit, just update the working directory")),
3388 ('', 'bypass', None,
3395 ('', 'bypass', None,
3389 _("apply patch without touching the working directory")),
3396 _("apply patch without touching the working directory")),
3390 ('', 'exact', None,
3397 ('', 'exact', None,
3391 _('apply patch to the nodes from which it was generated')),
3398 _('apply patch to the nodes from which it was generated')),
3392 ('', 'import-branch', None,
3399 ('', 'import-branch', None,
3393 _('use any branch information in patch (implied by --exact)'))] +
3400 _('use any branch information in patch (implied by --exact)'))] +
3394 commitopts + commitopts2 + similarityopts,
3401 commitopts + commitopts2 + similarityopts,
3395 _('[OPTION]... PATCH...'))
3402 _('[OPTION]... PATCH...'))
3396 def import_(ui, repo, patch1=None, *patches, **opts):
3403 def import_(ui, repo, patch1=None, *patches, **opts):
3397 """import an ordered set of patches
3404 """import an ordered set of patches
3398
3405
3399 Import a list of patches and commit them individually (unless
3406 Import a list of patches and commit them individually (unless
3400 --no-commit is specified).
3407 --no-commit is specified).
3401
3408
3402 If there are outstanding changes in the working directory, import
3409 If there are outstanding changes in the working directory, import
3403 will abort unless given the -f/--force flag.
3410 will abort unless given the -f/--force flag.
3404
3411
3405 You can import a patch straight from a mail message. Even patches
3412 You can import a patch straight from a mail message. Even patches
3406 as attachments work (to use the body part, it must have type
3413 as attachments work (to use the body part, it must have type
3407 text/plain or text/x-patch). From and Subject headers of email
3414 text/plain or text/x-patch). From and Subject headers of email
3408 message are used as default committer and commit message. All
3415 message are used as default committer and commit message. All
3409 text/plain body parts before first diff are added to commit
3416 text/plain body parts before first diff are added to commit
3410 message.
3417 message.
3411
3418
3412 If the imported patch was generated by :hg:`export`, user and
3419 If the imported patch was generated by :hg:`export`, user and
3413 description from patch override values from message headers and
3420 description from patch override values from message headers and
3414 body. Values given on command line with -m/--message and -u/--user
3421 body. Values given on command line with -m/--message and -u/--user
3415 override these.
3422 override these.
3416
3423
3417 If --exact is specified, import will set the working directory to
3424 If --exact is specified, import will set the working directory to
3418 the parent of each patch before applying it, and will abort if the
3425 the parent of each patch before applying it, and will abort if the
3419 resulting changeset has a different ID than the one recorded in
3426 resulting changeset has a different ID than the one recorded in
3420 the patch. This may happen due to character set problems or other
3427 the patch. This may happen due to character set problems or other
3421 deficiencies in the text patch format.
3428 deficiencies in the text patch format.
3422
3429
3423 Use --bypass to apply and commit patches directly to the
3430 Use --bypass to apply and commit patches directly to the
3424 repository, not touching the working directory. Without --exact,
3431 repository, not touching the working directory. Without --exact,
3425 patches will be applied on top of the working directory parent
3432 patches will be applied on top of the working directory parent
3426 revision.
3433 revision.
3427
3434
3428 With -s/--similarity, hg will attempt to discover renames and
3435 With -s/--similarity, hg will attempt to discover renames and
3429 copies in the patch in the same way as :hg:`addremove`.
3436 copies in the patch in the same way as :hg:`addremove`.
3430
3437
3431 To read a patch from standard input, use "-" as the patch name. If
3438 To read a patch from standard input, use "-" as the patch name. If
3432 a URL is specified, the patch will be downloaded from it.
3439 a URL is specified, the patch will be downloaded from it.
3433 See :hg:`help dates` for a list of formats valid for -d/--date.
3440 See :hg:`help dates` for a list of formats valid for -d/--date.
3434
3441
3435 .. container:: verbose
3442 .. container:: verbose
3436
3443
3437 Examples:
3444 Examples:
3438
3445
3439 - import a traditional patch from a website and detect renames::
3446 - import a traditional patch from a website and detect renames::
3440
3447
3441 hg import -s 80 http://example.com/bugfix.patch
3448 hg import -s 80 http://example.com/bugfix.patch
3442
3449
3443 - import a changeset from an hgweb server::
3450 - import a changeset from an hgweb server::
3444
3451
3445 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3452 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3446
3453
3447 - import all the patches in an Unix-style mbox::
3454 - import all the patches in an Unix-style mbox::
3448
3455
3449 hg import incoming-patches.mbox
3456 hg import incoming-patches.mbox
3450
3457
3451 - attempt to exactly restore an exported changeset (not always
3458 - attempt to exactly restore an exported changeset (not always
3452 possible)::
3459 possible)::
3453
3460
3454 hg import --exact proposed-fix.patch
3461 hg import --exact proposed-fix.patch
3455
3462
3456 Returns 0 on success.
3463 Returns 0 on success.
3457 """
3464 """
3458
3465
3459 if not patch1:
3466 if not patch1:
3460 raise util.Abort(_('need at least one patch to import'))
3467 raise util.Abort(_('need at least one patch to import'))
3461
3468
3462 patches = (patch1,) + patches
3469 patches = (patch1,) + patches
3463
3470
3464 date = opts.get('date')
3471 date = opts.get('date')
3465 if date:
3472 if date:
3466 opts['date'] = util.parsedate(date)
3473 opts['date'] = util.parsedate(date)
3467
3474
3468 editor = cmdutil.commiteditor
3475 editor = cmdutil.commiteditor
3469 if opts.get('edit'):
3476 if opts.get('edit'):
3470 editor = cmdutil.commitforceeditor
3477 editor = cmdutil.commitforceeditor
3471
3478
3472 update = not opts.get('bypass')
3479 update = not opts.get('bypass')
3473 if not update and opts.get('no_commit'):
3480 if not update and opts.get('no_commit'):
3474 raise util.Abort(_('cannot use --no-commit with --bypass'))
3481 raise util.Abort(_('cannot use --no-commit with --bypass'))
3475 try:
3482 try:
3476 sim = float(opts.get('similarity') or 0)
3483 sim = float(opts.get('similarity') or 0)
3477 except ValueError:
3484 except ValueError:
3478 raise util.Abort(_('similarity must be a number'))
3485 raise util.Abort(_('similarity must be a number'))
3479 if sim < 0 or sim > 100:
3486 if sim < 0 or sim > 100:
3480 raise util.Abort(_('similarity must be between 0 and 100'))
3487 raise util.Abort(_('similarity must be between 0 and 100'))
3481 if sim and not update:
3488 if sim and not update:
3482 raise util.Abort(_('cannot use --similarity with --bypass'))
3489 raise util.Abort(_('cannot use --similarity with --bypass'))
3483
3490
3484 if (opts.get('exact') or not opts.get('force')) and update:
3491 if (opts.get('exact') or not opts.get('force')) and update:
3485 cmdutil.bailifchanged(repo)
3492 cmdutil.bailifchanged(repo)
3486
3493
3487 base = opts["base"]
3494 base = opts["base"]
3488 strip = opts["strip"]
3495 strip = opts["strip"]
3489 wlock = lock = tr = None
3496 wlock = lock = tr = None
3490 msgs = []
3497 msgs = []
3491
3498
3492 def checkexact(repo, n, nodeid):
3499 def checkexact(repo, n, nodeid):
3493 if opts.get('exact') and hex(n) != nodeid:
3500 if opts.get('exact') and hex(n) != nodeid:
3494 raise util.Abort(_('patch is damaged or loses information'))
3501 raise util.Abort(_('patch is damaged or loses information'))
3495
3502
3496 def tryone(ui, hunk, parents):
3503 def tryone(ui, hunk, parents):
3497 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3504 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3498 patch.extract(ui, hunk)
3505 patch.extract(ui, hunk)
3499
3506
3500 if not tmpname:
3507 if not tmpname:
3501 return (None, None)
3508 return (None, None)
3502 msg = _('applied to working directory')
3509 msg = _('applied to working directory')
3503
3510
3504 try:
3511 try:
3505 cmdline_message = cmdutil.logmessage(ui, opts)
3512 cmdline_message = cmdutil.logmessage(ui, opts)
3506 if cmdline_message:
3513 if cmdline_message:
3507 # pickup the cmdline msg
3514 # pickup the cmdline msg
3508 message = cmdline_message
3515 message = cmdline_message
3509 elif message:
3516 elif message:
3510 # pickup the patch msg
3517 # pickup the patch msg
3511 message = message.strip()
3518 message = message.strip()
3512 else:
3519 else:
3513 # launch the editor
3520 # launch the editor
3514 message = None
3521 message = None
3515 ui.debug('message:\n%s\n' % message)
3522 ui.debug('message:\n%s\n' % message)
3516
3523
3517 if len(parents) == 1:
3524 if len(parents) == 1:
3518 parents.append(repo[nullid])
3525 parents.append(repo[nullid])
3519 if opts.get('exact'):
3526 if opts.get('exact'):
3520 if not nodeid or not p1:
3527 if not nodeid or not p1:
3521 raise util.Abort(_('not a Mercurial patch'))
3528 raise util.Abort(_('not a Mercurial patch'))
3522 p1 = repo[p1]
3529 p1 = repo[p1]
3523 p2 = repo[p2 or nullid]
3530 p2 = repo[p2 or nullid]
3524 elif p2:
3531 elif p2:
3525 try:
3532 try:
3526 p1 = repo[p1]
3533 p1 = repo[p1]
3527 p2 = repo[p2]
3534 p2 = repo[p2]
3528 # Without any options, consider p2 only if the
3535 # Without any options, consider p2 only if the
3529 # patch is being applied on top of the recorded
3536 # patch is being applied on top of the recorded
3530 # first parent.
3537 # first parent.
3531 if p1 != parents[0]:
3538 if p1 != parents[0]:
3532 p1 = parents[0]
3539 p1 = parents[0]
3533 p2 = repo[nullid]
3540 p2 = repo[nullid]
3534 except error.RepoError:
3541 except error.RepoError:
3535 p1, p2 = parents
3542 p1, p2 = parents
3536 else:
3543 else:
3537 p1, p2 = parents
3544 p1, p2 = parents
3538
3545
3539 n = None
3546 n = None
3540 if update:
3547 if update:
3541 if p1 != parents[0]:
3548 if p1 != parents[0]:
3542 hg.clean(repo, p1.node())
3549 hg.clean(repo, p1.node())
3543 if p2 != parents[1]:
3550 if p2 != parents[1]:
3544 repo.setparents(p1.node(), p2.node())
3551 repo.setparents(p1.node(), p2.node())
3545
3552
3546 if opts.get('exact') or opts.get('import_branch'):
3553 if opts.get('exact') or opts.get('import_branch'):
3547 repo.dirstate.setbranch(branch or 'default')
3554 repo.dirstate.setbranch(branch or 'default')
3548
3555
3549 files = set()
3556 files = set()
3550 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3557 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3551 eolmode=None, similarity=sim / 100.0)
3558 eolmode=None, similarity=sim / 100.0)
3552 files = list(files)
3559 files = list(files)
3553 if opts.get('no_commit'):
3560 if opts.get('no_commit'):
3554 if message:
3561 if message:
3555 msgs.append(message)
3562 msgs.append(message)
3556 else:
3563 else:
3557 if opts.get('exact') or p2:
3564 if opts.get('exact') or p2:
3558 # If you got here, you either use --force and know what
3565 # If you got here, you either use --force and know what
3559 # you are doing or used --exact or a merge patch while
3566 # you are doing or used --exact or a merge patch while
3560 # being updated to its first parent.
3567 # being updated to its first parent.
3561 m = None
3568 m = None
3562 else:
3569 else:
3563 m = scmutil.matchfiles(repo, files or [])
3570 m = scmutil.matchfiles(repo, files or [])
3564 n = repo.commit(message, opts.get('user') or user,
3571 n = repo.commit(message, opts.get('user') or user,
3565 opts.get('date') or date, match=m,
3572 opts.get('date') or date, match=m,
3566 editor=editor)
3573 editor=editor)
3567 checkexact(repo, n, nodeid)
3574 checkexact(repo, n, nodeid)
3568 else:
3575 else:
3569 if opts.get('exact') or opts.get('import_branch'):
3576 if opts.get('exact') or opts.get('import_branch'):
3570 branch = branch or 'default'
3577 branch = branch or 'default'
3571 else:
3578 else:
3572 branch = p1.branch()
3579 branch = p1.branch()
3573 store = patch.filestore()
3580 store = patch.filestore()
3574 try:
3581 try:
3575 files = set()
3582 files = set()
3576 try:
3583 try:
3577 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3584 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3578 files, eolmode=None)
3585 files, eolmode=None)
3579 except patch.PatchError, e:
3586 except patch.PatchError, e:
3580 raise util.Abort(str(e))
3587 raise util.Abort(str(e))
3581 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3588 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3582 message,
3589 message,
3583 opts.get('user') or user,
3590 opts.get('user') or user,
3584 opts.get('date') or date,
3591 opts.get('date') or date,
3585 branch, files, store,
3592 branch, files, store,
3586 editor=cmdutil.commiteditor)
3593 editor=cmdutil.commiteditor)
3587 repo.savecommitmessage(memctx.description())
3594 repo.savecommitmessage(memctx.description())
3588 n = memctx.commit()
3595 n = memctx.commit()
3589 checkexact(repo, n, nodeid)
3596 checkexact(repo, n, nodeid)
3590 finally:
3597 finally:
3591 store.close()
3598 store.close()
3592 if n:
3599 if n:
3593 # i18n: refers to a short changeset id
3600 # i18n: refers to a short changeset id
3594 msg = _('created %s') % short(n)
3601 msg = _('created %s') % short(n)
3595 return (msg, n)
3602 return (msg, n)
3596 finally:
3603 finally:
3597 os.unlink(tmpname)
3604 os.unlink(tmpname)
3598
3605
3599 try:
3606 try:
3600 try:
3607 try:
3601 wlock = repo.wlock()
3608 wlock = repo.wlock()
3602 if not opts.get('no_commit'):
3609 if not opts.get('no_commit'):
3603 lock = repo.lock()
3610 lock = repo.lock()
3604 tr = repo.transaction('import')
3611 tr = repo.transaction('import')
3605 parents = repo.parents()
3612 parents = repo.parents()
3606 for patchurl in patches:
3613 for patchurl in patches:
3607 if patchurl == '-':
3614 if patchurl == '-':
3608 ui.status(_('applying patch from stdin\n'))
3615 ui.status(_('applying patch from stdin\n'))
3609 patchfile = ui.fin
3616 patchfile = ui.fin
3610 patchurl = 'stdin' # for error message
3617 patchurl = 'stdin' # for error message
3611 else:
3618 else:
3612 patchurl = os.path.join(base, patchurl)
3619 patchurl = os.path.join(base, patchurl)
3613 ui.status(_('applying %s\n') % patchurl)
3620 ui.status(_('applying %s\n') % patchurl)
3614 patchfile = hg.openpath(ui, patchurl)
3621 patchfile = hg.openpath(ui, patchurl)
3615
3622
3616 haspatch = False
3623 haspatch = False
3617 for hunk in patch.split(patchfile):
3624 for hunk in patch.split(patchfile):
3618 (msg, node) = tryone(ui, hunk, parents)
3625 (msg, node) = tryone(ui, hunk, parents)
3619 if msg:
3626 if msg:
3620 haspatch = True
3627 haspatch = True
3621 ui.note(msg + '\n')
3628 ui.note(msg + '\n')
3622 if update or opts.get('exact'):
3629 if update or opts.get('exact'):
3623 parents = repo.parents()
3630 parents = repo.parents()
3624 else:
3631 else:
3625 parents = [repo[node]]
3632 parents = [repo[node]]
3626
3633
3627 if not haspatch:
3634 if not haspatch:
3628 raise util.Abort(_('%s: no diffs found') % patchurl)
3635 raise util.Abort(_('%s: no diffs found') % patchurl)
3629
3636
3630 if tr:
3637 if tr:
3631 tr.close()
3638 tr.close()
3632 if msgs:
3639 if msgs:
3633 repo.savecommitmessage('\n* * *\n'.join(msgs))
3640 repo.savecommitmessage('\n* * *\n'.join(msgs))
3634 except: # re-raises
3641 except: # re-raises
3635 # wlock.release() indirectly calls dirstate.write(): since
3642 # wlock.release() indirectly calls dirstate.write(): since
3636 # we're crashing, we do not want to change the working dir
3643 # we're crashing, we do not want to change the working dir
3637 # parent after all, so make sure it writes nothing
3644 # parent after all, so make sure it writes nothing
3638 repo.dirstate.invalidate()
3645 repo.dirstate.invalidate()
3639 raise
3646 raise
3640 finally:
3647 finally:
3641 if tr:
3648 if tr:
3642 tr.release()
3649 tr.release()
3643 release(lock, wlock)
3650 release(lock, wlock)
3644
3651
3645 @command('incoming|in',
3652 @command('incoming|in',
3646 [('f', 'force', None,
3653 [('f', 'force', None,
3647 _('run even if remote repository is unrelated')),
3654 _('run even if remote repository is unrelated')),
3648 ('n', 'newest-first', None, _('show newest record first')),
3655 ('n', 'newest-first', None, _('show newest record first')),
3649 ('', 'bundle', '',
3656 ('', 'bundle', '',
3650 _('file to store the bundles into'), _('FILE')),
3657 _('file to store the bundles into'), _('FILE')),
3651 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3658 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3652 ('B', 'bookmarks', False, _("compare bookmarks")),
3659 ('B', 'bookmarks', False, _("compare bookmarks")),
3653 ('b', 'branch', [],
3660 ('b', 'branch', [],
3654 _('a specific branch you would like to pull'), _('BRANCH')),
3661 _('a specific branch you would like to pull'), _('BRANCH')),
3655 ] + logopts + remoteopts + subrepoopts,
3662 ] + logopts + remoteopts + subrepoopts,
3656 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3663 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3657 def incoming(ui, repo, source="default", **opts):
3664 def incoming(ui, repo, source="default", **opts):
3658 """show new changesets found in source
3665 """show new changesets found in source
3659
3666
3660 Show new changesets found in the specified path/URL or the default
3667 Show new changesets found in the specified path/URL or the default
3661 pull location. These are the changesets that would have been pulled
3668 pull location. These are the changesets that would have been pulled
3662 if a pull at the time you issued this command.
3669 if a pull at the time you issued this command.
3663
3670
3664 For remote repository, using --bundle avoids downloading the
3671 For remote repository, using --bundle avoids downloading the
3665 changesets twice if the incoming is followed by a pull.
3672 changesets twice if the incoming is followed by a pull.
3666
3673
3667 See pull for valid source format details.
3674 See pull for valid source format details.
3668
3675
3669 Returns 0 if there are incoming changes, 1 otherwise.
3676 Returns 0 if there are incoming changes, 1 otherwise.
3670 """
3677 """
3671 if opts.get('graph'):
3678 if opts.get('graph'):
3672 cmdutil.checkunsupportedgraphflags([], opts)
3679 cmdutil.checkunsupportedgraphflags([], opts)
3673 def display(other, chlist, displayer):
3680 def display(other, chlist, displayer):
3674 revdag = cmdutil.graphrevs(other, chlist, opts)
3681 revdag = cmdutil.graphrevs(other, chlist, opts)
3675 showparents = [ctx.node() for ctx in repo[None].parents()]
3682 showparents = [ctx.node() for ctx in repo[None].parents()]
3676 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3683 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3677 graphmod.asciiedges)
3684 graphmod.asciiedges)
3678
3685
3679 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3686 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3680 return 0
3687 return 0
3681
3688
3682 if opts.get('bundle') and opts.get('subrepos'):
3689 if opts.get('bundle') and opts.get('subrepos'):
3683 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3690 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3684
3691
3685 if opts.get('bookmarks'):
3692 if opts.get('bookmarks'):
3686 source, branches = hg.parseurl(ui.expandpath(source),
3693 source, branches = hg.parseurl(ui.expandpath(source),
3687 opts.get('branch'))
3694 opts.get('branch'))
3688 other = hg.peer(repo, opts, source)
3695 other = hg.peer(repo, opts, source)
3689 if 'bookmarks' not in other.listkeys('namespaces'):
3696 if 'bookmarks' not in other.listkeys('namespaces'):
3690 ui.warn(_("remote doesn't support bookmarks\n"))
3697 ui.warn(_("remote doesn't support bookmarks\n"))
3691 return 0
3698 return 0
3692 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3699 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3693 return bookmarks.diff(ui, repo, other)
3700 return bookmarks.diff(ui, repo, other)
3694
3701
3695 repo._subtoppath = ui.expandpath(source)
3702 repo._subtoppath = ui.expandpath(source)
3696 try:
3703 try:
3697 return hg.incoming(ui, repo, source, opts)
3704 return hg.incoming(ui, repo, source, opts)
3698 finally:
3705 finally:
3699 del repo._subtoppath
3706 del repo._subtoppath
3700
3707
3701
3708
3702 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3709 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3703 def init(ui, dest=".", **opts):
3710 def init(ui, dest=".", **opts):
3704 """create a new repository in the given directory
3711 """create a new repository in the given directory
3705
3712
3706 Initialize a new repository in the given directory. If the given
3713 Initialize a new repository in the given directory. If the given
3707 directory does not exist, it will be created.
3714 directory does not exist, it will be created.
3708
3715
3709 If no directory is given, the current directory is used.
3716 If no directory is given, the current directory is used.
3710
3717
3711 It is possible to specify an ``ssh://`` URL as the destination.
3718 It is possible to specify an ``ssh://`` URL as the destination.
3712 See :hg:`help urls` for more information.
3719 See :hg:`help urls` for more information.
3713
3720
3714 Returns 0 on success.
3721 Returns 0 on success.
3715 """
3722 """
3716 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3723 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3717
3724
3718 @command('locate',
3725 @command('locate',
3719 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3726 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3720 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3727 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3721 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3728 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3722 ] + walkopts,
3729 ] + walkopts,
3723 _('[OPTION]... [PATTERN]...'))
3730 _('[OPTION]... [PATTERN]...'))
3724 def locate(ui, repo, *pats, **opts):
3731 def locate(ui, repo, *pats, **opts):
3725 """locate files matching specific patterns
3732 """locate files matching specific patterns
3726
3733
3727 Print files under Mercurial control in the working directory whose
3734 Print files under Mercurial control in the working directory whose
3728 names match the given patterns.
3735 names match the given patterns.
3729
3736
3730 By default, this command searches all directories in the working
3737 By default, this command searches all directories in the working
3731 directory. To search just the current directory and its
3738 directory. To search just the current directory and its
3732 subdirectories, use "--include .".
3739 subdirectories, use "--include .".
3733
3740
3734 If no patterns are given to match, this command prints the names
3741 If no patterns are given to match, this command prints the names
3735 of all files under Mercurial control in the working directory.
3742 of all files under Mercurial control in the working directory.
3736
3743
3737 If you want to feed the output of this command into the "xargs"
3744 If you want to feed the output of this command into the "xargs"
3738 command, use the -0 option to both this command and "xargs". This
3745 command, use the -0 option to both this command and "xargs". This
3739 will avoid the problem of "xargs" treating single filenames that
3746 will avoid the problem of "xargs" treating single filenames that
3740 contain whitespace as multiple filenames.
3747 contain whitespace as multiple filenames.
3741
3748
3742 Returns 0 if a match is found, 1 otherwise.
3749 Returns 0 if a match is found, 1 otherwise.
3743 """
3750 """
3744 end = opts.get('print0') and '\0' or '\n'
3751 end = opts.get('print0') and '\0' or '\n'
3745 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3752 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3746
3753
3747 ret = 1
3754 ret = 1
3748 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3755 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3749 m.bad = lambda x, y: False
3756 m.bad = lambda x, y: False
3750 for abs in repo[rev].walk(m):
3757 for abs in repo[rev].walk(m):
3751 if not rev and abs not in repo.dirstate:
3758 if not rev and abs not in repo.dirstate:
3752 continue
3759 continue
3753 if opts.get('fullpath'):
3760 if opts.get('fullpath'):
3754 ui.write(repo.wjoin(abs), end)
3761 ui.write(repo.wjoin(abs), end)
3755 else:
3762 else:
3756 ui.write(((pats and m.rel(abs)) or abs), end)
3763 ui.write(((pats and m.rel(abs)) or abs), end)
3757 ret = 0
3764 ret = 0
3758
3765
3759 return ret
3766 return ret
3760
3767
3761 @command('^log|history',
3768 @command('^log|history',
3762 [('f', 'follow', None,
3769 [('f', 'follow', None,
3763 _('follow changeset history, or file history across copies and renames')),
3770 _('follow changeset history, or file history across copies and renames')),
3764 ('', 'follow-first', None,
3771 ('', 'follow-first', None,
3765 _('only follow the first parent of merge changesets (DEPRECATED)')),
3772 _('only follow the first parent of merge changesets (DEPRECATED)')),
3766 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3773 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3767 ('C', 'copies', None, _('show copied files')),
3774 ('C', 'copies', None, _('show copied files')),
3768 ('k', 'keyword', [],
3775 ('k', 'keyword', [],
3769 _('do case-insensitive search for a given text'), _('TEXT')),
3776 _('do case-insensitive search for a given text'), _('TEXT')),
3770 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3777 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3771 ('', 'removed', None, _('include revisions where files were removed')),
3778 ('', 'removed', None, _('include revisions where files were removed')),
3772 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3779 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3773 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3780 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3774 ('', 'only-branch', [],
3781 ('', 'only-branch', [],
3775 _('show only changesets within the given named branch (DEPRECATED)'),
3782 _('show only changesets within the given named branch (DEPRECATED)'),
3776 _('BRANCH')),
3783 _('BRANCH')),
3777 ('b', 'branch', [],
3784 ('b', 'branch', [],
3778 _('show changesets within the given named branch'), _('BRANCH')),
3785 _('show changesets within the given named branch'), _('BRANCH')),
3779 ('P', 'prune', [],
3786 ('P', 'prune', [],
3780 _('do not display revision or any of its ancestors'), _('REV')),
3787 _('do not display revision or any of its ancestors'), _('REV')),
3781 ] + logopts + walkopts,
3788 ] + logopts + walkopts,
3782 _('[OPTION]... [FILE]'))
3789 _('[OPTION]... [FILE]'))
3783 def log(ui, repo, *pats, **opts):
3790 def log(ui, repo, *pats, **opts):
3784 """show revision history of entire repository or files
3791 """show revision history of entire repository or files
3785
3792
3786 Print the revision history of the specified files or the entire
3793 Print the revision history of the specified files or the entire
3787 project.
3794 project.
3788
3795
3789 If no revision range is specified, the default is ``tip:0`` unless
3796 If no revision range is specified, the default is ``tip:0`` unless
3790 --follow is set, in which case the working directory parent is
3797 --follow is set, in which case the working directory parent is
3791 used as the starting revision.
3798 used as the starting revision.
3792
3799
3793 File history is shown without following rename or copy history of
3800 File history is shown without following rename or copy history of
3794 files. Use -f/--follow with a filename to follow history across
3801 files. Use -f/--follow with a filename to follow history across
3795 renames and copies. --follow without a filename will only show
3802 renames and copies. --follow without a filename will only show
3796 ancestors or descendants of the starting revision.
3803 ancestors or descendants of the starting revision.
3797
3804
3798 By default this command prints revision number and changeset id,
3805 By default this command prints revision number and changeset id,
3799 tags, non-trivial parents, user, date and time, and a summary for
3806 tags, non-trivial parents, user, date and time, and a summary for
3800 each commit. When the -v/--verbose switch is used, the list of
3807 each commit. When the -v/--verbose switch is used, the list of
3801 changed files and full commit message are shown.
3808 changed files and full commit message are shown.
3802
3809
3803 .. note::
3810 .. note::
3804 log -p/--patch may generate unexpected diff output for merge
3811 log -p/--patch may generate unexpected diff output for merge
3805 changesets, as it will only compare the merge changeset against
3812 changesets, as it will only compare the merge changeset against
3806 its first parent. Also, only files different from BOTH parents
3813 its first parent. Also, only files different from BOTH parents
3807 will appear in files:.
3814 will appear in files:.
3808
3815
3809 .. note::
3816 .. note::
3810 for performance reasons, log FILE may omit duplicate changes
3817 for performance reasons, log FILE may omit duplicate changes
3811 made on branches and will not show deletions. To see all
3818 made on branches and will not show deletions. To see all
3812 changes including duplicates and deletions, use the --removed
3819 changes including duplicates and deletions, use the --removed
3813 switch.
3820 switch.
3814
3821
3815 .. container:: verbose
3822 .. container:: verbose
3816
3823
3817 Some examples:
3824 Some examples:
3818
3825
3819 - changesets with full descriptions and file lists::
3826 - changesets with full descriptions and file lists::
3820
3827
3821 hg log -v
3828 hg log -v
3822
3829
3823 - changesets ancestral to the working directory::
3830 - changesets ancestral to the working directory::
3824
3831
3825 hg log -f
3832 hg log -f
3826
3833
3827 - last 10 commits on the current branch::
3834 - last 10 commits on the current branch::
3828
3835
3829 hg log -l 10 -b .
3836 hg log -l 10 -b .
3830
3837
3831 - changesets showing all modifications of a file, including removals::
3838 - changesets showing all modifications of a file, including removals::
3832
3839
3833 hg log --removed file.c
3840 hg log --removed file.c
3834
3841
3835 - all changesets that touch a directory, with diffs, excluding merges::
3842 - all changesets that touch a directory, with diffs, excluding merges::
3836
3843
3837 hg log -Mp lib/
3844 hg log -Mp lib/
3838
3845
3839 - all revision numbers that match a keyword::
3846 - all revision numbers that match a keyword::
3840
3847
3841 hg log -k bug --template "{rev}\\n"
3848 hg log -k bug --template "{rev}\\n"
3842
3849
3843 - check if a given changeset is included is a tagged release::
3850 - check if a given changeset is included is a tagged release::
3844
3851
3845 hg log -r "a21ccf and ancestor(1.9)"
3852 hg log -r "a21ccf and ancestor(1.9)"
3846
3853
3847 - find all changesets by some user in a date range::
3854 - find all changesets by some user in a date range::
3848
3855
3849 hg log -k alice -d "may 2008 to jul 2008"
3856 hg log -k alice -d "may 2008 to jul 2008"
3850
3857
3851 - summary of all changesets after the last tag::
3858 - summary of all changesets after the last tag::
3852
3859
3853 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3860 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3854
3861
3855 See :hg:`help dates` for a list of formats valid for -d/--date.
3862 See :hg:`help dates` for a list of formats valid for -d/--date.
3856
3863
3857 See :hg:`help revisions` and :hg:`help revsets` for more about
3864 See :hg:`help revisions` and :hg:`help revsets` for more about
3858 specifying revisions.
3865 specifying revisions.
3859
3866
3860 See :hg:`help templates` for more about pre-packaged styles and
3867 See :hg:`help templates` for more about pre-packaged styles and
3861 specifying custom templates.
3868 specifying custom templates.
3862
3869
3863 Returns 0 on success.
3870 Returns 0 on success.
3864 """
3871 """
3865 if opts.get('graph'):
3872 if opts.get('graph'):
3866 return cmdutil.graphlog(ui, repo, *pats, **opts)
3873 return cmdutil.graphlog(ui, repo, *pats, **opts)
3867
3874
3868 matchfn = scmutil.match(repo[None], pats, opts)
3875 matchfn = scmutil.match(repo[None], pats, opts)
3869 limit = cmdutil.loglimit(opts)
3876 limit = cmdutil.loglimit(opts)
3870 count = 0
3877 count = 0
3871
3878
3872 getrenamed, endrev = None, None
3879 getrenamed, endrev = None, None
3873 if opts.get('copies'):
3880 if opts.get('copies'):
3874 if opts.get('rev'):
3881 if opts.get('rev'):
3875 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3882 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3876 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3883 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3877
3884
3878 df = False
3885 df = False
3879 if opts.get("date"):
3886 if opts.get("date"):
3880 df = util.matchdate(opts["date"])
3887 df = util.matchdate(opts["date"])
3881
3888
3882 branches = opts.get('branch', []) + opts.get('only_branch', [])
3889 branches = opts.get('branch', []) + opts.get('only_branch', [])
3883 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3890 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3884
3891
3885 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3892 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3886 def prep(ctx, fns):
3893 def prep(ctx, fns):
3887 rev = ctx.rev()
3894 rev = ctx.rev()
3888 parents = [p for p in repo.changelog.parentrevs(rev)
3895 parents = [p for p in repo.changelog.parentrevs(rev)
3889 if p != nullrev]
3896 if p != nullrev]
3890 if opts.get('no_merges') and len(parents) == 2:
3897 if opts.get('no_merges') and len(parents) == 2:
3891 return
3898 return
3892 if opts.get('only_merges') and len(parents) != 2:
3899 if opts.get('only_merges') and len(parents) != 2:
3893 return
3900 return
3894 if opts.get('branch') and ctx.branch() not in opts['branch']:
3901 if opts.get('branch') and ctx.branch() not in opts['branch']:
3895 return
3902 return
3896 if df and not df(ctx.date()[0]):
3903 if df and not df(ctx.date()[0]):
3897 return
3904 return
3898
3905
3899 lower = encoding.lower
3906 lower = encoding.lower
3900 if opts.get('user'):
3907 if opts.get('user'):
3901 luser = lower(ctx.user())
3908 luser = lower(ctx.user())
3902 for k in [lower(x) for x in opts['user']]:
3909 for k in [lower(x) for x in opts['user']]:
3903 if (k in luser):
3910 if (k in luser):
3904 break
3911 break
3905 else:
3912 else:
3906 return
3913 return
3907 if opts.get('keyword'):
3914 if opts.get('keyword'):
3908 luser = lower(ctx.user())
3915 luser = lower(ctx.user())
3909 ldesc = lower(ctx.description())
3916 ldesc = lower(ctx.description())
3910 lfiles = lower(" ".join(ctx.files()))
3917 lfiles = lower(" ".join(ctx.files()))
3911 for k in [lower(x) for x in opts['keyword']]:
3918 for k in [lower(x) for x in opts['keyword']]:
3912 if (k in luser or k in ldesc or k in lfiles):
3919 if (k in luser or k in ldesc or k in lfiles):
3913 break
3920 break
3914 else:
3921 else:
3915 return
3922 return
3916
3923
3917 copies = None
3924 copies = None
3918 if getrenamed is not None and rev:
3925 if getrenamed is not None and rev:
3919 copies = []
3926 copies = []
3920 for fn in ctx.files():
3927 for fn in ctx.files():
3921 rename = getrenamed(fn, rev)
3928 rename = getrenamed(fn, rev)
3922 if rename:
3929 if rename:
3923 copies.append((fn, rename[0]))
3930 copies.append((fn, rename[0]))
3924
3931
3925 revmatchfn = None
3932 revmatchfn = None
3926 if opts.get('patch') or opts.get('stat'):
3933 if opts.get('patch') or opts.get('stat'):
3927 if opts.get('follow') or opts.get('follow_first'):
3934 if opts.get('follow') or opts.get('follow_first'):
3928 # note: this might be wrong when following through merges
3935 # note: this might be wrong when following through merges
3929 revmatchfn = scmutil.match(repo[None], fns, default='path')
3936 revmatchfn = scmutil.match(repo[None], fns, default='path')
3930 else:
3937 else:
3931 revmatchfn = matchfn
3938 revmatchfn = matchfn
3932
3939
3933 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3940 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3934
3941
3935 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3942 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3936 if displayer.flush(ctx.rev()):
3943 if displayer.flush(ctx.rev()):
3937 count += 1
3944 count += 1
3938 if count == limit:
3945 if count == limit:
3939 break
3946 break
3940 displayer.close()
3947 displayer.close()
3941
3948
3942 @command('manifest',
3949 @command('manifest',
3943 [('r', 'rev', '', _('revision to display'), _('REV')),
3950 [('r', 'rev', '', _('revision to display'), _('REV')),
3944 ('', 'all', False, _("list files from all revisions"))],
3951 ('', 'all', False, _("list files from all revisions"))],
3945 _('[-r REV]'))
3952 _('[-r REV]'))
3946 def manifest(ui, repo, node=None, rev=None, **opts):
3953 def manifest(ui, repo, node=None, rev=None, **opts):
3947 """output the current or given revision of the project manifest
3954 """output the current or given revision of the project manifest
3948
3955
3949 Print a list of version controlled files for the given revision.
3956 Print a list of version controlled files for the given revision.
3950 If no revision is given, the first parent of the working directory
3957 If no revision is given, the first parent of the working directory
3951 is used, or the null revision if no revision is checked out.
3958 is used, or the null revision if no revision is checked out.
3952
3959
3953 With -v, print file permissions, symlink and executable bits.
3960 With -v, print file permissions, symlink and executable bits.
3954 With --debug, print file revision hashes.
3961 With --debug, print file revision hashes.
3955
3962
3956 If option --all is specified, the list of all files from all revisions
3963 If option --all is specified, the list of all files from all revisions
3957 is printed. This includes deleted and renamed files.
3964 is printed. This includes deleted and renamed files.
3958
3965
3959 Returns 0 on success.
3966 Returns 0 on success.
3960 """
3967 """
3961
3968
3962 fm = ui.formatter('manifest', opts)
3969 fm = ui.formatter('manifest', opts)
3963
3970
3964 if opts.get('all'):
3971 if opts.get('all'):
3965 if rev or node:
3972 if rev or node:
3966 raise util.Abort(_("can't specify a revision with --all"))
3973 raise util.Abort(_("can't specify a revision with --all"))
3967
3974
3968 res = []
3975 res = []
3969 prefix = "data/"
3976 prefix = "data/"
3970 suffix = ".i"
3977 suffix = ".i"
3971 plen = len(prefix)
3978 plen = len(prefix)
3972 slen = len(suffix)
3979 slen = len(suffix)
3973 lock = repo.lock()
3980 lock = repo.lock()
3974 try:
3981 try:
3975 for fn, b, size in repo.store.datafiles():
3982 for fn, b, size in repo.store.datafiles():
3976 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3983 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3977 res.append(fn[plen:-slen])
3984 res.append(fn[plen:-slen])
3978 finally:
3985 finally:
3979 lock.release()
3986 lock.release()
3980 for f in res:
3987 for f in res:
3981 fm.startitem()
3988 fm.startitem()
3982 fm.write("path", '%s\n', f)
3989 fm.write("path", '%s\n', f)
3983 fm.end()
3990 fm.end()
3984 return
3991 return
3985
3992
3986 if rev and node:
3993 if rev and node:
3987 raise util.Abort(_("please specify just one revision"))
3994 raise util.Abort(_("please specify just one revision"))
3988
3995
3989 if not node:
3996 if not node:
3990 node = rev
3997 node = rev
3991
3998
3992 char = {'l': '@', 'x': '*', '': ''}
3999 char = {'l': '@', 'x': '*', '': ''}
3993 mode = {'l': '644', 'x': '755', '': '644'}
4000 mode = {'l': '644', 'x': '755', '': '644'}
3994 ctx = scmutil.revsingle(repo, node)
4001 ctx = scmutil.revsingle(repo, node)
3995 mf = ctx.manifest()
4002 mf = ctx.manifest()
3996 for f in ctx:
4003 for f in ctx:
3997 fm.startitem()
4004 fm.startitem()
3998 fl = ctx[f].flags()
4005 fl = ctx[f].flags()
3999 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4006 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4000 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4007 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4001 fm.write('path', '%s\n', f)
4008 fm.write('path', '%s\n', f)
4002 fm.end()
4009 fm.end()
4003
4010
4004 @command('^merge',
4011 @command('^merge',
4005 [('f', 'force', None, _('force a merge with outstanding changes')),
4012 [('f', 'force', None, _('force a merge with outstanding changes')),
4006 ('r', 'rev', '', _('revision to merge'), _('REV')),
4013 ('r', 'rev', '', _('revision to merge'), _('REV')),
4007 ('P', 'preview', None,
4014 ('P', 'preview', None,
4008 _('review revisions to merge (no merge is performed)'))
4015 _('review revisions to merge (no merge is performed)'))
4009 ] + mergetoolopts,
4016 ] + mergetoolopts,
4010 _('[-P] [-f] [[-r] REV]'))
4017 _('[-P] [-f] [[-r] REV]'))
4011 def merge(ui, repo, node=None, **opts):
4018 def merge(ui, repo, node=None, **opts):
4012 """merge working directory with another revision
4019 """merge working directory with another revision
4013
4020
4014 The current working directory is updated with all changes made in
4021 The current working directory is updated with all changes made in
4015 the requested revision since the last common predecessor revision.
4022 the requested revision since the last common predecessor revision.
4016
4023
4017 Files that changed between either parent are marked as changed for
4024 Files that changed between either parent are marked as changed for
4018 the next commit and a commit must be performed before any further
4025 the next commit and a commit must be performed before any further
4019 updates to the repository are allowed. The next commit will have
4026 updates to the repository are allowed. The next commit will have
4020 two parents.
4027 two parents.
4021
4028
4022 ``--tool`` can be used to specify the merge tool used for file
4029 ``--tool`` can be used to specify the merge tool used for file
4023 merges. It overrides the HGMERGE environment variable and your
4030 merges. It overrides the HGMERGE environment variable and your
4024 configuration files. See :hg:`help merge-tools` for options.
4031 configuration files. See :hg:`help merge-tools` for options.
4025
4032
4026 If no revision is specified, the working directory's parent is a
4033 If no revision is specified, the working directory's parent is a
4027 head revision, and the current branch contains exactly one other
4034 head revision, and the current branch contains exactly one other
4028 head, the other head is merged with by default. Otherwise, an
4035 head, the other head is merged with by default. Otherwise, an
4029 explicit revision with which to merge with must be provided.
4036 explicit revision with which to merge with must be provided.
4030
4037
4031 :hg:`resolve` must be used to resolve unresolved files.
4038 :hg:`resolve` must be used to resolve unresolved files.
4032
4039
4033 To undo an uncommitted merge, use :hg:`update --clean .` which
4040 To undo an uncommitted merge, use :hg:`update --clean .` which
4034 will check out a clean copy of the original merge parent, losing
4041 will check out a clean copy of the original merge parent, losing
4035 all changes.
4042 all changes.
4036
4043
4037 Returns 0 on success, 1 if there are unresolved files.
4044 Returns 0 on success, 1 if there are unresolved files.
4038 """
4045 """
4039
4046
4040 if opts.get('rev') and node:
4047 if opts.get('rev') and node:
4041 raise util.Abort(_("please specify just one revision"))
4048 raise util.Abort(_("please specify just one revision"))
4042 if not node:
4049 if not node:
4043 node = opts.get('rev')
4050 node = opts.get('rev')
4044
4051
4045 if node:
4052 if node:
4046 node = scmutil.revsingle(repo, node).node()
4053 node = scmutil.revsingle(repo, node).node()
4047
4054
4048 if not node and repo._bookmarkcurrent:
4055 if not node and repo._bookmarkcurrent:
4049 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4056 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4050 curhead = repo[repo._bookmarkcurrent].node()
4057 curhead = repo[repo._bookmarkcurrent].node()
4051 if len(bmheads) == 2:
4058 if len(bmheads) == 2:
4052 if curhead == bmheads[0]:
4059 if curhead == bmheads[0]:
4053 node = bmheads[1]
4060 node = bmheads[1]
4054 else:
4061 else:
4055 node = bmheads[0]
4062 node = bmheads[0]
4056 elif len(bmheads) > 2:
4063 elif len(bmheads) > 2:
4057 raise util.Abort(_("multiple matching bookmarks to merge - "
4064 raise util.Abort(_("multiple matching bookmarks to merge - "
4058 "please merge with an explicit rev or bookmark"),
4065 "please merge with an explicit rev or bookmark"),
4059 hint=_("run 'hg heads' to see all heads"))
4066 hint=_("run 'hg heads' to see all heads"))
4060 elif len(bmheads) <= 1:
4067 elif len(bmheads) <= 1:
4061 raise util.Abort(_("no matching bookmark to merge - "
4068 raise util.Abort(_("no matching bookmark to merge - "
4062 "please merge with an explicit rev or bookmark"),
4069 "please merge with an explicit rev or bookmark"),
4063 hint=_("run 'hg heads' to see all heads"))
4070 hint=_("run 'hg heads' to see all heads"))
4064
4071
4065 if not node and not repo._bookmarkcurrent:
4072 if not node and not repo._bookmarkcurrent:
4066 branch = repo[None].branch()
4073 branch = repo[None].branch()
4067 bheads = repo.branchheads(branch)
4074 bheads = repo.branchheads(branch)
4068 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4075 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4069
4076
4070 if len(nbhs) > 2:
4077 if len(nbhs) > 2:
4071 raise util.Abort(_("branch '%s' has %d heads - "
4078 raise util.Abort(_("branch '%s' has %d heads - "
4072 "please merge with an explicit rev")
4079 "please merge with an explicit rev")
4073 % (branch, len(bheads)),
4080 % (branch, len(bheads)),
4074 hint=_("run 'hg heads .' to see heads"))
4081 hint=_("run 'hg heads .' to see heads"))
4075
4082
4076 parent = repo.dirstate.p1()
4083 parent = repo.dirstate.p1()
4077 if len(nbhs) <= 1:
4084 if len(nbhs) <= 1:
4078 if len(bheads) > 1:
4085 if len(bheads) > 1:
4079 raise util.Abort(_("heads are bookmarked - "
4086 raise util.Abort(_("heads are bookmarked - "
4080 "please merge with an explicit rev"),
4087 "please merge with an explicit rev"),
4081 hint=_("run 'hg heads' to see all heads"))
4088 hint=_("run 'hg heads' to see all heads"))
4082 if len(repo.heads()) > 1:
4089 if len(repo.heads()) > 1:
4083 raise util.Abort(_("branch '%s' has one head - "
4090 raise util.Abort(_("branch '%s' has one head - "
4084 "please merge with an explicit rev")
4091 "please merge with an explicit rev")
4085 % branch,
4092 % branch,
4086 hint=_("run 'hg heads' to see all heads"))
4093 hint=_("run 'hg heads' to see all heads"))
4087 msg, hint = _('nothing to merge'), None
4094 msg, hint = _('nothing to merge'), None
4088 if parent != repo.lookup(branch):
4095 if parent != repo.lookup(branch):
4089 hint = _("use 'hg update' instead")
4096 hint = _("use 'hg update' instead")
4090 raise util.Abort(msg, hint=hint)
4097 raise util.Abort(msg, hint=hint)
4091
4098
4092 if parent not in bheads:
4099 if parent not in bheads:
4093 raise util.Abort(_('working directory not at a head revision'),
4100 raise util.Abort(_('working directory not at a head revision'),
4094 hint=_("use 'hg update' or merge with an "
4101 hint=_("use 'hg update' or merge with an "
4095 "explicit revision"))
4102 "explicit revision"))
4096 if parent == nbhs[0]:
4103 if parent == nbhs[0]:
4097 node = nbhs[-1]
4104 node = nbhs[-1]
4098 else:
4105 else:
4099 node = nbhs[0]
4106 node = nbhs[0]
4100
4107
4101 if opts.get('preview'):
4108 if opts.get('preview'):
4102 # find nodes that are ancestors of p2 but not of p1
4109 # find nodes that are ancestors of p2 but not of p1
4103 p1 = repo.lookup('.')
4110 p1 = repo.lookup('.')
4104 p2 = repo.lookup(node)
4111 p2 = repo.lookup(node)
4105 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4112 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4106
4113
4107 displayer = cmdutil.show_changeset(ui, repo, opts)
4114 displayer = cmdutil.show_changeset(ui, repo, opts)
4108 for node in nodes:
4115 for node in nodes:
4109 displayer.show(repo[node])
4116 displayer.show(repo[node])
4110 displayer.close()
4117 displayer.close()
4111 return 0
4118 return 0
4112
4119
4113 try:
4120 try:
4114 # ui.forcemerge is an internal variable, do not document
4121 # ui.forcemerge is an internal variable, do not document
4115 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4122 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4116 return hg.merge(repo, node, force=opts.get('force'))
4123 return hg.merge(repo, node, force=opts.get('force'))
4117 finally:
4124 finally:
4118 ui.setconfig('ui', 'forcemerge', '')
4125 ui.setconfig('ui', 'forcemerge', '')
4119
4126
4120 @command('outgoing|out',
4127 @command('outgoing|out',
4121 [('f', 'force', None, _('run even when the destination is unrelated')),
4128 [('f', 'force', None, _('run even when the destination is unrelated')),
4122 ('r', 'rev', [],
4129 ('r', 'rev', [],
4123 _('a changeset intended to be included in the destination'), _('REV')),
4130 _('a changeset intended to be included in the destination'), _('REV')),
4124 ('n', 'newest-first', None, _('show newest record first')),
4131 ('n', 'newest-first', None, _('show newest record first')),
4125 ('B', 'bookmarks', False, _('compare bookmarks')),
4132 ('B', 'bookmarks', False, _('compare bookmarks')),
4126 ('b', 'branch', [], _('a specific branch you would like to push'),
4133 ('b', 'branch', [], _('a specific branch you would like to push'),
4127 _('BRANCH')),
4134 _('BRANCH')),
4128 ] + logopts + remoteopts + subrepoopts,
4135 ] + logopts + remoteopts + subrepoopts,
4129 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4136 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4130 def outgoing(ui, repo, dest=None, **opts):
4137 def outgoing(ui, repo, dest=None, **opts):
4131 """show changesets not found in the destination
4138 """show changesets not found in the destination
4132
4139
4133 Show changesets not found in the specified destination repository
4140 Show changesets not found in the specified destination repository
4134 or the default push location. These are the changesets that would
4141 or the default push location. These are the changesets that would
4135 be pushed if a push was requested.
4142 be pushed if a push was requested.
4136
4143
4137 See pull for details of valid destination formats.
4144 See pull for details of valid destination formats.
4138
4145
4139 Returns 0 if there are outgoing changes, 1 otherwise.
4146 Returns 0 if there are outgoing changes, 1 otherwise.
4140 """
4147 """
4141 if opts.get('graph'):
4148 if opts.get('graph'):
4142 cmdutil.checkunsupportedgraphflags([], opts)
4149 cmdutil.checkunsupportedgraphflags([], opts)
4143 o = hg._outgoing(ui, repo, dest, opts)
4150 o = hg._outgoing(ui, repo, dest, opts)
4144 if o is None:
4151 if o is None:
4145 return
4152 return
4146
4153
4147 revdag = cmdutil.graphrevs(repo, o, opts)
4154 revdag = cmdutil.graphrevs(repo, o, opts)
4148 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4155 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4149 showparents = [ctx.node() for ctx in repo[None].parents()]
4156 showparents = [ctx.node() for ctx in repo[None].parents()]
4150 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4157 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4151 graphmod.asciiedges)
4158 graphmod.asciiedges)
4152 return 0
4159 return 0
4153
4160
4154 if opts.get('bookmarks'):
4161 if opts.get('bookmarks'):
4155 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4162 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4156 dest, branches = hg.parseurl(dest, opts.get('branch'))
4163 dest, branches = hg.parseurl(dest, opts.get('branch'))
4157 other = hg.peer(repo, opts, dest)
4164 other = hg.peer(repo, opts, dest)
4158 if 'bookmarks' not in other.listkeys('namespaces'):
4165 if 'bookmarks' not in other.listkeys('namespaces'):
4159 ui.warn(_("remote doesn't support bookmarks\n"))
4166 ui.warn(_("remote doesn't support bookmarks\n"))
4160 return 0
4167 return 0
4161 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4168 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4162 return bookmarks.diff(ui, other, repo)
4169 return bookmarks.diff(ui, other, repo)
4163
4170
4164 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4171 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4165 try:
4172 try:
4166 return hg.outgoing(ui, repo, dest, opts)
4173 return hg.outgoing(ui, repo, dest, opts)
4167 finally:
4174 finally:
4168 del repo._subtoppath
4175 del repo._subtoppath
4169
4176
4170 @command('parents',
4177 @command('parents',
4171 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4178 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4172 ] + templateopts,
4179 ] + templateopts,
4173 _('[-r REV] [FILE]'))
4180 _('[-r REV] [FILE]'))
4174 def parents(ui, repo, file_=None, **opts):
4181 def parents(ui, repo, file_=None, **opts):
4175 """show the parents of the working directory or revision
4182 """show the parents of the working directory or revision
4176
4183
4177 Print the working directory's parent revisions. If a revision is
4184 Print the working directory's parent revisions. If a revision is
4178 given via -r/--rev, the parent of that revision will be printed.
4185 given via -r/--rev, the parent of that revision will be printed.
4179 If a file argument is given, the revision in which the file was
4186 If a file argument is given, the revision in which the file was
4180 last changed (before the working directory revision or the
4187 last changed (before the working directory revision or the
4181 argument to --rev if given) is printed.
4188 argument to --rev if given) is printed.
4182
4189
4183 Returns 0 on success.
4190 Returns 0 on success.
4184 """
4191 """
4185
4192
4186 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4193 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4187
4194
4188 if file_:
4195 if file_:
4189 m = scmutil.match(ctx, (file_,), opts)
4196 m = scmutil.match(ctx, (file_,), opts)
4190 if m.anypats() or len(m.files()) != 1:
4197 if m.anypats() or len(m.files()) != 1:
4191 raise util.Abort(_('can only specify an explicit filename'))
4198 raise util.Abort(_('can only specify an explicit filename'))
4192 file_ = m.files()[0]
4199 file_ = m.files()[0]
4193 filenodes = []
4200 filenodes = []
4194 for cp in ctx.parents():
4201 for cp in ctx.parents():
4195 if not cp:
4202 if not cp:
4196 continue
4203 continue
4197 try:
4204 try:
4198 filenodes.append(cp.filenode(file_))
4205 filenodes.append(cp.filenode(file_))
4199 except error.LookupError:
4206 except error.LookupError:
4200 pass
4207 pass
4201 if not filenodes:
4208 if not filenodes:
4202 raise util.Abort(_("'%s' not found in manifest!") % file_)
4209 raise util.Abort(_("'%s' not found in manifest!") % file_)
4203 fl = repo.file(file_)
4210 fl = repo.file(file_)
4204 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4211 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4205 else:
4212 else:
4206 p = [cp.node() for cp in ctx.parents()]
4213 p = [cp.node() for cp in ctx.parents()]
4207
4214
4208 displayer = cmdutil.show_changeset(ui, repo, opts)
4215 displayer = cmdutil.show_changeset(ui, repo, opts)
4209 for n in p:
4216 for n in p:
4210 if n != nullid:
4217 if n != nullid:
4211 displayer.show(repo[n])
4218 displayer.show(repo[n])
4212 displayer.close()
4219 displayer.close()
4213
4220
4214 @command('paths', [], _('[NAME]'))
4221 @command('paths', [], _('[NAME]'))
4215 def paths(ui, repo, search=None):
4222 def paths(ui, repo, search=None):
4216 """show aliases for remote repositories
4223 """show aliases for remote repositories
4217
4224
4218 Show definition of symbolic path name NAME. If no name is given,
4225 Show definition of symbolic path name NAME. If no name is given,
4219 show definition of all available names.
4226 show definition of all available names.
4220
4227
4221 Option -q/--quiet suppresses all output when searching for NAME
4228 Option -q/--quiet suppresses all output when searching for NAME
4222 and shows only the path names when listing all definitions.
4229 and shows only the path names when listing all definitions.
4223
4230
4224 Path names are defined in the [paths] section of your
4231 Path names are defined in the [paths] section of your
4225 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4232 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4226 repository, ``.hg/hgrc`` is used, too.
4233 repository, ``.hg/hgrc`` is used, too.
4227
4234
4228 The path names ``default`` and ``default-push`` have a special
4235 The path names ``default`` and ``default-push`` have a special
4229 meaning. When performing a push or pull operation, they are used
4236 meaning. When performing a push or pull operation, they are used
4230 as fallbacks if no location is specified on the command-line.
4237 as fallbacks if no location is specified on the command-line.
4231 When ``default-push`` is set, it will be used for push and
4238 When ``default-push`` is set, it will be used for push and
4232 ``default`` will be used for pull; otherwise ``default`` is used
4239 ``default`` will be used for pull; otherwise ``default`` is used
4233 as the fallback for both. When cloning a repository, the clone
4240 as the fallback for both. When cloning a repository, the clone
4234 source is written as ``default`` in ``.hg/hgrc``. Note that
4241 source is written as ``default`` in ``.hg/hgrc``. Note that
4235 ``default`` and ``default-push`` apply to all inbound (e.g.
4242 ``default`` and ``default-push`` apply to all inbound (e.g.
4236 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4243 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4237 :hg:`bundle`) operations.
4244 :hg:`bundle`) operations.
4238
4245
4239 See :hg:`help urls` for more information.
4246 See :hg:`help urls` for more information.
4240
4247
4241 Returns 0 on success.
4248 Returns 0 on success.
4242 """
4249 """
4243 if search:
4250 if search:
4244 for name, path in ui.configitems("paths"):
4251 for name, path in ui.configitems("paths"):
4245 if name == search:
4252 if name == search:
4246 ui.status("%s\n" % util.hidepassword(path))
4253 ui.status("%s\n" % util.hidepassword(path))
4247 return
4254 return
4248 if not ui.quiet:
4255 if not ui.quiet:
4249 ui.warn(_("not found!\n"))
4256 ui.warn(_("not found!\n"))
4250 return 1
4257 return 1
4251 else:
4258 else:
4252 for name, path in ui.configitems("paths"):
4259 for name, path in ui.configitems("paths"):
4253 if ui.quiet:
4260 if ui.quiet:
4254 ui.write("%s\n" % name)
4261 ui.write("%s\n" % name)
4255 else:
4262 else:
4256 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4263 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4257
4264
4258 @command('phase',
4265 @command('phase',
4259 [('p', 'public', False, _('set changeset phase to public')),
4266 [('p', 'public', False, _('set changeset phase to public')),
4260 ('d', 'draft', False, _('set changeset phase to draft')),
4267 ('d', 'draft', False, _('set changeset phase to draft')),
4261 ('s', 'secret', False, _('set changeset phase to secret')),
4268 ('s', 'secret', False, _('set changeset phase to secret')),
4262 ('f', 'force', False, _('allow to move boundary backward')),
4269 ('f', 'force', False, _('allow to move boundary backward')),
4263 ('r', 'rev', [], _('target revision'), _('REV')),
4270 ('r', 'rev', [], _('target revision'), _('REV')),
4264 ],
4271 ],
4265 _('[-p|-d|-s] [-f] [-r] REV...'))
4272 _('[-p|-d|-s] [-f] [-r] REV...'))
4266 def phase(ui, repo, *revs, **opts):
4273 def phase(ui, repo, *revs, **opts):
4267 """set or show the current phase name
4274 """set or show the current phase name
4268
4275
4269 With no argument, show the phase name of specified revisions.
4276 With no argument, show the phase name of specified revisions.
4270
4277
4271 With one of -p/--public, -d/--draft or -s/--secret, change the
4278 With one of -p/--public, -d/--draft or -s/--secret, change the
4272 phase value of the specified revisions.
4279 phase value of the specified revisions.
4273
4280
4274 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4281 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4275 lower phase to an higher phase. Phases are ordered as follows::
4282 lower phase to an higher phase. Phases are ordered as follows::
4276
4283
4277 public < draft < secret
4284 public < draft < secret
4278
4285
4279 Return 0 on success, 1 if no phases were changed or some could not
4286 Return 0 on success, 1 if no phases were changed or some could not
4280 be changed.
4287 be changed.
4281 """
4288 """
4282 # search for a unique phase argument
4289 # search for a unique phase argument
4283 targetphase = None
4290 targetphase = None
4284 for idx, name in enumerate(phases.phasenames):
4291 for idx, name in enumerate(phases.phasenames):
4285 if opts[name]:
4292 if opts[name]:
4286 if targetphase is not None:
4293 if targetphase is not None:
4287 raise util.Abort(_('only one phase can be specified'))
4294 raise util.Abort(_('only one phase can be specified'))
4288 targetphase = idx
4295 targetphase = idx
4289
4296
4290 # look for specified revision
4297 # look for specified revision
4291 revs = list(revs)
4298 revs = list(revs)
4292 revs.extend(opts['rev'])
4299 revs.extend(opts['rev'])
4293 if not revs:
4300 if not revs:
4294 raise util.Abort(_('no revisions specified'))
4301 raise util.Abort(_('no revisions specified'))
4295
4302
4296 revs = scmutil.revrange(repo, revs)
4303 revs = scmutil.revrange(repo, revs)
4297
4304
4298 lock = None
4305 lock = None
4299 ret = 0
4306 ret = 0
4300 if targetphase is None:
4307 if targetphase is None:
4301 # display
4308 # display
4302 for r in revs:
4309 for r in revs:
4303 ctx = repo[r]
4310 ctx = repo[r]
4304 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4311 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4305 else:
4312 else:
4306 lock = repo.lock()
4313 lock = repo.lock()
4307 try:
4314 try:
4308 # set phase
4315 # set phase
4309 if not revs:
4316 if not revs:
4310 raise util.Abort(_('empty revision set'))
4317 raise util.Abort(_('empty revision set'))
4311 nodes = [repo[r].node() for r in revs]
4318 nodes = [repo[r].node() for r in revs]
4312 olddata = repo._phasecache.getphaserevs(repo)[:]
4319 olddata = repo._phasecache.getphaserevs(repo)[:]
4313 phases.advanceboundary(repo, targetphase, nodes)
4320 phases.advanceboundary(repo, targetphase, nodes)
4314 if opts['force']:
4321 if opts['force']:
4315 phases.retractboundary(repo, targetphase, nodes)
4322 phases.retractboundary(repo, targetphase, nodes)
4316 finally:
4323 finally:
4317 lock.release()
4324 lock.release()
4318 # moving revision from public to draft may hide them
4325 # moving revision from public to draft may hide them
4319 # We have to check result on an unfiltered repository
4326 # We have to check result on an unfiltered repository
4320 unfi = repo.unfiltered()
4327 unfi = repo.unfiltered()
4321 newdata = repo._phasecache.getphaserevs(unfi)
4328 newdata = repo._phasecache.getphaserevs(unfi)
4322 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4329 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4323 cl = unfi.changelog
4330 cl = unfi.changelog
4324 rejected = [n for n in nodes
4331 rejected = [n for n in nodes
4325 if newdata[cl.rev(n)] < targetphase]
4332 if newdata[cl.rev(n)] < targetphase]
4326 if rejected:
4333 if rejected:
4327 ui.warn(_('cannot move %i changesets to a more permissive '
4334 ui.warn(_('cannot move %i changesets to a more permissive '
4328 'phase, use --force\n') % len(rejected))
4335 'phase, use --force\n') % len(rejected))
4329 ret = 1
4336 ret = 1
4330 if changes:
4337 if changes:
4331 msg = _('phase changed for %i changesets\n') % changes
4338 msg = _('phase changed for %i changesets\n') % changes
4332 if ret:
4339 if ret:
4333 ui.status(msg)
4340 ui.status(msg)
4334 else:
4341 else:
4335 ui.note(msg)
4342 ui.note(msg)
4336 else:
4343 else:
4337 ui.warn(_('no phases changed\n'))
4344 ui.warn(_('no phases changed\n'))
4338 ret = 1
4345 ret = 1
4339 return ret
4346 return ret
4340
4347
4341 def postincoming(ui, repo, modheads, optupdate, checkout):
4348 def postincoming(ui, repo, modheads, optupdate, checkout):
4342 if modheads == 0:
4349 if modheads == 0:
4343 return
4350 return
4344 if optupdate:
4351 if optupdate:
4345 movemarkfrom = repo['.'].node()
4352 movemarkfrom = repo['.'].node()
4346 try:
4353 try:
4347 ret = hg.update(repo, checkout)
4354 ret = hg.update(repo, checkout)
4348 except util.Abort, inst:
4355 except util.Abort, inst:
4349 ui.warn(_("not updating: %s\n") % str(inst))
4356 ui.warn(_("not updating: %s\n") % str(inst))
4350 return 0
4357 return 0
4351 if not ret and not checkout:
4358 if not ret and not checkout:
4352 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4359 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4353 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4360 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4354 return ret
4361 return ret
4355 if modheads > 1:
4362 if modheads > 1:
4356 currentbranchheads = len(repo.branchheads())
4363 currentbranchheads = len(repo.branchheads())
4357 if currentbranchheads == modheads:
4364 if currentbranchheads == modheads:
4358 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4365 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4359 elif currentbranchheads > 1:
4366 elif currentbranchheads > 1:
4360 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4367 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4361 "merge)\n"))
4368 "merge)\n"))
4362 else:
4369 else:
4363 ui.status(_("(run 'hg heads' to see heads)\n"))
4370 ui.status(_("(run 'hg heads' to see heads)\n"))
4364 else:
4371 else:
4365 ui.status(_("(run 'hg update' to get a working copy)\n"))
4372 ui.status(_("(run 'hg update' to get a working copy)\n"))
4366
4373
4367 @command('^pull',
4374 @command('^pull',
4368 [('u', 'update', None,
4375 [('u', 'update', None,
4369 _('update to new branch head if changesets were pulled')),
4376 _('update to new branch head if changesets were pulled')),
4370 ('f', 'force', None, _('run even when remote repository is unrelated')),
4377 ('f', 'force', None, _('run even when remote repository is unrelated')),
4371 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4378 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4372 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4379 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4373 ('b', 'branch', [], _('a specific branch you would like to pull'),
4380 ('b', 'branch', [], _('a specific branch you would like to pull'),
4374 _('BRANCH')),
4381 _('BRANCH')),
4375 ] + remoteopts,
4382 ] + remoteopts,
4376 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4383 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4377 def pull(ui, repo, source="default", **opts):
4384 def pull(ui, repo, source="default", **opts):
4378 """pull changes from the specified source
4385 """pull changes from the specified source
4379
4386
4380 Pull changes from a remote repository to a local one.
4387 Pull changes from a remote repository to a local one.
4381
4388
4382 This finds all changes from the repository at the specified path
4389 This finds all changes from the repository at the specified path
4383 or URL and adds them to a local repository (the current one unless
4390 or URL and adds them to a local repository (the current one unless
4384 -R is specified). By default, this does not update the copy of the
4391 -R is specified). By default, this does not update the copy of the
4385 project in the working directory.
4392 project in the working directory.
4386
4393
4387 Use :hg:`incoming` if you want to see what would have been added
4394 Use :hg:`incoming` if you want to see what would have been added
4388 by a pull at the time you issued this command. If you then decide
4395 by a pull at the time you issued this command. If you then decide
4389 to add those changes to the repository, you should use :hg:`pull
4396 to add those changes to the repository, you should use :hg:`pull
4390 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4397 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4391
4398
4392 If SOURCE is omitted, the 'default' path will be used.
4399 If SOURCE is omitted, the 'default' path will be used.
4393 See :hg:`help urls` for more information.
4400 See :hg:`help urls` for more information.
4394
4401
4395 Returns 0 on success, 1 if an update had unresolved files.
4402 Returns 0 on success, 1 if an update had unresolved files.
4396 """
4403 """
4397 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4404 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4398 other = hg.peer(repo, opts, source)
4405 other = hg.peer(repo, opts, source)
4399 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4406 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4400 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4407 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4401
4408
4402 if opts.get('bookmark'):
4409 if opts.get('bookmark'):
4403 if not revs:
4410 if not revs:
4404 revs = []
4411 revs = []
4405 rb = other.listkeys('bookmarks')
4412 rb = other.listkeys('bookmarks')
4406 for b in opts['bookmark']:
4413 for b in opts['bookmark']:
4407 if b not in rb:
4414 if b not in rb:
4408 raise util.Abort(_('remote bookmark %s not found!') % b)
4415 raise util.Abort(_('remote bookmark %s not found!') % b)
4409 revs.append(rb[b])
4416 revs.append(rb[b])
4410
4417
4411 if revs:
4418 if revs:
4412 try:
4419 try:
4413 revs = [other.lookup(rev) for rev in revs]
4420 revs = [other.lookup(rev) for rev in revs]
4414 except error.CapabilityError:
4421 except error.CapabilityError:
4415 err = _("other repository doesn't support revision lookup, "
4422 err = _("other repository doesn't support revision lookup, "
4416 "so a rev cannot be specified.")
4423 "so a rev cannot be specified.")
4417 raise util.Abort(err)
4424 raise util.Abort(err)
4418
4425
4419 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4426 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4420 bookmarks.updatefromremote(ui, repo, other, source)
4427 bookmarks.updatefromremote(ui, repo, other, source)
4421 if checkout:
4428 if checkout:
4422 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4429 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4423 repo._subtoppath = source
4430 repo._subtoppath = source
4424 try:
4431 try:
4425 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4432 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4426
4433
4427 finally:
4434 finally:
4428 del repo._subtoppath
4435 del repo._subtoppath
4429
4436
4430 # update specified bookmarks
4437 # update specified bookmarks
4431 if opts.get('bookmark'):
4438 if opts.get('bookmark'):
4432 marks = repo._bookmarks
4439 marks = repo._bookmarks
4433 for b in opts['bookmark']:
4440 for b in opts['bookmark']:
4434 # explicit pull overrides local bookmark if any
4441 # explicit pull overrides local bookmark if any
4435 ui.status(_("importing bookmark %s\n") % b)
4442 ui.status(_("importing bookmark %s\n") % b)
4436 marks[b] = repo[rb[b]].node()
4443 marks[b] = repo[rb[b]].node()
4437 marks.write()
4444 marks.write()
4438
4445
4439 return ret
4446 return ret
4440
4447
4441 @command('^push',
4448 @command('^push',
4442 [('f', 'force', None, _('force push')),
4449 [('f', 'force', None, _('force push')),
4443 ('r', 'rev', [],
4450 ('r', 'rev', [],
4444 _('a changeset intended to be included in the destination'),
4451 _('a changeset intended to be included in the destination'),
4445 _('REV')),
4452 _('REV')),
4446 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4453 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4447 ('b', 'branch', [],
4454 ('b', 'branch', [],
4448 _('a specific branch you would like to push'), _('BRANCH')),
4455 _('a specific branch you would like to push'), _('BRANCH')),
4449 ('', 'new-branch', False, _('allow pushing a new branch')),
4456 ('', 'new-branch', False, _('allow pushing a new branch')),
4450 ] + remoteopts,
4457 ] + remoteopts,
4451 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4458 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4452 def push(ui, repo, dest=None, **opts):
4459 def push(ui, repo, dest=None, **opts):
4453 """push changes to the specified destination
4460 """push changes to the specified destination
4454
4461
4455 Push changesets from the local repository to the specified
4462 Push changesets from the local repository to the specified
4456 destination.
4463 destination.
4457
4464
4458 This operation is symmetrical to pull: it is identical to a pull
4465 This operation is symmetrical to pull: it is identical to a pull
4459 in the destination repository from the current one.
4466 in the destination repository from the current one.
4460
4467
4461 By default, push will not allow creation of new heads at the
4468 By default, push will not allow creation of new heads at the
4462 destination, since multiple heads would make it unclear which head
4469 destination, since multiple heads would make it unclear which head
4463 to use. In this situation, it is recommended to pull and merge
4470 to use. In this situation, it is recommended to pull and merge
4464 before pushing.
4471 before pushing.
4465
4472
4466 Use --new-branch if you want to allow push to create a new named
4473 Use --new-branch if you want to allow push to create a new named
4467 branch that is not present at the destination. This allows you to
4474 branch that is not present at the destination. This allows you to
4468 only create a new branch without forcing other changes.
4475 only create a new branch without forcing other changes.
4469
4476
4470 Use -f/--force to override the default behavior and push all
4477 Use -f/--force to override the default behavior and push all
4471 changesets on all branches.
4478 changesets on all branches.
4472
4479
4473 If -r/--rev is used, the specified revision and all its ancestors
4480 If -r/--rev is used, the specified revision and all its ancestors
4474 will be pushed to the remote repository.
4481 will be pushed to the remote repository.
4475
4482
4476 If -B/--bookmark is used, the specified bookmarked revision, its
4483 If -B/--bookmark is used, the specified bookmarked revision, its
4477 ancestors, and the bookmark will be pushed to the remote
4484 ancestors, and the bookmark will be pushed to the remote
4478 repository.
4485 repository.
4479
4486
4480 Please see :hg:`help urls` for important details about ``ssh://``
4487 Please see :hg:`help urls` for important details about ``ssh://``
4481 URLs. If DESTINATION is omitted, a default path will be used.
4488 URLs. If DESTINATION is omitted, a default path will be used.
4482
4489
4483 Returns 0 if push was successful, 1 if nothing to push.
4490 Returns 0 if push was successful, 1 if nothing to push.
4484 """
4491 """
4485
4492
4486 if opts.get('bookmark'):
4493 if opts.get('bookmark'):
4487 for b in opts['bookmark']:
4494 for b in opts['bookmark']:
4488 # translate -B options to -r so changesets get pushed
4495 # translate -B options to -r so changesets get pushed
4489 if b in repo._bookmarks:
4496 if b in repo._bookmarks:
4490 opts.setdefault('rev', []).append(b)
4497 opts.setdefault('rev', []).append(b)
4491 else:
4498 else:
4492 # if we try to push a deleted bookmark, translate it to null
4499 # if we try to push a deleted bookmark, translate it to null
4493 # this lets simultaneous -r, -b options continue working
4500 # this lets simultaneous -r, -b options continue working
4494 opts.setdefault('rev', []).append("null")
4501 opts.setdefault('rev', []).append("null")
4495
4502
4496 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4503 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4497 dest, branches = hg.parseurl(dest, opts.get('branch'))
4504 dest, branches = hg.parseurl(dest, opts.get('branch'))
4498 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4505 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4499 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4506 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4500 other = hg.peer(repo, opts, dest)
4507 other = hg.peer(repo, opts, dest)
4501 if revs:
4508 if revs:
4502 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4509 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4503
4510
4504 repo._subtoppath = dest
4511 repo._subtoppath = dest
4505 try:
4512 try:
4506 # push subrepos depth-first for coherent ordering
4513 # push subrepos depth-first for coherent ordering
4507 c = repo['']
4514 c = repo['']
4508 subs = c.substate # only repos that are committed
4515 subs = c.substate # only repos that are committed
4509 for s in sorted(subs):
4516 for s in sorted(subs):
4510 if c.sub(s).push(opts) == 0:
4517 if c.sub(s).push(opts) == 0:
4511 return False
4518 return False
4512 finally:
4519 finally:
4513 del repo._subtoppath
4520 del repo._subtoppath
4514 result = repo.push(other, opts.get('force'), revs=revs,
4521 result = repo.push(other, opts.get('force'), revs=revs,
4515 newbranch=opts.get('new_branch'))
4522 newbranch=opts.get('new_branch'))
4516
4523
4517 result = not result
4524 result = not result
4518
4525
4519 if opts.get('bookmark'):
4526 if opts.get('bookmark'):
4520 rb = other.listkeys('bookmarks')
4527 rb = other.listkeys('bookmarks')
4521 for b in opts['bookmark']:
4528 for b in opts['bookmark']:
4522 # explicit push overrides remote bookmark if any
4529 # explicit push overrides remote bookmark if any
4523 if b in repo._bookmarks:
4530 if b in repo._bookmarks:
4524 ui.status(_("exporting bookmark %s\n") % b)
4531 ui.status(_("exporting bookmark %s\n") % b)
4525 new = repo[b].hex()
4532 new = repo[b].hex()
4526 elif b in rb:
4533 elif b in rb:
4527 ui.status(_("deleting remote bookmark %s\n") % b)
4534 ui.status(_("deleting remote bookmark %s\n") % b)
4528 new = '' # delete
4535 new = '' # delete
4529 else:
4536 else:
4530 ui.warn(_('bookmark %s does not exist on the local '
4537 ui.warn(_('bookmark %s does not exist on the local '
4531 'or remote repository!\n') % b)
4538 'or remote repository!\n') % b)
4532 return 2
4539 return 2
4533 old = rb.get(b, '')
4540 old = rb.get(b, '')
4534 r = other.pushkey('bookmarks', b, old, new)
4541 r = other.pushkey('bookmarks', b, old, new)
4535 if not r:
4542 if not r:
4536 ui.warn(_('updating bookmark %s failed!\n') % b)
4543 ui.warn(_('updating bookmark %s failed!\n') % b)
4537 if not result:
4544 if not result:
4538 result = 2
4545 result = 2
4539
4546
4540 return result
4547 return result
4541
4548
4542 @command('recover', [])
4549 @command('recover', [])
4543 def recover(ui, repo):
4550 def recover(ui, repo):
4544 """roll back an interrupted transaction
4551 """roll back an interrupted transaction
4545
4552
4546 Recover from an interrupted commit or pull.
4553 Recover from an interrupted commit or pull.
4547
4554
4548 This command tries to fix the repository status after an
4555 This command tries to fix the repository status after an
4549 interrupted operation. It should only be necessary when Mercurial
4556 interrupted operation. It should only be necessary when Mercurial
4550 suggests it.
4557 suggests it.
4551
4558
4552 Returns 0 if successful, 1 if nothing to recover or verify fails.
4559 Returns 0 if successful, 1 if nothing to recover or verify fails.
4553 """
4560 """
4554 if repo.recover():
4561 if repo.recover():
4555 return hg.verify(repo)
4562 return hg.verify(repo)
4556 return 1
4563 return 1
4557
4564
4558 @command('^remove|rm',
4565 @command('^remove|rm',
4559 [('A', 'after', None, _('record delete for missing files')),
4566 [('A', 'after', None, _('record delete for missing files')),
4560 ('f', 'force', None,
4567 ('f', 'force', None,
4561 _('remove (and delete) file even if added or modified')),
4568 _('remove (and delete) file even if added or modified')),
4562 ] + walkopts,
4569 ] + walkopts,
4563 _('[OPTION]... FILE...'))
4570 _('[OPTION]... FILE...'))
4564 def remove(ui, repo, *pats, **opts):
4571 def remove(ui, repo, *pats, **opts):
4565 """remove the specified files on the next commit
4572 """remove the specified files on the next commit
4566
4573
4567 Schedule the indicated files for removal from the current branch.
4574 Schedule the indicated files for removal from the current branch.
4568
4575
4569 This command schedules the files to be removed at the next commit.
4576 This command schedules the files to be removed at the next commit.
4570 To undo a remove before that, see :hg:`revert`. To undo added
4577 To undo a remove before that, see :hg:`revert`. To undo added
4571 files, see :hg:`forget`.
4578 files, see :hg:`forget`.
4572
4579
4573 .. container:: verbose
4580 .. container:: verbose
4574
4581
4575 -A/--after can be used to remove only files that have already
4582 -A/--after can be used to remove only files that have already
4576 been deleted, -f/--force can be used to force deletion, and -Af
4583 been deleted, -f/--force can be used to force deletion, and -Af
4577 can be used to remove files from the next revision without
4584 can be used to remove files from the next revision without
4578 deleting them from the working directory.
4585 deleting them from the working directory.
4579
4586
4580 The following table details the behavior of remove for different
4587 The following table details the behavior of remove for different
4581 file states (columns) and option combinations (rows). The file
4588 file states (columns) and option combinations (rows). The file
4582 states are Added [A], Clean [C], Modified [M] and Missing [!]
4589 states are Added [A], Clean [C], Modified [M] and Missing [!]
4583 (as reported by :hg:`status`). The actions are Warn, Remove
4590 (as reported by :hg:`status`). The actions are Warn, Remove
4584 (from branch) and Delete (from disk):
4591 (from branch) and Delete (from disk):
4585
4592
4586 ======= == == == ==
4593 ======= == == == ==
4587 A C M !
4594 A C M !
4588 ======= == == == ==
4595 ======= == == == ==
4589 none W RD W R
4596 none W RD W R
4590 -f R RD RD R
4597 -f R RD RD R
4591 -A W W W R
4598 -A W W W R
4592 -Af R R R R
4599 -Af R R R R
4593 ======= == == == ==
4600 ======= == == == ==
4594
4601
4595 Note that remove never deletes files in Added [A] state from the
4602 Note that remove never deletes files in Added [A] state from the
4596 working directory, not even if option --force is specified.
4603 working directory, not even if option --force is specified.
4597
4604
4598 Returns 0 on success, 1 if any warnings encountered.
4605 Returns 0 on success, 1 if any warnings encountered.
4599 """
4606 """
4600
4607
4601 ret = 0
4608 ret = 0
4602 after, force = opts.get('after'), opts.get('force')
4609 after, force = opts.get('after'), opts.get('force')
4603 if not pats and not after:
4610 if not pats and not after:
4604 raise util.Abort(_('no files specified'))
4611 raise util.Abort(_('no files specified'))
4605
4612
4606 m = scmutil.match(repo[None], pats, opts)
4613 m = scmutil.match(repo[None], pats, opts)
4607 s = repo.status(match=m, clean=True)
4614 s = repo.status(match=m, clean=True)
4608 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4615 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4609
4616
4610 # warn about failure to delete explicit files/dirs
4617 # warn about failure to delete explicit files/dirs
4611 wctx = repo[None]
4618 wctx = repo[None]
4612 for f in m.files():
4619 for f in m.files():
4613 if f in repo.dirstate or f in wctx.dirs():
4620 if f in repo.dirstate or f in wctx.dirs():
4614 continue
4621 continue
4615 if os.path.exists(m.rel(f)):
4622 if os.path.exists(m.rel(f)):
4616 if os.path.isdir(m.rel(f)):
4623 if os.path.isdir(m.rel(f)):
4617 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4624 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4618 else:
4625 else:
4619 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4626 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4620 # missing files will generate a warning elsewhere
4627 # missing files will generate a warning elsewhere
4621 ret = 1
4628 ret = 1
4622
4629
4623 if force:
4630 if force:
4624 list = modified + deleted + clean + added
4631 list = modified + deleted + clean + added
4625 elif after:
4632 elif after:
4626 list = deleted
4633 list = deleted
4627 for f in modified + added + clean:
4634 for f in modified + added + clean:
4628 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4635 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4629 ret = 1
4636 ret = 1
4630 else:
4637 else:
4631 list = deleted + clean
4638 list = deleted + clean
4632 for f in modified:
4639 for f in modified:
4633 ui.warn(_('not removing %s: file is modified (use -f'
4640 ui.warn(_('not removing %s: file is modified (use -f'
4634 ' to force removal)\n') % m.rel(f))
4641 ' to force removal)\n') % m.rel(f))
4635 ret = 1
4642 ret = 1
4636 for f in added:
4643 for f in added:
4637 ui.warn(_('not removing %s: file has been marked for add'
4644 ui.warn(_('not removing %s: file has been marked for add'
4638 ' (use forget to undo)\n') % m.rel(f))
4645 ' (use forget to undo)\n') % m.rel(f))
4639 ret = 1
4646 ret = 1
4640
4647
4641 for f in sorted(list):
4648 for f in sorted(list):
4642 if ui.verbose or not m.exact(f):
4649 if ui.verbose or not m.exact(f):
4643 ui.status(_('removing %s\n') % m.rel(f))
4650 ui.status(_('removing %s\n') % m.rel(f))
4644
4651
4645 wlock = repo.wlock()
4652 wlock = repo.wlock()
4646 try:
4653 try:
4647 if not after:
4654 if not after:
4648 for f in list:
4655 for f in list:
4649 if f in added:
4656 if f in added:
4650 continue # we never unlink added files on remove
4657 continue # we never unlink added files on remove
4651 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4658 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4652 repo[None].forget(list)
4659 repo[None].forget(list)
4653 finally:
4660 finally:
4654 wlock.release()
4661 wlock.release()
4655
4662
4656 return ret
4663 return ret
4657
4664
4658 @command('rename|move|mv',
4665 @command('rename|move|mv',
4659 [('A', 'after', None, _('record a rename that has already occurred')),
4666 [('A', 'after', None, _('record a rename that has already occurred')),
4660 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4667 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4661 ] + walkopts + dryrunopts,
4668 ] + walkopts + dryrunopts,
4662 _('[OPTION]... SOURCE... DEST'))
4669 _('[OPTION]... SOURCE... DEST'))
4663 def rename(ui, repo, *pats, **opts):
4670 def rename(ui, repo, *pats, **opts):
4664 """rename files; equivalent of copy + remove
4671 """rename files; equivalent of copy + remove
4665
4672
4666 Mark dest as copies of sources; mark sources for deletion. If dest
4673 Mark dest as copies of sources; mark sources for deletion. If dest
4667 is a directory, copies are put in that directory. If dest is a
4674 is a directory, copies are put in that directory. If dest is a
4668 file, there can only be one source.
4675 file, there can only be one source.
4669
4676
4670 By default, this command copies the contents of files as they
4677 By default, this command copies the contents of files as they
4671 exist in the working directory. If invoked with -A/--after, the
4678 exist in the working directory. If invoked with -A/--after, the
4672 operation is recorded, but no copying is performed.
4679 operation is recorded, but no copying is performed.
4673
4680
4674 This command takes effect at the next commit. To undo a rename
4681 This command takes effect at the next commit. To undo a rename
4675 before that, see :hg:`revert`.
4682 before that, see :hg:`revert`.
4676
4683
4677 Returns 0 on success, 1 if errors are encountered.
4684 Returns 0 on success, 1 if errors are encountered.
4678 """
4685 """
4679 wlock = repo.wlock(False)
4686 wlock = repo.wlock(False)
4680 try:
4687 try:
4681 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4688 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4682 finally:
4689 finally:
4683 wlock.release()
4690 wlock.release()
4684
4691
4685 @command('resolve',
4692 @command('resolve',
4686 [('a', 'all', None, _('select all unresolved files')),
4693 [('a', 'all', None, _('select all unresolved files')),
4687 ('l', 'list', None, _('list state of files needing merge')),
4694 ('l', 'list', None, _('list state of files needing merge')),
4688 ('m', 'mark', None, _('mark files as resolved')),
4695 ('m', 'mark', None, _('mark files as resolved')),
4689 ('u', 'unmark', None, _('mark files as unresolved')),
4696 ('u', 'unmark', None, _('mark files as unresolved')),
4690 ('n', 'no-status', None, _('hide status prefix'))]
4697 ('n', 'no-status', None, _('hide status prefix'))]
4691 + mergetoolopts + walkopts,
4698 + mergetoolopts + walkopts,
4692 _('[OPTION]... [FILE]...'))
4699 _('[OPTION]... [FILE]...'))
4693 def resolve(ui, repo, *pats, **opts):
4700 def resolve(ui, repo, *pats, **opts):
4694 """redo merges or set/view the merge status of files
4701 """redo merges or set/view the merge status of files
4695
4702
4696 Merges with unresolved conflicts are often the result of
4703 Merges with unresolved conflicts are often the result of
4697 non-interactive merging using the ``internal:merge`` configuration
4704 non-interactive merging using the ``internal:merge`` configuration
4698 setting, or a command-line merge tool like ``diff3``. The resolve
4705 setting, or a command-line merge tool like ``diff3``. The resolve
4699 command is used to manage the files involved in a merge, after
4706 command is used to manage the files involved in a merge, after
4700 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4707 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4701 working directory must have two parents). See :hg:`help
4708 working directory must have two parents). See :hg:`help
4702 merge-tools` for information on configuring merge tools.
4709 merge-tools` for information on configuring merge tools.
4703
4710
4704 The resolve command can be used in the following ways:
4711 The resolve command can be used in the following ways:
4705
4712
4706 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4713 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4707 files, discarding any previous merge attempts. Re-merging is not
4714 files, discarding any previous merge attempts. Re-merging is not
4708 performed for files already marked as resolved. Use ``--all/-a``
4715 performed for files already marked as resolved. Use ``--all/-a``
4709 to select all unresolved files. ``--tool`` can be used to specify
4716 to select all unresolved files. ``--tool`` can be used to specify
4710 the merge tool used for the given files. It overrides the HGMERGE
4717 the merge tool used for the given files. It overrides the HGMERGE
4711 environment variable and your configuration files. Previous file
4718 environment variable and your configuration files. Previous file
4712 contents are saved with a ``.orig`` suffix.
4719 contents are saved with a ``.orig`` suffix.
4713
4720
4714 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4721 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4715 (e.g. after having manually fixed-up the files). The default is
4722 (e.g. after having manually fixed-up the files). The default is
4716 to mark all unresolved files.
4723 to mark all unresolved files.
4717
4724
4718 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4725 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4719 default is to mark all resolved files.
4726 default is to mark all resolved files.
4720
4727
4721 - :hg:`resolve -l`: list files which had or still have conflicts.
4728 - :hg:`resolve -l`: list files which had or still have conflicts.
4722 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4729 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4723
4730
4724 Note that Mercurial will not let you commit files with unresolved
4731 Note that Mercurial will not let you commit files with unresolved
4725 merge conflicts. You must use :hg:`resolve -m ...` before you can
4732 merge conflicts. You must use :hg:`resolve -m ...` before you can
4726 commit after a conflicting merge.
4733 commit after a conflicting merge.
4727
4734
4728 Returns 0 on success, 1 if any files fail a resolve attempt.
4735 Returns 0 on success, 1 if any files fail a resolve attempt.
4729 """
4736 """
4730
4737
4731 all, mark, unmark, show, nostatus = \
4738 all, mark, unmark, show, nostatus = \
4732 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4739 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4733
4740
4734 if (show and (mark or unmark)) or (mark and unmark):
4741 if (show and (mark or unmark)) or (mark and unmark):
4735 raise util.Abort(_("too many options specified"))
4742 raise util.Abort(_("too many options specified"))
4736 if pats and all:
4743 if pats and all:
4737 raise util.Abort(_("can't specify --all and patterns"))
4744 raise util.Abort(_("can't specify --all and patterns"))
4738 if not (all or pats or show or mark or unmark):
4745 if not (all or pats or show or mark or unmark):
4739 raise util.Abort(_('no files or directories specified; '
4746 raise util.Abort(_('no files or directories specified; '
4740 'use --all to remerge all files'))
4747 'use --all to remerge all files'))
4741
4748
4742 ms = mergemod.mergestate(repo)
4749 ms = mergemod.mergestate(repo)
4743 m = scmutil.match(repo[None], pats, opts)
4750 m = scmutil.match(repo[None], pats, opts)
4744 ret = 0
4751 ret = 0
4745
4752
4746 for f in ms:
4753 for f in ms:
4747 if m(f):
4754 if m(f):
4748 if show:
4755 if show:
4749 if nostatus:
4756 if nostatus:
4750 ui.write("%s\n" % f)
4757 ui.write("%s\n" % f)
4751 else:
4758 else:
4752 ui.write("%s %s\n" % (ms[f].upper(), f),
4759 ui.write("%s %s\n" % (ms[f].upper(), f),
4753 label='resolve.' +
4760 label='resolve.' +
4754 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4761 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4755 elif mark:
4762 elif mark:
4756 ms.mark(f, "r")
4763 ms.mark(f, "r")
4757 elif unmark:
4764 elif unmark:
4758 ms.mark(f, "u")
4765 ms.mark(f, "u")
4759 else:
4766 else:
4760 wctx = repo[None]
4767 wctx = repo[None]
4761 mctx = wctx.parents()[-1]
4768 mctx = wctx.parents()[-1]
4762
4769
4763 # backup pre-resolve (merge uses .orig for its own purposes)
4770 # backup pre-resolve (merge uses .orig for its own purposes)
4764 a = repo.wjoin(f)
4771 a = repo.wjoin(f)
4765 util.copyfile(a, a + ".resolve")
4772 util.copyfile(a, a + ".resolve")
4766
4773
4767 try:
4774 try:
4768 # resolve file
4775 # resolve file
4769 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4776 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4770 if ms.resolve(f, wctx, mctx):
4777 if ms.resolve(f, wctx, mctx):
4771 ret = 1
4778 ret = 1
4772 finally:
4779 finally:
4773 ui.setconfig('ui', 'forcemerge', '')
4780 ui.setconfig('ui', 'forcemerge', '')
4774 ms.commit()
4781 ms.commit()
4775
4782
4776 # replace filemerge's .orig file with our resolve file
4783 # replace filemerge's .orig file with our resolve file
4777 util.rename(a + ".resolve", a + ".orig")
4784 util.rename(a + ".resolve", a + ".orig")
4778
4785
4779 ms.commit()
4786 ms.commit()
4780 return ret
4787 return ret
4781
4788
4782 @command('revert',
4789 @command('revert',
4783 [('a', 'all', None, _('revert all changes when no arguments given')),
4790 [('a', 'all', None, _('revert all changes when no arguments given')),
4784 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4791 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4785 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4792 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4786 ('C', 'no-backup', None, _('do not save backup copies of files')),
4793 ('C', 'no-backup', None, _('do not save backup copies of files')),
4787 ] + walkopts + dryrunopts,
4794 ] + walkopts + dryrunopts,
4788 _('[OPTION]... [-r REV] [NAME]...'))
4795 _('[OPTION]... [-r REV] [NAME]...'))
4789 def revert(ui, repo, *pats, **opts):
4796 def revert(ui, repo, *pats, **opts):
4790 """restore files to their checkout state
4797 """restore files to their checkout state
4791
4798
4792 .. note::
4799 .. note::
4793
4800
4794 To check out earlier revisions, you should use :hg:`update REV`.
4801 To check out earlier revisions, you should use :hg:`update REV`.
4795 To cancel an uncommitted merge (and lose your changes), use
4802 To cancel an uncommitted merge (and lose your changes), use
4796 :hg:`update --clean .`.
4803 :hg:`update --clean .`.
4797
4804
4798 With no revision specified, revert the specified files or directories
4805 With no revision specified, revert the specified files or directories
4799 to the contents they had in the parent of the working directory.
4806 to the contents they had in the parent of the working directory.
4800 This restores the contents of files to an unmodified
4807 This restores the contents of files to an unmodified
4801 state and unschedules adds, removes, copies, and renames. If the
4808 state and unschedules adds, removes, copies, and renames. If the
4802 working directory has two parents, you must explicitly specify a
4809 working directory has two parents, you must explicitly specify a
4803 revision.
4810 revision.
4804
4811
4805 Using the -r/--rev or -d/--date options, revert the given files or
4812 Using the -r/--rev or -d/--date options, revert the given files or
4806 directories to their states as of a specific revision. Because
4813 directories to their states as of a specific revision. Because
4807 revert does not change the working directory parents, this will
4814 revert does not change the working directory parents, this will
4808 cause these files to appear modified. This can be helpful to "back
4815 cause these files to appear modified. This can be helpful to "back
4809 out" some or all of an earlier change. See :hg:`backout` for a
4816 out" some or all of an earlier change. See :hg:`backout` for a
4810 related method.
4817 related method.
4811
4818
4812 Modified files are saved with a .orig suffix before reverting.
4819 Modified files are saved with a .orig suffix before reverting.
4813 To disable these backups, use --no-backup.
4820 To disable these backups, use --no-backup.
4814
4821
4815 See :hg:`help dates` for a list of formats valid for -d/--date.
4822 See :hg:`help dates` for a list of formats valid for -d/--date.
4816
4823
4817 Returns 0 on success.
4824 Returns 0 on success.
4818 """
4825 """
4819
4826
4820 if opts.get("date"):
4827 if opts.get("date"):
4821 if opts.get("rev"):
4828 if opts.get("rev"):
4822 raise util.Abort(_("you can't specify a revision and a date"))
4829 raise util.Abort(_("you can't specify a revision and a date"))
4823 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4830 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4824
4831
4825 parent, p2 = repo.dirstate.parents()
4832 parent, p2 = repo.dirstate.parents()
4826 if not opts.get('rev') and p2 != nullid:
4833 if not opts.get('rev') and p2 != nullid:
4827 # revert after merge is a trap for new users (issue2915)
4834 # revert after merge is a trap for new users (issue2915)
4828 raise util.Abort(_('uncommitted merge with no revision specified'),
4835 raise util.Abort(_('uncommitted merge with no revision specified'),
4829 hint=_('use "hg update" or see "hg help revert"'))
4836 hint=_('use "hg update" or see "hg help revert"'))
4830
4837
4831 ctx = scmutil.revsingle(repo, opts.get('rev'))
4838 ctx = scmutil.revsingle(repo, opts.get('rev'))
4832
4839
4833 if not pats and not opts.get('all'):
4840 if not pats and not opts.get('all'):
4834 msg = _("no files or directories specified")
4841 msg = _("no files or directories specified")
4835 if p2 != nullid:
4842 if p2 != nullid:
4836 hint = _("uncommitted merge, use --all to discard all changes,"
4843 hint = _("uncommitted merge, use --all to discard all changes,"
4837 " or 'hg update -C .' to abort the merge")
4844 " or 'hg update -C .' to abort the merge")
4838 raise util.Abort(msg, hint=hint)
4845 raise util.Abort(msg, hint=hint)
4839 dirty = util.any(repo.status())
4846 dirty = util.any(repo.status())
4840 node = ctx.node()
4847 node = ctx.node()
4841 if node != parent:
4848 if node != parent:
4842 if dirty:
4849 if dirty:
4843 hint = _("uncommitted changes, use --all to discard all"
4850 hint = _("uncommitted changes, use --all to discard all"
4844 " changes, or 'hg update %s' to update") % ctx.rev()
4851 " changes, or 'hg update %s' to update") % ctx.rev()
4845 else:
4852 else:
4846 hint = _("use --all to revert all files,"
4853 hint = _("use --all to revert all files,"
4847 " or 'hg update %s' to update") % ctx.rev()
4854 " or 'hg update %s' to update") % ctx.rev()
4848 elif dirty:
4855 elif dirty:
4849 hint = _("uncommitted changes, use --all to discard all changes")
4856 hint = _("uncommitted changes, use --all to discard all changes")
4850 else:
4857 else:
4851 hint = _("use --all to revert all files")
4858 hint = _("use --all to revert all files")
4852 raise util.Abort(msg, hint=hint)
4859 raise util.Abort(msg, hint=hint)
4853
4860
4854 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4861 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4855
4862
4856 @command('rollback', dryrunopts +
4863 @command('rollback', dryrunopts +
4857 [('f', 'force', False, _('ignore safety measures'))])
4864 [('f', 'force', False, _('ignore safety measures'))])
4858 def rollback(ui, repo, **opts):
4865 def rollback(ui, repo, **opts):
4859 """roll back the last transaction (dangerous)
4866 """roll back the last transaction (dangerous)
4860
4867
4861 This command should be used with care. There is only one level of
4868 This command should be used with care. There is only one level of
4862 rollback, and there is no way to undo a rollback. It will also
4869 rollback, and there is no way to undo a rollback. It will also
4863 restore the dirstate at the time of the last transaction, losing
4870 restore the dirstate at the time of the last transaction, losing
4864 any dirstate changes since that time. This command does not alter
4871 any dirstate changes since that time. This command does not alter
4865 the working directory.
4872 the working directory.
4866
4873
4867 Transactions are used to encapsulate the effects of all commands
4874 Transactions are used to encapsulate the effects of all commands
4868 that create new changesets or propagate existing changesets into a
4875 that create new changesets or propagate existing changesets into a
4869 repository.
4876 repository.
4870
4877
4871 .. container:: verbose
4878 .. container:: verbose
4872
4879
4873 For example, the following commands are transactional, and their
4880 For example, the following commands are transactional, and their
4874 effects can be rolled back:
4881 effects can be rolled back:
4875
4882
4876 - commit
4883 - commit
4877 - import
4884 - import
4878 - pull
4885 - pull
4879 - push (with this repository as the destination)
4886 - push (with this repository as the destination)
4880 - unbundle
4887 - unbundle
4881
4888
4882 To avoid permanent data loss, rollback will refuse to rollback a
4889 To avoid permanent data loss, rollback will refuse to rollback a
4883 commit transaction if it isn't checked out. Use --force to
4890 commit transaction if it isn't checked out. Use --force to
4884 override this protection.
4891 override this protection.
4885
4892
4886 This command is not intended for use on public repositories. Once
4893 This command is not intended for use on public repositories. Once
4887 changes are visible for pull by other users, rolling a transaction
4894 changes are visible for pull by other users, rolling a transaction
4888 back locally is ineffective (someone else may already have pulled
4895 back locally is ineffective (someone else may already have pulled
4889 the changes). Furthermore, a race is possible with readers of the
4896 the changes). Furthermore, a race is possible with readers of the
4890 repository; for example an in-progress pull from the repository
4897 repository; for example an in-progress pull from the repository
4891 may fail if a rollback is performed.
4898 may fail if a rollback is performed.
4892
4899
4893 Returns 0 on success, 1 if no rollback data is available.
4900 Returns 0 on success, 1 if no rollback data is available.
4894 """
4901 """
4895 return repo.rollback(dryrun=opts.get('dry_run'),
4902 return repo.rollback(dryrun=opts.get('dry_run'),
4896 force=opts.get('force'))
4903 force=opts.get('force'))
4897
4904
4898 @command('root', [])
4905 @command('root', [])
4899 def root(ui, repo):
4906 def root(ui, repo):
4900 """print the root (top) of the current working directory
4907 """print the root (top) of the current working directory
4901
4908
4902 Print the root directory of the current repository.
4909 Print the root directory of the current repository.
4903
4910
4904 Returns 0 on success.
4911 Returns 0 on success.
4905 """
4912 """
4906 ui.write(repo.root + "\n")
4913 ui.write(repo.root + "\n")
4907
4914
4908 @command('^serve',
4915 @command('^serve',
4909 [('A', 'accesslog', '', _('name of access log file to write to'),
4916 [('A', 'accesslog', '', _('name of access log file to write to'),
4910 _('FILE')),
4917 _('FILE')),
4911 ('d', 'daemon', None, _('run server in background')),
4918 ('d', 'daemon', None, _('run server in background')),
4912 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4919 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4913 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4920 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4914 # use string type, then we can check if something was passed
4921 # use string type, then we can check if something was passed
4915 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4922 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4916 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4923 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4917 _('ADDR')),
4924 _('ADDR')),
4918 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4925 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4919 _('PREFIX')),
4926 _('PREFIX')),
4920 ('n', 'name', '',
4927 ('n', 'name', '',
4921 _('name to show in web pages (default: working directory)'), _('NAME')),
4928 _('name to show in web pages (default: working directory)'), _('NAME')),
4922 ('', 'web-conf', '',
4929 ('', 'web-conf', '',
4923 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4930 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4924 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4931 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4925 _('FILE')),
4932 _('FILE')),
4926 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4933 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4927 ('', 'stdio', None, _('for remote clients')),
4934 ('', 'stdio', None, _('for remote clients')),
4928 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4935 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4929 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4936 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4930 ('', 'style', '', _('template style to use'), _('STYLE')),
4937 ('', 'style', '', _('template style to use'), _('STYLE')),
4931 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4938 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4932 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4939 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4933 _('[OPTION]...'))
4940 _('[OPTION]...'))
4934 def serve(ui, repo, **opts):
4941 def serve(ui, repo, **opts):
4935 """start stand-alone webserver
4942 """start stand-alone webserver
4936
4943
4937 Start a local HTTP repository browser and pull server. You can use
4944 Start a local HTTP repository browser and pull server. You can use
4938 this for ad-hoc sharing and browsing of repositories. It is
4945 this for ad-hoc sharing and browsing of repositories. It is
4939 recommended to use a real web server to serve a repository for
4946 recommended to use a real web server to serve a repository for
4940 longer periods of time.
4947 longer periods of time.
4941
4948
4942 Please note that the server does not implement access control.
4949 Please note that the server does not implement access control.
4943 This means that, by default, anybody can read from the server and
4950 This means that, by default, anybody can read from the server and
4944 nobody can write to it by default. Set the ``web.allow_push``
4951 nobody can write to it by default. Set the ``web.allow_push``
4945 option to ``*`` to allow everybody to push to the server. You
4952 option to ``*`` to allow everybody to push to the server. You
4946 should use a real web server if you need to authenticate users.
4953 should use a real web server if you need to authenticate users.
4947
4954
4948 By default, the server logs accesses to stdout and errors to
4955 By default, the server logs accesses to stdout and errors to
4949 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4956 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4950 files.
4957 files.
4951
4958
4952 To have the server choose a free port number to listen on, specify
4959 To have the server choose a free port number to listen on, specify
4953 a port number of 0; in this case, the server will print the port
4960 a port number of 0; in this case, the server will print the port
4954 number it uses.
4961 number it uses.
4955
4962
4956 Returns 0 on success.
4963 Returns 0 on success.
4957 """
4964 """
4958
4965
4959 if opts["stdio"] and opts["cmdserver"]:
4966 if opts["stdio"] and opts["cmdserver"]:
4960 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4967 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4961
4968
4962 def checkrepo():
4969 def checkrepo():
4963 if repo is None:
4970 if repo is None:
4964 raise error.RepoError(_("there is no Mercurial repository here"
4971 raise error.RepoError(_("there is no Mercurial repository here"
4965 " (.hg not found)"))
4972 " (.hg not found)"))
4966
4973
4967 if opts["stdio"]:
4974 if opts["stdio"]:
4968 checkrepo()
4975 checkrepo()
4969 s = sshserver.sshserver(ui, repo)
4976 s = sshserver.sshserver(ui, repo)
4970 s.serve_forever()
4977 s.serve_forever()
4971
4978
4972 if opts["cmdserver"]:
4979 if opts["cmdserver"]:
4973 checkrepo()
4980 checkrepo()
4974 s = commandserver.server(ui, repo, opts["cmdserver"])
4981 s = commandserver.server(ui, repo, opts["cmdserver"])
4975 return s.serve()
4982 return s.serve()
4976
4983
4977 # this way we can check if something was given in the command-line
4984 # this way we can check if something was given in the command-line
4978 if opts.get('port'):
4985 if opts.get('port'):
4979 opts['port'] = util.getport(opts.get('port'))
4986 opts['port'] = util.getport(opts.get('port'))
4980
4987
4981 baseui = repo and repo.baseui or ui
4988 baseui = repo and repo.baseui or ui
4982 optlist = ("name templates style address port prefix ipv6"
4989 optlist = ("name templates style address port prefix ipv6"
4983 " accesslog errorlog certificate encoding")
4990 " accesslog errorlog certificate encoding")
4984 for o in optlist.split():
4991 for o in optlist.split():
4985 val = opts.get(o, '')
4992 val = opts.get(o, '')
4986 if val in (None, ''): # should check against default options instead
4993 if val in (None, ''): # should check against default options instead
4987 continue
4994 continue
4988 baseui.setconfig("web", o, val)
4995 baseui.setconfig("web", o, val)
4989 if repo and repo.ui != baseui:
4996 if repo and repo.ui != baseui:
4990 repo.ui.setconfig("web", o, val)
4997 repo.ui.setconfig("web", o, val)
4991
4998
4992 o = opts.get('web_conf') or opts.get('webdir_conf')
4999 o = opts.get('web_conf') or opts.get('webdir_conf')
4993 if not o:
5000 if not o:
4994 if not repo:
5001 if not repo:
4995 raise error.RepoError(_("there is no Mercurial repository"
5002 raise error.RepoError(_("there is no Mercurial repository"
4996 " here (.hg not found)"))
5003 " here (.hg not found)"))
4997 o = repo.root
5004 o = repo.root
4998
5005
4999 app = hgweb.hgweb(o, baseui=ui)
5006 app = hgweb.hgweb(o, baseui=ui)
5000
5007
5001 class service(object):
5008 class service(object):
5002 def init(self):
5009 def init(self):
5003 util.setsignalhandler()
5010 util.setsignalhandler()
5004 self.httpd = hgweb.server.create_server(ui, app)
5011 self.httpd = hgweb.server.create_server(ui, app)
5005
5012
5006 if opts['port'] and not ui.verbose:
5013 if opts['port'] and not ui.verbose:
5007 return
5014 return
5008
5015
5009 if self.httpd.prefix:
5016 if self.httpd.prefix:
5010 prefix = self.httpd.prefix.strip('/') + '/'
5017 prefix = self.httpd.prefix.strip('/') + '/'
5011 else:
5018 else:
5012 prefix = ''
5019 prefix = ''
5013
5020
5014 port = ':%d' % self.httpd.port
5021 port = ':%d' % self.httpd.port
5015 if port == ':80':
5022 if port == ':80':
5016 port = ''
5023 port = ''
5017
5024
5018 bindaddr = self.httpd.addr
5025 bindaddr = self.httpd.addr
5019 if bindaddr == '0.0.0.0':
5026 if bindaddr == '0.0.0.0':
5020 bindaddr = '*'
5027 bindaddr = '*'
5021 elif ':' in bindaddr: # IPv6
5028 elif ':' in bindaddr: # IPv6
5022 bindaddr = '[%s]' % bindaddr
5029 bindaddr = '[%s]' % bindaddr
5023
5030
5024 fqaddr = self.httpd.fqaddr
5031 fqaddr = self.httpd.fqaddr
5025 if ':' in fqaddr:
5032 if ':' in fqaddr:
5026 fqaddr = '[%s]' % fqaddr
5033 fqaddr = '[%s]' % fqaddr
5027 if opts['port']:
5034 if opts['port']:
5028 write = ui.status
5035 write = ui.status
5029 else:
5036 else:
5030 write = ui.write
5037 write = ui.write
5031 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5038 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5032 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5039 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5033
5040
5034 def run(self):
5041 def run(self):
5035 self.httpd.serve_forever()
5042 self.httpd.serve_forever()
5036
5043
5037 service = service()
5044 service = service()
5038
5045
5039 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5046 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5040
5047
5041 @command('showconfig|debugconfig',
5048 @command('showconfig|debugconfig',
5042 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5049 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5043 _('[-u] [NAME]...'))
5050 _('[-u] [NAME]...'))
5044 def showconfig(ui, repo, *values, **opts):
5051 def showconfig(ui, repo, *values, **opts):
5045 """show combined config settings from all hgrc files
5052 """show combined config settings from all hgrc files
5046
5053
5047 With no arguments, print names and values of all config items.
5054 With no arguments, print names and values of all config items.
5048
5055
5049 With one argument of the form section.name, print just the value
5056 With one argument of the form section.name, print just the value
5050 of that config item.
5057 of that config item.
5051
5058
5052 With multiple arguments, print names and values of all config
5059 With multiple arguments, print names and values of all config
5053 items with matching section names.
5060 items with matching section names.
5054
5061
5055 With --debug, the source (filename and line number) is printed
5062 With --debug, the source (filename and line number) is printed
5056 for each config item.
5063 for each config item.
5057
5064
5058 Returns 0 on success.
5065 Returns 0 on success.
5059 """
5066 """
5060
5067
5061 for f in scmutil.rcpath():
5068 for f in scmutil.rcpath():
5062 ui.debug('read config from: %s\n' % f)
5069 ui.debug('read config from: %s\n' % f)
5063 untrusted = bool(opts.get('untrusted'))
5070 untrusted = bool(opts.get('untrusted'))
5064 if values:
5071 if values:
5065 sections = [v for v in values if '.' not in v]
5072 sections = [v for v in values if '.' not in v]
5066 items = [v for v in values if '.' in v]
5073 items = [v for v in values if '.' in v]
5067 if len(items) > 1 or items and sections:
5074 if len(items) > 1 or items and sections:
5068 raise util.Abort(_('only one config item permitted'))
5075 raise util.Abort(_('only one config item permitted'))
5069 for section, name, value in ui.walkconfig(untrusted=untrusted):
5076 for section, name, value in ui.walkconfig(untrusted=untrusted):
5070 value = str(value).replace('\n', '\\n')
5077 value = str(value).replace('\n', '\\n')
5071 sectname = section + '.' + name
5078 sectname = section + '.' + name
5072 if values:
5079 if values:
5073 for v in values:
5080 for v in values:
5074 if v == section:
5081 if v == section:
5075 ui.debug('%s: ' %
5082 ui.debug('%s: ' %
5076 ui.configsource(section, name, untrusted))
5083 ui.configsource(section, name, untrusted))
5077 ui.write('%s=%s\n' % (sectname, value))
5084 ui.write('%s=%s\n' % (sectname, value))
5078 elif v == sectname:
5085 elif v == sectname:
5079 ui.debug('%s: ' %
5086 ui.debug('%s: ' %
5080 ui.configsource(section, name, untrusted))
5087 ui.configsource(section, name, untrusted))
5081 ui.write(value, '\n')
5088 ui.write(value, '\n')
5082 else:
5089 else:
5083 ui.debug('%s: ' %
5090 ui.debug('%s: ' %
5084 ui.configsource(section, name, untrusted))
5091 ui.configsource(section, name, untrusted))
5085 ui.write('%s=%s\n' % (sectname, value))
5092 ui.write('%s=%s\n' % (sectname, value))
5086
5093
5087 @command('^status|st',
5094 @command('^status|st',
5088 [('A', 'all', None, _('show status of all files')),
5095 [('A', 'all', None, _('show status of all files')),
5089 ('m', 'modified', None, _('show only modified files')),
5096 ('m', 'modified', None, _('show only modified files')),
5090 ('a', 'added', None, _('show only added files')),
5097 ('a', 'added', None, _('show only added files')),
5091 ('r', 'removed', None, _('show only removed files')),
5098 ('r', 'removed', None, _('show only removed files')),
5092 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5099 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5093 ('c', 'clean', None, _('show only files without changes')),
5100 ('c', 'clean', None, _('show only files without changes')),
5094 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5101 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5095 ('i', 'ignored', None, _('show only ignored files')),
5102 ('i', 'ignored', None, _('show only ignored files')),
5096 ('n', 'no-status', None, _('hide status prefix')),
5103 ('n', 'no-status', None, _('hide status prefix')),
5097 ('C', 'copies', None, _('show source of copied files')),
5104 ('C', 'copies', None, _('show source of copied files')),
5098 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5105 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5099 ('', 'rev', [], _('show difference from revision'), _('REV')),
5106 ('', 'rev', [], _('show difference from revision'), _('REV')),
5100 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5107 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5101 ] + walkopts + subrepoopts,
5108 ] + walkopts + subrepoopts,
5102 _('[OPTION]... [FILE]...'))
5109 _('[OPTION]... [FILE]...'))
5103 def status(ui, repo, *pats, **opts):
5110 def status(ui, repo, *pats, **opts):
5104 """show changed files in the working directory
5111 """show changed files in the working directory
5105
5112
5106 Show status of files in the repository. If names are given, only
5113 Show status of files in the repository. If names are given, only
5107 files that match are shown. Files that are clean or ignored or
5114 files that match are shown. Files that are clean or ignored or
5108 the source of a copy/move operation, are not listed unless
5115 the source of a copy/move operation, are not listed unless
5109 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5116 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5110 Unless options described with "show only ..." are given, the
5117 Unless options described with "show only ..." are given, the
5111 options -mardu are used.
5118 options -mardu are used.
5112
5119
5113 Option -q/--quiet hides untracked (unknown and ignored) files
5120 Option -q/--quiet hides untracked (unknown and ignored) files
5114 unless explicitly requested with -u/--unknown or -i/--ignored.
5121 unless explicitly requested with -u/--unknown or -i/--ignored.
5115
5122
5116 .. note::
5123 .. note::
5117 status may appear to disagree with diff if permissions have
5124 status may appear to disagree with diff if permissions have
5118 changed or a merge has occurred. The standard diff format does
5125 changed or a merge has occurred. The standard diff format does
5119 not report permission changes and diff only reports changes
5126 not report permission changes and diff only reports changes
5120 relative to one merge parent.
5127 relative to one merge parent.
5121
5128
5122 If one revision is given, it is used as the base revision.
5129 If one revision is given, it is used as the base revision.
5123 If two revisions are given, the differences between them are
5130 If two revisions are given, the differences between them are
5124 shown. The --change option can also be used as a shortcut to list
5131 shown. The --change option can also be used as a shortcut to list
5125 the changed files of a revision from its first parent.
5132 the changed files of a revision from its first parent.
5126
5133
5127 The codes used to show the status of files are::
5134 The codes used to show the status of files are::
5128
5135
5129 M = modified
5136 M = modified
5130 A = added
5137 A = added
5131 R = removed
5138 R = removed
5132 C = clean
5139 C = clean
5133 ! = missing (deleted by non-hg command, but still tracked)
5140 ! = missing (deleted by non-hg command, but still tracked)
5134 ? = not tracked
5141 ? = not tracked
5135 I = ignored
5142 I = ignored
5136 = origin of the previous file listed as A (added)
5143 = origin of the previous file listed as A (added)
5137
5144
5138 .. container:: verbose
5145 .. container:: verbose
5139
5146
5140 Examples:
5147 Examples:
5141
5148
5142 - show changes in the working directory relative to a
5149 - show changes in the working directory relative to a
5143 changeset::
5150 changeset::
5144
5151
5145 hg status --rev 9353
5152 hg status --rev 9353
5146
5153
5147 - show all changes including copies in an existing changeset::
5154 - show all changes including copies in an existing changeset::
5148
5155
5149 hg status --copies --change 9353
5156 hg status --copies --change 9353
5150
5157
5151 - get a NUL separated list of added files, suitable for xargs::
5158 - get a NUL separated list of added files, suitable for xargs::
5152
5159
5153 hg status -an0
5160 hg status -an0
5154
5161
5155 Returns 0 on success.
5162 Returns 0 on success.
5156 """
5163 """
5157
5164
5158 revs = opts.get('rev')
5165 revs = opts.get('rev')
5159 change = opts.get('change')
5166 change = opts.get('change')
5160
5167
5161 if revs and change:
5168 if revs and change:
5162 msg = _('cannot specify --rev and --change at the same time')
5169 msg = _('cannot specify --rev and --change at the same time')
5163 raise util.Abort(msg)
5170 raise util.Abort(msg)
5164 elif change:
5171 elif change:
5165 node2 = scmutil.revsingle(repo, change, None).node()
5172 node2 = scmutil.revsingle(repo, change, None).node()
5166 node1 = repo[node2].p1().node()
5173 node1 = repo[node2].p1().node()
5167 else:
5174 else:
5168 node1, node2 = scmutil.revpair(repo, revs)
5175 node1, node2 = scmutil.revpair(repo, revs)
5169
5176
5170 cwd = (pats and repo.getcwd()) or ''
5177 cwd = (pats and repo.getcwd()) or ''
5171 end = opts.get('print0') and '\0' or '\n'
5178 end = opts.get('print0') and '\0' or '\n'
5172 copy = {}
5179 copy = {}
5173 states = 'modified added removed deleted unknown ignored clean'.split()
5180 states = 'modified added removed deleted unknown ignored clean'.split()
5174 show = [k for k in states if opts.get(k)]
5181 show = [k for k in states if opts.get(k)]
5175 if opts.get('all'):
5182 if opts.get('all'):
5176 show += ui.quiet and (states[:4] + ['clean']) or states
5183 show += ui.quiet and (states[:4] + ['clean']) or states
5177 if not show:
5184 if not show:
5178 show = ui.quiet and states[:4] or states[:5]
5185 show = ui.quiet and states[:4] or states[:5]
5179
5186
5180 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5187 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5181 'ignored' in show, 'clean' in show, 'unknown' in show,
5188 'ignored' in show, 'clean' in show, 'unknown' in show,
5182 opts.get('subrepos'))
5189 opts.get('subrepos'))
5183 changestates = zip(states, 'MAR!?IC', stat)
5190 changestates = zip(states, 'MAR!?IC', stat)
5184
5191
5185 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5192 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5186 copy = copies.pathcopies(repo[node1], repo[node2])
5193 copy = copies.pathcopies(repo[node1], repo[node2])
5187
5194
5188 fm = ui.formatter('status', opts)
5195 fm = ui.formatter('status', opts)
5189 fmt = '%s' + end
5196 fmt = '%s' + end
5190 showchar = not opts.get('no_status')
5197 showchar = not opts.get('no_status')
5191
5198
5192 for state, char, files in changestates:
5199 for state, char, files in changestates:
5193 if state in show:
5200 if state in show:
5194 label = 'status.' + state
5201 label = 'status.' + state
5195 for f in files:
5202 for f in files:
5196 fm.startitem()
5203 fm.startitem()
5197 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5204 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5198 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5205 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5199 if f in copy:
5206 if f in copy:
5200 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5207 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5201 label='status.copied')
5208 label='status.copied')
5202 fm.end()
5209 fm.end()
5203
5210
5204 @command('^summary|sum',
5211 @command('^summary|sum',
5205 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5212 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5206 def summary(ui, repo, **opts):
5213 def summary(ui, repo, **opts):
5207 """summarize working directory state
5214 """summarize working directory state
5208
5215
5209 This generates a brief summary of the working directory state,
5216 This generates a brief summary of the working directory state,
5210 including parents, branch, commit status, and available updates.
5217 including parents, branch, commit status, and available updates.
5211
5218
5212 With the --remote option, this will check the default paths for
5219 With the --remote option, this will check the default paths for
5213 incoming and outgoing changes. This can be time-consuming.
5220 incoming and outgoing changes. This can be time-consuming.
5214
5221
5215 Returns 0 on success.
5222 Returns 0 on success.
5216 """
5223 """
5217
5224
5218 ctx = repo[None]
5225 ctx = repo[None]
5219 parents = ctx.parents()
5226 parents = ctx.parents()
5220 pnode = parents[0].node()
5227 pnode = parents[0].node()
5221 marks = []
5228 marks = []
5222
5229
5223 for p in parents:
5230 for p in parents:
5224 # label with log.changeset (instead of log.parent) since this
5231 # label with log.changeset (instead of log.parent) since this
5225 # shows a working directory parent *changeset*:
5232 # shows a working directory parent *changeset*:
5226 # i18n: column positioning for "hg summary"
5233 # i18n: column positioning for "hg summary"
5227 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5234 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5228 label='log.changeset changeset.%s' % p.phasestr())
5235 label='log.changeset changeset.%s' % p.phasestr())
5229 ui.write(' '.join(p.tags()), label='log.tag')
5236 ui.write(' '.join(p.tags()), label='log.tag')
5230 if p.bookmarks():
5237 if p.bookmarks():
5231 marks.extend(p.bookmarks())
5238 marks.extend(p.bookmarks())
5232 if p.rev() == -1:
5239 if p.rev() == -1:
5233 if not len(repo):
5240 if not len(repo):
5234 ui.write(_(' (empty repository)'))
5241 ui.write(_(' (empty repository)'))
5235 else:
5242 else:
5236 ui.write(_(' (no revision checked out)'))
5243 ui.write(_(' (no revision checked out)'))
5237 ui.write('\n')
5244 ui.write('\n')
5238 if p.description():
5245 if p.description():
5239 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5246 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5240 label='log.summary')
5247 label='log.summary')
5241
5248
5242 branch = ctx.branch()
5249 branch = ctx.branch()
5243 bheads = repo.branchheads(branch)
5250 bheads = repo.branchheads(branch)
5244 # i18n: column positioning for "hg summary"
5251 # i18n: column positioning for "hg summary"
5245 m = _('branch: %s\n') % branch
5252 m = _('branch: %s\n') % branch
5246 if branch != 'default':
5253 if branch != 'default':
5247 ui.write(m, label='log.branch')
5254 ui.write(m, label='log.branch')
5248 else:
5255 else:
5249 ui.status(m, label='log.branch')
5256 ui.status(m, label='log.branch')
5250
5257
5251 if marks:
5258 if marks:
5252 current = repo._bookmarkcurrent
5259 current = repo._bookmarkcurrent
5253 # i18n: column positioning for "hg summary"
5260 # i18n: column positioning for "hg summary"
5254 ui.write(_('bookmarks:'), label='log.bookmark')
5261 ui.write(_('bookmarks:'), label='log.bookmark')
5255 if current is not None:
5262 if current is not None:
5256 if current in marks:
5263 if current in marks:
5257 ui.write(' *' + current, label='bookmarks.current')
5264 ui.write(' *' + current, label='bookmarks.current')
5258 marks.remove(current)
5265 marks.remove(current)
5259 else:
5266 else:
5260 ui.write(' [%s]' % current, label='bookmarks.current')
5267 ui.write(' [%s]' % current, label='bookmarks.current')
5261 for m in marks:
5268 for m in marks:
5262 ui.write(' ' + m, label='log.bookmark')
5269 ui.write(' ' + m, label='log.bookmark')
5263 ui.write('\n', label='log.bookmark')
5270 ui.write('\n', label='log.bookmark')
5264
5271
5265 st = list(repo.status(unknown=True))[:6]
5272 st = list(repo.status(unknown=True))[:6]
5266
5273
5267 c = repo.dirstate.copies()
5274 c = repo.dirstate.copies()
5268 copied, renamed = [], []
5275 copied, renamed = [], []
5269 for d, s in c.iteritems():
5276 for d, s in c.iteritems():
5270 if s in st[2]:
5277 if s in st[2]:
5271 st[2].remove(s)
5278 st[2].remove(s)
5272 renamed.append(d)
5279 renamed.append(d)
5273 else:
5280 else:
5274 copied.append(d)
5281 copied.append(d)
5275 if d in st[1]:
5282 if d in st[1]:
5276 st[1].remove(d)
5283 st[1].remove(d)
5277 st.insert(3, renamed)
5284 st.insert(3, renamed)
5278 st.insert(4, copied)
5285 st.insert(4, copied)
5279
5286
5280 ms = mergemod.mergestate(repo)
5287 ms = mergemod.mergestate(repo)
5281 st.append([f for f in ms if ms[f] == 'u'])
5288 st.append([f for f in ms if ms[f] == 'u'])
5282
5289
5283 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5290 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5284 st.append(subs)
5291 st.append(subs)
5285
5292
5286 labels = [ui.label(_('%d modified'), 'status.modified'),
5293 labels = [ui.label(_('%d modified'), 'status.modified'),
5287 ui.label(_('%d added'), 'status.added'),
5294 ui.label(_('%d added'), 'status.added'),
5288 ui.label(_('%d removed'), 'status.removed'),
5295 ui.label(_('%d removed'), 'status.removed'),
5289 ui.label(_('%d renamed'), 'status.copied'),
5296 ui.label(_('%d renamed'), 'status.copied'),
5290 ui.label(_('%d copied'), 'status.copied'),
5297 ui.label(_('%d copied'), 'status.copied'),
5291 ui.label(_('%d deleted'), 'status.deleted'),
5298 ui.label(_('%d deleted'), 'status.deleted'),
5292 ui.label(_('%d unknown'), 'status.unknown'),
5299 ui.label(_('%d unknown'), 'status.unknown'),
5293 ui.label(_('%d ignored'), 'status.ignored'),
5300 ui.label(_('%d ignored'), 'status.ignored'),
5294 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5301 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5295 ui.label(_('%d subrepos'), 'status.modified')]
5302 ui.label(_('%d subrepos'), 'status.modified')]
5296 t = []
5303 t = []
5297 for s, l in zip(st, labels):
5304 for s, l in zip(st, labels):
5298 if s:
5305 if s:
5299 t.append(l % len(s))
5306 t.append(l % len(s))
5300
5307
5301 t = ', '.join(t)
5308 t = ', '.join(t)
5302 cleanworkdir = False
5309 cleanworkdir = False
5303
5310
5304 if len(parents) > 1:
5311 if len(parents) > 1:
5305 t += _(' (merge)')
5312 t += _(' (merge)')
5306 elif branch != parents[0].branch():
5313 elif branch != parents[0].branch():
5307 t += _(' (new branch)')
5314 t += _(' (new branch)')
5308 elif (parents[0].closesbranch() and
5315 elif (parents[0].closesbranch() and
5309 pnode in repo.branchheads(branch, closed=True)):
5316 pnode in repo.branchheads(branch, closed=True)):
5310 t += _(' (head closed)')
5317 t += _(' (head closed)')
5311 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5318 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5312 t += _(' (clean)')
5319 t += _(' (clean)')
5313 cleanworkdir = True
5320 cleanworkdir = True
5314 elif pnode not in bheads:
5321 elif pnode not in bheads:
5315 t += _(' (new branch head)')
5322 t += _(' (new branch head)')
5316
5323
5317 if cleanworkdir:
5324 if cleanworkdir:
5318 # i18n: column positioning for "hg summary"
5325 # i18n: column positioning for "hg summary"
5319 ui.status(_('commit: %s\n') % t.strip())
5326 ui.status(_('commit: %s\n') % t.strip())
5320 else:
5327 else:
5321 # i18n: column positioning for "hg summary"
5328 # i18n: column positioning for "hg summary"
5322 ui.write(_('commit: %s\n') % t.strip())
5329 ui.write(_('commit: %s\n') % t.strip())
5323
5330
5324 # all ancestors of branch heads - all ancestors of parent = new csets
5331 # all ancestors of branch heads - all ancestors of parent = new csets
5325 new = [0] * len(repo)
5332 new = [0] * len(repo)
5326 cl = repo.changelog
5333 cl = repo.changelog
5327 for a in [cl.rev(n) for n in bheads]:
5334 for a in [cl.rev(n) for n in bheads]:
5328 new[a] = 1
5335 new[a] = 1
5329 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5336 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5330 new[a] = 1
5337 new[a] = 1
5331 for a in [p.rev() for p in parents]:
5338 for a in [p.rev() for p in parents]:
5332 if a >= 0:
5339 if a >= 0:
5333 new[a] = 0
5340 new[a] = 0
5334 for a in cl.ancestors([p.rev() for p in parents]):
5341 for a in cl.ancestors([p.rev() for p in parents]):
5335 new[a] = 0
5342 new[a] = 0
5336 new = sum(new)
5343 new = sum(new)
5337
5344
5338 if new == 0:
5345 if new == 0:
5339 # i18n: column positioning for "hg summary"
5346 # i18n: column positioning for "hg summary"
5340 ui.status(_('update: (current)\n'))
5347 ui.status(_('update: (current)\n'))
5341 elif pnode not in bheads:
5348 elif pnode not in bheads:
5342 # i18n: column positioning for "hg summary"
5349 # i18n: column positioning for "hg summary"
5343 ui.write(_('update: %d new changesets (update)\n') % new)
5350 ui.write(_('update: %d new changesets (update)\n') % new)
5344 else:
5351 else:
5345 # i18n: column positioning for "hg summary"
5352 # i18n: column positioning for "hg summary"
5346 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5353 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5347 (new, len(bheads)))
5354 (new, len(bheads)))
5348
5355
5349 if opts.get('remote'):
5356 if opts.get('remote'):
5350 t = []
5357 t = []
5351 source, branches = hg.parseurl(ui.expandpath('default'))
5358 source, branches = hg.parseurl(ui.expandpath('default'))
5352 other = hg.peer(repo, {}, source)
5359 other = hg.peer(repo, {}, source)
5353 revs, checkout = hg.addbranchrevs(repo, other, branches,
5360 revs, checkout = hg.addbranchrevs(repo, other, branches,
5354 opts.get('rev'))
5361 opts.get('rev'))
5355 ui.debug('comparing with %s\n' % util.hidepassword(source))
5362 ui.debug('comparing with %s\n' % util.hidepassword(source))
5356 repo.ui.pushbuffer()
5363 repo.ui.pushbuffer()
5357 commoninc = discovery.findcommonincoming(repo, other)
5364 commoninc = discovery.findcommonincoming(repo, other)
5358 _common, incoming, _rheads = commoninc
5365 _common, incoming, _rheads = commoninc
5359 repo.ui.popbuffer()
5366 repo.ui.popbuffer()
5360 if incoming:
5367 if incoming:
5361 t.append(_('1 or more incoming'))
5368 t.append(_('1 or more incoming'))
5362
5369
5363 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5370 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5364 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5371 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5365 if source != dest:
5372 if source != dest:
5366 other = hg.peer(repo, {}, dest)
5373 other = hg.peer(repo, {}, dest)
5367 commoninc = None
5374 commoninc = None
5368 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5375 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5369 repo.ui.pushbuffer()
5376 repo.ui.pushbuffer()
5370 outgoing = discovery.findcommonoutgoing(repo, other,
5377 outgoing = discovery.findcommonoutgoing(repo, other,
5371 commoninc=commoninc)
5378 commoninc=commoninc)
5372 repo.ui.popbuffer()
5379 repo.ui.popbuffer()
5373 o = outgoing.missing
5380 o = outgoing.missing
5374 if o:
5381 if o:
5375 t.append(_('%d outgoing') % len(o))
5382 t.append(_('%d outgoing') % len(o))
5376 if 'bookmarks' in other.listkeys('namespaces'):
5383 if 'bookmarks' in other.listkeys('namespaces'):
5377 lmarks = repo.listkeys('bookmarks')
5384 lmarks = repo.listkeys('bookmarks')
5378 rmarks = other.listkeys('bookmarks')
5385 rmarks = other.listkeys('bookmarks')
5379 diff = set(rmarks) - set(lmarks)
5386 diff = set(rmarks) - set(lmarks)
5380 if len(diff) > 0:
5387 if len(diff) > 0:
5381 t.append(_('%d incoming bookmarks') % len(diff))
5388 t.append(_('%d incoming bookmarks') % len(diff))
5382 diff = set(lmarks) - set(rmarks)
5389 diff = set(lmarks) - set(rmarks)
5383 if len(diff) > 0:
5390 if len(diff) > 0:
5384 t.append(_('%d outgoing bookmarks') % len(diff))
5391 t.append(_('%d outgoing bookmarks') % len(diff))
5385
5392
5386 if t:
5393 if t:
5387 # i18n: column positioning for "hg summary"
5394 # i18n: column positioning for "hg summary"
5388 ui.write(_('remote: %s\n') % (', '.join(t)))
5395 ui.write(_('remote: %s\n') % (', '.join(t)))
5389 else:
5396 else:
5390 # i18n: column positioning for "hg summary"
5397 # i18n: column positioning for "hg summary"
5391 ui.status(_('remote: (synced)\n'))
5398 ui.status(_('remote: (synced)\n'))
5392
5399
5393 @command('tag',
5400 @command('tag',
5394 [('f', 'force', None, _('force tag')),
5401 [('f', 'force', None, _('force tag')),
5395 ('l', 'local', None, _('make the tag local')),
5402 ('l', 'local', None, _('make the tag local')),
5396 ('r', 'rev', '', _('revision to tag'), _('REV')),
5403 ('r', 'rev', '', _('revision to tag'), _('REV')),
5397 ('', 'remove', None, _('remove a tag')),
5404 ('', 'remove', None, _('remove a tag')),
5398 # -l/--local is already there, commitopts cannot be used
5405 # -l/--local is already there, commitopts cannot be used
5399 ('e', 'edit', None, _('edit commit message')),
5406 ('e', 'edit', None, _('edit commit message')),
5400 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5407 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5401 ] + commitopts2,
5408 ] + commitopts2,
5402 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5409 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5403 def tag(ui, repo, name1, *names, **opts):
5410 def tag(ui, repo, name1, *names, **opts):
5404 """add one or more tags for the current or given revision
5411 """add one or more tags for the current or given revision
5405
5412
5406 Name a particular revision using <name>.
5413 Name a particular revision using <name>.
5407
5414
5408 Tags are used to name particular revisions of the repository and are
5415 Tags are used to name particular revisions of the repository and are
5409 very useful to compare different revisions, to go back to significant
5416 very useful to compare different revisions, to go back to significant
5410 earlier versions or to mark branch points as releases, etc. Changing
5417 earlier versions or to mark branch points as releases, etc. Changing
5411 an existing tag is normally disallowed; use -f/--force to override.
5418 an existing tag is normally disallowed; use -f/--force to override.
5412
5419
5413 If no revision is given, the parent of the working directory is
5420 If no revision is given, the parent of the working directory is
5414 used, or tip if no revision is checked out.
5421 used, or tip if no revision is checked out.
5415
5422
5416 To facilitate version control, distribution, and merging of tags,
5423 To facilitate version control, distribution, and merging of tags,
5417 they are stored as a file named ".hgtags" which is managed similarly
5424 they are stored as a file named ".hgtags" which is managed similarly
5418 to other project files and can be hand-edited if necessary. This
5425 to other project files and can be hand-edited if necessary. This
5419 also means that tagging creates a new commit. The file
5426 also means that tagging creates a new commit. The file
5420 ".hg/localtags" is used for local tags (not shared among
5427 ".hg/localtags" is used for local tags (not shared among
5421 repositories).
5428 repositories).
5422
5429
5423 Tag commits are usually made at the head of a branch. If the parent
5430 Tag commits are usually made at the head of a branch. If the parent
5424 of the working directory is not a branch head, :hg:`tag` aborts; use
5431 of the working directory is not a branch head, :hg:`tag` aborts; use
5425 -f/--force to force the tag commit to be based on a non-head
5432 -f/--force to force the tag commit to be based on a non-head
5426 changeset.
5433 changeset.
5427
5434
5428 See :hg:`help dates` for a list of formats valid for -d/--date.
5435 See :hg:`help dates` for a list of formats valid for -d/--date.
5429
5436
5430 Since tag names have priority over branch names during revision
5437 Since tag names have priority over branch names during revision
5431 lookup, using an existing branch name as a tag name is discouraged.
5438 lookup, using an existing branch name as a tag name is discouraged.
5432
5439
5433 Returns 0 on success.
5440 Returns 0 on success.
5434 """
5441 """
5435 wlock = lock = None
5442 wlock = lock = None
5436 try:
5443 try:
5437 wlock = repo.wlock()
5444 wlock = repo.wlock()
5438 lock = repo.lock()
5445 lock = repo.lock()
5439 rev_ = "."
5446 rev_ = "."
5440 names = [t.strip() for t in (name1,) + names]
5447 names = [t.strip() for t in (name1,) + names]
5441 if len(names) != len(set(names)):
5448 if len(names) != len(set(names)):
5442 raise util.Abort(_('tag names must be unique'))
5449 raise util.Abort(_('tag names must be unique'))
5443 for n in names:
5450 for n in names:
5444 scmutil.checknewlabel(repo, n, 'tag')
5451 scmutil.checknewlabel(repo, n, 'tag')
5445 if not n:
5452 if not n:
5446 raise util.Abort(_('tag names cannot consist entirely of '
5453 raise util.Abort(_('tag names cannot consist entirely of '
5447 'whitespace'))
5454 'whitespace'))
5448 if opts.get('rev') and opts.get('remove'):
5455 if opts.get('rev') and opts.get('remove'):
5449 raise util.Abort(_("--rev and --remove are incompatible"))
5456 raise util.Abort(_("--rev and --remove are incompatible"))
5450 if opts.get('rev'):
5457 if opts.get('rev'):
5451 rev_ = opts['rev']
5458 rev_ = opts['rev']
5452 message = opts.get('message')
5459 message = opts.get('message')
5453 if opts.get('remove'):
5460 if opts.get('remove'):
5454 expectedtype = opts.get('local') and 'local' or 'global'
5461 expectedtype = opts.get('local') and 'local' or 'global'
5455 for n in names:
5462 for n in names:
5456 if not repo.tagtype(n):
5463 if not repo.tagtype(n):
5457 raise util.Abort(_("tag '%s' does not exist") % n)
5464 raise util.Abort(_("tag '%s' does not exist") % n)
5458 if repo.tagtype(n) != expectedtype:
5465 if repo.tagtype(n) != expectedtype:
5459 if expectedtype == 'global':
5466 if expectedtype == 'global':
5460 raise util.Abort(_("tag '%s' is not a global tag") % n)
5467 raise util.Abort(_("tag '%s' is not a global tag") % n)
5461 else:
5468 else:
5462 raise util.Abort(_("tag '%s' is not a local tag") % n)
5469 raise util.Abort(_("tag '%s' is not a local tag") % n)
5463 rev_ = nullid
5470 rev_ = nullid
5464 if not message:
5471 if not message:
5465 # we don't translate commit messages
5472 # we don't translate commit messages
5466 message = 'Removed tag %s' % ', '.join(names)
5473 message = 'Removed tag %s' % ', '.join(names)
5467 elif not opts.get('force'):
5474 elif not opts.get('force'):
5468 for n in names:
5475 for n in names:
5469 if n in repo.tags():
5476 if n in repo.tags():
5470 raise util.Abort(_("tag '%s' already exists "
5477 raise util.Abort(_("tag '%s' already exists "
5471 "(use -f to force)") % n)
5478 "(use -f to force)") % n)
5472 if not opts.get('local'):
5479 if not opts.get('local'):
5473 p1, p2 = repo.dirstate.parents()
5480 p1, p2 = repo.dirstate.parents()
5474 if p2 != nullid:
5481 if p2 != nullid:
5475 raise util.Abort(_('uncommitted merge'))
5482 raise util.Abort(_('uncommitted merge'))
5476 bheads = repo.branchheads()
5483 bheads = repo.branchheads()
5477 if not opts.get('force') and bheads and p1 not in bheads:
5484 if not opts.get('force') and bheads and p1 not in bheads:
5478 raise util.Abort(_('not at a branch head (use -f to force)'))
5485 raise util.Abort(_('not at a branch head (use -f to force)'))
5479 r = scmutil.revsingle(repo, rev_).node()
5486 r = scmutil.revsingle(repo, rev_).node()
5480
5487
5481 if not message:
5488 if not message:
5482 # we don't translate commit messages
5489 # we don't translate commit messages
5483 message = ('Added tag %s for changeset %s' %
5490 message = ('Added tag %s for changeset %s' %
5484 (', '.join(names), short(r)))
5491 (', '.join(names), short(r)))
5485
5492
5486 date = opts.get('date')
5493 date = opts.get('date')
5487 if date:
5494 if date:
5488 date = util.parsedate(date)
5495 date = util.parsedate(date)
5489
5496
5490 if opts.get('edit'):
5497 if opts.get('edit'):
5491 message = ui.edit(message, ui.username())
5498 message = ui.edit(message, ui.username())
5492
5499
5493 # don't allow tagging the null rev
5500 # don't allow tagging the null rev
5494 if (not opts.get('remove') and
5501 if (not opts.get('remove') and
5495 scmutil.revsingle(repo, rev_).rev() == nullrev):
5502 scmutil.revsingle(repo, rev_).rev() == nullrev):
5496 raise util.Abort(_("null revision specified"))
5503 raise util.Abort(_("null revision specified"))
5497
5504
5498 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5505 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5499 finally:
5506 finally:
5500 release(lock, wlock)
5507 release(lock, wlock)
5501
5508
5502 @command('tags', [], '')
5509 @command('tags', [], '')
5503 def tags(ui, repo, **opts):
5510 def tags(ui, repo, **opts):
5504 """list repository tags
5511 """list repository tags
5505
5512
5506 This lists both regular and local tags. When the -v/--verbose
5513 This lists both regular and local tags. When the -v/--verbose
5507 switch is used, a third column "local" is printed for local tags.
5514 switch is used, a third column "local" is printed for local tags.
5508
5515
5509 Returns 0 on success.
5516 Returns 0 on success.
5510 """
5517 """
5511
5518
5512 fm = ui.formatter('tags', opts)
5519 fm = ui.formatter('tags', opts)
5513 hexfunc = ui.debugflag and hex or short
5520 hexfunc = ui.debugflag and hex or short
5514 tagtype = ""
5521 tagtype = ""
5515
5522
5516 for t, n in reversed(repo.tagslist()):
5523 for t, n in reversed(repo.tagslist()):
5517 hn = hexfunc(n)
5524 hn = hexfunc(n)
5518 label = 'tags.normal'
5525 label = 'tags.normal'
5519 tagtype = ''
5526 tagtype = ''
5520 if repo.tagtype(t) == 'local':
5527 if repo.tagtype(t) == 'local':
5521 label = 'tags.local'
5528 label = 'tags.local'
5522 tagtype = 'local'
5529 tagtype = 'local'
5523
5530
5524 fm.startitem()
5531 fm.startitem()
5525 fm.write('tag', '%s', t, label=label)
5532 fm.write('tag', '%s', t, label=label)
5526 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5533 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5527 fm.condwrite(not ui.quiet, 'rev id', fmt,
5534 fm.condwrite(not ui.quiet, 'rev id', fmt,
5528 repo.changelog.rev(n), hn, label=label)
5535 repo.changelog.rev(n), hn, label=label)
5529 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5536 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5530 tagtype, label=label)
5537 tagtype, label=label)
5531 fm.plain('\n')
5538 fm.plain('\n')
5532 fm.end()
5539 fm.end()
5533
5540
5534 @command('tip',
5541 @command('tip',
5535 [('p', 'patch', None, _('show patch')),
5542 [('p', 'patch', None, _('show patch')),
5536 ('g', 'git', None, _('use git extended diff format')),
5543 ('g', 'git', None, _('use git extended diff format')),
5537 ] + templateopts,
5544 ] + templateopts,
5538 _('[-p] [-g]'))
5545 _('[-p] [-g]'))
5539 def tip(ui, repo, **opts):
5546 def tip(ui, repo, **opts):
5540 """show the tip revision
5547 """show the tip revision
5541
5548
5542 The tip revision (usually just called the tip) is the changeset
5549 The tip revision (usually just called the tip) is the changeset
5543 most recently added to the repository (and therefore the most
5550 most recently added to the repository (and therefore the most
5544 recently changed head).
5551 recently changed head).
5545
5552
5546 If you have just made a commit, that commit will be the tip. If
5553 If you have just made a commit, that commit will be the tip. If
5547 you have just pulled changes from another repository, the tip of
5554 you have just pulled changes from another repository, the tip of
5548 that repository becomes the current tip. The "tip" tag is special
5555 that repository becomes the current tip. The "tip" tag is special
5549 and cannot be renamed or assigned to a different changeset.
5556 and cannot be renamed or assigned to a different changeset.
5550
5557
5551 Returns 0 on success.
5558 Returns 0 on success.
5552 """
5559 """
5553 displayer = cmdutil.show_changeset(ui, repo, opts)
5560 displayer = cmdutil.show_changeset(ui, repo, opts)
5554 displayer.show(repo['tip'])
5561 displayer.show(repo['tip'])
5555 displayer.close()
5562 displayer.close()
5556
5563
5557 @command('unbundle',
5564 @command('unbundle',
5558 [('u', 'update', None,
5565 [('u', 'update', None,
5559 _('update to new branch head if changesets were unbundled'))],
5566 _('update to new branch head if changesets were unbundled'))],
5560 _('[-u] FILE...'))
5567 _('[-u] FILE...'))
5561 def unbundle(ui, repo, fname1, *fnames, **opts):
5568 def unbundle(ui, repo, fname1, *fnames, **opts):
5562 """apply one or more changegroup files
5569 """apply one or more changegroup files
5563
5570
5564 Apply one or more compressed changegroup files generated by the
5571 Apply one or more compressed changegroup files generated by the
5565 bundle command.
5572 bundle command.
5566
5573
5567 Returns 0 on success, 1 if an update has unresolved files.
5574 Returns 0 on success, 1 if an update has unresolved files.
5568 """
5575 """
5569 fnames = (fname1,) + fnames
5576 fnames = (fname1,) + fnames
5570
5577
5571 lock = repo.lock()
5578 lock = repo.lock()
5572 wc = repo['.']
5579 wc = repo['.']
5573 try:
5580 try:
5574 for fname in fnames:
5581 for fname in fnames:
5575 f = hg.openpath(ui, fname)
5582 f = hg.openpath(ui, fname)
5576 gen = changegroup.readbundle(f, fname)
5583 gen = changegroup.readbundle(f, fname)
5577 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5584 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5578 finally:
5585 finally:
5579 lock.release()
5586 lock.release()
5580 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5587 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5581 return postincoming(ui, repo, modheads, opts.get('update'), None)
5588 return postincoming(ui, repo, modheads, opts.get('update'), None)
5582
5589
5583 @command('^update|up|checkout|co',
5590 @command('^update|up|checkout|co',
5584 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5591 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5585 ('c', 'check', None,
5592 ('c', 'check', None,
5586 _('update across branches if no uncommitted changes')),
5593 _('update across branches if no uncommitted changes')),
5587 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5594 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5588 ('r', 'rev', '', _('revision'), _('REV'))],
5595 ('r', 'rev', '', _('revision'), _('REV'))],
5589 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5596 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5590 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5597 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5591 """update working directory (or switch revisions)
5598 """update working directory (or switch revisions)
5592
5599
5593 Update the repository's working directory to the specified
5600 Update the repository's working directory to the specified
5594 changeset. If no changeset is specified, update to the tip of the
5601 changeset. If no changeset is specified, update to the tip of the
5595 current named branch and move the current bookmark (see :hg:`help
5602 current named branch and move the current bookmark (see :hg:`help
5596 bookmarks`).
5603 bookmarks`).
5597
5604
5598 Update sets the working directory's parent revision to the specified
5605 Update sets the working directory's parent revision to the specified
5599 changeset (see :hg:`help parents`).
5606 changeset (see :hg:`help parents`).
5600
5607
5601 If the changeset is not a descendant or ancestor of the working
5608 If the changeset is not a descendant or ancestor of the working
5602 directory's parent, the update is aborted. With the -c/--check
5609 directory's parent, the update is aborted. With the -c/--check
5603 option, the working directory is checked for uncommitted changes; if
5610 option, the working directory is checked for uncommitted changes; if
5604 none are found, the working directory is updated to the specified
5611 none are found, the working directory is updated to the specified
5605 changeset.
5612 changeset.
5606
5613
5607 .. container:: verbose
5614 .. container:: verbose
5608
5615
5609 The following rules apply when the working directory contains
5616 The following rules apply when the working directory contains
5610 uncommitted changes:
5617 uncommitted changes:
5611
5618
5612 1. If neither -c/--check nor -C/--clean is specified, and if
5619 1. If neither -c/--check nor -C/--clean is specified, and if
5613 the requested changeset is an ancestor or descendant of
5620 the requested changeset is an ancestor or descendant of
5614 the working directory's parent, the uncommitted changes
5621 the working directory's parent, the uncommitted changes
5615 are merged into the requested changeset and the merged
5622 are merged into the requested changeset and the merged
5616 result is left uncommitted. If the requested changeset is
5623 result is left uncommitted. If the requested changeset is
5617 not an ancestor or descendant (that is, it is on another
5624 not an ancestor or descendant (that is, it is on another
5618 branch), the update is aborted and the uncommitted changes
5625 branch), the update is aborted and the uncommitted changes
5619 are preserved.
5626 are preserved.
5620
5627
5621 2. With the -c/--check option, the update is aborted and the
5628 2. With the -c/--check option, the update is aborted and the
5622 uncommitted changes are preserved.
5629 uncommitted changes are preserved.
5623
5630
5624 3. With the -C/--clean option, uncommitted changes are discarded and
5631 3. With the -C/--clean option, uncommitted changes are discarded and
5625 the working directory is updated to the requested changeset.
5632 the working directory is updated to the requested changeset.
5626
5633
5627 To cancel an uncommitted merge (and lose your changes), use
5634 To cancel an uncommitted merge (and lose your changes), use
5628 :hg:`update --clean .`.
5635 :hg:`update --clean .`.
5629
5636
5630 Use null as the changeset to remove the working directory (like
5637 Use null as the changeset to remove the working directory (like
5631 :hg:`clone -U`).
5638 :hg:`clone -U`).
5632
5639
5633 If you want to revert just one file to an older revision, use
5640 If you want to revert just one file to an older revision, use
5634 :hg:`revert [-r REV] NAME`.
5641 :hg:`revert [-r REV] NAME`.
5635
5642
5636 See :hg:`help dates` for a list of formats valid for -d/--date.
5643 See :hg:`help dates` for a list of formats valid for -d/--date.
5637
5644
5638 Returns 0 on success, 1 if there are unresolved files.
5645 Returns 0 on success, 1 if there are unresolved files.
5639 """
5646 """
5640 if rev and node:
5647 if rev and node:
5641 raise util.Abort(_("please specify just one revision"))
5648 raise util.Abort(_("please specify just one revision"))
5642
5649
5643 if rev is None or rev == '':
5650 if rev is None or rev == '':
5644 rev = node
5651 rev = node
5645
5652
5646 # with no argument, we also move the current bookmark, if any
5653 # with no argument, we also move the current bookmark, if any
5647 movemarkfrom = None
5654 movemarkfrom = None
5648 if rev is None:
5655 if rev is None:
5649 curmark = repo._bookmarkcurrent
5656 curmark = repo._bookmarkcurrent
5650 if bookmarks.iscurrent(repo):
5657 if bookmarks.iscurrent(repo):
5651 movemarkfrom = repo['.'].node()
5658 movemarkfrom = repo['.'].node()
5652 elif curmark:
5659 elif curmark:
5653 ui.status(_("updating to active bookmark %s\n") % curmark)
5660 ui.status(_("updating to active bookmark %s\n") % curmark)
5654 rev = curmark
5661 rev = curmark
5655
5662
5656 # if we defined a bookmark, we have to remember the original bookmark name
5663 # if we defined a bookmark, we have to remember the original bookmark name
5657 brev = rev
5664 brev = rev
5658 rev = scmutil.revsingle(repo, rev, rev).rev()
5665 rev = scmutil.revsingle(repo, rev, rev).rev()
5659
5666
5660 if check and clean:
5667 if check and clean:
5661 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5668 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5662
5669
5663 if date:
5670 if date:
5664 if rev is not None:
5671 if rev is not None:
5665 raise util.Abort(_("you can't specify a revision and a date"))
5672 raise util.Abort(_("you can't specify a revision and a date"))
5666 rev = cmdutil.finddate(ui, repo, date)
5673 rev = cmdutil.finddate(ui, repo, date)
5667
5674
5668 if check:
5675 if check:
5669 c = repo[None]
5676 c = repo[None]
5670 if c.dirty(merge=False, branch=False, missing=True):
5677 if c.dirty(merge=False, branch=False, missing=True):
5671 raise util.Abort(_("uncommitted local changes"))
5678 raise util.Abort(_("uncommitted local changes"))
5672 if rev is None:
5679 if rev is None:
5673 rev = repo[repo[None].branch()].rev()
5680 rev = repo[repo[None].branch()].rev()
5674 mergemod._checkunknown(repo, repo[None], repo[rev])
5681 mergemod._checkunknown(repo, repo[None], repo[rev])
5675
5682
5676 if clean:
5683 if clean:
5677 ret = hg.clean(repo, rev)
5684 ret = hg.clean(repo, rev)
5678 else:
5685 else:
5679 ret = hg.update(repo, rev)
5686 ret = hg.update(repo, rev)
5680
5687
5681 if not ret and movemarkfrom:
5688 if not ret and movemarkfrom:
5682 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5689 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5683 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5690 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5684 elif brev in repo._bookmarks:
5691 elif brev in repo._bookmarks:
5685 bookmarks.setcurrent(repo, brev)
5692 bookmarks.setcurrent(repo, brev)
5686 elif brev:
5693 elif brev:
5687 bookmarks.unsetcurrent(repo)
5694 bookmarks.unsetcurrent(repo)
5688
5695
5689 return ret
5696 return ret
5690
5697
5691 @command('verify', [])
5698 @command('verify', [])
5692 def verify(ui, repo):
5699 def verify(ui, repo):
5693 """verify the integrity of the repository
5700 """verify the integrity of the repository
5694
5701
5695 Verify the integrity of the current repository.
5702 Verify the integrity of the current repository.
5696
5703
5697 This will perform an extensive check of the repository's
5704 This will perform an extensive check of the repository's
5698 integrity, validating the hashes and checksums of each entry in
5705 integrity, validating the hashes and checksums of each entry in
5699 the changelog, manifest, and tracked files, as well as the
5706 the changelog, manifest, and tracked files, as well as the
5700 integrity of their crosslinks and indices.
5707 integrity of their crosslinks and indices.
5701
5708
5702 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5709 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5703 for more information about recovery from corruption of the
5710 for more information about recovery from corruption of the
5704 repository.
5711 repository.
5705
5712
5706 Returns 0 on success, 1 if errors are encountered.
5713 Returns 0 on success, 1 if errors are encountered.
5707 """
5714 """
5708 return hg.verify(repo)
5715 return hg.verify(repo)
5709
5716
5710 @command('version', [])
5717 @command('version', [])
5711 def version_(ui):
5718 def version_(ui):
5712 """output version and copyright information"""
5719 """output version and copyright information"""
5713 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5720 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5714 % util.version())
5721 % util.version())
5715 ui.status(_(
5722 ui.status(_(
5716 "(see http://mercurial.selenic.com for more information)\n"
5723 "(see http://mercurial.selenic.com for more information)\n"
5717 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5724 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5718 "This is free software; see the source for copying conditions. "
5725 "This is free software; see the source for copying conditions. "
5719 "There is NO\nwarranty; "
5726 "There is NO\nwarranty; "
5720 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5727 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5721 ))
5728 ))
5722
5729
5723 norepo = ("clone init version help debugcommands debugcomplete"
5730 norepo = ("clone init version help debugcommands debugcomplete"
5724 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5731 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5725 " debugknown debuggetbundle debugbundle")
5732 " debugknown debuggetbundle debugbundle")
5726 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5733 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5727 " debugdata debugindex debugindexdot debugrevlog")
5734 " debugdata debugindex debugindexdot debugrevlog")
5728 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5735 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5729 " remove resolve status debugwalk")
5736 " remove resolve status debugwalk")
@@ -1,573 +1,579 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0, command should work even with ui.strict on
43 second bookmark for rev 0, command should work even with ui.strict on
44
44
45 $ hg --config ui.strict=1 bookmark X2
45 $ hg --config ui.strict=1 bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg log -r 'bookmark("re:X")'
87 $ hg log -r 'bookmark("re:X")'
88 changeset: 0:f7b1eb17ad24
88 changeset: 0:f7b1eb17ad24
89 bookmark: X
89 bookmark: X
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: 0
92 summary: 0
93
93
94 changeset: 1:925d80f479bb
94 changeset: 1:925d80f479bb
95 bookmark: X2
95 bookmark: X2
96 tag: tip
96 tag: tip
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: 1
99 summary: 1
100
100
101 $ hg log -r 'bookmark(unknown)'
101 $ hg log -r 'bookmark(unknown)'
102 abort: bookmark 'unknown' does not exist
102 abort: bookmark 'unknown' does not exist
103 [255]
103 [255]
104
104
105 $ hg help revsets | grep 'bookmark('
105 $ hg help revsets | grep 'bookmark('
106 "bookmark([name])"
106 "bookmark([name])"
107
107
108 bookmarks X and X2 moved to rev 1, Y at rev -1
108 bookmarks X and X2 moved to rev 1, Y at rev -1
109
109
110 $ hg bookmarks
110 $ hg bookmarks
111 X 0:f7b1eb17ad24
111 X 0:f7b1eb17ad24
112 * X2 1:925d80f479bb
112 * X2 1:925d80f479bb
113 Y -1:000000000000
113 Y -1:000000000000
114
114
115 bookmark rev 0 again
115 bookmark rev 0 again
116
116
117 $ hg bookmark -r 0 Z
117 $ hg bookmark -r 0 Z
118
118
119 $ hg update X
119 $ hg update X
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 $ echo c > c
121 $ echo c > c
122 $ hg add c
122 $ hg add c
123 $ hg commit -m 2
123 $ hg commit -m 2
124 created new head
124 created new head
125
125
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
127
127
128 $ hg bookmarks
128 $ hg bookmarks
129 * X 2:db815d6d32e6
129 * X 2:db815d6d32e6
130 X2 1:925d80f479bb
130 X2 1:925d80f479bb
131 Y -1:000000000000
131 Y -1:000000000000
132 Z 0:f7b1eb17ad24
132 Z 0:f7b1eb17ad24
133
133
134 rename nonexistent bookmark
134 rename nonexistent bookmark
135
135
136 $ hg bookmark -m A B
136 $ hg bookmark -m A B
137 abort: bookmark 'A' does not exist
137 abort: bookmark 'A' does not exist
138 [255]
138 [255]
139
139
140 rename to existent bookmark
140 rename to existent bookmark
141
141
142 $ hg bookmark -m X Y
142 $ hg bookmark -m X Y
143 abort: bookmark 'Y' already exists (use -f to force)
143 abort: bookmark 'Y' already exists (use -f to force)
144 [255]
144 [255]
145
145
146 force rename to existent bookmark
146 force rename to existent bookmark
147
147
148 $ hg bookmark -f -m X Y
148 $ hg bookmark -f -m X Y
149
149
150 list bookmarks
150 list bookmarks
151
151
152 $ hg bookmark
152 $ hg bookmark
153 X2 1:925d80f479bb
153 X2 1:925d80f479bb
154 * Y 2:db815d6d32e6
154 * Y 2:db815d6d32e6
155 Z 0:f7b1eb17ad24
155 Z 0:f7b1eb17ad24
156
156
157 bookmarks from a revset
157 bookmarks from a revset
158 $ hg bookmark -r '.^1' REVSET
158 $ hg bookmark -r '.^1' REVSET
159 $ hg bookmark -r ':tip' TIP
159 $ hg bookmark -r ':tip' TIP
160 $ hg bookmarks
160 $ hg bookmarks
161 REVSET 0:f7b1eb17ad24
161 REVSET 0:f7b1eb17ad24
162 * TIP 2:db815d6d32e6
162 * TIP 2:db815d6d32e6
163 X2 1:925d80f479bb
163 X2 1:925d80f479bb
164 Y 2:db815d6d32e6
164 Y 2:db815d6d32e6
165 Z 0:f7b1eb17ad24
165 Z 0:f7b1eb17ad24
166
166
167 $ hg bookmark -d REVSET
167 $ hg bookmark -d REVSET
168 $ hg bookmark -d TIP
168 $ hg bookmark -d TIP
169
169
170 rename without new name
170 rename without new name
171
171
172 $ hg bookmark -m Y
172 $ hg bookmark -m Y
173 abort: new bookmark name required
173 abort: new bookmark name required
174 [255]
174 [255]
175
175
176 delete without name
176 delete without name
177
177
178 $ hg bookmark -d
178 $ hg bookmark -d
179 abort: bookmark name required
179 abort: bookmark name required
180 [255]
180 [255]
181
181
182 delete nonexistent bookmark
182 delete nonexistent bookmark
183
183
184 $ hg bookmark -d A
184 $ hg bookmark -d A
185 abort: bookmark 'A' does not exist
185 abort: bookmark 'A' does not exist
186 [255]
186 [255]
187
187
188 bookmark name with spaces should be stripped
188 bookmark name with spaces should be stripped
189
189
190 $ hg bookmark ' x y '
190 $ hg bookmark ' x y '
191
191
192 list bookmarks
192 list bookmarks
193
193
194 $ hg bookmarks
194 $ hg bookmarks
195 X2 1:925d80f479bb
195 X2 1:925d80f479bb
196 Y 2:db815d6d32e6
196 Y 2:db815d6d32e6
197 Z 0:f7b1eb17ad24
197 Z 0:f7b1eb17ad24
198 * x y 2:db815d6d32e6
198 * x y 2:db815d6d32e6
199
199
200 look up stripped bookmark name
200 look up stripped bookmark name
201
201
202 $ hg log -r '"x y"'
202 $ hg log -r '"x y"'
203 changeset: 2:db815d6d32e6
203 changeset: 2:db815d6d32e6
204 bookmark: Y
204 bookmark: Y
205 bookmark: x y
205 bookmark: x y
206 tag: tip
206 tag: tip
207 parent: 0:f7b1eb17ad24
207 parent: 0:f7b1eb17ad24
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: 2
210 summary: 2
211
211
212
212
213 reject bookmark name with newline
213 reject bookmark name with newline
214
214
215 $ hg bookmark '
215 $ hg bookmark '
216 > '
216 > '
217 abort: bookmark names cannot consist entirely of whitespace
217 abort: bookmark names cannot consist entirely of whitespace
218 [255]
218 [255]
219
219
220 $ hg bookmark -m Z '
220 $ hg bookmark -m Z '
221 > '
221 > '
222 abort: bookmark names cannot consist entirely of whitespace
222 abort: bookmark names cannot consist entirely of whitespace
223 [255]
223 [255]
224
224
225 bookmark with reserved name
225 bookmark with reserved name
226
226
227 $ hg bookmark tip
227 $ hg bookmark tip
228 abort: the name 'tip' is reserved
228 abort: the name 'tip' is reserved
229 [255]
229 [255]
230
230
231 $ hg bookmark .
231 $ hg bookmark .
232 abort: the name '.' is reserved
232 abort: the name '.' is reserved
233 [255]
233 [255]
234
234
235 $ hg bookmark null
235 $ hg bookmark null
236 abort: the name 'null' is reserved
236 abort: the name 'null' is reserved
237 [255]
237 [255]
238
238
239
239
240 bookmark with existing name
240 bookmark with existing name
241
241
242 $ hg bookmark Z
242 $ hg bookmark X2
243 abort: bookmark 'Z' already exists (use -f to force)
243 abort: bookmark 'X2' already exists (use -f to force)
244 [255]
244 [255]
245
245
246 $ hg bookmark -m Y Z
246 $ hg bookmark -m Y Z
247 abort: bookmark 'Z' already exists (use -f to force)
247 abort: bookmark 'Z' already exists (use -f to force)
248 [255]
248 [255]
249
249
250 bookmark with name of branch
250 bookmark with name of branch
251
251
252 $ hg bookmark default
252 $ hg bookmark default
253 abort: a bookmark cannot have the name of an existing branch
253 abort: a bookmark cannot have the name of an existing branch
254 [255]
254 [255]
255
255
256 $ hg bookmark -m Y default
256 $ hg bookmark -m Y default
257 abort: a bookmark cannot have the name of an existing branch
257 abort: a bookmark cannot have the name of an existing branch
258 [255]
258 [255]
259
259
260 bookmark with integer name
260 bookmark with integer name
261
261
262 $ hg bookmark 10
262 $ hg bookmark 10
263 abort: a bookmark cannot have an integer as its name
263 abort: a bookmark cannot have an integer as its name
264 [255]
264 [255]
265
265
266 incompatible options
266 incompatible options
267
267
268 $ hg bookmark -m Y -d Z
268 $ hg bookmark -m Y -d Z
269 abort: --delete and --rename are incompatible
269 abort: --delete and --rename are incompatible
270 [255]
270 [255]
271
271
272 $ hg bookmark -r 1 -d Z
272 $ hg bookmark -r 1 -d Z
273 abort: --rev is incompatible with --delete
273 abort: --rev is incompatible with --delete
274 [255]
274 [255]
275
275
276 $ hg bookmark -r 1 -m Z Y
276 $ hg bookmark -r 1 -m Z Y
277 abort: --rev is incompatible with --rename
277 abort: --rev is incompatible with --rename
278 [255]
278 [255]
279
279
280 force bookmark with existing name
280 force bookmark with existing name
281
281
282 $ hg bookmark -f Z
282 $ hg bookmark -f X2
283 $ hg bookmark -fr1 X2
284
285 forward bookmark to descendant without --force
286
287 $ hg bookmark Z
288 moving bookmark 'Z' forward from 663762316562
283
289
284 list bookmarks
290 list bookmarks
285
291
286 $ hg bookmark
292 $ hg bookmark
287 X2 1:925d80f479bb
293 X2 1:925d80f479bb
288 Y 2:db815d6d32e6
294 Y 2:db815d6d32e6
289 * Z 2:db815d6d32e6
295 * Z 2:db815d6d32e6
290 x y 2:db815d6d32e6
296 x y 2:db815d6d32e6
291
297
292 revision but no bookmark name
298 revision but no bookmark name
293
299
294 $ hg bookmark -r .
300 $ hg bookmark -r .
295 abort: bookmark name required
301 abort: bookmark name required
296 [255]
302 [255]
297
303
298 bookmark name with whitespace only
304 bookmark name with whitespace only
299
305
300 $ hg bookmark ' '
306 $ hg bookmark ' '
301 abort: bookmark names cannot consist entirely of whitespace
307 abort: bookmark names cannot consist entirely of whitespace
302 [255]
308 [255]
303
309
304 $ hg bookmark -m Y ' '
310 $ hg bookmark -m Y ' '
305 abort: bookmark names cannot consist entirely of whitespace
311 abort: bookmark names cannot consist entirely of whitespace
306 [255]
312 [255]
307
313
308 invalid bookmark
314 invalid bookmark
309
315
310 $ hg bookmark 'foo:bar'
316 $ hg bookmark 'foo:bar'
311 abort: ':' cannot be used in a name
317 abort: ':' cannot be used in a name
312 [255]
318 [255]
313
319
314 $ hg bookmark 'foo
320 $ hg bookmark 'foo
315 > bar'
321 > bar'
316 abort: '\n' cannot be used in a name
322 abort: '\n' cannot be used in a name
317 [255]
323 [255]
318
324
319 the bookmark extension should be ignored now that it is part of core
325 the bookmark extension should be ignored now that it is part of core
320
326
321 $ echo "[extensions]" >> $HGRCPATH
327 $ echo "[extensions]" >> $HGRCPATH
322 $ echo "bookmarks=" >> $HGRCPATH
328 $ echo "bookmarks=" >> $HGRCPATH
323 $ hg bookmarks
329 $ hg bookmarks
324 X2 1:925d80f479bb
330 X2 1:925d80f479bb
325 Y 2:db815d6d32e6
331 Y 2:db815d6d32e6
326 * Z 2:db815d6d32e6
332 * Z 2:db815d6d32e6
327 x y 2:db815d6d32e6
333 x y 2:db815d6d32e6
328
334
329 test summary
335 test summary
330
336
331 $ hg summary
337 $ hg summary
332 parent: 2:db815d6d32e6 tip
338 parent: 2:db815d6d32e6 tip
333 2
339 2
334 branch: default
340 branch: default
335 bookmarks: *Z Y x y
341 bookmarks: *Z Y x y
336 commit: (clean)
342 commit: (clean)
337 update: 1 new changesets, 2 branch heads (merge)
343 update: 1 new changesets, 2 branch heads (merge)
338
344
339 test id
345 test id
340
346
341 $ hg id
347 $ hg id
342 db815d6d32e6 tip Y/Z/x y
348 db815d6d32e6 tip Y/Z/x y
343
349
344 test rollback
350 test rollback
345
351
346 $ echo foo > f1
352 $ echo foo > f1
347 $ hg ci -Amr
353 $ hg ci -Amr
348 adding f1
354 adding f1
349 $ hg bookmark -f Y -r 1
355 $ hg bookmark -f Y -r 1
350 $ hg bookmark -f Z -r 1
356 $ hg bookmark -f Z -r 1
351 $ hg rollback
357 $ hg rollback
352 repository tip rolled back to revision 2 (undo commit)
358 repository tip rolled back to revision 2 (undo commit)
353 working directory now based on revision 2
359 working directory now based on revision 2
354 $ hg bookmarks
360 $ hg bookmarks
355 X2 1:925d80f479bb
361 X2 1:925d80f479bb
356 Y 2:db815d6d32e6
362 Y 2:db815d6d32e6
357 * Z 2:db815d6d32e6
363 * Z 2:db815d6d32e6
358 x y 2:db815d6d32e6
364 x y 2:db815d6d32e6
359
365
360 test clone
366 test clone
361
367
362 $ hg bookmark -r 2 -i @
368 $ hg bookmark -r 2 -i @
363 $ hg bookmark -r 2 -i a@
369 $ hg bookmark -r 2 -i a@
364 $ hg bookmarks
370 $ hg bookmarks
365 @ 2:db815d6d32e6
371 @ 2:db815d6d32e6
366 X2 1:925d80f479bb
372 X2 1:925d80f479bb
367 Y 2:db815d6d32e6
373 Y 2:db815d6d32e6
368 * Z 2:db815d6d32e6
374 * Z 2:db815d6d32e6
369 a@ 2:db815d6d32e6
375 a@ 2:db815d6d32e6
370 x y 2:db815d6d32e6
376 x y 2:db815d6d32e6
371 $ hg clone . cloned-bookmarks
377 $ hg clone . cloned-bookmarks
372 updating to bookmark @
378 updating to bookmark @
373 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 $ hg -R cloned-bookmarks bookmarks
380 $ hg -R cloned-bookmarks bookmarks
375 * @ 2:db815d6d32e6
381 * @ 2:db815d6d32e6
376 X2 1:925d80f479bb
382 X2 1:925d80f479bb
377 Y 2:db815d6d32e6
383 Y 2:db815d6d32e6
378 Z 2:db815d6d32e6
384 Z 2:db815d6d32e6
379 a@ 2:db815d6d32e6
385 a@ 2:db815d6d32e6
380 x y 2:db815d6d32e6
386 x y 2:db815d6d32e6
381
387
382 test clone with pull protocol
388 test clone with pull protocol
383
389
384 $ hg clone --pull . cloned-bookmarks-pull
390 $ hg clone --pull . cloned-bookmarks-pull
385 requesting all changes
391 requesting all changes
386 adding changesets
392 adding changesets
387 adding manifests
393 adding manifests
388 adding file changes
394 adding file changes
389 added 3 changesets with 3 changes to 3 files (+1 heads)
395 added 3 changesets with 3 changes to 3 files (+1 heads)
390 updating to bookmark @
396 updating to bookmark @
391 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
397 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 $ hg -R cloned-bookmarks-pull bookmarks
398 $ hg -R cloned-bookmarks-pull bookmarks
393 * @ 2:db815d6d32e6
399 * @ 2:db815d6d32e6
394 X2 1:925d80f479bb
400 X2 1:925d80f479bb
395 Y 2:db815d6d32e6
401 Y 2:db815d6d32e6
396 Z 2:db815d6d32e6
402 Z 2:db815d6d32e6
397 a@ 2:db815d6d32e6
403 a@ 2:db815d6d32e6
398 x y 2:db815d6d32e6
404 x y 2:db815d6d32e6
399
405
400 $ hg bookmark -d @
406 $ hg bookmark -d @
401 $ hg bookmark -d a@
407 $ hg bookmark -d a@
402
408
403 test clone with a bookmark named "default" (issue3677)
409 test clone with a bookmark named "default" (issue3677)
404
410
405 $ hg bookmark -r 1 -f -i default
411 $ hg bookmark -r 1 -f -i default
406 $ hg clone . cloned-bookmark-default
412 $ hg clone . cloned-bookmark-default
407 updating to branch default
413 updating to branch default
408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 $ hg -R cloned-bookmark-default bookmarks
415 $ hg -R cloned-bookmark-default bookmarks
410 X2 1:925d80f479bb
416 X2 1:925d80f479bb
411 Y 2:db815d6d32e6
417 Y 2:db815d6d32e6
412 Z 2:db815d6d32e6
418 Z 2:db815d6d32e6
413 default 1:925d80f479bb
419 default 1:925d80f479bb
414 x y 2:db815d6d32e6
420 x y 2:db815d6d32e6
415 $ hg -R cloned-bookmark-default parents -q
421 $ hg -R cloned-bookmark-default parents -q
416 2:db815d6d32e6
422 2:db815d6d32e6
417 $ hg bookmark -d default
423 $ hg bookmark -d default
418
424
419 test clone with a specific revision
425 test clone with a specific revision
420
426
421 $ hg clone -r 925d80 . cloned-bookmarks-rev
427 $ hg clone -r 925d80 . cloned-bookmarks-rev
422 adding changesets
428 adding changesets
423 adding manifests
429 adding manifests
424 adding file changes
430 adding file changes
425 added 2 changesets with 2 changes to 2 files
431 added 2 changesets with 2 changes to 2 files
426 updating to branch default
432 updating to branch default
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 $ hg -R cloned-bookmarks-rev bookmarks
434 $ hg -R cloned-bookmarks-rev bookmarks
429 X2 1:925d80f479bb
435 X2 1:925d80f479bb
430
436
431 test clone with update to a bookmark
437 test clone with update to a bookmark
432
438
433 $ hg clone -u Z . cloned-bookmarks-update
439 $ hg clone -u Z . cloned-bookmarks-update
434 updating to branch default
440 updating to branch default
435 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 $ hg -R cloned-bookmarks-update bookmarks
442 $ hg -R cloned-bookmarks-update bookmarks
437 X2 1:925d80f479bb
443 X2 1:925d80f479bb
438 Y 2:db815d6d32e6
444 Y 2:db815d6d32e6
439 * Z 2:db815d6d32e6
445 * Z 2:db815d6d32e6
440 x y 2:db815d6d32e6
446 x y 2:db815d6d32e6
441
447
442 create bundle with two heads
448 create bundle with two heads
443
449
444 $ hg clone . tobundle
450 $ hg clone . tobundle
445 updating to branch default
451 updating to branch default
446 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
452 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 $ echo x > tobundle/x
453 $ echo x > tobundle/x
448 $ hg -R tobundle add tobundle/x
454 $ hg -R tobundle add tobundle/x
449 $ hg -R tobundle commit -m'x'
455 $ hg -R tobundle commit -m'x'
450 $ hg -R tobundle update -r -2
456 $ hg -R tobundle update -r -2
451 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
457 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
452 $ echo y > tobundle/y
458 $ echo y > tobundle/y
453 $ hg -R tobundle branch test
459 $ hg -R tobundle branch test
454 marked working directory as branch test
460 marked working directory as branch test
455 (branches are permanent and global, did you want a bookmark?)
461 (branches are permanent and global, did you want a bookmark?)
456 $ hg -R tobundle add tobundle/y
462 $ hg -R tobundle add tobundle/y
457 $ hg -R tobundle commit -m'y'
463 $ hg -R tobundle commit -m'y'
458 $ hg -R tobundle bundle tobundle.hg
464 $ hg -R tobundle bundle tobundle.hg
459 searching for changes
465 searching for changes
460 2 changesets found
466 2 changesets found
461 $ hg unbundle tobundle.hg
467 $ hg unbundle tobundle.hg
462 adding changesets
468 adding changesets
463 adding manifests
469 adding manifests
464 adding file changes
470 adding file changes
465 added 2 changesets with 2 changes to 2 files (+1 heads)
471 added 2 changesets with 2 changes to 2 files (+1 heads)
466 (run 'hg heads' to see heads, 'hg merge' to merge)
472 (run 'hg heads' to see heads, 'hg merge' to merge)
467
473
468 update to current bookmark if it's not the parent
474 update to current bookmark if it's not the parent
469
475
470 $ hg summary
476 $ hg summary
471 parent: 2:db815d6d32e6
477 parent: 2:db815d6d32e6
472 2
478 2
473 branch: default
479 branch: default
474 bookmarks: [Z] Y x y
480 bookmarks: [Z] Y x y
475 commit: 1 added, 1 unknown (new branch head)
481 commit: 1 added, 1 unknown (new branch head)
476 update: 2 new changesets (update)
482 update: 2 new changesets (update)
477 $ hg update
483 $ hg update
478 updating to active bookmark Z
484 updating to active bookmark Z
479 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
480 $ hg bookmarks
486 $ hg bookmarks
481 X2 1:925d80f479bb
487 X2 1:925d80f479bb
482 Y 2:db815d6d32e6
488 Y 2:db815d6d32e6
483 * Z 3:125c9a1d6df6
489 * Z 3:125c9a1d6df6
484 x y 2:db815d6d32e6
490 x y 2:db815d6d32e6
485
491
486 test wrongly formated bookmark
492 test wrongly formated bookmark
487
493
488 $ echo '' >> .hg/bookmarks
494 $ echo '' >> .hg/bookmarks
489 $ hg bookmarks
495 $ hg bookmarks
490 X2 1:925d80f479bb
496 X2 1:925d80f479bb
491 Y 2:db815d6d32e6
497 Y 2:db815d6d32e6
492 * Z 3:125c9a1d6df6
498 * Z 3:125c9a1d6df6
493 x y 2:db815d6d32e6
499 x y 2:db815d6d32e6
494 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
500 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
495 $ hg bookmarks
501 $ hg bookmarks
496 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
502 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
497 X2 1:925d80f479bb
503 X2 1:925d80f479bb
498 Y 2:db815d6d32e6
504 Y 2:db815d6d32e6
499 * Z 3:125c9a1d6df6
505 * Z 3:125c9a1d6df6
500 x y 2:db815d6d32e6
506 x y 2:db815d6d32e6
501
507
502 test missing revisions
508 test missing revisions
503
509
504 $ echo "925d80f479bc z" > .hg/bookmarks
510 $ echo "925d80f479bc z" > .hg/bookmarks
505 $ hg book
511 $ hg book
506 no bookmarks set
512 no bookmarks set
507
513
508 test stripping a non-checked-out but bookmarked revision
514 test stripping a non-checked-out but bookmarked revision
509
515
510 $ hg --config extensions.graphlog= log --graph
516 $ hg --config extensions.graphlog= log --graph
511 o changeset: 4:9ba5f110a0b3
517 o changeset: 4:9ba5f110a0b3
512 | branch: test
518 | branch: test
513 | tag: tip
519 | tag: tip
514 | parent: 2:db815d6d32e6
520 | parent: 2:db815d6d32e6
515 | user: test
521 | user: test
516 | date: Thu Jan 01 00:00:00 1970 +0000
522 | date: Thu Jan 01 00:00:00 1970 +0000
517 | summary: y
523 | summary: y
518 |
524 |
519 | @ changeset: 3:125c9a1d6df6
525 | @ changeset: 3:125c9a1d6df6
520 |/ user: test
526 |/ user: test
521 | date: Thu Jan 01 00:00:00 1970 +0000
527 | date: Thu Jan 01 00:00:00 1970 +0000
522 | summary: x
528 | summary: x
523 |
529 |
524 o changeset: 2:db815d6d32e6
530 o changeset: 2:db815d6d32e6
525 | parent: 0:f7b1eb17ad24
531 | parent: 0:f7b1eb17ad24
526 | user: test
532 | user: test
527 | date: Thu Jan 01 00:00:00 1970 +0000
533 | date: Thu Jan 01 00:00:00 1970 +0000
528 | summary: 2
534 | summary: 2
529 |
535 |
530 | o changeset: 1:925d80f479bb
536 | o changeset: 1:925d80f479bb
531 |/ user: test
537 |/ user: test
532 | date: Thu Jan 01 00:00:00 1970 +0000
538 | date: Thu Jan 01 00:00:00 1970 +0000
533 | summary: 1
539 | summary: 1
534 |
540 |
535 o changeset: 0:f7b1eb17ad24
541 o changeset: 0:f7b1eb17ad24
536 user: test
542 user: test
537 date: Thu Jan 01 00:00:00 1970 +0000
543 date: Thu Jan 01 00:00:00 1970 +0000
538 summary: 0
544 summary: 0
539
545
540 $ hg book should-end-on-two
546 $ hg book should-end-on-two
541 $ hg co --clean 4
547 $ hg co --clean 4
542 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
548 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
543 $ hg book four
549 $ hg book four
544 $ hg --config extensions.mq= strip 3
550 $ hg --config extensions.mq= strip 3
545 saved backup bundle to * (glob)
551 saved backup bundle to * (glob)
546 should-end-on-two should end up pointing to revision 2, as that's the
552 should-end-on-two should end up pointing to revision 2, as that's the
547 tipmost surviving ancestor of the stripped revision.
553 tipmost surviving ancestor of the stripped revision.
548 $ hg --config extensions.graphlog= log --graph
554 $ hg --config extensions.graphlog= log --graph
549 @ changeset: 3:9ba5f110a0b3
555 @ changeset: 3:9ba5f110a0b3
550 | branch: test
556 | branch: test
551 | bookmark: four
557 | bookmark: four
552 | tag: tip
558 | tag: tip
553 | user: test
559 | user: test
554 | date: Thu Jan 01 00:00:00 1970 +0000
560 | date: Thu Jan 01 00:00:00 1970 +0000
555 | summary: y
561 | summary: y
556 |
562 |
557 o changeset: 2:db815d6d32e6
563 o changeset: 2:db815d6d32e6
558 | bookmark: should-end-on-two
564 | bookmark: should-end-on-two
559 | parent: 0:f7b1eb17ad24
565 | parent: 0:f7b1eb17ad24
560 | user: test
566 | user: test
561 | date: Thu Jan 01 00:00:00 1970 +0000
567 | date: Thu Jan 01 00:00:00 1970 +0000
562 | summary: 2
568 | summary: 2
563 |
569 |
564 | o changeset: 1:925d80f479bb
570 | o changeset: 1:925d80f479bb
565 |/ user: test
571 |/ user: test
566 | date: Thu Jan 01 00:00:00 1970 +0000
572 | date: Thu Jan 01 00:00:00 1970 +0000
567 | summary: 1
573 | summary: 1
568 |
574 |
569 o changeset: 0:f7b1eb17ad24
575 o changeset: 0:f7b1eb17ad24
570 user: test
576 user: test
571 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
572 summary: 0
578 summary: 0
573
579
General Comments 0
You need to be logged in to leave comments. Login now