##// END OF EJS Templates
commit: --edit/-e to force edit of otherwise-supplied commit message...
"Bradley M. Kuhn" -
r21021:42298149 default
parent child Browse files
Show More
@@ -1,5938 +1,5942 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 from hgweb import server as hgweb_server
17 from hgweb import server as hgweb_server
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod
20 import dagparser, context, simplemerge, graphmod
21 import random
21 import random
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import phases, obsolete
23 import phases, obsolete
24
24
25 table = {}
25 table = {}
26
26
27 command = cmdutil.command(table)
27 command = cmdutil.command(table)
28
28
29 # common command options
29 # common command options
30
30
31 globalopts = [
31 globalopts = [
32 ('R', 'repository', '',
32 ('R', 'repository', '',
33 _('repository root directory or name of overlay bundle file'),
33 _('repository root directory or name of overlay bundle file'),
34 _('REPO')),
34 _('REPO')),
35 ('', 'cwd', '',
35 ('', 'cwd', '',
36 _('change working directory'), _('DIR')),
36 _('change working directory'), _('DIR')),
37 ('y', 'noninteractive', None,
37 ('y', 'noninteractive', None,
38 _('do not prompt, automatically pick the first choice for all prompts')),
38 _('do not prompt, automatically pick the first choice for all prompts')),
39 ('q', 'quiet', None, _('suppress output')),
39 ('q', 'quiet', None, _('suppress output')),
40 ('v', 'verbose', None, _('enable additional output')),
40 ('v', 'verbose', None, _('enable additional output')),
41 ('', 'config', [],
41 ('', 'config', [],
42 _('set/override config option (use \'section.name=value\')'),
42 _('set/override config option (use \'section.name=value\')'),
43 _('CONFIG')),
43 _('CONFIG')),
44 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debug', None, _('enable debugging output')),
45 ('', 'debugger', None, _('start debugger')),
45 ('', 'debugger', None, _('start debugger')),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
47 _('ENCODE')),
47 _('ENCODE')),
48 ('', 'encodingmode', encoding.encodingmode,
48 ('', 'encodingmode', encoding.encodingmode,
49 _('set the charset encoding mode'), _('MODE')),
49 _('set the charset encoding mode'), _('MODE')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
51 ('', 'time', None, _('time how long the command takes')),
51 ('', 'time', None, _('time how long the command takes')),
52 ('', 'profile', None, _('print command execution profile')),
52 ('', 'profile', None, _('print command execution profile')),
53 ('', 'version', None, _('output version information and exit')),
53 ('', 'version', None, _('output version information and exit')),
54 ('h', 'help', None, _('display help and exit')),
54 ('h', 'help', None, _('display help and exit')),
55 ('', 'hidden', False, _('consider hidden changesets')),
55 ('', 'hidden', False, _('consider hidden changesets')),
56 ]
56 ]
57
57
58 dryrunopts = [('n', 'dry-run', None,
58 dryrunopts = [('n', 'dry-run', None,
59 _('do not perform actions, just print output'))]
59 _('do not perform actions, just print output'))]
60
60
61 remoteopts = [
61 remoteopts = [
62 ('e', 'ssh', '',
62 ('e', 'ssh', '',
63 _('specify ssh command to use'), _('CMD')),
63 _('specify ssh command to use'), _('CMD')),
64 ('', 'remotecmd', '',
64 ('', 'remotecmd', '',
65 _('specify hg command to run on the remote side'), _('CMD')),
65 _('specify hg command to run on the remote side'), _('CMD')),
66 ('', 'insecure', None,
66 ('', 'insecure', None,
67 _('do not verify server certificate (ignoring web.cacerts config)')),
67 _('do not verify server certificate (ignoring web.cacerts config)')),
68 ]
68 ]
69
69
70 walkopts = [
70 walkopts = [
71 ('I', 'include', [],
71 ('I', 'include', [],
72 _('include names matching the given patterns'), _('PATTERN')),
72 _('include names matching the given patterns'), _('PATTERN')),
73 ('X', 'exclude', [],
73 ('X', 'exclude', [],
74 _('exclude names matching the given patterns'), _('PATTERN')),
74 _('exclude names matching the given patterns'), _('PATTERN')),
75 ]
75 ]
76
76
77 commitopts = [
77 commitopts = [
78 ('m', 'message', '',
78 ('m', 'message', '',
79 _('use text as commit message'), _('TEXT')),
79 _('use text as commit message'), _('TEXT')),
80 ('l', 'logfile', '',
80 ('l', 'logfile', '',
81 _('read commit message from file'), _('FILE')),
81 _('read commit message from file'), _('FILE')),
82 ]
82 ]
83
83
84 commitopts2 = [
84 commitopts2 = [
85 ('d', 'date', '',
85 ('d', 'date', '',
86 _('record the specified date as commit date'), _('DATE')),
86 _('record the specified date as commit date'), _('DATE')),
87 ('u', 'user', '',
87 ('u', 'user', '',
88 _('record the specified user as committer'), _('USER')),
88 _('record the specified user as committer'), _('USER')),
89 ]
89 ]
90
90
91 templateopts = [
91 templateopts = [
92 ('', 'style', '',
92 ('', 'style', '',
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
94 ('T', 'template', '',
94 ('T', 'template', '',
95 _('display with template'), _('TEMPLATE')),
95 _('display with template'), _('TEMPLATE')),
96 ]
96 ]
97
97
98 logopts = [
98 logopts = [
99 ('p', 'patch', None, _('show patch')),
99 ('p', 'patch', None, _('show patch')),
100 ('g', 'git', None, _('use git extended diff format')),
100 ('g', 'git', None, _('use git extended diff format')),
101 ('l', 'limit', '',
101 ('l', 'limit', '',
102 _('limit number of changes displayed'), _('NUM')),
102 _('limit number of changes displayed'), _('NUM')),
103 ('M', 'no-merges', None, _('do not show merges')),
103 ('M', 'no-merges', None, _('do not show merges')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
105 ('G', 'graph', None, _("show the revision DAG")),
105 ('G', 'graph', None, _("show the revision DAG")),
106 ] + templateopts
106 ] + templateopts
107
107
108 diffopts = [
108 diffopts = [
109 ('a', 'text', None, _('treat all files as text')),
109 ('a', 'text', None, _('treat all files as text')),
110 ('g', 'git', None, _('use git extended diff format')),
110 ('g', 'git', None, _('use git extended diff format')),
111 ('', 'nodates', None, _('omit dates from diff headers'))
111 ('', 'nodates', None, _('omit dates from diff headers'))
112 ]
112 ]
113
113
114 diffwsopts = [
114 diffwsopts = [
115 ('w', 'ignore-all-space', None,
115 ('w', 'ignore-all-space', None,
116 _('ignore white space when comparing lines')),
116 _('ignore white space when comparing lines')),
117 ('b', 'ignore-space-change', None,
117 ('b', 'ignore-space-change', None,
118 _('ignore changes in the amount of white space')),
118 _('ignore changes in the amount of white space')),
119 ('B', 'ignore-blank-lines', None,
119 ('B', 'ignore-blank-lines', None,
120 _('ignore changes whose lines are all blank')),
120 _('ignore changes whose lines are all blank')),
121 ]
121 ]
122
122
123 diffopts2 = [
123 diffopts2 = [
124 ('p', 'show-function', None, _('show which function each change is in')),
124 ('p', 'show-function', None, _('show which function each change is in')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
126 ] + diffwsopts + [
126 ] + diffwsopts + [
127 ('U', 'unified', '',
127 ('U', 'unified', '',
128 _('number of lines of context to show'), _('NUM')),
128 _('number of lines of context to show'), _('NUM')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
130 ]
130 ]
131
131
132 mergetoolopts = [
132 mergetoolopts = [
133 ('t', 'tool', '', _('specify merge tool')),
133 ('t', 'tool', '', _('specify merge tool')),
134 ]
134 ]
135
135
136 similarityopts = [
136 similarityopts = [
137 ('s', 'similarity', '',
137 ('s', 'similarity', '',
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
139 ]
139 ]
140
140
141 subrepoopts = [
141 subrepoopts = [
142 ('S', 'subrepos', None,
142 ('S', 'subrepos', None,
143 _('recurse into subrepositories'))
143 _('recurse into subrepositories'))
144 ]
144 ]
145
145
146 # Commands start here, listed alphabetically
146 # Commands start here, listed alphabetically
147
147
148 @command('^add',
148 @command('^add',
149 walkopts + subrepoopts + dryrunopts,
149 walkopts + subrepoopts + dryrunopts,
150 _('[OPTION]... [FILE]...'))
150 _('[OPTION]... [FILE]...'))
151 def add(ui, repo, *pats, **opts):
151 def add(ui, repo, *pats, **opts):
152 """add the specified files on the next commit
152 """add the specified files on the next commit
153
153
154 Schedule files to be version controlled and added to the
154 Schedule files to be version controlled and added to the
155 repository.
155 repository.
156
156
157 The files will be added to the repository at the next commit. To
157 The files will be added to the repository at the next commit. To
158 undo an add before that, see :hg:`forget`.
158 undo an add before that, see :hg:`forget`.
159
159
160 If no names are given, add all files to the repository.
160 If no names are given, add all files to the repository.
161
161
162 .. container:: verbose
162 .. container:: verbose
163
163
164 An example showing how new (unknown) files are added
164 An example showing how new (unknown) files are added
165 automatically by :hg:`add`::
165 automatically by :hg:`add`::
166
166
167 $ ls
167 $ ls
168 foo.c
168 foo.c
169 $ hg status
169 $ hg status
170 ? foo.c
170 ? foo.c
171 $ hg add
171 $ hg add
172 adding foo.c
172 adding foo.c
173 $ hg status
173 $ hg status
174 A foo.c
174 A foo.c
175
175
176 Returns 0 if all files are successfully added.
176 Returns 0 if all files are successfully added.
177 """
177 """
178
178
179 m = scmutil.match(repo[None], pats, opts)
179 m = scmutil.match(repo[None], pats, opts)
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
181 opts.get('subrepos'), prefix="", explicitonly=False)
181 opts.get('subrepos'), prefix="", explicitonly=False)
182 return rejected and 1 or 0
182 return rejected and 1 or 0
183
183
184 @command('addremove',
184 @command('addremove',
185 similarityopts + walkopts + dryrunopts,
185 similarityopts + walkopts + dryrunopts,
186 _('[OPTION]... [FILE]...'))
186 _('[OPTION]... [FILE]...'))
187 def addremove(ui, repo, *pats, **opts):
187 def addremove(ui, repo, *pats, **opts):
188 """add all new files, delete all missing files
188 """add all new files, delete all missing files
189
189
190 Add all new files and remove all missing files from the
190 Add all new files and remove all missing files from the
191 repository.
191 repository.
192
192
193 New files are ignored if they match any of the patterns in
193 New files are ignored if they match any of the patterns in
194 ``.hgignore``. As with add, these changes take effect at the next
194 ``.hgignore``. As with add, these changes take effect at the next
195 commit.
195 commit.
196
196
197 Use the -s/--similarity option to detect renamed files. This
197 Use the -s/--similarity option to detect renamed files. This
198 option takes a percentage between 0 (disabled) and 100 (files must
198 option takes a percentage between 0 (disabled) and 100 (files must
199 be identical) as its parameter. With a parameter greater than 0,
199 be identical) as its parameter. With a parameter greater than 0,
200 this compares every removed file with every added file and records
200 this compares every removed file with every added file and records
201 those similar enough as renames. Detecting renamed files this way
201 those similar enough as renames. Detecting renamed files this way
202 can be expensive. After using this option, :hg:`status -C` can be
202 can be expensive. After using this option, :hg:`status -C` can be
203 used to check which files were identified as moved or renamed. If
203 used to check which files were identified as moved or renamed. If
204 not specified, -s/--similarity defaults to 100 and only renames of
204 not specified, -s/--similarity defaults to 100 and only renames of
205 identical files are detected.
205 identical files are detected.
206
206
207 Returns 0 if all files are successfully added.
207 Returns 0 if all files are successfully added.
208 """
208 """
209 try:
209 try:
210 sim = float(opts.get('similarity') or 100)
210 sim = float(opts.get('similarity') or 100)
211 except ValueError:
211 except ValueError:
212 raise util.Abort(_('similarity must be a number'))
212 raise util.Abort(_('similarity must be a number'))
213 if sim < 0 or sim > 100:
213 if sim < 0 or sim > 100:
214 raise util.Abort(_('similarity must be between 0 and 100'))
214 raise util.Abort(_('similarity must be between 0 and 100'))
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
216
216
217 @command('^annotate|blame',
217 @command('^annotate|blame',
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
219 ('', 'follow', None,
219 ('', 'follow', None,
220 _('follow copies/renames and list the filename (DEPRECATED)')),
220 _('follow copies/renames and list the filename (DEPRECATED)')),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
222 ('a', 'text', None, _('treat all files as text')),
222 ('a', 'text', None, _('treat all files as text')),
223 ('u', 'user', None, _('list the author (long with -v)')),
223 ('u', 'user', None, _('list the author (long with -v)')),
224 ('f', 'file', None, _('list the filename')),
224 ('f', 'file', None, _('list the filename')),
225 ('d', 'date', None, _('list the date (short with -q)')),
225 ('d', 'date', None, _('list the date (short with -q)')),
226 ('n', 'number', None, _('list the revision number (default)')),
226 ('n', 'number', None, _('list the revision number (default)')),
227 ('c', 'changeset', None, _('list the changeset')),
227 ('c', 'changeset', None, _('list the changeset')),
228 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ('l', 'line-number', None, _('show line number at the first appearance'))
229 ] + diffwsopts + walkopts,
229 ] + diffwsopts + walkopts,
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
231 def annotate(ui, repo, *pats, **opts):
231 def annotate(ui, repo, *pats, **opts):
232 """show changeset information by line for each file
232 """show changeset information by line for each file
233
233
234 List changes in files, showing the revision id responsible for
234 List changes in files, showing the revision id responsible for
235 each line
235 each line
236
236
237 This command is useful for discovering when a change was made and
237 This command is useful for discovering when a change was made and
238 by whom.
238 by whom.
239
239
240 Without the -a/--text option, annotate will avoid processing files
240 Without the -a/--text option, annotate will avoid processing files
241 it detects as binary. With -a, annotate will annotate the file
241 it detects as binary. With -a, annotate will annotate the file
242 anyway, although the results will probably be neither useful
242 anyway, although the results will probably be neither useful
243 nor desirable.
243 nor desirable.
244
244
245 Returns 0 on success.
245 Returns 0 on success.
246 """
246 """
247 if opts.get('follow'):
247 if opts.get('follow'):
248 # --follow is deprecated and now just an alias for -f/--file
248 # --follow is deprecated and now just an alias for -f/--file
249 # to mimic the behavior of Mercurial before version 1.5
249 # to mimic the behavior of Mercurial before version 1.5
250 opts['file'] = True
250 opts['file'] = True
251
251
252 datefunc = ui.quiet and util.shortdate or util.datestr
252 datefunc = ui.quiet and util.shortdate or util.datestr
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
254
254
255 if not pats:
255 if not pats:
256 raise util.Abort(_('at least one filename or pattern is required'))
256 raise util.Abort(_('at least one filename or pattern is required'))
257
257
258 hexfn = ui.debugflag and hex or short
258 hexfn = ui.debugflag and hex or short
259
259
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
261 ('number', ' ', lambda x: str(x[0].rev())),
261 ('number', ' ', lambda x: str(x[0].rev())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
263 ('date', ' ', getdate),
263 ('date', ' ', getdate),
264 ('file', ' ', lambda x: x[0].path()),
264 ('file', ' ', lambda x: x[0].path()),
265 ('line_number', ':', lambda x: str(x[1])),
265 ('line_number', ':', lambda x: str(x[1])),
266 ]
266 ]
267
267
268 if (not opts.get('user') and not opts.get('changeset')
268 if (not opts.get('user') and not opts.get('changeset')
269 and not opts.get('date') and not opts.get('file')):
269 and not opts.get('date') and not opts.get('file')):
270 opts['number'] = True
270 opts['number'] = True
271
271
272 linenumber = opts.get('line_number') is not None
272 linenumber = opts.get('line_number') is not None
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
275
275
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
278
278
279 def bad(x, y):
279 def bad(x, y):
280 raise util.Abort("%s: %s" % (x, y))
280 raise util.Abort("%s: %s" % (x, y))
281
281
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 m = scmutil.match(ctx, pats, opts)
283 m = scmutil.match(ctx, pats, opts)
284 m.bad = bad
284 m.bad = bad
285 follow = not opts.get('no_follow')
285 follow = not opts.get('no_follow')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
287 for abs in ctx.walk(m):
287 for abs in ctx.walk(m):
288 fctx = ctx[abs]
288 fctx = ctx[abs]
289 if not opts.get('text') and util.binary(fctx.data()):
289 if not opts.get('text') and util.binary(fctx.data()):
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
291 continue
291 continue
292
292
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
294 diffopts=diffopts)
294 diffopts=diffopts)
295 pieces = []
295 pieces = []
296
296
297 for f, sep in funcmap:
297 for f, sep in funcmap:
298 l = [f(n) for n, dummy in lines]
298 l = [f(n) for n, dummy in lines]
299 if l:
299 if l:
300 sized = [(x, encoding.colwidth(x)) for x in l]
300 sized = [(x, encoding.colwidth(x)) for x in l]
301 ml = max([w for x, w in sized])
301 ml = max([w for x, w in sized])
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
303 for x, w in sized])
303 for x, w in sized])
304
304
305 if pieces:
305 if pieces:
306 for p, l in zip(zip(*pieces), lines):
306 for p, l in zip(zip(*pieces), lines):
307 ui.write("%s: %s" % ("".join(p), l[1]))
307 ui.write("%s: %s" % ("".join(p), l[1]))
308
308
309 if lines and not lines[-1][1].endswith('\n'):
309 if lines and not lines[-1][1].endswith('\n'):
310 ui.write('\n')
310 ui.write('\n')
311
311
312 @command('archive',
312 @command('archive',
313 [('', 'no-decode', None, _('do not pass files through decoders')),
313 [('', 'no-decode', None, _('do not pass files through decoders')),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
315 _('PREFIX')),
315 _('PREFIX')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
318 ] + subrepoopts + walkopts,
318 ] + subrepoopts + walkopts,
319 _('[OPTION]... DEST'))
319 _('[OPTION]... DEST'))
320 def archive(ui, repo, dest, **opts):
320 def archive(ui, repo, dest, **opts):
321 '''create an unversioned archive of a repository revision
321 '''create an unversioned archive of a repository revision
322
322
323 By default, the revision used is the parent of the working
323 By default, the revision used is the parent of the working
324 directory; use -r/--rev to specify a different revision.
324 directory; use -r/--rev to specify a different revision.
325
325
326 The archive type is automatically detected based on file
326 The archive type is automatically detected based on file
327 extension (or override using -t/--type).
327 extension (or override using -t/--type).
328
328
329 .. container:: verbose
329 .. container:: verbose
330
330
331 Examples:
331 Examples:
332
332
333 - create a zip file containing the 1.0 release::
333 - create a zip file containing the 1.0 release::
334
334
335 hg archive -r 1.0 project-1.0.zip
335 hg archive -r 1.0 project-1.0.zip
336
336
337 - create a tarball excluding .hg files::
337 - create a tarball excluding .hg files::
338
338
339 hg archive project.tar.gz -X ".hg*"
339 hg archive project.tar.gz -X ".hg*"
340
340
341 Valid types are:
341 Valid types are:
342
342
343 :``files``: a directory full of files (default)
343 :``files``: a directory full of files (default)
344 :``tar``: tar archive, uncompressed
344 :``tar``: tar archive, uncompressed
345 :``tbz2``: tar archive, compressed using bzip2
345 :``tbz2``: tar archive, compressed using bzip2
346 :``tgz``: tar archive, compressed using gzip
346 :``tgz``: tar archive, compressed using gzip
347 :``uzip``: zip archive, uncompressed
347 :``uzip``: zip archive, uncompressed
348 :``zip``: zip archive, compressed using deflate
348 :``zip``: zip archive, compressed using deflate
349
349
350 The exact name of the destination archive or directory is given
350 The exact name of the destination archive or directory is given
351 using a format string; see :hg:`help export` for details.
351 using a format string; see :hg:`help export` for details.
352
352
353 Each member added to an archive file has a directory prefix
353 Each member added to an archive file has a directory prefix
354 prepended. Use -p/--prefix to specify a format string for the
354 prepended. Use -p/--prefix to specify a format string for the
355 prefix. The default is the basename of the archive, with suffixes
355 prefix. The default is the basename of the archive, with suffixes
356 removed.
356 removed.
357
357
358 Returns 0 on success.
358 Returns 0 on success.
359 '''
359 '''
360
360
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
362 if not ctx:
362 if not ctx:
363 raise util.Abort(_('no working directory: please specify a revision'))
363 raise util.Abort(_('no working directory: please specify a revision'))
364 node = ctx.node()
364 node = ctx.node()
365 dest = cmdutil.makefilename(repo, dest, node)
365 dest = cmdutil.makefilename(repo, dest, node)
366 if os.path.realpath(dest) == repo.root:
366 if os.path.realpath(dest) == repo.root:
367 raise util.Abort(_('repository root cannot be destination'))
367 raise util.Abort(_('repository root cannot be destination'))
368
368
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
370 prefix = opts.get('prefix')
370 prefix = opts.get('prefix')
371
371
372 if dest == '-':
372 if dest == '-':
373 if kind == 'files':
373 if kind == 'files':
374 raise util.Abort(_('cannot archive plain files to stdout'))
374 raise util.Abort(_('cannot archive plain files to stdout'))
375 dest = cmdutil.makefileobj(repo, dest)
375 dest = cmdutil.makefileobj(repo, dest)
376 if not prefix:
376 if not prefix:
377 prefix = os.path.basename(repo.root) + '-%h'
377 prefix = os.path.basename(repo.root) + '-%h'
378
378
379 prefix = cmdutil.makefilename(repo, prefix, node)
379 prefix = cmdutil.makefilename(repo, prefix, node)
380 matchfn = scmutil.match(ctx, [], opts)
380 matchfn = scmutil.match(ctx, [], opts)
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
382 matchfn, prefix, subrepos=opts.get('subrepos'))
382 matchfn, prefix, subrepos=opts.get('subrepos'))
383
383
384 @command('backout',
384 @command('backout',
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
386 ('', 'parent', '',
386 ('', 'parent', '',
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
390 _('[OPTION]... [-r] REV'))
390 _('[OPTION]... [-r] REV'))
391 def backout(ui, repo, node=None, rev=None, **opts):
391 def backout(ui, repo, node=None, rev=None, **opts):
392 '''reverse effect of earlier changeset
392 '''reverse effect of earlier changeset
393
393
394 Prepare a new changeset with the effect of REV undone in the
394 Prepare a new changeset with the effect of REV undone in the
395 current working directory.
395 current working directory.
396
396
397 If REV is the parent of the working directory, then this new changeset
397 If REV is the parent of the working directory, then this new changeset
398 is committed automatically. Otherwise, hg needs to merge the
398 is committed automatically. Otherwise, hg needs to merge the
399 changes and the merged result is left uncommitted.
399 changes and the merged result is left uncommitted.
400
400
401 .. note::
401 .. note::
402
402
403 backout cannot be used to fix either an unwanted or
403 backout cannot be used to fix either an unwanted or
404 incorrect merge.
404 incorrect merge.
405
405
406 .. container:: verbose
406 .. container:: verbose
407
407
408 By default, the pending changeset will have one parent,
408 By default, the pending changeset will have one parent,
409 maintaining a linear history. With --merge, the pending
409 maintaining a linear history. With --merge, the pending
410 changeset will instead have two parents: the old parent of the
410 changeset will instead have two parents: the old parent of the
411 working directory and a new child of REV that simply undoes REV.
411 working directory and a new child of REV that simply undoes REV.
412
412
413 Before version 1.7, the behavior without --merge was equivalent
413 Before version 1.7, the behavior without --merge was equivalent
414 to specifying --merge followed by :hg:`update --clean .` to
414 to specifying --merge followed by :hg:`update --clean .` to
415 cancel the merge and leave the child of REV as a head to be
415 cancel the merge and leave the child of REV as a head to be
416 merged separately.
416 merged separately.
417
417
418 See :hg:`help dates` for a list of formats valid for -d/--date.
418 See :hg:`help dates` for a list of formats valid for -d/--date.
419
419
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
421 files.
421 files.
422 '''
422 '''
423 if rev and node:
423 if rev and node:
424 raise util.Abort(_("please specify just one revision"))
424 raise util.Abort(_("please specify just one revision"))
425
425
426 if not rev:
426 if not rev:
427 rev = node
427 rev = node
428
428
429 if not rev:
429 if not rev:
430 raise util.Abort(_("please specify a revision to backout"))
430 raise util.Abort(_("please specify a revision to backout"))
431
431
432 date = opts.get('date')
432 date = opts.get('date')
433 if date:
433 if date:
434 opts['date'] = util.parsedate(date)
434 opts['date'] = util.parsedate(date)
435
435
436 cmdutil.checkunfinished(repo)
436 cmdutil.checkunfinished(repo)
437 cmdutil.bailifchanged(repo)
437 cmdutil.bailifchanged(repo)
438 node = scmutil.revsingle(repo, rev).node()
438 node = scmutil.revsingle(repo, rev).node()
439
439
440 op1, op2 = repo.dirstate.parents()
440 op1, op2 = repo.dirstate.parents()
441 if node not in repo.changelog.commonancestors(op1, node):
441 if node not in repo.changelog.commonancestors(op1, node):
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
443
443
444 p1, p2 = repo.changelog.parents(node)
444 p1, p2 = repo.changelog.parents(node)
445 if p1 == nullid:
445 if p1 == nullid:
446 raise util.Abort(_('cannot backout a change with no parents'))
446 raise util.Abort(_('cannot backout a change with no parents'))
447 if p2 != nullid:
447 if p2 != nullid:
448 if not opts.get('parent'):
448 if not opts.get('parent'):
449 raise util.Abort(_('cannot backout a merge changeset'))
449 raise util.Abort(_('cannot backout a merge changeset'))
450 p = repo.lookup(opts['parent'])
450 p = repo.lookup(opts['parent'])
451 if p not in (p1, p2):
451 if p not in (p1, p2):
452 raise util.Abort(_('%s is not a parent of %s') %
452 raise util.Abort(_('%s is not a parent of %s') %
453 (short(p), short(node)))
453 (short(p), short(node)))
454 parent = p
454 parent = p
455 else:
455 else:
456 if opts.get('parent'):
456 if opts.get('parent'):
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
458 parent = p1
458 parent = p1
459
459
460 # the backout should appear on the same branch
460 # the backout should appear on the same branch
461 wlock = repo.wlock()
461 wlock = repo.wlock()
462 try:
462 try:
463 branch = repo.dirstate.branch()
463 branch = repo.dirstate.branch()
464 bheads = repo.branchheads(branch)
464 bheads = repo.branchheads(branch)
465 rctx = scmutil.revsingle(repo, hex(parent))
465 rctx = scmutil.revsingle(repo, hex(parent))
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
469 'backout')
469 'backout')
470 stats = mergemod.update(repo, parent, True, True, False,
470 stats = mergemod.update(repo, parent, True, True, False,
471 node, False)
471 node, False)
472 repo.setparents(op1, op2)
472 repo.setparents(op1, op2)
473 hg._showstats(repo, stats)
473 hg._showstats(repo, stats)
474 if stats[3]:
474 if stats[3]:
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
476 "file merges\n"))
476 "file merges\n"))
477 else:
477 else:
478 msg = _("changeset %s backed out, "
478 msg = _("changeset %s backed out, "
479 "don't forget to commit.\n")
479 "don't forget to commit.\n")
480 ui.status(msg % short(node))
480 ui.status(msg % short(node))
481 return stats[3] > 0
481 return stats[3] > 0
482 finally:
482 finally:
483 ui.setconfig('ui', 'forcemerge', '', '')
483 ui.setconfig('ui', 'forcemerge', '', '')
484 else:
484 else:
485 hg.clean(repo, node, show_stats=False)
485 hg.clean(repo, node, show_stats=False)
486 repo.dirstate.setbranch(branch)
486 repo.dirstate.setbranch(branch)
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
488
488
489
489
490 e = cmdutil.commiteditor
490 e = cmdutil.commiteditor
491 if not opts['message'] and not opts['logfile']:
491 if not opts['message'] and not opts['logfile']:
492 # we don't translate commit messages
492 # we don't translate commit messages
493 opts['message'] = "Backed out changeset %s" % short(node)
493 opts['message'] = "Backed out changeset %s" % short(node)
494 e = cmdutil.commitforceeditor
494 e = cmdutil.commitforceeditor
495
495
496 def commitfunc(ui, repo, message, match, opts):
496 def commitfunc(ui, repo, message, match, opts):
497 return repo.commit(message, opts.get('user'), opts.get('date'),
497 return repo.commit(message, opts.get('user'), opts.get('date'),
498 match, editor=e)
498 match, editor=e)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
500 if not newnode:
500 if not newnode:
501 ui.status(_("nothing changed\n"))
501 ui.status(_("nothing changed\n"))
502 return 1
502 return 1
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
504
504
505 def nice(node):
505 def nice(node):
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
507 ui.status(_('changeset %s backs out changeset %s\n') %
507 ui.status(_('changeset %s backs out changeset %s\n') %
508 (nice(repo.changelog.tip()), nice(node)))
508 (nice(repo.changelog.tip()), nice(node)))
509 if opts.get('merge') and op1 != node:
509 if opts.get('merge') and op1 != node:
510 hg.clean(repo, op1, show_stats=False)
510 hg.clean(repo, op1, show_stats=False)
511 ui.status(_('merging with changeset %s\n')
511 ui.status(_('merging with changeset %s\n')
512 % nice(repo.changelog.tip()))
512 % nice(repo.changelog.tip()))
513 try:
513 try:
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
515 'backout')
515 'backout')
516 return hg.merge(repo, hex(repo.changelog.tip()))
516 return hg.merge(repo, hex(repo.changelog.tip()))
517 finally:
517 finally:
518 ui.setconfig('ui', 'forcemerge', '', '')
518 ui.setconfig('ui', 'forcemerge', '', '')
519 finally:
519 finally:
520 wlock.release()
520 wlock.release()
521 return 0
521 return 0
522
522
523 @command('bisect',
523 @command('bisect',
524 [('r', 'reset', False, _('reset bisect state')),
524 [('r', 'reset', False, _('reset bisect state')),
525 ('g', 'good', False, _('mark changeset good')),
525 ('g', 'good', False, _('mark changeset good')),
526 ('b', 'bad', False, _('mark changeset bad')),
526 ('b', 'bad', False, _('mark changeset bad')),
527 ('s', 'skip', False, _('skip testing changeset')),
527 ('s', 'skip', False, _('skip testing changeset')),
528 ('e', 'extend', False, _('extend the bisect range')),
528 ('e', 'extend', False, _('extend the bisect range')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
530 ('U', 'noupdate', False, _('do not update to target'))],
530 ('U', 'noupdate', False, _('do not update to target'))],
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
532 def bisect(ui, repo, rev=None, extra=None, command=None,
532 def bisect(ui, repo, rev=None, extra=None, command=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
534 noupdate=None):
534 noupdate=None):
535 """subdivision search of changesets
535 """subdivision search of changesets
536
536
537 This command helps to find changesets which introduce problems. To
537 This command helps to find changesets which introduce problems. To
538 use, mark the earliest changeset you know exhibits the problem as
538 use, mark the earliest changeset you know exhibits the problem as
539 bad, then mark the latest changeset which is free from the problem
539 bad, then mark the latest changeset which is free from the problem
540 as good. Bisect will update your working directory to a revision
540 as good. Bisect will update your working directory to a revision
541 for testing (unless the -U/--noupdate option is specified). Once
541 for testing (unless the -U/--noupdate option is specified). Once
542 you have performed tests, mark the working directory as good or
542 you have performed tests, mark the working directory as good or
543 bad, and bisect will either update to another candidate changeset
543 bad, and bisect will either update to another candidate changeset
544 or announce that it has found the bad revision.
544 or announce that it has found the bad revision.
545
545
546 As a shortcut, you can also use the revision argument to mark a
546 As a shortcut, you can also use the revision argument to mark a
547 revision as good or bad without checking it out first.
547 revision as good or bad without checking it out first.
548
548
549 If you supply a command, it will be used for automatic bisection.
549 If you supply a command, it will be used for automatic bisection.
550 The environment variable HG_NODE will contain the ID of the
550 The environment variable HG_NODE will contain the ID of the
551 changeset being tested. The exit status of the command will be
551 changeset being tested. The exit status of the command will be
552 used to mark revisions as good or bad: status 0 means good, 125
552 used to mark revisions as good or bad: status 0 means good, 125
553 means to skip the revision, 127 (command not found) will abort the
553 means to skip the revision, 127 (command not found) will abort the
554 bisection, and any other non-zero exit status means the revision
554 bisection, and any other non-zero exit status means the revision
555 is bad.
555 is bad.
556
556
557 .. container:: verbose
557 .. container:: verbose
558
558
559 Some examples:
559 Some examples:
560
560
561 - start a bisection with known bad revision 34, and good revision 12::
561 - start a bisection with known bad revision 34, and good revision 12::
562
562
563 hg bisect --bad 34
563 hg bisect --bad 34
564 hg bisect --good 12
564 hg bisect --good 12
565
565
566 - advance the current bisection by marking current revision as good or
566 - advance the current bisection by marking current revision as good or
567 bad::
567 bad::
568
568
569 hg bisect --good
569 hg bisect --good
570 hg bisect --bad
570 hg bisect --bad
571
571
572 - mark the current revision, or a known revision, to be skipped (e.g. if
572 - mark the current revision, or a known revision, to be skipped (e.g. if
573 that revision is not usable because of another issue)::
573 that revision is not usable because of another issue)::
574
574
575 hg bisect --skip
575 hg bisect --skip
576 hg bisect --skip 23
576 hg bisect --skip 23
577
577
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
579
579
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
581
581
582 - forget the current bisection::
582 - forget the current bisection::
583
583
584 hg bisect --reset
584 hg bisect --reset
585
585
586 - use 'make && make tests' to automatically find the first broken
586 - use 'make && make tests' to automatically find the first broken
587 revision::
587 revision::
588
588
589 hg bisect --reset
589 hg bisect --reset
590 hg bisect --bad 34
590 hg bisect --bad 34
591 hg bisect --good 12
591 hg bisect --good 12
592 hg bisect --command "make && make tests"
592 hg bisect --command "make && make tests"
593
593
594 - see all changesets whose states are already known in the current
594 - see all changesets whose states are already known in the current
595 bisection::
595 bisection::
596
596
597 hg log -r "bisect(pruned)"
597 hg log -r "bisect(pruned)"
598
598
599 - see the changeset currently being bisected (especially useful
599 - see the changeset currently being bisected (especially useful
600 if running with -U/--noupdate)::
600 if running with -U/--noupdate)::
601
601
602 hg log -r "bisect(current)"
602 hg log -r "bisect(current)"
603
603
604 - see all changesets that took part in the current bisection::
604 - see all changesets that took part in the current bisection::
605
605
606 hg log -r "bisect(range)"
606 hg log -r "bisect(range)"
607
607
608 - you can even get a nice graph::
608 - you can even get a nice graph::
609
609
610 hg log --graph -r "bisect(range)"
610 hg log --graph -r "bisect(range)"
611
611
612 See :hg:`help revsets` for more about the `bisect()` keyword.
612 See :hg:`help revsets` for more about the `bisect()` keyword.
613
613
614 Returns 0 on success.
614 Returns 0 on success.
615 """
615 """
616 def extendbisectrange(nodes, good):
616 def extendbisectrange(nodes, good):
617 # bisect is incomplete when it ends on a merge node and
617 # bisect is incomplete when it ends on a merge node and
618 # one of the parent was not checked.
618 # one of the parent was not checked.
619 parents = repo[nodes[0]].parents()
619 parents = repo[nodes[0]].parents()
620 if len(parents) > 1:
620 if len(parents) > 1:
621 side = good and state['bad'] or state['good']
621 side = good and state['bad'] or state['good']
622 num = len(set(i.node() for i in parents) & set(side))
622 num = len(set(i.node() for i in parents) & set(side))
623 if num == 1:
623 if num == 1:
624 return parents[0].ancestor(parents[1])
624 return parents[0].ancestor(parents[1])
625 return None
625 return None
626
626
627 def print_result(nodes, good):
627 def print_result(nodes, good):
628 displayer = cmdutil.show_changeset(ui, repo, {})
628 displayer = cmdutil.show_changeset(ui, repo, {})
629 if len(nodes) == 1:
629 if len(nodes) == 1:
630 # narrowed it down to a single revision
630 # narrowed it down to a single revision
631 if good:
631 if good:
632 ui.write(_("The first good revision is:\n"))
632 ui.write(_("The first good revision is:\n"))
633 else:
633 else:
634 ui.write(_("The first bad revision is:\n"))
634 ui.write(_("The first bad revision is:\n"))
635 displayer.show(repo[nodes[0]])
635 displayer.show(repo[nodes[0]])
636 extendnode = extendbisectrange(nodes, good)
636 extendnode = extendbisectrange(nodes, good)
637 if extendnode is not None:
637 if extendnode is not None:
638 ui.write(_('Not all ancestors of this changeset have been'
638 ui.write(_('Not all ancestors of this changeset have been'
639 ' checked.\nUse bisect --extend to continue the '
639 ' checked.\nUse bisect --extend to continue the '
640 'bisection from\nthe common ancestor, %s.\n')
640 'bisection from\nthe common ancestor, %s.\n')
641 % extendnode)
641 % extendnode)
642 else:
642 else:
643 # multiple possible revisions
643 # multiple possible revisions
644 if good:
644 if good:
645 ui.write(_("Due to skipped revisions, the first "
645 ui.write(_("Due to skipped revisions, the first "
646 "good revision could be any of:\n"))
646 "good revision could be any of:\n"))
647 else:
647 else:
648 ui.write(_("Due to skipped revisions, the first "
648 ui.write(_("Due to skipped revisions, the first "
649 "bad revision could be any of:\n"))
649 "bad revision could be any of:\n"))
650 for n in nodes:
650 for n in nodes:
651 displayer.show(repo[n])
651 displayer.show(repo[n])
652 displayer.close()
652 displayer.close()
653
653
654 def check_state(state, interactive=True):
654 def check_state(state, interactive=True):
655 if not state['good'] or not state['bad']:
655 if not state['good'] or not state['bad']:
656 if (good or bad or skip or reset) and interactive:
656 if (good or bad or skip or reset) and interactive:
657 return
657 return
658 if not state['good']:
658 if not state['good']:
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
660 else:
660 else:
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
662 return True
662 return True
663
663
664 # backward compatibility
664 # backward compatibility
665 if rev in "good bad reset init".split():
665 if rev in "good bad reset init".split():
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
667 cmd, rev, extra = rev, extra, None
667 cmd, rev, extra = rev, extra, None
668 if cmd == "good":
668 if cmd == "good":
669 good = True
669 good = True
670 elif cmd == "bad":
670 elif cmd == "bad":
671 bad = True
671 bad = True
672 else:
672 else:
673 reset = True
673 reset = True
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
675 raise util.Abort(_('incompatible arguments'))
675 raise util.Abort(_('incompatible arguments'))
676
676
677 cmdutil.checkunfinished(repo)
677 cmdutil.checkunfinished(repo)
678
678
679 if reset:
679 if reset:
680 p = repo.join("bisect.state")
680 p = repo.join("bisect.state")
681 if os.path.exists(p):
681 if os.path.exists(p):
682 os.unlink(p)
682 os.unlink(p)
683 return
683 return
684
684
685 state = hbisect.load_state(repo)
685 state = hbisect.load_state(repo)
686
686
687 if command:
687 if command:
688 changesets = 1
688 changesets = 1
689 if noupdate:
689 if noupdate:
690 try:
690 try:
691 node = state['current'][0]
691 node = state['current'][0]
692 except LookupError:
692 except LookupError:
693 raise util.Abort(_('current bisect revision is unknown - '
693 raise util.Abort(_('current bisect revision is unknown - '
694 'start a new bisect to fix'))
694 'start a new bisect to fix'))
695 else:
695 else:
696 node, p2 = repo.dirstate.parents()
696 node, p2 = repo.dirstate.parents()
697 if p2 != nullid:
697 if p2 != nullid:
698 raise util.Abort(_('current bisect revision is a merge'))
698 raise util.Abort(_('current bisect revision is a merge'))
699 try:
699 try:
700 while changesets:
700 while changesets:
701 # update state
701 # update state
702 state['current'] = [node]
702 state['current'] = [node]
703 hbisect.save_state(repo, state)
703 hbisect.save_state(repo, state)
704 status = util.system(command,
704 status = util.system(command,
705 environ={'HG_NODE': hex(node)},
705 environ={'HG_NODE': hex(node)},
706 out=ui.fout)
706 out=ui.fout)
707 if status == 125:
707 if status == 125:
708 transition = "skip"
708 transition = "skip"
709 elif status == 0:
709 elif status == 0:
710 transition = "good"
710 transition = "good"
711 # status < 0 means process was killed
711 # status < 0 means process was killed
712 elif status == 127:
712 elif status == 127:
713 raise util.Abort(_("failed to execute %s") % command)
713 raise util.Abort(_("failed to execute %s") % command)
714 elif status < 0:
714 elif status < 0:
715 raise util.Abort(_("%s killed") % command)
715 raise util.Abort(_("%s killed") % command)
716 else:
716 else:
717 transition = "bad"
717 transition = "bad"
718 ctx = scmutil.revsingle(repo, rev, node)
718 ctx = scmutil.revsingle(repo, rev, node)
719 rev = None # clear for future iterations
719 rev = None # clear for future iterations
720 state[transition].append(ctx.node())
720 state[transition].append(ctx.node())
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
722 check_state(state, interactive=False)
722 check_state(state, interactive=False)
723 # bisect
723 # bisect
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
725 # update to next check
725 # update to next check
726 node = nodes[0]
726 node = nodes[0]
727 if not noupdate:
727 if not noupdate:
728 cmdutil.bailifchanged(repo)
728 cmdutil.bailifchanged(repo)
729 hg.clean(repo, node, show_stats=False)
729 hg.clean(repo, node, show_stats=False)
730 finally:
730 finally:
731 state['current'] = [node]
731 state['current'] = [node]
732 hbisect.save_state(repo, state)
732 hbisect.save_state(repo, state)
733 print_result(nodes, bgood)
733 print_result(nodes, bgood)
734 return
734 return
735
735
736 # update state
736 # update state
737
737
738 if rev:
738 if rev:
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
740 else:
740 else:
741 nodes = [repo.lookup('.')]
741 nodes = [repo.lookup('.')]
742
742
743 if good or bad or skip:
743 if good or bad or skip:
744 if good:
744 if good:
745 state['good'] += nodes
745 state['good'] += nodes
746 elif bad:
746 elif bad:
747 state['bad'] += nodes
747 state['bad'] += nodes
748 elif skip:
748 elif skip:
749 state['skip'] += nodes
749 state['skip'] += nodes
750 hbisect.save_state(repo, state)
750 hbisect.save_state(repo, state)
751
751
752 if not check_state(state):
752 if not check_state(state):
753 return
753 return
754
754
755 # actually bisect
755 # actually bisect
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
757 if extend:
757 if extend:
758 if not changesets:
758 if not changesets:
759 extendnode = extendbisectrange(nodes, good)
759 extendnode = extendbisectrange(nodes, good)
760 if extendnode is not None:
760 if extendnode is not None:
761 ui.write(_("Extending search to changeset %d:%s\n")
761 ui.write(_("Extending search to changeset %d:%s\n")
762 % (extendnode.rev(), extendnode))
762 % (extendnode.rev(), extendnode))
763 state['current'] = [extendnode.node()]
763 state['current'] = [extendnode.node()]
764 hbisect.save_state(repo, state)
764 hbisect.save_state(repo, state)
765 if noupdate:
765 if noupdate:
766 return
766 return
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, extendnode.node())
768 return hg.clean(repo, extendnode.node())
769 raise util.Abort(_("nothing to extend"))
769 raise util.Abort(_("nothing to extend"))
770
770
771 if changesets == 0:
771 if changesets == 0:
772 print_result(nodes, good)
772 print_result(nodes, good)
773 else:
773 else:
774 assert len(nodes) == 1 # only a single node can be tested next
774 assert len(nodes) == 1 # only a single node can be tested next
775 node = nodes[0]
775 node = nodes[0]
776 # compute the approximate number of remaining tests
776 # compute the approximate number of remaining tests
777 tests, size = 0, 2
777 tests, size = 0, 2
778 while size <= changesets:
778 while size <= changesets:
779 tests, size = tests + 1, size * 2
779 tests, size = tests + 1, size * 2
780 rev = repo.changelog.rev(node)
780 rev = repo.changelog.rev(node)
781 ui.write(_("Testing changeset %d:%s "
781 ui.write(_("Testing changeset %d:%s "
782 "(%d changesets remaining, ~%d tests)\n")
782 "(%d changesets remaining, ~%d tests)\n")
783 % (rev, short(node), changesets, tests))
783 % (rev, short(node), changesets, tests))
784 state['current'] = [node]
784 state['current'] = [node]
785 hbisect.save_state(repo, state)
785 hbisect.save_state(repo, state)
786 if not noupdate:
786 if not noupdate:
787 cmdutil.bailifchanged(repo)
787 cmdutil.bailifchanged(repo)
788 return hg.clean(repo, node)
788 return hg.clean(repo, node)
789
789
790 @command('bookmarks|bookmark',
790 @command('bookmarks|bookmark',
791 [('f', 'force', False, _('force')),
791 [('f', 'force', False, _('force')),
792 ('r', 'rev', '', _('revision'), _('REV')),
792 ('r', 'rev', '', _('revision'), _('REV')),
793 ('d', 'delete', False, _('delete a given bookmark')),
793 ('d', 'delete', False, _('delete a given bookmark')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
797 def bookmark(ui, repo, *names, **opts):
797 def bookmark(ui, repo, *names, **opts):
798 '''track a line of development with movable markers
798 '''track a line of development with movable markers
799
799
800 Bookmarks are pointers to certain commits that move when committing.
800 Bookmarks are pointers to certain commits that move when committing.
801 Bookmarks are local. They can be renamed, copied and deleted. It is
801 Bookmarks are local. They can be renamed, copied and deleted. It is
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
803 :hg:`update NAME` to update to a given bookmark.
803 :hg:`update NAME` to update to a given bookmark.
804
804
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
806 directory's parent revision with the given name. If you specify
806 directory's parent revision with the given name. If you specify
807 a revision using -r REV (where REV may be an existing bookmark),
807 a revision using -r REV (where REV may be an existing bookmark),
808 the bookmark is assigned to that revision.
808 the bookmark is assigned to that revision.
809
809
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
811 push` and :hg:`help pull`). This requires both the local and remote
811 push` and :hg:`help pull`). This requires both the local and remote
812 repositories to support bookmarks. For versions prior to 1.8, this means
812 repositories to support bookmarks. For versions prior to 1.8, this means
813 the bookmarks extension must be enabled.
813 the bookmarks extension must be enabled.
814
814
815 If you set a bookmark called '@', new clones of the repository will
815 If you set a bookmark called '@', new clones of the repository will
816 have that revision checked out (and the bookmark made active) by
816 have that revision checked out (and the bookmark made active) by
817 default.
817 default.
818
818
819 With -i/--inactive, the new bookmark will not be made the active
819 With -i/--inactive, the new bookmark will not be made the active
820 bookmark. If -r/--rev is given, the new bookmark will not be made
820 bookmark. If -r/--rev is given, the new bookmark will not be made
821 active even if -i/--inactive is not given. If no NAME is given, the
821 active even if -i/--inactive is not given. If no NAME is given, the
822 current active bookmark will be marked inactive.
822 current active bookmark will be marked inactive.
823 '''
823 '''
824 force = opts.get('force')
824 force = opts.get('force')
825 rev = opts.get('rev')
825 rev = opts.get('rev')
826 delete = opts.get('delete')
826 delete = opts.get('delete')
827 rename = opts.get('rename')
827 rename = opts.get('rename')
828 inactive = opts.get('inactive')
828 inactive = opts.get('inactive')
829
829
830 def checkformat(mark):
830 def checkformat(mark):
831 mark = mark.strip()
831 mark = mark.strip()
832 if not mark:
832 if not mark:
833 raise util.Abort(_("bookmark names cannot consist entirely of "
833 raise util.Abort(_("bookmark names cannot consist entirely of "
834 "whitespace"))
834 "whitespace"))
835 scmutil.checknewlabel(repo, mark, 'bookmark')
835 scmutil.checknewlabel(repo, mark, 'bookmark')
836 return mark
836 return mark
837
837
838 def checkconflict(repo, mark, cur, force=False, target=None):
838 def checkconflict(repo, mark, cur, force=False, target=None):
839 if mark in marks and not force:
839 if mark in marks and not force:
840 if target:
840 if target:
841 if marks[mark] == target and target == cur:
841 if marks[mark] == target and target == cur:
842 # re-activating a bookmark
842 # re-activating a bookmark
843 return
843 return
844 anc = repo.changelog.ancestors([repo[target].rev()])
844 anc = repo.changelog.ancestors([repo[target].rev()])
845 bmctx = repo[marks[mark]]
845 bmctx = repo[marks[mark]]
846 divs = [repo[b].node() for b in marks
846 divs = [repo[b].node() for b in marks
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
848
848
849 # allow resolving a single divergent bookmark even if moving
849 # allow resolving a single divergent bookmark even if moving
850 # the bookmark across branches when a revision is specified
850 # the bookmark across branches when a revision is specified
851 # that contains a divergent bookmark
851 # that contains a divergent bookmark
852 if bmctx.rev() not in anc and target in divs:
852 if bmctx.rev() not in anc and target in divs:
853 bookmarks.deletedivergent(repo, [target], mark)
853 bookmarks.deletedivergent(repo, [target], mark)
854 return
854 return
855
855
856 deletefrom = [b for b in divs
856 deletefrom = [b for b in divs
857 if repo[b].rev() in anc or b == target]
857 if repo[b].rev() in anc or b == target]
858 bookmarks.deletedivergent(repo, deletefrom, mark)
858 bookmarks.deletedivergent(repo, deletefrom, mark)
859 if bookmarks.validdest(repo, bmctx, repo[target]):
859 if bookmarks.validdest(repo, bmctx, repo[target]):
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
861 (mark, short(bmctx.node())))
861 (mark, short(bmctx.node())))
862 return
862 return
863 raise util.Abort(_("bookmark '%s' already exists "
863 raise util.Abort(_("bookmark '%s' already exists "
864 "(use -f to force)") % mark)
864 "(use -f to force)") % mark)
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
866 and not force):
866 and not force):
867 raise util.Abort(
867 raise util.Abort(
868 _("a bookmark cannot have the name of an existing branch"))
868 _("a bookmark cannot have the name of an existing branch"))
869
869
870 if delete and rename:
870 if delete and rename:
871 raise util.Abort(_("--delete and --rename are incompatible"))
871 raise util.Abort(_("--delete and --rename are incompatible"))
872 if delete and rev:
872 if delete and rev:
873 raise util.Abort(_("--rev is incompatible with --delete"))
873 raise util.Abort(_("--rev is incompatible with --delete"))
874 if rename and rev:
874 if rename and rev:
875 raise util.Abort(_("--rev is incompatible with --rename"))
875 raise util.Abort(_("--rev is incompatible with --rename"))
876 if not names and (delete or rev):
876 if not names and (delete or rev):
877 raise util.Abort(_("bookmark name required"))
877 raise util.Abort(_("bookmark name required"))
878
878
879 if delete or rename or names or inactive:
879 if delete or rename or names or inactive:
880 wlock = repo.wlock()
880 wlock = repo.wlock()
881 try:
881 try:
882 cur = repo.changectx('.').node()
882 cur = repo.changectx('.').node()
883 marks = repo._bookmarks
883 marks = repo._bookmarks
884 if delete:
884 if delete:
885 for mark in names:
885 for mark in names:
886 if mark not in marks:
886 if mark not in marks:
887 raise util.Abort(_("bookmark '%s' does not exist") %
887 raise util.Abort(_("bookmark '%s' does not exist") %
888 mark)
888 mark)
889 if mark == repo._bookmarkcurrent:
889 if mark == repo._bookmarkcurrent:
890 bookmarks.unsetcurrent(repo)
890 bookmarks.unsetcurrent(repo)
891 del marks[mark]
891 del marks[mark]
892 marks.write()
892 marks.write()
893
893
894 elif rename:
894 elif rename:
895 if not names:
895 if not names:
896 raise util.Abort(_("new bookmark name required"))
896 raise util.Abort(_("new bookmark name required"))
897 elif len(names) > 1:
897 elif len(names) > 1:
898 raise util.Abort(_("only one new bookmark name allowed"))
898 raise util.Abort(_("only one new bookmark name allowed"))
899 mark = checkformat(names[0])
899 mark = checkformat(names[0])
900 if rename not in marks:
900 if rename not in marks:
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
902 checkconflict(repo, mark, cur, force)
902 checkconflict(repo, mark, cur, force)
903 marks[mark] = marks[rename]
903 marks[mark] = marks[rename]
904 if repo._bookmarkcurrent == rename and not inactive:
904 if repo._bookmarkcurrent == rename and not inactive:
905 bookmarks.setcurrent(repo, mark)
905 bookmarks.setcurrent(repo, mark)
906 del marks[rename]
906 del marks[rename]
907 marks.write()
907 marks.write()
908
908
909 elif names:
909 elif names:
910 newact = None
910 newact = None
911 for mark in names:
911 for mark in names:
912 mark = checkformat(mark)
912 mark = checkformat(mark)
913 if newact is None:
913 if newact is None:
914 newact = mark
914 newact = mark
915 if inactive and mark == repo._bookmarkcurrent:
915 if inactive and mark == repo._bookmarkcurrent:
916 bookmarks.unsetcurrent(repo)
916 bookmarks.unsetcurrent(repo)
917 return
917 return
918 tgt = cur
918 tgt = cur
919 if rev:
919 if rev:
920 tgt = scmutil.revsingle(repo, rev).node()
920 tgt = scmutil.revsingle(repo, rev).node()
921 checkconflict(repo, mark, cur, force, tgt)
921 checkconflict(repo, mark, cur, force, tgt)
922 marks[mark] = tgt
922 marks[mark] = tgt
923 if not inactive and cur == marks[newact] and not rev:
923 if not inactive and cur == marks[newact] and not rev:
924 bookmarks.setcurrent(repo, newact)
924 bookmarks.setcurrent(repo, newact)
925 elif cur != tgt and newact == repo._bookmarkcurrent:
925 elif cur != tgt and newact == repo._bookmarkcurrent:
926 bookmarks.unsetcurrent(repo)
926 bookmarks.unsetcurrent(repo)
927 marks.write()
927 marks.write()
928
928
929 elif inactive:
929 elif inactive:
930 if len(marks) == 0:
930 if len(marks) == 0:
931 ui.status(_("no bookmarks set\n"))
931 ui.status(_("no bookmarks set\n"))
932 elif not repo._bookmarkcurrent:
932 elif not repo._bookmarkcurrent:
933 ui.status(_("no active bookmark\n"))
933 ui.status(_("no active bookmark\n"))
934 else:
934 else:
935 bookmarks.unsetcurrent(repo)
935 bookmarks.unsetcurrent(repo)
936 finally:
936 finally:
937 wlock.release()
937 wlock.release()
938 else: # show bookmarks
938 else: # show bookmarks
939 hexfn = ui.debugflag and hex or short
939 hexfn = ui.debugflag and hex or short
940 marks = repo._bookmarks
940 marks = repo._bookmarks
941 if len(marks) == 0:
941 if len(marks) == 0:
942 ui.status(_("no bookmarks set\n"))
942 ui.status(_("no bookmarks set\n"))
943 else:
943 else:
944 for bmark, n in sorted(marks.iteritems()):
944 for bmark, n in sorted(marks.iteritems()):
945 current = repo._bookmarkcurrent
945 current = repo._bookmarkcurrent
946 if bmark == current:
946 if bmark == current:
947 prefix, label = '*', 'bookmarks.current'
947 prefix, label = '*', 'bookmarks.current'
948 else:
948 else:
949 prefix, label = ' ', ''
949 prefix, label = ' ', ''
950
950
951 if ui.quiet:
951 if ui.quiet:
952 ui.write("%s\n" % bmark, label=label)
952 ui.write("%s\n" % bmark, label=label)
953 else:
953 else:
954 ui.write(" %s %-25s %d:%s\n" % (
954 ui.write(" %s %-25s %d:%s\n" % (
955 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
955 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
956 label=label)
956 label=label)
957
957
958 @command('branch',
958 @command('branch',
959 [('f', 'force', None,
959 [('f', 'force', None,
960 _('set branch name even if it shadows an existing branch')),
960 _('set branch name even if it shadows an existing branch')),
961 ('C', 'clean', None, _('reset branch name to parent branch name'))],
961 ('C', 'clean', None, _('reset branch name to parent branch name'))],
962 _('[-fC] [NAME]'))
962 _('[-fC] [NAME]'))
963 def branch(ui, repo, label=None, **opts):
963 def branch(ui, repo, label=None, **opts):
964 """set or show the current branch name
964 """set or show the current branch name
965
965
966 .. note::
966 .. note::
967
967
968 Branch names are permanent and global. Use :hg:`bookmark` to create a
968 Branch names are permanent and global. Use :hg:`bookmark` to create a
969 light-weight bookmark instead. See :hg:`help glossary` for more
969 light-weight bookmark instead. See :hg:`help glossary` for more
970 information about named branches and bookmarks.
970 information about named branches and bookmarks.
971
971
972 With no argument, show the current branch name. With one argument,
972 With no argument, show the current branch name. With one argument,
973 set the working directory branch name (the branch will not exist
973 set the working directory branch name (the branch will not exist
974 in the repository until the next commit). Standard practice
974 in the repository until the next commit). Standard practice
975 recommends that primary development take place on the 'default'
975 recommends that primary development take place on the 'default'
976 branch.
976 branch.
977
977
978 Unless -f/--force is specified, branch will not let you set a
978 Unless -f/--force is specified, branch will not let you set a
979 branch name that already exists, even if it's inactive.
979 branch name that already exists, even if it's inactive.
980
980
981 Use -C/--clean to reset the working directory branch to that of
981 Use -C/--clean to reset the working directory branch to that of
982 the parent of the working directory, negating a previous branch
982 the parent of the working directory, negating a previous branch
983 change.
983 change.
984
984
985 Use the command :hg:`update` to switch to an existing branch. Use
985 Use the command :hg:`update` to switch to an existing branch. Use
986 :hg:`commit --close-branch` to mark this branch as closed.
986 :hg:`commit --close-branch` to mark this branch as closed.
987
987
988 Returns 0 on success.
988 Returns 0 on success.
989 """
989 """
990 if label:
990 if label:
991 label = label.strip()
991 label = label.strip()
992
992
993 if not opts.get('clean') and not label:
993 if not opts.get('clean') and not label:
994 ui.write("%s\n" % repo.dirstate.branch())
994 ui.write("%s\n" % repo.dirstate.branch())
995 return
995 return
996
996
997 wlock = repo.wlock()
997 wlock = repo.wlock()
998 try:
998 try:
999 if opts.get('clean'):
999 if opts.get('clean'):
1000 label = repo[None].p1().branch()
1000 label = repo[None].p1().branch()
1001 repo.dirstate.setbranch(label)
1001 repo.dirstate.setbranch(label)
1002 ui.status(_('reset working directory to branch %s\n') % label)
1002 ui.status(_('reset working directory to branch %s\n') % label)
1003 elif label:
1003 elif label:
1004 if not opts.get('force') and label in repo.branchmap():
1004 if not opts.get('force') and label in repo.branchmap():
1005 if label not in [p.branch() for p in repo.parents()]:
1005 if label not in [p.branch() for p in repo.parents()]:
1006 raise util.Abort(_('a branch of the same name already'
1006 raise util.Abort(_('a branch of the same name already'
1007 ' exists'),
1007 ' exists'),
1008 # i18n: "it" refers to an existing branch
1008 # i18n: "it" refers to an existing branch
1009 hint=_("use 'hg update' to switch to it"))
1009 hint=_("use 'hg update' to switch to it"))
1010 scmutil.checknewlabel(repo, label, 'branch')
1010 scmutil.checknewlabel(repo, label, 'branch')
1011 repo.dirstate.setbranch(label)
1011 repo.dirstate.setbranch(label)
1012 ui.status(_('marked working directory as branch %s\n') % label)
1012 ui.status(_('marked working directory as branch %s\n') % label)
1013 ui.status(_('(branches are permanent and global, '
1013 ui.status(_('(branches are permanent and global, '
1014 'did you want a bookmark?)\n'))
1014 'did you want a bookmark?)\n'))
1015 finally:
1015 finally:
1016 wlock.release()
1016 wlock.release()
1017
1017
1018 @command('branches',
1018 @command('branches',
1019 [('a', 'active', False, _('show only branches that have unmerged heads')),
1019 [('a', 'active', False, _('show only branches that have unmerged heads')),
1020 ('c', 'closed', False, _('show normal and closed branches'))],
1020 ('c', 'closed', False, _('show normal and closed branches'))],
1021 _('[-ac]'))
1021 _('[-ac]'))
1022 def branches(ui, repo, active=False, closed=False):
1022 def branches(ui, repo, active=False, closed=False):
1023 """list repository named branches
1023 """list repository named branches
1024
1024
1025 List the repository's named branches, indicating which ones are
1025 List the repository's named branches, indicating which ones are
1026 inactive. If -c/--closed is specified, also list branches which have
1026 inactive. If -c/--closed is specified, also list branches which have
1027 been marked closed (see :hg:`commit --close-branch`).
1027 been marked closed (see :hg:`commit --close-branch`).
1028
1028
1029 If -a/--active is specified, only show active branches. A branch
1029 If -a/--active is specified, only show active branches. A branch
1030 is considered active if it contains repository heads.
1030 is considered active if it contains repository heads.
1031
1031
1032 Use the command :hg:`update` to switch to an existing branch.
1032 Use the command :hg:`update` to switch to an existing branch.
1033
1033
1034 Returns 0.
1034 Returns 0.
1035 """
1035 """
1036
1036
1037 hexfunc = ui.debugflag and hex or short
1037 hexfunc = ui.debugflag and hex or short
1038
1038
1039 allheads = set(repo.heads())
1039 allheads = set(repo.heads())
1040 branches = []
1040 branches = []
1041 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1041 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1042 isactive = not isclosed and bool(set(heads) & allheads)
1042 isactive = not isclosed and bool(set(heads) & allheads)
1043 branches.append((tag, repo[tip], isactive, not isclosed))
1043 branches.append((tag, repo[tip], isactive, not isclosed))
1044 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1044 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1045 reverse=True)
1045 reverse=True)
1046
1046
1047 for tag, ctx, isactive, isopen in branches:
1047 for tag, ctx, isactive, isopen in branches:
1048 if (not active) or isactive:
1048 if (not active) or isactive:
1049 if isactive:
1049 if isactive:
1050 label = 'branches.active'
1050 label = 'branches.active'
1051 notice = ''
1051 notice = ''
1052 elif not isopen:
1052 elif not isopen:
1053 if not closed:
1053 if not closed:
1054 continue
1054 continue
1055 label = 'branches.closed'
1055 label = 'branches.closed'
1056 notice = _(' (closed)')
1056 notice = _(' (closed)')
1057 else:
1057 else:
1058 label = 'branches.inactive'
1058 label = 'branches.inactive'
1059 notice = _(' (inactive)')
1059 notice = _(' (inactive)')
1060 if tag == repo.dirstate.branch():
1060 if tag == repo.dirstate.branch():
1061 label = 'branches.current'
1061 label = 'branches.current'
1062 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1062 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1063 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1063 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1064 'log.changeset changeset.%s' % ctx.phasestr())
1064 'log.changeset changeset.%s' % ctx.phasestr())
1065 labeledtag = ui.label(tag, label)
1065 labeledtag = ui.label(tag, label)
1066 if ui.quiet:
1066 if ui.quiet:
1067 ui.write("%s\n" % labeledtag)
1067 ui.write("%s\n" % labeledtag)
1068 else:
1068 else:
1069 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1069 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1070
1070
1071 @command('bundle',
1071 @command('bundle',
1072 [('f', 'force', None, _('run even when the destination is unrelated')),
1072 [('f', 'force', None, _('run even when the destination is unrelated')),
1073 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1073 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1074 _('REV')),
1074 _('REV')),
1075 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1075 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1076 _('BRANCH')),
1076 _('BRANCH')),
1077 ('', 'base', [],
1077 ('', 'base', [],
1078 _('a base changeset assumed to be available at the destination'),
1078 _('a base changeset assumed to be available at the destination'),
1079 _('REV')),
1079 _('REV')),
1080 ('a', 'all', None, _('bundle all changesets in the repository')),
1080 ('a', 'all', None, _('bundle all changesets in the repository')),
1081 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1081 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1082 ] + remoteopts,
1082 ] + remoteopts,
1083 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1083 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1084 def bundle(ui, repo, fname, dest=None, **opts):
1084 def bundle(ui, repo, fname, dest=None, **opts):
1085 """create a changegroup file
1085 """create a changegroup file
1086
1086
1087 Generate a compressed changegroup file collecting changesets not
1087 Generate a compressed changegroup file collecting changesets not
1088 known to be in another repository.
1088 known to be in another repository.
1089
1089
1090 If you omit the destination repository, then hg assumes the
1090 If you omit the destination repository, then hg assumes the
1091 destination will have all the nodes you specify with --base
1091 destination will have all the nodes you specify with --base
1092 parameters. To create a bundle containing all changesets, use
1092 parameters. To create a bundle containing all changesets, use
1093 -a/--all (or --base null).
1093 -a/--all (or --base null).
1094
1094
1095 You can change compression method with the -t/--type option.
1095 You can change compression method with the -t/--type option.
1096 The available compression methods are: none, bzip2, and
1096 The available compression methods are: none, bzip2, and
1097 gzip (by default, bundles are compressed using bzip2).
1097 gzip (by default, bundles are compressed using bzip2).
1098
1098
1099 The bundle file can then be transferred using conventional means
1099 The bundle file can then be transferred using conventional means
1100 and applied to another repository with the unbundle or pull
1100 and applied to another repository with the unbundle or pull
1101 command. This is useful when direct push and pull are not
1101 command. This is useful when direct push and pull are not
1102 available or when exporting an entire repository is undesirable.
1102 available or when exporting an entire repository is undesirable.
1103
1103
1104 Applying bundles preserves all changeset contents including
1104 Applying bundles preserves all changeset contents including
1105 permissions, copy/rename information, and revision history.
1105 permissions, copy/rename information, and revision history.
1106
1106
1107 Returns 0 on success, 1 if no changes found.
1107 Returns 0 on success, 1 if no changes found.
1108 """
1108 """
1109 revs = None
1109 revs = None
1110 if 'rev' in opts:
1110 if 'rev' in opts:
1111 revs = scmutil.revrange(repo, opts['rev'])
1111 revs = scmutil.revrange(repo, opts['rev'])
1112
1112
1113 bundletype = opts.get('type', 'bzip2').lower()
1113 bundletype = opts.get('type', 'bzip2').lower()
1114 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1114 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1115 bundletype = btypes.get(bundletype)
1115 bundletype = btypes.get(bundletype)
1116 if bundletype not in changegroup.bundletypes:
1116 if bundletype not in changegroup.bundletypes:
1117 raise util.Abort(_('unknown bundle type specified with --type'))
1117 raise util.Abort(_('unknown bundle type specified with --type'))
1118
1118
1119 if opts.get('all'):
1119 if opts.get('all'):
1120 base = ['null']
1120 base = ['null']
1121 else:
1121 else:
1122 base = scmutil.revrange(repo, opts.get('base'))
1122 base = scmutil.revrange(repo, opts.get('base'))
1123 # TODO: get desired bundlecaps from command line.
1123 # TODO: get desired bundlecaps from command line.
1124 bundlecaps = None
1124 bundlecaps = None
1125 if base:
1125 if base:
1126 if dest:
1126 if dest:
1127 raise util.Abort(_("--base is incompatible with specifying "
1127 raise util.Abort(_("--base is incompatible with specifying "
1128 "a destination"))
1128 "a destination"))
1129 common = [repo.lookup(rev) for rev in base]
1129 common = [repo.lookup(rev) for rev in base]
1130 heads = revs and map(repo.lookup, revs) or revs
1130 heads = revs and map(repo.lookup, revs) or revs
1131 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1131 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1132 bundlecaps=bundlecaps)
1132 bundlecaps=bundlecaps)
1133 outgoing = None
1133 outgoing = None
1134 else:
1134 else:
1135 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1135 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1136 dest, branches = hg.parseurl(dest, opts.get('branch'))
1136 dest, branches = hg.parseurl(dest, opts.get('branch'))
1137 other = hg.peer(repo, opts, dest)
1137 other = hg.peer(repo, opts, dest)
1138 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1138 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1139 heads = revs and map(repo.lookup, revs) or revs
1139 heads = revs and map(repo.lookup, revs) or revs
1140 outgoing = discovery.findcommonoutgoing(repo, other,
1140 outgoing = discovery.findcommonoutgoing(repo, other,
1141 onlyheads=heads,
1141 onlyheads=heads,
1142 force=opts.get('force'),
1142 force=opts.get('force'),
1143 portable=True)
1143 portable=True)
1144 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1144 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1145 if not cg:
1145 if not cg:
1146 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1146 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1147 return 1
1147 return 1
1148
1148
1149 changegroup.writebundle(cg, fname, bundletype)
1149 changegroup.writebundle(cg, fname, bundletype)
1150
1150
1151 @command('cat',
1151 @command('cat',
1152 [('o', 'output', '',
1152 [('o', 'output', '',
1153 _('print output to file with formatted name'), _('FORMAT')),
1153 _('print output to file with formatted name'), _('FORMAT')),
1154 ('r', 'rev', '', _('print the given revision'), _('REV')),
1154 ('r', 'rev', '', _('print the given revision'), _('REV')),
1155 ('', 'decode', None, _('apply any matching decode filter')),
1155 ('', 'decode', None, _('apply any matching decode filter')),
1156 ] + walkopts,
1156 ] + walkopts,
1157 _('[OPTION]... FILE...'))
1157 _('[OPTION]... FILE...'))
1158 def cat(ui, repo, file1, *pats, **opts):
1158 def cat(ui, repo, file1, *pats, **opts):
1159 """output the current or given revision of files
1159 """output the current or given revision of files
1160
1160
1161 Print the specified files as they were at the given revision. If
1161 Print the specified files as they were at the given revision. If
1162 no revision is given, the parent of the working directory is used.
1162 no revision is given, the parent of the working directory is used.
1163
1163
1164 Output may be to a file, in which case the name of the file is
1164 Output may be to a file, in which case the name of the file is
1165 given using a format string. The formatting rules are the same as
1165 given using a format string. The formatting rules are the same as
1166 for the export command, with the following additions:
1166 for the export command, with the following additions:
1167
1167
1168 :``%s``: basename of file being printed
1168 :``%s``: basename of file being printed
1169 :``%d``: dirname of file being printed, or '.' if in repository root
1169 :``%d``: dirname of file being printed, or '.' if in repository root
1170 :``%p``: root-relative path name of file being printed
1170 :``%p``: root-relative path name of file being printed
1171
1171
1172 Returns 0 on success.
1172 Returns 0 on success.
1173 """
1173 """
1174 ctx = scmutil.revsingle(repo, opts.get('rev'))
1174 ctx = scmutil.revsingle(repo, opts.get('rev'))
1175 err = 1
1175 err = 1
1176 m = scmutil.match(ctx, (file1,) + pats, opts)
1176 m = scmutil.match(ctx, (file1,) + pats, opts)
1177
1177
1178 def write(path):
1178 def write(path):
1179 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1179 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1180 pathname=path)
1180 pathname=path)
1181 data = ctx[path].data()
1181 data = ctx[path].data()
1182 if opts.get('decode'):
1182 if opts.get('decode'):
1183 data = repo.wwritedata(path, data)
1183 data = repo.wwritedata(path, data)
1184 fp.write(data)
1184 fp.write(data)
1185 fp.close()
1185 fp.close()
1186
1186
1187 # Automation often uses hg cat on single files, so special case it
1187 # Automation often uses hg cat on single files, so special case it
1188 # for performance to avoid the cost of parsing the manifest.
1188 # for performance to avoid the cost of parsing the manifest.
1189 if len(m.files()) == 1 and not m.anypats():
1189 if len(m.files()) == 1 and not m.anypats():
1190 file = m.files()[0]
1190 file = m.files()[0]
1191 mf = repo.manifest
1191 mf = repo.manifest
1192 mfnode = ctx._changeset[0]
1192 mfnode = ctx._changeset[0]
1193 if mf.find(mfnode, file)[0]:
1193 if mf.find(mfnode, file)[0]:
1194 write(file)
1194 write(file)
1195 return 0
1195 return 0
1196
1196
1197 for abs in ctx.walk(m):
1197 for abs in ctx.walk(m):
1198 write(abs)
1198 write(abs)
1199 err = 0
1199 err = 0
1200 return err
1200 return err
1201
1201
1202 @command('^clone',
1202 @command('^clone',
1203 [('U', 'noupdate', None,
1203 [('U', 'noupdate', None,
1204 _('the clone will include an empty working copy (only a repository)')),
1204 _('the clone will include an empty working copy (only a repository)')),
1205 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1205 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1206 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1206 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1207 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1207 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1208 ('', 'pull', None, _('use pull protocol to copy metadata')),
1208 ('', 'pull', None, _('use pull protocol to copy metadata')),
1209 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1209 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1210 ] + remoteopts,
1210 ] + remoteopts,
1211 _('[OPTION]... SOURCE [DEST]'))
1211 _('[OPTION]... SOURCE [DEST]'))
1212 def clone(ui, source, dest=None, **opts):
1212 def clone(ui, source, dest=None, **opts):
1213 """make a copy of an existing repository
1213 """make a copy of an existing repository
1214
1214
1215 Create a copy of an existing repository in a new directory.
1215 Create a copy of an existing repository in a new directory.
1216
1216
1217 If no destination directory name is specified, it defaults to the
1217 If no destination directory name is specified, it defaults to the
1218 basename of the source.
1218 basename of the source.
1219
1219
1220 The location of the source is added to the new repository's
1220 The location of the source is added to the new repository's
1221 ``.hg/hgrc`` file, as the default to be used for future pulls.
1221 ``.hg/hgrc`` file, as the default to be used for future pulls.
1222
1222
1223 Only local paths and ``ssh://`` URLs are supported as
1223 Only local paths and ``ssh://`` URLs are supported as
1224 destinations. For ``ssh://`` destinations, no working directory or
1224 destinations. For ``ssh://`` destinations, no working directory or
1225 ``.hg/hgrc`` will be created on the remote side.
1225 ``.hg/hgrc`` will be created on the remote side.
1226
1226
1227 To pull only a subset of changesets, specify one or more revisions
1227 To pull only a subset of changesets, specify one or more revisions
1228 identifiers with -r/--rev or branches with -b/--branch. The
1228 identifiers with -r/--rev or branches with -b/--branch. The
1229 resulting clone will contain only the specified changesets and
1229 resulting clone will contain only the specified changesets and
1230 their ancestors. These options (or 'clone src#rev dest') imply
1230 their ancestors. These options (or 'clone src#rev dest') imply
1231 --pull, even for local source repositories. Note that specifying a
1231 --pull, even for local source repositories. Note that specifying a
1232 tag will include the tagged changeset but not the changeset
1232 tag will include the tagged changeset but not the changeset
1233 containing the tag.
1233 containing the tag.
1234
1234
1235 If the source repository has a bookmark called '@' set, that
1235 If the source repository has a bookmark called '@' set, that
1236 revision will be checked out in the new repository by default.
1236 revision will be checked out in the new repository by default.
1237
1237
1238 To check out a particular version, use -u/--update, or
1238 To check out a particular version, use -u/--update, or
1239 -U/--noupdate to create a clone with no working directory.
1239 -U/--noupdate to create a clone with no working directory.
1240
1240
1241 .. container:: verbose
1241 .. container:: verbose
1242
1242
1243 For efficiency, hardlinks are used for cloning whenever the
1243 For efficiency, hardlinks are used for cloning whenever the
1244 source and destination are on the same filesystem (note this
1244 source and destination are on the same filesystem (note this
1245 applies only to the repository data, not to the working
1245 applies only to the repository data, not to the working
1246 directory). Some filesystems, such as AFS, implement hardlinking
1246 directory). Some filesystems, such as AFS, implement hardlinking
1247 incorrectly, but do not report errors. In these cases, use the
1247 incorrectly, but do not report errors. In these cases, use the
1248 --pull option to avoid hardlinking.
1248 --pull option to avoid hardlinking.
1249
1249
1250 In some cases, you can clone repositories and the working
1250 In some cases, you can clone repositories and the working
1251 directory using full hardlinks with ::
1251 directory using full hardlinks with ::
1252
1252
1253 $ cp -al REPO REPOCLONE
1253 $ cp -al REPO REPOCLONE
1254
1254
1255 This is the fastest way to clone, but it is not always safe. The
1255 This is the fastest way to clone, but it is not always safe. The
1256 operation is not atomic (making sure REPO is not modified during
1256 operation is not atomic (making sure REPO is not modified during
1257 the operation is up to you) and you have to make sure your
1257 the operation is up to you) and you have to make sure your
1258 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1258 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1259 so). Also, this is not compatible with certain extensions that
1259 so). Also, this is not compatible with certain extensions that
1260 place their metadata under the .hg directory, such as mq.
1260 place their metadata under the .hg directory, such as mq.
1261
1261
1262 Mercurial will update the working directory to the first applicable
1262 Mercurial will update the working directory to the first applicable
1263 revision from this list:
1263 revision from this list:
1264
1264
1265 a) null if -U or the source repository has no changesets
1265 a) null if -U or the source repository has no changesets
1266 b) if -u . and the source repository is local, the first parent of
1266 b) if -u . and the source repository is local, the first parent of
1267 the source repository's working directory
1267 the source repository's working directory
1268 c) the changeset specified with -u (if a branch name, this means the
1268 c) the changeset specified with -u (if a branch name, this means the
1269 latest head of that branch)
1269 latest head of that branch)
1270 d) the changeset specified with -r
1270 d) the changeset specified with -r
1271 e) the tipmost head specified with -b
1271 e) the tipmost head specified with -b
1272 f) the tipmost head specified with the url#branch source syntax
1272 f) the tipmost head specified with the url#branch source syntax
1273 g) the revision marked with the '@' bookmark, if present
1273 g) the revision marked with the '@' bookmark, if present
1274 h) the tipmost head of the default branch
1274 h) the tipmost head of the default branch
1275 i) tip
1275 i) tip
1276
1276
1277 Examples:
1277 Examples:
1278
1278
1279 - clone a remote repository to a new directory named hg/::
1279 - clone a remote repository to a new directory named hg/::
1280
1280
1281 hg clone http://selenic.com/hg
1281 hg clone http://selenic.com/hg
1282
1282
1283 - create a lightweight local clone::
1283 - create a lightweight local clone::
1284
1284
1285 hg clone project/ project-feature/
1285 hg clone project/ project-feature/
1286
1286
1287 - clone from an absolute path on an ssh server (note double-slash)::
1287 - clone from an absolute path on an ssh server (note double-slash)::
1288
1288
1289 hg clone ssh://user@server//home/projects/alpha/
1289 hg clone ssh://user@server//home/projects/alpha/
1290
1290
1291 - do a high-speed clone over a LAN while checking out a
1291 - do a high-speed clone over a LAN while checking out a
1292 specified version::
1292 specified version::
1293
1293
1294 hg clone --uncompressed http://server/repo -u 1.5
1294 hg clone --uncompressed http://server/repo -u 1.5
1295
1295
1296 - create a repository without changesets after a particular revision::
1296 - create a repository without changesets after a particular revision::
1297
1297
1298 hg clone -r 04e544 experimental/ good/
1298 hg clone -r 04e544 experimental/ good/
1299
1299
1300 - clone (and track) a particular named branch::
1300 - clone (and track) a particular named branch::
1301
1301
1302 hg clone http://selenic.com/hg#stable
1302 hg clone http://selenic.com/hg#stable
1303
1303
1304 See :hg:`help urls` for details on specifying URLs.
1304 See :hg:`help urls` for details on specifying URLs.
1305
1305
1306 Returns 0 on success.
1306 Returns 0 on success.
1307 """
1307 """
1308 if opts.get('noupdate') and opts.get('updaterev'):
1308 if opts.get('noupdate') and opts.get('updaterev'):
1309 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1309 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1310
1310
1311 r = hg.clone(ui, opts, source, dest,
1311 r = hg.clone(ui, opts, source, dest,
1312 pull=opts.get('pull'),
1312 pull=opts.get('pull'),
1313 stream=opts.get('uncompressed'),
1313 stream=opts.get('uncompressed'),
1314 rev=opts.get('rev'),
1314 rev=opts.get('rev'),
1315 update=opts.get('updaterev') or not opts.get('noupdate'),
1315 update=opts.get('updaterev') or not opts.get('noupdate'),
1316 branch=opts.get('branch'))
1316 branch=opts.get('branch'))
1317
1317
1318 return r is None
1318 return r is None
1319
1319
1320 @command('^commit|ci',
1320 @command('^commit|ci',
1321 [('A', 'addremove', None,
1321 [('A', 'addremove', None,
1322 _('mark new/missing files as added/removed before committing')),
1322 _('mark new/missing files as added/removed before committing')),
1323 ('', 'close-branch', None,
1323 ('', 'close-branch', None,
1324 _('mark a branch as closed, hiding it from the branch list')),
1324 _('mark a branch as closed, hiding it from the branch list')),
1325 ('', 'amend', None, _('amend the parent of the working dir')),
1325 ('', 'amend', None, _('amend the parent of the working dir')),
1326 ('s', 'secret', None, _('use the secret phase for committing')),
1326 ('s', 'secret', None, _('use the secret phase for committing')),
1327 ('e', 'edit', None,
1328 _('further edit commit message already specified')),
1327 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1329 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1328 _('[OPTION]... [FILE]...'))
1330 _('[OPTION]... [FILE]...'))
1329 def commit(ui, repo, *pats, **opts):
1331 def commit(ui, repo, *pats, **opts):
1330 """commit the specified files or all outstanding changes
1332 """commit the specified files or all outstanding changes
1331
1333
1332 Commit changes to the given files into the repository. Unlike a
1334 Commit changes to the given files into the repository. Unlike a
1333 centralized SCM, this operation is a local operation. See
1335 centralized SCM, this operation is a local operation. See
1334 :hg:`push` for a way to actively distribute your changes.
1336 :hg:`push` for a way to actively distribute your changes.
1335
1337
1336 If a list of files is omitted, all changes reported by :hg:`status`
1338 If a list of files is omitted, all changes reported by :hg:`status`
1337 will be committed.
1339 will be committed.
1338
1340
1339 If you are committing the result of a merge, do not provide any
1341 If you are committing the result of a merge, do not provide any
1340 filenames or -I/-X filters.
1342 filenames or -I/-X filters.
1341
1343
1342 If no commit message is specified, Mercurial starts your
1344 If no commit message is specified, Mercurial starts your
1343 configured editor where you can enter a message. In case your
1345 configured editor where you can enter a message. In case your
1344 commit fails, you will find a backup of your message in
1346 commit fails, you will find a backup of your message in
1345 ``.hg/last-message.txt``.
1347 ``.hg/last-message.txt``.
1346
1348
1347 The --amend flag can be used to amend the parent of the
1349 The --amend flag can be used to amend the parent of the
1348 working directory with a new commit that contains the changes
1350 working directory with a new commit that contains the changes
1349 in the parent in addition to those currently reported by :hg:`status`,
1351 in the parent in addition to those currently reported by :hg:`status`,
1350 if there are any. The old commit is stored in a backup bundle in
1352 if there are any. The old commit is stored in a backup bundle in
1351 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1353 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1352 on how to restore it).
1354 on how to restore it).
1353
1355
1354 Message, user and date are taken from the amended commit unless
1356 Message, user and date are taken from the amended commit unless
1355 specified. When a message isn't specified on the command line,
1357 specified. When a message isn't specified on the command line,
1356 the editor will open with the message of the amended commit.
1358 the editor will open with the message of the amended commit.
1357
1359
1358 It is not possible to amend public changesets (see :hg:`help phases`)
1360 It is not possible to amend public changesets (see :hg:`help phases`)
1359 or changesets that have children.
1361 or changesets that have children.
1360
1362
1361 See :hg:`help dates` for a list of formats valid for -d/--date.
1363 See :hg:`help dates` for a list of formats valid for -d/--date.
1362
1364
1363 Returns 0 on success, 1 if nothing changed.
1365 Returns 0 on success, 1 if nothing changed.
1364 """
1366 """
1367 forceeditor = opts.get('force_editor') or opts.get('edit')
1368
1365 if opts.get('subrepos'):
1369 if opts.get('subrepos'):
1366 if opts.get('amend'):
1370 if opts.get('amend'):
1367 raise util.Abort(_('cannot amend with --subrepos'))
1371 raise util.Abort(_('cannot amend with --subrepos'))
1368 # Let --subrepos on the command line override config setting.
1372 # Let --subrepos on the command line override config setting.
1369 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1373 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1370
1374
1371 # Save this for restoring it later
1375 # Save this for restoring it later
1372 oldcommitphase = ui.config('phases', 'new-commit')
1376 oldcommitphase = ui.config('phases', 'new-commit')
1373
1377
1374 cmdutil.checkunfinished(repo, commit=True)
1378 cmdutil.checkunfinished(repo, commit=True)
1375
1379
1376 branch = repo[None].branch()
1380 branch = repo[None].branch()
1377 bheads = repo.branchheads(branch)
1381 bheads = repo.branchheads(branch)
1378
1382
1379 extra = {}
1383 extra = {}
1380 if opts.get('close_branch'):
1384 if opts.get('close_branch'):
1381 extra['close'] = 1
1385 extra['close'] = 1
1382
1386
1383 if not bheads:
1387 if not bheads:
1384 raise util.Abort(_('can only close branch heads'))
1388 raise util.Abort(_('can only close branch heads'))
1385 elif opts.get('amend'):
1389 elif opts.get('amend'):
1386 if repo.parents()[0].p1().branch() != branch and \
1390 if repo.parents()[0].p1().branch() != branch and \
1387 repo.parents()[0].p2().branch() != branch:
1391 repo.parents()[0].p2().branch() != branch:
1388 raise util.Abort(_('can only close branch heads'))
1392 raise util.Abort(_('can only close branch heads'))
1389
1393
1390 if opts.get('amend'):
1394 if opts.get('amend'):
1391 if ui.configbool('ui', 'commitsubrepos'):
1395 if ui.configbool('ui', 'commitsubrepos'):
1392 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1396 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1393
1397
1394 old = repo['.']
1398 old = repo['.']
1395 if old.phase() == phases.public:
1399 if old.phase() == phases.public:
1396 raise util.Abort(_('cannot amend public changesets'))
1400 raise util.Abort(_('cannot amend public changesets'))
1397 if len(repo[None].parents()) > 1:
1401 if len(repo[None].parents()) > 1:
1398 raise util.Abort(_('cannot amend while merging'))
1402 raise util.Abort(_('cannot amend while merging'))
1399 if (not obsolete._enabled) and old.children():
1403 if (not obsolete._enabled) and old.children():
1400 raise util.Abort(_('cannot amend changeset with children'))
1404 raise util.Abort(_('cannot amend changeset with children'))
1401
1405
1402 e = cmdutil.commiteditor
1406 e = cmdutil.commiteditor
1403 if opts.get('force_editor'):
1407 if forceeditor:
1404 e = cmdutil.commitforceeditor
1408 e = cmdutil.commitforceeditor
1405
1409
1406 # commitfunc is used only for temporary amend commit by cmdutil.amend
1410 # commitfunc is used only for temporary amend commit by cmdutil.amend
1407 def commitfunc(ui, repo, message, match, opts):
1411 def commitfunc(ui, repo, message, match, opts):
1408 editor = e
1412 editor = e
1409 # message contains text from -m or -l, if it's empty,
1413 # message contains text from -m or -l, if it's empty,
1410 # open the editor with the old message
1414 # open the editor with the old message
1411 if not message:
1415 if not message:
1412 message = old.description()
1416 message = old.description()
1413 editor = cmdutil.commitforceeditor
1417 editor = cmdutil.commitforceeditor
1414 return repo.commit(message,
1418 return repo.commit(message,
1415 opts.get('user') or old.user(),
1419 opts.get('user') or old.user(),
1416 opts.get('date') or old.date(),
1420 opts.get('date') or old.date(),
1417 match,
1421 match,
1418 editor=editor,
1422 editor=editor,
1419 extra=extra)
1423 extra=extra)
1420
1424
1421 current = repo._bookmarkcurrent
1425 current = repo._bookmarkcurrent
1422 marks = old.bookmarks()
1426 marks = old.bookmarks()
1423 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1427 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1424 if node == old.node():
1428 if node == old.node():
1425 ui.status(_("nothing changed\n"))
1429 ui.status(_("nothing changed\n"))
1426 return 1
1430 return 1
1427 elif marks:
1431 elif marks:
1428 ui.debug('moving bookmarks %r from %s to %s\n' %
1432 ui.debug('moving bookmarks %r from %s to %s\n' %
1429 (marks, old.hex(), hex(node)))
1433 (marks, old.hex(), hex(node)))
1430 newmarks = repo._bookmarks
1434 newmarks = repo._bookmarks
1431 for bm in marks:
1435 for bm in marks:
1432 newmarks[bm] = node
1436 newmarks[bm] = node
1433 if bm == current:
1437 if bm == current:
1434 bookmarks.setcurrent(repo, bm)
1438 bookmarks.setcurrent(repo, bm)
1435 newmarks.write()
1439 newmarks.write()
1436 else:
1440 else:
1437 e = cmdutil.commiteditor
1441 e = cmdutil.commiteditor
1438 if opts.get('force_editor'):
1442 if forceeditor:
1439 e = cmdutil.commitforceeditor
1443 e = cmdutil.commitforceeditor
1440
1444
1441 def commitfunc(ui, repo, message, match, opts):
1445 def commitfunc(ui, repo, message, match, opts):
1442 try:
1446 try:
1443 if opts.get('secret'):
1447 if opts.get('secret'):
1444 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1448 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1445 # Propagate to subrepos
1449 # Propagate to subrepos
1446 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1450 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1447 'commit')
1451 'commit')
1448
1452
1449 return repo.commit(message, opts.get('user'), opts.get('date'),
1453 return repo.commit(message, opts.get('user'), opts.get('date'),
1450 match, editor=e, extra=extra)
1454 match, editor=e, extra=extra)
1451 finally:
1455 finally:
1452 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1456 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1453 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1457 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1454 'commit')
1458 'commit')
1455
1459
1456
1460
1457 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1461 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1458
1462
1459 if not node:
1463 if not node:
1460 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1464 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1461 if stat[3]:
1465 if stat[3]:
1462 ui.status(_("nothing changed (%d missing files, see "
1466 ui.status(_("nothing changed (%d missing files, see "
1463 "'hg status')\n") % len(stat[3]))
1467 "'hg status')\n") % len(stat[3]))
1464 else:
1468 else:
1465 ui.status(_("nothing changed\n"))
1469 ui.status(_("nothing changed\n"))
1466 return 1
1470 return 1
1467
1471
1468 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1472 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1469
1473
1470 @command('config|showconfig|debugconfig',
1474 @command('config|showconfig|debugconfig',
1471 [('u', 'untrusted', None, _('show untrusted configuration options')),
1475 [('u', 'untrusted', None, _('show untrusted configuration options')),
1472 ('e', 'edit', None, _('edit user config')),
1476 ('e', 'edit', None, _('edit user config')),
1473 ('l', 'local', None, _('edit repository config')),
1477 ('l', 'local', None, _('edit repository config')),
1474 ('g', 'global', None, _('edit global config'))],
1478 ('g', 'global', None, _('edit global config'))],
1475 _('[-u] [NAME]...'))
1479 _('[-u] [NAME]...'))
1476 def config(ui, repo, *values, **opts):
1480 def config(ui, repo, *values, **opts):
1477 """show combined config settings from all hgrc files
1481 """show combined config settings from all hgrc files
1478
1482
1479 With no arguments, print names and values of all config items.
1483 With no arguments, print names and values of all config items.
1480
1484
1481 With one argument of the form section.name, print just the value
1485 With one argument of the form section.name, print just the value
1482 of that config item.
1486 of that config item.
1483
1487
1484 With multiple arguments, print names and values of all config
1488 With multiple arguments, print names and values of all config
1485 items with matching section names.
1489 items with matching section names.
1486
1490
1487 With --edit, start an editor on the user-level config file. With
1491 With --edit, start an editor on the user-level config file. With
1488 --global, edit the system-wide config file. With --local, edit the
1492 --global, edit the system-wide config file. With --local, edit the
1489 repository-level config file.
1493 repository-level config file.
1490
1494
1491 With --debug, the source (filename and line number) is printed
1495 With --debug, the source (filename and line number) is printed
1492 for each config item.
1496 for each config item.
1493
1497
1494 See :hg:`help config` for more information about config files.
1498 See :hg:`help config` for more information about config files.
1495
1499
1496 Returns 0 on success.
1500 Returns 0 on success.
1497
1501
1498 """
1502 """
1499
1503
1500 if opts.get('edit') or opts.get('local') or opts.get('global'):
1504 if opts.get('edit') or opts.get('local') or opts.get('global'):
1501 if opts.get('local') and opts.get('global'):
1505 if opts.get('local') and opts.get('global'):
1502 raise util.Abort(_("can't use --local and --global together"))
1506 raise util.Abort(_("can't use --local and --global together"))
1503
1507
1504 if opts.get('local'):
1508 if opts.get('local'):
1505 if not repo:
1509 if not repo:
1506 raise util.Abort(_("can't use --local outside a repository"))
1510 raise util.Abort(_("can't use --local outside a repository"))
1507 paths = [repo.join('hgrc')]
1511 paths = [repo.join('hgrc')]
1508 elif opts.get('global'):
1512 elif opts.get('global'):
1509 paths = scmutil.systemrcpath()
1513 paths = scmutil.systemrcpath()
1510 else:
1514 else:
1511 paths = scmutil.userrcpath()
1515 paths = scmutil.userrcpath()
1512
1516
1513 for f in paths:
1517 for f in paths:
1514 if os.path.exists(f):
1518 if os.path.exists(f):
1515 break
1519 break
1516 else:
1520 else:
1517 f = paths[0]
1521 f = paths[0]
1518 fp = open(f, "w")
1522 fp = open(f, "w")
1519 fp.write(
1523 fp.write(
1520 '# example config (see "hg help config" for more info)\n'
1524 '# example config (see "hg help config" for more info)\n'
1521 '\n'
1525 '\n'
1522 '[ui]\n'
1526 '[ui]\n'
1523 '# name and email, e.g.\n'
1527 '# name and email, e.g.\n'
1524 '# username = Jane Doe <jdoe@example.com>\n'
1528 '# username = Jane Doe <jdoe@example.com>\n'
1525 'username =\n'
1529 'username =\n'
1526 '\n'
1530 '\n'
1527 '[extensions]\n'
1531 '[extensions]\n'
1528 '# uncomment these lines to enable some popular extensions\n'
1532 '# uncomment these lines to enable some popular extensions\n'
1529 '# (see "hg help extensions" for more info)\n'
1533 '# (see "hg help extensions" for more info)\n'
1530 '# pager =\n'
1534 '# pager =\n'
1531 '# progress =\n'
1535 '# progress =\n'
1532 '# color =\n')
1536 '# color =\n')
1533 fp.close()
1537 fp.close()
1534
1538
1535 editor = ui.geteditor()
1539 editor = ui.geteditor()
1536 util.system("%s \"%s\"" % (editor, f),
1540 util.system("%s \"%s\"" % (editor, f),
1537 onerr=util.Abort, errprefix=_("edit failed"),
1541 onerr=util.Abort, errprefix=_("edit failed"),
1538 out=ui.fout)
1542 out=ui.fout)
1539 return
1543 return
1540
1544
1541 for f in scmutil.rcpath():
1545 for f in scmutil.rcpath():
1542 ui.debug('read config from: %s\n' % f)
1546 ui.debug('read config from: %s\n' % f)
1543 untrusted = bool(opts.get('untrusted'))
1547 untrusted = bool(opts.get('untrusted'))
1544 if values:
1548 if values:
1545 sections = [v for v in values if '.' not in v]
1549 sections = [v for v in values if '.' not in v]
1546 items = [v for v in values if '.' in v]
1550 items = [v for v in values if '.' in v]
1547 if len(items) > 1 or items and sections:
1551 if len(items) > 1 or items and sections:
1548 raise util.Abort(_('only one config item permitted'))
1552 raise util.Abort(_('only one config item permitted'))
1549 for section, name, value in ui.walkconfig(untrusted=untrusted):
1553 for section, name, value in ui.walkconfig(untrusted=untrusted):
1550 value = str(value).replace('\n', '\\n')
1554 value = str(value).replace('\n', '\\n')
1551 sectname = section + '.' + name
1555 sectname = section + '.' + name
1552 if values:
1556 if values:
1553 for v in values:
1557 for v in values:
1554 if v == section:
1558 if v == section:
1555 ui.debug('%s: ' %
1559 ui.debug('%s: ' %
1556 ui.configsource(section, name, untrusted))
1560 ui.configsource(section, name, untrusted))
1557 ui.write('%s=%s\n' % (sectname, value))
1561 ui.write('%s=%s\n' % (sectname, value))
1558 elif v == sectname:
1562 elif v == sectname:
1559 ui.debug('%s: ' %
1563 ui.debug('%s: ' %
1560 ui.configsource(section, name, untrusted))
1564 ui.configsource(section, name, untrusted))
1561 ui.write(value, '\n')
1565 ui.write(value, '\n')
1562 else:
1566 else:
1563 ui.debug('%s: ' %
1567 ui.debug('%s: ' %
1564 ui.configsource(section, name, untrusted))
1568 ui.configsource(section, name, untrusted))
1565 ui.write('%s=%s\n' % (sectname, value))
1569 ui.write('%s=%s\n' % (sectname, value))
1566
1570
1567 @command('copy|cp',
1571 @command('copy|cp',
1568 [('A', 'after', None, _('record a copy that has already occurred')),
1572 [('A', 'after', None, _('record a copy that has already occurred')),
1569 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1573 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1570 ] + walkopts + dryrunopts,
1574 ] + walkopts + dryrunopts,
1571 _('[OPTION]... [SOURCE]... DEST'))
1575 _('[OPTION]... [SOURCE]... DEST'))
1572 def copy(ui, repo, *pats, **opts):
1576 def copy(ui, repo, *pats, **opts):
1573 """mark files as copied for the next commit
1577 """mark files as copied for the next commit
1574
1578
1575 Mark dest as having copies of source files. If dest is a
1579 Mark dest as having copies of source files. If dest is a
1576 directory, copies are put in that directory. If dest is a file,
1580 directory, copies are put in that directory. If dest is a file,
1577 the source must be a single file.
1581 the source must be a single file.
1578
1582
1579 By default, this command copies the contents of files as they
1583 By default, this command copies the contents of files as they
1580 exist in the working directory. If invoked with -A/--after, the
1584 exist in the working directory. If invoked with -A/--after, the
1581 operation is recorded, but no copying is performed.
1585 operation is recorded, but no copying is performed.
1582
1586
1583 This command takes effect with the next commit. To undo a copy
1587 This command takes effect with the next commit. To undo a copy
1584 before that, see :hg:`revert`.
1588 before that, see :hg:`revert`.
1585
1589
1586 Returns 0 on success, 1 if errors are encountered.
1590 Returns 0 on success, 1 if errors are encountered.
1587 """
1591 """
1588 wlock = repo.wlock(False)
1592 wlock = repo.wlock(False)
1589 try:
1593 try:
1590 return cmdutil.copy(ui, repo, pats, opts)
1594 return cmdutil.copy(ui, repo, pats, opts)
1591 finally:
1595 finally:
1592 wlock.release()
1596 wlock.release()
1593
1597
1594 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1598 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1595 def debugancestor(ui, repo, *args):
1599 def debugancestor(ui, repo, *args):
1596 """find the ancestor revision of two revisions in a given index"""
1600 """find the ancestor revision of two revisions in a given index"""
1597 if len(args) == 3:
1601 if len(args) == 3:
1598 index, rev1, rev2 = args
1602 index, rev1, rev2 = args
1599 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1603 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1600 lookup = r.lookup
1604 lookup = r.lookup
1601 elif len(args) == 2:
1605 elif len(args) == 2:
1602 if not repo:
1606 if not repo:
1603 raise util.Abort(_("there is no Mercurial repository here "
1607 raise util.Abort(_("there is no Mercurial repository here "
1604 "(.hg not found)"))
1608 "(.hg not found)"))
1605 rev1, rev2 = args
1609 rev1, rev2 = args
1606 r = repo.changelog
1610 r = repo.changelog
1607 lookup = repo.lookup
1611 lookup = repo.lookup
1608 else:
1612 else:
1609 raise util.Abort(_('either two or three arguments required'))
1613 raise util.Abort(_('either two or three arguments required'))
1610 a = r.ancestor(lookup(rev1), lookup(rev2))
1614 a = r.ancestor(lookup(rev1), lookup(rev2))
1611 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1615 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1612
1616
1613 @command('debugbuilddag',
1617 @command('debugbuilddag',
1614 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1618 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1615 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1619 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1616 ('n', 'new-file', None, _('add new file at each rev'))],
1620 ('n', 'new-file', None, _('add new file at each rev'))],
1617 _('[OPTION]... [TEXT]'))
1621 _('[OPTION]... [TEXT]'))
1618 def debugbuilddag(ui, repo, text=None,
1622 def debugbuilddag(ui, repo, text=None,
1619 mergeable_file=False,
1623 mergeable_file=False,
1620 overwritten_file=False,
1624 overwritten_file=False,
1621 new_file=False):
1625 new_file=False):
1622 """builds a repo with a given DAG from scratch in the current empty repo
1626 """builds a repo with a given DAG from scratch in the current empty repo
1623
1627
1624 The description of the DAG is read from stdin if not given on the
1628 The description of the DAG is read from stdin if not given on the
1625 command line.
1629 command line.
1626
1630
1627 Elements:
1631 Elements:
1628
1632
1629 - "+n" is a linear run of n nodes based on the current default parent
1633 - "+n" is a linear run of n nodes based on the current default parent
1630 - "." is a single node based on the current default parent
1634 - "." is a single node based on the current default parent
1631 - "$" resets the default parent to null (implied at the start);
1635 - "$" resets the default parent to null (implied at the start);
1632 otherwise the default parent is always the last node created
1636 otherwise the default parent is always the last node created
1633 - "<p" sets the default parent to the backref p
1637 - "<p" sets the default parent to the backref p
1634 - "*p" is a fork at parent p, which is a backref
1638 - "*p" is a fork at parent p, which is a backref
1635 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1639 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1636 - "/p2" is a merge of the preceding node and p2
1640 - "/p2" is a merge of the preceding node and p2
1637 - ":tag" defines a local tag for the preceding node
1641 - ":tag" defines a local tag for the preceding node
1638 - "@branch" sets the named branch for subsequent nodes
1642 - "@branch" sets the named branch for subsequent nodes
1639 - "#...\\n" is a comment up to the end of the line
1643 - "#...\\n" is a comment up to the end of the line
1640
1644
1641 Whitespace between the above elements is ignored.
1645 Whitespace between the above elements is ignored.
1642
1646
1643 A backref is either
1647 A backref is either
1644
1648
1645 - a number n, which references the node curr-n, where curr is the current
1649 - a number n, which references the node curr-n, where curr is the current
1646 node, or
1650 node, or
1647 - the name of a local tag you placed earlier using ":tag", or
1651 - the name of a local tag you placed earlier using ":tag", or
1648 - empty to denote the default parent.
1652 - empty to denote the default parent.
1649
1653
1650 All string valued-elements are either strictly alphanumeric, or must
1654 All string valued-elements are either strictly alphanumeric, or must
1651 be enclosed in double quotes ("..."), with "\\" as escape character.
1655 be enclosed in double quotes ("..."), with "\\" as escape character.
1652 """
1656 """
1653
1657
1654 if text is None:
1658 if text is None:
1655 ui.status(_("reading DAG from stdin\n"))
1659 ui.status(_("reading DAG from stdin\n"))
1656 text = ui.fin.read()
1660 text = ui.fin.read()
1657
1661
1658 cl = repo.changelog
1662 cl = repo.changelog
1659 if len(cl) > 0:
1663 if len(cl) > 0:
1660 raise util.Abort(_('repository is not empty'))
1664 raise util.Abort(_('repository is not empty'))
1661
1665
1662 # determine number of revs in DAG
1666 # determine number of revs in DAG
1663 total = 0
1667 total = 0
1664 for type, data in dagparser.parsedag(text):
1668 for type, data in dagparser.parsedag(text):
1665 if type == 'n':
1669 if type == 'n':
1666 total += 1
1670 total += 1
1667
1671
1668 if mergeable_file:
1672 if mergeable_file:
1669 linesperrev = 2
1673 linesperrev = 2
1670 # make a file with k lines per rev
1674 # make a file with k lines per rev
1671 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1675 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1672 initialmergedlines.append("")
1676 initialmergedlines.append("")
1673
1677
1674 tags = []
1678 tags = []
1675
1679
1676 lock = tr = None
1680 lock = tr = None
1677 try:
1681 try:
1678 lock = repo.lock()
1682 lock = repo.lock()
1679 tr = repo.transaction("builddag")
1683 tr = repo.transaction("builddag")
1680
1684
1681 at = -1
1685 at = -1
1682 atbranch = 'default'
1686 atbranch = 'default'
1683 nodeids = []
1687 nodeids = []
1684 id = 0
1688 id = 0
1685 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1689 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1686 for type, data in dagparser.parsedag(text):
1690 for type, data in dagparser.parsedag(text):
1687 if type == 'n':
1691 if type == 'n':
1688 ui.note(('node %s\n' % str(data)))
1692 ui.note(('node %s\n' % str(data)))
1689 id, ps = data
1693 id, ps = data
1690
1694
1691 files = []
1695 files = []
1692 fctxs = {}
1696 fctxs = {}
1693
1697
1694 p2 = None
1698 p2 = None
1695 if mergeable_file:
1699 if mergeable_file:
1696 fn = "mf"
1700 fn = "mf"
1697 p1 = repo[ps[0]]
1701 p1 = repo[ps[0]]
1698 if len(ps) > 1:
1702 if len(ps) > 1:
1699 p2 = repo[ps[1]]
1703 p2 = repo[ps[1]]
1700 pa = p1.ancestor(p2)
1704 pa = p1.ancestor(p2)
1701 base, local, other = [x[fn].data() for x in (pa, p1,
1705 base, local, other = [x[fn].data() for x in (pa, p1,
1702 p2)]
1706 p2)]
1703 m3 = simplemerge.Merge3Text(base, local, other)
1707 m3 = simplemerge.Merge3Text(base, local, other)
1704 ml = [l.strip() for l in m3.merge_lines()]
1708 ml = [l.strip() for l in m3.merge_lines()]
1705 ml.append("")
1709 ml.append("")
1706 elif at > 0:
1710 elif at > 0:
1707 ml = p1[fn].data().split("\n")
1711 ml = p1[fn].data().split("\n")
1708 else:
1712 else:
1709 ml = initialmergedlines
1713 ml = initialmergedlines
1710 ml[id * linesperrev] += " r%i" % id
1714 ml[id * linesperrev] += " r%i" % id
1711 mergedtext = "\n".join(ml)
1715 mergedtext = "\n".join(ml)
1712 files.append(fn)
1716 files.append(fn)
1713 fctxs[fn] = context.memfilectx(fn, mergedtext)
1717 fctxs[fn] = context.memfilectx(fn, mergedtext)
1714
1718
1715 if overwritten_file:
1719 if overwritten_file:
1716 fn = "of"
1720 fn = "of"
1717 files.append(fn)
1721 files.append(fn)
1718 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1722 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1719
1723
1720 if new_file:
1724 if new_file:
1721 fn = "nf%i" % id
1725 fn = "nf%i" % id
1722 files.append(fn)
1726 files.append(fn)
1723 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1727 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1724 if len(ps) > 1:
1728 if len(ps) > 1:
1725 if not p2:
1729 if not p2:
1726 p2 = repo[ps[1]]
1730 p2 = repo[ps[1]]
1727 for fn in p2:
1731 for fn in p2:
1728 if fn.startswith("nf"):
1732 if fn.startswith("nf"):
1729 files.append(fn)
1733 files.append(fn)
1730 fctxs[fn] = p2[fn]
1734 fctxs[fn] = p2[fn]
1731
1735
1732 def fctxfn(repo, cx, path):
1736 def fctxfn(repo, cx, path):
1733 return fctxs.get(path)
1737 return fctxs.get(path)
1734
1738
1735 if len(ps) == 0 or ps[0] < 0:
1739 if len(ps) == 0 or ps[0] < 0:
1736 pars = [None, None]
1740 pars = [None, None]
1737 elif len(ps) == 1:
1741 elif len(ps) == 1:
1738 pars = [nodeids[ps[0]], None]
1742 pars = [nodeids[ps[0]], None]
1739 else:
1743 else:
1740 pars = [nodeids[p] for p in ps]
1744 pars = [nodeids[p] for p in ps]
1741 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1745 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1742 date=(id, 0),
1746 date=(id, 0),
1743 user="debugbuilddag",
1747 user="debugbuilddag",
1744 extra={'branch': atbranch})
1748 extra={'branch': atbranch})
1745 nodeid = repo.commitctx(cx)
1749 nodeid = repo.commitctx(cx)
1746 nodeids.append(nodeid)
1750 nodeids.append(nodeid)
1747 at = id
1751 at = id
1748 elif type == 'l':
1752 elif type == 'l':
1749 id, name = data
1753 id, name = data
1750 ui.note(('tag %s\n' % name))
1754 ui.note(('tag %s\n' % name))
1751 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1755 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1752 elif type == 'a':
1756 elif type == 'a':
1753 ui.note(('branch %s\n' % data))
1757 ui.note(('branch %s\n' % data))
1754 atbranch = data
1758 atbranch = data
1755 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1759 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1756 tr.close()
1760 tr.close()
1757
1761
1758 if tags:
1762 if tags:
1759 repo.opener.write("localtags", "".join(tags))
1763 repo.opener.write("localtags", "".join(tags))
1760 finally:
1764 finally:
1761 ui.progress(_('building'), None)
1765 ui.progress(_('building'), None)
1762 release(tr, lock)
1766 release(tr, lock)
1763
1767
1764 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1768 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1765 def debugbundle(ui, bundlepath, all=None, **opts):
1769 def debugbundle(ui, bundlepath, all=None, **opts):
1766 """lists the contents of a bundle"""
1770 """lists the contents of a bundle"""
1767 f = hg.openpath(ui, bundlepath)
1771 f = hg.openpath(ui, bundlepath)
1768 try:
1772 try:
1769 gen = changegroup.readbundle(f, bundlepath)
1773 gen = changegroup.readbundle(f, bundlepath)
1770 if all:
1774 if all:
1771 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1775 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1772
1776
1773 def showchunks(named):
1777 def showchunks(named):
1774 ui.write("\n%s\n" % named)
1778 ui.write("\n%s\n" % named)
1775 chain = None
1779 chain = None
1776 while True:
1780 while True:
1777 chunkdata = gen.deltachunk(chain)
1781 chunkdata = gen.deltachunk(chain)
1778 if not chunkdata:
1782 if not chunkdata:
1779 break
1783 break
1780 node = chunkdata['node']
1784 node = chunkdata['node']
1781 p1 = chunkdata['p1']
1785 p1 = chunkdata['p1']
1782 p2 = chunkdata['p2']
1786 p2 = chunkdata['p2']
1783 cs = chunkdata['cs']
1787 cs = chunkdata['cs']
1784 deltabase = chunkdata['deltabase']
1788 deltabase = chunkdata['deltabase']
1785 delta = chunkdata['delta']
1789 delta = chunkdata['delta']
1786 ui.write("%s %s %s %s %s %s\n" %
1790 ui.write("%s %s %s %s %s %s\n" %
1787 (hex(node), hex(p1), hex(p2),
1791 (hex(node), hex(p1), hex(p2),
1788 hex(cs), hex(deltabase), len(delta)))
1792 hex(cs), hex(deltabase), len(delta)))
1789 chain = node
1793 chain = node
1790
1794
1791 chunkdata = gen.changelogheader()
1795 chunkdata = gen.changelogheader()
1792 showchunks("changelog")
1796 showchunks("changelog")
1793 chunkdata = gen.manifestheader()
1797 chunkdata = gen.manifestheader()
1794 showchunks("manifest")
1798 showchunks("manifest")
1795 while True:
1799 while True:
1796 chunkdata = gen.filelogheader()
1800 chunkdata = gen.filelogheader()
1797 if not chunkdata:
1801 if not chunkdata:
1798 break
1802 break
1799 fname = chunkdata['filename']
1803 fname = chunkdata['filename']
1800 showchunks(fname)
1804 showchunks(fname)
1801 else:
1805 else:
1802 chunkdata = gen.changelogheader()
1806 chunkdata = gen.changelogheader()
1803 chain = None
1807 chain = None
1804 while True:
1808 while True:
1805 chunkdata = gen.deltachunk(chain)
1809 chunkdata = gen.deltachunk(chain)
1806 if not chunkdata:
1810 if not chunkdata:
1807 break
1811 break
1808 node = chunkdata['node']
1812 node = chunkdata['node']
1809 ui.write("%s\n" % hex(node))
1813 ui.write("%s\n" % hex(node))
1810 chain = node
1814 chain = node
1811 finally:
1815 finally:
1812 f.close()
1816 f.close()
1813
1817
1814 @command('debugcheckstate', [], '')
1818 @command('debugcheckstate', [], '')
1815 def debugcheckstate(ui, repo):
1819 def debugcheckstate(ui, repo):
1816 """validate the correctness of the current dirstate"""
1820 """validate the correctness of the current dirstate"""
1817 parent1, parent2 = repo.dirstate.parents()
1821 parent1, parent2 = repo.dirstate.parents()
1818 m1 = repo[parent1].manifest()
1822 m1 = repo[parent1].manifest()
1819 m2 = repo[parent2].manifest()
1823 m2 = repo[parent2].manifest()
1820 errors = 0
1824 errors = 0
1821 for f in repo.dirstate:
1825 for f in repo.dirstate:
1822 state = repo.dirstate[f]
1826 state = repo.dirstate[f]
1823 if state in "nr" and f not in m1:
1827 if state in "nr" and f not in m1:
1824 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1828 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1825 errors += 1
1829 errors += 1
1826 if state in "a" and f in m1:
1830 if state in "a" and f in m1:
1827 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1831 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1828 errors += 1
1832 errors += 1
1829 if state in "m" and f not in m1 and f not in m2:
1833 if state in "m" and f not in m1 and f not in m2:
1830 ui.warn(_("%s in state %s, but not in either manifest\n") %
1834 ui.warn(_("%s in state %s, but not in either manifest\n") %
1831 (f, state))
1835 (f, state))
1832 errors += 1
1836 errors += 1
1833 for f in m1:
1837 for f in m1:
1834 state = repo.dirstate[f]
1838 state = repo.dirstate[f]
1835 if state not in "nrm":
1839 if state not in "nrm":
1836 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1840 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1837 errors += 1
1841 errors += 1
1838 if errors:
1842 if errors:
1839 error = _(".hg/dirstate inconsistent with current parent's manifest")
1843 error = _(".hg/dirstate inconsistent with current parent's manifest")
1840 raise util.Abort(error)
1844 raise util.Abort(error)
1841
1845
1842 @command('debugcommands', [], _('[COMMAND]'))
1846 @command('debugcommands', [], _('[COMMAND]'))
1843 def debugcommands(ui, cmd='', *args):
1847 def debugcommands(ui, cmd='', *args):
1844 """list all available commands and options"""
1848 """list all available commands and options"""
1845 for cmd, vals in sorted(table.iteritems()):
1849 for cmd, vals in sorted(table.iteritems()):
1846 cmd = cmd.split('|')[0].strip('^')
1850 cmd = cmd.split('|')[0].strip('^')
1847 opts = ', '.join([i[1] for i in vals[1]])
1851 opts = ', '.join([i[1] for i in vals[1]])
1848 ui.write('%s: %s\n' % (cmd, opts))
1852 ui.write('%s: %s\n' % (cmd, opts))
1849
1853
1850 @command('debugcomplete',
1854 @command('debugcomplete',
1851 [('o', 'options', None, _('show the command options'))],
1855 [('o', 'options', None, _('show the command options'))],
1852 _('[-o] CMD'))
1856 _('[-o] CMD'))
1853 def debugcomplete(ui, cmd='', **opts):
1857 def debugcomplete(ui, cmd='', **opts):
1854 """returns the completion list associated with the given command"""
1858 """returns the completion list associated with the given command"""
1855
1859
1856 if opts.get('options'):
1860 if opts.get('options'):
1857 options = []
1861 options = []
1858 otables = [globalopts]
1862 otables = [globalopts]
1859 if cmd:
1863 if cmd:
1860 aliases, entry = cmdutil.findcmd(cmd, table, False)
1864 aliases, entry = cmdutil.findcmd(cmd, table, False)
1861 otables.append(entry[1])
1865 otables.append(entry[1])
1862 for t in otables:
1866 for t in otables:
1863 for o in t:
1867 for o in t:
1864 if "(DEPRECATED)" in o[3]:
1868 if "(DEPRECATED)" in o[3]:
1865 continue
1869 continue
1866 if o[0]:
1870 if o[0]:
1867 options.append('-%s' % o[0])
1871 options.append('-%s' % o[0])
1868 options.append('--%s' % o[1])
1872 options.append('--%s' % o[1])
1869 ui.write("%s\n" % "\n".join(options))
1873 ui.write("%s\n" % "\n".join(options))
1870 return
1874 return
1871
1875
1872 cmdlist = cmdutil.findpossible(cmd, table)
1876 cmdlist = cmdutil.findpossible(cmd, table)
1873 if ui.verbose:
1877 if ui.verbose:
1874 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1878 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1875 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1879 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1876
1880
1877 @command('debugdag',
1881 @command('debugdag',
1878 [('t', 'tags', None, _('use tags as labels')),
1882 [('t', 'tags', None, _('use tags as labels')),
1879 ('b', 'branches', None, _('annotate with branch names')),
1883 ('b', 'branches', None, _('annotate with branch names')),
1880 ('', 'dots', None, _('use dots for runs')),
1884 ('', 'dots', None, _('use dots for runs')),
1881 ('s', 'spaces', None, _('separate elements by spaces'))],
1885 ('s', 'spaces', None, _('separate elements by spaces'))],
1882 _('[OPTION]... [FILE [REV]...]'))
1886 _('[OPTION]... [FILE [REV]...]'))
1883 def debugdag(ui, repo, file_=None, *revs, **opts):
1887 def debugdag(ui, repo, file_=None, *revs, **opts):
1884 """format the changelog or an index DAG as a concise textual description
1888 """format the changelog or an index DAG as a concise textual description
1885
1889
1886 If you pass a revlog index, the revlog's DAG is emitted. If you list
1890 If you pass a revlog index, the revlog's DAG is emitted. If you list
1887 revision numbers, they get labeled in the output as rN.
1891 revision numbers, they get labeled in the output as rN.
1888
1892
1889 Otherwise, the changelog DAG of the current repo is emitted.
1893 Otherwise, the changelog DAG of the current repo is emitted.
1890 """
1894 """
1891 spaces = opts.get('spaces')
1895 spaces = opts.get('spaces')
1892 dots = opts.get('dots')
1896 dots = opts.get('dots')
1893 if file_:
1897 if file_:
1894 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1898 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1895 revs = set((int(r) for r in revs))
1899 revs = set((int(r) for r in revs))
1896 def events():
1900 def events():
1897 for r in rlog:
1901 for r in rlog:
1898 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1902 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1899 if p != -1)))
1903 if p != -1)))
1900 if r in revs:
1904 if r in revs:
1901 yield 'l', (r, "r%i" % r)
1905 yield 'l', (r, "r%i" % r)
1902 elif repo:
1906 elif repo:
1903 cl = repo.changelog
1907 cl = repo.changelog
1904 tags = opts.get('tags')
1908 tags = opts.get('tags')
1905 branches = opts.get('branches')
1909 branches = opts.get('branches')
1906 if tags:
1910 if tags:
1907 labels = {}
1911 labels = {}
1908 for l, n in repo.tags().items():
1912 for l, n in repo.tags().items():
1909 labels.setdefault(cl.rev(n), []).append(l)
1913 labels.setdefault(cl.rev(n), []).append(l)
1910 def events():
1914 def events():
1911 b = "default"
1915 b = "default"
1912 for r in cl:
1916 for r in cl:
1913 if branches:
1917 if branches:
1914 newb = cl.read(cl.node(r))[5]['branch']
1918 newb = cl.read(cl.node(r))[5]['branch']
1915 if newb != b:
1919 if newb != b:
1916 yield 'a', newb
1920 yield 'a', newb
1917 b = newb
1921 b = newb
1918 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1922 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1919 if p != -1)))
1923 if p != -1)))
1920 if tags:
1924 if tags:
1921 ls = labels.get(r)
1925 ls = labels.get(r)
1922 if ls:
1926 if ls:
1923 for l in ls:
1927 for l in ls:
1924 yield 'l', (r, l)
1928 yield 'l', (r, l)
1925 else:
1929 else:
1926 raise util.Abort(_('need repo for changelog dag'))
1930 raise util.Abort(_('need repo for changelog dag'))
1927
1931
1928 for line in dagparser.dagtextlines(events(),
1932 for line in dagparser.dagtextlines(events(),
1929 addspaces=spaces,
1933 addspaces=spaces,
1930 wraplabels=True,
1934 wraplabels=True,
1931 wrapannotations=True,
1935 wrapannotations=True,
1932 wrapnonlinear=dots,
1936 wrapnonlinear=dots,
1933 usedots=dots,
1937 usedots=dots,
1934 maxlinewidth=70):
1938 maxlinewidth=70):
1935 ui.write(line)
1939 ui.write(line)
1936 ui.write("\n")
1940 ui.write("\n")
1937
1941
1938 @command('debugdata',
1942 @command('debugdata',
1939 [('c', 'changelog', False, _('open changelog')),
1943 [('c', 'changelog', False, _('open changelog')),
1940 ('m', 'manifest', False, _('open manifest'))],
1944 ('m', 'manifest', False, _('open manifest'))],
1941 _('-c|-m|FILE REV'))
1945 _('-c|-m|FILE REV'))
1942 def debugdata(ui, repo, file_, rev=None, **opts):
1946 def debugdata(ui, repo, file_, rev=None, **opts):
1943 """dump the contents of a data file revision"""
1947 """dump the contents of a data file revision"""
1944 if opts.get('changelog') or opts.get('manifest'):
1948 if opts.get('changelog') or opts.get('manifest'):
1945 file_, rev = None, file_
1949 file_, rev = None, file_
1946 elif rev is None:
1950 elif rev is None:
1947 raise error.CommandError('debugdata', _('invalid arguments'))
1951 raise error.CommandError('debugdata', _('invalid arguments'))
1948 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1952 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1949 try:
1953 try:
1950 ui.write(r.revision(r.lookup(rev)))
1954 ui.write(r.revision(r.lookup(rev)))
1951 except KeyError:
1955 except KeyError:
1952 raise util.Abort(_('invalid revision identifier %s') % rev)
1956 raise util.Abort(_('invalid revision identifier %s') % rev)
1953
1957
1954 @command('debugdate',
1958 @command('debugdate',
1955 [('e', 'extended', None, _('try extended date formats'))],
1959 [('e', 'extended', None, _('try extended date formats'))],
1956 _('[-e] DATE [RANGE]'))
1960 _('[-e] DATE [RANGE]'))
1957 def debugdate(ui, date, range=None, **opts):
1961 def debugdate(ui, date, range=None, **opts):
1958 """parse and display a date"""
1962 """parse and display a date"""
1959 if opts["extended"]:
1963 if opts["extended"]:
1960 d = util.parsedate(date, util.extendeddateformats)
1964 d = util.parsedate(date, util.extendeddateformats)
1961 else:
1965 else:
1962 d = util.parsedate(date)
1966 d = util.parsedate(date)
1963 ui.write(("internal: %s %s\n") % d)
1967 ui.write(("internal: %s %s\n") % d)
1964 ui.write(("standard: %s\n") % util.datestr(d))
1968 ui.write(("standard: %s\n") % util.datestr(d))
1965 if range:
1969 if range:
1966 m = util.matchdate(range)
1970 m = util.matchdate(range)
1967 ui.write(("match: %s\n") % m(d[0]))
1971 ui.write(("match: %s\n") % m(d[0]))
1968
1972
1969 @command('debugdiscovery',
1973 @command('debugdiscovery',
1970 [('', 'old', None, _('use old-style discovery')),
1974 [('', 'old', None, _('use old-style discovery')),
1971 ('', 'nonheads', None,
1975 ('', 'nonheads', None,
1972 _('use old-style discovery with non-heads included')),
1976 _('use old-style discovery with non-heads included')),
1973 ] + remoteopts,
1977 ] + remoteopts,
1974 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1978 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1975 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1979 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1976 """runs the changeset discovery protocol in isolation"""
1980 """runs the changeset discovery protocol in isolation"""
1977 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1981 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1978 opts.get('branch'))
1982 opts.get('branch'))
1979 remote = hg.peer(repo, opts, remoteurl)
1983 remote = hg.peer(repo, opts, remoteurl)
1980 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1984 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1981
1985
1982 # make sure tests are repeatable
1986 # make sure tests are repeatable
1983 random.seed(12323)
1987 random.seed(12323)
1984
1988
1985 def doit(localheads, remoteheads, remote=remote):
1989 def doit(localheads, remoteheads, remote=remote):
1986 if opts.get('old'):
1990 if opts.get('old'):
1987 if localheads:
1991 if localheads:
1988 raise util.Abort('cannot use localheads with old style '
1992 raise util.Abort('cannot use localheads with old style '
1989 'discovery')
1993 'discovery')
1990 if not util.safehasattr(remote, 'branches'):
1994 if not util.safehasattr(remote, 'branches'):
1991 # enable in-client legacy support
1995 # enable in-client legacy support
1992 remote = localrepo.locallegacypeer(remote.local())
1996 remote = localrepo.locallegacypeer(remote.local())
1993 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1997 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1994 force=True)
1998 force=True)
1995 common = set(common)
1999 common = set(common)
1996 if not opts.get('nonheads'):
2000 if not opts.get('nonheads'):
1997 ui.write(("unpruned common: %s\n") %
2001 ui.write(("unpruned common: %s\n") %
1998 " ".join(sorted(short(n) for n in common)))
2002 " ".join(sorted(short(n) for n in common)))
1999 dag = dagutil.revlogdag(repo.changelog)
2003 dag = dagutil.revlogdag(repo.changelog)
2000 all = dag.ancestorset(dag.internalizeall(common))
2004 all = dag.ancestorset(dag.internalizeall(common))
2001 common = dag.externalizeall(dag.headsetofconnecteds(all))
2005 common = dag.externalizeall(dag.headsetofconnecteds(all))
2002 else:
2006 else:
2003 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2007 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2004 common = set(common)
2008 common = set(common)
2005 rheads = set(hds)
2009 rheads = set(hds)
2006 lheads = set(repo.heads())
2010 lheads = set(repo.heads())
2007 ui.write(("common heads: %s\n") %
2011 ui.write(("common heads: %s\n") %
2008 " ".join(sorted(short(n) for n in common)))
2012 " ".join(sorted(short(n) for n in common)))
2009 if lheads <= common:
2013 if lheads <= common:
2010 ui.write(("local is subset\n"))
2014 ui.write(("local is subset\n"))
2011 elif rheads <= common:
2015 elif rheads <= common:
2012 ui.write(("remote is subset\n"))
2016 ui.write(("remote is subset\n"))
2013
2017
2014 serverlogs = opts.get('serverlog')
2018 serverlogs = opts.get('serverlog')
2015 if serverlogs:
2019 if serverlogs:
2016 for filename in serverlogs:
2020 for filename in serverlogs:
2017 logfile = open(filename, 'r')
2021 logfile = open(filename, 'r')
2018 try:
2022 try:
2019 line = logfile.readline()
2023 line = logfile.readline()
2020 while line:
2024 while line:
2021 parts = line.strip().split(';')
2025 parts = line.strip().split(';')
2022 op = parts[1]
2026 op = parts[1]
2023 if op == 'cg':
2027 if op == 'cg':
2024 pass
2028 pass
2025 elif op == 'cgss':
2029 elif op == 'cgss':
2026 doit(parts[2].split(' '), parts[3].split(' '))
2030 doit(parts[2].split(' '), parts[3].split(' '))
2027 elif op == 'unb':
2031 elif op == 'unb':
2028 doit(parts[3].split(' '), parts[2].split(' '))
2032 doit(parts[3].split(' '), parts[2].split(' '))
2029 line = logfile.readline()
2033 line = logfile.readline()
2030 finally:
2034 finally:
2031 logfile.close()
2035 logfile.close()
2032
2036
2033 else:
2037 else:
2034 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2038 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2035 opts.get('remote_head'))
2039 opts.get('remote_head'))
2036 localrevs = opts.get('local_head')
2040 localrevs = opts.get('local_head')
2037 doit(localrevs, remoterevs)
2041 doit(localrevs, remoterevs)
2038
2042
2039 @command('debugfileset',
2043 @command('debugfileset',
2040 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2044 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2041 _('[-r REV] FILESPEC'))
2045 _('[-r REV] FILESPEC'))
2042 def debugfileset(ui, repo, expr, **opts):
2046 def debugfileset(ui, repo, expr, **opts):
2043 '''parse and apply a fileset specification'''
2047 '''parse and apply a fileset specification'''
2044 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2048 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2045 if ui.verbose:
2049 if ui.verbose:
2046 tree = fileset.parse(expr)[0]
2050 tree = fileset.parse(expr)[0]
2047 ui.note(tree, "\n")
2051 ui.note(tree, "\n")
2048
2052
2049 for f in ctx.getfileset(expr):
2053 for f in ctx.getfileset(expr):
2050 ui.write("%s\n" % f)
2054 ui.write("%s\n" % f)
2051
2055
2052 @command('debugfsinfo', [], _('[PATH]'))
2056 @command('debugfsinfo', [], _('[PATH]'))
2053 def debugfsinfo(ui, path="."):
2057 def debugfsinfo(ui, path="."):
2054 """show information detected about current filesystem"""
2058 """show information detected about current filesystem"""
2055 util.writefile('.debugfsinfo', '')
2059 util.writefile('.debugfsinfo', '')
2056 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2060 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2057 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2061 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2058 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2062 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2059 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2063 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2060 and 'yes' or 'no'))
2064 and 'yes' or 'no'))
2061 os.unlink('.debugfsinfo')
2065 os.unlink('.debugfsinfo')
2062
2066
2063 @command('debuggetbundle',
2067 @command('debuggetbundle',
2064 [('H', 'head', [], _('id of head node'), _('ID')),
2068 [('H', 'head', [], _('id of head node'), _('ID')),
2065 ('C', 'common', [], _('id of common node'), _('ID')),
2069 ('C', 'common', [], _('id of common node'), _('ID')),
2066 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2070 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2067 _('REPO FILE [-H|-C ID]...'))
2071 _('REPO FILE [-H|-C ID]...'))
2068 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2072 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2069 """retrieves a bundle from a repo
2073 """retrieves a bundle from a repo
2070
2074
2071 Every ID must be a full-length hex node id string. Saves the bundle to the
2075 Every ID must be a full-length hex node id string. Saves the bundle to the
2072 given file.
2076 given file.
2073 """
2077 """
2074 repo = hg.peer(ui, opts, repopath)
2078 repo = hg.peer(ui, opts, repopath)
2075 if not repo.capable('getbundle'):
2079 if not repo.capable('getbundle'):
2076 raise util.Abort("getbundle() not supported by target repository")
2080 raise util.Abort("getbundle() not supported by target repository")
2077 args = {}
2081 args = {}
2078 if common:
2082 if common:
2079 args['common'] = [bin(s) for s in common]
2083 args['common'] = [bin(s) for s in common]
2080 if head:
2084 if head:
2081 args['heads'] = [bin(s) for s in head]
2085 args['heads'] = [bin(s) for s in head]
2082 # TODO: get desired bundlecaps from command line.
2086 # TODO: get desired bundlecaps from command line.
2083 args['bundlecaps'] = None
2087 args['bundlecaps'] = None
2084 bundle = repo.getbundle('debug', **args)
2088 bundle = repo.getbundle('debug', **args)
2085
2089
2086 bundletype = opts.get('type', 'bzip2').lower()
2090 bundletype = opts.get('type', 'bzip2').lower()
2087 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2091 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2088 bundletype = btypes.get(bundletype)
2092 bundletype = btypes.get(bundletype)
2089 if bundletype not in changegroup.bundletypes:
2093 if bundletype not in changegroup.bundletypes:
2090 raise util.Abort(_('unknown bundle type specified with --type'))
2094 raise util.Abort(_('unknown bundle type specified with --type'))
2091 changegroup.writebundle(bundle, bundlepath, bundletype)
2095 changegroup.writebundle(bundle, bundlepath, bundletype)
2092
2096
2093 @command('debugignore', [], '')
2097 @command('debugignore', [], '')
2094 def debugignore(ui, repo, *values, **opts):
2098 def debugignore(ui, repo, *values, **opts):
2095 """display the combined ignore pattern"""
2099 """display the combined ignore pattern"""
2096 ignore = repo.dirstate._ignore
2100 ignore = repo.dirstate._ignore
2097 includepat = getattr(ignore, 'includepat', None)
2101 includepat = getattr(ignore, 'includepat', None)
2098 if includepat is not None:
2102 if includepat is not None:
2099 ui.write("%s\n" % includepat)
2103 ui.write("%s\n" % includepat)
2100 else:
2104 else:
2101 raise util.Abort(_("no ignore patterns found"))
2105 raise util.Abort(_("no ignore patterns found"))
2102
2106
2103 @command('debugindex',
2107 @command('debugindex',
2104 [('c', 'changelog', False, _('open changelog')),
2108 [('c', 'changelog', False, _('open changelog')),
2105 ('m', 'manifest', False, _('open manifest')),
2109 ('m', 'manifest', False, _('open manifest')),
2106 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2110 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2107 _('[-f FORMAT] -c|-m|FILE'))
2111 _('[-f FORMAT] -c|-m|FILE'))
2108 def debugindex(ui, repo, file_=None, **opts):
2112 def debugindex(ui, repo, file_=None, **opts):
2109 """dump the contents of an index file"""
2113 """dump the contents of an index file"""
2110 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2114 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2111 format = opts.get('format', 0)
2115 format = opts.get('format', 0)
2112 if format not in (0, 1):
2116 if format not in (0, 1):
2113 raise util.Abort(_("unknown format %d") % format)
2117 raise util.Abort(_("unknown format %d") % format)
2114
2118
2115 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2119 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2116 if generaldelta:
2120 if generaldelta:
2117 basehdr = ' delta'
2121 basehdr = ' delta'
2118 else:
2122 else:
2119 basehdr = ' base'
2123 basehdr = ' base'
2120
2124
2121 if format == 0:
2125 if format == 0:
2122 ui.write(" rev offset length " + basehdr + " linkrev"
2126 ui.write(" rev offset length " + basehdr + " linkrev"
2123 " nodeid p1 p2\n")
2127 " nodeid p1 p2\n")
2124 elif format == 1:
2128 elif format == 1:
2125 ui.write(" rev flag offset length"
2129 ui.write(" rev flag offset length"
2126 " size " + basehdr + " link p1 p2"
2130 " size " + basehdr + " link p1 p2"
2127 " nodeid\n")
2131 " nodeid\n")
2128
2132
2129 for i in r:
2133 for i in r:
2130 node = r.node(i)
2134 node = r.node(i)
2131 if generaldelta:
2135 if generaldelta:
2132 base = r.deltaparent(i)
2136 base = r.deltaparent(i)
2133 else:
2137 else:
2134 base = r.chainbase(i)
2138 base = r.chainbase(i)
2135 if format == 0:
2139 if format == 0:
2136 try:
2140 try:
2137 pp = r.parents(node)
2141 pp = r.parents(node)
2138 except Exception:
2142 except Exception:
2139 pp = [nullid, nullid]
2143 pp = [nullid, nullid]
2140 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2144 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2141 i, r.start(i), r.length(i), base, r.linkrev(i),
2145 i, r.start(i), r.length(i), base, r.linkrev(i),
2142 short(node), short(pp[0]), short(pp[1])))
2146 short(node), short(pp[0]), short(pp[1])))
2143 elif format == 1:
2147 elif format == 1:
2144 pr = r.parentrevs(i)
2148 pr = r.parentrevs(i)
2145 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2149 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2146 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2150 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2147 base, r.linkrev(i), pr[0], pr[1], short(node)))
2151 base, r.linkrev(i), pr[0], pr[1], short(node)))
2148
2152
2149 @command('debugindexdot', [], _('FILE'))
2153 @command('debugindexdot', [], _('FILE'))
2150 def debugindexdot(ui, repo, file_):
2154 def debugindexdot(ui, repo, file_):
2151 """dump an index DAG as a graphviz dot file"""
2155 """dump an index DAG as a graphviz dot file"""
2152 r = None
2156 r = None
2153 if repo:
2157 if repo:
2154 filelog = repo.file(file_)
2158 filelog = repo.file(file_)
2155 if len(filelog):
2159 if len(filelog):
2156 r = filelog
2160 r = filelog
2157 if not r:
2161 if not r:
2158 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2162 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2159 ui.write(("digraph G {\n"))
2163 ui.write(("digraph G {\n"))
2160 for i in r:
2164 for i in r:
2161 node = r.node(i)
2165 node = r.node(i)
2162 pp = r.parents(node)
2166 pp = r.parents(node)
2163 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2167 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2164 if pp[1] != nullid:
2168 if pp[1] != nullid:
2165 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2169 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2166 ui.write("}\n")
2170 ui.write("}\n")
2167
2171
2168 @command('debuginstall', [], '')
2172 @command('debuginstall', [], '')
2169 def debuginstall(ui):
2173 def debuginstall(ui):
2170 '''test Mercurial installation
2174 '''test Mercurial installation
2171
2175
2172 Returns 0 on success.
2176 Returns 0 on success.
2173 '''
2177 '''
2174
2178
2175 def writetemp(contents):
2179 def writetemp(contents):
2176 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2180 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2177 f = os.fdopen(fd, "wb")
2181 f = os.fdopen(fd, "wb")
2178 f.write(contents)
2182 f.write(contents)
2179 f.close()
2183 f.close()
2180 return name
2184 return name
2181
2185
2182 problems = 0
2186 problems = 0
2183
2187
2184 # encoding
2188 # encoding
2185 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2189 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2186 try:
2190 try:
2187 encoding.fromlocal("test")
2191 encoding.fromlocal("test")
2188 except util.Abort, inst:
2192 except util.Abort, inst:
2189 ui.write(" %s\n" % inst)
2193 ui.write(" %s\n" % inst)
2190 ui.write(_(" (check that your locale is properly set)\n"))
2194 ui.write(_(" (check that your locale is properly set)\n"))
2191 problems += 1
2195 problems += 1
2192
2196
2193 # Python
2197 # Python
2194 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2198 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2195 ui.status(_("checking Python version (%s)\n")
2199 ui.status(_("checking Python version (%s)\n")
2196 % ("%s.%s.%s" % sys.version_info[:3]))
2200 % ("%s.%s.%s" % sys.version_info[:3]))
2197 ui.status(_("checking Python lib (%s)...\n")
2201 ui.status(_("checking Python lib (%s)...\n")
2198 % os.path.dirname(os.__file__))
2202 % os.path.dirname(os.__file__))
2199
2203
2200 # compiled modules
2204 # compiled modules
2201 ui.status(_("checking installed modules (%s)...\n")
2205 ui.status(_("checking installed modules (%s)...\n")
2202 % os.path.dirname(__file__))
2206 % os.path.dirname(__file__))
2203 try:
2207 try:
2204 import bdiff, mpatch, base85, osutil
2208 import bdiff, mpatch, base85, osutil
2205 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2209 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2206 except Exception, inst:
2210 except Exception, inst:
2207 ui.write(" %s\n" % inst)
2211 ui.write(" %s\n" % inst)
2208 ui.write(_(" One or more extensions could not be found"))
2212 ui.write(_(" One or more extensions could not be found"))
2209 ui.write(_(" (check that you compiled the extensions)\n"))
2213 ui.write(_(" (check that you compiled the extensions)\n"))
2210 problems += 1
2214 problems += 1
2211
2215
2212 # templates
2216 # templates
2213 import templater
2217 import templater
2214 p = templater.templatepath()
2218 p = templater.templatepath()
2215 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2219 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2216 if p:
2220 if p:
2217 m = templater.templatepath("map-cmdline.default")
2221 m = templater.templatepath("map-cmdline.default")
2218 if m:
2222 if m:
2219 # template found, check if it is working
2223 # template found, check if it is working
2220 try:
2224 try:
2221 templater.templater(m)
2225 templater.templater(m)
2222 except Exception, inst:
2226 except Exception, inst:
2223 ui.write(" %s\n" % inst)
2227 ui.write(" %s\n" % inst)
2224 p = None
2228 p = None
2225 else:
2229 else:
2226 ui.write(_(" template 'default' not found\n"))
2230 ui.write(_(" template 'default' not found\n"))
2227 p = None
2231 p = None
2228 else:
2232 else:
2229 ui.write(_(" no template directories found\n"))
2233 ui.write(_(" no template directories found\n"))
2230 if not p:
2234 if not p:
2231 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2235 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2232 problems += 1
2236 problems += 1
2233
2237
2234 # editor
2238 # editor
2235 ui.status(_("checking commit editor...\n"))
2239 ui.status(_("checking commit editor...\n"))
2236 editor = ui.geteditor()
2240 editor = ui.geteditor()
2237 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2241 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2238 if not cmdpath:
2242 if not cmdpath:
2239 if editor == 'vi':
2243 if editor == 'vi':
2240 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2244 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2241 ui.write(_(" (specify a commit editor in your configuration"
2245 ui.write(_(" (specify a commit editor in your configuration"
2242 " file)\n"))
2246 " file)\n"))
2243 else:
2247 else:
2244 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2248 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2245 ui.write(_(" (specify a commit editor in your configuration"
2249 ui.write(_(" (specify a commit editor in your configuration"
2246 " file)\n"))
2250 " file)\n"))
2247 problems += 1
2251 problems += 1
2248
2252
2249 # check username
2253 # check username
2250 ui.status(_("checking username...\n"))
2254 ui.status(_("checking username...\n"))
2251 try:
2255 try:
2252 ui.username()
2256 ui.username()
2253 except util.Abort, e:
2257 except util.Abort, e:
2254 ui.write(" %s\n" % e)
2258 ui.write(" %s\n" % e)
2255 ui.write(_(" (specify a username in your configuration file)\n"))
2259 ui.write(_(" (specify a username in your configuration file)\n"))
2256 problems += 1
2260 problems += 1
2257
2261
2258 if not problems:
2262 if not problems:
2259 ui.status(_("no problems detected\n"))
2263 ui.status(_("no problems detected\n"))
2260 else:
2264 else:
2261 ui.write(_("%s problems detected,"
2265 ui.write(_("%s problems detected,"
2262 " please check your install!\n") % problems)
2266 " please check your install!\n") % problems)
2263
2267
2264 return problems
2268 return problems
2265
2269
2266 @command('debugknown', [], _('REPO ID...'))
2270 @command('debugknown', [], _('REPO ID...'))
2267 def debugknown(ui, repopath, *ids, **opts):
2271 def debugknown(ui, repopath, *ids, **opts):
2268 """test whether node ids are known to a repo
2272 """test whether node ids are known to a repo
2269
2273
2270 Every ID must be a full-length hex node id string. Returns a list of 0s
2274 Every ID must be a full-length hex node id string. Returns a list of 0s
2271 and 1s indicating unknown/known.
2275 and 1s indicating unknown/known.
2272 """
2276 """
2273 repo = hg.peer(ui, opts, repopath)
2277 repo = hg.peer(ui, opts, repopath)
2274 if not repo.capable('known'):
2278 if not repo.capable('known'):
2275 raise util.Abort("known() not supported by target repository")
2279 raise util.Abort("known() not supported by target repository")
2276 flags = repo.known([bin(s) for s in ids])
2280 flags = repo.known([bin(s) for s in ids])
2277 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2281 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2278
2282
2279 @command('debuglabelcomplete', [], _('LABEL...'))
2283 @command('debuglabelcomplete', [], _('LABEL...'))
2280 def debuglabelcomplete(ui, repo, *args):
2284 def debuglabelcomplete(ui, repo, *args):
2281 '''complete "labels" - tags, open branch names, bookmark names'''
2285 '''complete "labels" - tags, open branch names, bookmark names'''
2282
2286
2283 labels = set()
2287 labels = set()
2284 labels.update(t[0] for t in repo.tagslist())
2288 labels.update(t[0] for t in repo.tagslist())
2285 labels.update(repo._bookmarks.keys())
2289 labels.update(repo._bookmarks.keys())
2286 labels.update(tag for (tag, heads, tip, closed)
2290 labels.update(tag for (tag, heads, tip, closed)
2287 in repo.branchmap().iterbranches() if not closed)
2291 in repo.branchmap().iterbranches() if not closed)
2288 completions = set()
2292 completions = set()
2289 if not args:
2293 if not args:
2290 args = ['']
2294 args = ['']
2291 for a in args:
2295 for a in args:
2292 completions.update(l for l in labels if l.startswith(a))
2296 completions.update(l for l in labels if l.startswith(a))
2293 ui.write('\n'.join(sorted(completions)))
2297 ui.write('\n'.join(sorted(completions)))
2294 ui.write('\n')
2298 ui.write('\n')
2295
2299
2296 @command('debugobsolete',
2300 @command('debugobsolete',
2297 [('', 'flags', 0, _('markers flag')),
2301 [('', 'flags', 0, _('markers flag')),
2298 ] + commitopts2,
2302 ] + commitopts2,
2299 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2303 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2300 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2304 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2301 """create arbitrary obsolete marker
2305 """create arbitrary obsolete marker
2302
2306
2303 With no arguments, displays the list of obsolescence markers."""
2307 With no arguments, displays the list of obsolescence markers."""
2304 def parsenodeid(s):
2308 def parsenodeid(s):
2305 try:
2309 try:
2306 # We do not use revsingle/revrange functions here to accept
2310 # We do not use revsingle/revrange functions here to accept
2307 # arbitrary node identifiers, possibly not present in the
2311 # arbitrary node identifiers, possibly not present in the
2308 # local repository.
2312 # local repository.
2309 n = bin(s)
2313 n = bin(s)
2310 if len(n) != len(nullid):
2314 if len(n) != len(nullid):
2311 raise TypeError()
2315 raise TypeError()
2312 return n
2316 return n
2313 except TypeError:
2317 except TypeError:
2314 raise util.Abort('changeset references must be full hexadecimal '
2318 raise util.Abort('changeset references must be full hexadecimal '
2315 'node identifiers')
2319 'node identifiers')
2316
2320
2317 if precursor is not None:
2321 if precursor is not None:
2318 metadata = {}
2322 metadata = {}
2319 if 'date' in opts:
2323 if 'date' in opts:
2320 metadata['date'] = opts['date']
2324 metadata['date'] = opts['date']
2321 metadata['user'] = opts['user'] or ui.username()
2325 metadata['user'] = opts['user'] or ui.username()
2322 succs = tuple(parsenodeid(succ) for succ in successors)
2326 succs = tuple(parsenodeid(succ) for succ in successors)
2323 l = repo.lock()
2327 l = repo.lock()
2324 try:
2328 try:
2325 tr = repo.transaction('debugobsolete')
2329 tr = repo.transaction('debugobsolete')
2326 try:
2330 try:
2327 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2331 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2328 opts['flags'], metadata)
2332 opts['flags'], metadata)
2329 tr.close()
2333 tr.close()
2330 finally:
2334 finally:
2331 tr.release()
2335 tr.release()
2332 finally:
2336 finally:
2333 l.release()
2337 l.release()
2334 else:
2338 else:
2335 for m in obsolete.allmarkers(repo):
2339 for m in obsolete.allmarkers(repo):
2336 cmdutil.showmarker(ui, m)
2340 cmdutil.showmarker(ui, m)
2337
2341
2338 @command('debugpathcomplete',
2342 @command('debugpathcomplete',
2339 [('f', 'full', None, _('complete an entire path')),
2343 [('f', 'full', None, _('complete an entire path')),
2340 ('n', 'normal', None, _('show only normal files')),
2344 ('n', 'normal', None, _('show only normal files')),
2341 ('a', 'added', None, _('show only added files')),
2345 ('a', 'added', None, _('show only added files')),
2342 ('r', 'removed', None, _('show only removed files'))],
2346 ('r', 'removed', None, _('show only removed files'))],
2343 _('FILESPEC...'))
2347 _('FILESPEC...'))
2344 def debugpathcomplete(ui, repo, *specs, **opts):
2348 def debugpathcomplete(ui, repo, *specs, **opts):
2345 '''complete part or all of a tracked path
2349 '''complete part or all of a tracked path
2346
2350
2347 This command supports shells that offer path name completion. It
2351 This command supports shells that offer path name completion. It
2348 currently completes only files already known to the dirstate.
2352 currently completes only files already known to the dirstate.
2349
2353
2350 Completion extends only to the next path segment unless
2354 Completion extends only to the next path segment unless
2351 --full is specified, in which case entire paths are used.'''
2355 --full is specified, in which case entire paths are used.'''
2352
2356
2353 def complete(path, acceptable):
2357 def complete(path, acceptable):
2354 dirstate = repo.dirstate
2358 dirstate = repo.dirstate
2355 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2359 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2356 rootdir = repo.root + os.sep
2360 rootdir = repo.root + os.sep
2357 if spec != repo.root and not spec.startswith(rootdir):
2361 if spec != repo.root and not spec.startswith(rootdir):
2358 return [], []
2362 return [], []
2359 if os.path.isdir(spec):
2363 if os.path.isdir(spec):
2360 spec += '/'
2364 spec += '/'
2361 spec = spec[len(rootdir):]
2365 spec = spec[len(rootdir):]
2362 fixpaths = os.sep != '/'
2366 fixpaths = os.sep != '/'
2363 if fixpaths:
2367 if fixpaths:
2364 spec = spec.replace(os.sep, '/')
2368 spec = spec.replace(os.sep, '/')
2365 speclen = len(spec)
2369 speclen = len(spec)
2366 fullpaths = opts['full']
2370 fullpaths = opts['full']
2367 files, dirs = set(), set()
2371 files, dirs = set(), set()
2368 adddir, addfile = dirs.add, files.add
2372 adddir, addfile = dirs.add, files.add
2369 for f, st in dirstate.iteritems():
2373 for f, st in dirstate.iteritems():
2370 if f.startswith(spec) and st[0] in acceptable:
2374 if f.startswith(spec) and st[0] in acceptable:
2371 if fixpaths:
2375 if fixpaths:
2372 f = f.replace('/', os.sep)
2376 f = f.replace('/', os.sep)
2373 if fullpaths:
2377 if fullpaths:
2374 addfile(f)
2378 addfile(f)
2375 continue
2379 continue
2376 s = f.find(os.sep, speclen)
2380 s = f.find(os.sep, speclen)
2377 if s >= 0:
2381 if s >= 0:
2378 adddir(f[:s])
2382 adddir(f[:s])
2379 else:
2383 else:
2380 addfile(f)
2384 addfile(f)
2381 return files, dirs
2385 return files, dirs
2382
2386
2383 acceptable = ''
2387 acceptable = ''
2384 if opts['normal']:
2388 if opts['normal']:
2385 acceptable += 'nm'
2389 acceptable += 'nm'
2386 if opts['added']:
2390 if opts['added']:
2387 acceptable += 'a'
2391 acceptable += 'a'
2388 if opts['removed']:
2392 if opts['removed']:
2389 acceptable += 'r'
2393 acceptable += 'r'
2390 cwd = repo.getcwd()
2394 cwd = repo.getcwd()
2391 if not specs:
2395 if not specs:
2392 specs = ['.']
2396 specs = ['.']
2393
2397
2394 files, dirs = set(), set()
2398 files, dirs = set(), set()
2395 for spec in specs:
2399 for spec in specs:
2396 f, d = complete(spec, acceptable or 'nmar')
2400 f, d = complete(spec, acceptable or 'nmar')
2397 files.update(f)
2401 files.update(f)
2398 dirs.update(d)
2402 dirs.update(d)
2399 files.update(dirs)
2403 files.update(dirs)
2400 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2404 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2401 ui.write('\n')
2405 ui.write('\n')
2402
2406
2403 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2407 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2404 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2408 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2405 '''access the pushkey key/value protocol
2409 '''access the pushkey key/value protocol
2406
2410
2407 With two args, list the keys in the given namespace.
2411 With two args, list the keys in the given namespace.
2408
2412
2409 With five args, set a key to new if it currently is set to old.
2413 With five args, set a key to new if it currently is set to old.
2410 Reports success or failure.
2414 Reports success or failure.
2411 '''
2415 '''
2412
2416
2413 target = hg.peer(ui, {}, repopath)
2417 target = hg.peer(ui, {}, repopath)
2414 if keyinfo:
2418 if keyinfo:
2415 key, old, new = keyinfo
2419 key, old, new = keyinfo
2416 r = target.pushkey(namespace, key, old, new)
2420 r = target.pushkey(namespace, key, old, new)
2417 ui.status(str(r) + '\n')
2421 ui.status(str(r) + '\n')
2418 return not r
2422 return not r
2419 else:
2423 else:
2420 for k, v in sorted(target.listkeys(namespace).iteritems()):
2424 for k, v in sorted(target.listkeys(namespace).iteritems()):
2421 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2425 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2422 v.encode('string-escape')))
2426 v.encode('string-escape')))
2423
2427
2424 @command('debugpvec', [], _('A B'))
2428 @command('debugpvec', [], _('A B'))
2425 def debugpvec(ui, repo, a, b=None):
2429 def debugpvec(ui, repo, a, b=None):
2426 ca = scmutil.revsingle(repo, a)
2430 ca = scmutil.revsingle(repo, a)
2427 cb = scmutil.revsingle(repo, b)
2431 cb = scmutil.revsingle(repo, b)
2428 pa = pvec.ctxpvec(ca)
2432 pa = pvec.ctxpvec(ca)
2429 pb = pvec.ctxpvec(cb)
2433 pb = pvec.ctxpvec(cb)
2430 if pa == pb:
2434 if pa == pb:
2431 rel = "="
2435 rel = "="
2432 elif pa > pb:
2436 elif pa > pb:
2433 rel = ">"
2437 rel = ">"
2434 elif pa < pb:
2438 elif pa < pb:
2435 rel = "<"
2439 rel = "<"
2436 elif pa | pb:
2440 elif pa | pb:
2437 rel = "|"
2441 rel = "|"
2438 ui.write(_("a: %s\n") % pa)
2442 ui.write(_("a: %s\n") % pa)
2439 ui.write(_("b: %s\n") % pb)
2443 ui.write(_("b: %s\n") % pb)
2440 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2444 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2441 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2445 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2442 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2446 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2443 pa.distance(pb), rel))
2447 pa.distance(pb), rel))
2444
2448
2445 @command('debugrebuilddirstate|debugrebuildstate',
2449 @command('debugrebuilddirstate|debugrebuildstate',
2446 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2450 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2447 _('[-r REV]'))
2451 _('[-r REV]'))
2448 def debugrebuilddirstate(ui, repo, rev):
2452 def debugrebuilddirstate(ui, repo, rev):
2449 """rebuild the dirstate as it would look like for the given revision
2453 """rebuild the dirstate as it would look like for the given revision
2450
2454
2451 If no revision is specified the first current parent will be used.
2455 If no revision is specified the first current parent will be used.
2452
2456
2453 The dirstate will be set to the files of the given revision.
2457 The dirstate will be set to the files of the given revision.
2454 The actual working directory content or existing dirstate
2458 The actual working directory content or existing dirstate
2455 information such as adds or removes is not considered.
2459 information such as adds or removes is not considered.
2456
2460
2457 One use of this command is to make the next :hg:`status` invocation
2461 One use of this command is to make the next :hg:`status` invocation
2458 check the actual file content.
2462 check the actual file content.
2459 """
2463 """
2460 ctx = scmutil.revsingle(repo, rev)
2464 ctx = scmutil.revsingle(repo, rev)
2461 wlock = repo.wlock()
2465 wlock = repo.wlock()
2462 try:
2466 try:
2463 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2467 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2464 finally:
2468 finally:
2465 wlock.release()
2469 wlock.release()
2466
2470
2467 @command('debugrename',
2471 @command('debugrename',
2468 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2472 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2469 _('[-r REV] FILE'))
2473 _('[-r REV] FILE'))
2470 def debugrename(ui, repo, file1, *pats, **opts):
2474 def debugrename(ui, repo, file1, *pats, **opts):
2471 """dump rename information"""
2475 """dump rename information"""
2472
2476
2473 ctx = scmutil.revsingle(repo, opts.get('rev'))
2477 ctx = scmutil.revsingle(repo, opts.get('rev'))
2474 m = scmutil.match(ctx, (file1,) + pats, opts)
2478 m = scmutil.match(ctx, (file1,) + pats, opts)
2475 for abs in ctx.walk(m):
2479 for abs in ctx.walk(m):
2476 fctx = ctx[abs]
2480 fctx = ctx[abs]
2477 o = fctx.filelog().renamed(fctx.filenode())
2481 o = fctx.filelog().renamed(fctx.filenode())
2478 rel = m.rel(abs)
2482 rel = m.rel(abs)
2479 if o:
2483 if o:
2480 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2484 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2481 else:
2485 else:
2482 ui.write(_("%s not renamed\n") % rel)
2486 ui.write(_("%s not renamed\n") % rel)
2483
2487
2484 @command('debugrevlog',
2488 @command('debugrevlog',
2485 [('c', 'changelog', False, _('open changelog')),
2489 [('c', 'changelog', False, _('open changelog')),
2486 ('m', 'manifest', False, _('open manifest')),
2490 ('m', 'manifest', False, _('open manifest')),
2487 ('d', 'dump', False, _('dump index data'))],
2491 ('d', 'dump', False, _('dump index data'))],
2488 _('-c|-m|FILE'))
2492 _('-c|-m|FILE'))
2489 def debugrevlog(ui, repo, file_=None, **opts):
2493 def debugrevlog(ui, repo, file_=None, **opts):
2490 """show data and statistics about a revlog"""
2494 """show data and statistics about a revlog"""
2491 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2495 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2492
2496
2493 if opts.get("dump"):
2497 if opts.get("dump"):
2494 numrevs = len(r)
2498 numrevs = len(r)
2495 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2499 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2496 " rawsize totalsize compression heads\n")
2500 " rawsize totalsize compression heads\n")
2497 ts = 0
2501 ts = 0
2498 heads = set()
2502 heads = set()
2499 for rev in xrange(numrevs):
2503 for rev in xrange(numrevs):
2500 dbase = r.deltaparent(rev)
2504 dbase = r.deltaparent(rev)
2501 if dbase == -1:
2505 if dbase == -1:
2502 dbase = rev
2506 dbase = rev
2503 cbase = r.chainbase(rev)
2507 cbase = r.chainbase(rev)
2504 p1, p2 = r.parentrevs(rev)
2508 p1, p2 = r.parentrevs(rev)
2505 rs = r.rawsize(rev)
2509 rs = r.rawsize(rev)
2506 ts = ts + rs
2510 ts = ts + rs
2507 heads -= set(r.parentrevs(rev))
2511 heads -= set(r.parentrevs(rev))
2508 heads.add(rev)
2512 heads.add(rev)
2509 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2513 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2510 (rev, p1, p2, r.start(rev), r.end(rev),
2514 (rev, p1, p2, r.start(rev), r.end(rev),
2511 r.start(dbase), r.start(cbase),
2515 r.start(dbase), r.start(cbase),
2512 r.start(p1), r.start(p2),
2516 r.start(p1), r.start(p2),
2513 rs, ts, ts / r.end(rev), len(heads)))
2517 rs, ts, ts / r.end(rev), len(heads)))
2514 return 0
2518 return 0
2515
2519
2516 v = r.version
2520 v = r.version
2517 format = v & 0xFFFF
2521 format = v & 0xFFFF
2518 flags = []
2522 flags = []
2519 gdelta = False
2523 gdelta = False
2520 if v & revlog.REVLOGNGINLINEDATA:
2524 if v & revlog.REVLOGNGINLINEDATA:
2521 flags.append('inline')
2525 flags.append('inline')
2522 if v & revlog.REVLOGGENERALDELTA:
2526 if v & revlog.REVLOGGENERALDELTA:
2523 gdelta = True
2527 gdelta = True
2524 flags.append('generaldelta')
2528 flags.append('generaldelta')
2525 if not flags:
2529 if not flags:
2526 flags = ['(none)']
2530 flags = ['(none)']
2527
2531
2528 nummerges = 0
2532 nummerges = 0
2529 numfull = 0
2533 numfull = 0
2530 numprev = 0
2534 numprev = 0
2531 nump1 = 0
2535 nump1 = 0
2532 nump2 = 0
2536 nump2 = 0
2533 numother = 0
2537 numother = 0
2534 nump1prev = 0
2538 nump1prev = 0
2535 nump2prev = 0
2539 nump2prev = 0
2536 chainlengths = []
2540 chainlengths = []
2537
2541
2538 datasize = [None, 0, 0L]
2542 datasize = [None, 0, 0L]
2539 fullsize = [None, 0, 0L]
2543 fullsize = [None, 0, 0L]
2540 deltasize = [None, 0, 0L]
2544 deltasize = [None, 0, 0L]
2541
2545
2542 def addsize(size, l):
2546 def addsize(size, l):
2543 if l[0] is None or size < l[0]:
2547 if l[0] is None or size < l[0]:
2544 l[0] = size
2548 l[0] = size
2545 if size > l[1]:
2549 if size > l[1]:
2546 l[1] = size
2550 l[1] = size
2547 l[2] += size
2551 l[2] += size
2548
2552
2549 numrevs = len(r)
2553 numrevs = len(r)
2550 for rev in xrange(numrevs):
2554 for rev in xrange(numrevs):
2551 p1, p2 = r.parentrevs(rev)
2555 p1, p2 = r.parentrevs(rev)
2552 delta = r.deltaparent(rev)
2556 delta = r.deltaparent(rev)
2553 if format > 0:
2557 if format > 0:
2554 addsize(r.rawsize(rev), datasize)
2558 addsize(r.rawsize(rev), datasize)
2555 if p2 != nullrev:
2559 if p2 != nullrev:
2556 nummerges += 1
2560 nummerges += 1
2557 size = r.length(rev)
2561 size = r.length(rev)
2558 if delta == nullrev:
2562 if delta == nullrev:
2559 chainlengths.append(0)
2563 chainlengths.append(0)
2560 numfull += 1
2564 numfull += 1
2561 addsize(size, fullsize)
2565 addsize(size, fullsize)
2562 else:
2566 else:
2563 chainlengths.append(chainlengths[delta] + 1)
2567 chainlengths.append(chainlengths[delta] + 1)
2564 addsize(size, deltasize)
2568 addsize(size, deltasize)
2565 if delta == rev - 1:
2569 if delta == rev - 1:
2566 numprev += 1
2570 numprev += 1
2567 if delta == p1:
2571 if delta == p1:
2568 nump1prev += 1
2572 nump1prev += 1
2569 elif delta == p2:
2573 elif delta == p2:
2570 nump2prev += 1
2574 nump2prev += 1
2571 elif delta == p1:
2575 elif delta == p1:
2572 nump1 += 1
2576 nump1 += 1
2573 elif delta == p2:
2577 elif delta == p2:
2574 nump2 += 1
2578 nump2 += 1
2575 elif delta != nullrev:
2579 elif delta != nullrev:
2576 numother += 1
2580 numother += 1
2577
2581
2578 # Adjust size min value for empty cases
2582 # Adjust size min value for empty cases
2579 for size in (datasize, fullsize, deltasize):
2583 for size in (datasize, fullsize, deltasize):
2580 if size[0] is None:
2584 if size[0] is None:
2581 size[0] = 0
2585 size[0] = 0
2582
2586
2583 numdeltas = numrevs - numfull
2587 numdeltas = numrevs - numfull
2584 numoprev = numprev - nump1prev - nump2prev
2588 numoprev = numprev - nump1prev - nump2prev
2585 totalrawsize = datasize[2]
2589 totalrawsize = datasize[2]
2586 datasize[2] /= numrevs
2590 datasize[2] /= numrevs
2587 fulltotal = fullsize[2]
2591 fulltotal = fullsize[2]
2588 fullsize[2] /= numfull
2592 fullsize[2] /= numfull
2589 deltatotal = deltasize[2]
2593 deltatotal = deltasize[2]
2590 if numrevs - numfull > 0:
2594 if numrevs - numfull > 0:
2591 deltasize[2] /= numrevs - numfull
2595 deltasize[2] /= numrevs - numfull
2592 totalsize = fulltotal + deltatotal
2596 totalsize = fulltotal + deltatotal
2593 avgchainlen = sum(chainlengths) / numrevs
2597 avgchainlen = sum(chainlengths) / numrevs
2594 compratio = totalrawsize / totalsize
2598 compratio = totalrawsize / totalsize
2595
2599
2596 basedfmtstr = '%%%dd\n'
2600 basedfmtstr = '%%%dd\n'
2597 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2601 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2598
2602
2599 def dfmtstr(max):
2603 def dfmtstr(max):
2600 return basedfmtstr % len(str(max))
2604 return basedfmtstr % len(str(max))
2601 def pcfmtstr(max, padding=0):
2605 def pcfmtstr(max, padding=0):
2602 return basepcfmtstr % (len(str(max)), ' ' * padding)
2606 return basepcfmtstr % (len(str(max)), ' ' * padding)
2603
2607
2604 def pcfmt(value, total):
2608 def pcfmt(value, total):
2605 return (value, 100 * float(value) / total)
2609 return (value, 100 * float(value) / total)
2606
2610
2607 ui.write(('format : %d\n') % format)
2611 ui.write(('format : %d\n') % format)
2608 ui.write(('flags : %s\n') % ', '.join(flags))
2612 ui.write(('flags : %s\n') % ', '.join(flags))
2609
2613
2610 ui.write('\n')
2614 ui.write('\n')
2611 fmt = pcfmtstr(totalsize)
2615 fmt = pcfmtstr(totalsize)
2612 fmt2 = dfmtstr(totalsize)
2616 fmt2 = dfmtstr(totalsize)
2613 ui.write(('revisions : ') + fmt2 % numrevs)
2617 ui.write(('revisions : ') + fmt2 % numrevs)
2614 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2618 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2615 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2619 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2616 ui.write(('revisions : ') + fmt2 % numrevs)
2620 ui.write(('revisions : ') + fmt2 % numrevs)
2617 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2621 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2618 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2622 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2619 ui.write(('revision size : ') + fmt2 % totalsize)
2623 ui.write(('revision size : ') + fmt2 % totalsize)
2620 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2624 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2621 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2625 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2622
2626
2623 ui.write('\n')
2627 ui.write('\n')
2624 fmt = dfmtstr(max(avgchainlen, compratio))
2628 fmt = dfmtstr(max(avgchainlen, compratio))
2625 ui.write(('avg chain length : ') + fmt % avgchainlen)
2629 ui.write(('avg chain length : ') + fmt % avgchainlen)
2626 ui.write(('compression ratio : ') + fmt % compratio)
2630 ui.write(('compression ratio : ') + fmt % compratio)
2627
2631
2628 if format > 0:
2632 if format > 0:
2629 ui.write('\n')
2633 ui.write('\n')
2630 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2634 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2631 % tuple(datasize))
2635 % tuple(datasize))
2632 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2636 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2633 % tuple(fullsize))
2637 % tuple(fullsize))
2634 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2638 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2635 % tuple(deltasize))
2639 % tuple(deltasize))
2636
2640
2637 if numdeltas > 0:
2641 if numdeltas > 0:
2638 ui.write('\n')
2642 ui.write('\n')
2639 fmt = pcfmtstr(numdeltas)
2643 fmt = pcfmtstr(numdeltas)
2640 fmt2 = pcfmtstr(numdeltas, 4)
2644 fmt2 = pcfmtstr(numdeltas, 4)
2641 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2645 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2642 if numprev > 0:
2646 if numprev > 0:
2643 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2647 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2644 numprev))
2648 numprev))
2645 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2649 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2646 numprev))
2650 numprev))
2647 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2651 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2648 numprev))
2652 numprev))
2649 if gdelta:
2653 if gdelta:
2650 ui.write(('deltas against p1 : ')
2654 ui.write(('deltas against p1 : ')
2651 + fmt % pcfmt(nump1, numdeltas))
2655 + fmt % pcfmt(nump1, numdeltas))
2652 ui.write(('deltas against p2 : ')
2656 ui.write(('deltas against p2 : ')
2653 + fmt % pcfmt(nump2, numdeltas))
2657 + fmt % pcfmt(nump2, numdeltas))
2654 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2658 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2655 numdeltas))
2659 numdeltas))
2656
2660
2657 @command('debugrevspec',
2661 @command('debugrevspec',
2658 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2662 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2659 ('REVSPEC'))
2663 ('REVSPEC'))
2660 def debugrevspec(ui, repo, expr, **opts):
2664 def debugrevspec(ui, repo, expr, **opts):
2661 """parse and apply a revision specification
2665 """parse and apply a revision specification
2662
2666
2663 Use --verbose to print the parsed tree before and after aliases
2667 Use --verbose to print the parsed tree before and after aliases
2664 expansion.
2668 expansion.
2665 """
2669 """
2666 if ui.verbose:
2670 if ui.verbose:
2667 tree = revset.parse(expr)[0]
2671 tree = revset.parse(expr)[0]
2668 ui.note(revset.prettyformat(tree), "\n")
2672 ui.note(revset.prettyformat(tree), "\n")
2669 newtree = revset.findaliases(ui, tree)
2673 newtree = revset.findaliases(ui, tree)
2670 if newtree != tree:
2674 if newtree != tree:
2671 ui.note(revset.prettyformat(newtree), "\n")
2675 ui.note(revset.prettyformat(newtree), "\n")
2672 if opts["optimize"]:
2676 if opts["optimize"]:
2673 weight, optimizedtree = revset.optimize(newtree, True)
2677 weight, optimizedtree = revset.optimize(newtree, True)
2674 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2678 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2675 func = revset.match(ui, expr)
2679 func = revset.match(ui, expr)
2676 for c in func(repo, revset.spanset(repo)):
2680 for c in func(repo, revset.spanset(repo)):
2677 ui.write("%s\n" % c)
2681 ui.write("%s\n" % c)
2678
2682
2679 @command('debugsetparents', [], _('REV1 [REV2]'))
2683 @command('debugsetparents', [], _('REV1 [REV2]'))
2680 def debugsetparents(ui, repo, rev1, rev2=None):
2684 def debugsetparents(ui, repo, rev1, rev2=None):
2681 """manually set the parents of the current working directory
2685 """manually set the parents of the current working directory
2682
2686
2683 This is useful for writing repository conversion tools, but should
2687 This is useful for writing repository conversion tools, but should
2684 be used with care.
2688 be used with care.
2685
2689
2686 Returns 0 on success.
2690 Returns 0 on success.
2687 """
2691 """
2688
2692
2689 r1 = scmutil.revsingle(repo, rev1).node()
2693 r1 = scmutil.revsingle(repo, rev1).node()
2690 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2694 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2691
2695
2692 wlock = repo.wlock()
2696 wlock = repo.wlock()
2693 try:
2697 try:
2694 repo.setparents(r1, r2)
2698 repo.setparents(r1, r2)
2695 finally:
2699 finally:
2696 wlock.release()
2700 wlock.release()
2697
2701
2698 @command('debugdirstate|debugstate',
2702 @command('debugdirstate|debugstate',
2699 [('', 'nodates', None, _('do not display the saved mtime')),
2703 [('', 'nodates', None, _('do not display the saved mtime')),
2700 ('', 'datesort', None, _('sort by saved mtime'))],
2704 ('', 'datesort', None, _('sort by saved mtime'))],
2701 _('[OPTION]...'))
2705 _('[OPTION]...'))
2702 def debugstate(ui, repo, nodates=None, datesort=None):
2706 def debugstate(ui, repo, nodates=None, datesort=None):
2703 """show the contents of the current dirstate"""
2707 """show the contents of the current dirstate"""
2704 timestr = ""
2708 timestr = ""
2705 showdate = not nodates
2709 showdate = not nodates
2706 if datesort:
2710 if datesort:
2707 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2711 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2708 else:
2712 else:
2709 keyfunc = None # sort by filename
2713 keyfunc = None # sort by filename
2710 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2714 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2711 if showdate:
2715 if showdate:
2712 if ent[3] == -1:
2716 if ent[3] == -1:
2713 # Pad or slice to locale representation
2717 # Pad or slice to locale representation
2714 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2718 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2715 time.localtime(0)))
2719 time.localtime(0)))
2716 timestr = 'unset'
2720 timestr = 'unset'
2717 timestr = (timestr[:locale_len] +
2721 timestr = (timestr[:locale_len] +
2718 ' ' * (locale_len - len(timestr)))
2722 ' ' * (locale_len - len(timestr)))
2719 else:
2723 else:
2720 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2724 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2721 time.localtime(ent[3]))
2725 time.localtime(ent[3]))
2722 if ent[1] & 020000:
2726 if ent[1] & 020000:
2723 mode = 'lnk'
2727 mode = 'lnk'
2724 else:
2728 else:
2725 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2729 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2726 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2730 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2727 for f in repo.dirstate.copies():
2731 for f in repo.dirstate.copies():
2728 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2732 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2729
2733
2730 @command('debugsub',
2734 @command('debugsub',
2731 [('r', 'rev', '',
2735 [('r', 'rev', '',
2732 _('revision to check'), _('REV'))],
2736 _('revision to check'), _('REV'))],
2733 _('[-r REV] [REV]'))
2737 _('[-r REV] [REV]'))
2734 def debugsub(ui, repo, rev=None):
2738 def debugsub(ui, repo, rev=None):
2735 ctx = scmutil.revsingle(repo, rev, None)
2739 ctx = scmutil.revsingle(repo, rev, None)
2736 for k, v in sorted(ctx.substate.items()):
2740 for k, v in sorted(ctx.substate.items()):
2737 ui.write(('path %s\n') % k)
2741 ui.write(('path %s\n') % k)
2738 ui.write((' source %s\n') % v[0])
2742 ui.write((' source %s\n') % v[0])
2739 ui.write((' revision %s\n') % v[1])
2743 ui.write((' revision %s\n') % v[1])
2740
2744
2741 @command('debugsuccessorssets',
2745 @command('debugsuccessorssets',
2742 [],
2746 [],
2743 _('[REV]'))
2747 _('[REV]'))
2744 def debugsuccessorssets(ui, repo, *revs):
2748 def debugsuccessorssets(ui, repo, *revs):
2745 """show set of successors for revision
2749 """show set of successors for revision
2746
2750
2747 A successors set of changeset A is a consistent group of revisions that
2751 A successors set of changeset A is a consistent group of revisions that
2748 succeed A. It contains non-obsolete changesets only.
2752 succeed A. It contains non-obsolete changesets only.
2749
2753
2750 In most cases a changeset A has a single successors set containing a single
2754 In most cases a changeset A has a single successors set containing a single
2751 successor (changeset A replaced by A').
2755 successor (changeset A replaced by A').
2752
2756
2753 A changeset that is made obsolete with no successors are called "pruned".
2757 A changeset that is made obsolete with no successors are called "pruned".
2754 Such changesets have no successors sets at all.
2758 Such changesets have no successors sets at all.
2755
2759
2756 A changeset that has been "split" will have a successors set containing
2760 A changeset that has been "split" will have a successors set containing
2757 more than one successor.
2761 more than one successor.
2758
2762
2759 A changeset that has been rewritten in multiple different ways is called
2763 A changeset that has been rewritten in multiple different ways is called
2760 "divergent". Such changesets have multiple successor sets (each of which
2764 "divergent". Such changesets have multiple successor sets (each of which
2761 may also be split, i.e. have multiple successors).
2765 may also be split, i.e. have multiple successors).
2762
2766
2763 Results are displayed as follows::
2767 Results are displayed as follows::
2764
2768
2765 <rev1>
2769 <rev1>
2766 <successors-1A>
2770 <successors-1A>
2767 <rev2>
2771 <rev2>
2768 <successors-2A>
2772 <successors-2A>
2769 <successors-2B1> <successors-2B2> <successors-2B3>
2773 <successors-2B1> <successors-2B2> <successors-2B3>
2770
2774
2771 Here rev2 has two possible (i.e. divergent) successors sets. The first
2775 Here rev2 has two possible (i.e. divergent) successors sets. The first
2772 holds one element, whereas the second holds three (i.e. the changeset has
2776 holds one element, whereas the second holds three (i.e. the changeset has
2773 been split).
2777 been split).
2774 """
2778 """
2775 # passed to successorssets caching computation from one call to another
2779 # passed to successorssets caching computation from one call to another
2776 cache = {}
2780 cache = {}
2777 ctx2str = str
2781 ctx2str = str
2778 node2str = short
2782 node2str = short
2779 if ui.debug():
2783 if ui.debug():
2780 def ctx2str(ctx):
2784 def ctx2str(ctx):
2781 return ctx.hex()
2785 return ctx.hex()
2782 node2str = hex
2786 node2str = hex
2783 for rev in scmutil.revrange(repo, revs):
2787 for rev in scmutil.revrange(repo, revs):
2784 ctx = repo[rev]
2788 ctx = repo[rev]
2785 ui.write('%s\n'% ctx2str(ctx))
2789 ui.write('%s\n'% ctx2str(ctx))
2786 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2790 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2787 if succsset:
2791 if succsset:
2788 ui.write(' ')
2792 ui.write(' ')
2789 ui.write(node2str(succsset[0]))
2793 ui.write(node2str(succsset[0]))
2790 for node in succsset[1:]:
2794 for node in succsset[1:]:
2791 ui.write(' ')
2795 ui.write(' ')
2792 ui.write(node2str(node))
2796 ui.write(node2str(node))
2793 ui.write('\n')
2797 ui.write('\n')
2794
2798
2795 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2799 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2796 def debugwalk(ui, repo, *pats, **opts):
2800 def debugwalk(ui, repo, *pats, **opts):
2797 """show how files match on given patterns"""
2801 """show how files match on given patterns"""
2798 m = scmutil.match(repo[None], pats, opts)
2802 m = scmutil.match(repo[None], pats, opts)
2799 items = list(repo.walk(m))
2803 items = list(repo.walk(m))
2800 if not items:
2804 if not items:
2801 return
2805 return
2802 f = lambda fn: fn
2806 f = lambda fn: fn
2803 if ui.configbool('ui', 'slash') and os.sep != '/':
2807 if ui.configbool('ui', 'slash') and os.sep != '/':
2804 f = lambda fn: util.normpath(fn)
2808 f = lambda fn: util.normpath(fn)
2805 fmt = 'f %%-%ds %%-%ds %%s' % (
2809 fmt = 'f %%-%ds %%-%ds %%s' % (
2806 max([len(abs) for abs in items]),
2810 max([len(abs) for abs in items]),
2807 max([len(m.rel(abs)) for abs in items]))
2811 max([len(m.rel(abs)) for abs in items]))
2808 for abs in items:
2812 for abs in items:
2809 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2813 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2810 ui.write("%s\n" % line.rstrip())
2814 ui.write("%s\n" % line.rstrip())
2811
2815
2812 @command('debugwireargs',
2816 @command('debugwireargs',
2813 [('', 'three', '', 'three'),
2817 [('', 'three', '', 'three'),
2814 ('', 'four', '', 'four'),
2818 ('', 'four', '', 'four'),
2815 ('', 'five', '', 'five'),
2819 ('', 'five', '', 'five'),
2816 ] + remoteopts,
2820 ] + remoteopts,
2817 _('REPO [OPTIONS]... [ONE [TWO]]'))
2821 _('REPO [OPTIONS]... [ONE [TWO]]'))
2818 def debugwireargs(ui, repopath, *vals, **opts):
2822 def debugwireargs(ui, repopath, *vals, **opts):
2819 repo = hg.peer(ui, opts, repopath)
2823 repo = hg.peer(ui, opts, repopath)
2820 for opt in remoteopts:
2824 for opt in remoteopts:
2821 del opts[opt[1]]
2825 del opts[opt[1]]
2822 args = {}
2826 args = {}
2823 for k, v in opts.iteritems():
2827 for k, v in opts.iteritems():
2824 if v:
2828 if v:
2825 args[k] = v
2829 args[k] = v
2826 # run twice to check that we don't mess up the stream for the next command
2830 # run twice to check that we don't mess up the stream for the next command
2827 res1 = repo.debugwireargs(*vals, **args)
2831 res1 = repo.debugwireargs(*vals, **args)
2828 res2 = repo.debugwireargs(*vals, **args)
2832 res2 = repo.debugwireargs(*vals, **args)
2829 ui.write("%s\n" % res1)
2833 ui.write("%s\n" % res1)
2830 if res1 != res2:
2834 if res1 != res2:
2831 ui.warn("%s\n" % res2)
2835 ui.warn("%s\n" % res2)
2832
2836
2833 @command('^diff',
2837 @command('^diff',
2834 [('r', 'rev', [], _('revision'), _('REV')),
2838 [('r', 'rev', [], _('revision'), _('REV')),
2835 ('c', 'change', '', _('change made by revision'), _('REV'))
2839 ('c', 'change', '', _('change made by revision'), _('REV'))
2836 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2840 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2837 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2841 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2838 def diff(ui, repo, *pats, **opts):
2842 def diff(ui, repo, *pats, **opts):
2839 """diff repository (or selected files)
2843 """diff repository (or selected files)
2840
2844
2841 Show differences between revisions for the specified files.
2845 Show differences between revisions for the specified files.
2842
2846
2843 Differences between files are shown using the unified diff format.
2847 Differences between files are shown using the unified diff format.
2844
2848
2845 .. note::
2849 .. note::
2846
2850
2847 diff may generate unexpected results for merges, as it will
2851 diff may generate unexpected results for merges, as it will
2848 default to comparing against the working directory's first
2852 default to comparing against the working directory's first
2849 parent changeset if no revisions are specified.
2853 parent changeset if no revisions are specified.
2850
2854
2851 When two revision arguments are given, then changes are shown
2855 When two revision arguments are given, then changes are shown
2852 between those revisions. If only one revision is specified then
2856 between those revisions. If only one revision is specified then
2853 that revision is compared to the working directory, and, when no
2857 that revision is compared to the working directory, and, when no
2854 revisions are specified, the working directory files are compared
2858 revisions are specified, the working directory files are compared
2855 to its parent.
2859 to its parent.
2856
2860
2857 Alternatively you can specify -c/--change with a revision to see
2861 Alternatively you can specify -c/--change with a revision to see
2858 the changes in that changeset relative to its first parent.
2862 the changes in that changeset relative to its first parent.
2859
2863
2860 Without the -a/--text option, diff will avoid generating diffs of
2864 Without the -a/--text option, diff will avoid generating diffs of
2861 files it detects as binary. With -a, diff will generate a diff
2865 files it detects as binary. With -a, diff will generate a diff
2862 anyway, probably with undesirable results.
2866 anyway, probably with undesirable results.
2863
2867
2864 Use the -g/--git option to generate diffs in the git extended diff
2868 Use the -g/--git option to generate diffs in the git extended diff
2865 format. For more information, read :hg:`help diffs`.
2869 format. For more information, read :hg:`help diffs`.
2866
2870
2867 .. container:: verbose
2871 .. container:: verbose
2868
2872
2869 Examples:
2873 Examples:
2870
2874
2871 - compare a file in the current working directory to its parent::
2875 - compare a file in the current working directory to its parent::
2872
2876
2873 hg diff foo.c
2877 hg diff foo.c
2874
2878
2875 - compare two historical versions of a directory, with rename info::
2879 - compare two historical versions of a directory, with rename info::
2876
2880
2877 hg diff --git -r 1.0:1.2 lib/
2881 hg diff --git -r 1.0:1.2 lib/
2878
2882
2879 - get change stats relative to the last change on some date::
2883 - get change stats relative to the last change on some date::
2880
2884
2881 hg diff --stat -r "date('may 2')"
2885 hg diff --stat -r "date('may 2')"
2882
2886
2883 - diff all newly-added files that contain a keyword::
2887 - diff all newly-added files that contain a keyword::
2884
2888
2885 hg diff "set:added() and grep(GNU)"
2889 hg diff "set:added() and grep(GNU)"
2886
2890
2887 - compare a revision and its parents::
2891 - compare a revision and its parents::
2888
2892
2889 hg diff -c 9353 # compare against first parent
2893 hg diff -c 9353 # compare against first parent
2890 hg diff -r 9353^:9353 # same using revset syntax
2894 hg diff -r 9353^:9353 # same using revset syntax
2891 hg diff -r 9353^2:9353 # compare against the second parent
2895 hg diff -r 9353^2:9353 # compare against the second parent
2892
2896
2893 Returns 0 on success.
2897 Returns 0 on success.
2894 """
2898 """
2895
2899
2896 revs = opts.get('rev')
2900 revs = opts.get('rev')
2897 change = opts.get('change')
2901 change = opts.get('change')
2898 stat = opts.get('stat')
2902 stat = opts.get('stat')
2899 reverse = opts.get('reverse')
2903 reverse = opts.get('reverse')
2900
2904
2901 if revs and change:
2905 if revs and change:
2902 msg = _('cannot specify --rev and --change at the same time')
2906 msg = _('cannot specify --rev and --change at the same time')
2903 raise util.Abort(msg)
2907 raise util.Abort(msg)
2904 elif change:
2908 elif change:
2905 node2 = scmutil.revsingle(repo, change, None).node()
2909 node2 = scmutil.revsingle(repo, change, None).node()
2906 node1 = repo[node2].p1().node()
2910 node1 = repo[node2].p1().node()
2907 else:
2911 else:
2908 node1, node2 = scmutil.revpair(repo, revs)
2912 node1, node2 = scmutil.revpair(repo, revs)
2909
2913
2910 if reverse:
2914 if reverse:
2911 node1, node2 = node2, node1
2915 node1, node2 = node2, node1
2912
2916
2913 diffopts = patch.diffopts(ui, opts)
2917 diffopts = patch.diffopts(ui, opts)
2914 m = scmutil.match(repo[node2], pats, opts)
2918 m = scmutil.match(repo[node2], pats, opts)
2915 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2919 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2916 listsubrepos=opts.get('subrepos'))
2920 listsubrepos=opts.get('subrepos'))
2917
2921
2918 @command('^export',
2922 @command('^export',
2919 [('o', 'output', '',
2923 [('o', 'output', '',
2920 _('print output to file with formatted name'), _('FORMAT')),
2924 _('print output to file with formatted name'), _('FORMAT')),
2921 ('', 'switch-parent', None, _('diff against the second parent')),
2925 ('', 'switch-parent', None, _('diff against the second parent')),
2922 ('r', 'rev', [], _('revisions to export'), _('REV')),
2926 ('r', 'rev', [], _('revisions to export'), _('REV')),
2923 ] + diffopts,
2927 ] + diffopts,
2924 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2928 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2925 def export(ui, repo, *changesets, **opts):
2929 def export(ui, repo, *changesets, **opts):
2926 """dump the header and diffs for one or more changesets
2930 """dump the header and diffs for one or more changesets
2927
2931
2928 Print the changeset header and diffs for one or more revisions.
2932 Print the changeset header and diffs for one or more revisions.
2929 If no revision is given, the parent of the working directory is used.
2933 If no revision is given, the parent of the working directory is used.
2930
2934
2931 The information shown in the changeset header is: author, date,
2935 The information shown in the changeset header is: author, date,
2932 branch name (if non-default), changeset hash, parent(s) and commit
2936 branch name (if non-default), changeset hash, parent(s) and commit
2933 comment.
2937 comment.
2934
2938
2935 .. note::
2939 .. note::
2936
2940
2937 export may generate unexpected diff output for merge
2941 export may generate unexpected diff output for merge
2938 changesets, as it will compare the merge changeset against its
2942 changesets, as it will compare the merge changeset against its
2939 first parent only.
2943 first parent only.
2940
2944
2941 Output may be to a file, in which case the name of the file is
2945 Output may be to a file, in which case the name of the file is
2942 given using a format string. The formatting rules are as follows:
2946 given using a format string. The formatting rules are as follows:
2943
2947
2944 :``%%``: literal "%" character
2948 :``%%``: literal "%" character
2945 :``%H``: changeset hash (40 hexadecimal digits)
2949 :``%H``: changeset hash (40 hexadecimal digits)
2946 :``%N``: number of patches being generated
2950 :``%N``: number of patches being generated
2947 :``%R``: changeset revision number
2951 :``%R``: changeset revision number
2948 :``%b``: basename of the exporting repository
2952 :``%b``: basename of the exporting repository
2949 :``%h``: short-form changeset hash (12 hexadecimal digits)
2953 :``%h``: short-form changeset hash (12 hexadecimal digits)
2950 :``%m``: first line of the commit message (only alphanumeric characters)
2954 :``%m``: first line of the commit message (only alphanumeric characters)
2951 :``%n``: zero-padded sequence number, starting at 1
2955 :``%n``: zero-padded sequence number, starting at 1
2952 :``%r``: zero-padded changeset revision number
2956 :``%r``: zero-padded changeset revision number
2953
2957
2954 Without the -a/--text option, export will avoid generating diffs
2958 Without the -a/--text option, export will avoid generating diffs
2955 of files it detects as binary. With -a, export will generate a
2959 of files it detects as binary. With -a, export will generate a
2956 diff anyway, probably with undesirable results.
2960 diff anyway, probably with undesirable results.
2957
2961
2958 Use the -g/--git option to generate diffs in the git extended diff
2962 Use the -g/--git option to generate diffs in the git extended diff
2959 format. See :hg:`help diffs` for more information.
2963 format. See :hg:`help diffs` for more information.
2960
2964
2961 With the --switch-parent option, the diff will be against the
2965 With the --switch-parent option, the diff will be against the
2962 second parent. It can be useful to review a merge.
2966 second parent. It can be useful to review a merge.
2963
2967
2964 .. container:: verbose
2968 .. container:: verbose
2965
2969
2966 Examples:
2970 Examples:
2967
2971
2968 - use export and import to transplant a bugfix to the current
2972 - use export and import to transplant a bugfix to the current
2969 branch::
2973 branch::
2970
2974
2971 hg export -r 9353 | hg import -
2975 hg export -r 9353 | hg import -
2972
2976
2973 - export all the changesets between two revisions to a file with
2977 - export all the changesets between two revisions to a file with
2974 rename information::
2978 rename information::
2975
2979
2976 hg export --git -r 123:150 > changes.txt
2980 hg export --git -r 123:150 > changes.txt
2977
2981
2978 - split outgoing changes into a series of patches with
2982 - split outgoing changes into a series of patches with
2979 descriptive names::
2983 descriptive names::
2980
2984
2981 hg export -r "outgoing()" -o "%n-%m.patch"
2985 hg export -r "outgoing()" -o "%n-%m.patch"
2982
2986
2983 Returns 0 on success.
2987 Returns 0 on success.
2984 """
2988 """
2985 changesets += tuple(opts.get('rev', []))
2989 changesets += tuple(opts.get('rev', []))
2986 if not changesets:
2990 if not changesets:
2987 changesets = ['.']
2991 changesets = ['.']
2988 revs = scmutil.revrange(repo, changesets)
2992 revs = scmutil.revrange(repo, changesets)
2989 if not revs:
2993 if not revs:
2990 raise util.Abort(_("export requires at least one changeset"))
2994 raise util.Abort(_("export requires at least one changeset"))
2991 if len(revs) > 1:
2995 if len(revs) > 1:
2992 ui.note(_('exporting patches:\n'))
2996 ui.note(_('exporting patches:\n'))
2993 else:
2997 else:
2994 ui.note(_('exporting patch:\n'))
2998 ui.note(_('exporting patch:\n'))
2995 cmdutil.export(repo, revs, template=opts.get('output'),
2999 cmdutil.export(repo, revs, template=opts.get('output'),
2996 switch_parent=opts.get('switch_parent'),
3000 switch_parent=opts.get('switch_parent'),
2997 opts=patch.diffopts(ui, opts))
3001 opts=patch.diffopts(ui, opts))
2998
3002
2999 @command('^forget', walkopts, _('[OPTION]... FILE...'))
3003 @command('^forget', walkopts, _('[OPTION]... FILE...'))
3000 def forget(ui, repo, *pats, **opts):
3004 def forget(ui, repo, *pats, **opts):
3001 """forget the specified files on the next commit
3005 """forget the specified files on the next commit
3002
3006
3003 Mark the specified files so they will no longer be tracked
3007 Mark the specified files so they will no longer be tracked
3004 after the next commit.
3008 after the next commit.
3005
3009
3006 This only removes files from the current branch, not from the
3010 This only removes files from the current branch, not from the
3007 entire project history, and it does not delete them from the
3011 entire project history, and it does not delete them from the
3008 working directory.
3012 working directory.
3009
3013
3010 To undo a forget before the next commit, see :hg:`add`.
3014 To undo a forget before the next commit, see :hg:`add`.
3011
3015
3012 .. container:: verbose
3016 .. container:: verbose
3013
3017
3014 Examples:
3018 Examples:
3015
3019
3016 - forget newly-added binary files::
3020 - forget newly-added binary files::
3017
3021
3018 hg forget "set:added() and binary()"
3022 hg forget "set:added() and binary()"
3019
3023
3020 - forget files that would be excluded by .hgignore::
3024 - forget files that would be excluded by .hgignore::
3021
3025
3022 hg forget "set:hgignore()"
3026 hg forget "set:hgignore()"
3023
3027
3024 Returns 0 on success.
3028 Returns 0 on success.
3025 """
3029 """
3026
3030
3027 if not pats:
3031 if not pats:
3028 raise util.Abort(_('no files specified'))
3032 raise util.Abort(_('no files specified'))
3029
3033
3030 m = scmutil.match(repo[None], pats, opts)
3034 m = scmutil.match(repo[None], pats, opts)
3031 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3035 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3032 return rejected and 1 or 0
3036 return rejected and 1 or 0
3033
3037
3034 @command(
3038 @command(
3035 'graft',
3039 'graft',
3036 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3040 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3037 ('c', 'continue', False, _('resume interrupted graft')),
3041 ('c', 'continue', False, _('resume interrupted graft')),
3038 ('e', 'edit', False, _('invoke editor on commit messages')),
3042 ('e', 'edit', False, _('invoke editor on commit messages')),
3039 ('', 'log', None, _('append graft info to log message')),
3043 ('', 'log', None, _('append graft info to log message')),
3040 ('D', 'currentdate', False,
3044 ('D', 'currentdate', False,
3041 _('record the current date as commit date')),
3045 _('record the current date as commit date')),
3042 ('U', 'currentuser', False,
3046 ('U', 'currentuser', False,
3043 _('record the current user as committer'), _('DATE'))]
3047 _('record the current user as committer'), _('DATE'))]
3044 + commitopts2 + mergetoolopts + dryrunopts,
3048 + commitopts2 + mergetoolopts + dryrunopts,
3045 _('[OPTION]... [-r] REV...'))
3049 _('[OPTION]... [-r] REV...'))
3046 def graft(ui, repo, *revs, **opts):
3050 def graft(ui, repo, *revs, **opts):
3047 '''copy changes from other branches onto the current branch
3051 '''copy changes from other branches onto the current branch
3048
3052
3049 This command uses Mercurial's merge logic to copy individual
3053 This command uses Mercurial's merge logic to copy individual
3050 changes from other branches without merging branches in the
3054 changes from other branches without merging branches in the
3051 history graph. This is sometimes known as 'backporting' or
3055 history graph. This is sometimes known as 'backporting' or
3052 'cherry-picking'. By default, graft will copy user, date, and
3056 'cherry-picking'. By default, graft will copy user, date, and
3053 description from the source changesets.
3057 description from the source changesets.
3054
3058
3055 Changesets that are ancestors of the current revision, that have
3059 Changesets that are ancestors of the current revision, that have
3056 already been grafted, or that are merges will be skipped.
3060 already been grafted, or that are merges will be skipped.
3057
3061
3058 If --log is specified, log messages will have a comment appended
3062 If --log is specified, log messages will have a comment appended
3059 of the form::
3063 of the form::
3060
3064
3061 (grafted from CHANGESETHASH)
3065 (grafted from CHANGESETHASH)
3062
3066
3063 If a graft merge results in conflicts, the graft process is
3067 If a graft merge results in conflicts, the graft process is
3064 interrupted so that the current merge can be manually resolved.
3068 interrupted so that the current merge can be manually resolved.
3065 Once all conflicts are addressed, the graft process can be
3069 Once all conflicts are addressed, the graft process can be
3066 continued with the -c/--continue option.
3070 continued with the -c/--continue option.
3067
3071
3068 .. note::
3072 .. note::
3069
3073
3070 The -c/--continue option does not reapply earlier options.
3074 The -c/--continue option does not reapply earlier options.
3071
3075
3072 .. container:: verbose
3076 .. container:: verbose
3073
3077
3074 Examples:
3078 Examples:
3075
3079
3076 - copy a single change to the stable branch and edit its description::
3080 - copy a single change to the stable branch and edit its description::
3077
3081
3078 hg update stable
3082 hg update stable
3079 hg graft --edit 9393
3083 hg graft --edit 9393
3080
3084
3081 - graft a range of changesets with one exception, updating dates::
3085 - graft a range of changesets with one exception, updating dates::
3082
3086
3083 hg graft -D "2085::2093 and not 2091"
3087 hg graft -D "2085::2093 and not 2091"
3084
3088
3085 - continue a graft after resolving conflicts::
3089 - continue a graft after resolving conflicts::
3086
3090
3087 hg graft -c
3091 hg graft -c
3088
3092
3089 - show the source of a grafted changeset::
3093 - show the source of a grafted changeset::
3090
3094
3091 hg log --debug -r .
3095 hg log --debug -r .
3092
3096
3093 Returns 0 on successful completion.
3097 Returns 0 on successful completion.
3094 '''
3098 '''
3095
3099
3096 revs = list(revs)
3100 revs = list(revs)
3097 revs.extend(opts['rev'])
3101 revs.extend(opts['rev'])
3098
3102
3099 if not opts.get('user') and opts.get('currentuser'):
3103 if not opts.get('user') and opts.get('currentuser'):
3100 opts['user'] = ui.username()
3104 opts['user'] = ui.username()
3101 if not opts.get('date') and opts.get('currentdate'):
3105 if not opts.get('date') and opts.get('currentdate'):
3102 opts['date'] = "%d %d" % util.makedate()
3106 opts['date'] = "%d %d" % util.makedate()
3103
3107
3104 editor = None
3108 editor = None
3105 if opts.get('edit'):
3109 if opts.get('edit'):
3106 editor = cmdutil.commitforceeditor
3110 editor = cmdutil.commitforceeditor
3107
3111
3108 cont = False
3112 cont = False
3109 if opts['continue']:
3113 if opts['continue']:
3110 cont = True
3114 cont = True
3111 if revs:
3115 if revs:
3112 raise util.Abort(_("can't specify --continue and revisions"))
3116 raise util.Abort(_("can't specify --continue and revisions"))
3113 # read in unfinished revisions
3117 # read in unfinished revisions
3114 try:
3118 try:
3115 nodes = repo.opener.read('graftstate').splitlines()
3119 nodes = repo.opener.read('graftstate').splitlines()
3116 revs = [repo[node].rev() for node in nodes]
3120 revs = [repo[node].rev() for node in nodes]
3117 except IOError, inst:
3121 except IOError, inst:
3118 if inst.errno != errno.ENOENT:
3122 if inst.errno != errno.ENOENT:
3119 raise
3123 raise
3120 raise util.Abort(_("no graft state found, can't continue"))
3124 raise util.Abort(_("no graft state found, can't continue"))
3121 else:
3125 else:
3122 cmdutil.checkunfinished(repo)
3126 cmdutil.checkunfinished(repo)
3123 cmdutil.bailifchanged(repo)
3127 cmdutil.bailifchanged(repo)
3124 if not revs:
3128 if not revs:
3125 raise util.Abort(_('no revisions specified'))
3129 raise util.Abort(_('no revisions specified'))
3126 revs = scmutil.revrange(repo, revs)
3130 revs = scmutil.revrange(repo, revs)
3127
3131
3128 # check for merges
3132 # check for merges
3129 for rev in repo.revs('%ld and merge()', revs):
3133 for rev in repo.revs('%ld and merge()', revs):
3130 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3134 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3131 revs.remove(rev)
3135 revs.remove(rev)
3132 if not revs:
3136 if not revs:
3133 return -1
3137 return -1
3134
3138
3135 # check for ancestors of dest branch
3139 # check for ancestors of dest branch
3136 crev = repo['.'].rev()
3140 crev = repo['.'].rev()
3137 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3141 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3138 # don't mutate while iterating, create a copy
3142 # don't mutate while iterating, create a copy
3139 for rev in list(revs):
3143 for rev in list(revs):
3140 if rev in ancestors:
3144 if rev in ancestors:
3141 ui.warn(_('skipping ancestor revision %s\n') % rev)
3145 ui.warn(_('skipping ancestor revision %s\n') % rev)
3142 revs.remove(rev)
3146 revs.remove(rev)
3143 if not revs:
3147 if not revs:
3144 return -1
3148 return -1
3145
3149
3146 # analyze revs for earlier grafts
3150 # analyze revs for earlier grafts
3147 ids = {}
3151 ids = {}
3148 for ctx in repo.set("%ld", revs):
3152 for ctx in repo.set("%ld", revs):
3149 ids[ctx.hex()] = ctx.rev()
3153 ids[ctx.hex()] = ctx.rev()
3150 n = ctx.extra().get('source')
3154 n = ctx.extra().get('source')
3151 if n:
3155 if n:
3152 ids[n] = ctx.rev()
3156 ids[n] = ctx.rev()
3153
3157
3154 # check ancestors for earlier grafts
3158 # check ancestors for earlier grafts
3155 ui.debug('scanning for duplicate grafts\n')
3159 ui.debug('scanning for duplicate grafts\n')
3156
3160
3157 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3161 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3158 ctx = repo[rev]
3162 ctx = repo[rev]
3159 n = ctx.extra().get('source')
3163 n = ctx.extra().get('source')
3160 if n in ids:
3164 if n in ids:
3161 r = repo[n].rev()
3165 r = repo[n].rev()
3162 if r in revs:
3166 if r in revs:
3163 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3167 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3164 % (r, rev))
3168 % (r, rev))
3165 revs.remove(r)
3169 revs.remove(r)
3166 elif ids[n] in revs:
3170 elif ids[n] in revs:
3167 ui.warn(_('skipping already grafted revision %s '
3171 ui.warn(_('skipping already grafted revision %s '
3168 '(%s also has origin %d)\n') % (ids[n], rev, r))
3172 '(%s also has origin %d)\n') % (ids[n], rev, r))
3169 revs.remove(ids[n])
3173 revs.remove(ids[n])
3170 elif ctx.hex() in ids:
3174 elif ctx.hex() in ids:
3171 r = ids[ctx.hex()]
3175 r = ids[ctx.hex()]
3172 ui.warn(_('skipping already grafted revision %s '
3176 ui.warn(_('skipping already grafted revision %s '
3173 '(was grafted from %d)\n') % (r, rev))
3177 '(was grafted from %d)\n') % (r, rev))
3174 revs.remove(r)
3178 revs.remove(r)
3175 if not revs:
3179 if not revs:
3176 return -1
3180 return -1
3177
3181
3178 wlock = repo.wlock()
3182 wlock = repo.wlock()
3179 try:
3183 try:
3180 current = repo['.']
3184 current = repo['.']
3181 for pos, ctx in enumerate(repo.set("%ld", revs)):
3185 for pos, ctx in enumerate(repo.set("%ld", revs)):
3182
3186
3183 ui.status(_('grafting revision %s\n') % ctx.rev())
3187 ui.status(_('grafting revision %s\n') % ctx.rev())
3184 if opts.get('dry_run'):
3188 if opts.get('dry_run'):
3185 continue
3189 continue
3186
3190
3187 source = ctx.extra().get('source')
3191 source = ctx.extra().get('source')
3188 if not source:
3192 if not source:
3189 source = ctx.hex()
3193 source = ctx.hex()
3190 extra = {'source': source}
3194 extra = {'source': source}
3191 user = ctx.user()
3195 user = ctx.user()
3192 if opts.get('user'):
3196 if opts.get('user'):
3193 user = opts['user']
3197 user = opts['user']
3194 date = ctx.date()
3198 date = ctx.date()
3195 if opts.get('date'):
3199 if opts.get('date'):
3196 date = opts['date']
3200 date = opts['date']
3197 message = ctx.description()
3201 message = ctx.description()
3198 if opts.get('log'):
3202 if opts.get('log'):
3199 message += '\n(grafted from %s)' % ctx.hex()
3203 message += '\n(grafted from %s)' % ctx.hex()
3200
3204
3201 # we don't merge the first commit when continuing
3205 # we don't merge the first commit when continuing
3202 if not cont:
3206 if not cont:
3203 # perform the graft merge with p1(rev) as 'ancestor'
3207 # perform the graft merge with p1(rev) as 'ancestor'
3204 try:
3208 try:
3205 # ui.forcemerge is an internal variable, do not document
3209 # ui.forcemerge is an internal variable, do not document
3206 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3210 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3207 'graft')
3211 'graft')
3208 stats = mergemod.update(repo, ctx.node(), True, True, False,
3212 stats = mergemod.update(repo, ctx.node(), True, True, False,
3209 ctx.p1().node())
3213 ctx.p1().node())
3210 finally:
3214 finally:
3211 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3215 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3212 # report any conflicts
3216 # report any conflicts
3213 if stats and stats[3] > 0:
3217 if stats and stats[3] > 0:
3214 # write out state for --continue
3218 # write out state for --continue
3215 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3219 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3216 repo.opener.write('graftstate', ''.join(nodelines))
3220 repo.opener.write('graftstate', ''.join(nodelines))
3217 raise util.Abort(
3221 raise util.Abort(
3218 _("unresolved conflicts, can't continue"),
3222 _("unresolved conflicts, can't continue"),
3219 hint=_('use hg resolve and hg graft --continue'))
3223 hint=_('use hg resolve and hg graft --continue'))
3220 else:
3224 else:
3221 cont = False
3225 cont = False
3222
3226
3223 # drop the second merge parent
3227 # drop the second merge parent
3224 repo.setparents(current.node(), nullid)
3228 repo.setparents(current.node(), nullid)
3225 repo.dirstate.write()
3229 repo.dirstate.write()
3226 # fix up dirstate for copies and renames
3230 # fix up dirstate for copies and renames
3227 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3231 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3228
3232
3229 # commit
3233 # commit
3230 node = repo.commit(text=message, user=user,
3234 node = repo.commit(text=message, user=user,
3231 date=date, extra=extra, editor=editor)
3235 date=date, extra=extra, editor=editor)
3232 if node is None:
3236 if node is None:
3233 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3237 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3234 else:
3238 else:
3235 current = repo[node]
3239 current = repo[node]
3236 finally:
3240 finally:
3237 wlock.release()
3241 wlock.release()
3238
3242
3239 # remove state when we complete successfully
3243 # remove state when we complete successfully
3240 if not opts.get('dry_run'):
3244 if not opts.get('dry_run'):
3241 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3245 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3242
3246
3243 return 0
3247 return 0
3244
3248
3245 @command('grep',
3249 @command('grep',
3246 [('0', 'print0', None, _('end fields with NUL')),
3250 [('0', 'print0', None, _('end fields with NUL')),
3247 ('', 'all', None, _('print all revisions that match')),
3251 ('', 'all', None, _('print all revisions that match')),
3248 ('a', 'text', None, _('treat all files as text')),
3252 ('a', 'text', None, _('treat all files as text')),
3249 ('f', 'follow', None,
3253 ('f', 'follow', None,
3250 _('follow changeset history,'
3254 _('follow changeset history,'
3251 ' or file history across copies and renames')),
3255 ' or file history across copies and renames')),
3252 ('i', 'ignore-case', None, _('ignore case when matching')),
3256 ('i', 'ignore-case', None, _('ignore case when matching')),
3253 ('l', 'files-with-matches', None,
3257 ('l', 'files-with-matches', None,
3254 _('print only filenames and revisions that match')),
3258 _('print only filenames and revisions that match')),
3255 ('n', 'line-number', None, _('print matching line numbers')),
3259 ('n', 'line-number', None, _('print matching line numbers')),
3256 ('r', 'rev', [],
3260 ('r', 'rev', [],
3257 _('only search files changed within revision range'), _('REV')),
3261 _('only search files changed within revision range'), _('REV')),
3258 ('u', 'user', None, _('list the author (long with -v)')),
3262 ('u', 'user', None, _('list the author (long with -v)')),
3259 ('d', 'date', None, _('list the date (short with -q)')),
3263 ('d', 'date', None, _('list the date (short with -q)')),
3260 ] + walkopts,
3264 ] + walkopts,
3261 _('[OPTION]... PATTERN [FILE]...'))
3265 _('[OPTION]... PATTERN [FILE]...'))
3262 def grep(ui, repo, pattern, *pats, **opts):
3266 def grep(ui, repo, pattern, *pats, **opts):
3263 """search for a pattern in specified files and revisions
3267 """search for a pattern in specified files and revisions
3264
3268
3265 Search revisions of files for a regular expression.
3269 Search revisions of files for a regular expression.
3266
3270
3267 This command behaves differently than Unix grep. It only accepts
3271 This command behaves differently than Unix grep. It only accepts
3268 Python/Perl regexps. It searches repository history, not the
3272 Python/Perl regexps. It searches repository history, not the
3269 working directory. It always prints the revision number in which a
3273 working directory. It always prints the revision number in which a
3270 match appears.
3274 match appears.
3271
3275
3272 By default, grep only prints output for the first revision of a
3276 By default, grep only prints output for the first revision of a
3273 file in which it finds a match. To get it to print every revision
3277 file in which it finds a match. To get it to print every revision
3274 that contains a change in match status ("-" for a match that
3278 that contains a change in match status ("-" for a match that
3275 becomes a non-match, or "+" for a non-match that becomes a match),
3279 becomes a non-match, or "+" for a non-match that becomes a match),
3276 use the --all flag.
3280 use the --all flag.
3277
3281
3278 Returns 0 if a match is found, 1 otherwise.
3282 Returns 0 if a match is found, 1 otherwise.
3279 """
3283 """
3280 reflags = re.M
3284 reflags = re.M
3281 if opts.get('ignore_case'):
3285 if opts.get('ignore_case'):
3282 reflags |= re.I
3286 reflags |= re.I
3283 try:
3287 try:
3284 regexp = util.compilere(pattern, reflags)
3288 regexp = util.compilere(pattern, reflags)
3285 except re.error, inst:
3289 except re.error, inst:
3286 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3290 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3287 return 1
3291 return 1
3288 sep, eol = ':', '\n'
3292 sep, eol = ':', '\n'
3289 if opts.get('print0'):
3293 if opts.get('print0'):
3290 sep = eol = '\0'
3294 sep = eol = '\0'
3291
3295
3292 getfile = util.lrucachefunc(repo.file)
3296 getfile = util.lrucachefunc(repo.file)
3293
3297
3294 def matchlines(body):
3298 def matchlines(body):
3295 begin = 0
3299 begin = 0
3296 linenum = 0
3300 linenum = 0
3297 while begin < len(body):
3301 while begin < len(body):
3298 match = regexp.search(body, begin)
3302 match = regexp.search(body, begin)
3299 if not match:
3303 if not match:
3300 break
3304 break
3301 mstart, mend = match.span()
3305 mstart, mend = match.span()
3302 linenum += body.count('\n', begin, mstart) + 1
3306 linenum += body.count('\n', begin, mstart) + 1
3303 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3307 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3304 begin = body.find('\n', mend) + 1 or len(body) + 1
3308 begin = body.find('\n', mend) + 1 or len(body) + 1
3305 lend = begin - 1
3309 lend = begin - 1
3306 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3310 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3307
3311
3308 class linestate(object):
3312 class linestate(object):
3309 def __init__(self, line, linenum, colstart, colend):
3313 def __init__(self, line, linenum, colstart, colend):
3310 self.line = line
3314 self.line = line
3311 self.linenum = linenum
3315 self.linenum = linenum
3312 self.colstart = colstart
3316 self.colstart = colstart
3313 self.colend = colend
3317 self.colend = colend
3314
3318
3315 def __hash__(self):
3319 def __hash__(self):
3316 return hash((self.linenum, self.line))
3320 return hash((self.linenum, self.line))
3317
3321
3318 def __eq__(self, other):
3322 def __eq__(self, other):
3319 return self.line == other.line
3323 return self.line == other.line
3320
3324
3321 def __iter__(self):
3325 def __iter__(self):
3322 yield (self.line[:self.colstart], '')
3326 yield (self.line[:self.colstart], '')
3323 yield (self.line[self.colstart:self.colend], 'grep.match')
3327 yield (self.line[self.colstart:self.colend], 'grep.match')
3324 rest = self.line[self.colend:]
3328 rest = self.line[self.colend:]
3325 while rest != '':
3329 while rest != '':
3326 match = regexp.search(rest)
3330 match = regexp.search(rest)
3327 if not match:
3331 if not match:
3328 yield (rest, '')
3332 yield (rest, '')
3329 break
3333 break
3330 mstart, mend = match.span()
3334 mstart, mend = match.span()
3331 yield (rest[:mstart], '')
3335 yield (rest[:mstart], '')
3332 yield (rest[mstart:mend], 'grep.match')
3336 yield (rest[mstart:mend], 'grep.match')
3333 rest = rest[mend:]
3337 rest = rest[mend:]
3334
3338
3335 matches = {}
3339 matches = {}
3336 copies = {}
3340 copies = {}
3337 def grepbody(fn, rev, body):
3341 def grepbody(fn, rev, body):
3338 matches[rev].setdefault(fn, [])
3342 matches[rev].setdefault(fn, [])
3339 m = matches[rev][fn]
3343 m = matches[rev][fn]
3340 for lnum, cstart, cend, line in matchlines(body):
3344 for lnum, cstart, cend, line in matchlines(body):
3341 s = linestate(line, lnum, cstart, cend)
3345 s = linestate(line, lnum, cstart, cend)
3342 m.append(s)
3346 m.append(s)
3343
3347
3344 def difflinestates(a, b):
3348 def difflinestates(a, b):
3345 sm = difflib.SequenceMatcher(None, a, b)
3349 sm = difflib.SequenceMatcher(None, a, b)
3346 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3350 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3347 if tag == 'insert':
3351 if tag == 'insert':
3348 for i in xrange(blo, bhi):
3352 for i in xrange(blo, bhi):
3349 yield ('+', b[i])
3353 yield ('+', b[i])
3350 elif tag == 'delete':
3354 elif tag == 'delete':
3351 for i in xrange(alo, ahi):
3355 for i in xrange(alo, ahi):
3352 yield ('-', a[i])
3356 yield ('-', a[i])
3353 elif tag == 'replace':
3357 elif tag == 'replace':
3354 for i in xrange(alo, ahi):
3358 for i in xrange(alo, ahi):
3355 yield ('-', a[i])
3359 yield ('-', a[i])
3356 for i in xrange(blo, bhi):
3360 for i in xrange(blo, bhi):
3357 yield ('+', b[i])
3361 yield ('+', b[i])
3358
3362
3359 def display(fn, ctx, pstates, states):
3363 def display(fn, ctx, pstates, states):
3360 rev = ctx.rev()
3364 rev = ctx.rev()
3361 datefunc = ui.quiet and util.shortdate or util.datestr
3365 datefunc = ui.quiet and util.shortdate or util.datestr
3362 found = False
3366 found = False
3363 @util.cachefunc
3367 @util.cachefunc
3364 def binary():
3368 def binary():
3365 flog = getfile(fn)
3369 flog = getfile(fn)
3366 return util.binary(flog.read(ctx.filenode(fn)))
3370 return util.binary(flog.read(ctx.filenode(fn)))
3367
3371
3368 if opts.get('all'):
3372 if opts.get('all'):
3369 iter = difflinestates(pstates, states)
3373 iter = difflinestates(pstates, states)
3370 else:
3374 else:
3371 iter = [('', l) for l in states]
3375 iter = [('', l) for l in states]
3372 for change, l in iter:
3376 for change, l in iter:
3373 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3377 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3374
3378
3375 if opts.get('line_number'):
3379 if opts.get('line_number'):
3376 cols.append((str(l.linenum), 'grep.linenumber'))
3380 cols.append((str(l.linenum), 'grep.linenumber'))
3377 if opts.get('all'):
3381 if opts.get('all'):
3378 cols.append((change, 'grep.change'))
3382 cols.append((change, 'grep.change'))
3379 if opts.get('user'):
3383 if opts.get('user'):
3380 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3384 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3381 if opts.get('date'):
3385 if opts.get('date'):
3382 cols.append((datefunc(ctx.date()), 'grep.date'))
3386 cols.append((datefunc(ctx.date()), 'grep.date'))
3383 for col, label in cols[:-1]:
3387 for col, label in cols[:-1]:
3384 ui.write(col, label=label)
3388 ui.write(col, label=label)
3385 ui.write(sep, label='grep.sep')
3389 ui.write(sep, label='grep.sep')
3386 ui.write(cols[-1][0], label=cols[-1][1])
3390 ui.write(cols[-1][0], label=cols[-1][1])
3387 if not opts.get('files_with_matches'):
3391 if not opts.get('files_with_matches'):
3388 ui.write(sep, label='grep.sep')
3392 ui.write(sep, label='grep.sep')
3389 if not opts.get('text') and binary():
3393 if not opts.get('text') and binary():
3390 ui.write(" Binary file matches")
3394 ui.write(" Binary file matches")
3391 else:
3395 else:
3392 for s, label in l:
3396 for s, label in l:
3393 ui.write(s, label=label)
3397 ui.write(s, label=label)
3394 ui.write(eol)
3398 ui.write(eol)
3395 found = True
3399 found = True
3396 if opts.get('files_with_matches'):
3400 if opts.get('files_with_matches'):
3397 break
3401 break
3398 return found
3402 return found
3399
3403
3400 skip = {}
3404 skip = {}
3401 revfiles = {}
3405 revfiles = {}
3402 matchfn = scmutil.match(repo[None], pats, opts)
3406 matchfn = scmutil.match(repo[None], pats, opts)
3403 found = False
3407 found = False
3404 follow = opts.get('follow')
3408 follow = opts.get('follow')
3405
3409
3406 def prep(ctx, fns):
3410 def prep(ctx, fns):
3407 rev = ctx.rev()
3411 rev = ctx.rev()
3408 pctx = ctx.p1()
3412 pctx = ctx.p1()
3409 parent = pctx.rev()
3413 parent = pctx.rev()
3410 matches.setdefault(rev, {})
3414 matches.setdefault(rev, {})
3411 matches.setdefault(parent, {})
3415 matches.setdefault(parent, {})
3412 files = revfiles.setdefault(rev, [])
3416 files = revfiles.setdefault(rev, [])
3413 for fn in fns:
3417 for fn in fns:
3414 flog = getfile(fn)
3418 flog = getfile(fn)
3415 try:
3419 try:
3416 fnode = ctx.filenode(fn)
3420 fnode = ctx.filenode(fn)
3417 except error.LookupError:
3421 except error.LookupError:
3418 continue
3422 continue
3419
3423
3420 copied = flog.renamed(fnode)
3424 copied = flog.renamed(fnode)
3421 copy = follow and copied and copied[0]
3425 copy = follow and copied and copied[0]
3422 if copy:
3426 if copy:
3423 copies.setdefault(rev, {})[fn] = copy
3427 copies.setdefault(rev, {})[fn] = copy
3424 if fn in skip:
3428 if fn in skip:
3425 if copy:
3429 if copy:
3426 skip[copy] = True
3430 skip[copy] = True
3427 continue
3431 continue
3428 files.append(fn)
3432 files.append(fn)
3429
3433
3430 if fn not in matches[rev]:
3434 if fn not in matches[rev]:
3431 grepbody(fn, rev, flog.read(fnode))
3435 grepbody(fn, rev, flog.read(fnode))
3432
3436
3433 pfn = copy or fn
3437 pfn = copy or fn
3434 if pfn not in matches[parent]:
3438 if pfn not in matches[parent]:
3435 try:
3439 try:
3436 fnode = pctx.filenode(pfn)
3440 fnode = pctx.filenode(pfn)
3437 grepbody(pfn, parent, flog.read(fnode))
3441 grepbody(pfn, parent, flog.read(fnode))
3438 except error.LookupError:
3442 except error.LookupError:
3439 pass
3443 pass
3440
3444
3441 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3445 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3442 rev = ctx.rev()
3446 rev = ctx.rev()
3443 parent = ctx.p1().rev()
3447 parent = ctx.p1().rev()
3444 for fn in sorted(revfiles.get(rev, [])):
3448 for fn in sorted(revfiles.get(rev, [])):
3445 states = matches[rev][fn]
3449 states = matches[rev][fn]
3446 copy = copies.get(rev, {}).get(fn)
3450 copy = copies.get(rev, {}).get(fn)
3447 if fn in skip:
3451 if fn in skip:
3448 if copy:
3452 if copy:
3449 skip[copy] = True
3453 skip[copy] = True
3450 continue
3454 continue
3451 pstates = matches.get(parent, {}).get(copy or fn, [])
3455 pstates = matches.get(parent, {}).get(copy or fn, [])
3452 if pstates or states:
3456 if pstates or states:
3453 r = display(fn, ctx, pstates, states)
3457 r = display(fn, ctx, pstates, states)
3454 found = found or r
3458 found = found or r
3455 if r and not opts.get('all'):
3459 if r and not opts.get('all'):
3456 skip[fn] = True
3460 skip[fn] = True
3457 if copy:
3461 if copy:
3458 skip[copy] = True
3462 skip[copy] = True
3459 del matches[rev]
3463 del matches[rev]
3460 del revfiles[rev]
3464 del revfiles[rev]
3461
3465
3462 return not found
3466 return not found
3463
3467
3464 @command('heads',
3468 @command('heads',
3465 [('r', 'rev', '',
3469 [('r', 'rev', '',
3466 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3470 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3467 ('t', 'topo', False, _('show topological heads only')),
3471 ('t', 'topo', False, _('show topological heads only')),
3468 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3472 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3469 ('c', 'closed', False, _('show normal and closed branch heads')),
3473 ('c', 'closed', False, _('show normal and closed branch heads')),
3470 ] + templateopts,
3474 ] + templateopts,
3471 _('[-ct] [-r STARTREV] [REV]...'))
3475 _('[-ct] [-r STARTREV] [REV]...'))
3472 def heads(ui, repo, *branchrevs, **opts):
3476 def heads(ui, repo, *branchrevs, **opts):
3473 """show branch heads
3477 """show branch heads
3474
3478
3475 With no arguments, show all open branch heads in the repository.
3479 With no arguments, show all open branch heads in the repository.
3476 Branch heads are changesets that have no descendants on the
3480 Branch heads are changesets that have no descendants on the
3477 same branch. They are where development generally takes place and
3481 same branch. They are where development generally takes place and
3478 are the usual targets for update and merge operations.
3482 are the usual targets for update and merge operations.
3479
3483
3480 If one or more REVs are given, only open branch heads on the
3484 If one or more REVs are given, only open branch heads on the
3481 branches associated with the specified changesets are shown. This
3485 branches associated with the specified changesets are shown. This
3482 means that you can use :hg:`heads .` to see the heads on the
3486 means that you can use :hg:`heads .` to see the heads on the
3483 currently checked-out branch.
3487 currently checked-out branch.
3484
3488
3485 If -c/--closed is specified, also show branch heads marked closed
3489 If -c/--closed is specified, also show branch heads marked closed
3486 (see :hg:`commit --close-branch`).
3490 (see :hg:`commit --close-branch`).
3487
3491
3488 If STARTREV is specified, only those heads that are descendants of
3492 If STARTREV is specified, only those heads that are descendants of
3489 STARTREV will be displayed.
3493 STARTREV will be displayed.
3490
3494
3491 If -t/--topo is specified, named branch mechanics will be ignored and only
3495 If -t/--topo is specified, named branch mechanics will be ignored and only
3492 topological heads (changesets with no children) will be shown.
3496 topological heads (changesets with no children) will be shown.
3493
3497
3494 Returns 0 if matching heads are found, 1 if not.
3498 Returns 0 if matching heads are found, 1 if not.
3495 """
3499 """
3496
3500
3497 start = None
3501 start = None
3498 if 'rev' in opts:
3502 if 'rev' in opts:
3499 start = scmutil.revsingle(repo, opts['rev'], None).node()
3503 start = scmutil.revsingle(repo, opts['rev'], None).node()
3500
3504
3501 if opts.get('topo'):
3505 if opts.get('topo'):
3502 heads = [repo[h] for h in repo.heads(start)]
3506 heads = [repo[h] for h in repo.heads(start)]
3503 else:
3507 else:
3504 heads = []
3508 heads = []
3505 for branch in repo.branchmap():
3509 for branch in repo.branchmap():
3506 heads += repo.branchheads(branch, start, opts.get('closed'))
3510 heads += repo.branchheads(branch, start, opts.get('closed'))
3507 heads = [repo[h] for h in heads]
3511 heads = [repo[h] for h in heads]
3508
3512
3509 if branchrevs:
3513 if branchrevs:
3510 branches = set(repo[br].branch() for br in branchrevs)
3514 branches = set(repo[br].branch() for br in branchrevs)
3511 heads = [h for h in heads if h.branch() in branches]
3515 heads = [h for h in heads if h.branch() in branches]
3512
3516
3513 if opts.get('active') and branchrevs:
3517 if opts.get('active') and branchrevs:
3514 dagheads = repo.heads(start)
3518 dagheads = repo.heads(start)
3515 heads = [h for h in heads if h.node() in dagheads]
3519 heads = [h for h in heads if h.node() in dagheads]
3516
3520
3517 if branchrevs:
3521 if branchrevs:
3518 haveheads = set(h.branch() for h in heads)
3522 haveheads = set(h.branch() for h in heads)
3519 if branches - haveheads:
3523 if branches - haveheads:
3520 headless = ', '.join(b for b in branches - haveheads)
3524 headless = ', '.join(b for b in branches - haveheads)
3521 msg = _('no open branch heads found on branches %s')
3525 msg = _('no open branch heads found on branches %s')
3522 if opts.get('rev'):
3526 if opts.get('rev'):
3523 msg += _(' (started at %s)') % opts['rev']
3527 msg += _(' (started at %s)') % opts['rev']
3524 ui.warn((msg + '\n') % headless)
3528 ui.warn((msg + '\n') % headless)
3525
3529
3526 if not heads:
3530 if not heads:
3527 return 1
3531 return 1
3528
3532
3529 heads = sorted(heads, key=lambda x: -x.rev())
3533 heads = sorted(heads, key=lambda x: -x.rev())
3530 displayer = cmdutil.show_changeset(ui, repo, opts)
3534 displayer = cmdutil.show_changeset(ui, repo, opts)
3531 for ctx in heads:
3535 for ctx in heads:
3532 displayer.show(ctx)
3536 displayer.show(ctx)
3533 displayer.close()
3537 displayer.close()
3534
3538
3535 @command('help',
3539 @command('help',
3536 [('e', 'extension', None, _('show only help for extensions')),
3540 [('e', 'extension', None, _('show only help for extensions')),
3537 ('c', 'command', None, _('show only help for commands')),
3541 ('c', 'command', None, _('show only help for commands')),
3538 ('k', 'keyword', '', _('show topics matching keyword')),
3542 ('k', 'keyword', '', _('show topics matching keyword')),
3539 ],
3543 ],
3540 _('[-ec] [TOPIC]'))
3544 _('[-ec] [TOPIC]'))
3541 def help_(ui, name=None, **opts):
3545 def help_(ui, name=None, **opts):
3542 """show help for a given topic or a help overview
3546 """show help for a given topic or a help overview
3543
3547
3544 With no arguments, print a list of commands with short help messages.
3548 With no arguments, print a list of commands with short help messages.
3545
3549
3546 Given a topic, extension, or command name, print help for that
3550 Given a topic, extension, or command name, print help for that
3547 topic.
3551 topic.
3548
3552
3549 Returns 0 if successful.
3553 Returns 0 if successful.
3550 """
3554 """
3551
3555
3552 textwidth = min(ui.termwidth(), 80) - 2
3556 textwidth = min(ui.termwidth(), 80) - 2
3553
3557
3554 keep = ui.verbose and ['verbose'] or []
3558 keep = ui.verbose and ['verbose'] or []
3555 text = help.help_(ui, name, **opts)
3559 text = help.help_(ui, name, **opts)
3556
3560
3557 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3561 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3558 if 'verbose' in pruned:
3562 if 'verbose' in pruned:
3559 keep.append('omitted')
3563 keep.append('omitted')
3560 else:
3564 else:
3561 keep.append('notomitted')
3565 keep.append('notomitted')
3562 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3566 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3563 ui.write(formatted)
3567 ui.write(formatted)
3564
3568
3565
3569
3566 @command('identify|id',
3570 @command('identify|id',
3567 [('r', 'rev', '',
3571 [('r', 'rev', '',
3568 _('identify the specified revision'), _('REV')),
3572 _('identify the specified revision'), _('REV')),
3569 ('n', 'num', None, _('show local revision number')),
3573 ('n', 'num', None, _('show local revision number')),
3570 ('i', 'id', None, _('show global revision id')),
3574 ('i', 'id', None, _('show global revision id')),
3571 ('b', 'branch', None, _('show branch')),
3575 ('b', 'branch', None, _('show branch')),
3572 ('t', 'tags', None, _('show tags')),
3576 ('t', 'tags', None, _('show tags')),
3573 ('B', 'bookmarks', None, _('show bookmarks')),
3577 ('B', 'bookmarks', None, _('show bookmarks')),
3574 ] + remoteopts,
3578 ] + remoteopts,
3575 _('[-nibtB] [-r REV] [SOURCE]'))
3579 _('[-nibtB] [-r REV] [SOURCE]'))
3576 def identify(ui, repo, source=None, rev=None,
3580 def identify(ui, repo, source=None, rev=None,
3577 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3581 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3578 """identify the working copy or specified revision
3582 """identify the working copy or specified revision
3579
3583
3580 Print a summary identifying the repository state at REV using one or
3584 Print a summary identifying the repository state at REV using one or
3581 two parent hash identifiers, followed by a "+" if the working
3585 two parent hash identifiers, followed by a "+" if the working
3582 directory has uncommitted changes, the branch name (if not default),
3586 directory has uncommitted changes, the branch name (if not default),
3583 a list of tags, and a list of bookmarks.
3587 a list of tags, and a list of bookmarks.
3584
3588
3585 When REV is not given, print a summary of the current state of the
3589 When REV is not given, print a summary of the current state of the
3586 repository.
3590 repository.
3587
3591
3588 Specifying a path to a repository root or Mercurial bundle will
3592 Specifying a path to a repository root or Mercurial bundle will
3589 cause lookup to operate on that repository/bundle.
3593 cause lookup to operate on that repository/bundle.
3590
3594
3591 .. container:: verbose
3595 .. container:: verbose
3592
3596
3593 Examples:
3597 Examples:
3594
3598
3595 - generate a build identifier for the working directory::
3599 - generate a build identifier for the working directory::
3596
3600
3597 hg id --id > build-id.dat
3601 hg id --id > build-id.dat
3598
3602
3599 - find the revision corresponding to a tag::
3603 - find the revision corresponding to a tag::
3600
3604
3601 hg id -n -r 1.3
3605 hg id -n -r 1.3
3602
3606
3603 - check the most recent revision of a remote repository::
3607 - check the most recent revision of a remote repository::
3604
3608
3605 hg id -r tip http://selenic.com/hg/
3609 hg id -r tip http://selenic.com/hg/
3606
3610
3607 Returns 0 if successful.
3611 Returns 0 if successful.
3608 """
3612 """
3609
3613
3610 if not repo and not source:
3614 if not repo and not source:
3611 raise util.Abort(_("there is no Mercurial repository here "
3615 raise util.Abort(_("there is no Mercurial repository here "
3612 "(.hg not found)"))
3616 "(.hg not found)"))
3613
3617
3614 hexfunc = ui.debugflag and hex or short
3618 hexfunc = ui.debugflag and hex or short
3615 default = not (num or id or branch or tags or bookmarks)
3619 default = not (num or id or branch or tags or bookmarks)
3616 output = []
3620 output = []
3617 revs = []
3621 revs = []
3618
3622
3619 if source:
3623 if source:
3620 source, branches = hg.parseurl(ui.expandpath(source))
3624 source, branches = hg.parseurl(ui.expandpath(source))
3621 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3625 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3622 repo = peer.local()
3626 repo = peer.local()
3623 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3627 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3624
3628
3625 if not repo:
3629 if not repo:
3626 if num or branch or tags:
3630 if num or branch or tags:
3627 raise util.Abort(
3631 raise util.Abort(
3628 _("can't query remote revision number, branch, or tags"))
3632 _("can't query remote revision number, branch, or tags"))
3629 if not rev and revs:
3633 if not rev and revs:
3630 rev = revs[0]
3634 rev = revs[0]
3631 if not rev:
3635 if not rev:
3632 rev = "tip"
3636 rev = "tip"
3633
3637
3634 remoterev = peer.lookup(rev)
3638 remoterev = peer.lookup(rev)
3635 if default or id:
3639 if default or id:
3636 output = [hexfunc(remoterev)]
3640 output = [hexfunc(remoterev)]
3637
3641
3638 def getbms():
3642 def getbms():
3639 bms = []
3643 bms = []
3640
3644
3641 if 'bookmarks' in peer.listkeys('namespaces'):
3645 if 'bookmarks' in peer.listkeys('namespaces'):
3642 hexremoterev = hex(remoterev)
3646 hexremoterev = hex(remoterev)
3643 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3647 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3644 if bmr == hexremoterev]
3648 if bmr == hexremoterev]
3645
3649
3646 return sorted(bms)
3650 return sorted(bms)
3647
3651
3648 if bookmarks:
3652 if bookmarks:
3649 output.extend(getbms())
3653 output.extend(getbms())
3650 elif default and not ui.quiet:
3654 elif default and not ui.quiet:
3651 # multiple bookmarks for a single parent separated by '/'
3655 # multiple bookmarks for a single parent separated by '/'
3652 bm = '/'.join(getbms())
3656 bm = '/'.join(getbms())
3653 if bm:
3657 if bm:
3654 output.append(bm)
3658 output.append(bm)
3655 else:
3659 else:
3656 if not rev:
3660 if not rev:
3657 ctx = repo[None]
3661 ctx = repo[None]
3658 parents = ctx.parents()
3662 parents = ctx.parents()
3659 changed = ""
3663 changed = ""
3660 if default or id or num:
3664 if default or id or num:
3661 if (util.any(repo.status())
3665 if (util.any(repo.status())
3662 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3666 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3663 changed = '+'
3667 changed = '+'
3664 if default or id:
3668 if default or id:
3665 output = ["%s%s" %
3669 output = ["%s%s" %
3666 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3670 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3667 if num:
3671 if num:
3668 output.append("%s%s" %
3672 output.append("%s%s" %
3669 ('+'.join([str(p.rev()) for p in parents]), changed))
3673 ('+'.join([str(p.rev()) for p in parents]), changed))
3670 else:
3674 else:
3671 ctx = scmutil.revsingle(repo, rev)
3675 ctx = scmutil.revsingle(repo, rev)
3672 if default or id:
3676 if default or id:
3673 output = [hexfunc(ctx.node())]
3677 output = [hexfunc(ctx.node())]
3674 if num:
3678 if num:
3675 output.append(str(ctx.rev()))
3679 output.append(str(ctx.rev()))
3676
3680
3677 if default and not ui.quiet:
3681 if default and not ui.quiet:
3678 b = ctx.branch()
3682 b = ctx.branch()
3679 if b != 'default':
3683 if b != 'default':
3680 output.append("(%s)" % b)
3684 output.append("(%s)" % b)
3681
3685
3682 # multiple tags for a single parent separated by '/'
3686 # multiple tags for a single parent separated by '/'
3683 t = '/'.join(ctx.tags())
3687 t = '/'.join(ctx.tags())
3684 if t:
3688 if t:
3685 output.append(t)
3689 output.append(t)
3686
3690
3687 # multiple bookmarks for a single parent separated by '/'
3691 # multiple bookmarks for a single parent separated by '/'
3688 bm = '/'.join(ctx.bookmarks())
3692 bm = '/'.join(ctx.bookmarks())
3689 if bm:
3693 if bm:
3690 output.append(bm)
3694 output.append(bm)
3691 else:
3695 else:
3692 if branch:
3696 if branch:
3693 output.append(ctx.branch())
3697 output.append(ctx.branch())
3694
3698
3695 if tags:
3699 if tags:
3696 output.extend(ctx.tags())
3700 output.extend(ctx.tags())
3697
3701
3698 if bookmarks:
3702 if bookmarks:
3699 output.extend(ctx.bookmarks())
3703 output.extend(ctx.bookmarks())
3700
3704
3701 ui.write("%s\n" % ' '.join(output))
3705 ui.write("%s\n" % ' '.join(output))
3702
3706
3703 @command('import|patch',
3707 @command('import|patch',
3704 [('p', 'strip', 1,
3708 [('p', 'strip', 1,
3705 _('directory strip option for patch. This has the same '
3709 _('directory strip option for patch. This has the same '
3706 'meaning as the corresponding patch option'), _('NUM')),
3710 'meaning as the corresponding patch option'), _('NUM')),
3707 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3711 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3708 ('e', 'edit', False, _('invoke editor on commit messages')),
3712 ('e', 'edit', False, _('invoke editor on commit messages')),
3709 ('f', 'force', None,
3713 ('f', 'force', None,
3710 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3714 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3711 ('', 'no-commit', None,
3715 ('', 'no-commit', None,
3712 _("don't commit, just update the working directory")),
3716 _("don't commit, just update the working directory")),
3713 ('', 'bypass', None,
3717 ('', 'bypass', None,
3714 _("apply patch without touching the working directory")),
3718 _("apply patch without touching the working directory")),
3715 ('', 'exact', None,
3719 ('', 'exact', None,
3716 _('apply patch to the nodes from which it was generated')),
3720 _('apply patch to the nodes from which it was generated')),
3717 ('', 'import-branch', None,
3721 ('', 'import-branch', None,
3718 _('use any branch information in patch (implied by --exact)'))] +
3722 _('use any branch information in patch (implied by --exact)'))] +
3719 commitopts + commitopts2 + similarityopts,
3723 commitopts + commitopts2 + similarityopts,
3720 _('[OPTION]... PATCH...'))
3724 _('[OPTION]... PATCH...'))
3721 def import_(ui, repo, patch1=None, *patches, **opts):
3725 def import_(ui, repo, patch1=None, *patches, **opts):
3722 """import an ordered set of patches
3726 """import an ordered set of patches
3723
3727
3724 Import a list of patches and commit them individually (unless
3728 Import a list of patches and commit them individually (unless
3725 --no-commit is specified).
3729 --no-commit is specified).
3726
3730
3727 Because import first applies changes to the working directory,
3731 Because import first applies changes to the working directory,
3728 import will abort if there are outstanding changes.
3732 import will abort if there are outstanding changes.
3729
3733
3730 You can import a patch straight from a mail message. Even patches
3734 You can import a patch straight from a mail message. Even patches
3731 as attachments work (to use the body part, it must have type
3735 as attachments work (to use the body part, it must have type
3732 text/plain or text/x-patch). From and Subject headers of email
3736 text/plain or text/x-patch). From and Subject headers of email
3733 message are used as default committer and commit message. All
3737 message are used as default committer and commit message. All
3734 text/plain body parts before first diff are added to commit
3738 text/plain body parts before first diff are added to commit
3735 message.
3739 message.
3736
3740
3737 If the imported patch was generated by :hg:`export`, user and
3741 If the imported patch was generated by :hg:`export`, user and
3738 description from patch override values from message headers and
3742 description from patch override values from message headers and
3739 body. Values given on command line with -m/--message and -u/--user
3743 body. Values given on command line with -m/--message and -u/--user
3740 override these.
3744 override these.
3741
3745
3742 If --exact is specified, import will set the working directory to
3746 If --exact is specified, import will set the working directory to
3743 the parent of each patch before applying it, and will abort if the
3747 the parent of each patch before applying it, and will abort if the
3744 resulting changeset has a different ID than the one recorded in
3748 resulting changeset has a different ID than the one recorded in
3745 the patch. This may happen due to character set problems or other
3749 the patch. This may happen due to character set problems or other
3746 deficiencies in the text patch format.
3750 deficiencies in the text patch format.
3747
3751
3748 Use --bypass to apply and commit patches directly to the
3752 Use --bypass to apply and commit patches directly to the
3749 repository, not touching the working directory. Without --exact,
3753 repository, not touching the working directory. Without --exact,
3750 patches will be applied on top of the working directory parent
3754 patches will be applied on top of the working directory parent
3751 revision.
3755 revision.
3752
3756
3753 With -s/--similarity, hg will attempt to discover renames and
3757 With -s/--similarity, hg will attempt to discover renames and
3754 copies in the patch in the same way as :hg:`addremove`.
3758 copies in the patch in the same way as :hg:`addremove`.
3755
3759
3756 To read a patch from standard input, use "-" as the patch name. If
3760 To read a patch from standard input, use "-" as the patch name. If
3757 a URL is specified, the patch will be downloaded from it.
3761 a URL is specified, the patch will be downloaded from it.
3758 See :hg:`help dates` for a list of formats valid for -d/--date.
3762 See :hg:`help dates` for a list of formats valid for -d/--date.
3759
3763
3760 .. container:: verbose
3764 .. container:: verbose
3761
3765
3762 Examples:
3766 Examples:
3763
3767
3764 - import a traditional patch from a website and detect renames::
3768 - import a traditional patch from a website and detect renames::
3765
3769
3766 hg import -s 80 http://example.com/bugfix.patch
3770 hg import -s 80 http://example.com/bugfix.patch
3767
3771
3768 - import a changeset from an hgweb server::
3772 - import a changeset from an hgweb server::
3769
3773
3770 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3774 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3771
3775
3772 - import all the patches in an Unix-style mbox::
3776 - import all the patches in an Unix-style mbox::
3773
3777
3774 hg import incoming-patches.mbox
3778 hg import incoming-patches.mbox
3775
3779
3776 - attempt to exactly restore an exported changeset (not always
3780 - attempt to exactly restore an exported changeset (not always
3777 possible)::
3781 possible)::
3778
3782
3779 hg import --exact proposed-fix.patch
3783 hg import --exact proposed-fix.patch
3780
3784
3781 Returns 0 on success.
3785 Returns 0 on success.
3782 """
3786 """
3783
3787
3784 if not patch1:
3788 if not patch1:
3785 raise util.Abort(_('need at least one patch to import'))
3789 raise util.Abort(_('need at least one patch to import'))
3786
3790
3787 patches = (patch1,) + patches
3791 patches = (patch1,) + patches
3788
3792
3789 date = opts.get('date')
3793 date = opts.get('date')
3790 if date:
3794 if date:
3791 opts['date'] = util.parsedate(date)
3795 opts['date'] = util.parsedate(date)
3792
3796
3793 update = not opts.get('bypass')
3797 update = not opts.get('bypass')
3794 if not update and opts.get('no_commit'):
3798 if not update and opts.get('no_commit'):
3795 raise util.Abort(_('cannot use --no-commit with --bypass'))
3799 raise util.Abort(_('cannot use --no-commit with --bypass'))
3796 try:
3800 try:
3797 sim = float(opts.get('similarity') or 0)
3801 sim = float(opts.get('similarity') or 0)
3798 except ValueError:
3802 except ValueError:
3799 raise util.Abort(_('similarity must be a number'))
3803 raise util.Abort(_('similarity must be a number'))
3800 if sim < 0 or sim > 100:
3804 if sim < 0 or sim > 100:
3801 raise util.Abort(_('similarity must be between 0 and 100'))
3805 raise util.Abort(_('similarity must be between 0 and 100'))
3802 if sim and not update:
3806 if sim and not update:
3803 raise util.Abort(_('cannot use --similarity with --bypass'))
3807 raise util.Abort(_('cannot use --similarity with --bypass'))
3804
3808
3805 if update:
3809 if update:
3806 cmdutil.checkunfinished(repo)
3810 cmdutil.checkunfinished(repo)
3807 if (opts.get('exact') or not opts.get('force')) and update:
3811 if (opts.get('exact') or not opts.get('force')) and update:
3808 cmdutil.bailifchanged(repo)
3812 cmdutil.bailifchanged(repo)
3809
3813
3810 base = opts["base"]
3814 base = opts["base"]
3811 wlock = lock = tr = None
3815 wlock = lock = tr = None
3812 msgs = []
3816 msgs = []
3813
3817
3814
3818
3815 try:
3819 try:
3816 try:
3820 try:
3817 wlock = repo.wlock()
3821 wlock = repo.wlock()
3818 if not opts.get('no_commit'):
3822 if not opts.get('no_commit'):
3819 lock = repo.lock()
3823 lock = repo.lock()
3820 tr = repo.transaction('import')
3824 tr = repo.transaction('import')
3821 parents = repo.parents()
3825 parents = repo.parents()
3822 for patchurl in patches:
3826 for patchurl in patches:
3823 if patchurl == '-':
3827 if patchurl == '-':
3824 ui.status(_('applying patch from stdin\n'))
3828 ui.status(_('applying patch from stdin\n'))
3825 patchfile = ui.fin
3829 patchfile = ui.fin
3826 patchurl = 'stdin' # for error message
3830 patchurl = 'stdin' # for error message
3827 else:
3831 else:
3828 patchurl = os.path.join(base, patchurl)
3832 patchurl = os.path.join(base, patchurl)
3829 ui.status(_('applying %s\n') % patchurl)
3833 ui.status(_('applying %s\n') % patchurl)
3830 patchfile = hg.openpath(ui, patchurl)
3834 patchfile = hg.openpath(ui, patchurl)
3831
3835
3832 haspatch = False
3836 haspatch = False
3833 for hunk in patch.split(patchfile):
3837 for hunk in patch.split(patchfile):
3834 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3838 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3835 opts, msgs, hg.clean)
3839 opts, msgs, hg.clean)
3836 if msg:
3840 if msg:
3837 haspatch = True
3841 haspatch = True
3838 ui.note(msg + '\n')
3842 ui.note(msg + '\n')
3839 if update or opts.get('exact'):
3843 if update or opts.get('exact'):
3840 parents = repo.parents()
3844 parents = repo.parents()
3841 else:
3845 else:
3842 parents = [repo[node]]
3846 parents = [repo[node]]
3843
3847
3844 if not haspatch:
3848 if not haspatch:
3845 raise util.Abort(_('%s: no diffs found') % patchurl)
3849 raise util.Abort(_('%s: no diffs found') % patchurl)
3846
3850
3847 if tr:
3851 if tr:
3848 tr.close()
3852 tr.close()
3849 if msgs:
3853 if msgs:
3850 repo.savecommitmessage('\n* * *\n'.join(msgs))
3854 repo.savecommitmessage('\n* * *\n'.join(msgs))
3851 except: # re-raises
3855 except: # re-raises
3852 # wlock.release() indirectly calls dirstate.write(): since
3856 # wlock.release() indirectly calls dirstate.write(): since
3853 # we're crashing, we do not want to change the working dir
3857 # we're crashing, we do not want to change the working dir
3854 # parent after all, so make sure it writes nothing
3858 # parent after all, so make sure it writes nothing
3855 repo.dirstate.invalidate()
3859 repo.dirstate.invalidate()
3856 raise
3860 raise
3857 finally:
3861 finally:
3858 if tr:
3862 if tr:
3859 tr.release()
3863 tr.release()
3860 release(lock, wlock)
3864 release(lock, wlock)
3861
3865
3862 @command('incoming|in',
3866 @command('incoming|in',
3863 [('f', 'force', None,
3867 [('f', 'force', None,
3864 _('run even if remote repository is unrelated')),
3868 _('run even if remote repository is unrelated')),
3865 ('n', 'newest-first', None, _('show newest record first')),
3869 ('n', 'newest-first', None, _('show newest record first')),
3866 ('', 'bundle', '',
3870 ('', 'bundle', '',
3867 _('file to store the bundles into'), _('FILE')),
3871 _('file to store the bundles into'), _('FILE')),
3868 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3872 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3869 ('B', 'bookmarks', False, _("compare bookmarks")),
3873 ('B', 'bookmarks', False, _("compare bookmarks")),
3870 ('b', 'branch', [],
3874 ('b', 'branch', [],
3871 _('a specific branch you would like to pull'), _('BRANCH')),
3875 _('a specific branch you would like to pull'), _('BRANCH')),
3872 ] + logopts + remoteopts + subrepoopts,
3876 ] + logopts + remoteopts + subrepoopts,
3873 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3877 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3874 def incoming(ui, repo, source="default", **opts):
3878 def incoming(ui, repo, source="default", **opts):
3875 """show new changesets found in source
3879 """show new changesets found in source
3876
3880
3877 Show new changesets found in the specified path/URL or the default
3881 Show new changesets found in the specified path/URL or the default
3878 pull location. These are the changesets that would have been pulled
3882 pull location. These are the changesets that would have been pulled
3879 if a pull at the time you issued this command.
3883 if a pull at the time you issued this command.
3880
3884
3881 For remote repository, using --bundle avoids downloading the
3885 For remote repository, using --bundle avoids downloading the
3882 changesets twice if the incoming is followed by a pull.
3886 changesets twice if the incoming is followed by a pull.
3883
3887
3884 See pull for valid source format details.
3888 See pull for valid source format details.
3885
3889
3886 .. container:: verbose
3890 .. container:: verbose
3887
3891
3888 Examples:
3892 Examples:
3889
3893
3890 - show incoming changes with patches and full description::
3894 - show incoming changes with patches and full description::
3891
3895
3892 hg incoming -vp
3896 hg incoming -vp
3893
3897
3894 - show incoming changes excluding merges, store a bundle::
3898 - show incoming changes excluding merges, store a bundle::
3895
3899
3896 hg in -vpM --bundle incoming.hg
3900 hg in -vpM --bundle incoming.hg
3897 hg pull incoming.hg
3901 hg pull incoming.hg
3898
3902
3899 - briefly list changes inside a bundle::
3903 - briefly list changes inside a bundle::
3900
3904
3901 hg in changes.hg -T "{desc|firstline}\\n"
3905 hg in changes.hg -T "{desc|firstline}\\n"
3902
3906
3903 Returns 0 if there are incoming changes, 1 otherwise.
3907 Returns 0 if there are incoming changes, 1 otherwise.
3904 """
3908 """
3905 if opts.get('graph'):
3909 if opts.get('graph'):
3906 cmdutil.checkunsupportedgraphflags([], opts)
3910 cmdutil.checkunsupportedgraphflags([], opts)
3907 def display(other, chlist, displayer):
3911 def display(other, chlist, displayer):
3908 revdag = cmdutil.graphrevs(other, chlist, opts)
3912 revdag = cmdutil.graphrevs(other, chlist, opts)
3909 showparents = [ctx.node() for ctx in repo[None].parents()]
3913 showparents = [ctx.node() for ctx in repo[None].parents()]
3910 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3914 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3911 graphmod.asciiedges)
3915 graphmod.asciiedges)
3912
3916
3913 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3917 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3914 return 0
3918 return 0
3915
3919
3916 if opts.get('bundle') and opts.get('subrepos'):
3920 if opts.get('bundle') and opts.get('subrepos'):
3917 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3921 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3918
3922
3919 if opts.get('bookmarks'):
3923 if opts.get('bookmarks'):
3920 source, branches = hg.parseurl(ui.expandpath(source),
3924 source, branches = hg.parseurl(ui.expandpath(source),
3921 opts.get('branch'))
3925 opts.get('branch'))
3922 other = hg.peer(repo, opts, source)
3926 other = hg.peer(repo, opts, source)
3923 if 'bookmarks' not in other.listkeys('namespaces'):
3927 if 'bookmarks' not in other.listkeys('namespaces'):
3924 ui.warn(_("remote doesn't support bookmarks\n"))
3928 ui.warn(_("remote doesn't support bookmarks\n"))
3925 return 0
3929 return 0
3926 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3930 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3927 return bookmarks.diff(ui, repo, other)
3931 return bookmarks.diff(ui, repo, other)
3928
3932
3929 repo._subtoppath = ui.expandpath(source)
3933 repo._subtoppath = ui.expandpath(source)
3930 try:
3934 try:
3931 return hg.incoming(ui, repo, source, opts)
3935 return hg.incoming(ui, repo, source, opts)
3932 finally:
3936 finally:
3933 del repo._subtoppath
3937 del repo._subtoppath
3934
3938
3935
3939
3936 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3940 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3937 def init(ui, dest=".", **opts):
3941 def init(ui, dest=".", **opts):
3938 """create a new repository in the given directory
3942 """create a new repository in the given directory
3939
3943
3940 Initialize a new repository in the given directory. If the given
3944 Initialize a new repository in the given directory. If the given
3941 directory does not exist, it will be created.
3945 directory does not exist, it will be created.
3942
3946
3943 If no directory is given, the current directory is used.
3947 If no directory is given, the current directory is used.
3944
3948
3945 It is possible to specify an ``ssh://`` URL as the destination.
3949 It is possible to specify an ``ssh://`` URL as the destination.
3946 See :hg:`help urls` for more information.
3950 See :hg:`help urls` for more information.
3947
3951
3948 Returns 0 on success.
3952 Returns 0 on success.
3949 """
3953 """
3950 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3954 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3951
3955
3952 @command('locate',
3956 @command('locate',
3953 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3957 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3954 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3958 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3955 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3959 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3956 ] + walkopts,
3960 ] + walkopts,
3957 _('[OPTION]... [PATTERN]...'))
3961 _('[OPTION]... [PATTERN]...'))
3958 def locate(ui, repo, *pats, **opts):
3962 def locate(ui, repo, *pats, **opts):
3959 """locate files matching specific patterns
3963 """locate files matching specific patterns
3960
3964
3961 Print files under Mercurial control in the working directory whose
3965 Print files under Mercurial control in the working directory whose
3962 names match the given patterns.
3966 names match the given patterns.
3963
3967
3964 By default, this command searches all directories in the working
3968 By default, this command searches all directories in the working
3965 directory. To search just the current directory and its
3969 directory. To search just the current directory and its
3966 subdirectories, use "--include .".
3970 subdirectories, use "--include .".
3967
3971
3968 If no patterns are given to match, this command prints the names
3972 If no patterns are given to match, this command prints the names
3969 of all files under Mercurial control in the working directory.
3973 of all files under Mercurial control in the working directory.
3970
3974
3971 If you want to feed the output of this command into the "xargs"
3975 If you want to feed the output of this command into the "xargs"
3972 command, use the -0 option to both this command and "xargs". This
3976 command, use the -0 option to both this command and "xargs". This
3973 will avoid the problem of "xargs" treating single filenames that
3977 will avoid the problem of "xargs" treating single filenames that
3974 contain whitespace as multiple filenames.
3978 contain whitespace as multiple filenames.
3975
3979
3976 Returns 0 if a match is found, 1 otherwise.
3980 Returns 0 if a match is found, 1 otherwise.
3977 """
3981 """
3978 end = opts.get('print0') and '\0' or '\n'
3982 end = opts.get('print0') and '\0' or '\n'
3979 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3983 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3980
3984
3981 ret = 1
3985 ret = 1
3982 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3986 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3983 m.bad = lambda x, y: False
3987 m.bad = lambda x, y: False
3984 for abs in repo[rev].walk(m):
3988 for abs in repo[rev].walk(m):
3985 if not rev and abs not in repo.dirstate:
3989 if not rev and abs not in repo.dirstate:
3986 continue
3990 continue
3987 if opts.get('fullpath'):
3991 if opts.get('fullpath'):
3988 ui.write(repo.wjoin(abs), end)
3992 ui.write(repo.wjoin(abs), end)
3989 else:
3993 else:
3990 ui.write(((pats and m.rel(abs)) or abs), end)
3994 ui.write(((pats and m.rel(abs)) or abs), end)
3991 ret = 0
3995 ret = 0
3992
3996
3993 return ret
3997 return ret
3994
3998
3995 @command('^log|history',
3999 @command('^log|history',
3996 [('f', 'follow', None,
4000 [('f', 'follow', None,
3997 _('follow changeset history, or file history across copies and renames')),
4001 _('follow changeset history, or file history across copies and renames')),
3998 ('', 'follow-first', None,
4002 ('', 'follow-first', None,
3999 _('only follow the first parent of merge changesets (DEPRECATED)')),
4003 _('only follow the first parent of merge changesets (DEPRECATED)')),
4000 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4004 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4001 ('C', 'copies', None, _('show copied files')),
4005 ('C', 'copies', None, _('show copied files')),
4002 ('k', 'keyword', [],
4006 ('k', 'keyword', [],
4003 _('do case-insensitive search for a given text'), _('TEXT')),
4007 _('do case-insensitive search for a given text'), _('TEXT')),
4004 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4008 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4005 ('', 'removed', None, _('include revisions where files were removed')),
4009 ('', 'removed', None, _('include revisions where files were removed')),
4006 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4010 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4007 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4011 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4008 ('', 'only-branch', [],
4012 ('', 'only-branch', [],
4009 _('show only changesets within the given named branch (DEPRECATED)'),
4013 _('show only changesets within the given named branch (DEPRECATED)'),
4010 _('BRANCH')),
4014 _('BRANCH')),
4011 ('b', 'branch', [],
4015 ('b', 'branch', [],
4012 _('show changesets within the given named branch'), _('BRANCH')),
4016 _('show changesets within the given named branch'), _('BRANCH')),
4013 ('P', 'prune', [],
4017 ('P', 'prune', [],
4014 _('do not display revision or any of its ancestors'), _('REV')),
4018 _('do not display revision or any of its ancestors'), _('REV')),
4015 ] + logopts + walkopts,
4019 ] + logopts + walkopts,
4016 _('[OPTION]... [FILE]'))
4020 _('[OPTION]... [FILE]'))
4017 def log(ui, repo, *pats, **opts):
4021 def log(ui, repo, *pats, **opts):
4018 """show revision history of entire repository or files
4022 """show revision history of entire repository or files
4019
4023
4020 Print the revision history of the specified files or the entire
4024 Print the revision history of the specified files or the entire
4021 project.
4025 project.
4022
4026
4023 If no revision range is specified, the default is ``tip:0`` unless
4027 If no revision range is specified, the default is ``tip:0`` unless
4024 --follow is set, in which case the working directory parent is
4028 --follow is set, in which case the working directory parent is
4025 used as the starting revision.
4029 used as the starting revision.
4026
4030
4027 File history is shown without following rename or copy history of
4031 File history is shown without following rename or copy history of
4028 files. Use -f/--follow with a filename to follow history across
4032 files. Use -f/--follow with a filename to follow history across
4029 renames and copies. --follow without a filename will only show
4033 renames and copies. --follow without a filename will only show
4030 ancestors or descendants of the starting revision.
4034 ancestors or descendants of the starting revision.
4031
4035
4032 By default this command prints revision number and changeset id,
4036 By default this command prints revision number and changeset id,
4033 tags, non-trivial parents, user, date and time, and a summary for
4037 tags, non-trivial parents, user, date and time, and a summary for
4034 each commit. When the -v/--verbose switch is used, the list of
4038 each commit. When the -v/--verbose switch is used, the list of
4035 changed files and full commit message are shown.
4039 changed files and full commit message are shown.
4036
4040
4037 With --graph the revisions are shown as an ASCII art DAG with the most
4041 With --graph the revisions are shown as an ASCII art DAG with the most
4038 recent changeset at the top.
4042 recent changeset at the top.
4039 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4043 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4040 and '+' represents a fork where the changeset from the lines below is a
4044 and '+' represents a fork where the changeset from the lines below is a
4041 parent of the 'o' merge on the same same line.
4045 parent of the 'o' merge on the same same line.
4042
4046
4043 .. note::
4047 .. note::
4044
4048
4045 log -p/--patch may generate unexpected diff output for merge
4049 log -p/--patch may generate unexpected diff output for merge
4046 changesets, as it will only compare the merge changeset against
4050 changesets, as it will only compare the merge changeset against
4047 its first parent. Also, only files different from BOTH parents
4051 its first parent. Also, only files different from BOTH parents
4048 will appear in files:.
4052 will appear in files:.
4049
4053
4050 .. note::
4054 .. note::
4051
4055
4052 for performance reasons, log FILE may omit duplicate changes
4056 for performance reasons, log FILE may omit duplicate changes
4053 made on branches and will not show deletions. To see all
4057 made on branches and will not show deletions. To see all
4054 changes including duplicates and deletions, use the --removed
4058 changes including duplicates and deletions, use the --removed
4055 switch.
4059 switch.
4056
4060
4057 .. container:: verbose
4061 .. container:: verbose
4058
4062
4059 Some examples:
4063 Some examples:
4060
4064
4061 - changesets with full descriptions and file lists::
4065 - changesets with full descriptions and file lists::
4062
4066
4063 hg log -v
4067 hg log -v
4064
4068
4065 - changesets ancestral to the working directory::
4069 - changesets ancestral to the working directory::
4066
4070
4067 hg log -f
4071 hg log -f
4068
4072
4069 - last 10 commits on the current branch::
4073 - last 10 commits on the current branch::
4070
4074
4071 hg log -l 10 -b .
4075 hg log -l 10 -b .
4072
4076
4073 - changesets showing all modifications of a file, including removals::
4077 - changesets showing all modifications of a file, including removals::
4074
4078
4075 hg log --removed file.c
4079 hg log --removed file.c
4076
4080
4077 - all changesets that touch a directory, with diffs, excluding merges::
4081 - all changesets that touch a directory, with diffs, excluding merges::
4078
4082
4079 hg log -Mp lib/
4083 hg log -Mp lib/
4080
4084
4081 - all revision numbers that match a keyword::
4085 - all revision numbers that match a keyword::
4082
4086
4083 hg log -k bug --template "{rev}\\n"
4087 hg log -k bug --template "{rev}\\n"
4084
4088
4085 - check if a given changeset is included is a tagged release::
4089 - check if a given changeset is included is a tagged release::
4086
4090
4087 hg log -r "a21ccf and ancestor(1.9)"
4091 hg log -r "a21ccf and ancestor(1.9)"
4088
4092
4089 - find all changesets by some user in a date range::
4093 - find all changesets by some user in a date range::
4090
4094
4091 hg log -k alice -d "may 2008 to jul 2008"
4095 hg log -k alice -d "may 2008 to jul 2008"
4092
4096
4093 - summary of all changesets after the last tag::
4097 - summary of all changesets after the last tag::
4094
4098
4095 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4099 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4096
4100
4097 See :hg:`help dates` for a list of formats valid for -d/--date.
4101 See :hg:`help dates` for a list of formats valid for -d/--date.
4098
4102
4099 See :hg:`help revisions` and :hg:`help revsets` for more about
4103 See :hg:`help revisions` and :hg:`help revsets` for more about
4100 specifying revisions.
4104 specifying revisions.
4101
4105
4102 See :hg:`help templates` for more about pre-packaged styles and
4106 See :hg:`help templates` for more about pre-packaged styles and
4103 specifying custom templates.
4107 specifying custom templates.
4104
4108
4105 Returns 0 on success.
4109 Returns 0 on success.
4106 """
4110 """
4107 if opts.get('graph'):
4111 if opts.get('graph'):
4108 return cmdutil.graphlog(ui, repo, *pats, **opts)
4112 return cmdutil.graphlog(ui, repo, *pats, **opts)
4109
4113
4110 matchfn = scmutil.match(repo[None], pats, opts)
4114 matchfn = scmutil.match(repo[None], pats, opts)
4111 limit = cmdutil.loglimit(opts)
4115 limit = cmdutil.loglimit(opts)
4112 count = 0
4116 count = 0
4113
4117
4114 getrenamed, endrev = None, None
4118 getrenamed, endrev = None, None
4115 if opts.get('copies'):
4119 if opts.get('copies'):
4116 if opts.get('rev'):
4120 if opts.get('rev'):
4117 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4121 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4118 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4122 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4119
4123
4120 df = False
4124 df = False
4121 if opts.get("date"):
4125 if opts.get("date"):
4122 df = util.matchdate(opts["date"])
4126 df = util.matchdate(opts["date"])
4123
4127
4124 branches = opts.get('branch', []) + opts.get('only_branch', [])
4128 branches = opts.get('branch', []) + opts.get('only_branch', [])
4125 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4129 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4126
4130
4127 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4131 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4128 def prep(ctx, fns):
4132 def prep(ctx, fns):
4129 rev = ctx.rev()
4133 rev = ctx.rev()
4130 parents = [p for p in repo.changelog.parentrevs(rev)
4134 parents = [p for p in repo.changelog.parentrevs(rev)
4131 if p != nullrev]
4135 if p != nullrev]
4132 if opts.get('no_merges') and len(parents) == 2:
4136 if opts.get('no_merges') and len(parents) == 2:
4133 return
4137 return
4134 if opts.get('only_merges') and len(parents) != 2:
4138 if opts.get('only_merges') and len(parents) != 2:
4135 return
4139 return
4136 if opts.get('branch') and ctx.branch() not in opts['branch']:
4140 if opts.get('branch') and ctx.branch() not in opts['branch']:
4137 return
4141 return
4138 if df and not df(ctx.date()[0]):
4142 if df and not df(ctx.date()[0]):
4139 return
4143 return
4140
4144
4141 lower = encoding.lower
4145 lower = encoding.lower
4142 if opts.get('user'):
4146 if opts.get('user'):
4143 luser = lower(ctx.user())
4147 luser = lower(ctx.user())
4144 for k in [lower(x) for x in opts['user']]:
4148 for k in [lower(x) for x in opts['user']]:
4145 if (k in luser):
4149 if (k in luser):
4146 break
4150 break
4147 else:
4151 else:
4148 return
4152 return
4149 if opts.get('keyword'):
4153 if opts.get('keyword'):
4150 luser = lower(ctx.user())
4154 luser = lower(ctx.user())
4151 ldesc = lower(ctx.description())
4155 ldesc = lower(ctx.description())
4152 lfiles = lower(" ".join(ctx.files()))
4156 lfiles = lower(" ".join(ctx.files()))
4153 for k in [lower(x) for x in opts['keyword']]:
4157 for k in [lower(x) for x in opts['keyword']]:
4154 if (k in luser or k in ldesc or k in lfiles):
4158 if (k in luser or k in ldesc or k in lfiles):
4155 break
4159 break
4156 else:
4160 else:
4157 return
4161 return
4158
4162
4159 copies = None
4163 copies = None
4160 if getrenamed is not None and rev:
4164 if getrenamed is not None and rev:
4161 copies = []
4165 copies = []
4162 for fn in ctx.files():
4166 for fn in ctx.files():
4163 rename = getrenamed(fn, rev)
4167 rename = getrenamed(fn, rev)
4164 if rename:
4168 if rename:
4165 copies.append((fn, rename[0]))
4169 copies.append((fn, rename[0]))
4166
4170
4167 revmatchfn = None
4171 revmatchfn = None
4168 if opts.get('patch') or opts.get('stat'):
4172 if opts.get('patch') or opts.get('stat'):
4169 if opts.get('follow') or opts.get('follow_first'):
4173 if opts.get('follow') or opts.get('follow_first'):
4170 # note: this might be wrong when following through merges
4174 # note: this might be wrong when following through merges
4171 revmatchfn = scmutil.match(repo[None], fns, default='path')
4175 revmatchfn = scmutil.match(repo[None], fns, default='path')
4172 else:
4176 else:
4173 revmatchfn = matchfn
4177 revmatchfn = matchfn
4174
4178
4175 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4179 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4176
4180
4177 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4181 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4178 if displayer.flush(ctx.rev()):
4182 if displayer.flush(ctx.rev()):
4179 count += 1
4183 count += 1
4180 if count == limit:
4184 if count == limit:
4181 break
4185 break
4182 displayer.close()
4186 displayer.close()
4183
4187
4184 @command('manifest',
4188 @command('manifest',
4185 [('r', 'rev', '', _('revision to display'), _('REV')),
4189 [('r', 'rev', '', _('revision to display'), _('REV')),
4186 ('', 'all', False, _("list files from all revisions"))],
4190 ('', 'all', False, _("list files from all revisions"))],
4187 _('[-r REV]'))
4191 _('[-r REV]'))
4188 def manifest(ui, repo, node=None, rev=None, **opts):
4192 def manifest(ui, repo, node=None, rev=None, **opts):
4189 """output the current or given revision of the project manifest
4193 """output the current or given revision of the project manifest
4190
4194
4191 Print a list of version controlled files for the given revision.
4195 Print a list of version controlled files for the given revision.
4192 If no revision is given, the first parent of the working directory
4196 If no revision is given, the first parent of the working directory
4193 is used, or the null revision if no revision is checked out.
4197 is used, or the null revision if no revision is checked out.
4194
4198
4195 With -v, print file permissions, symlink and executable bits.
4199 With -v, print file permissions, symlink and executable bits.
4196 With --debug, print file revision hashes.
4200 With --debug, print file revision hashes.
4197
4201
4198 If option --all is specified, the list of all files from all revisions
4202 If option --all is specified, the list of all files from all revisions
4199 is printed. This includes deleted and renamed files.
4203 is printed. This includes deleted and renamed files.
4200
4204
4201 Returns 0 on success.
4205 Returns 0 on success.
4202 """
4206 """
4203
4207
4204 fm = ui.formatter('manifest', opts)
4208 fm = ui.formatter('manifest', opts)
4205
4209
4206 if opts.get('all'):
4210 if opts.get('all'):
4207 if rev or node:
4211 if rev or node:
4208 raise util.Abort(_("can't specify a revision with --all"))
4212 raise util.Abort(_("can't specify a revision with --all"))
4209
4213
4210 res = []
4214 res = []
4211 prefix = "data/"
4215 prefix = "data/"
4212 suffix = ".i"
4216 suffix = ".i"
4213 plen = len(prefix)
4217 plen = len(prefix)
4214 slen = len(suffix)
4218 slen = len(suffix)
4215 lock = repo.lock()
4219 lock = repo.lock()
4216 try:
4220 try:
4217 for fn, b, size in repo.store.datafiles():
4221 for fn, b, size in repo.store.datafiles():
4218 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4222 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4219 res.append(fn[plen:-slen])
4223 res.append(fn[plen:-slen])
4220 finally:
4224 finally:
4221 lock.release()
4225 lock.release()
4222 for f in res:
4226 for f in res:
4223 fm.startitem()
4227 fm.startitem()
4224 fm.write("path", '%s\n', f)
4228 fm.write("path", '%s\n', f)
4225 fm.end()
4229 fm.end()
4226 return
4230 return
4227
4231
4228 if rev and node:
4232 if rev and node:
4229 raise util.Abort(_("please specify just one revision"))
4233 raise util.Abort(_("please specify just one revision"))
4230
4234
4231 if not node:
4235 if not node:
4232 node = rev
4236 node = rev
4233
4237
4234 char = {'l': '@', 'x': '*', '': ''}
4238 char = {'l': '@', 'x': '*', '': ''}
4235 mode = {'l': '644', 'x': '755', '': '644'}
4239 mode = {'l': '644', 'x': '755', '': '644'}
4236 ctx = scmutil.revsingle(repo, node)
4240 ctx = scmutil.revsingle(repo, node)
4237 mf = ctx.manifest()
4241 mf = ctx.manifest()
4238 for f in ctx:
4242 for f in ctx:
4239 fm.startitem()
4243 fm.startitem()
4240 fl = ctx[f].flags()
4244 fl = ctx[f].flags()
4241 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4245 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4242 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4246 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4243 fm.write('path', '%s\n', f)
4247 fm.write('path', '%s\n', f)
4244 fm.end()
4248 fm.end()
4245
4249
4246 @command('^merge',
4250 @command('^merge',
4247 [('f', 'force', None,
4251 [('f', 'force', None,
4248 _('force a merge including outstanding changes (DEPRECATED)')),
4252 _('force a merge including outstanding changes (DEPRECATED)')),
4249 ('r', 'rev', '', _('revision to merge'), _('REV')),
4253 ('r', 'rev', '', _('revision to merge'), _('REV')),
4250 ('P', 'preview', None,
4254 ('P', 'preview', None,
4251 _('review revisions to merge (no merge is performed)'))
4255 _('review revisions to merge (no merge is performed)'))
4252 ] + mergetoolopts,
4256 ] + mergetoolopts,
4253 _('[-P] [-f] [[-r] REV]'))
4257 _('[-P] [-f] [[-r] REV]'))
4254 def merge(ui, repo, node=None, **opts):
4258 def merge(ui, repo, node=None, **opts):
4255 """merge working directory with another revision
4259 """merge working directory with another revision
4256
4260
4257 The current working directory is updated with all changes made in
4261 The current working directory is updated with all changes made in
4258 the requested revision since the last common predecessor revision.
4262 the requested revision since the last common predecessor revision.
4259
4263
4260 Files that changed between either parent are marked as changed for
4264 Files that changed between either parent are marked as changed for
4261 the next commit and a commit must be performed before any further
4265 the next commit and a commit must be performed before any further
4262 updates to the repository are allowed. The next commit will have
4266 updates to the repository are allowed. The next commit will have
4263 two parents.
4267 two parents.
4264
4268
4265 ``--tool`` can be used to specify the merge tool used for file
4269 ``--tool`` can be used to specify the merge tool used for file
4266 merges. It overrides the HGMERGE environment variable and your
4270 merges. It overrides the HGMERGE environment variable and your
4267 configuration files. See :hg:`help merge-tools` for options.
4271 configuration files. See :hg:`help merge-tools` for options.
4268
4272
4269 If no revision is specified, the working directory's parent is a
4273 If no revision is specified, the working directory's parent is a
4270 head revision, and the current branch contains exactly one other
4274 head revision, and the current branch contains exactly one other
4271 head, the other head is merged with by default. Otherwise, an
4275 head, the other head is merged with by default. Otherwise, an
4272 explicit revision with which to merge with must be provided.
4276 explicit revision with which to merge with must be provided.
4273
4277
4274 :hg:`resolve` must be used to resolve unresolved files.
4278 :hg:`resolve` must be used to resolve unresolved files.
4275
4279
4276 To undo an uncommitted merge, use :hg:`update --clean .` which
4280 To undo an uncommitted merge, use :hg:`update --clean .` which
4277 will check out a clean copy of the original merge parent, losing
4281 will check out a clean copy of the original merge parent, losing
4278 all changes.
4282 all changes.
4279
4283
4280 Returns 0 on success, 1 if there are unresolved files.
4284 Returns 0 on success, 1 if there are unresolved files.
4281 """
4285 """
4282
4286
4283 if opts.get('rev') and node:
4287 if opts.get('rev') and node:
4284 raise util.Abort(_("please specify just one revision"))
4288 raise util.Abort(_("please specify just one revision"))
4285 if not node:
4289 if not node:
4286 node = opts.get('rev')
4290 node = opts.get('rev')
4287
4291
4288 if node:
4292 if node:
4289 node = scmutil.revsingle(repo, node).node()
4293 node = scmutil.revsingle(repo, node).node()
4290
4294
4291 if not node and repo._bookmarkcurrent:
4295 if not node and repo._bookmarkcurrent:
4292 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4296 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4293 curhead = repo[repo._bookmarkcurrent].node()
4297 curhead = repo[repo._bookmarkcurrent].node()
4294 if len(bmheads) == 2:
4298 if len(bmheads) == 2:
4295 if curhead == bmheads[0]:
4299 if curhead == bmheads[0]:
4296 node = bmheads[1]
4300 node = bmheads[1]
4297 else:
4301 else:
4298 node = bmheads[0]
4302 node = bmheads[0]
4299 elif len(bmheads) > 2:
4303 elif len(bmheads) > 2:
4300 raise util.Abort(_("multiple matching bookmarks to merge - "
4304 raise util.Abort(_("multiple matching bookmarks to merge - "
4301 "please merge with an explicit rev or bookmark"),
4305 "please merge with an explicit rev or bookmark"),
4302 hint=_("run 'hg heads' to see all heads"))
4306 hint=_("run 'hg heads' to see all heads"))
4303 elif len(bmheads) <= 1:
4307 elif len(bmheads) <= 1:
4304 raise util.Abort(_("no matching bookmark to merge - "
4308 raise util.Abort(_("no matching bookmark to merge - "
4305 "please merge with an explicit rev or bookmark"),
4309 "please merge with an explicit rev or bookmark"),
4306 hint=_("run 'hg heads' to see all heads"))
4310 hint=_("run 'hg heads' to see all heads"))
4307
4311
4308 if not node and not repo._bookmarkcurrent:
4312 if not node and not repo._bookmarkcurrent:
4309 branch = repo[None].branch()
4313 branch = repo[None].branch()
4310 bheads = repo.branchheads(branch)
4314 bheads = repo.branchheads(branch)
4311 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4315 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4312
4316
4313 if len(nbhs) > 2:
4317 if len(nbhs) > 2:
4314 raise util.Abort(_("branch '%s' has %d heads - "
4318 raise util.Abort(_("branch '%s' has %d heads - "
4315 "please merge with an explicit rev")
4319 "please merge with an explicit rev")
4316 % (branch, len(bheads)),
4320 % (branch, len(bheads)),
4317 hint=_("run 'hg heads .' to see heads"))
4321 hint=_("run 'hg heads .' to see heads"))
4318
4322
4319 parent = repo.dirstate.p1()
4323 parent = repo.dirstate.p1()
4320 if len(nbhs) <= 1:
4324 if len(nbhs) <= 1:
4321 if len(bheads) > 1:
4325 if len(bheads) > 1:
4322 raise util.Abort(_("heads are bookmarked - "
4326 raise util.Abort(_("heads are bookmarked - "
4323 "please merge with an explicit rev"),
4327 "please merge with an explicit rev"),
4324 hint=_("run 'hg heads' to see all heads"))
4328 hint=_("run 'hg heads' to see all heads"))
4325 if len(repo.heads()) > 1:
4329 if len(repo.heads()) > 1:
4326 raise util.Abort(_("branch '%s' has one head - "
4330 raise util.Abort(_("branch '%s' has one head - "
4327 "please merge with an explicit rev")
4331 "please merge with an explicit rev")
4328 % branch,
4332 % branch,
4329 hint=_("run 'hg heads' to see all heads"))
4333 hint=_("run 'hg heads' to see all heads"))
4330 msg, hint = _('nothing to merge'), None
4334 msg, hint = _('nothing to merge'), None
4331 if parent != repo.lookup(branch):
4335 if parent != repo.lookup(branch):
4332 hint = _("use 'hg update' instead")
4336 hint = _("use 'hg update' instead")
4333 raise util.Abort(msg, hint=hint)
4337 raise util.Abort(msg, hint=hint)
4334
4338
4335 if parent not in bheads:
4339 if parent not in bheads:
4336 raise util.Abort(_('working directory not at a head revision'),
4340 raise util.Abort(_('working directory not at a head revision'),
4337 hint=_("use 'hg update' or merge with an "
4341 hint=_("use 'hg update' or merge with an "
4338 "explicit revision"))
4342 "explicit revision"))
4339 if parent == nbhs[0]:
4343 if parent == nbhs[0]:
4340 node = nbhs[-1]
4344 node = nbhs[-1]
4341 else:
4345 else:
4342 node = nbhs[0]
4346 node = nbhs[0]
4343
4347
4344 if opts.get('preview'):
4348 if opts.get('preview'):
4345 # find nodes that are ancestors of p2 but not of p1
4349 # find nodes that are ancestors of p2 but not of p1
4346 p1 = repo.lookup('.')
4350 p1 = repo.lookup('.')
4347 p2 = repo.lookup(node)
4351 p2 = repo.lookup(node)
4348 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4352 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4349
4353
4350 displayer = cmdutil.show_changeset(ui, repo, opts)
4354 displayer = cmdutil.show_changeset(ui, repo, opts)
4351 for node in nodes:
4355 for node in nodes:
4352 displayer.show(repo[node])
4356 displayer.show(repo[node])
4353 displayer.close()
4357 displayer.close()
4354 return 0
4358 return 0
4355
4359
4356 try:
4360 try:
4357 # ui.forcemerge is an internal variable, do not document
4361 # ui.forcemerge is an internal variable, do not document
4358 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4362 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4359 return hg.merge(repo, node, force=opts.get('force'))
4363 return hg.merge(repo, node, force=opts.get('force'))
4360 finally:
4364 finally:
4361 ui.setconfig('ui', 'forcemerge', '', 'merge')
4365 ui.setconfig('ui', 'forcemerge', '', 'merge')
4362
4366
4363 @command('outgoing|out',
4367 @command('outgoing|out',
4364 [('f', 'force', None, _('run even when the destination is unrelated')),
4368 [('f', 'force', None, _('run even when the destination is unrelated')),
4365 ('r', 'rev', [],
4369 ('r', 'rev', [],
4366 _('a changeset intended to be included in the destination'), _('REV')),
4370 _('a changeset intended to be included in the destination'), _('REV')),
4367 ('n', 'newest-first', None, _('show newest record first')),
4371 ('n', 'newest-first', None, _('show newest record first')),
4368 ('B', 'bookmarks', False, _('compare bookmarks')),
4372 ('B', 'bookmarks', False, _('compare bookmarks')),
4369 ('b', 'branch', [], _('a specific branch you would like to push'),
4373 ('b', 'branch', [], _('a specific branch you would like to push'),
4370 _('BRANCH')),
4374 _('BRANCH')),
4371 ] + logopts + remoteopts + subrepoopts,
4375 ] + logopts + remoteopts + subrepoopts,
4372 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4376 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4373 def outgoing(ui, repo, dest=None, **opts):
4377 def outgoing(ui, repo, dest=None, **opts):
4374 """show changesets not found in the destination
4378 """show changesets not found in the destination
4375
4379
4376 Show changesets not found in the specified destination repository
4380 Show changesets not found in the specified destination repository
4377 or the default push location. These are the changesets that would
4381 or the default push location. These are the changesets that would
4378 be pushed if a push was requested.
4382 be pushed if a push was requested.
4379
4383
4380 See pull for details of valid destination formats.
4384 See pull for details of valid destination formats.
4381
4385
4382 Returns 0 if there are outgoing changes, 1 otherwise.
4386 Returns 0 if there are outgoing changes, 1 otherwise.
4383 """
4387 """
4384 if opts.get('graph'):
4388 if opts.get('graph'):
4385 cmdutil.checkunsupportedgraphflags([], opts)
4389 cmdutil.checkunsupportedgraphflags([], opts)
4386 o = hg._outgoing(ui, repo, dest, opts)
4390 o = hg._outgoing(ui, repo, dest, opts)
4387 if o is None:
4391 if o is None:
4388 return
4392 return
4389
4393
4390 revdag = cmdutil.graphrevs(repo, o, opts)
4394 revdag = cmdutil.graphrevs(repo, o, opts)
4391 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4395 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4392 showparents = [ctx.node() for ctx in repo[None].parents()]
4396 showparents = [ctx.node() for ctx in repo[None].parents()]
4393 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4397 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4394 graphmod.asciiedges)
4398 graphmod.asciiedges)
4395 return 0
4399 return 0
4396
4400
4397 if opts.get('bookmarks'):
4401 if opts.get('bookmarks'):
4398 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4402 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4399 dest, branches = hg.parseurl(dest, opts.get('branch'))
4403 dest, branches = hg.parseurl(dest, opts.get('branch'))
4400 other = hg.peer(repo, opts, dest)
4404 other = hg.peer(repo, opts, dest)
4401 if 'bookmarks' not in other.listkeys('namespaces'):
4405 if 'bookmarks' not in other.listkeys('namespaces'):
4402 ui.warn(_("remote doesn't support bookmarks\n"))
4406 ui.warn(_("remote doesn't support bookmarks\n"))
4403 return 0
4407 return 0
4404 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4408 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4405 return bookmarks.diff(ui, other, repo)
4409 return bookmarks.diff(ui, other, repo)
4406
4410
4407 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4411 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4408 try:
4412 try:
4409 return hg.outgoing(ui, repo, dest, opts)
4413 return hg.outgoing(ui, repo, dest, opts)
4410 finally:
4414 finally:
4411 del repo._subtoppath
4415 del repo._subtoppath
4412
4416
4413 @command('parents',
4417 @command('parents',
4414 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4418 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4415 ] + templateopts,
4419 ] + templateopts,
4416 _('[-r REV] [FILE]'))
4420 _('[-r REV] [FILE]'))
4417 def parents(ui, repo, file_=None, **opts):
4421 def parents(ui, repo, file_=None, **opts):
4418 """show the parents of the working directory or revision
4422 """show the parents of the working directory or revision
4419
4423
4420 Print the working directory's parent revisions. If a revision is
4424 Print the working directory's parent revisions. If a revision is
4421 given via -r/--rev, the parent of that revision will be printed.
4425 given via -r/--rev, the parent of that revision will be printed.
4422 If a file argument is given, the revision in which the file was
4426 If a file argument is given, the revision in which the file was
4423 last changed (before the working directory revision or the
4427 last changed (before the working directory revision or the
4424 argument to --rev if given) is printed.
4428 argument to --rev if given) is printed.
4425
4429
4426 Returns 0 on success.
4430 Returns 0 on success.
4427 """
4431 """
4428
4432
4429 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4433 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4430
4434
4431 if file_:
4435 if file_:
4432 m = scmutil.match(ctx, (file_,), opts)
4436 m = scmutil.match(ctx, (file_,), opts)
4433 if m.anypats() or len(m.files()) != 1:
4437 if m.anypats() or len(m.files()) != 1:
4434 raise util.Abort(_('can only specify an explicit filename'))
4438 raise util.Abort(_('can only specify an explicit filename'))
4435 file_ = m.files()[0]
4439 file_ = m.files()[0]
4436 filenodes = []
4440 filenodes = []
4437 for cp in ctx.parents():
4441 for cp in ctx.parents():
4438 if not cp:
4442 if not cp:
4439 continue
4443 continue
4440 try:
4444 try:
4441 filenodes.append(cp.filenode(file_))
4445 filenodes.append(cp.filenode(file_))
4442 except error.LookupError:
4446 except error.LookupError:
4443 pass
4447 pass
4444 if not filenodes:
4448 if not filenodes:
4445 raise util.Abort(_("'%s' not found in manifest!") % file_)
4449 raise util.Abort(_("'%s' not found in manifest!") % file_)
4446 p = []
4450 p = []
4447 for fn in filenodes:
4451 for fn in filenodes:
4448 fctx = repo.filectx(file_, fileid=fn)
4452 fctx = repo.filectx(file_, fileid=fn)
4449 p.append(fctx.node())
4453 p.append(fctx.node())
4450 else:
4454 else:
4451 p = [cp.node() for cp in ctx.parents()]
4455 p = [cp.node() for cp in ctx.parents()]
4452
4456
4453 displayer = cmdutil.show_changeset(ui, repo, opts)
4457 displayer = cmdutil.show_changeset(ui, repo, opts)
4454 for n in p:
4458 for n in p:
4455 if n != nullid:
4459 if n != nullid:
4456 displayer.show(repo[n])
4460 displayer.show(repo[n])
4457 displayer.close()
4461 displayer.close()
4458
4462
4459 @command('paths', [], _('[NAME]'))
4463 @command('paths', [], _('[NAME]'))
4460 def paths(ui, repo, search=None):
4464 def paths(ui, repo, search=None):
4461 """show aliases for remote repositories
4465 """show aliases for remote repositories
4462
4466
4463 Show definition of symbolic path name NAME. If no name is given,
4467 Show definition of symbolic path name NAME. If no name is given,
4464 show definition of all available names.
4468 show definition of all available names.
4465
4469
4466 Option -q/--quiet suppresses all output when searching for NAME
4470 Option -q/--quiet suppresses all output when searching for NAME
4467 and shows only the path names when listing all definitions.
4471 and shows only the path names when listing all definitions.
4468
4472
4469 Path names are defined in the [paths] section of your
4473 Path names are defined in the [paths] section of your
4470 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4474 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4471 repository, ``.hg/hgrc`` is used, too.
4475 repository, ``.hg/hgrc`` is used, too.
4472
4476
4473 The path names ``default`` and ``default-push`` have a special
4477 The path names ``default`` and ``default-push`` have a special
4474 meaning. When performing a push or pull operation, they are used
4478 meaning. When performing a push or pull operation, they are used
4475 as fallbacks if no location is specified on the command-line.
4479 as fallbacks if no location is specified on the command-line.
4476 When ``default-push`` is set, it will be used for push and
4480 When ``default-push`` is set, it will be used for push and
4477 ``default`` will be used for pull; otherwise ``default`` is used
4481 ``default`` will be used for pull; otherwise ``default`` is used
4478 as the fallback for both. When cloning a repository, the clone
4482 as the fallback for both. When cloning a repository, the clone
4479 source is written as ``default`` in ``.hg/hgrc``. Note that
4483 source is written as ``default`` in ``.hg/hgrc``. Note that
4480 ``default`` and ``default-push`` apply to all inbound (e.g.
4484 ``default`` and ``default-push`` apply to all inbound (e.g.
4481 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4485 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4482 :hg:`bundle`) operations.
4486 :hg:`bundle`) operations.
4483
4487
4484 See :hg:`help urls` for more information.
4488 See :hg:`help urls` for more information.
4485
4489
4486 Returns 0 on success.
4490 Returns 0 on success.
4487 """
4491 """
4488 if search:
4492 if search:
4489 for name, path in ui.configitems("paths"):
4493 for name, path in ui.configitems("paths"):
4490 if name == search:
4494 if name == search:
4491 ui.status("%s\n" % util.hidepassword(path))
4495 ui.status("%s\n" % util.hidepassword(path))
4492 return
4496 return
4493 if not ui.quiet:
4497 if not ui.quiet:
4494 ui.warn(_("not found!\n"))
4498 ui.warn(_("not found!\n"))
4495 return 1
4499 return 1
4496 else:
4500 else:
4497 for name, path in ui.configitems("paths"):
4501 for name, path in ui.configitems("paths"):
4498 if ui.quiet:
4502 if ui.quiet:
4499 ui.write("%s\n" % name)
4503 ui.write("%s\n" % name)
4500 else:
4504 else:
4501 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4505 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4502
4506
4503 @command('phase',
4507 @command('phase',
4504 [('p', 'public', False, _('set changeset phase to public')),
4508 [('p', 'public', False, _('set changeset phase to public')),
4505 ('d', 'draft', False, _('set changeset phase to draft')),
4509 ('d', 'draft', False, _('set changeset phase to draft')),
4506 ('s', 'secret', False, _('set changeset phase to secret')),
4510 ('s', 'secret', False, _('set changeset phase to secret')),
4507 ('f', 'force', False, _('allow to move boundary backward')),
4511 ('f', 'force', False, _('allow to move boundary backward')),
4508 ('r', 'rev', [], _('target revision'), _('REV')),
4512 ('r', 'rev', [], _('target revision'), _('REV')),
4509 ],
4513 ],
4510 _('[-p|-d|-s] [-f] [-r] REV...'))
4514 _('[-p|-d|-s] [-f] [-r] REV...'))
4511 def phase(ui, repo, *revs, **opts):
4515 def phase(ui, repo, *revs, **opts):
4512 """set or show the current phase name
4516 """set or show the current phase name
4513
4517
4514 With no argument, show the phase name of specified revisions.
4518 With no argument, show the phase name of specified revisions.
4515
4519
4516 With one of -p/--public, -d/--draft or -s/--secret, change the
4520 With one of -p/--public, -d/--draft or -s/--secret, change the
4517 phase value of the specified revisions.
4521 phase value of the specified revisions.
4518
4522
4519 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4523 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4520 lower phase to an higher phase. Phases are ordered as follows::
4524 lower phase to an higher phase. Phases are ordered as follows::
4521
4525
4522 public < draft < secret
4526 public < draft < secret
4523
4527
4524 Returns 0 on success, 1 if no phases were changed or some could not
4528 Returns 0 on success, 1 if no phases were changed or some could not
4525 be changed.
4529 be changed.
4526 """
4530 """
4527 # search for a unique phase argument
4531 # search for a unique phase argument
4528 targetphase = None
4532 targetphase = None
4529 for idx, name in enumerate(phases.phasenames):
4533 for idx, name in enumerate(phases.phasenames):
4530 if opts[name]:
4534 if opts[name]:
4531 if targetphase is not None:
4535 if targetphase is not None:
4532 raise util.Abort(_('only one phase can be specified'))
4536 raise util.Abort(_('only one phase can be specified'))
4533 targetphase = idx
4537 targetphase = idx
4534
4538
4535 # look for specified revision
4539 # look for specified revision
4536 revs = list(revs)
4540 revs = list(revs)
4537 revs.extend(opts['rev'])
4541 revs.extend(opts['rev'])
4538 if not revs:
4542 if not revs:
4539 raise util.Abort(_('no revisions specified'))
4543 raise util.Abort(_('no revisions specified'))
4540
4544
4541 revs = scmutil.revrange(repo, revs)
4545 revs = scmutil.revrange(repo, revs)
4542
4546
4543 lock = None
4547 lock = None
4544 ret = 0
4548 ret = 0
4545 if targetphase is None:
4549 if targetphase is None:
4546 # display
4550 # display
4547 for r in revs:
4551 for r in revs:
4548 ctx = repo[r]
4552 ctx = repo[r]
4549 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4553 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4550 else:
4554 else:
4551 lock = repo.lock()
4555 lock = repo.lock()
4552 try:
4556 try:
4553 # set phase
4557 # set phase
4554 if not revs:
4558 if not revs:
4555 raise util.Abort(_('empty revision set'))
4559 raise util.Abort(_('empty revision set'))
4556 nodes = [repo[r].node() for r in revs]
4560 nodes = [repo[r].node() for r in revs]
4557 olddata = repo._phasecache.getphaserevs(repo)[:]
4561 olddata = repo._phasecache.getphaserevs(repo)[:]
4558 phases.advanceboundary(repo, targetphase, nodes)
4562 phases.advanceboundary(repo, targetphase, nodes)
4559 if opts['force']:
4563 if opts['force']:
4560 phases.retractboundary(repo, targetphase, nodes)
4564 phases.retractboundary(repo, targetphase, nodes)
4561 finally:
4565 finally:
4562 lock.release()
4566 lock.release()
4563 # moving revision from public to draft may hide them
4567 # moving revision from public to draft may hide them
4564 # We have to check result on an unfiltered repository
4568 # We have to check result on an unfiltered repository
4565 unfi = repo.unfiltered()
4569 unfi = repo.unfiltered()
4566 newdata = repo._phasecache.getphaserevs(unfi)
4570 newdata = repo._phasecache.getphaserevs(unfi)
4567 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4571 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4568 cl = unfi.changelog
4572 cl = unfi.changelog
4569 rejected = [n for n in nodes
4573 rejected = [n for n in nodes
4570 if newdata[cl.rev(n)] < targetphase]
4574 if newdata[cl.rev(n)] < targetphase]
4571 if rejected:
4575 if rejected:
4572 ui.warn(_('cannot move %i changesets to a higher '
4576 ui.warn(_('cannot move %i changesets to a higher '
4573 'phase, use --force\n') % len(rejected))
4577 'phase, use --force\n') % len(rejected))
4574 ret = 1
4578 ret = 1
4575 if changes:
4579 if changes:
4576 msg = _('phase changed for %i changesets\n') % changes
4580 msg = _('phase changed for %i changesets\n') % changes
4577 if ret:
4581 if ret:
4578 ui.status(msg)
4582 ui.status(msg)
4579 else:
4583 else:
4580 ui.note(msg)
4584 ui.note(msg)
4581 else:
4585 else:
4582 ui.warn(_('no phases changed\n'))
4586 ui.warn(_('no phases changed\n'))
4583 ret = 1
4587 ret = 1
4584 return ret
4588 return ret
4585
4589
4586 def postincoming(ui, repo, modheads, optupdate, checkout):
4590 def postincoming(ui, repo, modheads, optupdate, checkout):
4587 if modheads == 0:
4591 if modheads == 0:
4588 return
4592 return
4589 if optupdate:
4593 if optupdate:
4590 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4594 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4591 try:
4595 try:
4592 ret = hg.update(repo, checkout)
4596 ret = hg.update(repo, checkout)
4593 except util.Abort, inst:
4597 except util.Abort, inst:
4594 ui.warn(_("not updating: %s\n") % str(inst))
4598 ui.warn(_("not updating: %s\n") % str(inst))
4595 if inst.hint:
4599 if inst.hint:
4596 ui.warn(_("(%s)\n") % inst.hint)
4600 ui.warn(_("(%s)\n") % inst.hint)
4597 return 0
4601 return 0
4598 if not ret and not checkout:
4602 if not ret and not checkout:
4599 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4603 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4600 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4604 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4601 return ret
4605 return ret
4602 if modheads > 1:
4606 if modheads > 1:
4603 currentbranchheads = len(repo.branchheads())
4607 currentbranchheads = len(repo.branchheads())
4604 if currentbranchheads == modheads:
4608 if currentbranchheads == modheads:
4605 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4609 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4606 elif currentbranchheads > 1:
4610 elif currentbranchheads > 1:
4607 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4611 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4608 "merge)\n"))
4612 "merge)\n"))
4609 else:
4613 else:
4610 ui.status(_("(run 'hg heads' to see heads)\n"))
4614 ui.status(_("(run 'hg heads' to see heads)\n"))
4611 else:
4615 else:
4612 ui.status(_("(run 'hg update' to get a working copy)\n"))
4616 ui.status(_("(run 'hg update' to get a working copy)\n"))
4613
4617
4614 @command('^pull',
4618 @command('^pull',
4615 [('u', 'update', None,
4619 [('u', 'update', None,
4616 _('update to new branch head if changesets were pulled')),
4620 _('update to new branch head if changesets were pulled')),
4617 ('f', 'force', None, _('run even when remote repository is unrelated')),
4621 ('f', 'force', None, _('run even when remote repository is unrelated')),
4618 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4622 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4619 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4623 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4620 ('b', 'branch', [], _('a specific branch you would like to pull'),
4624 ('b', 'branch', [], _('a specific branch you would like to pull'),
4621 _('BRANCH')),
4625 _('BRANCH')),
4622 ] + remoteopts,
4626 ] + remoteopts,
4623 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4627 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4624 def pull(ui, repo, source="default", **opts):
4628 def pull(ui, repo, source="default", **opts):
4625 """pull changes from the specified source
4629 """pull changes from the specified source
4626
4630
4627 Pull changes from a remote repository to a local one.
4631 Pull changes from a remote repository to a local one.
4628
4632
4629 This finds all changes from the repository at the specified path
4633 This finds all changes from the repository at the specified path
4630 or URL and adds them to a local repository (the current one unless
4634 or URL and adds them to a local repository (the current one unless
4631 -R is specified). By default, this does not update the copy of the
4635 -R is specified). By default, this does not update the copy of the
4632 project in the working directory.
4636 project in the working directory.
4633
4637
4634 Use :hg:`incoming` if you want to see what would have been added
4638 Use :hg:`incoming` if you want to see what would have been added
4635 by a pull at the time you issued this command. If you then decide
4639 by a pull at the time you issued this command. If you then decide
4636 to add those changes to the repository, you should use :hg:`pull
4640 to add those changes to the repository, you should use :hg:`pull
4637 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4641 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4638
4642
4639 If SOURCE is omitted, the 'default' path will be used.
4643 If SOURCE is omitted, the 'default' path will be used.
4640 See :hg:`help urls` for more information.
4644 See :hg:`help urls` for more information.
4641
4645
4642 Returns 0 on success, 1 if an update had unresolved files.
4646 Returns 0 on success, 1 if an update had unresolved files.
4643 """
4647 """
4644 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4648 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4645 other = hg.peer(repo, opts, source)
4649 other = hg.peer(repo, opts, source)
4646 try:
4650 try:
4647 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4651 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4648 revs, checkout = hg.addbranchrevs(repo, other, branches,
4652 revs, checkout = hg.addbranchrevs(repo, other, branches,
4649 opts.get('rev'))
4653 opts.get('rev'))
4650
4654
4651 remotebookmarks = other.listkeys('bookmarks')
4655 remotebookmarks = other.listkeys('bookmarks')
4652
4656
4653 if opts.get('bookmark'):
4657 if opts.get('bookmark'):
4654 if not revs:
4658 if not revs:
4655 revs = []
4659 revs = []
4656 for b in opts['bookmark']:
4660 for b in opts['bookmark']:
4657 if b not in remotebookmarks:
4661 if b not in remotebookmarks:
4658 raise util.Abort(_('remote bookmark %s not found!') % b)
4662 raise util.Abort(_('remote bookmark %s not found!') % b)
4659 revs.append(remotebookmarks[b])
4663 revs.append(remotebookmarks[b])
4660
4664
4661 if revs:
4665 if revs:
4662 try:
4666 try:
4663 revs = [other.lookup(rev) for rev in revs]
4667 revs = [other.lookup(rev) for rev in revs]
4664 except error.CapabilityError:
4668 except error.CapabilityError:
4665 err = _("other repository doesn't support revision lookup, "
4669 err = _("other repository doesn't support revision lookup, "
4666 "so a rev cannot be specified.")
4670 "so a rev cannot be specified.")
4667 raise util.Abort(err)
4671 raise util.Abort(err)
4668
4672
4669 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4673 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4670 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4674 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4671 if checkout:
4675 if checkout:
4672 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4676 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4673 repo._subtoppath = source
4677 repo._subtoppath = source
4674 try:
4678 try:
4675 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4679 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4676
4680
4677 finally:
4681 finally:
4678 del repo._subtoppath
4682 del repo._subtoppath
4679
4683
4680 # update specified bookmarks
4684 # update specified bookmarks
4681 if opts.get('bookmark'):
4685 if opts.get('bookmark'):
4682 marks = repo._bookmarks
4686 marks = repo._bookmarks
4683 for b in opts['bookmark']:
4687 for b in opts['bookmark']:
4684 # explicit pull overrides local bookmark if any
4688 # explicit pull overrides local bookmark if any
4685 ui.status(_("importing bookmark %s\n") % b)
4689 ui.status(_("importing bookmark %s\n") % b)
4686 marks[b] = repo[remotebookmarks[b]].node()
4690 marks[b] = repo[remotebookmarks[b]].node()
4687 marks.write()
4691 marks.write()
4688 finally:
4692 finally:
4689 other.close()
4693 other.close()
4690 return ret
4694 return ret
4691
4695
4692 @command('^push',
4696 @command('^push',
4693 [('f', 'force', None, _('force push')),
4697 [('f', 'force', None, _('force push')),
4694 ('r', 'rev', [],
4698 ('r', 'rev', [],
4695 _('a changeset intended to be included in the destination'),
4699 _('a changeset intended to be included in the destination'),
4696 _('REV')),
4700 _('REV')),
4697 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4701 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4698 ('b', 'branch', [],
4702 ('b', 'branch', [],
4699 _('a specific branch you would like to push'), _('BRANCH')),
4703 _('a specific branch you would like to push'), _('BRANCH')),
4700 ('', 'new-branch', False, _('allow pushing a new branch')),
4704 ('', 'new-branch', False, _('allow pushing a new branch')),
4701 ] + remoteopts,
4705 ] + remoteopts,
4702 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4706 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4703 def push(ui, repo, dest=None, **opts):
4707 def push(ui, repo, dest=None, **opts):
4704 """push changes to the specified destination
4708 """push changes to the specified destination
4705
4709
4706 Push changesets from the local repository to the specified
4710 Push changesets from the local repository to the specified
4707 destination.
4711 destination.
4708
4712
4709 This operation is symmetrical to pull: it is identical to a pull
4713 This operation is symmetrical to pull: it is identical to a pull
4710 in the destination repository from the current one.
4714 in the destination repository from the current one.
4711
4715
4712 By default, push will not allow creation of new heads at the
4716 By default, push will not allow creation of new heads at the
4713 destination, since multiple heads would make it unclear which head
4717 destination, since multiple heads would make it unclear which head
4714 to use. In this situation, it is recommended to pull and merge
4718 to use. In this situation, it is recommended to pull and merge
4715 before pushing.
4719 before pushing.
4716
4720
4717 Use --new-branch if you want to allow push to create a new named
4721 Use --new-branch if you want to allow push to create a new named
4718 branch that is not present at the destination. This allows you to
4722 branch that is not present at the destination. This allows you to
4719 only create a new branch without forcing other changes.
4723 only create a new branch without forcing other changes.
4720
4724
4721 .. note::
4725 .. note::
4722
4726
4723 Extra care should be taken with the -f/--force option,
4727 Extra care should be taken with the -f/--force option,
4724 which will push all new heads on all branches, an action which will
4728 which will push all new heads on all branches, an action which will
4725 almost always cause confusion for collaborators.
4729 almost always cause confusion for collaborators.
4726
4730
4727 If -r/--rev is used, the specified revision and all its ancestors
4731 If -r/--rev is used, the specified revision and all its ancestors
4728 will be pushed to the remote repository.
4732 will be pushed to the remote repository.
4729
4733
4730 If -B/--bookmark is used, the specified bookmarked revision, its
4734 If -B/--bookmark is used, the specified bookmarked revision, its
4731 ancestors, and the bookmark will be pushed to the remote
4735 ancestors, and the bookmark will be pushed to the remote
4732 repository.
4736 repository.
4733
4737
4734 Please see :hg:`help urls` for important details about ``ssh://``
4738 Please see :hg:`help urls` for important details about ``ssh://``
4735 URLs. If DESTINATION is omitted, a default path will be used.
4739 URLs. If DESTINATION is omitted, a default path will be used.
4736
4740
4737 Returns 0 if push was successful, 1 if nothing to push.
4741 Returns 0 if push was successful, 1 if nothing to push.
4738 """
4742 """
4739
4743
4740 if opts.get('bookmark'):
4744 if opts.get('bookmark'):
4741 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4745 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4742 for b in opts['bookmark']:
4746 for b in opts['bookmark']:
4743 # translate -B options to -r so changesets get pushed
4747 # translate -B options to -r so changesets get pushed
4744 if b in repo._bookmarks:
4748 if b in repo._bookmarks:
4745 opts.setdefault('rev', []).append(b)
4749 opts.setdefault('rev', []).append(b)
4746 else:
4750 else:
4747 # if we try to push a deleted bookmark, translate it to null
4751 # if we try to push a deleted bookmark, translate it to null
4748 # this lets simultaneous -r, -b options continue working
4752 # this lets simultaneous -r, -b options continue working
4749 opts.setdefault('rev', []).append("null")
4753 opts.setdefault('rev', []).append("null")
4750
4754
4751 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4755 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4752 dest, branches = hg.parseurl(dest, opts.get('branch'))
4756 dest, branches = hg.parseurl(dest, opts.get('branch'))
4753 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4757 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4754 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4758 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4755 try:
4759 try:
4756 other = hg.peer(repo, opts, dest)
4760 other = hg.peer(repo, opts, dest)
4757 except error.RepoError:
4761 except error.RepoError:
4758 if dest == "default-push":
4762 if dest == "default-push":
4759 raise util.Abort(_("default repository not configured!"),
4763 raise util.Abort(_("default repository not configured!"),
4760 hint=_('see the "path" section in "hg help config"'))
4764 hint=_('see the "path" section in "hg help config"'))
4761 else:
4765 else:
4762 raise
4766 raise
4763
4767
4764 if revs:
4768 if revs:
4765 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4769 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4766
4770
4767 repo._subtoppath = dest
4771 repo._subtoppath = dest
4768 try:
4772 try:
4769 # push subrepos depth-first for coherent ordering
4773 # push subrepos depth-first for coherent ordering
4770 c = repo['']
4774 c = repo['']
4771 subs = c.substate # only repos that are committed
4775 subs = c.substate # only repos that are committed
4772 for s in sorted(subs):
4776 for s in sorted(subs):
4773 if c.sub(s).push(opts) == 0:
4777 if c.sub(s).push(opts) == 0:
4774 return False
4778 return False
4775 finally:
4779 finally:
4776 del repo._subtoppath
4780 del repo._subtoppath
4777 result = repo.push(other, opts.get('force'), revs=revs,
4781 result = repo.push(other, opts.get('force'), revs=revs,
4778 newbranch=opts.get('new_branch'))
4782 newbranch=opts.get('new_branch'))
4779
4783
4780 result = not result
4784 result = not result
4781
4785
4782 if opts.get('bookmark'):
4786 if opts.get('bookmark'):
4783 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4787 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4784 if bresult == 2:
4788 if bresult == 2:
4785 return 2
4789 return 2
4786 if not result and bresult:
4790 if not result and bresult:
4787 result = 2
4791 result = 2
4788
4792
4789 return result
4793 return result
4790
4794
4791 @command('recover', [])
4795 @command('recover', [])
4792 def recover(ui, repo):
4796 def recover(ui, repo):
4793 """roll back an interrupted transaction
4797 """roll back an interrupted transaction
4794
4798
4795 Recover from an interrupted commit or pull.
4799 Recover from an interrupted commit or pull.
4796
4800
4797 This command tries to fix the repository status after an
4801 This command tries to fix the repository status after an
4798 interrupted operation. It should only be necessary when Mercurial
4802 interrupted operation. It should only be necessary when Mercurial
4799 suggests it.
4803 suggests it.
4800
4804
4801 Returns 0 if successful, 1 if nothing to recover or verify fails.
4805 Returns 0 if successful, 1 if nothing to recover or verify fails.
4802 """
4806 """
4803 if repo.recover():
4807 if repo.recover():
4804 return hg.verify(repo)
4808 return hg.verify(repo)
4805 return 1
4809 return 1
4806
4810
4807 @command('^remove|rm',
4811 @command('^remove|rm',
4808 [('A', 'after', None, _('record delete for missing files')),
4812 [('A', 'after', None, _('record delete for missing files')),
4809 ('f', 'force', None,
4813 ('f', 'force', None,
4810 _('remove (and delete) file even if added or modified')),
4814 _('remove (and delete) file even if added or modified')),
4811 ] + walkopts,
4815 ] + walkopts,
4812 _('[OPTION]... FILE...'))
4816 _('[OPTION]... FILE...'))
4813 def remove(ui, repo, *pats, **opts):
4817 def remove(ui, repo, *pats, **opts):
4814 """remove the specified files on the next commit
4818 """remove the specified files on the next commit
4815
4819
4816 Schedule the indicated files for removal from the current branch.
4820 Schedule the indicated files for removal from the current branch.
4817
4821
4818 This command schedules the files to be removed at the next commit.
4822 This command schedules the files to be removed at the next commit.
4819 To undo a remove before that, see :hg:`revert`. To undo added
4823 To undo a remove before that, see :hg:`revert`. To undo added
4820 files, see :hg:`forget`.
4824 files, see :hg:`forget`.
4821
4825
4822 .. container:: verbose
4826 .. container:: verbose
4823
4827
4824 -A/--after can be used to remove only files that have already
4828 -A/--after can be used to remove only files that have already
4825 been deleted, -f/--force can be used to force deletion, and -Af
4829 been deleted, -f/--force can be used to force deletion, and -Af
4826 can be used to remove files from the next revision without
4830 can be used to remove files from the next revision without
4827 deleting them from the working directory.
4831 deleting them from the working directory.
4828
4832
4829 The following table details the behavior of remove for different
4833 The following table details the behavior of remove for different
4830 file states (columns) and option combinations (rows). The file
4834 file states (columns) and option combinations (rows). The file
4831 states are Added [A], Clean [C], Modified [M] and Missing [!]
4835 states are Added [A], Clean [C], Modified [M] and Missing [!]
4832 (as reported by :hg:`status`). The actions are Warn, Remove
4836 (as reported by :hg:`status`). The actions are Warn, Remove
4833 (from branch) and Delete (from disk):
4837 (from branch) and Delete (from disk):
4834
4838
4835 ========= == == == ==
4839 ========= == == == ==
4836 opt/state A C M !
4840 opt/state A C M !
4837 ========= == == == ==
4841 ========= == == == ==
4838 none W RD W R
4842 none W RD W R
4839 -f R RD RD R
4843 -f R RD RD R
4840 -A W W W R
4844 -A W W W R
4841 -Af R R R R
4845 -Af R R R R
4842 ========= == == == ==
4846 ========= == == == ==
4843
4847
4844 Note that remove never deletes files in Added [A] state from the
4848 Note that remove never deletes files in Added [A] state from the
4845 working directory, not even if option --force is specified.
4849 working directory, not even if option --force is specified.
4846
4850
4847 Returns 0 on success, 1 if any warnings encountered.
4851 Returns 0 on success, 1 if any warnings encountered.
4848 """
4852 """
4849
4853
4850 ret = 0
4854 ret = 0
4851 after, force = opts.get('after'), opts.get('force')
4855 after, force = opts.get('after'), opts.get('force')
4852 if not pats and not after:
4856 if not pats and not after:
4853 raise util.Abort(_('no files specified'))
4857 raise util.Abort(_('no files specified'))
4854
4858
4855 m = scmutil.match(repo[None], pats, opts)
4859 m = scmutil.match(repo[None], pats, opts)
4856 s = repo.status(match=m, clean=True)
4860 s = repo.status(match=m, clean=True)
4857 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4861 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4858
4862
4859 # warn about failure to delete explicit files/dirs
4863 # warn about failure to delete explicit files/dirs
4860 wctx = repo[None]
4864 wctx = repo[None]
4861 for f in m.files():
4865 for f in m.files():
4862 if f in repo.dirstate or f in wctx.dirs():
4866 if f in repo.dirstate or f in wctx.dirs():
4863 continue
4867 continue
4864 if os.path.exists(m.rel(f)):
4868 if os.path.exists(m.rel(f)):
4865 if os.path.isdir(m.rel(f)):
4869 if os.path.isdir(m.rel(f)):
4866 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4870 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4867 else:
4871 else:
4868 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4872 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4869 # missing files will generate a warning elsewhere
4873 # missing files will generate a warning elsewhere
4870 ret = 1
4874 ret = 1
4871
4875
4872 if force:
4876 if force:
4873 list = modified + deleted + clean + added
4877 list = modified + deleted + clean + added
4874 elif after:
4878 elif after:
4875 list = deleted
4879 list = deleted
4876 for f in modified + added + clean:
4880 for f in modified + added + clean:
4877 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4881 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4878 ret = 1
4882 ret = 1
4879 else:
4883 else:
4880 list = deleted + clean
4884 list = deleted + clean
4881 for f in modified:
4885 for f in modified:
4882 ui.warn(_('not removing %s: file is modified (use -f'
4886 ui.warn(_('not removing %s: file is modified (use -f'
4883 ' to force removal)\n') % m.rel(f))
4887 ' to force removal)\n') % m.rel(f))
4884 ret = 1
4888 ret = 1
4885 for f in added:
4889 for f in added:
4886 ui.warn(_('not removing %s: file has been marked for add'
4890 ui.warn(_('not removing %s: file has been marked for add'
4887 ' (use forget to undo)\n') % m.rel(f))
4891 ' (use forget to undo)\n') % m.rel(f))
4888 ret = 1
4892 ret = 1
4889
4893
4890 for f in sorted(list):
4894 for f in sorted(list):
4891 if ui.verbose or not m.exact(f):
4895 if ui.verbose or not m.exact(f):
4892 ui.status(_('removing %s\n') % m.rel(f))
4896 ui.status(_('removing %s\n') % m.rel(f))
4893
4897
4894 wlock = repo.wlock()
4898 wlock = repo.wlock()
4895 try:
4899 try:
4896 if not after:
4900 if not after:
4897 for f in list:
4901 for f in list:
4898 if f in added:
4902 if f in added:
4899 continue # we never unlink added files on remove
4903 continue # we never unlink added files on remove
4900 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4904 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4901 repo[None].forget(list)
4905 repo[None].forget(list)
4902 finally:
4906 finally:
4903 wlock.release()
4907 wlock.release()
4904
4908
4905 return ret
4909 return ret
4906
4910
4907 @command('rename|move|mv',
4911 @command('rename|move|mv',
4908 [('A', 'after', None, _('record a rename that has already occurred')),
4912 [('A', 'after', None, _('record a rename that has already occurred')),
4909 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4913 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4910 ] + walkopts + dryrunopts,
4914 ] + walkopts + dryrunopts,
4911 _('[OPTION]... SOURCE... DEST'))
4915 _('[OPTION]... SOURCE... DEST'))
4912 def rename(ui, repo, *pats, **opts):
4916 def rename(ui, repo, *pats, **opts):
4913 """rename files; equivalent of copy + remove
4917 """rename files; equivalent of copy + remove
4914
4918
4915 Mark dest as copies of sources; mark sources for deletion. If dest
4919 Mark dest as copies of sources; mark sources for deletion. If dest
4916 is a directory, copies are put in that directory. If dest is a
4920 is a directory, copies are put in that directory. If dest is a
4917 file, there can only be one source.
4921 file, there can only be one source.
4918
4922
4919 By default, this command copies the contents of files as they
4923 By default, this command copies the contents of files as they
4920 exist in the working directory. If invoked with -A/--after, the
4924 exist in the working directory. If invoked with -A/--after, the
4921 operation is recorded, but no copying is performed.
4925 operation is recorded, but no copying is performed.
4922
4926
4923 This command takes effect at the next commit. To undo a rename
4927 This command takes effect at the next commit. To undo a rename
4924 before that, see :hg:`revert`.
4928 before that, see :hg:`revert`.
4925
4929
4926 Returns 0 on success, 1 if errors are encountered.
4930 Returns 0 on success, 1 if errors are encountered.
4927 """
4931 """
4928 wlock = repo.wlock(False)
4932 wlock = repo.wlock(False)
4929 try:
4933 try:
4930 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4934 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4931 finally:
4935 finally:
4932 wlock.release()
4936 wlock.release()
4933
4937
4934 @command('resolve',
4938 @command('resolve',
4935 [('a', 'all', None, _('select all unresolved files')),
4939 [('a', 'all', None, _('select all unresolved files')),
4936 ('l', 'list', None, _('list state of files needing merge')),
4940 ('l', 'list', None, _('list state of files needing merge')),
4937 ('m', 'mark', None, _('mark files as resolved')),
4941 ('m', 'mark', None, _('mark files as resolved')),
4938 ('u', 'unmark', None, _('mark files as unresolved')),
4942 ('u', 'unmark', None, _('mark files as unresolved')),
4939 ('n', 'no-status', None, _('hide status prefix'))]
4943 ('n', 'no-status', None, _('hide status prefix'))]
4940 + mergetoolopts + walkopts,
4944 + mergetoolopts + walkopts,
4941 _('[OPTION]... [FILE]...'))
4945 _('[OPTION]... [FILE]...'))
4942 def resolve(ui, repo, *pats, **opts):
4946 def resolve(ui, repo, *pats, **opts):
4943 """redo merges or set/view the merge status of files
4947 """redo merges or set/view the merge status of files
4944
4948
4945 Merges with unresolved conflicts are often the result of
4949 Merges with unresolved conflicts are often the result of
4946 non-interactive merging using the ``internal:merge`` configuration
4950 non-interactive merging using the ``internal:merge`` configuration
4947 setting, or a command-line merge tool like ``diff3``. The resolve
4951 setting, or a command-line merge tool like ``diff3``. The resolve
4948 command is used to manage the files involved in a merge, after
4952 command is used to manage the files involved in a merge, after
4949 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4953 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4950 working directory must have two parents). See :hg:`help
4954 working directory must have two parents). See :hg:`help
4951 merge-tools` for information on configuring merge tools.
4955 merge-tools` for information on configuring merge tools.
4952
4956
4953 The resolve command can be used in the following ways:
4957 The resolve command can be used in the following ways:
4954
4958
4955 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4959 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4956 files, discarding any previous merge attempts. Re-merging is not
4960 files, discarding any previous merge attempts. Re-merging is not
4957 performed for files already marked as resolved. Use ``--all/-a``
4961 performed for files already marked as resolved. Use ``--all/-a``
4958 to select all unresolved files. ``--tool`` can be used to specify
4962 to select all unresolved files. ``--tool`` can be used to specify
4959 the merge tool used for the given files. It overrides the HGMERGE
4963 the merge tool used for the given files. It overrides the HGMERGE
4960 environment variable and your configuration files. Previous file
4964 environment variable and your configuration files. Previous file
4961 contents are saved with a ``.orig`` suffix.
4965 contents are saved with a ``.orig`` suffix.
4962
4966
4963 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4967 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4964 (e.g. after having manually fixed-up the files). The default is
4968 (e.g. after having manually fixed-up the files). The default is
4965 to mark all unresolved files.
4969 to mark all unresolved files.
4966
4970
4967 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4971 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4968 default is to mark all resolved files.
4972 default is to mark all resolved files.
4969
4973
4970 - :hg:`resolve -l`: list files which had or still have conflicts.
4974 - :hg:`resolve -l`: list files which had or still have conflicts.
4971 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4975 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4972
4976
4973 Note that Mercurial will not let you commit files with unresolved
4977 Note that Mercurial will not let you commit files with unresolved
4974 merge conflicts. You must use :hg:`resolve -m ...` before you can
4978 merge conflicts. You must use :hg:`resolve -m ...` before you can
4975 commit after a conflicting merge.
4979 commit after a conflicting merge.
4976
4980
4977 Returns 0 on success, 1 if any files fail a resolve attempt.
4981 Returns 0 on success, 1 if any files fail a resolve attempt.
4978 """
4982 """
4979
4983
4980 all, mark, unmark, show, nostatus = \
4984 all, mark, unmark, show, nostatus = \
4981 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4985 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4982
4986
4983 if (show and (mark or unmark)) or (mark and unmark):
4987 if (show and (mark or unmark)) or (mark and unmark):
4984 raise util.Abort(_("too many options specified"))
4988 raise util.Abort(_("too many options specified"))
4985 if pats and all:
4989 if pats and all:
4986 raise util.Abort(_("can't specify --all and patterns"))
4990 raise util.Abort(_("can't specify --all and patterns"))
4987 if not (all or pats or show or mark or unmark):
4991 if not (all or pats or show or mark or unmark):
4988 raise util.Abort(_('no files or directories specified; '
4992 raise util.Abort(_('no files or directories specified; '
4989 'use --all to remerge all files'))
4993 'use --all to remerge all files'))
4990
4994
4991 ms = mergemod.mergestate(repo)
4995 ms = mergemod.mergestate(repo)
4992 m = scmutil.match(repo[None], pats, opts)
4996 m = scmutil.match(repo[None], pats, opts)
4993 ret = 0
4997 ret = 0
4994
4998
4995 for f in ms:
4999 for f in ms:
4996 if m(f):
5000 if m(f):
4997 if show:
5001 if show:
4998 if nostatus:
5002 if nostatus:
4999 ui.write("%s\n" % f)
5003 ui.write("%s\n" % f)
5000 else:
5004 else:
5001 ui.write("%s %s\n" % (ms[f].upper(), f),
5005 ui.write("%s %s\n" % (ms[f].upper(), f),
5002 label='resolve.' +
5006 label='resolve.' +
5003 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5007 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5004 elif mark:
5008 elif mark:
5005 ms.mark(f, "r")
5009 ms.mark(f, "r")
5006 elif unmark:
5010 elif unmark:
5007 ms.mark(f, "u")
5011 ms.mark(f, "u")
5008 else:
5012 else:
5009 wctx = repo[None]
5013 wctx = repo[None]
5010
5014
5011 # backup pre-resolve (merge uses .orig for its own purposes)
5015 # backup pre-resolve (merge uses .orig for its own purposes)
5012 a = repo.wjoin(f)
5016 a = repo.wjoin(f)
5013 util.copyfile(a, a + ".resolve")
5017 util.copyfile(a, a + ".resolve")
5014
5018
5015 try:
5019 try:
5016 # resolve file
5020 # resolve file
5017 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5021 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5018 'resolve')
5022 'resolve')
5019 if ms.resolve(f, wctx):
5023 if ms.resolve(f, wctx):
5020 ret = 1
5024 ret = 1
5021 finally:
5025 finally:
5022 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5026 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5023 ms.commit()
5027 ms.commit()
5024
5028
5025 # replace filemerge's .orig file with our resolve file
5029 # replace filemerge's .orig file with our resolve file
5026 util.rename(a + ".resolve", a + ".orig")
5030 util.rename(a + ".resolve", a + ".orig")
5027
5031
5028 ms.commit()
5032 ms.commit()
5029 return ret
5033 return ret
5030
5034
5031 @command('revert',
5035 @command('revert',
5032 [('a', 'all', None, _('revert all changes when no arguments given')),
5036 [('a', 'all', None, _('revert all changes when no arguments given')),
5033 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5037 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5034 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5038 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5035 ('C', 'no-backup', None, _('do not save backup copies of files')),
5039 ('C', 'no-backup', None, _('do not save backup copies of files')),
5036 ] + walkopts + dryrunopts,
5040 ] + walkopts + dryrunopts,
5037 _('[OPTION]... [-r REV] [NAME]...'))
5041 _('[OPTION]... [-r REV] [NAME]...'))
5038 def revert(ui, repo, *pats, **opts):
5042 def revert(ui, repo, *pats, **opts):
5039 """restore files to their checkout state
5043 """restore files to their checkout state
5040
5044
5041 .. note::
5045 .. note::
5042
5046
5043 To check out earlier revisions, you should use :hg:`update REV`.
5047 To check out earlier revisions, you should use :hg:`update REV`.
5044 To cancel an uncommitted merge (and lose your changes),
5048 To cancel an uncommitted merge (and lose your changes),
5045 use :hg:`update --clean .`.
5049 use :hg:`update --clean .`.
5046
5050
5047 With no revision specified, revert the specified files or directories
5051 With no revision specified, revert the specified files or directories
5048 to the contents they had in the parent of the working directory.
5052 to the contents they had in the parent of the working directory.
5049 This restores the contents of files to an unmodified
5053 This restores the contents of files to an unmodified
5050 state and unschedules adds, removes, copies, and renames. If the
5054 state and unschedules adds, removes, copies, and renames. If the
5051 working directory has two parents, you must explicitly specify a
5055 working directory has two parents, you must explicitly specify a
5052 revision.
5056 revision.
5053
5057
5054 Using the -r/--rev or -d/--date options, revert the given files or
5058 Using the -r/--rev or -d/--date options, revert the given files or
5055 directories to their states as of a specific revision. Because
5059 directories to their states as of a specific revision. Because
5056 revert does not change the working directory parents, this will
5060 revert does not change the working directory parents, this will
5057 cause these files to appear modified. This can be helpful to "back
5061 cause these files to appear modified. This can be helpful to "back
5058 out" some or all of an earlier change. See :hg:`backout` for a
5062 out" some or all of an earlier change. See :hg:`backout` for a
5059 related method.
5063 related method.
5060
5064
5061 Modified files are saved with a .orig suffix before reverting.
5065 Modified files are saved with a .orig suffix before reverting.
5062 To disable these backups, use --no-backup.
5066 To disable these backups, use --no-backup.
5063
5067
5064 See :hg:`help dates` for a list of formats valid for -d/--date.
5068 See :hg:`help dates` for a list of formats valid for -d/--date.
5065
5069
5066 Returns 0 on success.
5070 Returns 0 on success.
5067 """
5071 """
5068
5072
5069 if opts.get("date"):
5073 if opts.get("date"):
5070 if opts.get("rev"):
5074 if opts.get("rev"):
5071 raise util.Abort(_("you can't specify a revision and a date"))
5075 raise util.Abort(_("you can't specify a revision and a date"))
5072 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5076 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5073
5077
5074 parent, p2 = repo.dirstate.parents()
5078 parent, p2 = repo.dirstate.parents()
5075 if not opts.get('rev') and p2 != nullid:
5079 if not opts.get('rev') and p2 != nullid:
5076 # revert after merge is a trap for new users (issue2915)
5080 # revert after merge is a trap for new users (issue2915)
5077 raise util.Abort(_('uncommitted merge with no revision specified'),
5081 raise util.Abort(_('uncommitted merge with no revision specified'),
5078 hint=_('use "hg update" or see "hg help revert"'))
5082 hint=_('use "hg update" or see "hg help revert"'))
5079
5083
5080 ctx = scmutil.revsingle(repo, opts.get('rev'))
5084 ctx = scmutil.revsingle(repo, opts.get('rev'))
5081
5085
5082 if not pats and not opts.get('all'):
5086 if not pats and not opts.get('all'):
5083 msg = _("no files or directories specified")
5087 msg = _("no files or directories specified")
5084 if p2 != nullid:
5088 if p2 != nullid:
5085 hint = _("uncommitted merge, use --all to discard all changes,"
5089 hint = _("uncommitted merge, use --all to discard all changes,"
5086 " or 'hg update -C .' to abort the merge")
5090 " or 'hg update -C .' to abort the merge")
5087 raise util.Abort(msg, hint=hint)
5091 raise util.Abort(msg, hint=hint)
5088 dirty = util.any(repo.status())
5092 dirty = util.any(repo.status())
5089 node = ctx.node()
5093 node = ctx.node()
5090 if node != parent:
5094 if node != parent:
5091 if dirty:
5095 if dirty:
5092 hint = _("uncommitted changes, use --all to discard all"
5096 hint = _("uncommitted changes, use --all to discard all"
5093 " changes, or 'hg update %s' to update") % ctx.rev()
5097 " changes, or 'hg update %s' to update") % ctx.rev()
5094 else:
5098 else:
5095 hint = _("use --all to revert all files,"
5099 hint = _("use --all to revert all files,"
5096 " or 'hg update %s' to update") % ctx.rev()
5100 " or 'hg update %s' to update") % ctx.rev()
5097 elif dirty:
5101 elif dirty:
5098 hint = _("uncommitted changes, use --all to discard all changes")
5102 hint = _("uncommitted changes, use --all to discard all changes")
5099 else:
5103 else:
5100 hint = _("use --all to revert all files")
5104 hint = _("use --all to revert all files")
5101 raise util.Abort(msg, hint=hint)
5105 raise util.Abort(msg, hint=hint)
5102
5106
5103 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5107 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5104
5108
5105 @command('rollback', dryrunopts +
5109 @command('rollback', dryrunopts +
5106 [('f', 'force', False, _('ignore safety measures'))])
5110 [('f', 'force', False, _('ignore safety measures'))])
5107 def rollback(ui, repo, **opts):
5111 def rollback(ui, repo, **opts):
5108 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5112 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5109
5113
5110 Please use :hg:`commit --amend` instead of rollback to correct
5114 Please use :hg:`commit --amend` instead of rollback to correct
5111 mistakes in the last commit.
5115 mistakes in the last commit.
5112
5116
5113 This command should be used with care. There is only one level of
5117 This command should be used with care. There is only one level of
5114 rollback, and there is no way to undo a rollback. It will also
5118 rollback, and there is no way to undo a rollback. It will also
5115 restore the dirstate at the time of the last transaction, losing
5119 restore the dirstate at the time of the last transaction, losing
5116 any dirstate changes since that time. This command does not alter
5120 any dirstate changes since that time. This command does not alter
5117 the working directory.
5121 the working directory.
5118
5122
5119 Transactions are used to encapsulate the effects of all commands
5123 Transactions are used to encapsulate the effects of all commands
5120 that create new changesets or propagate existing changesets into a
5124 that create new changesets or propagate existing changesets into a
5121 repository.
5125 repository.
5122
5126
5123 .. container:: verbose
5127 .. container:: verbose
5124
5128
5125 For example, the following commands are transactional, and their
5129 For example, the following commands are transactional, and their
5126 effects can be rolled back:
5130 effects can be rolled back:
5127
5131
5128 - commit
5132 - commit
5129 - import
5133 - import
5130 - pull
5134 - pull
5131 - push (with this repository as the destination)
5135 - push (with this repository as the destination)
5132 - unbundle
5136 - unbundle
5133
5137
5134 To avoid permanent data loss, rollback will refuse to rollback a
5138 To avoid permanent data loss, rollback will refuse to rollback a
5135 commit transaction if it isn't checked out. Use --force to
5139 commit transaction if it isn't checked out. Use --force to
5136 override this protection.
5140 override this protection.
5137
5141
5138 This command is not intended for use on public repositories. Once
5142 This command is not intended for use on public repositories. Once
5139 changes are visible for pull by other users, rolling a transaction
5143 changes are visible for pull by other users, rolling a transaction
5140 back locally is ineffective (someone else may already have pulled
5144 back locally is ineffective (someone else may already have pulled
5141 the changes). Furthermore, a race is possible with readers of the
5145 the changes). Furthermore, a race is possible with readers of the
5142 repository; for example an in-progress pull from the repository
5146 repository; for example an in-progress pull from the repository
5143 may fail if a rollback is performed.
5147 may fail if a rollback is performed.
5144
5148
5145 Returns 0 on success, 1 if no rollback data is available.
5149 Returns 0 on success, 1 if no rollback data is available.
5146 """
5150 """
5147 return repo.rollback(dryrun=opts.get('dry_run'),
5151 return repo.rollback(dryrun=opts.get('dry_run'),
5148 force=opts.get('force'))
5152 force=opts.get('force'))
5149
5153
5150 @command('root', [])
5154 @command('root', [])
5151 def root(ui, repo):
5155 def root(ui, repo):
5152 """print the root (top) of the current working directory
5156 """print the root (top) of the current working directory
5153
5157
5154 Print the root directory of the current repository.
5158 Print the root directory of the current repository.
5155
5159
5156 Returns 0 on success.
5160 Returns 0 on success.
5157 """
5161 """
5158 ui.write(repo.root + "\n")
5162 ui.write(repo.root + "\n")
5159
5163
5160 @command('^serve',
5164 @command('^serve',
5161 [('A', 'accesslog', '', _('name of access log file to write to'),
5165 [('A', 'accesslog', '', _('name of access log file to write to'),
5162 _('FILE')),
5166 _('FILE')),
5163 ('d', 'daemon', None, _('run server in background')),
5167 ('d', 'daemon', None, _('run server in background')),
5164 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5168 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5165 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5169 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5166 # use string type, then we can check if something was passed
5170 # use string type, then we can check if something was passed
5167 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5171 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5168 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5172 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5169 _('ADDR')),
5173 _('ADDR')),
5170 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5174 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5171 _('PREFIX')),
5175 _('PREFIX')),
5172 ('n', 'name', '',
5176 ('n', 'name', '',
5173 _('name to show in web pages (default: working directory)'), _('NAME')),
5177 _('name to show in web pages (default: working directory)'), _('NAME')),
5174 ('', 'web-conf', '',
5178 ('', 'web-conf', '',
5175 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5179 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5176 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5180 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5177 _('FILE')),
5181 _('FILE')),
5178 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5182 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5179 ('', 'stdio', None, _('for remote clients')),
5183 ('', 'stdio', None, _('for remote clients')),
5180 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5184 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5181 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5185 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5182 ('', 'style', '', _('template style to use'), _('STYLE')),
5186 ('', 'style', '', _('template style to use'), _('STYLE')),
5183 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5187 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5184 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5188 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5185 _('[OPTION]...'))
5189 _('[OPTION]...'))
5186 def serve(ui, repo, **opts):
5190 def serve(ui, repo, **opts):
5187 """start stand-alone webserver
5191 """start stand-alone webserver
5188
5192
5189 Start a local HTTP repository browser and pull server. You can use
5193 Start a local HTTP repository browser and pull server. You can use
5190 this for ad-hoc sharing and browsing of repositories. It is
5194 this for ad-hoc sharing and browsing of repositories. It is
5191 recommended to use a real web server to serve a repository for
5195 recommended to use a real web server to serve a repository for
5192 longer periods of time.
5196 longer periods of time.
5193
5197
5194 Please note that the server does not implement access control.
5198 Please note that the server does not implement access control.
5195 This means that, by default, anybody can read from the server and
5199 This means that, by default, anybody can read from the server and
5196 nobody can write to it by default. Set the ``web.allow_push``
5200 nobody can write to it by default. Set the ``web.allow_push``
5197 option to ``*`` to allow everybody to push to the server. You
5201 option to ``*`` to allow everybody to push to the server. You
5198 should use a real web server if you need to authenticate users.
5202 should use a real web server if you need to authenticate users.
5199
5203
5200 By default, the server logs accesses to stdout and errors to
5204 By default, the server logs accesses to stdout and errors to
5201 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5205 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5202 files.
5206 files.
5203
5207
5204 To have the server choose a free port number to listen on, specify
5208 To have the server choose a free port number to listen on, specify
5205 a port number of 0; in this case, the server will print the port
5209 a port number of 0; in this case, the server will print the port
5206 number it uses.
5210 number it uses.
5207
5211
5208 Returns 0 on success.
5212 Returns 0 on success.
5209 """
5213 """
5210
5214
5211 if opts["stdio"] and opts["cmdserver"]:
5215 if opts["stdio"] and opts["cmdserver"]:
5212 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5216 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5213
5217
5214 def checkrepo():
5218 def checkrepo():
5215 if repo is None:
5219 if repo is None:
5216 raise error.RepoError(_("there is no Mercurial repository here"
5220 raise error.RepoError(_("there is no Mercurial repository here"
5217 " (.hg not found)"))
5221 " (.hg not found)"))
5218
5222
5219 if opts["stdio"]:
5223 if opts["stdio"]:
5220 checkrepo()
5224 checkrepo()
5221 s = sshserver.sshserver(ui, repo)
5225 s = sshserver.sshserver(ui, repo)
5222 s.serve_forever()
5226 s.serve_forever()
5223
5227
5224 if opts["cmdserver"]:
5228 if opts["cmdserver"]:
5225 s = commandserver.server(ui, repo, opts["cmdserver"])
5229 s = commandserver.server(ui, repo, opts["cmdserver"])
5226 return s.serve()
5230 return s.serve()
5227
5231
5228 # this way we can check if something was given in the command-line
5232 # this way we can check if something was given in the command-line
5229 if opts.get('port'):
5233 if opts.get('port'):
5230 opts['port'] = util.getport(opts.get('port'))
5234 opts['port'] = util.getport(opts.get('port'))
5231
5235
5232 baseui = repo and repo.baseui or ui
5236 baseui = repo and repo.baseui or ui
5233 optlist = ("name templates style address port prefix ipv6"
5237 optlist = ("name templates style address port prefix ipv6"
5234 " accesslog errorlog certificate encoding")
5238 " accesslog errorlog certificate encoding")
5235 for o in optlist.split():
5239 for o in optlist.split():
5236 val = opts.get(o, '')
5240 val = opts.get(o, '')
5237 if val in (None, ''): # should check against default options instead
5241 if val in (None, ''): # should check against default options instead
5238 continue
5242 continue
5239 baseui.setconfig("web", o, val, 'serve')
5243 baseui.setconfig("web", o, val, 'serve')
5240 if repo and repo.ui != baseui:
5244 if repo and repo.ui != baseui:
5241 repo.ui.setconfig("web", o, val, 'serve')
5245 repo.ui.setconfig("web", o, val, 'serve')
5242
5246
5243 o = opts.get('web_conf') or opts.get('webdir_conf')
5247 o = opts.get('web_conf') or opts.get('webdir_conf')
5244 if not o:
5248 if not o:
5245 if not repo:
5249 if not repo:
5246 raise error.RepoError(_("there is no Mercurial repository"
5250 raise error.RepoError(_("there is no Mercurial repository"
5247 " here (.hg not found)"))
5251 " here (.hg not found)"))
5248 o = repo
5252 o = repo
5249
5253
5250 app = hgweb.hgweb(o, baseui=baseui)
5254 app = hgweb.hgweb(o, baseui=baseui)
5251 service = httpservice(ui, app, opts)
5255 service = httpservice(ui, app, opts)
5252 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5256 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5253
5257
5254 class httpservice(object):
5258 class httpservice(object):
5255 def __init__(self, ui, app, opts):
5259 def __init__(self, ui, app, opts):
5256 self.ui = ui
5260 self.ui = ui
5257 self.app = app
5261 self.app = app
5258 self.opts = opts
5262 self.opts = opts
5259
5263
5260 def init(self):
5264 def init(self):
5261 util.setsignalhandler()
5265 util.setsignalhandler()
5262 self.httpd = hgweb_server.create_server(self.ui, self.app)
5266 self.httpd = hgweb_server.create_server(self.ui, self.app)
5263
5267
5264 if self.opts['port'] and not self.ui.verbose:
5268 if self.opts['port'] and not self.ui.verbose:
5265 return
5269 return
5266
5270
5267 if self.httpd.prefix:
5271 if self.httpd.prefix:
5268 prefix = self.httpd.prefix.strip('/') + '/'
5272 prefix = self.httpd.prefix.strip('/') + '/'
5269 else:
5273 else:
5270 prefix = ''
5274 prefix = ''
5271
5275
5272 port = ':%d' % self.httpd.port
5276 port = ':%d' % self.httpd.port
5273 if port == ':80':
5277 if port == ':80':
5274 port = ''
5278 port = ''
5275
5279
5276 bindaddr = self.httpd.addr
5280 bindaddr = self.httpd.addr
5277 if bindaddr == '0.0.0.0':
5281 if bindaddr == '0.0.0.0':
5278 bindaddr = '*'
5282 bindaddr = '*'
5279 elif ':' in bindaddr: # IPv6
5283 elif ':' in bindaddr: # IPv6
5280 bindaddr = '[%s]' % bindaddr
5284 bindaddr = '[%s]' % bindaddr
5281
5285
5282 fqaddr = self.httpd.fqaddr
5286 fqaddr = self.httpd.fqaddr
5283 if ':' in fqaddr:
5287 if ':' in fqaddr:
5284 fqaddr = '[%s]' % fqaddr
5288 fqaddr = '[%s]' % fqaddr
5285 if self.opts['port']:
5289 if self.opts['port']:
5286 write = self.ui.status
5290 write = self.ui.status
5287 else:
5291 else:
5288 write = self.ui.write
5292 write = self.ui.write
5289 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5293 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5290 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5294 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5291
5295
5292 def run(self):
5296 def run(self):
5293 self.httpd.serve_forever()
5297 self.httpd.serve_forever()
5294
5298
5295
5299
5296 @command('^status|st',
5300 @command('^status|st',
5297 [('A', 'all', None, _('show status of all files')),
5301 [('A', 'all', None, _('show status of all files')),
5298 ('m', 'modified', None, _('show only modified files')),
5302 ('m', 'modified', None, _('show only modified files')),
5299 ('a', 'added', None, _('show only added files')),
5303 ('a', 'added', None, _('show only added files')),
5300 ('r', 'removed', None, _('show only removed files')),
5304 ('r', 'removed', None, _('show only removed files')),
5301 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5305 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5302 ('c', 'clean', None, _('show only files without changes')),
5306 ('c', 'clean', None, _('show only files without changes')),
5303 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5307 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5304 ('i', 'ignored', None, _('show only ignored files')),
5308 ('i', 'ignored', None, _('show only ignored files')),
5305 ('n', 'no-status', None, _('hide status prefix')),
5309 ('n', 'no-status', None, _('hide status prefix')),
5306 ('C', 'copies', None, _('show source of copied files')),
5310 ('C', 'copies', None, _('show source of copied files')),
5307 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5311 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5308 ('', 'rev', [], _('show difference from revision'), _('REV')),
5312 ('', 'rev', [], _('show difference from revision'), _('REV')),
5309 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5313 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5310 ] + walkopts + subrepoopts,
5314 ] + walkopts + subrepoopts,
5311 _('[OPTION]... [FILE]...'))
5315 _('[OPTION]... [FILE]...'))
5312 def status(ui, repo, *pats, **opts):
5316 def status(ui, repo, *pats, **opts):
5313 """show changed files in the working directory
5317 """show changed files in the working directory
5314
5318
5315 Show status of files in the repository. If names are given, only
5319 Show status of files in the repository. If names are given, only
5316 files that match are shown. Files that are clean or ignored or
5320 files that match are shown. Files that are clean or ignored or
5317 the source of a copy/move operation, are not listed unless
5321 the source of a copy/move operation, are not listed unless
5318 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5322 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5319 Unless options described with "show only ..." are given, the
5323 Unless options described with "show only ..." are given, the
5320 options -mardu are used.
5324 options -mardu are used.
5321
5325
5322 Option -q/--quiet hides untracked (unknown and ignored) files
5326 Option -q/--quiet hides untracked (unknown and ignored) files
5323 unless explicitly requested with -u/--unknown or -i/--ignored.
5327 unless explicitly requested with -u/--unknown or -i/--ignored.
5324
5328
5325 .. note::
5329 .. note::
5326
5330
5327 status may appear to disagree with diff if permissions have
5331 status may appear to disagree with diff if permissions have
5328 changed or a merge has occurred. The standard diff format does
5332 changed or a merge has occurred. The standard diff format does
5329 not report permission changes and diff only reports changes
5333 not report permission changes and diff only reports changes
5330 relative to one merge parent.
5334 relative to one merge parent.
5331
5335
5332 If one revision is given, it is used as the base revision.
5336 If one revision is given, it is used as the base revision.
5333 If two revisions are given, the differences between them are
5337 If two revisions are given, the differences between them are
5334 shown. The --change option can also be used as a shortcut to list
5338 shown. The --change option can also be used as a shortcut to list
5335 the changed files of a revision from its first parent.
5339 the changed files of a revision from its first parent.
5336
5340
5337 The codes used to show the status of files are::
5341 The codes used to show the status of files are::
5338
5342
5339 M = modified
5343 M = modified
5340 A = added
5344 A = added
5341 R = removed
5345 R = removed
5342 C = clean
5346 C = clean
5343 ! = missing (deleted by non-hg command, but still tracked)
5347 ! = missing (deleted by non-hg command, but still tracked)
5344 ? = not tracked
5348 ? = not tracked
5345 I = ignored
5349 I = ignored
5346 = origin of the previous file (with --copies)
5350 = origin of the previous file (with --copies)
5347
5351
5348 .. container:: verbose
5352 .. container:: verbose
5349
5353
5350 Examples:
5354 Examples:
5351
5355
5352 - show changes in the working directory relative to a
5356 - show changes in the working directory relative to a
5353 changeset::
5357 changeset::
5354
5358
5355 hg status --rev 9353
5359 hg status --rev 9353
5356
5360
5357 - show all changes including copies in an existing changeset::
5361 - show all changes including copies in an existing changeset::
5358
5362
5359 hg status --copies --change 9353
5363 hg status --copies --change 9353
5360
5364
5361 - get a NUL separated list of added files, suitable for xargs::
5365 - get a NUL separated list of added files, suitable for xargs::
5362
5366
5363 hg status -an0
5367 hg status -an0
5364
5368
5365 Returns 0 on success.
5369 Returns 0 on success.
5366 """
5370 """
5367
5371
5368 revs = opts.get('rev')
5372 revs = opts.get('rev')
5369 change = opts.get('change')
5373 change = opts.get('change')
5370
5374
5371 if revs and change:
5375 if revs and change:
5372 msg = _('cannot specify --rev and --change at the same time')
5376 msg = _('cannot specify --rev and --change at the same time')
5373 raise util.Abort(msg)
5377 raise util.Abort(msg)
5374 elif change:
5378 elif change:
5375 node2 = scmutil.revsingle(repo, change, None).node()
5379 node2 = scmutil.revsingle(repo, change, None).node()
5376 node1 = repo[node2].p1().node()
5380 node1 = repo[node2].p1().node()
5377 else:
5381 else:
5378 node1, node2 = scmutil.revpair(repo, revs)
5382 node1, node2 = scmutil.revpair(repo, revs)
5379
5383
5380 cwd = (pats and repo.getcwd()) or ''
5384 cwd = (pats and repo.getcwd()) or ''
5381 end = opts.get('print0') and '\0' or '\n'
5385 end = opts.get('print0') and '\0' or '\n'
5382 copy = {}
5386 copy = {}
5383 states = 'modified added removed deleted unknown ignored clean'.split()
5387 states = 'modified added removed deleted unknown ignored clean'.split()
5384 show = [k for k in states if opts.get(k)]
5388 show = [k for k in states if opts.get(k)]
5385 if opts.get('all'):
5389 if opts.get('all'):
5386 show += ui.quiet and (states[:4] + ['clean']) or states
5390 show += ui.quiet and (states[:4] + ['clean']) or states
5387 if not show:
5391 if not show:
5388 show = ui.quiet and states[:4] or states[:5]
5392 show = ui.quiet and states[:4] or states[:5]
5389
5393
5390 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5394 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5391 'ignored' in show, 'clean' in show, 'unknown' in show,
5395 'ignored' in show, 'clean' in show, 'unknown' in show,
5392 opts.get('subrepos'))
5396 opts.get('subrepos'))
5393 changestates = zip(states, 'MAR!?IC', stat)
5397 changestates = zip(states, 'MAR!?IC', stat)
5394
5398
5395 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5399 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5396 copy = copies.pathcopies(repo[node1], repo[node2])
5400 copy = copies.pathcopies(repo[node1], repo[node2])
5397
5401
5398 fm = ui.formatter('status', opts)
5402 fm = ui.formatter('status', opts)
5399 fmt = '%s' + end
5403 fmt = '%s' + end
5400 showchar = not opts.get('no_status')
5404 showchar = not opts.get('no_status')
5401
5405
5402 for state, char, files in changestates:
5406 for state, char, files in changestates:
5403 if state in show:
5407 if state in show:
5404 label = 'status.' + state
5408 label = 'status.' + state
5405 for f in files:
5409 for f in files:
5406 fm.startitem()
5410 fm.startitem()
5407 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5411 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5408 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5412 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5409 if f in copy:
5413 if f in copy:
5410 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5414 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5411 label='status.copied')
5415 label='status.copied')
5412 fm.end()
5416 fm.end()
5413
5417
5414 @command('^summary|sum',
5418 @command('^summary|sum',
5415 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5419 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5416 def summary(ui, repo, **opts):
5420 def summary(ui, repo, **opts):
5417 """summarize working directory state
5421 """summarize working directory state
5418
5422
5419 This generates a brief summary of the working directory state,
5423 This generates a brief summary of the working directory state,
5420 including parents, branch, commit status, and available updates.
5424 including parents, branch, commit status, and available updates.
5421
5425
5422 With the --remote option, this will check the default paths for
5426 With the --remote option, this will check the default paths for
5423 incoming and outgoing changes. This can be time-consuming.
5427 incoming and outgoing changes. This can be time-consuming.
5424
5428
5425 Returns 0 on success.
5429 Returns 0 on success.
5426 """
5430 """
5427
5431
5428 ctx = repo[None]
5432 ctx = repo[None]
5429 parents = ctx.parents()
5433 parents = ctx.parents()
5430 pnode = parents[0].node()
5434 pnode = parents[0].node()
5431 marks = []
5435 marks = []
5432
5436
5433 for p in parents:
5437 for p in parents:
5434 # label with log.changeset (instead of log.parent) since this
5438 # label with log.changeset (instead of log.parent) since this
5435 # shows a working directory parent *changeset*:
5439 # shows a working directory parent *changeset*:
5436 # i18n: column positioning for "hg summary"
5440 # i18n: column positioning for "hg summary"
5437 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5441 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5438 label='log.changeset changeset.%s' % p.phasestr())
5442 label='log.changeset changeset.%s' % p.phasestr())
5439 ui.write(' '.join(p.tags()), label='log.tag')
5443 ui.write(' '.join(p.tags()), label='log.tag')
5440 if p.bookmarks():
5444 if p.bookmarks():
5441 marks.extend(p.bookmarks())
5445 marks.extend(p.bookmarks())
5442 if p.rev() == -1:
5446 if p.rev() == -1:
5443 if not len(repo):
5447 if not len(repo):
5444 ui.write(_(' (empty repository)'))
5448 ui.write(_(' (empty repository)'))
5445 else:
5449 else:
5446 ui.write(_(' (no revision checked out)'))
5450 ui.write(_(' (no revision checked out)'))
5447 ui.write('\n')
5451 ui.write('\n')
5448 if p.description():
5452 if p.description():
5449 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5453 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5450 label='log.summary')
5454 label='log.summary')
5451
5455
5452 branch = ctx.branch()
5456 branch = ctx.branch()
5453 bheads = repo.branchheads(branch)
5457 bheads = repo.branchheads(branch)
5454 # i18n: column positioning for "hg summary"
5458 # i18n: column positioning for "hg summary"
5455 m = _('branch: %s\n') % branch
5459 m = _('branch: %s\n') % branch
5456 if branch != 'default':
5460 if branch != 'default':
5457 ui.write(m, label='log.branch')
5461 ui.write(m, label='log.branch')
5458 else:
5462 else:
5459 ui.status(m, label='log.branch')
5463 ui.status(m, label='log.branch')
5460
5464
5461 if marks:
5465 if marks:
5462 current = repo._bookmarkcurrent
5466 current = repo._bookmarkcurrent
5463 # i18n: column positioning for "hg summary"
5467 # i18n: column positioning for "hg summary"
5464 ui.write(_('bookmarks:'), label='log.bookmark')
5468 ui.write(_('bookmarks:'), label='log.bookmark')
5465 if current is not None:
5469 if current is not None:
5466 if current in marks:
5470 if current in marks:
5467 ui.write(' *' + current, label='bookmarks.current')
5471 ui.write(' *' + current, label='bookmarks.current')
5468 marks.remove(current)
5472 marks.remove(current)
5469 else:
5473 else:
5470 ui.write(' [%s]' % current, label='bookmarks.current')
5474 ui.write(' [%s]' % current, label='bookmarks.current')
5471 for m in marks:
5475 for m in marks:
5472 ui.write(' ' + m, label='log.bookmark')
5476 ui.write(' ' + m, label='log.bookmark')
5473 ui.write('\n', label='log.bookmark')
5477 ui.write('\n', label='log.bookmark')
5474
5478
5475 st = list(repo.status(unknown=True))[:6]
5479 st = list(repo.status(unknown=True))[:6]
5476
5480
5477 c = repo.dirstate.copies()
5481 c = repo.dirstate.copies()
5478 copied, renamed = [], []
5482 copied, renamed = [], []
5479 for d, s in c.iteritems():
5483 for d, s in c.iteritems():
5480 if s in st[2]:
5484 if s in st[2]:
5481 st[2].remove(s)
5485 st[2].remove(s)
5482 renamed.append(d)
5486 renamed.append(d)
5483 else:
5487 else:
5484 copied.append(d)
5488 copied.append(d)
5485 if d in st[1]:
5489 if d in st[1]:
5486 st[1].remove(d)
5490 st[1].remove(d)
5487 st.insert(3, renamed)
5491 st.insert(3, renamed)
5488 st.insert(4, copied)
5492 st.insert(4, copied)
5489
5493
5490 ms = mergemod.mergestate(repo)
5494 ms = mergemod.mergestate(repo)
5491 st.append([f for f in ms if ms[f] == 'u'])
5495 st.append([f for f in ms if ms[f] == 'u'])
5492
5496
5493 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5497 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5494 st.append(subs)
5498 st.append(subs)
5495
5499
5496 labels = [ui.label(_('%d modified'), 'status.modified'),
5500 labels = [ui.label(_('%d modified'), 'status.modified'),
5497 ui.label(_('%d added'), 'status.added'),
5501 ui.label(_('%d added'), 'status.added'),
5498 ui.label(_('%d removed'), 'status.removed'),
5502 ui.label(_('%d removed'), 'status.removed'),
5499 ui.label(_('%d renamed'), 'status.copied'),
5503 ui.label(_('%d renamed'), 'status.copied'),
5500 ui.label(_('%d copied'), 'status.copied'),
5504 ui.label(_('%d copied'), 'status.copied'),
5501 ui.label(_('%d deleted'), 'status.deleted'),
5505 ui.label(_('%d deleted'), 'status.deleted'),
5502 ui.label(_('%d unknown'), 'status.unknown'),
5506 ui.label(_('%d unknown'), 'status.unknown'),
5503 ui.label(_('%d ignored'), 'status.ignored'),
5507 ui.label(_('%d ignored'), 'status.ignored'),
5504 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5508 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5505 ui.label(_('%d subrepos'), 'status.modified')]
5509 ui.label(_('%d subrepos'), 'status.modified')]
5506 t = []
5510 t = []
5507 for s, l in zip(st, labels):
5511 for s, l in zip(st, labels):
5508 if s:
5512 if s:
5509 t.append(l % len(s))
5513 t.append(l % len(s))
5510
5514
5511 t = ', '.join(t)
5515 t = ', '.join(t)
5512 cleanworkdir = False
5516 cleanworkdir = False
5513
5517
5514 if repo.vfs.exists('updatestate'):
5518 if repo.vfs.exists('updatestate'):
5515 t += _(' (interrupted update)')
5519 t += _(' (interrupted update)')
5516 elif len(parents) > 1:
5520 elif len(parents) > 1:
5517 t += _(' (merge)')
5521 t += _(' (merge)')
5518 elif branch != parents[0].branch():
5522 elif branch != parents[0].branch():
5519 t += _(' (new branch)')
5523 t += _(' (new branch)')
5520 elif (parents[0].closesbranch() and
5524 elif (parents[0].closesbranch() and
5521 pnode in repo.branchheads(branch, closed=True)):
5525 pnode in repo.branchheads(branch, closed=True)):
5522 t += _(' (head closed)')
5526 t += _(' (head closed)')
5523 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5527 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5524 t += _(' (clean)')
5528 t += _(' (clean)')
5525 cleanworkdir = True
5529 cleanworkdir = True
5526 elif pnode not in bheads:
5530 elif pnode not in bheads:
5527 t += _(' (new branch head)')
5531 t += _(' (new branch head)')
5528
5532
5529 if cleanworkdir:
5533 if cleanworkdir:
5530 # i18n: column positioning for "hg summary"
5534 # i18n: column positioning for "hg summary"
5531 ui.status(_('commit: %s\n') % t.strip())
5535 ui.status(_('commit: %s\n') % t.strip())
5532 else:
5536 else:
5533 # i18n: column positioning for "hg summary"
5537 # i18n: column positioning for "hg summary"
5534 ui.write(_('commit: %s\n') % t.strip())
5538 ui.write(_('commit: %s\n') % t.strip())
5535
5539
5536 # all ancestors of branch heads - all ancestors of parent = new csets
5540 # all ancestors of branch heads - all ancestors of parent = new csets
5537 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5541 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5538 bheads))
5542 bheads))
5539
5543
5540 if new == 0:
5544 if new == 0:
5541 # i18n: column positioning for "hg summary"
5545 # i18n: column positioning for "hg summary"
5542 ui.status(_('update: (current)\n'))
5546 ui.status(_('update: (current)\n'))
5543 elif pnode not in bheads:
5547 elif pnode not in bheads:
5544 # i18n: column positioning for "hg summary"
5548 # i18n: column positioning for "hg summary"
5545 ui.write(_('update: %d new changesets (update)\n') % new)
5549 ui.write(_('update: %d new changesets (update)\n') % new)
5546 else:
5550 else:
5547 # i18n: column positioning for "hg summary"
5551 # i18n: column positioning for "hg summary"
5548 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5552 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5549 (new, len(bheads)))
5553 (new, len(bheads)))
5550
5554
5551 cmdutil.summaryhooks(ui, repo)
5555 cmdutil.summaryhooks(ui, repo)
5552
5556
5553 if opts.get('remote'):
5557 if opts.get('remote'):
5554 t = []
5558 t = []
5555 source, branches = hg.parseurl(ui.expandpath('default'))
5559 source, branches = hg.parseurl(ui.expandpath('default'))
5556 sbranch = branches[0]
5560 sbranch = branches[0]
5557 other = hg.peer(repo, {}, source)
5561 other = hg.peer(repo, {}, source)
5558 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5562 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5559 if revs:
5563 if revs:
5560 revs = [other.lookup(rev) for rev in revs]
5564 revs = [other.lookup(rev) for rev in revs]
5561 ui.debug('comparing with %s\n' % util.hidepassword(source))
5565 ui.debug('comparing with %s\n' % util.hidepassword(source))
5562 repo.ui.pushbuffer()
5566 repo.ui.pushbuffer()
5563 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5567 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5564 _common, incoming, _rheads = commoninc
5568 _common, incoming, _rheads = commoninc
5565 repo.ui.popbuffer()
5569 repo.ui.popbuffer()
5566 if incoming:
5570 if incoming:
5567 t.append(_('1 or more incoming'))
5571 t.append(_('1 or more incoming'))
5568
5572
5569 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5573 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5570 dbranch = branches[0]
5574 dbranch = branches[0]
5571 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5575 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5572 if source != dest:
5576 if source != dest:
5573 other = hg.peer(repo, {}, dest)
5577 other = hg.peer(repo, {}, dest)
5574 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5578 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5575 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5579 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5576 commoninc = None
5580 commoninc = None
5577 if revs:
5581 if revs:
5578 revs = [repo.lookup(rev) for rev in revs]
5582 revs = [repo.lookup(rev) for rev in revs]
5579 repo.ui.pushbuffer()
5583 repo.ui.pushbuffer()
5580 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5584 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5581 commoninc=commoninc)
5585 commoninc=commoninc)
5582 repo.ui.popbuffer()
5586 repo.ui.popbuffer()
5583 o = outgoing.missing
5587 o = outgoing.missing
5584 if o:
5588 if o:
5585 t.append(_('%d outgoing') % len(o))
5589 t.append(_('%d outgoing') % len(o))
5586 if 'bookmarks' in other.listkeys('namespaces'):
5590 if 'bookmarks' in other.listkeys('namespaces'):
5587 lmarks = repo.listkeys('bookmarks')
5591 lmarks = repo.listkeys('bookmarks')
5588 rmarks = other.listkeys('bookmarks')
5592 rmarks = other.listkeys('bookmarks')
5589 diff = set(rmarks) - set(lmarks)
5593 diff = set(rmarks) - set(lmarks)
5590 if len(diff) > 0:
5594 if len(diff) > 0:
5591 t.append(_('%d incoming bookmarks') % len(diff))
5595 t.append(_('%d incoming bookmarks') % len(diff))
5592 diff = set(lmarks) - set(rmarks)
5596 diff = set(lmarks) - set(rmarks)
5593 if len(diff) > 0:
5597 if len(diff) > 0:
5594 t.append(_('%d outgoing bookmarks') % len(diff))
5598 t.append(_('%d outgoing bookmarks') % len(diff))
5595
5599
5596 if t:
5600 if t:
5597 # i18n: column positioning for "hg summary"
5601 # i18n: column positioning for "hg summary"
5598 ui.write(_('remote: %s\n') % (', '.join(t)))
5602 ui.write(_('remote: %s\n') % (', '.join(t)))
5599 else:
5603 else:
5600 # i18n: column positioning for "hg summary"
5604 # i18n: column positioning for "hg summary"
5601 ui.status(_('remote: (synced)\n'))
5605 ui.status(_('remote: (synced)\n'))
5602
5606
5603 @command('tag',
5607 @command('tag',
5604 [('f', 'force', None, _('force tag')),
5608 [('f', 'force', None, _('force tag')),
5605 ('l', 'local', None, _('make the tag local')),
5609 ('l', 'local', None, _('make the tag local')),
5606 ('r', 'rev', '', _('revision to tag'), _('REV')),
5610 ('r', 'rev', '', _('revision to tag'), _('REV')),
5607 ('', 'remove', None, _('remove a tag')),
5611 ('', 'remove', None, _('remove a tag')),
5608 # -l/--local is already there, commitopts cannot be used
5612 # -l/--local is already there, commitopts cannot be used
5609 ('e', 'edit', None, _('edit commit message')),
5613 ('e', 'edit', None, _('edit commit message')),
5610 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5614 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5611 ] + commitopts2,
5615 ] + commitopts2,
5612 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5616 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5613 def tag(ui, repo, name1, *names, **opts):
5617 def tag(ui, repo, name1, *names, **opts):
5614 """add one or more tags for the current or given revision
5618 """add one or more tags for the current or given revision
5615
5619
5616 Name a particular revision using <name>.
5620 Name a particular revision using <name>.
5617
5621
5618 Tags are used to name particular revisions of the repository and are
5622 Tags are used to name particular revisions of the repository and are
5619 very useful to compare different revisions, to go back to significant
5623 very useful to compare different revisions, to go back to significant
5620 earlier versions or to mark branch points as releases, etc. Changing
5624 earlier versions or to mark branch points as releases, etc. Changing
5621 an existing tag is normally disallowed; use -f/--force to override.
5625 an existing tag is normally disallowed; use -f/--force to override.
5622
5626
5623 If no revision is given, the parent of the working directory is
5627 If no revision is given, the parent of the working directory is
5624 used.
5628 used.
5625
5629
5626 To facilitate version control, distribution, and merging of tags,
5630 To facilitate version control, distribution, and merging of tags,
5627 they are stored as a file named ".hgtags" which is managed similarly
5631 they are stored as a file named ".hgtags" which is managed similarly
5628 to other project files and can be hand-edited if necessary. This
5632 to other project files and can be hand-edited if necessary. This
5629 also means that tagging creates a new commit. The file
5633 also means that tagging creates a new commit. The file
5630 ".hg/localtags" is used for local tags (not shared among
5634 ".hg/localtags" is used for local tags (not shared among
5631 repositories).
5635 repositories).
5632
5636
5633 Tag commits are usually made at the head of a branch. If the parent
5637 Tag commits are usually made at the head of a branch. If the parent
5634 of the working directory is not a branch head, :hg:`tag` aborts; use
5638 of the working directory is not a branch head, :hg:`tag` aborts; use
5635 -f/--force to force the tag commit to be based on a non-head
5639 -f/--force to force the tag commit to be based on a non-head
5636 changeset.
5640 changeset.
5637
5641
5638 See :hg:`help dates` for a list of formats valid for -d/--date.
5642 See :hg:`help dates` for a list of formats valid for -d/--date.
5639
5643
5640 Since tag names have priority over branch names during revision
5644 Since tag names have priority over branch names during revision
5641 lookup, using an existing branch name as a tag name is discouraged.
5645 lookup, using an existing branch name as a tag name is discouraged.
5642
5646
5643 Returns 0 on success.
5647 Returns 0 on success.
5644 """
5648 """
5645 wlock = lock = None
5649 wlock = lock = None
5646 try:
5650 try:
5647 wlock = repo.wlock()
5651 wlock = repo.wlock()
5648 lock = repo.lock()
5652 lock = repo.lock()
5649 rev_ = "."
5653 rev_ = "."
5650 names = [t.strip() for t in (name1,) + names]
5654 names = [t.strip() for t in (name1,) + names]
5651 if len(names) != len(set(names)):
5655 if len(names) != len(set(names)):
5652 raise util.Abort(_('tag names must be unique'))
5656 raise util.Abort(_('tag names must be unique'))
5653 for n in names:
5657 for n in names:
5654 scmutil.checknewlabel(repo, n, 'tag')
5658 scmutil.checknewlabel(repo, n, 'tag')
5655 if not n:
5659 if not n:
5656 raise util.Abort(_('tag names cannot consist entirely of '
5660 raise util.Abort(_('tag names cannot consist entirely of '
5657 'whitespace'))
5661 'whitespace'))
5658 if opts.get('rev') and opts.get('remove'):
5662 if opts.get('rev') and opts.get('remove'):
5659 raise util.Abort(_("--rev and --remove are incompatible"))
5663 raise util.Abort(_("--rev and --remove are incompatible"))
5660 if opts.get('rev'):
5664 if opts.get('rev'):
5661 rev_ = opts['rev']
5665 rev_ = opts['rev']
5662 message = opts.get('message')
5666 message = opts.get('message')
5663 if opts.get('remove'):
5667 if opts.get('remove'):
5664 expectedtype = opts.get('local') and 'local' or 'global'
5668 expectedtype = opts.get('local') and 'local' or 'global'
5665 for n in names:
5669 for n in names:
5666 if not repo.tagtype(n):
5670 if not repo.tagtype(n):
5667 raise util.Abort(_("tag '%s' does not exist") % n)
5671 raise util.Abort(_("tag '%s' does not exist") % n)
5668 if repo.tagtype(n) != expectedtype:
5672 if repo.tagtype(n) != expectedtype:
5669 if expectedtype == 'global':
5673 if expectedtype == 'global':
5670 raise util.Abort(_("tag '%s' is not a global tag") % n)
5674 raise util.Abort(_("tag '%s' is not a global tag") % n)
5671 else:
5675 else:
5672 raise util.Abort(_("tag '%s' is not a local tag") % n)
5676 raise util.Abort(_("tag '%s' is not a local tag") % n)
5673 rev_ = nullid
5677 rev_ = nullid
5674 if not message:
5678 if not message:
5675 # we don't translate commit messages
5679 # we don't translate commit messages
5676 message = 'Removed tag %s' % ', '.join(names)
5680 message = 'Removed tag %s' % ', '.join(names)
5677 elif not opts.get('force'):
5681 elif not opts.get('force'):
5678 for n in names:
5682 for n in names:
5679 if n in repo.tags():
5683 if n in repo.tags():
5680 raise util.Abort(_("tag '%s' already exists "
5684 raise util.Abort(_("tag '%s' already exists "
5681 "(use -f to force)") % n)
5685 "(use -f to force)") % n)
5682 if not opts.get('local'):
5686 if not opts.get('local'):
5683 p1, p2 = repo.dirstate.parents()
5687 p1, p2 = repo.dirstate.parents()
5684 if p2 != nullid:
5688 if p2 != nullid:
5685 raise util.Abort(_('uncommitted merge'))
5689 raise util.Abort(_('uncommitted merge'))
5686 bheads = repo.branchheads()
5690 bheads = repo.branchheads()
5687 if not opts.get('force') and bheads and p1 not in bheads:
5691 if not opts.get('force') and bheads and p1 not in bheads:
5688 raise util.Abort(_('not at a branch head (use -f to force)'))
5692 raise util.Abort(_('not at a branch head (use -f to force)'))
5689 r = scmutil.revsingle(repo, rev_).node()
5693 r = scmutil.revsingle(repo, rev_).node()
5690
5694
5691 if not message:
5695 if not message:
5692 # we don't translate commit messages
5696 # we don't translate commit messages
5693 message = ('Added tag %s for changeset %s' %
5697 message = ('Added tag %s for changeset %s' %
5694 (', '.join(names), short(r)))
5698 (', '.join(names), short(r)))
5695
5699
5696 date = opts.get('date')
5700 date = opts.get('date')
5697 if date:
5701 if date:
5698 date = util.parsedate(date)
5702 date = util.parsedate(date)
5699
5703
5700 if opts.get('edit'):
5704 if opts.get('edit'):
5701 message = ui.edit(message, ui.username())
5705 message = ui.edit(message, ui.username())
5702 repo.savecommitmessage(message)
5706 repo.savecommitmessage(message)
5703
5707
5704 # don't allow tagging the null rev
5708 # don't allow tagging the null rev
5705 if (not opts.get('remove') and
5709 if (not opts.get('remove') and
5706 scmutil.revsingle(repo, rev_).rev() == nullrev):
5710 scmutil.revsingle(repo, rev_).rev() == nullrev):
5707 raise util.Abort(_("cannot tag null revision"))
5711 raise util.Abort(_("cannot tag null revision"))
5708
5712
5709 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5713 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5710 finally:
5714 finally:
5711 release(lock, wlock)
5715 release(lock, wlock)
5712
5716
5713 @command('tags', [], '')
5717 @command('tags', [], '')
5714 def tags(ui, repo, **opts):
5718 def tags(ui, repo, **opts):
5715 """list repository tags
5719 """list repository tags
5716
5720
5717 This lists both regular and local tags. When the -v/--verbose
5721 This lists both regular and local tags. When the -v/--verbose
5718 switch is used, a third column "local" is printed for local tags.
5722 switch is used, a third column "local" is printed for local tags.
5719
5723
5720 Returns 0 on success.
5724 Returns 0 on success.
5721 """
5725 """
5722
5726
5723 fm = ui.formatter('tags', opts)
5727 fm = ui.formatter('tags', opts)
5724 hexfunc = ui.debugflag and hex or short
5728 hexfunc = ui.debugflag and hex or short
5725 tagtype = ""
5729 tagtype = ""
5726
5730
5727 for t, n in reversed(repo.tagslist()):
5731 for t, n in reversed(repo.tagslist()):
5728 hn = hexfunc(n)
5732 hn = hexfunc(n)
5729 label = 'tags.normal'
5733 label = 'tags.normal'
5730 tagtype = ''
5734 tagtype = ''
5731 if repo.tagtype(t) == 'local':
5735 if repo.tagtype(t) == 'local':
5732 label = 'tags.local'
5736 label = 'tags.local'
5733 tagtype = 'local'
5737 tagtype = 'local'
5734
5738
5735 fm.startitem()
5739 fm.startitem()
5736 fm.write('tag', '%s', t, label=label)
5740 fm.write('tag', '%s', t, label=label)
5737 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5741 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5738 fm.condwrite(not ui.quiet, 'rev id', fmt,
5742 fm.condwrite(not ui.quiet, 'rev id', fmt,
5739 repo.changelog.rev(n), hn, label=label)
5743 repo.changelog.rev(n), hn, label=label)
5740 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5744 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5741 tagtype, label=label)
5745 tagtype, label=label)
5742 fm.plain('\n')
5746 fm.plain('\n')
5743 fm.end()
5747 fm.end()
5744
5748
5745 @command('tip',
5749 @command('tip',
5746 [('p', 'patch', None, _('show patch')),
5750 [('p', 'patch', None, _('show patch')),
5747 ('g', 'git', None, _('use git extended diff format')),
5751 ('g', 'git', None, _('use git extended diff format')),
5748 ] + templateopts,
5752 ] + templateopts,
5749 _('[-p] [-g]'))
5753 _('[-p] [-g]'))
5750 def tip(ui, repo, **opts):
5754 def tip(ui, repo, **opts):
5751 """show the tip revision (DEPRECATED)
5755 """show the tip revision (DEPRECATED)
5752
5756
5753 The tip revision (usually just called the tip) is the changeset
5757 The tip revision (usually just called the tip) is the changeset
5754 most recently added to the repository (and therefore the most
5758 most recently added to the repository (and therefore the most
5755 recently changed head).
5759 recently changed head).
5756
5760
5757 If you have just made a commit, that commit will be the tip. If
5761 If you have just made a commit, that commit will be the tip. If
5758 you have just pulled changes from another repository, the tip of
5762 you have just pulled changes from another repository, the tip of
5759 that repository becomes the current tip. The "tip" tag is special
5763 that repository becomes the current tip. The "tip" tag is special
5760 and cannot be renamed or assigned to a different changeset.
5764 and cannot be renamed or assigned to a different changeset.
5761
5765
5762 This command is deprecated, please use :hg:`heads` instead.
5766 This command is deprecated, please use :hg:`heads` instead.
5763
5767
5764 Returns 0 on success.
5768 Returns 0 on success.
5765 """
5769 """
5766 displayer = cmdutil.show_changeset(ui, repo, opts)
5770 displayer = cmdutil.show_changeset(ui, repo, opts)
5767 displayer.show(repo['tip'])
5771 displayer.show(repo['tip'])
5768 displayer.close()
5772 displayer.close()
5769
5773
5770 @command('unbundle',
5774 @command('unbundle',
5771 [('u', 'update', None,
5775 [('u', 'update', None,
5772 _('update to new branch head if changesets were unbundled'))],
5776 _('update to new branch head if changesets were unbundled'))],
5773 _('[-u] FILE...'))
5777 _('[-u] FILE...'))
5774 def unbundle(ui, repo, fname1, *fnames, **opts):
5778 def unbundle(ui, repo, fname1, *fnames, **opts):
5775 """apply one or more changegroup files
5779 """apply one or more changegroup files
5776
5780
5777 Apply one or more compressed changegroup files generated by the
5781 Apply one or more compressed changegroup files generated by the
5778 bundle command.
5782 bundle command.
5779
5783
5780 Returns 0 on success, 1 if an update has unresolved files.
5784 Returns 0 on success, 1 if an update has unresolved files.
5781 """
5785 """
5782 fnames = (fname1,) + fnames
5786 fnames = (fname1,) + fnames
5783
5787
5784 lock = repo.lock()
5788 lock = repo.lock()
5785 wc = repo['.']
5789 wc = repo['.']
5786 try:
5790 try:
5787 for fname in fnames:
5791 for fname in fnames:
5788 f = hg.openpath(ui, fname)
5792 f = hg.openpath(ui, fname)
5789 gen = changegroup.readbundle(f, fname)
5793 gen = changegroup.readbundle(f, fname)
5790 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5794 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5791 'bundle:' + fname)
5795 'bundle:' + fname)
5792 finally:
5796 finally:
5793 lock.release()
5797 lock.release()
5794 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5798 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5795 return postincoming(ui, repo, modheads, opts.get('update'), None)
5799 return postincoming(ui, repo, modheads, opts.get('update'), None)
5796
5800
5797 @command('^update|up|checkout|co',
5801 @command('^update|up|checkout|co',
5798 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5802 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5799 ('c', 'check', None,
5803 ('c', 'check', None,
5800 _('update across branches if no uncommitted changes')),
5804 _('update across branches if no uncommitted changes')),
5801 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5805 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5802 ('r', 'rev', '', _('revision'), _('REV'))],
5806 ('r', 'rev', '', _('revision'), _('REV'))],
5803 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5807 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5804 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5808 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5805 """update working directory (or switch revisions)
5809 """update working directory (or switch revisions)
5806
5810
5807 Update the repository's working directory to the specified
5811 Update the repository's working directory to the specified
5808 changeset. If no changeset is specified, update to the tip of the
5812 changeset. If no changeset is specified, update to the tip of the
5809 current named branch and move the current bookmark (see :hg:`help
5813 current named branch and move the current bookmark (see :hg:`help
5810 bookmarks`).
5814 bookmarks`).
5811
5815
5812 Update sets the working directory's parent revision to the specified
5816 Update sets the working directory's parent revision to the specified
5813 changeset (see :hg:`help parents`).
5817 changeset (see :hg:`help parents`).
5814
5818
5815 If the changeset is not a descendant or ancestor of the working
5819 If the changeset is not a descendant or ancestor of the working
5816 directory's parent, the update is aborted. With the -c/--check
5820 directory's parent, the update is aborted. With the -c/--check
5817 option, the working directory is checked for uncommitted changes; if
5821 option, the working directory is checked for uncommitted changes; if
5818 none are found, the working directory is updated to the specified
5822 none are found, the working directory is updated to the specified
5819 changeset.
5823 changeset.
5820
5824
5821 .. container:: verbose
5825 .. container:: verbose
5822
5826
5823 The following rules apply when the working directory contains
5827 The following rules apply when the working directory contains
5824 uncommitted changes:
5828 uncommitted changes:
5825
5829
5826 1. If neither -c/--check nor -C/--clean is specified, and if
5830 1. If neither -c/--check nor -C/--clean is specified, and if
5827 the requested changeset is an ancestor or descendant of
5831 the requested changeset is an ancestor or descendant of
5828 the working directory's parent, the uncommitted changes
5832 the working directory's parent, the uncommitted changes
5829 are merged into the requested changeset and the merged
5833 are merged into the requested changeset and the merged
5830 result is left uncommitted. If the requested changeset is
5834 result is left uncommitted. If the requested changeset is
5831 not an ancestor or descendant (that is, it is on another
5835 not an ancestor or descendant (that is, it is on another
5832 branch), the update is aborted and the uncommitted changes
5836 branch), the update is aborted and the uncommitted changes
5833 are preserved.
5837 are preserved.
5834
5838
5835 2. With the -c/--check option, the update is aborted and the
5839 2. With the -c/--check option, the update is aborted and the
5836 uncommitted changes are preserved.
5840 uncommitted changes are preserved.
5837
5841
5838 3. With the -C/--clean option, uncommitted changes are discarded and
5842 3. With the -C/--clean option, uncommitted changes are discarded and
5839 the working directory is updated to the requested changeset.
5843 the working directory is updated to the requested changeset.
5840
5844
5841 To cancel an uncommitted merge (and lose your changes), use
5845 To cancel an uncommitted merge (and lose your changes), use
5842 :hg:`update --clean .`.
5846 :hg:`update --clean .`.
5843
5847
5844 Use null as the changeset to remove the working directory (like
5848 Use null as the changeset to remove the working directory (like
5845 :hg:`clone -U`).
5849 :hg:`clone -U`).
5846
5850
5847 If you want to revert just one file to an older revision, use
5851 If you want to revert just one file to an older revision, use
5848 :hg:`revert [-r REV] NAME`.
5852 :hg:`revert [-r REV] NAME`.
5849
5853
5850 See :hg:`help dates` for a list of formats valid for -d/--date.
5854 See :hg:`help dates` for a list of formats valid for -d/--date.
5851
5855
5852 Returns 0 on success, 1 if there are unresolved files.
5856 Returns 0 on success, 1 if there are unresolved files.
5853 """
5857 """
5854 if rev and node:
5858 if rev and node:
5855 raise util.Abort(_("please specify just one revision"))
5859 raise util.Abort(_("please specify just one revision"))
5856
5860
5857 if rev is None or rev == '':
5861 if rev is None or rev == '':
5858 rev = node
5862 rev = node
5859
5863
5860 cmdutil.clearunfinished(repo)
5864 cmdutil.clearunfinished(repo)
5861
5865
5862 # with no argument, we also move the current bookmark, if any
5866 # with no argument, we also move the current bookmark, if any
5863 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5867 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5864
5868
5865 # if we defined a bookmark, we have to remember the original bookmark name
5869 # if we defined a bookmark, we have to remember the original bookmark name
5866 brev = rev
5870 brev = rev
5867 rev = scmutil.revsingle(repo, rev, rev).rev()
5871 rev = scmutil.revsingle(repo, rev, rev).rev()
5868
5872
5869 if check and clean:
5873 if check and clean:
5870 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5874 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5871
5875
5872 if date:
5876 if date:
5873 if rev is not None:
5877 if rev is not None:
5874 raise util.Abort(_("you can't specify a revision and a date"))
5878 raise util.Abort(_("you can't specify a revision and a date"))
5875 rev = cmdutil.finddate(ui, repo, date)
5879 rev = cmdutil.finddate(ui, repo, date)
5876
5880
5877 if check:
5881 if check:
5878 c = repo[None]
5882 c = repo[None]
5879 if c.dirty(merge=False, branch=False, missing=True):
5883 if c.dirty(merge=False, branch=False, missing=True):
5880 raise util.Abort(_("uncommitted changes"))
5884 raise util.Abort(_("uncommitted changes"))
5881 if rev is None:
5885 if rev is None:
5882 rev = repo[repo[None].branch()].rev()
5886 rev = repo[repo[None].branch()].rev()
5883 mergemod._checkunknown(repo, repo[None], repo[rev])
5887 mergemod._checkunknown(repo, repo[None], repo[rev])
5884
5888
5885 if clean:
5889 if clean:
5886 ret = hg.clean(repo, rev)
5890 ret = hg.clean(repo, rev)
5887 else:
5891 else:
5888 ret = hg.update(repo, rev)
5892 ret = hg.update(repo, rev)
5889
5893
5890 if not ret and movemarkfrom:
5894 if not ret and movemarkfrom:
5891 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5895 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5892 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5896 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5893 elif brev in repo._bookmarks:
5897 elif brev in repo._bookmarks:
5894 bookmarks.setcurrent(repo, brev)
5898 bookmarks.setcurrent(repo, brev)
5895 elif brev:
5899 elif brev:
5896 bookmarks.unsetcurrent(repo)
5900 bookmarks.unsetcurrent(repo)
5897
5901
5898 return ret
5902 return ret
5899
5903
5900 @command('verify', [])
5904 @command('verify', [])
5901 def verify(ui, repo):
5905 def verify(ui, repo):
5902 """verify the integrity of the repository
5906 """verify the integrity of the repository
5903
5907
5904 Verify the integrity of the current repository.
5908 Verify the integrity of the current repository.
5905
5909
5906 This will perform an extensive check of the repository's
5910 This will perform an extensive check of the repository's
5907 integrity, validating the hashes and checksums of each entry in
5911 integrity, validating the hashes and checksums of each entry in
5908 the changelog, manifest, and tracked files, as well as the
5912 the changelog, manifest, and tracked files, as well as the
5909 integrity of their crosslinks and indices.
5913 integrity of their crosslinks and indices.
5910
5914
5911 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5915 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5912 for more information about recovery from corruption of the
5916 for more information about recovery from corruption of the
5913 repository.
5917 repository.
5914
5918
5915 Returns 0 on success, 1 if errors are encountered.
5919 Returns 0 on success, 1 if errors are encountered.
5916 """
5920 """
5917 return hg.verify(repo)
5921 return hg.verify(repo)
5918
5922
5919 @command('version', [])
5923 @command('version', [])
5920 def version_(ui):
5924 def version_(ui):
5921 """output version and copyright information"""
5925 """output version and copyright information"""
5922 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5926 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5923 % util.version())
5927 % util.version())
5924 ui.status(_(
5928 ui.status(_(
5925 "(see http://mercurial.selenic.com for more information)\n"
5929 "(see http://mercurial.selenic.com for more information)\n"
5926 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5930 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5927 "This is free software; see the source for copying conditions. "
5931 "This is free software; see the source for copying conditions. "
5928 "There is NO\nwarranty; "
5932 "There is NO\nwarranty; "
5929 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5933 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5930 ))
5934 ))
5931
5935
5932 norepo = ("clone init version help debugcommands debugcomplete"
5936 norepo = ("clone init version help debugcommands debugcomplete"
5933 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5937 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5934 " debugknown debuggetbundle debugbundle")
5938 " debugknown debuggetbundle debugbundle")
5935 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5939 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5936 " debugdata debugindex debugindexdot debugrevlog")
5940 " debugdata debugindex debugindexdot debugrevlog")
5937 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5941 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5938 " remove resolve status debugwalk")
5942 " remove resolve status debugwalk")
@@ -1,356 +1,379 b''
1 commit date test
1 commit date test
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo foo > foo
5 $ echo foo > foo
6 $ hg add foo
6 $ hg add foo
7 $ HGEDITOR=true hg commit -m ""
7 $ HGEDITOR=true hg commit -m ""
8 abort: empty commit message
8 abort: empty commit message
9 [255]
9 [255]
10 $ hg commit -d '0 0' -m commit-1
10 $ hg commit -d '0 0' -m commit-1
11 $ echo foo >> foo
11 $ echo foo >> foo
12 $ hg commit -d '1 4444444' -m commit-3
12 $ hg commit -d '1 4444444' -m commit-3
13 abort: impossible time zone offset: 4444444
13 abort: impossible time zone offset: 4444444
14 [255]
14 [255]
15 $ hg commit -d '1 15.1' -m commit-4
15 $ hg commit -d '1 15.1' -m commit-4
16 abort: invalid date: '1\t15.1'
16 abort: invalid date: '1\t15.1'
17 [255]
17 [255]
18 $ hg commit -d 'foo bar' -m commit-5
18 $ hg commit -d 'foo bar' -m commit-5
19 abort: invalid date: 'foo bar'
19 abort: invalid date: 'foo bar'
20 [255]
20 [255]
21 $ hg commit -d ' 1 4444' -m commit-6
21 $ hg commit -d ' 1 4444' -m commit-6
22 $ hg commit -d '111111111111 0' -m commit-7
22 $ hg commit -d '111111111111 0' -m commit-7
23 abort: date exceeds 32 bits: 111111111111
23 abort: date exceeds 32 bits: 111111111111
24 [255]
24 [255]
25 $ hg commit -d '-7654321 3600' -m commit-7
25 $ hg commit -d '-7654321 3600' -m commit-7
26 abort: negative date value: -7654321
26 abort: negative date value: -7654321
27 [255]
27 [255]
28
28
29 commit added file that has been deleted
29 commit added file that has been deleted
30
30
31 $ echo bar > bar
31 $ echo bar > bar
32 $ hg add bar
32 $ hg add bar
33 $ rm bar
33 $ rm bar
34 $ hg commit -m commit-8
34 $ hg commit -m commit-8
35 nothing changed (1 missing files, see 'hg status')
35 nothing changed (1 missing files, see 'hg status')
36 [1]
36 [1]
37 $ hg commit -m commit-8-2 bar
37 $ hg commit -m commit-8-2 bar
38 abort: bar: file not found!
38 abort: bar: file not found!
39 [255]
39 [255]
40
40
41 $ hg -q revert -a --no-backup
41 $ hg -q revert -a --no-backup
42
42
43 $ mkdir dir
43 $ mkdir dir
44 $ echo boo > dir/file
44 $ echo boo > dir/file
45 $ hg add
45 $ hg add
46 adding dir/file (glob)
46 adding dir/file (glob)
47 $ hg -v commit -m commit-9 dir
47 $ hg -v commit -m commit-9 dir
48 dir/file
48 dir/file
49 committed changeset 2:d2a76177cb42
49 committed changeset 2:d2a76177cb42
50
50
51 $ echo > dir.file
51 $ echo > dir.file
52 $ hg add
52 $ hg add
53 adding dir.file
53 adding dir.file
54 $ hg commit -m commit-10 dir dir.file
54 $ hg commit -m commit-10 dir dir.file
55 abort: dir: no match under directory!
55 abort: dir: no match under directory!
56 [255]
56 [255]
57
57
58 $ echo >> dir/file
58 $ echo >> dir/file
59 $ mkdir bleh
59 $ mkdir bleh
60 $ mkdir dir2
60 $ mkdir dir2
61 $ cd bleh
61 $ cd bleh
62 $ hg commit -m commit-11 .
62 $ hg commit -m commit-11 .
63 abort: bleh: no match under directory!
63 abort: bleh: no match under directory!
64 [255]
64 [255]
65 $ hg commit -m commit-12 ../dir ../dir2
65 $ hg commit -m commit-12 ../dir ../dir2
66 abort: dir2: no match under directory!
66 abort: dir2: no match under directory!
67 [255]
67 [255]
68 $ hg -v commit -m commit-13 ../dir
68 $ hg -v commit -m commit-13 ../dir
69 dir/file
69 dir/file
70 committed changeset 3:1cd62a2d8db5
70 committed changeset 3:1cd62a2d8db5
71 $ cd ..
71 $ cd ..
72
72
73 $ hg commit -m commit-14 does-not-exist
73 $ hg commit -m commit-14 does-not-exist
74 abort: does-not-exist: * (glob)
74 abort: does-not-exist: * (glob)
75 [255]
75 [255]
76
76
77 #if symlink
77 #if symlink
78 $ ln -s foo baz
78 $ ln -s foo baz
79 $ hg commit -m commit-15 baz
79 $ hg commit -m commit-15 baz
80 abort: baz: file not tracked!
80 abort: baz: file not tracked!
81 [255]
81 [255]
82 #endif
82 #endif
83
83
84 $ touch quux
84 $ touch quux
85 $ hg commit -m commit-16 quux
85 $ hg commit -m commit-16 quux
86 abort: quux: file not tracked!
86 abort: quux: file not tracked!
87 [255]
87 [255]
88 $ echo >> dir/file
88 $ echo >> dir/file
89 $ hg -v commit -m commit-17 dir/file
89 $ hg -v commit -m commit-17 dir/file
90 dir/file
90 dir/file
91 committed changeset 4:49176991390e
91 committed changeset 4:49176991390e
92
92
93 An empty date was interpreted as epoch origin
93 An empty date was interpreted as epoch origin
94
94
95 $ echo foo >> foo
95 $ echo foo >> foo
96 $ hg commit -d '' -m commit-no-date
96 $ hg commit -d '' -m commit-no-date
97 $ hg tip --template '{date|isodate}\n' | grep '1970'
97 $ hg tip --template '{date|isodate}\n' | grep '1970'
98 [1]
98 [1]
99
99
100 Make sure we do not obscure unknown requires file entries (issue2649)
100 Make sure we do not obscure unknown requires file entries (issue2649)
101
101
102 $ echo foo >> foo
102 $ echo foo >> foo
103 $ echo fake >> .hg/requires
103 $ echo fake >> .hg/requires
104 $ hg commit -m bla
104 $ hg commit -m bla
105 abort: repository requires features unknown to this Mercurial: fake!
105 abort: repository requires features unknown to this Mercurial: fake!
106 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
106 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
107 [255]
107 [255]
108
108
109 $ cd ..
109 $ cd ..
110
110
111
111
112 partial subdir commit test
112 partial subdir commit test
113
113
114 $ hg init test2
114 $ hg init test2
115 $ cd test2
115 $ cd test2
116 $ mkdir foo
116 $ mkdir foo
117 $ echo foo > foo/foo
117 $ echo foo > foo/foo
118 $ mkdir bar
118 $ mkdir bar
119 $ echo bar > bar/bar
119 $ echo bar > bar/bar
120 $ hg add
120 $ hg add
121 adding bar/bar (glob)
121 adding bar/bar (glob)
122 adding foo/foo (glob)
122 adding foo/foo (glob)
123 $ hg ci -m commit-subdir-1 foo
123 $ HGEDITOR=cat hg ci -e -m commit-subdir-1 foo
124 commit-subdir-1
125
126
127 HG: Enter commit message. Lines beginning with 'HG:' are removed.
128 HG: Leave message empty to abort commit.
129 HG: --
130 HG: user: test
131 HG: branch 'default'
132 HG: added foo/foo
133
134
124 $ hg ci -m commit-subdir-2 bar
135 $ hg ci -m commit-subdir-2 bar
125
136
126 subdir log 1
137 subdir log 1
127
138
128 $ hg log -v foo
139 $ hg log -v foo
129 changeset: 0:f97e73a25882
140 changeset: 0:f97e73a25882
130 user: test
141 user: test
131 date: Thu Jan 01 00:00:00 1970 +0000
142 date: Thu Jan 01 00:00:00 1970 +0000
132 files: foo/foo
143 files: foo/foo
133 description:
144 description:
134 commit-subdir-1
145 commit-subdir-1
135
146
136
147
137
148
138 subdir log 2
149 subdir log 2
139
150
140 $ hg log -v bar
151 $ hg log -v bar
141 changeset: 1:aa809156d50d
152 changeset: 1:aa809156d50d
142 tag: tip
153 tag: tip
143 user: test
154 user: test
144 date: Thu Jan 01 00:00:00 1970 +0000
155 date: Thu Jan 01 00:00:00 1970 +0000
145 files: bar/bar
156 files: bar/bar
146 description:
157 description:
147 commit-subdir-2
158 commit-subdir-2
148
159
149
160
150
161
151 full log
162 full log
152
163
153 $ hg log -v
164 $ hg log -v
154 changeset: 1:aa809156d50d
165 changeset: 1:aa809156d50d
155 tag: tip
166 tag: tip
156 user: test
167 user: test
157 date: Thu Jan 01 00:00:00 1970 +0000
168 date: Thu Jan 01 00:00:00 1970 +0000
158 files: bar/bar
169 files: bar/bar
159 description:
170 description:
160 commit-subdir-2
171 commit-subdir-2
161
172
162
173
163 changeset: 0:f97e73a25882
174 changeset: 0:f97e73a25882
164 user: test
175 user: test
165 date: Thu Jan 01 00:00:00 1970 +0000
176 date: Thu Jan 01 00:00:00 1970 +0000
166 files: foo/foo
177 files: foo/foo
167 description:
178 description:
168 commit-subdir-1
179 commit-subdir-1
169
180
170
181
171 $ cd ..
182 $ cd ..
172
183
173
184
174 dot and subdir commit test
185 dot and subdir commit test
175
186
176 $ hg init test3
187 $ hg init test3
188 $ echo commit-foo-subdir > commit-log-test
177 $ cd test3
189 $ cd test3
178 $ mkdir foo
190 $ mkdir foo
179 $ echo foo content > foo/plain-file
191 $ echo foo content > foo/plain-file
180 $ hg add foo/plain-file
192 $ hg add foo/plain-file
181 $ hg ci -m commit-foo-subdir foo
193 $ HGEDITOR=cat hg ci --edit -l ../commit-log-test foo
194 commit-foo-subdir
195
196
197 HG: Enter commit message. Lines beginning with 'HG:' are removed.
198 HG: Leave message empty to abort commit.
199 HG: --
200 HG: user: test
201 HG: branch 'default'
202 HG: added foo/plain-file
203
204
182 $ echo modified foo content > foo/plain-file
205 $ echo modified foo content > foo/plain-file
183 $ hg ci -m commit-foo-dot .
206 $ hg ci -m commit-foo-dot .
184
207
185 full log
208 full log
186
209
187 $ hg log -v
210 $ hg log -v
188 changeset: 1:95b38e3a5b2e
211 changeset: 1:95b38e3a5b2e
189 tag: tip
212 tag: tip
190 user: test
213 user: test
191 date: Thu Jan 01 00:00:00 1970 +0000
214 date: Thu Jan 01 00:00:00 1970 +0000
192 files: foo/plain-file
215 files: foo/plain-file
193 description:
216 description:
194 commit-foo-dot
217 commit-foo-dot
195
218
196
219
197 changeset: 0:65d4e9386227
220 changeset: 0:65d4e9386227
198 user: test
221 user: test
199 date: Thu Jan 01 00:00:00 1970 +0000
222 date: Thu Jan 01 00:00:00 1970 +0000
200 files: foo/plain-file
223 files: foo/plain-file
201 description:
224 description:
202 commit-foo-subdir
225 commit-foo-subdir
203
226
204
227
205
228
206 subdir log
229 subdir log
207
230
208 $ cd foo
231 $ cd foo
209 $ hg log .
232 $ hg log .
210 changeset: 1:95b38e3a5b2e
233 changeset: 1:95b38e3a5b2e
211 tag: tip
234 tag: tip
212 user: test
235 user: test
213 date: Thu Jan 01 00:00:00 1970 +0000
236 date: Thu Jan 01 00:00:00 1970 +0000
214 summary: commit-foo-dot
237 summary: commit-foo-dot
215
238
216 changeset: 0:65d4e9386227
239 changeset: 0:65d4e9386227
217 user: test
240 user: test
218 date: Thu Jan 01 00:00:00 1970 +0000
241 date: Thu Jan 01 00:00:00 1970 +0000
219 summary: commit-foo-subdir
242 summary: commit-foo-subdir
220
243
221 $ cd ..
244 $ cd ..
222 $ cd ..
245 $ cd ..
223
246
224 Issue1049: Hg permits partial commit of merge without warning
247 Issue1049: Hg permits partial commit of merge without warning
225
248
226 $ hg init issue1049
249 $ hg init issue1049
227 $ cd issue1049
250 $ cd issue1049
228 $ echo a > a
251 $ echo a > a
229 $ hg ci -Ama
252 $ hg ci -Ama
230 adding a
253 adding a
231 $ echo a >> a
254 $ echo a >> a
232 $ hg ci -mb
255 $ hg ci -mb
233 $ hg up 0
256 $ hg up 0
234 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 $ echo b >> a
258 $ echo b >> a
236 $ hg ci -mc
259 $ hg ci -mc
237 created new head
260 created new head
238 $ HGMERGE=true hg merge
261 $ HGMERGE=true hg merge
239 merging a
262 merging a
240 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
263 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
264 (branch merge, don't forget to commit)
242
265
243 should fail because we are specifying a file name
266 should fail because we are specifying a file name
244
267
245 $ hg ci -mmerge a
268 $ hg ci -mmerge a
246 abort: cannot partially commit a merge (do not specify files or patterns)
269 abort: cannot partially commit a merge (do not specify files or patterns)
247 [255]
270 [255]
248
271
249 should fail because we are specifying a pattern
272 should fail because we are specifying a pattern
250
273
251 $ hg ci -mmerge -I a
274 $ hg ci -mmerge -I a
252 abort: cannot partially commit a merge (do not specify files or patterns)
275 abort: cannot partially commit a merge (do not specify files or patterns)
253 [255]
276 [255]
254
277
255 should succeed
278 should succeed
256
279
257 $ hg ci -mmerge
280 $ hg ci -mmerge
258 $ cd ..
281 $ cd ..
259
282
260
283
261 test commit message content
284 test commit message content
262
285
263 $ hg init commitmsg
286 $ hg init commitmsg
264 $ cd commitmsg
287 $ cd commitmsg
265 $ echo changed > changed
288 $ echo changed > changed
266 $ echo removed > removed
289 $ echo removed > removed
267 $ hg book currentbookmark
290 $ hg book currentbookmark
268 $ hg ci -qAm init
291 $ hg ci -qAm init
269
292
270 $ hg rm removed
293 $ hg rm removed
271 $ echo changed >> changed
294 $ echo changed >> changed
272 $ echo added > added
295 $ echo added > added
273 $ hg add added
296 $ hg add added
274 $ HGEDITOR=cat hg ci -A
297 $ HGEDITOR=cat hg ci -A
275
298
276
299
277 HG: Enter commit message. Lines beginning with 'HG:' are removed.
300 HG: Enter commit message. Lines beginning with 'HG:' are removed.
278 HG: Leave message empty to abort commit.
301 HG: Leave message empty to abort commit.
279 HG: --
302 HG: --
280 HG: user: test
303 HG: user: test
281 HG: branch 'default'
304 HG: branch 'default'
282 HG: bookmark 'currentbookmark'
305 HG: bookmark 'currentbookmark'
283 HG: added added
306 HG: added added
284 HG: changed changed
307 HG: changed changed
285 HG: removed removed
308 HG: removed removed
286 abort: empty commit message
309 abort: empty commit message
287 [255]
310 [255]
288
311
289 test saving last-message.txt
312 test saving last-message.txt
290
313
291 $ hg init sub
314 $ hg init sub
292 $ echo a > sub/a
315 $ echo a > sub/a
293 $ hg -R sub add sub/a
316 $ hg -R sub add sub/a
294 $ cat > sub/.hg/hgrc <<EOF
317 $ cat > sub/.hg/hgrc <<EOF
295 > [hooks]
318 > [hooks]
296 > precommit.test-saving-last-message = false
319 > precommit.test-saving-last-message = false
297 > EOF
320 > EOF
298
321
299 $ echo 'sub = sub' > .hgsub
322 $ echo 'sub = sub' > .hgsub
300 $ hg add .hgsub
323 $ hg add .hgsub
301
324
302 $ cat > $TESTTMP/editor.sh <<EOF
325 $ cat > $TESTTMP/editor.sh <<EOF
303 > echo "==== before editing:"
326 > echo "==== before editing:"
304 > cat \$1
327 > cat \$1
305 > echo "===="
328 > echo "===="
306 > echo "test saving last-message.txt" >> \$1
329 > echo "test saving last-message.txt" >> \$1
307 > EOF
330 > EOF
308
331
309 $ rm -f .hg/last-message.txt
332 $ rm -f .hg/last-message.txt
310 $ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -S -q
333 $ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -S -q
311 ==== before editing:
334 ==== before editing:
312
335
313
336
314 HG: Enter commit message. Lines beginning with 'HG:' are removed.
337 HG: Enter commit message. Lines beginning with 'HG:' are removed.
315 HG: Leave message empty to abort commit.
338 HG: Leave message empty to abort commit.
316 HG: --
339 HG: --
317 HG: user: test
340 HG: user: test
318 HG: branch 'default'
341 HG: branch 'default'
319 HG: bookmark 'currentbookmark'
342 HG: bookmark 'currentbookmark'
320 HG: subrepo sub
343 HG: subrepo sub
321 HG: added .hgsub
344 HG: added .hgsub
322 HG: added added
345 HG: added added
323 HG: changed .hgsubstate
346 HG: changed .hgsubstate
324 HG: changed changed
347 HG: changed changed
325 HG: removed removed
348 HG: removed removed
326 ====
349 ====
327 abort: precommit.test-saving-last-message hook exited with status 1 (in subrepo sub)
350 abort: precommit.test-saving-last-message hook exited with status 1 (in subrepo sub)
328 [255]
351 [255]
329 $ cat .hg/last-message.txt
352 $ cat .hg/last-message.txt
330
353
331
354
332 test saving last-message.txt
355 test saving last-message.txt
333
356
334 $ cd ..
357 $ cd ..
335
358
336
359
337 commit copy
360 commit copy
338
361
339 $ hg init dir2
362 $ hg init dir2
340 $ cd dir2
363 $ cd dir2
341 $ echo bleh > bar
364 $ echo bleh > bar
342 $ hg add bar
365 $ hg add bar
343 $ hg ci -m 'add bar'
366 $ hg ci -m 'add bar'
344
367
345 $ hg cp bar foo
368 $ hg cp bar foo
346 $ echo >> bar
369 $ echo >> bar
347 $ hg ci -m 'cp bar foo; change bar'
370 $ hg ci -m 'cp bar foo; change bar'
348
371
349 $ hg debugrename foo
372 $ hg debugrename foo
350 foo renamed from bar:26d3ca0dfd18e44d796b564e38dd173c9668d3a9
373 foo renamed from bar:26d3ca0dfd18e44d796b564e38dd173c9668d3a9
351 $ hg debugindex bar
374 $ hg debugindex bar
352 rev offset length ..... linkrev nodeid p1 p2 (re)
375 rev offset length ..... linkrev nodeid p1 p2 (re)
353 0 0 6 ..... 0 26d3ca0dfd18 000000000000 000000000000 (re)
376 0 0 6 ..... 0 26d3ca0dfd18 000000000000 000000000000 (re)
354 1 6 7 ..... 1 d267bddd54f7 26d3ca0dfd18 000000000000 (re)
377 1 6 7 ..... 1 d267bddd54f7 26d3ca0dfd18 000000000000 (re)
355
378
356 $ cd ..
379 $ cd ..
@@ -1,332 +1,332 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 forget
20 forget
21 graft
21 graft
22 grep
22 grep
23 heads
23 heads
24 help
24 help
25 identify
25 identify
26 import
26 import
27 incoming
27 incoming
28 init
28 init
29 locate
29 locate
30 log
30 log
31 manifest
31 manifest
32 merge
32 merge
33 outgoing
33 outgoing
34 parents
34 parents
35 paths
35 paths
36 phase
36 phase
37 pull
37 pull
38 push
38 push
39 recover
39 recover
40 remove
40 remove
41 rename
41 rename
42 resolve
42 resolve
43 revert
43 revert
44 rollback
44 rollback
45 root
45 root
46 serve
46 serve
47 status
47 status
48 summary
48 summary
49 tag
49 tag
50 tags
50 tags
51 tip
51 tip
52 unbundle
52 unbundle
53 update
53 update
54 verify
54 verify
55 version
55 version
56
56
57 Show all commands that start with "a"
57 Show all commands that start with "a"
58 $ hg debugcomplete a
58 $ hg debugcomplete a
59 add
59 add
60 addremove
60 addremove
61 annotate
61 annotate
62 archive
62 archive
63
63
64 Do not show debug commands if there are other candidates
64 Do not show debug commands if there are other candidates
65 $ hg debugcomplete d
65 $ hg debugcomplete d
66 diff
66 diff
67
67
68 Show debug commands if there are no other candidates
68 Show debug commands if there are no other candidates
69 $ hg debugcomplete debug
69 $ hg debugcomplete debug
70 debugancestor
70 debugancestor
71 debugbuilddag
71 debugbuilddag
72 debugbundle
72 debugbundle
73 debugcheckstate
73 debugcheckstate
74 debugcommands
74 debugcommands
75 debugcomplete
75 debugcomplete
76 debugconfig
76 debugconfig
77 debugdag
77 debugdag
78 debugdata
78 debugdata
79 debugdate
79 debugdate
80 debugdirstate
80 debugdirstate
81 debugdiscovery
81 debugdiscovery
82 debugfileset
82 debugfileset
83 debugfsinfo
83 debugfsinfo
84 debuggetbundle
84 debuggetbundle
85 debugignore
85 debugignore
86 debugindex
86 debugindex
87 debugindexdot
87 debugindexdot
88 debuginstall
88 debuginstall
89 debugknown
89 debugknown
90 debuglabelcomplete
90 debuglabelcomplete
91 debugobsolete
91 debugobsolete
92 debugpathcomplete
92 debugpathcomplete
93 debugpushkey
93 debugpushkey
94 debugpvec
94 debugpvec
95 debugrebuilddirstate
95 debugrebuilddirstate
96 debugrename
96 debugrename
97 debugrevlog
97 debugrevlog
98 debugrevspec
98 debugrevspec
99 debugsetparents
99 debugsetparents
100 debugsub
100 debugsub
101 debugsuccessorssets
101 debugsuccessorssets
102 debugwalk
102 debugwalk
103 debugwireargs
103 debugwireargs
104
104
105 Do not show the alias of a debug command if there are other candidates
105 Do not show the alias of a debug command if there are other candidates
106 (this should hide rawcommit)
106 (this should hide rawcommit)
107 $ hg debugcomplete r
107 $ hg debugcomplete r
108 recover
108 recover
109 remove
109 remove
110 rename
110 rename
111 resolve
111 resolve
112 revert
112 revert
113 rollback
113 rollback
114 root
114 root
115 Show the alias of a debug command if there are no other candidates
115 Show the alias of a debug command if there are no other candidates
116 $ hg debugcomplete rawc
116 $ hg debugcomplete rawc
117
117
118
118
119 Show the global options
119 Show the global options
120 $ hg debugcomplete --options | sort
120 $ hg debugcomplete --options | sort
121 --config
121 --config
122 --cwd
122 --cwd
123 --debug
123 --debug
124 --debugger
124 --debugger
125 --encoding
125 --encoding
126 --encodingmode
126 --encodingmode
127 --help
127 --help
128 --hidden
128 --hidden
129 --noninteractive
129 --noninteractive
130 --profile
130 --profile
131 --quiet
131 --quiet
132 --repository
132 --repository
133 --time
133 --time
134 --traceback
134 --traceback
135 --verbose
135 --verbose
136 --version
136 --version
137 -R
137 -R
138 -h
138 -h
139 -q
139 -q
140 -v
140 -v
141 -y
141 -y
142
142
143 Show the options for the "serve" command
143 Show the options for the "serve" command
144 $ hg debugcomplete --options serve | sort
144 $ hg debugcomplete --options serve | sort
145 --accesslog
145 --accesslog
146 --address
146 --address
147 --certificate
147 --certificate
148 --cmdserver
148 --cmdserver
149 --config
149 --config
150 --cwd
150 --cwd
151 --daemon
151 --daemon
152 --daemon-pipefds
152 --daemon-pipefds
153 --debug
153 --debug
154 --debugger
154 --debugger
155 --encoding
155 --encoding
156 --encodingmode
156 --encodingmode
157 --errorlog
157 --errorlog
158 --help
158 --help
159 --hidden
159 --hidden
160 --ipv6
160 --ipv6
161 --name
161 --name
162 --noninteractive
162 --noninteractive
163 --pid-file
163 --pid-file
164 --port
164 --port
165 --prefix
165 --prefix
166 --profile
166 --profile
167 --quiet
167 --quiet
168 --repository
168 --repository
169 --stdio
169 --stdio
170 --style
170 --style
171 --templates
171 --templates
172 --time
172 --time
173 --traceback
173 --traceback
174 --verbose
174 --verbose
175 --version
175 --version
176 --web-conf
176 --web-conf
177 -6
177 -6
178 -A
178 -A
179 -E
179 -E
180 -R
180 -R
181 -a
181 -a
182 -d
182 -d
183 -h
183 -h
184 -n
184 -n
185 -p
185 -p
186 -q
186 -q
187 -t
187 -t
188 -v
188 -v
189 -y
189 -y
190
190
191 Show an error if we use --options with an ambiguous abbreviation
191 Show an error if we use --options with an ambiguous abbreviation
192 $ hg debugcomplete --options s
192 $ hg debugcomplete --options s
193 hg: command 's' is ambiguous:
193 hg: command 's' is ambiguous:
194 serve showconfig status summary
194 serve showconfig status summary
195 [255]
195 [255]
196
196
197 Show all commands + options
197 Show all commands + options
198 $ hg debugcommands
198 $ hg debugcommands
199 add: include, exclude, subrepos, dry-run
199 add: include, exclude, subrepos, dry-run
200 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
200 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
201 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
201 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
202 commit: addremove, close-branch, amend, secret, include, exclude, message, logfile, date, user, subrepos
202 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
203 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
203 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
204 export: output, switch-parent, rev, text, git, nodates
204 export: output, switch-parent, rev, text, git, nodates
205 forget: include, exclude
205 forget: include, exclude
206 init: ssh, remotecmd, insecure
206 init: ssh, remotecmd, insecure
207 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
207 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
208 merge: force, rev, preview, tool
208 merge: force, rev, preview, tool
209 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
209 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
210 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
210 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
211 remove: after, force, include, exclude
211 remove: after, force, include, exclude
212 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
212 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
213 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
213 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
214 summary: remote
214 summary: remote
215 update: clean, check, date, rev
215 update: clean, check, date, rev
216 addremove: similarity, include, exclude, dry-run
216 addremove: similarity, include, exclude, dry-run
217 archive: no-decode, prefix, rev, type, subrepos, include, exclude
217 archive: no-decode, prefix, rev, type, subrepos, include, exclude
218 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
218 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
219 bisect: reset, good, bad, skip, extend, command, noupdate
219 bisect: reset, good, bad, skip, extend, command, noupdate
220 bookmarks: force, rev, delete, rename, inactive
220 bookmarks: force, rev, delete, rename, inactive
221 branch: force, clean
221 branch: force, clean
222 branches: active, closed
222 branches: active, closed
223 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
223 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
224 cat: output, rev, decode, include, exclude
224 cat: output, rev, decode, include, exclude
225 config: untrusted, edit, local, global
225 config: untrusted, edit, local, global
226 copy: after, force, include, exclude, dry-run
226 copy: after, force, include, exclude, dry-run
227 debugancestor:
227 debugancestor:
228 debugbuilddag: mergeable-file, overwritten-file, new-file
228 debugbuilddag: mergeable-file, overwritten-file, new-file
229 debugbundle: all
229 debugbundle: all
230 debugcheckstate:
230 debugcheckstate:
231 debugcommands:
231 debugcommands:
232 debugcomplete: options
232 debugcomplete: options
233 debugdag: tags, branches, dots, spaces
233 debugdag: tags, branches, dots, spaces
234 debugdata: changelog, manifest
234 debugdata: changelog, manifest
235 debugdate: extended
235 debugdate: extended
236 debugdirstate: nodates, datesort
236 debugdirstate: nodates, datesort
237 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
237 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
238 debugfileset: rev
238 debugfileset: rev
239 debugfsinfo:
239 debugfsinfo:
240 debuggetbundle: head, common, type
240 debuggetbundle: head, common, type
241 debugignore:
241 debugignore:
242 debugindex: changelog, manifest, format
242 debugindex: changelog, manifest, format
243 debugindexdot:
243 debugindexdot:
244 debuginstall:
244 debuginstall:
245 debugknown:
245 debugknown:
246 debuglabelcomplete:
246 debuglabelcomplete:
247 debugobsolete: flags, date, user
247 debugobsolete: flags, date, user
248 debugpathcomplete: full, normal, added, removed
248 debugpathcomplete: full, normal, added, removed
249 debugpushkey:
249 debugpushkey:
250 debugpvec:
250 debugpvec:
251 debugrebuilddirstate: rev
251 debugrebuilddirstate: rev
252 debugrename: rev
252 debugrename: rev
253 debugrevlog: changelog, manifest, dump
253 debugrevlog: changelog, manifest, dump
254 debugrevspec: optimize
254 debugrevspec: optimize
255 debugsetparents:
255 debugsetparents:
256 debugsub: rev
256 debugsub: rev
257 debugsuccessorssets:
257 debugsuccessorssets:
258 debugwalk: include, exclude
258 debugwalk: include, exclude
259 debugwireargs: three, four, five, ssh, remotecmd, insecure
259 debugwireargs: three, four, five, ssh, remotecmd, insecure
260 graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
260 graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
261 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
261 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
262 heads: rev, topo, active, closed, style, template
262 heads: rev, topo, active, closed, style, template
263 help: extension, command, keyword
263 help: extension, command, keyword
264 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
264 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
265 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
265 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
266 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
266 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
267 locate: rev, print0, fullpath, include, exclude
267 locate: rev, print0, fullpath, include, exclude
268 manifest: rev, all
268 manifest: rev, all
269 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
269 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
270 parents: rev, style, template
270 parents: rev, style, template
271 paths:
271 paths:
272 phase: public, draft, secret, force, rev
272 phase: public, draft, secret, force, rev
273 recover:
273 recover:
274 rename: after, force, include, exclude, dry-run
274 rename: after, force, include, exclude, dry-run
275 resolve: all, list, mark, unmark, no-status, tool, include, exclude
275 resolve: all, list, mark, unmark, no-status, tool, include, exclude
276 revert: all, date, rev, no-backup, include, exclude, dry-run
276 revert: all, date, rev, no-backup, include, exclude, dry-run
277 rollback: dry-run, force
277 rollback: dry-run, force
278 root:
278 root:
279 tag: force, local, rev, remove, edit, message, date, user
279 tag: force, local, rev, remove, edit, message, date, user
280 tags:
280 tags:
281 tip: patch, git, style, template
281 tip: patch, git, style, template
282 unbundle: update
282 unbundle: update
283 verify:
283 verify:
284 version:
284 version:
285
285
286 $ hg init a
286 $ hg init a
287 $ cd a
287 $ cd a
288 $ echo fee > fee
288 $ echo fee > fee
289 $ hg ci -q -Amfee
289 $ hg ci -q -Amfee
290 $ hg tag fee
290 $ hg tag fee
291 $ mkdir fie
291 $ mkdir fie
292 $ echo dead > fie/dead
292 $ echo dead > fie/dead
293 $ echo live > fie/live
293 $ echo live > fie/live
294 $ hg bookmark fo
294 $ hg bookmark fo
295 $ hg branch -q fie
295 $ hg branch -q fie
296 $ hg ci -q -Amfie
296 $ hg ci -q -Amfie
297 $ echo fo > fo
297 $ echo fo > fo
298 $ hg branch -qf default
298 $ hg branch -qf default
299 $ hg ci -q -Amfo
299 $ hg ci -q -Amfo
300 $ echo Fum > Fum
300 $ echo Fum > Fum
301 $ hg ci -q -AmFum
301 $ hg ci -q -AmFum
302 $ hg bookmark Fum
302 $ hg bookmark Fum
303
303
304 Test debugpathcomplete
304 Test debugpathcomplete
305
305
306 $ hg debugpathcomplete f
306 $ hg debugpathcomplete f
307 fee
307 fee
308 fie
308 fie
309 fo
309 fo
310 $ hg debugpathcomplete -f f
310 $ hg debugpathcomplete -f f
311 fee
311 fee
312 fie/dead
312 fie/dead
313 fie/live
313 fie/live
314 fo
314 fo
315
315
316 $ hg rm Fum
316 $ hg rm Fum
317 $ hg debugpathcomplete -r F
317 $ hg debugpathcomplete -r F
318 Fum
318 Fum
319
319
320 Test debuglabelcomplete
320 Test debuglabelcomplete
321
321
322 $ hg debuglabelcomplete
322 $ hg debuglabelcomplete
323 Fum
323 Fum
324 default
324 default
325 fee
325 fee
326 fie
326 fie
327 fo
327 fo
328 tip
328 tip
329 $ hg debuglabelcomplete f
329 $ hg debuglabelcomplete f
330 fee
330 fee
331 fie
331 fie
332 fo
332 fo
@@ -1,403 +1,404 b''
1 Create configuration
1 Create configuration
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "interactive=true" >> $HGRCPATH
4 $ echo "interactive=true" >> $HGRCPATH
5
5
6 help record (no record)
6 help record (no record)
7
7
8 $ hg help record
8 $ hg help record
9 record extension - commands to interactively select changes for
9 record extension - commands to interactively select changes for
10 commit/qrefresh
10 commit/qrefresh
11
11
12 use "hg help extensions" for information on enabling extensions
12 use "hg help extensions" for information on enabling extensions
13
13
14 help qrecord (no record)
14 help qrecord (no record)
15
15
16 $ hg help qrecord
16 $ hg help qrecord
17 'qrecord' is provided by the following extension:
17 'qrecord' is provided by the following extension:
18
18
19 record commands to interactively select changes for commit/qrefresh
19 record commands to interactively select changes for commit/qrefresh
20
20
21 use "hg help extensions" for information on enabling extensions
21 use "hg help extensions" for information on enabling extensions
22
22
23 $ echo "[extensions]" >> $HGRCPATH
23 $ echo "[extensions]" >> $HGRCPATH
24 $ echo "record=" >> $HGRCPATH
24 $ echo "record=" >> $HGRCPATH
25
25
26 help record (record)
26 help record (record)
27
27
28 $ hg help record
28 $ hg help record
29 hg record [OPTION]... [FILE]...
29 hg record [OPTION]... [FILE]...
30
30
31 interactively select changes to commit
31 interactively select changes to commit
32
32
33 If a list of files is omitted, all changes reported by "hg status" will be
33 If a list of files is omitted, all changes reported by "hg status" will be
34 candidates for recording.
34 candidates for recording.
35
35
36 See "hg help dates" for a list of formats valid for -d/--date.
36 See "hg help dates" for a list of formats valid for -d/--date.
37
37
38 You will be prompted for whether to record changes to each modified file,
38 You will be prompted for whether to record changes to each modified file,
39 and for files with multiple changes, for each change to use. For each
39 and for files with multiple changes, for each change to use. For each
40 query, the following responses are possible:
40 query, the following responses are possible:
41
41
42 y - record this change
42 y - record this change
43 n - skip this change
43 n - skip this change
44 e - edit this change manually
44 e - edit this change manually
45
45
46 s - skip remaining changes to this file
46 s - skip remaining changes to this file
47 f - record remaining changes to this file
47 f - record remaining changes to this file
48
48
49 d - done, skip remaining changes and files
49 d - done, skip remaining changes and files
50 a - record all changes to all remaining files
50 a - record all changes to all remaining files
51 q - quit, recording no changes
51 q - quit, recording no changes
52
52
53 ? - display help
53 ? - display help
54
54
55 This command is not available when committing a merge.
55 This command is not available when committing a merge.
56
56
57 options:
57 options:
58
58
59 -A --addremove mark new/missing files as added/removed before
59 -A --addremove mark new/missing files as added/removed before
60 committing
60 committing
61 --close-branch mark a branch as closed, hiding it from the branch
61 --close-branch mark a branch as closed, hiding it from the branch
62 list
62 list
63 --amend amend the parent of the working dir
63 --amend amend the parent of the working dir
64 -s --secret use the secret phase for committing
64 -s --secret use the secret phase for committing
65 -e --edit further edit commit message already specified
65 -I --include PATTERN [+] include names matching the given patterns
66 -I --include PATTERN [+] include names matching the given patterns
66 -X --exclude PATTERN [+] exclude names matching the given patterns
67 -X --exclude PATTERN [+] exclude names matching the given patterns
67 -m --message TEXT use text as commit message
68 -m --message TEXT use text as commit message
68 -l --logfile FILE read commit message from file
69 -l --logfile FILE read commit message from file
69 -d --date DATE record the specified date as commit date
70 -d --date DATE record the specified date as commit date
70 -u --user USER record the specified user as committer
71 -u --user USER record the specified user as committer
71 -S --subrepos recurse into subrepositories
72 -S --subrepos recurse into subrepositories
72 -w --ignore-all-space ignore white space when comparing lines
73 -w --ignore-all-space ignore white space when comparing lines
73 -b --ignore-space-change ignore changes in the amount of white space
74 -b --ignore-space-change ignore changes in the amount of white space
74 -B --ignore-blank-lines ignore changes whose lines are all blank
75 -B --ignore-blank-lines ignore changes whose lines are all blank
75
76
76 [+] marked option can be specified multiple times
77 [+] marked option can be specified multiple times
77
78
78 use "hg -v help record" to show the global options
79 use "hg -v help record" to show the global options
79
80
80 help (no mq, so no qrecord)
81 help (no mq, so no qrecord)
81
82
82 $ hg help qrecord
83 $ hg help qrecord
83 hg qrecord [OPTION]... PATCH [FILE]...
84 hg qrecord [OPTION]... PATCH [FILE]...
84
85
85 interactively record a new patch
86 interactively record a new patch
86
87
87 See "hg help qnew" & "hg help record" for more information and usage.
88 See "hg help qnew" & "hg help record" for more information and usage.
88
89
89 use "hg -v help qrecord" to show the global options
90 use "hg -v help qrecord" to show the global options
90
91
91 $ hg init a
92 $ hg init a
92
93
93 qrecord (mq not present)
94 qrecord (mq not present)
94
95
95 $ hg -R a qrecord
96 $ hg -R a qrecord
96 hg qrecord: invalid arguments
97 hg qrecord: invalid arguments
97 hg qrecord [OPTION]... PATCH [FILE]...
98 hg qrecord [OPTION]... PATCH [FILE]...
98
99
99 interactively record a new patch
100 interactively record a new patch
100
101
101 use "hg help qrecord" to show the full help text
102 use "hg help qrecord" to show the full help text
102 [255]
103 [255]
103
104
104 qrecord patch (mq not present)
105 qrecord patch (mq not present)
105
106
106 $ hg -R a qrecord patch
107 $ hg -R a qrecord patch
107 abort: 'mq' extension not loaded
108 abort: 'mq' extension not loaded
108 [255]
109 [255]
109
110
110 help (bad mq)
111 help (bad mq)
111
112
112 $ echo "mq=nonexistent" >> $HGRCPATH
113 $ echo "mq=nonexistent" >> $HGRCPATH
113 $ hg help qrecord
114 $ hg help qrecord
114 *** failed to import extension mq from nonexistent: [Errno *] * (glob)
115 *** failed to import extension mq from nonexistent: [Errno *] * (glob)
115 hg qrecord [OPTION]... PATCH [FILE]...
116 hg qrecord [OPTION]... PATCH [FILE]...
116
117
117 interactively record a new patch
118 interactively record a new patch
118
119
119 See "hg help qnew" & "hg help record" for more information and usage.
120 See "hg help qnew" & "hg help record" for more information and usage.
120
121
121 use "hg -v help qrecord" to show the global options
122 use "hg -v help qrecord" to show the global options
122
123
123 help (mq present)
124 help (mq present)
124
125
125 $ sed 's/mq=nonexistent/mq=/' $HGRCPATH > hgrc.tmp
126 $ sed 's/mq=nonexistent/mq=/' $HGRCPATH > hgrc.tmp
126 $ mv hgrc.tmp $HGRCPATH
127 $ mv hgrc.tmp $HGRCPATH
127
128
128 $ hg help qrecord
129 $ hg help qrecord
129 hg qrecord [OPTION]... PATCH [FILE]...
130 hg qrecord [OPTION]... PATCH [FILE]...
130
131
131 interactively record a new patch
132 interactively record a new patch
132
133
133 See "hg help qnew" & "hg help record" for more information and usage.
134 See "hg help qnew" & "hg help record" for more information and usage.
134
135
135 options:
136 options:
136
137
137 -e --edit edit commit message
138 -e --edit edit commit message
138 -g --git use git extended diff format
139 -g --git use git extended diff format
139 -U --currentuser add "From: <current user>" to patch
140 -U --currentuser add "From: <current user>" to patch
140 -u --user USER add "From: <USER>" to patch
141 -u --user USER add "From: <USER>" to patch
141 -D --currentdate add "Date: <current date>" to patch
142 -D --currentdate add "Date: <current date>" to patch
142 -d --date DATE add "Date: <DATE>" to patch
143 -d --date DATE add "Date: <DATE>" to patch
143 -I --include PATTERN [+] include names matching the given patterns
144 -I --include PATTERN [+] include names matching the given patterns
144 -X --exclude PATTERN [+] exclude names matching the given patterns
145 -X --exclude PATTERN [+] exclude names matching the given patterns
145 -m --message TEXT use text as commit message
146 -m --message TEXT use text as commit message
146 -l --logfile FILE read commit message from file
147 -l --logfile FILE read commit message from file
147 -w --ignore-all-space ignore white space when comparing lines
148 -w --ignore-all-space ignore white space when comparing lines
148 -b --ignore-space-change ignore changes in the amount of white space
149 -b --ignore-space-change ignore changes in the amount of white space
149 -B --ignore-blank-lines ignore changes whose lines are all blank
150 -B --ignore-blank-lines ignore changes whose lines are all blank
150 --mq operate on patch repository
151 --mq operate on patch repository
151
152
152 [+] marked option can be specified multiple times
153 [+] marked option can be specified multiple times
153
154
154 use "hg -v help qrecord" to show the global options
155 use "hg -v help qrecord" to show the global options
155
156
156 $ cd a
157 $ cd a
157
158
158 Base commit
159 Base commit
159
160
160 $ cat > 1.txt <<EOF
161 $ cat > 1.txt <<EOF
161 > 1
162 > 1
162 > 2
163 > 2
163 > 3
164 > 3
164 > 4
165 > 4
165 > 5
166 > 5
166 > EOF
167 > EOF
167 $ cat > 2.txt <<EOF
168 $ cat > 2.txt <<EOF
168 > a
169 > a
169 > b
170 > b
170 > c
171 > c
171 > d
172 > d
172 > e
173 > e
173 > f
174 > f
174 > EOF
175 > EOF
175
176
176 $ mkdir dir
177 $ mkdir dir
177 $ cat > dir/a.txt <<EOF
178 $ cat > dir/a.txt <<EOF
178 > hello world
179 > hello world
179 >
180 >
180 > someone
181 > someone
181 > up
182 > up
182 > there
183 > there
183 > loves
184 > loves
184 > me
185 > me
185 > EOF
186 > EOF
186
187
187 $ hg add 1.txt 2.txt dir/a.txt
188 $ hg add 1.txt 2.txt dir/a.txt
188 $ hg commit -m 'initial checkin'
189 $ hg commit -m 'initial checkin'
189
190
190 Changing files
191 Changing files
191
192
192 $ sed -e 's/2/2 2/;s/4/4 4/' 1.txt > 1.txt.new
193 $ sed -e 's/2/2 2/;s/4/4 4/' 1.txt > 1.txt.new
193 $ sed -e 's/b/b b/' 2.txt > 2.txt.new
194 $ sed -e 's/b/b b/' 2.txt > 2.txt.new
194 $ sed -e 's/hello world/hello world!/' dir/a.txt > dir/a.txt.new
195 $ sed -e 's/hello world/hello world!/' dir/a.txt > dir/a.txt.new
195
196
196 $ mv -f 1.txt.new 1.txt
197 $ mv -f 1.txt.new 1.txt
197 $ mv -f 2.txt.new 2.txt
198 $ mv -f 2.txt.new 2.txt
198 $ mv -f dir/a.txt.new dir/a.txt
199 $ mv -f dir/a.txt.new dir/a.txt
199
200
200 Whole diff
201 Whole diff
201
202
202 $ hg diff --nodates
203 $ hg diff --nodates
203 diff -r 1057167b20ef 1.txt
204 diff -r 1057167b20ef 1.txt
204 --- a/1.txt
205 --- a/1.txt
205 +++ b/1.txt
206 +++ b/1.txt
206 @@ -1,5 +1,5 @@
207 @@ -1,5 +1,5 @@
207 1
208 1
208 -2
209 -2
209 +2 2
210 +2 2
210 3
211 3
211 -4
212 -4
212 +4 4
213 +4 4
213 5
214 5
214 diff -r 1057167b20ef 2.txt
215 diff -r 1057167b20ef 2.txt
215 --- a/2.txt
216 --- a/2.txt
216 +++ b/2.txt
217 +++ b/2.txt
217 @@ -1,5 +1,5 @@
218 @@ -1,5 +1,5 @@
218 a
219 a
219 -b
220 -b
220 +b b
221 +b b
221 c
222 c
222 d
223 d
223 e
224 e
224 diff -r 1057167b20ef dir/a.txt
225 diff -r 1057167b20ef dir/a.txt
225 --- a/dir/a.txt
226 --- a/dir/a.txt
226 +++ b/dir/a.txt
227 +++ b/dir/a.txt
227 @@ -1,4 +1,4 @@
228 @@ -1,4 +1,4 @@
228 -hello world
229 -hello world
229 +hello world!
230 +hello world!
230
231
231 someone
232 someone
232 up
233 up
233
234
234 qrecord with bad patch name, should abort before prompting
235 qrecord with bad patch name, should abort before prompting
235
236
236 $ hg qrecord .hg
237 $ hg qrecord .hg
237 abort: patch name cannot begin with ".hg"
238 abort: patch name cannot begin with ".hg"
238 [255]
239 [255]
239
240
240 qrecord a.patch
241 qrecord a.patch
241
242
242 $ hg qrecord -d '0 0' -m aaa a.patch <<EOF
243 $ hg qrecord -d '0 0' -m aaa a.patch <<EOF
243 > y
244 > y
244 > y
245 > y
245 > n
246 > n
246 > y
247 > y
247 > y
248 > y
248 > n
249 > n
249 > EOF
250 > EOF
250 diff --git a/1.txt b/1.txt
251 diff --git a/1.txt b/1.txt
251 2 hunks, 2 lines changed
252 2 hunks, 2 lines changed
252 examine changes to '1.txt'? [Ynesfdaq?]
253 examine changes to '1.txt'? [Ynesfdaq?]
253 @@ -1,3 +1,3 @@
254 @@ -1,3 +1,3 @@
254 1
255 1
255 -2
256 -2
256 +2 2
257 +2 2
257 3
258 3
258 record change 1/4 to '1.txt'? [Ynesfdaq?]
259 record change 1/4 to '1.txt'? [Ynesfdaq?]
259 @@ -3,3 +3,3 @@
260 @@ -3,3 +3,3 @@
260 3
261 3
261 -4
262 -4
262 +4 4
263 +4 4
263 5
264 5
264 record change 2/4 to '1.txt'? [Ynesfdaq?]
265 record change 2/4 to '1.txt'? [Ynesfdaq?]
265 diff --git a/2.txt b/2.txt
266 diff --git a/2.txt b/2.txt
266 1 hunks, 1 lines changed
267 1 hunks, 1 lines changed
267 examine changes to '2.txt'? [Ynesfdaq?]
268 examine changes to '2.txt'? [Ynesfdaq?]
268 @@ -1,5 +1,5 @@
269 @@ -1,5 +1,5 @@
269 a
270 a
270 -b
271 -b
271 +b b
272 +b b
272 c
273 c
273 d
274 d
274 e
275 e
275 record change 3/4 to '2.txt'? [Ynesfdaq?]
276 record change 3/4 to '2.txt'? [Ynesfdaq?]
276 diff --git a/dir/a.txt b/dir/a.txt
277 diff --git a/dir/a.txt b/dir/a.txt
277 1 hunks, 1 lines changed
278 1 hunks, 1 lines changed
278 examine changes to 'dir/a.txt'? [Ynesfdaq?]
279 examine changes to 'dir/a.txt'? [Ynesfdaq?]
279
280
280 After qrecord a.patch 'tip'"
281 After qrecord a.patch 'tip'"
281
282
282 $ hg tip -p
283 $ hg tip -p
283 changeset: 1:5d1ca63427ee
284 changeset: 1:5d1ca63427ee
284 tag: a.patch
285 tag: a.patch
285 tag: qbase
286 tag: qbase
286 tag: qtip
287 tag: qtip
287 tag: tip
288 tag: tip
288 user: test
289 user: test
289 date: Thu Jan 01 00:00:00 1970 +0000
290 date: Thu Jan 01 00:00:00 1970 +0000
290 summary: aaa
291 summary: aaa
291
292
292 diff -r 1057167b20ef -r 5d1ca63427ee 1.txt
293 diff -r 1057167b20ef -r 5d1ca63427ee 1.txt
293 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
294 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
294 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
295 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
295 @@ -1,5 +1,5 @@
296 @@ -1,5 +1,5 @@
296 1
297 1
297 -2
298 -2
298 +2 2
299 +2 2
299 3
300 3
300 4
301 4
301 5
302 5
302 diff -r 1057167b20ef -r 5d1ca63427ee 2.txt
303 diff -r 1057167b20ef -r 5d1ca63427ee 2.txt
303 --- a/2.txt Thu Jan 01 00:00:00 1970 +0000
304 --- a/2.txt Thu Jan 01 00:00:00 1970 +0000
304 +++ b/2.txt Thu Jan 01 00:00:00 1970 +0000
305 +++ b/2.txt Thu Jan 01 00:00:00 1970 +0000
305 @@ -1,5 +1,5 @@
306 @@ -1,5 +1,5 @@
306 a
307 a
307 -b
308 -b
308 +b b
309 +b b
309 c
310 c
310 d
311 d
311 e
312 e
312
313
313
314
314 After qrecord a.patch 'diff'"
315 After qrecord a.patch 'diff'"
315
316
316 $ hg diff --nodates
317 $ hg diff --nodates
317 diff -r 5d1ca63427ee 1.txt
318 diff -r 5d1ca63427ee 1.txt
318 --- a/1.txt
319 --- a/1.txt
319 +++ b/1.txt
320 +++ b/1.txt
320 @@ -1,5 +1,5 @@
321 @@ -1,5 +1,5 @@
321 1
322 1
322 2 2
323 2 2
323 3
324 3
324 -4
325 -4
325 +4 4
326 +4 4
326 5
327 5
327 diff -r 5d1ca63427ee dir/a.txt
328 diff -r 5d1ca63427ee dir/a.txt
328 --- a/dir/a.txt
329 --- a/dir/a.txt
329 +++ b/dir/a.txt
330 +++ b/dir/a.txt
330 @@ -1,4 +1,4 @@
331 @@ -1,4 +1,4 @@
331 -hello world
332 -hello world
332 +hello world!
333 +hello world!
333
334
334 someone
335 someone
335 up
336 up
336
337
337 qrecord b.patch
338 qrecord b.patch
338
339
339 $ hg qrecord -d '0 0' -m bbb b.patch <<EOF
340 $ hg qrecord -d '0 0' -m bbb b.patch <<EOF
340 > y
341 > y
341 > y
342 > y
342 > y
343 > y
343 > y
344 > y
344 > EOF
345 > EOF
345 diff --git a/1.txt b/1.txt
346 diff --git a/1.txt b/1.txt
346 1 hunks, 1 lines changed
347 1 hunks, 1 lines changed
347 examine changes to '1.txt'? [Ynesfdaq?]
348 examine changes to '1.txt'? [Ynesfdaq?]
348 @@ -1,5 +1,5 @@
349 @@ -1,5 +1,5 @@
349 1
350 1
350 2 2
351 2 2
351 3
352 3
352 -4
353 -4
353 +4 4
354 +4 4
354 5
355 5
355 record change 1/2 to '1.txt'? [Ynesfdaq?]
356 record change 1/2 to '1.txt'? [Ynesfdaq?]
356 diff --git a/dir/a.txt b/dir/a.txt
357 diff --git a/dir/a.txt b/dir/a.txt
357 1 hunks, 1 lines changed
358 1 hunks, 1 lines changed
358 examine changes to 'dir/a.txt'? [Ynesfdaq?]
359 examine changes to 'dir/a.txt'? [Ynesfdaq?]
359 @@ -1,4 +1,4 @@
360 @@ -1,4 +1,4 @@
360 -hello world
361 -hello world
361 +hello world!
362 +hello world!
362
363
363 someone
364 someone
364 up
365 up
365 record change 2/2 to 'dir/a.txt'? [Ynesfdaq?]
366 record change 2/2 to 'dir/a.txt'? [Ynesfdaq?]
366
367
367 After qrecord b.patch 'tip'
368 After qrecord b.patch 'tip'
368
369
369 $ hg tip -p
370 $ hg tip -p
370 changeset: 2:b056198bf878
371 changeset: 2:b056198bf878
371 tag: b.patch
372 tag: b.patch
372 tag: qtip
373 tag: qtip
373 tag: tip
374 tag: tip
374 user: test
375 user: test
375 date: Thu Jan 01 00:00:00 1970 +0000
376 date: Thu Jan 01 00:00:00 1970 +0000
376 summary: bbb
377 summary: bbb
377
378
378 diff -r 5d1ca63427ee -r b056198bf878 1.txt
379 diff -r 5d1ca63427ee -r b056198bf878 1.txt
379 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
380 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
380 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
381 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
381 @@ -1,5 +1,5 @@
382 @@ -1,5 +1,5 @@
382 1
383 1
383 2 2
384 2 2
384 3
385 3
385 -4
386 -4
386 +4 4
387 +4 4
387 5
388 5
388 diff -r 5d1ca63427ee -r b056198bf878 dir/a.txt
389 diff -r 5d1ca63427ee -r b056198bf878 dir/a.txt
389 --- a/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
390 --- a/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
390 +++ b/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
391 +++ b/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
391 @@ -1,4 +1,4 @@
392 @@ -1,4 +1,4 @@
392 -hello world
393 -hello world
393 +hello world!
394 +hello world!
394
395
395 someone
396 someone
396 up
397 up
397
398
398
399
399 After qrecord b.patch 'diff'
400 After qrecord b.patch 'diff'
400
401
401 $ hg diff --nodates
402 $ hg diff --nodates
402
403
403 $ cd ..
404 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now