##// END OF EJS Templates
update: put rules for uncommitted changes into verbose help section
Adrian Buehlmann -
r17218:b8661d7c default
parent child Browse files
Show More
@@ -1,5862 +1,5864
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, 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 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('G', 'graph', None, _("show the revision DAG")),
101 ('G', 'graph', None, _("show the revision DAG")),
102 ] + templateopts
102 ] + templateopts
103
103
104 diffopts = [
104 diffopts = [
105 ('a', 'text', None, _('treat all files as text')),
105 ('a', 'text', None, _('treat all files as text')),
106 ('g', 'git', None, _('use git extended diff format')),
106 ('g', 'git', None, _('use git extended diff format')),
107 ('', 'nodates', None, _('omit dates from diff headers'))
107 ('', 'nodates', None, _('omit dates from diff headers'))
108 ]
108 ]
109
109
110 diffwsopts = [
110 diffwsopts = [
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ]
117 ]
118
118
119 diffopts2 = [
119 diffopts2 = [
120 ('p', 'show-function', None, _('show which function each change is in')),
120 ('p', 'show-function', None, _('show which function each change is in')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ] + diffwsopts + [
122 ] + diffwsopts + [
123 ('U', 'unified', '',
123 ('U', 'unified', '',
124 _('number of lines of context to show'), _('NUM')),
124 _('number of lines of context to show'), _('NUM')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ]
126 ]
127
127
128 mergetoolopts = [
128 mergetoolopts = [
129 ('t', 'tool', '', _('specify merge tool')),
129 ('t', 'tool', '', _('specify merge tool')),
130 ]
130 ]
131
131
132 similarityopts = [
132 similarityopts = [
133 ('s', 'similarity', '',
133 ('s', 'similarity', '',
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 ]
135 ]
136
136
137 subrepoopts = [
137 subrepoopts = [
138 ('S', 'subrepos', None,
138 ('S', 'subrepos', None,
139 _('recurse into subrepositories'))
139 _('recurse into subrepositories'))
140 ]
140 ]
141
141
142 # Commands start here, listed alphabetically
142 # Commands start here, listed alphabetically
143
143
144 @command('^add',
144 @command('^add',
145 walkopts + subrepoopts + dryrunopts,
145 walkopts + subrepoopts + dryrunopts,
146 _('[OPTION]... [FILE]...'))
146 _('[OPTION]... [FILE]...'))
147 def add(ui, repo, *pats, **opts):
147 def add(ui, repo, *pats, **opts):
148 """add the specified files on the next commit
148 """add the specified files on the next commit
149
149
150 Schedule files to be version controlled and added to the
150 Schedule files to be version controlled and added to the
151 repository.
151 repository.
152
152
153 The files will be added to the repository at the next commit. To
153 The files will be added to the repository at the next commit. To
154 undo an add before that, see :hg:`forget`.
154 undo an add before that, see :hg:`forget`.
155
155
156 If no names are given, add all files to the repository.
156 If no names are given, add all files to the repository.
157
157
158 .. container:: verbose
158 .. container:: verbose
159
159
160 An example showing how new (unknown) files are added
160 An example showing how new (unknown) files are added
161 automatically by :hg:`add`::
161 automatically by :hg:`add`::
162
162
163 $ ls
163 $ ls
164 foo.c
164 foo.c
165 $ hg status
165 $ hg status
166 ? foo.c
166 ? foo.c
167 $ hg add
167 $ hg add
168 adding foo.c
168 adding foo.c
169 $ hg status
169 $ hg status
170 A foo.c
170 A foo.c
171
171
172 Returns 0 if all files are successfully added.
172 Returns 0 if all files are successfully added.
173 """
173 """
174
174
175 m = scmutil.match(repo[None], pats, opts)
175 m = scmutil.match(repo[None], pats, opts)
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 opts.get('subrepos'), prefix="", explicitonly=False)
177 opts.get('subrepos'), prefix="", explicitonly=False)
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. With a
193 Use the -s/--similarity option to detect renamed files. With a
194 parameter greater than 0, this compares every removed file with
194 parameter greater than 0, this compares every removed file with
195 every added file and records those similar enough as renames. This
195 every added file and records those similar enough as renames. This
196 option takes a percentage between 0 (disabled) and 100 (files must
196 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. Detecting renamed files this way
197 be identical) as its parameter. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed.
199 used to check which files were identified as moved or renamed.
200 If this option is not specified, only renames of identical files
200 If this option is not specified, only renames of identical files
201 are detected.
201 are detected.
202
202
203 Returns 0 if all files are successfully added.
203 Returns 0 if all files are successfully added.
204 """
204 """
205 try:
205 try:
206 sim = float(opts.get('similarity') or 100)
206 sim = float(opts.get('similarity') or 100)
207 except ValueError:
207 except ValueError:
208 raise util.Abort(_('similarity must be a number'))
208 raise util.Abort(_('similarity must be a number'))
209 if sim < 0 or sim > 100:
209 if sim < 0 or sim > 100:
210 raise util.Abort(_('similarity must be between 0 and 100'))
210 raise util.Abort(_('similarity must be between 0 and 100'))
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212
212
213 @command('^annotate|blame',
213 @command('^annotate|blame',
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 ('', 'follow', None,
215 ('', 'follow', None,
216 _('follow copies/renames and list the filename (DEPRECATED)')),
216 _('follow copies/renames and list the filename (DEPRECATED)')),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('a', 'text', None, _('treat all files as text')),
218 ('a', 'text', None, _('treat all files as text')),
219 ('u', 'user', None, _('list the author (long with -v)')),
219 ('u', 'user', None, _('list the author (long with -v)')),
220 ('f', 'file', None, _('list the filename')),
220 ('f', 'file', None, _('list the filename')),
221 ('d', 'date', None, _('list the date (short with -q)')),
221 ('d', 'date', None, _('list the date (short with -q)')),
222 ('n', 'number', None, _('list the revision number (default)')),
222 ('n', 'number', None, _('list the revision number (default)')),
223 ('c', 'changeset', None, _('list the changeset')),
223 ('c', 'changeset', None, _('list the changeset')),
224 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ] + diffwsopts + walkopts,
225 ] + diffwsopts + walkopts,
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 def annotate(ui, repo, *pats, **opts):
227 def annotate(ui, repo, *pats, **opts):
228 """show changeset information by line for each file
228 """show changeset information by line for each file
229
229
230 List changes in files, showing the revision id responsible for
230 List changes in files, showing the revision id responsible for
231 each line
231 each line
232
232
233 This command is useful for discovering when a change was made and
233 This command is useful for discovering when a change was made and
234 by whom.
234 by whom.
235
235
236 Without the -a/--text option, annotate will avoid processing files
236 Without the -a/--text option, annotate will avoid processing files
237 it detects as binary. With -a, annotate will annotate the file
237 it detects as binary. With -a, annotate will annotate the file
238 anyway, although the results will probably be neither useful
238 anyway, although the results will probably be neither useful
239 nor desirable.
239 nor desirable.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 """
242 """
243 if opts.get('follow'):
243 if opts.get('follow'):
244 # --follow is deprecated and now just an alias for -f/--file
244 # --follow is deprecated and now just an alias for -f/--file
245 # to mimic the behavior of Mercurial before version 1.5
245 # to mimic the behavior of Mercurial before version 1.5
246 opts['file'] = True
246 opts['file'] = True
247
247
248 datefunc = ui.quiet and util.shortdate or util.datestr
248 datefunc = ui.quiet and util.shortdate or util.datestr
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250
250
251 if not pats:
251 if not pats:
252 raise util.Abort(_('at least one filename or pattern is required'))
252 raise util.Abort(_('at least one filename or pattern is required'))
253
253
254 hexfn = ui.debugflag and hex or short
254 hexfn = ui.debugflag and hex or short
255
255
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 ('number', ' ', lambda x: str(x[0].rev())),
257 ('number', ' ', lambda x: str(x[0].rev())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('date', ' ', getdate),
259 ('date', ' ', getdate),
260 ('file', ' ', lambda x: x[0].path()),
260 ('file', ' ', lambda x: x[0].path()),
261 ('line_number', ':', lambda x: str(x[1])),
261 ('line_number', ':', lambda x: str(x[1])),
262 ]
262 ]
263
263
264 if (not opts.get('user') and not opts.get('changeset')
264 if (not opts.get('user') and not opts.get('changeset')
265 and not opts.get('date') and not opts.get('file')):
265 and not opts.get('date') and not opts.get('file')):
266 opts['number'] = True
266 opts['number'] = True
267
267
268 linenumber = opts.get('line_number') is not None
268 linenumber = opts.get('line_number') is not None
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
271
271
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274
274
275 def bad(x, y):
275 def bad(x, y):
276 raise util.Abort("%s: %s" % (x, y))
276 raise util.Abort("%s: %s" % (x, y))
277
277
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 m = scmutil.match(ctx, pats, opts)
279 m = scmutil.match(ctx, pats, opts)
280 m.bad = bad
280 m.bad = bad
281 follow = not opts.get('no_follow')
281 follow = not opts.get('no_follow')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
283 for abs in ctx.walk(m):
283 for abs in ctx.walk(m):
284 fctx = ctx[abs]
284 fctx = ctx[abs]
285 if not opts.get('text') and util.binary(fctx.data()):
285 if not opts.get('text') and util.binary(fctx.data()):
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 continue
287 continue
288
288
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 diffopts=diffopts)
290 diffopts=diffopts)
291 pieces = []
291 pieces = []
292
292
293 for f, sep in funcmap:
293 for f, sep in funcmap:
294 l = [f(n) for n, dummy in lines]
294 l = [f(n) for n, dummy in lines]
295 if l:
295 if l:
296 sized = [(x, encoding.colwidth(x)) for x in l]
296 sized = [(x, encoding.colwidth(x)) for x in l]
297 ml = max([w for x, w in sized])
297 ml = max([w for x, w in sized])
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 for x, w in sized])
299 for x, w in sized])
300
300
301 if pieces:
301 if pieces:
302 for p, l in zip(zip(*pieces), lines):
302 for p, l in zip(zip(*pieces), lines):
303 ui.write("%s: %s" % ("".join(p), l[1]))
303 ui.write("%s: %s" % ("".join(p), l[1]))
304
304
305 if lines and not lines[-1][1].endswith('\n'):
305 if lines and not lines[-1][1].endswith('\n'):
306 ui.write('\n')
306 ui.write('\n')
307
307
308 @command('archive',
308 @command('archive',
309 [('', 'no-decode', None, _('do not pass files through decoders')),
309 [('', 'no-decode', None, _('do not pass files through decoders')),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 _('PREFIX')),
311 _('PREFIX')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ] + subrepoopts + walkopts,
314 ] + subrepoopts + walkopts,
315 _('[OPTION]... DEST'))
315 _('[OPTION]... DEST'))
316 def archive(ui, repo, dest, **opts):
316 def archive(ui, repo, dest, **opts):
317 '''create an unversioned archive of a repository revision
317 '''create an unversioned archive of a repository revision
318
318
319 By default, the revision used is the parent of the working
319 By default, the revision used is the parent of the working
320 directory; use -r/--rev to specify a different revision.
320 directory; use -r/--rev to specify a different revision.
321
321
322 The archive type is automatically detected based on file
322 The archive type is automatically detected based on file
323 extension (or override using -t/--type).
323 extension (or override using -t/--type).
324
324
325 .. container:: verbose
325 .. container:: verbose
326
326
327 Examples:
327 Examples:
328
328
329 - create a zip file containing the 1.0 release::
329 - create a zip file containing the 1.0 release::
330
330
331 hg archive -r 1.0 project-1.0.zip
331 hg archive -r 1.0 project-1.0.zip
332
332
333 - create a tarball excluding .hg files::
333 - create a tarball excluding .hg files::
334
334
335 hg archive project.tar.gz -X ".hg*"
335 hg archive project.tar.gz -X ".hg*"
336
336
337 Valid types are:
337 Valid types are:
338
338
339 :``files``: a directory full of files (default)
339 :``files``: a directory full of files (default)
340 :``tar``: tar archive, uncompressed
340 :``tar``: tar archive, uncompressed
341 :``tbz2``: tar archive, compressed using bzip2
341 :``tbz2``: tar archive, compressed using bzip2
342 :``tgz``: tar archive, compressed using gzip
342 :``tgz``: tar archive, compressed using gzip
343 :``uzip``: zip archive, uncompressed
343 :``uzip``: zip archive, uncompressed
344 :``zip``: zip archive, compressed using deflate
344 :``zip``: zip archive, compressed using deflate
345
345
346 The exact name of the destination archive or directory is given
346 The exact name of the destination archive or directory is given
347 using a format string; see :hg:`help export` for details.
347 using a format string; see :hg:`help export` for details.
348
348
349 Each member added to an archive file has a directory prefix
349 Each member added to an archive file has a directory prefix
350 prepended. Use -p/--prefix to specify a format string for the
350 prepended. Use -p/--prefix to specify a format string for the
351 prefix. The default is the basename of the archive, with suffixes
351 prefix. The default is the basename of the archive, with suffixes
352 removed.
352 removed.
353
353
354 Returns 0 on success.
354 Returns 0 on success.
355 '''
355 '''
356
356
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 if not ctx:
358 if not ctx:
359 raise util.Abort(_('no working directory: please specify a revision'))
359 raise util.Abort(_('no working directory: please specify a revision'))
360 node = ctx.node()
360 node = ctx.node()
361 dest = cmdutil.makefilename(repo, dest, node)
361 dest = cmdutil.makefilename(repo, dest, node)
362 if os.path.realpath(dest) == repo.root:
362 if os.path.realpath(dest) == repo.root:
363 raise util.Abort(_('repository root cannot be destination'))
363 raise util.Abort(_('repository root cannot be destination'))
364
364
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 prefix = opts.get('prefix')
366 prefix = opts.get('prefix')
367
367
368 if dest == '-':
368 if dest == '-':
369 if kind == 'files':
369 if kind == 'files':
370 raise util.Abort(_('cannot archive plain files to stdout'))
370 raise util.Abort(_('cannot archive plain files to stdout'))
371 dest = cmdutil.makefileobj(repo, dest)
371 dest = cmdutil.makefileobj(repo, dest)
372 if not prefix:
372 if not prefix:
373 prefix = os.path.basename(repo.root) + '-%h'
373 prefix = os.path.basename(repo.root) + '-%h'
374
374
375 prefix = cmdutil.makefilename(repo, prefix, node)
375 prefix = cmdutil.makefilename(repo, prefix, node)
376 matchfn = scmutil.match(ctx, [], opts)
376 matchfn = scmutil.match(ctx, [], opts)
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 matchfn, prefix, subrepos=opts.get('subrepos'))
378 matchfn, prefix, subrepos=opts.get('subrepos'))
379
379
380 @command('backout',
380 @command('backout',
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 ('', 'parent', '',
382 ('', 'parent', '',
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 _('[OPTION]... [-r] REV'))
386 _('[OPTION]... [-r] REV'))
387 def backout(ui, repo, node=None, rev=None, **opts):
387 def backout(ui, repo, node=None, rev=None, **opts):
388 '''reverse effect of earlier changeset
388 '''reverse effect of earlier changeset
389
389
390 Prepare a new changeset with the effect of REV undone in the
390 Prepare a new changeset with the effect of REV undone in the
391 current working directory.
391 current working directory.
392
392
393 If REV is the parent of the working directory, then this new changeset
393 If REV is the parent of the working directory, then this new changeset
394 is committed automatically. Otherwise, hg needs to merge the
394 is committed automatically. Otherwise, hg needs to merge the
395 changes and the merged result is left uncommitted.
395 changes and the merged result is left uncommitted.
396
396
397 .. note::
397 .. note::
398 backout cannot be used to fix either an unwanted or
398 backout cannot be used to fix either an unwanted or
399 incorrect merge.
399 incorrect merge.
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 By default, the pending changeset will have one parent,
403 By default, the pending changeset will have one parent,
404 maintaining a linear history. With --merge, the pending
404 maintaining a linear history. With --merge, the pending
405 changeset will instead have two parents: the old parent of the
405 changeset will instead have two parents: the old parent of the
406 working directory and a new child of REV that simply undoes REV.
406 working directory and a new child of REV that simply undoes REV.
407
407
408 Before version 1.7, the behavior without --merge was equivalent
408 Before version 1.7, the behavior without --merge was equivalent
409 to specifying --merge followed by :hg:`update --clean .` to
409 to specifying --merge followed by :hg:`update --clean .` to
410 cancel the merge and leave the child of REV as a head to be
410 cancel the merge and leave the child of REV as a head to be
411 merged separately.
411 merged separately.
412
412
413 See :hg:`help dates` for a list of formats valid for -d/--date.
413 See :hg:`help dates` for a list of formats valid for -d/--date.
414
414
415 Returns 0 on success.
415 Returns 0 on success.
416 '''
416 '''
417 if rev and node:
417 if rev and node:
418 raise util.Abort(_("please specify just one revision"))
418 raise util.Abort(_("please specify just one revision"))
419
419
420 if not rev:
420 if not rev:
421 rev = node
421 rev = node
422
422
423 if not rev:
423 if not rev:
424 raise util.Abort(_("please specify a revision to backout"))
424 raise util.Abort(_("please specify a revision to backout"))
425
425
426 date = opts.get('date')
426 date = opts.get('date')
427 if date:
427 if date:
428 opts['date'] = util.parsedate(date)
428 opts['date'] = util.parsedate(date)
429
429
430 cmdutil.bailifchanged(repo)
430 cmdutil.bailifchanged(repo)
431 node = scmutil.revsingle(repo, rev).node()
431 node = scmutil.revsingle(repo, rev).node()
432
432
433 op1, op2 = repo.dirstate.parents()
433 op1, op2 = repo.dirstate.parents()
434 a = repo.changelog.ancestor(op1, node)
434 a = repo.changelog.ancestor(op1, node)
435 if a != node:
435 if a != node:
436 raise util.Abort(_('cannot backout change on a different branch'))
436 raise util.Abort(_('cannot backout change on a different branch'))
437
437
438 p1, p2 = repo.changelog.parents(node)
438 p1, p2 = repo.changelog.parents(node)
439 if p1 == nullid:
439 if p1 == nullid:
440 raise util.Abort(_('cannot backout a change with no parents'))
440 raise util.Abort(_('cannot backout a change with no parents'))
441 if p2 != nullid:
441 if p2 != nullid:
442 if not opts.get('parent'):
442 if not opts.get('parent'):
443 raise util.Abort(_('cannot backout a merge changeset'))
443 raise util.Abort(_('cannot backout a merge changeset'))
444 p = repo.lookup(opts['parent'])
444 p = repo.lookup(opts['parent'])
445 if p not in (p1, p2):
445 if p not in (p1, p2):
446 raise util.Abort(_('%s is not a parent of %s') %
446 raise util.Abort(_('%s is not a parent of %s') %
447 (short(p), short(node)))
447 (short(p), short(node)))
448 parent = p
448 parent = p
449 else:
449 else:
450 if opts.get('parent'):
450 if opts.get('parent'):
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 parent = p1
452 parent = p1
453
453
454 # the backout should appear on the same branch
454 # the backout should appear on the same branch
455 wlock = repo.wlock()
455 wlock = repo.wlock()
456 try:
456 try:
457 branch = repo.dirstate.branch()
457 branch = repo.dirstate.branch()
458 hg.clean(repo, node, show_stats=False)
458 hg.clean(repo, node, show_stats=False)
459 repo.dirstate.setbranch(branch)
459 repo.dirstate.setbranch(branch)
460 revert_opts = opts.copy()
460 revert_opts = opts.copy()
461 revert_opts['date'] = None
461 revert_opts['date'] = None
462 revert_opts['all'] = True
462 revert_opts['all'] = True
463 revert_opts['rev'] = hex(parent)
463 revert_opts['rev'] = hex(parent)
464 revert_opts['no_backup'] = None
464 revert_opts['no_backup'] = None
465 revert(ui, repo, **revert_opts)
465 revert(ui, repo, **revert_opts)
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 commit_opts = opts.copy()
473 commit_opts = opts.copy()
474 commit_opts['addremove'] = False
474 commit_opts['addremove'] = False
475 if not commit_opts['message'] and not commit_opts['logfile']:
475 if not commit_opts['message'] and not commit_opts['logfile']:
476 # we don't translate commit messages
476 # we don't translate commit messages
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['force_editor'] = True
478 commit_opts['force_editor'] = True
479 commit(ui, repo, **commit_opts)
479 commit(ui, repo, **commit_opts)
480 def nice(node):
480 def nice(node):
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 ui.status(_('changeset %s backs out changeset %s\n') %
482 ui.status(_('changeset %s backs out changeset %s\n') %
483 (nice(repo.changelog.tip()), nice(node)))
483 (nice(repo.changelog.tip()), nice(node)))
484 if opts.get('merge') and op1 != node:
484 if opts.get('merge') and op1 != node:
485 hg.clean(repo, op1, show_stats=False)
485 hg.clean(repo, op1, show_stats=False)
486 ui.status(_('merging with changeset %s\n')
486 ui.status(_('merging with changeset %s\n')
487 % nice(repo.changelog.tip()))
487 % nice(repo.changelog.tip()))
488 try:
488 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 return hg.merge(repo, hex(repo.changelog.tip()))
490 return hg.merge(repo, hex(repo.changelog.tip()))
491 finally:
491 finally:
492 ui.setconfig('ui', 'forcemerge', '')
492 ui.setconfig('ui', 'forcemerge', '')
493 finally:
493 finally:
494 wlock.release()
494 wlock.release()
495 return 0
495 return 0
496
496
497 @command('bisect',
497 @command('bisect',
498 [('r', 'reset', False, _('reset bisect state')),
498 [('r', 'reset', False, _('reset bisect state')),
499 ('g', 'good', False, _('mark changeset good')),
499 ('g', 'good', False, _('mark changeset good')),
500 ('b', 'bad', False, _('mark changeset bad')),
500 ('b', 'bad', False, _('mark changeset bad')),
501 ('s', 'skip', False, _('skip testing changeset')),
501 ('s', 'skip', False, _('skip testing changeset')),
502 ('e', 'extend', False, _('extend the bisect range')),
502 ('e', 'extend', False, _('extend the bisect range')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('U', 'noupdate', False, _('do not update to target'))],
504 ('U', 'noupdate', False, _('do not update to target'))],
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 def bisect(ui, repo, rev=None, extra=None, command=None,
506 def bisect(ui, repo, rev=None, extra=None, command=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
508 noupdate=None):
508 noupdate=None):
509 """subdivision search of changesets
509 """subdivision search of changesets
510
510
511 This command helps to find changesets which introduce problems. To
511 This command helps to find changesets which introduce problems. To
512 use, mark the earliest changeset you know exhibits the problem as
512 use, mark the earliest changeset you know exhibits the problem as
513 bad, then mark the latest changeset which is free from the problem
513 bad, then mark the latest changeset which is free from the problem
514 as good. Bisect will update your working directory to a revision
514 as good. Bisect will update your working directory to a revision
515 for testing (unless the -U/--noupdate option is specified). Once
515 for testing (unless the -U/--noupdate option is specified). Once
516 you have performed tests, mark the working directory as good or
516 you have performed tests, mark the working directory as good or
517 bad, and bisect will either update to another candidate changeset
517 bad, and bisect will either update to another candidate changeset
518 or announce that it has found the bad revision.
518 or announce that it has found the bad revision.
519
519
520 As a shortcut, you can also use the revision argument to mark a
520 As a shortcut, you can also use the revision argument to mark a
521 revision as good or bad without checking it out first.
521 revision as good or bad without checking it out first.
522
522
523 If you supply a command, it will be used for automatic bisection.
523 If you supply a command, it will be used for automatic bisection.
524 The environment variable HG_NODE will contain the ID of the
524 The environment variable HG_NODE will contain the ID of the
525 changeset being tested. The exit status of the command will be
525 changeset being tested. The exit status of the command will be
526 used to mark revisions as good or bad: status 0 means good, 125
526 used to mark revisions as good or bad: status 0 means good, 125
527 means to skip the revision, 127 (command not found) will abort the
527 means to skip the revision, 127 (command not found) will abort the
528 bisection, and any other non-zero exit status means the revision
528 bisection, and any other non-zero exit status means the revision
529 is bad.
529 is bad.
530
530
531 .. container:: verbose
531 .. container:: verbose
532
532
533 Some examples:
533 Some examples:
534
534
535 - start a bisection with known bad revision 12, and good revision 34::
535 - start a bisection with known bad revision 12, and good revision 34::
536
536
537 hg bisect --bad 34
537 hg bisect --bad 34
538 hg bisect --good 12
538 hg bisect --good 12
539
539
540 - advance the current bisection by marking current revision as good or
540 - advance the current bisection by marking current revision as good or
541 bad::
541 bad::
542
542
543 hg bisect --good
543 hg bisect --good
544 hg bisect --bad
544 hg bisect --bad
545
545
546 - mark the current revision, or a known revision, to be skipped (eg. if
546 - mark the current revision, or a known revision, to be skipped (eg. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - forget the current bisection::
552 - forget the current bisection::
553
553
554 hg bisect --reset
554 hg bisect --reset
555
555
556 - use 'make && make tests' to automatically find the first broken
556 - use 'make && make tests' to automatically find the first broken
557 revision::
557 revision::
558
558
559 hg bisect --reset
559 hg bisect --reset
560 hg bisect --bad 34
560 hg bisect --bad 34
561 hg bisect --good 12
561 hg bisect --good 12
562 hg bisect --command 'make && make tests'
562 hg bisect --command 'make && make tests'
563
563
564 - see all changesets whose states are already known in the current
564 - see all changesets whose states are already known in the current
565 bisection::
565 bisection::
566
566
567 hg log -r "bisect(pruned)"
567 hg log -r "bisect(pruned)"
568
568
569 - see the changeset currently being bisected (especially useful
569 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
570 if running with -U/--noupdate)::
571
571
572 hg log -r "bisect(current)"
572 hg log -r "bisect(current)"
573
573
574 - see all changesets that took part in the current bisection::
574 - see all changesets that took part in the current bisection::
575
575
576 hg log -r "bisect(range)"
576 hg log -r "bisect(range)"
577
577
578 - with the graphlog extension, you can even get a nice graph::
578 - with the graphlog extension, you can even get a nice graph::
579
579
580 hg log --graph -r "bisect(range)"
580 hg log --graph -r "bisect(range)"
581
581
582 See :hg:`help revsets` for more about the `bisect()` keyword.
582 See :hg:`help revsets` for more about the `bisect()` keyword.
583
583
584 Returns 0 on success.
584 Returns 0 on success.
585 """
585 """
586 def extendbisectrange(nodes, good):
586 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
587 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
588 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
589 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
590 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
591 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
592 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
593 if num == 1:
594 return parents[0].ancestor(parents[1])
594 return parents[0].ancestor(parents[1])
595 return None
595 return None
596
596
597 def print_result(nodes, good):
597 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
598 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
599 if len(nodes) == 1:
600 # narrowed it down to a single revision
600 # narrowed it down to a single revision
601 if good:
601 if good:
602 ui.write(_("The first good revision is:\n"))
602 ui.write(_("The first good revision is:\n"))
603 else:
603 else:
604 ui.write(_("The first bad revision is:\n"))
604 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
605 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
606 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
607 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
608 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
609 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
610 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
611 % extendnode)
612 else:
612 else:
613 # multiple possible revisions
613 # multiple possible revisions
614 if good:
614 if good:
615 ui.write(_("Due to skipped revisions, the first "
615 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
616 "good revision could be any of:\n"))
617 else:
617 else:
618 ui.write(_("Due to skipped revisions, the first "
618 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
619 "bad revision could be any of:\n"))
620 for n in nodes:
620 for n in nodes:
621 displayer.show(repo[n])
621 displayer.show(repo[n])
622 displayer.close()
622 displayer.close()
623
623
624 def check_state(state, interactive=True):
624 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
625 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
626 if (good or bad or skip or reset) and interactive:
627 return
627 return
628 if not state['good']:
628 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
630 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
632 return True
633
633
634 # backward compatibility
634 # backward compatibility
635 if rev in "good bad reset init".split():
635 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
637 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
638 if cmd == "good":
639 good = True
639 good = True
640 elif cmd == "bad":
640 elif cmd == "bad":
641 bad = True
641 bad = True
642 else:
642 else:
643 reset = True
643 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
645 raise util.Abort(_('incompatible arguments'))
646
646
647 if reset:
647 if reset:
648 p = repo.join("bisect.state")
648 p = repo.join("bisect.state")
649 if os.path.exists(p):
649 if os.path.exists(p):
650 os.unlink(p)
650 os.unlink(p)
651 return
651 return
652
652
653 state = hbisect.load_state(repo)
653 state = hbisect.load_state(repo)
654
654
655 if command:
655 if command:
656 changesets = 1
656 changesets = 1
657 try:
657 try:
658 node = state['current'][0]
658 node = state['current'][0]
659 except LookupError:
659 except LookupError:
660 if noupdate:
660 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
661 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
662 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
663 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
664 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
665 raise util.Abort(_('current bisect revision is a merge'))
666 try:
666 try:
667 while changesets:
667 while changesets:
668 # update state
668 # update state
669 state['current'] = [node]
669 state['current'] = [node]
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 status = util.system(command,
671 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
672 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
673 out=ui.fout)
674 if status == 125:
674 if status == 125:
675 transition = "skip"
675 transition = "skip"
676 elif status == 0:
676 elif status == 0:
677 transition = "good"
677 transition = "good"
678 # status < 0 means process was killed
678 # status < 0 means process was killed
679 elif status == 127:
679 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
680 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
681 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
682 raise util.Abort(_("%s killed") % command)
683 else:
683 else:
684 transition = "bad"
684 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
685 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
686 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
687 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
689 check_state(state, interactive=False)
690 # bisect
690 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
692 # update to next check
693 node = nodes[0]
693 node = nodes[0]
694 if not noupdate:
694 if not noupdate:
695 cmdutil.bailifchanged(repo)
695 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
696 hg.clean(repo, node, show_stats=False)
697 finally:
697 finally:
698 state['current'] = [node]
698 state['current'] = [node]
699 hbisect.save_state(repo, state)
699 hbisect.save_state(repo, state)
700 print_result(nodes, good)
700 print_result(nodes, good)
701 return
701 return
702
702
703 # update state
703 # update state
704
704
705 if rev:
705 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
707 else:
708 nodes = [repo.lookup('.')]
708 nodes = [repo.lookup('.')]
709
709
710 if good or bad or skip:
710 if good or bad or skip:
711 if good:
711 if good:
712 state['good'] += nodes
712 state['good'] += nodes
713 elif bad:
713 elif bad:
714 state['bad'] += nodes
714 state['bad'] += nodes
715 elif skip:
715 elif skip:
716 state['skip'] += nodes
716 state['skip'] += nodes
717 hbisect.save_state(repo, state)
717 hbisect.save_state(repo, state)
718
718
719 if not check_state(state):
719 if not check_state(state):
720 return
720 return
721
721
722 # actually bisect
722 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
724 if extend:
725 if not changesets:
725 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
728 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
729 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
730 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 if noupdate:
732 if noupdate:
733 return
733 return
734 cmdutil.bailifchanged(repo)
734 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
735 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
736 raise util.Abort(_("nothing to extend"))
737
737
738 if changesets == 0:
738 if changesets == 0:
739 print_result(nodes, good)
739 print_result(nodes, good)
740 else:
740 else:
741 assert len(nodes) == 1 # only a single node can be tested next
741 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
742 node = nodes[0]
743 # compute the approximate number of remaining tests
743 # compute the approximate number of remaining tests
744 tests, size = 0, 2
744 tests, size = 0, 2
745 while size <= changesets:
745 while size <= changesets:
746 tests, size = tests + 1, size * 2
746 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
747 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
748 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
749 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
750 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
751 state['current'] = [node]
752 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
753 if not noupdate:
753 if not noupdate:
754 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
755 return hg.clean(repo, node)
756
756
757 @command('bookmarks',
757 @command('bookmarks',
758 [('f', 'force', False, _('force')),
758 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
759 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
760 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
765 rename=None, inactive=False):
766 '''track a line of development with movable markers
766 '''track a line of development with movable markers
767
767
768 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
769 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
771 :hg:`update NAME` to update to a given bookmark.
772
772
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
774 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
775 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
776 the bookmark is assigned to that revision.
777
777
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
779 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
780 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
781 the bookmarks extension must be enabled.
782
782
783 With -i/--inactive, the new bookmark will not be made the active
783 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
784 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
785 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
786 current active bookmark will be marked inactive.
787 '''
787 '''
788 hexfn = ui.debugflag and hex or short
788 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
789 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
790 cur = repo.changectx('.').node()
791
791
792 if delete:
792 if delete:
793 if mark is None:
793 if mark is None:
794 raise util.Abort(_("bookmark name required"))
794 raise util.Abort(_("bookmark name required"))
795 if mark not in marks:
795 if mark not in marks:
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
797 if mark == repo._bookmarkcurrent:
797 if mark == repo._bookmarkcurrent:
798 bookmarks.setcurrent(repo, None)
798 bookmarks.setcurrent(repo, None)
799 del marks[mark]
799 del marks[mark]
800 bookmarks.write(repo)
800 bookmarks.write(repo)
801 return
801 return
802
802
803 if rename:
803 if rename:
804 if rename not in marks:
804 if rename not in marks:
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
806 if mark in marks and not force:
806 if mark in marks and not force:
807 raise util.Abort(_("bookmark '%s' already exists "
807 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
808 "(use -f to force)") % mark)
809 if mark is None:
809 if mark is None:
810 raise util.Abort(_("new bookmark name required"))
810 raise util.Abort(_("new bookmark name required"))
811 marks[mark] = marks[rename]
811 marks[mark] = marks[rename]
812 if repo._bookmarkcurrent == rename and not inactive:
812 if repo._bookmarkcurrent == rename and not inactive:
813 bookmarks.setcurrent(repo, mark)
813 bookmarks.setcurrent(repo, mark)
814 del marks[rename]
814 del marks[rename]
815 bookmarks.write(repo)
815 bookmarks.write(repo)
816 return
816 return
817
817
818 if mark is not None:
818 if mark is not None:
819 if "\n" in mark:
819 if "\n" in mark:
820 raise util.Abort(_("bookmark name cannot contain newlines"))
820 raise util.Abort(_("bookmark name cannot contain newlines"))
821 mark = mark.strip()
821 mark = mark.strip()
822 if not mark:
822 if not mark:
823 raise util.Abort(_("bookmark names cannot consist entirely of "
823 raise util.Abort(_("bookmark names cannot consist entirely of "
824 "whitespace"))
824 "whitespace"))
825 if inactive and mark == repo._bookmarkcurrent:
825 if inactive and mark == repo._bookmarkcurrent:
826 bookmarks.setcurrent(repo, None)
826 bookmarks.setcurrent(repo, None)
827 return
827 return
828 if mark in marks and not force:
828 if mark in marks and not force:
829 raise util.Abort(_("bookmark '%s' already exists "
829 raise util.Abort(_("bookmark '%s' already exists "
830 "(use -f to force)") % mark)
830 "(use -f to force)") % mark)
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
832 and not force):
832 and not force):
833 raise util.Abort(
833 raise util.Abort(
834 _("a bookmark cannot have the name of an existing branch"))
834 _("a bookmark cannot have the name of an existing branch"))
835 if rev:
835 if rev:
836 marks[mark] = repo.lookup(rev)
836 marks[mark] = repo.lookup(rev)
837 else:
837 else:
838 marks[mark] = cur
838 marks[mark] = cur
839 if not inactive and cur == marks[mark]:
839 if not inactive and cur == marks[mark]:
840 bookmarks.setcurrent(repo, mark)
840 bookmarks.setcurrent(repo, mark)
841 bookmarks.write(repo)
841 bookmarks.write(repo)
842 return
842 return
843
843
844 if mark is None:
844 if mark is None:
845 if rev:
845 if rev:
846 raise util.Abort(_("bookmark name required"))
846 raise util.Abort(_("bookmark name required"))
847 if len(marks) == 0:
847 if len(marks) == 0:
848 ui.status(_("no bookmarks set\n"))
848 ui.status(_("no bookmarks set\n"))
849 else:
849 else:
850 for bmark, n in sorted(marks.iteritems()):
850 for bmark, n in sorted(marks.iteritems()):
851 current = repo._bookmarkcurrent
851 current = repo._bookmarkcurrent
852 if bmark == current and n == cur:
852 if bmark == current and n == cur:
853 prefix, label = '*', 'bookmarks.current'
853 prefix, label = '*', 'bookmarks.current'
854 else:
854 else:
855 prefix, label = ' ', ''
855 prefix, label = ' ', ''
856
856
857 if ui.quiet:
857 if ui.quiet:
858 ui.write("%s\n" % bmark, label=label)
858 ui.write("%s\n" % bmark, label=label)
859 else:
859 else:
860 ui.write(" %s %-25s %d:%s\n" % (
860 ui.write(" %s %-25s %d:%s\n" % (
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
862 label=label)
862 label=label)
863 return
863 return
864
864
865 @command('branch',
865 @command('branch',
866 [('f', 'force', None,
866 [('f', 'force', None,
867 _('set branch name even if it shadows an existing branch')),
867 _('set branch name even if it shadows an existing branch')),
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
869 _('[-fC] [NAME]'))
869 _('[-fC] [NAME]'))
870 def branch(ui, repo, label=None, **opts):
870 def branch(ui, repo, label=None, **opts):
871 """set or show the current branch name
871 """set or show the current branch name
872
872
873 .. note::
873 .. note::
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
875 light-weight bookmark instead. See :hg:`help glossary` for more
875 light-weight bookmark instead. See :hg:`help glossary` for more
876 information about named branches and bookmarks.
876 information about named branches and bookmarks.
877
877
878 With no argument, show the current branch name. With one argument,
878 With no argument, show the current branch name. With one argument,
879 set the working directory branch name (the branch will not exist
879 set the working directory branch name (the branch will not exist
880 in the repository until the next commit). Standard practice
880 in the repository until the next commit). Standard practice
881 recommends that primary development take place on the 'default'
881 recommends that primary development take place on the 'default'
882 branch.
882 branch.
883
883
884 Unless -f/--force is specified, branch will not let you set a
884 Unless -f/--force is specified, branch will not let you set a
885 branch name that already exists, even if it's inactive.
885 branch name that already exists, even if it's inactive.
886
886
887 Use -C/--clean to reset the working directory branch to that of
887 Use -C/--clean to reset the working directory branch to that of
888 the parent of the working directory, negating a previous branch
888 the parent of the working directory, negating a previous branch
889 change.
889 change.
890
890
891 Use the command :hg:`update` to switch to an existing branch. Use
891 Use the command :hg:`update` to switch to an existing branch. Use
892 :hg:`commit --close-branch` to mark this branch as closed.
892 :hg:`commit --close-branch` to mark this branch as closed.
893
893
894 Returns 0 on success.
894 Returns 0 on success.
895 """
895 """
896 if not opts.get('clean') and not label:
896 if not opts.get('clean') and not label:
897 ui.write("%s\n" % repo.dirstate.branch())
897 ui.write("%s\n" % repo.dirstate.branch())
898 return
898 return
899
899
900 wlock = repo.wlock()
900 wlock = repo.wlock()
901 try:
901 try:
902 if opts.get('clean'):
902 if opts.get('clean'):
903 label = repo[None].p1().branch()
903 label = repo[None].p1().branch()
904 repo.dirstate.setbranch(label)
904 repo.dirstate.setbranch(label)
905 ui.status(_('reset working directory to branch %s\n') % label)
905 ui.status(_('reset working directory to branch %s\n') % label)
906 elif label:
906 elif label:
907 if not opts.get('force') and label in repo.branchmap():
907 if not opts.get('force') and label in repo.branchmap():
908 if label not in [p.branch() for p in repo.parents()]:
908 if label not in [p.branch() for p in repo.parents()]:
909 raise util.Abort(_('a branch of the same name already'
909 raise util.Abort(_('a branch of the same name already'
910 ' exists'),
910 ' exists'),
911 # i18n: "it" refers to an existing branch
911 # i18n: "it" refers to an existing branch
912 hint=_("use 'hg update' to switch to it"))
912 hint=_("use 'hg update' to switch to it"))
913 repo.dirstate.setbranch(label)
913 repo.dirstate.setbranch(label)
914 ui.status(_('marked working directory as branch %s\n') % label)
914 ui.status(_('marked working directory as branch %s\n') % label)
915 ui.status(_('(branches are permanent and global, '
915 ui.status(_('(branches are permanent and global, '
916 'did you want a bookmark?)\n'))
916 'did you want a bookmark?)\n'))
917 finally:
917 finally:
918 wlock.release()
918 wlock.release()
919
919
920 @command('branches',
920 @command('branches',
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
922 ('c', 'closed', False, _('show normal and closed branches'))],
922 ('c', 'closed', False, _('show normal and closed branches'))],
923 _('[-ac]'))
923 _('[-ac]'))
924 def branches(ui, repo, active=False, closed=False):
924 def branches(ui, repo, active=False, closed=False):
925 """list repository named branches
925 """list repository named branches
926
926
927 List the repository's named branches, indicating which ones are
927 List the repository's named branches, indicating which ones are
928 inactive. If -c/--closed is specified, also list branches which have
928 inactive. If -c/--closed is specified, also list branches which have
929 been marked closed (see :hg:`commit --close-branch`).
929 been marked closed (see :hg:`commit --close-branch`).
930
930
931 If -a/--active is specified, only show active branches. A branch
931 If -a/--active is specified, only show active branches. A branch
932 is considered active if it contains repository heads.
932 is considered active if it contains repository heads.
933
933
934 Use the command :hg:`update` to switch to an existing branch.
934 Use the command :hg:`update` to switch to an existing branch.
935
935
936 Returns 0.
936 Returns 0.
937 """
937 """
938
938
939 hexfunc = ui.debugflag and hex or short
939 hexfunc = ui.debugflag and hex or short
940
940
941 activebranches = set([repo[n].branch() for n in repo.heads()])
941 activebranches = set([repo[n].branch() for n in repo.heads()])
942 branches = []
942 branches = []
943 for tag, heads in repo.branchmap().iteritems():
943 for tag, heads in repo.branchmap().iteritems():
944 for h in reversed(heads):
944 for h in reversed(heads):
945 ctx = repo[h]
945 ctx = repo[h]
946 isopen = not ctx.closesbranch()
946 isopen = not ctx.closesbranch()
947 if isopen:
947 if isopen:
948 tip = ctx
948 tip = ctx
949 break
949 break
950 else:
950 else:
951 tip = repo[heads[-1]]
951 tip = repo[heads[-1]]
952 isactive = tag in activebranches and isopen
952 isactive = tag in activebranches and isopen
953 branches.append((tip, isactive, isopen))
953 branches.append((tip, isactive, isopen))
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
955 reverse=True)
955 reverse=True)
956
956
957 for ctx, isactive, isopen in branches:
957 for ctx, isactive, isopen in branches:
958 if (not active) or isactive:
958 if (not active) or isactive:
959 if isactive:
959 if isactive:
960 label = 'branches.active'
960 label = 'branches.active'
961 notice = ''
961 notice = ''
962 elif not isopen:
962 elif not isopen:
963 if not closed:
963 if not closed:
964 continue
964 continue
965 label = 'branches.closed'
965 label = 'branches.closed'
966 notice = _(' (closed)')
966 notice = _(' (closed)')
967 else:
967 else:
968 label = 'branches.inactive'
968 label = 'branches.inactive'
969 notice = _(' (inactive)')
969 notice = _(' (inactive)')
970 if ctx.branch() == repo.dirstate.branch():
970 if ctx.branch() == repo.dirstate.branch():
971 label = 'branches.current'
971 label = 'branches.current'
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
974 'log.changeset')
974 'log.changeset')
975 tag = ui.label(ctx.branch(), label)
975 tag = ui.label(ctx.branch(), label)
976 if ui.quiet:
976 if ui.quiet:
977 ui.write("%s\n" % tag)
977 ui.write("%s\n" % tag)
978 else:
978 else:
979 ui.write("%s %s%s\n" % (tag, rev, notice))
979 ui.write("%s %s%s\n" % (tag, rev, notice))
980
980
981 @command('bundle',
981 @command('bundle',
982 [('f', 'force', None, _('run even when the destination is unrelated')),
982 [('f', 'force', None, _('run even when the destination is unrelated')),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
984 _('REV')),
984 _('REV')),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
986 _('BRANCH')),
986 _('BRANCH')),
987 ('', 'base', [],
987 ('', 'base', [],
988 _('a base changeset assumed to be available at the destination'),
988 _('a base changeset assumed to be available at the destination'),
989 _('REV')),
989 _('REV')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
992 ] + remoteopts,
992 ] + remoteopts,
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
994 def bundle(ui, repo, fname, dest=None, **opts):
994 def bundle(ui, repo, fname, dest=None, **opts):
995 """create a changegroup file
995 """create a changegroup file
996
996
997 Generate a compressed changegroup file collecting changesets not
997 Generate a compressed changegroup file collecting changesets not
998 known to be in another repository.
998 known to be in another repository.
999
999
1000 If you omit the destination repository, then hg assumes the
1000 If you omit the destination repository, then hg assumes the
1001 destination will have all the nodes you specify with --base
1001 destination will have all the nodes you specify with --base
1002 parameters. To create a bundle containing all changesets, use
1002 parameters. To create a bundle containing all changesets, use
1003 -a/--all (or --base null).
1003 -a/--all (or --base null).
1004
1004
1005 You can change compression method with the -t/--type option.
1005 You can change compression method with the -t/--type option.
1006 The available compression methods are: none, bzip2, and
1006 The available compression methods are: none, bzip2, and
1007 gzip (by default, bundles are compressed using bzip2).
1007 gzip (by default, bundles are compressed using bzip2).
1008
1008
1009 The bundle file can then be transferred using conventional means
1009 The bundle file can then be transferred using conventional means
1010 and applied to another repository with the unbundle or pull
1010 and applied to another repository with the unbundle or pull
1011 command. This is useful when direct push and pull are not
1011 command. This is useful when direct push and pull are not
1012 available or when exporting an entire repository is undesirable.
1012 available or when exporting an entire repository is undesirable.
1013
1013
1014 Applying bundles preserves all changeset contents including
1014 Applying bundles preserves all changeset contents including
1015 permissions, copy/rename information, and revision history.
1015 permissions, copy/rename information, and revision history.
1016
1016
1017 Returns 0 on success, 1 if no changes found.
1017 Returns 0 on success, 1 if no changes found.
1018 """
1018 """
1019 revs = None
1019 revs = None
1020 if 'rev' in opts:
1020 if 'rev' in opts:
1021 revs = scmutil.revrange(repo, opts['rev'])
1021 revs = scmutil.revrange(repo, opts['rev'])
1022
1022
1023 bundletype = opts.get('type', 'bzip2').lower()
1023 bundletype = opts.get('type', 'bzip2').lower()
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1025 bundletype = btypes.get(bundletype)
1025 bundletype = btypes.get(bundletype)
1026 if bundletype not in changegroup.bundletypes:
1026 if bundletype not in changegroup.bundletypes:
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1028
1028
1029 if opts.get('all'):
1029 if opts.get('all'):
1030 base = ['null']
1030 base = ['null']
1031 else:
1031 else:
1032 base = scmutil.revrange(repo, opts.get('base'))
1032 base = scmutil.revrange(repo, opts.get('base'))
1033 if base:
1033 if base:
1034 if dest:
1034 if dest:
1035 raise util.Abort(_("--base is incompatible with specifying "
1035 raise util.Abort(_("--base is incompatible with specifying "
1036 "a destination"))
1036 "a destination"))
1037 common = [repo.lookup(rev) for rev in base]
1037 common = [repo.lookup(rev) for rev in base]
1038 heads = revs and map(repo.lookup, revs) or revs
1038 heads = revs and map(repo.lookup, revs) or revs
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1040 outgoing = None
1040 outgoing = None
1041 else:
1041 else:
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1044 other = hg.peer(repo, opts, dest)
1044 other = hg.peer(repo, opts, dest)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1046 heads = revs and map(repo.lookup, revs) or revs
1046 heads = revs and map(repo.lookup, revs) or revs
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1048 onlyheads=heads,
1048 onlyheads=heads,
1049 force=opts.get('force'),
1049 force=opts.get('force'),
1050 portable=True)
1050 portable=True)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1052 if not cg:
1052 if not cg:
1053 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1053 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1054 return 1
1054 return 1
1055
1055
1056 changegroup.writebundle(cg, fname, bundletype)
1056 changegroup.writebundle(cg, fname, bundletype)
1057
1057
1058 @command('cat',
1058 @command('cat',
1059 [('o', 'output', '',
1059 [('o', 'output', '',
1060 _('print output to file with formatted name'), _('FORMAT')),
1060 _('print output to file with formatted name'), _('FORMAT')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1063 ] + walkopts,
1063 ] + walkopts,
1064 _('[OPTION]... FILE...'))
1064 _('[OPTION]... FILE...'))
1065 def cat(ui, repo, file1, *pats, **opts):
1065 def cat(ui, repo, file1, *pats, **opts):
1066 """output the current or given revision of files
1066 """output the current or given revision of files
1067
1067
1068 Print the specified files as they were at the given revision. If
1068 Print the specified files as they were at the given revision. If
1069 no revision is given, the parent of the working directory is used,
1069 no revision is given, the parent of the working directory is used,
1070 or tip if no revision is checked out.
1070 or tip if no revision is checked out.
1071
1071
1072 Output may be to a file, in which case the name of the file is
1072 Output may be to a file, in which case the name of the file is
1073 given using a format string. The formatting rules are the same as
1073 given using a format string. The formatting rules are the same as
1074 for the export command, with the following additions:
1074 for the export command, with the following additions:
1075
1075
1076 :``%s``: basename of file being printed
1076 :``%s``: basename of file being printed
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1078 :``%p``: root-relative path name of file being printed
1078 :``%p``: root-relative path name of file being printed
1079
1079
1080 Returns 0 on success.
1080 Returns 0 on success.
1081 """
1081 """
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1083 err = 1
1083 err = 1
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1085 for abs in ctx.walk(m):
1085 for abs in ctx.walk(m):
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1087 pathname=abs)
1087 pathname=abs)
1088 data = ctx[abs].data()
1088 data = ctx[abs].data()
1089 if opts.get('decode'):
1089 if opts.get('decode'):
1090 data = repo.wwritedata(abs, data)
1090 data = repo.wwritedata(abs, data)
1091 fp.write(data)
1091 fp.write(data)
1092 fp.close()
1092 fp.close()
1093 err = 0
1093 err = 0
1094 return err
1094 return err
1095
1095
1096 @command('^clone',
1096 @command('^clone',
1097 [('U', 'noupdate', None,
1097 [('U', 'noupdate', None,
1098 _('the clone will include an empty working copy (only a repository)')),
1098 _('the clone will include an empty working copy (only a repository)')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1104 ] + remoteopts,
1104 ] + remoteopts,
1105 _('[OPTION]... SOURCE [DEST]'))
1105 _('[OPTION]... SOURCE [DEST]'))
1106 def clone(ui, source, dest=None, **opts):
1106 def clone(ui, source, dest=None, **opts):
1107 """make a copy of an existing repository
1107 """make a copy of an existing repository
1108
1108
1109 Create a copy of an existing repository in a new directory.
1109 Create a copy of an existing repository in a new directory.
1110
1110
1111 If no destination directory name is specified, it defaults to the
1111 If no destination directory name is specified, it defaults to the
1112 basename of the source.
1112 basename of the source.
1113
1113
1114 The location of the source is added to the new repository's
1114 The location of the source is added to the new repository's
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1116
1116
1117 Only local paths and ``ssh://`` URLs are supported as
1117 Only local paths and ``ssh://`` URLs are supported as
1118 destinations. For ``ssh://`` destinations, no working directory or
1118 destinations. For ``ssh://`` destinations, no working directory or
1119 ``.hg/hgrc`` will be created on the remote side.
1119 ``.hg/hgrc`` will be created on the remote side.
1120
1120
1121 To pull only a subset of changesets, specify one or more revisions
1121 To pull only a subset of changesets, specify one or more revisions
1122 identifiers with -r/--rev or branches with -b/--branch. The
1122 identifiers with -r/--rev or branches with -b/--branch. The
1123 resulting clone will contain only the specified changesets and
1123 resulting clone will contain only the specified changesets and
1124 their ancestors. These options (or 'clone src#rev dest') imply
1124 their ancestors. These options (or 'clone src#rev dest') imply
1125 --pull, even for local source repositories. Note that specifying a
1125 --pull, even for local source repositories. Note that specifying a
1126 tag will include the tagged changeset but not the changeset
1126 tag will include the tagged changeset but not the changeset
1127 containing the tag.
1127 containing the tag.
1128
1128
1129 To check out a particular version, use -u/--update, or
1129 To check out a particular version, use -u/--update, or
1130 -U/--noupdate to create a clone with no working directory.
1130 -U/--noupdate to create a clone with no working directory.
1131
1131
1132 .. container:: verbose
1132 .. container:: verbose
1133
1133
1134 For efficiency, hardlinks are used for cloning whenever the
1134 For efficiency, hardlinks are used for cloning whenever the
1135 source and destination are on the same filesystem (note this
1135 source and destination are on the same filesystem (note this
1136 applies only to the repository data, not to the working
1136 applies only to the repository data, not to the working
1137 directory). Some filesystems, such as AFS, implement hardlinking
1137 directory). Some filesystems, such as AFS, implement hardlinking
1138 incorrectly, but do not report errors. In these cases, use the
1138 incorrectly, but do not report errors. In these cases, use the
1139 --pull option to avoid hardlinking.
1139 --pull option to avoid hardlinking.
1140
1140
1141 In some cases, you can clone repositories and the working
1141 In some cases, you can clone repositories and the working
1142 directory using full hardlinks with ::
1142 directory using full hardlinks with ::
1143
1143
1144 $ cp -al REPO REPOCLONE
1144 $ cp -al REPO REPOCLONE
1145
1145
1146 This is the fastest way to clone, but it is not always safe. The
1146 This is the fastest way to clone, but it is not always safe. The
1147 operation is not atomic (making sure REPO is not modified during
1147 operation is not atomic (making sure REPO is not modified during
1148 the operation is up to you) and you have to make sure your
1148 the operation is up to you) and you have to make sure your
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1150 so). Also, this is not compatible with certain extensions that
1150 so). Also, this is not compatible with certain extensions that
1151 place their metadata under the .hg directory, such as mq.
1151 place their metadata under the .hg directory, such as mq.
1152
1152
1153 Mercurial will update the working directory to the first applicable
1153 Mercurial will update the working directory to the first applicable
1154 revision from this list:
1154 revision from this list:
1155
1155
1156 a) null if -U or the source repository has no changesets
1156 a) null if -U or the source repository has no changesets
1157 b) if -u . and the source repository is local, the first parent of
1157 b) if -u . and the source repository is local, the first parent of
1158 the source repository's working directory
1158 the source repository's working directory
1159 c) the changeset specified with -u (if a branch name, this means the
1159 c) the changeset specified with -u (if a branch name, this means the
1160 latest head of that branch)
1160 latest head of that branch)
1161 d) the changeset specified with -r
1161 d) the changeset specified with -r
1162 e) the tipmost head specified with -b
1162 e) the tipmost head specified with -b
1163 f) the tipmost head specified with the url#branch source syntax
1163 f) the tipmost head specified with the url#branch source syntax
1164 g) the tipmost head of the default branch
1164 g) the tipmost head of the default branch
1165 h) tip
1165 h) tip
1166
1166
1167 Examples:
1167 Examples:
1168
1168
1169 - clone a remote repository to a new directory named hg/::
1169 - clone a remote repository to a new directory named hg/::
1170
1170
1171 hg clone http://selenic.com/hg
1171 hg clone http://selenic.com/hg
1172
1172
1173 - create a lightweight local clone::
1173 - create a lightweight local clone::
1174
1174
1175 hg clone project/ project-feature/
1175 hg clone project/ project-feature/
1176
1176
1177 - clone from an absolute path on an ssh server (note double-slash)::
1177 - clone from an absolute path on an ssh server (note double-slash)::
1178
1178
1179 hg clone ssh://user@server//home/projects/alpha/
1179 hg clone ssh://user@server//home/projects/alpha/
1180
1180
1181 - do a high-speed clone over a LAN while checking out a
1181 - do a high-speed clone over a LAN while checking out a
1182 specified version::
1182 specified version::
1183
1183
1184 hg clone --uncompressed http://server/repo -u 1.5
1184 hg clone --uncompressed http://server/repo -u 1.5
1185
1185
1186 - create a repository without changesets after a particular revision::
1186 - create a repository without changesets after a particular revision::
1187
1187
1188 hg clone -r 04e544 experimental/ good/
1188 hg clone -r 04e544 experimental/ good/
1189
1189
1190 - clone (and track) a particular named branch::
1190 - clone (and track) a particular named branch::
1191
1191
1192 hg clone http://selenic.com/hg#stable
1192 hg clone http://selenic.com/hg#stable
1193
1193
1194 See :hg:`help urls` for details on specifying URLs.
1194 See :hg:`help urls` for details on specifying URLs.
1195
1195
1196 Returns 0 on success.
1196 Returns 0 on success.
1197 """
1197 """
1198 if opts.get('noupdate') and opts.get('updaterev'):
1198 if opts.get('noupdate') and opts.get('updaterev'):
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1200
1200
1201 r = hg.clone(ui, opts, source, dest,
1201 r = hg.clone(ui, opts, source, dest,
1202 pull=opts.get('pull'),
1202 pull=opts.get('pull'),
1203 stream=opts.get('uncompressed'),
1203 stream=opts.get('uncompressed'),
1204 rev=opts.get('rev'),
1204 rev=opts.get('rev'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1206 branch=opts.get('branch'))
1206 branch=opts.get('branch'))
1207
1207
1208 return r is None
1208 return r is None
1209
1209
1210 @command('^commit|ci',
1210 @command('^commit|ci',
1211 [('A', 'addremove', None,
1211 [('A', 'addremove', None,
1212 _('mark new/missing files as added/removed before committing')),
1212 _('mark new/missing files as added/removed before committing')),
1213 ('', 'close-branch', None,
1213 ('', 'close-branch', None,
1214 _('mark a branch as closed, hiding it from the branch list')),
1214 _('mark a branch as closed, hiding it from the branch list')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1217 _('[OPTION]... [FILE]...'))
1217 _('[OPTION]... [FILE]...'))
1218 def commit(ui, repo, *pats, **opts):
1218 def commit(ui, repo, *pats, **opts):
1219 """commit the specified files or all outstanding changes
1219 """commit the specified files or all outstanding changes
1220
1220
1221 Commit changes to the given files into the repository. Unlike a
1221 Commit changes to the given files into the repository. Unlike a
1222 centralized SCM, this operation is a local operation. See
1222 centralized SCM, this operation is a local operation. See
1223 :hg:`push` for a way to actively distribute your changes.
1223 :hg:`push` for a way to actively distribute your changes.
1224
1224
1225 If a list of files is omitted, all changes reported by :hg:`status`
1225 If a list of files is omitted, all changes reported by :hg:`status`
1226 will be committed.
1226 will be committed.
1227
1227
1228 If you are committing the result of a merge, do not provide any
1228 If you are committing the result of a merge, do not provide any
1229 filenames or -I/-X filters.
1229 filenames or -I/-X filters.
1230
1230
1231 If no commit message is specified, Mercurial starts your
1231 If no commit message is specified, Mercurial starts your
1232 configured editor where you can enter a message. In case your
1232 configured editor where you can enter a message. In case your
1233 commit fails, you will find a backup of your message in
1233 commit fails, you will find a backup of your message in
1234 ``.hg/last-message.txt``.
1234 ``.hg/last-message.txt``.
1235
1235
1236 The --amend flag can be used to amend the parent of the
1236 The --amend flag can be used to amend the parent of the
1237 working directory with a new commit that contains the changes
1237 working directory with a new commit that contains the changes
1238 in the parent in addition to those currently reported by :hg:`status`,
1238 in the parent in addition to those currently reported by :hg:`status`,
1239 if there are any. The old commit is stored in a backup bundle in
1239 if there are any. The old commit is stored in a backup bundle in
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1241 on how to restore it).
1241 on how to restore it).
1242
1242
1243 Message, user and date are taken from the amended commit unless
1243 Message, user and date are taken from the amended commit unless
1244 specified. When a message isn't specified on the command line,
1244 specified. When a message isn't specified on the command line,
1245 the editor will open with the message of the amended commit.
1245 the editor will open with the message of the amended commit.
1246
1246
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1248 or changesets that have children.
1248 or changesets that have children.
1249
1249
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1251
1251
1252 Returns 0 on success, 1 if nothing changed.
1252 Returns 0 on success, 1 if nothing changed.
1253 """
1253 """
1254 if opts.get('subrepos'):
1254 if opts.get('subrepos'):
1255 # Let --subrepos on the command line overide config setting.
1255 # Let --subrepos on the command line overide config setting.
1256 ui.setconfig('ui', 'commitsubrepos', True)
1256 ui.setconfig('ui', 'commitsubrepos', True)
1257
1257
1258 extra = {}
1258 extra = {}
1259 if opts.get('close_branch'):
1259 if opts.get('close_branch'):
1260 if repo['.'].node() not in repo.branchheads():
1260 if repo['.'].node() not in repo.branchheads():
1261 # The topo heads set is included in the branch heads set of the
1261 # The topo heads set is included in the branch heads set of the
1262 # current branch, so it's sufficient to test branchheads
1262 # current branch, so it's sufficient to test branchheads
1263 raise util.Abort(_('can only close branch heads'))
1263 raise util.Abort(_('can only close branch heads'))
1264 extra['close'] = 1
1264 extra['close'] = 1
1265
1265
1266 branch = repo[None].branch()
1266 branch = repo[None].branch()
1267 bheads = repo.branchheads(branch)
1267 bheads = repo.branchheads(branch)
1268
1268
1269 if opts.get('amend'):
1269 if opts.get('amend'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1271 raise util.Abort(_('cannot amend recursively'))
1271 raise util.Abort(_('cannot amend recursively'))
1272
1272
1273 old = repo['.']
1273 old = repo['.']
1274 if old.phase() == phases.public:
1274 if old.phase() == phases.public:
1275 raise util.Abort(_('cannot amend public changesets'))
1275 raise util.Abort(_('cannot amend public changesets'))
1276 if len(old.parents()) > 1:
1276 if len(old.parents()) > 1:
1277 raise util.Abort(_('cannot amend merge changesets'))
1277 raise util.Abort(_('cannot amend merge changesets'))
1278 if len(repo[None].parents()) > 1:
1278 if len(repo[None].parents()) > 1:
1279 raise util.Abort(_('cannot amend while merging'))
1279 raise util.Abort(_('cannot amend while merging'))
1280 if old.children():
1280 if old.children():
1281 raise util.Abort(_('cannot amend changeset with children'))
1281 raise util.Abort(_('cannot amend changeset with children'))
1282
1282
1283 e = cmdutil.commiteditor
1283 e = cmdutil.commiteditor
1284 if opts.get('force_editor'):
1284 if opts.get('force_editor'):
1285 e = cmdutil.commitforceeditor
1285 e = cmdutil.commitforceeditor
1286
1286
1287 def commitfunc(ui, repo, message, match, opts):
1287 def commitfunc(ui, repo, message, match, opts):
1288 editor = e
1288 editor = e
1289 # message contains text from -m or -l, if it's empty,
1289 # message contains text from -m or -l, if it's empty,
1290 # open the editor with the old message
1290 # open the editor with the old message
1291 if not message:
1291 if not message:
1292 message = old.description()
1292 message = old.description()
1293 editor = cmdutil.commitforceeditor
1293 editor = cmdutil.commitforceeditor
1294 return repo.commit(message,
1294 return repo.commit(message,
1295 opts.get('user') or old.user(),
1295 opts.get('user') or old.user(),
1296 opts.get('date') or old.date(),
1296 opts.get('date') or old.date(),
1297 match,
1297 match,
1298 editor=editor,
1298 editor=editor,
1299 extra=extra)
1299 extra=extra)
1300
1300
1301 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1301 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1302 if node == old.node():
1302 if node == old.node():
1303 ui.status(_("nothing changed\n"))
1303 ui.status(_("nothing changed\n"))
1304 return 1
1304 return 1
1305 else:
1305 else:
1306 e = cmdutil.commiteditor
1306 e = cmdutil.commiteditor
1307 if opts.get('force_editor'):
1307 if opts.get('force_editor'):
1308 e = cmdutil.commitforceeditor
1308 e = cmdutil.commitforceeditor
1309
1309
1310 def commitfunc(ui, repo, message, match, opts):
1310 def commitfunc(ui, repo, message, match, opts):
1311 return repo.commit(message, opts.get('user'), opts.get('date'),
1311 return repo.commit(message, opts.get('user'), opts.get('date'),
1312 match, editor=e, extra=extra)
1312 match, editor=e, extra=extra)
1313
1313
1314 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1314 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1315
1315
1316 if not node:
1316 if not node:
1317 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1317 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1318 if stat[3]:
1318 if stat[3]:
1319 ui.status(_("nothing changed (%d missing files, see "
1319 ui.status(_("nothing changed (%d missing files, see "
1320 "'hg status')\n") % len(stat[3]))
1320 "'hg status')\n") % len(stat[3]))
1321 else:
1321 else:
1322 ui.status(_("nothing changed\n"))
1322 ui.status(_("nothing changed\n"))
1323 return 1
1323 return 1
1324
1324
1325 ctx = repo[node]
1325 ctx = repo[node]
1326 parents = ctx.parents()
1326 parents = ctx.parents()
1327
1327
1328 if (not opts.get('amend') and bheads and node not in bheads and not
1328 if (not opts.get('amend') and bheads and node not in bheads and not
1329 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1329 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1330 ui.status(_('created new head\n'))
1330 ui.status(_('created new head\n'))
1331 # The message is not printed for initial roots. For the other
1331 # The message is not printed for initial roots. For the other
1332 # changesets, it is printed in the following situations:
1332 # changesets, it is printed in the following situations:
1333 #
1333 #
1334 # Par column: for the 2 parents with ...
1334 # Par column: for the 2 parents with ...
1335 # N: null or no parent
1335 # N: null or no parent
1336 # B: parent is on another named branch
1336 # B: parent is on another named branch
1337 # C: parent is a regular non head changeset
1337 # C: parent is a regular non head changeset
1338 # H: parent was a branch head of the current branch
1338 # H: parent was a branch head of the current branch
1339 # Msg column: whether we print "created new head" message
1339 # Msg column: whether we print "created new head" message
1340 # In the following, it is assumed that there already exists some
1340 # In the following, it is assumed that there already exists some
1341 # initial branch heads of the current branch, otherwise nothing is
1341 # initial branch heads of the current branch, otherwise nothing is
1342 # printed anyway.
1342 # printed anyway.
1343 #
1343 #
1344 # Par Msg Comment
1344 # Par Msg Comment
1345 # NN y additional topo root
1345 # NN y additional topo root
1346 #
1346 #
1347 # BN y additional branch root
1347 # BN y additional branch root
1348 # CN y additional topo head
1348 # CN y additional topo head
1349 # HN n usual case
1349 # HN n usual case
1350 #
1350 #
1351 # BB y weird additional branch root
1351 # BB y weird additional branch root
1352 # CB y branch merge
1352 # CB y branch merge
1353 # HB n merge with named branch
1353 # HB n merge with named branch
1354 #
1354 #
1355 # CC y additional head from merge
1355 # CC y additional head from merge
1356 # CH n merge with a head
1356 # CH n merge with a head
1357 #
1357 #
1358 # HH n head merge: head count decreases
1358 # HH n head merge: head count decreases
1359
1359
1360 if not opts.get('close_branch'):
1360 if not opts.get('close_branch'):
1361 for r in parents:
1361 for r in parents:
1362 if r.closesbranch() and r.branch() == branch:
1362 if r.closesbranch() and r.branch() == branch:
1363 ui.status(_('reopening closed branch head %d\n') % r)
1363 ui.status(_('reopening closed branch head %d\n') % r)
1364
1364
1365 if ui.debugflag:
1365 if ui.debugflag:
1366 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1366 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1367 elif ui.verbose:
1367 elif ui.verbose:
1368 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1368 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1369
1369
1370 @command('copy|cp',
1370 @command('copy|cp',
1371 [('A', 'after', None, _('record a copy that has already occurred')),
1371 [('A', 'after', None, _('record a copy that has already occurred')),
1372 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1372 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1373 ] + walkopts + dryrunopts,
1373 ] + walkopts + dryrunopts,
1374 _('[OPTION]... [SOURCE]... DEST'))
1374 _('[OPTION]... [SOURCE]... DEST'))
1375 def copy(ui, repo, *pats, **opts):
1375 def copy(ui, repo, *pats, **opts):
1376 """mark files as copied for the next commit
1376 """mark files as copied for the next commit
1377
1377
1378 Mark dest as having copies of source files. If dest is a
1378 Mark dest as having copies of source files. If dest is a
1379 directory, copies are put in that directory. If dest is a file,
1379 directory, copies are put in that directory. If dest is a file,
1380 the source must be a single file.
1380 the source must be a single file.
1381
1381
1382 By default, this command copies the contents of files as they
1382 By default, this command copies the contents of files as they
1383 exist in the working directory. If invoked with -A/--after, the
1383 exist in the working directory. If invoked with -A/--after, the
1384 operation is recorded, but no copying is performed.
1384 operation is recorded, but no copying is performed.
1385
1385
1386 This command takes effect with the next commit. To undo a copy
1386 This command takes effect with the next commit. To undo a copy
1387 before that, see :hg:`revert`.
1387 before that, see :hg:`revert`.
1388
1388
1389 Returns 0 on success, 1 if errors are encountered.
1389 Returns 0 on success, 1 if errors are encountered.
1390 """
1390 """
1391 wlock = repo.wlock(False)
1391 wlock = repo.wlock(False)
1392 try:
1392 try:
1393 return cmdutil.copy(ui, repo, pats, opts)
1393 return cmdutil.copy(ui, repo, pats, opts)
1394 finally:
1394 finally:
1395 wlock.release()
1395 wlock.release()
1396
1396
1397 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1397 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1398 def debugancestor(ui, repo, *args):
1398 def debugancestor(ui, repo, *args):
1399 """find the ancestor revision of two revisions in a given index"""
1399 """find the ancestor revision of two revisions in a given index"""
1400 if len(args) == 3:
1400 if len(args) == 3:
1401 index, rev1, rev2 = args
1401 index, rev1, rev2 = args
1402 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1402 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1403 lookup = r.lookup
1403 lookup = r.lookup
1404 elif len(args) == 2:
1404 elif len(args) == 2:
1405 if not repo:
1405 if not repo:
1406 raise util.Abort(_("there is no Mercurial repository here "
1406 raise util.Abort(_("there is no Mercurial repository here "
1407 "(.hg not found)"))
1407 "(.hg not found)"))
1408 rev1, rev2 = args
1408 rev1, rev2 = args
1409 r = repo.changelog
1409 r = repo.changelog
1410 lookup = repo.lookup
1410 lookup = repo.lookup
1411 else:
1411 else:
1412 raise util.Abort(_('either two or three arguments required'))
1412 raise util.Abort(_('either two or three arguments required'))
1413 a = r.ancestor(lookup(rev1), lookup(rev2))
1413 a = r.ancestor(lookup(rev1), lookup(rev2))
1414 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1414 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1415
1415
1416 @command('debugbuilddag',
1416 @command('debugbuilddag',
1417 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1417 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1418 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1418 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1419 ('n', 'new-file', None, _('add new file at each rev'))],
1419 ('n', 'new-file', None, _('add new file at each rev'))],
1420 _('[OPTION]... [TEXT]'))
1420 _('[OPTION]... [TEXT]'))
1421 def debugbuilddag(ui, repo, text=None,
1421 def debugbuilddag(ui, repo, text=None,
1422 mergeable_file=False,
1422 mergeable_file=False,
1423 overwritten_file=False,
1423 overwritten_file=False,
1424 new_file=False):
1424 new_file=False):
1425 """builds a repo with a given DAG from scratch in the current empty repo
1425 """builds a repo with a given DAG from scratch in the current empty repo
1426
1426
1427 The description of the DAG is read from stdin if not given on the
1427 The description of the DAG is read from stdin if not given on the
1428 command line.
1428 command line.
1429
1429
1430 Elements:
1430 Elements:
1431
1431
1432 - "+n" is a linear run of n nodes based on the current default parent
1432 - "+n" is a linear run of n nodes based on the current default parent
1433 - "." is a single node based on the current default parent
1433 - "." is a single node based on the current default parent
1434 - "$" resets the default parent to null (implied at the start);
1434 - "$" resets the default parent to null (implied at the start);
1435 otherwise the default parent is always the last node created
1435 otherwise the default parent is always the last node created
1436 - "<p" sets the default parent to the backref p
1436 - "<p" sets the default parent to the backref p
1437 - "*p" is a fork at parent p, which is a backref
1437 - "*p" is a fork at parent p, which is a backref
1438 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1438 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1439 - "/p2" is a merge of the preceding node and p2
1439 - "/p2" is a merge of the preceding node and p2
1440 - ":tag" defines a local tag for the preceding node
1440 - ":tag" defines a local tag for the preceding node
1441 - "@branch" sets the named branch for subsequent nodes
1441 - "@branch" sets the named branch for subsequent nodes
1442 - "#...\\n" is a comment up to the end of the line
1442 - "#...\\n" is a comment up to the end of the line
1443
1443
1444 Whitespace between the above elements is ignored.
1444 Whitespace between the above elements is ignored.
1445
1445
1446 A backref is either
1446 A backref is either
1447
1447
1448 - a number n, which references the node curr-n, where curr is the current
1448 - a number n, which references the node curr-n, where curr is the current
1449 node, or
1449 node, or
1450 - the name of a local tag you placed earlier using ":tag", or
1450 - the name of a local tag you placed earlier using ":tag", or
1451 - empty to denote the default parent.
1451 - empty to denote the default parent.
1452
1452
1453 All string valued-elements are either strictly alphanumeric, or must
1453 All string valued-elements are either strictly alphanumeric, or must
1454 be enclosed in double quotes ("..."), with "\\" as escape character.
1454 be enclosed in double quotes ("..."), with "\\" as escape character.
1455 """
1455 """
1456
1456
1457 if text is None:
1457 if text is None:
1458 ui.status(_("reading DAG from stdin\n"))
1458 ui.status(_("reading DAG from stdin\n"))
1459 text = ui.fin.read()
1459 text = ui.fin.read()
1460
1460
1461 cl = repo.changelog
1461 cl = repo.changelog
1462 if len(cl) > 0:
1462 if len(cl) > 0:
1463 raise util.Abort(_('repository is not empty'))
1463 raise util.Abort(_('repository is not empty'))
1464
1464
1465 # determine number of revs in DAG
1465 # determine number of revs in DAG
1466 total = 0
1466 total = 0
1467 for type, data in dagparser.parsedag(text):
1467 for type, data in dagparser.parsedag(text):
1468 if type == 'n':
1468 if type == 'n':
1469 total += 1
1469 total += 1
1470
1470
1471 if mergeable_file:
1471 if mergeable_file:
1472 linesperrev = 2
1472 linesperrev = 2
1473 # make a file with k lines per rev
1473 # make a file with k lines per rev
1474 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1474 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1475 initialmergedlines.append("")
1475 initialmergedlines.append("")
1476
1476
1477 tags = []
1477 tags = []
1478
1478
1479 lock = tr = None
1479 lock = tr = None
1480 try:
1480 try:
1481 lock = repo.lock()
1481 lock = repo.lock()
1482 tr = repo.transaction("builddag")
1482 tr = repo.transaction("builddag")
1483
1483
1484 at = -1
1484 at = -1
1485 atbranch = 'default'
1485 atbranch = 'default'
1486 nodeids = []
1486 nodeids = []
1487 id = 0
1487 id = 0
1488 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1488 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1489 for type, data in dagparser.parsedag(text):
1489 for type, data in dagparser.parsedag(text):
1490 if type == 'n':
1490 if type == 'n':
1491 ui.note('node %s\n' % str(data))
1491 ui.note('node %s\n' % str(data))
1492 id, ps = data
1492 id, ps = data
1493
1493
1494 files = []
1494 files = []
1495 fctxs = {}
1495 fctxs = {}
1496
1496
1497 p2 = None
1497 p2 = None
1498 if mergeable_file:
1498 if mergeable_file:
1499 fn = "mf"
1499 fn = "mf"
1500 p1 = repo[ps[0]]
1500 p1 = repo[ps[0]]
1501 if len(ps) > 1:
1501 if len(ps) > 1:
1502 p2 = repo[ps[1]]
1502 p2 = repo[ps[1]]
1503 pa = p1.ancestor(p2)
1503 pa = p1.ancestor(p2)
1504 base, local, other = [x[fn].data() for x in pa, p1, p2]
1504 base, local, other = [x[fn].data() for x in pa, p1, p2]
1505 m3 = simplemerge.Merge3Text(base, local, other)
1505 m3 = simplemerge.Merge3Text(base, local, other)
1506 ml = [l.strip() for l in m3.merge_lines()]
1506 ml = [l.strip() for l in m3.merge_lines()]
1507 ml.append("")
1507 ml.append("")
1508 elif at > 0:
1508 elif at > 0:
1509 ml = p1[fn].data().split("\n")
1509 ml = p1[fn].data().split("\n")
1510 else:
1510 else:
1511 ml = initialmergedlines
1511 ml = initialmergedlines
1512 ml[id * linesperrev] += " r%i" % id
1512 ml[id * linesperrev] += " r%i" % id
1513 mergedtext = "\n".join(ml)
1513 mergedtext = "\n".join(ml)
1514 files.append(fn)
1514 files.append(fn)
1515 fctxs[fn] = context.memfilectx(fn, mergedtext)
1515 fctxs[fn] = context.memfilectx(fn, mergedtext)
1516
1516
1517 if overwritten_file:
1517 if overwritten_file:
1518 fn = "of"
1518 fn = "of"
1519 files.append(fn)
1519 files.append(fn)
1520 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1520 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1521
1521
1522 if new_file:
1522 if new_file:
1523 fn = "nf%i" % id
1523 fn = "nf%i" % id
1524 files.append(fn)
1524 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1526 if len(ps) > 1:
1526 if len(ps) > 1:
1527 if not p2:
1527 if not p2:
1528 p2 = repo[ps[1]]
1528 p2 = repo[ps[1]]
1529 for fn in p2:
1529 for fn in p2:
1530 if fn.startswith("nf"):
1530 if fn.startswith("nf"):
1531 files.append(fn)
1531 files.append(fn)
1532 fctxs[fn] = p2[fn]
1532 fctxs[fn] = p2[fn]
1533
1533
1534 def fctxfn(repo, cx, path):
1534 def fctxfn(repo, cx, path):
1535 return fctxs.get(path)
1535 return fctxs.get(path)
1536
1536
1537 if len(ps) == 0 or ps[0] < 0:
1537 if len(ps) == 0 or ps[0] < 0:
1538 pars = [None, None]
1538 pars = [None, None]
1539 elif len(ps) == 1:
1539 elif len(ps) == 1:
1540 pars = [nodeids[ps[0]], None]
1540 pars = [nodeids[ps[0]], None]
1541 else:
1541 else:
1542 pars = [nodeids[p] for p in ps]
1542 pars = [nodeids[p] for p in ps]
1543 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1543 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1544 date=(id, 0),
1544 date=(id, 0),
1545 user="debugbuilddag",
1545 user="debugbuilddag",
1546 extra={'branch': atbranch})
1546 extra={'branch': atbranch})
1547 nodeid = repo.commitctx(cx)
1547 nodeid = repo.commitctx(cx)
1548 nodeids.append(nodeid)
1548 nodeids.append(nodeid)
1549 at = id
1549 at = id
1550 elif type == 'l':
1550 elif type == 'l':
1551 id, name = data
1551 id, name = data
1552 ui.note('tag %s\n' % name)
1552 ui.note('tag %s\n' % name)
1553 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1553 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1554 elif type == 'a':
1554 elif type == 'a':
1555 ui.note('branch %s\n' % data)
1555 ui.note('branch %s\n' % data)
1556 atbranch = data
1556 atbranch = data
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1558 tr.close()
1558 tr.close()
1559
1559
1560 if tags:
1560 if tags:
1561 repo.opener.write("localtags", "".join(tags))
1561 repo.opener.write("localtags", "".join(tags))
1562 finally:
1562 finally:
1563 ui.progress(_('building'), None)
1563 ui.progress(_('building'), None)
1564 release(tr, lock)
1564 release(tr, lock)
1565
1565
1566 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1566 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1567 def debugbundle(ui, bundlepath, all=None, **opts):
1567 def debugbundle(ui, bundlepath, all=None, **opts):
1568 """lists the contents of a bundle"""
1568 """lists the contents of a bundle"""
1569 f = url.open(ui, bundlepath)
1569 f = url.open(ui, bundlepath)
1570 try:
1570 try:
1571 gen = changegroup.readbundle(f, bundlepath)
1571 gen = changegroup.readbundle(f, bundlepath)
1572 if all:
1572 if all:
1573 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1573 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1574
1574
1575 def showchunks(named):
1575 def showchunks(named):
1576 ui.write("\n%s\n" % named)
1576 ui.write("\n%s\n" % named)
1577 chain = None
1577 chain = None
1578 while True:
1578 while True:
1579 chunkdata = gen.deltachunk(chain)
1579 chunkdata = gen.deltachunk(chain)
1580 if not chunkdata:
1580 if not chunkdata:
1581 break
1581 break
1582 node = chunkdata['node']
1582 node = chunkdata['node']
1583 p1 = chunkdata['p1']
1583 p1 = chunkdata['p1']
1584 p2 = chunkdata['p2']
1584 p2 = chunkdata['p2']
1585 cs = chunkdata['cs']
1585 cs = chunkdata['cs']
1586 deltabase = chunkdata['deltabase']
1586 deltabase = chunkdata['deltabase']
1587 delta = chunkdata['delta']
1587 delta = chunkdata['delta']
1588 ui.write("%s %s %s %s %s %s\n" %
1588 ui.write("%s %s %s %s %s %s\n" %
1589 (hex(node), hex(p1), hex(p2),
1589 (hex(node), hex(p1), hex(p2),
1590 hex(cs), hex(deltabase), len(delta)))
1590 hex(cs), hex(deltabase), len(delta)))
1591 chain = node
1591 chain = node
1592
1592
1593 chunkdata = gen.changelogheader()
1593 chunkdata = gen.changelogheader()
1594 showchunks("changelog")
1594 showchunks("changelog")
1595 chunkdata = gen.manifestheader()
1595 chunkdata = gen.manifestheader()
1596 showchunks("manifest")
1596 showchunks("manifest")
1597 while True:
1597 while True:
1598 chunkdata = gen.filelogheader()
1598 chunkdata = gen.filelogheader()
1599 if not chunkdata:
1599 if not chunkdata:
1600 break
1600 break
1601 fname = chunkdata['filename']
1601 fname = chunkdata['filename']
1602 showchunks(fname)
1602 showchunks(fname)
1603 else:
1603 else:
1604 chunkdata = gen.changelogheader()
1604 chunkdata = gen.changelogheader()
1605 chain = None
1605 chain = None
1606 while True:
1606 while True:
1607 chunkdata = gen.deltachunk(chain)
1607 chunkdata = gen.deltachunk(chain)
1608 if not chunkdata:
1608 if not chunkdata:
1609 break
1609 break
1610 node = chunkdata['node']
1610 node = chunkdata['node']
1611 ui.write("%s\n" % hex(node))
1611 ui.write("%s\n" % hex(node))
1612 chain = node
1612 chain = node
1613 finally:
1613 finally:
1614 f.close()
1614 f.close()
1615
1615
1616 @command('debugcheckstate', [], '')
1616 @command('debugcheckstate', [], '')
1617 def debugcheckstate(ui, repo):
1617 def debugcheckstate(ui, repo):
1618 """validate the correctness of the current dirstate"""
1618 """validate the correctness of the current dirstate"""
1619 parent1, parent2 = repo.dirstate.parents()
1619 parent1, parent2 = repo.dirstate.parents()
1620 m1 = repo[parent1].manifest()
1620 m1 = repo[parent1].manifest()
1621 m2 = repo[parent2].manifest()
1621 m2 = repo[parent2].manifest()
1622 errors = 0
1622 errors = 0
1623 for f in repo.dirstate:
1623 for f in repo.dirstate:
1624 state = repo.dirstate[f]
1624 state = repo.dirstate[f]
1625 if state in "nr" and f not in m1:
1625 if state in "nr" and f not in m1:
1626 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1626 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1627 errors += 1
1627 errors += 1
1628 if state in "a" and f in m1:
1628 if state in "a" and f in m1:
1629 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1629 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1630 errors += 1
1630 errors += 1
1631 if state in "m" and f not in m1 and f not in m2:
1631 if state in "m" and f not in m1 and f not in m2:
1632 ui.warn(_("%s in state %s, but not in either manifest\n") %
1632 ui.warn(_("%s in state %s, but not in either manifest\n") %
1633 (f, state))
1633 (f, state))
1634 errors += 1
1634 errors += 1
1635 for f in m1:
1635 for f in m1:
1636 state = repo.dirstate[f]
1636 state = repo.dirstate[f]
1637 if state not in "nrm":
1637 if state not in "nrm":
1638 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1638 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1639 errors += 1
1639 errors += 1
1640 if errors:
1640 if errors:
1641 error = _(".hg/dirstate inconsistent with current parent's manifest")
1641 error = _(".hg/dirstate inconsistent with current parent's manifest")
1642 raise util.Abort(error)
1642 raise util.Abort(error)
1643
1643
1644 @command('debugcommands', [], _('[COMMAND]'))
1644 @command('debugcommands', [], _('[COMMAND]'))
1645 def debugcommands(ui, cmd='', *args):
1645 def debugcommands(ui, cmd='', *args):
1646 """list all available commands and options"""
1646 """list all available commands and options"""
1647 for cmd, vals in sorted(table.iteritems()):
1647 for cmd, vals in sorted(table.iteritems()):
1648 cmd = cmd.split('|')[0].strip('^')
1648 cmd = cmd.split('|')[0].strip('^')
1649 opts = ', '.join([i[1] for i in vals[1]])
1649 opts = ', '.join([i[1] for i in vals[1]])
1650 ui.write('%s: %s\n' % (cmd, opts))
1650 ui.write('%s: %s\n' % (cmd, opts))
1651
1651
1652 @command('debugcomplete',
1652 @command('debugcomplete',
1653 [('o', 'options', None, _('show the command options'))],
1653 [('o', 'options', None, _('show the command options'))],
1654 _('[-o] CMD'))
1654 _('[-o] CMD'))
1655 def debugcomplete(ui, cmd='', **opts):
1655 def debugcomplete(ui, cmd='', **opts):
1656 """returns the completion list associated with the given command"""
1656 """returns the completion list associated with the given command"""
1657
1657
1658 if opts.get('options'):
1658 if opts.get('options'):
1659 options = []
1659 options = []
1660 otables = [globalopts]
1660 otables = [globalopts]
1661 if cmd:
1661 if cmd:
1662 aliases, entry = cmdutil.findcmd(cmd, table, False)
1662 aliases, entry = cmdutil.findcmd(cmd, table, False)
1663 otables.append(entry[1])
1663 otables.append(entry[1])
1664 for t in otables:
1664 for t in otables:
1665 for o in t:
1665 for o in t:
1666 if "(DEPRECATED)" in o[3]:
1666 if "(DEPRECATED)" in o[3]:
1667 continue
1667 continue
1668 if o[0]:
1668 if o[0]:
1669 options.append('-%s' % o[0])
1669 options.append('-%s' % o[0])
1670 options.append('--%s' % o[1])
1670 options.append('--%s' % o[1])
1671 ui.write("%s\n" % "\n".join(options))
1671 ui.write("%s\n" % "\n".join(options))
1672 return
1672 return
1673
1673
1674 cmdlist = cmdutil.findpossible(cmd, table)
1674 cmdlist = cmdutil.findpossible(cmd, table)
1675 if ui.verbose:
1675 if ui.verbose:
1676 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1676 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1677 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1677 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1678
1678
1679 @command('debugdag',
1679 @command('debugdag',
1680 [('t', 'tags', None, _('use tags as labels')),
1680 [('t', 'tags', None, _('use tags as labels')),
1681 ('b', 'branches', None, _('annotate with branch names')),
1681 ('b', 'branches', None, _('annotate with branch names')),
1682 ('', 'dots', None, _('use dots for runs')),
1682 ('', 'dots', None, _('use dots for runs')),
1683 ('s', 'spaces', None, _('separate elements by spaces'))],
1683 ('s', 'spaces', None, _('separate elements by spaces'))],
1684 _('[OPTION]... [FILE [REV]...]'))
1684 _('[OPTION]... [FILE [REV]...]'))
1685 def debugdag(ui, repo, file_=None, *revs, **opts):
1685 def debugdag(ui, repo, file_=None, *revs, **opts):
1686 """format the changelog or an index DAG as a concise textual description
1686 """format the changelog or an index DAG as a concise textual description
1687
1687
1688 If you pass a revlog index, the revlog's DAG is emitted. If you list
1688 If you pass a revlog index, the revlog's DAG is emitted. If you list
1689 revision numbers, they get labelled in the output as rN.
1689 revision numbers, they get labelled in the output as rN.
1690
1690
1691 Otherwise, the changelog DAG of the current repo is emitted.
1691 Otherwise, the changelog DAG of the current repo is emitted.
1692 """
1692 """
1693 spaces = opts.get('spaces')
1693 spaces = opts.get('spaces')
1694 dots = opts.get('dots')
1694 dots = opts.get('dots')
1695 if file_:
1695 if file_:
1696 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1696 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1697 revs = set((int(r) for r in revs))
1697 revs = set((int(r) for r in revs))
1698 def events():
1698 def events():
1699 for r in rlog:
1699 for r in rlog:
1700 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1700 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1701 if p != -1)))
1701 if p != -1)))
1702 if r in revs:
1702 if r in revs:
1703 yield 'l', (r, "r%i" % r)
1703 yield 'l', (r, "r%i" % r)
1704 elif repo:
1704 elif repo:
1705 cl = repo.changelog
1705 cl = repo.changelog
1706 tags = opts.get('tags')
1706 tags = opts.get('tags')
1707 branches = opts.get('branches')
1707 branches = opts.get('branches')
1708 if tags:
1708 if tags:
1709 labels = {}
1709 labels = {}
1710 for l, n in repo.tags().items():
1710 for l, n in repo.tags().items():
1711 labels.setdefault(cl.rev(n), []).append(l)
1711 labels.setdefault(cl.rev(n), []).append(l)
1712 def events():
1712 def events():
1713 b = "default"
1713 b = "default"
1714 for r in cl:
1714 for r in cl:
1715 if branches:
1715 if branches:
1716 newb = cl.read(cl.node(r))[5]['branch']
1716 newb = cl.read(cl.node(r))[5]['branch']
1717 if newb != b:
1717 if newb != b:
1718 yield 'a', newb
1718 yield 'a', newb
1719 b = newb
1719 b = newb
1720 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1720 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1721 if p != -1)))
1721 if p != -1)))
1722 if tags:
1722 if tags:
1723 ls = labels.get(r)
1723 ls = labels.get(r)
1724 if ls:
1724 if ls:
1725 for l in ls:
1725 for l in ls:
1726 yield 'l', (r, l)
1726 yield 'l', (r, l)
1727 else:
1727 else:
1728 raise util.Abort(_('need repo for changelog dag'))
1728 raise util.Abort(_('need repo for changelog dag'))
1729
1729
1730 for line in dagparser.dagtextlines(events(),
1730 for line in dagparser.dagtextlines(events(),
1731 addspaces=spaces,
1731 addspaces=spaces,
1732 wraplabels=True,
1732 wraplabels=True,
1733 wrapannotations=True,
1733 wrapannotations=True,
1734 wrapnonlinear=dots,
1734 wrapnonlinear=dots,
1735 usedots=dots,
1735 usedots=dots,
1736 maxlinewidth=70):
1736 maxlinewidth=70):
1737 ui.write(line)
1737 ui.write(line)
1738 ui.write("\n")
1738 ui.write("\n")
1739
1739
1740 @command('debugdata',
1740 @command('debugdata',
1741 [('c', 'changelog', False, _('open changelog')),
1741 [('c', 'changelog', False, _('open changelog')),
1742 ('m', 'manifest', False, _('open manifest'))],
1742 ('m', 'manifest', False, _('open manifest'))],
1743 _('-c|-m|FILE REV'))
1743 _('-c|-m|FILE REV'))
1744 def debugdata(ui, repo, file_, rev = None, **opts):
1744 def debugdata(ui, repo, file_, rev = None, **opts):
1745 """dump the contents of a data file revision"""
1745 """dump the contents of a data file revision"""
1746 if opts.get('changelog') or opts.get('manifest'):
1746 if opts.get('changelog') or opts.get('manifest'):
1747 file_, rev = None, file_
1747 file_, rev = None, file_
1748 elif rev is None:
1748 elif rev is None:
1749 raise error.CommandError('debugdata', _('invalid arguments'))
1749 raise error.CommandError('debugdata', _('invalid arguments'))
1750 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1750 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1751 try:
1751 try:
1752 ui.write(r.revision(r.lookup(rev)))
1752 ui.write(r.revision(r.lookup(rev)))
1753 except KeyError:
1753 except KeyError:
1754 raise util.Abort(_('invalid revision identifier %s') % rev)
1754 raise util.Abort(_('invalid revision identifier %s') % rev)
1755
1755
1756 @command('debugdate',
1756 @command('debugdate',
1757 [('e', 'extended', None, _('try extended date formats'))],
1757 [('e', 'extended', None, _('try extended date formats'))],
1758 _('[-e] DATE [RANGE]'))
1758 _('[-e] DATE [RANGE]'))
1759 def debugdate(ui, date, range=None, **opts):
1759 def debugdate(ui, date, range=None, **opts):
1760 """parse and display a date"""
1760 """parse and display a date"""
1761 if opts["extended"]:
1761 if opts["extended"]:
1762 d = util.parsedate(date, util.extendeddateformats)
1762 d = util.parsedate(date, util.extendeddateformats)
1763 else:
1763 else:
1764 d = util.parsedate(date)
1764 d = util.parsedate(date)
1765 ui.write("internal: %s %s\n" % d)
1765 ui.write("internal: %s %s\n" % d)
1766 ui.write("standard: %s\n" % util.datestr(d))
1766 ui.write("standard: %s\n" % util.datestr(d))
1767 if range:
1767 if range:
1768 m = util.matchdate(range)
1768 m = util.matchdate(range)
1769 ui.write("match: %s\n" % m(d[0]))
1769 ui.write("match: %s\n" % m(d[0]))
1770
1770
1771 @command('debugdiscovery',
1771 @command('debugdiscovery',
1772 [('', 'old', None, _('use old-style discovery')),
1772 [('', 'old', None, _('use old-style discovery')),
1773 ('', 'nonheads', None,
1773 ('', 'nonheads', None,
1774 _('use old-style discovery with non-heads included')),
1774 _('use old-style discovery with non-heads included')),
1775 ] + remoteopts,
1775 ] + remoteopts,
1776 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1776 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1777 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1777 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1778 """runs the changeset discovery protocol in isolation"""
1778 """runs the changeset discovery protocol in isolation"""
1779 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1779 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1780 opts.get('branch'))
1780 opts.get('branch'))
1781 remote = hg.peer(repo, opts, remoteurl)
1781 remote = hg.peer(repo, opts, remoteurl)
1782 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1782 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1783
1783
1784 # make sure tests are repeatable
1784 # make sure tests are repeatable
1785 random.seed(12323)
1785 random.seed(12323)
1786
1786
1787 def doit(localheads, remoteheads, remote=remote):
1787 def doit(localheads, remoteheads, remote=remote):
1788 if opts.get('old'):
1788 if opts.get('old'):
1789 if localheads:
1789 if localheads:
1790 raise util.Abort('cannot use localheads with old style '
1790 raise util.Abort('cannot use localheads with old style '
1791 'discovery')
1791 'discovery')
1792 if not util.safehasattr(remote, 'branches'):
1792 if not util.safehasattr(remote, 'branches'):
1793 # enable in-client legacy support
1793 # enable in-client legacy support
1794 remote = localrepo.locallegacypeer(remote.local())
1794 remote = localrepo.locallegacypeer(remote.local())
1795 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1795 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1796 force=True)
1796 force=True)
1797 common = set(common)
1797 common = set(common)
1798 if not opts.get('nonheads'):
1798 if not opts.get('nonheads'):
1799 ui.write("unpruned common: %s\n" % " ".join([short(n)
1799 ui.write("unpruned common: %s\n" % " ".join([short(n)
1800 for n in common]))
1800 for n in common]))
1801 dag = dagutil.revlogdag(repo.changelog)
1801 dag = dagutil.revlogdag(repo.changelog)
1802 all = dag.ancestorset(dag.internalizeall(common))
1802 all = dag.ancestorset(dag.internalizeall(common))
1803 common = dag.externalizeall(dag.headsetofconnecteds(all))
1803 common = dag.externalizeall(dag.headsetofconnecteds(all))
1804 else:
1804 else:
1805 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1805 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1806 common = set(common)
1806 common = set(common)
1807 rheads = set(hds)
1807 rheads = set(hds)
1808 lheads = set(repo.heads())
1808 lheads = set(repo.heads())
1809 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1809 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1810 if lheads <= common:
1810 if lheads <= common:
1811 ui.write("local is subset\n")
1811 ui.write("local is subset\n")
1812 elif rheads <= common:
1812 elif rheads <= common:
1813 ui.write("remote is subset\n")
1813 ui.write("remote is subset\n")
1814
1814
1815 serverlogs = opts.get('serverlog')
1815 serverlogs = opts.get('serverlog')
1816 if serverlogs:
1816 if serverlogs:
1817 for filename in serverlogs:
1817 for filename in serverlogs:
1818 logfile = open(filename, 'r')
1818 logfile = open(filename, 'r')
1819 try:
1819 try:
1820 line = logfile.readline()
1820 line = logfile.readline()
1821 while line:
1821 while line:
1822 parts = line.strip().split(';')
1822 parts = line.strip().split(';')
1823 op = parts[1]
1823 op = parts[1]
1824 if op == 'cg':
1824 if op == 'cg':
1825 pass
1825 pass
1826 elif op == 'cgss':
1826 elif op == 'cgss':
1827 doit(parts[2].split(' '), parts[3].split(' '))
1827 doit(parts[2].split(' '), parts[3].split(' '))
1828 elif op == 'unb':
1828 elif op == 'unb':
1829 doit(parts[3].split(' '), parts[2].split(' '))
1829 doit(parts[3].split(' '), parts[2].split(' '))
1830 line = logfile.readline()
1830 line = logfile.readline()
1831 finally:
1831 finally:
1832 logfile.close()
1832 logfile.close()
1833
1833
1834 else:
1834 else:
1835 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1835 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1836 opts.get('remote_head'))
1836 opts.get('remote_head'))
1837 localrevs = opts.get('local_head')
1837 localrevs = opts.get('local_head')
1838 doit(localrevs, remoterevs)
1838 doit(localrevs, remoterevs)
1839
1839
1840 @command('debugfileset', [], ('REVSPEC'))
1840 @command('debugfileset', [], ('REVSPEC'))
1841 def debugfileset(ui, repo, expr):
1841 def debugfileset(ui, repo, expr):
1842 '''parse and apply a fileset specification'''
1842 '''parse and apply a fileset specification'''
1843 if ui.verbose:
1843 if ui.verbose:
1844 tree = fileset.parse(expr)[0]
1844 tree = fileset.parse(expr)[0]
1845 ui.note(tree, "\n")
1845 ui.note(tree, "\n")
1846
1846
1847 for f in fileset.getfileset(repo[None], expr):
1847 for f in fileset.getfileset(repo[None], expr):
1848 ui.write("%s\n" % f)
1848 ui.write("%s\n" % f)
1849
1849
1850 @command('debugfsinfo', [], _('[PATH]'))
1850 @command('debugfsinfo', [], _('[PATH]'))
1851 def debugfsinfo(ui, path = "."):
1851 def debugfsinfo(ui, path = "."):
1852 """show information detected about current filesystem"""
1852 """show information detected about current filesystem"""
1853 util.writefile('.debugfsinfo', '')
1853 util.writefile('.debugfsinfo', '')
1854 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1854 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1855 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1855 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1856 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1856 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1857 and 'yes' or 'no'))
1857 and 'yes' or 'no'))
1858 os.unlink('.debugfsinfo')
1858 os.unlink('.debugfsinfo')
1859
1859
1860 @command('debuggetbundle',
1860 @command('debuggetbundle',
1861 [('H', 'head', [], _('id of head node'), _('ID')),
1861 [('H', 'head', [], _('id of head node'), _('ID')),
1862 ('C', 'common', [], _('id of common node'), _('ID')),
1862 ('C', 'common', [], _('id of common node'), _('ID')),
1863 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1863 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1864 _('REPO FILE [-H|-C ID]...'))
1864 _('REPO FILE [-H|-C ID]...'))
1865 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1865 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1866 """retrieves a bundle from a repo
1866 """retrieves a bundle from a repo
1867
1867
1868 Every ID must be a full-length hex node id string. Saves the bundle to the
1868 Every ID must be a full-length hex node id string. Saves the bundle to the
1869 given file.
1869 given file.
1870 """
1870 """
1871 repo = hg.peer(ui, opts, repopath)
1871 repo = hg.peer(ui, opts, repopath)
1872 if not repo.capable('getbundle'):
1872 if not repo.capable('getbundle'):
1873 raise util.Abort("getbundle() not supported by target repository")
1873 raise util.Abort("getbundle() not supported by target repository")
1874 args = {}
1874 args = {}
1875 if common:
1875 if common:
1876 args['common'] = [bin(s) for s in common]
1876 args['common'] = [bin(s) for s in common]
1877 if head:
1877 if head:
1878 args['heads'] = [bin(s) for s in head]
1878 args['heads'] = [bin(s) for s in head]
1879 bundle = repo.getbundle('debug', **args)
1879 bundle = repo.getbundle('debug', **args)
1880
1880
1881 bundletype = opts.get('type', 'bzip2').lower()
1881 bundletype = opts.get('type', 'bzip2').lower()
1882 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1882 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1883 bundletype = btypes.get(bundletype)
1883 bundletype = btypes.get(bundletype)
1884 if bundletype not in changegroup.bundletypes:
1884 if bundletype not in changegroup.bundletypes:
1885 raise util.Abort(_('unknown bundle type specified with --type'))
1885 raise util.Abort(_('unknown bundle type specified with --type'))
1886 changegroup.writebundle(bundle, bundlepath, bundletype)
1886 changegroup.writebundle(bundle, bundlepath, bundletype)
1887
1887
1888 @command('debugignore', [], '')
1888 @command('debugignore', [], '')
1889 def debugignore(ui, repo, *values, **opts):
1889 def debugignore(ui, repo, *values, **opts):
1890 """display the combined ignore pattern"""
1890 """display the combined ignore pattern"""
1891 ignore = repo.dirstate._ignore
1891 ignore = repo.dirstate._ignore
1892 includepat = getattr(ignore, 'includepat', None)
1892 includepat = getattr(ignore, 'includepat', None)
1893 if includepat is not None:
1893 if includepat is not None:
1894 ui.write("%s\n" % includepat)
1894 ui.write("%s\n" % includepat)
1895 else:
1895 else:
1896 raise util.Abort(_("no ignore patterns found"))
1896 raise util.Abort(_("no ignore patterns found"))
1897
1897
1898 @command('debugindex',
1898 @command('debugindex',
1899 [('c', 'changelog', False, _('open changelog')),
1899 [('c', 'changelog', False, _('open changelog')),
1900 ('m', 'manifest', False, _('open manifest')),
1900 ('m', 'manifest', False, _('open manifest')),
1901 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1901 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1902 _('[-f FORMAT] -c|-m|FILE'))
1902 _('[-f FORMAT] -c|-m|FILE'))
1903 def debugindex(ui, repo, file_ = None, **opts):
1903 def debugindex(ui, repo, file_ = None, **opts):
1904 """dump the contents of an index file"""
1904 """dump the contents of an index file"""
1905 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1905 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1906 format = opts.get('format', 0)
1906 format = opts.get('format', 0)
1907 if format not in (0, 1):
1907 if format not in (0, 1):
1908 raise util.Abort(_("unknown format %d") % format)
1908 raise util.Abort(_("unknown format %d") % format)
1909
1909
1910 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1910 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1911 if generaldelta:
1911 if generaldelta:
1912 basehdr = ' delta'
1912 basehdr = ' delta'
1913 else:
1913 else:
1914 basehdr = ' base'
1914 basehdr = ' base'
1915
1915
1916 if format == 0:
1916 if format == 0:
1917 ui.write(" rev offset length " + basehdr + " linkrev"
1917 ui.write(" rev offset length " + basehdr + " linkrev"
1918 " nodeid p1 p2\n")
1918 " nodeid p1 p2\n")
1919 elif format == 1:
1919 elif format == 1:
1920 ui.write(" rev flag offset length"
1920 ui.write(" rev flag offset length"
1921 " size " + basehdr + " link p1 p2"
1921 " size " + basehdr + " link p1 p2"
1922 " nodeid\n")
1922 " nodeid\n")
1923
1923
1924 for i in r:
1924 for i in r:
1925 node = r.node(i)
1925 node = r.node(i)
1926 if generaldelta:
1926 if generaldelta:
1927 base = r.deltaparent(i)
1927 base = r.deltaparent(i)
1928 else:
1928 else:
1929 base = r.chainbase(i)
1929 base = r.chainbase(i)
1930 if format == 0:
1930 if format == 0:
1931 try:
1931 try:
1932 pp = r.parents(node)
1932 pp = r.parents(node)
1933 except Exception:
1933 except Exception:
1934 pp = [nullid, nullid]
1934 pp = [nullid, nullid]
1935 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1935 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1936 i, r.start(i), r.length(i), base, r.linkrev(i),
1936 i, r.start(i), r.length(i), base, r.linkrev(i),
1937 short(node), short(pp[0]), short(pp[1])))
1937 short(node), short(pp[0]), short(pp[1])))
1938 elif format == 1:
1938 elif format == 1:
1939 pr = r.parentrevs(i)
1939 pr = r.parentrevs(i)
1940 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1940 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1941 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1941 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1942 base, r.linkrev(i), pr[0], pr[1], short(node)))
1942 base, r.linkrev(i), pr[0], pr[1], short(node)))
1943
1943
1944 @command('debugindexdot', [], _('FILE'))
1944 @command('debugindexdot', [], _('FILE'))
1945 def debugindexdot(ui, repo, file_):
1945 def debugindexdot(ui, repo, file_):
1946 """dump an index DAG as a graphviz dot file"""
1946 """dump an index DAG as a graphviz dot file"""
1947 r = None
1947 r = None
1948 if repo:
1948 if repo:
1949 filelog = repo.file(file_)
1949 filelog = repo.file(file_)
1950 if len(filelog):
1950 if len(filelog):
1951 r = filelog
1951 r = filelog
1952 if not r:
1952 if not r:
1953 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1953 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1954 ui.write("digraph G {\n")
1954 ui.write("digraph G {\n")
1955 for i in r:
1955 for i in r:
1956 node = r.node(i)
1956 node = r.node(i)
1957 pp = r.parents(node)
1957 pp = r.parents(node)
1958 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1958 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1959 if pp[1] != nullid:
1959 if pp[1] != nullid:
1960 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1960 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1961 ui.write("}\n")
1961 ui.write("}\n")
1962
1962
1963 @command('debuginstall', [], '')
1963 @command('debuginstall', [], '')
1964 def debuginstall(ui):
1964 def debuginstall(ui):
1965 '''test Mercurial installation
1965 '''test Mercurial installation
1966
1966
1967 Returns 0 on success.
1967 Returns 0 on success.
1968 '''
1968 '''
1969
1969
1970 def writetemp(contents):
1970 def writetemp(contents):
1971 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1971 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1972 f = os.fdopen(fd, "wb")
1972 f = os.fdopen(fd, "wb")
1973 f.write(contents)
1973 f.write(contents)
1974 f.close()
1974 f.close()
1975 return name
1975 return name
1976
1976
1977 problems = 0
1977 problems = 0
1978
1978
1979 # encoding
1979 # encoding
1980 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1980 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1981 try:
1981 try:
1982 encoding.fromlocal("test")
1982 encoding.fromlocal("test")
1983 except util.Abort, inst:
1983 except util.Abort, inst:
1984 ui.write(" %s\n" % inst)
1984 ui.write(" %s\n" % inst)
1985 ui.write(_(" (check that your locale is properly set)\n"))
1985 ui.write(_(" (check that your locale is properly set)\n"))
1986 problems += 1
1986 problems += 1
1987
1987
1988 # compiled modules
1988 # compiled modules
1989 ui.status(_("checking installed modules (%s)...\n")
1989 ui.status(_("checking installed modules (%s)...\n")
1990 % os.path.dirname(__file__))
1990 % os.path.dirname(__file__))
1991 try:
1991 try:
1992 import bdiff, mpatch, base85, osutil
1992 import bdiff, mpatch, base85, osutil
1993 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1993 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1994 except Exception, inst:
1994 except Exception, inst:
1995 ui.write(" %s\n" % inst)
1995 ui.write(" %s\n" % inst)
1996 ui.write(_(" One or more extensions could not be found"))
1996 ui.write(_(" One or more extensions could not be found"))
1997 ui.write(_(" (check that you compiled the extensions)\n"))
1997 ui.write(_(" (check that you compiled the extensions)\n"))
1998 problems += 1
1998 problems += 1
1999
1999
2000 # templates
2000 # templates
2001 import templater
2001 import templater
2002 p = templater.templatepath()
2002 p = templater.templatepath()
2003 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2003 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2004 try:
2004 try:
2005 templater.templater(templater.templatepath("map-cmdline.default"))
2005 templater.templater(templater.templatepath("map-cmdline.default"))
2006 except Exception, inst:
2006 except Exception, inst:
2007 ui.write(" %s\n" % inst)
2007 ui.write(" %s\n" % inst)
2008 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2008 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2009 problems += 1
2009 problems += 1
2010
2010
2011 # editor
2011 # editor
2012 ui.status(_("checking commit editor...\n"))
2012 ui.status(_("checking commit editor...\n"))
2013 editor = ui.geteditor()
2013 editor = ui.geteditor()
2014 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2014 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2015 if not cmdpath:
2015 if not cmdpath:
2016 if editor == 'vi':
2016 if editor == 'vi':
2017 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2017 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2018 ui.write(_(" (specify a commit editor in your configuration"
2018 ui.write(_(" (specify a commit editor in your configuration"
2019 " file)\n"))
2019 " file)\n"))
2020 else:
2020 else:
2021 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2021 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2022 ui.write(_(" (specify a commit editor in your configuration"
2022 ui.write(_(" (specify a commit editor in your configuration"
2023 " file)\n"))
2023 " file)\n"))
2024 problems += 1
2024 problems += 1
2025
2025
2026 # check username
2026 # check username
2027 ui.status(_("checking username...\n"))
2027 ui.status(_("checking username...\n"))
2028 try:
2028 try:
2029 ui.username()
2029 ui.username()
2030 except util.Abort, e:
2030 except util.Abort, e:
2031 ui.write(" %s\n" % e)
2031 ui.write(" %s\n" % e)
2032 ui.write(_(" (specify a username in your configuration file)\n"))
2032 ui.write(_(" (specify a username in your configuration file)\n"))
2033 problems += 1
2033 problems += 1
2034
2034
2035 if not problems:
2035 if not problems:
2036 ui.status(_("no problems detected\n"))
2036 ui.status(_("no problems detected\n"))
2037 else:
2037 else:
2038 ui.write(_("%s problems detected,"
2038 ui.write(_("%s problems detected,"
2039 " please check your install!\n") % problems)
2039 " please check your install!\n") % problems)
2040
2040
2041 return problems
2041 return problems
2042
2042
2043 @command('debugknown', [], _('REPO ID...'))
2043 @command('debugknown', [], _('REPO ID...'))
2044 def debugknown(ui, repopath, *ids, **opts):
2044 def debugknown(ui, repopath, *ids, **opts):
2045 """test whether node ids are known to a repo
2045 """test whether node ids are known to a repo
2046
2046
2047 Every ID must be a full-length hex node id string. Returns a list of 0s
2047 Every ID must be a full-length hex node id string. Returns a list of 0s
2048 and 1s indicating unknown/known.
2048 and 1s indicating unknown/known.
2049 """
2049 """
2050 repo = hg.peer(ui, opts, repopath)
2050 repo = hg.peer(ui, opts, repopath)
2051 if not repo.capable('known'):
2051 if not repo.capable('known'):
2052 raise util.Abort("known() not supported by target repository")
2052 raise util.Abort("known() not supported by target repository")
2053 flags = repo.known([bin(s) for s in ids])
2053 flags = repo.known([bin(s) for s in ids])
2054 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2054 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2055
2055
2056 @command('debugobsolete', [] + commitopts2,
2056 @command('debugobsolete', [] + commitopts2,
2057 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2057 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2058 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2058 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2059 """create arbitrary obsolete marker"""
2059 """create arbitrary obsolete marker"""
2060 if precursor is not None:
2060 if precursor is not None:
2061 metadata = {}
2061 metadata = {}
2062 if 'date' in opts:
2062 if 'date' in opts:
2063 metadata['date'] = opts['date']
2063 metadata['date'] = opts['date']
2064 metadata['user'] = opts['user'] or ui.username()
2064 metadata['user'] = opts['user'] or ui.username()
2065 succs = tuple(bin(succ) for succ in successors)
2065 succs = tuple(bin(succ) for succ in successors)
2066 l = repo.lock()
2066 l = repo.lock()
2067 try:
2067 try:
2068 tr = repo.transaction('debugobsolete')
2068 tr = repo.transaction('debugobsolete')
2069 try:
2069 try:
2070 repo.obsstore.create(tr, bin(precursor), succs, 0, metadata)
2070 repo.obsstore.create(tr, bin(precursor), succs, 0, metadata)
2071 tr.close()
2071 tr.close()
2072 finally:
2072 finally:
2073 tr.release()
2073 tr.release()
2074 finally:
2074 finally:
2075 l.release()
2075 l.release()
2076 else:
2076 else:
2077 for m in obsolete.allmarkers(repo):
2077 for m in obsolete.allmarkers(repo):
2078 ui.write(hex(m.precnode()))
2078 ui.write(hex(m.precnode()))
2079 for repl in m.succnodes():
2079 for repl in m.succnodes():
2080 ui.write(' ')
2080 ui.write(' ')
2081 ui.write(hex(repl))
2081 ui.write(hex(repl))
2082 ui.write(' %X ' % m._data[2])
2082 ui.write(' %X ' % m._data[2])
2083 ui.write(m.metadata())
2083 ui.write(m.metadata())
2084 ui.write('\n')
2084 ui.write('\n')
2085
2085
2086 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2086 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2087 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2087 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2088 '''access the pushkey key/value protocol
2088 '''access the pushkey key/value protocol
2089
2089
2090 With two args, list the keys in the given namespace.
2090 With two args, list the keys in the given namespace.
2091
2091
2092 With five args, set a key to new if it currently is set to old.
2092 With five args, set a key to new if it currently is set to old.
2093 Reports success or failure.
2093 Reports success or failure.
2094 '''
2094 '''
2095
2095
2096 target = hg.peer(ui, {}, repopath)
2096 target = hg.peer(ui, {}, repopath)
2097 if keyinfo:
2097 if keyinfo:
2098 key, old, new = keyinfo
2098 key, old, new = keyinfo
2099 r = target.pushkey(namespace, key, old, new)
2099 r = target.pushkey(namespace, key, old, new)
2100 ui.status(str(r) + '\n')
2100 ui.status(str(r) + '\n')
2101 return not r
2101 return not r
2102 else:
2102 else:
2103 for k, v in target.listkeys(namespace).iteritems():
2103 for k, v in target.listkeys(namespace).iteritems():
2104 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2104 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2105 v.encode('string-escape')))
2105 v.encode('string-escape')))
2106
2106
2107 @command('debugpvec', [], _('A B'))
2107 @command('debugpvec', [], _('A B'))
2108 def debugpvec(ui, repo, a, b=None):
2108 def debugpvec(ui, repo, a, b=None):
2109 ca = scmutil.revsingle(repo, a)
2109 ca = scmutil.revsingle(repo, a)
2110 cb = scmutil.revsingle(repo, b)
2110 cb = scmutil.revsingle(repo, b)
2111 pa = pvec.ctxpvec(ca)
2111 pa = pvec.ctxpvec(ca)
2112 pb = pvec.ctxpvec(cb)
2112 pb = pvec.ctxpvec(cb)
2113 if pa == pb:
2113 if pa == pb:
2114 rel = "="
2114 rel = "="
2115 elif pa > pb:
2115 elif pa > pb:
2116 rel = ">"
2116 rel = ">"
2117 elif pa < pb:
2117 elif pa < pb:
2118 rel = "<"
2118 rel = "<"
2119 elif pa | pb:
2119 elif pa | pb:
2120 rel = "|"
2120 rel = "|"
2121 ui.write(_("a: %s\n") % pa)
2121 ui.write(_("a: %s\n") % pa)
2122 ui.write(_("b: %s\n") % pb)
2122 ui.write(_("b: %s\n") % pb)
2123 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2123 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2124 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2124 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2125 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2125 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2126 pa.distance(pb), rel))
2126 pa.distance(pb), rel))
2127
2127
2128 @command('debugrebuildstate',
2128 @command('debugrebuildstate',
2129 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2129 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2130 _('[-r REV] [REV]'))
2130 _('[-r REV] [REV]'))
2131 def debugrebuildstate(ui, repo, rev="tip"):
2131 def debugrebuildstate(ui, repo, rev="tip"):
2132 """rebuild the dirstate as it would look like for the given revision"""
2132 """rebuild the dirstate as it would look like for the given revision"""
2133 ctx = scmutil.revsingle(repo, rev)
2133 ctx = scmutil.revsingle(repo, rev)
2134 wlock = repo.wlock()
2134 wlock = repo.wlock()
2135 try:
2135 try:
2136 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2136 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2137 finally:
2137 finally:
2138 wlock.release()
2138 wlock.release()
2139
2139
2140 @command('debugrename',
2140 @command('debugrename',
2141 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2141 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2142 _('[-r REV] FILE'))
2142 _('[-r REV] FILE'))
2143 def debugrename(ui, repo, file1, *pats, **opts):
2143 def debugrename(ui, repo, file1, *pats, **opts):
2144 """dump rename information"""
2144 """dump rename information"""
2145
2145
2146 ctx = scmutil.revsingle(repo, opts.get('rev'))
2146 ctx = scmutil.revsingle(repo, opts.get('rev'))
2147 m = scmutil.match(ctx, (file1,) + pats, opts)
2147 m = scmutil.match(ctx, (file1,) + pats, opts)
2148 for abs in ctx.walk(m):
2148 for abs in ctx.walk(m):
2149 fctx = ctx[abs]
2149 fctx = ctx[abs]
2150 o = fctx.filelog().renamed(fctx.filenode())
2150 o = fctx.filelog().renamed(fctx.filenode())
2151 rel = m.rel(abs)
2151 rel = m.rel(abs)
2152 if o:
2152 if o:
2153 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2153 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2154 else:
2154 else:
2155 ui.write(_("%s not renamed\n") % rel)
2155 ui.write(_("%s not renamed\n") % rel)
2156
2156
2157 @command('debugrevlog',
2157 @command('debugrevlog',
2158 [('c', 'changelog', False, _('open changelog')),
2158 [('c', 'changelog', False, _('open changelog')),
2159 ('m', 'manifest', False, _('open manifest')),
2159 ('m', 'manifest', False, _('open manifest')),
2160 ('d', 'dump', False, _('dump index data'))],
2160 ('d', 'dump', False, _('dump index data'))],
2161 _('-c|-m|FILE'))
2161 _('-c|-m|FILE'))
2162 def debugrevlog(ui, repo, file_ = None, **opts):
2162 def debugrevlog(ui, repo, file_ = None, **opts):
2163 """show data and statistics about a revlog"""
2163 """show data and statistics about a revlog"""
2164 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2164 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2165
2165
2166 if opts.get("dump"):
2166 if opts.get("dump"):
2167 numrevs = len(r)
2167 numrevs = len(r)
2168 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2168 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2169 " rawsize totalsize compression heads\n")
2169 " rawsize totalsize compression heads\n")
2170 ts = 0
2170 ts = 0
2171 heads = set()
2171 heads = set()
2172 for rev in xrange(numrevs):
2172 for rev in xrange(numrevs):
2173 dbase = r.deltaparent(rev)
2173 dbase = r.deltaparent(rev)
2174 if dbase == -1:
2174 if dbase == -1:
2175 dbase = rev
2175 dbase = rev
2176 cbase = r.chainbase(rev)
2176 cbase = r.chainbase(rev)
2177 p1, p2 = r.parentrevs(rev)
2177 p1, p2 = r.parentrevs(rev)
2178 rs = r.rawsize(rev)
2178 rs = r.rawsize(rev)
2179 ts = ts + rs
2179 ts = ts + rs
2180 heads -= set(r.parentrevs(rev))
2180 heads -= set(r.parentrevs(rev))
2181 heads.add(rev)
2181 heads.add(rev)
2182 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2182 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2183 (rev, p1, p2, r.start(rev), r.end(rev),
2183 (rev, p1, p2, r.start(rev), r.end(rev),
2184 r.start(dbase), r.start(cbase),
2184 r.start(dbase), r.start(cbase),
2185 r.start(p1), r.start(p2),
2185 r.start(p1), r.start(p2),
2186 rs, ts, ts / r.end(rev), len(heads)))
2186 rs, ts, ts / r.end(rev), len(heads)))
2187 return 0
2187 return 0
2188
2188
2189 v = r.version
2189 v = r.version
2190 format = v & 0xFFFF
2190 format = v & 0xFFFF
2191 flags = []
2191 flags = []
2192 gdelta = False
2192 gdelta = False
2193 if v & revlog.REVLOGNGINLINEDATA:
2193 if v & revlog.REVLOGNGINLINEDATA:
2194 flags.append('inline')
2194 flags.append('inline')
2195 if v & revlog.REVLOGGENERALDELTA:
2195 if v & revlog.REVLOGGENERALDELTA:
2196 gdelta = True
2196 gdelta = True
2197 flags.append('generaldelta')
2197 flags.append('generaldelta')
2198 if not flags:
2198 if not flags:
2199 flags = ['(none)']
2199 flags = ['(none)']
2200
2200
2201 nummerges = 0
2201 nummerges = 0
2202 numfull = 0
2202 numfull = 0
2203 numprev = 0
2203 numprev = 0
2204 nump1 = 0
2204 nump1 = 0
2205 nump2 = 0
2205 nump2 = 0
2206 numother = 0
2206 numother = 0
2207 nump1prev = 0
2207 nump1prev = 0
2208 nump2prev = 0
2208 nump2prev = 0
2209 chainlengths = []
2209 chainlengths = []
2210
2210
2211 datasize = [None, 0, 0L]
2211 datasize = [None, 0, 0L]
2212 fullsize = [None, 0, 0L]
2212 fullsize = [None, 0, 0L]
2213 deltasize = [None, 0, 0L]
2213 deltasize = [None, 0, 0L]
2214
2214
2215 def addsize(size, l):
2215 def addsize(size, l):
2216 if l[0] is None or size < l[0]:
2216 if l[0] is None or size < l[0]:
2217 l[0] = size
2217 l[0] = size
2218 if size > l[1]:
2218 if size > l[1]:
2219 l[1] = size
2219 l[1] = size
2220 l[2] += size
2220 l[2] += size
2221
2221
2222 numrevs = len(r)
2222 numrevs = len(r)
2223 for rev in xrange(numrevs):
2223 for rev in xrange(numrevs):
2224 p1, p2 = r.parentrevs(rev)
2224 p1, p2 = r.parentrevs(rev)
2225 delta = r.deltaparent(rev)
2225 delta = r.deltaparent(rev)
2226 if format > 0:
2226 if format > 0:
2227 addsize(r.rawsize(rev), datasize)
2227 addsize(r.rawsize(rev), datasize)
2228 if p2 != nullrev:
2228 if p2 != nullrev:
2229 nummerges += 1
2229 nummerges += 1
2230 size = r.length(rev)
2230 size = r.length(rev)
2231 if delta == nullrev:
2231 if delta == nullrev:
2232 chainlengths.append(0)
2232 chainlengths.append(0)
2233 numfull += 1
2233 numfull += 1
2234 addsize(size, fullsize)
2234 addsize(size, fullsize)
2235 else:
2235 else:
2236 chainlengths.append(chainlengths[delta] + 1)
2236 chainlengths.append(chainlengths[delta] + 1)
2237 addsize(size, deltasize)
2237 addsize(size, deltasize)
2238 if delta == rev - 1:
2238 if delta == rev - 1:
2239 numprev += 1
2239 numprev += 1
2240 if delta == p1:
2240 if delta == p1:
2241 nump1prev += 1
2241 nump1prev += 1
2242 elif delta == p2:
2242 elif delta == p2:
2243 nump2prev += 1
2243 nump2prev += 1
2244 elif delta == p1:
2244 elif delta == p1:
2245 nump1 += 1
2245 nump1 += 1
2246 elif delta == p2:
2246 elif delta == p2:
2247 nump2 += 1
2247 nump2 += 1
2248 elif delta != nullrev:
2248 elif delta != nullrev:
2249 numother += 1
2249 numother += 1
2250
2250
2251 # Adjust size min value for empty cases
2251 # Adjust size min value for empty cases
2252 for size in (datasize, fullsize, deltasize):
2252 for size in (datasize, fullsize, deltasize):
2253 if size[0] is None:
2253 if size[0] is None:
2254 size[0] = 0
2254 size[0] = 0
2255
2255
2256 numdeltas = numrevs - numfull
2256 numdeltas = numrevs - numfull
2257 numoprev = numprev - nump1prev - nump2prev
2257 numoprev = numprev - nump1prev - nump2prev
2258 totalrawsize = datasize[2]
2258 totalrawsize = datasize[2]
2259 datasize[2] /= numrevs
2259 datasize[2] /= numrevs
2260 fulltotal = fullsize[2]
2260 fulltotal = fullsize[2]
2261 fullsize[2] /= numfull
2261 fullsize[2] /= numfull
2262 deltatotal = deltasize[2]
2262 deltatotal = deltasize[2]
2263 if numrevs - numfull > 0:
2263 if numrevs - numfull > 0:
2264 deltasize[2] /= numrevs - numfull
2264 deltasize[2] /= numrevs - numfull
2265 totalsize = fulltotal + deltatotal
2265 totalsize = fulltotal + deltatotal
2266 avgchainlen = sum(chainlengths) / numrevs
2266 avgchainlen = sum(chainlengths) / numrevs
2267 compratio = totalrawsize / totalsize
2267 compratio = totalrawsize / totalsize
2268
2268
2269 basedfmtstr = '%%%dd\n'
2269 basedfmtstr = '%%%dd\n'
2270 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2270 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2271
2271
2272 def dfmtstr(max):
2272 def dfmtstr(max):
2273 return basedfmtstr % len(str(max))
2273 return basedfmtstr % len(str(max))
2274 def pcfmtstr(max, padding=0):
2274 def pcfmtstr(max, padding=0):
2275 return basepcfmtstr % (len(str(max)), ' ' * padding)
2275 return basepcfmtstr % (len(str(max)), ' ' * padding)
2276
2276
2277 def pcfmt(value, total):
2277 def pcfmt(value, total):
2278 return (value, 100 * float(value) / total)
2278 return (value, 100 * float(value) / total)
2279
2279
2280 ui.write('format : %d\n' % format)
2280 ui.write('format : %d\n' % format)
2281 ui.write('flags : %s\n' % ', '.join(flags))
2281 ui.write('flags : %s\n' % ', '.join(flags))
2282
2282
2283 ui.write('\n')
2283 ui.write('\n')
2284 fmt = pcfmtstr(totalsize)
2284 fmt = pcfmtstr(totalsize)
2285 fmt2 = dfmtstr(totalsize)
2285 fmt2 = dfmtstr(totalsize)
2286 ui.write('revisions : ' + fmt2 % numrevs)
2286 ui.write('revisions : ' + fmt2 % numrevs)
2287 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2287 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2288 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2288 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2289 ui.write('revisions : ' + fmt2 % numrevs)
2289 ui.write('revisions : ' + fmt2 % numrevs)
2290 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2290 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2291 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2291 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2292 ui.write('revision size : ' + fmt2 % totalsize)
2292 ui.write('revision size : ' + fmt2 % totalsize)
2293 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2293 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2294 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2294 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2295
2295
2296 ui.write('\n')
2296 ui.write('\n')
2297 fmt = dfmtstr(max(avgchainlen, compratio))
2297 fmt = dfmtstr(max(avgchainlen, compratio))
2298 ui.write('avg chain length : ' + fmt % avgchainlen)
2298 ui.write('avg chain length : ' + fmt % avgchainlen)
2299 ui.write('compression ratio : ' + fmt % compratio)
2299 ui.write('compression ratio : ' + fmt % compratio)
2300
2300
2301 if format > 0:
2301 if format > 0:
2302 ui.write('\n')
2302 ui.write('\n')
2303 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2303 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2304 % tuple(datasize))
2304 % tuple(datasize))
2305 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2305 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2306 % tuple(fullsize))
2306 % tuple(fullsize))
2307 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2307 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2308 % tuple(deltasize))
2308 % tuple(deltasize))
2309
2309
2310 if numdeltas > 0:
2310 if numdeltas > 0:
2311 ui.write('\n')
2311 ui.write('\n')
2312 fmt = pcfmtstr(numdeltas)
2312 fmt = pcfmtstr(numdeltas)
2313 fmt2 = pcfmtstr(numdeltas, 4)
2313 fmt2 = pcfmtstr(numdeltas, 4)
2314 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2314 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2315 if numprev > 0:
2315 if numprev > 0:
2316 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2316 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2317 numprev))
2317 numprev))
2318 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2318 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2319 numprev))
2319 numprev))
2320 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2320 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2321 numprev))
2321 numprev))
2322 if gdelta:
2322 if gdelta:
2323 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2323 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2324 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2324 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2325 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2325 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2326 numdeltas))
2326 numdeltas))
2327
2327
2328 @command('debugrevspec', [], ('REVSPEC'))
2328 @command('debugrevspec', [], ('REVSPEC'))
2329 def debugrevspec(ui, repo, expr):
2329 def debugrevspec(ui, repo, expr):
2330 """parse and apply a revision specification
2330 """parse and apply a revision specification
2331
2331
2332 Use --verbose to print the parsed tree before and after aliases
2332 Use --verbose to print the parsed tree before and after aliases
2333 expansion.
2333 expansion.
2334 """
2334 """
2335 if ui.verbose:
2335 if ui.verbose:
2336 tree = revset.parse(expr)[0]
2336 tree = revset.parse(expr)[0]
2337 ui.note(revset.prettyformat(tree), "\n")
2337 ui.note(revset.prettyformat(tree), "\n")
2338 newtree = revset.findaliases(ui, tree)
2338 newtree = revset.findaliases(ui, tree)
2339 if newtree != tree:
2339 if newtree != tree:
2340 ui.note(revset.prettyformat(newtree), "\n")
2340 ui.note(revset.prettyformat(newtree), "\n")
2341 func = revset.match(ui, expr)
2341 func = revset.match(ui, expr)
2342 for c in func(repo, range(len(repo))):
2342 for c in func(repo, range(len(repo))):
2343 ui.write("%s\n" % c)
2343 ui.write("%s\n" % c)
2344
2344
2345 @command('debugsetparents', [], _('REV1 [REV2]'))
2345 @command('debugsetparents', [], _('REV1 [REV2]'))
2346 def debugsetparents(ui, repo, rev1, rev2=None):
2346 def debugsetparents(ui, repo, rev1, rev2=None):
2347 """manually set the parents of the current working directory
2347 """manually set the parents of the current working directory
2348
2348
2349 This is useful for writing repository conversion tools, but should
2349 This is useful for writing repository conversion tools, but should
2350 be used with care.
2350 be used with care.
2351
2351
2352 Returns 0 on success.
2352 Returns 0 on success.
2353 """
2353 """
2354
2354
2355 r1 = scmutil.revsingle(repo, rev1).node()
2355 r1 = scmutil.revsingle(repo, rev1).node()
2356 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2356 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2357
2357
2358 wlock = repo.wlock()
2358 wlock = repo.wlock()
2359 try:
2359 try:
2360 repo.setparents(r1, r2)
2360 repo.setparents(r1, r2)
2361 finally:
2361 finally:
2362 wlock.release()
2362 wlock.release()
2363
2363
2364 @command('debugstate',
2364 @command('debugstate',
2365 [('', 'nodates', None, _('do not display the saved mtime')),
2365 [('', 'nodates', None, _('do not display the saved mtime')),
2366 ('', 'datesort', None, _('sort by saved mtime'))],
2366 ('', 'datesort', None, _('sort by saved mtime'))],
2367 _('[OPTION]...'))
2367 _('[OPTION]...'))
2368 def debugstate(ui, repo, nodates=None, datesort=None):
2368 def debugstate(ui, repo, nodates=None, datesort=None):
2369 """show the contents of the current dirstate"""
2369 """show the contents of the current dirstate"""
2370 timestr = ""
2370 timestr = ""
2371 showdate = not nodates
2371 showdate = not nodates
2372 if datesort:
2372 if datesort:
2373 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2373 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2374 else:
2374 else:
2375 keyfunc = None # sort by filename
2375 keyfunc = None # sort by filename
2376 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2376 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2377 if showdate:
2377 if showdate:
2378 if ent[3] == -1:
2378 if ent[3] == -1:
2379 # Pad or slice to locale representation
2379 # Pad or slice to locale representation
2380 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2380 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2381 time.localtime(0)))
2381 time.localtime(0)))
2382 timestr = 'unset'
2382 timestr = 'unset'
2383 timestr = (timestr[:locale_len] +
2383 timestr = (timestr[:locale_len] +
2384 ' ' * (locale_len - len(timestr)))
2384 ' ' * (locale_len - len(timestr)))
2385 else:
2385 else:
2386 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2386 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2387 time.localtime(ent[3]))
2387 time.localtime(ent[3]))
2388 if ent[1] & 020000:
2388 if ent[1] & 020000:
2389 mode = 'lnk'
2389 mode = 'lnk'
2390 else:
2390 else:
2391 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2391 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2392 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2392 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2393 for f in repo.dirstate.copies():
2393 for f in repo.dirstate.copies():
2394 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2394 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2395
2395
2396 @command('debugsub',
2396 @command('debugsub',
2397 [('r', 'rev', '',
2397 [('r', 'rev', '',
2398 _('revision to check'), _('REV'))],
2398 _('revision to check'), _('REV'))],
2399 _('[-r REV] [REV]'))
2399 _('[-r REV] [REV]'))
2400 def debugsub(ui, repo, rev=None):
2400 def debugsub(ui, repo, rev=None):
2401 ctx = scmutil.revsingle(repo, rev, None)
2401 ctx = scmutil.revsingle(repo, rev, None)
2402 for k, v in sorted(ctx.substate.items()):
2402 for k, v in sorted(ctx.substate.items()):
2403 ui.write('path %s\n' % k)
2403 ui.write('path %s\n' % k)
2404 ui.write(' source %s\n' % v[0])
2404 ui.write(' source %s\n' % v[0])
2405 ui.write(' revision %s\n' % v[1])
2405 ui.write(' revision %s\n' % v[1])
2406
2406
2407 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2407 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2408 def debugwalk(ui, repo, *pats, **opts):
2408 def debugwalk(ui, repo, *pats, **opts):
2409 """show how files match on given patterns"""
2409 """show how files match on given patterns"""
2410 m = scmutil.match(repo[None], pats, opts)
2410 m = scmutil.match(repo[None], pats, opts)
2411 items = list(repo.walk(m))
2411 items = list(repo.walk(m))
2412 if not items:
2412 if not items:
2413 return
2413 return
2414 f = lambda fn: fn
2414 f = lambda fn: fn
2415 if ui.configbool('ui', 'slash') and os.sep != '/':
2415 if ui.configbool('ui', 'slash') and os.sep != '/':
2416 f = lambda fn: util.normpath(fn)
2416 f = lambda fn: util.normpath(fn)
2417 fmt = 'f %%-%ds %%-%ds %%s' % (
2417 fmt = 'f %%-%ds %%-%ds %%s' % (
2418 max([len(abs) for abs in items]),
2418 max([len(abs) for abs in items]),
2419 max([len(m.rel(abs)) for abs in items]))
2419 max([len(m.rel(abs)) for abs in items]))
2420 for abs in items:
2420 for abs in items:
2421 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2421 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2422 ui.write("%s\n" % line.rstrip())
2422 ui.write("%s\n" % line.rstrip())
2423
2423
2424 @command('debugwireargs',
2424 @command('debugwireargs',
2425 [('', 'three', '', 'three'),
2425 [('', 'three', '', 'three'),
2426 ('', 'four', '', 'four'),
2426 ('', 'four', '', 'four'),
2427 ('', 'five', '', 'five'),
2427 ('', 'five', '', 'five'),
2428 ] + remoteopts,
2428 ] + remoteopts,
2429 _('REPO [OPTIONS]... [ONE [TWO]]'))
2429 _('REPO [OPTIONS]... [ONE [TWO]]'))
2430 def debugwireargs(ui, repopath, *vals, **opts):
2430 def debugwireargs(ui, repopath, *vals, **opts):
2431 repo = hg.peer(ui, opts, repopath)
2431 repo = hg.peer(ui, opts, repopath)
2432 for opt in remoteopts:
2432 for opt in remoteopts:
2433 del opts[opt[1]]
2433 del opts[opt[1]]
2434 args = {}
2434 args = {}
2435 for k, v in opts.iteritems():
2435 for k, v in opts.iteritems():
2436 if v:
2436 if v:
2437 args[k] = v
2437 args[k] = v
2438 # run twice to check that we don't mess up the stream for the next command
2438 # run twice to check that we don't mess up the stream for the next command
2439 res1 = repo.debugwireargs(*vals, **args)
2439 res1 = repo.debugwireargs(*vals, **args)
2440 res2 = repo.debugwireargs(*vals, **args)
2440 res2 = repo.debugwireargs(*vals, **args)
2441 ui.write("%s\n" % res1)
2441 ui.write("%s\n" % res1)
2442 if res1 != res2:
2442 if res1 != res2:
2443 ui.warn("%s\n" % res2)
2443 ui.warn("%s\n" % res2)
2444
2444
2445 @command('^diff',
2445 @command('^diff',
2446 [('r', 'rev', [], _('revision'), _('REV')),
2446 [('r', 'rev', [], _('revision'), _('REV')),
2447 ('c', 'change', '', _('change made by revision'), _('REV'))
2447 ('c', 'change', '', _('change made by revision'), _('REV'))
2448 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2448 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2449 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2449 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2450 def diff(ui, repo, *pats, **opts):
2450 def diff(ui, repo, *pats, **opts):
2451 """diff repository (or selected files)
2451 """diff repository (or selected files)
2452
2452
2453 Show differences between revisions for the specified files.
2453 Show differences between revisions for the specified files.
2454
2454
2455 Differences between files are shown using the unified diff format.
2455 Differences between files are shown using the unified diff format.
2456
2456
2457 .. note::
2457 .. note::
2458 diff may generate unexpected results for merges, as it will
2458 diff may generate unexpected results for merges, as it will
2459 default to comparing against the working directory's first
2459 default to comparing against the working directory's first
2460 parent changeset if no revisions are specified.
2460 parent changeset if no revisions are specified.
2461
2461
2462 When two revision arguments are given, then changes are shown
2462 When two revision arguments are given, then changes are shown
2463 between those revisions. If only one revision is specified then
2463 between those revisions. If only one revision is specified then
2464 that revision is compared to the working directory, and, when no
2464 that revision is compared to the working directory, and, when no
2465 revisions are specified, the working directory files are compared
2465 revisions are specified, the working directory files are compared
2466 to its parent.
2466 to its parent.
2467
2467
2468 Alternatively you can specify -c/--change with a revision to see
2468 Alternatively you can specify -c/--change with a revision to see
2469 the changes in that changeset relative to its first parent.
2469 the changes in that changeset relative to its first parent.
2470
2470
2471 Without the -a/--text option, diff will avoid generating diffs of
2471 Without the -a/--text option, diff will avoid generating diffs of
2472 files it detects as binary. With -a, diff will generate a diff
2472 files it detects as binary. With -a, diff will generate a diff
2473 anyway, probably with undesirable results.
2473 anyway, probably with undesirable results.
2474
2474
2475 Use the -g/--git option to generate diffs in the git extended diff
2475 Use the -g/--git option to generate diffs in the git extended diff
2476 format. For more information, read :hg:`help diffs`.
2476 format. For more information, read :hg:`help diffs`.
2477
2477
2478 .. container:: verbose
2478 .. container:: verbose
2479
2479
2480 Examples:
2480 Examples:
2481
2481
2482 - compare a file in the current working directory to its parent::
2482 - compare a file in the current working directory to its parent::
2483
2483
2484 hg diff foo.c
2484 hg diff foo.c
2485
2485
2486 - compare two historical versions of a directory, with rename info::
2486 - compare two historical versions of a directory, with rename info::
2487
2487
2488 hg diff --git -r 1.0:1.2 lib/
2488 hg diff --git -r 1.0:1.2 lib/
2489
2489
2490 - get change stats relative to the last change on some date::
2490 - get change stats relative to the last change on some date::
2491
2491
2492 hg diff --stat -r "date('may 2')"
2492 hg diff --stat -r "date('may 2')"
2493
2493
2494 - diff all newly-added files that contain a keyword::
2494 - diff all newly-added files that contain a keyword::
2495
2495
2496 hg diff "set:added() and grep(GNU)"
2496 hg diff "set:added() and grep(GNU)"
2497
2497
2498 - compare a revision and its parents::
2498 - compare a revision and its parents::
2499
2499
2500 hg diff -c 9353 # compare against first parent
2500 hg diff -c 9353 # compare against first parent
2501 hg diff -r 9353^:9353 # same using revset syntax
2501 hg diff -r 9353^:9353 # same using revset syntax
2502 hg diff -r 9353^2:9353 # compare against the second parent
2502 hg diff -r 9353^2:9353 # compare against the second parent
2503
2503
2504 Returns 0 on success.
2504 Returns 0 on success.
2505 """
2505 """
2506
2506
2507 revs = opts.get('rev')
2507 revs = opts.get('rev')
2508 change = opts.get('change')
2508 change = opts.get('change')
2509 stat = opts.get('stat')
2509 stat = opts.get('stat')
2510 reverse = opts.get('reverse')
2510 reverse = opts.get('reverse')
2511
2511
2512 if revs and change:
2512 if revs and change:
2513 msg = _('cannot specify --rev and --change at the same time')
2513 msg = _('cannot specify --rev and --change at the same time')
2514 raise util.Abort(msg)
2514 raise util.Abort(msg)
2515 elif change:
2515 elif change:
2516 node2 = scmutil.revsingle(repo, change, None).node()
2516 node2 = scmutil.revsingle(repo, change, None).node()
2517 node1 = repo[node2].p1().node()
2517 node1 = repo[node2].p1().node()
2518 else:
2518 else:
2519 node1, node2 = scmutil.revpair(repo, revs)
2519 node1, node2 = scmutil.revpair(repo, revs)
2520
2520
2521 if reverse:
2521 if reverse:
2522 node1, node2 = node2, node1
2522 node1, node2 = node2, node1
2523
2523
2524 diffopts = patch.diffopts(ui, opts)
2524 diffopts = patch.diffopts(ui, opts)
2525 m = scmutil.match(repo[node2], pats, opts)
2525 m = scmutil.match(repo[node2], pats, opts)
2526 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2526 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2527 listsubrepos=opts.get('subrepos'))
2527 listsubrepos=opts.get('subrepos'))
2528
2528
2529 @command('^export',
2529 @command('^export',
2530 [('o', 'output', '',
2530 [('o', 'output', '',
2531 _('print output to file with formatted name'), _('FORMAT')),
2531 _('print output to file with formatted name'), _('FORMAT')),
2532 ('', 'switch-parent', None, _('diff against the second parent')),
2532 ('', 'switch-parent', None, _('diff against the second parent')),
2533 ('r', 'rev', [], _('revisions to export'), _('REV')),
2533 ('r', 'rev', [], _('revisions to export'), _('REV')),
2534 ] + diffopts,
2534 ] + diffopts,
2535 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2535 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2536 def export(ui, repo, *changesets, **opts):
2536 def export(ui, repo, *changesets, **opts):
2537 """dump the header and diffs for one or more changesets
2537 """dump the header and diffs for one or more changesets
2538
2538
2539 Print the changeset header and diffs for one or more revisions.
2539 Print the changeset header and diffs for one or more revisions.
2540
2540
2541 The information shown in the changeset header is: author, date,
2541 The information shown in the changeset header is: author, date,
2542 branch name (if non-default), changeset hash, parent(s) and commit
2542 branch name (if non-default), changeset hash, parent(s) and commit
2543 comment.
2543 comment.
2544
2544
2545 .. note::
2545 .. note::
2546 export may generate unexpected diff output for merge
2546 export may generate unexpected diff output for merge
2547 changesets, as it will compare the merge changeset against its
2547 changesets, as it will compare the merge changeset against its
2548 first parent only.
2548 first parent only.
2549
2549
2550 Output may be to a file, in which case the name of the file is
2550 Output may be to a file, in which case the name of the file is
2551 given using a format string. The formatting rules are as follows:
2551 given using a format string. The formatting rules are as follows:
2552
2552
2553 :``%%``: literal "%" character
2553 :``%%``: literal "%" character
2554 :``%H``: changeset hash (40 hexadecimal digits)
2554 :``%H``: changeset hash (40 hexadecimal digits)
2555 :``%N``: number of patches being generated
2555 :``%N``: number of patches being generated
2556 :``%R``: changeset revision number
2556 :``%R``: changeset revision number
2557 :``%b``: basename of the exporting repository
2557 :``%b``: basename of the exporting repository
2558 :``%h``: short-form changeset hash (12 hexadecimal digits)
2558 :``%h``: short-form changeset hash (12 hexadecimal digits)
2559 :``%m``: first line of the commit message (only alphanumeric characters)
2559 :``%m``: first line of the commit message (only alphanumeric characters)
2560 :``%n``: zero-padded sequence number, starting at 1
2560 :``%n``: zero-padded sequence number, starting at 1
2561 :``%r``: zero-padded changeset revision number
2561 :``%r``: zero-padded changeset revision number
2562
2562
2563 Without the -a/--text option, export will avoid generating diffs
2563 Without the -a/--text option, export will avoid generating diffs
2564 of files it detects as binary. With -a, export will generate a
2564 of files it detects as binary. With -a, export will generate a
2565 diff anyway, probably with undesirable results.
2565 diff anyway, probably with undesirable results.
2566
2566
2567 Use the -g/--git option to generate diffs in the git extended diff
2567 Use the -g/--git option to generate diffs in the git extended diff
2568 format. See :hg:`help diffs` for more information.
2568 format. See :hg:`help diffs` for more information.
2569
2569
2570 With the --switch-parent option, the diff will be against the
2570 With the --switch-parent option, the diff will be against the
2571 second parent. It can be useful to review a merge.
2571 second parent. It can be useful to review a merge.
2572
2572
2573 .. container:: verbose
2573 .. container:: verbose
2574
2574
2575 Examples:
2575 Examples:
2576
2576
2577 - use export and import to transplant a bugfix to the current
2577 - use export and import to transplant a bugfix to the current
2578 branch::
2578 branch::
2579
2579
2580 hg export -r 9353 | hg import -
2580 hg export -r 9353 | hg import -
2581
2581
2582 - export all the changesets between two revisions to a file with
2582 - export all the changesets between two revisions to a file with
2583 rename information::
2583 rename information::
2584
2584
2585 hg export --git -r 123:150 > changes.txt
2585 hg export --git -r 123:150 > changes.txt
2586
2586
2587 - split outgoing changes into a series of patches with
2587 - split outgoing changes into a series of patches with
2588 descriptive names::
2588 descriptive names::
2589
2589
2590 hg export -r "outgoing()" -o "%n-%m.patch"
2590 hg export -r "outgoing()" -o "%n-%m.patch"
2591
2591
2592 Returns 0 on success.
2592 Returns 0 on success.
2593 """
2593 """
2594 changesets += tuple(opts.get('rev', []))
2594 changesets += tuple(opts.get('rev', []))
2595 revs = scmutil.revrange(repo, changesets)
2595 revs = scmutil.revrange(repo, changesets)
2596 if not revs:
2596 if not revs:
2597 raise util.Abort(_("export requires at least one changeset"))
2597 raise util.Abort(_("export requires at least one changeset"))
2598 if len(revs) > 1:
2598 if len(revs) > 1:
2599 ui.note(_('exporting patches:\n'))
2599 ui.note(_('exporting patches:\n'))
2600 else:
2600 else:
2601 ui.note(_('exporting patch:\n'))
2601 ui.note(_('exporting patch:\n'))
2602 cmdutil.export(repo, revs, template=opts.get('output'),
2602 cmdutil.export(repo, revs, template=opts.get('output'),
2603 switch_parent=opts.get('switch_parent'),
2603 switch_parent=opts.get('switch_parent'),
2604 opts=patch.diffopts(ui, opts))
2604 opts=patch.diffopts(ui, opts))
2605
2605
2606 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2606 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2607 def forget(ui, repo, *pats, **opts):
2607 def forget(ui, repo, *pats, **opts):
2608 """forget the specified files on the next commit
2608 """forget the specified files on the next commit
2609
2609
2610 Mark the specified files so they will no longer be tracked
2610 Mark the specified files so they will no longer be tracked
2611 after the next commit.
2611 after the next commit.
2612
2612
2613 This only removes files from the current branch, not from the
2613 This only removes files from the current branch, not from the
2614 entire project history, and it does not delete them from the
2614 entire project history, and it does not delete them from the
2615 working directory.
2615 working directory.
2616
2616
2617 To undo a forget before the next commit, see :hg:`add`.
2617 To undo a forget before the next commit, see :hg:`add`.
2618
2618
2619 .. container:: verbose
2619 .. container:: verbose
2620
2620
2621 Examples:
2621 Examples:
2622
2622
2623 - forget newly-added binary files::
2623 - forget newly-added binary files::
2624
2624
2625 hg forget "set:added() and binary()"
2625 hg forget "set:added() and binary()"
2626
2626
2627 - forget files that would be excluded by .hgignore::
2627 - forget files that would be excluded by .hgignore::
2628
2628
2629 hg forget "set:hgignore()"
2629 hg forget "set:hgignore()"
2630
2630
2631 Returns 0 on success.
2631 Returns 0 on success.
2632 """
2632 """
2633
2633
2634 if not pats:
2634 if not pats:
2635 raise util.Abort(_('no files specified'))
2635 raise util.Abort(_('no files specified'))
2636
2636
2637 m = scmutil.match(repo[None], pats, opts)
2637 m = scmutil.match(repo[None], pats, opts)
2638 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2638 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2639 return rejected and 1 or 0
2639 return rejected and 1 or 0
2640
2640
2641 @command(
2641 @command(
2642 'graft',
2642 'graft',
2643 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2643 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2644 ('c', 'continue', False, _('resume interrupted graft')),
2644 ('c', 'continue', False, _('resume interrupted graft')),
2645 ('e', 'edit', False, _('invoke editor on commit messages')),
2645 ('e', 'edit', False, _('invoke editor on commit messages')),
2646 ('', 'log', None, _('append graft info to log message')),
2646 ('', 'log', None, _('append graft info to log message')),
2647 ('D', 'currentdate', False,
2647 ('D', 'currentdate', False,
2648 _('record the current date as commit date')),
2648 _('record the current date as commit date')),
2649 ('U', 'currentuser', False,
2649 ('U', 'currentuser', False,
2650 _('record the current user as committer'), _('DATE'))]
2650 _('record the current user as committer'), _('DATE'))]
2651 + commitopts2 + mergetoolopts + dryrunopts,
2651 + commitopts2 + mergetoolopts + dryrunopts,
2652 _('[OPTION]... [-r] REV...'))
2652 _('[OPTION]... [-r] REV...'))
2653 def graft(ui, repo, *revs, **opts):
2653 def graft(ui, repo, *revs, **opts):
2654 '''copy changes from other branches onto the current branch
2654 '''copy changes from other branches onto the current branch
2655
2655
2656 This command uses Mercurial's merge logic to copy individual
2656 This command uses Mercurial's merge logic to copy individual
2657 changes from other branches without merging branches in the
2657 changes from other branches without merging branches in the
2658 history graph. This is sometimes known as 'backporting' or
2658 history graph. This is sometimes known as 'backporting' or
2659 'cherry-picking'. By default, graft will copy user, date, and
2659 'cherry-picking'. By default, graft will copy user, date, and
2660 description from the source changesets.
2660 description from the source changesets.
2661
2661
2662 Changesets that are ancestors of the current revision, that have
2662 Changesets that are ancestors of the current revision, that have
2663 already been grafted, or that are merges will be skipped.
2663 already been grafted, or that are merges will be skipped.
2664
2664
2665 If --log is specified, log messages will have a comment appended
2665 If --log is specified, log messages will have a comment appended
2666 of the form::
2666 of the form::
2667
2667
2668 (grafted from CHANGESETHASH)
2668 (grafted from CHANGESETHASH)
2669
2669
2670 If a graft merge results in conflicts, the graft process is
2670 If a graft merge results in conflicts, the graft process is
2671 interrupted so that the current merge can be manually resolved.
2671 interrupted so that the current merge can be manually resolved.
2672 Once all conflicts are addressed, the graft process can be
2672 Once all conflicts are addressed, the graft process can be
2673 continued with the -c/--continue option.
2673 continued with the -c/--continue option.
2674
2674
2675 .. note::
2675 .. note::
2676 The -c/--continue option does not reapply earlier options.
2676 The -c/--continue option does not reapply earlier options.
2677
2677
2678 .. container:: verbose
2678 .. container:: verbose
2679
2679
2680 Examples:
2680 Examples:
2681
2681
2682 - copy a single change to the stable branch and edit its description::
2682 - copy a single change to the stable branch and edit its description::
2683
2683
2684 hg update stable
2684 hg update stable
2685 hg graft --edit 9393
2685 hg graft --edit 9393
2686
2686
2687 - graft a range of changesets with one exception, updating dates::
2687 - graft a range of changesets with one exception, updating dates::
2688
2688
2689 hg graft -D "2085::2093 and not 2091"
2689 hg graft -D "2085::2093 and not 2091"
2690
2690
2691 - continue a graft after resolving conflicts::
2691 - continue a graft after resolving conflicts::
2692
2692
2693 hg graft -c
2693 hg graft -c
2694
2694
2695 - show the source of a grafted changeset::
2695 - show the source of a grafted changeset::
2696
2696
2697 hg log --debug -r tip
2697 hg log --debug -r tip
2698
2698
2699 Returns 0 on successful completion.
2699 Returns 0 on successful completion.
2700 '''
2700 '''
2701
2701
2702 revs = list(revs)
2702 revs = list(revs)
2703 revs.extend(opts['rev'])
2703 revs.extend(opts['rev'])
2704
2704
2705 if not opts.get('user') and opts.get('currentuser'):
2705 if not opts.get('user') and opts.get('currentuser'):
2706 opts['user'] = ui.username()
2706 opts['user'] = ui.username()
2707 if not opts.get('date') and opts.get('currentdate'):
2707 if not opts.get('date') and opts.get('currentdate'):
2708 opts['date'] = "%d %d" % util.makedate()
2708 opts['date'] = "%d %d" % util.makedate()
2709
2709
2710 editor = None
2710 editor = None
2711 if opts.get('edit'):
2711 if opts.get('edit'):
2712 editor = cmdutil.commitforceeditor
2712 editor = cmdutil.commitforceeditor
2713
2713
2714 cont = False
2714 cont = False
2715 if opts['continue']:
2715 if opts['continue']:
2716 cont = True
2716 cont = True
2717 if revs:
2717 if revs:
2718 raise util.Abort(_("can't specify --continue and revisions"))
2718 raise util.Abort(_("can't specify --continue and revisions"))
2719 # read in unfinished revisions
2719 # read in unfinished revisions
2720 try:
2720 try:
2721 nodes = repo.opener.read('graftstate').splitlines()
2721 nodes = repo.opener.read('graftstate').splitlines()
2722 revs = [repo[node].rev() for node in nodes]
2722 revs = [repo[node].rev() for node in nodes]
2723 except IOError, inst:
2723 except IOError, inst:
2724 if inst.errno != errno.ENOENT:
2724 if inst.errno != errno.ENOENT:
2725 raise
2725 raise
2726 raise util.Abort(_("no graft state found, can't continue"))
2726 raise util.Abort(_("no graft state found, can't continue"))
2727 else:
2727 else:
2728 cmdutil.bailifchanged(repo)
2728 cmdutil.bailifchanged(repo)
2729 if not revs:
2729 if not revs:
2730 raise util.Abort(_('no revisions specified'))
2730 raise util.Abort(_('no revisions specified'))
2731 revs = scmutil.revrange(repo, revs)
2731 revs = scmutil.revrange(repo, revs)
2732
2732
2733 # check for merges
2733 # check for merges
2734 for rev in repo.revs('%ld and merge()', revs):
2734 for rev in repo.revs('%ld and merge()', revs):
2735 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2735 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2736 revs.remove(rev)
2736 revs.remove(rev)
2737 if not revs:
2737 if not revs:
2738 return -1
2738 return -1
2739
2739
2740 # check for ancestors of dest branch
2740 # check for ancestors of dest branch
2741 for rev in repo.revs('::. and %ld', revs):
2741 for rev in repo.revs('::. and %ld', revs):
2742 ui.warn(_('skipping ancestor revision %s\n') % rev)
2742 ui.warn(_('skipping ancestor revision %s\n') % rev)
2743 revs.remove(rev)
2743 revs.remove(rev)
2744 if not revs:
2744 if not revs:
2745 return -1
2745 return -1
2746
2746
2747 # analyze revs for earlier grafts
2747 # analyze revs for earlier grafts
2748 ids = {}
2748 ids = {}
2749 for ctx in repo.set("%ld", revs):
2749 for ctx in repo.set("%ld", revs):
2750 ids[ctx.hex()] = ctx.rev()
2750 ids[ctx.hex()] = ctx.rev()
2751 n = ctx.extra().get('source')
2751 n = ctx.extra().get('source')
2752 if n:
2752 if n:
2753 ids[n] = ctx.rev()
2753 ids[n] = ctx.rev()
2754
2754
2755 # check ancestors for earlier grafts
2755 # check ancestors for earlier grafts
2756 ui.debug('scanning for duplicate grafts\n')
2756 ui.debug('scanning for duplicate grafts\n')
2757 for ctx in repo.set("::. - ::%ld", revs):
2757 for ctx in repo.set("::. - ::%ld", revs):
2758 n = ctx.extra().get('source')
2758 n = ctx.extra().get('source')
2759 if n in ids:
2759 if n in ids:
2760 r = repo[n].rev()
2760 r = repo[n].rev()
2761 if r in revs:
2761 if r in revs:
2762 ui.warn(_('skipping already grafted revision %s\n') % r)
2762 ui.warn(_('skipping already grafted revision %s\n') % r)
2763 revs.remove(r)
2763 revs.remove(r)
2764 elif ids[n] in revs:
2764 elif ids[n] in revs:
2765 ui.warn(_('skipping already grafted revision %s '
2765 ui.warn(_('skipping already grafted revision %s '
2766 '(same origin %d)\n') % (ids[n], r))
2766 '(same origin %d)\n') % (ids[n], r))
2767 revs.remove(ids[n])
2767 revs.remove(ids[n])
2768 elif ctx.hex() in ids:
2768 elif ctx.hex() in ids:
2769 r = ids[ctx.hex()]
2769 r = ids[ctx.hex()]
2770 ui.warn(_('skipping already grafted revision %s '
2770 ui.warn(_('skipping already grafted revision %s '
2771 '(was grafted from %d)\n') % (r, ctx.rev()))
2771 '(was grafted from %d)\n') % (r, ctx.rev()))
2772 revs.remove(r)
2772 revs.remove(r)
2773 if not revs:
2773 if not revs:
2774 return -1
2774 return -1
2775
2775
2776 wlock = repo.wlock()
2776 wlock = repo.wlock()
2777 try:
2777 try:
2778 for pos, ctx in enumerate(repo.set("%ld", revs)):
2778 for pos, ctx in enumerate(repo.set("%ld", revs)):
2779 current = repo['.']
2779 current = repo['.']
2780
2780
2781 ui.status(_('grafting revision %s\n') % ctx.rev())
2781 ui.status(_('grafting revision %s\n') % ctx.rev())
2782 if opts.get('dry_run'):
2782 if opts.get('dry_run'):
2783 continue
2783 continue
2784
2784
2785 # we don't merge the first commit when continuing
2785 # we don't merge the first commit when continuing
2786 if not cont:
2786 if not cont:
2787 # perform the graft merge with p1(rev) as 'ancestor'
2787 # perform the graft merge with p1(rev) as 'ancestor'
2788 try:
2788 try:
2789 # ui.forcemerge is an internal variable, do not document
2789 # ui.forcemerge is an internal variable, do not document
2790 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2790 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2791 stats = mergemod.update(repo, ctx.node(), True, True, False,
2791 stats = mergemod.update(repo, ctx.node(), True, True, False,
2792 ctx.p1().node())
2792 ctx.p1().node())
2793 finally:
2793 finally:
2794 repo.ui.setconfig('ui', 'forcemerge', '')
2794 repo.ui.setconfig('ui', 'forcemerge', '')
2795 # report any conflicts
2795 # report any conflicts
2796 if stats and stats[3] > 0:
2796 if stats and stats[3] > 0:
2797 # write out state for --continue
2797 # write out state for --continue
2798 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2798 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2799 repo.opener.write('graftstate', ''.join(nodelines))
2799 repo.opener.write('graftstate', ''.join(nodelines))
2800 raise util.Abort(
2800 raise util.Abort(
2801 _("unresolved conflicts, can't continue"),
2801 _("unresolved conflicts, can't continue"),
2802 hint=_('use hg resolve and hg graft --continue'))
2802 hint=_('use hg resolve and hg graft --continue'))
2803 else:
2803 else:
2804 cont = False
2804 cont = False
2805
2805
2806 # drop the second merge parent
2806 # drop the second merge parent
2807 repo.setparents(current.node(), nullid)
2807 repo.setparents(current.node(), nullid)
2808 repo.dirstate.write()
2808 repo.dirstate.write()
2809 # fix up dirstate for copies and renames
2809 # fix up dirstate for copies and renames
2810 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2810 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2811
2811
2812 # commit
2812 # commit
2813 source = ctx.extra().get('source')
2813 source = ctx.extra().get('source')
2814 if not source:
2814 if not source:
2815 source = ctx.hex()
2815 source = ctx.hex()
2816 extra = {'source': source}
2816 extra = {'source': source}
2817 user = ctx.user()
2817 user = ctx.user()
2818 if opts.get('user'):
2818 if opts.get('user'):
2819 user = opts['user']
2819 user = opts['user']
2820 date = ctx.date()
2820 date = ctx.date()
2821 if opts.get('date'):
2821 if opts.get('date'):
2822 date = opts['date']
2822 date = opts['date']
2823 message = ctx.description()
2823 message = ctx.description()
2824 if opts.get('log'):
2824 if opts.get('log'):
2825 message += '\n(grafted from %s)' % ctx.hex()
2825 message += '\n(grafted from %s)' % ctx.hex()
2826 node = repo.commit(text=message, user=user,
2826 node = repo.commit(text=message, user=user,
2827 date=date, extra=extra, editor=editor)
2827 date=date, extra=extra, editor=editor)
2828 if node is None:
2828 if node is None:
2829 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2829 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2830 finally:
2830 finally:
2831 wlock.release()
2831 wlock.release()
2832
2832
2833 # remove state when we complete successfully
2833 # remove state when we complete successfully
2834 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2834 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2835 util.unlinkpath(repo.join('graftstate'))
2835 util.unlinkpath(repo.join('graftstate'))
2836
2836
2837 return 0
2837 return 0
2838
2838
2839 @command('grep',
2839 @command('grep',
2840 [('0', 'print0', None, _('end fields with NUL')),
2840 [('0', 'print0', None, _('end fields with NUL')),
2841 ('', 'all', None, _('print all revisions that match')),
2841 ('', 'all', None, _('print all revisions that match')),
2842 ('a', 'text', None, _('treat all files as text')),
2842 ('a', 'text', None, _('treat all files as text')),
2843 ('f', 'follow', None,
2843 ('f', 'follow', None,
2844 _('follow changeset history,'
2844 _('follow changeset history,'
2845 ' or file history across copies and renames')),
2845 ' or file history across copies and renames')),
2846 ('i', 'ignore-case', None, _('ignore case when matching')),
2846 ('i', 'ignore-case', None, _('ignore case when matching')),
2847 ('l', 'files-with-matches', None,
2847 ('l', 'files-with-matches', None,
2848 _('print only filenames and revisions that match')),
2848 _('print only filenames and revisions that match')),
2849 ('n', 'line-number', None, _('print matching line numbers')),
2849 ('n', 'line-number', None, _('print matching line numbers')),
2850 ('r', 'rev', [],
2850 ('r', 'rev', [],
2851 _('only search files changed within revision range'), _('REV')),
2851 _('only search files changed within revision range'), _('REV')),
2852 ('u', 'user', None, _('list the author (long with -v)')),
2852 ('u', 'user', None, _('list the author (long with -v)')),
2853 ('d', 'date', None, _('list the date (short with -q)')),
2853 ('d', 'date', None, _('list the date (short with -q)')),
2854 ] + walkopts,
2854 ] + walkopts,
2855 _('[OPTION]... PATTERN [FILE]...'))
2855 _('[OPTION]... PATTERN [FILE]...'))
2856 def grep(ui, repo, pattern, *pats, **opts):
2856 def grep(ui, repo, pattern, *pats, **opts):
2857 """search for a pattern in specified files and revisions
2857 """search for a pattern in specified files and revisions
2858
2858
2859 Search revisions of files for a regular expression.
2859 Search revisions of files for a regular expression.
2860
2860
2861 This command behaves differently than Unix grep. It only accepts
2861 This command behaves differently than Unix grep. It only accepts
2862 Python/Perl regexps. It searches repository history, not the
2862 Python/Perl regexps. It searches repository history, not the
2863 working directory. It always prints the revision number in which a
2863 working directory. It always prints the revision number in which a
2864 match appears.
2864 match appears.
2865
2865
2866 By default, grep only prints output for the first revision of a
2866 By default, grep only prints output for the first revision of a
2867 file in which it finds a match. To get it to print every revision
2867 file in which it finds a match. To get it to print every revision
2868 that contains a change in match status ("-" for a match that
2868 that contains a change in match status ("-" for a match that
2869 becomes a non-match, or "+" for a non-match that becomes a match),
2869 becomes a non-match, or "+" for a non-match that becomes a match),
2870 use the --all flag.
2870 use the --all flag.
2871
2871
2872 Returns 0 if a match is found, 1 otherwise.
2872 Returns 0 if a match is found, 1 otherwise.
2873 """
2873 """
2874 reflags = re.M
2874 reflags = re.M
2875 if opts.get('ignore_case'):
2875 if opts.get('ignore_case'):
2876 reflags |= re.I
2876 reflags |= re.I
2877 try:
2877 try:
2878 regexp = re.compile(pattern, reflags)
2878 regexp = re.compile(pattern, reflags)
2879 except re.error, inst:
2879 except re.error, inst:
2880 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2880 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2881 return 1
2881 return 1
2882 sep, eol = ':', '\n'
2882 sep, eol = ':', '\n'
2883 if opts.get('print0'):
2883 if opts.get('print0'):
2884 sep = eol = '\0'
2884 sep = eol = '\0'
2885
2885
2886 getfile = util.lrucachefunc(repo.file)
2886 getfile = util.lrucachefunc(repo.file)
2887
2887
2888 def matchlines(body):
2888 def matchlines(body):
2889 begin = 0
2889 begin = 0
2890 linenum = 0
2890 linenum = 0
2891 while True:
2891 while True:
2892 match = regexp.search(body, begin)
2892 match = regexp.search(body, begin)
2893 if not match:
2893 if not match:
2894 break
2894 break
2895 mstart, mend = match.span()
2895 mstart, mend = match.span()
2896 linenum += body.count('\n', begin, mstart) + 1
2896 linenum += body.count('\n', begin, mstart) + 1
2897 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2897 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2898 begin = body.find('\n', mend) + 1 or len(body) + 1
2898 begin = body.find('\n', mend) + 1 or len(body) + 1
2899 lend = begin - 1
2899 lend = begin - 1
2900 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2900 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2901
2901
2902 class linestate(object):
2902 class linestate(object):
2903 def __init__(self, line, linenum, colstart, colend):
2903 def __init__(self, line, linenum, colstart, colend):
2904 self.line = line
2904 self.line = line
2905 self.linenum = linenum
2905 self.linenum = linenum
2906 self.colstart = colstart
2906 self.colstart = colstart
2907 self.colend = colend
2907 self.colend = colend
2908
2908
2909 def __hash__(self):
2909 def __hash__(self):
2910 return hash((self.linenum, self.line))
2910 return hash((self.linenum, self.line))
2911
2911
2912 def __eq__(self, other):
2912 def __eq__(self, other):
2913 return self.line == other.line
2913 return self.line == other.line
2914
2914
2915 matches = {}
2915 matches = {}
2916 copies = {}
2916 copies = {}
2917 def grepbody(fn, rev, body):
2917 def grepbody(fn, rev, body):
2918 matches[rev].setdefault(fn, [])
2918 matches[rev].setdefault(fn, [])
2919 m = matches[rev][fn]
2919 m = matches[rev][fn]
2920 for lnum, cstart, cend, line in matchlines(body):
2920 for lnum, cstart, cend, line in matchlines(body):
2921 s = linestate(line, lnum, cstart, cend)
2921 s = linestate(line, lnum, cstart, cend)
2922 m.append(s)
2922 m.append(s)
2923
2923
2924 def difflinestates(a, b):
2924 def difflinestates(a, b):
2925 sm = difflib.SequenceMatcher(None, a, b)
2925 sm = difflib.SequenceMatcher(None, a, b)
2926 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2926 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2927 if tag == 'insert':
2927 if tag == 'insert':
2928 for i in xrange(blo, bhi):
2928 for i in xrange(blo, bhi):
2929 yield ('+', b[i])
2929 yield ('+', b[i])
2930 elif tag == 'delete':
2930 elif tag == 'delete':
2931 for i in xrange(alo, ahi):
2931 for i in xrange(alo, ahi):
2932 yield ('-', a[i])
2932 yield ('-', a[i])
2933 elif tag == 'replace':
2933 elif tag == 'replace':
2934 for i in xrange(alo, ahi):
2934 for i in xrange(alo, ahi):
2935 yield ('-', a[i])
2935 yield ('-', a[i])
2936 for i in xrange(blo, bhi):
2936 for i in xrange(blo, bhi):
2937 yield ('+', b[i])
2937 yield ('+', b[i])
2938
2938
2939 def display(fn, ctx, pstates, states):
2939 def display(fn, ctx, pstates, states):
2940 rev = ctx.rev()
2940 rev = ctx.rev()
2941 datefunc = ui.quiet and util.shortdate or util.datestr
2941 datefunc = ui.quiet and util.shortdate or util.datestr
2942 found = False
2942 found = False
2943 filerevmatches = {}
2943 filerevmatches = {}
2944 def binary():
2944 def binary():
2945 flog = getfile(fn)
2945 flog = getfile(fn)
2946 return util.binary(flog.read(ctx.filenode(fn)))
2946 return util.binary(flog.read(ctx.filenode(fn)))
2947
2947
2948 if opts.get('all'):
2948 if opts.get('all'):
2949 iter = difflinestates(pstates, states)
2949 iter = difflinestates(pstates, states)
2950 else:
2950 else:
2951 iter = [('', l) for l in states]
2951 iter = [('', l) for l in states]
2952 for change, l in iter:
2952 for change, l in iter:
2953 cols = [fn, str(rev)]
2953 cols = [fn, str(rev)]
2954 before, match, after = None, None, None
2954 before, match, after = None, None, None
2955 if opts.get('line_number'):
2955 if opts.get('line_number'):
2956 cols.append(str(l.linenum))
2956 cols.append(str(l.linenum))
2957 if opts.get('all'):
2957 if opts.get('all'):
2958 cols.append(change)
2958 cols.append(change)
2959 if opts.get('user'):
2959 if opts.get('user'):
2960 cols.append(ui.shortuser(ctx.user()))
2960 cols.append(ui.shortuser(ctx.user()))
2961 if opts.get('date'):
2961 if opts.get('date'):
2962 cols.append(datefunc(ctx.date()))
2962 cols.append(datefunc(ctx.date()))
2963 if opts.get('files_with_matches'):
2963 if opts.get('files_with_matches'):
2964 c = (fn, rev)
2964 c = (fn, rev)
2965 if c in filerevmatches:
2965 if c in filerevmatches:
2966 continue
2966 continue
2967 filerevmatches[c] = 1
2967 filerevmatches[c] = 1
2968 else:
2968 else:
2969 before = l.line[:l.colstart]
2969 before = l.line[:l.colstart]
2970 match = l.line[l.colstart:l.colend]
2970 match = l.line[l.colstart:l.colend]
2971 after = l.line[l.colend:]
2971 after = l.line[l.colend:]
2972 ui.write(sep.join(cols))
2972 ui.write(sep.join(cols))
2973 if before is not None:
2973 if before is not None:
2974 if not opts.get('text') and binary():
2974 if not opts.get('text') and binary():
2975 ui.write(sep + " Binary file matches")
2975 ui.write(sep + " Binary file matches")
2976 else:
2976 else:
2977 ui.write(sep + before)
2977 ui.write(sep + before)
2978 ui.write(match, label='grep.match')
2978 ui.write(match, label='grep.match')
2979 ui.write(after)
2979 ui.write(after)
2980 ui.write(eol)
2980 ui.write(eol)
2981 found = True
2981 found = True
2982 return found
2982 return found
2983
2983
2984 skip = {}
2984 skip = {}
2985 revfiles = {}
2985 revfiles = {}
2986 matchfn = scmutil.match(repo[None], pats, opts)
2986 matchfn = scmutil.match(repo[None], pats, opts)
2987 found = False
2987 found = False
2988 follow = opts.get('follow')
2988 follow = opts.get('follow')
2989
2989
2990 def prep(ctx, fns):
2990 def prep(ctx, fns):
2991 rev = ctx.rev()
2991 rev = ctx.rev()
2992 pctx = ctx.p1()
2992 pctx = ctx.p1()
2993 parent = pctx.rev()
2993 parent = pctx.rev()
2994 matches.setdefault(rev, {})
2994 matches.setdefault(rev, {})
2995 matches.setdefault(parent, {})
2995 matches.setdefault(parent, {})
2996 files = revfiles.setdefault(rev, [])
2996 files = revfiles.setdefault(rev, [])
2997 for fn in fns:
2997 for fn in fns:
2998 flog = getfile(fn)
2998 flog = getfile(fn)
2999 try:
2999 try:
3000 fnode = ctx.filenode(fn)
3000 fnode = ctx.filenode(fn)
3001 except error.LookupError:
3001 except error.LookupError:
3002 continue
3002 continue
3003
3003
3004 copied = flog.renamed(fnode)
3004 copied = flog.renamed(fnode)
3005 copy = follow and copied and copied[0]
3005 copy = follow and copied and copied[0]
3006 if copy:
3006 if copy:
3007 copies.setdefault(rev, {})[fn] = copy
3007 copies.setdefault(rev, {})[fn] = copy
3008 if fn in skip:
3008 if fn in skip:
3009 if copy:
3009 if copy:
3010 skip[copy] = True
3010 skip[copy] = True
3011 continue
3011 continue
3012 files.append(fn)
3012 files.append(fn)
3013
3013
3014 if fn not in matches[rev]:
3014 if fn not in matches[rev]:
3015 grepbody(fn, rev, flog.read(fnode))
3015 grepbody(fn, rev, flog.read(fnode))
3016
3016
3017 pfn = copy or fn
3017 pfn = copy or fn
3018 if pfn not in matches[parent]:
3018 if pfn not in matches[parent]:
3019 try:
3019 try:
3020 fnode = pctx.filenode(pfn)
3020 fnode = pctx.filenode(pfn)
3021 grepbody(pfn, parent, flog.read(fnode))
3021 grepbody(pfn, parent, flog.read(fnode))
3022 except error.LookupError:
3022 except error.LookupError:
3023 pass
3023 pass
3024
3024
3025 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3025 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3026 rev = ctx.rev()
3026 rev = ctx.rev()
3027 parent = ctx.p1().rev()
3027 parent = ctx.p1().rev()
3028 for fn in sorted(revfiles.get(rev, [])):
3028 for fn in sorted(revfiles.get(rev, [])):
3029 states = matches[rev][fn]
3029 states = matches[rev][fn]
3030 copy = copies.get(rev, {}).get(fn)
3030 copy = copies.get(rev, {}).get(fn)
3031 if fn in skip:
3031 if fn in skip:
3032 if copy:
3032 if copy:
3033 skip[copy] = True
3033 skip[copy] = True
3034 continue
3034 continue
3035 pstates = matches.get(parent, {}).get(copy or fn, [])
3035 pstates = matches.get(parent, {}).get(copy or fn, [])
3036 if pstates or states:
3036 if pstates or states:
3037 r = display(fn, ctx, pstates, states)
3037 r = display(fn, ctx, pstates, states)
3038 found = found or r
3038 found = found or r
3039 if r and not opts.get('all'):
3039 if r and not opts.get('all'):
3040 skip[fn] = True
3040 skip[fn] = True
3041 if copy:
3041 if copy:
3042 skip[copy] = True
3042 skip[copy] = True
3043 del matches[rev]
3043 del matches[rev]
3044 del revfiles[rev]
3044 del revfiles[rev]
3045
3045
3046 return not found
3046 return not found
3047
3047
3048 @command('heads',
3048 @command('heads',
3049 [('r', 'rev', '',
3049 [('r', 'rev', '',
3050 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3050 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3051 ('t', 'topo', False, _('show topological heads only')),
3051 ('t', 'topo', False, _('show topological heads only')),
3052 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3052 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3053 ('c', 'closed', False, _('show normal and closed branch heads')),
3053 ('c', 'closed', False, _('show normal and closed branch heads')),
3054 ] + templateopts,
3054 ] + templateopts,
3055 _('[-ct] [-r STARTREV] [REV]...'))
3055 _('[-ct] [-r STARTREV] [REV]...'))
3056 def heads(ui, repo, *branchrevs, **opts):
3056 def heads(ui, repo, *branchrevs, **opts):
3057 """show current repository heads or show branch heads
3057 """show current repository heads or show branch heads
3058
3058
3059 With no arguments, show all repository branch heads.
3059 With no arguments, show all repository branch heads.
3060
3060
3061 Repository "heads" are changesets with no child changesets. They are
3061 Repository "heads" are changesets with no child changesets. They are
3062 where development generally takes place and are the usual targets
3062 where development generally takes place and are the usual targets
3063 for update and merge operations. Branch heads are changesets that have
3063 for update and merge operations. Branch heads are changesets that have
3064 no child changeset on the same branch.
3064 no child changeset on the same branch.
3065
3065
3066 If one or more REVs are given, only branch heads on the branches
3066 If one or more REVs are given, only branch heads on the branches
3067 associated with the specified changesets are shown. This means
3067 associated with the specified changesets are shown. This means
3068 that you can use :hg:`heads foo` to see the heads on a branch
3068 that you can use :hg:`heads foo` to see the heads on a branch
3069 named ``foo``.
3069 named ``foo``.
3070
3070
3071 If -c/--closed is specified, also show branch heads marked closed
3071 If -c/--closed is specified, also show branch heads marked closed
3072 (see :hg:`commit --close-branch`).
3072 (see :hg:`commit --close-branch`).
3073
3073
3074 If STARTREV is specified, only those heads that are descendants of
3074 If STARTREV is specified, only those heads that are descendants of
3075 STARTREV will be displayed.
3075 STARTREV will be displayed.
3076
3076
3077 If -t/--topo is specified, named branch mechanics will be ignored and only
3077 If -t/--topo is specified, named branch mechanics will be ignored and only
3078 changesets without children will be shown.
3078 changesets without children will be shown.
3079
3079
3080 Returns 0 if matching heads are found, 1 if not.
3080 Returns 0 if matching heads are found, 1 if not.
3081 """
3081 """
3082
3082
3083 start = None
3083 start = None
3084 if 'rev' in opts:
3084 if 'rev' in opts:
3085 start = scmutil.revsingle(repo, opts['rev'], None).node()
3085 start = scmutil.revsingle(repo, opts['rev'], None).node()
3086
3086
3087 if opts.get('topo'):
3087 if opts.get('topo'):
3088 heads = [repo[h] for h in repo.heads(start)]
3088 heads = [repo[h] for h in repo.heads(start)]
3089 else:
3089 else:
3090 heads = []
3090 heads = []
3091 for branch in repo.branchmap():
3091 for branch in repo.branchmap():
3092 heads += repo.branchheads(branch, start, opts.get('closed'))
3092 heads += repo.branchheads(branch, start, opts.get('closed'))
3093 heads = [repo[h] for h in heads]
3093 heads = [repo[h] for h in heads]
3094
3094
3095 if branchrevs:
3095 if branchrevs:
3096 branches = set(repo[br].branch() for br in branchrevs)
3096 branches = set(repo[br].branch() for br in branchrevs)
3097 heads = [h for h in heads if h.branch() in branches]
3097 heads = [h for h in heads if h.branch() in branches]
3098
3098
3099 if opts.get('active') and branchrevs:
3099 if opts.get('active') and branchrevs:
3100 dagheads = repo.heads(start)
3100 dagheads = repo.heads(start)
3101 heads = [h for h in heads if h.node() in dagheads]
3101 heads = [h for h in heads if h.node() in dagheads]
3102
3102
3103 if branchrevs:
3103 if branchrevs:
3104 haveheads = set(h.branch() for h in heads)
3104 haveheads = set(h.branch() for h in heads)
3105 if branches - haveheads:
3105 if branches - haveheads:
3106 headless = ', '.join(b for b in branches - haveheads)
3106 headless = ', '.join(b for b in branches - haveheads)
3107 msg = _('no open branch heads found on branches %s')
3107 msg = _('no open branch heads found on branches %s')
3108 if opts.get('rev'):
3108 if opts.get('rev'):
3109 msg += _(' (started at %s)') % opts['rev']
3109 msg += _(' (started at %s)') % opts['rev']
3110 ui.warn((msg + '\n') % headless)
3110 ui.warn((msg + '\n') % headless)
3111
3111
3112 if not heads:
3112 if not heads:
3113 return 1
3113 return 1
3114
3114
3115 heads = sorted(heads, key=lambda x: -x.rev())
3115 heads = sorted(heads, key=lambda x: -x.rev())
3116 displayer = cmdutil.show_changeset(ui, repo, opts)
3116 displayer = cmdutil.show_changeset(ui, repo, opts)
3117 for ctx in heads:
3117 for ctx in heads:
3118 displayer.show(ctx)
3118 displayer.show(ctx)
3119 displayer.close()
3119 displayer.close()
3120
3120
3121 @command('help',
3121 @command('help',
3122 [('e', 'extension', None, _('show only help for extensions')),
3122 [('e', 'extension', None, _('show only help for extensions')),
3123 ('c', 'command', None, _('show only help for commands')),
3123 ('c', 'command', None, _('show only help for commands')),
3124 ('k', 'keyword', '', _('show topics matching keyword')),
3124 ('k', 'keyword', '', _('show topics matching keyword')),
3125 ],
3125 ],
3126 _('[-ec] [TOPIC]'))
3126 _('[-ec] [TOPIC]'))
3127 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3127 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3128 """show help for a given topic or a help overview
3128 """show help for a given topic or a help overview
3129
3129
3130 With no arguments, print a list of commands with short help messages.
3130 With no arguments, print a list of commands with short help messages.
3131
3131
3132 Given a topic, extension, or command name, print help for that
3132 Given a topic, extension, or command name, print help for that
3133 topic.
3133 topic.
3134
3134
3135 Returns 0 if successful.
3135 Returns 0 if successful.
3136 """
3136 """
3137
3137
3138 textwidth = min(ui.termwidth(), 80) - 2
3138 textwidth = min(ui.termwidth(), 80) - 2
3139
3139
3140 def helpcmd(name):
3140 def helpcmd(name):
3141 try:
3141 try:
3142 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3142 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3143 except error.AmbiguousCommand, inst:
3143 except error.AmbiguousCommand, inst:
3144 # py3k fix: except vars can't be used outside the scope of the
3144 # py3k fix: except vars can't be used outside the scope of the
3145 # except block, nor can be used inside a lambda. python issue4617
3145 # except block, nor can be used inside a lambda. python issue4617
3146 prefix = inst.args[0]
3146 prefix = inst.args[0]
3147 select = lambda c: c.lstrip('^').startswith(prefix)
3147 select = lambda c: c.lstrip('^').startswith(prefix)
3148 rst = helplist(select)
3148 rst = helplist(select)
3149 return rst
3149 return rst
3150
3150
3151 rst = []
3151 rst = []
3152
3152
3153 # check if it's an invalid alias and display its error if it is
3153 # check if it's an invalid alias and display its error if it is
3154 if getattr(entry[0], 'badalias', False):
3154 if getattr(entry[0], 'badalias', False):
3155 if not unknowncmd:
3155 if not unknowncmd:
3156 ui.pushbuffer()
3156 ui.pushbuffer()
3157 entry[0](ui)
3157 entry[0](ui)
3158 rst.append(ui.popbuffer())
3158 rst.append(ui.popbuffer())
3159 return rst
3159 return rst
3160
3160
3161 # synopsis
3161 # synopsis
3162 if len(entry) > 2:
3162 if len(entry) > 2:
3163 if entry[2].startswith('hg'):
3163 if entry[2].startswith('hg'):
3164 rst.append("%s\n" % entry[2])
3164 rst.append("%s\n" % entry[2])
3165 else:
3165 else:
3166 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3166 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3167 else:
3167 else:
3168 rst.append('hg %s\n' % aliases[0])
3168 rst.append('hg %s\n' % aliases[0])
3169 # aliases
3169 # aliases
3170 if full and not ui.quiet and len(aliases) > 1:
3170 if full and not ui.quiet and len(aliases) > 1:
3171 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3171 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3172 rst.append('\n')
3172 rst.append('\n')
3173
3173
3174 # description
3174 # description
3175 doc = gettext(entry[0].__doc__)
3175 doc = gettext(entry[0].__doc__)
3176 if not doc:
3176 if not doc:
3177 doc = _("(no help text available)")
3177 doc = _("(no help text available)")
3178 if util.safehasattr(entry[0], 'definition'): # aliased command
3178 if util.safehasattr(entry[0], 'definition'): # aliased command
3179 if entry[0].definition.startswith('!'): # shell alias
3179 if entry[0].definition.startswith('!'): # shell alias
3180 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3180 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3181 else:
3181 else:
3182 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3182 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3183 doc = doc.splitlines(True)
3183 doc = doc.splitlines(True)
3184 if ui.quiet or not full:
3184 if ui.quiet or not full:
3185 rst.append(doc[0])
3185 rst.append(doc[0])
3186 else:
3186 else:
3187 rst.extend(doc)
3187 rst.extend(doc)
3188 rst.append('\n')
3188 rst.append('\n')
3189
3189
3190 # check if this command shadows a non-trivial (multi-line)
3190 # check if this command shadows a non-trivial (multi-line)
3191 # extension help text
3191 # extension help text
3192 try:
3192 try:
3193 mod = extensions.find(name)
3193 mod = extensions.find(name)
3194 doc = gettext(mod.__doc__) or ''
3194 doc = gettext(mod.__doc__) or ''
3195 if '\n' in doc.strip():
3195 if '\n' in doc.strip():
3196 msg = _('use "hg help -e %s" to show help for '
3196 msg = _('use "hg help -e %s" to show help for '
3197 'the %s extension') % (name, name)
3197 'the %s extension') % (name, name)
3198 rst.append('\n%s\n' % msg)
3198 rst.append('\n%s\n' % msg)
3199 except KeyError:
3199 except KeyError:
3200 pass
3200 pass
3201
3201
3202 # options
3202 # options
3203 if not ui.quiet and entry[1]:
3203 if not ui.quiet and entry[1]:
3204 rst.append('\n%s\n\n' % _("options:"))
3204 rst.append('\n%s\n\n' % _("options:"))
3205 rst.append(help.optrst(entry[1], ui.verbose))
3205 rst.append(help.optrst(entry[1], ui.verbose))
3206
3206
3207 if ui.verbose:
3207 if ui.verbose:
3208 rst.append('\n%s\n\n' % _("global options:"))
3208 rst.append('\n%s\n\n' % _("global options:"))
3209 rst.append(help.optrst(globalopts, ui.verbose))
3209 rst.append(help.optrst(globalopts, ui.verbose))
3210
3210
3211 if not ui.verbose:
3211 if not ui.verbose:
3212 if not full:
3212 if not full:
3213 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3213 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3214 % name)
3214 % name)
3215 elif not ui.quiet:
3215 elif not ui.quiet:
3216 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3216 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3217 % name)
3217 % name)
3218 return rst
3218 return rst
3219
3219
3220
3220
3221 def helplist(select=None):
3221 def helplist(select=None):
3222 # list of commands
3222 # list of commands
3223 if name == "shortlist":
3223 if name == "shortlist":
3224 header = _('basic commands:\n\n')
3224 header = _('basic commands:\n\n')
3225 else:
3225 else:
3226 header = _('list of commands:\n\n')
3226 header = _('list of commands:\n\n')
3227
3227
3228 h = {}
3228 h = {}
3229 cmds = {}
3229 cmds = {}
3230 for c, e in table.iteritems():
3230 for c, e in table.iteritems():
3231 f = c.split("|", 1)[0]
3231 f = c.split("|", 1)[0]
3232 if select and not select(f):
3232 if select and not select(f):
3233 continue
3233 continue
3234 if (not select and name != 'shortlist' and
3234 if (not select and name != 'shortlist' and
3235 e[0].__module__ != __name__):
3235 e[0].__module__ != __name__):
3236 continue
3236 continue
3237 if name == "shortlist" and not f.startswith("^"):
3237 if name == "shortlist" and not f.startswith("^"):
3238 continue
3238 continue
3239 f = f.lstrip("^")
3239 f = f.lstrip("^")
3240 if not ui.debugflag and f.startswith("debug"):
3240 if not ui.debugflag and f.startswith("debug"):
3241 continue
3241 continue
3242 doc = e[0].__doc__
3242 doc = e[0].__doc__
3243 if doc and 'DEPRECATED' in doc and not ui.verbose:
3243 if doc and 'DEPRECATED' in doc and not ui.verbose:
3244 continue
3244 continue
3245 doc = gettext(doc)
3245 doc = gettext(doc)
3246 if not doc:
3246 if not doc:
3247 doc = _("(no help text available)")
3247 doc = _("(no help text available)")
3248 h[f] = doc.splitlines()[0].rstrip()
3248 h[f] = doc.splitlines()[0].rstrip()
3249 cmds[f] = c.lstrip("^")
3249 cmds[f] = c.lstrip("^")
3250
3250
3251 rst = []
3251 rst = []
3252 if not h:
3252 if not h:
3253 if not ui.quiet:
3253 if not ui.quiet:
3254 rst.append(_('no commands defined\n'))
3254 rst.append(_('no commands defined\n'))
3255 return rst
3255 return rst
3256
3256
3257 if not ui.quiet:
3257 if not ui.quiet:
3258 rst.append(header)
3258 rst.append(header)
3259 fns = sorted(h)
3259 fns = sorted(h)
3260 for f in fns:
3260 for f in fns:
3261 if ui.verbose:
3261 if ui.verbose:
3262 commands = cmds[f].replace("|",", ")
3262 commands = cmds[f].replace("|",", ")
3263 rst.append(" :%s: %s\n" % (commands, h[f]))
3263 rst.append(" :%s: %s\n" % (commands, h[f]))
3264 else:
3264 else:
3265 rst.append(' :%s: %s\n' % (f, h[f]))
3265 rst.append(' :%s: %s\n' % (f, h[f]))
3266
3266
3267 if not name:
3267 if not name:
3268 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3268 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3269 if exts:
3269 if exts:
3270 rst.append('\n')
3270 rst.append('\n')
3271 rst.extend(exts)
3271 rst.extend(exts)
3272
3272
3273 rst.append(_("\nadditional help topics:\n\n"))
3273 rst.append(_("\nadditional help topics:\n\n"))
3274 topics = []
3274 topics = []
3275 for names, header, doc in help.helptable:
3275 for names, header, doc in help.helptable:
3276 topics.append((sorted(names, key=len, reverse=True)[0], header))
3276 topics.append((sorted(names, key=len, reverse=True)[0], header))
3277 for t, desc in topics:
3277 for t, desc in topics:
3278 rst.append(" :%s: %s\n" % (t, desc))
3278 rst.append(" :%s: %s\n" % (t, desc))
3279
3279
3280 optlist = []
3280 optlist = []
3281 if not ui.quiet:
3281 if not ui.quiet:
3282 if ui.verbose:
3282 if ui.verbose:
3283 optlist.append((_("global options:"), globalopts))
3283 optlist.append((_("global options:"), globalopts))
3284 if name == 'shortlist':
3284 if name == 'shortlist':
3285 optlist.append((_('use "hg help" for the full list '
3285 optlist.append((_('use "hg help" for the full list '
3286 'of commands'), ()))
3286 'of commands'), ()))
3287 else:
3287 else:
3288 if name == 'shortlist':
3288 if name == 'shortlist':
3289 msg = _('use "hg help" for the full list of commands '
3289 msg = _('use "hg help" for the full list of commands '
3290 'or "hg -v" for details')
3290 'or "hg -v" for details')
3291 elif name and not full:
3291 elif name and not full:
3292 msg = _('use "hg help %s" to show the full help '
3292 msg = _('use "hg help %s" to show the full help '
3293 'text') % name
3293 'text') % name
3294 else:
3294 else:
3295 msg = _('use "hg -v help%s" to show builtin aliases and '
3295 msg = _('use "hg -v help%s" to show builtin aliases and '
3296 'global options') % (name and " " + name or "")
3296 'global options') % (name and " " + name or "")
3297 optlist.append((msg, ()))
3297 optlist.append((msg, ()))
3298
3298
3299 if optlist:
3299 if optlist:
3300 for title, options in optlist:
3300 for title, options in optlist:
3301 rst.append('\n%s\n' % title)
3301 rst.append('\n%s\n' % title)
3302 if options:
3302 if options:
3303 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3303 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3304 return rst
3304 return rst
3305
3305
3306 def helptopic(name):
3306 def helptopic(name):
3307 for names, header, doc in help.helptable:
3307 for names, header, doc in help.helptable:
3308 if name in names:
3308 if name in names:
3309 break
3309 break
3310 else:
3310 else:
3311 raise error.UnknownCommand(name)
3311 raise error.UnknownCommand(name)
3312
3312
3313 rst = ["%s\n\n" % header]
3313 rst = ["%s\n\n" % header]
3314 # description
3314 # description
3315 if not doc:
3315 if not doc:
3316 rst.append(" %s\n" % _("(no help text available)"))
3316 rst.append(" %s\n" % _("(no help text available)"))
3317 if util.safehasattr(doc, '__call__'):
3317 if util.safehasattr(doc, '__call__'):
3318 rst += [" %s\n" % l for l in doc().splitlines()]
3318 rst += [" %s\n" % l for l in doc().splitlines()]
3319
3319
3320 try:
3320 try:
3321 cmdutil.findcmd(name, table)
3321 cmdutil.findcmd(name, table)
3322 rst.append(_('\nuse "hg help -c %s" to see help for '
3322 rst.append(_('\nuse "hg help -c %s" to see help for '
3323 'the %s command\n') % (name, name))
3323 'the %s command\n') % (name, name))
3324 except error.UnknownCommand:
3324 except error.UnknownCommand:
3325 pass
3325 pass
3326 return rst
3326 return rst
3327
3327
3328 def helpext(name):
3328 def helpext(name):
3329 try:
3329 try:
3330 mod = extensions.find(name)
3330 mod = extensions.find(name)
3331 doc = gettext(mod.__doc__) or _('no help text available')
3331 doc = gettext(mod.__doc__) or _('no help text available')
3332 except KeyError:
3332 except KeyError:
3333 mod = None
3333 mod = None
3334 doc = extensions.disabledext(name)
3334 doc = extensions.disabledext(name)
3335 if not doc:
3335 if not doc:
3336 raise error.UnknownCommand(name)
3336 raise error.UnknownCommand(name)
3337
3337
3338 if '\n' not in doc:
3338 if '\n' not in doc:
3339 head, tail = doc, ""
3339 head, tail = doc, ""
3340 else:
3340 else:
3341 head, tail = doc.split('\n', 1)
3341 head, tail = doc.split('\n', 1)
3342 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3342 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3343 if tail:
3343 if tail:
3344 rst.extend(tail.splitlines(True))
3344 rst.extend(tail.splitlines(True))
3345 rst.append('\n')
3345 rst.append('\n')
3346
3346
3347 if mod:
3347 if mod:
3348 try:
3348 try:
3349 ct = mod.cmdtable
3349 ct = mod.cmdtable
3350 except AttributeError:
3350 except AttributeError:
3351 ct = {}
3351 ct = {}
3352 modcmds = set([c.split('|', 1)[0] for c in ct])
3352 modcmds = set([c.split('|', 1)[0] for c in ct])
3353 rst.extend(helplist(modcmds.__contains__))
3353 rst.extend(helplist(modcmds.__contains__))
3354 else:
3354 else:
3355 rst.append(_('use "hg help extensions" for information on enabling '
3355 rst.append(_('use "hg help extensions" for information on enabling '
3356 'extensions\n'))
3356 'extensions\n'))
3357 return rst
3357 return rst
3358
3358
3359 def helpextcmd(name):
3359 def helpextcmd(name):
3360 cmd, ext, mod = extensions.disabledcmd(ui, name,
3360 cmd, ext, mod = extensions.disabledcmd(ui, name,
3361 ui.configbool('ui', 'strict'))
3361 ui.configbool('ui', 'strict'))
3362 doc = gettext(mod.__doc__).splitlines()[0]
3362 doc = gettext(mod.__doc__).splitlines()[0]
3363
3363
3364 rst = help.listexts(_("'%s' is provided by the following "
3364 rst = help.listexts(_("'%s' is provided by the following "
3365 "extension:") % cmd, {ext: doc}, indent=4)
3365 "extension:") % cmd, {ext: doc}, indent=4)
3366 rst.append('\n')
3366 rst.append('\n')
3367 rst.append(_('use "hg help extensions" for information on enabling '
3367 rst.append(_('use "hg help extensions" for information on enabling '
3368 'extensions\n'))
3368 'extensions\n'))
3369 return rst
3369 return rst
3370
3370
3371
3371
3372 rst = []
3372 rst = []
3373 kw = opts.get('keyword')
3373 kw = opts.get('keyword')
3374 if kw:
3374 if kw:
3375 matches = help.topicmatch(kw)
3375 matches = help.topicmatch(kw)
3376 for t, title in (('topics', _('Topics')),
3376 for t, title in (('topics', _('Topics')),
3377 ('commands', _('Commands')),
3377 ('commands', _('Commands')),
3378 ('extensions', _('Extensions')),
3378 ('extensions', _('Extensions')),
3379 ('extensioncommands', _('Extension Commands'))):
3379 ('extensioncommands', _('Extension Commands'))):
3380 if matches[t]:
3380 if matches[t]:
3381 rst.append('%s:\n\n' % title)
3381 rst.append('%s:\n\n' % title)
3382 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3382 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3383 rst.append('\n')
3383 rst.append('\n')
3384 elif name and name != 'shortlist':
3384 elif name and name != 'shortlist':
3385 i = None
3385 i = None
3386 if unknowncmd:
3386 if unknowncmd:
3387 queries = (helpextcmd,)
3387 queries = (helpextcmd,)
3388 elif opts.get('extension'):
3388 elif opts.get('extension'):
3389 queries = (helpext,)
3389 queries = (helpext,)
3390 elif opts.get('command'):
3390 elif opts.get('command'):
3391 queries = (helpcmd,)
3391 queries = (helpcmd,)
3392 else:
3392 else:
3393 queries = (helptopic, helpcmd, helpext, helpextcmd)
3393 queries = (helptopic, helpcmd, helpext, helpextcmd)
3394 for f in queries:
3394 for f in queries:
3395 try:
3395 try:
3396 rst = f(name)
3396 rst = f(name)
3397 i = None
3397 i = None
3398 break
3398 break
3399 except error.UnknownCommand, inst:
3399 except error.UnknownCommand, inst:
3400 i = inst
3400 i = inst
3401 if i:
3401 if i:
3402 raise i
3402 raise i
3403 else:
3403 else:
3404 # program name
3404 # program name
3405 if not ui.quiet:
3405 if not ui.quiet:
3406 rst = [_("Mercurial Distributed SCM\n"), '\n']
3406 rst = [_("Mercurial Distributed SCM\n"), '\n']
3407 rst.extend(helplist())
3407 rst.extend(helplist())
3408
3408
3409 keep = ui.verbose and ['verbose'] or []
3409 keep = ui.verbose and ['verbose'] or []
3410 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3410 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3411 ui.write(formatted)
3411 ui.write(formatted)
3412
3412
3413
3413
3414 @command('identify|id',
3414 @command('identify|id',
3415 [('r', 'rev', '',
3415 [('r', 'rev', '',
3416 _('identify the specified revision'), _('REV')),
3416 _('identify the specified revision'), _('REV')),
3417 ('n', 'num', None, _('show local revision number')),
3417 ('n', 'num', None, _('show local revision number')),
3418 ('i', 'id', None, _('show global revision id')),
3418 ('i', 'id', None, _('show global revision id')),
3419 ('b', 'branch', None, _('show branch')),
3419 ('b', 'branch', None, _('show branch')),
3420 ('t', 'tags', None, _('show tags')),
3420 ('t', 'tags', None, _('show tags')),
3421 ('B', 'bookmarks', None, _('show bookmarks')),
3421 ('B', 'bookmarks', None, _('show bookmarks')),
3422 ] + remoteopts,
3422 ] + remoteopts,
3423 _('[-nibtB] [-r REV] [SOURCE]'))
3423 _('[-nibtB] [-r REV] [SOURCE]'))
3424 def identify(ui, repo, source=None, rev=None,
3424 def identify(ui, repo, source=None, rev=None,
3425 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3425 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3426 """identify the working copy or specified revision
3426 """identify the working copy or specified revision
3427
3427
3428 Print a summary identifying the repository state at REV using one or
3428 Print a summary identifying the repository state at REV using one or
3429 two parent hash identifiers, followed by a "+" if the working
3429 two parent hash identifiers, followed by a "+" if the working
3430 directory has uncommitted changes, the branch name (if not default),
3430 directory has uncommitted changes, the branch name (if not default),
3431 a list of tags, and a list of bookmarks.
3431 a list of tags, and a list of bookmarks.
3432
3432
3433 When REV is not given, print a summary of the current state of the
3433 When REV is not given, print a summary of the current state of the
3434 repository.
3434 repository.
3435
3435
3436 Specifying a path to a repository root or Mercurial bundle will
3436 Specifying a path to a repository root or Mercurial bundle will
3437 cause lookup to operate on that repository/bundle.
3437 cause lookup to operate on that repository/bundle.
3438
3438
3439 .. container:: verbose
3439 .. container:: verbose
3440
3440
3441 Examples:
3441 Examples:
3442
3442
3443 - generate a build identifier for the working directory::
3443 - generate a build identifier for the working directory::
3444
3444
3445 hg id --id > build-id.dat
3445 hg id --id > build-id.dat
3446
3446
3447 - find the revision corresponding to a tag::
3447 - find the revision corresponding to a tag::
3448
3448
3449 hg id -n -r 1.3
3449 hg id -n -r 1.3
3450
3450
3451 - check the most recent revision of a remote repository::
3451 - check the most recent revision of a remote repository::
3452
3452
3453 hg id -r tip http://selenic.com/hg/
3453 hg id -r tip http://selenic.com/hg/
3454
3454
3455 Returns 0 if successful.
3455 Returns 0 if successful.
3456 """
3456 """
3457
3457
3458 if not repo and not source:
3458 if not repo and not source:
3459 raise util.Abort(_("there is no Mercurial repository here "
3459 raise util.Abort(_("there is no Mercurial repository here "
3460 "(.hg not found)"))
3460 "(.hg not found)"))
3461
3461
3462 hexfunc = ui.debugflag and hex or short
3462 hexfunc = ui.debugflag and hex or short
3463 default = not (num or id or branch or tags or bookmarks)
3463 default = not (num or id or branch or tags or bookmarks)
3464 output = []
3464 output = []
3465 revs = []
3465 revs = []
3466
3466
3467 if source:
3467 if source:
3468 source, branches = hg.parseurl(ui.expandpath(source))
3468 source, branches = hg.parseurl(ui.expandpath(source))
3469 peer = hg.peer(ui, opts, source)
3469 peer = hg.peer(ui, opts, source)
3470 repo = peer.local()
3470 repo = peer.local()
3471 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3471 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3472
3472
3473 if not repo:
3473 if not repo:
3474 if num or branch or tags:
3474 if num or branch or tags:
3475 raise util.Abort(
3475 raise util.Abort(
3476 _("can't query remote revision number, branch, or tags"))
3476 _("can't query remote revision number, branch, or tags"))
3477 if not rev and revs:
3477 if not rev and revs:
3478 rev = revs[0]
3478 rev = revs[0]
3479 if not rev:
3479 if not rev:
3480 rev = "tip"
3480 rev = "tip"
3481
3481
3482 remoterev = peer.lookup(rev)
3482 remoterev = peer.lookup(rev)
3483 if default or id:
3483 if default or id:
3484 output = [hexfunc(remoterev)]
3484 output = [hexfunc(remoterev)]
3485
3485
3486 def getbms():
3486 def getbms():
3487 bms = []
3487 bms = []
3488
3488
3489 if 'bookmarks' in peer.listkeys('namespaces'):
3489 if 'bookmarks' in peer.listkeys('namespaces'):
3490 hexremoterev = hex(remoterev)
3490 hexremoterev = hex(remoterev)
3491 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3491 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3492 if bmr == hexremoterev]
3492 if bmr == hexremoterev]
3493
3493
3494 return bms
3494 return bms
3495
3495
3496 if bookmarks:
3496 if bookmarks:
3497 output.extend(getbms())
3497 output.extend(getbms())
3498 elif default and not ui.quiet:
3498 elif default and not ui.quiet:
3499 # multiple bookmarks for a single parent separated by '/'
3499 # multiple bookmarks for a single parent separated by '/'
3500 bm = '/'.join(getbms())
3500 bm = '/'.join(getbms())
3501 if bm:
3501 if bm:
3502 output.append(bm)
3502 output.append(bm)
3503 else:
3503 else:
3504 if not rev:
3504 if not rev:
3505 ctx = repo[None]
3505 ctx = repo[None]
3506 parents = ctx.parents()
3506 parents = ctx.parents()
3507 changed = ""
3507 changed = ""
3508 if default or id or num:
3508 if default or id or num:
3509 changed = util.any(repo.status()) and "+" or ""
3509 changed = util.any(repo.status()) and "+" or ""
3510 if default or id:
3510 if default or id:
3511 output = ["%s%s" %
3511 output = ["%s%s" %
3512 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3512 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3513 if num:
3513 if num:
3514 output.append("%s%s" %
3514 output.append("%s%s" %
3515 ('+'.join([str(p.rev()) for p in parents]), changed))
3515 ('+'.join([str(p.rev()) for p in parents]), changed))
3516 else:
3516 else:
3517 ctx = scmutil.revsingle(repo, rev)
3517 ctx = scmutil.revsingle(repo, rev)
3518 if default or id:
3518 if default or id:
3519 output = [hexfunc(ctx.node())]
3519 output = [hexfunc(ctx.node())]
3520 if num:
3520 if num:
3521 output.append(str(ctx.rev()))
3521 output.append(str(ctx.rev()))
3522
3522
3523 if default and not ui.quiet:
3523 if default and not ui.quiet:
3524 b = ctx.branch()
3524 b = ctx.branch()
3525 if b != 'default':
3525 if b != 'default':
3526 output.append("(%s)" % b)
3526 output.append("(%s)" % b)
3527
3527
3528 # multiple tags for a single parent separated by '/'
3528 # multiple tags for a single parent separated by '/'
3529 t = '/'.join(ctx.tags())
3529 t = '/'.join(ctx.tags())
3530 if t:
3530 if t:
3531 output.append(t)
3531 output.append(t)
3532
3532
3533 # multiple bookmarks for a single parent separated by '/'
3533 # multiple bookmarks for a single parent separated by '/'
3534 bm = '/'.join(ctx.bookmarks())
3534 bm = '/'.join(ctx.bookmarks())
3535 if bm:
3535 if bm:
3536 output.append(bm)
3536 output.append(bm)
3537 else:
3537 else:
3538 if branch:
3538 if branch:
3539 output.append(ctx.branch())
3539 output.append(ctx.branch())
3540
3540
3541 if tags:
3541 if tags:
3542 output.extend(ctx.tags())
3542 output.extend(ctx.tags())
3543
3543
3544 if bookmarks:
3544 if bookmarks:
3545 output.extend(ctx.bookmarks())
3545 output.extend(ctx.bookmarks())
3546
3546
3547 ui.write("%s\n" % ' '.join(output))
3547 ui.write("%s\n" % ' '.join(output))
3548
3548
3549 @command('import|patch',
3549 @command('import|patch',
3550 [('p', 'strip', 1,
3550 [('p', 'strip', 1,
3551 _('directory strip option for patch. This has the same '
3551 _('directory strip option for patch. This has the same '
3552 'meaning as the corresponding patch option'), _('NUM')),
3552 'meaning as the corresponding patch option'), _('NUM')),
3553 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3553 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3554 ('e', 'edit', False, _('invoke editor on commit messages')),
3554 ('e', 'edit', False, _('invoke editor on commit messages')),
3555 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3555 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3556 ('', 'no-commit', None,
3556 ('', 'no-commit', None,
3557 _("don't commit, just update the working directory")),
3557 _("don't commit, just update the working directory")),
3558 ('', 'bypass', None,
3558 ('', 'bypass', None,
3559 _("apply patch without touching the working directory")),
3559 _("apply patch without touching the working directory")),
3560 ('', 'exact', None,
3560 ('', 'exact', None,
3561 _('apply patch to the nodes from which it was generated')),
3561 _('apply patch to the nodes from which it was generated')),
3562 ('', 'import-branch', None,
3562 ('', 'import-branch', None,
3563 _('use any branch information in patch (implied by --exact)'))] +
3563 _('use any branch information in patch (implied by --exact)'))] +
3564 commitopts + commitopts2 + similarityopts,
3564 commitopts + commitopts2 + similarityopts,
3565 _('[OPTION]... PATCH...'))
3565 _('[OPTION]... PATCH...'))
3566 def import_(ui, repo, patch1=None, *patches, **opts):
3566 def import_(ui, repo, patch1=None, *patches, **opts):
3567 """import an ordered set of patches
3567 """import an ordered set of patches
3568
3568
3569 Import a list of patches and commit them individually (unless
3569 Import a list of patches and commit them individually (unless
3570 --no-commit is specified).
3570 --no-commit is specified).
3571
3571
3572 If there are outstanding changes in the working directory, import
3572 If there are outstanding changes in the working directory, import
3573 will abort unless given the -f/--force flag.
3573 will abort unless given the -f/--force flag.
3574
3574
3575 You can import a patch straight from a mail message. Even patches
3575 You can import a patch straight from a mail message. Even patches
3576 as attachments work (to use the body part, it must have type
3576 as attachments work (to use the body part, it must have type
3577 text/plain or text/x-patch). From and Subject headers of email
3577 text/plain or text/x-patch). From and Subject headers of email
3578 message are used as default committer and commit message. All
3578 message are used as default committer and commit message. All
3579 text/plain body parts before first diff are added to commit
3579 text/plain body parts before first diff are added to commit
3580 message.
3580 message.
3581
3581
3582 If the imported patch was generated by :hg:`export`, user and
3582 If the imported patch was generated by :hg:`export`, user and
3583 description from patch override values from message headers and
3583 description from patch override values from message headers and
3584 body. Values given on command line with -m/--message and -u/--user
3584 body. Values given on command line with -m/--message and -u/--user
3585 override these.
3585 override these.
3586
3586
3587 If --exact is specified, import will set the working directory to
3587 If --exact is specified, import will set the working directory to
3588 the parent of each patch before applying it, and will abort if the
3588 the parent of each patch before applying it, and will abort if the
3589 resulting changeset has a different ID than the one recorded in
3589 resulting changeset has a different ID than the one recorded in
3590 the patch. This may happen due to character set problems or other
3590 the patch. This may happen due to character set problems or other
3591 deficiencies in the text patch format.
3591 deficiencies in the text patch format.
3592
3592
3593 Use --bypass to apply and commit patches directly to the
3593 Use --bypass to apply and commit patches directly to the
3594 repository, not touching the working directory. Without --exact,
3594 repository, not touching the working directory. Without --exact,
3595 patches will be applied on top of the working directory parent
3595 patches will be applied on top of the working directory parent
3596 revision.
3596 revision.
3597
3597
3598 With -s/--similarity, hg will attempt to discover renames and
3598 With -s/--similarity, hg will attempt to discover renames and
3599 copies in the patch in the same way as :hg:`addremove`.
3599 copies in the patch in the same way as :hg:`addremove`.
3600
3600
3601 To read a patch from standard input, use "-" as the patch name. If
3601 To read a patch from standard input, use "-" as the patch name. If
3602 a URL is specified, the patch will be downloaded from it.
3602 a URL is specified, the patch will be downloaded from it.
3603 See :hg:`help dates` for a list of formats valid for -d/--date.
3603 See :hg:`help dates` for a list of formats valid for -d/--date.
3604
3604
3605 .. container:: verbose
3605 .. container:: verbose
3606
3606
3607 Examples:
3607 Examples:
3608
3608
3609 - import a traditional patch from a website and detect renames::
3609 - import a traditional patch from a website and detect renames::
3610
3610
3611 hg import -s 80 http://example.com/bugfix.patch
3611 hg import -s 80 http://example.com/bugfix.patch
3612
3612
3613 - import a changeset from an hgweb server::
3613 - import a changeset from an hgweb server::
3614
3614
3615 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3615 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3616
3616
3617 - import all the patches in an Unix-style mbox::
3617 - import all the patches in an Unix-style mbox::
3618
3618
3619 hg import incoming-patches.mbox
3619 hg import incoming-patches.mbox
3620
3620
3621 - attempt to exactly restore an exported changeset (not always
3621 - attempt to exactly restore an exported changeset (not always
3622 possible)::
3622 possible)::
3623
3623
3624 hg import --exact proposed-fix.patch
3624 hg import --exact proposed-fix.patch
3625
3625
3626 Returns 0 on success.
3626 Returns 0 on success.
3627 """
3627 """
3628
3628
3629 if not patch1:
3629 if not patch1:
3630 raise util.Abort(_('need at least one patch to import'))
3630 raise util.Abort(_('need at least one patch to import'))
3631
3631
3632 patches = (patch1,) + patches
3632 patches = (patch1,) + patches
3633
3633
3634 date = opts.get('date')
3634 date = opts.get('date')
3635 if date:
3635 if date:
3636 opts['date'] = util.parsedate(date)
3636 opts['date'] = util.parsedate(date)
3637
3637
3638 editor = cmdutil.commiteditor
3638 editor = cmdutil.commiteditor
3639 if opts.get('edit'):
3639 if opts.get('edit'):
3640 editor = cmdutil.commitforceeditor
3640 editor = cmdutil.commitforceeditor
3641
3641
3642 update = not opts.get('bypass')
3642 update = not opts.get('bypass')
3643 if not update and opts.get('no_commit'):
3643 if not update and opts.get('no_commit'):
3644 raise util.Abort(_('cannot use --no-commit with --bypass'))
3644 raise util.Abort(_('cannot use --no-commit with --bypass'))
3645 try:
3645 try:
3646 sim = float(opts.get('similarity') or 0)
3646 sim = float(opts.get('similarity') or 0)
3647 except ValueError:
3647 except ValueError:
3648 raise util.Abort(_('similarity must be a number'))
3648 raise util.Abort(_('similarity must be a number'))
3649 if sim < 0 or sim > 100:
3649 if sim < 0 or sim > 100:
3650 raise util.Abort(_('similarity must be between 0 and 100'))
3650 raise util.Abort(_('similarity must be between 0 and 100'))
3651 if sim and not update:
3651 if sim and not update:
3652 raise util.Abort(_('cannot use --similarity with --bypass'))
3652 raise util.Abort(_('cannot use --similarity with --bypass'))
3653
3653
3654 if (opts.get('exact') or not opts.get('force')) and update:
3654 if (opts.get('exact') or not opts.get('force')) and update:
3655 cmdutil.bailifchanged(repo)
3655 cmdutil.bailifchanged(repo)
3656
3656
3657 base = opts["base"]
3657 base = opts["base"]
3658 strip = opts["strip"]
3658 strip = opts["strip"]
3659 wlock = lock = tr = None
3659 wlock = lock = tr = None
3660 msgs = []
3660 msgs = []
3661
3661
3662 def checkexact(repo, n, nodeid):
3662 def checkexact(repo, n, nodeid):
3663 if opts.get('exact') and hex(n) != nodeid:
3663 if opts.get('exact') and hex(n) != nodeid:
3664 repo.rollback()
3664 repo.rollback()
3665 raise util.Abort(_('patch is damaged or loses information'))
3665 raise util.Abort(_('patch is damaged or loses information'))
3666
3666
3667 def tryone(ui, hunk, parents):
3667 def tryone(ui, hunk, parents):
3668 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3668 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3669 patch.extract(ui, hunk)
3669 patch.extract(ui, hunk)
3670
3670
3671 if not tmpname:
3671 if not tmpname:
3672 return (None, None)
3672 return (None, None)
3673 msg = _('applied to working directory')
3673 msg = _('applied to working directory')
3674
3674
3675 try:
3675 try:
3676 cmdline_message = cmdutil.logmessage(ui, opts)
3676 cmdline_message = cmdutil.logmessage(ui, opts)
3677 if cmdline_message:
3677 if cmdline_message:
3678 # pickup the cmdline msg
3678 # pickup the cmdline msg
3679 message = cmdline_message
3679 message = cmdline_message
3680 elif message:
3680 elif message:
3681 # pickup the patch msg
3681 # pickup the patch msg
3682 message = message.strip()
3682 message = message.strip()
3683 else:
3683 else:
3684 # launch the editor
3684 # launch the editor
3685 message = None
3685 message = None
3686 ui.debug('message:\n%s\n' % message)
3686 ui.debug('message:\n%s\n' % message)
3687
3687
3688 if len(parents) == 1:
3688 if len(parents) == 1:
3689 parents.append(repo[nullid])
3689 parents.append(repo[nullid])
3690 if opts.get('exact'):
3690 if opts.get('exact'):
3691 if not nodeid or not p1:
3691 if not nodeid or not p1:
3692 raise util.Abort(_('not a Mercurial patch'))
3692 raise util.Abort(_('not a Mercurial patch'))
3693 p1 = repo[p1]
3693 p1 = repo[p1]
3694 p2 = repo[p2 or nullid]
3694 p2 = repo[p2 or nullid]
3695 elif p2:
3695 elif p2:
3696 try:
3696 try:
3697 p1 = repo[p1]
3697 p1 = repo[p1]
3698 p2 = repo[p2]
3698 p2 = repo[p2]
3699 # Without any options, consider p2 only if the
3699 # Without any options, consider p2 only if the
3700 # patch is being applied on top of the recorded
3700 # patch is being applied on top of the recorded
3701 # first parent.
3701 # first parent.
3702 if p1 != parents[0]:
3702 if p1 != parents[0]:
3703 p1 = parents[0]
3703 p1 = parents[0]
3704 p2 = repo[nullid]
3704 p2 = repo[nullid]
3705 except error.RepoError:
3705 except error.RepoError:
3706 p1, p2 = parents
3706 p1, p2 = parents
3707 else:
3707 else:
3708 p1, p2 = parents
3708 p1, p2 = parents
3709
3709
3710 n = None
3710 n = None
3711 if update:
3711 if update:
3712 if p1 != parents[0]:
3712 if p1 != parents[0]:
3713 hg.clean(repo, p1.node())
3713 hg.clean(repo, p1.node())
3714 if p2 != parents[1]:
3714 if p2 != parents[1]:
3715 repo.setparents(p1.node(), p2.node())
3715 repo.setparents(p1.node(), p2.node())
3716
3716
3717 if opts.get('exact') or opts.get('import_branch'):
3717 if opts.get('exact') or opts.get('import_branch'):
3718 repo.dirstate.setbranch(branch or 'default')
3718 repo.dirstate.setbranch(branch or 'default')
3719
3719
3720 files = set()
3720 files = set()
3721 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3721 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3722 eolmode=None, similarity=sim / 100.0)
3722 eolmode=None, similarity=sim / 100.0)
3723 files = list(files)
3723 files = list(files)
3724 if opts.get('no_commit'):
3724 if opts.get('no_commit'):
3725 if message:
3725 if message:
3726 msgs.append(message)
3726 msgs.append(message)
3727 else:
3727 else:
3728 if opts.get('exact') or p2:
3728 if opts.get('exact') or p2:
3729 # If you got here, you either use --force and know what
3729 # If you got here, you either use --force and know what
3730 # you are doing or used --exact or a merge patch while
3730 # you are doing or used --exact or a merge patch while
3731 # being updated to its first parent.
3731 # being updated to its first parent.
3732 m = None
3732 m = None
3733 else:
3733 else:
3734 m = scmutil.matchfiles(repo, files or [])
3734 m = scmutil.matchfiles(repo, files or [])
3735 n = repo.commit(message, opts.get('user') or user,
3735 n = repo.commit(message, opts.get('user') or user,
3736 opts.get('date') or date, match=m,
3736 opts.get('date') or date, match=m,
3737 editor=editor)
3737 editor=editor)
3738 checkexact(repo, n, nodeid)
3738 checkexact(repo, n, nodeid)
3739 else:
3739 else:
3740 if opts.get('exact') or opts.get('import_branch'):
3740 if opts.get('exact') or opts.get('import_branch'):
3741 branch = branch or 'default'
3741 branch = branch or 'default'
3742 else:
3742 else:
3743 branch = p1.branch()
3743 branch = p1.branch()
3744 store = patch.filestore()
3744 store = patch.filestore()
3745 try:
3745 try:
3746 files = set()
3746 files = set()
3747 try:
3747 try:
3748 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3748 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3749 files, eolmode=None)
3749 files, eolmode=None)
3750 except patch.PatchError, e:
3750 except patch.PatchError, e:
3751 raise util.Abort(str(e))
3751 raise util.Abort(str(e))
3752 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3752 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3753 message,
3753 message,
3754 opts.get('user') or user,
3754 opts.get('user') or user,
3755 opts.get('date') or date,
3755 opts.get('date') or date,
3756 branch, files, store,
3756 branch, files, store,
3757 editor=cmdutil.commiteditor)
3757 editor=cmdutil.commiteditor)
3758 repo.savecommitmessage(memctx.description())
3758 repo.savecommitmessage(memctx.description())
3759 n = memctx.commit()
3759 n = memctx.commit()
3760 checkexact(repo, n, nodeid)
3760 checkexact(repo, n, nodeid)
3761 finally:
3761 finally:
3762 store.close()
3762 store.close()
3763 if n:
3763 if n:
3764 # i18n: refers to a short changeset id
3764 # i18n: refers to a short changeset id
3765 msg = _('created %s') % short(n)
3765 msg = _('created %s') % short(n)
3766 return (msg, n)
3766 return (msg, n)
3767 finally:
3767 finally:
3768 os.unlink(tmpname)
3768 os.unlink(tmpname)
3769
3769
3770 try:
3770 try:
3771 try:
3771 try:
3772 wlock = repo.wlock()
3772 wlock = repo.wlock()
3773 if not opts.get('no_commit'):
3773 if not opts.get('no_commit'):
3774 lock = repo.lock()
3774 lock = repo.lock()
3775 tr = repo.transaction('import')
3775 tr = repo.transaction('import')
3776 parents = repo.parents()
3776 parents = repo.parents()
3777 for patchurl in patches:
3777 for patchurl in patches:
3778 if patchurl == '-':
3778 if patchurl == '-':
3779 ui.status(_('applying patch from stdin\n'))
3779 ui.status(_('applying patch from stdin\n'))
3780 patchfile = ui.fin
3780 patchfile = ui.fin
3781 patchurl = 'stdin' # for error message
3781 patchurl = 'stdin' # for error message
3782 else:
3782 else:
3783 patchurl = os.path.join(base, patchurl)
3783 patchurl = os.path.join(base, patchurl)
3784 ui.status(_('applying %s\n') % patchurl)
3784 ui.status(_('applying %s\n') % patchurl)
3785 patchfile = url.open(ui, patchurl)
3785 patchfile = url.open(ui, patchurl)
3786
3786
3787 haspatch = False
3787 haspatch = False
3788 for hunk in patch.split(patchfile):
3788 for hunk in patch.split(patchfile):
3789 (msg, node) = tryone(ui, hunk, parents)
3789 (msg, node) = tryone(ui, hunk, parents)
3790 if msg:
3790 if msg:
3791 haspatch = True
3791 haspatch = True
3792 ui.note(msg + '\n')
3792 ui.note(msg + '\n')
3793 if update or opts.get('exact'):
3793 if update or opts.get('exact'):
3794 parents = repo.parents()
3794 parents = repo.parents()
3795 else:
3795 else:
3796 parents = [repo[node]]
3796 parents = [repo[node]]
3797
3797
3798 if not haspatch:
3798 if not haspatch:
3799 raise util.Abort(_('%s: no diffs found') % patchurl)
3799 raise util.Abort(_('%s: no diffs found') % patchurl)
3800
3800
3801 if tr:
3801 if tr:
3802 tr.close()
3802 tr.close()
3803 if msgs:
3803 if msgs:
3804 repo.savecommitmessage('\n* * *\n'.join(msgs))
3804 repo.savecommitmessage('\n* * *\n'.join(msgs))
3805 except: # re-raises
3805 except: # re-raises
3806 # wlock.release() indirectly calls dirstate.write(): since
3806 # wlock.release() indirectly calls dirstate.write(): since
3807 # we're crashing, we do not want to change the working dir
3807 # we're crashing, we do not want to change the working dir
3808 # parent after all, so make sure it writes nothing
3808 # parent after all, so make sure it writes nothing
3809 repo.dirstate.invalidate()
3809 repo.dirstate.invalidate()
3810 raise
3810 raise
3811 finally:
3811 finally:
3812 if tr:
3812 if tr:
3813 tr.release()
3813 tr.release()
3814 release(lock, wlock)
3814 release(lock, wlock)
3815
3815
3816 @command('incoming|in',
3816 @command('incoming|in',
3817 [('f', 'force', None,
3817 [('f', 'force', None,
3818 _('run even if remote repository is unrelated')),
3818 _('run even if remote repository is unrelated')),
3819 ('n', 'newest-first', None, _('show newest record first')),
3819 ('n', 'newest-first', None, _('show newest record first')),
3820 ('', 'bundle', '',
3820 ('', 'bundle', '',
3821 _('file to store the bundles into'), _('FILE')),
3821 _('file to store the bundles into'), _('FILE')),
3822 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3822 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3823 ('B', 'bookmarks', False, _("compare bookmarks")),
3823 ('B', 'bookmarks', False, _("compare bookmarks")),
3824 ('b', 'branch', [],
3824 ('b', 'branch', [],
3825 _('a specific branch you would like to pull'), _('BRANCH')),
3825 _('a specific branch you would like to pull'), _('BRANCH')),
3826 ] + logopts + remoteopts + subrepoopts,
3826 ] + logopts + remoteopts + subrepoopts,
3827 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3827 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3828 def incoming(ui, repo, source="default", **opts):
3828 def incoming(ui, repo, source="default", **opts):
3829 """show new changesets found in source
3829 """show new changesets found in source
3830
3830
3831 Show new changesets found in the specified path/URL or the default
3831 Show new changesets found in the specified path/URL or the default
3832 pull location. These are the changesets that would have been pulled
3832 pull location. These are the changesets that would have been pulled
3833 if a pull at the time you issued this command.
3833 if a pull at the time you issued this command.
3834
3834
3835 For remote repository, using --bundle avoids downloading the
3835 For remote repository, using --bundle avoids downloading the
3836 changesets twice if the incoming is followed by a pull.
3836 changesets twice if the incoming is followed by a pull.
3837
3837
3838 See pull for valid source format details.
3838 See pull for valid source format details.
3839
3839
3840 Returns 0 if there are incoming changes, 1 otherwise.
3840 Returns 0 if there are incoming changes, 1 otherwise.
3841 """
3841 """
3842 if opts.get('graph'):
3842 if opts.get('graph'):
3843 cmdutil.checkunsupportedgraphflags([], opts)
3843 cmdutil.checkunsupportedgraphflags([], opts)
3844 def display(other, chlist, displayer):
3844 def display(other, chlist, displayer):
3845 revdag = cmdutil.graphrevs(other, chlist, opts)
3845 revdag = cmdutil.graphrevs(other, chlist, opts)
3846 showparents = [ctx.node() for ctx in repo[None].parents()]
3846 showparents = [ctx.node() for ctx in repo[None].parents()]
3847 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3847 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3848 graphmod.asciiedges)
3848 graphmod.asciiedges)
3849
3849
3850 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3850 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3851 return 0
3851 return 0
3852
3852
3853 if opts.get('bundle') and opts.get('subrepos'):
3853 if opts.get('bundle') and opts.get('subrepos'):
3854 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3854 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3855
3855
3856 if opts.get('bookmarks'):
3856 if opts.get('bookmarks'):
3857 source, branches = hg.parseurl(ui.expandpath(source),
3857 source, branches = hg.parseurl(ui.expandpath(source),
3858 opts.get('branch'))
3858 opts.get('branch'))
3859 other = hg.peer(repo, opts, source)
3859 other = hg.peer(repo, opts, source)
3860 if 'bookmarks' not in other.listkeys('namespaces'):
3860 if 'bookmarks' not in other.listkeys('namespaces'):
3861 ui.warn(_("remote doesn't support bookmarks\n"))
3861 ui.warn(_("remote doesn't support bookmarks\n"))
3862 return 0
3862 return 0
3863 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3863 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3864 return bookmarks.diff(ui, repo, other)
3864 return bookmarks.diff(ui, repo, other)
3865
3865
3866 repo._subtoppath = ui.expandpath(source)
3866 repo._subtoppath = ui.expandpath(source)
3867 try:
3867 try:
3868 return hg.incoming(ui, repo, source, opts)
3868 return hg.incoming(ui, repo, source, opts)
3869 finally:
3869 finally:
3870 del repo._subtoppath
3870 del repo._subtoppath
3871
3871
3872
3872
3873 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3873 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3874 def init(ui, dest=".", **opts):
3874 def init(ui, dest=".", **opts):
3875 """create a new repository in the given directory
3875 """create a new repository in the given directory
3876
3876
3877 Initialize a new repository in the given directory. If the given
3877 Initialize a new repository in the given directory. If the given
3878 directory does not exist, it will be created.
3878 directory does not exist, it will be created.
3879
3879
3880 If no directory is given, the current directory is used.
3880 If no directory is given, the current directory is used.
3881
3881
3882 It is possible to specify an ``ssh://`` URL as the destination.
3882 It is possible to specify an ``ssh://`` URL as the destination.
3883 See :hg:`help urls` for more information.
3883 See :hg:`help urls` for more information.
3884
3884
3885 Returns 0 on success.
3885 Returns 0 on success.
3886 """
3886 """
3887 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3887 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3888
3888
3889 @command('locate',
3889 @command('locate',
3890 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3890 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3891 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3891 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3892 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3892 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3893 ] + walkopts,
3893 ] + walkopts,
3894 _('[OPTION]... [PATTERN]...'))
3894 _('[OPTION]... [PATTERN]...'))
3895 def locate(ui, repo, *pats, **opts):
3895 def locate(ui, repo, *pats, **opts):
3896 """locate files matching specific patterns
3896 """locate files matching specific patterns
3897
3897
3898 Print files under Mercurial control in the working directory whose
3898 Print files under Mercurial control in the working directory whose
3899 names match the given patterns.
3899 names match the given patterns.
3900
3900
3901 By default, this command searches all directories in the working
3901 By default, this command searches all directories in the working
3902 directory. To search just the current directory and its
3902 directory. To search just the current directory and its
3903 subdirectories, use "--include .".
3903 subdirectories, use "--include .".
3904
3904
3905 If no patterns are given to match, this command prints the names
3905 If no patterns are given to match, this command prints the names
3906 of all files under Mercurial control in the working directory.
3906 of all files under Mercurial control in the working directory.
3907
3907
3908 If you want to feed the output of this command into the "xargs"
3908 If you want to feed the output of this command into the "xargs"
3909 command, use the -0 option to both this command and "xargs". This
3909 command, use the -0 option to both this command and "xargs". This
3910 will avoid the problem of "xargs" treating single filenames that
3910 will avoid the problem of "xargs" treating single filenames that
3911 contain whitespace as multiple filenames.
3911 contain whitespace as multiple filenames.
3912
3912
3913 Returns 0 if a match is found, 1 otherwise.
3913 Returns 0 if a match is found, 1 otherwise.
3914 """
3914 """
3915 end = opts.get('print0') and '\0' or '\n'
3915 end = opts.get('print0') and '\0' or '\n'
3916 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3916 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3917
3917
3918 ret = 1
3918 ret = 1
3919 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3919 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3920 m.bad = lambda x, y: False
3920 m.bad = lambda x, y: False
3921 for abs in repo[rev].walk(m):
3921 for abs in repo[rev].walk(m):
3922 if not rev and abs not in repo.dirstate:
3922 if not rev and abs not in repo.dirstate:
3923 continue
3923 continue
3924 if opts.get('fullpath'):
3924 if opts.get('fullpath'):
3925 ui.write(repo.wjoin(abs), end)
3925 ui.write(repo.wjoin(abs), end)
3926 else:
3926 else:
3927 ui.write(((pats and m.rel(abs)) or abs), end)
3927 ui.write(((pats and m.rel(abs)) or abs), end)
3928 ret = 0
3928 ret = 0
3929
3929
3930 return ret
3930 return ret
3931
3931
3932 @command('^log|history',
3932 @command('^log|history',
3933 [('f', 'follow', None,
3933 [('f', 'follow', None,
3934 _('follow changeset history, or file history across copies and renames')),
3934 _('follow changeset history, or file history across copies and renames')),
3935 ('', 'follow-first', None,
3935 ('', 'follow-first', None,
3936 _('only follow the first parent of merge changesets (DEPRECATED)')),
3936 _('only follow the first parent of merge changesets (DEPRECATED)')),
3937 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3937 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3938 ('C', 'copies', None, _('show copied files')),
3938 ('C', 'copies', None, _('show copied files')),
3939 ('k', 'keyword', [],
3939 ('k', 'keyword', [],
3940 _('do case-insensitive search for a given text'), _('TEXT')),
3940 _('do case-insensitive search for a given text'), _('TEXT')),
3941 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3941 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3942 ('', 'removed', None, _('include revisions where files were removed')),
3942 ('', 'removed', None, _('include revisions where files were removed')),
3943 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3943 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3944 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3944 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3945 ('', 'only-branch', [],
3945 ('', 'only-branch', [],
3946 _('show only changesets within the given named branch (DEPRECATED)'),
3946 _('show only changesets within the given named branch (DEPRECATED)'),
3947 _('BRANCH')),
3947 _('BRANCH')),
3948 ('b', 'branch', [],
3948 ('b', 'branch', [],
3949 _('show changesets within the given named branch'), _('BRANCH')),
3949 _('show changesets within the given named branch'), _('BRANCH')),
3950 ('P', 'prune', [],
3950 ('P', 'prune', [],
3951 _('do not display revision or any of its ancestors'), _('REV')),
3951 _('do not display revision or any of its ancestors'), _('REV')),
3952 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3952 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3953 ] + logopts + walkopts,
3953 ] + logopts + walkopts,
3954 _('[OPTION]... [FILE]'))
3954 _('[OPTION]... [FILE]'))
3955 def log(ui, repo, *pats, **opts):
3955 def log(ui, repo, *pats, **opts):
3956 """show revision history of entire repository or files
3956 """show revision history of entire repository or files
3957
3957
3958 Print the revision history of the specified files or the entire
3958 Print the revision history of the specified files or the entire
3959 project.
3959 project.
3960
3960
3961 If no revision range is specified, the default is ``tip:0`` unless
3961 If no revision range is specified, the default is ``tip:0`` unless
3962 --follow is set, in which case the working directory parent is
3962 --follow is set, in which case the working directory parent is
3963 used as the starting revision.
3963 used as the starting revision.
3964
3964
3965 File history is shown without following rename or copy history of
3965 File history is shown without following rename or copy history of
3966 files. Use -f/--follow with a filename to follow history across
3966 files. Use -f/--follow with a filename to follow history across
3967 renames and copies. --follow without a filename will only show
3967 renames and copies. --follow without a filename will only show
3968 ancestors or descendants of the starting revision.
3968 ancestors or descendants of the starting revision.
3969
3969
3970 By default this command prints revision number and changeset id,
3970 By default this command prints revision number and changeset id,
3971 tags, non-trivial parents, user, date and time, and a summary for
3971 tags, non-trivial parents, user, date and time, and a summary for
3972 each commit. When the -v/--verbose switch is used, the list of
3972 each commit. When the -v/--verbose switch is used, the list of
3973 changed files and full commit message are shown.
3973 changed files and full commit message are shown.
3974
3974
3975 .. note::
3975 .. note::
3976 log -p/--patch may generate unexpected diff output for merge
3976 log -p/--patch may generate unexpected diff output for merge
3977 changesets, as it will only compare the merge changeset against
3977 changesets, as it will only compare the merge changeset against
3978 its first parent. Also, only files different from BOTH parents
3978 its first parent. Also, only files different from BOTH parents
3979 will appear in files:.
3979 will appear in files:.
3980
3980
3981 .. note::
3981 .. note::
3982 for performance reasons, log FILE may omit duplicate changes
3982 for performance reasons, log FILE may omit duplicate changes
3983 made on branches and will not show deletions. To see all
3983 made on branches and will not show deletions. To see all
3984 changes including duplicates and deletions, use the --removed
3984 changes including duplicates and deletions, use the --removed
3985 switch.
3985 switch.
3986
3986
3987 .. container:: verbose
3987 .. container:: verbose
3988
3988
3989 Some examples:
3989 Some examples:
3990
3990
3991 - changesets with full descriptions and file lists::
3991 - changesets with full descriptions and file lists::
3992
3992
3993 hg log -v
3993 hg log -v
3994
3994
3995 - changesets ancestral to the working directory::
3995 - changesets ancestral to the working directory::
3996
3996
3997 hg log -f
3997 hg log -f
3998
3998
3999 - last 10 commits on the current branch::
3999 - last 10 commits on the current branch::
4000
4000
4001 hg log -l 10 -b .
4001 hg log -l 10 -b .
4002
4002
4003 - changesets showing all modifications of a file, including removals::
4003 - changesets showing all modifications of a file, including removals::
4004
4004
4005 hg log --removed file.c
4005 hg log --removed file.c
4006
4006
4007 - all changesets that touch a directory, with diffs, excluding merges::
4007 - all changesets that touch a directory, with diffs, excluding merges::
4008
4008
4009 hg log -Mp lib/
4009 hg log -Mp lib/
4010
4010
4011 - all revision numbers that match a keyword::
4011 - all revision numbers that match a keyword::
4012
4012
4013 hg log -k bug --template "{rev}\\n"
4013 hg log -k bug --template "{rev}\\n"
4014
4014
4015 - check if a given changeset is included is a tagged release::
4015 - check if a given changeset is included is a tagged release::
4016
4016
4017 hg log -r "a21ccf and ancestor(1.9)"
4017 hg log -r "a21ccf and ancestor(1.9)"
4018
4018
4019 - find all changesets by some user in a date range::
4019 - find all changesets by some user in a date range::
4020
4020
4021 hg log -k alice -d "may 2008 to jul 2008"
4021 hg log -k alice -d "may 2008 to jul 2008"
4022
4022
4023 - summary of all changesets after the last tag::
4023 - summary of all changesets after the last tag::
4024
4024
4025 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4025 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4026
4026
4027 See :hg:`help dates` for a list of formats valid for -d/--date.
4027 See :hg:`help dates` for a list of formats valid for -d/--date.
4028
4028
4029 See :hg:`help revisions` and :hg:`help revsets` for more about
4029 See :hg:`help revisions` and :hg:`help revsets` for more about
4030 specifying revisions.
4030 specifying revisions.
4031
4031
4032 See :hg:`help templates` for more about pre-packaged styles and
4032 See :hg:`help templates` for more about pre-packaged styles and
4033 specifying custom templates.
4033 specifying custom templates.
4034
4034
4035 Returns 0 on success.
4035 Returns 0 on success.
4036 """
4036 """
4037 if opts.get('graph'):
4037 if opts.get('graph'):
4038 return cmdutil.graphlog(ui, repo, *pats, **opts)
4038 return cmdutil.graphlog(ui, repo, *pats, **opts)
4039
4039
4040 matchfn = scmutil.match(repo[None], pats, opts)
4040 matchfn = scmutil.match(repo[None], pats, opts)
4041 limit = cmdutil.loglimit(opts)
4041 limit = cmdutil.loglimit(opts)
4042 count = 0
4042 count = 0
4043
4043
4044 getrenamed, endrev = None, None
4044 getrenamed, endrev = None, None
4045 if opts.get('copies'):
4045 if opts.get('copies'):
4046 if opts.get('rev'):
4046 if opts.get('rev'):
4047 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4047 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4048 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4048 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4049
4049
4050 df = False
4050 df = False
4051 if opts["date"]:
4051 if opts["date"]:
4052 df = util.matchdate(opts["date"])
4052 df = util.matchdate(opts["date"])
4053
4053
4054 branches = opts.get('branch', []) + opts.get('only_branch', [])
4054 branches = opts.get('branch', []) + opts.get('only_branch', [])
4055 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4055 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4056
4056
4057 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4057 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4058 def prep(ctx, fns):
4058 def prep(ctx, fns):
4059 rev = ctx.rev()
4059 rev = ctx.rev()
4060 parents = [p for p in repo.changelog.parentrevs(rev)
4060 parents = [p for p in repo.changelog.parentrevs(rev)
4061 if p != nullrev]
4061 if p != nullrev]
4062 if opts.get('no_merges') and len(parents) == 2:
4062 if opts.get('no_merges') and len(parents) == 2:
4063 return
4063 return
4064 if opts.get('only_merges') and len(parents) != 2:
4064 if opts.get('only_merges') and len(parents) != 2:
4065 return
4065 return
4066 if opts.get('branch') and ctx.branch() not in opts['branch']:
4066 if opts.get('branch') and ctx.branch() not in opts['branch']:
4067 return
4067 return
4068 if not opts.get('hidden') and ctx.hidden():
4068 if not opts.get('hidden') and ctx.hidden():
4069 return
4069 return
4070 if df and not df(ctx.date()[0]):
4070 if df and not df(ctx.date()[0]):
4071 return
4071 return
4072
4072
4073 lower = encoding.lower
4073 lower = encoding.lower
4074 if opts.get('user'):
4074 if opts.get('user'):
4075 luser = lower(ctx.user())
4075 luser = lower(ctx.user())
4076 for k in [lower(x) for x in opts['user']]:
4076 for k in [lower(x) for x in opts['user']]:
4077 if (k in luser):
4077 if (k in luser):
4078 break
4078 break
4079 else:
4079 else:
4080 return
4080 return
4081 if opts.get('keyword'):
4081 if opts.get('keyword'):
4082 luser = lower(ctx.user())
4082 luser = lower(ctx.user())
4083 ldesc = lower(ctx.description())
4083 ldesc = lower(ctx.description())
4084 lfiles = lower(" ".join(ctx.files()))
4084 lfiles = lower(" ".join(ctx.files()))
4085 for k in [lower(x) for x in opts['keyword']]:
4085 for k in [lower(x) for x in opts['keyword']]:
4086 if (k in luser or k in ldesc or k in lfiles):
4086 if (k in luser or k in ldesc or k in lfiles):
4087 break
4087 break
4088 else:
4088 else:
4089 return
4089 return
4090
4090
4091 copies = None
4091 copies = None
4092 if getrenamed is not None and rev:
4092 if getrenamed is not None and rev:
4093 copies = []
4093 copies = []
4094 for fn in ctx.files():
4094 for fn in ctx.files():
4095 rename = getrenamed(fn, rev)
4095 rename = getrenamed(fn, rev)
4096 if rename:
4096 if rename:
4097 copies.append((fn, rename[0]))
4097 copies.append((fn, rename[0]))
4098
4098
4099 revmatchfn = None
4099 revmatchfn = None
4100 if opts.get('patch') or opts.get('stat'):
4100 if opts.get('patch') or opts.get('stat'):
4101 if opts.get('follow') or opts.get('follow_first'):
4101 if opts.get('follow') or opts.get('follow_first'):
4102 # note: this might be wrong when following through merges
4102 # note: this might be wrong when following through merges
4103 revmatchfn = scmutil.match(repo[None], fns, default='path')
4103 revmatchfn = scmutil.match(repo[None], fns, default='path')
4104 else:
4104 else:
4105 revmatchfn = matchfn
4105 revmatchfn = matchfn
4106
4106
4107 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4107 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4108
4108
4109 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4109 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4110 if count == limit:
4110 if count == limit:
4111 break
4111 break
4112 if displayer.flush(ctx.rev()):
4112 if displayer.flush(ctx.rev()):
4113 count += 1
4113 count += 1
4114 displayer.close()
4114 displayer.close()
4115
4115
4116 @command('manifest',
4116 @command('manifest',
4117 [('r', 'rev', '', _('revision to display'), _('REV')),
4117 [('r', 'rev', '', _('revision to display'), _('REV')),
4118 ('', 'all', False, _("list files from all revisions"))],
4118 ('', 'all', False, _("list files from all revisions"))],
4119 _('[-r REV]'))
4119 _('[-r REV]'))
4120 def manifest(ui, repo, node=None, rev=None, **opts):
4120 def manifest(ui, repo, node=None, rev=None, **opts):
4121 """output the current or given revision of the project manifest
4121 """output the current or given revision of the project manifest
4122
4122
4123 Print a list of version controlled files for the given revision.
4123 Print a list of version controlled files for the given revision.
4124 If no revision is given, the first parent of the working directory
4124 If no revision is given, the first parent of the working directory
4125 is used, or the null revision if no revision is checked out.
4125 is used, or the null revision if no revision is checked out.
4126
4126
4127 With -v, print file permissions, symlink and executable bits.
4127 With -v, print file permissions, symlink and executable bits.
4128 With --debug, print file revision hashes.
4128 With --debug, print file revision hashes.
4129
4129
4130 If option --all is specified, the list of all files from all revisions
4130 If option --all is specified, the list of all files from all revisions
4131 is printed. This includes deleted and renamed files.
4131 is printed. This includes deleted and renamed files.
4132
4132
4133 Returns 0 on success.
4133 Returns 0 on success.
4134 """
4134 """
4135 if opts.get('all'):
4135 if opts.get('all'):
4136 if rev or node:
4136 if rev or node:
4137 raise util.Abort(_("can't specify a revision with --all"))
4137 raise util.Abort(_("can't specify a revision with --all"))
4138
4138
4139 res = []
4139 res = []
4140 prefix = "data/"
4140 prefix = "data/"
4141 suffix = ".i"
4141 suffix = ".i"
4142 plen = len(prefix)
4142 plen = len(prefix)
4143 slen = len(suffix)
4143 slen = len(suffix)
4144 lock = repo.lock()
4144 lock = repo.lock()
4145 try:
4145 try:
4146 for fn, b, size in repo.store.datafiles():
4146 for fn, b, size in repo.store.datafiles():
4147 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4147 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4148 res.append(fn[plen:-slen])
4148 res.append(fn[plen:-slen])
4149 finally:
4149 finally:
4150 lock.release()
4150 lock.release()
4151 for f in sorted(res):
4151 for f in sorted(res):
4152 ui.write("%s\n" % f)
4152 ui.write("%s\n" % f)
4153 return
4153 return
4154
4154
4155 if rev and node:
4155 if rev and node:
4156 raise util.Abort(_("please specify just one revision"))
4156 raise util.Abort(_("please specify just one revision"))
4157
4157
4158 if not node:
4158 if not node:
4159 node = rev
4159 node = rev
4160
4160
4161 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4161 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4162 ctx = scmutil.revsingle(repo, node)
4162 ctx = scmutil.revsingle(repo, node)
4163 for f in ctx:
4163 for f in ctx:
4164 if ui.debugflag:
4164 if ui.debugflag:
4165 ui.write("%40s " % hex(ctx.manifest()[f]))
4165 ui.write("%40s " % hex(ctx.manifest()[f]))
4166 if ui.verbose:
4166 if ui.verbose:
4167 ui.write(decor[ctx.flags(f)])
4167 ui.write(decor[ctx.flags(f)])
4168 ui.write("%s\n" % f)
4168 ui.write("%s\n" % f)
4169
4169
4170 @command('^merge',
4170 @command('^merge',
4171 [('f', 'force', None, _('force a merge with outstanding changes')),
4171 [('f', 'force', None, _('force a merge with outstanding changes')),
4172 ('r', 'rev', '', _('revision to merge'), _('REV')),
4172 ('r', 'rev', '', _('revision to merge'), _('REV')),
4173 ('P', 'preview', None,
4173 ('P', 'preview', None,
4174 _('review revisions to merge (no merge is performed)'))
4174 _('review revisions to merge (no merge is performed)'))
4175 ] + mergetoolopts,
4175 ] + mergetoolopts,
4176 _('[-P] [-f] [[-r] REV]'))
4176 _('[-P] [-f] [[-r] REV]'))
4177 def merge(ui, repo, node=None, **opts):
4177 def merge(ui, repo, node=None, **opts):
4178 """merge working directory with another revision
4178 """merge working directory with another revision
4179
4179
4180 The current working directory is updated with all changes made in
4180 The current working directory is updated with all changes made in
4181 the requested revision since the last common predecessor revision.
4181 the requested revision since the last common predecessor revision.
4182
4182
4183 Files that changed between either parent are marked as changed for
4183 Files that changed between either parent are marked as changed for
4184 the next commit and a commit must be performed before any further
4184 the next commit and a commit must be performed before any further
4185 updates to the repository are allowed. The next commit will have
4185 updates to the repository are allowed. The next commit will have
4186 two parents.
4186 two parents.
4187
4187
4188 ``--tool`` can be used to specify the merge tool used for file
4188 ``--tool`` can be used to specify the merge tool used for file
4189 merges. It overrides the HGMERGE environment variable and your
4189 merges. It overrides the HGMERGE environment variable and your
4190 configuration files. See :hg:`help merge-tools` for options.
4190 configuration files. See :hg:`help merge-tools` for options.
4191
4191
4192 If no revision is specified, the working directory's parent is a
4192 If no revision is specified, the working directory's parent is a
4193 head revision, and the current branch contains exactly one other
4193 head revision, and the current branch contains exactly one other
4194 head, the other head is merged with by default. Otherwise, an
4194 head, the other head is merged with by default. Otherwise, an
4195 explicit revision with which to merge with must be provided.
4195 explicit revision with which to merge with must be provided.
4196
4196
4197 :hg:`resolve` must be used to resolve unresolved files.
4197 :hg:`resolve` must be used to resolve unresolved files.
4198
4198
4199 To undo an uncommitted merge, use :hg:`update --clean .` which
4199 To undo an uncommitted merge, use :hg:`update --clean .` which
4200 will check out a clean copy of the original merge parent, losing
4200 will check out a clean copy of the original merge parent, losing
4201 all changes.
4201 all changes.
4202
4202
4203 Returns 0 on success, 1 if there are unresolved files.
4203 Returns 0 on success, 1 if there are unresolved files.
4204 """
4204 """
4205
4205
4206 if opts.get('rev') and node:
4206 if opts.get('rev') and node:
4207 raise util.Abort(_("please specify just one revision"))
4207 raise util.Abort(_("please specify just one revision"))
4208 if not node:
4208 if not node:
4209 node = opts.get('rev')
4209 node = opts.get('rev')
4210
4210
4211 if node:
4211 if node:
4212 node = scmutil.revsingle(repo, node).node()
4212 node = scmutil.revsingle(repo, node).node()
4213
4213
4214 if not node and repo._bookmarkcurrent:
4214 if not node and repo._bookmarkcurrent:
4215 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4215 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4216 curhead = repo[repo._bookmarkcurrent]
4216 curhead = repo[repo._bookmarkcurrent]
4217 if len(bmheads) == 2:
4217 if len(bmheads) == 2:
4218 if curhead == bmheads[0]:
4218 if curhead == bmheads[0]:
4219 node = bmheads[1]
4219 node = bmheads[1]
4220 else:
4220 else:
4221 node = bmheads[0]
4221 node = bmheads[0]
4222 elif len(bmheads) > 2:
4222 elif len(bmheads) > 2:
4223 raise util.Abort(_("multiple matching bookmarks to merge - "
4223 raise util.Abort(_("multiple matching bookmarks to merge - "
4224 "please merge with an explicit rev or bookmark"),
4224 "please merge with an explicit rev or bookmark"),
4225 hint=_("run 'hg heads' to see all heads"))
4225 hint=_("run 'hg heads' to see all heads"))
4226 elif len(bmheads) <= 1:
4226 elif len(bmheads) <= 1:
4227 raise util.Abort(_("no matching bookmark to merge - "
4227 raise util.Abort(_("no matching bookmark to merge - "
4228 "please merge with an explicit rev or bookmark"),
4228 "please merge with an explicit rev or bookmark"),
4229 hint=_("run 'hg heads' to see all heads"))
4229 hint=_("run 'hg heads' to see all heads"))
4230
4230
4231 if not node and not repo._bookmarkcurrent:
4231 if not node and not repo._bookmarkcurrent:
4232 branch = repo[None].branch()
4232 branch = repo[None].branch()
4233 bheads = repo.branchheads(branch)
4233 bheads = repo.branchheads(branch)
4234 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4234 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4235
4235
4236 if len(nbhs) > 2:
4236 if len(nbhs) > 2:
4237 raise util.Abort(_("branch '%s' has %d heads - "
4237 raise util.Abort(_("branch '%s' has %d heads - "
4238 "please merge with an explicit rev")
4238 "please merge with an explicit rev")
4239 % (branch, len(bheads)),
4239 % (branch, len(bheads)),
4240 hint=_("run 'hg heads .' to see heads"))
4240 hint=_("run 'hg heads .' to see heads"))
4241
4241
4242 parent = repo.dirstate.p1()
4242 parent = repo.dirstate.p1()
4243 if len(nbhs) == 1:
4243 if len(nbhs) == 1:
4244 if len(bheads) > 1:
4244 if len(bheads) > 1:
4245 raise util.Abort(_("heads are bookmarked - "
4245 raise util.Abort(_("heads are bookmarked - "
4246 "please merge with an explicit rev"),
4246 "please merge with an explicit rev"),
4247 hint=_("run 'hg heads' to see all heads"))
4247 hint=_("run 'hg heads' to see all heads"))
4248 if len(repo.heads()) > 1:
4248 if len(repo.heads()) > 1:
4249 raise util.Abort(_("branch '%s' has one head - "
4249 raise util.Abort(_("branch '%s' has one head - "
4250 "please merge with an explicit rev")
4250 "please merge with an explicit rev")
4251 % branch,
4251 % branch,
4252 hint=_("run 'hg heads' to see all heads"))
4252 hint=_("run 'hg heads' to see all heads"))
4253 msg, hint = _('nothing to merge'), None
4253 msg, hint = _('nothing to merge'), None
4254 if parent != repo.lookup(branch):
4254 if parent != repo.lookup(branch):
4255 hint = _("use 'hg update' instead")
4255 hint = _("use 'hg update' instead")
4256 raise util.Abort(msg, hint=hint)
4256 raise util.Abort(msg, hint=hint)
4257
4257
4258 if parent not in bheads:
4258 if parent not in bheads:
4259 raise util.Abort(_('working directory not at a head revision'),
4259 raise util.Abort(_('working directory not at a head revision'),
4260 hint=_("use 'hg update' or merge with an "
4260 hint=_("use 'hg update' or merge with an "
4261 "explicit revision"))
4261 "explicit revision"))
4262 if parent == nbhs[0]:
4262 if parent == nbhs[0]:
4263 node = nbhs[-1]
4263 node = nbhs[-1]
4264 else:
4264 else:
4265 node = nbhs[0]
4265 node = nbhs[0]
4266
4266
4267 if opts.get('preview'):
4267 if opts.get('preview'):
4268 # find nodes that are ancestors of p2 but not of p1
4268 # find nodes that are ancestors of p2 but not of p1
4269 p1 = repo.lookup('.')
4269 p1 = repo.lookup('.')
4270 p2 = repo.lookup(node)
4270 p2 = repo.lookup(node)
4271 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4271 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4272
4272
4273 displayer = cmdutil.show_changeset(ui, repo, opts)
4273 displayer = cmdutil.show_changeset(ui, repo, opts)
4274 for node in nodes:
4274 for node in nodes:
4275 displayer.show(repo[node])
4275 displayer.show(repo[node])
4276 displayer.close()
4276 displayer.close()
4277 return 0
4277 return 0
4278
4278
4279 try:
4279 try:
4280 # ui.forcemerge is an internal variable, do not document
4280 # ui.forcemerge is an internal variable, do not document
4281 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4281 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4282 return hg.merge(repo, node, force=opts.get('force'))
4282 return hg.merge(repo, node, force=opts.get('force'))
4283 finally:
4283 finally:
4284 ui.setconfig('ui', 'forcemerge', '')
4284 ui.setconfig('ui', 'forcemerge', '')
4285
4285
4286 @command('outgoing|out',
4286 @command('outgoing|out',
4287 [('f', 'force', None, _('run even when the destination is unrelated')),
4287 [('f', 'force', None, _('run even when the destination is unrelated')),
4288 ('r', 'rev', [],
4288 ('r', 'rev', [],
4289 _('a changeset intended to be included in the destination'), _('REV')),
4289 _('a changeset intended to be included in the destination'), _('REV')),
4290 ('n', 'newest-first', None, _('show newest record first')),
4290 ('n', 'newest-first', None, _('show newest record first')),
4291 ('B', 'bookmarks', False, _('compare bookmarks')),
4291 ('B', 'bookmarks', False, _('compare bookmarks')),
4292 ('b', 'branch', [], _('a specific branch you would like to push'),
4292 ('b', 'branch', [], _('a specific branch you would like to push'),
4293 _('BRANCH')),
4293 _('BRANCH')),
4294 ] + logopts + remoteopts + subrepoopts,
4294 ] + logopts + remoteopts + subrepoopts,
4295 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4295 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4296 def outgoing(ui, repo, dest=None, **opts):
4296 def outgoing(ui, repo, dest=None, **opts):
4297 """show changesets not found in the destination
4297 """show changesets not found in the destination
4298
4298
4299 Show changesets not found in the specified destination repository
4299 Show changesets not found in the specified destination repository
4300 or the default push location. These are the changesets that would
4300 or the default push location. These are the changesets that would
4301 be pushed if a push was requested.
4301 be pushed if a push was requested.
4302
4302
4303 See pull for details of valid destination formats.
4303 See pull for details of valid destination formats.
4304
4304
4305 Returns 0 if there are outgoing changes, 1 otherwise.
4305 Returns 0 if there are outgoing changes, 1 otherwise.
4306 """
4306 """
4307 if opts.get('graph'):
4307 if opts.get('graph'):
4308 cmdutil.checkunsupportedgraphflags([], opts)
4308 cmdutil.checkunsupportedgraphflags([], opts)
4309 o = hg._outgoing(ui, repo, dest, opts)
4309 o = hg._outgoing(ui, repo, dest, opts)
4310 if o is None:
4310 if o is None:
4311 return
4311 return
4312
4312
4313 revdag = cmdutil.graphrevs(repo, o, opts)
4313 revdag = cmdutil.graphrevs(repo, o, opts)
4314 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4314 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4315 showparents = [ctx.node() for ctx in repo[None].parents()]
4315 showparents = [ctx.node() for ctx in repo[None].parents()]
4316 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4316 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4317 graphmod.asciiedges)
4317 graphmod.asciiedges)
4318 return 0
4318 return 0
4319
4319
4320 if opts.get('bookmarks'):
4320 if opts.get('bookmarks'):
4321 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4321 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4322 dest, branches = hg.parseurl(dest, opts.get('branch'))
4322 dest, branches = hg.parseurl(dest, opts.get('branch'))
4323 other = hg.peer(repo, opts, dest)
4323 other = hg.peer(repo, opts, dest)
4324 if 'bookmarks' not in other.listkeys('namespaces'):
4324 if 'bookmarks' not in other.listkeys('namespaces'):
4325 ui.warn(_("remote doesn't support bookmarks\n"))
4325 ui.warn(_("remote doesn't support bookmarks\n"))
4326 return 0
4326 return 0
4327 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4327 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4328 return bookmarks.diff(ui, other, repo)
4328 return bookmarks.diff(ui, other, repo)
4329
4329
4330 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4330 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4331 try:
4331 try:
4332 return hg.outgoing(ui, repo, dest, opts)
4332 return hg.outgoing(ui, repo, dest, opts)
4333 finally:
4333 finally:
4334 del repo._subtoppath
4334 del repo._subtoppath
4335
4335
4336 @command('parents',
4336 @command('parents',
4337 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4337 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4338 ] + templateopts,
4338 ] + templateopts,
4339 _('[-r REV] [FILE]'))
4339 _('[-r REV] [FILE]'))
4340 def parents(ui, repo, file_=None, **opts):
4340 def parents(ui, repo, file_=None, **opts):
4341 """show the parents of the working directory or revision
4341 """show the parents of the working directory or revision
4342
4342
4343 Print the working directory's parent revisions. If a revision is
4343 Print the working directory's parent revisions. If a revision is
4344 given via -r/--rev, the parent of that revision will be printed.
4344 given via -r/--rev, the parent of that revision will be printed.
4345 If a file argument is given, the revision in which the file was
4345 If a file argument is given, the revision in which the file was
4346 last changed (before the working directory revision or the
4346 last changed (before the working directory revision or the
4347 argument to --rev if given) is printed.
4347 argument to --rev if given) is printed.
4348
4348
4349 Returns 0 on success.
4349 Returns 0 on success.
4350 """
4350 """
4351
4351
4352 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4352 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4353
4353
4354 if file_:
4354 if file_:
4355 m = scmutil.match(ctx, (file_,), opts)
4355 m = scmutil.match(ctx, (file_,), opts)
4356 if m.anypats() or len(m.files()) != 1:
4356 if m.anypats() or len(m.files()) != 1:
4357 raise util.Abort(_('can only specify an explicit filename'))
4357 raise util.Abort(_('can only specify an explicit filename'))
4358 file_ = m.files()[0]
4358 file_ = m.files()[0]
4359 filenodes = []
4359 filenodes = []
4360 for cp in ctx.parents():
4360 for cp in ctx.parents():
4361 if not cp:
4361 if not cp:
4362 continue
4362 continue
4363 try:
4363 try:
4364 filenodes.append(cp.filenode(file_))
4364 filenodes.append(cp.filenode(file_))
4365 except error.LookupError:
4365 except error.LookupError:
4366 pass
4366 pass
4367 if not filenodes:
4367 if not filenodes:
4368 raise util.Abort(_("'%s' not found in manifest!") % file_)
4368 raise util.Abort(_("'%s' not found in manifest!") % file_)
4369 fl = repo.file(file_)
4369 fl = repo.file(file_)
4370 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4370 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4371 else:
4371 else:
4372 p = [cp.node() for cp in ctx.parents()]
4372 p = [cp.node() for cp in ctx.parents()]
4373
4373
4374 displayer = cmdutil.show_changeset(ui, repo, opts)
4374 displayer = cmdutil.show_changeset(ui, repo, opts)
4375 for n in p:
4375 for n in p:
4376 if n != nullid:
4376 if n != nullid:
4377 displayer.show(repo[n])
4377 displayer.show(repo[n])
4378 displayer.close()
4378 displayer.close()
4379
4379
4380 @command('paths', [], _('[NAME]'))
4380 @command('paths', [], _('[NAME]'))
4381 def paths(ui, repo, search=None):
4381 def paths(ui, repo, search=None):
4382 """show aliases for remote repositories
4382 """show aliases for remote repositories
4383
4383
4384 Show definition of symbolic path name NAME. If no name is given,
4384 Show definition of symbolic path name NAME. If no name is given,
4385 show definition of all available names.
4385 show definition of all available names.
4386
4386
4387 Option -q/--quiet suppresses all output when searching for NAME
4387 Option -q/--quiet suppresses all output when searching for NAME
4388 and shows only the path names when listing all definitions.
4388 and shows only the path names when listing all definitions.
4389
4389
4390 Path names are defined in the [paths] section of your
4390 Path names are defined in the [paths] section of your
4391 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4391 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4392 repository, ``.hg/hgrc`` is used, too.
4392 repository, ``.hg/hgrc`` is used, too.
4393
4393
4394 The path names ``default`` and ``default-push`` have a special
4394 The path names ``default`` and ``default-push`` have a special
4395 meaning. When performing a push or pull operation, they are used
4395 meaning. When performing a push or pull operation, they are used
4396 as fallbacks if no location is specified on the command-line.
4396 as fallbacks if no location is specified on the command-line.
4397 When ``default-push`` is set, it will be used for push and
4397 When ``default-push`` is set, it will be used for push and
4398 ``default`` will be used for pull; otherwise ``default`` is used
4398 ``default`` will be used for pull; otherwise ``default`` is used
4399 as the fallback for both. When cloning a repository, the clone
4399 as the fallback for both. When cloning a repository, the clone
4400 source is written as ``default`` in ``.hg/hgrc``. Note that
4400 source is written as ``default`` in ``.hg/hgrc``. Note that
4401 ``default`` and ``default-push`` apply to all inbound (e.g.
4401 ``default`` and ``default-push`` apply to all inbound (e.g.
4402 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4402 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4403 :hg:`bundle`) operations.
4403 :hg:`bundle`) operations.
4404
4404
4405 See :hg:`help urls` for more information.
4405 See :hg:`help urls` for more information.
4406
4406
4407 Returns 0 on success.
4407 Returns 0 on success.
4408 """
4408 """
4409 if search:
4409 if search:
4410 for name, path in ui.configitems("paths"):
4410 for name, path in ui.configitems("paths"):
4411 if name == search:
4411 if name == search:
4412 ui.status("%s\n" % util.hidepassword(path))
4412 ui.status("%s\n" % util.hidepassword(path))
4413 return
4413 return
4414 if not ui.quiet:
4414 if not ui.quiet:
4415 ui.warn(_("not found!\n"))
4415 ui.warn(_("not found!\n"))
4416 return 1
4416 return 1
4417 else:
4417 else:
4418 for name, path in ui.configitems("paths"):
4418 for name, path in ui.configitems("paths"):
4419 if ui.quiet:
4419 if ui.quiet:
4420 ui.write("%s\n" % name)
4420 ui.write("%s\n" % name)
4421 else:
4421 else:
4422 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4422 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4423
4423
4424 @command('^phase',
4424 @command('^phase',
4425 [('p', 'public', False, _('set changeset phase to public')),
4425 [('p', 'public', False, _('set changeset phase to public')),
4426 ('d', 'draft', False, _('set changeset phase to draft')),
4426 ('d', 'draft', False, _('set changeset phase to draft')),
4427 ('s', 'secret', False, _('set changeset phase to secret')),
4427 ('s', 'secret', False, _('set changeset phase to secret')),
4428 ('f', 'force', False, _('allow to move boundary backward')),
4428 ('f', 'force', False, _('allow to move boundary backward')),
4429 ('r', 'rev', [], _('target revision'), _('REV')),
4429 ('r', 'rev', [], _('target revision'), _('REV')),
4430 ],
4430 ],
4431 _('[-p|-d|-s] [-f] [-r] REV...'))
4431 _('[-p|-d|-s] [-f] [-r] REV...'))
4432 def phase(ui, repo, *revs, **opts):
4432 def phase(ui, repo, *revs, **opts):
4433 """set or show the current phase name
4433 """set or show the current phase name
4434
4434
4435 With no argument, show the phase name of specified revisions.
4435 With no argument, show the phase name of specified revisions.
4436
4436
4437 With one of -p/--public, -d/--draft or -s/--secret, change the
4437 With one of -p/--public, -d/--draft or -s/--secret, change the
4438 phase value of the specified revisions.
4438 phase value of the specified revisions.
4439
4439
4440 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4440 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4441 lower phase to an higher phase. Phases are ordered as follows::
4441 lower phase to an higher phase. Phases are ordered as follows::
4442
4442
4443 public < draft < secret
4443 public < draft < secret
4444
4444
4445 Return 0 on success, 1 if no phases were changed or some could not
4445 Return 0 on success, 1 if no phases were changed or some could not
4446 be changed.
4446 be changed.
4447 """
4447 """
4448 # search for a unique phase argument
4448 # search for a unique phase argument
4449 targetphase = None
4449 targetphase = None
4450 for idx, name in enumerate(phases.phasenames):
4450 for idx, name in enumerate(phases.phasenames):
4451 if opts[name]:
4451 if opts[name]:
4452 if targetphase is not None:
4452 if targetphase is not None:
4453 raise util.Abort(_('only one phase can be specified'))
4453 raise util.Abort(_('only one phase can be specified'))
4454 targetphase = idx
4454 targetphase = idx
4455
4455
4456 # look for specified revision
4456 # look for specified revision
4457 revs = list(revs)
4457 revs = list(revs)
4458 revs.extend(opts['rev'])
4458 revs.extend(opts['rev'])
4459 if not revs:
4459 if not revs:
4460 raise util.Abort(_('no revisions specified'))
4460 raise util.Abort(_('no revisions specified'))
4461
4461
4462 revs = scmutil.revrange(repo, revs)
4462 revs = scmutil.revrange(repo, revs)
4463
4463
4464 lock = None
4464 lock = None
4465 ret = 0
4465 ret = 0
4466 if targetphase is None:
4466 if targetphase is None:
4467 # display
4467 # display
4468 for r in revs:
4468 for r in revs:
4469 ctx = repo[r]
4469 ctx = repo[r]
4470 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4470 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4471 else:
4471 else:
4472 lock = repo.lock()
4472 lock = repo.lock()
4473 try:
4473 try:
4474 # set phase
4474 # set phase
4475 if not revs:
4475 if not revs:
4476 raise util.Abort(_('empty revision set'))
4476 raise util.Abort(_('empty revision set'))
4477 nodes = [repo[r].node() for r in revs]
4477 nodes = [repo[r].node() for r in revs]
4478 olddata = repo._phasecache.getphaserevs(repo)[:]
4478 olddata = repo._phasecache.getphaserevs(repo)[:]
4479 phases.advanceboundary(repo, targetphase, nodes)
4479 phases.advanceboundary(repo, targetphase, nodes)
4480 if opts['force']:
4480 if opts['force']:
4481 phases.retractboundary(repo, targetphase, nodes)
4481 phases.retractboundary(repo, targetphase, nodes)
4482 finally:
4482 finally:
4483 lock.release()
4483 lock.release()
4484 newdata = repo._phasecache.getphaserevs(repo)
4484 newdata = repo._phasecache.getphaserevs(repo)
4485 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4485 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4486 rejected = [n for n in nodes
4486 rejected = [n for n in nodes
4487 if newdata[repo[n].rev()] < targetphase]
4487 if newdata[repo[n].rev()] < targetphase]
4488 if rejected:
4488 if rejected:
4489 ui.warn(_('cannot move %i changesets to a more permissive '
4489 ui.warn(_('cannot move %i changesets to a more permissive '
4490 'phase, use --force\n') % len(rejected))
4490 'phase, use --force\n') % len(rejected))
4491 ret = 1
4491 ret = 1
4492 if changes:
4492 if changes:
4493 msg = _('phase changed for %i changesets\n') % changes
4493 msg = _('phase changed for %i changesets\n') % changes
4494 if ret:
4494 if ret:
4495 ui.status(msg)
4495 ui.status(msg)
4496 else:
4496 else:
4497 ui.note(msg)
4497 ui.note(msg)
4498 else:
4498 else:
4499 ui.warn(_('no phases changed\n'))
4499 ui.warn(_('no phases changed\n'))
4500 ret = 1
4500 ret = 1
4501 return ret
4501 return ret
4502
4502
4503 def postincoming(ui, repo, modheads, optupdate, checkout):
4503 def postincoming(ui, repo, modheads, optupdate, checkout):
4504 if modheads == 0:
4504 if modheads == 0:
4505 return
4505 return
4506 if optupdate:
4506 if optupdate:
4507 movemarkfrom = repo['.'].node()
4507 movemarkfrom = repo['.'].node()
4508 try:
4508 try:
4509 ret = hg.update(repo, checkout)
4509 ret = hg.update(repo, checkout)
4510 except util.Abort, inst:
4510 except util.Abort, inst:
4511 ui.warn(_("not updating: %s\n") % str(inst))
4511 ui.warn(_("not updating: %s\n") % str(inst))
4512 return 0
4512 return 0
4513 if not ret and not checkout:
4513 if not ret and not checkout:
4514 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4514 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4515 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4515 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4516 return ret
4516 return ret
4517 if modheads > 1:
4517 if modheads > 1:
4518 currentbranchheads = len(repo.branchheads())
4518 currentbranchheads = len(repo.branchheads())
4519 if currentbranchheads == modheads:
4519 if currentbranchheads == modheads:
4520 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4520 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4521 elif currentbranchheads > 1:
4521 elif currentbranchheads > 1:
4522 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4522 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4523 "merge)\n"))
4523 "merge)\n"))
4524 else:
4524 else:
4525 ui.status(_("(run 'hg heads' to see heads)\n"))
4525 ui.status(_("(run 'hg heads' to see heads)\n"))
4526 else:
4526 else:
4527 ui.status(_("(run 'hg update' to get a working copy)\n"))
4527 ui.status(_("(run 'hg update' to get a working copy)\n"))
4528
4528
4529 @command('^pull',
4529 @command('^pull',
4530 [('u', 'update', None,
4530 [('u', 'update', None,
4531 _('update to new branch head if changesets were pulled')),
4531 _('update to new branch head if changesets were pulled')),
4532 ('f', 'force', None, _('run even when remote repository is unrelated')),
4532 ('f', 'force', None, _('run even when remote repository is unrelated')),
4533 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4533 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4534 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4534 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4535 ('b', 'branch', [], _('a specific branch you would like to pull'),
4535 ('b', 'branch', [], _('a specific branch you would like to pull'),
4536 _('BRANCH')),
4536 _('BRANCH')),
4537 ] + remoteopts,
4537 ] + remoteopts,
4538 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4538 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4539 def pull(ui, repo, source="default", **opts):
4539 def pull(ui, repo, source="default", **opts):
4540 """pull changes from the specified source
4540 """pull changes from the specified source
4541
4541
4542 Pull changes from a remote repository to a local one.
4542 Pull changes from a remote repository to a local one.
4543
4543
4544 This finds all changes from the repository at the specified path
4544 This finds all changes from the repository at the specified path
4545 or URL and adds them to a local repository (the current one unless
4545 or URL and adds them to a local repository (the current one unless
4546 -R is specified). By default, this does not update the copy of the
4546 -R is specified). By default, this does not update the copy of the
4547 project in the working directory.
4547 project in the working directory.
4548
4548
4549 Use :hg:`incoming` if you want to see what would have been added
4549 Use :hg:`incoming` if you want to see what would have been added
4550 by a pull at the time you issued this command. If you then decide
4550 by a pull at the time you issued this command. If you then decide
4551 to add those changes to the repository, you should use :hg:`pull
4551 to add those changes to the repository, you should use :hg:`pull
4552 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4552 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4553
4553
4554 If SOURCE is omitted, the 'default' path will be used.
4554 If SOURCE is omitted, the 'default' path will be used.
4555 See :hg:`help urls` for more information.
4555 See :hg:`help urls` for more information.
4556
4556
4557 Returns 0 on success, 1 if an update had unresolved files.
4557 Returns 0 on success, 1 if an update had unresolved files.
4558 """
4558 """
4559 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4559 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4560 other = hg.peer(repo, opts, source)
4560 other = hg.peer(repo, opts, source)
4561 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4561 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4562 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4562 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4563
4563
4564 if opts.get('bookmark'):
4564 if opts.get('bookmark'):
4565 if not revs:
4565 if not revs:
4566 revs = []
4566 revs = []
4567 rb = other.listkeys('bookmarks')
4567 rb = other.listkeys('bookmarks')
4568 for b in opts['bookmark']:
4568 for b in opts['bookmark']:
4569 if b not in rb:
4569 if b not in rb:
4570 raise util.Abort(_('remote bookmark %s not found!') % b)
4570 raise util.Abort(_('remote bookmark %s not found!') % b)
4571 revs.append(rb[b])
4571 revs.append(rb[b])
4572
4572
4573 if revs:
4573 if revs:
4574 try:
4574 try:
4575 revs = [other.lookup(rev) for rev in revs]
4575 revs = [other.lookup(rev) for rev in revs]
4576 except error.CapabilityError:
4576 except error.CapabilityError:
4577 err = _("other repository doesn't support revision lookup, "
4577 err = _("other repository doesn't support revision lookup, "
4578 "so a rev cannot be specified.")
4578 "so a rev cannot be specified.")
4579 raise util.Abort(err)
4579 raise util.Abort(err)
4580
4580
4581 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4581 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4582 bookmarks.updatefromremote(ui, repo, other, source)
4582 bookmarks.updatefromremote(ui, repo, other, source)
4583 if checkout:
4583 if checkout:
4584 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4584 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4585 repo._subtoppath = source
4585 repo._subtoppath = source
4586 try:
4586 try:
4587 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4587 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4588
4588
4589 finally:
4589 finally:
4590 del repo._subtoppath
4590 del repo._subtoppath
4591
4591
4592 # update specified bookmarks
4592 # update specified bookmarks
4593 if opts.get('bookmark'):
4593 if opts.get('bookmark'):
4594 for b in opts['bookmark']:
4594 for b in opts['bookmark']:
4595 # explicit pull overrides local bookmark if any
4595 # explicit pull overrides local bookmark if any
4596 ui.status(_("importing bookmark %s\n") % b)
4596 ui.status(_("importing bookmark %s\n") % b)
4597 repo._bookmarks[b] = repo[rb[b]].node()
4597 repo._bookmarks[b] = repo[rb[b]].node()
4598 bookmarks.write(repo)
4598 bookmarks.write(repo)
4599
4599
4600 return ret
4600 return ret
4601
4601
4602 @command('^push',
4602 @command('^push',
4603 [('f', 'force', None, _('force push')),
4603 [('f', 'force', None, _('force push')),
4604 ('r', 'rev', [],
4604 ('r', 'rev', [],
4605 _('a changeset intended to be included in the destination'),
4605 _('a changeset intended to be included in the destination'),
4606 _('REV')),
4606 _('REV')),
4607 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4607 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4608 ('b', 'branch', [],
4608 ('b', 'branch', [],
4609 _('a specific branch you would like to push'), _('BRANCH')),
4609 _('a specific branch you would like to push'), _('BRANCH')),
4610 ('', 'new-branch', False, _('allow pushing a new branch')),
4610 ('', 'new-branch', False, _('allow pushing a new branch')),
4611 ] + remoteopts,
4611 ] + remoteopts,
4612 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4612 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4613 def push(ui, repo, dest=None, **opts):
4613 def push(ui, repo, dest=None, **opts):
4614 """push changes to the specified destination
4614 """push changes to the specified destination
4615
4615
4616 Push changesets from the local repository to the specified
4616 Push changesets from the local repository to the specified
4617 destination.
4617 destination.
4618
4618
4619 This operation is symmetrical to pull: it is identical to a pull
4619 This operation is symmetrical to pull: it is identical to a pull
4620 in the destination repository from the current one.
4620 in the destination repository from the current one.
4621
4621
4622 By default, push will not allow creation of new heads at the
4622 By default, push will not allow creation of new heads at the
4623 destination, since multiple heads would make it unclear which head
4623 destination, since multiple heads would make it unclear which head
4624 to use. In this situation, it is recommended to pull and merge
4624 to use. In this situation, it is recommended to pull and merge
4625 before pushing.
4625 before pushing.
4626
4626
4627 Use --new-branch if you want to allow push to create a new named
4627 Use --new-branch if you want to allow push to create a new named
4628 branch that is not present at the destination. This allows you to
4628 branch that is not present at the destination. This allows you to
4629 only create a new branch without forcing other changes.
4629 only create a new branch without forcing other changes.
4630
4630
4631 Use -f/--force to override the default behavior and push all
4631 Use -f/--force to override the default behavior and push all
4632 changesets on all branches.
4632 changesets on all branches.
4633
4633
4634 If -r/--rev is used, the specified revision and all its ancestors
4634 If -r/--rev is used, the specified revision and all its ancestors
4635 will be pushed to the remote repository.
4635 will be pushed to the remote repository.
4636
4636
4637 If -B/--bookmark is used, the specified bookmarked revision, its
4637 If -B/--bookmark is used, the specified bookmarked revision, its
4638 ancestors, and the bookmark will be pushed to the remote
4638 ancestors, and the bookmark will be pushed to the remote
4639 repository.
4639 repository.
4640
4640
4641 Please see :hg:`help urls` for important details about ``ssh://``
4641 Please see :hg:`help urls` for important details about ``ssh://``
4642 URLs. If DESTINATION is omitted, a default path will be used.
4642 URLs. If DESTINATION is omitted, a default path will be used.
4643
4643
4644 Returns 0 if push was successful, 1 if nothing to push.
4644 Returns 0 if push was successful, 1 if nothing to push.
4645 """
4645 """
4646
4646
4647 if opts.get('bookmark'):
4647 if opts.get('bookmark'):
4648 for b in opts['bookmark']:
4648 for b in opts['bookmark']:
4649 # translate -B options to -r so changesets get pushed
4649 # translate -B options to -r so changesets get pushed
4650 if b in repo._bookmarks:
4650 if b in repo._bookmarks:
4651 opts.setdefault('rev', []).append(b)
4651 opts.setdefault('rev', []).append(b)
4652 else:
4652 else:
4653 # if we try to push a deleted bookmark, translate it to null
4653 # if we try to push a deleted bookmark, translate it to null
4654 # this lets simultaneous -r, -b options continue working
4654 # this lets simultaneous -r, -b options continue working
4655 opts.setdefault('rev', []).append("null")
4655 opts.setdefault('rev', []).append("null")
4656
4656
4657 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4657 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4658 dest, branches = hg.parseurl(dest, opts.get('branch'))
4658 dest, branches = hg.parseurl(dest, opts.get('branch'))
4659 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4659 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4660 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4660 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4661 other = hg.peer(repo, opts, dest)
4661 other = hg.peer(repo, opts, dest)
4662 if revs:
4662 if revs:
4663 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4663 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4664
4664
4665 repo._subtoppath = dest
4665 repo._subtoppath = dest
4666 try:
4666 try:
4667 # push subrepos depth-first for coherent ordering
4667 # push subrepos depth-first for coherent ordering
4668 c = repo['']
4668 c = repo['']
4669 subs = c.substate # only repos that are committed
4669 subs = c.substate # only repos that are committed
4670 for s in sorted(subs):
4670 for s in sorted(subs):
4671 if c.sub(s).push(opts) == 0:
4671 if c.sub(s).push(opts) == 0:
4672 return False
4672 return False
4673 finally:
4673 finally:
4674 del repo._subtoppath
4674 del repo._subtoppath
4675 result = repo.push(other, opts.get('force'), revs=revs,
4675 result = repo.push(other, opts.get('force'), revs=revs,
4676 newbranch=opts.get('new_branch'))
4676 newbranch=opts.get('new_branch'))
4677
4677
4678 result = not result
4678 result = not result
4679
4679
4680 if opts.get('bookmark'):
4680 if opts.get('bookmark'):
4681 rb = other.listkeys('bookmarks')
4681 rb = other.listkeys('bookmarks')
4682 for b in opts['bookmark']:
4682 for b in opts['bookmark']:
4683 # explicit push overrides remote bookmark if any
4683 # explicit push overrides remote bookmark if any
4684 if b in repo._bookmarks:
4684 if b in repo._bookmarks:
4685 ui.status(_("exporting bookmark %s\n") % b)
4685 ui.status(_("exporting bookmark %s\n") % b)
4686 new = repo[b].hex()
4686 new = repo[b].hex()
4687 elif b in rb:
4687 elif b in rb:
4688 ui.status(_("deleting remote bookmark %s\n") % b)
4688 ui.status(_("deleting remote bookmark %s\n") % b)
4689 new = '' # delete
4689 new = '' # delete
4690 else:
4690 else:
4691 ui.warn(_('bookmark %s does not exist on the local '
4691 ui.warn(_('bookmark %s does not exist on the local '
4692 'or remote repository!\n') % b)
4692 'or remote repository!\n') % b)
4693 return 2
4693 return 2
4694 old = rb.get(b, '')
4694 old = rb.get(b, '')
4695 r = other.pushkey('bookmarks', b, old, new)
4695 r = other.pushkey('bookmarks', b, old, new)
4696 if not r:
4696 if not r:
4697 ui.warn(_('updating bookmark %s failed!\n') % b)
4697 ui.warn(_('updating bookmark %s failed!\n') % b)
4698 if not result:
4698 if not result:
4699 result = 2
4699 result = 2
4700
4700
4701 return result
4701 return result
4702
4702
4703 @command('recover', [])
4703 @command('recover', [])
4704 def recover(ui, repo):
4704 def recover(ui, repo):
4705 """roll back an interrupted transaction
4705 """roll back an interrupted transaction
4706
4706
4707 Recover from an interrupted commit or pull.
4707 Recover from an interrupted commit or pull.
4708
4708
4709 This command tries to fix the repository status after an
4709 This command tries to fix the repository status after an
4710 interrupted operation. It should only be necessary when Mercurial
4710 interrupted operation. It should only be necessary when Mercurial
4711 suggests it.
4711 suggests it.
4712
4712
4713 Returns 0 if successful, 1 if nothing to recover or verify fails.
4713 Returns 0 if successful, 1 if nothing to recover or verify fails.
4714 """
4714 """
4715 if repo.recover():
4715 if repo.recover():
4716 return hg.verify(repo)
4716 return hg.verify(repo)
4717 return 1
4717 return 1
4718
4718
4719 @command('^remove|rm',
4719 @command('^remove|rm',
4720 [('A', 'after', None, _('record delete for missing files')),
4720 [('A', 'after', None, _('record delete for missing files')),
4721 ('f', 'force', None,
4721 ('f', 'force', None,
4722 _('remove (and delete) file even if added or modified')),
4722 _('remove (and delete) file even if added or modified')),
4723 ] + walkopts,
4723 ] + walkopts,
4724 _('[OPTION]... FILE...'))
4724 _('[OPTION]... FILE...'))
4725 def remove(ui, repo, *pats, **opts):
4725 def remove(ui, repo, *pats, **opts):
4726 """remove the specified files on the next commit
4726 """remove the specified files on the next commit
4727
4727
4728 Schedule the indicated files for removal from the current branch.
4728 Schedule the indicated files for removal from the current branch.
4729
4729
4730 This command schedules the files to be removed at the next commit.
4730 This command schedules the files to be removed at the next commit.
4731 To undo a remove before that, see :hg:`revert`. To undo added
4731 To undo a remove before that, see :hg:`revert`. To undo added
4732 files, see :hg:`forget`.
4732 files, see :hg:`forget`.
4733
4733
4734 .. container:: verbose
4734 .. container:: verbose
4735
4735
4736 -A/--after can be used to remove only files that have already
4736 -A/--after can be used to remove only files that have already
4737 been deleted, -f/--force can be used to force deletion, and -Af
4737 been deleted, -f/--force can be used to force deletion, and -Af
4738 can be used to remove files from the next revision without
4738 can be used to remove files from the next revision without
4739 deleting them from the working directory.
4739 deleting them from the working directory.
4740
4740
4741 The following table details the behavior of remove for different
4741 The following table details the behavior of remove for different
4742 file states (columns) and option combinations (rows). The file
4742 file states (columns) and option combinations (rows). The file
4743 states are Added [A], Clean [C], Modified [M] and Missing [!]
4743 states are Added [A], Clean [C], Modified [M] and Missing [!]
4744 (as reported by :hg:`status`). The actions are Warn, Remove
4744 (as reported by :hg:`status`). The actions are Warn, Remove
4745 (from branch) and Delete (from disk):
4745 (from branch) and Delete (from disk):
4746
4746
4747 ======= == == == ==
4747 ======= == == == ==
4748 A C M !
4748 A C M !
4749 ======= == == == ==
4749 ======= == == == ==
4750 none W RD W R
4750 none W RD W R
4751 -f R RD RD R
4751 -f R RD RD R
4752 -A W W W R
4752 -A W W W R
4753 -Af R R R R
4753 -Af R R R R
4754 ======= == == == ==
4754 ======= == == == ==
4755
4755
4756 Note that remove never deletes files in Added [A] state from the
4756 Note that remove never deletes files in Added [A] state from the
4757 working directory, not even if option --force is specified.
4757 working directory, not even if option --force is specified.
4758
4758
4759 Returns 0 on success, 1 if any warnings encountered.
4759 Returns 0 on success, 1 if any warnings encountered.
4760 """
4760 """
4761
4761
4762 ret = 0
4762 ret = 0
4763 after, force = opts.get('after'), opts.get('force')
4763 after, force = opts.get('after'), opts.get('force')
4764 if not pats and not after:
4764 if not pats and not after:
4765 raise util.Abort(_('no files specified'))
4765 raise util.Abort(_('no files specified'))
4766
4766
4767 m = scmutil.match(repo[None], pats, opts)
4767 m = scmutil.match(repo[None], pats, opts)
4768 s = repo.status(match=m, clean=True)
4768 s = repo.status(match=m, clean=True)
4769 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4769 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4770
4770
4771 for f in m.files():
4771 for f in m.files():
4772 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4772 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4773 if os.path.exists(m.rel(f)):
4773 if os.path.exists(m.rel(f)):
4774 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4774 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4775 ret = 1
4775 ret = 1
4776
4776
4777 if force:
4777 if force:
4778 list = modified + deleted + clean + added
4778 list = modified + deleted + clean + added
4779 elif after:
4779 elif after:
4780 list = deleted
4780 list = deleted
4781 for f in modified + added + clean:
4781 for f in modified + added + clean:
4782 ui.warn(_('not removing %s: file still exists (use -f'
4782 ui.warn(_('not removing %s: file still exists (use -f'
4783 ' to force removal)\n') % m.rel(f))
4783 ' to force removal)\n') % m.rel(f))
4784 ret = 1
4784 ret = 1
4785 else:
4785 else:
4786 list = deleted + clean
4786 list = deleted + clean
4787 for f in modified:
4787 for f in modified:
4788 ui.warn(_('not removing %s: file is modified (use -f'
4788 ui.warn(_('not removing %s: file is modified (use -f'
4789 ' to force removal)\n') % m.rel(f))
4789 ' to force removal)\n') % m.rel(f))
4790 ret = 1
4790 ret = 1
4791 for f in added:
4791 for f in added:
4792 ui.warn(_('not removing %s: file has been marked for add'
4792 ui.warn(_('not removing %s: file has been marked for add'
4793 ' (use forget to undo)\n') % m.rel(f))
4793 ' (use forget to undo)\n') % m.rel(f))
4794 ret = 1
4794 ret = 1
4795
4795
4796 for f in sorted(list):
4796 for f in sorted(list):
4797 if ui.verbose or not m.exact(f):
4797 if ui.verbose or not m.exact(f):
4798 ui.status(_('removing %s\n') % m.rel(f))
4798 ui.status(_('removing %s\n') % m.rel(f))
4799
4799
4800 wlock = repo.wlock()
4800 wlock = repo.wlock()
4801 try:
4801 try:
4802 if not after:
4802 if not after:
4803 for f in list:
4803 for f in list:
4804 if f in added:
4804 if f in added:
4805 continue # we never unlink added files on remove
4805 continue # we never unlink added files on remove
4806 try:
4806 try:
4807 util.unlinkpath(repo.wjoin(f))
4807 util.unlinkpath(repo.wjoin(f))
4808 except OSError, inst:
4808 except OSError, inst:
4809 if inst.errno != errno.ENOENT:
4809 if inst.errno != errno.ENOENT:
4810 raise
4810 raise
4811 repo[None].forget(list)
4811 repo[None].forget(list)
4812 finally:
4812 finally:
4813 wlock.release()
4813 wlock.release()
4814
4814
4815 return ret
4815 return ret
4816
4816
4817 @command('rename|move|mv',
4817 @command('rename|move|mv',
4818 [('A', 'after', None, _('record a rename that has already occurred')),
4818 [('A', 'after', None, _('record a rename that has already occurred')),
4819 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4819 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4820 ] + walkopts + dryrunopts,
4820 ] + walkopts + dryrunopts,
4821 _('[OPTION]... SOURCE... DEST'))
4821 _('[OPTION]... SOURCE... DEST'))
4822 def rename(ui, repo, *pats, **opts):
4822 def rename(ui, repo, *pats, **opts):
4823 """rename files; equivalent of copy + remove
4823 """rename files; equivalent of copy + remove
4824
4824
4825 Mark dest as copies of sources; mark sources for deletion. If dest
4825 Mark dest as copies of sources; mark sources for deletion. If dest
4826 is a directory, copies are put in that directory. If dest is a
4826 is a directory, copies are put in that directory. If dest is a
4827 file, there can only be one source.
4827 file, there can only be one source.
4828
4828
4829 By default, this command copies the contents of files as they
4829 By default, this command copies the contents of files as they
4830 exist in the working directory. If invoked with -A/--after, the
4830 exist in the working directory. If invoked with -A/--after, the
4831 operation is recorded, but no copying is performed.
4831 operation is recorded, but no copying is performed.
4832
4832
4833 This command takes effect at the next commit. To undo a rename
4833 This command takes effect at the next commit. To undo a rename
4834 before that, see :hg:`revert`.
4834 before that, see :hg:`revert`.
4835
4835
4836 Returns 0 on success, 1 if errors are encountered.
4836 Returns 0 on success, 1 if errors are encountered.
4837 """
4837 """
4838 wlock = repo.wlock(False)
4838 wlock = repo.wlock(False)
4839 try:
4839 try:
4840 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4840 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4841 finally:
4841 finally:
4842 wlock.release()
4842 wlock.release()
4843
4843
4844 @command('resolve',
4844 @command('resolve',
4845 [('a', 'all', None, _('select all unresolved files')),
4845 [('a', 'all', None, _('select all unresolved files')),
4846 ('l', 'list', None, _('list state of files needing merge')),
4846 ('l', 'list', None, _('list state of files needing merge')),
4847 ('m', 'mark', None, _('mark files as resolved')),
4847 ('m', 'mark', None, _('mark files as resolved')),
4848 ('u', 'unmark', None, _('mark files as unresolved')),
4848 ('u', 'unmark', None, _('mark files as unresolved')),
4849 ('n', 'no-status', None, _('hide status prefix'))]
4849 ('n', 'no-status', None, _('hide status prefix'))]
4850 + mergetoolopts + walkopts,
4850 + mergetoolopts + walkopts,
4851 _('[OPTION]... [FILE]...'))
4851 _('[OPTION]... [FILE]...'))
4852 def resolve(ui, repo, *pats, **opts):
4852 def resolve(ui, repo, *pats, **opts):
4853 """redo merges or set/view the merge status of files
4853 """redo merges or set/view the merge status of files
4854
4854
4855 Merges with unresolved conflicts are often the result of
4855 Merges with unresolved conflicts are often the result of
4856 non-interactive merging using the ``internal:merge`` configuration
4856 non-interactive merging using the ``internal:merge`` configuration
4857 setting, or a command-line merge tool like ``diff3``. The resolve
4857 setting, or a command-line merge tool like ``diff3``. The resolve
4858 command is used to manage the files involved in a merge, after
4858 command is used to manage the files involved in a merge, after
4859 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4859 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4860 working directory must have two parents). See :hg:`help
4860 working directory must have two parents). See :hg:`help
4861 merge-tools` for information on configuring merge tools.
4861 merge-tools` for information on configuring merge tools.
4862
4862
4863 The resolve command can be used in the following ways:
4863 The resolve command can be used in the following ways:
4864
4864
4865 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4865 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4866 files, discarding any previous merge attempts. Re-merging is not
4866 files, discarding any previous merge attempts. Re-merging is not
4867 performed for files already marked as resolved. Use ``--all/-a``
4867 performed for files already marked as resolved. Use ``--all/-a``
4868 to select all unresolved files. ``--tool`` can be used to specify
4868 to select all unresolved files. ``--tool`` can be used to specify
4869 the merge tool used for the given files. It overrides the HGMERGE
4869 the merge tool used for the given files. It overrides the HGMERGE
4870 environment variable and your configuration files. Previous file
4870 environment variable and your configuration files. Previous file
4871 contents are saved with a ``.orig`` suffix.
4871 contents are saved with a ``.orig`` suffix.
4872
4872
4873 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4873 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4874 (e.g. after having manually fixed-up the files). The default is
4874 (e.g. after having manually fixed-up the files). The default is
4875 to mark all unresolved files.
4875 to mark all unresolved files.
4876
4876
4877 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4877 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4878 default is to mark all resolved files.
4878 default is to mark all resolved files.
4879
4879
4880 - :hg:`resolve -l`: list files which had or still have conflicts.
4880 - :hg:`resolve -l`: list files which had or still have conflicts.
4881 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4881 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4882
4882
4883 Note that Mercurial will not let you commit files with unresolved
4883 Note that Mercurial will not let you commit files with unresolved
4884 merge conflicts. You must use :hg:`resolve -m ...` before you can
4884 merge conflicts. You must use :hg:`resolve -m ...` before you can
4885 commit after a conflicting merge.
4885 commit after a conflicting merge.
4886
4886
4887 Returns 0 on success, 1 if any files fail a resolve attempt.
4887 Returns 0 on success, 1 if any files fail a resolve attempt.
4888 """
4888 """
4889
4889
4890 all, mark, unmark, show, nostatus = \
4890 all, mark, unmark, show, nostatus = \
4891 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4891 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4892
4892
4893 if (show and (mark or unmark)) or (mark and unmark):
4893 if (show and (mark or unmark)) or (mark and unmark):
4894 raise util.Abort(_("too many options specified"))
4894 raise util.Abort(_("too many options specified"))
4895 if pats and all:
4895 if pats and all:
4896 raise util.Abort(_("can't specify --all and patterns"))
4896 raise util.Abort(_("can't specify --all and patterns"))
4897 if not (all or pats or show or mark or unmark):
4897 if not (all or pats or show or mark or unmark):
4898 raise util.Abort(_('no files or directories specified; '
4898 raise util.Abort(_('no files or directories specified; '
4899 'use --all to remerge all files'))
4899 'use --all to remerge all files'))
4900
4900
4901 ms = mergemod.mergestate(repo)
4901 ms = mergemod.mergestate(repo)
4902 m = scmutil.match(repo[None], pats, opts)
4902 m = scmutil.match(repo[None], pats, opts)
4903 ret = 0
4903 ret = 0
4904
4904
4905 for f in ms:
4905 for f in ms:
4906 if m(f):
4906 if m(f):
4907 if show:
4907 if show:
4908 if nostatus:
4908 if nostatus:
4909 ui.write("%s\n" % f)
4909 ui.write("%s\n" % f)
4910 else:
4910 else:
4911 ui.write("%s %s\n" % (ms[f].upper(), f),
4911 ui.write("%s %s\n" % (ms[f].upper(), f),
4912 label='resolve.' +
4912 label='resolve.' +
4913 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4913 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4914 elif mark:
4914 elif mark:
4915 ms.mark(f, "r")
4915 ms.mark(f, "r")
4916 elif unmark:
4916 elif unmark:
4917 ms.mark(f, "u")
4917 ms.mark(f, "u")
4918 else:
4918 else:
4919 wctx = repo[None]
4919 wctx = repo[None]
4920 mctx = wctx.parents()[-1]
4920 mctx = wctx.parents()[-1]
4921
4921
4922 # backup pre-resolve (merge uses .orig for its own purposes)
4922 # backup pre-resolve (merge uses .orig for its own purposes)
4923 a = repo.wjoin(f)
4923 a = repo.wjoin(f)
4924 util.copyfile(a, a + ".resolve")
4924 util.copyfile(a, a + ".resolve")
4925
4925
4926 try:
4926 try:
4927 # resolve file
4927 # resolve file
4928 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4928 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4929 if ms.resolve(f, wctx, mctx):
4929 if ms.resolve(f, wctx, mctx):
4930 ret = 1
4930 ret = 1
4931 finally:
4931 finally:
4932 ui.setconfig('ui', 'forcemerge', '')
4932 ui.setconfig('ui', 'forcemerge', '')
4933
4933
4934 # replace filemerge's .orig file with our resolve file
4934 # replace filemerge's .orig file with our resolve file
4935 util.rename(a + ".resolve", a + ".orig")
4935 util.rename(a + ".resolve", a + ".orig")
4936
4936
4937 ms.commit()
4937 ms.commit()
4938 return ret
4938 return ret
4939
4939
4940 @command('revert',
4940 @command('revert',
4941 [('a', 'all', None, _('revert all changes when no arguments given')),
4941 [('a', 'all', None, _('revert all changes when no arguments given')),
4942 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4942 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4943 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4943 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4944 ('C', 'no-backup', None, _('do not save backup copies of files')),
4944 ('C', 'no-backup', None, _('do not save backup copies of files')),
4945 ] + walkopts + dryrunopts,
4945 ] + walkopts + dryrunopts,
4946 _('[OPTION]... [-r REV] [NAME]...'))
4946 _('[OPTION]... [-r REV] [NAME]...'))
4947 def revert(ui, repo, *pats, **opts):
4947 def revert(ui, repo, *pats, **opts):
4948 """restore files to their checkout state
4948 """restore files to their checkout state
4949
4949
4950 .. note::
4950 .. note::
4951
4951
4952 To check out earlier revisions, you should use :hg:`update REV`.
4952 To check out earlier revisions, you should use :hg:`update REV`.
4953 To cancel an uncommitted merge (and lose your changes), use
4953 To cancel an uncommitted merge (and lose your changes), use
4954 :hg:`update --clean .`.
4954 :hg:`update --clean .`.
4955
4955
4956 With no revision specified, revert the specified files or directories
4956 With no revision specified, revert the specified files or directories
4957 to the contents they had in the parent of the working directory.
4957 to the contents they had in the parent of the working directory.
4958 This restores the contents of files to an unmodified
4958 This restores the contents of files to an unmodified
4959 state and unschedules adds, removes, copies, and renames. If the
4959 state and unschedules adds, removes, copies, and renames. If the
4960 working directory has two parents, you must explicitly specify a
4960 working directory has two parents, you must explicitly specify a
4961 revision.
4961 revision.
4962
4962
4963 Using the -r/--rev or -d/--date options, revert the given files or
4963 Using the -r/--rev or -d/--date options, revert the given files or
4964 directories to their states as of a specific revision. Because
4964 directories to their states as of a specific revision. Because
4965 revert does not change the working directory parents, this will
4965 revert does not change the working directory parents, this will
4966 cause these files to appear modified. This can be helpful to "back
4966 cause these files to appear modified. This can be helpful to "back
4967 out" some or all of an earlier change. See :hg:`backout` for a
4967 out" some or all of an earlier change. See :hg:`backout` for a
4968 related method.
4968 related method.
4969
4969
4970 Modified files are saved with a .orig suffix before reverting.
4970 Modified files are saved with a .orig suffix before reverting.
4971 To disable these backups, use --no-backup.
4971 To disable these backups, use --no-backup.
4972
4972
4973 See :hg:`help dates` for a list of formats valid for -d/--date.
4973 See :hg:`help dates` for a list of formats valid for -d/--date.
4974
4974
4975 Returns 0 on success.
4975 Returns 0 on success.
4976 """
4976 """
4977
4977
4978 if opts.get("date"):
4978 if opts.get("date"):
4979 if opts.get("rev"):
4979 if opts.get("rev"):
4980 raise util.Abort(_("you can't specify a revision and a date"))
4980 raise util.Abort(_("you can't specify a revision and a date"))
4981 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4981 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4982
4982
4983 parent, p2 = repo.dirstate.parents()
4983 parent, p2 = repo.dirstate.parents()
4984 if not opts.get('rev') and p2 != nullid:
4984 if not opts.get('rev') and p2 != nullid:
4985 # revert after merge is a trap for new users (issue2915)
4985 # revert after merge is a trap for new users (issue2915)
4986 raise util.Abort(_('uncommitted merge with no revision specified'),
4986 raise util.Abort(_('uncommitted merge with no revision specified'),
4987 hint=_('use "hg update" or see "hg help revert"'))
4987 hint=_('use "hg update" or see "hg help revert"'))
4988
4988
4989 ctx = scmutil.revsingle(repo, opts.get('rev'))
4989 ctx = scmutil.revsingle(repo, opts.get('rev'))
4990
4990
4991 if not pats and not opts.get('all'):
4991 if not pats and not opts.get('all'):
4992 msg = _("no files or directories specified")
4992 msg = _("no files or directories specified")
4993 if p2 != nullid:
4993 if p2 != nullid:
4994 hint = _("uncommitted merge, use --all to discard all changes,"
4994 hint = _("uncommitted merge, use --all to discard all changes,"
4995 " or 'hg update -C .' to abort the merge")
4995 " or 'hg update -C .' to abort the merge")
4996 raise util.Abort(msg, hint=hint)
4996 raise util.Abort(msg, hint=hint)
4997 dirty = util.any(repo.status())
4997 dirty = util.any(repo.status())
4998 node = ctx.node()
4998 node = ctx.node()
4999 if node != parent:
4999 if node != parent:
5000 if dirty:
5000 if dirty:
5001 hint = _("uncommitted changes, use --all to discard all"
5001 hint = _("uncommitted changes, use --all to discard all"
5002 " changes, or 'hg update %s' to update") % ctx.rev()
5002 " changes, or 'hg update %s' to update") % ctx.rev()
5003 else:
5003 else:
5004 hint = _("use --all to revert all files,"
5004 hint = _("use --all to revert all files,"
5005 " or 'hg update %s' to update") % ctx.rev()
5005 " or 'hg update %s' to update") % ctx.rev()
5006 elif dirty:
5006 elif dirty:
5007 hint = _("uncommitted changes, use --all to discard all changes")
5007 hint = _("uncommitted changes, use --all to discard all changes")
5008 else:
5008 else:
5009 hint = _("use --all to revert all files")
5009 hint = _("use --all to revert all files")
5010 raise util.Abort(msg, hint=hint)
5010 raise util.Abort(msg, hint=hint)
5011
5011
5012 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5012 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5013
5013
5014 @command('rollback', dryrunopts +
5014 @command('rollback', dryrunopts +
5015 [('f', 'force', False, _('ignore safety measures'))])
5015 [('f', 'force', False, _('ignore safety measures'))])
5016 def rollback(ui, repo, **opts):
5016 def rollback(ui, repo, **opts):
5017 """roll back the last transaction (dangerous)
5017 """roll back the last transaction (dangerous)
5018
5018
5019 This command should be used with care. There is only one level of
5019 This command should be used with care. There is only one level of
5020 rollback, and there is no way to undo a rollback. It will also
5020 rollback, and there is no way to undo a rollback. It will also
5021 restore the dirstate at the time of the last transaction, losing
5021 restore the dirstate at the time of the last transaction, losing
5022 any dirstate changes since that time. This command does not alter
5022 any dirstate changes since that time. This command does not alter
5023 the working directory.
5023 the working directory.
5024
5024
5025 Transactions are used to encapsulate the effects of all commands
5025 Transactions are used to encapsulate the effects of all commands
5026 that create new changesets or propagate existing changesets into a
5026 that create new changesets or propagate existing changesets into a
5027 repository.
5027 repository.
5028
5028
5029 .. container:: verbose
5029 .. container:: verbose
5030
5030
5031 For example, the following commands are transactional, and their
5031 For example, the following commands are transactional, and their
5032 effects can be rolled back:
5032 effects can be rolled back:
5033
5033
5034 - commit
5034 - commit
5035 - import
5035 - import
5036 - pull
5036 - pull
5037 - push (with this repository as the destination)
5037 - push (with this repository as the destination)
5038 - unbundle
5038 - unbundle
5039
5039
5040 To avoid permanent data loss, rollback will refuse to rollback a
5040 To avoid permanent data loss, rollback will refuse to rollback a
5041 commit transaction if it isn't checked out. Use --force to
5041 commit transaction if it isn't checked out. Use --force to
5042 override this protection.
5042 override this protection.
5043
5043
5044 This command is not intended for use on public repositories. Once
5044 This command is not intended for use on public repositories. Once
5045 changes are visible for pull by other users, rolling a transaction
5045 changes are visible for pull by other users, rolling a transaction
5046 back locally is ineffective (someone else may already have pulled
5046 back locally is ineffective (someone else may already have pulled
5047 the changes). Furthermore, a race is possible with readers of the
5047 the changes). Furthermore, a race is possible with readers of the
5048 repository; for example an in-progress pull from the repository
5048 repository; for example an in-progress pull from the repository
5049 may fail if a rollback is performed.
5049 may fail if a rollback is performed.
5050
5050
5051 Returns 0 on success, 1 if no rollback data is available.
5051 Returns 0 on success, 1 if no rollback data is available.
5052 """
5052 """
5053 return repo.rollback(dryrun=opts.get('dry_run'),
5053 return repo.rollback(dryrun=opts.get('dry_run'),
5054 force=opts.get('force'))
5054 force=opts.get('force'))
5055
5055
5056 @command('root', [])
5056 @command('root', [])
5057 def root(ui, repo):
5057 def root(ui, repo):
5058 """print the root (top) of the current working directory
5058 """print the root (top) of the current working directory
5059
5059
5060 Print the root directory of the current repository.
5060 Print the root directory of the current repository.
5061
5061
5062 Returns 0 on success.
5062 Returns 0 on success.
5063 """
5063 """
5064 ui.write(repo.root + "\n")
5064 ui.write(repo.root + "\n")
5065
5065
5066 @command('^serve',
5066 @command('^serve',
5067 [('A', 'accesslog', '', _('name of access log file to write to'),
5067 [('A', 'accesslog', '', _('name of access log file to write to'),
5068 _('FILE')),
5068 _('FILE')),
5069 ('d', 'daemon', None, _('run server in background')),
5069 ('d', 'daemon', None, _('run server in background')),
5070 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5070 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5071 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5071 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5072 # use string type, then we can check if something was passed
5072 # use string type, then we can check if something was passed
5073 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5073 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5074 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5074 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5075 _('ADDR')),
5075 _('ADDR')),
5076 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5076 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5077 _('PREFIX')),
5077 _('PREFIX')),
5078 ('n', 'name', '',
5078 ('n', 'name', '',
5079 _('name to show in web pages (default: working directory)'), _('NAME')),
5079 _('name to show in web pages (default: working directory)'), _('NAME')),
5080 ('', 'web-conf', '',
5080 ('', 'web-conf', '',
5081 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5081 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5082 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5082 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5083 _('FILE')),
5083 _('FILE')),
5084 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5084 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5085 ('', 'stdio', None, _('for remote clients')),
5085 ('', 'stdio', None, _('for remote clients')),
5086 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5086 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5087 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5087 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5088 ('', 'style', '', _('template style to use'), _('STYLE')),
5088 ('', 'style', '', _('template style to use'), _('STYLE')),
5089 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5089 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5090 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5090 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5091 _('[OPTION]...'))
5091 _('[OPTION]...'))
5092 def serve(ui, repo, **opts):
5092 def serve(ui, repo, **opts):
5093 """start stand-alone webserver
5093 """start stand-alone webserver
5094
5094
5095 Start a local HTTP repository browser and pull server. You can use
5095 Start a local HTTP repository browser and pull server. You can use
5096 this for ad-hoc sharing and browsing of repositories. It is
5096 this for ad-hoc sharing and browsing of repositories. It is
5097 recommended to use a real web server to serve a repository for
5097 recommended to use a real web server to serve a repository for
5098 longer periods of time.
5098 longer periods of time.
5099
5099
5100 Please note that the server does not implement access control.
5100 Please note that the server does not implement access control.
5101 This means that, by default, anybody can read from the server and
5101 This means that, by default, anybody can read from the server and
5102 nobody can write to it by default. Set the ``web.allow_push``
5102 nobody can write to it by default. Set the ``web.allow_push``
5103 option to ``*`` to allow everybody to push to the server. You
5103 option to ``*`` to allow everybody to push to the server. You
5104 should use a real web server if you need to authenticate users.
5104 should use a real web server if you need to authenticate users.
5105
5105
5106 By default, the server logs accesses to stdout and errors to
5106 By default, the server logs accesses to stdout and errors to
5107 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5107 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5108 files.
5108 files.
5109
5109
5110 To have the server choose a free port number to listen on, specify
5110 To have the server choose a free port number to listen on, specify
5111 a port number of 0; in this case, the server will print the port
5111 a port number of 0; in this case, the server will print the port
5112 number it uses.
5112 number it uses.
5113
5113
5114 Returns 0 on success.
5114 Returns 0 on success.
5115 """
5115 """
5116
5116
5117 if opts["stdio"] and opts["cmdserver"]:
5117 if opts["stdio"] and opts["cmdserver"]:
5118 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5118 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5119
5119
5120 def checkrepo():
5120 def checkrepo():
5121 if repo is None:
5121 if repo is None:
5122 raise error.RepoError(_("there is no Mercurial repository here"
5122 raise error.RepoError(_("there is no Mercurial repository here"
5123 " (.hg not found)"))
5123 " (.hg not found)"))
5124
5124
5125 if opts["stdio"]:
5125 if opts["stdio"]:
5126 checkrepo()
5126 checkrepo()
5127 s = sshserver.sshserver(ui, repo)
5127 s = sshserver.sshserver(ui, repo)
5128 s.serve_forever()
5128 s.serve_forever()
5129
5129
5130 if opts["cmdserver"]:
5130 if opts["cmdserver"]:
5131 checkrepo()
5131 checkrepo()
5132 s = commandserver.server(ui, repo, opts["cmdserver"])
5132 s = commandserver.server(ui, repo, opts["cmdserver"])
5133 return s.serve()
5133 return s.serve()
5134
5134
5135 # this way we can check if something was given in the command-line
5135 # this way we can check if something was given in the command-line
5136 if opts.get('port'):
5136 if opts.get('port'):
5137 opts['port'] = util.getport(opts.get('port'))
5137 opts['port'] = util.getport(opts.get('port'))
5138
5138
5139 baseui = repo and repo.baseui or ui
5139 baseui = repo and repo.baseui or ui
5140 optlist = ("name templates style address port prefix ipv6"
5140 optlist = ("name templates style address port prefix ipv6"
5141 " accesslog errorlog certificate encoding")
5141 " accesslog errorlog certificate encoding")
5142 for o in optlist.split():
5142 for o in optlist.split():
5143 val = opts.get(o, '')
5143 val = opts.get(o, '')
5144 if val in (None, ''): # should check against default options instead
5144 if val in (None, ''): # should check against default options instead
5145 continue
5145 continue
5146 baseui.setconfig("web", o, val)
5146 baseui.setconfig("web", o, val)
5147 if repo and repo.ui != baseui:
5147 if repo and repo.ui != baseui:
5148 repo.ui.setconfig("web", o, val)
5148 repo.ui.setconfig("web", o, val)
5149
5149
5150 o = opts.get('web_conf') or opts.get('webdir_conf')
5150 o = opts.get('web_conf') or opts.get('webdir_conf')
5151 if not o:
5151 if not o:
5152 if not repo:
5152 if not repo:
5153 raise error.RepoError(_("there is no Mercurial repository"
5153 raise error.RepoError(_("there is no Mercurial repository"
5154 " here (.hg not found)"))
5154 " here (.hg not found)"))
5155 o = repo.root
5155 o = repo.root
5156
5156
5157 app = hgweb.hgweb(o, baseui=ui)
5157 app = hgweb.hgweb(o, baseui=ui)
5158
5158
5159 class service(object):
5159 class service(object):
5160 def init(self):
5160 def init(self):
5161 util.setsignalhandler()
5161 util.setsignalhandler()
5162 self.httpd = hgweb.server.create_server(ui, app)
5162 self.httpd = hgweb.server.create_server(ui, app)
5163
5163
5164 if opts['port'] and not ui.verbose:
5164 if opts['port'] and not ui.verbose:
5165 return
5165 return
5166
5166
5167 if self.httpd.prefix:
5167 if self.httpd.prefix:
5168 prefix = self.httpd.prefix.strip('/') + '/'
5168 prefix = self.httpd.prefix.strip('/') + '/'
5169 else:
5169 else:
5170 prefix = ''
5170 prefix = ''
5171
5171
5172 port = ':%d' % self.httpd.port
5172 port = ':%d' % self.httpd.port
5173 if port == ':80':
5173 if port == ':80':
5174 port = ''
5174 port = ''
5175
5175
5176 bindaddr = self.httpd.addr
5176 bindaddr = self.httpd.addr
5177 if bindaddr == '0.0.0.0':
5177 if bindaddr == '0.0.0.0':
5178 bindaddr = '*'
5178 bindaddr = '*'
5179 elif ':' in bindaddr: # IPv6
5179 elif ':' in bindaddr: # IPv6
5180 bindaddr = '[%s]' % bindaddr
5180 bindaddr = '[%s]' % bindaddr
5181
5181
5182 fqaddr = self.httpd.fqaddr
5182 fqaddr = self.httpd.fqaddr
5183 if ':' in fqaddr:
5183 if ':' in fqaddr:
5184 fqaddr = '[%s]' % fqaddr
5184 fqaddr = '[%s]' % fqaddr
5185 if opts['port']:
5185 if opts['port']:
5186 write = ui.status
5186 write = ui.status
5187 else:
5187 else:
5188 write = ui.write
5188 write = ui.write
5189 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5189 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5190 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5190 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5191
5191
5192 def run(self):
5192 def run(self):
5193 self.httpd.serve_forever()
5193 self.httpd.serve_forever()
5194
5194
5195 service = service()
5195 service = service()
5196
5196
5197 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5197 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5198
5198
5199 @command('showconfig|debugconfig',
5199 @command('showconfig|debugconfig',
5200 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5200 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5201 _('[-u] [NAME]...'))
5201 _('[-u] [NAME]...'))
5202 def showconfig(ui, repo, *values, **opts):
5202 def showconfig(ui, repo, *values, **opts):
5203 """show combined config settings from all hgrc files
5203 """show combined config settings from all hgrc files
5204
5204
5205 With no arguments, print names and values of all config items.
5205 With no arguments, print names and values of all config items.
5206
5206
5207 With one argument of the form section.name, print just the value
5207 With one argument of the form section.name, print just the value
5208 of that config item.
5208 of that config item.
5209
5209
5210 With multiple arguments, print names and values of all config
5210 With multiple arguments, print names and values of all config
5211 items with matching section names.
5211 items with matching section names.
5212
5212
5213 With --debug, the source (filename and line number) is printed
5213 With --debug, the source (filename and line number) is printed
5214 for each config item.
5214 for each config item.
5215
5215
5216 Returns 0 on success.
5216 Returns 0 on success.
5217 """
5217 """
5218
5218
5219 for f in scmutil.rcpath():
5219 for f in scmutil.rcpath():
5220 ui.debug('read config from: %s\n' % f)
5220 ui.debug('read config from: %s\n' % f)
5221 untrusted = bool(opts.get('untrusted'))
5221 untrusted = bool(opts.get('untrusted'))
5222 if values:
5222 if values:
5223 sections = [v for v in values if '.' not in v]
5223 sections = [v for v in values if '.' not in v]
5224 items = [v for v in values if '.' in v]
5224 items = [v for v in values if '.' in v]
5225 if len(items) > 1 or items and sections:
5225 if len(items) > 1 or items and sections:
5226 raise util.Abort(_('only one config item permitted'))
5226 raise util.Abort(_('only one config item permitted'))
5227 for section, name, value in ui.walkconfig(untrusted=untrusted):
5227 for section, name, value in ui.walkconfig(untrusted=untrusted):
5228 value = str(value).replace('\n', '\\n')
5228 value = str(value).replace('\n', '\\n')
5229 sectname = section + '.' + name
5229 sectname = section + '.' + name
5230 if values:
5230 if values:
5231 for v in values:
5231 for v in values:
5232 if v == section:
5232 if v == section:
5233 ui.debug('%s: ' %
5233 ui.debug('%s: ' %
5234 ui.configsource(section, name, untrusted))
5234 ui.configsource(section, name, untrusted))
5235 ui.write('%s=%s\n' % (sectname, value))
5235 ui.write('%s=%s\n' % (sectname, value))
5236 elif v == sectname:
5236 elif v == sectname:
5237 ui.debug('%s: ' %
5237 ui.debug('%s: ' %
5238 ui.configsource(section, name, untrusted))
5238 ui.configsource(section, name, untrusted))
5239 ui.write(value, '\n')
5239 ui.write(value, '\n')
5240 else:
5240 else:
5241 ui.debug('%s: ' %
5241 ui.debug('%s: ' %
5242 ui.configsource(section, name, untrusted))
5242 ui.configsource(section, name, untrusted))
5243 ui.write('%s=%s\n' % (sectname, value))
5243 ui.write('%s=%s\n' % (sectname, value))
5244
5244
5245 @command('^status|st',
5245 @command('^status|st',
5246 [('A', 'all', None, _('show status of all files')),
5246 [('A', 'all', None, _('show status of all files')),
5247 ('m', 'modified', None, _('show only modified files')),
5247 ('m', 'modified', None, _('show only modified files')),
5248 ('a', 'added', None, _('show only added files')),
5248 ('a', 'added', None, _('show only added files')),
5249 ('r', 'removed', None, _('show only removed files')),
5249 ('r', 'removed', None, _('show only removed files')),
5250 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5250 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5251 ('c', 'clean', None, _('show only files without changes')),
5251 ('c', 'clean', None, _('show only files without changes')),
5252 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5252 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5253 ('i', 'ignored', None, _('show only ignored files')),
5253 ('i', 'ignored', None, _('show only ignored files')),
5254 ('n', 'no-status', None, _('hide status prefix')),
5254 ('n', 'no-status', None, _('hide status prefix')),
5255 ('C', 'copies', None, _('show source of copied files')),
5255 ('C', 'copies', None, _('show source of copied files')),
5256 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5256 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5257 ('', 'rev', [], _('show difference from revision'), _('REV')),
5257 ('', 'rev', [], _('show difference from revision'), _('REV')),
5258 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5258 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5259 ] + walkopts + subrepoopts,
5259 ] + walkopts + subrepoopts,
5260 _('[OPTION]... [FILE]...'))
5260 _('[OPTION]... [FILE]...'))
5261 def status(ui, repo, *pats, **opts):
5261 def status(ui, repo, *pats, **opts):
5262 """show changed files in the working directory
5262 """show changed files in the working directory
5263
5263
5264 Show status of files in the repository. If names are given, only
5264 Show status of files in the repository. If names are given, only
5265 files that match are shown. Files that are clean or ignored or
5265 files that match are shown. Files that are clean or ignored or
5266 the source of a copy/move operation, are not listed unless
5266 the source of a copy/move operation, are not listed unless
5267 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5267 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5268 Unless options described with "show only ..." are given, the
5268 Unless options described with "show only ..." are given, the
5269 options -mardu are used.
5269 options -mardu are used.
5270
5270
5271 Option -q/--quiet hides untracked (unknown and ignored) files
5271 Option -q/--quiet hides untracked (unknown and ignored) files
5272 unless explicitly requested with -u/--unknown or -i/--ignored.
5272 unless explicitly requested with -u/--unknown or -i/--ignored.
5273
5273
5274 .. note::
5274 .. note::
5275 status may appear to disagree with diff if permissions have
5275 status may appear to disagree with diff if permissions have
5276 changed or a merge has occurred. The standard diff format does
5276 changed or a merge has occurred. The standard diff format does
5277 not report permission changes and diff only reports changes
5277 not report permission changes and diff only reports changes
5278 relative to one merge parent.
5278 relative to one merge parent.
5279
5279
5280 If one revision is given, it is used as the base revision.
5280 If one revision is given, it is used as the base revision.
5281 If two revisions are given, the differences between them are
5281 If two revisions are given, the differences between them are
5282 shown. The --change option can also be used as a shortcut to list
5282 shown. The --change option can also be used as a shortcut to list
5283 the changed files of a revision from its first parent.
5283 the changed files of a revision from its first parent.
5284
5284
5285 The codes used to show the status of files are::
5285 The codes used to show the status of files are::
5286
5286
5287 M = modified
5287 M = modified
5288 A = added
5288 A = added
5289 R = removed
5289 R = removed
5290 C = clean
5290 C = clean
5291 ! = missing (deleted by non-hg command, but still tracked)
5291 ! = missing (deleted by non-hg command, but still tracked)
5292 ? = not tracked
5292 ? = not tracked
5293 I = ignored
5293 I = ignored
5294 = origin of the previous file listed as A (added)
5294 = origin of the previous file listed as A (added)
5295
5295
5296 .. container:: verbose
5296 .. container:: verbose
5297
5297
5298 Examples:
5298 Examples:
5299
5299
5300 - show changes in the working directory relative to a
5300 - show changes in the working directory relative to a
5301 changeset::
5301 changeset::
5302
5302
5303 hg status --rev 9353
5303 hg status --rev 9353
5304
5304
5305 - show all changes including copies in an existing changeset::
5305 - show all changes including copies in an existing changeset::
5306
5306
5307 hg status --copies --change 9353
5307 hg status --copies --change 9353
5308
5308
5309 - get a NUL separated list of added files, suitable for xargs::
5309 - get a NUL separated list of added files, suitable for xargs::
5310
5310
5311 hg status -an0
5311 hg status -an0
5312
5312
5313 Returns 0 on success.
5313 Returns 0 on success.
5314 """
5314 """
5315
5315
5316 revs = opts.get('rev')
5316 revs = opts.get('rev')
5317 change = opts.get('change')
5317 change = opts.get('change')
5318
5318
5319 if revs and change:
5319 if revs and change:
5320 msg = _('cannot specify --rev and --change at the same time')
5320 msg = _('cannot specify --rev and --change at the same time')
5321 raise util.Abort(msg)
5321 raise util.Abort(msg)
5322 elif change:
5322 elif change:
5323 node2 = scmutil.revsingle(repo, change, None).node()
5323 node2 = scmutil.revsingle(repo, change, None).node()
5324 node1 = repo[node2].p1().node()
5324 node1 = repo[node2].p1().node()
5325 else:
5325 else:
5326 node1, node2 = scmutil.revpair(repo, revs)
5326 node1, node2 = scmutil.revpair(repo, revs)
5327
5327
5328 cwd = (pats and repo.getcwd()) or ''
5328 cwd = (pats and repo.getcwd()) or ''
5329 end = opts.get('print0') and '\0' or '\n'
5329 end = opts.get('print0') and '\0' or '\n'
5330 copy = {}
5330 copy = {}
5331 states = 'modified added removed deleted unknown ignored clean'.split()
5331 states = 'modified added removed deleted unknown ignored clean'.split()
5332 show = [k for k in states if opts.get(k)]
5332 show = [k for k in states if opts.get(k)]
5333 if opts.get('all'):
5333 if opts.get('all'):
5334 show += ui.quiet and (states[:4] + ['clean']) or states
5334 show += ui.quiet and (states[:4] + ['clean']) or states
5335 if not show:
5335 if not show:
5336 show = ui.quiet and states[:4] or states[:5]
5336 show = ui.quiet and states[:4] or states[:5]
5337
5337
5338 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5338 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5339 'ignored' in show, 'clean' in show, 'unknown' in show,
5339 'ignored' in show, 'clean' in show, 'unknown' in show,
5340 opts.get('subrepos'))
5340 opts.get('subrepos'))
5341 changestates = zip(states, 'MAR!?IC', stat)
5341 changestates = zip(states, 'MAR!?IC', stat)
5342
5342
5343 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5343 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5344 copy = copies.pathcopies(repo[node1], repo[node2])
5344 copy = copies.pathcopies(repo[node1], repo[node2])
5345
5345
5346 fm = ui.formatter('status', opts)
5346 fm = ui.formatter('status', opts)
5347 format = '%s %s' + end
5347 format = '%s %s' + end
5348 if opts.get('no_status'):
5348 if opts.get('no_status'):
5349 format = '%.0s%s' + end
5349 format = '%.0s%s' + end
5350
5350
5351 for state, char, files in changestates:
5351 for state, char, files in changestates:
5352 if state in show:
5352 if state in show:
5353 label = 'status.' + state
5353 label = 'status.' + state
5354 for f in files:
5354 for f in files:
5355 fm.startitem()
5355 fm.startitem()
5356 fm.write("status path", format, char,
5356 fm.write("status path", format, char,
5357 repo.pathto(f, cwd), label=label)
5357 repo.pathto(f, cwd), label=label)
5358 if f in copy:
5358 if f in copy:
5359 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5359 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5360 label='status.copied')
5360 label='status.copied')
5361 fm.end()
5361 fm.end()
5362
5362
5363 @command('^summary|sum',
5363 @command('^summary|sum',
5364 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5364 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5365 def summary(ui, repo, **opts):
5365 def summary(ui, repo, **opts):
5366 """summarize working directory state
5366 """summarize working directory state
5367
5367
5368 This generates a brief summary of the working directory state,
5368 This generates a brief summary of the working directory state,
5369 including parents, branch, commit status, and available updates.
5369 including parents, branch, commit status, and available updates.
5370
5370
5371 With the --remote option, this will check the default paths for
5371 With the --remote option, this will check the default paths for
5372 incoming and outgoing changes. This can be time-consuming.
5372 incoming and outgoing changes. This can be time-consuming.
5373
5373
5374 Returns 0 on success.
5374 Returns 0 on success.
5375 """
5375 """
5376
5376
5377 ctx = repo[None]
5377 ctx = repo[None]
5378 parents = ctx.parents()
5378 parents = ctx.parents()
5379 pnode = parents[0].node()
5379 pnode = parents[0].node()
5380 marks = []
5380 marks = []
5381
5381
5382 for p in parents:
5382 for p in parents:
5383 # label with log.changeset (instead of log.parent) since this
5383 # label with log.changeset (instead of log.parent) since this
5384 # shows a working directory parent *changeset*:
5384 # shows a working directory parent *changeset*:
5385 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5385 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5386 label='log.changeset')
5386 label='log.changeset')
5387 ui.write(' '.join(p.tags()), label='log.tag')
5387 ui.write(' '.join(p.tags()), label='log.tag')
5388 if p.bookmarks():
5388 if p.bookmarks():
5389 marks.extend(p.bookmarks())
5389 marks.extend(p.bookmarks())
5390 if p.rev() == -1:
5390 if p.rev() == -1:
5391 if not len(repo):
5391 if not len(repo):
5392 ui.write(_(' (empty repository)'))
5392 ui.write(_(' (empty repository)'))
5393 else:
5393 else:
5394 ui.write(_(' (no revision checked out)'))
5394 ui.write(_(' (no revision checked out)'))
5395 ui.write('\n')
5395 ui.write('\n')
5396 if p.description():
5396 if p.description():
5397 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5397 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5398 label='log.summary')
5398 label='log.summary')
5399
5399
5400 branch = ctx.branch()
5400 branch = ctx.branch()
5401 bheads = repo.branchheads(branch)
5401 bheads = repo.branchheads(branch)
5402 m = _('branch: %s\n') % branch
5402 m = _('branch: %s\n') % branch
5403 if branch != 'default':
5403 if branch != 'default':
5404 ui.write(m, label='log.branch')
5404 ui.write(m, label='log.branch')
5405 else:
5405 else:
5406 ui.status(m, label='log.branch')
5406 ui.status(m, label='log.branch')
5407
5407
5408 if marks:
5408 if marks:
5409 current = repo._bookmarkcurrent
5409 current = repo._bookmarkcurrent
5410 ui.write(_('bookmarks:'), label='log.bookmark')
5410 ui.write(_('bookmarks:'), label='log.bookmark')
5411 if current is not None:
5411 if current is not None:
5412 try:
5412 try:
5413 marks.remove(current)
5413 marks.remove(current)
5414 ui.write(' *' + current, label='bookmarks.current')
5414 ui.write(' *' + current, label='bookmarks.current')
5415 except ValueError:
5415 except ValueError:
5416 # current bookmark not in parent ctx marks
5416 # current bookmark not in parent ctx marks
5417 pass
5417 pass
5418 for m in marks:
5418 for m in marks:
5419 ui.write(' ' + m, label='log.bookmark')
5419 ui.write(' ' + m, label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5421
5421
5422 st = list(repo.status(unknown=True))[:6]
5422 st = list(repo.status(unknown=True))[:6]
5423
5423
5424 c = repo.dirstate.copies()
5424 c = repo.dirstate.copies()
5425 copied, renamed = [], []
5425 copied, renamed = [], []
5426 for d, s in c.iteritems():
5426 for d, s in c.iteritems():
5427 if s in st[2]:
5427 if s in st[2]:
5428 st[2].remove(s)
5428 st[2].remove(s)
5429 renamed.append(d)
5429 renamed.append(d)
5430 else:
5430 else:
5431 copied.append(d)
5431 copied.append(d)
5432 if d in st[1]:
5432 if d in st[1]:
5433 st[1].remove(d)
5433 st[1].remove(d)
5434 st.insert(3, renamed)
5434 st.insert(3, renamed)
5435 st.insert(4, copied)
5435 st.insert(4, copied)
5436
5436
5437 ms = mergemod.mergestate(repo)
5437 ms = mergemod.mergestate(repo)
5438 st.append([f for f in ms if ms[f] == 'u'])
5438 st.append([f for f in ms if ms[f] == 'u'])
5439
5439
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5441 st.append(subs)
5441 st.append(subs)
5442
5442
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5444 ui.label(_('%d added'), 'status.added'),
5444 ui.label(_('%d added'), 'status.added'),
5445 ui.label(_('%d removed'), 'status.removed'),
5445 ui.label(_('%d removed'), 'status.removed'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5452 ui.label(_('%d subrepos'), 'status.modified')]
5452 ui.label(_('%d subrepos'), 'status.modified')]
5453 t = []
5453 t = []
5454 for s, l in zip(st, labels):
5454 for s, l in zip(st, labels):
5455 if s:
5455 if s:
5456 t.append(l % len(s))
5456 t.append(l % len(s))
5457
5457
5458 t = ', '.join(t)
5458 t = ', '.join(t)
5459 cleanworkdir = False
5459 cleanworkdir = False
5460
5460
5461 if len(parents) > 1:
5461 if len(parents) > 1:
5462 t += _(' (merge)')
5462 t += _(' (merge)')
5463 elif branch != parents[0].branch():
5463 elif branch != parents[0].branch():
5464 t += _(' (new branch)')
5464 t += _(' (new branch)')
5465 elif (parents[0].closesbranch() and
5465 elif (parents[0].closesbranch() and
5466 pnode in repo.branchheads(branch, closed=True)):
5466 pnode in repo.branchheads(branch, closed=True)):
5467 t += _(' (head closed)')
5467 t += _(' (head closed)')
5468 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5468 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5469 t += _(' (clean)')
5469 t += _(' (clean)')
5470 cleanworkdir = True
5470 cleanworkdir = True
5471 elif pnode not in bheads:
5471 elif pnode not in bheads:
5472 t += _(' (new branch head)')
5472 t += _(' (new branch head)')
5473
5473
5474 if cleanworkdir:
5474 if cleanworkdir:
5475 ui.status(_('commit: %s\n') % t.strip())
5475 ui.status(_('commit: %s\n') % t.strip())
5476 else:
5476 else:
5477 ui.write(_('commit: %s\n') % t.strip())
5477 ui.write(_('commit: %s\n') % t.strip())
5478
5478
5479 # all ancestors of branch heads - all ancestors of parent = new csets
5479 # all ancestors of branch heads - all ancestors of parent = new csets
5480 new = [0] * len(repo)
5480 new = [0] * len(repo)
5481 cl = repo.changelog
5481 cl = repo.changelog
5482 for a in [cl.rev(n) for n in bheads]:
5482 for a in [cl.rev(n) for n in bheads]:
5483 new[a] = 1
5483 new[a] = 1
5484 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5484 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5485 new[a] = 1
5485 new[a] = 1
5486 for a in [p.rev() for p in parents]:
5486 for a in [p.rev() for p in parents]:
5487 if a >= 0:
5487 if a >= 0:
5488 new[a] = 0
5488 new[a] = 0
5489 for a in cl.ancestors([p.rev() for p in parents]):
5489 for a in cl.ancestors([p.rev() for p in parents]):
5490 new[a] = 0
5490 new[a] = 0
5491 new = sum(new)
5491 new = sum(new)
5492
5492
5493 if new == 0:
5493 if new == 0:
5494 ui.status(_('update: (current)\n'))
5494 ui.status(_('update: (current)\n'))
5495 elif pnode not in bheads:
5495 elif pnode not in bheads:
5496 ui.write(_('update: %d new changesets (update)\n') % new)
5496 ui.write(_('update: %d new changesets (update)\n') % new)
5497 else:
5497 else:
5498 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5498 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5499 (new, len(bheads)))
5499 (new, len(bheads)))
5500
5500
5501 if opts.get('remote'):
5501 if opts.get('remote'):
5502 t = []
5502 t = []
5503 source, branches = hg.parseurl(ui.expandpath('default'))
5503 source, branches = hg.parseurl(ui.expandpath('default'))
5504 other = hg.peer(repo, {}, source)
5504 other = hg.peer(repo, {}, source)
5505 revs, checkout = hg.addbranchrevs(repo, other, branches,
5505 revs, checkout = hg.addbranchrevs(repo, other, branches,
5506 opts.get('rev'))
5506 opts.get('rev'))
5507 ui.debug('comparing with %s\n' % util.hidepassword(source))
5507 ui.debug('comparing with %s\n' % util.hidepassword(source))
5508 repo.ui.pushbuffer()
5508 repo.ui.pushbuffer()
5509 commoninc = discovery.findcommonincoming(repo, other)
5509 commoninc = discovery.findcommonincoming(repo, other)
5510 _common, incoming, _rheads = commoninc
5510 _common, incoming, _rheads = commoninc
5511 repo.ui.popbuffer()
5511 repo.ui.popbuffer()
5512 if incoming:
5512 if incoming:
5513 t.append(_('1 or more incoming'))
5513 t.append(_('1 or more incoming'))
5514
5514
5515 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5515 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5516 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5516 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5517 if source != dest:
5517 if source != dest:
5518 other = hg.peer(repo, {}, dest)
5518 other = hg.peer(repo, {}, dest)
5519 commoninc = None
5519 commoninc = None
5520 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5520 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5521 repo.ui.pushbuffer()
5521 repo.ui.pushbuffer()
5522 outgoing = discovery.findcommonoutgoing(repo, other,
5522 outgoing = discovery.findcommonoutgoing(repo, other,
5523 commoninc=commoninc)
5523 commoninc=commoninc)
5524 repo.ui.popbuffer()
5524 repo.ui.popbuffer()
5525 o = outgoing.missing
5525 o = outgoing.missing
5526 if o:
5526 if o:
5527 t.append(_('%d outgoing') % len(o))
5527 t.append(_('%d outgoing') % len(o))
5528 if 'bookmarks' in other.listkeys('namespaces'):
5528 if 'bookmarks' in other.listkeys('namespaces'):
5529 lmarks = repo.listkeys('bookmarks')
5529 lmarks = repo.listkeys('bookmarks')
5530 rmarks = other.listkeys('bookmarks')
5530 rmarks = other.listkeys('bookmarks')
5531 diff = set(rmarks) - set(lmarks)
5531 diff = set(rmarks) - set(lmarks)
5532 if len(diff) > 0:
5532 if len(diff) > 0:
5533 t.append(_('%d incoming bookmarks') % len(diff))
5533 t.append(_('%d incoming bookmarks') % len(diff))
5534 diff = set(lmarks) - set(rmarks)
5534 diff = set(lmarks) - set(rmarks)
5535 if len(diff) > 0:
5535 if len(diff) > 0:
5536 t.append(_('%d outgoing bookmarks') % len(diff))
5536 t.append(_('%d outgoing bookmarks') % len(diff))
5537
5537
5538 if t:
5538 if t:
5539 ui.write(_('remote: %s\n') % (', '.join(t)))
5539 ui.write(_('remote: %s\n') % (', '.join(t)))
5540 else:
5540 else:
5541 ui.status(_('remote: (synced)\n'))
5541 ui.status(_('remote: (synced)\n'))
5542
5542
5543 @command('tag',
5543 @command('tag',
5544 [('f', 'force', None, _('force tag')),
5544 [('f', 'force', None, _('force tag')),
5545 ('l', 'local', None, _('make the tag local')),
5545 ('l', 'local', None, _('make the tag local')),
5546 ('r', 'rev', '', _('revision to tag'), _('REV')),
5546 ('r', 'rev', '', _('revision to tag'), _('REV')),
5547 ('', 'remove', None, _('remove a tag')),
5547 ('', 'remove', None, _('remove a tag')),
5548 # -l/--local is already there, commitopts cannot be used
5548 # -l/--local is already there, commitopts cannot be used
5549 ('e', 'edit', None, _('edit commit message')),
5549 ('e', 'edit', None, _('edit commit message')),
5550 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5550 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5551 ] + commitopts2,
5551 ] + commitopts2,
5552 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5552 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5553 def tag(ui, repo, name1, *names, **opts):
5553 def tag(ui, repo, name1, *names, **opts):
5554 """add one or more tags for the current or given revision
5554 """add one or more tags for the current or given revision
5555
5555
5556 Name a particular revision using <name>.
5556 Name a particular revision using <name>.
5557
5557
5558 Tags are used to name particular revisions of the repository and are
5558 Tags are used to name particular revisions of the repository and are
5559 very useful to compare different revisions, to go back to significant
5559 very useful to compare different revisions, to go back to significant
5560 earlier versions or to mark branch points as releases, etc. Changing
5560 earlier versions or to mark branch points as releases, etc. Changing
5561 an existing tag is normally disallowed; use -f/--force to override.
5561 an existing tag is normally disallowed; use -f/--force to override.
5562
5562
5563 If no revision is given, the parent of the working directory is
5563 If no revision is given, the parent of the working directory is
5564 used, or tip if no revision is checked out.
5564 used, or tip if no revision is checked out.
5565
5565
5566 To facilitate version control, distribution, and merging of tags,
5566 To facilitate version control, distribution, and merging of tags,
5567 they are stored as a file named ".hgtags" which is managed similarly
5567 they are stored as a file named ".hgtags" which is managed similarly
5568 to other project files and can be hand-edited if necessary. This
5568 to other project files and can be hand-edited if necessary. This
5569 also means that tagging creates a new commit. The file
5569 also means that tagging creates a new commit. The file
5570 ".hg/localtags" is used for local tags (not shared among
5570 ".hg/localtags" is used for local tags (not shared among
5571 repositories).
5571 repositories).
5572
5572
5573 Tag commits are usually made at the head of a branch. If the parent
5573 Tag commits are usually made at the head of a branch. If the parent
5574 of the working directory is not a branch head, :hg:`tag` aborts; use
5574 of the working directory is not a branch head, :hg:`tag` aborts; use
5575 -f/--force to force the tag commit to be based on a non-head
5575 -f/--force to force the tag commit to be based on a non-head
5576 changeset.
5576 changeset.
5577
5577
5578 See :hg:`help dates` for a list of formats valid for -d/--date.
5578 See :hg:`help dates` for a list of formats valid for -d/--date.
5579
5579
5580 Since tag names have priority over branch names during revision
5580 Since tag names have priority over branch names during revision
5581 lookup, using an existing branch name as a tag name is discouraged.
5581 lookup, using an existing branch name as a tag name is discouraged.
5582
5582
5583 Returns 0 on success.
5583 Returns 0 on success.
5584 """
5584 """
5585 wlock = lock = None
5585 wlock = lock = None
5586 try:
5586 try:
5587 wlock = repo.wlock()
5587 wlock = repo.wlock()
5588 lock = repo.lock()
5588 lock = repo.lock()
5589 rev_ = "."
5589 rev_ = "."
5590 names = [t.strip() for t in (name1,) + names]
5590 names = [t.strip() for t in (name1,) + names]
5591 if len(names) != len(set(names)):
5591 if len(names) != len(set(names)):
5592 raise util.Abort(_('tag names must be unique'))
5592 raise util.Abort(_('tag names must be unique'))
5593 for n in names:
5593 for n in names:
5594 if n in ['tip', '.', 'null']:
5594 if n in ['tip', '.', 'null']:
5595 raise util.Abort(_("the name '%s' is reserved") % n)
5595 raise util.Abort(_("the name '%s' is reserved") % n)
5596 if not n:
5596 if not n:
5597 raise util.Abort(_('tag names cannot consist entirely of '
5597 raise util.Abort(_('tag names cannot consist entirely of '
5598 'whitespace'))
5598 'whitespace'))
5599 if opts.get('rev') and opts.get('remove'):
5599 if opts.get('rev') and opts.get('remove'):
5600 raise util.Abort(_("--rev and --remove are incompatible"))
5600 raise util.Abort(_("--rev and --remove are incompatible"))
5601 if opts.get('rev'):
5601 if opts.get('rev'):
5602 rev_ = opts['rev']
5602 rev_ = opts['rev']
5603 message = opts.get('message')
5603 message = opts.get('message')
5604 if opts.get('remove'):
5604 if opts.get('remove'):
5605 expectedtype = opts.get('local') and 'local' or 'global'
5605 expectedtype = opts.get('local') and 'local' or 'global'
5606 for n in names:
5606 for n in names:
5607 if not repo.tagtype(n):
5607 if not repo.tagtype(n):
5608 raise util.Abort(_("tag '%s' does not exist") % n)
5608 raise util.Abort(_("tag '%s' does not exist") % n)
5609 if repo.tagtype(n) != expectedtype:
5609 if repo.tagtype(n) != expectedtype:
5610 if expectedtype == 'global':
5610 if expectedtype == 'global':
5611 raise util.Abort(_("tag '%s' is not a global tag") % n)
5611 raise util.Abort(_("tag '%s' is not a global tag") % n)
5612 else:
5612 else:
5613 raise util.Abort(_("tag '%s' is not a local tag") % n)
5613 raise util.Abort(_("tag '%s' is not a local tag") % n)
5614 rev_ = nullid
5614 rev_ = nullid
5615 if not message:
5615 if not message:
5616 # we don't translate commit messages
5616 # we don't translate commit messages
5617 message = 'Removed tag %s' % ', '.join(names)
5617 message = 'Removed tag %s' % ', '.join(names)
5618 elif not opts.get('force'):
5618 elif not opts.get('force'):
5619 for n in names:
5619 for n in names:
5620 if n in repo.tags():
5620 if n in repo.tags():
5621 raise util.Abort(_("tag '%s' already exists "
5621 raise util.Abort(_("tag '%s' already exists "
5622 "(use -f to force)") % n)
5622 "(use -f to force)") % n)
5623 if not opts.get('local'):
5623 if not opts.get('local'):
5624 p1, p2 = repo.dirstate.parents()
5624 p1, p2 = repo.dirstate.parents()
5625 if p2 != nullid:
5625 if p2 != nullid:
5626 raise util.Abort(_('uncommitted merge'))
5626 raise util.Abort(_('uncommitted merge'))
5627 bheads = repo.branchheads()
5627 bheads = repo.branchheads()
5628 if not opts.get('force') and bheads and p1 not in bheads:
5628 if not opts.get('force') and bheads and p1 not in bheads:
5629 raise util.Abort(_('not at a branch head (use -f to force)'))
5629 raise util.Abort(_('not at a branch head (use -f to force)'))
5630 r = scmutil.revsingle(repo, rev_).node()
5630 r = scmutil.revsingle(repo, rev_).node()
5631
5631
5632 if not message:
5632 if not message:
5633 # we don't translate commit messages
5633 # we don't translate commit messages
5634 message = ('Added tag %s for changeset %s' %
5634 message = ('Added tag %s for changeset %s' %
5635 (', '.join(names), short(r)))
5635 (', '.join(names), short(r)))
5636
5636
5637 date = opts.get('date')
5637 date = opts.get('date')
5638 if date:
5638 if date:
5639 date = util.parsedate(date)
5639 date = util.parsedate(date)
5640
5640
5641 if opts.get('edit'):
5641 if opts.get('edit'):
5642 message = ui.edit(message, ui.username())
5642 message = ui.edit(message, ui.username())
5643
5643
5644 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5644 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5645 finally:
5645 finally:
5646 release(lock, wlock)
5646 release(lock, wlock)
5647
5647
5648 @command('tags', [], '')
5648 @command('tags', [], '')
5649 def tags(ui, repo):
5649 def tags(ui, repo):
5650 """list repository tags
5650 """list repository tags
5651
5651
5652 This lists both regular and local tags. When the -v/--verbose
5652 This lists both regular and local tags. When the -v/--verbose
5653 switch is used, a third column "local" is printed for local tags.
5653 switch is used, a third column "local" is printed for local tags.
5654
5654
5655 Returns 0 on success.
5655 Returns 0 on success.
5656 """
5656 """
5657
5657
5658 hexfunc = ui.debugflag and hex or short
5658 hexfunc = ui.debugflag and hex or short
5659 tagtype = ""
5659 tagtype = ""
5660
5660
5661 for t, n in reversed(repo.tagslist()):
5661 for t, n in reversed(repo.tagslist()):
5662 if ui.quiet:
5662 if ui.quiet:
5663 ui.write("%s\n" % t, label='tags.normal')
5663 ui.write("%s\n" % t, label='tags.normal')
5664 continue
5664 continue
5665
5665
5666 hn = hexfunc(n)
5666 hn = hexfunc(n)
5667 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5667 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5668 rev = ui.label(r, 'log.changeset')
5668 rev = ui.label(r, 'log.changeset')
5669 spaces = " " * (30 - encoding.colwidth(t))
5669 spaces = " " * (30 - encoding.colwidth(t))
5670
5670
5671 tag = ui.label(t, 'tags.normal')
5671 tag = ui.label(t, 'tags.normal')
5672 if ui.verbose:
5672 if ui.verbose:
5673 if repo.tagtype(t) == 'local':
5673 if repo.tagtype(t) == 'local':
5674 tagtype = " local"
5674 tagtype = " local"
5675 tag = ui.label(t, 'tags.local')
5675 tag = ui.label(t, 'tags.local')
5676 else:
5676 else:
5677 tagtype = ""
5677 tagtype = ""
5678 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5678 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5679
5679
5680 @command('tip',
5680 @command('tip',
5681 [('p', 'patch', None, _('show patch')),
5681 [('p', 'patch', None, _('show patch')),
5682 ('g', 'git', None, _('use git extended diff format')),
5682 ('g', 'git', None, _('use git extended diff format')),
5683 ] + templateopts,
5683 ] + templateopts,
5684 _('[-p] [-g]'))
5684 _('[-p] [-g]'))
5685 def tip(ui, repo, **opts):
5685 def tip(ui, repo, **opts):
5686 """show the tip revision
5686 """show the tip revision
5687
5687
5688 The tip revision (usually just called the tip) is the changeset
5688 The tip revision (usually just called the tip) is the changeset
5689 most recently added to the repository (and therefore the most
5689 most recently added to the repository (and therefore the most
5690 recently changed head).
5690 recently changed head).
5691
5691
5692 If you have just made a commit, that commit will be the tip. If
5692 If you have just made a commit, that commit will be the tip. If
5693 you have just pulled changes from another repository, the tip of
5693 you have just pulled changes from another repository, the tip of
5694 that repository becomes the current tip. The "tip" tag is special
5694 that repository becomes the current tip. The "tip" tag is special
5695 and cannot be renamed or assigned to a different changeset.
5695 and cannot be renamed or assigned to a different changeset.
5696
5696
5697 Returns 0 on success.
5697 Returns 0 on success.
5698 """
5698 """
5699 displayer = cmdutil.show_changeset(ui, repo, opts)
5699 displayer = cmdutil.show_changeset(ui, repo, opts)
5700 displayer.show(repo[len(repo) - 1])
5700 displayer.show(repo[len(repo) - 1])
5701 displayer.close()
5701 displayer.close()
5702
5702
5703 @command('unbundle',
5703 @command('unbundle',
5704 [('u', 'update', None,
5704 [('u', 'update', None,
5705 _('update to new branch head if changesets were unbundled'))],
5705 _('update to new branch head if changesets were unbundled'))],
5706 _('[-u] FILE...'))
5706 _('[-u] FILE...'))
5707 def unbundle(ui, repo, fname1, *fnames, **opts):
5707 def unbundle(ui, repo, fname1, *fnames, **opts):
5708 """apply one or more changegroup files
5708 """apply one or more changegroup files
5709
5709
5710 Apply one or more compressed changegroup files generated by the
5710 Apply one or more compressed changegroup files generated by the
5711 bundle command.
5711 bundle command.
5712
5712
5713 Returns 0 on success, 1 if an update has unresolved files.
5713 Returns 0 on success, 1 if an update has unresolved files.
5714 """
5714 """
5715 fnames = (fname1,) + fnames
5715 fnames = (fname1,) + fnames
5716
5716
5717 lock = repo.lock()
5717 lock = repo.lock()
5718 wc = repo['.']
5718 wc = repo['.']
5719 try:
5719 try:
5720 for fname in fnames:
5720 for fname in fnames:
5721 f = url.open(ui, fname)
5721 f = url.open(ui, fname)
5722 gen = changegroup.readbundle(f, fname)
5722 gen = changegroup.readbundle(f, fname)
5723 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5723 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5724 finally:
5724 finally:
5725 lock.release()
5725 lock.release()
5726 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5726 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5727 return postincoming(ui, repo, modheads, opts.get('update'), None)
5727 return postincoming(ui, repo, modheads, opts.get('update'), None)
5728
5728
5729 @command('^update|up|checkout|co',
5729 @command('^update|up|checkout|co',
5730 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5730 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5731 ('c', 'check', None,
5731 ('c', 'check', None,
5732 _('update across branches if no uncommitted changes')),
5732 _('update across branches if no uncommitted changes')),
5733 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5733 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5734 ('r', 'rev', '', _('revision'), _('REV'))],
5734 ('r', 'rev', '', _('revision'), _('REV'))],
5735 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5735 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5736 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5736 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5737 """update working directory (or switch revisions)
5737 """update working directory (or switch revisions)
5738
5738
5739 Update the repository's working directory to the specified
5739 Update the repository's working directory to the specified
5740 changeset. If no changeset is specified, update to the tip of the
5740 changeset. If no changeset is specified, update to the tip of the
5741 current named branch and move the current bookmark (see :hg:`help
5741 current named branch and move the current bookmark (see :hg:`help
5742 bookmarks`).
5742 bookmarks`).
5743
5743
5744 Update sets the working directory's parent revison to the specified
5744 Update sets the working directory's parent revison to the specified
5745 changeset (see :hg:`help parents`).
5745 changeset (see :hg:`help parents`).
5746
5746
5747 If the changeset is not a descendant or ancestor of the working
5747 If the changeset is not a descendant or ancestor of the working
5748 directory's parent, the update is aborted. With the -c/--check
5748 directory's parent, the update is aborted. With the -c/--check
5749 option, the working directory is checked for uncommitted changes; if
5749 option, the working directory is checked for uncommitted changes; if
5750 none are found, the working directory is updated to the specified
5750 none are found, the working directory is updated to the specified
5751 changeset.
5751 changeset.
5752
5752
5753 The following rules apply when the working directory contains
5753 .. container:: verbose
5754 uncommitted changes:
5754
5755
5755 The following rules apply when the working directory contains
5756 1. If neither -c/--check nor -C/--clean is specified, and if
5756 uncommitted changes:
5757 the requested changeset is an ancestor or descendant of
5757
5758 the working directory's parent, the uncommitted changes
5758 1. If neither -c/--check nor -C/--clean is specified, and if
5759 are merged into the requested changeset and the merged
5759 the requested changeset is an ancestor or descendant of
5760 result is left uncommitted. If the requested changeset is
5760 the working directory's parent, the uncommitted changes
5761 not an ancestor or descendant (that is, it is on another
5761 are merged into the requested changeset and the merged
5762 branch), the update is aborted and the uncommitted changes
5762 result is left uncommitted. If the requested changeset is
5763 are preserved.
5763 not an ancestor or descendant (that is, it is on another
5764
5764 branch), the update is aborted and the uncommitted changes
5765 2. With the -c/--check option, the update is aborted and the
5765 are preserved.
5766 uncommitted changes are preserved.
5766
5767
5767 2. With the -c/--check option, the update is aborted and the
5768 3. With the -C/--clean option, uncommitted changes are discarded and
5768 uncommitted changes are preserved.
5769 the working directory is updated to the requested changeset.
5769
5770 3. With the -C/--clean option, uncommitted changes are discarded and
5771 the working directory is updated to the requested changeset.
5770
5772
5771 To cancel an uncommitted merge (and lose your changes), use
5773 To cancel an uncommitted merge (and lose your changes), use
5772 :hg:`update --clean .`.
5774 :hg:`update --clean .`.
5773
5775
5774 Use null as the changeset to remove the working directory (like
5776 Use null as the changeset to remove the working directory (like
5775 :hg:`clone -U`).
5777 :hg:`clone -U`).
5776
5778
5777 If you want to revert just one file to an older revision, use
5779 If you want to revert just one file to an older revision, use
5778 :hg:`revert [-r REV] NAME`.
5780 :hg:`revert [-r REV] NAME`.
5779
5781
5780 See :hg:`help dates` for a list of formats valid for -d/--date.
5782 See :hg:`help dates` for a list of formats valid for -d/--date.
5781
5783
5782 Returns 0 on success, 1 if there are unresolved files.
5784 Returns 0 on success, 1 if there are unresolved files.
5783 """
5785 """
5784 if rev and node:
5786 if rev and node:
5785 raise util.Abort(_("please specify just one revision"))
5787 raise util.Abort(_("please specify just one revision"))
5786
5788
5787 if rev is None or rev == '':
5789 if rev is None or rev == '':
5788 rev = node
5790 rev = node
5789
5791
5790 # with no argument, we also move the current bookmark, if any
5792 # with no argument, we also move the current bookmark, if any
5791 movemarkfrom = None
5793 movemarkfrom = None
5792 if rev is None or node == '':
5794 if rev is None or node == '':
5793 movemarkfrom = repo['.'].node()
5795 movemarkfrom = repo['.'].node()
5794
5796
5795 # if we defined a bookmark, we have to remember the original bookmark name
5797 # if we defined a bookmark, we have to remember the original bookmark name
5796 brev = rev
5798 brev = rev
5797 rev = scmutil.revsingle(repo, rev, rev).rev()
5799 rev = scmutil.revsingle(repo, rev, rev).rev()
5798
5800
5799 if check and clean:
5801 if check and clean:
5800 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5802 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5801
5803
5802 if date:
5804 if date:
5803 if rev is not None:
5805 if rev is not None:
5804 raise util.Abort(_("you can't specify a revision and a date"))
5806 raise util.Abort(_("you can't specify a revision and a date"))
5805 rev = cmdutil.finddate(ui, repo, date)
5807 rev = cmdutil.finddate(ui, repo, date)
5806
5808
5807 if check:
5809 if check:
5808 c = repo[None]
5810 c = repo[None]
5809 if c.dirty(merge=False, branch=False):
5811 if c.dirty(merge=False, branch=False):
5810 raise util.Abort(_("uncommitted local changes"))
5812 raise util.Abort(_("uncommitted local changes"))
5811 if rev is None:
5813 if rev is None:
5812 rev = repo[repo[None].branch()].rev()
5814 rev = repo[repo[None].branch()].rev()
5813 mergemod._checkunknown(repo, repo[None], repo[rev])
5815 mergemod._checkunknown(repo, repo[None], repo[rev])
5814
5816
5815 if clean:
5817 if clean:
5816 ret = hg.clean(repo, rev)
5818 ret = hg.clean(repo, rev)
5817 else:
5819 else:
5818 ret = hg.update(repo, rev)
5820 ret = hg.update(repo, rev)
5819
5821
5820 if not ret and movemarkfrom:
5822 if not ret and movemarkfrom:
5821 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5823 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5822 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5824 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5823 elif brev in repo._bookmarks:
5825 elif brev in repo._bookmarks:
5824 bookmarks.setcurrent(repo, brev)
5826 bookmarks.setcurrent(repo, brev)
5825 elif brev:
5827 elif brev:
5826 bookmarks.unsetcurrent(repo)
5828 bookmarks.unsetcurrent(repo)
5827
5829
5828 return ret
5830 return ret
5829
5831
5830 @command('verify', [])
5832 @command('verify', [])
5831 def verify(ui, repo):
5833 def verify(ui, repo):
5832 """verify the integrity of the repository
5834 """verify the integrity of the repository
5833
5835
5834 Verify the integrity of the current repository.
5836 Verify the integrity of the current repository.
5835
5837
5836 This will perform an extensive check of the repository's
5838 This will perform an extensive check of the repository's
5837 integrity, validating the hashes and checksums of each entry in
5839 integrity, validating the hashes and checksums of each entry in
5838 the changelog, manifest, and tracked files, as well as the
5840 the changelog, manifest, and tracked files, as well as the
5839 integrity of their crosslinks and indices.
5841 integrity of their crosslinks and indices.
5840
5842
5841 Returns 0 on success, 1 if errors are encountered.
5843 Returns 0 on success, 1 if errors are encountered.
5842 """
5844 """
5843 return hg.verify(repo)
5845 return hg.verify(repo)
5844
5846
5845 @command('version', [])
5847 @command('version', [])
5846 def version_(ui):
5848 def version_(ui):
5847 """output version and copyright information"""
5849 """output version and copyright information"""
5848 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5850 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5849 % util.version())
5851 % util.version())
5850 ui.status(_(
5852 ui.status(_(
5851 "(see http://mercurial.selenic.com for more information)\n"
5853 "(see http://mercurial.selenic.com for more information)\n"
5852 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5854 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5853 "This is free software; see the source for copying conditions. "
5855 "This is free software; see the source for copying conditions. "
5854 "There is NO\nwarranty; "
5856 "There is NO\nwarranty; "
5855 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5857 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5856 ))
5858 ))
5857
5859
5858 norepo = ("clone init version help debugcommands debugcomplete"
5860 norepo = ("clone init version help debugcommands debugcomplete"
5859 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5861 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5860 " debugknown debuggetbundle debugbundle")
5862 " debugknown debuggetbundle debugbundle")
5861 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5863 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5862 " debugdata debugindex debugindexdot debugrevlog")
5864 " debugdata debugindex debugindexdot debugrevlog")
General Comments 0
You need to be logged in to leave comments. Login now