##// END OF EJS Templates
import: don't rollback on failed import --exact (issue3616)...
Kevin Bullock -
r18656:8eb3408b default
parent child Browse files
Show More
@@ -1,6051 +1,6050 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, 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 hg.clean(repo, node, show_stats=False)
459 hg.clean(repo, node, show_stats=False)
460 repo.dirstate.setbranch(branch)
460 repo.dirstate.setbranch(branch)
461 revert_opts = opts.copy()
461 revert_opts = opts.copy()
462 revert_opts['date'] = None
462 revert_opts['date'] = None
463 revert_opts['all'] = True
463 revert_opts['all'] = True
464 revert_opts['rev'] = hex(parent)
464 revert_opts['rev'] = hex(parent)
465 revert_opts['no_backup'] = None
465 revert_opts['no_backup'] = None
466 revert(ui, repo, **revert_opts)
466 revert(ui, repo, **revert_opts)
467 if not opts.get('merge') and op1 != node:
467 if not opts.get('merge') and op1 != node:
468 try:
468 try:
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 return hg.update(repo, op1)
470 return hg.update(repo, op1)
471 finally:
471 finally:
472 ui.setconfig('ui', 'forcemerge', '')
472 ui.setconfig('ui', 'forcemerge', '')
473
473
474 commit_opts = opts.copy()
474 commit_opts = opts.copy()
475 commit_opts['addremove'] = False
475 commit_opts['addremove'] = False
476 if not commit_opts['message'] and not commit_opts['logfile']:
476 if not commit_opts['message'] and not commit_opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
479 commit_opts['force_editor'] = True
479 commit_opts['force_editor'] = True
480 commit(ui, repo, **commit_opts)
480 commit(ui, repo, **commit_opts)
481 def nice(node):
481 def nice(node):
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
483 ui.status(_('changeset %s backs out changeset %s\n') %
483 ui.status(_('changeset %s backs out changeset %s\n') %
484 (nice(repo.changelog.tip()), nice(node)))
484 (nice(repo.changelog.tip()), nice(node)))
485 if opts.get('merge') and op1 != node:
485 if opts.get('merge') and op1 != node:
486 hg.clean(repo, op1, show_stats=False)
486 hg.clean(repo, op1, show_stats=False)
487 ui.status(_('merging with changeset %s\n')
487 ui.status(_('merging with changeset %s\n')
488 % nice(repo.changelog.tip()))
488 % nice(repo.changelog.tip()))
489 try:
489 try:
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
491 return hg.merge(repo, hex(repo.changelog.tip()))
491 return hg.merge(repo, hex(repo.changelog.tip()))
492 finally:
492 finally:
493 ui.setconfig('ui', 'forcemerge', '')
493 ui.setconfig('ui', 'forcemerge', '')
494 finally:
494 finally:
495 wlock.release()
495 wlock.release()
496 return 0
496 return 0
497
497
498 @command('bisect',
498 @command('bisect',
499 [('r', 'reset', False, _('reset bisect state')),
499 [('r', 'reset', False, _('reset bisect state')),
500 ('g', 'good', False, _('mark changeset good')),
500 ('g', 'good', False, _('mark changeset good')),
501 ('b', 'bad', False, _('mark changeset bad')),
501 ('b', 'bad', False, _('mark changeset bad')),
502 ('s', 'skip', False, _('skip testing changeset')),
502 ('s', 'skip', False, _('skip testing changeset')),
503 ('e', 'extend', False, _('extend the bisect range')),
503 ('e', 'extend', False, _('extend the bisect range')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
505 ('U', 'noupdate', False, _('do not update to target'))],
505 ('U', 'noupdate', False, _('do not update to target'))],
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
507 def bisect(ui, repo, rev=None, extra=None, command=None,
507 def bisect(ui, repo, rev=None, extra=None, command=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
509 noupdate=None):
509 noupdate=None):
510 """subdivision search of changesets
510 """subdivision search of changesets
511
511
512 This command helps to find changesets which introduce problems. To
512 This command helps to find changesets which introduce problems. To
513 use, mark the earliest changeset you know exhibits the problem as
513 use, mark the earliest changeset you know exhibits the problem as
514 bad, then mark the latest changeset which is free from the problem
514 bad, then mark the latest changeset which is free from the problem
515 as good. Bisect will update your working directory to a revision
515 as good. Bisect will update your working directory to a revision
516 for testing (unless the -U/--noupdate option is specified). Once
516 for testing (unless the -U/--noupdate option is specified). Once
517 you have performed tests, mark the working directory as good or
517 you have performed tests, mark the working directory as good or
518 bad, and bisect will either update to another candidate changeset
518 bad, and bisect will either update to another candidate changeset
519 or announce that it has found the bad revision.
519 or announce that it has found the bad revision.
520
520
521 As a shortcut, you can also use the revision argument to mark a
521 As a shortcut, you can also use the revision argument to mark a
522 revision as good or bad without checking it out first.
522 revision as good or bad without checking it out first.
523
523
524 If you supply a command, it will be used for automatic bisection.
524 If you supply a command, it will be used for automatic bisection.
525 The environment variable HG_NODE will contain the ID of the
525 The environment variable HG_NODE will contain the ID of the
526 changeset being tested. The exit status of the command will be
526 changeset being tested. The exit status of the command will be
527 used to mark revisions as good or bad: status 0 means good, 125
527 used to mark revisions as good or bad: status 0 means good, 125
528 means to skip the revision, 127 (command not found) will abort the
528 means to skip the revision, 127 (command not found) will abort the
529 bisection, and any other non-zero exit status means the revision
529 bisection, and any other non-zero exit status means the revision
530 is bad.
530 is bad.
531
531
532 .. container:: verbose
532 .. container:: verbose
533
533
534 Some examples:
534 Some examples:
535
535
536 - start a bisection with known bad revision 12, and good revision 34::
536 - start a bisection with known bad revision 12, and good revision 34::
537
537
538 hg bisect --bad 34
538 hg bisect --bad 34
539 hg bisect --good 12
539 hg bisect --good 12
540
540
541 - advance the current bisection by marking current revision as good or
541 - advance the current bisection by marking current revision as good or
542 bad::
542 bad::
543
543
544 hg bisect --good
544 hg bisect --good
545 hg bisect --bad
545 hg bisect --bad
546
546
547 - mark the current revision, or a known revision, to be skipped (e.g. if
547 - mark the current revision, or a known revision, to be skipped (e.g. if
548 that revision is not usable because of another issue)::
548 that revision is not usable because of another issue)::
549
549
550 hg bisect --skip
550 hg bisect --skip
551 hg bisect --skip 23
551 hg bisect --skip 23
552
552
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
554
554
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
556
556
557 - forget the current bisection::
557 - forget the current bisection::
558
558
559 hg bisect --reset
559 hg bisect --reset
560
560
561 - use 'make && make tests' to automatically find the first broken
561 - use 'make && make tests' to automatically find the first broken
562 revision::
562 revision::
563
563
564 hg bisect --reset
564 hg bisect --reset
565 hg bisect --bad 34
565 hg bisect --bad 34
566 hg bisect --good 12
566 hg bisect --good 12
567 hg bisect --command 'make && make tests'
567 hg bisect --command 'make && make tests'
568
568
569 - see all changesets whose states are already known in the current
569 - see all changesets whose states are already known in the current
570 bisection::
570 bisection::
571
571
572 hg log -r "bisect(pruned)"
572 hg log -r "bisect(pruned)"
573
573
574 - see the changeset currently being bisected (especially useful
574 - see the changeset currently being bisected (especially useful
575 if running with -U/--noupdate)::
575 if running with -U/--noupdate)::
576
576
577 hg log -r "bisect(current)"
577 hg log -r "bisect(current)"
578
578
579 - see all changesets that took part in the current bisection::
579 - see all changesets that took part in the current bisection::
580
580
581 hg log -r "bisect(range)"
581 hg log -r "bisect(range)"
582
582
583 - with the graphlog extension, you can even get a nice graph::
583 - with the graphlog extension, you can even get a nice graph::
584
584
585 hg log --graph -r "bisect(range)"
585 hg log --graph -r "bisect(range)"
586
586
587 See :hg:`help revsets` for more about the `bisect()` keyword.
587 See :hg:`help revsets` for more about the `bisect()` keyword.
588
588
589 Returns 0 on success.
589 Returns 0 on success.
590 """
590 """
591 def extendbisectrange(nodes, good):
591 def extendbisectrange(nodes, good):
592 # bisect is incomplete when it ends on a merge node and
592 # bisect is incomplete when it ends on a merge node and
593 # one of the parent was not checked.
593 # one of the parent was not checked.
594 parents = repo[nodes[0]].parents()
594 parents = repo[nodes[0]].parents()
595 if len(parents) > 1:
595 if len(parents) > 1:
596 side = good and state['bad'] or state['good']
596 side = good and state['bad'] or state['good']
597 num = len(set(i.node() for i in parents) & set(side))
597 num = len(set(i.node() for i in parents) & set(side))
598 if num == 1:
598 if num == 1:
599 return parents[0].ancestor(parents[1])
599 return parents[0].ancestor(parents[1])
600 return None
600 return None
601
601
602 def print_result(nodes, good):
602 def print_result(nodes, good):
603 displayer = cmdutil.show_changeset(ui, repo, {})
603 displayer = cmdutil.show_changeset(ui, repo, {})
604 if len(nodes) == 1:
604 if len(nodes) == 1:
605 # narrowed it down to a single revision
605 # narrowed it down to a single revision
606 if good:
606 if good:
607 ui.write(_("The first good revision is:\n"))
607 ui.write(_("The first good revision is:\n"))
608 else:
608 else:
609 ui.write(_("The first bad revision is:\n"))
609 ui.write(_("The first bad revision is:\n"))
610 displayer.show(repo[nodes[0]])
610 displayer.show(repo[nodes[0]])
611 extendnode = extendbisectrange(nodes, good)
611 extendnode = extendbisectrange(nodes, good)
612 if extendnode is not None:
612 if extendnode is not None:
613 ui.write(_('Not all ancestors of this changeset have been'
613 ui.write(_('Not all ancestors of this changeset have been'
614 ' checked.\nUse bisect --extend to continue the '
614 ' checked.\nUse bisect --extend to continue the '
615 'bisection from\nthe common ancestor, %s.\n')
615 'bisection from\nthe common ancestor, %s.\n')
616 % extendnode)
616 % extendnode)
617 else:
617 else:
618 # multiple possible revisions
618 # multiple possible revisions
619 if good:
619 if good:
620 ui.write(_("Due to skipped revisions, the first "
620 ui.write(_("Due to skipped revisions, the first "
621 "good revision could be any of:\n"))
621 "good revision could be any of:\n"))
622 else:
622 else:
623 ui.write(_("Due to skipped revisions, the first "
623 ui.write(_("Due to skipped revisions, the first "
624 "bad revision could be any of:\n"))
624 "bad revision could be any of:\n"))
625 for n in nodes:
625 for n in nodes:
626 displayer.show(repo[n])
626 displayer.show(repo[n])
627 displayer.close()
627 displayer.close()
628
628
629 def check_state(state, interactive=True):
629 def check_state(state, interactive=True):
630 if not state['good'] or not state['bad']:
630 if not state['good'] or not state['bad']:
631 if (good or bad or skip or reset) and interactive:
631 if (good or bad or skip or reset) and interactive:
632 return
632 return
633 if not state['good']:
633 if not state['good']:
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
635 else:
635 else:
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
637 return True
637 return True
638
638
639 # backward compatibility
639 # backward compatibility
640 if rev in "good bad reset init".split():
640 if rev in "good bad reset init".split():
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
642 cmd, rev, extra = rev, extra, None
642 cmd, rev, extra = rev, extra, None
643 if cmd == "good":
643 if cmd == "good":
644 good = True
644 good = True
645 elif cmd == "bad":
645 elif cmd == "bad":
646 bad = True
646 bad = True
647 else:
647 else:
648 reset = True
648 reset = True
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
650 raise util.Abort(_('incompatible arguments'))
650 raise util.Abort(_('incompatible arguments'))
651
651
652 if reset:
652 if reset:
653 p = repo.join("bisect.state")
653 p = repo.join("bisect.state")
654 if os.path.exists(p):
654 if os.path.exists(p):
655 os.unlink(p)
655 os.unlink(p)
656 return
656 return
657
657
658 state = hbisect.load_state(repo)
658 state = hbisect.load_state(repo)
659
659
660 if command:
660 if command:
661 changesets = 1
661 changesets = 1
662 try:
662 try:
663 node = state['current'][0]
663 node = state['current'][0]
664 except LookupError:
664 except LookupError:
665 if noupdate:
665 if noupdate:
666 raise util.Abort(_('current bisect revision is unknown - '
666 raise util.Abort(_('current bisect revision is unknown - '
667 'start a new bisect to fix'))
667 'start a new bisect to fix'))
668 node, p2 = repo.dirstate.parents()
668 node, p2 = repo.dirstate.parents()
669 if p2 != nullid:
669 if p2 != nullid:
670 raise util.Abort(_('current bisect revision is a merge'))
670 raise util.Abort(_('current bisect revision is a merge'))
671 try:
671 try:
672 while changesets:
672 while changesets:
673 # update state
673 # update state
674 state['current'] = [node]
674 state['current'] = [node]
675 hbisect.save_state(repo, state)
675 hbisect.save_state(repo, state)
676 status = util.system(command,
676 status = util.system(command,
677 environ={'HG_NODE': hex(node)},
677 environ={'HG_NODE': hex(node)},
678 out=ui.fout)
678 out=ui.fout)
679 if status == 125:
679 if status == 125:
680 transition = "skip"
680 transition = "skip"
681 elif status == 0:
681 elif status == 0:
682 transition = "good"
682 transition = "good"
683 # status < 0 means process was killed
683 # status < 0 means process was killed
684 elif status == 127:
684 elif status == 127:
685 raise util.Abort(_("failed to execute %s") % command)
685 raise util.Abort(_("failed to execute %s") % command)
686 elif status < 0:
686 elif status < 0:
687 raise util.Abort(_("%s killed") % command)
687 raise util.Abort(_("%s killed") % command)
688 else:
688 else:
689 transition = "bad"
689 transition = "bad"
690 ctx = scmutil.revsingle(repo, rev, node)
690 ctx = scmutil.revsingle(repo, rev, node)
691 rev = None # clear for future iterations
691 rev = None # clear for future iterations
692 state[transition].append(ctx.node())
692 state[transition].append(ctx.node())
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
694 check_state(state, interactive=False)
694 check_state(state, interactive=False)
695 # bisect
695 # bisect
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
697 # update to next check
697 # update to next check
698 node = nodes[0]
698 node = nodes[0]
699 if not noupdate:
699 if not noupdate:
700 cmdutil.bailifchanged(repo)
700 cmdutil.bailifchanged(repo)
701 hg.clean(repo, node, show_stats=False)
701 hg.clean(repo, node, show_stats=False)
702 finally:
702 finally:
703 state['current'] = [node]
703 state['current'] = [node]
704 hbisect.save_state(repo, state)
704 hbisect.save_state(repo, state)
705 print_result(nodes, good)
705 print_result(nodes, good)
706 return
706 return
707
707
708 # update state
708 # update state
709
709
710 if rev:
710 if rev:
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
712 else:
712 else:
713 nodes = [repo.lookup('.')]
713 nodes = [repo.lookup('.')]
714
714
715 if good or bad or skip:
715 if good or bad or skip:
716 if good:
716 if good:
717 state['good'] += nodes
717 state['good'] += nodes
718 elif bad:
718 elif bad:
719 state['bad'] += nodes
719 state['bad'] += nodes
720 elif skip:
720 elif skip:
721 state['skip'] += nodes
721 state['skip'] += nodes
722 hbisect.save_state(repo, state)
722 hbisect.save_state(repo, state)
723
723
724 if not check_state(state):
724 if not check_state(state):
725 return
725 return
726
726
727 # actually bisect
727 # actually bisect
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
729 if extend:
729 if extend:
730 if not changesets:
730 if not changesets:
731 extendnode = extendbisectrange(nodes, good)
731 extendnode = extendbisectrange(nodes, good)
732 if extendnode is not None:
732 if extendnode is not None:
733 ui.write(_("Extending search to changeset %d:%s\n"
733 ui.write(_("Extending search to changeset %d:%s\n"
734 % (extendnode.rev(), extendnode)))
734 % (extendnode.rev(), extendnode)))
735 state['current'] = [extendnode.node()]
735 state['current'] = [extendnode.node()]
736 hbisect.save_state(repo, state)
736 hbisect.save_state(repo, state)
737 if noupdate:
737 if noupdate:
738 return
738 return
739 cmdutil.bailifchanged(repo)
739 cmdutil.bailifchanged(repo)
740 return hg.clean(repo, extendnode.node())
740 return hg.clean(repo, extendnode.node())
741 raise util.Abort(_("nothing to extend"))
741 raise util.Abort(_("nothing to extend"))
742
742
743 if changesets == 0:
743 if changesets == 0:
744 print_result(nodes, good)
744 print_result(nodes, good)
745 else:
745 else:
746 assert len(nodes) == 1 # only a single node can be tested next
746 assert len(nodes) == 1 # only a single node can be tested next
747 node = nodes[0]
747 node = nodes[0]
748 # compute the approximate number of remaining tests
748 # compute the approximate number of remaining tests
749 tests, size = 0, 2
749 tests, size = 0, 2
750 while size <= changesets:
750 while size <= changesets:
751 tests, size = tests + 1, size * 2
751 tests, size = tests + 1, size * 2
752 rev = repo.changelog.rev(node)
752 rev = repo.changelog.rev(node)
753 ui.write(_("Testing changeset %d:%s "
753 ui.write(_("Testing changeset %d:%s "
754 "(%d changesets remaining, ~%d tests)\n")
754 "(%d changesets remaining, ~%d tests)\n")
755 % (rev, short(node), changesets, tests))
755 % (rev, short(node), changesets, tests))
756 state['current'] = [node]
756 state['current'] = [node]
757 hbisect.save_state(repo, state)
757 hbisect.save_state(repo, state)
758 if not noupdate:
758 if not noupdate:
759 cmdutil.bailifchanged(repo)
759 cmdutil.bailifchanged(repo)
760 return hg.clean(repo, node)
760 return hg.clean(repo, node)
761
761
762 @command('bookmarks|bookmark',
762 @command('bookmarks|bookmark',
763 [('f', 'force', False, _('force')),
763 [('f', 'force', False, _('force')),
764 ('r', 'rev', '', _('revision'), _('REV')),
764 ('r', 'rev', '', _('revision'), _('REV')),
765 ('d', 'delete', False, _('delete a given bookmark')),
765 ('d', 'delete', False, _('delete a given bookmark')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
770 rename=None, inactive=False):
770 rename=None, inactive=False):
771 '''track a line of development with movable markers
771 '''track a line of development with movable markers
772
772
773 Bookmarks are pointers to certain commits that move when committing.
773 Bookmarks are pointers to certain commits that move when committing.
774 Bookmarks are local. They can be renamed, copied and deleted. It is
774 Bookmarks are local. They can be renamed, copied and deleted. It is
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
776 :hg:`update NAME` to update to a given bookmark.
776 :hg:`update NAME` to update to a given bookmark.
777
777
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
779 directory's parent revision with the given name. If you specify
779 directory's parent revision with the given name. If you specify
780 a revision using -r REV (where REV may be an existing bookmark),
780 a revision using -r REV (where REV may be an existing bookmark),
781 the bookmark is assigned to that revision.
781 the bookmark is assigned to that revision.
782
782
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
784 push` and :hg:`help pull`). This requires both the local and remote
784 push` and :hg:`help pull`). This requires both the local and remote
785 repositories to support bookmarks. For versions prior to 1.8, this means
785 repositories to support bookmarks. For versions prior to 1.8, this means
786 the bookmarks extension must be enabled.
786 the bookmarks extension must be enabled.
787
787
788 If you set a bookmark called '@', new clones of the repository will
788 If you set a bookmark called '@', new clones of the repository will
789 have that revision checked out (and the bookmark made active) by
789 have that revision checked out (and the bookmark made active) by
790 default.
790 default.
791
791
792 With -i/--inactive, the new bookmark will not be made the active
792 With -i/--inactive, the new bookmark will not be made the active
793 bookmark. If -r/--rev is given, the new bookmark will not be made
793 bookmark. If -r/--rev is given, the new bookmark will not be made
794 active even if -i/--inactive is not given. If no NAME is given, the
794 active even if -i/--inactive is not given. If no NAME is given, the
795 current active bookmark will be marked inactive.
795 current active bookmark will be marked inactive.
796 '''
796 '''
797 hexfn = ui.debugflag and hex or short
797 hexfn = ui.debugflag and hex or short
798 marks = repo._bookmarks
798 marks = repo._bookmarks
799 cur = repo.changectx('.').node()
799 cur = repo.changectx('.').node()
800
800
801 def checkformat(mark):
801 def checkformat(mark):
802 mark = mark.strip()
802 mark = mark.strip()
803 if not mark:
803 if not mark:
804 raise util.Abort(_("bookmark names cannot consist entirely of "
804 raise util.Abort(_("bookmark names cannot consist entirely of "
805 "whitespace"))
805 "whitespace"))
806 scmutil.checknewlabel(repo, mark, 'bookmark')
806 scmutil.checknewlabel(repo, mark, 'bookmark')
807 return mark
807 return mark
808
808
809 def checkconflict(repo, mark, force=False):
809 def checkconflict(repo, mark, force=False):
810 if mark in marks and not force:
810 if mark in marks and not force:
811 raise util.Abort(_("bookmark '%s' already exists "
811 raise util.Abort(_("bookmark '%s' already exists "
812 "(use -f to force)") % mark)
812 "(use -f to force)") % mark)
813 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
813 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
814 and not force):
814 and not force):
815 raise util.Abort(
815 raise util.Abort(
816 _("a bookmark cannot have the name of an existing branch"))
816 _("a bookmark cannot have the name of an existing branch"))
817
817
818 if delete and rename:
818 if delete and rename:
819 raise util.Abort(_("--delete and --rename are incompatible"))
819 raise util.Abort(_("--delete and --rename are incompatible"))
820 if delete and rev:
820 if delete and rev:
821 raise util.Abort(_("--rev is incompatible with --delete"))
821 raise util.Abort(_("--rev is incompatible with --delete"))
822 if rename and rev:
822 if rename and rev:
823 raise util.Abort(_("--rev is incompatible with --rename"))
823 raise util.Abort(_("--rev is incompatible with --rename"))
824 if mark is None and (delete or rev):
824 if mark is None and (delete or rev):
825 raise util.Abort(_("bookmark name required"))
825 raise util.Abort(_("bookmark name required"))
826
826
827 if delete:
827 if delete:
828 if mark not in marks:
828 if mark not in marks:
829 raise util.Abort(_("bookmark '%s' does not exist") % mark)
829 raise util.Abort(_("bookmark '%s' does not exist") % mark)
830 if mark == repo._bookmarkcurrent:
830 if mark == repo._bookmarkcurrent:
831 bookmarks.setcurrent(repo, None)
831 bookmarks.setcurrent(repo, None)
832 del marks[mark]
832 del marks[mark]
833 marks.write()
833 marks.write()
834
834
835 elif rename:
835 elif rename:
836 if mark is None:
836 if mark is None:
837 raise util.Abort(_("new bookmark name required"))
837 raise util.Abort(_("new bookmark name required"))
838 mark = checkformat(mark)
838 mark = checkformat(mark)
839 if rename not in marks:
839 if rename not in marks:
840 raise util.Abort(_("bookmark '%s' does not exist") % rename)
840 raise util.Abort(_("bookmark '%s' does not exist") % rename)
841 checkconflict(repo, mark, force)
841 checkconflict(repo, mark, force)
842 marks[mark] = marks[rename]
842 marks[mark] = marks[rename]
843 if repo._bookmarkcurrent == rename and not inactive:
843 if repo._bookmarkcurrent == rename and not inactive:
844 bookmarks.setcurrent(repo, mark)
844 bookmarks.setcurrent(repo, mark)
845 del marks[rename]
845 del marks[rename]
846 marks.write()
846 marks.write()
847
847
848 elif mark is not None:
848 elif mark is not None:
849 mark = checkformat(mark)
849 mark = checkformat(mark)
850 if inactive and mark == repo._bookmarkcurrent:
850 if inactive and mark == repo._bookmarkcurrent:
851 bookmarks.setcurrent(repo, None)
851 bookmarks.setcurrent(repo, None)
852 return
852 return
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 if rev:
854 if rev:
855 marks[mark] = scmutil.revsingle(repo, rev).node()
855 marks[mark] = scmutil.revsingle(repo, rev).node()
856 else:
856 else:
857 marks[mark] = cur
857 marks[mark] = cur
858 if not inactive and cur == marks[mark]:
858 if not inactive and cur == marks[mark]:
859 bookmarks.setcurrent(repo, mark)
859 bookmarks.setcurrent(repo, mark)
860 marks.write()
860 marks.write()
861
861
862 # Same message whether trying to deactivate the current bookmark (-i
862 # Same message whether trying to deactivate the current bookmark (-i
863 # with no NAME) or listing bookmarks
863 # with no NAME) or listing bookmarks
864 elif len(marks) == 0:
864 elif len(marks) == 0:
865 ui.status(_("no bookmarks set\n"))
865 ui.status(_("no bookmarks set\n"))
866
866
867 elif inactive:
867 elif inactive:
868 if not repo._bookmarkcurrent:
868 if not repo._bookmarkcurrent:
869 ui.status(_("no active bookmark\n"))
869 ui.status(_("no active bookmark\n"))
870 else:
870 else:
871 bookmarks.setcurrent(repo, None)
871 bookmarks.setcurrent(repo, None)
872
872
873 else: # show bookmarks
873 else: # show bookmarks
874 for bmark, n in sorted(marks.iteritems()):
874 for bmark, n in sorted(marks.iteritems()):
875 current = repo._bookmarkcurrent
875 current = repo._bookmarkcurrent
876 if bmark == current:
876 if bmark == current:
877 prefix, label = '*', 'bookmarks.current'
877 prefix, label = '*', 'bookmarks.current'
878 else:
878 else:
879 prefix, label = ' ', ''
879 prefix, label = ' ', ''
880
880
881 if ui.quiet:
881 if ui.quiet:
882 ui.write("%s\n" % bmark, label=label)
882 ui.write("%s\n" % bmark, label=label)
883 else:
883 else:
884 ui.write(" %s %-25s %d:%s\n" % (
884 ui.write(" %s %-25s %d:%s\n" % (
885 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
885 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
886 label=label)
886 label=label)
887
887
888 @command('branch',
888 @command('branch',
889 [('f', 'force', None,
889 [('f', 'force', None,
890 _('set branch name even if it shadows an existing branch')),
890 _('set branch name even if it shadows an existing branch')),
891 ('C', 'clean', None, _('reset branch name to parent branch name'))],
891 ('C', 'clean', None, _('reset branch name to parent branch name'))],
892 _('[-fC] [NAME]'))
892 _('[-fC] [NAME]'))
893 def branch(ui, repo, label=None, **opts):
893 def branch(ui, repo, label=None, **opts):
894 """set or show the current branch name
894 """set or show the current branch name
895
895
896 .. note::
896 .. note::
897 Branch names are permanent and global. Use :hg:`bookmark` to create a
897 Branch names are permanent and global. Use :hg:`bookmark` to create a
898 light-weight bookmark instead. See :hg:`help glossary` for more
898 light-weight bookmark instead. See :hg:`help glossary` for more
899 information about named branches and bookmarks.
899 information about named branches and bookmarks.
900
900
901 With no argument, show the current branch name. With one argument,
901 With no argument, show the current branch name. With one argument,
902 set the working directory branch name (the branch will not exist
902 set the working directory branch name (the branch will not exist
903 in the repository until the next commit). Standard practice
903 in the repository until the next commit). Standard practice
904 recommends that primary development take place on the 'default'
904 recommends that primary development take place on the 'default'
905 branch.
905 branch.
906
906
907 Unless -f/--force is specified, branch will not let you set a
907 Unless -f/--force is specified, branch will not let you set a
908 branch name that already exists, even if it's inactive.
908 branch name that already exists, even if it's inactive.
909
909
910 Use -C/--clean to reset the working directory branch to that of
910 Use -C/--clean to reset the working directory branch to that of
911 the parent of the working directory, negating a previous branch
911 the parent of the working directory, negating a previous branch
912 change.
912 change.
913
913
914 Use the command :hg:`update` to switch to an existing branch. Use
914 Use the command :hg:`update` to switch to an existing branch. Use
915 :hg:`commit --close-branch` to mark this branch as closed.
915 :hg:`commit --close-branch` to mark this branch as closed.
916
916
917 Returns 0 on success.
917 Returns 0 on success.
918 """
918 """
919 if not opts.get('clean') and not label:
919 if not opts.get('clean') and not label:
920 ui.write("%s\n" % repo.dirstate.branch())
920 ui.write("%s\n" % repo.dirstate.branch())
921 return
921 return
922
922
923 wlock = repo.wlock()
923 wlock = repo.wlock()
924 try:
924 try:
925 if opts.get('clean'):
925 if opts.get('clean'):
926 label = repo[None].p1().branch()
926 label = repo[None].p1().branch()
927 repo.dirstate.setbranch(label)
927 repo.dirstate.setbranch(label)
928 ui.status(_('reset working directory to branch %s\n') % label)
928 ui.status(_('reset working directory to branch %s\n') % label)
929 elif label:
929 elif label:
930 if not opts.get('force') and label in repo.branchmap():
930 if not opts.get('force') and label in repo.branchmap():
931 if label not in [p.branch() for p in repo.parents()]:
931 if label not in [p.branch() for p in repo.parents()]:
932 raise util.Abort(_('a branch of the same name already'
932 raise util.Abort(_('a branch of the same name already'
933 ' exists'),
933 ' exists'),
934 # i18n: "it" refers to an existing branch
934 # i18n: "it" refers to an existing branch
935 hint=_("use 'hg update' to switch to it"))
935 hint=_("use 'hg update' to switch to it"))
936 scmutil.checknewlabel(repo, label, 'branch')
936 scmutil.checknewlabel(repo, label, 'branch')
937 repo.dirstate.setbranch(label)
937 repo.dirstate.setbranch(label)
938 ui.status(_('marked working directory as branch %s\n') % label)
938 ui.status(_('marked working directory as branch %s\n') % label)
939 ui.status(_('(branches are permanent and global, '
939 ui.status(_('(branches are permanent and global, '
940 'did you want a bookmark?)\n'))
940 'did you want a bookmark?)\n'))
941 finally:
941 finally:
942 wlock.release()
942 wlock.release()
943
943
944 @command('branches',
944 @command('branches',
945 [('a', 'active', False, _('show only branches that have unmerged heads')),
945 [('a', 'active', False, _('show only branches that have unmerged heads')),
946 ('c', 'closed', False, _('show normal and closed branches'))],
946 ('c', 'closed', False, _('show normal and closed branches'))],
947 _('[-ac]'))
947 _('[-ac]'))
948 def branches(ui, repo, active=False, closed=False):
948 def branches(ui, repo, active=False, closed=False):
949 """list repository named branches
949 """list repository named branches
950
950
951 List the repository's named branches, indicating which ones are
951 List the repository's named branches, indicating which ones are
952 inactive. If -c/--closed is specified, also list branches which have
952 inactive. If -c/--closed is specified, also list branches which have
953 been marked closed (see :hg:`commit --close-branch`).
953 been marked closed (see :hg:`commit --close-branch`).
954
954
955 If -a/--active is specified, only show active branches. A branch
955 If -a/--active is specified, only show active branches. A branch
956 is considered active if it contains repository heads.
956 is considered active if it contains repository heads.
957
957
958 Use the command :hg:`update` to switch to an existing branch.
958 Use the command :hg:`update` to switch to an existing branch.
959
959
960 Returns 0.
960 Returns 0.
961 """
961 """
962
962
963 hexfunc = ui.debugflag and hex or short
963 hexfunc = ui.debugflag and hex or short
964
964
965 activebranches = set([repo[n].branch() for n in repo.heads()])
965 activebranches = set([repo[n].branch() for n in repo.heads()])
966 branches = []
966 branches = []
967 for tag, heads in repo.branchmap().iteritems():
967 for tag, heads in repo.branchmap().iteritems():
968 for h in reversed(heads):
968 for h in reversed(heads):
969 ctx = repo[h]
969 ctx = repo[h]
970 isopen = not ctx.closesbranch()
970 isopen = not ctx.closesbranch()
971 if isopen:
971 if isopen:
972 tip = ctx
972 tip = ctx
973 break
973 break
974 else:
974 else:
975 tip = repo[heads[-1]]
975 tip = repo[heads[-1]]
976 isactive = tag in activebranches and isopen
976 isactive = tag in activebranches and isopen
977 branches.append((tip, isactive, isopen))
977 branches.append((tip, isactive, isopen))
978 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
978 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
979 reverse=True)
979 reverse=True)
980
980
981 for ctx, isactive, isopen in branches:
981 for ctx, isactive, isopen in branches:
982 if (not active) or isactive:
982 if (not active) or isactive:
983 if isactive:
983 if isactive:
984 label = 'branches.active'
984 label = 'branches.active'
985 notice = ''
985 notice = ''
986 elif not isopen:
986 elif not isopen:
987 if not closed:
987 if not closed:
988 continue
988 continue
989 label = 'branches.closed'
989 label = 'branches.closed'
990 notice = _(' (closed)')
990 notice = _(' (closed)')
991 else:
991 else:
992 label = 'branches.inactive'
992 label = 'branches.inactive'
993 notice = _(' (inactive)')
993 notice = _(' (inactive)')
994 if ctx.branch() == repo.dirstate.branch():
994 if ctx.branch() == repo.dirstate.branch():
995 label = 'branches.current'
995 label = 'branches.current'
996 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
996 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
997 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
997 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
998 'log.changeset changeset.%s' % ctx.phasestr())
998 'log.changeset changeset.%s' % ctx.phasestr())
999 tag = ui.label(ctx.branch(), label)
999 tag = ui.label(ctx.branch(), label)
1000 if ui.quiet:
1000 if ui.quiet:
1001 ui.write("%s\n" % tag)
1001 ui.write("%s\n" % tag)
1002 else:
1002 else:
1003 ui.write("%s %s%s\n" % (tag, rev, notice))
1003 ui.write("%s %s%s\n" % (tag, rev, notice))
1004
1004
1005 @command('bundle',
1005 @command('bundle',
1006 [('f', 'force', None, _('run even when the destination is unrelated')),
1006 [('f', 'force', None, _('run even when the destination is unrelated')),
1007 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1007 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1008 _('REV')),
1008 _('REV')),
1009 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1009 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1010 _('BRANCH')),
1010 _('BRANCH')),
1011 ('', 'base', [],
1011 ('', 'base', [],
1012 _('a base changeset assumed to be available at the destination'),
1012 _('a base changeset assumed to be available at the destination'),
1013 _('REV')),
1013 _('REV')),
1014 ('a', 'all', None, _('bundle all changesets in the repository')),
1014 ('a', 'all', None, _('bundle all changesets in the repository')),
1015 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1015 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1016 ] + remoteopts,
1016 ] + remoteopts,
1017 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1017 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1018 def bundle(ui, repo, fname, dest=None, **opts):
1018 def bundle(ui, repo, fname, dest=None, **opts):
1019 """create a changegroup file
1019 """create a changegroup file
1020
1020
1021 Generate a compressed changegroup file collecting changesets not
1021 Generate a compressed changegroup file collecting changesets not
1022 known to be in another repository.
1022 known to be in another repository.
1023
1023
1024 If you omit the destination repository, then hg assumes the
1024 If you omit the destination repository, then hg assumes the
1025 destination will have all the nodes you specify with --base
1025 destination will have all the nodes you specify with --base
1026 parameters. To create a bundle containing all changesets, use
1026 parameters. To create a bundle containing all changesets, use
1027 -a/--all (or --base null).
1027 -a/--all (or --base null).
1028
1028
1029 You can change compression method with the -t/--type option.
1029 You can change compression method with the -t/--type option.
1030 The available compression methods are: none, bzip2, and
1030 The available compression methods are: none, bzip2, and
1031 gzip (by default, bundles are compressed using bzip2).
1031 gzip (by default, bundles are compressed using bzip2).
1032
1032
1033 The bundle file can then be transferred using conventional means
1033 The bundle file can then be transferred using conventional means
1034 and applied to another repository with the unbundle or pull
1034 and applied to another repository with the unbundle or pull
1035 command. This is useful when direct push and pull are not
1035 command. This is useful when direct push and pull are not
1036 available or when exporting an entire repository is undesirable.
1036 available or when exporting an entire repository is undesirable.
1037
1037
1038 Applying bundles preserves all changeset contents including
1038 Applying bundles preserves all changeset contents including
1039 permissions, copy/rename information, and revision history.
1039 permissions, copy/rename information, and revision history.
1040
1040
1041 Returns 0 on success, 1 if no changes found.
1041 Returns 0 on success, 1 if no changes found.
1042 """
1042 """
1043 revs = None
1043 revs = None
1044 if 'rev' in opts:
1044 if 'rev' in opts:
1045 revs = scmutil.revrange(repo, opts['rev'])
1045 revs = scmutil.revrange(repo, opts['rev'])
1046
1046
1047 bundletype = opts.get('type', 'bzip2').lower()
1047 bundletype = opts.get('type', 'bzip2').lower()
1048 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1048 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1049 bundletype = btypes.get(bundletype)
1049 bundletype = btypes.get(bundletype)
1050 if bundletype not in changegroup.bundletypes:
1050 if bundletype not in changegroup.bundletypes:
1051 raise util.Abort(_('unknown bundle type specified with --type'))
1051 raise util.Abort(_('unknown bundle type specified with --type'))
1052
1052
1053 if opts.get('all'):
1053 if opts.get('all'):
1054 base = ['null']
1054 base = ['null']
1055 else:
1055 else:
1056 base = scmutil.revrange(repo, opts.get('base'))
1056 base = scmutil.revrange(repo, opts.get('base'))
1057 if base:
1057 if base:
1058 if dest:
1058 if dest:
1059 raise util.Abort(_("--base is incompatible with specifying "
1059 raise util.Abort(_("--base is incompatible with specifying "
1060 "a destination"))
1060 "a destination"))
1061 common = [repo.lookup(rev) for rev in base]
1061 common = [repo.lookup(rev) for rev in base]
1062 heads = revs and map(repo.lookup, revs) or revs
1062 heads = revs and map(repo.lookup, revs) or revs
1063 cg = repo.getbundle('bundle', heads=heads, common=common)
1063 cg = repo.getbundle('bundle', heads=heads, common=common)
1064 outgoing = None
1064 outgoing = None
1065 else:
1065 else:
1066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1067 dest, branches = hg.parseurl(dest, opts.get('branch'))
1067 dest, branches = hg.parseurl(dest, opts.get('branch'))
1068 other = hg.peer(repo, opts, dest)
1068 other = hg.peer(repo, opts, dest)
1069 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1069 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1070 heads = revs and map(repo.lookup, revs) or revs
1070 heads = revs and map(repo.lookup, revs) or revs
1071 outgoing = discovery.findcommonoutgoing(repo, other,
1071 outgoing = discovery.findcommonoutgoing(repo, other,
1072 onlyheads=heads,
1072 onlyheads=heads,
1073 force=opts.get('force'),
1073 force=opts.get('force'),
1074 portable=True)
1074 portable=True)
1075 cg = repo.getlocalbundle('bundle', outgoing)
1075 cg = repo.getlocalbundle('bundle', outgoing)
1076 if not cg:
1076 if not cg:
1077 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1077 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1078 return 1
1078 return 1
1079
1079
1080 changegroup.writebundle(cg, fname, bundletype)
1080 changegroup.writebundle(cg, fname, bundletype)
1081
1081
1082 @command('cat',
1082 @command('cat',
1083 [('o', 'output', '',
1083 [('o', 'output', '',
1084 _('print output to file with formatted name'), _('FORMAT')),
1084 _('print output to file with formatted name'), _('FORMAT')),
1085 ('r', 'rev', '', _('print the given revision'), _('REV')),
1085 ('r', 'rev', '', _('print the given revision'), _('REV')),
1086 ('', 'decode', None, _('apply any matching decode filter')),
1086 ('', 'decode', None, _('apply any matching decode filter')),
1087 ] + walkopts,
1087 ] + walkopts,
1088 _('[OPTION]... FILE...'))
1088 _('[OPTION]... FILE...'))
1089 def cat(ui, repo, file1, *pats, **opts):
1089 def cat(ui, repo, file1, *pats, **opts):
1090 """output the current or given revision of files
1090 """output the current or given revision of files
1091
1091
1092 Print the specified files as they were at the given revision. If
1092 Print the specified files as they were at the given revision. If
1093 no revision is given, the parent of the working directory is used,
1093 no revision is given, the parent of the working directory is used,
1094 or tip if no revision is checked out.
1094 or tip if no revision is checked out.
1095
1095
1096 Output may be to a file, in which case the name of the file is
1096 Output may be to a file, in which case the name of the file is
1097 given using a format string. The formatting rules are the same as
1097 given using a format string. The formatting rules are the same as
1098 for the export command, with the following additions:
1098 for the export command, with the following additions:
1099
1099
1100 :``%s``: basename of file being printed
1100 :``%s``: basename of file being printed
1101 :``%d``: dirname of file being printed, or '.' if in repository root
1101 :``%d``: dirname of file being printed, or '.' if in repository root
1102 :``%p``: root-relative path name of file being printed
1102 :``%p``: root-relative path name of file being printed
1103
1103
1104 Returns 0 on success.
1104 Returns 0 on success.
1105 """
1105 """
1106 ctx = scmutil.revsingle(repo, opts.get('rev'))
1106 ctx = scmutil.revsingle(repo, opts.get('rev'))
1107 err = 1
1107 err = 1
1108 m = scmutil.match(ctx, (file1,) + pats, opts)
1108 m = scmutil.match(ctx, (file1,) + pats, opts)
1109 for abs in ctx.walk(m):
1109 for abs in ctx.walk(m):
1110 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1110 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1111 pathname=abs)
1111 pathname=abs)
1112 data = ctx[abs].data()
1112 data = ctx[abs].data()
1113 if opts.get('decode'):
1113 if opts.get('decode'):
1114 data = repo.wwritedata(abs, data)
1114 data = repo.wwritedata(abs, data)
1115 fp.write(data)
1115 fp.write(data)
1116 fp.close()
1116 fp.close()
1117 err = 0
1117 err = 0
1118 return err
1118 return err
1119
1119
1120 @command('^clone',
1120 @command('^clone',
1121 [('U', 'noupdate', None,
1121 [('U', 'noupdate', None,
1122 _('the clone will include an empty working copy (only a repository)')),
1122 _('the clone will include an empty working copy (only a repository)')),
1123 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1123 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1124 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1124 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1125 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1125 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1126 ('', 'pull', None, _('use pull protocol to copy metadata')),
1126 ('', 'pull', None, _('use pull protocol to copy metadata')),
1127 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1127 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1128 ] + remoteopts,
1128 ] + remoteopts,
1129 _('[OPTION]... SOURCE [DEST]'))
1129 _('[OPTION]... SOURCE [DEST]'))
1130 def clone(ui, source, dest=None, **opts):
1130 def clone(ui, source, dest=None, **opts):
1131 """make a copy of an existing repository
1131 """make a copy of an existing repository
1132
1132
1133 Create a copy of an existing repository in a new directory.
1133 Create a copy of an existing repository in a new directory.
1134
1134
1135 If no destination directory name is specified, it defaults to the
1135 If no destination directory name is specified, it defaults to the
1136 basename of the source.
1136 basename of the source.
1137
1137
1138 The location of the source is added to the new repository's
1138 The location of the source is added to the new repository's
1139 ``.hg/hgrc`` file, as the default to be used for future pulls.
1139 ``.hg/hgrc`` file, as the default to be used for future pulls.
1140
1140
1141 Only local paths and ``ssh://`` URLs are supported as
1141 Only local paths and ``ssh://`` URLs are supported as
1142 destinations. For ``ssh://`` destinations, no working directory or
1142 destinations. For ``ssh://`` destinations, no working directory or
1143 ``.hg/hgrc`` will be created on the remote side.
1143 ``.hg/hgrc`` will be created on the remote side.
1144
1144
1145 To pull only a subset of changesets, specify one or more revisions
1145 To pull only a subset of changesets, specify one or more revisions
1146 identifiers with -r/--rev or branches with -b/--branch. The
1146 identifiers with -r/--rev or branches with -b/--branch. The
1147 resulting clone will contain only the specified changesets and
1147 resulting clone will contain only the specified changesets and
1148 their ancestors. These options (or 'clone src#rev dest') imply
1148 their ancestors. These options (or 'clone src#rev dest') imply
1149 --pull, even for local source repositories. Note that specifying a
1149 --pull, even for local source repositories. Note that specifying a
1150 tag will include the tagged changeset but not the changeset
1150 tag will include the tagged changeset but not the changeset
1151 containing the tag.
1151 containing the tag.
1152
1152
1153 If the source repository has a bookmark called '@' set, that
1153 If the source repository has a bookmark called '@' set, that
1154 revision will be checked out in the new repository by default.
1154 revision will be checked out in the new repository by default.
1155
1155
1156 To check out a particular version, use -u/--update, or
1156 To check out a particular version, use -u/--update, or
1157 -U/--noupdate to create a clone with no working directory.
1157 -U/--noupdate to create a clone with no working directory.
1158
1158
1159 .. container:: verbose
1159 .. container:: verbose
1160
1160
1161 For efficiency, hardlinks are used for cloning whenever the
1161 For efficiency, hardlinks are used for cloning whenever the
1162 source and destination are on the same filesystem (note this
1162 source and destination are on the same filesystem (note this
1163 applies only to the repository data, not to the working
1163 applies only to the repository data, not to the working
1164 directory). Some filesystems, such as AFS, implement hardlinking
1164 directory). Some filesystems, such as AFS, implement hardlinking
1165 incorrectly, but do not report errors. In these cases, use the
1165 incorrectly, but do not report errors. In these cases, use the
1166 --pull option to avoid hardlinking.
1166 --pull option to avoid hardlinking.
1167
1167
1168 In some cases, you can clone repositories and the working
1168 In some cases, you can clone repositories and the working
1169 directory using full hardlinks with ::
1169 directory using full hardlinks with ::
1170
1170
1171 $ cp -al REPO REPOCLONE
1171 $ cp -al REPO REPOCLONE
1172
1172
1173 This is the fastest way to clone, but it is not always safe. The
1173 This is the fastest way to clone, but it is not always safe. The
1174 operation is not atomic (making sure REPO is not modified during
1174 operation is not atomic (making sure REPO is not modified during
1175 the operation is up to you) and you have to make sure your
1175 the operation is up to you) and you have to make sure your
1176 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1176 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1177 so). Also, this is not compatible with certain extensions that
1177 so). Also, this is not compatible with certain extensions that
1178 place their metadata under the .hg directory, such as mq.
1178 place their metadata under the .hg directory, such as mq.
1179
1179
1180 Mercurial will update the working directory to the first applicable
1180 Mercurial will update the working directory to the first applicable
1181 revision from this list:
1181 revision from this list:
1182
1182
1183 a) null if -U or the source repository has no changesets
1183 a) null if -U or the source repository has no changesets
1184 b) if -u . and the source repository is local, the first parent of
1184 b) if -u . and the source repository is local, the first parent of
1185 the source repository's working directory
1185 the source repository's working directory
1186 c) the changeset specified with -u (if a branch name, this means the
1186 c) the changeset specified with -u (if a branch name, this means the
1187 latest head of that branch)
1187 latest head of that branch)
1188 d) the changeset specified with -r
1188 d) the changeset specified with -r
1189 e) the tipmost head specified with -b
1189 e) the tipmost head specified with -b
1190 f) the tipmost head specified with the url#branch source syntax
1190 f) the tipmost head specified with the url#branch source syntax
1191 g) the revision marked with the '@' bookmark, if present
1191 g) the revision marked with the '@' bookmark, if present
1192 h) the tipmost head of the default branch
1192 h) the tipmost head of the default branch
1193 i) tip
1193 i) tip
1194
1194
1195 Examples:
1195 Examples:
1196
1196
1197 - clone a remote repository to a new directory named hg/::
1197 - clone a remote repository to a new directory named hg/::
1198
1198
1199 hg clone http://selenic.com/hg
1199 hg clone http://selenic.com/hg
1200
1200
1201 - create a lightweight local clone::
1201 - create a lightweight local clone::
1202
1202
1203 hg clone project/ project-feature/
1203 hg clone project/ project-feature/
1204
1204
1205 - clone from an absolute path on an ssh server (note double-slash)::
1205 - clone from an absolute path on an ssh server (note double-slash)::
1206
1206
1207 hg clone ssh://user@server//home/projects/alpha/
1207 hg clone ssh://user@server//home/projects/alpha/
1208
1208
1209 - do a high-speed clone over a LAN while checking out a
1209 - do a high-speed clone over a LAN while checking out a
1210 specified version::
1210 specified version::
1211
1211
1212 hg clone --uncompressed http://server/repo -u 1.5
1212 hg clone --uncompressed http://server/repo -u 1.5
1213
1213
1214 - create a repository without changesets after a particular revision::
1214 - create a repository without changesets after a particular revision::
1215
1215
1216 hg clone -r 04e544 experimental/ good/
1216 hg clone -r 04e544 experimental/ good/
1217
1217
1218 - clone (and track) a particular named branch::
1218 - clone (and track) a particular named branch::
1219
1219
1220 hg clone http://selenic.com/hg#stable
1220 hg clone http://selenic.com/hg#stable
1221
1221
1222 See :hg:`help urls` for details on specifying URLs.
1222 See :hg:`help urls` for details on specifying URLs.
1223
1223
1224 Returns 0 on success.
1224 Returns 0 on success.
1225 """
1225 """
1226 if opts.get('noupdate') and opts.get('updaterev'):
1226 if opts.get('noupdate') and opts.get('updaterev'):
1227 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1227 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1228
1228
1229 r = hg.clone(ui, opts, source, dest,
1229 r = hg.clone(ui, opts, source, dest,
1230 pull=opts.get('pull'),
1230 pull=opts.get('pull'),
1231 stream=opts.get('uncompressed'),
1231 stream=opts.get('uncompressed'),
1232 rev=opts.get('rev'),
1232 rev=opts.get('rev'),
1233 update=opts.get('updaterev') or not opts.get('noupdate'),
1233 update=opts.get('updaterev') or not opts.get('noupdate'),
1234 branch=opts.get('branch'))
1234 branch=opts.get('branch'))
1235
1235
1236 return r is None
1236 return r is None
1237
1237
1238 @command('^commit|ci',
1238 @command('^commit|ci',
1239 [('A', 'addremove', None,
1239 [('A', 'addremove', None,
1240 _('mark new/missing files as added/removed before committing')),
1240 _('mark new/missing files as added/removed before committing')),
1241 ('', 'close-branch', None,
1241 ('', 'close-branch', None,
1242 _('mark a branch as closed, hiding it from the branch list')),
1242 _('mark a branch as closed, hiding it from the branch list')),
1243 ('', 'amend', None, _('amend the parent of the working dir')),
1243 ('', 'amend', None, _('amend the parent of the working dir')),
1244 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1244 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1245 _('[OPTION]... [FILE]...'))
1245 _('[OPTION]... [FILE]...'))
1246 def commit(ui, repo, *pats, **opts):
1246 def commit(ui, repo, *pats, **opts):
1247 """commit the specified files or all outstanding changes
1247 """commit the specified files or all outstanding changes
1248
1248
1249 Commit changes to the given files into the repository. Unlike a
1249 Commit changes to the given files into the repository. Unlike a
1250 centralized SCM, this operation is a local operation. See
1250 centralized SCM, this operation is a local operation. See
1251 :hg:`push` for a way to actively distribute your changes.
1251 :hg:`push` for a way to actively distribute your changes.
1252
1252
1253 If a list of files is omitted, all changes reported by :hg:`status`
1253 If a list of files is omitted, all changes reported by :hg:`status`
1254 will be committed.
1254 will be committed.
1255
1255
1256 If you are committing the result of a merge, do not provide any
1256 If you are committing the result of a merge, do not provide any
1257 filenames or -I/-X filters.
1257 filenames or -I/-X filters.
1258
1258
1259 If no commit message is specified, Mercurial starts your
1259 If no commit message is specified, Mercurial starts your
1260 configured editor where you can enter a message. In case your
1260 configured editor where you can enter a message. In case your
1261 commit fails, you will find a backup of your message in
1261 commit fails, you will find a backup of your message in
1262 ``.hg/last-message.txt``.
1262 ``.hg/last-message.txt``.
1263
1263
1264 The --amend flag can be used to amend the parent of the
1264 The --amend flag can be used to amend the parent of the
1265 working directory with a new commit that contains the changes
1265 working directory with a new commit that contains the changes
1266 in the parent in addition to those currently reported by :hg:`status`,
1266 in the parent in addition to those currently reported by :hg:`status`,
1267 if there are any. The old commit is stored in a backup bundle in
1267 if there are any. The old commit is stored in a backup bundle in
1268 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1268 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1269 on how to restore it).
1269 on how to restore it).
1270
1270
1271 Message, user and date are taken from the amended commit unless
1271 Message, user and date are taken from the amended commit unless
1272 specified. When a message isn't specified on the command line,
1272 specified. When a message isn't specified on the command line,
1273 the editor will open with the message of the amended commit.
1273 the editor will open with the message of the amended commit.
1274
1274
1275 It is not possible to amend public changesets (see :hg:`help phases`)
1275 It is not possible to amend public changesets (see :hg:`help phases`)
1276 or changesets that have children.
1276 or changesets that have children.
1277
1277
1278 See :hg:`help dates` for a list of formats valid for -d/--date.
1278 See :hg:`help dates` for a list of formats valid for -d/--date.
1279
1279
1280 Returns 0 on success, 1 if nothing changed.
1280 Returns 0 on success, 1 if nothing changed.
1281 """
1281 """
1282 if opts.get('subrepos'):
1282 if opts.get('subrepos'):
1283 # Let --subrepos on the command line override config setting.
1283 # Let --subrepos on the command line override config setting.
1284 ui.setconfig('ui', 'commitsubrepos', True)
1284 ui.setconfig('ui', 'commitsubrepos', True)
1285
1285
1286 extra = {}
1286 extra = {}
1287 if opts.get('close_branch'):
1287 if opts.get('close_branch'):
1288 if repo['.'].node() not in repo.branchheads():
1288 if repo['.'].node() not in repo.branchheads():
1289 # The topo heads set is included in the branch heads set of the
1289 # The topo heads set is included in the branch heads set of the
1290 # current branch, so it's sufficient to test branchheads
1290 # current branch, so it's sufficient to test branchheads
1291 raise util.Abort(_('can only close branch heads'))
1291 raise util.Abort(_('can only close branch heads'))
1292 extra['close'] = 1
1292 extra['close'] = 1
1293
1293
1294 branch = repo[None].branch()
1294 branch = repo[None].branch()
1295 bheads = repo.branchheads(branch)
1295 bheads = repo.branchheads(branch)
1296
1296
1297 if opts.get('amend'):
1297 if opts.get('amend'):
1298 if ui.configbool('ui', 'commitsubrepos'):
1298 if ui.configbool('ui', 'commitsubrepos'):
1299 raise util.Abort(_('cannot amend recursively'))
1299 raise util.Abort(_('cannot amend recursively'))
1300
1300
1301 old = repo['.']
1301 old = repo['.']
1302 if old.phase() == phases.public:
1302 if old.phase() == phases.public:
1303 raise util.Abort(_('cannot amend public changesets'))
1303 raise util.Abort(_('cannot amend public changesets'))
1304 if len(old.parents()) > 1:
1304 if len(old.parents()) > 1:
1305 raise util.Abort(_('cannot amend merge changesets'))
1305 raise util.Abort(_('cannot amend merge changesets'))
1306 if len(repo[None].parents()) > 1:
1306 if len(repo[None].parents()) > 1:
1307 raise util.Abort(_('cannot amend while merging'))
1307 raise util.Abort(_('cannot amend while merging'))
1308 if (not obsolete._enabled) and old.children():
1308 if (not obsolete._enabled) and old.children():
1309 raise util.Abort(_('cannot amend changeset with children'))
1309 raise util.Abort(_('cannot amend changeset with children'))
1310
1310
1311 e = cmdutil.commiteditor
1311 e = cmdutil.commiteditor
1312 if opts.get('force_editor'):
1312 if opts.get('force_editor'):
1313 e = cmdutil.commitforceeditor
1313 e = cmdutil.commitforceeditor
1314
1314
1315 def commitfunc(ui, repo, message, match, opts):
1315 def commitfunc(ui, repo, message, match, opts):
1316 editor = e
1316 editor = e
1317 # message contains text from -m or -l, if it's empty,
1317 # message contains text from -m or -l, if it's empty,
1318 # open the editor with the old message
1318 # open the editor with the old message
1319 if not message:
1319 if not message:
1320 message = old.description()
1320 message = old.description()
1321 editor = cmdutil.commitforceeditor
1321 editor = cmdutil.commitforceeditor
1322 return repo.commit(message,
1322 return repo.commit(message,
1323 opts.get('user') or old.user(),
1323 opts.get('user') or old.user(),
1324 opts.get('date') or old.date(),
1324 opts.get('date') or old.date(),
1325 match,
1325 match,
1326 editor=editor,
1326 editor=editor,
1327 extra=extra)
1327 extra=extra)
1328
1328
1329 current = repo._bookmarkcurrent
1329 current = repo._bookmarkcurrent
1330 marks = old.bookmarks()
1330 marks = old.bookmarks()
1331 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1331 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1332 if node == old.node():
1332 if node == old.node():
1333 ui.status(_("nothing changed\n"))
1333 ui.status(_("nothing changed\n"))
1334 return 1
1334 return 1
1335 elif marks:
1335 elif marks:
1336 ui.debug('moving bookmarks %r from %s to %s\n' %
1336 ui.debug('moving bookmarks %r from %s to %s\n' %
1337 (marks, old.hex(), hex(node)))
1337 (marks, old.hex(), hex(node)))
1338 newmarks = repo._bookmarks
1338 newmarks = repo._bookmarks
1339 for bm in marks:
1339 for bm in marks:
1340 newmarks[bm] = node
1340 newmarks[bm] = node
1341 if bm == current:
1341 if bm == current:
1342 bookmarks.setcurrent(repo, bm)
1342 bookmarks.setcurrent(repo, bm)
1343 newmarks.write()
1343 newmarks.write()
1344 else:
1344 else:
1345 e = cmdutil.commiteditor
1345 e = cmdutil.commiteditor
1346 if opts.get('force_editor'):
1346 if opts.get('force_editor'):
1347 e = cmdutil.commitforceeditor
1347 e = cmdutil.commitforceeditor
1348
1348
1349 def commitfunc(ui, repo, message, match, opts):
1349 def commitfunc(ui, repo, message, match, opts):
1350 return repo.commit(message, opts.get('user'), opts.get('date'),
1350 return repo.commit(message, opts.get('user'), opts.get('date'),
1351 match, editor=e, extra=extra)
1351 match, editor=e, extra=extra)
1352
1352
1353 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1353 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1354
1354
1355 if not node:
1355 if not node:
1356 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1356 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1357 if stat[3]:
1357 if stat[3]:
1358 ui.status(_("nothing changed (%d missing files, see "
1358 ui.status(_("nothing changed (%d missing files, see "
1359 "'hg status')\n") % len(stat[3]))
1359 "'hg status')\n") % len(stat[3]))
1360 else:
1360 else:
1361 ui.status(_("nothing changed\n"))
1361 ui.status(_("nothing changed\n"))
1362 return 1
1362 return 1
1363
1363
1364 ctx = repo[node]
1364 ctx = repo[node]
1365 parents = ctx.parents()
1365 parents = ctx.parents()
1366
1366
1367 if (not opts.get('amend') and bheads and node not in bheads and not
1367 if (not opts.get('amend') and bheads and node not in bheads and not
1368 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1368 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1369 ui.status(_('created new head\n'))
1369 ui.status(_('created new head\n'))
1370 # The message is not printed for initial roots. For the other
1370 # The message is not printed for initial roots. For the other
1371 # changesets, it is printed in the following situations:
1371 # changesets, it is printed in the following situations:
1372 #
1372 #
1373 # Par column: for the 2 parents with ...
1373 # Par column: for the 2 parents with ...
1374 # N: null or no parent
1374 # N: null or no parent
1375 # B: parent is on another named branch
1375 # B: parent is on another named branch
1376 # C: parent is a regular non head changeset
1376 # C: parent is a regular non head changeset
1377 # H: parent was a branch head of the current branch
1377 # H: parent was a branch head of the current branch
1378 # Msg column: whether we print "created new head" message
1378 # Msg column: whether we print "created new head" message
1379 # In the following, it is assumed that there already exists some
1379 # In the following, it is assumed that there already exists some
1380 # initial branch heads of the current branch, otherwise nothing is
1380 # initial branch heads of the current branch, otherwise nothing is
1381 # printed anyway.
1381 # printed anyway.
1382 #
1382 #
1383 # Par Msg Comment
1383 # Par Msg Comment
1384 # N N y additional topo root
1384 # N N y additional topo root
1385 #
1385 #
1386 # B N y additional branch root
1386 # B N y additional branch root
1387 # C N y additional topo head
1387 # C N y additional topo head
1388 # H N n usual case
1388 # H N n usual case
1389 #
1389 #
1390 # B B y weird additional branch root
1390 # B B y weird additional branch root
1391 # C B y branch merge
1391 # C B y branch merge
1392 # H B n merge with named branch
1392 # H B n merge with named branch
1393 #
1393 #
1394 # C C y additional head from merge
1394 # C C y additional head from merge
1395 # C H n merge with a head
1395 # C H n merge with a head
1396 #
1396 #
1397 # H H n head merge: head count decreases
1397 # H H n head merge: head count decreases
1398
1398
1399 if not opts.get('close_branch'):
1399 if not opts.get('close_branch'):
1400 for r in parents:
1400 for r in parents:
1401 if r.closesbranch() and r.branch() == branch:
1401 if r.closesbranch() and r.branch() == branch:
1402 ui.status(_('reopening closed branch head %d\n') % r)
1402 ui.status(_('reopening closed branch head %d\n') % r)
1403
1403
1404 if ui.debugflag:
1404 if ui.debugflag:
1405 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1405 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1406 elif ui.verbose:
1406 elif ui.verbose:
1407 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1407 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1408
1408
1409 @command('copy|cp',
1409 @command('copy|cp',
1410 [('A', 'after', None, _('record a copy that has already occurred')),
1410 [('A', 'after', None, _('record a copy that has already occurred')),
1411 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1411 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1412 ] + walkopts + dryrunopts,
1412 ] + walkopts + dryrunopts,
1413 _('[OPTION]... [SOURCE]... DEST'))
1413 _('[OPTION]... [SOURCE]... DEST'))
1414 def copy(ui, repo, *pats, **opts):
1414 def copy(ui, repo, *pats, **opts):
1415 """mark files as copied for the next commit
1415 """mark files as copied for the next commit
1416
1416
1417 Mark dest as having copies of source files. If dest is a
1417 Mark dest as having copies of source files. If dest is a
1418 directory, copies are put in that directory. If dest is a file,
1418 directory, copies are put in that directory. If dest is a file,
1419 the source must be a single file.
1419 the source must be a single file.
1420
1420
1421 By default, this command copies the contents of files as they
1421 By default, this command copies the contents of files as they
1422 exist in the working directory. If invoked with -A/--after, the
1422 exist in the working directory. If invoked with -A/--after, the
1423 operation is recorded, but no copying is performed.
1423 operation is recorded, but no copying is performed.
1424
1424
1425 This command takes effect with the next commit. To undo a copy
1425 This command takes effect with the next commit. To undo a copy
1426 before that, see :hg:`revert`.
1426 before that, see :hg:`revert`.
1427
1427
1428 Returns 0 on success, 1 if errors are encountered.
1428 Returns 0 on success, 1 if errors are encountered.
1429 """
1429 """
1430 wlock = repo.wlock(False)
1430 wlock = repo.wlock(False)
1431 try:
1431 try:
1432 return cmdutil.copy(ui, repo, pats, opts)
1432 return cmdutil.copy(ui, repo, pats, opts)
1433 finally:
1433 finally:
1434 wlock.release()
1434 wlock.release()
1435
1435
1436 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1436 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1437 def debugancestor(ui, repo, *args):
1437 def debugancestor(ui, repo, *args):
1438 """find the ancestor revision of two revisions in a given index"""
1438 """find the ancestor revision of two revisions in a given index"""
1439 if len(args) == 3:
1439 if len(args) == 3:
1440 index, rev1, rev2 = args
1440 index, rev1, rev2 = args
1441 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1441 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1442 lookup = r.lookup
1442 lookup = r.lookup
1443 elif len(args) == 2:
1443 elif len(args) == 2:
1444 if not repo:
1444 if not repo:
1445 raise util.Abort(_("there is no Mercurial repository here "
1445 raise util.Abort(_("there is no Mercurial repository here "
1446 "(.hg not found)"))
1446 "(.hg not found)"))
1447 rev1, rev2 = args
1447 rev1, rev2 = args
1448 r = repo.changelog
1448 r = repo.changelog
1449 lookup = repo.lookup
1449 lookup = repo.lookup
1450 else:
1450 else:
1451 raise util.Abort(_('either two or three arguments required'))
1451 raise util.Abort(_('either two or three arguments required'))
1452 a = r.ancestor(lookup(rev1), lookup(rev2))
1452 a = r.ancestor(lookup(rev1), lookup(rev2))
1453 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1453 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1454
1454
1455 @command('debugbuilddag',
1455 @command('debugbuilddag',
1456 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1456 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1457 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1457 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1458 ('n', 'new-file', None, _('add new file at each rev'))],
1458 ('n', 'new-file', None, _('add new file at each rev'))],
1459 _('[OPTION]... [TEXT]'))
1459 _('[OPTION]... [TEXT]'))
1460 def debugbuilddag(ui, repo, text=None,
1460 def debugbuilddag(ui, repo, text=None,
1461 mergeable_file=False,
1461 mergeable_file=False,
1462 overwritten_file=False,
1462 overwritten_file=False,
1463 new_file=False):
1463 new_file=False):
1464 """builds a repo with a given DAG from scratch in the current empty repo
1464 """builds a repo with a given DAG from scratch in the current empty repo
1465
1465
1466 The description of the DAG is read from stdin if not given on the
1466 The description of the DAG is read from stdin if not given on the
1467 command line.
1467 command line.
1468
1468
1469 Elements:
1469 Elements:
1470
1470
1471 - "+n" is a linear run of n nodes based on the current default parent
1471 - "+n" is a linear run of n nodes based on the current default parent
1472 - "." is a single node based on the current default parent
1472 - "." is a single node based on the current default parent
1473 - "$" resets the default parent to null (implied at the start);
1473 - "$" resets the default parent to null (implied at the start);
1474 otherwise the default parent is always the last node created
1474 otherwise the default parent is always the last node created
1475 - "<p" sets the default parent to the backref p
1475 - "<p" sets the default parent to the backref p
1476 - "*p" is a fork at parent p, which is a backref
1476 - "*p" is a fork at parent p, which is a backref
1477 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1477 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1478 - "/p2" is a merge of the preceding node and p2
1478 - "/p2" is a merge of the preceding node and p2
1479 - ":tag" defines a local tag for the preceding node
1479 - ":tag" defines a local tag for the preceding node
1480 - "@branch" sets the named branch for subsequent nodes
1480 - "@branch" sets the named branch for subsequent nodes
1481 - "#...\\n" is a comment up to the end of the line
1481 - "#...\\n" is a comment up to the end of the line
1482
1482
1483 Whitespace between the above elements is ignored.
1483 Whitespace between the above elements is ignored.
1484
1484
1485 A backref is either
1485 A backref is either
1486
1486
1487 - a number n, which references the node curr-n, where curr is the current
1487 - a number n, which references the node curr-n, where curr is the current
1488 node, or
1488 node, or
1489 - the name of a local tag you placed earlier using ":tag", or
1489 - the name of a local tag you placed earlier using ":tag", or
1490 - empty to denote the default parent.
1490 - empty to denote the default parent.
1491
1491
1492 All string valued-elements are either strictly alphanumeric, or must
1492 All string valued-elements are either strictly alphanumeric, or must
1493 be enclosed in double quotes ("..."), with "\\" as escape character.
1493 be enclosed in double quotes ("..."), with "\\" as escape character.
1494 """
1494 """
1495
1495
1496 if text is None:
1496 if text is None:
1497 ui.status(_("reading DAG from stdin\n"))
1497 ui.status(_("reading DAG from stdin\n"))
1498 text = ui.fin.read()
1498 text = ui.fin.read()
1499
1499
1500 cl = repo.changelog
1500 cl = repo.changelog
1501 if len(cl) > 0:
1501 if len(cl) > 0:
1502 raise util.Abort(_('repository is not empty'))
1502 raise util.Abort(_('repository is not empty'))
1503
1503
1504 # determine number of revs in DAG
1504 # determine number of revs in DAG
1505 total = 0
1505 total = 0
1506 for type, data in dagparser.parsedag(text):
1506 for type, data in dagparser.parsedag(text):
1507 if type == 'n':
1507 if type == 'n':
1508 total += 1
1508 total += 1
1509
1509
1510 if mergeable_file:
1510 if mergeable_file:
1511 linesperrev = 2
1511 linesperrev = 2
1512 # make a file with k lines per rev
1512 # make a file with k lines per rev
1513 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1513 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1514 initialmergedlines.append("")
1514 initialmergedlines.append("")
1515
1515
1516 tags = []
1516 tags = []
1517
1517
1518 lock = tr = None
1518 lock = tr = None
1519 try:
1519 try:
1520 lock = repo.lock()
1520 lock = repo.lock()
1521 tr = repo.transaction("builddag")
1521 tr = repo.transaction("builddag")
1522
1522
1523 at = -1
1523 at = -1
1524 atbranch = 'default'
1524 atbranch = 'default'
1525 nodeids = []
1525 nodeids = []
1526 id = 0
1526 id = 0
1527 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1527 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1528 for type, data in dagparser.parsedag(text):
1528 for type, data in dagparser.parsedag(text):
1529 if type == 'n':
1529 if type == 'n':
1530 ui.note(('node %s\n' % str(data)))
1530 ui.note(('node %s\n' % str(data)))
1531 id, ps = data
1531 id, ps = data
1532
1532
1533 files = []
1533 files = []
1534 fctxs = {}
1534 fctxs = {}
1535
1535
1536 p2 = None
1536 p2 = None
1537 if mergeable_file:
1537 if mergeable_file:
1538 fn = "mf"
1538 fn = "mf"
1539 p1 = repo[ps[0]]
1539 p1 = repo[ps[0]]
1540 if len(ps) > 1:
1540 if len(ps) > 1:
1541 p2 = repo[ps[1]]
1541 p2 = repo[ps[1]]
1542 pa = p1.ancestor(p2)
1542 pa = p1.ancestor(p2)
1543 base, local, other = [x[fn].data() for x in (pa, p1,
1543 base, local, other = [x[fn].data() for x in (pa, p1,
1544 p2)]
1544 p2)]
1545 m3 = simplemerge.Merge3Text(base, local, other)
1545 m3 = simplemerge.Merge3Text(base, local, other)
1546 ml = [l.strip() for l in m3.merge_lines()]
1546 ml = [l.strip() for l in m3.merge_lines()]
1547 ml.append("")
1547 ml.append("")
1548 elif at > 0:
1548 elif at > 0:
1549 ml = p1[fn].data().split("\n")
1549 ml = p1[fn].data().split("\n")
1550 else:
1550 else:
1551 ml = initialmergedlines
1551 ml = initialmergedlines
1552 ml[id * linesperrev] += " r%i" % id
1552 ml[id * linesperrev] += " r%i" % id
1553 mergedtext = "\n".join(ml)
1553 mergedtext = "\n".join(ml)
1554 files.append(fn)
1554 files.append(fn)
1555 fctxs[fn] = context.memfilectx(fn, mergedtext)
1555 fctxs[fn] = context.memfilectx(fn, mergedtext)
1556
1556
1557 if overwritten_file:
1557 if overwritten_file:
1558 fn = "of"
1558 fn = "of"
1559 files.append(fn)
1559 files.append(fn)
1560 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1560 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1561
1561
1562 if new_file:
1562 if new_file:
1563 fn = "nf%i" % id
1563 fn = "nf%i" % id
1564 files.append(fn)
1564 files.append(fn)
1565 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1565 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1566 if len(ps) > 1:
1566 if len(ps) > 1:
1567 if not p2:
1567 if not p2:
1568 p2 = repo[ps[1]]
1568 p2 = repo[ps[1]]
1569 for fn in p2:
1569 for fn in p2:
1570 if fn.startswith("nf"):
1570 if fn.startswith("nf"):
1571 files.append(fn)
1571 files.append(fn)
1572 fctxs[fn] = p2[fn]
1572 fctxs[fn] = p2[fn]
1573
1573
1574 def fctxfn(repo, cx, path):
1574 def fctxfn(repo, cx, path):
1575 return fctxs.get(path)
1575 return fctxs.get(path)
1576
1576
1577 if len(ps) == 0 or ps[0] < 0:
1577 if len(ps) == 0 or ps[0] < 0:
1578 pars = [None, None]
1578 pars = [None, None]
1579 elif len(ps) == 1:
1579 elif len(ps) == 1:
1580 pars = [nodeids[ps[0]], None]
1580 pars = [nodeids[ps[0]], None]
1581 else:
1581 else:
1582 pars = [nodeids[p] for p in ps]
1582 pars = [nodeids[p] for p in ps]
1583 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1583 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1584 date=(id, 0),
1584 date=(id, 0),
1585 user="debugbuilddag",
1585 user="debugbuilddag",
1586 extra={'branch': atbranch})
1586 extra={'branch': atbranch})
1587 nodeid = repo.commitctx(cx)
1587 nodeid = repo.commitctx(cx)
1588 nodeids.append(nodeid)
1588 nodeids.append(nodeid)
1589 at = id
1589 at = id
1590 elif type == 'l':
1590 elif type == 'l':
1591 id, name = data
1591 id, name = data
1592 ui.note(('tag %s\n' % name))
1592 ui.note(('tag %s\n' % name))
1593 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1593 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1594 elif type == 'a':
1594 elif type == 'a':
1595 ui.note(('branch %s\n' % data))
1595 ui.note(('branch %s\n' % data))
1596 atbranch = data
1596 atbranch = data
1597 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1597 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1598 tr.close()
1598 tr.close()
1599
1599
1600 if tags:
1600 if tags:
1601 repo.opener.write("localtags", "".join(tags))
1601 repo.opener.write("localtags", "".join(tags))
1602 finally:
1602 finally:
1603 ui.progress(_('building'), None)
1603 ui.progress(_('building'), None)
1604 release(tr, lock)
1604 release(tr, lock)
1605
1605
1606 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1606 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1607 def debugbundle(ui, bundlepath, all=None, **opts):
1607 def debugbundle(ui, bundlepath, all=None, **opts):
1608 """lists the contents of a bundle"""
1608 """lists the contents of a bundle"""
1609 f = hg.openpath(ui, bundlepath)
1609 f = hg.openpath(ui, bundlepath)
1610 try:
1610 try:
1611 gen = changegroup.readbundle(f, bundlepath)
1611 gen = changegroup.readbundle(f, bundlepath)
1612 if all:
1612 if all:
1613 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1613 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1614
1614
1615 def showchunks(named):
1615 def showchunks(named):
1616 ui.write("\n%s\n" % named)
1616 ui.write("\n%s\n" % named)
1617 chain = None
1617 chain = None
1618 while True:
1618 while True:
1619 chunkdata = gen.deltachunk(chain)
1619 chunkdata = gen.deltachunk(chain)
1620 if not chunkdata:
1620 if not chunkdata:
1621 break
1621 break
1622 node = chunkdata['node']
1622 node = chunkdata['node']
1623 p1 = chunkdata['p1']
1623 p1 = chunkdata['p1']
1624 p2 = chunkdata['p2']
1624 p2 = chunkdata['p2']
1625 cs = chunkdata['cs']
1625 cs = chunkdata['cs']
1626 deltabase = chunkdata['deltabase']
1626 deltabase = chunkdata['deltabase']
1627 delta = chunkdata['delta']
1627 delta = chunkdata['delta']
1628 ui.write("%s %s %s %s %s %s\n" %
1628 ui.write("%s %s %s %s %s %s\n" %
1629 (hex(node), hex(p1), hex(p2),
1629 (hex(node), hex(p1), hex(p2),
1630 hex(cs), hex(deltabase), len(delta)))
1630 hex(cs), hex(deltabase), len(delta)))
1631 chain = node
1631 chain = node
1632
1632
1633 chunkdata = gen.changelogheader()
1633 chunkdata = gen.changelogheader()
1634 showchunks("changelog")
1634 showchunks("changelog")
1635 chunkdata = gen.manifestheader()
1635 chunkdata = gen.manifestheader()
1636 showchunks("manifest")
1636 showchunks("manifest")
1637 while True:
1637 while True:
1638 chunkdata = gen.filelogheader()
1638 chunkdata = gen.filelogheader()
1639 if not chunkdata:
1639 if not chunkdata:
1640 break
1640 break
1641 fname = chunkdata['filename']
1641 fname = chunkdata['filename']
1642 showchunks(fname)
1642 showchunks(fname)
1643 else:
1643 else:
1644 chunkdata = gen.changelogheader()
1644 chunkdata = gen.changelogheader()
1645 chain = None
1645 chain = None
1646 while True:
1646 while True:
1647 chunkdata = gen.deltachunk(chain)
1647 chunkdata = gen.deltachunk(chain)
1648 if not chunkdata:
1648 if not chunkdata:
1649 break
1649 break
1650 node = chunkdata['node']
1650 node = chunkdata['node']
1651 ui.write("%s\n" % hex(node))
1651 ui.write("%s\n" % hex(node))
1652 chain = node
1652 chain = node
1653 finally:
1653 finally:
1654 f.close()
1654 f.close()
1655
1655
1656 @command('debugcheckstate', [], '')
1656 @command('debugcheckstate', [], '')
1657 def debugcheckstate(ui, repo):
1657 def debugcheckstate(ui, repo):
1658 """validate the correctness of the current dirstate"""
1658 """validate the correctness of the current dirstate"""
1659 parent1, parent2 = repo.dirstate.parents()
1659 parent1, parent2 = repo.dirstate.parents()
1660 m1 = repo[parent1].manifest()
1660 m1 = repo[parent1].manifest()
1661 m2 = repo[parent2].manifest()
1661 m2 = repo[parent2].manifest()
1662 errors = 0
1662 errors = 0
1663 for f in repo.dirstate:
1663 for f in repo.dirstate:
1664 state = repo.dirstate[f]
1664 state = repo.dirstate[f]
1665 if state in "nr" and f not in m1:
1665 if state in "nr" and f not in m1:
1666 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1666 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1667 errors += 1
1667 errors += 1
1668 if state in "a" and f in m1:
1668 if state in "a" and f in m1:
1669 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1669 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1670 errors += 1
1670 errors += 1
1671 if state in "m" and f not in m1 and f not in m2:
1671 if state in "m" and f not in m1 and f not in m2:
1672 ui.warn(_("%s in state %s, but not in either manifest\n") %
1672 ui.warn(_("%s in state %s, but not in either manifest\n") %
1673 (f, state))
1673 (f, state))
1674 errors += 1
1674 errors += 1
1675 for f in m1:
1675 for f in m1:
1676 state = repo.dirstate[f]
1676 state = repo.dirstate[f]
1677 if state not in "nrm":
1677 if state not in "nrm":
1678 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1678 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1679 errors += 1
1679 errors += 1
1680 if errors:
1680 if errors:
1681 error = _(".hg/dirstate inconsistent with current parent's manifest")
1681 error = _(".hg/dirstate inconsistent with current parent's manifest")
1682 raise util.Abort(error)
1682 raise util.Abort(error)
1683
1683
1684 @command('debugcommands', [], _('[COMMAND]'))
1684 @command('debugcommands', [], _('[COMMAND]'))
1685 def debugcommands(ui, cmd='', *args):
1685 def debugcommands(ui, cmd='', *args):
1686 """list all available commands and options"""
1686 """list all available commands and options"""
1687 for cmd, vals in sorted(table.iteritems()):
1687 for cmd, vals in sorted(table.iteritems()):
1688 cmd = cmd.split('|')[0].strip('^')
1688 cmd = cmd.split('|')[0].strip('^')
1689 opts = ', '.join([i[1] for i in vals[1]])
1689 opts = ', '.join([i[1] for i in vals[1]])
1690 ui.write('%s: %s\n' % (cmd, opts))
1690 ui.write('%s: %s\n' % (cmd, opts))
1691
1691
1692 @command('debugcomplete',
1692 @command('debugcomplete',
1693 [('o', 'options', None, _('show the command options'))],
1693 [('o', 'options', None, _('show the command options'))],
1694 _('[-o] CMD'))
1694 _('[-o] CMD'))
1695 def debugcomplete(ui, cmd='', **opts):
1695 def debugcomplete(ui, cmd='', **opts):
1696 """returns the completion list associated with the given command"""
1696 """returns the completion list associated with the given command"""
1697
1697
1698 if opts.get('options'):
1698 if opts.get('options'):
1699 options = []
1699 options = []
1700 otables = [globalopts]
1700 otables = [globalopts]
1701 if cmd:
1701 if cmd:
1702 aliases, entry = cmdutil.findcmd(cmd, table, False)
1702 aliases, entry = cmdutil.findcmd(cmd, table, False)
1703 otables.append(entry[1])
1703 otables.append(entry[1])
1704 for t in otables:
1704 for t in otables:
1705 for o in t:
1705 for o in t:
1706 if "(DEPRECATED)" in o[3]:
1706 if "(DEPRECATED)" in o[3]:
1707 continue
1707 continue
1708 if o[0]:
1708 if o[0]:
1709 options.append('-%s' % o[0])
1709 options.append('-%s' % o[0])
1710 options.append('--%s' % o[1])
1710 options.append('--%s' % o[1])
1711 ui.write("%s\n" % "\n".join(options))
1711 ui.write("%s\n" % "\n".join(options))
1712 return
1712 return
1713
1713
1714 cmdlist = cmdutil.findpossible(cmd, table)
1714 cmdlist = cmdutil.findpossible(cmd, table)
1715 if ui.verbose:
1715 if ui.verbose:
1716 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1716 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1717 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1717 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1718
1718
1719 @command('debugdag',
1719 @command('debugdag',
1720 [('t', 'tags', None, _('use tags as labels')),
1720 [('t', 'tags', None, _('use tags as labels')),
1721 ('b', 'branches', None, _('annotate with branch names')),
1721 ('b', 'branches', None, _('annotate with branch names')),
1722 ('', 'dots', None, _('use dots for runs')),
1722 ('', 'dots', None, _('use dots for runs')),
1723 ('s', 'spaces', None, _('separate elements by spaces'))],
1723 ('s', 'spaces', None, _('separate elements by spaces'))],
1724 _('[OPTION]... [FILE [REV]...]'))
1724 _('[OPTION]... [FILE [REV]...]'))
1725 def debugdag(ui, repo, file_=None, *revs, **opts):
1725 def debugdag(ui, repo, file_=None, *revs, **opts):
1726 """format the changelog or an index DAG as a concise textual description
1726 """format the changelog or an index DAG as a concise textual description
1727
1727
1728 If you pass a revlog index, the revlog's DAG is emitted. If you list
1728 If you pass a revlog index, the revlog's DAG is emitted. If you list
1729 revision numbers, they get labeled in the output as rN.
1729 revision numbers, they get labeled in the output as rN.
1730
1730
1731 Otherwise, the changelog DAG of the current repo is emitted.
1731 Otherwise, the changelog DAG of the current repo is emitted.
1732 """
1732 """
1733 spaces = opts.get('spaces')
1733 spaces = opts.get('spaces')
1734 dots = opts.get('dots')
1734 dots = opts.get('dots')
1735 if file_:
1735 if file_:
1736 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1736 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1737 revs = set((int(r) for r in revs))
1737 revs = set((int(r) for r in revs))
1738 def events():
1738 def events():
1739 for r in rlog:
1739 for r in rlog:
1740 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1740 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1741 if p != -1)))
1741 if p != -1)))
1742 if r in revs:
1742 if r in revs:
1743 yield 'l', (r, "r%i" % r)
1743 yield 'l', (r, "r%i" % r)
1744 elif repo:
1744 elif repo:
1745 cl = repo.changelog
1745 cl = repo.changelog
1746 tags = opts.get('tags')
1746 tags = opts.get('tags')
1747 branches = opts.get('branches')
1747 branches = opts.get('branches')
1748 if tags:
1748 if tags:
1749 labels = {}
1749 labels = {}
1750 for l, n in repo.tags().items():
1750 for l, n in repo.tags().items():
1751 labels.setdefault(cl.rev(n), []).append(l)
1751 labels.setdefault(cl.rev(n), []).append(l)
1752 def events():
1752 def events():
1753 b = "default"
1753 b = "default"
1754 for r in cl:
1754 for r in cl:
1755 if branches:
1755 if branches:
1756 newb = cl.read(cl.node(r))[5]['branch']
1756 newb = cl.read(cl.node(r))[5]['branch']
1757 if newb != b:
1757 if newb != b:
1758 yield 'a', newb
1758 yield 'a', newb
1759 b = newb
1759 b = newb
1760 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1760 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1761 if p != -1)))
1761 if p != -1)))
1762 if tags:
1762 if tags:
1763 ls = labels.get(r)
1763 ls = labels.get(r)
1764 if ls:
1764 if ls:
1765 for l in ls:
1765 for l in ls:
1766 yield 'l', (r, l)
1766 yield 'l', (r, l)
1767 else:
1767 else:
1768 raise util.Abort(_('need repo for changelog dag'))
1768 raise util.Abort(_('need repo for changelog dag'))
1769
1769
1770 for line in dagparser.dagtextlines(events(),
1770 for line in dagparser.dagtextlines(events(),
1771 addspaces=spaces,
1771 addspaces=spaces,
1772 wraplabels=True,
1772 wraplabels=True,
1773 wrapannotations=True,
1773 wrapannotations=True,
1774 wrapnonlinear=dots,
1774 wrapnonlinear=dots,
1775 usedots=dots,
1775 usedots=dots,
1776 maxlinewidth=70):
1776 maxlinewidth=70):
1777 ui.write(line)
1777 ui.write(line)
1778 ui.write("\n")
1778 ui.write("\n")
1779
1779
1780 @command('debugdata',
1780 @command('debugdata',
1781 [('c', 'changelog', False, _('open changelog')),
1781 [('c', 'changelog', False, _('open changelog')),
1782 ('m', 'manifest', False, _('open manifest'))],
1782 ('m', 'manifest', False, _('open manifest'))],
1783 _('-c|-m|FILE REV'))
1783 _('-c|-m|FILE REV'))
1784 def debugdata(ui, repo, file_, rev = None, **opts):
1784 def debugdata(ui, repo, file_, rev = None, **opts):
1785 """dump the contents of a data file revision"""
1785 """dump the contents of a data file revision"""
1786 if opts.get('changelog') or opts.get('manifest'):
1786 if opts.get('changelog') or opts.get('manifest'):
1787 file_, rev = None, file_
1787 file_, rev = None, file_
1788 elif rev is None:
1788 elif rev is None:
1789 raise error.CommandError('debugdata', _('invalid arguments'))
1789 raise error.CommandError('debugdata', _('invalid arguments'))
1790 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1790 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1791 try:
1791 try:
1792 ui.write(r.revision(r.lookup(rev)))
1792 ui.write(r.revision(r.lookup(rev)))
1793 except KeyError:
1793 except KeyError:
1794 raise util.Abort(_('invalid revision identifier %s') % rev)
1794 raise util.Abort(_('invalid revision identifier %s') % rev)
1795
1795
1796 @command('debugdate',
1796 @command('debugdate',
1797 [('e', 'extended', None, _('try extended date formats'))],
1797 [('e', 'extended', None, _('try extended date formats'))],
1798 _('[-e] DATE [RANGE]'))
1798 _('[-e] DATE [RANGE]'))
1799 def debugdate(ui, date, range=None, **opts):
1799 def debugdate(ui, date, range=None, **opts):
1800 """parse and display a date"""
1800 """parse and display a date"""
1801 if opts["extended"]:
1801 if opts["extended"]:
1802 d = util.parsedate(date, util.extendeddateformats)
1802 d = util.parsedate(date, util.extendeddateformats)
1803 else:
1803 else:
1804 d = util.parsedate(date)
1804 d = util.parsedate(date)
1805 ui.write(("internal: %s %s\n") % d)
1805 ui.write(("internal: %s %s\n") % d)
1806 ui.write(("standard: %s\n") % util.datestr(d))
1806 ui.write(("standard: %s\n") % util.datestr(d))
1807 if range:
1807 if range:
1808 m = util.matchdate(range)
1808 m = util.matchdate(range)
1809 ui.write(("match: %s\n") % m(d[0]))
1809 ui.write(("match: %s\n") % m(d[0]))
1810
1810
1811 @command('debugdiscovery',
1811 @command('debugdiscovery',
1812 [('', 'old', None, _('use old-style discovery')),
1812 [('', 'old', None, _('use old-style discovery')),
1813 ('', 'nonheads', None,
1813 ('', 'nonheads', None,
1814 _('use old-style discovery with non-heads included')),
1814 _('use old-style discovery with non-heads included')),
1815 ] + remoteopts,
1815 ] + remoteopts,
1816 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1816 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1817 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1817 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1818 """runs the changeset discovery protocol in isolation"""
1818 """runs the changeset discovery protocol in isolation"""
1819 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1819 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1820 opts.get('branch'))
1820 opts.get('branch'))
1821 remote = hg.peer(repo, opts, remoteurl)
1821 remote = hg.peer(repo, opts, remoteurl)
1822 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1822 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1823
1823
1824 # make sure tests are repeatable
1824 # make sure tests are repeatable
1825 random.seed(12323)
1825 random.seed(12323)
1826
1826
1827 def doit(localheads, remoteheads, remote=remote):
1827 def doit(localheads, remoteheads, remote=remote):
1828 if opts.get('old'):
1828 if opts.get('old'):
1829 if localheads:
1829 if localheads:
1830 raise util.Abort('cannot use localheads with old style '
1830 raise util.Abort('cannot use localheads with old style '
1831 'discovery')
1831 'discovery')
1832 if not util.safehasattr(remote, 'branches'):
1832 if not util.safehasattr(remote, 'branches'):
1833 # enable in-client legacy support
1833 # enable in-client legacy support
1834 remote = localrepo.locallegacypeer(remote.local())
1834 remote = localrepo.locallegacypeer(remote.local())
1835 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1835 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1836 force=True)
1836 force=True)
1837 common = set(common)
1837 common = set(common)
1838 if not opts.get('nonheads'):
1838 if not opts.get('nonheads'):
1839 ui.write(("unpruned common: %s\n") %
1839 ui.write(("unpruned common: %s\n") %
1840 " ".join(sorted(short(n) for n in common)))
1840 " ".join(sorted(short(n) for n in common)))
1841 dag = dagutil.revlogdag(repo.changelog)
1841 dag = dagutil.revlogdag(repo.changelog)
1842 all = dag.ancestorset(dag.internalizeall(common))
1842 all = dag.ancestorset(dag.internalizeall(common))
1843 common = dag.externalizeall(dag.headsetofconnecteds(all))
1843 common = dag.externalizeall(dag.headsetofconnecteds(all))
1844 else:
1844 else:
1845 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1845 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1846 common = set(common)
1846 common = set(common)
1847 rheads = set(hds)
1847 rheads = set(hds)
1848 lheads = set(repo.heads())
1848 lheads = set(repo.heads())
1849 ui.write(("common heads: %s\n") %
1849 ui.write(("common heads: %s\n") %
1850 " ".join(sorted(short(n) for n in common)))
1850 " ".join(sorted(short(n) for n in common)))
1851 if lheads <= common:
1851 if lheads <= common:
1852 ui.write(("local is subset\n"))
1852 ui.write(("local is subset\n"))
1853 elif rheads <= common:
1853 elif rheads <= common:
1854 ui.write(("remote is subset\n"))
1854 ui.write(("remote is subset\n"))
1855
1855
1856 serverlogs = opts.get('serverlog')
1856 serverlogs = opts.get('serverlog')
1857 if serverlogs:
1857 if serverlogs:
1858 for filename in serverlogs:
1858 for filename in serverlogs:
1859 logfile = open(filename, 'r')
1859 logfile = open(filename, 'r')
1860 try:
1860 try:
1861 line = logfile.readline()
1861 line = logfile.readline()
1862 while line:
1862 while line:
1863 parts = line.strip().split(';')
1863 parts = line.strip().split(';')
1864 op = parts[1]
1864 op = parts[1]
1865 if op == 'cg':
1865 if op == 'cg':
1866 pass
1866 pass
1867 elif op == 'cgss':
1867 elif op == 'cgss':
1868 doit(parts[2].split(' '), parts[3].split(' '))
1868 doit(parts[2].split(' '), parts[3].split(' '))
1869 elif op == 'unb':
1869 elif op == 'unb':
1870 doit(parts[3].split(' '), parts[2].split(' '))
1870 doit(parts[3].split(' '), parts[2].split(' '))
1871 line = logfile.readline()
1871 line = logfile.readline()
1872 finally:
1872 finally:
1873 logfile.close()
1873 logfile.close()
1874
1874
1875 else:
1875 else:
1876 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1876 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1877 opts.get('remote_head'))
1877 opts.get('remote_head'))
1878 localrevs = opts.get('local_head')
1878 localrevs = opts.get('local_head')
1879 doit(localrevs, remoterevs)
1879 doit(localrevs, remoterevs)
1880
1880
1881 @command('debugfileset',
1881 @command('debugfileset',
1882 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1882 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1883 _('[-r REV] FILESPEC'))
1883 _('[-r REV] FILESPEC'))
1884 def debugfileset(ui, repo, expr, **opts):
1884 def debugfileset(ui, repo, expr, **opts):
1885 '''parse and apply a fileset specification'''
1885 '''parse and apply a fileset specification'''
1886 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1886 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1887 if ui.verbose:
1887 if ui.verbose:
1888 tree = fileset.parse(expr)[0]
1888 tree = fileset.parse(expr)[0]
1889 ui.note(tree, "\n")
1889 ui.note(tree, "\n")
1890
1890
1891 for f in fileset.getfileset(ctx, expr):
1891 for f in fileset.getfileset(ctx, expr):
1892 ui.write("%s\n" % f)
1892 ui.write("%s\n" % f)
1893
1893
1894 @command('debugfsinfo', [], _('[PATH]'))
1894 @command('debugfsinfo', [], _('[PATH]'))
1895 def debugfsinfo(ui, path = "."):
1895 def debugfsinfo(ui, path = "."):
1896 """show information detected about current filesystem"""
1896 """show information detected about current filesystem"""
1897 util.writefile('.debugfsinfo', '')
1897 util.writefile('.debugfsinfo', '')
1898 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1898 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1899 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1899 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1900 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1900 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1901 and 'yes' or 'no'))
1901 and 'yes' or 'no'))
1902 os.unlink('.debugfsinfo')
1902 os.unlink('.debugfsinfo')
1903
1903
1904 @command('debuggetbundle',
1904 @command('debuggetbundle',
1905 [('H', 'head', [], _('id of head node'), _('ID')),
1905 [('H', 'head', [], _('id of head node'), _('ID')),
1906 ('C', 'common', [], _('id of common node'), _('ID')),
1906 ('C', 'common', [], _('id of common node'), _('ID')),
1907 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1907 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1908 _('REPO FILE [-H|-C ID]...'))
1908 _('REPO FILE [-H|-C ID]...'))
1909 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1909 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1910 """retrieves a bundle from a repo
1910 """retrieves a bundle from a repo
1911
1911
1912 Every ID must be a full-length hex node id string. Saves the bundle to the
1912 Every ID must be a full-length hex node id string. Saves the bundle to the
1913 given file.
1913 given file.
1914 """
1914 """
1915 repo = hg.peer(ui, opts, repopath)
1915 repo = hg.peer(ui, opts, repopath)
1916 if not repo.capable('getbundle'):
1916 if not repo.capable('getbundle'):
1917 raise util.Abort("getbundle() not supported by target repository")
1917 raise util.Abort("getbundle() not supported by target repository")
1918 args = {}
1918 args = {}
1919 if common:
1919 if common:
1920 args['common'] = [bin(s) for s in common]
1920 args['common'] = [bin(s) for s in common]
1921 if head:
1921 if head:
1922 args['heads'] = [bin(s) for s in head]
1922 args['heads'] = [bin(s) for s in head]
1923 bundle = repo.getbundle('debug', **args)
1923 bundle = repo.getbundle('debug', **args)
1924
1924
1925 bundletype = opts.get('type', 'bzip2').lower()
1925 bundletype = opts.get('type', 'bzip2').lower()
1926 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1926 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1927 bundletype = btypes.get(bundletype)
1927 bundletype = btypes.get(bundletype)
1928 if bundletype not in changegroup.bundletypes:
1928 if bundletype not in changegroup.bundletypes:
1929 raise util.Abort(_('unknown bundle type specified with --type'))
1929 raise util.Abort(_('unknown bundle type specified with --type'))
1930 changegroup.writebundle(bundle, bundlepath, bundletype)
1930 changegroup.writebundle(bundle, bundlepath, bundletype)
1931
1931
1932 @command('debugignore', [], '')
1932 @command('debugignore', [], '')
1933 def debugignore(ui, repo, *values, **opts):
1933 def debugignore(ui, repo, *values, **opts):
1934 """display the combined ignore pattern"""
1934 """display the combined ignore pattern"""
1935 ignore = repo.dirstate._ignore
1935 ignore = repo.dirstate._ignore
1936 includepat = getattr(ignore, 'includepat', None)
1936 includepat = getattr(ignore, 'includepat', None)
1937 if includepat is not None:
1937 if includepat is not None:
1938 ui.write("%s\n" % includepat)
1938 ui.write("%s\n" % includepat)
1939 else:
1939 else:
1940 raise util.Abort(_("no ignore patterns found"))
1940 raise util.Abort(_("no ignore patterns found"))
1941
1941
1942 @command('debugindex',
1942 @command('debugindex',
1943 [('c', 'changelog', False, _('open changelog')),
1943 [('c', 'changelog', False, _('open changelog')),
1944 ('m', 'manifest', False, _('open manifest')),
1944 ('m', 'manifest', False, _('open manifest')),
1945 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1945 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1946 _('[-f FORMAT] -c|-m|FILE'))
1946 _('[-f FORMAT] -c|-m|FILE'))
1947 def debugindex(ui, repo, file_ = None, **opts):
1947 def debugindex(ui, repo, file_ = None, **opts):
1948 """dump the contents of an index file"""
1948 """dump the contents of an index file"""
1949 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1949 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1950 format = opts.get('format', 0)
1950 format = opts.get('format', 0)
1951 if format not in (0, 1):
1951 if format not in (0, 1):
1952 raise util.Abort(_("unknown format %d") % format)
1952 raise util.Abort(_("unknown format %d") % format)
1953
1953
1954 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1954 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1955 if generaldelta:
1955 if generaldelta:
1956 basehdr = ' delta'
1956 basehdr = ' delta'
1957 else:
1957 else:
1958 basehdr = ' base'
1958 basehdr = ' base'
1959
1959
1960 if format == 0:
1960 if format == 0:
1961 ui.write(" rev offset length " + basehdr + " linkrev"
1961 ui.write(" rev offset length " + basehdr + " linkrev"
1962 " nodeid p1 p2\n")
1962 " nodeid p1 p2\n")
1963 elif format == 1:
1963 elif format == 1:
1964 ui.write(" rev flag offset length"
1964 ui.write(" rev flag offset length"
1965 " size " + basehdr + " link p1 p2"
1965 " size " + basehdr + " link p1 p2"
1966 " nodeid\n")
1966 " nodeid\n")
1967
1967
1968 for i in r:
1968 for i in r:
1969 node = r.node(i)
1969 node = r.node(i)
1970 if generaldelta:
1970 if generaldelta:
1971 base = r.deltaparent(i)
1971 base = r.deltaparent(i)
1972 else:
1972 else:
1973 base = r.chainbase(i)
1973 base = r.chainbase(i)
1974 if format == 0:
1974 if format == 0:
1975 try:
1975 try:
1976 pp = r.parents(node)
1976 pp = r.parents(node)
1977 except Exception:
1977 except Exception:
1978 pp = [nullid, nullid]
1978 pp = [nullid, nullid]
1979 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1979 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1980 i, r.start(i), r.length(i), base, r.linkrev(i),
1980 i, r.start(i), r.length(i), base, r.linkrev(i),
1981 short(node), short(pp[0]), short(pp[1])))
1981 short(node), short(pp[0]), short(pp[1])))
1982 elif format == 1:
1982 elif format == 1:
1983 pr = r.parentrevs(i)
1983 pr = r.parentrevs(i)
1984 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1984 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1985 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1985 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1986 base, r.linkrev(i), pr[0], pr[1], short(node)))
1986 base, r.linkrev(i), pr[0], pr[1], short(node)))
1987
1987
1988 @command('debugindexdot', [], _('FILE'))
1988 @command('debugindexdot', [], _('FILE'))
1989 def debugindexdot(ui, repo, file_):
1989 def debugindexdot(ui, repo, file_):
1990 """dump an index DAG as a graphviz dot file"""
1990 """dump an index DAG as a graphviz dot file"""
1991 r = None
1991 r = None
1992 if repo:
1992 if repo:
1993 filelog = repo.file(file_)
1993 filelog = repo.file(file_)
1994 if len(filelog):
1994 if len(filelog):
1995 r = filelog
1995 r = filelog
1996 if not r:
1996 if not r:
1997 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1997 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1998 ui.write(("digraph G {\n"))
1998 ui.write(("digraph G {\n"))
1999 for i in r:
1999 for i in r:
2000 node = r.node(i)
2000 node = r.node(i)
2001 pp = r.parents(node)
2001 pp = r.parents(node)
2002 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2002 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2003 if pp[1] != nullid:
2003 if pp[1] != nullid:
2004 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2004 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2005 ui.write("}\n")
2005 ui.write("}\n")
2006
2006
2007 @command('debuginstall', [], '')
2007 @command('debuginstall', [], '')
2008 def debuginstall(ui):
2008 def debuginstall(ui):
2009 '''test Mercurial installation
2009 '''test Mercurial installation
2010
2010
2011 Returns 0 on success.
2011 Returns 0 on success.
2012 '''
2012 '''
2013
2013
2014 def writetemp(contents):
2014 def writetemp(contents):
2015 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2015 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2016 f = os.fdopen(fd, "wb")
2016 f = os.fdopen(fd, "wb")
2017 f.write(contents)
2017 f.write(contents)
2018 f.close()
2018 f.close()
2019 return name
2019 return name
2020
2020
2021 problems = 0
2021 problems = 0
2022
2022
2023 # encoding
2023 # encoding
2024 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2024 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2025 try:
2025 try:
2026 encoding.fromlocal("test")
2026 encoding.fromlocal("test")
2027 except util.Abort, inst:
2027 except util.Abort, inst:
2028 ui.write(" %s\n" % inst)
2028 ui.write(" %s\n" % inst)
2029 ui.write(_(" (check that your locale is properly set)\n"))
2029 ui.write(_(" (check that your locale is properly set)\n"))
2030 problems += 1
2030 problems += 1
2031
2031
2032 # Python lib
2032 # Python lib
2033 ui.status(_("checking Python lib (%s)...\n")
2033 ui.status(_("checking Python lib (%s)...\n")
2034 % os.path.dirname(os.__file__))
2034 % os.path.dirname(os.__file__))
2035
2035
2036 # compiled modules
2036 # compiled modules
2037 ui.status(_("checking installed modules (%s)...\n")
2037 ui.status(_("checking installed modules (%s)...\n")
2038 % os.path.dirname(__file__))
2038 % os.path.dirname(__file__))
2039 try:
2039 try:
2040 import bdiff, mpatch, base85, osutil
2040 import bdiff, mpatch, base85, osutil
2041 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2041 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2042 except Exception, inst:
2042 except Exception, inst:
2043 ui.write(" %s\n" % inst)
2043 ui.write(" %s\n" % inst)
2044 ui.write(_(" One or more extensions could not be found"))
2044 ui.write(_(" One or more extensions could not be found"))
2045 ui.write(_(" (check that you compiled the extensions)\n"))
2045 ui.write(_(" (check that you compiled the extensions)\n"))
2046 problems += 1
2046 problems += 1
2047
2047
2048 # templates
2048 # templates
2049 import templater
2049 import templater
2050 p = templater.templatepath()
2050 p = templater.templatepath()
2051 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2051 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2052 try:
2052 try:
2053 templater.templater(templater.templatepath("map-cmdline.default"))
2053 templater.templater(templater.templatepath("map-cmdline.default"))
2054 except Exception, inst:
2054 except Exception, inst:
2055 ui.write(" %s\n" % inst)
2055 ui.write(" %s\n" % inst)
2056 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2056 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2057 problems += 1
2057 problems += 1
2058
2058
2059 # editor
2059 # editor
2060 ui.status(_("checking commit editor...\n"))
2060 ui.status(_("checking commit editor...\n"))
2061 editor = ui.geteditor()
2061 editor = ui.geteditor()
2062 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2062 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2063 if not cmdpath:
2063 if not cmdpath:
2064 if editor == 'vi':
2064 if editor == 'vi':
2065 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2065 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2066 ui.write(_(" (specify a commit editor in your configuration"
2066 ui.write(_(" (specify a commit editor in your configuration"
2067 " file)\n"))
2067 " file)\n"))
2068 else:
2068 else:
2069 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2069 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2070 ui.write(_(" (specify a commit editor in your configuration"
2070 ui.write(_(" (specify a commit editor in your configuration"
2071 " file)\n"))
2071 " file)\n"))
2072 problems += 1
2072 problems += 1
2073
2073
2074 # check username
2074 # check username
2075 ui.status(_("checking username...\n"))
2075 ui.status(_("checking username...\n"))
2076 try:
2076 try:
2077 ui.username()
2077 ui.username()
2078 except util.Abort, e:
2078 except util.Abort, e:
2079 ui.write(" %s\n" % e)
2079 ui.write(" %s\n" % e)
2080 ui.write(_(" (specify a username in your configuration file)\n"))
2080 ui.write(_(" (specify a username in your configuration file)\n"))
2081 problems += 1
2081 problems += 1
2082
2082
2083 if not problems:
2083 if not problems:
2084 ui.status(_("no problems detected\n"))
2084 ui.status(_("no problems detected\n"))
2085 else:
2085 else:
2086 ui.write(_("%s problems detected,"
2086 ui.write(_("%s problems detected,"
2087 " please check your install!\n") % problems)
2087 " please check your install!\n") % problems)
2088
2088
2089 return problems
2089 return problems
2090
2090
2091 @command('debugknown', [], _('REPO ID...'))
2091 @command('debugknown', [], _('REPO ID...'))
2092 def debugknown(ui, repopath, *ids, **opts):
2092 def debugknown(ui, repopath, *ids, **opts):
2093 """test whether node ids are known to a repo
2093 """test whether node ids are known to a repo
2094
2094
2095 Every ID must be a full-length hex node id string. Returns a list of 0s
2095 Every ID must be a full-length hex node id string. Returns a list of 0s
2096 and 1s indicating unknown/known.
2096 and 1s indicating unknown/known.
2097 """
2097 """
2098 repo = hg.peer(ui, opts, repopath)
2098 repo = hg.peer(ui, opts, repopath)
2099 if not repo.capable('known'):
2099 if not repo.capable('known'):
2100 raise util.Abort("known() not supported by target repository")
2100 raise util.Abort("known() not supported by target repository")
2101 flags = repo.known([bin(s) for s in ids])
2101 flags = repo.known([bin(s) for s in ids])
2102 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2102 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2103
2103
2104 @command('debugobsolete',
2104 @command('debugobsolete',
2105 [('', 'flags', 0, _('markers flag')),
2105 [('', 'flags', 0, _('markers flag')),
2106 ] + commitopts2,
2106 ] + commitopts2,
2107 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2107 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2108 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2108 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2109 """create arbitrary obsolete marker"""
2109 """create arbitrary obsolete marker"""
2110 def parsenodeid(s):
2110 def parsenodeid(s):
2111 try:
2111 try:
2112 # We do not use revsingle/revrange functions here to accept
2112 # We do not use revsingle/revrange functions here to accept
2113 # arbitrary node identifiers, possibly not present in the
2113 # arbitrary node identifiers, possibly not present in the
2114 # local repository.
2114 # local repository.
2115 n = bin(s)
2115 n = bin(s)
2116 if len(n) != len(nullid):
2116 if len(n) != len(nullid):
2117 raise TypeError()
2117 raise TypeError()
2118 return n
2118 return n
2119 except TypeError:
2119 except TypeError:
2120 raise util.Abort('changeset references must be full hexadecimal '
2120 raise util.Abort('changeset references must be full hexadecimal '
2121 'node identifiers')
2121 'node identifiers')
2122
2122
2123 if precursor is not None:
2123 if precursor is not None:
2124 metadata = {}
2124 metadata = {}
2125 if 'date' in opts:
2125 if 'date' in opts:
2126 metadata['date'] = opts['date']
2126 metadata['date'] = opts['date']
2127 metadata['user'] = opts['user'] or ui.username()
2127 metadata['user'] = opts['user'] or ui.username()
2128 succs = tuple(parsenodeid(succ) for succ in successors)
2128 succs = tuple(parsenodeid(succ) for succ in successors)
2129 l = repo.lock()
2129 l = repo.lock()
2130 try:
2130 try:
2131 tr = repo.transaction('debugobsolete')
2131 tr = repo.transaction('debugobsolete')
2132 try:
2132 try:
2133 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2133 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2134 opts['flags'], metadata)
2134 opts['flags'], metadata)
2135 tr.close()
2135 tr.close()
2136 finally:
2136 finally:
2137 tr.release()
2137 tr.release()
2138 finally:
2138 finally:
2139 l.release()
2139 l.release()
2140 else:
2140 else:
2141 for m in obsolete.allmarkers(repo):
2141 for m in obsolete.allmarkers(repo):
2142 ui.write(hex(m.precnode()))
2142 ui.write(hex(m.precnode()))
2143 for repl in m.succnodes():
2143 for repl in m.succnodes():
2144 ui.write(' ')
2144 ui.write(' ')
2145 ui.write(hex(repl))
2145 ui.write(hex(repl))
2146 ui.write(' %X ' % m._data[2])
2146 ui.write(' %X ' % m._data[2])
2147 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2147 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2148 sorted(m.metadata().items()))))
2148 sorted(m.metadata().items()))))
2149 ui.write('\n')
2149 ui.write('\n')
2150
2150
2151 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2151 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2152 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2152 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2153 '''access the pushkey key/value protocol
2153 '''access the pushkey key/value protocol
2154
2154
2155 With two args, list the keys in the given namespace.
2155 With two args, list the keys in the given namespace.
2156
2156
2157 With five args, set a key to new if it currently is set to old.
2157 With five args, set a key to new if it currently is set to old.
2158 Reports success or failure.
2158 Reports success or failure.
2159 '''
2159 '''
2160
2160
2161 target = hg.peer(ui, {}, repopath)
2161 target = hg.peer(ui, {}, repopath)
2162 if keyinfo:
2162 if keyinfo:
2163 key, old, new = keyinfo
2163 key, old, new = keyinfo
2164 r = target.pushkey(namespace, key, old, new)
2164 r = target.pushkey(namespace, key, old, new)
2165 ui.status(str(r) + '\n')
2165 ui.status(str(r) + '\n')
2166 return not r
2166 return not r
2167 else:
2167 else:
2168 for k, v in sorted(target.listkeys(namespace).iteritems()):
2168 for k, v in sorted(target.listkeys(namespace).iteritems()):
2169 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2169 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2170 v.encode('string-escape')))
2170 v.encode('string-escape')))
2171
2171
2172 @command('debugpvec', [], _('A B'))
2172 @command('debugpvec', [], _('A B'))
2173 def debugpvec(ui, repo, a, b=None):
2173 def debugpvec(ui, repo, a, b=None):
2174 ca = scmutil.revsingle(repo, a)
2174 ca = scmutil.revsingle(repo, a)
2175 cb = scmutil.revsingle(repo, b)
2175 cb = scmutil.revsingle(repo, b)
2176 pa = pvec.ctxpvec(ca)
2176 pa = pvec.ctxpvec(ca)
2177 pb = pvec.ctxpvec(cb)
2177 pb = pvec.ctxpvec(cb)
2178 if pa == pb:
2178 if pa == pb:
2179 rel = "="
2179 rel = "="
2180 elif pa > pb:
2180 elif pa > pb:
2181 rel = ">"
2181 rel = ">"
2182 elif pa < pb:
2182 elif pa < pb:
2183 rel = "<"
2183 rel = "<"
2184 elif pa | pb:
2184 elif pa | pb:
2185 rel = "|"
2185 rel = "|"
2186 ui.write(_("a: %s\n") % pa)
2186 ui.write(_("a: %s\n") % pa)
2187 ui.write(_("b: %s\n") % pb)
2187 ui.write(_("b: %s\n") % pb)
2188 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2188 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2189 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2189 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2190 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2190 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2191 pa.distance(pb), rel))
2191 pa.distance(pb), rel))
2192
2192
2193 @command('debugrebuildstate',
2193 @command('debugrebuildstate',
2194 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2194 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2195 _('[-r REV] [REV]'))
2195 _('[-r REV] [REV]'))
2196 def debugrebuildstate(ui, repo, rev="tip"):
2196 def debugrebuildstate(ui, repo, rev="tip"):
2197 """rebuild the dirstate as it would look like for the given revision"""
2197 """rebuild the dirstate as it would look like for the given revision"""
2198 ctx = scmutil.revsingle(repo, rev)
2198 ctx = scmutil.revsingle(repo, rev)
2199 wlock = repo.wlock()
2199 wlock = repo.wlock()
2200 try:
2200 try:
2201 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2201 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2202 finally:
2202 finally:
2203 wlock.release()
2203 wlock.release()
2204
2204
2205 @command('debugrename',
2205 @command('debugrename',
2206 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2206 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2207 _('[-r REV] FILE'))
2207 _('[-r REV] FILE'))
2208 def debugrename(ui, repo, file1, *pats, **opts):
2208 def debugrename(ui, repo, file1, *pats, **opts):
2209 """dump rename information"""
2209 """dump rename information"""
2210
2210
2211 ctx = scmutil.revsingle(repo, opts.get('rev'))
2211 ctx = scmutil.revsingle(repo, opts.get('rev'))
2212 m = scmutil.match(ctx, (file1,) + pats, opts)
2212 m = scmutil.match(ctx, (file1,) + pats, opts)
2213 for abs in ctx.walk(m):
2213 for abs in ctx.walk(m):
2214 fctx = ctx[abs]
2214 fctx = ctx[abs]
2215 o = fctx.filelog().renamed(fctx.filenode())
2215 o = fctx.filelog().renamed(fctx.filenode())
2216 rel = m.rel(abs)
2216 rel = m.rel(abs)
2217 if o:
2217 if o:
2218 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2218 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2219 else:
2219 else:
2220 ui.write(_("%s not renamed\n") % rel)
2220 ui.write(_("%s not renamed\n") % rel)
2221
2221
2222 @command('debugrevlog',
2222 @command('debugrevlog',
2223 [('c', 'changelog', False, _('open changelog')),
2223 [('c', 'changelog', False, _('open changelog')),
2224 ('m', 'manifest', False, _('open manifest')),
2224 ('m', 'manifest', False, _('open manifest')),
2225 ('d', 'dump', False, _('dump index data'))],
2225 ('d', 'dump', False, _('dump index data'))],
2226 _('-c|-m|FILE'))
2226 _('-c|-m|FILE'))
2227 def debugrevlog(ui, repo, file_ = None, **opts):
2227 def debugrevlog(ui, repo, file_ = None, **opts):
2228 """show data and statistics about a revlog"""
2228 """show data and statistics about a revlog"""
2229 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2229 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2230
2230
2231 if opts.get("dump"):
2231 if opts.get("dump"):
2232 numrevs = len(r)
2232 numrevs = len(r)
2233 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2233 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2234 " rawsize totalsize compression heads\n")
2234 " rawsize totalsize compression heads\n")
2235 ts = 0
2235 ts = 0
2236 heads = set()
2236 heads = set()
2237 for rev in xrange(numrevs):
2237 for rev in xrange(numrevs):
2238 dbase = r.deltaparent(rev)
2238 dbase = r.deltaparent(rev)
2239 if dbase == -1:
2239 if dbase == -1:
2240 dbase = rev
2240 dbase = rev
2241 cbase = r.chainbase(rev)
2241 cbase = r.chainbase(rev)
2242 p1, p2 = r.parentrevs(rev)
2242 p1, p2 = r.parentrevs(rev)
2243 rs = r.rawsize(rev)
2243 rs = r.rawsize(rev)
2244 ts = ts + rs
2244 ts = ts + rs
2245 heads -= set(r.parentrevs(rev))
2245 heads -= set(r.parentrevs(rev))
2246 heads.add(rev)
2246 heads.add(rev)
2247 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2247 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2248 (rev, p1, p2, r.start(rev), r.end(rev),
2248 (rev, p1, p2, r.start(rev), r.end(rev),
2249 r.start(dbase), r.start(cbase),
2249 r.start(dbase), r.start(cbase),
2250 r.start(p1), r.start(p2),
2250 r.start(p1), r.start(p2),
2251 rs, ts, ts / r.end(rev), len(heads)))
2251 rs, ts, ts / r.end(rev), len(heads)))
2252 return 0
2252 return 0
2253
2253
2254 v = r.version
2254 v = r.version
2255 format = v & 0xFFFF
2255 format = v & 0xFFFF
2256 flags = []
2256 flags = []
2257 gdelta = False
2257 gdelta = False
2258 if v & revlog.REVLOGNGINLINEDATA:
2258 if v & revlog.REVLOGNGINLINEDATA:
2259 flags.append('inline')
2259 flags.append('inline')
2260 if v & revlog.REVLOGGENERALDELTA:
2260 if v & revlog.REVLOGGENERALDELTA:
2261 gdelta = True
2261 gdelta = True
2262 flags.append('generaldelta')
2262 flags.append('generaldelta')
2263 if not flags:
2263 if not flags:
2264 flags = ['(none)']
2264 flags = ['(none)']
2265
2265
2266 nummerges = 0
2266 nummerges = 0
2267 numfull = 0
2267 numfull = 0
2268 numprev = 0
2268 numprev = 0
2269 nump1 = 0
2269 nump1 = 0
2270 nump2 = 0
2270 nump2 = 0
2271 numother = 0
2271 numother = 0
2272 nump1prev = 0
2272 nump1prev = 0
2273 nump2prev = 0
2273 nump2prev = 0
2274 chainlengths = []
2274 chainlengths = []
2275
2275
2276 datasize = [None, 0, 0L]
2276 datasize = [None, 0, 0L]
2277 fullsize = [None, 0, 0L]
2277 fullsize = [None, 0, 0L]
2278 deltasize = [None, 0, 0L]
2278 deltasize = [None, 0, 0L]
2279
2279
2280 def addsize(size, l):
2280 def addsize(size, l):
2281 if l[0] is None or size < l[0]:
2281 if l[0] is None or size < l[0]:
2282 l[0] = size
2282 l[0] = size
2283 if size > l[1]:
2283 if size > l[1]:
2284 l[1] = size
2284 l[1] = size
2285 l[2] += size
2285 l[2] += size
2286
2286
2287 numrevs = len(r)
2287 numrevs = len(r)
2288 for rev in xrange(numrevs):
2288 for rev in xrange(numrevs):
2289 p1, p2 = r.parentrevs(rev)
2289 p1, p2 = r.parentrevs(rev)
2290 delta = r.deltaparent(rev)
2290 delta = r.deltaparent(rev)
2291 if format > 0:
2291 if format > 0:
2292 addsize(r.rawsize(rev), datasize)
2292 addsize(r.rawsize(rev), datasize)
2293 if p2 != nullrev:
2293 if p2 != nullrev:
2294 nummerges += 1
2294 nummerges += 1
2295 size = r.length(rev)
2295 size = r.length(rev)
2296 if delta == nullrev:
2296 if delta == nullrev:
2297 chainlengths.append(0)
2297 chainlengths.append(0)
2298 numfull += 1
2298 numfull += 1
2299 addsize(size, fullsize)
2299 addsize(size, fullsize)
2300 else:
2300 else:
2301 chainlengths.append(chainlengths[delta] + 1)
2301 chainlengths.append(chainlengths[delta] + 1)
2302 addsize(size, deltasize)
2302 addsize(size, deltasize)
2303 if delta == rev - 1:
2303 if delta == rev - 1:
2304 numprev += 1
2304 numprev += 1
2305 if delta == p1:
2305 if delta == p1:
2306 nump1prev += 1
2306 nump1prev += 1
2307 elif delta == p2:
2307 elif delta == p2:
2308 nump2prev += 1
2308 nump2prev += 1
2309 elif delta == p1:
2309 elif delta == p1:
2310 nump1 += 1
2310 nump1 += 1
2311 elif delta == p2:
2311 elif delta == p2:
2312 nump2 += 1
2312 nump2 += 1
2313 elif delta != nullrev:
2313 elif delta != nullrev:
2314 numother += 1
2314 numother += 1
2315
2315
2316 # Adjust size min value for empty cases
2316 # Adjust size min value for empty cases
2317 for size in (datasize, fullsize, deltasize):
2317 for size in (datasize, fullsize, deltasize):
2318 if size[0] is None:
2318 if size[0] is None:
2319 size[0] = 0
2319 size[0] = 0
2320
2320
2321 numdeltas = numrevs - numfull
2321 numdeltas = numrevs - numfull
2322 numoprev = numprev - nump1prev - nump2prev
2322 numoprev = numprev - nump1prev - nump2prev
2323 totalrawsize = datasize[2]
2323 totalrawsize = datasize[2]
2324 datasize[2] /= numrevs
2324 datasize[2] /= numrevs
2325 fulltotal = fullsize[2]
2325 fulltotal = fullsize[2]
2326 fullsize[2] /= numfull
2326 fullsize[2] /= numfull
2327 deltatotal = deltasize[2]
2327 deltatotal = deltasize[2]
2328 if numrevs - numfull > 0:
2328 if numrevs - numfull > 0:
2329 deltasize[2] /= numrevs - numfull
2329 deltasize[2] /= numrevs - numfull
2330 totalsize = fulltotal + deltatotal
2330 totalsize = fulltotal + deltatotal
2331 avgchainlen = sum(chainlengths) / numrevs
2331 avgchainlen = sum(chainlengths) / numrevs
2332 compratio = totalrawsize / totalsize
2332 compratio = totalrawsize / totalsize
2333
2333
2334 basedfmtstr = '%%%dd\n'
2334 basedfmtstr = '%%%dd\n'
2335 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2335 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2336
2336
2337 def dfmtstr(max):
2337 def dfmtstr(max):
2338 return basedfmtstr % len(str(max))
2338 return basedfmtstr % len(str(max))
2339 def pcfmtstr(max, padding=0):
2339 def pcfmtstr(max, padding=0):
2340 return basepcfmtstr % (len(str(max)), ' ' * padding)
2340 return basepcfmtstr % (len(str(max)), ' ' * padding)
2341
2341
2342 def pcfmt(value, total):
2342 def pcfmt(value, total):
2343 return (value, 100 * float(value) / total)
2343 return (value, 100 * float(value) / total)
2344
2344
2345 ui.write(('format : %d\n') % format)
2345 ui.write(('format : %d\n') % format)
2346 ui.write(('flags : %s\n') % ', '.join(flags))
2346 ui.write(('flags : %s\n') % ', '.join(flags))
2347
2347
2348 ui.write('\n')
2348 ui.write('\n')
2349 fmt = pcfmtstr(totalsize)
2349 fmt = pcfmtstr(totalsize)
2350 fmt2 = dfmtstr(totalsize)
2350 fmt2 = dfmtstr(totalsize)
2351 ui.write(('revisions : ') + fmt2 % numrevs)
2351 ui.write(('revisions : ') + fmt2 % numrevs)
2352 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2352 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2353 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2353 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2354 ui.write(('revisions : ') + fmt2 % numrevs)
2354 ui.write(('revisions : ') + fmt2 % numrevs)
2355 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2355 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2356 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2356 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2357 ui.write(('revision size : ') + fmt2 % totalsize)
2357 ui.write(('revision size : ') + fmt2 % totalsize)
2358 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2358 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2359 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2359 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2360
2360
2361 ui.write('\n')
2361 ui.write('\n')
2362 fmt = dfmtstr(max(avgchainlen, compratio))
2362 fmt = dfmtstr(max(avgchainlen, compratio))
2363 ui.write(('avg chain length : ') + fmt % avgchainlen)
2363 ui.write(('avg chain length : ') + fmt % avgchainlen)
2364 ui.write(('compression ratio : ') + fmt % compratio)
2364 ui.write(('compression ratio : ') + fmt % compratio)
2365
2365
2366 if format > 0:
2366 if format > 0:
2367 ui.write('\n')
2367 ui.write('\n')
2368 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2368 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2369 % tuple(datasize))
2369 % tuple(datasize))
2370 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2370 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2371 % tuple(fullsize))
2371 % tuple(fullsize))
2372 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2372 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2373 % tuple(deltasize))
2373 % tuple(deltasize))
2374
2374
2375 if numdeltas > 0:
2375 if numdeltas > 0:
2376 ui.write('\n')
2376 ui.write('\n')
2377 fmt = pcfmtstr(numdeltas)
2377 fmt = pcfmtstr(numdeltas)
2378 fmt2 = pcfmtstr(numdeltas, 4)
2378 fmt2 = pcfmtstr(numdeltas, 4)
2379 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2379 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2380 if numprev > 0:
2380 if numprev > 0:
2381 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2381 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2382 numprev))
2382 numprev))
2383 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2383 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2384 numprev))
2384 numprev))
2385 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2385 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2386 numprev))
2386 numprev))
2387 if gdelta:
2387 if gdelta:
2388 ui.write(('deltas against p1 : ')
2388 ui.write(('deltas against p1 : ')
2389 + fmt % pcfmt(nump1, numdeltas))
2389 + fmt % pcfmt(nump1, numdeltas))
2390 ui.write(('deltas against p2 : ')
2390 ui.write(('deltas against p2 : ')
2391 + fmt % pcfmt(nump2, numdeltas))
2391 + fmt % pcfmt(nump2, numdeltas))
2392 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2392 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2393 numdeltas))
2393 numdeltas))
2394
2394
2395 @command('debugrevspec', [], ('REVSPEC'))
2395 @command('debugrevspec', [], ('REVSPEC'))
2396 def debugrevspec(ui, repo, expr):
2396 def debugrevspec(ui, repo, expr):
2397 """parse and apply a revision specification
2397 """parse and apply a revision specification
2398
2398
2399 Use --verbose to print the parsed tree before and after aliases
2399 Use --verbose to print the parsed tree before and after aliases
2400 expansion.
2400 expansion.
2401 """
2401 """
2402 if ui.verbose:
2402 if ui.verbose:
2403 tree = revset.parse(expr)[0]
2403 tree = revset.parse(expr)[0]
2404 ui.note(revset.prettyformat(tree), "\n")
2404 ui.note(revset.prettyformat(tree), "\n")
2405 newtree = revset.findaliases(ui, tree)
2405 newtree = revset.findaliases(ui, tree)
2406 if newtree != tree:
2406 if newtree != tree:
2407 ui.note(revset.prettyformat(newtree), "\n")
2407 ui.note(revset.prettyformat(newtree), "\n")
2408 func = revset.match(ui, expr)
2408 func = revset.match(ui, expr)
2409 for c in func(repo, range(len(repo))):
2409 for c in func(repo, range(len(repo))):
2410 ui.write("%s\n" % c)
2410 ui.write("%s\n" % c)
2411
2411
2412 @command('debugsetparents', [], _('REV1 [REV2]'))
2412 @command('debugsetparents', [], _('REV1 [REV2]'))
2413 def debugsetparents(ui, repo, rev1, rev2=None):
2413 def debugsetparents(ui, repo, rev1, rev2=None):
2414 """manually set the parents of the current working directory
2414 """manually set the parents of the current working directory
2415
2415
2416 This is useful for writing repository conversion tools, but should
2416 This is useful for writing repository conversion tools, but should
2417 be used with care.
2417 be used with care.
2418
2418
2419 Returns 0 on success.
2419 Returns 0 on success.
2420 """
2420 """
2421
2421
2422 r1 = scmutil.revsingle(repo, rev1).node()
2422 r1 = scmutil.revsingle(repo, rev1).node()
2423 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2423 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2424
2424
2425 wlock = repo.wlock()
2425 wlock = repo.wlock()
2426 try:
2426 try:
2427 repo.setparents(r1, r2)
2427 repo.setparents(r1, r2)
2428 finally:
2428 finally:
2429 wlock.release()
2429 wlock.release()
2430
2430
2431 @command('debugstate',
2431 @command('debugstate',
2432 [('', 'nodates', None, _('do not display the saved mtime')),
2432 [('', 'nodates', None, _('do not display the saved mtime')),
2433 ('', 'datesort', None, _('sort by saved mtime'))],
2433 ('', 'datesort', None, _('sort by saved mtime'))],
2434 _('[OPTION]...'))
2434 _('[OPTION]...'))
2435 def debugstate(ui, repo, nodates=None, datesort=None):
2435 def debugstate(ui, repo, nodates=None, datesort=None):
2436 """show the contents of the current dirstate"""
2436 """show the contents of the current dirstate"""
2437 timestr = ""
2437 timestr = ""
2438 showdate = not nodates
2438 showdate = not nodates
2439 if datesort:
2439 if datesort:
2440 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2440 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2441 else:
2441 else:
2442 keyfunc = None # sort by filename
2442 keyfunc = None # sort by filename
2443 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2443 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2444 if showdate:
2444 if showdate:
2445 if ent[3] == -1:
2445 if ent[3] == -1:
2446 # Pad or slice to locale representation
2446 # Pad or slice to locale representation
2447 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2447 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2448 time.localtime(0)))
2448 time.localtime(0)))
2449 timestr = 'unset'
2449 timestr = 'unset'
2450 timestr = (timestr[:locale_len] +
2450 timestr = (timestr[:locale_len] +
2451 ' ' * (locale_len - len(timestr)))
2451 ' ' * (locale_len - len(timestr)))
2452 else:
2452 else:
2453 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2453 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2454 time.localtime(ent[3]))
2454 time.localtime(ent[3]))
2455 if ent[1] & 020000:
2455 if ent[1] & 020000:
2456 mode = 'lnk'
2456 mode = 'lnk'
2457 else:
2457 else:
2458 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2458 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2459 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2459 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2460 for f in repo.dirstate.copies():
2460 for f in repo.dirstate.copies():
2461 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2461 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2462
2462
2463 @command('debugsub',
2463 @command('debugsub',
2464 [('r', 'rev', '',
2464 [('r', 'rev', '',
2465 _('revision to check'), _('REV'))],
2465 _('revision to check'), _('REV'))],
2466 _('[-r REV] [REV]'))
2466 _('[-r REV] [REV]'))
2467 def debugsub(ui, repo, rev=None):
2467 def debugsub(ui, repo, rev=None):
2468 ctx = scmutil.revsingle(repo, rev, None)
2468 ctx = scmutil.revsingle(repo, rev, None)
2469 for k, v in sorted(ctx.substate.items()):
2469 for k, v in sorted(ctx.substate.items()):
2470 ui.write(('path %s\n') % k)
2470 ui.write(('path %s\n') % k)
2471 ui.write((' source %s\n') % v[0])
2471 ui.write((' source %s\n') % v[0])
2472 ui.write((' revision %s\n') % v[1])
2472 ui.write((' revision %s\n') % v[1])
2473
2473
2474 @command('debugsuccessorssets',
2474 @command('debugsuccessorssets',
2475 [],
2475 [],
2476 _('[REV]'))
2476 _('[REV]'))
2477 def debugsuccessorssets(ui, repo, *revs):
2477 def debugsuccessorssets(ui, repo, *revs):
2478 """show set of successors for revision
2478 """show set of successors for revision
2479
2479
2480 A successors set of changeset A is a consistent group of revisions that
2480 A successors set of changeset A is a consistent group of revisions that
2481 succeed A. It contains non-obsolete changesets only.
2481 succeed A. It contains non-obsolete changesets only.
2482
2482
2483 In most cases a changeset A has a single successors set containing a single
2483 In most cases a changeset A has a single successors set containing a single
2484 successor (changeset A replaced by A').
2484 successor (changeset A replaced by A').
2485
2485
2486 A changeset that is made obsolete with no successors are called "pruned".
2486 A changeset that is made obsolete with no successors are called "pruned".
2487 Such changesets have no successors sets at all.
2487 Such changesets have no successors sets at all.
2488
2488
2489 A changeset that has been "split" will have a successors set containing
2489 A changeset that has been "split" will have a successors set containing
2490 more than one successor.
2490 more than one successor.
2491
2491
2492 A changeset that has been rewritten in multiple different ways is called
2492 A changeset that has been rewritten in multiple different ways is called
2493 "divergent". Such changesets have multiple successor sets (each of which
2493 "divergent". Such changesets have multiple successor sets (each of which
2494 may also be split, i.e. have multiple successors).
2494 may also be split, i.e. have multiple successors).
2495
2495
2496 Results are displayed as follows::
2496 Results are displayed as follows::
2497
2497
2498 <rev1>
2498 <rev1>
2499 <successors-1A>
2499 <successors-1A>
2500 <rev2>
2500 <rev2>
2501 <successors-2A>
2501 <successors-2A>
2502 <successors-2B1> <successors-2B2> <successors-2B3>
2502 <successors-2B1> <successors-2B2> <successors-2B3>
2503
2503
2504 Here rev2 has two possible (i.e. divergent) successors sets. The first
2504 Here rev2 has two possible (i.e. divergent) successors sets. The first
2505 holds one element, whereas the second holds three (i.e. the changeset has
2505 holds one element, whereas the second holds three (i.e. the changeset has
2506 been split).
2506 been split).
2507 """
2507 """
2508 # passed to successorssets caching computation from one call to another
2508 # passed to successorssets caching computation from one call to another
2509 cache = {}
2509 cache = {}
2510 ctx2str = str
2510 ctx2str = str
2511 node2str = short
2511 node2str = short
2512 if ui.debug():
2512 if ui.debug():
2513 def ctx2str(ctx):
2513 def ctx2str(ctx):
2514 return ctx.hex()
2514 return ctx.hex()
2515 node2str = hex
2515 node2str = hex
2516 for rev in scmutil.revrange(repo, revs):
2516 for rev in scmutil.revrange(repo, revs):
2517 ctx = repo[rev]
2517 ctx = repo[rev]
2518 ui.write('%s\n'% ctx2str(ctx))
2518 ui.write('%s\n'% ctx2str(ctx))
2519 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2519 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2520 if succsset:
2520 if succsset:
2521 ui.write(' ')
2521 ui.write(' ')
2522 ui.write(node2str(succsset[0]))
2522 ui.write(node2str(succsset[0]))
2523 for node in succsset[1:]:
2523 for node in succsset[1:]:
2524 ui.write(' ')
2524 ui.write(' ')
2525 ui.write(node2str(node))
2525 ui.write(node2str(node))
2526 ui.write('\n')
2526 ui.write('\n')
2527
2527
2528 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2528 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2529 def debugwalk(ui, repo, *pats, **opts):
2529 def debugwalk(ui, repo, *pats, **opts):
2530 """show how files match on given patterns"""
2530 """show how files match on given patterns"""
2531 m = scmutil.match(repo[None], pats, opts)
2531 m = scmutil.match(repo[None], pats, opts)
2532 items = list(repo.walk(m))
2532 items = list(repo.walk(m))
2533 if not items:
2533 if not items:
2534 return
2534 return
2535 f = lambda fn: fn
2535 f = lambda fn: fn
2536 if ui.configbool('ui', 'slash') and os.sep != '/':
2536 if ui.configbool('ui', 'slash') and os.sep != '/':
2537 f = lambda fn: util.normpath(fn)
2537 f = lambda fn: util.normpath(fn)
2538 fmt = 'f %%-%ds %%-%ds %%s' % (
2538 fmt = 'f %%-%ds %%-%ds %%s' % (
2539 max([len(abs) for abs in items]),
2539 max([len(abs) for abs in items]),
2540 max([len(m.rel(abs)) for abs in items]))
2540 max([len(m.rel(abs)) for abs in items]))
2541 for abs in items:
2541 for abs in items:
2542 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2542 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2543 ui.write("%s\n" % line.rstrip())
2543 ui.write("%s\n" % line.rstrip())
2544
2544
2545 @command('debugwireargs',
2545 @command('debugwireargs',
2546 [('', 'three', '', 'three'),
2546 [('', 'three', '', 'three'),
2547 ('', 'four', '', 'four'),
2547 ('', 'four', '', 'four'),
2548 ('', 'five', '', 'five'),
2548 ('', 'five', '', 'five'),
2549 ] + remoteopts,
2549 ] + remoteopts,
2550 _('REPO [OPTIONS]... [ONE [TWO]]'))
2550 _('REPO [OPTIONS]... [ONE [TWO]]'))
2551 def debugwireargs(ui, repopath, *vals, **opts):
2551 def debugwireargs(ui, repopath, *vals, **opts):
2552 repo = hg.peer(ui, opts, repopath)
2552 repo = hg.peer(ui, opts, repopath)
2553 for opt in remoteopts:
2553 for opt in remoteopts:
2554 del opts[opt[1]]
2554 del opts[opt[1]]
2555 args = {}
2555 args = {}
2556 for k, v in opts.iteritems():
2556 for k, v in opts.iteritems():
2557 if v:
2557 if v:
2558 args[k] = v
2558 args[k] = v
2559 # run twice to check that we don't mess up the stream for the next command
2559 # run twice to check that we don't mess up the stream for the next command
2560 res1 = repo.debugwireargs(*vals, **args)
2560 res1 = repo.debugwireargs(*vals, **args)
2561 res2 = repo.debugwireargs(*vals, **args)
2561 res2 = repo.debugwireargs(*vals, **args)
2562 ui.write("%s\n" % res1)
2562 ui.write("%s\n" % res1)
2563 if res1 != res2:
2563 if res1 != res2:
2564 ui.warn("%s\n" % res2)
2564 ui.warn("%s\n" % res2)
2565
2565
2566 @command('^diff',
2566 @command('^diff',
2567 [('r', 'rev', [], _('revision'), _('REV')),
2567 [('r', 'rev', [], _('revision'), _('REV')),
2568 ('c', 'change', '', _('change made by revision'), _('REV'))
2568 ('c', 'change', '', _('change made by revision'), _('REV'))
2569 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2569 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2570 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2570 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2571 def diff(ui, repo, *pats, **opts):
2571 def diff(ui, repo, *pats, **opts):
2572 """diff repository (or selected files)
2572 """diff repository (or selected files)
2573
2573
2574 Show differences between revisions for the specified files.
2574 Show differences between revisions for the specified files.
2575
2575
2576 Differences between files are shown using the unified diff format.
2576 Differences between files are shown using the unified diff format.
2577
2577
2578 .. note::
2578 .. note::
2579 diff may generate unexpected results for merges, as it will
2579 diff may generate unexpected results for merges, as it will
2580 default to comparing against the working directory's first
2580 default to comparing against the working directory's first
2581 parent changeset if no revisions are specified.
2581 parent changeset if no revisions are specified.
2582
2582
2583 When two revision arguments are given, then changes are shown
2583 When two revision arguments are given, then changes are shown
2584 between those revisions. If only one revision is specified then
2584 between those revisions. If only one revision is specified then
2585 that revision is compared to the working directory, and, when no
2585 that revision is compared to the working directory, and, when no
2586 revisions are specified, the working directory files are compared
2586 revisions are specified, the working directory files are compared
2587 to its parent.
2587 to its parent.
2588
2588
2589 Alternatively you can specify -c/--change with a revision to see
2589 Alternatively you can specify -c/--change with a revision to see
2590 the changes in that changeset relative to its first parent.
2590 the changes in that changeset relative to its first parent.
2591
2591
2592 Without the -a/--text option, diff will avoid generating diffs of
2592 Without the -a/--text option, diff will avoid generating diffs of
2593 files it detects as binary. With -a, diff will generate a diff
2593 files it detects as binary. With -a, diff will generate a diff
2594 anyway, probably with undesirable results.
2594 anyway, probably with undesirable results.
2595
2595
2596 Use the -g/--git option to generate diffs in the git extended diff
2596 Use the -g/--git option to generate diffs in the git extended diff
2597 format. For more information, read :hg:`help diffs`.
2597 format. For more information, read :hg:`help diffs`.
2598
2598
2599 .. container:: verbose
2599 .. container:: verbose
2600
2600
2601 Examples:
2601 Examples:
2602
2602
2603 - compare a file in the current working directory to its parent::
2603 - compare a file in the current working directory to its parent::
2604
2604
2605 hg diff foo.c
2605 hg diff foo.c
2606
2606
2607 - compare two historical versions of a directory, with rename info::
2607 - compare two historical versions of a directory, with rename info::
2608
2608
2609 hg diff --git -r 1.0:1.2 lib/
2609 hg diff --git -r 1.0:1.2 lib/
2610
2610
2611 - get change stats relative to the last change on some date::
2611 - get change stats relative to the last change on some date::
2612
2612
2613 hg diff --stat -r "date('may 2')"
2613 hg diff --stat -r "date('may 2')"
2614
2614
2615 - diff all newly-added files that contain a keyword::
2615 - diff all newly-added files that contain a keyword::
2616
2616
2617 hg diff "set:added() and grep(GNU)"
2617 hg diff "set:added() and grep(GNU)"
2618
2618
2619 - compare a revision and its parents::
2619 - compare a revision and its parents::
2620
2620
2621 hg diff -c 9353 # compare against first parent
2621 hg diff -c 9353 # compare against first parent
2622 hg diff -r 9353^:9353 # same using revset syntax
2622 hg diff -r 9353^:9353 # same using revset syntax
2623 hg diff -r 9353^2:9353 # compare against the second parent
2623 hg diff -r 9353^2:9353 # compare against the second parent
2624
2624
2625 Returns 0 on success.
2625 Returns 0 on success.
2626 """
2626 """
2627
2627
2628 revs = opts.get('rev')
2628 revs = opts.get('rev')
2629 change = opts.get('change')
2629 change = opts.get('change')
2630 stat = opts.get('stat')
2630 stat = opts.get('stat')
2631 reverse = opts.get('reverse')
2631 reverse = opts.get('reverse')
2632
2632
2633 if revs and change:
2633 if revs and change:
2634 msg = _('cannot specify --rev and --change at the same time')
2634 msg = _('cannot specify --rev and --change at the same time')
2635 raise util.Abort(msg)
2635 raise util.Abort(msg)
2636 elif change:
2636 elif change:
2637 node2 = scmutil.revsingle(repo, change, None).node()
2637 node2 = scmutil.revsingle(repo, change, None).node()
2638 node1 = repo[node2].p1().node()
2638 node1 = repo[node2].p1().node()
2639 else:
2639 else:
2640 node1, node2 = scmutil.revpair(repo, revs)
2640 node1, node2 = scmutil.revpair(repo, revs)
2641
2641
2642 if reverse:
2642 if reverse:
2643 node1, node2 = node2, node1
2643 node1, node2 = node2, node1
2644
2644
2645 diffopts = patch.diffopts(ui, opts)
2645 diffopts = patch.diffopts(ui, opts)
2646 m = scmutil.match(repo[node2], pats, opts)
2646 m = scmutil.match(repo[node2], pats, opts)
2647 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2647 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2648 listsubrepos=opts.get('subrepos'))
2648 listsubrepos=opts.get('subrepos'))
2649
2649
2650 @command('^export',
2650 @command('^export',
2651 [('o', 'output', '',
2651 [('o', 'output', '',
2652 _('print output to file with formatted name'), _('FORMAT')),
2652 _('print output to file with formatted name'), _('FORMAT')),
2653 ('', 'switch-parent', None, _('diff against the second parent')),
2653 ('', 'switch-parent', None, _('diff against the second parent')),
2654 ('r', 'rev', [], _('revisions to export'), _('REV')),
2654 ('r', 'rev', [], _('revisions to export'), _('REV')),
2655 ] + diffopts,
2655 ] + diffopts,
2656 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2656 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2657 def export(ui, repo, *changesets, **opts):
2657 def export(ui, repo, *changesets, **opts):
2658 """dump the header and diffs for one or more changesets
2658 """dump the header and diffs for one or more changesets
2659
2659
2660 Print the changeset header and diffs for one or more revisions.
2660 Print the changeset header and diffs for one or more revisions.
2661
2661
2662 The information shown in the changeset header is: author, date,
2662 The information shown in the changeset header is: author, date,
2663 branch name (if non-default), changeset hash, parent(s) and commit
2663 branch name (if non-default), changeset hash, parent(s) and commit
2664 comment.
2664 comment.
2665
2665
2666 .. note::
2666 .. note::
2667 export may generate unexpected diff output for merge
2667 export may generate unexpected diff output for merge
2668 changesets, as it will compare the merge changeset against its
2668 changesets, as it will compare the merge changeset against its
2669 first parent only.
2669 first parent only.
2670
2670
2671 Output may be to a file, in which case the name of the file is
2671 Output may be to a file, in which case the name of the file is
2672 given using a format string. The formatting rules are as follows:
2672 given using a format string. The formatting rules are as follows:
2673
2673
2674 :``%%``: literal "%" character
2674 :``%%``: literal "%" character
2675 :``%H``: changeset hash (40 hexadecimal digits)
2675 :``%H``: changeset hash (40 hexadecimal digits)
2676 :``%N``: number of patches being generated
2676 :``%N``: number of patches being generated
2677 :``%R``: changeset revision number
2677 :``%R``: changeset revision number
2678 :``%b``: basename of the exporting repository
2678 :``%b``: basename of the exporting repository
2679 :``%h``: short-form changeset hash (12 hexadecimal digits)
2679 :``%h``: short-form changeset hash (12 hexadecimal digits)
2680 :``%m``: first line of the commit message (only alphanumeric characters)
2680 :``%m``: first line of the commit message (only alphanumeric characters)
2681 :``%n``: zero-padded sequence number, starting at 1
2681 :``%n``: zero-padded sequence number, starting at 1
2682 :``%r``: zero-padded changeset revision number
2682 :``%r``: zero-padded changeset revision number
2683
2683
2684 Without the -a/--text option, export will avoid generating diffs
2684 Without the -a/--text option, export will avoid generating diffs
2685 of files it detects as binary. With -a, export will generate a
2685 of files it detects as binary. With -a, export will generate a
2686 diff anyway, probably with undesirable results.
2686 diff anyway, probably with undesirable results.
2687
2687
2688 Use the -g/--git option to generate diffs in the git extended diff
2688 Use the -g/--git option to generate diffs in the git extended diff
2689 format. See :hg:`help diffs` for more information.
2689 format. See :hg:`help diffs` for more information.
2690
2690
2691 With the --switch-parent option, the diff will be against the
2691 With the --switch-parent option, the diff will be against the
2692 second parent. It can be useful to review a merge.
2692 second parent. It can be useful to review a merge.
2693
2693
2694 .. container:: verbose
2694 .. container:: verbose
2695
2695
2696 Examples:
2696 Examples:
2697
2697
2698 - use export and import to transplant a bugfix to the current
2698 - use export and import to transplant a bugfix to the current
2699 branch::
2699 branch::
2700
2700
2701 hg export -r 9353 | hg import -
2701 hg export -r 9353 | hg import -
2702
2702
2703 - export all the changesets between two revisions to a file with
2703 - export all the changesets between two revisions to a file with
2704 rename information::
2704 rename information::
2705
2705
2706 hg export --git -r 123:150 > changes.txt
2706 hg export --git -r 123:150 > changes.txt
2707
2707
2708 - split outgoing changes into a series of patches with
2708 - split outgoing changes into a series of patches with
2709 descriptive names::
2709 descriptive names::
2710
2710
2711 hg export -r "outgoing()" -o "%n-%m.patch"
2711 hg export -r "outgoing()" -o "%n-%m.patch"
2712
2712
2713 Returns 0 on success.
2713 Returns 0 on success.
2714 """
2714 """
2715 changesets += tuple(opts.get('rev', []))
2715 changesets += tuple(opts.get('rev', []))
2716 revs = scmutil.revrange(repo, changesets)
2716 revs = scmutil.revrange(repo, changesets)
2717 if not revs:
2717 if not revs:
2718 raise util.Abort(_("export requires at least one changeset"))
2718 raise util.Abort(_("export requires at least one changeset"))
2719 if len(revs) > 1:
2719 if len(revs) > 1:
2720 ui.note(_('exporting patches:\n'))
2720 ui.note(_('exporting patches:\n'))
2721 else:
2721 else:
2722 ui.note(_('exporting patch:\n'))
2722 ui.note(_('exporting patch:\n'))
2723 cmdutil.export(repo, revs, template=opts.get('output'),
2723 cmdutil.export(repo, revs, template=opts.get('output'),
2724 switch_parent=opts.get('switch_parent'),
2724 switch_parent=opts.get('switch_parent'),
2725 opts=patch.diffopts(ui, opts))
2725 opts=patch.diffopts(ui, opts))
2726
2726
2727 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2727 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2728 def forget(ui, repo, *pats, **opts):
2728 def forget(ui, repo, *pats, **opts):
2729 """forget the specified files on the next commit
2729 """forget the specified files on the next commit
2730
2730
2731 Mark the specified files so they will no longer be tracked
2731 Mark the specified files so they will no longer be tracked
2732 after the next commit.
2732 after the next commit.
2733
2733
2734 This only removes files from the current branch, not from the
2734 This only removes files from the current branch, not from the
2735 entire project history, and it does not delete them from the
2735 entire project history, and it does not delete them from the
2736 working directory.
2736 working directory.
2737
2737
2738 To undo a forget before the next commit, see :hg:`add`.
2738 To undo a forget before the next commit, see :hg:`add`.
2739
2739
2740 .. container:: verbose
2740 .. container:: verbose
2741
2741
2742 Examples:
2742 Examples:
2743
2743
2744 - forget newly-added binary files::
2744 - forget newly-added binary files::
2745
2745
2746 hg forget "set:added() and binary()"
2746 hg forget "set:added() and binary()"
2747
2747
2748 - forget files that would be excluded by .hgignore::
2748 - forget files that would be excluded by .hgignore::
2749
2749
2750 hg forget "set:hgignore()"
2750 hg forget "set:hgignore()"
2751
2751
2752 Returns 0 on success.
2752 Returns 0 on success.
2753 """
2753 """
2754
2754
2755 if not pats:
2755 if not pats:
2756 raise util.Abort(_('no files specified'))
2756 raise util.Abort(_('no files specified'))
2757
2757
2758 m = scmutil.match(repo[None], pats, opts)
2758 m = scmutil.match(repo[None], pats, opts)
2759 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2759 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2760 return rejected and 1 or 0
2760 return rejected and 1 or 0
2761
2761
2762 @command(
2762 @command(
2763 'graft',
2763 'graft',
2764 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2764 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2765 ('c', 'continue', False, _('resume interrupted graft')),
2765 ('c', 'continue', False, _('resume interrupted graft')),
2766 ('e', 'edit', False, _('invoke editor on commit messages')),
2766 ('e', 'edit', False, _('invoke editor on commit messages')),
2767 ('', 'log', None, _('append graft info to log message')),
2767 ('', 'log', None, _('append graft info to log message')),
2768 ('D', 'currentdate', False,
2768 ('D', 'currentdate', False,
2769 _('record the current date as commit date')),
2769 _('record the current date as commit date')),
2770 ('U', 'currentuser', False,
2770 ('U', 'currentuser', False,
2771 _('record the current user as committer'), _('DATE'))]
2771 _('record the current user as committer'), _('DATE'))]
2772 + commitopts2 + mergetoolopts + dryrunopts,
2772 + commitopts2 + mergetoolopts + dryrunopts,
2773 _('[OPTION]... [-r] REV...'))
2773 _('[OPTION]... [-r] REV...'))
2774 def graft(ui, repo, *revs, **opts):
2774 def graft(ui, repo, *revs, **opts):
2775 '''copy changes from other branches onto the current branch
2775 '''copy changes from other branches onto the current branch
2776
2776
2777 This command uses Mercurial's merge logic to copy individual
2777 This command uses Mercurial's merge logic to copy individual
2778 changes from other branches without merging branches in the
2778 changes from other branches without merging branches in the
2779 history graph. This is sometimes known as 'backporting' or
2779 history graph. This is sometimes known as 'backporting' or
2780 'cherry-picking'. By default, graft will copy user, date, and
2780 'cherry-picking'. By default, graft will copy user, date, and
2781 description from the source changesets.
2781 description from the source changesets.
2782
2782
2783 Changesets that are ancestors of the current revision, that have
2783 Changesets that are ancestors of the current revision, that have
2784 already been grafted, or that are merges will be skipped.
2784 already been grafted, or that are merges will be skipped.
2785
2785
2786 If --log is specified, log messages will have a comment appended
2786 If --log is specified, log messages will have a comment appended
2787 of the form::
2787 of the form::
2788
2788
2789 (grafted from CHANGESETHASH)
2789 (grafted from CHANGESETHASH)
2790
2790
2791 If a graft merge results in conflicts, the graft process is
2791 If a graft merge results in conflicts, the graft process is
2792 interrupted so that the current merge can be manually resolved.
2792 interrupted so that the current merge can be manually resolved.
2793 Once all conflicts are addressed, the graft process can be
2793 Once all conflicts are addressed, the graft process can be
2794 continued with the -c/--continue option.
2794 continued with the -c/--continue option.
2795
2795
2796 .. note::
2796 .. note::
2797 The -c/--continue option does not reapply earlier options.
2797 The -c/--continue option does not reapply earlier options.
2798
2798
2799 .. container:: verbose
2799 .. container:: verbose
2800
2800
2801 Examples:
2801 Examples:
2802
2802
2803 - copy a single change to the stable branch and edit its description::
2803 - copy a single change to the stable branch and edit its description::
2804
2804
2805 hg update stable
2805 hg update stable
2806 hg graft --edit 9393
2806 hg graft --edit 9393
2807
2807
2808 - graft a range of changesets with one exception, updating dates::
2808 - graft a range of changesets with one exception, updating dates::
2809
2809
2810 hg graft -D "2085::2093 and not 2091"
2810 hg graft -D "2085::2093 and not 2091"
2811
2811
2812 - continue a graft after resolving conflicts::
2812 - continue a graft after resolving conflicts::
2813
2813
2814 hg graft -c
2814 hg graft -c
2815
2815
2816 - show the source of a grafted changeset::
2816 - show the source of a grafted changeset::
2817
2817
2818 hg log --debug -r tip
2818 hg log --debug -r tip
2819
2819
2820 Returns 0 on successful completion.
2820 Returns 0 on successful completion.
2821 '''
2821 '''
2822
2822
2823 revs = list(revs)
2823 revs = list(revs)
2824 revs.extend(opts['rev'])
2824 revs.extend(opts['rev'])
2825
2825
2826 if not opts.get('user') and opts.get('currentuser'):
2826 if not opts.get('user') and opts.get('currentuser'):
2827 opts['user'] = ui.username()
2827 opts['user'] = ui.username()
2828 if not opts.get('date') and opts.get('currentdate'):
2828 if not opts.get('date') and opts.get('currentdate'):
2829 opts['date'] = "%d %d" % util.makedate()
2829 opts['date'] = "%d %d" % util.makedate()
2830
2830
2831 editor = None
2831 editor = None
2832 if opts.get('edit'):
2832 if opts.get('edit'):
2833 editor = cmdutil.commitforceeditor
2833 editor = cmdutil.commitforceeditor
2834
2834
2835 cont = False
2835 cont = False
2836 if opts['continue']:
2836 if opts['continue']:
2837 cont = True
2837 cont = True
2838 if revs:
2838 if revs:
2839 raise util.Abort(_("can't specify --continue and revisions"))
2839 raise util.Abort(_("can't specify --continue and revisions"))
2840 # read in unfinished revisions
2840 # read in unfinished revisions
2841 try:
2841 try:
2842 nodes = repo.opener.read('graftstate').splitlines()
2842 nodes = repo.opener.read('graftstate').splitlines()
2843 revs = [repo[node].rev() for node in nodes]
2843 revs = [repo[node].rev() for node in nodes]
2844 except IOError, inst:
2844 except IOError, inst:
2845 if inst.errno != errno.ENOENT:
2845 if inst.errno != errno.ENOENT:
2846 raise
2846 raise
2847 raise util.Abort(_("no graft state found, can't continue"))
2847 raise util.Abort(_("no graft state found, can't continue"))
2848 else:
2848 else:
2849 cmdutil.bailifchanged(repo)
2849 cmdutil.bailifchanged(repo)
2850 if not revs:
2850 if not revs:
2851 raise util.Abort(_('no revisions specified'))
2851 raise util.Abort(_('no revisions specified'))
2852 revs = scmutil.revrange(repo, revs)
2852 revs = scmutil.revrange(repo, revs)
2853
2853
2854 # check for merges
2854 # check for merges
2855 for rev in repo.revs('%ld and merge()', revs):
2855 for rev in repo.revs('%ld and merge()', revs):
2856 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2856 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2857 revs.remove(rev)
2857 revs.remove(rev)
2858 if not revs:
2858 if not revs:
2859 return -1
2859 return -1
2860
2860
2861 # check for ancestors of dest branch
2861 # check for ancestors of dest branch
2862 for rev in repo.revs('::. and %ld', revs):
2862 for rev in repo.revs('::. and %ld', revs):
2863 ui.warn(_('skipping ancestor revision %s\n') % rev)
2863 ui.warn(_('skipping ancestor revision %s\n') % rev)
2864 revs.remove(rev)
2864 revs.remove(rev)
2865 if not revs:
2865 if not revs:
2866 return -1
2866 return -1
2867
2867
2868 # analyze revs for earlier grafts
2868 # analyze revs for earlier grafts
2869 ids = {}
2869 ids = {}
2870 for ctx in repo.set("%ld", revs):
2870 for ctx in repo.set("%ld", revs):
2871 ids[ctx.hex()] = ctx.rev()
2871 ids[ctx.hex()] = ctx.rev()
2872 n = ctx.extra().get('source')
2872 n = ctx.extra().get('source')
2873 if n:
2873 if n:
2874 ids[n] = ctx.rev()
2874 ids[n] = ctx.rev()
2875
2875
2876 # check ancestors for earlier grafts
2876 # check ancestors for earlier grafts
2877 ui.debug('scanning for duplicate grafts\n')
2877 ui.debug('scanning for duplicate grafts\n')
2878 for ctx in repo.set("::. - ::%ld", revs):
2878 for ctx in repo.set("::. - ::%ld", revs):
2879 n = ctx.extra().get('source')
2879 n = ctx.extra().get('source')
2880 if n in ids:
2880 if n in ids:
2881 r = repo[n].rev()
2881 r = repo[n].rev()
2882 if r in revs:
2882 if r in revs:
2883 ui.warn(_('skipping already grafted revision %s\n') % r)
2883 ui.warn(_('skipping already grafted revision %s\n') % r)
2884 revs.remove(r)
2884 revs.remove(r)
2885 elif ids[n] in revs:
2885 elif ids[n] in revs:
2886 ui.warn(_('skipping already grafted revision %s '
2886 ui.warn(_('skipping already grafted revision %s '
2887 '(same origin %d)\n') % (ids[n], r))
2887 '(same origin %d)\n') % (ids[n], r))
2888 revs.remove(ids[n])
2888 revs.remove(ids[n])
2889 elif ctx.hex() in ids:
2889 elif ctx.hex() in ids:
2890 r = ids[ctx.hex()]
2890 r = ids[ctx.hex()]
2891 ui.warn(_('skipping already grafted revision %s '
2891 ui.warn(_('skipping already grafted revision %s '
2892 '(was grafted from %d)\n') % (r, ctx.rev()))
2892 '(was grafted from %d)\n') % (r, ctx.rev()))
2893 revs.remove(r)
2893 revs.remove(r)
2894 if not revs:
2894 if not revs:
2895 return -1
2895 return -1
2896
2896
2897 wlock = repo.wlock()
2897 wlock = repo.wlock()
2898 try:
2898 try:
2899 current = repo['.']
2899 current = repo['.']
2900 for pos, ctx in enumerate(repo.set("%ld", revs)):
2900 for pos, ctx in enumerate(repo.set("%ld", revs)):
2901
2901
2902 ui.status(_('grafting revision %s\n') % ctx.rev())
2902 ui.status(_('grafting revision %s\n') % ctx.rev())
2903 if opts.get('dry_run'):
2903 if opts.get('dry_run'):
2904 continue
2904 continue
2905
2905
2906 source = ctx.extra().get('source')
2906 source = ctx.extra().get('source')
2907 if not source:
2907 if not source:
2908 source = ctx.hex()
2908 source = ctx.hex()
2909 extra = {'source': source}
2909 extra = {'source': source}
2910 user = ctx.user()
2910 user = ctx.user()
2911 if opts.get('user'):
2911 if opts.get('user'):
2912 user = opts['user']
2912 user = opts['user']
2913 date = ctx.date()
2913 date = ctx.date()
2914 if opts.get('date'):
2914 if opts.get('date'):
2915 date = opts['date']
2915 date = opts['date']
2916 message = ctx.description()
2916 message = ctx.description()
2917 if opts.get('log'):
2917 if opts.get('log'):
2918 message += '\n(grafted from %s)' % ctx.hex()
2918 message += '\n(grafted from %s)' % ctx.hex()
2919
2919
2920 # we don't merge the first commit when continuing
2920 # we don't merge the first commit when continuing
2921 if not cont:
2921 if not cont:
2922 # perform the graft merge with p1(rev) as 'ancestor'
2922 # perform the graft merge with p1(rev) as 'ancestor'
2923 try:
2923 try:
2924 # ui.forcemerge is an internal variable, do not document
2924 # ui.forcemerge is an internal variable, do not document
2925 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2925 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2926 stats = mergemod.update(repo, ctx.node(), True, True, False,
2926 stats = mergemod.update(repo, ctx.node(), True, True, False,
2927 ctx.p1().node())
2927 ctx.p1().node())
2928 finally:
2928 finally:
2929 repo.ui.setconfig('ui', 'forcemerge', '')
2929 repo.ui.setconfig('ui', 'forcemerge', '')
2930 # report any conflicts
2930 # report any conflicts
2931 if stats and stats[3] > 0:
2931 if stats and stats[3] > 0:
2932 # write out state for --continue
2932 # write out state for --continue
2933 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2933 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2934 repo.opener.write('graftstate', ''.join(nodelines))
2934 repo.opener.write('graftstate', ''.join(nodelines))
2935 raise util.Abort(
2935 raise util.Abort(
2936 _("unresolved conflicts, can't continue"),
2936 _("unresolved conflicts, can't continue"),
2937 hint=_('use hg resolve and hg graft --continue'))
2937 hint=_('use hg resolve and hg graft --continue'))
2938 else:
2938 else:
2939 cont = False
2939 cont = False
2940
2940
2941 # drop the second merge parent
2941 # drop the second merge parent
2942 repo.setparents(current.node(), nullid)
2942 repo.setparents(current.node(), nullid)
2943 repo.dirstate.write()
2943 repo.dirstate.write()
2944 # fix up dirstate for copies and renames
2944 # fix up dirstate for copies and renames
2945 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2945 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2946
2946
2947 # commit
2947 # commit
2948 node = repo.commit(text=message, user=user,
2948 node = repo.commit(text=message, user=user,
2949 date=date, extra=extra, editor=editor)
2949 date=date, extra=extra, editor=editor)
2950 if node is None:
2950 if node is None:
2951 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2951 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2952 else:
2952 else:
2953 current = repo[node]
2953 current = repo[node]
2954 finally:
2954 finally:
2955 wlock.release()
2955 wlock.release()
2956
2956
2957 # remove state when we complete successfully
2957 # remove state when we complete successfully
2958 if not opts.get('dry_run'):
2958 if not opts.get('dry_run'):
2959 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2959 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2960
2960
2961 return 0
2961 return 0
2962
2962
2963 @command('grep',
2963 @command('grep',
2964 [('0', 'print0', None, _('end fields with NUL')),
2964 [('0', 'print0', None, _('end fields with NUL')),
2965 ('', 'all', None, _('print all revisions that match')),
2965 ('', 'all', None, _('print all revisions that match')),
2966 ('a', 'text', None, _('treat all files as text')),
2966 ('a', 'text', None, _('treat all files as text')),
2967 ('f', 'follow', None,
2967 ('f', 'follow', None,
2968 _('follow changeset history,'
2968 _('follow changeset history,'
2969 ' or file history across copies and renames')),
2969 ' or file history across copies and renames')),
2970 ('i', 'ignore-case', None, _('ignore case when matching')),
2970 ('i', 'ignore-case', None, _('ignore case when matching')),
2971 ('l', 'files-with-matches', None,
2971 ('l', 'files-with-matches', None,
2972 _('print only filenames and revisions that match')),
2972 _('print only filenames and revisions that match')),
2973 ('n', 'line-number', None, _('print matching line numbers')),
2973 ('n', 'line-number', None, _('print matching line numbers')),
2974 ('r', 'rev', [],
2974 ('r', 'rev', [],
2975 _('only search files changed within revision range'), _('REV')),
2975 _('only search files changed within revision range'), _('REV')),
2976 ('u', 'user', None, _('list the author (long with -v)')),
2976 ('u', 'user', None, _('list the author (long with -v)')),
2977 ('d', 'date', None, _('list the date (short with -q)')),
2977 ('d', 'date', None, _('list the date (short with -q)')),
2978 ] + walkopts,
2978 ] + walkopts,
2979 _('[OPTION]... PATTERN [FILE]...'))
2979 _('[OPTION]... PATTERN [FILE]...'))
2980 def grep(ui, repo, pattern, *pats, **opts):
2980 def grep(ui, repo, pattern, *pats, **opts):
2981 """search for a pattern in specified files and revisions
2981 """search for a pattern in specified files and revisions
2982
2982
2983 Search revisions of files for a regular expression.
2983 Search revisions of files for a regular expression.
2984
2984
2985 This command behaves differently than Unix grep. It only accepts
2985 This command behaves differently than Unix grep. It only accepts
2986 Python/Perl regexps. It searches repository history, not the
2986 Python/Perl regexps. It searches repository history, not the
2987 working directory. It always prints the revision number in which a
2987 working directory. It always prints the revision number in which a
2988 match appears.
2988 match appears.
2989
2989
2990 By default, grep only prints output for the first revision of a
2990 By default, grep only prints output for the first revision of a
2991 file in which it finds a match. To get it to print every revision
2991 file in which it finds a match. To get it to print every revision
2992 that contains a change in match status ("-" for a match that
2992 that contains a change in match status ("-" for a match that
2993 becomes a non-match, or "+" for a non-match that becomes a match),
2993 becomes a non-match, or "+" for a non-match that becomes a match),
2994 use the --all flag.
2994 use the --all flag.
2995
2995
2996 Returns 0 if a match is found, 1 otherwise.
2996 Returns 0 if a match is found, 1 otherwise.
2997 """
2997 """
2998 reflags = re.M
2998 reflags = re.M
2999 if opts.get('ignore_case'):
2999 if opts.get('ignore_case'):
3000 reflags |= re.I
3000 reflags |= re.I
3001 try:
3001 try:
3002 regexp = re.compile(pattern, reflags)
3002 regexp = re.compile(pattern, reflags)
3003 except re.error, inst:
3003 except re.error, inst:
3004 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3004 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3005 return 1
3005 return 1
3006 sep, eol = ':', '\n'
3006 sep, eol = ':', '\n'
3007 if opts.get('print0'):
3007 if opts.get('print0'):
3008 sep = eol = '\0'
3008 sep = eol = '\0'
3009
3009
3010 getfile = util.lrucachefunc(repo.file)
3010 getfile = util.lrucachefunc(repo.file)
3011
3011
3012 def matchlines(body):
3012 def matchlines(body):
3013 begin = 0
3013 begin = 0
3014 linenum = 0
3014 linenum = 0
3015 while begin < len(body):
3015 while begin < len(body):
3016 match = regexp.search(body, begin)
3016 match = regexp.search(body, begin)
3017 if not match:
3017 if not match:
3018 break
3018 break
3019 mstart, mend = match.span()
3019 mstart, mend = match.span()
3020 linenum += body.count('\n', begin, mstart) + 1
3020 linenum += body.count('\n', begin, mstart) + 1
3021 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3021 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3022 begin = body.find('\n', mend) + 1 or len(body) + 1
3022 begin = body.find('\n', mend) + 1 or len(body) + 1
3023 lend = begin - 1
3023 lend = begin - 1
3024 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3024 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3025
3025
3026 class linestate(object):
3026 class linestate(object):
3027 def __init__(self, line, linenum, colstart, colend):
3027 def __init__(self, line, linenum, colstart, colend):
3028 self.line = line
3028 self.line = line
3029 self.linenum = linenum
3029 self.linenum = linenum
3030 self.colstart = colstart
3030 self.colstart = colstart
3031 self.colend = colend
3031 self.colend = colend
3032
3032
3033 def __hash__(self):
3033 def __hash__(self):
3034 return hash((self.linenum, self.line))
3034 return hash((self.linenum, self.line))
3035
3035
3036 def __eq__(self, other):
3036 def __eq__(self, other):
3037 return self.line == other.line
3037 return self.line == other.line
3038
3038
3039 matches = {}
3039 matches = {}
3040 copies = {}
3040 copies = {}
3041 def grepbody(fn, rev, body):
3041 def grepbody(fn, rev, body):
3042 matches[rev].setdefault(fn, [])
3042 matches[rev].setdefault(fn, [])
3043 m = matches[rev][fn]
3043 m = matches[rev][fn]
3044 for lnum, cstart, cend, line in matchlines(body):
3044 for lnum, cstart, cend, line in matchlines(body):
3045 s = linestate(line, lnum, cstart, cend)
3045 s = linestate(line, lnum, cstart, cend)
3046 m.append(s)
3046 m.append(s)
3047
3047
3048 def difflinestates(a, b):
3048 def difflinestates(a, b):
3049 sm = difflib.SequenceMatcher(None, a, b)
3049 sm = difflib.SequenceMatcher(None, a, b)
3050 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3050 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3051 if tag == 'insert':
3051 if tag == 'insert':
3052 for i in xrange(blo, bhi):
3052 for i in xrange(blo, bhi):
3053 yield ('+', b[i])
3053 yield ('+', b[i])
3054 elif tag == 'delete':
3054 elif tag == 'delete':
3055 for i in xrange(alo, ahi):
3055 for i in xrange(alo, ahi):
3056 yield ('-', a[i])
3056 yield ('-', a[i])
3057 elif tag == 'replace':
3057 elif tag == 'replace':
3058 for i in xrange(alo, ahi):
3058 for i in xrange(alo, ahi):
3059 yield ('-', a[i])
3059 yield ('-', a[i])
3060 for i in xrange(blo, bhi):
3060 for i in xrange(blo, bhi):
3061 yield ('+', b[i])
3061 yield ('+', b[i])
3062
3062
3063 def display(fn, ctx, pstates, states):
3063 def display(fn, ctx, pstates, states):
3064 rev = ctx.rev()
3064 rev = ctx.rev()
3065 datefunc = ui.quiet and util.shortdate or util.datestr
3065 datefunc = ui.quiet and util.shortdate or util.datestr
3066 found = False
3066 found = False
3067 filerevmatches = {}
3067 filerevmatches = {}
3068 def binary():
3068 def binary():
3069 flog = getfile(fn)
3069 flog = getfile(fn)
3070 return util.binary(flog.read(ctx.filenode(fn)))
3070 return util.binary(flog.read(ctx.filenode(fn)))
3071
3071
3072 if opts.get('all'):
3072 if opts.get('all'):
3073 iter = difflinestates(pstates, states)
3073 iter = difflinestates(pstates, states)
3074 else:
3074 else:
3075 iter = [('', l) for l in states]
3075 iter = [('', l) for l in states]
3076 for change, l in iter:
3076 for change, l in iter:
3077 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3077 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3078 before, match, after = None, None, None
3078 before, match, after = None, None, None
3079
3079
3080 if opts.get('line_number'):
3080 if opts.get('line_number'):
3081 cols.append((str(l.linenum), 'grep.linenumber'))
3081 cols.append((str(l.linenum), 'grep.linenumber'))
3082 if opts.get('all'):
3082 if opts.get('all'):
3083 cols.append((change, 'grep.change'))
3083 cols.append((change, 'grep.change'))
3084 if opts.get('user'):
3084 if opts.get('user'):
3085 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3085 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3086 if opts.get('date'):
3086 if opts.get('date'):
3087 cols.append((datefunc(ctx.date()), 'grep.date'))
3087 cols.append((datefunc(ctx.date()), 'grep.date'))
3088 if opts.get('files_with_matches'):
3088 if opts.get('files_with_matches'):
3089 c = (fn, rev)
3089 c = (fn, rev)
3090 if c in filerevmatches:
3090 if c in filerevmatches:
3091 continue
3091 continue
3092 filerevmatches[c] = 1
3092 filerevmatches[c] = 1
3093 else:
3093 else:
3094 before = l.line[:l.colstart]
3094 before = l.line[:l.colstart]
3095 match = l.line[l.colstart:l.colend]
3095 match = l.line[l.colstart:l.colend]
3096 after = l.line[l.colend:]
3096 after = l.line[l.colend:]
3097 for col, label in cols[:-1]:
3097 for col, label in cols[:-1]:
3098 ui.write(col, label=label)
3098 ui.write(col, label=label)
3099 ui.write(sep, label='grep.sep')
3099 ui.write(sep, label='grep.sep')
3100 ui.write(cols[-1][0], label=cols[-1][1])
3100 ui.write(cols[-1][0], label=cols[-1][1])
3101 if before is not None:
3101 if before is not None:
3102 ui.write(sep, label='grep.sep')
3102 ui.write(sep, label='grep.sep')
3103 if not opts.get('text') and binary():
3103 if not opts.get('text') and binary():
3104 ui.write(" Binary file matches")
3104 ui.write(" Binary file matches")
3105 else:
3105 else:
3106 ui.write(before)
3106 ui.write(before)
3107 ui.write(match, label='grep.match')
3107 ui.write(match, label='grep.match')
3108 ui.write(after)
3108 ui.write(after)
3109 ui.write(eol)
3109 ui.write(eol)
3110 found = True
3110 found = True
3111 return found
3111 return found
3112
3112
3113 skip = {}
3113 skip = {}
3114 revfiles = {}
3114 revfiles = {}
3115 matchfn = scmutil.match(repo[None], pats, opts)
3115 matchfn = scmutil.match(repo[None], pats, opts)
3116 found = False
3116 found = False
3117 follow = opts.get('follow')
3117 follow = opts.get('follow')
3118
3118
3119 def prep(ctx, fns):
3119 def prep(ctx, fns):
3120 rev = ctx.rev()
3120 rev = ctx.rev()
3121 pctx = ctx.p1()
3121 pctx = ctx.p1()
3122 parent = pctx.rev()
3122 parent = pctx.rev()
3123 matches.setdefault(rev, {})
3123 matches.setdefault(rev, {})
3124 matches.setdefault(parent, {})
3124 matches.setdefault(parent, {})
3125 files = revfiles.setdefault(rev, [])
3125 files = revfiles.setdefault(rev, [])
3126 for fn in fns:
3126 for fn in fns:
3127 flog = getfile(fn)
3127 flog = getfile(fn)
3128 try:
3128 try:
3129 fnode = ctx.filenode(fn)
3129 fnode = ctx.filenode(fn)
3130 except error.LookupError:
3130 except error.LookupError:
3131 continue
3131 continue
3132
3132
3133 copied = flog.renamed(fnode)
3133 copied = flog.renamed(fnode)
3134 copy = follow and copied and copied[0]
3134 copy = follow and copied and copied[0]
3135 if copy:
3135 if copy:
3136 copies.setdefault(rev, {})[fn] = copy
3136 copies.setdefault(rev, {})[fn] = copy
3137 if fn in skip:
3137 if fn in skip:
3138 if copy:
3138 if copy:
3139 skip[copy] = True
3139 skip[copy] = True
3140 continue
3140 continue
3141 files.append(fn)
3141 files.append(fn)
3142
3142
3143 if fn not in matches[rev]:
3143 if fn not in matches[rev]:
3144 grepbody(fn, rev, flog.read(fnode))
3144 grepbody(fn, rev, flog.read(fnode))
3145
3145
3146 pfn = copy or fn
3146 pfn = copy or fn
3147 if pfn not in matches[parent]:
3147 if pfn not in matches[parent]:
3148 try:
3148 try:
3149 fnode = pctx.filenode(pfn)
3149 fnode = pctx.filenode(pfn)
3150 grepbody(pfn, parent, flog.read(fnode))
3150 grepbody(pfn, parent, flog.read(fnode))
3151 except error.LookupError:
3151 except error.LookupError:
3152 pass
3152 pass
3153
3153
3154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3155 rev = ctx.rev()
3155 rev = ctx.rev()
3156 parent = ctx.p1().rev()
3156 parent = ctx.p1().rev()
3157 for fn in sorted(revfiles.get(rev, [])):
3157 for fn in sorted(revfiles.get(rev, [])):
3158 states = matches[rev][fn]
3158 states = matches[rev][fn]
3159 copy = copies.get(rev, {}).get(fn)
3159 copy = copies.get(rev, {}).get(fn)
3160 if fn in skip:
3160 if fn in skip:
3161 if copy:
3161 if copy:
3162 skip[copy] = True
3162 skip[copy] = True
3163 continue
3163 continue
3164 pstates = matches.get(parent, {}).get(copy or fn, [])
3164 pstates = matches.get(parent, {}).get(copy or fn, [])
3165 if pstates or states:
3165 if pstates or states:
3166 r = display(fn, ctx, pstates, states)
3166 r = display(fn, ctx, pstates, states)
3167 found = found or r
3167 found = found or r
3168 if r and not opts.get('all'):
3168 if r and not opts.get('all'):
3169 skip[fn] = True
3169 skip[fn] = True
3170 if copy:
3170 if copy:
3171 skip[copy] = True
3171 skip[copy] = True
3172 del matches[rev]
3172 del matches[rev]
3173 del revfiles[rev]
3173 del revfiles[rev]
3174
3174
3175 return not found
3175 return not found
3176
3176
3177 @command('heads',
3177 @command('heads',
3178 [('r', 'rev', '',
3178 [('r', 'rev', '',
3179 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3179 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3180 ('t', 'topo', False, _('show topological heads only')),
3180 ('t', 'topo', False, _('show topological heads only')),
3181 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3181 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3182 ('c', 'closed', False, _('show normal and closed branch heads')),
3182 ('c', 'closed', False, _('show normal and closed branch heads')),
3183 ] + templateopts,
3183 ] + templateopts,
3184 _('[-ct] [-r STARTREV] [REV]...'))
3184 _('[-ct] [-r STARTREV] [REV]...'))
3185 def heads(ui, repo, *branchrevs, **opts):
3185 def heads(ui, repo, *branchrevs, **opts):
3186 """show current repository heads or show branch heads
3186 """show current repository heads or show branch heads
3187
3187
3188 With no arguments, show all repository branch heads.
3188 With no arguments, show all repository branch heads.
3189
3189
3190 Repository "heads" are changesets with no child changesets. They are
3190 Repository "heads" are changesets with no child changesets. They are
3191 where development generally takes place and are the usual targets
3191 where development generally takes place and are the usual targets
3192 for update and merge operations. Branch heads are changesets that have
3192 for update and merge operations. Branch heads are changesets that have
3193 no child changeset on the same branch.
3193 no child changeset on the same branch.
3194
3194
3195 If one or more REVs are given, only branch heads on the branches
3195 If one or more REVs are given, only branch heads on the branches
3196 associated with the specified changesets are shown. This means
3196 associated with the specified changesets are shown. This means
3197 that you can use :hg:`heads foo` to see the heads on a branch
3197 that you can use :hg:`heads foo` to see the heads on a branch
3198 named ``foo``.
3198 named ``foo``.
3199
3199
3200 If -c/--closed is specified, also show branch heads marked closed
3200 If -c/--closed is specified, also show branch heads marked closed
3201 (see :hg:`commit --close-branch`).
3201 (see :hg:`commit --close-branch`).
3202
3202
3203 If STARTREV is specified, only those heads that are descendants of
3203 If STARTREV is specified, only those heads that are descendants of
3204 STARTREV will be displayed.
3204 STARTREV will be displayed.
3205
3205
3206 If -t/--topo is specified, named branch mechanics will be ignored and only
3206 If -t/--topo is specified, named branch mechanics will be ignored and only
3207 changesets without children will be shown.
3207 changesets without children will be shown.
3208
3208
3209 Returns 0 if matching heads are found, 1 if not.
3209 Returns 0 if matching heads are found, 1 if not.
3210 """
3210 """
3211
3211
3212 start = None
3212 start = None
3213 if 'rev' in opts:
3213 if 'rev' in opts:
3214 start = scmutil.revsingle(repo, opts['rev'], None).node()
3214 start = scmutil.revsingle(repo, opts['rev'], None).node()
3215
3215
3216 if opts.get('topo'):
3216 if opts.get('topo'):
3217 heads = [repo[h] for h in repo.heads(start)]
3217 heads = [repo[h] for h in repo.heads(start)]
3218 else:
3218 else:
3219 heads = []
3219 heads = []
3220 for branch in repo.branchmap():
3220 for branch in repo.branchmap():
3221 heads += repo.branchheads(branch, start, opts.get('closed'))
3221 heads += repo.branchheads(branch, start, opts.get('closed'))
3222 heads = [repo[h] for h in heads]
3222 heads = [repo[h] for h in heads]
3223
3223
3224 if branchrevs:
3224 if branchrevs:
3225 branches = set(repo[br].branch() for br in branchrevs)
3225 branches = set(repo[br].branch() for br in branchrevs)
3226 heads = [h for h in heads if h.branch() in branches]
3226 heads = [h for h in heads if h.branch() in branches]
3227
3227
3228 if opts.get('active') and branchrevs:
3228 if opts.get('active') and branchrevs:
3229 dagheads = repo.heads(start)
3229 dagheads = repo.heads(start)
3230 heads = [h for h in heads if h.node() in dagheads]
3230 heads = [h for h in heads if h.node() in dagheads]
3231
3231
3232 if branchrevs:
3232 if branchrevs:
3233 haveheads = set(h.branch() for h in heads)
3233 haveheads = set(h.branch() for h in heads)
3234 if branches - haveheads:
3234 if branches - haveheads:
3235 headless = ', '.join(b for b in branches - haveheads)
3235 headless = ', '.join(b for b in branches - haveheads)
3236 msg = _('no open branch heads found on branches %s')
3236 msg = _('no open branch heads found on branches %s')
3237 if opts.get('rev'):
3237 if opts.get('rev'):
3238 msg += _(' (started at %s)') % opts['rev']
3238 msg += _(' (started at %s)') % opts['rev']
3239 ui.warn((msg + '\n') % headless)
3239 ui.warn((msg + '\n') % headless)
3240
3240
3241 if not heads:
3241 if not heads:
3242 return 1
3242 return 1
3243
3243
3244 heads = sorted(heads, key=lambda x: -x.rev())
3244 heads = sorted(heads, key=lambda x: -x.rev())
3245 displayer = cmdutil.show_changeset(ui, repo, opts)
3245 displayer = cmdutil.show_changeset(ui, repo, opts)
3246 for ctx in heads:
3246 for ctx in heads:
3247 displayer.show(ctx)
3247 displayer.show(ctx)
3248 displayer.close()
3248 displayer.close()
3249
3249
3250 @command('help',
3250 @command('help',
3251 [('e', 'extension', None, _('show only help for extensions')),
3251 [('e', 'extension', None, _('show only help for extensions')),
3252 ('c', 'command', None, _('show only help for commands')),
3252 ('c', 'command', None, _('show only help for commands')),
3253 ('k', 'keyword', '', _('show topics matching keyword')),
3253 ('k', 'keyword', '', _('show topics matching keyword')),
3254 ],
3254 ],
3255 _('[-ec] [TOPIC]'))
3255 _('[-ec] [TOPIC]'))
3256 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3256 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3257 """show help for a given topic or a help overview
3257 """show help for a given topic or a help overview
3258
3258
3259 With no arguments, print a list of commands with short help messages.
3259 With no arguments, print a list of commands with short help messages.
3260
3260
3261 Given a topic, extension, or command name, print help for that
3261 Given a topic, extension, or command name, print help for that
3262 topic.
3262 topic.
3263
3263
3264 Returns 0 if successful.
3264 Returns 0 if successful.
3265 """
3265 """
3266
3266
3267 textwidth = min(ui.termwidth(), 80) - 2
3267 textwidth = min(ui.termwidth(), 80) - 2
3268
3268
3269 def helpcmd(name):
3269 def helpcmd(name):
3270 try:
3270 try:
3271 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3271 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3272 except error.AmbiguousCommand, inst:
3272 except error.AmbiguousCommand, inst:
3273 # py3k fix: except vars can't be used outside the scope of the
3273 # py3k fix: except vars can't be used outside the scope of the
3274 # except block, nor can be used inside a lambda. python issue4617
3274 # except block, nor can be used inside a lambda. python issue4617
3275 prefix = inst.args[0]
3275 prefix = inst.args[0]
3276 select = lambda c: c.lstrip('^').startswith(prefix)
3276 select = lambda c: c.lstrip('^').startswith(prefix)
3277 rst = helplist(select)
3277 rst = helplist(select)
3278 return rst
3278 return rst
3279
3279
3280 rst = []
3280 rst = []
3281
3281
3282 # check if it's an invalid alias and display its error if it is
3282 # check if it's an invalid alias and display its error if it is
3283 if getattr(entry[0], 'badalias', False):
3283 if getattr(entry[0], 'badalias', False):
3284 if not unknowncmd:
3284 if not unknowncmd:
3285 ui.pushbuffer()
3285 ui.pushbuffer()
3286 entry[0](ui)
3286 entry[0](ui)
3287 rst.append(ui.popbuffer())
3287 rst.append(ui.popbuffer())
3288 return rst
3288 return rst
3289
3289
3290 # synopsis
3290 # synopsis
3291 if len(entry) > 2:
3291 if len(entry) > 2:
3292 if entry[2].startswith('hg'):
3292 if entry[2].startswith('hg'):
3293 rst.append("%s\n" % entry[2])
3293 rst.append("%s\n" % entry[2])
3294 else:
3294 else:
3295 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3295 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3296 else:
3296 else:
3297 rst.append('hg %s\n' % aliases[0])
3297 rst.append('hg %s\n' % aliases[0])
3298 # aliases
3298 # aliases
3299 if full and not ui.quiet and len(aliases) > 1:
3299 if full and not ui.quiet and len(aliases) > 1:
3300 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3300 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3301 rst.append('\n')
3301 rst.append('\n')
3302
3302
3303 # description
3303 # description
3304 doc = gettext(entry[0].__doc__)
3304 doc = gettext(entry[0].__doc__)
3305 if not doc:
3305 if not doc:
3306 doc = _("(no help text available)")
3306 doc = _("(no help text available)")
3307 if util.safehasattr(entry[0], 'definition'): # aliased command
3307 if util.safehasattr(entry[0], 'definition'): # aliased command
3308 if entry[0].definition.startswith('!'): # shell alias
3308 if entry[0].definition.startswith('!'): # shell alias
3309 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3309 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3310 else:
3310 else:
3311 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3311 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3312 doc = doc.splitlines(True)
3312 doc = doc.splitlines(True)
3313 if ui.quiet or not full:
3313 if ui.quiet or not full:
3314 rst.append(doc[0])
3314 rst.append(doc[0])
3315 else:
3315 else:
3316 rst.extend(doc)
3316 rst.extend(doc)
3317 rst.append('\n')
3317 rst.append('\n')
3318
3318
3319 # check if this command shadows a non-trivial (multi-line)
3319 # check if this command shadows a non-trivial (multi-line)
3320 # extension help text
3320 # extension help text
3321 try:
3321 try:
3322 mod = extensions.find(name)
3322 mod = extensions.find(name)
3323 doc = gettext(mod.__doc__) or ''
3323 doc = gettext(mod.__doc__) or ''
3324 if '\n' in doc.strip():
3324 if '\n' in doc.strip():
3325 msg = _('use "hg help -e %s" to show help for '
3325 msg = _('use "hg help -e %s" to show help for '
3326 'the %s extension') % (name, name)
3326 'the %s extension') % (name, name)
3327 rst.append('\n%s\n' % msg)
3327 rst.append('\n%s\n' % msg)
3328 except KeyError:
3328 except KeyError:
3329 pass
3329 pass
3330
3330
3331 # options
3331 # options
3332 if not ui.quiet and entry[1]:
3332 if not ui.quiet and entry[1]:
3333 rst.append('\n%s\n\n' % _("options:"))
3333 rst.append('\n%s\n\n' % _("options:"))
3334 rst.append(help.optrst(entry[1], ui.verbose))
3334 rst.append(help.optrst(entry[1], ui.verbose))
3335
3335
3336 if ui.verbose:
3336 if ui.verbose:
3337 rst.append('\n%s\n\n' % _("global options:"))
3337 rst.append('\n%s\n\n' % _("global options:"))
3338 rst.append(help.optrst(globalopts, ui.verbose))
3338 rst.append(help.optrst(globalopts, ui.verbose))
3339
3339
3340 if not ui.verbose:
3340 if not ui.verbose:
3341 if not full:
3341 if not full:
3342 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3342 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3343 % name)
3343 % name)
3344 elif not ui.quiet:
3344 elif not ui.quiet:
3345 omitted = _('use "hg -v help %s" to show more complete'
3345 omitted = _('use "hg -v help %s" to show more complete'
3346 ' help and the global options') % name
3346 ' help and the global options') % name
3347 notomitted = _('use "hg -v help %s" to show'
3347 notomitted = _('use "hg -v help %s" to show'
3348 ' the global options') % name
3348 ' the global options') % name
3349 help.indicateomitted(rst, omitted, notomitted)
3349 help.indicateomitted(rst, omitted, notomitted)
3350
3350
3351 return rst
3351 return rst
3352
3352
3353
3353
3354 def helplist(select=None):
3354 def helplist(select=None):
3355 # list of commands
3355 # list of commands
3356 if name == "shortlist":
3356 if name == "shortlist":
3357 header = _('basic commands:\n\n')
3357 header = _('basic commands:\n\n')
3358 else:
3358 else:
3359 header = _('list of commands:\n\n')
3359 header = _('list of commands:\n\n')
3360
3360
3361 h = {}
3361 h = {}
3362 cmds = {}
3362 cmds = {}
3363 for c, e in table.iteritems():
3363 for c, e in table.iteritems():
3364 f = c.split("|", 1)[0]
3364 f = c.split("|", 1)[0]
3365 if select and not select(f):
3365 if select and not select(f):
3366 continue
3366 continue
3367 if (not select and name != 'shortlist' and
3367 if (not select and name != 'shortlist' and
3368 e[0].__module__ != __name__):
3368 e[0].__module__ != __name__):
3369 continue
3369 continue
3370 if name == "shortlist" and not f.startswith("^"):
3370 if name == "shortlist" and not f.startswith("^"):
3371 continue
3371 continue
3372 f = f.lstrip("^")
3372 f = f.lstrip("^")
3373 if not ui.debugflag and f.startswith("debug"):
3373 if not ui.debugflag and f.startswith("debug"):
3374 continue
3374 continue
3375 doc = e[0].__doc__
3375 doc = e[0].__doc__
3376 if doc and 'DEPRECATED' in doc and not ui.verbose:
3376 if doc and 'DEPRECATED' in doc and not ui.verbose:
3377 continue
3377 continue
3378 doc = gettext(doc)
3378 doc = gettext(doc)
3379 if not doc:
3379 if not doc:
3380 doc = _("(no help text available)")
3380 doc = _("(no help text available)")
3381 h[f] = doc.splitlines()[0].rstrip()
3381 h[f] = doc.splitlines()[0].rstrip()
3382 cmds[f] = c.lstrip("^")
3382 cmds[f] = c.lstrip("^")
3383
3383
3384 rst = []
3384 rst = []
3385 if not h:
3385 if not h:
3386 if not ui.quiet:
3386 if not ui.quiet:
3387 rst.append(_('no commands defined\n'))
3387 rst.append(_('no commands defined\n'))
3388 return rst
3388 return rst
3389
3389
3390 if not ui.quiet:
3390 if not ui.quiet:
3391 rst.append(header)
3391 rst.append(header)
3392 fns = sorted(h)
3392 fns = sorted(h)
3393 for f in fns:
3393 for f in fns:
3394 if ui.verbose:
3394 if ui.verbose:
3395 commands = cmds[f].replace("|",", ")
3395 commands = cmds[f].replace("|",", ")
3396 rst.append(" :%s: %s\n" % (commands, h[f]))
3396 rst.append(" :%s: %s\n" % (commands, h[f]))
3397 else:
3397 else:
3398 rst.append(' :%s: %s\n' % (f, h[f]))
3398 rst.append(' :%s: %s\n' % (f, h[f]))
3399
3399
3400 if not name:
3400 if not name:
3401 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3401 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3402 if exts:
3402 if exts:
3403 rst.append('\n')
3403 rst.append('\n')
3404 rst.extend(exts)
3404 rst.extend(exts)
3405
3405
3406 rst.append(_("\nadditional help topics:\n\n"))
3406 rst.append(_("\nadditional help topics:\n\n"))
3407 topics = []
3407 topics = []
3408 for names, header, doc in help.helptable:
3408 for names, header, doc in help.helptable:
3409 topics.append((names[0], header))
3409 topics.append((names[0], header))
3410 for t, desc in topics:
3410 for t, desc in topics:
3411 rst.append(" :%s: %s\n" % (t, desc))
3411 rst.append(" :%s: %s\n" % (t, desc))
3412
3412
3413 optlist = []
3413 optlist = []
3414 if not ui.quiet:
3414 if not ui.quiet:
3415 if ui.verbose:
3415 if ui.verbose:
3416 optlist.append((_("global options:"), globalopts))
3416 optlist.append((_("global options:"), globalopts))
3417 if name == 'shortlist':
3417 if name == 'shortlist':
3418 optlist.append((_('use "hg help" for the full list '
3418 optlist.append((_('use "hg help" for the full list '
3419 'of commands'), ()))
3419 'of commands'), ()))
3420 else:
3420 else:
3421 if name == 'shortlist':
3421 if name == 'shortlist':
3422 msg = _('use "hg help" for the full list of commands '
3422 msg = _('use "hg help" for the full list of commands '
3423 'or "hg -v" for details')
3423 'or "hg -v" for details')
3424 elif name and not full:
3424 elif name and not full:
3425 msg = _('use "hg help %s" to show the full help '
3425 msg = _('use "hg help %s" to show the full help '
3426 'text') % name
3426 'text') % name
3427 else:
3427 else:
3428 msg = _('use "hg -v help%s" to show builtin aliases and '
3428 msg = _('use "hg -v help%s" to show builtin aliases and '
3429 'global options') % (name and " " + name or "")
3429 'global options') % (name and " " + name or "")
3430 optlist.append((msg, ()))
3430 optlist.append((msg, ()))
3431
3431
3432 if optlist:
3432 if optlist:
3433 for title, options in optlist:
3433 for title, options in optlist:
3434 rst.append('\n%s\n' % title)
3434 rst.append('\n%s\n' % title)
3435 if options:
3435 if options:
3436 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3436 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3437 return rst
3437 return rst
3438
3438
3439 def helptopic(name):
3439 def helptopic(name):
3440 for names, header, doc in help.helptable:
3440 for names, header, doc in help.helptable:
3441 if name in names:
3441 if name in names:
3442 break
3442 break
3443 else:
3443 else:
3444 raise error.UnknownCommand(name)
3444 raise error.UnknownCommand(name)
3445
3445
3446 rst = ["%s\n\n" % header]
3446 rst = ["%s\n\n" % header]
3447 # description
3447 # description
3448 if not doc:
3448 if not doc:
3449 rst.append(" %s\n" % _("(no help text available)"))
3449 rst.append(" %s\n" % _("(no help text available)"))
3450 if util.safehasattr(doc, '__call__'):
3450 if util.safehasattr(doc, '__call__'):
3451 rst += [" %s\n" % l for l in doc().splitlines()]
3451 rst += [" %s\n" % l for l in doc().splitlines()]
3452
3452
3453 if not ui.verbose:
3453 if not ui.verbose:
3454 omitted = (_('use "hg help -v %s" to show more complete help') %
3454 omitted = (_('use "hg help -v %s" to show more complete help') %
3455 name)
3455 name)
3456 help.indicateomitted(rst, omitted)
3456 help.indicateomitted(rst, omitted)
3457
3457
3458 try:
3458 try:
3459 cmdutil.findcmd(name, table)
3459 cmdutil.findcmd(name, table)
3460 rst.append(_('\nuse "hg help -c %s" to see help for '
3460 rst.append(_('\nuse "hg help -c %s" to see help for '
3461 'the %s command\n') % (name, name))
3461 'the %s command\n') % (name, name))
3462 except error.UnknownCommand:
3462 except error.UnknownCommand:
3463 pass
3463 pass
3464 return rst
3464 return rst
3465
3465
3466 def helpext(name):
3466 def helpext(name):
3467 try:
3467 try:
3468 mod = extensions.find(name)
3468 mod = extensions.find(name)
3469 doc = gettext(mod.__doc__) or _('no help text available')
3469 doc = gettext(mod.__doc__) or _('no help text available')
3470 except KeyError:
3470 except KeyError:
3471 mod = None
3471 mod = None
3472 doc = extensions.disabledext(name)
3472 doc = extensions.disabledext(name)
3473 if not doc:
3473 if not doc:
3474 raise error.UnknownCommand(name)
3474 raise error.UnknownCommand(name)
3475
3475
3476 if '\n' not in doc:
3476 if '\n' not in doc:
3477 head, tail = doc, ""
3477 head, tail = doc, ""
3478 else:
3478 else:
3479 head, tail = doc.split('\n', 1)
3479 head, tail = doc.split('\n', 1)
3480 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3480 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3481 if tail:
3481 if tail:
3482 rst.extend(tail.splitlines(True))
3482 rst.extend(tail.splitlines(True))
3483 rst.append('\n')
3483 rst.append('\n')
3484
3484
3485 if not ui.verbose:
3485 if not ui.verbose:
3486 omitted = (_('use "hg help -v %s" to show more complete help') %
3486 omitted = (_('use "hg help -v %s" to show more complete help') %
3487 name)
3487 name)
3488 help.indicateomitted(rst, omitted)
3488 help.indicateomitted(rst, omitted)
3489
3489
3490 if mod:
3490 if mod:
3491 try:
3491 try:
3492 ct = mod.cmdtable
3492 ct = mod.cmdtable
3493 except AttributeError:
3493 except AttributeError:
3494 ct = {}
3494 ct = {}
3495 modcmds = set([c.split('|', 1)[0] for c in ct])
3495 modcmds = set([c.split('|', 1)[0] for c in ct])
3496 rst.extend(helplist(modcmds.__contains__))
3496 rst.extend(helplist(modcmds.__contains__))
3497 else:
3497 else:
3498 rst.append(_('use "hg help extensions" for information on enabling '
3498 rst.append(_('use "hg help extensions" for information on enabling '
3499 'extensions\n'))
3499 'extensions\n'))
3500 return rst
3500 return rst
3501
3501
3502 def helpextcmd(name):
3502 def helpextcmd(name):
3503 cmd, ext, mod = extensions.disabledcmd(ui, name,
3503 cmd, ext, mod = extensions.disabledcmd(ui, name,
3504 ui.configbool('ui', 'strict'))
3504 ui.configbool('ui', 'strict'))
3505 doc = gettext(mod.__doc__).splitlines()[0]
3505 doc = gettext(mod.__doc__).splitlines()[0]
3506
3506
3507 rst = help.listexts(_("'%s' is provided by the following "
3507 rst = help.listexts(_("'%s' is provided by the following "
3508 "extension:") % cmd, {ext: doc}, indent=4)
3508 "extension:") % cmd, {ext: doc}, indent=4)
3509 rst.append('\n')
3509 rst.append('\n')
3510 rst.append(_('use "hg help extensions" for information on enabling '
3510 rst.append(_('use "hg help extensions" for information on enabling '
3511 'extensions\n'))
3511 'extensions\n'))
3512 return rst
3512 return rst
3513
3513
3514
3514
3515 rst = []
3515 rst = []
3516 kw = opts.get('keyword')
3516 kw = opts.get('keyword')
3517 if kw:
3517 if kw:
3518 matches = help.topicmatch(kw)
3518 matches = help.topicmatch(kw)
3519 for t, title in (('topics', _('Topics')),
3519 for t, title in (('topics', _('Topics')),
3520 ('commands', _('Commands')),
3520 ('commands', _('Commands')),
3521 ('extensions', _('Extensions')),
3521 ('extensions', _('Extensions')),
3522 ('extensioncommands', _('Extension Commands'))):
3522 ('extensioncommands', _('Extension Commands'))):
3523 if matches[t]:
3523 if matches[t]:
3524 rst.append('%s:\n\n' % title)
3524 rst.append('%s:\n\n' % title)
3525 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3525 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3526 rst.append('\n')
3526 rst.append('\n')
3527 elif name and name != 'shortlist':
3527 elif name and name != 'shortlist':
3528 i = None
3528 i = None
3529 if unknowncmd:
3529 if unknowncmd:
3530 queries = (helpextcmd,)
3530 queries = (helpextcmd,)
3531 elif opts.get('extension'):
3531 elif opts.get('extension'):
3532 queries = (helpext,)
3532 queries = (helpext,)
3533 elif opts.get('command'):
3533 elif opts.get('command'):
3534 queries = (helpcmd,)
3534 queries = (helpcmd,)
3535 else:
3535 else:
3536 queries = (helptopic, helpcmd, helpext, helpextcmd)
3536 queries = (helptopic, helpcmd, helpext, helpextcmd)
3537 for f in queries:
3537 for f in queries:
3538 try:
3538 try:
3539 rst = f(name)
3539 rst = f(name)
3540 i = None
3540 i = None
3541 break
3541 break
3542 except error.UnknownCommand, inst:
3542 except error.UnknownCommand, inst:
3543 i = inst
3543 i = inst
3544 if i:
3544 if i:
3545 raise i
3545 raise i
3546 else:
3546 else:
3547 # program name
3547 # program name
3548 if not ui.quiet:
3548 if not ui.quiet:
3549 rst = [_("Mercurial Distributed SCM\n"), '\n']
3549 rst = [_("Mercurial Distributed SCM\n"), '\n']
3550 rst.extend(helplist())
3550 rst.extend(helplist())
3551
3551
3552 keep = ui.verbose and ['verbose'] or []
3552 keep = ui.verbose and ['verbose'] or []
3553 text = ''.join(rst)
3553 text = ''.join(rst)
3554 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3554 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3555 if 'verbose' in pruned:
3555 if 'verbose' in pruned:
3556 keep.append('omitted')
3556 keep.append('omitted')
3557 else:
3557 else:
3558 keep.append('notomitted')
3558 keep.append('notomitted')
3559 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3559 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3560 ui.write(formatted)
3560 ui.write(formatted)
3561
3561
3562
3562
3563 @command('identify|id',
3563 @command('identify|id',
3564 [('r', 'rev', '',
3564 [('r', 'rev', '',
3565 _('identify the specified revision'), _('REV')),
3565 _('identify the specified revision'), _('REV')),
3566 ('n', 'num', None, _('show local revision number')),
3566 ('n', 'num', None, _('show local revision number')),
3567 ('i', 'id', None, _('show global revision id')),
3567 ('i', 'id', None, _('show global revision id')),
3568 ('b', 'branch', None, _('show branch')),
3568 ('b', 'branch', None, _('show branch')),
3569 ('t', 'tags', None, _('show tags')),
3569 ('t', 'tags', None, _('show tags')),
3570 ('B', 'bookmarks', None, _('show bookmarks')),
3570 ('B', 'bookmarks', None, _('show bookmarks')),
3571 ] + remoteopts,
3571 ] + remoteopts,
3572 _('[-nibtB] [-r REV] [SOURCE]'))
3572 _('[-nibtB] [-r REV] [SOURCE]'))
3573 def identify(ui, repo, source=None, rev=None,
3573 def identify(ui, repo, source=None, rev=None,
3574 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3574 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3575 """identify the working copy or specified revision
3575 """identify the working copy or specified revision
3576
3576
3577 Print a summary identifying the repository state at REV using one or
3577 Print a summary identifying the repository state at REV using one or
3578 two parent hash identifiers, followed by a "+" if the working
3578 two parent hash identifiers, followed by a "+" if the working
3579 directory has uncommitted changes, the branch name (if not default),
3579 directory has uncommitted changes, the branch name (if not default),
3580 a list of tags, and a list of bookmarks.
3580 a list of tags, and a list of bookmarks.
3581
3581
3582 When REV is not given, print a summary of the current state of the
3582 When REV is not given, print a summary of the current state of the
3583 repository.
3583 repository.
3584
3584
3585 Specifying a path to a repository root or Mercurial bundle will
3585 Specifying a path to a repository root or Mercurial bundle will
3586 cause lookup to operate on that repository/bundle.
3586 cause lookup to operate on that repository/bundle.
3587
3587
3588 .. container:: verbose
3588 .. container:: verbose
3589
3589
3590 Examples:
3590 Examples:
3591
3591
3592 - generate a build identifier for the working directory::
3592 - generate a build identifier for the working directory::
3593
3593
3594 hg id --id > build-id.dat
3594 hg id --id > build-id.dat
3595
3595
3596 - find the revision corresponding to a tag::
3596 - find the revision corresponding to a tag::
3597
3597
3598 hg id -n -r 1.3
3598 hg id -n -r 1.3
3599
3599
3600 - check the most recent revision of a remote repository::
3600 - check the most recent revision of a remote repository::
3601
3601
3602 hg id -r tip http://selenic.com/hg/
3602 hg id -r tip http://selenic.com/hg/
3603
3603
3604 Returns 0 if successful.
3604 Returns 0 if successful.
3605 """
3605 """
3606
3606
3607 if not repo and not source:
3607 if not repo and not source:
3608 raise util.Abort(_("there is no Mercurial repository here "
3608 raise util.Abort(_("there is no Mercurial repository here "
3609 "(.hg not found)"))
3609 "(.hg not found)"))
3610
3610
3611 hexfunc = ui.debugflag and hex or short
3611 hexfunc = ui.debugflag and hex or short
3612 default = not (num or id or branch or tags or bookmarks)
3612 default = not (num or id or branch or tags or bookmarks)
3613 output = []
3613 output = []
3614 revs = []
3614 revs = []
3615
3615
3616 if source:
3616 if source:
3617 source, branches = hg.parseurl(ui.expandpath(source))
3617 source, branches = hg.parseurl(ui.expandpath(source))
3618 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3618 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3619 repo = peer.local()
3619 repo = peer.local()
3620 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3620 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3621
3621
3622 if not repo:
3622 if not repo:
3623 if num or branch or tags:
3623 if num or branch or tags:
3624 raise util.Abort(
3624 raise util.Abort(
3625 _("can't query remote revision number, branch, or tags"))
3625 _("can't query remote revision number, branch, or tags"))
3626 if not rev and revs:
3626 if not rev and revs:
3627 rev = revs[0]
3627 rev = revs[0]
3628 if not rev:
3628 if not rev:
3629 rev = "tip"
3629 rev = "tip"
3630
3630
3631 remoterev = peer.lookup(rev)
3631 remoterev = peer.lookup(rev)
3632 if default or id:
3632 if default or id:
3633 output = [hexfunc(remoterev)]
3633 output = [hexfunc(remoterev)]
3634
3634
3635 def getbms():
3635 def getbms():
3636 bms = []
3636 bms = []
3637
3637
3638 if 'bookmarks' in peer.listkeys('namespaces'):
3638 if 'bookmarks' in peer.listkeys('namespaces'):
3639 hexremoterev = hex(remoterev)
3639 hexremoterev = hex(remoterev)
3640 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3640 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3641 if bmr == hexremoterev]
3641 if bmr == hexremoterev]
3642
3642
3643 return sorted(bms)
3643 return sorted(bms)
3644
3644
3645 if bookmarks:
3645 if bookmarks:
3646 output.extend(getbms())
3646 output.extend(getbms())
3647 elif default and not ui.quiet:
3647 elif default and not ui.quiet:
3648 # multiple bookmarks for a single parent separated by '/'
3648 # multiple bookmarks for a single parent separated by '/'
3649 bm = '/'.join(getbms())
3649 bm = '/'.join(getbms())
3650 if bm:
3650 if bm:
3651 output.append(bm)
3651 output.append(bm)
3652 else:
3652 else:
3653 if not rev:
3653 if not rev:
3654 ctx = repo[None]
3654 ctx = repo[None]
3655 parents = ctx.parents()
3655 parents = ctx.parents()
3656 changed = ""
3656 changed = ""
3657 if default or id or num:
3657 if default or id or num:
3658 if (util.any(repo.status())
3658 if (util.any(repo.status())
3659 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3659 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3660 changed = '+'
3660 changed = '+'
3661 if default or id:
3661 if default or id:
3662 output = ["%s%s" %
3662 output = ["%s%s" %
3663 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3663 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3664 if num:
3664 if num:
3665 output.append("%s%s" %
3665 output.append("%s%s" %
3666 ('+'.join([str(p.rev()) for p in parents]), changed))
3666 ('+'.join([str(p.rev()) for p in parents]), changed))
3667 else:
3667 else:
3668 ctx = scmutil.revsingle(repo, rev)
3668 ctx = scmutil.revsingle(repo, rev)
3669 if default or id:
3669 if default or id:
3670 output = [hexfunc(ctx.node())]
3670 output = [hexfunc(ctx.node())]
3671 if num:
3671 if num:
3672 output.append(str(ctx.rev()))
3672 output.append(str(ctx.rev()))
3673
3673
3674 if default and not ui.quiet:
3674 if default and not ui.quiet:
3675 b = ctx.branch()
3675 b = ctx.branch()
3676 if b != 'default':
3676 if b != 'default':
3677 output.append("(%s)" % b)
3677 output.append("(%s)" % b)
3678
3678
3679 # multiple tags for a single parent separated by '/'
3679 # multiple tags for a single parent separated by '/'
3680 t = '/'.join(ctx.tags())
3680 t = '/'.join(ctx.tags())
3681 if t:
3681 if t:
3682 output.append(t)
3682 output.append(t)
3683
3683
3684 # multiple bookmarks for a single parent separated by '/'
3684 # multiple bookmarks for a single parent separated by '/'
3685 bm = '/'.join(ctx.bookmarks())
3685 bm = '/'.join(ctx.bookmarks())
3686 if bm:
3686 if bm:
3687 output.append(bm)
3687 output.append(bm)
3688 else:
3688 else:
3689 if branch:
3689 if branch:
3690 output.append(ctx.branch())
3690 output.append(ctx.branch())
3691
3691
3692 if tags:
3692 if tags:
3693 output.extend(ctx.tags())
3693 output.extend(ctx.tags())
3694
3694
3695 if bookmarks:
3695 if bookmarks:
3696 output.extend(ctx.bookmarks())
3696 output.extend(ctx.bookmarks())
3697
3697
3698 ui.write("%s\n" % ' '.join(output))
3698 ui.write("%s\n" % ' '.join(output))
3699
3699
3700 @command('import|patch',
3700 @command('import|patch',
3701 [('p', 'strip', 1,
3701 [('p', 'strip', 1,
3702 _('directory strip option for patch. This has the same '
3702 _('directory strip option for patch. This has the same '
3703 'meaning as the corresponding patch option'), _('NUM')),
3703 'meaning as the corresponding patch option'), _('NUM')),
3704 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3704 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3705 ('e', 'edit', False, _('invoke editor on commit messages')),
3705 ('e', 'edit', False, _('invoke editor on commit messages')),
3706 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3706 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3707 ('', 'no-commit', None,
3707 ('', 'no-commit', None,
3708 _("don't commit, just update the working directory")),
3708 _("don't commit, just update the working directory")),
3709 ('', 'bypass', None,
3709 ('', 'bypass', None,
3710 _("apply patch without touching the working directory")),
3710 _("apply patch without touching the working directory")),
3711 ('', 'exact', None,
3711 ('', 'exact', None,
3712 _('apply patch to the nodes from which it was generated')),
3712 _('apply patch to the nodes from which it was generated')),
3713 ('', 'import-branch', None,
3713 ('', 'import-branch', None,
3714 _('use any branch information in patch (implied by --exact)'))] +
3714 _('use any branch information in patch (implied by --exact)'))] +
3715 commitopts + commitopts2 + similarityopts,
3715 commitopts + commitopts2 + similarityopts,
3716 _('[OPTION]... PATCH...'))
3716 _('[OPTION]... PATCH...'))
3717 def import_(ui, repo, patch1=None, *patches, **opts):
3717 def import_(ui, repo, patch1=None, *patches, **opts):
3718 """import an ordered set of patches
3718 """import an ordered set of patches
3719
3719
3720 Import a list of patches and commit them individually (unless
3720 Import a list of patches and commit them individually (unless
3721 --no-commit is specified).
3721 --no-commit is specified).
3722
3722
3723 If there are outstanding changes in the working directory, import
3723 If there are outstanding changes in the working directory, import
3724 will abort unless given the -f/--force flag.
3724 will abort unless given the -f/--force flag.
3725
3725
3726 You can import a patch straight from a mail message. Even patches
3726 You can import a patch straight from a mail message. Even patches
3727 as attachments work (to use the body part, it must have type
3727 as attachments work (to use the body part, it must have type
3728 text/plain or text/x-patch). From and Subject headers of email
3728 text/plain or text/x-patch). From and Subject headers of email
3729 message are used as default committer and commit message. All
3729 message are used as default committer and commit message. All
3730 text/plain body parts before first diff are added to commit
3730 text/plain body parts before first diff are added to commit
3731 message.
3731 message.
3732
3732
3733 If the imported patch was generated by :hg:`export`, user and
3733 If the imported patch was generated by :hg:`export`, user and
3734 description from patch override values from message headers and
3734 description from patch override values from message headers and
3735 body. Values given on command line with -m/--message and -u/--user
3735 body. Values given on command line with -m/--message and -u/--user
3736 override these.
3736 override these.
3737
3737
3738 If --exact is specified, import will set the working directory to
3738 If --exact is specified, import will set the working directory to
3739 the parent of each patch before applying it, and will abort if the
3739 the parent of each patch before applying it, and will abort if the
3740 resulting changeset has a different ID than the one recorded in
3740 resulting changeset has a different ID than the one recorded in
3741 the patch. This may happen due to character set problems or other
3741 the patch. This may happen due to character set problems or other
3742 deficiencies in the text patch format.
3742 deficiencies in the text patch format.
3743
3743
3744 Use --bypass to apply and commit patches directly to the
3744 Use --bypass to apply and commit patches directly to the
3745 repository, not touching the working directory. Without --exact,
3745 repository, not touching the working directory. Without --exact,
3746 patches will be applied on top of the working directory parent
3746 patches will be applied on top of the working directory parent
3747 revision.
3747 revision.
3748
3748
3749 With -s/--similarity, hg will attempt to discover renames and
3749 With -s/--similarity, hg will attempt to discover renames and
3750 copies in the patch in the same way as :hg:`addremove`.
3750 copies in the patch in the same way as :hg:`addremove`.
3751
3751
3752 To read a patch from standard input, use "-" as the patch name. If
3752 To read a patch from standard input, use "-" as the patch name. If
3753 a URL is specified, the patch will be downloaded from it.
3753 a URL is specified, the patch will be downloaded from it.
3754 See :hg:`help dates` for a list of formats valid for -d/--date.
3754 See :hg:`help dates` for a list of formats valid for -d/--date.
3755
3755
3756 .. container:: verbose
3756 .. container:: verbose
3757
3757
3758 Examples:
3758 Examples:
3759
3759
3760 - import a traditional patch from a website and detect renames::
3760 - import a traditional patch from a website and detect renames::
3761
3761
3762 hg import -s 80 http://example.com/bugfix.patch
3762 hg import -s 80 http://example.com/bugfix.patch
3763
3763
3764 - import a changeset from an hgweb server::
3764 - import a changeset from an hgweb server::
3765
3765
3766 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3766 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3767
3767
3768 - import all the patches in an Unix-style mbox::
3768 - import all the patches in an Unix-style mbox::
3769
3769
3770 hg import incoming-patches.mbox
3770 hg import incoming-patches.mbox
3771
3771
3772 - attempt to exactly restore an exported changeset (not always
3772 - attempt to exactly restore an exported changeset (not always
3773 possible)::
3773 possible)::
3774
3774
3775 hg import --exact proposed-fix.patch
3775 hg import --exact proposed-fix.patch
3776
3776
3777 Returns 0 on success.
3777 Returns 0 on success.
3778 """
3778 """
3779
3779
3780 if not patch1:
3780 if not patch1:
3781 raise util.Abort(_('need at least one patch to import'))
3781 raise util.Abort(_('need at least one patch to import'))
3782
3782
3783 patches = (patch1,) + patches
3783 patches = (patch1,) + patches
3784
3784
3785 date = opts.get('date')
3785 date = opts.get('date')
3786 if date:
3786 if date:
3787 opts['date'] = util.parsedate(date)
3787 opts['date'] = util.parsedate(date)
3788
3788
3789 editor = cmdutil.commiteditor
3789 editor = cmdutil.commiteditor
3790 if opts.get('edit'):
3790 if opts.get('edit'):
3791 editor = cmdutil.commitforceeditor
3791 editor = cmdutil.commitforceeditor
3792
3792
3793 update = not opts.get('bypass')
3793 update = not opts.get('bypass')
3794 if not update and opts.get('no_commit'):
3794 if not update and opts.get('no_commit'):
3795 raise util.Abort(_('cannot use --no-commit with --bypass'))
3795 raise util.Abort(_('cannot use --no-commit with --bypass'))
3796 try:
3796 try:
3797 sim = float(opts.get('similarity') or 0)
3797 sim = float(opts.get('similarity') or 0)
3798 except ValueError:
3798 except ValueError:
3799 raise util.Abort(_('similarity must be a number'))
3799 raise util.Abort(_('similarity must be a number'))
3800 if sim < 0 or sim > 100:
3800 if sim < 0 or sim > 100:
3801 raise util.Abort(_('similarity must be between 0 and 100'))
3801 raise util.Abort(_('similarity must be between 0 and 100'))
3802 if sim and not update:
3802 if sim and not update:
3803 raise util.Abort(_('cannot use --similarity with --bypass'))
3803 raise util.Abort(_('cannot use --similarity with --bypass'))
3804
3804
3805 if (opts.get('exact') or not opts.get('force')) and update:
3805 if (opts.get('exact') or not opts.get('force')) and update:
3806 cmdutil.bailifchanged(repo)
3806 cmdutil.bailifchanged(repo)
3807
3807
3808 base = opts["base"]
3808 base = opts["base"]
3809 strip = opts["strip"]
3809 strip = opts["strip"]
3810 wlock = lock = tr = None
3810 wlock = lock = tr = None
3811 msgs = []
3811 msgs = []
3812
3812
3813 def checkexact(repo, n, nodeid):
3813 def checkexact(repo, n, nodeid):
3814 if opts.get('exact') and hex(n) != nodeid:
3814 if opts.get('exact') and hex(n) != nodeid:
3815 repo.rollback()
3816 raise util.Abort(_('patch is damaged or loses information'))
3815 raise util.Abort(_('patch is damaged or loses information'))
3817
3816
3818 def tryone(ui, hunk, parents):
3817 def tryone(ui, hunk, parents):
3819 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3818 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3820 patch.extract(ui, hunk)
3819 patch.extract(ui, hunk)
3821
3820
3822 if not tmpname:
3821 if not tmpname:
3823 return (None, None)
3822 return (None, None)
3824 msg = _('applied to working directory')
3823 msg = _('applied to working directory')
3825
3824
3826 try:
3825 try:
3827 cmdline_message = cmdutil.logmessage(ui, opts)
3826 cmdline_message = cmdutil.logmessage(ui, opts)
3828 if cmdline_message:
3827 if cmdline_message:
3829 # pickup the cmdline msg
3828 # pickup the cmdline msg
3830 message = cmdline_message
3829 message = cmdline_message
3831 elif message:
3830 elif message:
3832 # pickup the patch msg
3831 # pickup the patch msg
3833 message = message.strip()
3832 message = message.strip()
3834 else:
3833 else:
3835 # launch the editor
3834 # launch the editor
3836 message = None
3835 message = None
3837 ui.debug('message:\n%s\n' % message)
3836 ui.debug('message:\n%s\n' % message)
3838
3837
3839 if len(parents) == 1:
3838 if len(parents) == 1:
3840 parents.append(repo[nullid])
3839 parents.append(repo[nullid])
3841 if opts.get('exact'):
3840 if opts.get('exact'):
3842 if not nodeid or not p1:
3841 if not nodeid or not p1:
3843 raise util.Abort(_('not a Mercurial patch'))
3842 raise util.Abort(_('not a Mercurial patch'))
3844 p1 = repo[p1]
3843 p1 = repo[p1]
3845 p2 = repo[p2 or nullid]
3844 p2 = repo[p2 or nullid]
3846 elif p2:
3845 elif p2:
3847 try:
3846 try:
3848 p1 = repo[p1]
3847 p1 = repo[p1]
3849 p2 = repo[p2]
3848 p2 = repo[p2]
3850 # Without any options, consider p2 only if the
3849 # Without any options, consider p2 only if the
3851 # patch is being applied on top of the recorded
3850 # patch is being applied on top of the recorded
3852 # first parent.
3851 # first parent.
3853 if p1 != parents[0]:
3852 if p1 != parents[0]:
3854 p1 = parents[0]
3853 p1 = parents[0]
3855 p2 = repo[nullid]
3854 p2 = repo[nullid]
3856 except error.RepoError:
3855 except error.RepoError:
3857 p1, p2 = parents
3856 p1, p2 = parents
3858 else:
3857 else:
3859 p1, p2 = parents
3858 p1, p2 = parents
3860
3859
3861 n = None
3860 n = None
3862 if update:
3861 if update:
3863 if p1 != parents[0]:
3862 if p1 != parents[0]:
3864 hg.clean(repo, p1.node())
3863 hg.clean(repo, p1.node())
3865 if p2 != parents[1]:
3864 if p2 != parents[1]:
3866 repo.setparents(p1.node(), p2.node())
3865 repo.setparents(p1.node(), p2.node())
3867
3866
3868 if opts.get('exact') or opts.get('import_branch'):
3867 if opts.get('exact') or opts.get('import_branch'):
3869 repo.dirstate.setbranch(branch or 'default')
3868 repo.dirstate.setbranch(branch or 'default')
3870
3869
3871 files = set()
3870 files = set()
3872 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3871 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3873 eolmode=None, similarity=sim / 100.0)
3872 eolmode=None, similarity=sim / 100.0)
3874 files = list(files)
3873 files = list(files)
3875 if opts.get('no_commit'):
3874 if opts.get('no_commit'):
3876 if message:
3875 if message:
3877 msgs.append(message)
3876 msgs.append(message)
3878 else:
3877 else:
3879 if opts.get('exact') or p2:
3878 if opts.get('exact') or p2:
3880 # If you got here, you either use --force and know what
3879 # If you got here, you either use --force and know what
3881 # you are doing or used --exact or a merge patch while
3880 # you are doing or used --exact or a merge patch while
3882 # being updated to its first parent.
3881 # being updated to its first parent.
3883 m = None
3882 m = None
3884 else:
3883 else:
3885 m = scmutil.matchfiles(repo, files or [])
3884 m = scmutil.matchfiles(repo, files or [])
3886 n = repo.commit(message, opts.get('user') or user,
3885 n = repo.commit(message, opts.get('user') or user,
3887 opts.get('date') or date, match=m,
3886 opts.get('date') or date, match=m,
3888 editor=editor)
3887 editor=editor)
3889 checkexact(repo, n, nodeid)
3888 checkexact(repo, n, nodeid)
3890 else:
3889 else:
3891 if opts.get('exact') or opts.get('import_branch'):
3890 if opts.get('exact') or opts.get('import_branch'):
3892 branch = branch or 'default'
3891 branch = branch or 'default'
3893 else:
3892 else:
3894 branch = p1.branch()
3893 branch = p1.branch()
3895 store = patch.filestore()
3894 store = patch.filestore()
3896 try:
3895 try:
3897 files = set()
3896 files = set()
3898 try:
3897 try:
3899 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3898 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3900 files, eolmode=None)
3899 files, eolmode=None)
3901 except patch.PatchError, e:
3900 except patch.PatchError, e:
3902 raise util.Abort(str(e))
3901 raise util.Abort(str(e))
3903 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3902 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3904 message,
3903 message,
3905 opts.get('user') or user,
3904 opts.get('user') or user,
3906 opts.get('date') or date,
3905 opts.get('date') or date,
3907 branch, files, store,
3906 branch, files, store,
3908 editor=cmdutil.commiteditor)
3907 editor=cmdutil.commiteditor)
3909 repo.savecommitmessage(memctx.description())
3908 repo.savecommitmessage(memctx.description())
3910 n = memctx.commit()
3909 n = memctx.commit()
3911 checkexact(repo, n, nodeid)
3910 checkexact(repo, n, nodeid)
3912 finally:
3911 finally:
3913 store.close()
3912 store.close()
3914 if n:
3913 if n:
3915 # i18n: refers to a short changeset id
3914 # i18n: refers to a short changeset id
3916 msg = _('created %s') % short(n)
3915 msg = _('created %s') % short(n)
3917 return (msg, n)
3916 return (msg, n)
3918 finally:
3917 finally:
3919 os.unlink(tmpname)
3918 os.unlink(tmpname)
3920
3919
3921 try:
3920 try:
3922 try:
3921 try:
3923 wlock = repo.wlock()
3922 wlock = repo.wlock()
3924 if not opts.get('no_commit'):
3923 if not opts.get('no_commit'):
3925 lock = repo.lock()
3924 lock = repo.lock()
3926 tr = repo.transaction('import')
3925 tr = repo.transaction('import')
3927 parents = repo.parents()
3926 parents = repo.parents()
3928 for patchurl in patches:
3927 for patchurl in patches:
3929 if patchurl == '-':
3928 if patchurl == '-':
3930 ui.status(_('applying patch from stdin\n'))
3929 ui.status(_('applying patch from stdin\n'))
3931 patchfile = ui.fin
3930 patchfile = ui.fin
3932 patchurl = 'stdin' # for error message
3931 patchurl = 'stdin' # for error message
3933 else:
3932 else:
3934 patchurl = os.path.join(base, patchurl)
3933 patchurl = os.path.join(base, patchurl)
3935 ui.status(_('applying %s\n') % patchurl)
3934 ui.status(_('applying %s\n') % patchurl)
3936 patchfile = hg.openpath(ui, patchurl)
3935 patchfile = hg.openpath(ui, patchurl)
3937
3936
3938 haspatch = False
3937 haspatch = False
3939 for hunk in patch.split(patchfile):
3938 for hunk in patch.split(patchfile):
3940 (msg, node) = tryone(ui, hunk, parents)
3939 (msg, node) = tryone(ui, hunk, parents)
3941 if msg:
3940 if msg:
3942 haspatch = True
3941 haspatch = True
3943 ui.note(msg + '\n')
3942 ui.note(msg + '\n')
3944 if update or opts.get('exact'):
3943 if update or opts.get('exact'):
3945 parents = repo.parents()
3944 parents = repo.parents()
3946 else:
3945 else:
3947 parents = [repo[node]]
3946 parents = [repo[node]]
3948
3947
3949 if not haspatch:
3948 if not haspatch:
3950 raise util.Abort(_('%s: no diffs found') % patchurl)
3949 raise util.Abort(_('%s: no diffs found') % patchurl)
3951
3950
3952 if tr:
3951 if tr:
3953 tr.close()
3952 tr.close()
3954 if msgs:
3953 if msgs:
3955 repo.savecommitmessage('\n* * *\n'.join(msgs))
3954 repo.savecommitmessage('\n* * *\n'.join(msgs))
3956 except: # re-raises
3955 except: # re-raises
3957 # wlock.release() indirectly calls dirstate.write(): since
3956 # wlock.release() indirectly calls dirstate.write(): since
3958 # we're crashing, we do not want to change the working dir
3957 # we're crashing, we do not want to change the working dir
3959 # parent after all, so make sure it writes nothing
3958 # parent after all, so make sure it writes nothing
3960 repo.dirstate.invalidate()
3959 repo.dirstate.invalidate()
3961 raise
3960 raise
3962 finally:
3961 finally:
3963 if tr:
3962 if tr:
3964 tr.release()
3963 tr.release()
3965 release(lock, wlock)
3964 release(lock, wlock)
3966
3965
3967 @command('incoming|in',
3966 @command('incoming|in',
3968 [('f', 'force', None,
3967 [('f', 'force', None,
3969 _('run even if remote repository is unrelated')),
3968 _('run even if remote repository is unrelated')),
3970 ('n', 'newest-first', None, _('show newest record first')),
3969 ('n', 'newest-first', None, _('show newest record first')),
3971 ('', 'bundle', '',
3970 ('', 'bundle', '',
3972 _('file to store the bundles into'), _('FILE')),
3971 _('file to store the bundles into'), _('FILE')),
3973 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3972 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3974 ('B', 'bookmarks', False, _("compare bookmarks")),
3973 ('B', 'bookmarks', False, _("compare bookmarks")),
3975 ('b', 'branch', [],
3974 ('b', 'branch', [],
3976 _('a specific branch you would like to pull'), _('BRANCH')),
3975 _('a specific branch you would like to pull'), _('BRANCH')),
3977 ] + logopts + remoteopts + subrepoopts,
3976 ] + logopts + remoteopts + subrepoopts,
3978 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3977 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3979 def incoming(ui, repo, source="default", **opts):
3978 def incoming(ui, repo, source="default", **opts):
3980 """show new changesets found in source
3979 """show new changesets found in source
3981
3980
3982 Show new changesets found in the specified path/URL or the default
3981 Show new changesets found in the specified path/URL or the default
3983 pull location. These are the changesets that would have been pulled
3982 pull location. These are the changesets that would have been pulled
3984 if a pull at the time you issued this command.
3983 if a pull at the time you issued this command.
3985
3984
3986 For remote repository, using --bundle avoids downloading the
3985 For remote repository, using --bundle avoids downloading the
3987 changesets twice if the incoming is followed by a pull.
3986 changesets twice if the incoming is followed by a pull.
3988
3987
3989 See pull for valid source format details.
3988 See pull for valid source format details.
3990
3989
3991 Returns 0 if there are incoming changes, 1 otherwise.
3990 Returns 0 if there are incoming changes, 1 otherwise.
3992 """
3991 """
3993 if opts.get('graph'):
3992 if opts.get('graph'):
3994 cmdutil.checkunsupportedgraphflags([], opts)
3993 cmdutil.checkunsupportedgraphflags([], opts)
3995 def display(other, chlist, displayer):
3994 def display(other, chlist, displayer):
3996 revdag = cmdutil.graphrevs(other, chlist, opts)
3995 revdag = cmdutil.graphrevs(other, chlist, opts)
3997 showparents = [ctx.node() for ctx in repo[None].parents()]
3996 showparents = [ctx.node() for ctx in repo[None].parents()]
3998 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3997 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3999 graphmod.asciiedges)
3998 graphmod.asciiedges)
4000
3999
4001 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4000 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4002 return 0
4001 return 0
4003
4002
4004 if opts.get('bundle') and opts.get('subrepos'):
4003 if opts.get('bundle') and opts.get('subrepos'):
4005 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4004 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4006
4005
4007 if opts.get('bookmarks'):
4006 if opts.get('bookmarks'):
4008 source, branches = hg.parseurl(ui.expandpath(source),
4007 source, branches = hg.parseurl(ui.expandpath(source),
4009 opts.get('branch'))
4008 opts.get('branch'))
4010 other = hg.peer(repo, opts, source)
4009 other = hg.peer(repo, opts, source)
4011 if 'bookmarks' not in other.listkeys('namespaces'):
4010 if 'bookmarks' not in other.listkeys('namespaces'):
4012 ui.warn(_("remote doesn't support bookmarks\n"))
4011 ui.warn(_("remote doesn't support bookmarks\n"))
4013 return 0
4012 return 0
4014 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4013 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4015 return bookmarks.diff(ui, repo, other)
4014 return bookmarks.diff(ui, repo, other)
4016
4015
4017 repo._subtoppath = ui.expandpath(source)
4016 repo._subtoppath = ui.expandpath(source)
4018 try:
4017 try:
4019 return hg.incoming(ui, repo, source, opts)
4018 return hg.incoming(ui, repo, source, opts)
4020 finally:
4019 finally:
4021 del repo._subtoppath
4020 del repo._subtoppath
4022
4021
4023
4022
4024 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4023 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4025 def init(ui, dest=".", **opts):
4024 def init(ui, dest=".", **opts):
4026 """create a new repository in the given directory
4025 """create a new repository in the given directory
4027
4026
4028 Initialize a new repository in the given directory. If the given
4027 Initialize a new repository in the given directory. If the given
4029 directory does not exist, it will be created.
4028 directory does not exist, it will be created.
4030
4029
4031 If no directory is given, the current directory is used.
4030 If no directory is given, the current directory is used.
4032
4031
4033 It is possible to specify an ``ssh://`` URL as the destination.
4032 It is possible to specify an ``ssh://`` URL as the destination.
4034 See :hg:`help urls` for more information.
4033 See :hg:`help urls` for more information.
4035
4034
4036 Returns 0 on success.
4035 Returns 0 on success.
4037 """
4036 """
4038 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4037 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4039
4038
4040 @command('locate',
4039 @command('locate',
4041 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4040 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4042 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4041 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4043 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4042 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4044 ] + walkopts,
4043 ] + walkopts,
4045 _('[OPTION]... [PATTERN]...'))
4044 _('[OPTION]... [PATTERN]...'))
4046 def locate(ui, repo, *pats, **opts):
4045 def locate(ui, repo, *pats, **opts):
4047 """locate files matching specific patterns
4046 """locate files matching specific patterns
4048
4047
4049 Print files under Mercurial control in the working directory whose
4048 Print files under Mercurial control in the working directory whose
4050 names match the given patterns.
4049 names match the given patterns.
4051
4050
4052 By default, this command searches all directories in the working
4051 By default, this command searches all directories in the working
4053 directory. To search just the current directory and its
4052 directory. To search just the current directory and its
4054 subdirectories, use "--include .".
4053 subdirectories, use "--include .".
4055
4054
4056 If no patterns are given to match, this command prints the names
4055 If no patterns are given to match, this command prints the names
4057 of all files under Mercurial control in the working directory.
4056 of all files under Mercurial control in the working directory.
4058
4057
4059 If you want to feed the output of this command into the "xargs"
4058 If you want to feed the output of this command into the "xargs"
4060 command, use the -0 option to both this command and "xargs". This
4059 command, use the -0 option to both this command and "xargs". This
4061 will avoid the problem of "xargs" treating single filenames that
4060 will avoid the problem of "xargs" treating single filenames that
4062 contain whitespace as multiple filenames.
4061 contain whitespace as multiple filenames.
4063
4062
4064 Returns 0 if a match is found, 1 otherwise.
4063 Returns 0 if a match is found, 1 otherwise.
4065 """
4064 """
4066 end = opts.get('print0') and '\0' or '\n'
4065 end = opts.get('print0') and '\0' or '\n'
4067 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4066 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4068
4067
4069 ret = 1
4068 ret = 1
4070 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4069 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4071 m.bad = lambda x, y: False
4070 m.bad = lambda x, y: False
4072 for abs in repo[rev].walk(m):
4071 for abs in repo[rev].walk(m):
4073 if not rev and abs not in repo.dirstate:
4072 if not rev and abs not in repo.dirstate:
4074 continue
4073 continue
4075 if opts.get('fullpath'):
4074 if opts.get('fullpath'):
4076 ui.write(repo.wjoin(abs), end)
4075 ui.write(repo.wjoin(abs), end)
4077 else:
4076 else:
4078 ui.write(((pats and m.rel(abs)) or abs), end)
4077 ui.write(((pats and m.rel(abs)) or abs), end)
4079 ret = 0
4078 ret = 0
4080
4079
4081 return ret
4080 return ret
4082
4081
4083 @command('^log|history',
4082 @command('^log|history',
4084 [('f', 'follow', None,
4083 [('f', 'follow', None,
4085 _('follow changeset history, or file history across copies and renames')),
4084 _('follow changeset history, or file history across copies and renames')),
4086 ('', 'follow-first', None,
4085 ('', 'follow-first', None,
4087 _('only follow the first parent of merge changesets (DEPRECATED)')),
4086 _('only follow the first parent of merge changesets (DEPRECATED)')),
4088 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4087 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4089 ('C', 'copies', None, _('show copied files')),
4088 ('C', 'copies', None, _('show copied files')),
4090 ('k', 'keyword', [],
4089 ('k', 'keyword', [],
4091 _('do case-insensitive search for a given text'), _('TEXT')),
4090 _('do case-insensitive search for a given text'), _('TEXT')),
4092 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4091 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4093 ('', 'removed', None, _('include revisions where files were removed')),
4092 ('', 'removed', None, _('include revisions where files were removed')),
4094 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4093 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4095 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4094 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4096 ('', 'only-branch', [],
4095 ('', 'only-branch', [],
4097 _('show only changesets within the given named branch (DEPRECATED)'),
4096 _('show only changesets within the given named branch (DEPRECATED)'),
4098 _('BRANCH')),
4097 _('BRANCH')),
4099 ('b', 'branch', [],
4098 ('b', 'branch', [],
4100 _('show changesets within the given named branch'), _('BRANCH')),
4099 _('show changesets within the given named branch'), _('BRANCH')),
4101 ('P', 'prune', [],
4100 ('P', 'prune', [],
4102 _('do not display revision or any of its ancestors'), _('REV')),
4101 _('do not display revision or any of its ancestors'), _('REV')),
4103 ] + logopts + walkopts,
4102 ] + logopts + walkopts,
4104 _('[OPTION]... [FILE]'))
4103 _('[OPTION]... [FILE]'))
4105 def log(ui, repo, *pats, **opts):
4104 def log(ui, repo, *pats, **opts):
4106 """show revision history of entire repository or files
4105 """show revision history of entire repository or files
4107
4106
4108 Print the revision history of the specified files or the entire
4107 Print the revision history of the specified files or the entire
4109 project.
4108 project.
4110
4109
4111 If no revision range is specified, the default is ``tip:0`` unless
4110 If no revision range is specified, the default is ``tip:0`` unless
4112 --follow is set, in which case the working directory parent is
4111 --follow is set, in which case the working directory parent is
4113 used as the starting revision.
4112 used as the starting revision.
4114
4113
4115 File history is shown without following rename or copy history of
4114 File history is shown without following rename or copy history of
4116 files. Use -f/--follow with a filename to follow history across
4115 files. Use -f/--follow with a filename to follow history across
4117 renames and copies. --follow without a filename will only show
4116 renames and copies. --follow without a filename will only show
4118 ancestors or descendants of the starting revision.
4117 ancestors or descendants of the starting revision.
4119
4118
4120 By default this command prints revision number and changeset id,
4119 By default this command prints revision number and changeset id,
4121 tags, non-trivial parents, user, date and time, and a summary for
4120 tags, non-trivial parents, user, date and time, and a summary for
4122 each commit. When the -v/--verbose switch is used, the list of
4121 each commit. When the -v/--verbose switch is used, the list of
4123 changed files and full commit message are shown.
4122 changed files and full commit message are shown.
4124
4123
4125 .. note::
4124 .. note::
4126 log -p/--patch may generate unexpected diff output for merge
4125 log -p/--patch may generate unexpected diff output for merge
4127 changesets, as it will only compare the merge changeset against
4126 changesets, as it will only compare the merge changeset against
4128 its first parent. Also, only files different from BOTH parents
4127 its first parent. Also, only files different from BOTH parents
4129 will appear in files:.
4128 will appear in files:.
4130
4129
4131 .. note::
4130 .. note::
4132 for performance reasons, log FILE may omit duplicate changes
4131 for performance reasons, log FILE may omit duplicate changes
4133 made on branches and will not show deletions. To see all
4132 made on branches and will not show deletions. To see all
4134 changes including duplicates and deletions, use the --removed
4133 changes including duplicates and deletions, use the --removed
4135 switch.
4134 switch.
4136
4135
4137 .. container:: verbose
4136 .. container:: verbose
4138
4137
4139 Some examples:
4138 Some examples:
4140
4139
4141 - changesets with full descriptions and file lists::
4140 - changesets with full descriptions and file lists::
4142
4141
4143 hg log -v
4142 hg log -v
4144
4143
4145 - changesets ancestral to the working directory::
4144 - changesets ancestral to the working directory::
4146
4145
4147 hg log -f
4146 hg log -f
4148
4147
4149 - last 10 commits on the current branch::
4148 - last 10 commits on the current branch::
4150
4149
4151 hg log -l 10 -b .
4150 hg log -l 10 -b .
4152
4151
4153 - changesets showing all modifications of a file, including removals::
4152 - changesets showing all modifications of a file, including removals::
4154
4153
4155 hg log --removed file.c
4154 hg log --removed file.c
4156
4155
4157 - all changesets that touch a directory, with diffs, excluding merges::
4156 - all changesets that touch a directory, with diffs, excluding merges::
4158
4157
4159 hg log -Mp lib/
4158 hg log -Mp lib/
4160
4159
4161 - all revision numbers that match a keyword::
4160 - all revision numbers that match a keyword::
4162
4161
4163 hg log -k bug --template "{rev}\\n"
4162 hg log -k bug --template "{rev}\\n"
4164
4163
4165 - check if a given changeset is included is a tagged release::
4164 - check if a given changeset is included is a tagged release::
4166
4165
4167 hg log -r "a21ccf and ancestor(1.9)"
4166 hg log -r "a21ccf and ancestor(1.9)"
4168
4167
4169 - find all changesets by some user in a date range::
4168 - find all changesets by some user in a date range::
4170
4169
4171 hg log -k alice -d "may 2008 to jul 2008"
4170 hg log -k alice -d "may 2008 to jul 2008"
4172
4171
4173 - summary of all changesets after the last tag::
4172 - summary of all changesets after the last tag::
4174
4173
4175 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4174 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4176
4175
4177 See :hg:`help dates` for a list of formats valid for -d/--date.
4176 See :hg:`help dates` for a list of formats valid for -d/--date.
4178
4177
4179 See :hg:`help revisions` and :hg:`help revsets` for more about
4178 See :hg:`help revisions` and :hg:`help revsets` for more about
4180 specifying revisions.
4179 specifying revisions.
4181
4180
4182 See :hg:`help templates` for more about pre-packaged styles and
4181 See :hg:`help templates` for more about pre-packaged styles and
4183 specifying custom templates.
4182 specifying custom templates.
4184
4183
4185 Returns 0 on success.
4184 Returns 0 on success.
4186 """
4185 """
4187 if opts.get('graph'):
4186 if opts.get('graph'):
4188 return cmdutil.graphlog(ui, repo, *pats, **opts)
4187 return cmdutil.graphlog(ui, repo, *pats, **opts)
4189
4188
4190 matchfn = scmutil.match(repo[None], pats, opts)
4189 matchfn = scmutil.match(repo[None], pats, opts)
4191 limit = cmdutil.loglimit(opts)
4190 limit = cmdutil.loglimit(opts)
4192 count = 0
4191 count = 0
4193
4192
4194 getrenamed, endrev = None, None
4193 getrenamed, endrev = None, None
4195 if opts.get('copies'):
4194 if opts.get('copies'):
4196 if opts.get('rev'):
4195 if opts.get('rev'):
4197 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4196 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4198 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4197 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4199
4198
4200 df = False
4199 df = False
4201 if opts.get("date"):
4200 if opts.get("date"):
4202 df = util.matchdate(opts["date"])
4201 df = util.matchdate(opts["date"])
4203
4202
4204 branches = opts.get('branch', []) + opts.get('only_branch', [])
4203 branches = opts.get('branch', []) + opts.get('only_branch', [])
4205 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4204 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4206
4205
4207 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4206 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4208 def prep(ctx, fns):
4207 def prep(ctx, fns):
4209 rev = ctx.rev()
4208 rev = ctx.rev()
4210 parents = [p for p in repo.changelog.parentrevs(rev)
4209 parents = [p for p in repo.changelog.parentrevs(rev)
4211 if p != nullrev]
4210 if p != nullrev]
4212 if opts.get('no_merges') and len(parents) == 2:
4211 if opts.get('no_merges') and len(parents) == 2:
4213 return
4212 return
4214 if opts.get('only_merges') and len(parents) != 2:
4213 if opts.get('only_merges') and len(parents) != 2:
4215 return
4214 return
4216 if opts.get('branch') and ctx.branch() not in opts['branch']:
4215 if opts.get('branch') and ctx.branch() not in opts['branch']:
4217 return
4216 return
4218 if df and not df(ctx.date()[0]):
4217 if df and not df(ctx.date()[0]):
4219 return
4218 return
4220
4219
4221 lower = encoding.lower
4220 lower = encoding.lower
4222 if opts.get('user'):
4221 if opts.get('user'):
4223 luser = lower(ctx.user())
4222 luser = lower(ctx.user())
4224 for k in [lower(x) for x in opts['user']]:
4223 for k in [lower(x) for x in opts['user']]:
4225 if (k in luser):
4224 if (k in luser):
4226 break
4225 break
4227 else:
4226 else:
4228 return
4227 return
4229 if opts.get('keyword'):
4228 if opts.get('keyword'):
4230 luser = lower(ctx.user())
4229 luser = lower(ctx.user())
4231 ldesc = lower(ctx.description())
4230 ldesc = lower(ctx.description())
4232 lfiles = lower(" ".join(ctx.files()))
4231 lfiles = lower(" ".join(ctx.files()))
4233 for k in [lower(x) for x in opts['keyword']]:
4232 for k in [lower(x) for x in opts['keyword']]:
4234 if (k in luser or k in ldesc or k in lfiles):
4233 if (k in luser or k in ldesc or k in lfiles):
4235 break
4234 break
4236 else:
4235 else:
4237 return
4236 return
4238
4237
4239 copies = None
4238 copies = None
4240 if getrenamed is not None and rev:
4239 if getrenamed is not None and rev:
4241 copies = []
4240 copies = []
4242 for fn in ctx.files():
4241 for fn in ctx.files():
4243 rename = getrenamed(fn, rev)
4242 rename = getrenamed(fn, rev)
4244 if rename:
4243 if rename:
4245 copies.append((fn, rename[0]))
4244 copies.append((fn, rename[0]))
4246
4245
4247 revmatchfn = None
4246 revmatchfn = None
4248 if opts.get('patch') or opts.get('stat'):
4247 if opts.get('patch') or opts.get('stat'):
4249 if opts.get('follow') or opts.get('follow_first'):
4248 if opts.get('follow') or opts.get('follow_first'):
4250 # note: this might be wrong when following through merges
4249 # note: this might be wrong when following through merges
4251 revmatchfn = scmutil.match(repo[None], fns, default='path')
4250 revmatchfn = scmutil.match(repo[None], fns, default='path')
4252 else:
4251 else:
4253 revmatchfn = matchfn
4252 revmatchfn = matchfn
4254
4253
4255 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4254 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4256
4255
4257 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4256 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4258 if count == limit:
4257 if count == limit:
4259 break
4258 break
4260 if displayer.flush(ctx.rev()):
4259 if displayer.flush(ctx.rev()):
4261 count += 1
4260 count += 1
4262 displayer.close()
4261 displayer.close()
4263
4262
4264 @command('manifest',
4263 @command('manifest',
4265 [('r', 'rev', '', _('revision to display'), _('REV')),
4264 [('r', 'rev', '', _('revision to display'), _('REV')),
4266 ('', 'all', False, _("list files from all revisions"))],
4265 ('', 'all', False, _("list files from all revisions"))],
4267 _('[-r REV]'))
4266 _('[-r REV]'))
4268 def manifest(ui, repo, node=None, rev=None, **opts):
4267 def manifest(ui, repo, node=None, rev=None, **opts):
4269 """output the current or given revision of the project manifest
4268 """output the current or given revision of the project manifest
4270
4269
4271 Print a list of version controlled files for the given revision.
4270 Print a list of version controlled files for the given revision.
4272 If no revision is given, the first parent of the working directory
4271 If no revision is given, the first parent of the working directory
4273 is used, or the null revision if no revision is checked out.
4272 is used, or the null revision if no revision is checked out.
4274
4273
4275 With -v, print file permissions, symlink and executable bits.
4274 With -v, print file permissions, symlink and executable bits.
4276 With --debug, print file revision hashes.
4275 With --debug, print file revision hashes.
4277
4276
4278 If option --all is specified, the list of all files from all revisions
4277 If option --all is specified, the list of all files from all revisions
4279 is printed. This includes deleted and renamed files.
4278 is printed. This includes deleted and renamed files.
4280
4279
4281 Returns 0 on success.
4280 Returns 0 on success.
4282 """
4281 """
4283
4282
4284 fm = ui.formatter('manifest', opts)
4283 fm = ui.formatter('manifest', opts)
4285
4284
4286 if opts.get('all'):
4285 if opts.get('all'):
4287 if rev or node:
4286 if rev or node:
4288 raise util.Abort(_("can't specify a revision with --all"))
4287 raise util.Abort(_("can't specify a revision with --all"))
4289
4288
4290 res = []
4289 res = []
4291 prefix = "data/"
4290 prefix = "data/"
4292 suffix = ".i"
4291 suffix = ".i"
4293 plen = len(prefix)
4292 plen = len(prefix)
4294 slen = len(suffix)
4293 slen = len(suffix)
4295 lock = repo.lock()
4294 lock = repo.lock()
4296 try:
4295 try:
4297 for fn, b, size in repo.store.datafiles():
4296 for fn, b, size in repo.store.datafiles():
4298 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4297 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4299 res.append(fn[plen:-slen])
4298 res.append(fn[plen:-slen])
4300 finally:
4299 finally:
4301 lock.release()
4300 lock.release()
4302 for f in res:
4301 for f in res:
4303 fm.startitem()
4302 fm.startitem()
4304 fm.write("path", '%s\n', f)
4303 fm.write("path", '%s\n', f)
4305 fm.end()
4304 fm.end()
4306 return
4305 return
4307
4306
4308 if rev and node:
4307 if rev and node:
4309 raise util.Abort(_("please specify just one revision"))
4308 raise util.Abort(_("please specify just one revision"))
4310
4309
4311 if not node:
4310 if not node:
4312 node = rev
4311 node = rev
4313
4312
4314 char = {'l': '@', 'x': '*', '': ''}
4313 char = {'l': '@', 'x': '*', '': ''}
4315 mode = {'l': '644', 'x': '755', '': '644'}
4314 mode = {'l': '644', 'x': '755', '': '644'}
4316 ctx = scmutil.revsingle(repo, node)
4315 ctx = scmutil.revsingle(repo, node)
4317 mf = ctx.manifest()
4316 mf = ctx.manifest()
4318 for f in ctx:
4317 for f in ctx:
4319 fm.startitem()
4318 fm.startitem()
4320 fl = ctx[f].flags()
4319 fl = ctx[f].flags()
4321 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4320 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4322 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4321 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4323 fm.write('path', '%s\n', f)
4322 fm.write('path', '%s\n', f)
4324 fm.end()
4323 fm.end()
4325
4324
4326 @command('^merge',
4325 @command('^merge',
4327 [('f', 'force', None, _('force a merge with outstanding changes')),
4326 [('f', 'force', None, _('force a merge with outstanding changes')),
4328 ('r', 'rev', '', _('revision to merge'), _('REV')),
4327 ('r', 'rev', '', _('revision to merge'), _('REV')),
4329 ('P', 'preview', None,
4328 ('P', 'preview', None,
4330 _('review revisions to merge (no merge is performed)'))
4329 _('review revisions to merge (no merge is performed)'))
4331 ] + mergetoolopts,
4330 ] + mergetoolopts,
4332 _('[-P] [-f] [[-r] REV]'))
4331 _('[-P] [-f] [[-r] REV]'))
4333 def merge(ui, repo, node=None, **opts):
4332 def merge(ui, repo, node=None, **opts):
4334 """merge working directory with another revision
4333 """merge working directory with another revision
4335
4334
4336 The current working directory is updated with all changes made in
4335 The current working directory is updated with all changes made in
4337 the requested revision since the last common predecessor revision.
4336 the requested revision since the last common predecessor revision.
4338
4337
4339 Files that changed between either parent are marked as changed for
4338 Files that changed between either parent are marked as changed for
4340 the next commit and a commit must be performed before any further
4339 the next commit and a commit must be performed before any further
4341 updates to the repository are allowed. The next commit will have
4340 updates to the repository are allowed. The next commit will have
4342 two parents.
4341 two parents.
4343
4342
4344 ``--tool`` can be used to specify the merge tool used for file
4343 ``--tool`` can be used to specify the merge tool used for file
4345 merges. It overrides the HGMERGE environment variable and your
4344 merges. It overrides the HGMERGE environment variable and your
4346 configuration files. See :hg:`help merge-tools` for options.
4345 configuration files. See :hg:`help merge-tools` for options.
4347
4346
4348 If no revision is specified, the working directory's parent is a
4347 If no revision is specified, the working directory's parent is a
4349 head revision, and the current branch contains exactly one other
4348 head revision, and the current branch contains exactly one other
4350 head, the other head is merged with by default. Otherwise, an
4349 head, the other head is merged with by default. Otherwise, an
4351 explicit revision with which to merge with must be provided.
4350 explicit revision with which to merge with must be provided.
4352
4351
4353 :hg:`resolve` must be used to resolve unresolved files.
4352 :hg:`resolve` must be used to resolve unresolved files.
4354
4353
4355 To undo an uncommitted merge, use :hg:`update --clean .` which
4354 To undo an uncommitted merge, use :hg:`update --clean .` which
4356 will check out a clean copy of the original merge parent, losing
4355 will check out a clean copy of the original merge parent, losing
4357 all changes.
4356 all changes.
4358
4357
4359 Returns 0 on success, 1 if there are unresolved files.
4358 Returns 0 on success, 1 if there are unresolved files.
4360 """
4359 """
4361
4360
4362 if opts.get('rev') and node:
4361 if opts.get('rev') and node:
4363 raise util.Abort(_("please specify just one revision"))
4362 raise util.Abort(_("please specify just one revision"))
4364 if not node:
4363 if not node:
4365 node = opts.get('rev')
4364 node = opts.get('rev')
4366
4365
4367 if node:
4366 if node:
4368 node = scmutil.revsingle(repo, node).node()
4367 node = scmutil.revsingle(repo, node).node()
4369
4368
4370 if not node and repo._bookmarkcurrent:
4369 if not node and repo._bookmarkcurrent:
4371 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4370 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4372 curhead = repo[repo._bookmarkcurrent].node()
4371 curhead = repo[repo._bookmarkcurrent].node()
4373 if len(bmheads) == 2:
4372 if len(bmheads) == 2:
4374 if curhead == bmheads[0]:
4373 if curhead == bmheads[0]:
4375 node = bmheads[1]
4374 node = bmheads[1]
4376 else:
4375 else:
4377 node = bmheads[0]
4376 node = bmheads[0]
4378 elif len(bmheads) > 2:
4377 elif len(bmheads) > 2:
4379 raise util.Abort(_("multiple matching bookmarks to merge - "
4378 raise util.Abort(_("multiple matching bookmarks to merge - "
4380 "please merge with an explicit rev or bookmark"),
4379 "please merge with an explicit rev or bookmark"),
4381 hint=_("run 'hg heads' to see all heads"))
4380 hint=_("run 'hg heads' to see all heads"))
4382 elif len(bmheads) <= 1:
4381 elif len(bmheads) <= 1:
4383 raise util.Abort(_("no matching bookmark to merge - "
4382 raise util.Abort(_("no matching bookmark to merge - "
4384 "please merge with an explicit rev or bookmark"),
4383 "please merge with an explicit rev or bookmark"),
4385 hint=_("run 'hg heads' to see all heads"))
4384 hint=_("run 'hg heads' to see all heads"))
4386
4385
4387 if not node and not repo._bookmarkcurrent:
4386 if not node and not repo._bookmarkcurrent:
4388 branch = repo[None].branch()
4387 branch = repo[None].branch()
4389 bheads = repo.branchheads(branch)
4388 bheads = repo.branchheads(branch)
4390 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4389 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4391
4390
4392 if len(nbhs) > 2:
4391 if len(nbhs) > 2:
4393 raise util.Abort(_("branch '%s' has %d heads - "
4392 raise util.Abort(_("branch '%s' has %d heads - "
4394 "please merge with an explicit rev")
4393 "please merge with an explicit rev")
4395 % (branch, len(bheads)),
4394 % (branch, len(bheads)),
4396 hint=_("run 'hg heads .' to see heads"))
4395 hint=_("run 'hg heads .' to see heads"))
4397
4396
4398 parent = repo.dirstate.p1()
4397 parent = repo.dirstate.p1()
4399 if len(nbhs) <= 1:
4398 if len(nbhs) <= 1:
4400 if len(bheads) > 1:
4399 if len(bheads) > 1:
4401 raise util.Abort(_("heads are bookmarked - "
4400 raise util.Abort(_("heads are bookmarked - "
4402 "please merge with an explicit rev"),
4401 "please merge with an explicit rev"),
4403 hint=_("run 'hg heads' to see all heads"))
4402 hint=_("run 'hg heads' to see all heads"))
4404 if len(repo.heads()) > 1:
4403 if len(repo.heads()) > 1:
4405 raise util.Abort(_("branch '%s' has one head - "
4404 raise util.Abort(_("branch '%s' has one head - "
4406 "please merge with an explicit rev")
4405 "please merge with an explicit rev")
4407 % branch,
4406 % branch,
4408 hint=_("run 'hg heads' to see all heads"))
4407 hint=_("run 'hg heads' to see all heads"))
4409 msg, hint = _('nothing to merge'), None
4408 msg, hint = _('nothing to merge'), None
4410 if parent != repo.lookup(branch):
4409 if parent != repo.lookup(branch):
4411 hint = _("use 'hg update' instead")
4410 hint = _("use 'hg update' instead")
4412 raise util.Abort(msg, hint=hint)
4411 raise util.Abort(msg, hint=hint)
4413
4412
4414 if parent not in bheads:
4413 if parent not in bheads:
4415 raise util.Abort(_('working directory not at a head revision'),
4414 raise util.Abort(_('working directory not at a head revision'),
4416 hint=_("use 'hg update' or merge with an "
4415 hint=_("use 'hg update' or merge with an "
4417 "explicit revision"))
4416 "explicit revision"))
4418 if parent == nbhs[0]:
4417 if parent == nbhs[0]:
4419 node = nbhs[-1]
4418 node = nbhs[-1]
4420 else:
4419 else:
4421 node = nbhs[0]
4420 node = nbhs[0]
4422
4421
4423 if opts.get('preview'):
4422 if opts.get('preview'):
4424 # find nodes that are ancestors of p2 but not of p1
4423 # find nodes that are ancestors of p2 but not of p1
4425 p1 = repo.lookup('.')
4424 p1 = repo.lookup('.')
4426 p2 = repo.lookup(node)
4425 p2 = repo.lookup(node)
4427 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4426 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4428
4427
4429 displayer = cmdutil.show_changeset(ui, repo, opts)
4428 displayer = cmdutil.show_changeset(ui, repo, opts)
4430 for node in nodes:
4429 for node in nodes:
4431 displayer.show(repo[node])
4430 displayer.show(repo[node])
4432 displayer.close()
4431 displayer.close()
4433 return 0
4432 return 0
4434
4433
4435 try:
4434 try:
4436 # ui.forcemerge is an internal variable, do not document
4435 # ui.forcemerge is an internal variable, do not document
4437 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4436 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4438 return hg.merge(repo, node, force=opts.get('force'))
4437 return hg.merge(repo, node, force=opts.get('force'))
4439 finally:
4438 finally:
4440 ui.setconfig('ui', 'forcemerge', '')
4439 ui.setconfig('ui', 'forcemerge', '')
4441
4440
4442 @command('outgoing|out',
4441 @command('outgoing|out',
4443 [('f', 'force', None, _('run even when the destination is unrelated')),
4442 [('f', 'force', None, _('run even when the destination is unrelated')),
4444 ('r', 'rev', [],
4443 ('r', 'rev', [],
4445 _('a changeset intended to be included in the destination'), _('REV')),
4444 _('a changeset intended to be included in the destination'), _('REV')),
4446 ('n', 'newest-first', None, _('show newest record first')),
4445 ('n', 'newest-first', None, _('show newest record first')),
4447 ('B', 'bookmarks', False, _('compare bookmarks')),
4446 ('B', 'bookmarks', False, _('compare bookmarks')),
4448 ('b', 'branch', [], _('a specific branch you would like to push'),
4447 ('b', 'branch', [], _('a specific branch you would like to push'),
4449 _('BRANCH')),
4448 _('BRANCH')),
4450 ] + logopts + remoteopts + subrepoopts,
4449 ] + logopts + remoteopts + subrepoopts,
4451 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4450 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4452 def outgoing(ui, repo, dest=None, **opts):
4451 def outgoing(ui, repo, dest=None, **opts):
4453 """show changesets not found in the destination
4452 """show changesets not found in the destination
4454
4453
4455 Show changesets not found in the specified destination repository
4454 Show changesets not found in the specified destination repository
4456 or the default push location. These are the changesets that would
4455 or the default push location. These are the changesets that would
4457 be pushed if a push was requested.
4456 be pushed if a push was requested.
4458
4457
4459 See pull for details of valid destination formats.
4458 See pull for details of valid destination formats.
4460
4459
4461 Returns 0 if there are outgoing changes, 1 otherwise.
4460 Returns 0 if there are outgoing changes, 1 otherwise.
4462 """
4461 """
4463 if opts.get('graph'):
4462 if opts.get('graph'):
4464 cmdutil.checkunsupportedgraphflags([], opts)
4463 cmdutil.checkunsupportedgraphflags([], opts)
4465 o = hg._outgoing(ui, repo, dest, opts)
4464 o = hg._outgoing(ui, repo, dest, opts)
4466 if o is None:
4465 if o is None:
4467 return
4466 return
4468
4467
4469 revdag = cmdutil.graphrevs(repo, o, opts)
4468 revdag = cmdutil.graphrevs(repo, o, opts)
4470 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4469 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4471 showparents = [ctx.node() for ctx in repo[None].parents()]
4470 showparents = [ctx.node() for ctx in repo[None].parents()]
4472 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4471 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4473 graphmod.asciiedges)
4472 graphmod.asciiedges)
4474 return 0
4473 return 0
4475
4474
4476 if opts.get('bookmarks'):
4475 if opts.get('bookmarks'):
4477 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4476 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4478 dest, branches = hg.parseurl(dest, opts.get('branch'))
4477 dest, branches = hg.parseurl(dest, opts.get('branch'))
4479 other = hg.peer(repo, opts, dest)
4478 other = hg.peer(repo, opts, dest)
4480 if 'bookmarks' not in other.listkeys('namespaces'):
4479 if 'bookmarks' not in other.listkeys('namespaces'):
4481 ui.warn(_("remote doesn't support bookmarks\n"))
4480 ui.warn(_("remote doesn't support bookmarks\n"))
4482 return 0
4481 return 0
4483 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4482 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4484 return bookmarks.diff(ui, other, repo)
4483 return bookmarks.diff(ui, other, repo)
4485
4484
4486 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4485 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4487 try:
4486 try:
4488 return hg.outgoing(ui, repo, dest, opts)
4487 return hg.outgoing(ui, repo, dest, opts)
4489 finally:
4488 finally:
4490 del repo._subtoppath
4489 del repo._subtoppath
4491
4490
4492 @command('parents',
4491 @command('parents',
4493 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4492 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4494 ] + templateopts,
4493 ] + templateopts,
4495 _('[-r REV] [FILE]'))
4494 _('[-r REV] [FILE]'))
4496 def parents(ui, repo, file_=None, **opts):
4495 def parents(ui, repo, file_=None, **opts):
4497 """show the parents of the working directory or revision
4496 """show the parents of the working directory or revision
4498
4497
4499 Print the working directory's parent revisions. If a revision is
4498 Print the working directory's parent revisions. If a revision is
4500 given via -r/--rev, the parent of that revision will be printed.
4499 given via -r/--rev, the parent of that revision will be printed.
4501 If a file argument is given, the revision in which the file was
4500 If a file argument is given, the revision in which the file was
4502 last changed (before the working directory revision or the
4501 last changed (before the working directory revision or the
4503 argument to --rev if given) is printed.
4502 argument to --rev if given) is printed.
4504
4503
4505 Returns 0 on success.
4504 Returns 0 on success.
4506 """
4505 """
4507
4506
4508 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4507 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4509
4508
4510 if file_:
4509 if file_:
4511 m = scmutil.match(ctx, (file_,), opts)
4510 m = scmutil.match(ctx, (file_,), opts)
4512 if m.anypats() or len(m.files()) != 1:
4511 if m.anypats() or len(m.files()) != 1:
4513 raise util.Abort(_('can only specify an explicit filename'))
4512 raise util.Abort(_('can only specify an explicit filename'))
4514 file_ = m.files()[0]
4513 file_ = m.files()[0]
4515 filenodes = []
4514 filenodes = []
4516 for cp in ctx.parents():
4515 for cp in ctx.parents():
4517 if not cp:
4516 if not cp:
4518 continue
4517 continue
4519 try:
4518 try:
4520 filenodes.append(cp.filenode(file_))
4519 filenodes.append(cp.filenode(file_))
4521 except error.LookupError:
4520 except error.LookupError:
4522 pass
4521 pass
4523 if not filenodes:
4522 if not filenodes:
4524 raise util.Abort(_("'%s' not found in manifest!") % file_)
4523 raise util.Abort(_("'%s' not found in manifest!") % file_)
4525 fl = repo.file(file_)
4524 fl = repo.file(file_)
4526 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4525 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4527 else:
4526 else:
4528 p = [cp.node() for cp in ctx.parents()]
4527 p = [cp.node() for cp in ctx.parents()]
4529
4528
4530 displayer = cmdutil.show_changeset(ui, repo, opts)
4529 displayer = cmdutil.show_changeset(ui, repo, opts)
4531 for n in p:
4530 for n in p:
4532 if n != nullid:
4531 if n != nullid:
4533 displayer.show(repo[n])
4532 displayer.show(repo[n])
4534 displayer.close()
4533 displayer.close()
4535
4534
4536 @command('paths', [], _('[NAME]'))
4535 @command('paths', [], _('[NAME]'))
4537 def paths(ui, repo, search=None):
4536 def paths(ui, repo, search=None):
4538 """show aliases for remote repositories
4537 """show aliases for remote repositories
4539
4538
4540 Show definition of symbolic path name NAME. If no name is given,
4539 Show definition of symbolic path name NAME. If no name is given,
4541 show definition of all available names.
4540 show definition of all available names.
4542
4541
4543 Option -q/--quiet suppresses all output when searching for NAME
4542 Option -q/--quiet suppresses all output when searching for NAME
4544 and shows only the path names when listing all definitions.
4543 and shows only the path names when listing all definitions.
4545
4544
4546 Path names are defined in the [paths] section of your
4545 Path names are defined in the [paths] section of your
4547 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4546 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4548 repository, ``.hg/hgrc`` is used, too.
4547 repository, ``.hg/hgrc`` is used, too.
4549
4548
4550 The path names ``default`` and ``default-push`` have a special
4549 The path names ``default`` and ``default-push`` have a special
4551 meaning. When performing a push or pull operation, they are used
4550 meaning. When performing a push or pull operation, they are used
4552 as fallbacks if no location is specified on the command-line.
4551 as fallbacks if no location is specified on the command-line.
4553 When ``default-push`` is set, it will be used for push and
4552 When ``default-push`` is set, it will be used for push and
4554 ``default`` will be used for pull; otherwise ``default`` is used
4553 ``default`` will be used for pull; otherwise ``default`` is used
4555 as the fallback for both. When cloning a repository, the clone
4554 as the fallback for both. When cloning a repository, the clone
4556 source is written as ``default`` in ``.hg/hgrc``. Note that
4555 source is written as ``default`` in ``.hg/hgrc``. Note that
4557 ``default`` and ``default-push`` apply to all inbound (e.g.
4556 ``default`` and ``default-push`` apply to all inbound (e.g.
4558 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4557 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4559 :hg:`bundle`) operations.
4558 :hg:`bundle`) operations.
4560
4559
4561 See :hg:`help urls` for more information.
4560 See :hg:`help urls` for more information.
4562
4561
4563 Returns 0 on success.
4562 Returns 0 on success.
4564 """
4563 """
4565 if search:
4564 if search:
4566 for name, path in ui.configitems("paths"):
4565 for name, path in ui.configitems("paths"):
4567 if name == search:
4566 if name == search:
4568 ui.status("%s\n" % util.hidepassword(path))
4567 ui.status("%s\n" % util.hidepassword(path))
4569 return
4568 return
4570 if not ui.quiet:
4569 if not ui.quiet:
4571 ui.warn(_("not found!\n"))
4570 ui.warn(_("not found!\n"))
4572 return 1
4571 return 1
4573 else:
4572 else:
4574 for name, path in ui.configitems("paths"):
4573 for name, path in ui.configitems("paths"):
4575 if ui.quiet:
4574 if ui.quiet:
4576 ui.write("%s\n" % name)
4575 ui.write("%s\n" % name)
4577 else:
4576 else:
4578 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4577 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4579
4578
4580 @command('phase',
4579 @command('phase',
4581 [('p', 'public', False, _('set changeset phase to public')),
4580 [('p', 'public', False, _('set changeset phase to public')),
4582 ('d', 'draft', False, _('set changeset phase to draft')),
4581 ('d', 'draft', False, _('set changeset phase to draft')),
4583 ('s', 'secret', False, _('set changeset phase to secret')),
4582 ('s', 'secret', False, _('set changeset phase to secret')),
4584 ('f', 'force', False, _('allow to move boundary backward')),
4583 ('f', 'force', False, _('allow to move boundary backward')),
4585 ('r', 'rev', [], _('target revision'), _('REV')),
4584 ('r', 'rev', [], _('target revision'), _('REV')),
4586 ],
4585 ],
4587 _('[-p|-d|-s] [-f] [-r] REV...'))
4586 _('[-p|-d|-s] [-f] [-r] REV...'))
4588 def phase(ui, repo, *revs, **opts):
4587 def phase(ui, repo, *revs, **opts):
4589 """set or show the current phase name
4588 """set or show the current phase name
4590
4589
4591 With no argument, show the phase name of specified revisions.
4590 With no argument, show the phase name of specified revisions.
4592
4591
4593 With one of -p/--public, -d/--draft or -s/--secret, change the
4592 With one of -p/--public, -d/--draft or -s/--secret, change the
4594 phase value of the specified revisions.
4593 phase value of the specified revisions.
4595
4594
4596 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4595 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4597 lower phase to an higher phase. Phases are ordered as follows::
4596 lower phase to an higher phase. Phases are ordered as follows::
4598
4597
4599 public < draft < secret
4598 public < draft < secret
4600
4599
4601 Return 0 on success, 1 if no phases were changed or some could not
4600 Return 0 on success, 1 if no phases were changed or some could not
4602 be changed.
4601 be changed.
4603 """
4602 """
4604 # search for a unique phase argument
4603 # search for a unique phase argument
4605 targetphase = None
4604 targetphase = None
4606 for idx, name in enumerate(phases.phasenames):
4605 for idx, name in enumerate(phases.phasenames):
4607 if opts[name]:
4606 if opts[name]:
4608 if targetphase is not None:
4607 if targetphase is not None:
4609 raise util.Abort(_('only one phase can be specified'))
4608 raise util.Abort(_('only one phase can be specified'))
4610 targetphase = idx
4609 targetphase = idx
4611
4610
4612 # look for specified revision
4611 # look for specified revision
4613 revs = list(revs)
4612 revs = list(revs)
4614 revs.extend(opts['rev'])
4613 revs.extend(opts['rev'])
4615 if not revs:
4614 if not revs:
4616 raise util.Abort(_('no revisions specified'))
4615 raise util.Abort(_('no revisions specified'))
4617
4616
4618 revs = scmutil.revrange(repo, revs)
4617 revs = scmutil.revrange(repo, revs)
4619
4618
4620 lock = None
4619 lock = None
4621 ret = 0
4620 ret = 0
4622 if targetphase is None:
4621 if targetphase is None:
4623 # display
4622 # display
4624 for r in revs:
4623 for r in revs:
4625 ctx = repo[r]
4624 ctx = repo[r]
4626 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4625 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4627 else:
4626 else:
4628 lock = repo.lock()
4627 lock = repo.lock()
4629 try:
4628 try:
4630 # set phase
4629 # set phase
4631 if not revs:
4630 if not revs:
4632 raise util.Abort(_('empty revision set'))
4631 raise util.Abort(_('empty revision set'))
4633 nodes = [repo[r].node() for r in revs]
4632 nodes = [repo[r].node() for r in revs]
4634 olddata = repo._phasecache.getphaserevs(repo)[:]
4633 olddata = repo._phasecache.getphaserevs(repo)[:]
4635 phases.advanceboundary(repo, targetphase, nodes)
4634 phases.advanceboundary(repo, targetphase, nodes)
4636 if opts['force']:
4635 if opts['force']:
4637 phases.retractboundary(repo, targetphase, nodes)
4636 phases.retractboundary(repo, targetphase, nodes)
4638 finally:
4637 finally:
4639 lock.release()
4638 lock.release()
4640 # moving revision from public to draft may hide them
4639 # moving revision from public to draft may hide them
4641 # We have to check result on an unfiltered repository
4640 # We have to check result on an unfiltered repository
4642 unfi = repo.unfiltered()
4641 unfi = repo.unfiltered()
4643 newdata = repo._phasecache.getphaserevs(unfi)
4642 newdata = repo._phasecache.getphaserevs(unfi)
4644 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4643 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4645 cl = unfi.changelog
4644 cl = unfi.changelog
4646 rejected = [n for n in nodes
4645 rejected = [n for n in nodes
4647 if newdata[cl.rev(n)] < targetphase]
4646 if newdata[cl.rev(n)] < targetphase]
4648 if rejected:
4647 if rejected:
4649 ui.warn(_('cannot move %i changesets to a more permissive '
4648 ui.warn(_('cannot move %i changesets to a more permissive '
4650 'phase, use --force\n') % len(rejected))
4649 'phase, use --force\n') % len(rejected))
4651 ret = 1
4650 ret = 1
4652 if changes:
4651 if changes:
4653 msg = _('phase changed for %i changesets\n') % changes
4652 msg = _('phase changed for %i changesets\n') % changes
4654 if ret:
4653 if ret:
4655 ui.status(msg)
4654 ui.status(msg)
4656 else:
4655 else:
4657 ui.note(msg)
4656 ui.note(msg)
4658 else:
4657 else:
4659 ui.warn(_('no phases changed\n'))
4658 ui.warn(_('no phases changed\n'))
4660 ret = 1
4659 ret = 1
4661 return ret
4660 return ret
4662
4661
4663 def postincoming(ui, repo, modheads, optupdate, checkout):
4662 def postincoming(ui, repo, modheads, optupdate, checkout):
4664 if modheads == 0:
4663 if modheads == 0:
4665 return
4664 return
4666 if optupdate:
4665 if optupdate:
4667 movemarkfrom = repo['.'].node()
4666 movemarkfrom = repo['.'].node()
4668 try:
4667 try:
4669 ret = hg.update(repo, checkout)
4668 ret = hg.update(repo, checkout)
4670 except util.Abort, inst:
4669 except util.Abort, inst:
4671 ui.warn(_("not updating: %s\n") % str(inst))
4670 ui.warn(_("not updating: %s\n") % str(inst))
4672 return 0
4671 return 0
4673 if not ret and not checkout:
4672 if not ret and not checkout:
4674 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4673 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4675 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4674 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4676 return ret
4675 return ret
4677 if modheads > 1:
4676 if modheads > 1:
4678 currentbranchheads = len(repo.branchheads())
4677 currentbranchheads = len(repo.branchheads())
4679 if currentbranchheads == modheads:
4678 if currentbranchheads == modheads:
4680 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4679 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4681 elif currentbranchheads > 1:
4680 elif currentbranchheads > 1:
4682 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4681 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4683 "merge)\n"))
4682 "merge)\n"))
4684 else:
4683 else:
4685 ui.status(_("(run 'hg heads' to see heads)\n"))
4684 ui.status(_("(run 'hg heads' to see heads)\n"))
4686 else:
4685 else:
4687 ui.status(_("(run 'hg update' to get a working copy)\n"))
4686 ui.status(_("(run 'hg update' to get a working copy)\n"))
4688
4687
4689 @command('^pull',
4688 @command('^pull',
4690 [('u', 'update', None,
4689 [('u', 'update', None,
4691 _('update to new branch head if changesets were pulled')),
4690 _('update to new branch head if changesets were pulled')),
4692 ('f', 'force', None, _('run even when remote repository is unrelated')),
4691 ('f', 'force', None, _('run even when remote repository is unrelated')),
4693 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4692 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4694 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4693 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4695 ('b', 'branch', [], _('a specific branch you would like to pull'),
4694 ('b', 'branch', [], _('a specific branch you would like to pull'),
4696 _('BRANCH')),
4695 _('BRANCH')),
4697 ] + remoteopts,
4696 ] + remoteopts,
4698 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4697 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4699 def pull(ui, repo, source="default", **opts):
4698 def pull(ui, repo, source="default", **opts):
4700 """pull changes from the specified source
4699 """pull changes from the specified source
4701
4700
4702 Pull changes from a remote repository to a local one.
4701 Pull changes from a remote repository to a local one.
4703
4702
4704 This finds all changes from the repository at the specified path
4703 This finds all changes from the repository at the specified path
4705 or URL and adds them to a local repository (the current one unless
4704 or URL and adds them to a local repository (the current one unless
4706 -R is specified). By default, this does not update the copy of the
4705 -R is specified). By default, this does not update the copy of the
4707 project in the working directory.
4706 project in the working directory.
4708
4707
4709 Use :hg:`incoming` if you want to see what would have been added
4708 Use :hg:`incoming` if you want to see what would have been added
4710 by a pull at the time you issued this command. If you then decide
4709 by a pull at the time you issued this command. If you then decide
4711 to add those changes to the repository, you should use :hg:`pull
4710 to add those changes to the repository, you should use :hg:`pull
4712 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4711 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4713
4712
4714 If SOURCE is omitted, the 'default' path will be used.
4713 If SOURCE is omitted, the 'default' path will be used.
4715 See :hg:`help urls` for more information.
4714 See :hg:`help urls` for more information.
4716
4715
4717 Returns 0 on success, 1 if an update had unresolved files.
4716 Returns 0 on success, 1 if an update had unresolved files.
4718 """
4717 """
4719 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4718 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4720 other = hg.peer(repo, opts, source)
4719 other = hg.peer(repo, opts, source)
4721 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4720 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4722 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4721 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4723
4722
4724 if opts.get('bookmark'):
4723 if opts.get('bookmark'):
4725 if not revs:
4724 if not revs:
4726 revs = []
4725 revs = []
4727 rb = other.listkeys('bookmarks')
4726 rb = other.listkeys('bookmarks')
4728 for b in opts['bookmark']:
4727 for b in opts['bookmark']:
4729 if b not in rb:
4728 if b not in rb:
4730 raise util.Abort(_('remote bookmark %s not found!') % b)
4729 raise util.Abort(_('remote bookmark %s not found!') % b)
4731 revs.append(rb[b])
4730 revs.append(rb[b])
4732
4731
4733 if revs:
4732 if revs:
4734 try:
4733 try:
4735 revs = [other.lookup(rev) for rev in revs]
4734 revs = [other.lookup(rev) for rev in revs]
4736 except error.CapabilityError:
4735 except error.CapabilityError:
4737 err = _("other repository doesn't support revision lookup, "
4736 err = _("other repository doesn't support revision lookup, "
4738 "so a rev cannot be specified.")
4737 "so a rev cannot be specified.")
4739 raise util.Abort(err)
4738 raise util.Abort(err)
4740
4739
4741 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4740 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4742 bookmarks.updatefromremote(ui, repo, other, source)
4741 bookmarks.updatefromremote(ui, repo, other, source)
4743 if checkout:
4742 if checkout:
4744 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4743 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4745 repo._subtoppath = source
4744 repo._subtoppath = source
4746 try:
4745 try:
4747 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4746 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4748
4747
4749 finally:
4748 finally:
4750 del repo._subtoppath
4749 del repo._subtoppath
4751
4750
4752 # update specified bookmarks
4751 # update specified bookmarks
4753 if opts.get('bookmark'):
4752 if opts.get('bookmark'):
4754 marks = repo._bookmarks
4753 marks = repo._bookmarks
4755 for b in opts['bookmark']:
4754 for b in opts['bookmark']:
4756 # explicit pull overrides local bookmark if any
4755 # explicit pull overrides local bookmark if any
4757 ui.status(_("importing bookmark %s\n") % b)
4756 ui.status(_("importing bookmark %s\n") % b)
4758 marks[b] = repo[rb[b]].node()
4757 marks[b] = repo[rb[b]].node()
4759 marks.write()
4758 marks.write()
4760
4759
4761 return ret
4760 return ret
4762
4761
4763 @command('^push',
4762 @command('^push',
4764 [('f', 'force', None, _('force push')),
4763 [('f', 'force', None, _('force push')),
4765 ('r', 'rev', [],
4764 ('r', 'rev', [],
4766 _('a changeset intended to be included in the destination'),
4765 _('a changeset intended to be included in the destination'),
4767 _('REV')),
4766 _('REV')),
4768 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4767 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4769 ('b', 'branch', [],
4768 ('b', 'branch', [],
4770 _('a specific branch you would like to push'), _('BRANCH')),
4769 _('a specific branch you would like to push'), _('BRANCH')),
4771 ('', 'new-branch', False, _('allow pushing a new branch')),
4770 ('', 'new-branch', False, _('allow pushing a new branch')),
4772 ] + remoteopts,
4771 ] + remoteopts,
4773 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4772 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4774 def push(ui, repo, dest=None, **opts):
4773 def push(ui, repo, dest=None, **opts):
4775 """push changes to the specified destination
4774 """push changes to the specified destination
4776
4775
4777 Push changesets from the local repository to the specified
4776 Push changesets from the local repository to the specified
4778 destination.
4777 destination.
4779
4778
4780 This operation is symmetrical to pull: it is identical to a pull
4779 This operation is symmetrical to pull: it is identical to a pull
4781 in the destination repository from the current one.
4780 in the destination repository from the current one.
4782
4781
4783 By default, push will not allow creation of new heads at the
4782 By default, push will not allow creation of new heads at the
4784 destination, since multiple heads would make it unclear which head
4783 destination, since multiple heads would make it unclear which head
4785 to use. In this situation, it is recommended to pull and merge
4784 to use. In this situation, it is recommended to pull and merge
4786 before pushing.
4785 before pushing.
4787
4786
4788 Use --new-branch if you want to allow push to create a new named
4787 Use --new-branch if you want to allow push to create a new named
4789 branch that is not present at the destination. This allows you to
4788 branch that is not present at the destination. This allows you to
4790 only create a new branch without forcing other changes.
4789 only create a new branch without forcing other changes.
4791
4790
4792 Use -f/--force to override the default behavior and push all
4791 Use -f/--force to override the default behavior and push all
4793 changesets on all branches.
4792 changesets on all branches.
4794
4793
4795 If -r/--rev is used, the specified revision and all its ancestors
4794 If -r/--rev is used, the specified revision and all its ancestors
4796 will be pushed to the remote repository.
4795 will be pushed to the remote repository.
4797
4796
4798 If -B/--bookmark is used, the specified bookmarked revision, its
4797 If -B/--bookmark is used, the specified bookmarked revision, its
4799 ancestors, and the bookmark will be pushed to the remote
4798 ancestors, and the bookmark will be pushed to the remote
4800 repository.
4799 repository.
4801
4800
4802 Please see :hg:`help urls` for important details about ``ssh://``
4801 Please see :hg:`help urls` for important details about ``ssh://``
4803 URLs. If DESTINATION is omitted, a default path will be used.
4802 URLs. If DESTINATION is omitted, a default path will be used.
4804
4803
4805 Returns 0 if push was successful, 1 if nothing to push.
4804 Returns 0 if push was successful, 1 if nothing to push.
4806 """
4805 """
4807
4806
4808 if opts.get('bookmark'):
4807 if opts.get('bookmark'):
4809 for b in opts['bookmark']:
4808 for b in opts['bookmark']:
4810 # translate -B options to -r so changesets get pushed
4809 # translate -B options to -r so changesets get pushed
4811 if b in repo._bookmarks:
4810 if b in repo._bookmarks:
4812 opts.setdefault('rev', []).append(b)
4811 opts.setdefault('rev', []).append(b)
4813 else:
4812 else:
4814 # if we try to push a deleted bookmark, translate it to null
4813 # if we try to push a deleted bookmark, translate it to null
4815 # this lets simultaneous -r, -b options continue working
4814 # this lets simultaneous -r, -b options continue working
4816 opts.setdefault('rev', []).append("null")
4815 opts.setdefault('rev', []).append("null")
4817
4816
4818 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4817 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4819 dest, branches = hg.parseurl(dest, opts.get('branch'))
4818 dest, branches = hg.parseurl(dest, opts.get('branch'))
4820 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4819 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4821 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4820 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4822 other = hg.peer(repo, opts, dest)
4821 other = hg.peer(repo, opts, dest)
4823 if revs:
4822 if revs:
4824 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4823 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4825
4824
4826 repo._subtoppath = dest
4825 repo._subtoppath = dest
4827 try:
4826 try:
4828 # push subrepos depth-first for coherent ordering
4827 # push subrepos depth-first for coherent ordering
4829 c = repo['']
4828 c = repo['']
4830 subs = c.substate # only repos that are committed
4829 subs = c.substate # only repos that are committed
4831 for s in sorted(subs):
4830 for s in sorted(subs):
4832 if c.sub(s).push(opts) == 0:
4831 if c.sub(s).push(opts) == 0:
4833 return False
4832 return False
4834 finally:
4833 finally:
4835 del repo._subtoppath
4834 del repo._subtoppath
4836 result = repo.push(other, opts.get('force'), revs=revs,
4835 result = repo.push(other, opts.get('force'), revs=revs,
4837 newbranch=opts.get('new_branch'))
4836 newbranch=opts.get('new_branch'))
4838
4837
4839 result = not result
4838 result = not result
4840
4839
4841 if opts.get('bookmark'):
4840 if opts.get('bookmark'):
4842 rb = other.listkeys('bookmarks')
4841 rb = other.listkeys('bookmarks')
4843 for b in opts['bookmark']:
4842 for b in opts['bookmark']:
4844 # explicit push overrides remote bookmark if any
4843 # explicit push overrides remote bookmark if any
4845 if b in repo._bookmarks:
4844 if b in repo._bookmarks:
4846 ui.status(_("exporting bookmark %s\n") % b)
4845 ui.status(_("exporting bookmark %s\n") % b)
4847 new = repo[b].hex()
4846 new = repo[b].hex()
4848 elif b in rb:
4847 elif b in rb:
4849 ui.status(_("deleting remote bookmark %s\n") % b)
4848 ui.status(_("deleting remote bookmark %s\n") % b)
4850 new = '' # delete
4849 new = '' # delete
4851 else:
4850 else:
4852 ui.warn(_('bookmark %s does not exist on the local '
4851 ui.warn(_('bookmark %s does not exist on the local '
4853 'or remote repository!\n') % b)
4852 'or remote repository!\n') % b)
4854 return 2
4853 return 2
4855 old = rb.get(b, '')
4854 old = rb.get(b, '')
4856 r = other.pushkey('bookmarks', b, old, new)
4855 r = other.pushkey('bookmarks', b, old, new)
4857 if not r:
4856 if not r:
4858 ui.warn(_('updating bookmark %s failed!\n') % b)
4857 ui.warn(_('updating bookmark %s failed!\n') % b)
4859 if not result:
4858 if not result:
4860 result = 2
4859 result = 2
4861
4860
4862 return result
4861 return result
4863
4862
4864 @command('recover', [])
4863 @command('recover', [])
4865 def recover(ui, repo):
4864 def recover(ui, repo):
4866 """roll back an interrupted transaction
4865 """roll back an interrupted transaction
4867
4866
4868 Recover from an interrupted commit or pull.
4867 Recover from an interrupted commit or pull.
4869
4868
4870 This command tries to fix the repository status after an
4869 This command tries to fix the repository status after an
4871 interrupted operation. It should only be necessary when Mercurial
4870 interrupted operation. It should only be necessary when Mercurial
4872 suggests it.
4871 suggests it.
4873
4872
4874 Returns 0 if successful, 1 if nothing to recover or verify fails.
4873 Returns 0 if successful, 1 if nothing to recover or verify fails.
4875 """
4874 """
4876 if repo.recover():
4875 if repo.recover():
4877 return hg.verify(repo)
4876 return hg.verify(repo)
4878 return 1
4877 return 1
4879
4878
4880 @command('^remove|rm',
4879 @command('^remove|rm',
4881 [('A', 'after', None, _('record delete for missing files')),
4880 [('A', 'after', None, _('record delete for missing files')),
4882 ('f', 'force', None,
4881 ('f', 'force', None,
4883 _('remove (and delete) file even if added or modified')),
4882 _('remove (and delete) file even if added or modified')),
4884 ] + walkopts,
4883 ] + walkopts,
4885 _('[OPTION]... FILE...'))
4884 _('[OPTION]... FILE...'))
4886 def remove(ui, repo, *pats, **opts):
4885 def remove(ui, repo, *pats, **opts):
4887 """remove the specified files on the next commit
4886 """remove the specified files on the next commit
4888
4887
4889 Schedule the indicated files for removal from the current branch.
4888 Schedule the indicated files for removal from the current branch.
4890
4889
4891 This command schedules the files to be removed at the next commit.
4890 This command schedules the files to be removed at the next commit.
4892 To undo a remove before that, see :hg:`revert`. To undo added
4891 To undo a remove before that, see :hg:`revert`. To undo added
4893 files, see :hg:`forget`.
4892 files, see :hg:`forget`.
4894
4893
4895 .. container:: verbose
4894 .. container:: verbose
4896
4895
4897 -A/--after can be used to remove only files that have already
4896 -A/--after can be used to remove only files that have already
4898 been deleted, -f/--force can be used to force deletion, and -Af
4897 been deleted, -f/--force can be used to force deletion, and -Af
4899 can be used to remove files from the next revision without
4898 can be used to remove files from the next revision without
4900 deleting them from the working directory.
4899 deleting them from the working directory.
4901
4900
4902 The following table details the behavior of remove for different
4901 The following table details the behavior of remove for different
4903 file states (columns) and option combinations (rows). The file
4902 file states (columns) and option combinations (rows). The file
4904 states are Added [A], Clean [C], Modified [M] and Missing [!]
4903 states are Added [A], Clean [C], Modified [M] and Missing [!]
4905 (as reported by :hg:`status`). The actions are Warn, Remove
4904 (as reported by :hg:`status`). The actions are Warn, Remove
4906 (from branch) and Delete (from disk):
4905 (from branch) and Delete (from disk):
4907
4906
4908 ======= == == == ==
4907 ======= == == == ==
4909 A C M !
4908 A C M !
4910 ======= == == == ==
4909 ======= == == == ==
4911 none W RD W R
4910 none W RD W R
4912 -f R RD RD R
4911 -f R RD RD R
4913 -A W W W R
4912 -A W W W R
4914 -Af R R R R
4913 -Af R R R R
4915 ======= == == == ==
4914 ======= == == == ==
4916
4915
4917 Note that remove never deletes files in Added [A] state from the
4916 Note that remove never deletes files in Added [A] state from the
4918 working directory, not even if option --force is specified.
4917 working directory, not even if option --force is specified.
4919
4918
4920 Returns 0 on success, 1 if any warnings encountered.
4919 Returns 0 on success, 1 if any warnings encountered.
4921 """
4920 """
4922
4921
4923 ret = 0
4922 ret = 0
4924 after, force = opts.get('after'), opts.get('force')
4923 after, force = opts.get('after'), opts.get('force')
4925 if not pats and not after:
4924 if not pats and not after:
4926 raise util.Abort(_('no files specified'))
4925 raise util.Abort(_('no files specified'))
4927
4926
4928 m = scmutil.match(repo[None], pats, opts)
4927 m = scmutil.match(repo[None], pats, opts)
4929 s = repo.status(match=m, clean=True)
4928 s = repo.status(match=m, clean=True)
4930 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4929 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4931
4930
4932 # warn about failure to delete explicit files/dirs
4931 # warn about failure to delete explicit files/dirs
4933 wctx = repo[None]
4932 wctx = repo[None]
4934 for f in m.files():
4933 for f in m.files():
4935 if f in repo.dirstate or f in wctx.dirs():
4934 if f in repo.dirstate or f in wctx.dirs():
4936 continue
4935 continue
4937 if os.path.exists(m.rel(f)):
4936 if os.path.exists(m.rel(f)):
4938 if os.path.isdir(m.rel(f)):
4937 if os.path.isdir(m.rel(f)):
4939 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4938 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4940 else:
4939 else:
4941 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4940 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4942 # missing files will generate a warning elsewhere
4941 # missing files will generate a warning elsewhere
4943 ret = 1
4942 ret = 1
4944
4943
4945 if force:
4944 if force:
4946 list = modified + deleted + clean + added
4945 list = modified + deleted + clean + added
4947 elif after:
4946 elif after:
4948 list = deleted
4947 list = deleted
4949 for f in modified + added + clean:
4948 for f in modified + added + clean:
4950 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4949 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4951 ret = 1
4950 ret = 1
4952 else:
4951 else:
4953 list = deleted + clean
4952 list = deleted + clean
4954 for f in modified:
4953 for f in modified:
4955 ui.warn(_('not removing %s: file is modified (use -f'
4954 ui.warn(_('not removing %s: file is modified (use -f'
4956 ' to force removal)\n') % m.rel(f))
4955 ' to force removal)\n') % m.rel(f))
4957 ret = 1
4956 ret = 1
4958 for f in added:
4957 for f in added:
4959 ui.warn(_('not removing %s: file has been marked for add'
4958 ui.warn(_('not removing %s: file has been marked for add'
4960 ' (use forget to undo)\n') % m.rel(f))
4959 ' (use forget to undo)\n') % m.rel(f))
4961 ret = 1
4960 ret = 1
4962
4961
4963 for f in sorted(list):
4962 for f in sorted(list):
4964 if ui.verbose or not m.exact(f):
4963 if ui.verbose or not m.exact(f):
4965 ui.status(_('removing %s\n') % m.rel(f))
4964 ui.status(_('removing %s\n') % m.rel(f))
4966
4965
4967 wlock = repo.wlock()
4966 wlock = repo.wlock()
4968 try:
4967 try:
4969 if not after:
4968 if not after:
4970 for f in list:
4969 for f in list:
4971 if f in added:
4970 if f in added:
4972 continue # we never unlink added files on remove
4971 continue # we never unlink added files on remove
4973 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4972 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4974 repo[None].forget(list)
4973 repo[None].forget(list)
4975 finally:
4974 finally:
4976 wlock.release()
4975 wlock.release()
4977
4976
4978 return ret
4977 return ret
4979
4978
4980 @command('rename|move|mv',
4979 @command('rename|move|mv',
4981 [('A', 'after', None, _('record a rename that has already occurred')),
4980 [('A', 'after', None, _('record a rename that has already occurred')),
4982 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4981 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4983 ] + walkopts + dryrunopts,
4982 ] + walkopts + dryrunopts,
4984 _('[OPTION]... SOURCE... DEST'))
4983 _('[OPTION]... SOURCE... DEST'))
4985 def rename(ui, repo, *pats, **opts):
4984 def rename(ui, repo, *pats, **opts):
4986 """rename files; equivalent of copy + remove
4985 """rename files; equivalent of copy + remove
4987
4986
4988 Mark dest as copies of sources; mark sources for deletion. If dest
4987 Mark dest as copies of sources; mark sources for deletion. If dest
4989 is a directory, copies are put in that directory. If dest is a
4988 is a directory, copies are put in that directory. If dest is a
4990 file, there can only be one source.
4989 file, there can only be one source.
4991
4990
4992 By default, this command copies the contents of files as they
4991 By default, this command copies the contents of files as they
4993 exist in the working directory. If invoked with -A/--after, the
4992 exist in the working directory. If invoked with -A/--after, the
4994 operation is recorded, but no copying is performed.
4993 operation is recorded, but no copying is performed.
4995
4994
4996 This command takes effect at the next commit. To undo a rename
4995 This command takes effect at the next commit. To undo a rename
4997 before that, see :hg:`revert`.
4996 before that, see :hg:`revert`.
4998
4997
4999 Returns 0 on success, 1 if errors are encountered.
4998 Returns 0 on success, 1 if errors are encountered.
5000 """
4999 """
5001 wlock = repo.wlock(False)
5000 wlock = repo.wlock(False)
5002 try:
5001 try:
5003 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5002 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5004 finally:
5003 finally:
5005 wlock.release()
5004 wlock.release()
5006
5005
5007 @command('resolve',
5006 @command('resolve',
5008 [('a', 'all', None, _('select all unresolved files')),
5007 [('a', 'all', None, _('select all unresolved files')),
5009 ('l', 'list', None, _('list state of files needing merge')),
5008 ('l', 'list', None, _('list state of files needing merge')),
5010 ('m', 'mark', None, _('mark files as resolved')),
5009 ('m', 'mark', None, _('mark files as resolved')),
5011 ('u', 'unmark', None, _('mark files as unresolved')),
5010 ('u', 'unmark', None, _('mark files as unresolved')),
5012 ('n', 'no-status', None, _('hide status prefix'))]
5011 ('n', 'no-status', None, _('hide status prefix'))]
5013 + mergetoolopts + walkopts,
5012 + mergetoolopts + walkopts,
5014 _('[OPTION]... [FILE]...'))
5013 _('[OPTION]... [FILE]...'))
5015 def resolve(ui, repo, *pats, **opts):
5014 def resolve(ui, repo, *pats, **opts):
5016 """redo merges or set/view the merge status of files
5015 """redo merges or set/view the merge status of files
5017
5016
5018 Merges with unresolved conflicts are often the result of
5017 Merges with unresolved conflicts are often the result of
5019 non-interactive merging using the ``internal:merge`` configuration
5018 non-interactive merging using the ``internal:merge`` configuration
5020 setting, or a command-line merge tool like ``diff3``. The resolve
5019 setting, or a command-line merge tool like ``diff3``. The resolve
5021 command is used to manage the files involved in a merge, after
5020 command is used to manage the files involved in a merge, after
5022 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5021 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5023 working directory must have two parents). See :hg:`help
5022 working directory must have two parents). See :hg:`help
5024 merge-tools` for information on configuring merge tools.
5023 merge-tools` for information on configuring merge tools.
5025
5024
5026 The resolve command can be used in the following ways:
5025 The resolve command can be used in the following ways:
5027
5026
5028 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5027 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5029 files, discarding any previous merge attempts. Re-merging is not
5028 files, discarding any previous merge attempts. Re-merging is not
5030 performed for files already marked as resolved. Use ``--all/-a``
5029 performed for files already marked as resolved. Use ``--all/-a``
5031 to select all unresolved files. ``--tool`` can be used to specify
5030 to select all unresolved files. ``--tool`` can be used to specify
5032 the merge tool used for the given files. It overrides the HGMERGE
5031 the merge tool used for the given files. It overrides the HGMERGE
5033 environment variable and your configuration files. Previous file
5032 environment variable and your configuration files. Previous file
5034 contents are saved with a ``.orig`` suffix.
5033 contents are saved with a ``.orig`` suffix.
5035
5034
5036 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5035 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5037 (e.g. after having manually fixed-up the files). The default is
5036 (e.g. after having manually fixed-up the files). The default is
5038 to mark all unresolved files.
5037 to mark all unresolved files.
5039
5038
5040 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5039 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5041 default is to mark all resolved files.
5040 default is to mark all resolved files.
5042
5041
5043 - :hg:`resolve -l`: list files which had or still have conflicts.
5042 - :hg:`resolve -l`: list files which had or still have conflicts.
5044 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5043 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5045
5044
5046 Note that Mercurial will not let you commit files with unresolved
5045 Note that Mercurial will not let you commit files with unresolved
5047 merge conflicts. You must use :hg:`resolve -m ...` before you can
5046 merge conflicts. You must use :hg:`resolve -m ...` before you can
5048 commit after a conflicting merge.
5047 commit after a conflicting merge.
5049
5048
5050 Returns 0 on success, 1 if any files fail a resolve attempt.
5049 Returns 0 on success, 1 if any files fail a resolve attempt.
5051 """
5050 """
5052
5051
5053 all, mark, unmark, show, nostatus = \
5052 all, mark, unmark, show, nostatus = \
5054 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5053 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5055
5054
5056 if (show and (mark or unmark)) or (mark and unmark):
5055 if (show and (mark or unmark)) or (mark and unmark):
5057 raise util.Abort(_("too many options specified"))
5056 raise util.Abort(_("too many options specified"))
5058 if pats and all:
5057 if pats and all:
5059 raise util.Abort(_("can't specify --all and patterns"))
5058 raise util.Abort(_("can't specify --all and patterns"))
5060 if not (all or pats or show or mark or unmark):
5059 if not (all or pats or show or mark or unmark):
5061 raise util.Abort(_('no files or directories specified; '
5060 raise util.Abort(_('no files or directories specified; '
5062 'use --all to remerge all files'))
5061 'use --all to remerge all files'))
5063
5062
5064 ms = mergemod.mergestate(repo)
5063 ms = mergemod.mergestate(repo)
5065 m = scmutil.match(repo[None], pats, opts)
5064 m = scmutil.match(repo[None], pats, opts)
5066 ret = 0
5065 ret = 0
5067
5066
5068 for f in ms:
5067 for f in ms:
5069 if m(f):
5068 if m(f):
5070 if show:
5069 if show:
5071 if nostatus:
5070 if nostatus:
5072 ui.write("%s\n" % f)
5071 ui.write("%s\n" % f)
5073 else:
5072 else:
5074 ui.write("%s %s\n" % (ms[f].upper(), f),
5073 ui.write("%s %s\n" % (ms[f].upper(), f),
5075 label='resolve.' +
5074 label='resolve.' +
5076 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5075 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5077 elif mark:
5076 elif mark:
5078 ms.mark(f, "r")
5077 ms.mark(f, "r")
5079 elif unmark:
5078 elif unmark:
5080 ms.mark(f, "u")
5079 ms.mark(f, "u")
5081 else:
5080 else:
5082 wctx = repo[None]
5081 wctx = repo[None]
5083 mctx = wctx.parents()[-1]
5082 mctx = wctx.parents()[-1]
5084
5083
5085 # backup pre-resolve (merge uses .orig for its own purposes)
5084 # backup pre-resolve (merge uses .orig for its own purposes)
5086 a = repo.wjoin(f)
5085 a = repo.wjoin(f)
5087 util.copyfile(a, a + ".resolve")
5086 util.copyfile(a, a + ".resolve")
5088
5087
5089 try:
5088 try:
5090 # resolve file
5089 # resolve file
5091 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5090 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5092 if ms.resolve(f, wctx, mctx):
5091 if ms.resolve(f, wctx, mctx):
5093 ret = 1
5092 ret = 1
5094 finally:
5093 finally:
5095 ui.setconfig('ui', 'forcemerge', '')
5094 ui.setconfig('ui', 'forcemerge', '')
5096 ms.commit()
5095 ms.commit()
5097
5096
5098 # replace filemerge's .orig file with our resolve file
5097 # replace filemerge's .orig file with our resolve file
5099 util.rename(a + ".resolve", a + ".orig")
5098 util.rename(a + ".resolve", a + ".orig")
5100
5099
5101 ms.commit()
5100 ms.commit()
5102 return ret
5101 return ret
5103
5102
5104 @command('revert',
5103 @command('revert',
5105 [('a', 'all', None, _('revert all changes when no arguments given')),
5104 [('a', 'all', None, _('revert all changes when no arguments given')),
5106 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5105 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5107 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5106 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5108 ('C', 'no-backup', None, _('do not save backup copies of files')),
5107 ('C', 'no-backup', None, _('do not save backup copies of files')),
5109 ] + walkopts + dryrunopts,
5108 ] + walkopts + dryrunopts,
5110 _('[OPTION]... [-r REV] [NAME]...'))
5109 _('[OPTION]... [-r REV] [NAME]...'))
5111 def revert(ui, repo, *pats, **opts):
5110 def revert(ui, repo, *pats, **opts):
5112 """restore files to their checkout state
5111 """restore files to their checkout state
5113
5112
5114 .. note::
5113 .. note::
5115
5114
5116 To check out earlier revisions, you should use :hg:`update REV`.
5115 To check out earlier revisions, you should use :hg:`update REV`.
5117 To cancel an uncommitted merge (and lose your changes), use
5116 To cancel an uncommitted merge (and lose your changes), use
5118 :hg:`update --clean .`.
5117 :hg:`update --clean .`.
5119
5118
5120 With no revision specified, revert the specified files or directories
5119 With no revision specified, revert the specified files or directories
5121 to the contents they had in the parent of the working directory.
5120 to the contents they had in the parent of the working directory.
5122 This restores the contents of files to an unmodified
5121 This restores the contents of files to an unmodified
5123 state and unschedules adds, removes, copies, and renames. If the
5122 state and unschedules adds, removes, copies, and renames. If the
5124 working directory has two parents, you must explicitly specify a
5123 working directory has two parents, you must explicitly specify a
5125 revision.
5124 revision.
5126
5125
5127 Using the -r/--rev or -d/--date options, revert the given files or
5126 Using the -r/--rev or -d/--date options, revert the given files or
5128 directories to their states as of a specific revision. Because
5127 directories to their states as of a specific revision. Because
5129 revert does not change the working directory parents, this will
5128 revert does not change the working directory parents, this will
5130 cause these files to appear modified. This can be helpful to "back
5129 cause these files to appear modified. This can be helpful to "back
5131 out" some or all of an earlier change. See :hg:`backout` for a
5130 out" some or all of an earlier change. See :hg:`backout` for a
5132 related method.
5131 related method.
5133
5132
5134 Modified files are saved with a .orig suffix before reverting.
5133 Modified files are saved with a .orig suffix before reverting.
5135 To disable these backups, use --no-backup.
5134 To disable these backups, use --no-backup.
5136
5135
5137 See :hg:`help dates` for a list of formats valid for -d/--date.
5136 See :hg:`help dates` for a list of formats valid for -d/--date.
5138
5137
5139 Returns 0 on success.
5138 Returns 0 on success.
5140 """
5139 """
5141
5140
5142 if opts.get("date"):
5141 if opts.get("date"):
5143 if opts.get("rev"):
5142 if opts.get("rev"):
5144 raise util.Abort(_("you can't specify a revision and a date"))
5143 raise util.Abort(_("you can't specify a revision and a date"))
5145 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5144 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5146
5145
5147 parent, p2 = repo.dirstate.parents()
5146 parent, p2 = repo.dirstate.parents()
5148 if not opts.get('rev') and p2 != nullid:
5147 if not opts.get('rev') and p2 != nullid:
5149 # revert after merge is a trap for new users (issue2915)
5148 # revert after merge is a trap for new users (issue2915)
5150 raise util.Abort(_('uncommitted merge with no revision specified'),
5149 raise util.Abort(_('uncommitted merge with no revision specified'),
5151 hint=_('use "hg update" or see "hg help revert"'))
5150 hint=_('use "hg update" or see "hg help revert"'))
5152
5151
5153 ctx = scmutil.revsingle(repo, opts.get('rev'))
5152 ctx = scmutil.revsingle(repo, opts.get('rev'))
5154
5153
5155 if not pats and not opts.get('all'):
5154 if not pats and not opts.get('all'):
5156 msg = _("no files or directories specified")
5155 msg = _("no files or directories specified")
5157 if p2 != nullid:
5156 if p2 != nullid:
5158 hint = _("uncommitted merge, use --all to discard all changes,"
5157 hint = _("uncommitted merge, use --all to discard all changes,"
5159 " or 'hg update -C .' to abort the merge")
5158 " or 'hg update -C .' to abort the merge")
5160 raise util.Abort(msg, hint=hint)
5159 raise util.Abort(msg, hint=hint)
5161 dirty = util.any(repo.status())
5160 dirty = util.any(repo.status())
5162 node = ctx.node()
5161 node = ctx.node()
5163 if node != parent:
5162 if node != parent:
5164 if dirty:
5163 if dirty:
5165 hint = _("uncommitted changes, use --all to discard all"
5164 hint = _("uncommitted changes, use --all to discard all"
5166 " changes, or 'hg update %s' to update") % ctx.rev()
5165 " changes, or 'hg update %s' to update") % ctx.rev()
5167 else:
5166 else:
5168 hint = _("use --all to revert all files,"
5167 hint = _("use --all to revert all files,"
5169 " or 'hg update %s' to update") % ctx.rev()
5168 " or 'hg update %s' to update") % ctx.rev()
5170 elif dirty:
5169 elif dirty:
5171 hint = _("uncommitted changes, use --all to discard all changes")
5170 hint = _("uncommitted changes, use --all to discard all changes")
5172 else:
5171 else:
5173 hint = _("use --all to revert all files")
5172 hint = _("use --all to revert all files")
5174 raise util.Abort(msg, hint=hint)
5173 raise util.Abort(msg, hint=hint)
5175
5174
5176 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5175 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5177
5176
5178 @command('rollback', dryrunopts +
5177 @command('rollback', dryrunopts +
5179 [('f', 'force', False, _('ignore safety measures'))])
5178 [('f', 'force', False, _('ignore safety measures'))])
5180 def rollback(ui, repo, **opts):
5179 def rollback(ui, repo, **opts):
5181 """roll back the last transaction (dangerous)
5180 """roll back the last transaction (dangerous)
5182
5181
5183 This command should be used with care. There is only one level of
5182 This command should be used with care. There is only one level of
5184 rollback, and there is no way to undo a rollback. It will also
5183 rollback, and there is no way to undo a rollback. It will also
5185 restore the dirstate at the time of the last transaction, losing
5184 restore the dirstate at the time of the last transaction, losing
5186 any dirstate changes since that time. This command does not alter
5185 any dirstate changes since that time. This command does not alter
5187 the working directory.
5186 the working directory.
5188
5187
5189 Transactions are used to encapsulate the effects of all commands
5188 Transactions are used to encapsulate the effects of all commands
5190 that create new changesets or propagate existing changesets into a
5189 that create new changesets or propagate existing changesets into a
5191 repository.
5190 repository.
5192
5191
5193 .. container:: verbose
5192 .. container:: verbose
5194
5193
5195 For example, the following commands are transactional, and their
5194 For example, the following commands are transactional, and their
5196 effects can be rolled back:
5195 effects can be rolled back:
5197
5196
5198 - commit
5197 - commit
5199 - import
5198 - import
5200 - pull
5199 - pull
5201 - push (with this repository as the destination)
5200 - push (with this repository as the destination)
5202 - unbundle
5201 - unbundle
5203
5202
5204 To avoid permanent data loss, rollback will refuse to rollback a
5203 To avoid permanent data loss, rollback will refuse to rollback a
5205 commit transaction if it isn't checked out. Use --force to
5204 commit transaction if it isn't checked out. Use --force to
5206 override this protection.
5205 override this protection.
5207
5206
5208 This command is not intended for use on public repositories. Once
5207 This command is not intended for use on public repositories. Once
5209 changes are visible for pull by other users, rolling a transaction
5208 changes are visible for pull by other users, rolling a transaction
5210 back locally is ineffective (someone else may already have pulled
5209 back locally is ineffective (someone else may already have pulled
5211 the changes). Furthermore, a race is possible with readers of the
5210 the changes). Furthermore, a race is possible with readers of the
5212 repository; for example an in-progress pull from the repository
5211 repository; for example an in-progress pull from the repository
5213 may fail if a rollback is performed.
5212 may fail if a rollback is performed.
5214
5213
5215 Returns 0 on success, 1 if no rollback data is available.
5214 Returns 0 on success, 1 if no rollback data is available.
5216 """
5215 """
5217 return repo.rollback(dryrun=opts.get('dry_run'),
5216 return repo.rollback(dryrun=opts.get('dry_run'),
5218 force=opts.get('force'))
5217 force=opts.get('force'))
5219
5218
5220 @command('root', [])
5219 @command('root', [])
5221 def root(ui, repo):
5220 def root(ui, repo):
5222 """print the root (top) of the current working directory
5221 """print the root (top) of the current working directory
5223
5222
5224 Print the root directory of the current repository.
5223 Print the root directory of the current repository.
5225
5224
5226 Returns 0 on success.
5225 Returns 0 on success.
5227 """
5226 """
5228 ui.write(repo.root + "\n")
5227 ui.write(repo.root + "\n")
5229
5228
5230 @command('^serve',
5229 @command('^serve',
5231 [('A', 'accesslog', '', _('name of access log file to write to'),
5230 [('A', 'accesslog', '', _('name of access log file to write to'),
5232 _('FILE')),
5231 _('FILE')),
5233 ('d', 'daemon', None, _('run server in background')),
5232 ('d', 'daemon', None, _('run server in background')),
5234 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5233 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5235 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5234 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5236 # use string type, then we can check if something was passed
5235 # use string type, then we can check if something was passed
5237 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5236 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5238 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5237 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5239 _('ADDR')),
5238 _('ADDR')),
5240 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5239 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5241 _('PREFIX')),
5240 _('PREFIX')),
5242 ('n', 'name', '',
5241 ('n', 'name', '',
5243 _('name to show in web pages (default: working directory)'), _('NAME')),
5242 _('name to show in web pages (default: working directory)'), _('NAME')),
5244 ('', 'web-conf', '',
5243 ('', 'web-conf', '',
5245 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5244 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5246 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5245 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5247 _('FILE')),
5246 _('FILE')),
5248 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5247 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5249 ('', 'stdio', None, _('for remote clients')),
5248 ('', 'stdio', None, _('for remote clients')),
5250 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5249 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5251 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5250 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5252 ('', 'style', '', _('template style to use'), _('STYLE')),
5251 ('', 'style', '', _('template style to use'), _('STYLE')),
5253 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5252 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5254 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5253 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5255 _('[OPTION]...'))
5254 _('[OPTION]...'))
5256 def serve(ui, repo, **opts):
5255 def serve(ui, repo, **opts):
5257 """start stand-alone webserver
5256 """start stand-alone webserver
5258
5257
5259 Start a local HTTP repository browser and pull server. You can use
5258 Start a local HTTP repository browser and pull server. You can use
5260 this for ad-hoc sharing and browsing of repositories. It is
5259 this for ad-hoc sharing and browsing of repositories. It is
5261 recommended to use a real web server to serve a repository for
5260 recommended to use a real web server to serve a repository for
5262 longer periods of time.
5261 longer periods of time.
5263
5262
5264 Please note that the server does not implement access control.
5263 Please note that the server does not implement access control.
5265 This means that, by default, anybody can read from the server and
5264 This means that, by default, anybody can read from the server and
5266 nobody can write to it by default. Set the ``web.allow_push``
5265 nobody can write to it by default. Set the ``web.allow_push``
5267 option to ``*`` to allow everybody to push to the server. You
5266 option to ``*`` to allow everybody to push to the server. You
5268 should use a real web server if you need to authenticate users.
5267 should use a real web server if you need to authenticate users.
5269
5268
5270 By default, the server logs accesses to stdout and errors to
5269 By default, the server logs accesses to stdout and errors to
5271 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5270 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5272 files.
5271 files.
5273
5272
5274 To have the server choose a free port number to listen on, specify
5273 To have the server choose a free port number to listen on, specify
5275 a port number of 0; in this case, the server will print the port
5274 a port number of 0; in this case, the server will print the port
5276 number it uses.
5275 number it uses.
5277
5276
5278 Returns 0 on success.
5277 Returns 0 on success.
5279 """
5278 """
5280
5279
5281 if opts["stdio"] and opts["cmdserver"]:
5280 if opts["stdio"] and opts["cmdserver"]:
5282 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5281 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5283
5282
5284 def checkrepo():
5283 def checkrepo():
5285 if repo is None:
5284 if repo is None:
5286 raise error.RepoError(_("there is no Mercurial repository here"
5285 raise error.RepoError(_("there is no Mercurial repository here"
5287 " (.hg not found)"))
5286 " (.hg not found)"))
5288
5287
5289 if opts["stdio"]:
5288 if opts["stdio"]:
5290 checkrepo()
5289 checkrepo()
5291 s = sshserver.sshserver(ui, repo)
5290 s = sshserver.sshserver(ui, repo)
5292 s.serve_forever()
5291 s.serve_forever()
5293
5292
5294 if opts["cmdserver"]:
5293 if opts["cmdserver"]:
5295 checkrepo()
5294 checkrepo()
5296 s = commandserver.server(ui, repo, opts["cmdserver"])
5295 s = commandserver.server(ui, repo, opts["cmdserver"])
5297 return s.serve()
5296 return s.serve()
5298
5297
5299 # this way we can check if something was given in the command-line
5298 # this way we can check if something was given in the command-line
5300 if opts.get('port'):
5299 if opts.get('port'):
5301 opts['port'] = util.getport(opts.get('port'))
5300 opts['port'] = util.getport(opts.get('port'))
5302
5301
5303 baseui = repo and repo.baseui or ui
5302 baseui = repo and repo.baseui or ui
5304 optlist = ("name templates style address port prefix ipv6"
5303 optlist = ("name templates style address port prefix ipv6"
5305 " accesslog errorlog certificate encoding")
5304 " accesslog errorlog certificate encoding")
5306 for o in optlist.split():
5305 for o in optlist.split():
5307 val = opts.get(o, '')
5306 val = opts.get(o, '')
5308 if val in (None, ''): # should check against default options instead
5307 if val in (None, ''): # should check against default options instead
5309 continue
5308 continue
5310 baseui.setconfig("web", o, val)
5309 baseui.setconfig("web", o, val)
5311 if repo and repo.ui != baseui:
5310 if repo and repo.ui != baseui:
5312 repo.ui.setconfig("web", o, val)
5311 repo.ui.setconfig("web", o, val)
5313
5312
5314 o = opts.get('web_conf') or opts.get('webdir_conf')
5313 o = opts.get('web_conf') or opts.get('webdir_conf')
5315 if not o:
5314 if not o:
5316 if not repo:
5315 if not repo:
5317 raise error.RepoError(_("there is no Mercurial repository"
5316 raise error.RepoError(_("there is no Mercurial repository"
5318 " here (.hg not found)"))
5317 " here (.hg not found)"))
5319 o = repo.root
5318 o = repo.root
5320
5319
5321 app = hgweb.hgweb(o, baseui=ui)
5320 app = hgweb.hgweb(o, baseui=ui)
5322
5321
5323 class service(object):
5322 class service(object):
5324 def init(self):
5323 def init(self):
5325 util.setsignalhandler()
5324 util.setsignalhandler()
5326 self.httpd = hgweb.server.create_server(ui, app)
5325 self.httpd = hgweb.server.create_server(ui, app)
5327
5326
5328 if opts['port'] and not ui.verbose:
5327 if opts['port'] and not ui.verbose:
5329 return
5328 return
5330
5329
5331 if self.httpd.prefix:
5330 if self.httpd.prefix:
5332 prefix = self.httpd.prefix.strip('/') + '/'
5331 prefix = self.httpd.prefix.strip('/') + '/'
5333 else:
5332 else:
5334 prefix = ''
5333 prefix = ''
5335
5334
5336 port = ':%d' % self.httpd.port
5335 port = ':%d' % self.httpd.port
5337 if port == ':80':
5336 if port == ':80':
5338 port = ''
5337 port = ''
5339
5338
5340 bindaddr = self.httpd.addr
5339 bindaddr = self.httpd.addr
5341 if bindaddr == '0.0.0.0':
5340 if bindaddr == '0.0.0.0':
5342 bindaddr = '*'
5341 bindaddr = '*'
5343 elif ':' in bindaddr: # IPv6
5342 elif ':' in bindaddr: # IPv6
5344 bindaddr = '[%s]' % bindaddr
5343 bindaddr = '[%s]' % bindaddr
5345
5344
5346 fqaddr = self.httpd.fqaddr
5345 fqaddr = self.httpd.fqaddr
5347 if ':' in fqaddr:
5346 if ':' in fqaddr:
5348 fqaddr = '[%s]' % fqaddr
5347 fqaddr = '[%s]' % fqaddr
5349 if opts['port']:
5348 if opts['port']:
5350 write = ui.status
5349 write = ui.status
5351 else:
5350 else:
5352 write = ui.write
5351 write = ui.write
5353 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5352 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5354 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5353 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5355
5354
5356 def run(self):
5355 def run(self):
5357 self.httpd.serve_forever()
5356 self.httpd.serve_forever()
5358
5357
5359 service = service()
5358 service = service()
5360
5359
5361 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5360 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5362
5361
5363 @command('showconfig|debugconfig',
5362 @command('showconfig|debugconfig',
5364 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5363 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5365 _('[-u] [NAME]...'))
5364 _('[-u] [NAME]...'))
5366 def showconfig(ui, repo, *values, **opts):
5365 def showconfig(ui, repo, *values, **opts):
5367 """show combined config settings from all hgrc files
5366 """show combined config settings from all hgrc files
5368
5367
5369 With no arguments, print names and values of all config items.
5368 With no arguments, print names and values of all config items.
5370
5369
5371 With one argument of the form section.name, print just the value
5370 With one argument of the form section.name, print just the value
5372 of that config item.
5371 of that config item.
5373
5372
5374 With multiple arguments, print names and values of all config
5373 With multiple arguments, print names and values of all config
5375 items with matching section names.
5374 items with matching section names.
5376
5375
5377 With --debug, the source (filename and line number) is printed
5376 With --debug, the source (filename and line number) is printed
5378 for each config item.
5377 for each config item.
5379
5378
5380 Returns 0 on success.
5379 Returns 0 on success.
5381 """
5380 """
5382
5381
5383 for f in scmutil.rcpath():
5382 for f in scmutil.rcpath():
5384 ui.debug('read config from: %s\n' % f)
5383 ui.debug('read config from: %s\n' % f)
5385 untrusted = bool(opts.get('untrusted'))
5384 untrusted = bool(opts.get('untrusted'))
5386 if values:
5385 if values:
5387 sections = [v for v in values if '.' not in v]
5386 sections = [v for v in values if '.' not in v]
5388 items = [v for v in values if '.' in v]
5387 items = [v for v in values if '.' in v]
5389 if len(items) > 1 or items and sections:
5388 if len(items) > 1 or items and sections:
5390 raise util.Abort(_('only one config item permitted'))
5389 raise util.Abort(_('only one config item permitted'))
5391 for section, name, value in ui.walkconfig(untrusted=untrusted):
5390 for section, name, value in ui.walkconfig(untrusted=untrusted):
5392 value = str(value).replace('\n', '\\n')
5391 value = str(value).replace('\n', '\\n')
5393 sectname = section + '.' + name
5392 sectname = section + '.' + name
5394 if values:
5393 if values:
5395 for v in values:
5394 for v in values:
5396 if v == section:
5395 if v == section:
5397 ui.debug('%s: ' %
5396 ui.debug('%s: ' %
5398 ui.configsource(section, name, untrusted))
5397 ui.configsource(section, name, untrusted))
5399 ui.write('%s=%s\n' % (sectname, value))
5398 ui.write('%s=%s\n' % (sectname, value))
5400 elif v == sectname:
5399 elif v == sectname:
5401 ui.debug('%s: ' %
5400 ui.debug('%s: ' %
5402 ui.configsource(section, name, untrusted))
5401 ui.configsource(section, name, untrusted))
5403 ui.write(value, '\n')
5402 ui.write(value, '\n')
5404 else:
5403 else:
5405 ui.debug('%s: ' %
5404 ui.debug('%s: ' %
5406 ui.configsource(section, name, untrusted))
5405 ui.configsource(section, name, untrusted))
5407 ui.write('%s=%s\n' % (sectname, value))
5406 ui.write('%s=%s\n' % (sectname, value))
5408
5407
5409 @command('^status|st',
5408 @command('^status|st',
5410 [('A', 'all', None, _('show status of all files')),
5409 [('A', 'all', None, _('show status of all files')),
5411 ('m', 'modified', None, _('show only modified files')),
5410 ('m', 'modified', None, _('show only modified files')),
5412 ('a', 'added', None, _('show only added files')),
5411 ('a', 'added', None, _('show only added files')),
5413 ('r', 'removed', None, _('show only removed files')),
5412 ('r', 'removed', None, _('show only removed files')),
5414 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5413 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5415 ('c', 'clean', None, _('show only files without changes')),
5414 ('c', 'clean', None, _('show only files without changes')),
5416 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5415 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5417 ('i', 'ignored', None, _('show only ignored files')),
5416 ('i', 'ignored', None, _('show only ignored files')),
5418 ('n', 'no-status', None, _('hide status prefix')),
5417 ('n', 'no-status', None, _('hide status prefix')),
5419 ('C', 'copies', None, _('show source of copied files')),
5418 ('C', 'copies', None, _('show source of copied files')),
5420 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5419 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5421 ('', 'rev', [], _('show difference from revision'), _('REV')),
5420 ('', 'rev', [], _('show difference from revision'), _('REV')),
5422 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5421 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5423 ] + walkopts + subrepoopts,
5422 ] + walkopts + subrepoopts,
5424 _('[OPTION]... [FILE]...'))
5423 _('[OPTION]... [FILE]...'))
5425 def status(ui, repo, *pats, **opts):
5424 def status(ui, repo, *pats, **opts):
5426 """show changed files in the working directory
5425 """show changed files in the working directory
5427
5426
5428 Show status of files in the repository. If names are given, only
5427 Show status of files in the repository. If names are given, only
5429 files that match are shown. Files that are clean or ignored or
5428 files that match are shown. Files that are clean or ignored or
5430 the source of a copy/move operation, are not listed unless
5429 the source of a copy/move operation, are not listed unless
5431 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5430 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5432 Unless options described with "show only ..." are given, the
5431 Unless options described with "show only ..." are given, the
5433 options -mardu are used.
5432 options -mardu are used.
5434
5433
5435 Option -q/--quiet hides untracked (unknown and ignored) files
5434 Option -q/--quiet hides untracked (unknown and ignored) files
5436 unless explicitly requested with -u/--unknown or -i/--ignored.
5435 unless explicitly requested with -u/--unknown or -i/--ignored.
5437
5436
5438 .. note::
5437 .. note::
5439 status may appear to disagree with diff if permissions have
5438 status may appear to disagree with diff if permissions have
5440 changed or a merge has occurred. The standard diff format does
5439 changed or a merge has occurred. The standard diff format does
5441 not report permission changes and diff only reports changes
5440 not report permission changes and diff only reports changes
5442 relative to one merge parent.
5441 relative to one merge parent.
5443
5442
5444 If one revision is given, it is used as the base revision.
5443 If one revision is given, it is used as the base revision.
5445 If two revisions are given, the differences between them are
5444 If two revisions are given, the differences between them are
5446 shown. The --change option can also be used as a shortcut to list
5445 shown. The --change option can also be used as a shortcut to list
5447 the changed files of a revision from its first parent.
5446 the changed files of a revision from its first parent.
5448
5447
5449 The codes used to show the status of files are::
5448 The codes used to show the status of files are::
5450
5449
5451 M = modified
5450 M = modified
5452 A = added
5451 A = added
5453 R = removed
5452 R = removed
5454 C = clean
5453 C = clean
5455 ! = missing (deleted by non-hg command, but still tracked)
5454 ! = missing (deleted by non-hg command, but still tracked)
5456 ? = not tracked
5455 ? = not tracked
5457 I = ignored
5456 I = ignored
5458 = origin of the previous file listed as A (added)
5457 = origin of the previous file listed as A (added)
5459
5458
5460 .. container:: verbose
5459 .. container:: verbose
5461
5460
5462 Examples:
5461 Examples:
5463
5462
5464 - show changes in the working directory relative to a
5463 - show changes in the working directory relative to a
5465 changeset::
5464 changeset::
5466
5465
5467 hg status --rev 9353
5466 hg status --rev 9353
5468
5467
5469 - show all changes including copies in an existing changeset::
5468 - show all changes including copies in an existing changeset::
5470
5469
5471 hg status --copies --change 9353
5470 hg status --copies --change 9353
5472
5471
5473 - get a NUL separated list of added files, suitable for xargs::
5472 - get a NUL separated list of added files, suitable for xargs::
5474
5473
5475 hg status -an0
5474 hg status -an0
5476
5475
5477 Returns 0 on success.
5476 Returns 0 on success.
5478 """
5477 """
5479
5478
5480 revs = opts.get('rev')
5479 revs = opts.get('rev')
5481 change = opts.get('change')
5480 change = opts.get('change')
5482
5481
5483 if revs and change:
5482 if revs and change:
5484 msg = _('cannot specify --rev and --change at the same time')
5483 msg = _('cannot specify --rev and --change at the same time')
5485 raise util.Abort(msg)
5484 raise util.Abort(msg)
5486 elif change:
5485 elif change:
5487 node2 = scmutil.revsingle(repo, change, None).node()
5486 node2 = scmutil.revsingle(repo, change, None).node()
5488 node1 = repo[node2].p1().node()
5487 node1 = repo[node2].p1().node()
5489 else:
5488 else:
5490 node1, node2 = scmutil.revpair(repo, revs)
5489 node1, node2 = scmutil.revpair(repo, revs)
5491
5490
5492 cwd = (pats and repo.getcwd()) or ''
5491 cwd = (pats and repo.getcwd()) or ''
5493 end = opts.get('print0') and '\0' or '\n'
5492 end = opts.get('print0') and '\0' or '\n'
5494 copy = {}
5493 copy = {}
5495 states = 'modified added removed deleted unknown ignored clean'.split()
5494 states = 'modified added removed deleted unknown ignored clean'.split()
5496 show = [k for k in states if opts.get(k)]
5495 show = [k for k in states if opts.get(k)]
5497 if opts.get('all'):
5496 if opts.get('all'):
5498 show += ui.quiet and (states[:4] + ['clean']) or states
5497 show += ui.quiet and (states[:4] + ['clean']) or states
5499 if not show:
5498 if not show:
5500 show = ui.quiet and states[:4] or states[:5]
5499 show = ui.quiet and states[:4] or states[:5]
5501
5500
5502 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5501 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5503 'ignored' in show, 'clean' in show, 'unknown' in show,
5502 'ignored' in show, 'clean' in show, 'unknown' in show,
5504 opts.get('subrepos'))
5503 opts.get('subrepos'))
5505 changestates = zip(states, 'MAR!?IC', stat)
5504 changestates = zip(states, 'MAR!?IC', stat)
5506
5505
5507 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5506 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5508 copy = copies.pathcopies(repo[node1], repo[node2])
5507 copy = copies.pathcopies(repo[node1], repo[node2])
5509
5508
5510 fm = ui.formatter('status', opts)
5509 fm = ui.formatter('status', opts)
5511 fmt = '%s' + end
5510 fmt = '%s' + end
5512 showchar = not opts.get('no_status')
5511 showchar = not opts.get('no_status')
5513
5512
5514 for state, char, files in changestates:
5513 for state, char, files in changestates:
5515 if state in show:
5514 if state in show:
5516 label = 'status.' + state
5515 label = 'status.' + state
5517 for f in files:
5516 for f in files:
5518 fm.startitem()
5517 fm.startitem()
5519 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5518 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5520 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5519 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5521 if f in copy:
5520 if f in copy:
5522 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5521 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5523 label='status.copied')
5522 label='status.copied')
5524 fm.end()
5523 fm.end()
5525
5524
5526 @command('^summary|sum',
5525 @command('^summary|sum',
5527 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5526 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5528 def summary(ui, repo, **opts):
5527 def summary(ui, repo, **opts):
5529 """summarize working directory state
5528 """summarize working directory state
5530
5529
5531 This generates a brief summary of the working directory state,
5530 This generates a brief summary of the working directory state,
5532 including parents, branch, commit status, and available updates.
5531 including parents, branch, commit status, and available updates.
5533
5532
5534 With the --remote option, this will check the default paths for
5533 With the --remote option, this will check the default paths for
5535 incoming and outgoing changes. This can be time-consuming.
5534 incoming and outgoing changes. This can be time-consuming.
5536
5535
5537 Returns 0 on success.
5536 Returns 0 on success.
5538 """
5537 """
5539
5538
5540 ctx = repo[None]
5539 ctx = repo[None]
5541 parents = ctx.parents()
5540 parents = ctx.parents()
5542 pnode = parents[0].node()
5541 pnode = parents[0].node()
5543 marks = []
5542 marks = []
5544
5543
5545 for p in parents:
5544 for p in parents:
5546 # label with log.changeset (instead of log.parent) since this
5545 # label with log.changeset (instead of log.parent) since this
5547 # shows a working directory parent *changeset*:
5546 # shows a working directory parent *changeset*:
5548 # i18n: column positioning for "hg summary"
5547 # i18n: column positioning for "hg summary"
5549 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5548 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5550 label='log.changeset changeset.%s' % p.phasestr())
5549 label='log.changeset changeset.%s' % p.phasestr())
5551 ui.write(' '.join(p.tags()), label='log.tag')
5550 ui.write(' '.join(p.tags()), label='log.tag')
5552 if p.bookmarks():
5551 if p.bookmarks():
5553 marks.extend(p.bookmarks())
5552 marks.extend(p.bookmarks())
5554 if p.rev() == -1:
5553 if p.rev() == -1:
5555 if not len(repo):
5554 if not len(repo):
5556 ui.write(_(' (empty repository)'))
5555 ui.write(_(' (empty repository)'))
5557 else:
5556 else:
5558 ui.write(_(' (no revision checked out)'))
5557 ui.write(_(' (no revision checked out)'))
5559 ui.write('\n')
5558 ui.write('\n')
5560 if p.description():
5559 if p.description():
5561 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5560 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5562 label='log.summary')
5561 label='log.summary')
5563
5562
5564 branch = ctx.branch()
5563 branch = ctx.branch()
5565 bheads = repo.branchheads(branch)
5564 bheads = repo.branchheads(branch)
5566 # i18n: column positioning for "hg summary"
5565 # i18n: column positioning for "hg summary"
5567 m = _('branch: %s\n') % branch
5566 m = _('branch: %s\n') % branch
5568 if branch != 'default':
5567 if branch != 'default':
5569 ui.write(m, label='log.branch')
5568 ui.write(m, label='log.branch')
5570 else:
5569 else:
5571 ui.status(m, label='log.branch')
5570 ui.status(m, label='log.branch')
5572
5571
5573 if marks:
5572 if marks:
5574 current = repo._bookmarkcurrent
5573 current = repo._bookmarkcurrent
5575 # i18n: column positioning for "hg summary"
5574 # i18n: column positioning for "hg summary"
5576 ui.write(_('bookmarks:'), label='log.bookmark')
5575 ui.write(_('bookmarks:'), label='log.bookmark')
5577 if current is not None:
5576 if current is not None:
5578 if current in marks:
5577 if current in marks:
5579 ui.write(' *' + current, label='bookmarks.current')
5578 ui.write(' *' + current, label='bookmarks.current')
5580 marks.remove(current)
5579 marks.remove(current)
5581 else:
5580 else:
5582 ui.write(' [%s]' % current, label='bookmarks.current')
5581 ui.write(' [%s]' % current, label='bookmarks.current')
5583 for m in marks:
5582 for m in marks:
5584 ui.write(' ' + m, label='log.bookmark')
5583 ui.write(' ' + m, label='log.bookmark')
5585 ui.write('\n', label='log.bookmark')
5584 ui.write('\n', label='log.bookmark')
5586
5585
5587 st = list(repo.status(unknown=True))[:6]
5586 st = list(repo.status(unknown=True))[:6]
5588
5587
5589 c = repo.dirstate.copies()
5588 c = repo.dirstate.copies()
5590 copied, renamed = [], []
5589 copied, renamed = [], []
5591 for d, s in c.iteritems():
5590 for d, s in c.iteritems():
5592 if s in st[2]:
5591 if s in st[2]:
5593 st[2].remove(s)
5592 st[2].remove(s)
5594 renamed.append(d)
5593 renamed.append(d)
5595 else:
5594 else:
5596 copied.append(d)
5595 copied.append(d)
5597 if d in st[1]:
5596 if d in st[1]:
5598 st[1].remove(d)
5597 st[1].remove(d)
5599 st.insert(3, renamed)
5598 st.insert(3, renamed)
5600 st.insert(4, copied)
5599 st.insert(4, copied)
5601
5600
5602 ms = mergemod.mergestate(repo)
5601 ms = mergemod.mergestate(repo)
5603 st.append([f for f in ms if ms[f] == 'u'])
5602 st.append([f for f in ms if ms[f] == 'u'])
5604
5603
5605 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5604 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5606 st.append(subs)
5605 st.append(subs)
5607
5606
5608 labels = [ui.label(_('%d modified'), 'status.modified'),
5607 labels = [ui.label(_('%d modified'), 'status.modified'),
5609 ui.label(_('%d added'), 'status.added'),
5608 ui.label(_('%d added'), 'status.added'),
5610 ui.label(_('%d removed'), 'status.removed'),
5609 ui.label(_('%d removed'), 'status.removed'),
5611 ui.label(_('%d renamed'), 'status.copied'),
5610 ui.label(_('%d renamed'), 'status.copied'),
5612 ui.label(_('%d copied'), 'status.copied'),
5611 ui.label(_('%d copied'), 'status.copied'),
5613 ui.label(_('%d deleted'), 'status.deleted'),
5612 ui.label(_('%d deleted'), 'status.deleted'),
5614 ui.label(_('%d unknown'), 'status.unknown'),
5613 ui.label(_('%d unknown'), 'status.unknown'),
5615 ui.label(_('%d ignored'), 'status.ignored'),
5614 ui.label(_('%d ignored'), 'status.ignored'),
5616 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5615 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5617 ui.label(_('%d subrepos'), 'status.modified')]
5616 ui.label(_('%d subrepos'), 'status.modified')]
5618 t = []
5617 t = []
5619 for s, l in zip(st, labels):
5618 for s, l in zip(st, labels):
5620 if s:
5619 if s:
5621 t.append(l % len(s))
5620 t.append(l % len(s))
5622
5621
5623 t = ', '.join(t)
5622 t = ', '.join(t)
5624 cleanworkdir = False
5623 cleanworkdir = False
5625
5624
5626 if len(parents) > 1:
5625 if len(parents) > 1:
5627 t += _(' (merge)')
5626 t += _(' (merge)')
5628 elif branch != parents[0].branch():
5627 elif branch != parents[0].branch():
5629 t += _(' (new branch)')
5628 t += _(' (new branch)')
5630 elif (parents[0].closesbranch() and
5629 elif (parents[0].closesbranch() and
5631 pnode in repo.branchheads(branch, closed=True)):
5630 pnode in repo.branchheads(branch, closed=True)):
5632 t += _(' (head closed)')
5631 t += _(' (head closed)')
5633 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5632 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5634 t += _(' (clean)')
5633 t += _(' (clean)')
5635 cleanworkdir = True
5634 cleanworkdir = True
5636 elif pnode not in bheads:
5635 elif pnode not in bheads:
5637 t += _(' (new branch head)')
5636 t += _(' (new branch head)')
5638
5637
5639 if cleanworkdir:
5638 if cleanworkdir:
5640 # i18n: column positioning for "hg summary"
5639 # i18n: column positioning for "hg summary"
5641 ui.status(_('commit: %s\n') % t.strip())
5640 ui.status(_('commit: %s\n') % t.strip())
5642 else:
5641 else:
5643 # i18n: column positioning for "hg summary"
5642 # i18n: column positioning for "hg summary"
5644 ui.write(_('commit: %s\n') % t.strip())
5643 ui.write(_('commit: %s\n') % t.strip())
5645
5644
5646 # all ancestors of branch heads - all ancestors of parent = new csets
5645 # all ancestors of branch heads - all ancestors of parent = new csets
5647 new = [0] * len(repo)
5646 new = [0] * len(repo)
5648 cl = repo.changelog
5647 cl = repo.changelog
5649 for a in [cl.rev(n) for n in bheads]:
5648 for a in [cl.rev(n) for n in bheads]:
5650 new[a] = 1
5649 new[a] = 1
5651 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5650 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5652 new[a] = 1
5651 new[a] = 1
5653 for a in [p.rev() for p in parents]:
5652 for a in [p.rev() for p in parents]:
5654 if a >= 0:
5653 if a >= 0:
5655 new[a] = 0
5654 new[a] = 0
5656 for a in cl.ancestors([p.rev() for p in parents]):
5655 for a in cl.ancestors([p.rev() for p in parents]):
5657 new[a] = 0
5656 new[a] = 0
5658 new = sum(new)
5657 new = sum(new)
5659
5658
5660 if new == 0:
5659 if new == 0:
5661 # i18n: column positioning for "hg summary"
5660 # i18n: column positioning for "hg summary"
5662 ui.status(_('update: (current)\n'))
5661 ui.status(_('update: (current)\n'))
5663 elif pnode not in bheads:
5662 elif pnode not in bheads:
5664 # i18n: column positioning for "hg summary"
5663 # i18n: column positioning for "hg summary"
5665 ui.write(_('update: %d new changesets (update)\n') % new)
5664 ui.write(_('update: %d new changesets (update)\n') % new)
5666 else:
5665 else:
5667 # i18n: column positioning for "hg summary"
5666 # i18n: column positioning for "hg summary"
5668 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5667 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5669 (new, len(bheads)))
5668 (new, len(bheads)))
5670
5669
5671 if opts.get('remote'):
5670 if opts.get('remote'):
5672 t = []
5671 t = []
5673 source, branches = hg.parseurl(ui.expandpath('default'))
5672 source, branches = hg.parseurl(ui.expandpath('default'))
5674 other = hg.peer(repo, {}, source)
5673 other = hg.peer(repo, {}, source)
5675 revs, checkout = hg.addbranchrevs(repo, other, branches,
5674 revs, checkout = hg.addbranchrevs(repo, other, branches,
5676 opts.get('rev'))
5675 opts.get('rev'))
5677 ui.debug('comparing with %s\n' % util.hidepassword(source))
5676 ui.debug('comparing with %s\n' % util.hidepassword(source))
5678 repo.ui.pushbuffer()
5677 repo.ui.pushbuffer()
5679 commoninc = discovery.findcommonincoming(repo, other)
5678 commoninc = discovery.findcommonincoming(repo, other)
5680 _common, incoming, _rheads = commoninc
5679 _common, incoming, _rheads = commoninc
5681 repo.ui.popbuffer()
5680 repo.ui.popbuffer()
5682 if incoming:
5681 if incoming:
5683 t.append(_('1 or more incoming'))
5682 t.append(_('1 or more incoming'))
5684
5683
5685 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5684 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5686 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5685 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5687 if source != dest:
5686 if source != dest:
5688 other = hg.peer(repo, {}, dest)
5687 other = hg.peer(repo, {}, dest)
5689 commoninc = None
5688 commoninc = None
5690 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5689 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5691 repo.ui.pushbuffer()
5690 repo.ui.pushbuffer()
5692 outgoing = discovery.findcommonoutgoing(repo, other,
5691 outgoing = discovery.findcommonoutgoing(repo, other,
5693 commoninc=commoninc)
5692 commoninc=commoninc)
5694 repo.ui.popbuffer()
5693 repo.ui.popbuffer()
5695 o = outgoing.missing
5694 o = outgoing.missing
5696 if o:
5695 if o:
5697 t.append(_('%d outgoing') % len(o))
5696 t.append(_('%d outgoing') % len(o))
5698 if 'bookmarks' in other.listkeys('namespaces'):
5697 if 'bookmarks' in other.listkeys('namespaces'):
5699 lmarks = repo.listkeys('bookmarks')
5698 lmarks = repo.listkeys('bookmarks')
5700 rmarks = other.listkeys('bookmarks')
5699 rmarks = other.listkeys('bookmarks')
5701 diff = set(rmarks) - set(lmarks)
5700 diff = set(rmarks) - set(lmarks)
5702 if len(diff) > 0:
5701 if len(diff) > 0:
5703 t.append(_('%d incoming bookmarks') % len(diff))
5702 t.append(_('%d incoming bookmarks') % len(diff))
5704 diff = set(lmarks) - set(rmarks)
5703 diff = set(lmarks) - set(rmarks)
5705 if len(diff) > 0:
5704 if len(diff) > 0:
5706 t.append(_('%d outgoing bookmarks') % len(diff))
5705 t.append(_('%d outgoing bookmarks') % len(diff))
5707
5706
5708 if t:
5707 if t:
5709 # i18n: column positioning for "hg summary"
5708 # i18n: column positioning for "hg summary"
5710 ui.write(_('remote: %s\n') % (', '.join(t)))
5709 ui.write(_('remote: %s\n') % (', '.join(t)))
5711 else:
5710 else:
5712 # i18n: column positioning for "hg summary"
5711 # i18n: column positioning for "hg summary"
5713 ui.status(_('remote: (synced)\n'))
5712 ui.status(_('remote: (synced)\n'))
5714
5713
5715 @command('tag',
5714 @command('tag',
5716 [('f', 'force', None, _('force tag')),
5715 [('f', 'force', None, _('force tag')),
5717 ('l', 'local', None, _('make the tag local')),
5716 ('l', 'local', None, _('make the tag local')),
5718 ('r', 'rev', '', _('revision to tag'), _('REV')),
5717 ('r', 'rev', '', _('revision to tag'), _('REV')),
5719 ('', 'remove', None, _('remove a tag')),
5718 ('', 'remove', None, _('remove a tag')),
5720 # -l/--local is already there, commitopts cannot be used
5719 # -l/--local is already there, commitopts cannot be used
5721 ('e', 'edit', None, _('edit commit message')),
5720 ('e', 'edit', None, _('edit commit message')),
5722 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5721 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5723 ] + commitopts2,
5722 ] + commitopts2,
5724 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5723 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5725 def tag(ui, repo, name1, *names, **opts):
5724 def tag(ui, repo, name1, *names, **opts):
5726 """add one or more tags for the current or given revision
5725 """add one or more tags for the current or given revision
5727
5726
5728 Name a particular revision using <name>.
5727 Name a particular revision using <name>.
5729
5728
5730 Tags are used to name particular revisions of the repository and are
5729 Tags are used to name particular revisions of the repository and are
5731 very useful to compare different revisions, to go back to significant
5730 very useful to compare different revisions, to go back to significant
5732 earlier versions or to mark branch points as releases, etc. Changing
5731 earlier versions or to mark branch points as releases, etc. Changing
5733 an existing tag is normally disallowed; use -f/--force to override.
5732 an existing tag is normally disallowed; use -f/--force to override.
5734
5733
5735 If no revision is given, the parent of the working directory is
5734 If no revision is given, the parent of the working directory is
5736 used, or tip if no revision is checked out.
5735 used, or tip if no revision is checked out.
5737
5736
5738 To facilitate version control, distribution, and merging of tags,
5737 To facilitate version control, distribution, and merging of tags,
5739 they are stored as a file named ".hgtags" which is managed similarly
5738 they are stored as a file named ".hgtags" which is managed similarly
5740 to other project files and can be hand-edited if necessary. This
5739 to other project files and can be hand-edited if necessary. This
5741 also means that tagging creates a new commit. The file
5740 also means that tagging creates a new commit. The file
5742 ".hg/localtags" is used for local tags (not shared among
5741 ".hg/localtags" is used for local tags (not shared among
5743 repositories).
5742 repositories).
5744
5743
5745 Tag commits are usually made at the head of a branch. If the parent
5744 Tag commits are usually made at the head of a branch. If the parent
5746 of the working directory is not a branch head, :hg:`tag` aborts; use
5745 of the working directory is not a branch head, :hg:`tag` aborts; use
5747 -f/--force to force the tag commit to be based on a non-head
5746 -f/--force to force the tag commit to be based on a non-head
5748 changeset.
5747 changeset.
5749
5748
5750 See :hg:`help dates` for a list of formats valid for -d/--date.
5749 See :hg:`help dates` for a list of formats valid for -d/--date.
5751
5750
5752 Since tag names have priority over branch names during revision
5751 Since tag names have priority over branch names during revision
5753 lookup, using an existing branch name as a tag name is discouraged.
5752 lookup, using an existing branch name as a tag name is discouraged.
5754
5753
5755 Returns 0 on success.
5754 Returns 0 on success.
5756 """
5755 """
5757 wlock = lock = None
5756 wlock = lock = None
5758 try:
5757 try:
5759 wlock = repo.wlock()
5758 wlock = repo.wlock()
5760 lock = repo.lock()
5759 lock = repo.lock()
5761 rev_ = "."
5760 rev_ = "."
5762 names = [t.strip() for t in (name1,) + names]
5761 names = [t.strip() for t in (name1,) + names]
5763 if len(names) != len(set(names)):
5762 if len(names) != len(set(names)):
5764 raise util.Abort(_('tag names must be unique'))
5763 raise util.Abort(_('tag names must be unique'))
5765 for n in names:
5764 for n in names:
5766 scmutil.checknewlabel(repo, n, 'tag')
5765 scmutil.checknewlabel(repo, n, 'tag')
5767 if not n:
5766 if not n:
5768 raise util.Abort(_('tag names cannot consist entirely of '
5767 raise util.Abort(_('tag names cannot consist entirely of '
5769 'whitespace'))
5768 'whitespace'))
5770 if opts.get('rev') and opts.get('remove'):
5769 if opts.get('rev') and opts.get('remove'):
5771 raise util.Abort(_("--rev and --remove are incompatible"))
5770 raise util.Abort(_("--rev and --remove are incompatible"))
5772 if opts.get('rev'):
5771 if opts.get('rev'):
5773 rev_ = opts['rev']
5772 rev_ = opts['rev']
5774 message = opts.get('message')
5773 message = opts.get('message')
5775 if opts.get('remove'):
5774 if opts.get('remove'):
5776 expectedtype = opts.get('local') and 'local' or 'global'
5775 expectedtype = opts.get('local') and 'local' or 'global'
5777 for n in names:
5776 for n in names:
5778 if not repo.tagtype(n):
5777 if not repo.tagtype(n):
5779 raise util.Abort(_("tag '%s' does not exist") % n)
5778 raise util.Abort(_("tag '%s' does not exist") % n)
5780 if repo.tagtype(n) != expectedtype:
5779 if repo.tagtype(n) != expectedtype:
5781 if expectedtype == 'global':
5780 if expectedtype == 'global':
5782 raise util.Abort(_("tag '%s' is not a global tag") % n)
5781 raise util.Abort(_("tag '%s' is not a global tag") % n)
5783 else:
5782 else:
5784 raise util.Abort(_("tag '%s' is not a local tag") % n)
5783 raise util.Abort(_("tag '%s' is not a local tag") % n)
5785 rev_ = nullid
5784 rev_ = nullid
5786 if not message:
5785 if not message:
5787 # we don't translate commit messages
5786 # we don't translate commit messages
5788 message = 'Removed tag %s' % ', '.join(names)
5787 message = 'Removed tag %s' % ', '.join(names)
5789 elif not opts.get('force'):
5788 elif not opts.get('force'):
5790 for n in names:
5789 for n in names:
5791 if n in repo.tags():
5790 if n in repo.tags():
5792 raise util.Abort(_("tag '%s' already exists "
5791 raise util.Abort(_("tag '%s' already exists "
5793 "(use -f to force)") % n)
5792 "(use -f to force)") % n)
5794 if not opts.get('local'):
5793 if not opts.get('local'):
5795 p1, p2 = repo.dirstate.parents()
5794 p1, p2 = repo.dirstate.parents()
5796 if p2 != nullid:
5795 if p2 != nullid:
5797 raise util.Abort(_('uncommitted merge'))
5796 raise util.Abort(_('uncommitted merge'))
5798 bheads = repo.branchheads()
5797 bheads = repo.branchheads()
5799 if not opts.get('force') and bheads and p1 not in bheads:
5798 if not opts.get('force') and bheads and p1 not in bheads:
5800 raise util.Abort(_('not at a branch head (use -f to force)'))
5799 raise util.Abort(_('not at a branch head (use -f to force)'))
5801 r = scmutil.revsingle(repo, rev_).node()
5800 r = scmutil.revsingle(repo, rev_).node()
5802
5801
5803 if not message:
5802 if not message:
5804 # we don't translate commit messages
5803 # we don't translate commit messages
5805 message = ('Added tag %s for changeset %s' %
5804 message = ('Added tag %s for changeset %s' %
5806 (', '.join(names), short(r)))
5805 (', '.join(names), short(r)))
5807
5806
5808 date = opts.get('date')
5807 date = opts.get('date')
5809 if date:
5808 if date:
5810 date = util.parsedate(date)
5809 date = util.parsedate(date)
5811
5810
5812 if opts.get('edit'):
5811 if opts.get('edit'):
5813 message = ui.edit(message, ui.username())
5812 message = ui.edit(message, ui.username())
5814
5813
5815 # don't allow tagging the null rev
5814 # don't allow tagging the null rev
5816 if (not opts.get('remove') and
5815 if (not opts.get('remove') and
5817 scmutil.revsingle(repo, rev_).rev() == nullrev):
5816 scmutil.revsingle(repo, rev_).rev() == nullrev):
5818 raise util.Abort(_("null revision specified"))
5817 raise util.Abort(_("null revision specified"))
5819
5818
5820 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5819 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5821 finally:
5820 finally:
5822 release(lock, wlock)
5821 release(lock, wlock)
5823
5822
5824 @command('tags', [], '')
5823 @command('tags', [], '')
5825 def tags(ui, repo, **opts):
5824 def tags(ui, repo, **opts):
5826 """list repository tags
5825 """list repository tags
5827
5826
5828 This lists both regular and local tags. When the -v/--verbose
5827 This lists both regular and local tags. When the -v/--verbose
5829 switch is used, a third column "local" is printed for local tags.
5828 switch is used, a third column "local" is printed for local tags.
5830
5829
5831 Returns 0 on success.
5830 Returns 0 on success.
5832 """
5831 """
5833
5832
5834 fm = ui.formatter('tags', opts)
5833 fm = ui.formatter('tags', opts)
5835 hexfunc = ui.debugflag and hex or short
5834 hexfunc = ui.debugflag and hex or short
5836 tagtype = ""
5835 tagtype = ""
5837
5836
5838 for t, n in reversed(repo.tagslist()):
5837 for t, n in reversed(repo.tagslist()):
5839 hn = hexfunc(n)
5838 hn = hexfunc(n)
5840 label = 'tags.normal'
5839 label = 'tags.normal'
5841 tagtype = ''
5840 tagtype = ''
5842 if repo.tagtype(t) == 'local':
5841 if repo.tagtype(t) == 'local':
5843 label = 'tags.local'
5842 label = 'tags.local'
5844 tagtype = 'local'
5843 tagtype = 'local'
5845
5844
5846 fm.startitem()
5845 fm.startitem()
5847 fm.write('tag', '%s', t, label=label)
5846 fm.write('tag', '%s', t, label=label)
5848 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5847 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5849 fm.condwrite(not ui.quiet, 'rev id', fmt,
5848 fm.condwrite(not ui.quiet, 'rev id', fmt,
5850 repo.changelog.rev(n), hn, label=label)
5849 repo.changelog.rev(n), hn, label=label)
5851 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5850 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5852 tagtype, label=label)
5851 tagtype, label=label)
5853 fm.plain('\n')
5852 fm.plain('\n')
5854 fm.end()
5853 fm.end()
5855
5854
5856 @command('tip',
5855 @command('tip',
5857 [('p', 'patch', None, _('show patch')),
5856 [('p', 'patch', None, _('show patch')),
5858 ('g', 'git', None, _('use git extended diff format')),
5857 ('g', 'git', None, _('use git extended diff format')),
5859 ] + templateopts,
5858 ] + templateopts,
5860 _('[-p] [-g]'))
5859 _('[-p] [-g]'))
5861 def tip(ui, repo, **opts):
5860 def tip(ui, repo, **opts):
5862 """show the tip revision
5861 """show the tip revision
5863
5862
5864 The tip revision (usually just called the tip) is the changeset
5863 The tip revision (usually just called the tip) is the changeset
5865 most recently added to the repository (and therefore the most
5864 most recently added to the repository (and therefore the most
5866 recently changed head).
5865 recently changed head).
5867
5866
5868 If you have just made a commit, that commit will be the tip. If
5867 If you have just made a commit, that commit will be the tip. If
5869 you have just pulled changes from another repository, the tip of
5868 you have just pulled changes from another repository, the tip of
5870 that repository becomes the current tip. The "tip" tag is special
5869 that repository becomes the current tip. The "tip" tag is special
5871 and cannot be renamed or assigned to a different changeset.
5870 and cannot be renamed or assigned to a different changeset.
5872
5871
5873 Returns 0 on success.
5872 Returns 0 on success.
5874 """
5873 """
5875 displayer = cmdutil.show_changeset(ui, repo, opts)
5874 displayer = cmdutil.show_changeset(ui, repo, opts)
5876 displayer.show(repo['tip'])
5875 displayer.show(repo['tip'])
5877 displayer.close()
5876 displayer.close()
5878
5877
5879 @command('unbundle',
5878 @command('unbundle',
5880 [('u', 'update', None,
5879 [('u', 'update', None,
5881 _('update to new branch head if changesets were unbundled'))],
5880 _('update to new branch head if changesets were unbundled'))],
5882 _('[-u] FILE...'))
5881 _('[-u] FILE...'))
5883 def unbundle(ui, repo, fname1, *fnames, **opts):
5882 def unbundle(ui, repo, fname1, *fnames, **opts):
5884 """apply one or more changegroup files
5883 """apply one or more changegroup files
5885
5884
5886 Apply one or more compressed changegroup files generated by the
5885 Apply one or more compressed changegroup files generated by the
5887 bundle command.
5886 bundle command.
5888
5887
5889 Returns 0 on success, 1 if an update has unresolved files.
5888 Returns 0 on success, 1 if an update has unresolved files.
5890 """
5889 """
5891 fnames = (fname1,) + fnames
5890 fnames = (fname1,) + fnames
5892
5891
5893 lock = repo.lock()
5892 lock = repo.lock()
5894 wc = repo['.']
5893 wc = repo['.']
5895 try:
5894 try:
5896 for fname in fnames:
5895 for fname in fnames:
5897 f = hg.openpath(ui, fname)
5896 f = hg.openpath(ui, fname)
5898 gen = changegroup.readbundle(f, fname)
5897 gen = changegroup.readbundle(f, fname)
5899 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5898 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5900 finally:
5899 finally:
5901 lock.release()
5900 lock.release()
5902 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5901 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5903 return postincoming(ui, repo, modheads, opts.get('update'), None)
5902 return postincoming(ui, repo, modheads, opts.get('update'), None)
5904
5903
5905 @command('^update|up|checkout|co',
5904 @command('^update|up|checkout|co',
5906 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5905 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5907 ('c', 'check', None,
5906 ('c', 'check', None,
5908 _('update across branches if no uncommitted changes')),
5907 _('update across branches if no uncommitted changes')),
5909 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5908 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5910 ('r', 'rev', '', _('revision'), _('REV'))],
5909 ('r', 'rev', '', _('revision'), _('REV'))],
5911 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5910 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5912 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5911 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5913 """update working directory (or switch revisions)
5912 """update working directory (or switch revisions)
5914
5913
5915 Update the repository's working directory to the specified
5914 Update the repository's working directory to the specified
5916 changeset. If no changeset is specified, update to the tip of the
5915 changeset. If no changeset is specified, update to the tip of the
5917 current named branch and move the current bookmark (see :hg:`help
5916 current named branch and move the current bookmark (see :hg:`help
5918 bookmarks`).
5917 bookmarks`).
5919
5918
5920 Update sets the working directory's parent revision to the specified
5919 Update sets the working directory's parent revision to the specified
5921 changeset (see :hg:`help parents`).
5920 changeset (see :hg:`help parents`).
5922
5921
5923 If the changeset is not a descendant or ancestor of the working
5922 If the changeset is not a descendant or ancestor of the working
5924 directory's parent, the update is aborted. With the -c/--check
5923 directory's parent, the update is aborted. With the -c/--check
5925 option, the working directory is checked for uncommitted changes; if
5924 option, the working directory is checked for uncommitted changes; if
5926 none are found, the working directory is updated to the specified
5925 none are found, the working directory is updated to the specified
5927 changeset.
5926 changeset.
5928
5927
5929 .. container:: verbose
5928 .. container:: verbose
5930
5929
5931 The following rules apply when the working directory contains
5930 The following rules apply when the working directory contains
5932 uncommitted changes:
5931 uncommitted changes:
5933
5932
5934 1. If neither -c/--check nor -C/--clean is specified, and if
5933 1. If neither -c/--check nor -C/--clean is specified, and if
5935 the requested changeset is an ancestor or descendant of
5934 the requested changeset is an ancestor or descendant of
5936 the working directory's parent, the uncommitted changes
5935 the working directory's parent, the uncommitted changes
5937 are merged into the requested changeset and the merged
5936 are merged into the requested changeset and the merged
5938 result is left uncommitted. If the requested changeset is
5937 result is left uncommitted. If the requested changeset is
5939 not an ancestor or descendant (that is, it is on another
5938 not an ancestor or descendant (that is, it is on another
5940 branch), the update is aborted and the uncommitted changes
5939 branch), the update is aborted and the uncommitted changes
5941 are preserved.
5940 are preserved.
5942
5941
5943 2. With the -c/--check option, the update is aborted and the
5942 2. With the -c/--check option, the update is aborted and the
5944 uncommitted changes are preserved.
5943 uncommitted changes are preserved.
5945
5944
5946 3. With the -C/--clean option, uncommitted changes are discarded and
5945 3. With the -C/--clean option, uncommitted changes are discarded and
5947 the working directory is updated to the requested changeset.
5946 the working directory is updated to the requested changeset.
5948
5947
5949 To cancel an uncommitted merge (and lose your changes), use
5948 To cancel an uncommitted merge (and lose your changes), use
5950 :hg:`update --clean .`.
5949 :hg:`update --clean .`.
5951
5950
5952 Use null as the changeset to remove the working directory (like
5951 Use null as the changeset to remove the working directory (like
5953 :hg:`clone -U`).
5952 :hg:`clone -U`).
5954
5953
5955 If you want to revert just one file to an older revision, use
5954 If you want to revert just one file to an older revision, use
5956 :hg:`revert [-r REV] NAME`.
5955 :hg:`revert [-r REV] NAME`.
5957
5956
5958 See :hg:`help dates` for a list of formats valid for -d/--date.
5957 See :hg:`help dates` for a list of formats valid for -d/--date.
5959
5958
5960 Returns 0 on success, 1 if there are unresolved files.
5959 Returns 0 on success, 1 if there are unresolved files.
5961 """
5960 """
5962 if rev and node:
5961 if rev and node:
5963 raise util.Abort(_("please specify just one revision"))
5962 raise util.Abort(_("please specify just one revision"))
5964
5963
5965 if rev is None or rev == '':
5964 if rev is None or rev == '':
5966 rev = node
5965 rev = node
5967
5966
5968 # with no argument, we also move the current bookmark, if any
5967 # with no argument, we also move the current bookmark, if any
5969 movemarkfrom = None
5968 movemarkfrom = None
5970 if rev is None:
5969 if rev is None:
5971 curmark = repo._bookmarkcurrent
5970 curmark = repo._bookmarkcurrent
5972 if bookmarks.iscurrent(repo):
5971 if bookmarks.iscurrent(repo):
5973 movemarkfrom = repo['.'].node()
5972 movemarkfrom = repo['.'].node()
5974 elif curmark:
5973 elif curmark:
5975 ui.status(_("updating to active bookmark %s\n") % curmark)
5974 ui.status(_("updating to active bookmark %s\n") % curmark)
5976 rev = curmark
5975 rev = curmark
5977
5976
5978 # if we defined a bookmark, we have to remember the original bookmark name
5977 # if we defined a bookmark, we have to remember the original bookmark name
5979 brev = rev
5978 brev = rev
5980 rev = scmutil.revsingle(repo, rev, rev).rev()
5979 rev = scmutil.revsingle(repo, rev, rev).rev()
5981
5980
5982 if check and clean:
5981 if check and clean:
5983 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5982 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5984
5983
5985 if date:
5984 if date:
5986 if rev is not None:
5985 if rev is not None:
5987 raise util.Abort(_("you can't specify a revision and a date"))
5986 raise util.Abort(_("you can't specify a revision and a date"))
5988 rev = cmdutil.finddate(ui, repo, date)
5987 rev = cmdutil.finddate(ui, repo, date)
5989
5988
5990 if check:
5989 if check:
5991 c = repo[None]
5990 c = repo[None]
5992 if c.dirty(merge=False, branch=False, missing=True):
5991 if c.dirty(merge=False, branch=False, missing=True):
5993 raise util.Abort(_("uncommitted local changes"))
5992 raise util.Abort(_("uncommitted local changes"))
5994 if rev is None:
5993 if rev is None:
5995 rev = repo[repo[None].branch()].rev()
5994 rev = repo[repo[None].branch()].rev()
5996 mergemod._checkunknown(repo, repo[None], repo[rev])
5995 mergemod._checkunknown(repo, repo[None], repo[rev])
5997
5996
5998 if clean:
5997 if clean:
5999 ret = hg.clean(repo, rev)
5998 ret = hg.clean(repo, rev)
6000 else:
5999 else:
6001 ret = hg.update(repo, rev)
6000 ret = hg.update(repo, rev)
6002
6001
6003 if not ret and movemarkfrom:
6002 if not ret and movemarkfrom:
6004 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6003 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6005 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6004 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6006 elif brev in repo._bookmarks:
6005 elif brev in repo._bookmarks:
6007 bookmarks.setcurrent(repo, brev)
6006 bookmarks.setcurrent(repo, brev)
6008 elif brev:
6007 elif brev:
6009 bookmarks.unsetcurrent(repo)
6008 bookmarks.unsetcurrent(repo)
6010
6009
6011 return ret
6010 return ret
6012
6011
6013 @command('verify', [])
6012 @command('verify', [])
6014 def verify(ui, repo):
6013 def verify(ui, repo):
6015 """verify the integrity of the repository
6014 """verify the integrity of the repository
6016
6015
6017 Verify the integrity of the current repository.
6016 Verify the integrity of the current repository.
6018
6017
6019 This will perform an extensive check of the repository's
6018 This will perform an extensive check of the repository's
6020 integrity, validating the hashes and checksums of each entry in
6019 integrity, validating the hashes and checksums of each entry in
6021 the changelog, manifest, and tracked files, as well as the
6020 the changelog, manifest, and tracked files, as well as the
6022 integrity of their crosslinks and indices.
6021 integrity of their crosslinks and indices.
6023
6022
6024 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6023 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6025 for more information about recovery from corruption of the
6024 for more information about recovery from corruption of the
6026 repository.
6025 repository.
6027
6026
6028 Returns 0 on success, 1 if errors are encountered.
6027 Returns 0 on success, 1 if errors are encountered.
6029 """
6028 """
6030 return hg.verify(repo)
6029 return hg.verify(repo)
6031
6030
6032 @command('version', [])
6031 @command('version', [])
6033 def version_(ui):
6032 def version_(ui):
6034 """output version and copyright information"""
6033 """output version and copyright information"""
6035 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6034 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6036 % util.version())
6035 % util.version())
6037 ui.status(_(
6036 ui.status(_(
6038 "(see http://mercurial.selenic.com for more information)\n"
6037 "(see http://mercurial.selenic.com for more information)\n"
6039 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6038 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6040 "This is free software; see the source for copying conditions. "
6039 "This is free software; see the source for copying conditions. "
6041 "There is NO\nwarranty; "
6040 "There is NO\nwarranty; "
6042 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6041 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6043 ))
6042 ))
6044
6043
6045 norepo = ("clone init version help debugcommands debugcomplete"
6044 norepo = ("clone init version help debugcommands debugcomplete"
6046 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6045 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6047 " debugknown debuggetbundle debugbundle")
6046 " debugknown debuggetbundle debugbundle")
6048 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6047 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6049 " debugdata debugindex debugindexdot debugrevlog")
6048 " debugdata debugindex debugindexdot debugrevlog")
6050 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6049 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6051 " remove resolve status debugwalk")
6050 " remove resolve status debugwalk")
@@ -1,115 +1,153 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "mq=" >> $HGRCPATH
2 $ echo "mq=" >> $HGRCPATH
3
3
4 $ tipparents() {
4 $ tipparents() {
5 > hg parents --template "{rev}:{node|short} {desc|firstline}\n" -r tip
5 > hg parents --template "{rev}:{node|short} {desc|firstline}\n" -r tip
6 > }
6 > }
7
7
8 Test import and merge diffs
8 Test import and merge diffs
9
9
10 $ hg init repo
10 $ hg init repo
11 $ cd repo
11 $ cd repo
12 $ echo a > a
12 $ echo a > a
13 $ hg ci -Am adda
13 $ hg ci -Am adda
14 adding a
14 adding a
15 $ echo a >> a
15 $ echo a >> a
16 $ hg ci -m changea
16 $ hg ci -m changea
17 $ echo c > c
17 $ echo c > c
18 $ hg ci -Am addc
18 $ hg ci -Am addc
19 adding c
19 adding c
20 $ hg up 0
20 $ hg up 0
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 $ echo b > b
22 $ echo b > b
23 $ hg ci -Am addb
23 $ hg ci -Am addb
24 adding b
24 adding b
25 created new head
25 created new head
26 $ hg up 1
26 $ hg up 1
27 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
28 $ hg merge 3
28 $ hg merge 3
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 (branch merge, don't forget to commit)
30 (branch merge, don't forget to commit)
31 $ hg ci -m merge
31 $ hg ci -m merge
32 $ hg export . > ../merge.diff
32 $ hg export . > ../merge.diff
33 $ cd ..
33 $ cd ..
34 $ hg clone -r2 repo repo2
34 $ hg clone -r2 repo repo2
35 adding changesets
35 adding changesets
36 adding manifests
36 adding manifests
37 adding file changes
37 adding file changes
38 added 3 changesets with 3 changes to 2 files
38 added 3 changesets with 3 changes to 2 files
39 updating to branch default
39 updating to branch default
40 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 $ cd repo2
41 $ cd repo2
42 $ hg pull -r3 ../repo
42 $ hg pull -r3 ../repo
43 pulling from ../repo
43 pulling from ../repo
44 searching for changes
44 searching for changes
45 adding changesets
45 adding changesets
46 adding manifests
46 adding manifests
47 adding file changes
47 adding file changes
48 added 1 changesets with 1 changes to 1 files (+1 heads)
48 added 1 changesets with 1 changes to 1 files (+1 heads)
49 (run 'hg heads' to see heads, 'hg merge' to merge)
49 (run 'hg heads' to see heads, 'hg merge' to merge)
50
50
51 Test without --exact and diff.p1 == workingdir.p1
51 Test without --exact and diff.p1 == workingdir.p1
52
52
53 $ hg up 1
53 $ hg up 1
54 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
54 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
55 $ hg import ../merge.diff
55 $ hg import ../merge.diff
56 applying ../merge.diff
56 applying ../merge.diff
57 $ tipparents
57 $ tipparents
58 1:540395c44225 changea
58 1:540395c44225 changea
59 3:102a90ea7b4a addb
59 3:102a90ea7b4a addb
60 $ hg strip --no-backup tip
60 $ hg strip --no-backup tip
61 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
61 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
62
62
63 Test without --exact and diff.p1 != workingdir.p1
63 Test without --exact and diff.p1 != workingdir.p1
64
64
65 $ hg up 2
65 $ hg up 2
66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 $ hg import ../merge.diff
67 $ hg import ../merge.diff
68 applying ../merge.diff
68 applying ../merge.diff
69 $ tipparents
69 $ tipparents
70 2:890ecaa90481 addc
70 2:890ecaa90481 addc
71 $ hg strip --no-backup tip
71 $ hg strip --no-backup tip
72 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
72 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
73
73
74 Test with --exact
74 Test with --exact
75
75
76 $ hg import --exact ../merge.diff
76 $ hg import --exact ../merge.diff
77 applying ../merge.diff
77 applying ../merge.diff
78 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
78 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
79 $ tipparents
79 $ tipparents
80 1:540395c44225 changea
80 1:540395c44225 changea
81 3:102a90ea7b4a addb
81 3:102a90ea7b4a addb
82 $ hg strip --no-backup tip
82 $ hg strip --no-backup tip
83 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
83 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84
84
85 Test with --bypass and diff.p1 == workingdir.p1
85 Test with --bypass and diff.p1 == workingdir.p1
86
86
87 $ hg up 1
87 $ hg up 1
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 $ hg import --bypass ../merge.diff
89 $ hg import --bypass ../merge.diff
90 applying ../merge.diff
90 applying ../merge.diff
91 $ tipparents
91 $ tipparents
92 1:540395c44225 changea
92 1:540395c44225 changea
93 3:102a90ea7b4a addb
93 3:102a90ea7b4a addb
94 $ hg strip --no-backup tip
94 $ hg strip --no-backup tip
95
95
96 Test with --bypass and diff.p1 != workingdir.p1
96 Test with --bypass and diff.p1 != workingdir.p1
97
97
98 $ hg up 2
98 $ hg up 2
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 $ hg import --bypass ../merge.diff
100 $ hg import --bypass ../merge.diff
101 applying ../merge.diff
101 applying ../merge.diff
102 $ tipparents
102 $ tipparents
103 2:890ecaa90481 addc
103 2:890ecaa90481 addc
104 $ hg strip --no-backup tip
104 $ hg strip --no-backup tip
105
105
106 Test with --bypass and --exact
106 Test with --bypass and --exact
107
107
108 $ hg import --bypass --exact ../merge.diff
108 $ hg import --bypass --exact ../merge.diff
109 applying ../merge.diff
109 applying ../merge.diff
110 $ tipparents
110 $ tipparents
111 1:540395c44225 changea
111 1:540395c44225 changea
112 3:102a90ea7b4a addb
112 3:102a90ea7b4a addb
113 $ hg strip --no-backup tip
113 $ hg strip --no-backup tip
114
114
115 $ cd ..
115 $ cd ..
116
117 Test that --exact on a bad header doesn't corrupt the repo (issue3616)
118
119 $ hg init repo3
120 $ cd repo3
121 $ echo a>a
122 $ hg ci -Aqm0
123 $ echo a>>a
124 $ hg ci -m1
125 $ echo a>>a
126 $ hg ci -m2
127 $ echo a>a
128 $ echo b>>a
129 $ echo a>>a
130 $ hg ci -m3
131 $ hg export 2 | head -7 > ../a.patch
132 $ hg export tip | tail -n +8 >> ../a.patch
133
134 $ cd ..
135 $ hg clone -qr0 repo3 repo3-clone
136 $ cd repo3-clone
137 $ hg pull -qr1 ../repo3
138
139 $ hg import --exact ../a.patch
140 applying ../a.patch
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 patching file a
143 Hunk #1 succeeded at 1 with fuzz 1 (offset -1 lines).
144 transaction abort!
145 rollback completed
146 abort: patch is damaged or loses information
147 [255]
148 $ hg verify
149 checking changesets
150 checking manifests
151 crosschecking files in changesets and manifests
152 checking files
153 1 files, 2 changesets, 2 total revisions
General Comments 0
You need to be logged in to leave comments. Login now