##// END OF EJS Templates
bookmarks: abort when incompatible options are used (issue3663)...
David Soria Parra -
r17790:0291e122 default
parent child Browse files
Show More
@@ -1,5921 +1,5928
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('G', 'graph', None, _("show the revision DAG")),
101 ('G', 'graph', None, _("show the revision DAG")),
102 ] + templateopts
102 ] + templateopts
103
103
104 diffopts = [
104 diffopts = [
105 ('a', 'text', None, _('treat all files as text')),
105 ('a', 'text', None, _('treat all files as text')),
106 ('g', 'git', None, _('use git extended diff format')),
106 ('g', 'git', None, _('use git extended diff format')),
107 ('', 'nodates', None, _('omit dates from diff headers'))
107 ('', 'nodates', None, _('omit dates from diff headers'))
108 ]
108 ]
109
109
110 diffwsopts = [
110 diffwsopts = [
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ]
117 ]
118
118
119 diffopts2 = [
119 diffopts2 = [
120 ('p', 'show-function', None, _('show which function each change is in')),
120 ('p', 'show-function', None, _('show which function each change is in')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ] + diffwsopts + [
122 ] + diffwsopts + [
123 ('U', 'unified', '',
123 ('U', 'unified', '',
124 _('number of lines of context to show'), _('NUM')),
124 _('number of lines of context to show'), _('NUM')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ]
126 ]
127
127
128 mergetoolopts = [
128 mergetoolopts = [
129 ('t', 'tool', '', _('specify merge tool')),
129 ('t', 'tool', '', _('specify merge tool')),
130 ]
130 ]
131
131
132 similarityopts = [
132 similarityopts = [
133 ('s', 'similarity', '',
133 ('s', 'similarity', '',
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 ]
135 ]
136
136
137 subrepoopts = [
137 subrepoopts = [
138 ('S', 'subrepos', None,
138 ('S', 'subrepos', None,
139 _('recurse into subrepositories'))
139 _('recurse into subrepositories'))
140 ]
140 ]
141
141
142 # Commands start here, listed alphabetically
142 # Commands start here, listed alphabetically
143
143
144 @command('^add',
144 @command('^add',
145 walkopts + subrepoopts + dryrunopts,
145 walkopts + subrepoopts + dryrunopts,
146 _('[OPTION]... [FILE]...'))
146 _('[OPTION]... [FILE]...'))
147 def add(ui, repo, *pats, **opts):
147 def add(ui, repo, *pats, **opts):
148 """add the specified files on the next commit
148 """add the specified files on the next commit
149
149
150 Schedule files to be version controlled and added to the
150 Schedule files to be version controlled and added to the
151 repository.
151 repository.
152
152
153 The files will be added to the repository at the next commit. To
153 The files will be added to the repository at the next commit. To
154 undo an add before that, see :hg:`forget`.
154 undo an add before that, see :hg:`forget`.
155
155
156 If no names are given, add all files to the repository.
156 If no names are given, add all files to the repository.
157
157
158 .. container:: verbose
158 .. container:: verbose
159
159
160 An example showing how new (unknown) files are added
160 An example showing how new (unknown) files are added
161 automatically by :hg:`add`::
161 automatically by :hg:`add`::
162
162
163 $ ls
163 $ ls
164 foo.c
164 foo.c
165 $ hg status
165 $ hg status
166 ? foo.c
166 ? foo.c
167 $ hg add
167 $ hg add
168 adding foo.c
168 adding foo.c
169 $ hg status
169 $ hg status
170 A foo.c
170 A foo.c
171
171
172 Returns 0 if all files are successfully added.
172 Returns 0 if all files are successfully added.
173 """
173 """
174
174
175 m = scmutil.match(repo[None], pats, opts)
175 m = scmutil.match(repo[None], pats, opts)
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 opts.get('subrepos'), prefix="", explicitonly=False)
177 opts.get('subrepos'), prefix="", explicitonly=False)
178 return rejected and 1 or 0
178 return rejected and 1 or 0
179
179
180 @command('addremove',
180 @command('addremove',
181 similarityopts + walkopts + dryrunopts,
181 similarityopts + walkopts + dryrunopts,
182 _('[OPTION]... [FILE]...'))
182 _('[OPTION]... [FILE]...'))
183 def addremove(ui, repo, *pats, **opts):
183 def addremove(ui, repo, *pats, **opts):
184 """add all new files, delete all missing files
184 """add all new files, delete all missing files
185
185
186 Add all new files and remove all missing files from the
186 Add all new files and remove all missing files from the
187 repository.
187 repository.
188
188
189 New files are ignored if they match any of the patterns in
189 New files are ignored if they match any of the patterns in
190 ``.hgignore``. As with add, these changes take effect at the next
190 ``.hgignore``. As with add, these changes take effect at the next
191 commit.
191 commit.
192
192
193 Use the -s/--similarity option to detect renamed files. This
193 Use the -s/--similarity option to detect renamed files. This
194 option takes a percentage between 0 (disabled) and 100 (files must
194 option takes a percentage between 0 (disabled) and 100 (files must
195 be identical) as its parameter. With a parameter greater than 0,
195 be identical) as its parameter. With a parameter greater than 0,
196 this compares every removed file with every added file and records
196 this compares every removed file with every added file and records
197 those similar enough as renames. Detecting renamed files this way
197 those similar enough as renames. Detecting renamed files this way
198 can be expensive. After using this option, :hg:`status -C` can be
198 can be expensive. After using this option, :hg:`status -C` can be
199 used to check which files were identified as moved or renamed. If
199 used to check which files were identified as moved or renamed. If
200 not specified, -s/--similarity defaults to 100 and only renames of
200 not specified, -s/--similarity defaults to 100 and only renames of
201 identical files are detected.
201 identical files are detected.
202
202
203 Returns 0 if all files are successfully added.
203 Returns 0 if all files are successfully added.
204 """
204 """
205 try:
205 try:
206 sim = float(opts.get('similarity') or 100)
206 sim = float(opts.get('similarity') or 100)
207 except ValueError:
207 except ValueError:
208 raise util.Abort(_('similarity must be a number'))
208 raise util.Abort(_('similarity must be a number'))
209 if sim < 0 or sim > 100:
209 if sim < 0 or sim > 100:
210 raise util.Abort(_('similarity must be between 0 and 100'))
210 raise util.Abort(_('similarity must be between 0 and 100'))
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212
212
213 @command('^annotate|blame',
213 @command('^annotate|blame',
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 ('', 'follow', None,
215 ('', 'follow', None,
216 _('follow copies/renames and list the filename (DEPRECATED)')),
216 _('follow copies/renames and list the filename (DEPRECATED)')),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('a', 'text', None, _('treat all files as text')),
218 ('a', 'text', None, _('treat all files as text')),
219 ('u', 'user', None, _('list the author (long with -v)')),
219 ('u', 'user', None, _('list the author (long with -v)')),
220 ('f', 'file', None, _('list the filename')),
220 ('f', 'file', None, _('list the filename')),
221 ('d', 'date', None, _('list the date (short with -q)')),
221 ('d', 'date', None, _('list the date (short with -q)')),
222 ('n', 'number', None, _('list the revision number (default)')),
222 ('n', 'number', None, _('list the revision number (default)')),
223 ('c', 'changeset', None, _('list the changeset')),
223 ('c', 'changeset', None, _('list the changeset')),
224 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ] + diffwsopts + walkopts,
225 ] + diffwsopts + walkopts,
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 def annotate(ui, repo, *pats, **opts):
227 def annotate(ui, repo, *pats, **opts):
228 """show changeset information by line for each file
228 """show changeset information by line for each file
229
229
230 List changes in files, showing the revision id responsible for
230 List changes in files, showing the revision id responsible for
231 each line
231 each line
232
232
233 This command is useful for discovering when a change was made and
233 This command is useful for discovering when a change was made and
234 by whom.
234 by whom.
235
235
236 Without the -a/--text option, annotate will avoid processing files
236 Without the -a/--text option, annotate will avoid processing files
237 it detects as binary. With -a, annotate will annotate the file
237 it detects as binary. With -a, annotate will annotate the file
238 anyway, although the results will probably be neither useful
238 anyway, although the results will probably be neither useful
239 nor desirable.
239 nor desirable.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 """
242 """
243 if opts.get('follow'):
243 if opts.get('follow'):
244 # --follow is deprecated and now just an alias for -f/--file
244 # --follow is deprecated and now just an alias for -f/--file
245 # to mimic the behavior of Mercurial before version 1.5
245 # to mimic the behavior of Mercurial before version 1.5
246 opts['file'] = True
246 opts['file'] = True
247
247
248 datefunc = ui.quiet and util.shortdate or util.datestr
248 datefunc = ui.quiet and util.shortdate or util.datestr
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250
250
251 if not pats:
251 if not pats:
252 raise util.Abort(_('at least one filename or pattern is required'))
252 raise util.Abort(_('at least one filename or pattern is required'))
253
253
254 hexfn = ui.debugflag and hex or short
254 hexfn = ui.debugflag and hex or short
255
255
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 ('number', ' ', lambda x: str(x[0].rev())),
257 ('number', ' ', lambda x: str(x[0].rev())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('date', ' ', getdate),
259 ('date', ' ', getdate),
260 ('file', ' ', lambda x: x[0].path()),
260 ('file', ' ', lambda x: x[0].path()),
261 ('line_number', ':', lambda x: str(x[1])),
261 ('line_number', ':', lambda x: str(x[1])),
262 ]
262 ]
263
263
264 if (not opts.get('user') and not opts.get('changeset')
264 if (not opts.get('user') and not opts.get('changeset')
265 and not opts.get('date') and not opts.get('file')):
265 and not opts.get('date') and not opts.get('file')):
266 opts['number'] = True
266 opts['number'] = True
267
267
268 linenumber = opts.get('line_number') is not None
268 linenumber = opts.get('line_number') is not None
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
270 raise util.Abort(_('at least one of -n/-c is required for -l'))
271
271
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274
274
275 def bad(x, y):
275 def bad(x, y):
276 raise util.Abort("%s: %s" % (x, y))
276 raise util.Abort("%s: %s" % (x, y))
277
277
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 m = scmutil.match(ctx, pats, opts)
279 m = scmutil.match(ctx, pats, opts)
280 m.bad = bad
280 m.bad = bad
281 follow = not opts.get('no_follow')
281 follow = not opts.get('no_follow')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
282 diffopts = patch.diffopts(ui, opts, section='annotate')
283 for abs in ctx.walk(m):
283 for abs in ctx.walk(m):
284 fctx = ctx[abs]
284 fctx = ctx[abs]
285 if not opts.get('text') and util.binary(fctx.data()):
285 if not opts.get('text') and util.binary(fctx.data()):
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 continue
287 continue
288
288
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 diffopts=diffopts)
290 diffopts=diffopts)
291 pieces = []
291 pieces = []
292
292
293 for f, sep in funcmap:
293 for f, sep in funcmap:
294 l = [f(n) for n, dummy in lines]
294 l = [f(n) for n, dummy in lines]
295 if l:
295 if l:
296 sized = [(x, encoding.colwidth(x)) for x in l]
296 sized = [(x, encoding.colwidth(x)) for x in l]
297 ml = max([w for x, w in sized])
297 ml = max([w for x, w in sized])
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 for x, w in sized])
299 for x, w in sized])
300
300
301 if pieces:
301 if pieces:
302 for p, l in zip(zip(*pieces), lines):
302 for p, l in zip(zip(*pieces), lines):
303 ui.write("%s: %s" % ("".join(p), l[1]))
303 ui.write("%s: %s" % ("".join(p), l[1]))
304
304
305 if lines and not lines[-1][1].endswith('\n'):
305 if lines and not lines[-1][1].endswith('\n'):
306 ui.write('\n')
306 ui.write('\n')
307
307
308 @command('archive',
308 @command('archive',
309 [('', 'no-decode', None, _('do not pass files through decoders')),
309 [('', 'no-decode', None, _('do not pass files through decoders')),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 _('PREFIX')),
311 _('PREFIX')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ] + subrepoopts + walkopts,
314 ] + subrepoopts + walkopts,
315 _('[OPTION]... DEST'))
315 _('[OPTION]... DEST'))
316 def archive(ui, repo, dest, **opts):
316 def archive(ui, repo, dest, **opts):
317 '''create an unversioned archive of a repository revision
317 '''create an unversioned archive of a repository revision
318
318
319 By default, the revision used is the parent of the working
319 By default, the revision used is the parent of the working
320 directory; use -r/--rev to specify a different revision.
320 directory; use -r/--rev to specify a different revision.
321
321
322 The archive type is automatically detected based on file
322 The archive type is automatically detected based on file
323 extension (or override using -t/--type).
323 extension (or override using -t/--type).
324
324
325 .. container:: verbose
325 .. container:: verbose
326
326
327 Examples:
327 Examples:
328
328
329 - create a zip file containing the 1.0 release::
329 - create a zip file containing the 1.0 release::
330
330
331 hg archive -r 1.0 project-1.0.zip
331 hg archive -r 1.0 project-1.0.zip
332
332
333 - create a tarball excluding .hg files::
333 - create a tarball excluding .hg files::
334
334
335 hg archive project.tar.gz -X ".hg*"
335 hg archive project.tar.gz -X ".hg*"
336
336
337 Valid types are:
337 Valid types are:
338
338
339 :``files``: a directory full of files (default)
339 :``files``: a directory full of files (default)
340 :``tar``: tar archive, uncompressed
340 :``tar``: tar archive, uncompressed
341 :``tbz2``: tar archive, compressed using bzip2
341 :``tbz2``: tar archive, compressed using bzip2
342 :``tgz``: tar archive, compressed using gzip
342 :``tgz``: tar archive, compressed using gzip
343 :``uzip``: zip archive, uncompressed
343 :``uzip``: zip archive, uncompressed
344 :``zip``: zip archive, compressed using deflate
344 :``zip``: zip archive, compressed using deflate
345
345
346 The exact name of the destination archive or directory is given
346 The exact name of the destination archive or directory is given
347 using a format string; see :hg:`help export` for details.
347 using a format string; see :hg:`help export` for details.
348
348
349 Each member added to an archive file has a directory prefix
349 Each member added to an archive file has a directory prefix
350 prepended. Use -p/--prefix to specify a format string for the
350 prepended. Use -p/--prefix to specify a format string for the
351 prefix. The default is the basename of the archive, with suffixes
351 prefix. The default is the basename of the archive, with suffixes
352 removed.
352 removed.
353
353
354 Returns 0 on success.
354 Returns 0 on success.
355 '''
355 '''
356
356
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 if not ctx:
358 if not ctx:
359 raise util.Abort(_('no working directory: please specify a revision'))
359 raise util.Abort(_('no working directory: please specify a revision'))
360 node = ctx.node()
360 node = ctx.node()
361 dest = cmdutil.makefilename(repo, dest, node)
361 dest = cmdutil.makefilename(repo, dest, node)
362 if os.path.realpath(dest) == repo.root:
362 if os.path.realpath(dest) == repo.root:
363 raise util.Abort(_('repository root cannot be destination'))
363 raise util.Abort(_('repository root cannot be destination'))
364
364
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 prefix = opts.get('prefix')
366 prefix = opts.get('prefix')
367
367
368 if dest == '-':
368 if dest == '-':
369 if kind == 'files':
369 if kind == 'files':
370 raise util.Abort(_('cannot archive plain files to stdout'))
370 raise util.Abort(_('cannot archive plain files to stdout'))
371 dest = cmdutil.makefileobj(repo, dest)
371 dest = cmdutil.makefileobj(repo, dest)
372 if not prefix:
372 if not prefix:
373 prefix = os.path.basename(repo.root) + '-%h'
373 prefix = os.path.basename(repo.root) + '-%h'
374
374
375 prefix = cmdutil.makefilename(repo, prefix, node)
375 prefix = cmdutil.makefilename(repo, prefix, node)
376 matchfn = scmutil.match(ctx, [], opts)
376 matchfn = scmutil.match(ctx, [], opts)
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 matchfn, prefix, subrepos=opts.get('subrepos'))
378 matchfn, prefix, subrepos=opts.get('subrepos'))
379
379
380 @command('backout',
380 @command('backout',
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 ('', 'parent', '',
382 ('', 'parent', '',
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 _('[OPTION]... [-r] REV'))
386 _('[OPTION]... [-r] REV'))
387 def backout(ui, repo, node=None, rev=None, **opts):
387 def backout(ui, repo, node=None, rev=None, **opts):
388 '''reverse effect of earlier changeset
388 '''reverse effect of earlier changeset
389
389
390 Prepare a new changeset with the effect of REV undone in the
390 Prepare a new changeset with the effect of REV undone in the
391 current working directory.
391 current working directory.
392
392
393 If REV is the parent of the working directory, then this new changeset
393 If REV is the parent of the working directory, then this new changeset
394 is committed automatically. Otherwise, hg needs to merge the
394 is committed automatically. Otherwise, hg needs to merge the
395 changes and the merged result is left uncommitted.
395 changes and the merged result is left uncommitted.
396
396
397 .. note::
397 .. note::
398 backout cannot be used to fix either an unwanted or
398 backout cannot be used to fix either an unwanted or
399 incorrect merge.
399 incorrect merge.
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 By default, the pending changeset will have one parent,
403 By default, the pending changeset will have one parent,
404 maintaining a linear history. With --merge, the pending
404 maintaining a linear history. With --merge, the pending
405 changeset will instead have two parents: the old parent of the
405 changeset will instead have two parents: the old parent of the
406 working directory and a new child of REV that simply undoes REV.
406 working directory and a new child of REV that simply undoes REV.
407
407
408 Before version 1.7, the behavior without --merge was equivalent
408 Before version 1.7, the behavior without --merge was equivalent
409 to specifying --merge followed by :hg:`update --clean .` to
409 to specifying --merge followed by :hg:`update --clean .` to
410 cancel the merge and leave the child of REV as a head to be
410 cancel the merge and leave the child of REV as a head to be
411 merged separately.
411 merged separately.
412
412
413 See :hg:`help dates` for a list of formats valid for -d/--date.
413 See :hg:`help dates` for a list of formats valid for -d/--date.
414
414
415 Returns 0 on success.
415 Returns 0 on success.
416 '''
416 '''
417 if rev and node:
417 if rev and node:
418 raise util.Abort(_("please specify just one revision"))
418 raise util.Abort(_("please specify just one revision"))
419
419
420 if not rev:
420 if not rev:
421 rev = node
421 rev = node
422
422
423 if not rev:
423 if not rev:
424 raise util.Abort(_("please specify a revision to backout"))
424 raise util.Abort(_("please specify a revision to backout"))
425
425
426 date = opts.get('date')
426 date = opts.get('date')
427 if date:
427 if date:
428 opts['date'] = util.parsedate(date)
428 opts['date'] = util.parsedate(date)
429
429
430 cmdutil.bailifchanged(repo)
430 cmdutil.bailifchanged(repo)
431 node = scmutil.revsingle(repo, rev).node()
431 node = scmutil.revsingle(repo, rev).node()
432
432
433 op1, op2 = repo.dirstate.parents()
433 op1, op2 = repo.dirstate.parents()
434 a = repo.changelog.ancestor(op1, node)
434 a = repo.changelog.ancestor(op1, node)
435 if a != node:
435 if a != node:
436 raise util.Abort(_('cannot backout change on a different branch'))
436 raise util.Abort(_('cannot backout change on a different branch'))
437
437
438 p1, p2 = repo.changelog.parents(node)
438 p1, p2 = repo.changelog.parents(node)
439 if p1 == nullid:
439 if p1 == nullid:
440 raise util.Abort(_('cannot backout a change with no parents'))
440 raise util.Abort(_('cannot backout a change with no parents'))
441 if p2 != nullid:
441 if p2 != nullid:
442 if not opts.get('parent'):
442 if not opts.get('parent'):
443 raise util.Abort(_('cannot backout a merge changeset'))
443 raise util.Abort(_('cannot backout a merge changeset'))
444 p = repo.lookup(opts['parent'])
444 p = repo.lookup(opts['parent'])
445 if p not in (p1, p2):
445 if p not in (p1, p2):
446 raise util.Abort(_('%s is not a parent of %s') %
446 raise util.Abort(_('%s is not a parent of %s') %
447 (short(p), short(node)))
447 (short(p), short(node)))
448 parent = p
448 parent = p
449 else:
449 else:
450 if opts.get('parent'):
450 if opts.get('parent'):
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 parent = p1
452 parent = p1
453
453
454 # the backout should appear on the same branch
454 # the backout should appear on the same branch
455 wlock = repo.wlock()
455 wlock = repo.wlock()
456 try:
456 try:
457 branch = repo.dirstate.branch()
457 branch = repo.dirstate.branch()
458 hg.clean(repo, node, show_stats=False)
458 hg.clean(repo, node, show_stats=False)
459 repo.dirstate.setbranch(branch)
459 repo.dirstate.setbranch(branch)
460 revert_opts = opts.copy()
460 revert_opts = opts.copy()
461 revert_opts['date'] = None
461 revert_opts['date'] = None
462 revert_opts['all'] = True
462 revert_opts['all'] = True
463 revert_opts['rev'] = hex(parent)
463 revert_opts['rev'] = hex(parent)
464 revert_opts['no_backup'] = None
464 revert_opts['no_backup'] = None
465 revert(ui, repo, **revert_opts)
465 revert(ui, repo, **revert_opts)
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 commit_opts = opts.copy()
473 commit_opts = opts.copy()
474 commit_opts['addremove'] = False
474 commit_opts['addremove'] = False
475 if not commit_opts['message'] and not commit_opts['logfile']:
475 if not commit_opts['message'] and not commit_opts['logfile']:
476 # we don't translate commit messages
476 # we don't translate commit messages
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['force_editor'] = True
478 commit_opts['force_editor'] = True
479 commit(ui, repo, **commit_opts)
479 commit(ui, repo, **commit_opts)
480 def nice(node):
480 def nice(node):
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 ui.status(_('changeset %s backs out changeset %s\n') %
482 ui.status(_('changeset %s backs out changeset %s\n') %
483 (nice(repo.changelog.tip()), nice(node)))
483 (nice(repo.changelog.tip()), nice(node)))
484 if opts.get('merge') and op1 != node:
484 if opts.get('merge') and op1 != node:
485 hg.clean(repo, op1, show_stats=False)
485 hg.clean(repo, op1, show_stats=False)
486 ui.status(_('merging with changeset %s\n')
486 ui.status(_('merging with changeset %s\n')
487 % nice(repo.changelog.tip()))
487 % nice(repo.changelog.tip()))
488 try:
488 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 return hg.merge(repo, hex(repo.changelog.tip()))
490 return hg.merge(repo, hex(repo.changelog.tip()))
491 finally:
491 finally:
492 ui.setconfig('ui', 'forcemerge', '')
492 ui.setconfig('ui', 'forcemerge', '')
493 finally:
493 finally:
494 wlock.release()
494 wlock.release()
495 return 0
495 return 0
496
496
497 @command('bisect',
497 @command('bisect',
498 [('r', 'reset', False, _('reset bisect state')),
498 [('r', 'reset', False, _('reset bisect state')),
499 ('g', 'good', False, _('mark changeset good')),
499 ('g', 'good', False, _('mark changeset good')),
500 ('b', 'bad', False, _('mark changeset bad')),
500 ('b', 'bad', False, _('mark changeset bad')),
501 ('s', 'skip', False, _('skip testing changeset')),
501 ('s', 'skip', False, _('skip testing changeset')),
502 ('e', 'extend', False, _('extend the bisect range')),
502 ('e', 'extend', False, _('extend the bisect range')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('U', 'noupdate', False, _('do not update to target'))],
504 ('U', 'noupdate', False, _('do not update to target'))],
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 def bisect(ui, repo, rev=None, extra=None, command=None,
506 def bisect(ui, repo, rev=None, extra=None, command=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
507 reset=None, good=None, bad=None, skip=None, extend=None,
508 noupdate=None):
508 noupdate=None):
509 """subdivision search of changesets
509 """subdivision search of changesets
510
510
511 This command helps to find changesets which introduce problems. To
511 This command helps to find changesets which introduce problems. To
512 use, mark the earliest changeset you know exhibits the problem as
512 use, mark the earliest changeset you know exhibits the problem as
513 bad, then mark the latest changeset which is free from the problem
513 bad, then mark the latest changeset which is free from the problem
514 as good. Bisect will update your working directory to a revision
514 as good. Bisect will update your working directory to a revision
515 for testing (unless the -U/--noupdate option is specified). Once
515 for testing (unless the -U/--noupdate option is specified). Once
516 you have performed tests, mark the working directory as good or
516 you have performed tests, mark the working directory as good or
517 bad, and bisect will either update to another candidate changeset
517 bad, and bisect will either update to another candidate changeset
518 or announce that it has found the bad revision.
518 or announce that it has found the bad revision.
519
519
520 As a shortcut, you can also use the revision argument to mark a
520 As a shortcut, you can also use the revision argument to mark a
521 revision as good or bad without checking it out first.
521 revision as good or bad without checking it out first.
522
522
523 If you supply a command, it will be used for automatic bisection.
523 If you supply a command, it will be used for automatic bisection.
524 The environment variable HG_NODE will contain the ID of the
524 The environment variable HG_NODE will contain the ID of the
525 changeset being tested. The exit status of the command will be
525 changeset being tested. The exit status of the command will be
526 used to mark revisions as good or bad: status 0 means good, 125
526 used to mark revisions as good or bad: status 0 means good, 125
527 means to skip the revision, 127 (command not found) will abort the
527 means to skip the revision, 127 (command not found) will abort the
528 bisection, and any other non-zero exit status means the revision
528 bisection, and any other non-zero exit status means the revision
529 is bad.
529 is bad.
530
530
531 .. container:: verbose
531 .. container:: verbose
532
532
533 Some examples:
533 Some examples:
534
534
535 - start a bisection with known bad revision 12, and good revision 34::
535 - start a bisection with known bad revision 12, and good revision 34::
536
536
537 hg bisect --bad 34
537 hg bisect --bad 34
538 hg bisect --good 12
538 hg bisect --good 12
539
539
540 - advance the current bisection by marking current revision as good or
540 - advance the current bisection by marking current revision as good or
541 bad::
541 bad::
542
542
543 hg bisect --good
543 hg bisect --good
544 hg bisect --bad
544 hg bisect --bad
545
545
546 - mark the current revision, or a known revision, to be skipped (e.g. if
546 - mark the current revision, or a known revision, to be skipped (e.g. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - forget the current bisection::
552 - forget the current bisection::
553
553
554 hg bisect --reset
554 hg bisect --reset
555
555
556 - use 'make && make tests' to automatically find the first broken
556 - use 'make && make tests' to automatically find the first broken
557 revision::
557 revision::
558
558
559 hg bisect --reset
559 hg bisect --reset
560 hg bisect --bad 34
560 hg bisect --bad 34
561 hg bisect --good 12
561 hg bisect --good 12
562 hg bisect --command 'make && make tests'
562 hg bisect --command 'make && make tests'
563
563
564 - see all changesets whose states are already known in the current
564 - see all changesets whose states are already known in the current
565 bisection::
565 bisection::
566
566
567 hg log -r "bisect(pruned)"
567 hg log -r "bisect(pruned)"
568
568
569 - see the changeset currently being bisected (especially useful
569 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
570 if running with -U/--noupdate)::
571
571
572 hg log -r "bisect(current)"
572 hg log -r "bisect(current)"
573
573
574 - see all changesets that took part in the current bisection::
574 - see all changesets that took part in the current bisection::
575
575
576 hg log -r "bisect(range)"
576 hg log -r "bisect(range)"
577
577
578 - with the graphlog extension, you can even get a nice graph::
578 - with the graphlog extension, you can even get a nice graph::
579
579
580 hg log --graph -r "bisect(range)"
580 hg log --graph -r "bisect(range)"
581
581
582 See :hg:`help revsets` for more about the `bisect()` keyword.
582 See :hg:`help revsets` for more about the `bisect()` keyword.
583
583
584 Returns 0 on success.
584 Returns 0 on success.
585 """
585 """
586 def extendbisectrange(nodes, good):
586 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
587 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
588 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
589 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
590 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
591 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
592 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
593 if num == 1:
594 return parents[0].ancestor(parents[1])
594 return parents[0].ancestor(parents[1])
595 return None
595 return None
596
596
597 def print_result(nodes, good):
597 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
598 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
599 if len(nodes) == 1:
600 # narrowed it down to a single revision
600 # narrowed it down to a single revision
601 if good:
601 if good:
602 ui.write(_("The first good revision is:\n"))
602 ui.write(_("The first good revision is:\n"))
603 else:
603 else:
604 ui.write(_("The first bad revision is:\n"))
604 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
605 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
606 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
607 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
608 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
609 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
610 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
611 % extendnode)
612 else:
612 else:
613 # multiple possible revisions
613 # multiple possible revisions
614 if good:
614 if good:
615 ui.write(_("Due to skipped revisions, the first "
615 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
616 "good revision could be any of:\n"))
617 else:
617 else:
618 ui.write(_("Due to skipped revisions, the first "
618 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
619 "bad revision could be any of:\n"))
620 for n in nodes:
620 for n in nodes:
621 displayer.show(repo[n])
621 displayer.show(repo[n])
622 displayer.close()
622 displayer.close()
623
623
624 def check_state(state, interactive=True):
624 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
625 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
626 if (good or bad or skip or reset) and interactive:
627 return
627 return
628 if not state['good']:
628 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
630 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
632 return True
633
633
634 # backward compatibility
634 # backward compatibility
635 if rev in "good bad reset init".split():
635 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
637 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
638 if cmd == "good":
639 good = True
639 good = True
640 elif cmd == "bad":
640 elif cmd == "bad":
641 bad = True
641 bad = True
642 else:
642 else:
643 reset = True
643 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
645 raise util.Abort(_('incompatible arguments'))
646
646
647 if reset:
647 if reset:
648 p = repo.join("bisect.state")
648 p = repo.join("bisect.state")
649 if os.path.exists(p):
649 if os.path.exists(p):
650 os.unlink(p)
650 os.unlink(p)
651 return
651 return
652
652
653 state = hbisect.load_state(repo)
653 state = hbisect.load_state(repo)
654
654
655 if command:
655 if command:
656 changesets = 1
656 changesets = 1
657 try:
657 try:
658 node = state['current'][0]
658 node = state['current'][0]
659 except LookupError:
659 except LookupError:
660 if noupdate:
660 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
661 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
662 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
663 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
664 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
665 raise util.Abort(_('current bisect revision is a merge'))
666 try:
666 try:
667 while changesets:
667 while changesets:
668 # update state
668 # update state
669 state['current'] = [node]
669 state['current'] = [node]
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 status = util.system(command,
671 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
672 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
673 out=ui.fout)
674 if status == 125:
674 if status == 125:
675 transition = "skip"
675 transition = "skip"
676 elif status == 0:
676 elif status == 0:
677 transition = "good"
677 transition = "good"
678 # status < 0 means process was killed
678 # status < 0 means process was killed
679 elif status == 127:
679 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
680 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
681 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
682 raise util.Abort(_("%s killed") % command)
683 else:
683 else:
684 transition = "bad"
684 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
685 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
686 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
687 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
689 check_state(state, interactive=False)
690 # bisect
690 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
692 # update to next check
693 node = nodes[0]
693 node = nodes[0]
694 if not noupdate:
694 if not noupdate:
695 cmdutil.bailifchanged(repo)
695 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
696 hg.clean(repo, node, show_stats=False)
697 finally:
697 finally:
698 state['current'] = [node]
698 state['current'] = [node]
699 hbisect.save_state(repo, state)
699 hbisect.save_state(repo, state)
700 print_result(nodes, good)
700 print_result(nodes, good)
701 return
701 return
702
702
703 # update state
703 # update state
704
704
705 if rev:
705 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
707 else:
708 nodes = [repo.lookup('.')]
708 nodes = [repo.lookup('.')]
709
709
710 if good or bad or skip:
710 if good or bad or skip:
711 if good:
711 if good:
712 state['good'] += nodes
712 state['good'] += nodes
713 elif bad:
713 elif bad:
714 state['bad'] += nodes
714 state['bad'] += nodes
715 elif skip:
715 elif skip:
716 state['skip'] += nodes
716 state['skip'] += nodes
717 hbisect.save_state(repo, state)
717 hbisect.save_state(repo, state)
718
718
719 if not check_state(state):
719 if not check_state(state):
720 return
720 return
721
721
722 # actually bisect
722 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
724 if extend:
725 if not changesets:
725 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
728 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
729 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
730 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 if noupdate:
732 if noupdate:
733 return
733 return
734 cmdutil.bailifchanged(repo)
734 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
735 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
736 raise util.Abort(_("nothing to extend"))
737
737
738 if changesets == 0:
738 if changesets == 0:
739 print_result(nodes, good)
739 print_result(nodes, good)
740 else:
740 else:
741 assert len(nodes) == 1 # only a single node can be tested next
741 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
742 node = nodes[0]
743 # compute the approximate number of remaining tests
743 # compute the approximate number of remaining tests
744 tests, size = 0, 2
744 tests, size = 0, 2
745 while size <= changesets:
745 while size <= changesets:
746 tests, size = tests + 1, size * 2
746 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
747 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
748 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
749 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
750 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
751 state['current'] = [node]
752 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
753 if not noupdate:
753 if not noupdate:
754 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
755 return hg.clean(repo, node)
756
756
757 @command('bookmarks',
757 @command('bookmarks',
758 [('f', 'force', False, _('force')),
758 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
759 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
760 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
765 rename=None, inactive=False):
766 '''track a line of development with movable markers
766 '''track a line of development with movable markers
767
767
768 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
769 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
771 :hg:`update NAME` to update to a given bookmark.
772
772
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
774 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
775 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
776 the bookmark is assigned to that revision.
777
777
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
779 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
780 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
781 the bookmarks extension must be enabled.
782
782
783 With -i/--inactive, the new bookmark will not be made the active
783 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
784 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
785 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
786 current active bookmark will be marked inactive.
787 '''
787 '''
788 hexfn = ui.debugflag and hex or short
788 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
789 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
790 cur = repo.changectx('.').node()
791
791
792 def checkformat(mark):
792 def checkformat(mark):
793 if "\n" in mark:
793 if "\n" in mark:
794 raise util.Abort(_("bookmark name cannot contain newlines"))
794 raise util.Abort(_("bookmark name cannot contain newlines"))
795 mark = mark.strip()
795 mark = mark.strip()
796 if not mark:
796 if not mark:
797 raise util.Abort(_("bookmark names cannot consist entirely of "
797 raise util.Abort(_("bookmark names cannot consist entirely of "
798 "whitespace"))
798 "whitespace"))
799 return mark
799 return mark
800
800
801 def checkconflict(repo, mark, force=False):
801 def checkconflict(repo, mark, force=False):
802 if mark in marks and not force:
802 if mark in marks and not force:
803 raise util.Abort(_("bookmark '%s' already exists "
803 raise util.Abort(_("bookmark '%s' already exists "
804 "(use -f to force)") % mark)
804 "(use -f to force)") % mark)
805 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
805 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
806 and not force):
806 and not force):
807 raise util.Abort(
807 raise util.Abort(
808 _("a bookmark cannot have the name of an existing branch"))
808 _("a bookmark cannot have the name of an existing branch"))
809
809
810 if delete and rename:
811 raise util.Abort(_("--delete and --rename are incompatible"))
812 if delete and rev:
813 raise util.Abort(_("--rev is incompatible with --delete"))
814 if rename and rev:
815 raise util.Abort(_("--rev is incompatible with --rename"))
816
810 if delete:
817 if delete:
811 if mark is None:
818 if mark is None:
812 raise util.Abort(_("bookmark name required"))
819 raise util.Abort(_("bookmark name required"))
813 if mark not in marks:
820 if mark not in marks:
814 raise util.Abort(_("bookmark '%s' does not exist") % mark)
821 raise util.Abort(_("bookmark '%s' does not exist") % mark)
815 if mark == repo._bookmarkcurrent:
822 if mark == repo._bookmarkcurrent:
816 bookmarks.setcurrent(repo, None)
823 bookmarks.setcurrent(repo, None)
817 del marks[mark]
824 del marks[mark]
818 bookmarks.write(repo)
825 bookmarks.write(repo)
819 return
826 return
820
827
821 if rename:
828 if rename:
822 if mark is None:
829 if mark is None:
823 raise util.Abort(_("new bookmark name required"))
830 raise util.Abort(_("new bookmark name required"))
824 mark = checkformat(mark)
831 mark = checkformat(mark)
825 if rename not in marks:
832 if rename not in marks:
826 raise util.Abort(_("bookmark '%s' does not exist") % rename)
833 raise util.Abort(_("bookmark '%s' does not exist") % rename)
827 checkconflict(repo, mark, force)
834 checkconflict(repo, mark, force)
828 marks[mark] = marks[rename]
835 marks[mark] = marks[rename]
829 if repo._bookmarkcurrent == rename and not inactive:
836 if repo._bookmarkcurrent == rename and not inactive:
830 bookmarks.setcurrent(repo, mark)
837 bookmarks.setcurrent(repo, mark)
831 del marks[rename]
838 del marks[rename]
832 bookmarks.write(repo)
839 bookmarks.write(repo)
833 return
840 return
834
841
835 if mark is not None:
842 if mark is not None:
836 mark = checkformat(mark)
843 mark = checkformat(mark)
837 if inactive and mark == repo._bookmarkcurrent:
844 if inactive and mark == repo._bookmarkcurrent:
838 bookmarks.setcurrent(repo, None)
845 bookmarks.setcurrent(repo, None)
839 return
846 return
840 checkconflict(repo, mark, force)
847 checkconflict(repo, mark, force)
841 if rev:
848 if rev:
842 marks[mark] = scmutil.revsingle(repo, rev).node()
849 marks[mark] = scmutil.revsingle(repo, rev).node()
843 else:
850 else:
844 marks[mark] = cur
851 marks[mark] = cur
845 if not inactive and cur == marks[mark]:
852 if not inactive and cur == marks[mark]:
846 bookmarks.setcurrent(repo, mark)
853 bookmarks.setcurrent(repo, mark)
847 bookmarks.write(repo)
854 bookmarks.write(repo)
848 return
855 return
849
856
850 if mark is None:
857 if mark is None:
851 if rev:
858 if rev:
852 raise util.Abort(_("bookmark name required"))
859 raise util.Abort(_("bookmark name required"))
853 if len(marks) == 0:
860 if len(marks) == 0:
854 ui.status(_("no bookmarks set\n"))
861 ui.status(_("no bookmarks set\n"))
855 if inactive:
862 if inactive:
856 if not repo._bookmarkcurrent:
863 if not repo._bookmarkcurrent:
857 ui.status(_("no active bookmark\n"))
864 ui.status(_("no active bookmark\n"))
858 else:
865 else:
859 bookmarks.setcurrent(repo, None)
866 bookmarks.setcurrent(repo, None)
860 return
867 return
861 else:
868 else:
862 for bmark, n in sorted(marks.iteritems()):
869 for bmark, n in sorted(marks.iteritems()):
863 current = repo._bookmarkcurrent
870 current = repo._bookmarkcurrent
864 if bmark == current and n == cur:
871 if bmark == current and n == cur:
865 prefix, label = '*', 'bookmarks.current'
872 prefix, label = '*', 'bookmarks.current'
866 else:
873 else:
867 prefix, label = ' ', ''
874 prefix, label = ' ', ''
868
875
869 if ui.quiet:
876 if ui.quiet:
870 ui.write("%s\n" % bmark, label=label)
877 ui.write("%s\n" % bmark, label=label)
871 else:
878 else:
872 ui.write(" %s %-25s %d:%s\n" % (
879 ui.write(" %s %-25s %d:%s\n" % (
873 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
880 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
874 label=label)
881 label=label)
875 return
882 return
876
883
877 @command('branch',
884 @command('branch',
878 [('f', 'force', None,
885 [('f', 'force', None,
879 _('set branch name even if it shadows an existing branch')),
886 _('set branch name even if it shadows an existing branch')),
880 ('C', 'clean', None, _('reset branch name to parent branch name'))],
887 ('C', 'clean', None, _('reset branch name to parent branch name'))],
881 _('[-fC] [NAME]'))
888 _('[-fC] [NAME]'))
882 def branch(ui, repo, label=None, **opts):
889 def branch(ui, repo, label=None, **opts):
883 """set or show the current branch name
890 """set or show the current branch name
884
891
885 .. note::
892 .. note::
886 Branch names are permanent and global. Use :hg:`bookmark` to create a
893 Branch names are permanent and global. Use :hg:`bookmark` to create a
887 light-weight bookmark instead. See :hg:`help glossary` for more
894 light-weight bookmark instead. See :hg:`help glossary` for more
888 information about named branches and bookmarks.
895 information about named branches and bookmarks.
889
896
890 With no argument, show the current branch name. With one argument,
897 With no argument, show the current branch name. With one argument,
891 set the working directory branch name (the branch will not exist
898 set the working directory branch name (the branch will not exist
892 in the repository until the next commit). Standard practice
899 in the repository until the next commit). Standard practice
893 recommends that primary development take place on the 'default'
900 recommends that primary development take place on the 'default'
894 branch.
901 branch.
895
902
896 Unless -f/--force is specified, branch will not let you set a
903 Unless -f/--force is specified, branch will not let you set a
897 branch name that already exists, even if it's inactive.
904 branch name that already exists, even if it's inactive.
898
905
899 Use -C/--clean to reset the working directory branch to that of
906 Use -C/--clean to reset the working directory branch to that of
900 the parent of the working directory, negating a previous branch
907 the parent of the working directory, negating a previous branch
901 change.
908 change.
902
909
903 Use the command :hg:`update` to switch to an existing branch. Use
910 Use the command :hg:`update` to switch to an existing branch. Use
904 :hg:`commit --close-branch` to mark this branch as closed.
911 :hg:`commit --close-branch` to mark this branch as closed.
905
912
906 Returns 0 on success.
913 Returns 0 on success.
907 """
914 """
908 if not opts.get('clean') and not label:
915 if not opts.get('clean') and not label:
909 ui.write("%s\n" % repo.dirstate.branch())
916 ui.write("%s\n" % repo.dirstate.branch())
910 return
917 return
911
918
912 wlock = repo.wlock()
919 wlock = repo.wlock()
913 try:
920 try:
914 if opts.get('clean'):
921 if opts.get('clean'):
915 label = repo[None].p1().branch()
922 label = repo[None].p1().branch()
916 repo.dirstate.setbranch(label)
923 repo.dirstate.setbranch(label)
917 ui.status(_('reset working directory to branch %s\n') % label)
924 ui.status(_('reset working directory to branch %s\n') % label)
918 elif label:
925 elif label:
919 if not opts.get('force') and label in repo.branchmap():
926 if not opts.get('force') and label in repo.branchmap():
920 if label not in [p.branch() for p in repo.parents()]:
927 if label not in [p.branch() for p in repo.parents()]:
921 raise util.Abort(_('a branch of the same name already'
928 raise util.Abort(_('a branch of the same name already'
922 ' exists'),
929 ' exists'),
923 # i18n: "it" refers to an existing branch
930 # i18n: "it" refers to an existing branch
924 hint=_("use 'hg update' to switch to it"))
931 hint=_("use 'hg update' to switch to it"))
925 repo.dirstate.setbranch(label)
932 repo.dirstate.setbranch(label)
926 ui.status(_('marked working directory as branch %s\n') % label)
933 ui.status(_('marked working directory as branch %s\n') % label)
927 ui.status(_('(branches are permanent and global, '
934 ui.status(_('(branches are permanent and global, '
928 'did you want a bookmark?)\n'))
935 'did you want a bookmark?)\n'))
929 finally:
936 finally:
930 wlock.release()
937 wlock.release()
931
938
932 @command('branches',
939 @command('branches',
933 [('a', 'active', False, _('show only branches that have unmerged heads')),
940 [('a', 'active', False, _('show only branches that have unmerged heads')),
934 ('c', 'closed', False, _('show normal and closed branches'))],
941 ('c', 'closed', False, _('show normal and closed branches'))],
935 _('[-ac]'))
942 _('[-ac]'))
936 def branches(ui, repo, active=False, closed=False):
943 def branches(ui, repo, active=False, closed=False):
937 """list repository named branches
944 """list repository named branches
938
945
939 List the repository's named branches, indicating which ones are
946 List the repository's named branches, indicating which ones are
940 inactive. If -c/--closed is specified, also list branches which have
947 inactive. If -c/--closed is specified, also list branches which have
941 been marked closed (see :hg:`commit --close-branch`).
948 been marked closed (see :hg:`commit --close-branch`).
942
949
943 If -a/--active is specified, only show active branches. A branch
950 If -a/--active is specified, only show active branches. A branch
944 is considered active if it contains repository heads.
951 is considered active if it contains repository heads.
945
952
946 Use the command :hg:`update` to switch to an existing branch.
953 Use the command :hg:`update` to switch to an existing branch.
947
954
948 Returns 0.
955 Returns 0.
949 """
956 """
950
957
951 hexfunc = ui.debugflag and hex or short
958 hexfunc = ui.debugflag and hex or short
952
959
953 activebranches = set([repo[n].branch() for n in repo.heads()])
960 activebranches = set([repo[n].branch() for n in repo.heads()])
954 branches = []
961 branches = []
955 for tag, heads in repo.branchmap().iteritems():
962 for tag, heads in repo.branchmap().iteritems():
956 for h in reversed(heads):
963 for h in reversed(heads):
957 ctx = repo[h]
964 ctx = repo[h]
958 isopen = not ctx.closesbranch()
965 isopen = not ctx.closesbranch()
959 if isopen:
966 if isopen:
960 tip = ctx
967 tip = ctx
961 break
968 break
962 else:
969 else:
963 tip = repo[heads[-1]]
970 tip = repo[heads[-1]]
964 isactive = tag in activebranches and isopen
971 isactive = tag in activebranches and isopen
965 branches.append((tip, isactive, isopen))
972 branches.append((tip, isactive, isopen))
966 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
973 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
967 reverse=True)
974 reverse=True)
968
975
969 for ctx, isactive, isopen in branches:
976 for ctx, isactive, isopen in branches:
970 if (not active) or isactive:
977 if (not active) or isactive:
971 if isactive:
978 if isactive:
972 label = 'branches.active'
979 label = 'branches.active'
973 notice = ''
980 notice = ''
974 elif not isopen:
981 elif not isopen:
975 if not closed:
982 if not closed:
976 continue
983 continue
977 label = 'branches.closed'
984 label = 'branches.closed'
978 notice = _(' (closed)')
985 notice = _(' (closed)')
979 else:
986 else:
980 label = 'branches.inactive'
987 label = 'branches.inactive'
981 notice = _(' (inactive)')
988 notice = _(' (inactive)')
982 if ctx.branch() == repo.dirstate.branch():
989 if ctx.branch() == repo.dirstate.branch():
983 label = 'branches.current'
990 label = 'branches.current'
984 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
991 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
985 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
992 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
986 'log.changeset changeset.%s' % ctx.phasestr())
993 'log.changeset changeset.%s' % ctx.phasestr())
987 tag = ui.label(ctx.branch(), label)
994 tag = ui.label(ctx.branch(), label)
988 if ui.quiet:
995 if ui.quiet:
989 ui.write("%s\n" % tag)
996 ui.write("%s\n" % tag)
990 else:
997 else:
991 ui.write("%s %s%s\n" % (tag, rev, notice))
998 ui.write("%s %s%s\n" % (tag, rev, notice))
992
999
993 @command('bundle',
1000 @command('bundle',
994 [('f', 'force', None, _('run even when the destination is unrelated')),
1001 [('f', 'force', None, _('run even when the destination is unrelated')),
995 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1002 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
996 _('REV')),
1003 _('REV')),
997 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1004 ('b', 'branch', [], _('a specific branch you would like to bundle'),
998 _('BRANCH')),
1005 _('BRANCH')),
999 ('', 'base', [],
1006 ('', 'base', [],
1000 _('a base changeset assumed to be available at the destination'),
1007 _('a base changeset assumed to be available at the destination'),
1001 _('REV')),
1008 _('REV')),
1002 ('a', 'all', None, _('bundle all changesets in the repository')),
1009 ('a', 'all', None, _('bundle all changesets in the repository')),
1003 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1010 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1004 ] + remoteopts,
1011 ] + remoteopts,
1005 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1012 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1006 def bundle(ui, repo, fname, dest=None, **opts):
1013 def bundle(ui, repo, fname, dest=None, **opts):
1007 """create a changegroup file
1014 """create a changegroup file
1008
1015
1009 Generate a compressed changegroup file collecting changesets not
1016 Generate a compressed changegroup file collecting changesets not
1010 known to be in another repository.
1017 known to be in another repository.
1011
1018
1012 If you omit the destination repository, then hg assumes the
1019 If you omit the destination repository, then hg assumes the
1013 destination will have all the nodes you specify with --base
1020 destination will have all the nodes you specify with --base
1014 parameters. To create a bundle containing all changesets, use
1021 parameters. To create a bundle containing all changesets, use
1015 -a/--all (or --base null).
1022 -a/--all (or --base null).
1016
1023
1017 You can change compression method with the -t/--type option.
1024 You can change compression method with the -t/--type option.
1018 The available compression methods are: none, bzip2, and
1025 The available compression methods are: none, bzip2, and
1019 gzip (by default, bundles are compressed using bzip2).
1026 gzip (by default, bundles are compressed using bzip2).
1020
1027
1021 The bundle file can then be transferred using conventional means
1028 The bundle file can then be transferred using conventional means
1022 and applied to another repository with the unbundle or pull
1029 and applied to another repository with the unbundle or pull
1023 command. This is useful when direct push and pull are not
1030 command. This is useful when direct push and pull are not
1024 available or when exporting an entire repository is undesirable.
1031 available or when exporting an entire repository is undesirable.
1025
1032
1026 Applying bundles preserves all changeset contents including
1033 Applying bundles preserves all changeset contents including
1027 permissions, copy/rename information, and revision history.
1034 permissions, copy/rename information, and revision history.
1028
1035
1029 Returns 0 on success, 1 if no changes found.
1036 Returns 0 on success, 1 if no changes found.
1030 """
1037 """
1031 revs = None
1038 revs = None
1032 if 'rev' in opts:
1039 if 'rev' in opts:
1033 revs = scmutil.revrange(repo, opts['rev'])
1040 revs = scmutil.revrange(repo, opts['rev'])
1034
1041
1035 bundletype = opts.get('type', 'bzip2').lower()
1042 bundletype = opts.get('type', 'bzip2').lower()
1036 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1043 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1037 bundletype = btypes.get(bundletype)
1044 bundletype = btypes.get(bundletype)
1038 if bundletype not in changegroup.bundletypes:
1045 if bundletype not in changegroup.bundletypes:
1039 raise util.Abort(_('unknown bundle type specified with --type'))
1046 raise util.Abort(_('unknown bundle type specified with --type'))
1040
1047
1041 if opts.get('all'):
1048 if opts.get('all'):
1042 base = ['null']
1049 base = ['null']
1043 else:
1050 else:
1044 base = scmutil.revrange(repo, opts.get('base'))
1051 base = scmutil.revrange(repo, opts.get('base'))
1045 if base:
1052 if base:
1046 if dest:
1053 if dest:
1047 raise util.Abort(_("--base is incompatible with specifying "
1054 raise util.Abort(_("--base is incompatible with specifying "
1048 "a destination"))
1055 "a destination"))
1049 common = [repo.lookup(rev) for rev in base]
1056 common = [repo.lookup(rev) for rev in base]
1050 heads = revs and map(repo.lookup, revs) or revs
1057 heads = revs and map(repo.lookup, revs) or revs
1051 cg = repo.getbundle('bundle', heads=heads, common=common)
1058 cg = repo.getbundle('bundle', heads=heads, common=common)
1052 outgoing = None
1059 outgoing = None
1053 else:
1060 else:
1054 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1061 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1055 dest, branches = hg.parseurl(dest, opts.get('branch'))
1062 dest, branches = hg.parseurl(dest, opts.get('branch'))
1056 other = hg.peer(repo, opts, dest)
1063 other = hg.peer(repo, opts, dest)
1057 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1064 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1058 heads = revs and map(repo.lookup, revs) or revs
1065 heads = revs and map(repo.lookup, revs) or revs
1059 outgoing = discovery.findcommonoutgoing(repo, other,
1066 outgoing = discovery.findcommonoutgoing(repo, other,
1060 onlyheads=heads,
1067 onlyheads=heads,
1061 force=opts.get('force'),
1068 force=opts.get('force'),
1062 portable=True)
1069 portable=True)
1063 cg = repo.getlocalbundle('bundle', outgoing)
1070 cg = repo.getlocalbundle('bundle', outgoing)
1064 if not cg:
1071 if not cg:
1065 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1072 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1066 return 1
1073 return 1
1067
1074
1068 changegroup.writebundle(cg, fname, bundletype)
1075 changegroup.writebundle(cg, fname, bundletype)
1069
1076
1070 @command('cat',
1077 @command('cat',
1071 [('o', 'output', '',
1078 [('o', 'output', '',
1072 _('print output to file with formatted name'), _('FORMAT')),
1079 _('print output to file with formatted name'), _('FORMAT')),
1073 ('r', 'rev', '', _('print the given revision'), _('REV')),
1080 ('r', 'rev', '', _('print the given revision'), _('REV')),
1074 ('', 'decode', None, _('apply any matching decode filter')),
1081 ('', 'decode', None, _('apply any matching decode filter')),
1075 ] + walkopts,
1082 ] + walkopts,
1076 _('[OPTION]... FILE...'))
1083 _('[OPTION]... FILE...'))
1077 def cat(ui, repo, file1, *pats, **opts):
1084 def cat(ui, repo, file1, *pats, **opts):
1078 """output the current or given revision of files
1085 """output the current or given revision of files
1079
1086
1080 Print the specified files as they were at the given revision. If
1087 Print the specified files as they were at the given revision. If
1081 no revision is given, the parent of the working directory is used,
1088 no revision is given, the parent of the working directory is used,
1082 or tip if no revision is checked out.
1089 or tip if no revision is checked out.
1083
1090
1084 Output may be to a file, in which case the name of the file is
1091 Output may be to a file, in which case the name of the file is
1085 given using a format string. The formatting rules are the same as
1092 given using a format string. The formatting rules are the same as
1086 for the export command, with the following additions:
1093 for the export command, with the following additions:
1087
1094
1088 :``%s``: basename of file being printed
1095 :``%s``: basename of file being printed
1089 :``%d``: dirname of file being printed, or '.' if in repository root
1096 :``%d``: dirname of file being printed, or '.' if in repository root
1090 :``%p``: root-relative path name of file being printed
1097 :``%p``: root-relative path name of file being printed
1091
1098
1092 Returns 0 on success.
1099 Returns 0 on success.
1093 """
1100 """
1094 ctx = scmutil.revsingle(repo, opts.get('rev'))
1101 ctx = scmutil.revsingle(repo, opts.get('rev'))
1095 err = 1
1102 err = 1
1096 m = scmutil.match(ctx, (file1,) + pats, opts)
1103 m = scmutil.match(ctx, (file1,) + pats, opts)
1097 for abs in ctx.walk(m):
1104 for abs in ctx.walk(m):
1098 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1105 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1099 pathname=abs)
1106 pathname=abs)
1100 data = ctx[abs].data()
1107 data = ctx[abs].data()
1101 if opts.get('decode'):
1108 if opts.get('decode'):
1102 data = repo.wwritedata(abs, data)
1109 data = repo.wwritedata(abs, data)
1103 fp.write(data)
1110 fp.write(data)
1104 fp.close()
1111 fp.close()
1105 err = 0
1112 err = 0
1106 return err
1113 return err
1107
1114
1108 @command('^clone',
1115 @command('^clone',
1109 [('U', 'noupdate', None,
1116 [('U', 'noupdate', None,
1110 _('the clone will include an empty working copy (only a repository)')),
1117 _('the clone will include an empty working copy (only a repository)')),
1111 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1118 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1112 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1119 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1113 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1120 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1114 ('', 'pull', None, _('use pull protocol to copy metadata')),
1121 ('', 'pull', None, _('use pull protocol to copy metadata')),
1115 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1122 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1116 ] + remoteopts,
1123 ] + remoteopts,
1117 _('[OPTION]... SOURCE [DEST]'))
1124 _('[OPTION]... SOURCE [DEST]'))
1118 def clone(ui, source, dest=None, **opts):
1125 def clone(ui, source, dest=None, **opts):
1119 """make a copy of an existing repository
1126 """make a copy of an existing repository
1120
1127
1121 Create a copy of an existing repository in a new directory.
1128 Create a copy of an existing repository in a new directory.
1122
1129
1123 If no destination directory name is specified, it defaults to the
1130 If no destination directory name is specified, it defaults to the
1124 basename of the source.
1131 basename of the source.
1125
1132
1126 The location of the source is added to the new repository's
1133 The location of the source is added to the new repository's
1127 ``.hg/hgrc`` file, as the default to be used for future pulls.
1134 ``.hg/hgrc`` file, as the default to be used for future pulls.
1128
1135
1129 Only local paths and ``ssh://`` URLs are supported as
1136 Only local paths and ``ssh://`` URLs are supported as
1130 destinations. For ``ssh://`` destinations, no working directory or
1137 destinations. For ``ssh://`` destinations, no working directory or
1131 ``.hg/hgrc`` will be created on the remote side.
1138 ``.hg/hgrc`` will be created on the remote side.
1132
1139
1133 To pull only a subset of changesets, specify one or more revisions
1140 To pull only a subset of changesets, specify one or more revisions
1134 identifiers with -r/--rev or branches with -b/--branch. The
1141 identifiers with -r/--rev or branches with -b/--branch. The
1135 resulting clone will contain only the specified changesets and
1142 resulting clone will contain only the specified changesets and
1136 their ancestors. These options (or 'clone src#rev dest') imply
1143 their ancestors. These options (or 'clone src#rev dest') imply
1137 --pull, even for local source repositories. Note that specifying a
1144 --pull, even for local source repositories. Note that specifying a
1138 tag will include the tagged changeset but not the changeset
1145 tag will include the tagged changeset but not the changeset
1139 containing the tag.
1146 containing the tag.
1140
1147
1141 To check out a particular version, use -u/--update, or
1148 To check out a particular version, use -u/--update, or
1142 -U/--noupdate to create a clone with no working directory.
1149 -U/--noupdate to create a clone with no working directory.
1143
1150
1144 .. container:: verbose
1151 .. container:: verbose
1145
1152
1146 For efficiency, hardlinks are used for cloning whenever the
1153 For efficiency, hardlinks are used for cloning whenever the
1147 source and destination are on the same filesystem (note this
1154 source and destination are on the same filesystem (note this
1148 applies only to the repository data, not to the working
1155 applies only to the repository data, not to the working
1149 directory). Some filesystems, such as AFS, implement hardlinking
1156 directory). Some filesystems, such as AFS, implement hardlinking
1150 incorrectly, but do not report errors. In these cases, use the
1157 incorrectly, but do not report errors. In these cases, use the
1151 --pull option to avoid hardlinking.
1158 --pull option to avoid hardlinking.
1152
1159
1153 In some cases, you can clone repositories and the working
1160 In some cases, you can clone repositories and the working
1154 directory using full hardlinks with ::
1161 directory using full hardlinks with ::
1155
1162
1156 $ cp -al REPO REPOCLONE
1163 $ cp -al REPO REPOCLONE
1157
1164
1158 This is the fastest way to clone, but it is not always safe. The
1165 This is the fastest way to clone, but it is not always safe. The
1159 operation is not atomic (making sure REPO is not modified during
1166 operation is not atomic (making sure REPO is not modified during
1160 the operation is up to you) and you have to make sure your
1167 the operation is up to you) and you have to make sure your
1161 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1168 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1162 so). Also, this is not compatible with certain extensions that
1169 so). Also, this is not compatible with certain extensions that
1163 place their metadata under the .hg directory, such as mq.
1170 place their metadata under the .hg directory, such as mq.
1164
1171
1165 Mercurial will update the working directory to the first applicable
1172 Mercurial will update the working directory to the first applicable
1166 revision from this list:
1173 revision from this list:
1167
1174
1168 a) null if -U or the source repository has no changesets
1175 a) null if -U or the source repository has no changesets
1169 b) if -u . and the source repository is local, the first parent of
1176 b) if -u . and the source repository is local, the first parent of
1170 the source repository's working directory
1177 the source repository's working directory
1171 c) the changeset specified with -u (if a branch name, this means the
1178 c) the changeset specified with -u (if a branch name, this means the
1172 latest head of that branch)
1179 latest head of that branch)
1173 d) the changeset specified with -r
1180 d) the changeset specified with -r
1174 e) the tipmost head specified with -b
1181 e) the tipmost head specified with -b
1175 f) the tipmost head specified with the url#branch source syntax
1182 f) the tipmost head specified with the url#branch source syntax
1176 g) the tipmost head of the default branch
1183 g) the tipmost head of the default branch
1177 h) tip
1184 h) tip
1178
1185
1179 Examples:
1186 Examples:
1180
1187
1181 - clone a remote repository to a new directory named hg/::
1188 - clone a remote repository to a new directory named hg/::
1182
1189
1183 hg clone http://selenic.com/hg
1190 hg clone http://selenic.com/hg
1184
1191
1185 - create a lightweight local clone::
1192 - create a lightweight local clone::
1186
1193
1187 hg clone project/ project-feature/
1194 hg clone project/ project-feature/
1188
1195
1189 - clone from an absolute path on an ssh server (note double-slash)::
1196 - clone from an absolute path on an ssh server (note double-slash)::
1190
1197
1191 hg clone ssh://user@server//home/projects/alpha/
1198 hg clone ssh://user@server//home/projects/alpha/
1192
1199
1193 - do a high-speed clone over a LAN while checking out a
1200 - do a high-speed clone over a LAN while checking out a
1194 specified version::
1201 specified version::
1195
1202
1196 hg clone --uncompressed http://server/repo -u 1.5
1203 hg clone --uncompressed http://server/repo -u 1.5
1197
1204
1198 - create a repository without changesets after a particular revision::
1205 - create a repository without changesets after a particular revision::
1199
1206
1200 hg clone -r 04e544 experimental/ good/
1207 hg clone -r 04e544 experimental/ good/
1201
1208
1202 - clone (and track) a particular named branch::
1209 - clone (and track) a particular named branch::
1203
1210
1204 hg clone http://selenic.com/hg#stable
1211 hg clone http://selenic.com/hg#stable
1205
1212
1206 See :hg:`help urls` for details on specifying URLs.
1213 See :hg:`help urls` for details on specifying URLs.
1207
1214
1208 Returns 0 on success.
1215 Returns 0 on success.
1209 """
1216 """
1210 if opts.get('noupdate') and opts.get('updaterev'):
1217 if opts.get('noupdate') and opts.get('updaterev'):
1211 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1218 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1212
1219
1213 r = hg.clone(ui, opts, source, dest,
1220 r = hg.clone(ui, opts, source, dest,
1214 pull=opts.get('pull'),
1221 pull=opts.get('pull'),
1215 stream=opts.get('uncompressed'),
1222 stream=opts.get('uncompressed'),
1216 rev=opts.get('rev'),
1223 rev=opts.get('rev'),
1217 update=opts.get('updaterev') or not opts.get('noupdate'),
1224 update=opts.get('updaterev') or not opts.get('noupdate'),
1218 branch=opts.get('branch'))
1225 branch=opts.get('branch'))
1219
1226
1220 return r is None
1227 return r is None
1221
1228
1222 @command('^commit|ci',
1229 @command('^commit|ci',
1223 [('A', 'addremove', None,
1230 [('A', 'addremove', None,
1224 _('mark new/missing files as added/removed before committing')),
1231 _('mark new/missing files as added/removed before committing')),
1225 ('', 'close-branch', None,
1232 ('', 'close-branch', None,
1226 _('mark a branch as closed, hiding it from the branch list')),
1233 _('mark a branch as closed, hiding it from the branch list')),
1227 ('', 'amend', None, _('amend the parent of the working dir')),
1234 ('', 'amend', None, _('amend the parent of the working dir')),
1228 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1235 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1229 _('[OPTION]... [FILE]...'))
1236 _('[OPTION]... [FILE]...'))
1230 def commit(ui, repo, *pats, **opts):
1237 def commit(ui, repo, *pats, **opts):
1231 """commit the specified files or all outstanding changes
1238 """commit the specified files or all outstanding changes
1232
1239
1233 Commit changes to the given files into the repository. Unlike a
1240 Commit changes to the given files into the repository. Unlike a
1234 centralized SCM, this operation is a local operation. See
1241 centralized SCM, this operation is a local operation. See
1235 :hg:`push` for a way to actively distribute your changes.
1242 :hg:`push` for a way to actively distribute your changes.
1236
1243
1237 If a list of files is omitted, all changes reported by :hg:`status`
1244 If a list of files is omitted, all changes reported by :hg:`status`
1238 will be committed.
1245 will be committed.
1239
1246
1240 If you are committing the result of a merge, do not provide any
1247 If you are committing the result of a merge, do not provide any
1241 filenames or -I/-X filters.
1248 filenames or -I/-X filters.
1242
1249
1243 If no commit message is specified, Mercurial starts your
1250 If no commit message is specified, Mercurial starts your
1244 configured editor where you can enter a message. In case your
1251 configured editor where you can enter a message. In case your
1245 commit fails, you will find a backup of your message in
1252 commit fails, you will find a backup of your message in
1246 ``.hg/last-message.txt``.
1253 ``.hg/last-message.txt``.
1247
1254
1248 The --amend flag can be used to amend the parent of the
1255 The --amend flag can be used to amend the parent of the
1249 working directory with a new commit that contains the changes
1256 working directory with a new commit that contains the changes
1250 in the parent in addition to those currently reported by :hg:`status`,
1257 in the parent in addition to those currently reported by :hg:`status`,
1251 if there are any. The old commit is stored in a backup bundle in
1258 if there are any. The old commit is stored in a backup bundle in
1252 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1259 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1253 on how to restore it).
1260 on how to restore it).
1254
1261
1255 Message, user and date are taken from the amended commit unless
1262 Message, user and date are taken from the amended commit unless
1256 specified. When a message isn't specified on the command line,
1263 specified. When a message isn't specified on the command line,
1257 the editor will open with the message of the amended commit.
1264 the editor will open with the message of the amended commit.
1258
1265
1259 It is not possible to amend public changesets (see :hg:`help phases`)
1266 It is not possible to amend public changesets (see :hg:`help phases`)
1260 or changesets that have children.
1267 or changesets that have children.
1261
1268
1262 See :hg:`help dates` for a list of formats valid for -d/--date.
1269 See :hg:`help dates` for a list of formats valid for -d/--date.
1263
1270
1264 Returns 0 on success, 1 if nothing changed.
1271 Returns 0 on success, 1 if nothing changed.
1265 """
1272 """
1266 if opts.get('subrepos'):
1273 if opts.get('subrepos'):
1267 # Let --subrepos on the command line override config setting.
1274 # Let --subrepos on the command line override config setting.
1268 ui.setconfig('ui', 'commitsubrepos', True)
1275 ui.setconfig('ui', 'commitsubrepos', True)
1269
1276
1270 extra = {}
1277 extra = {}
1271 if opts.get('close_branch'):
1278 if opts.get('close_branch'):
1272 if repo['.'].node() not in repo.branchheads():
1279 if repo['.'].node() not in repo.branchheads():
1273 # The topo heads set is included in the branch heads set of the
1280 # The topo heads set is included in the branch heads set of the
1274 # current branch, so it's sufficient to test branchheads
1281 # current branch, so it's sufficient to test branchheads
1275 raise util.Abort(_('can only close branch heads'))
1282 raise util.Abort(_('can only close branch heads'))
1276 extra['close'] = 1
1283 extra['close'] = 1
1277
1284
1278 branch = repo[None].branch()
1285 branch = repo[None].branch()
1279 bheads = repo.branchheads(branch)
1286 bheads = repo.branchheads(branch)
1280
1287
1281 if opts.get('amend'):
1288 if opts.get('amend'):
1282 if ui.configbool('ui', 'commitsubrepos'):
1289 if ui.configbool('ui', 'commitsubrepos'):
1283 raise util.Abort(_('cannot amend recursively'))
1290 raise util.Abort(_('cannot amend recursively'))
1284
1291
1285 old = repo['.']
1292 old = repo['.']
1286 if old.phase() == phases.public:
1293 if old.phase() == phases.public:
1287 raise util.Abort(_('cannot amend public changesets'))
1294 raise util.Abort(_('cannot amend public changesets'))
1288 if len(old.parents()) > 1:
1295 if len(old.parents()) > 1:
1289 raise util.Abort(_('cannot amend merge changesets'))
1296 raise util.Abort(_('cannot amend merge changesets'))
1290 if len(repo[None].parents()) > 1:
1297 if len(repo[None].parents()) > 1:
1291 raise util.Abort(_('cannot amend while merging'))
1298 raise util.Abort(_('cannot amend while merging'))
1292 if old.children():
1299 if old.children():
1293 raise util.Abort(_('cannot amend changeset with children'))
1300 raise util.Abort(_('cannot amend changeset with children'))
1294
1301
1295 e = cmdutil.commiteditor
1302 e = cmdutil.commiteditor
1296 if opts.get('force_editor'):
1303 if opts.get('force_editor'):
1297 e = cmdutil.commitforceeditor
1304 e = cmdutil.commitforceeditor
1298
1305
1299 def commitfunc(ui, repo, message, match, opts):
1306 def commitfunc(ui, repo, message, match, opts):
1300 editor = e
1307 editor = e
1301 # message contains text from -m or -l, if it's empty,
1308 # message contains text from -m or -l, if it's empty,
1302 # open the editor with the old message
1309 # open the editor with the old message
1303 if not message:
1310 if not message:
1304 message = old.description()
1311 message = old.description()
1305 editor = cmdutil.commitforceeditor
1312 editor = cmdutil.commitforceeditor
1306 return repo.commit(message,
1313 return repo.commit(message,
1307 opts.get('user') or old.user(),
1314 opts.get('user') or old.user(),
1308 opts.get('date') or old.date(),
1315 opts.get('date') or old.date(),
1309 match,
1316 match,
1310 editor=editor,
1317 editor=editor,
1311 extra=extra)
1318 extra=extra)
1312
1319
1313 current = repo._bookmarkcurrent
1320 current = repo._bookmarkcurrent
1314 marks = old.bookmarks()
1321 marks = old.bookmarks()
1315 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1322 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1316 if node == old.node():
1323 if node == old.node():
1317 ui.status(_("nothing changed\n"))
1324 ui.status(_("nothing changed\n"))
1318 return 1
1325 return 1
1319 elif marks:
1326 elif marks:
1320 ui.debug('moving bookmarks %r from %s to %s\n' %
1327 ui.debug('moving bookmarks %r from %s to %s\n' %
1321 (marks, old.hex(), hex(node)))
1328 (marks, old.hex(), hex(node)))
1322 for bm in marks:
1329 for bm in marks:
1323 repo._bookmarks[bm] = node
1330 repo._bookmarks[bm] = node
1324 if bm == current:
1331 if bm == current:
1325 bookmarks.setcurrent(repo, bm)
1332 bookmarks.setcurrent(repo, bm)
1326 bookmarks.write(repo)
1333 bookmarks.write(repo)
1327 else:
1334 else:
1328 e = cmdutil.commiteditor
1335 e = cmdutil.commiteditor
1329 if opts.get('force_editor'):
1336 if opts.get('force_editor'):
1330 e = cmdutil.commitforceeditor
1337 e = cmdutil.commitforceeditor
1331
1338
1332 def commitfunc(ui, repo, message, match, opts):
1339 def commitfunc(ui, repo, message, match, opts):
1333 return repo.commit(message, opts.get('user'), opts.get('date'),
1340 return repo.commit(message, opts.get('user'), opts.get('date'),
1334 match, editor=e, extra=extra)
1341 match, editor=e, extra=extra)
1335
1342
1336 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1343 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1337
1344
1338 if not node:
1345 if not node:
1339 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1346 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1340 if stat[3]:
1347 if stat[3]:
1341 ui.status(_("nothing changed (%d missing files, see "
1348 ui.status(_("nothing changed (%d missing files, see "
1342 "'hg status')\n") % len(stat[3]))
1349 "'hg status')\n") % len(stat[3]))
1343 else:
1350 else:
1344 ui.status(_("nothing changed\n"))
1351 ui.status(_("nothing changed\n"))
1345 return 1
1352 return 1
1346
1353
1347 ctx = repo[node]
1354 ctx = repo[node]
1348 parents = ctx.parents()
1355 parents = ctx.parents()
1349
1356
1350 if (not opts.get('amend') and bheads and node not in bheads and not
1357 if (not opts.get('amend') and bheads and node not in bheads and not
1351 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1358 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1352 ui.status(_('created new head\n'))
1359 ui.status(_('created new head\n'))
1353 # The message is not printed for initial roots. For the other
1360 # The message is not printed for initial roots. For the other
1354 # changesets, it is printed in the following situations:
1361 # changesets, it is printed in the following situations:
1355 #
1362 #
1356 # Par column: for the 2 parents with ...
1363 # Par column: for the 2 parents with ...
1357 # N: null or no parent
1364 # N: null or no parent
1358 # B: parent is on another named branch
1365 # B: parent is on another named branch
1359 # C: parent is a regular non head changeset
1366 # C: parent is a regular non head changeset
1360 # H: parent was a branch head of the current branch
1367 # H: parent was a branch head of the current branch
1361 # Msg column: whether we print "created new head" message
1368 # Msg column: whether we print "created new head" message
1362 # In the following, it is assumed that there already exists some
1369 # In the following, it is assumed that there already exists some
1363 # initial branch heads of the current branch, otherwise nothing is
1370 # initial branch heads of the current branch, otherwise nothing is
1364 # printed anyway.
1371 # printed anyway.
1365 #
1372 #
1366 # Par Msg Comment
1373 # Par Msg Comment
1367 # N N y additional topo root
1374 # N N y additional topo root
1368 #
1375 #
1369 # B N y additional branch root
1376 # B N y additional branch root
1370 # C N y additional topo head
1377 # C N y additional topo head
1371 # H N n usual case
1378 # H N n usual case
1372 #
1379 #
1373 # B B y weird additional branch root
1380 # B B y weird additional branch root
1374 # C B y branch merge
1381 # C B y branch merge
1375 # H B n merge with named branch
1382 # H B n merge with named branch
1376 #
1383 #
1377 # C C y additional head from merge
1384 # C C y additional head from merge
1378 # C H n merge with a head
1385 # C H n merge with a head
1379 #
1386 #
1380 # H H n head merge: head count decreases
1387 # H H n head merge: head count decreases
1381
1388
1382 if not opts.get('close_branch'):
1389 if not opts.get('close_branch'):
1383 for r in parents:
1390 for r in parents:
1384 if r.closesbranch() and r.branch() == branch:
1391 if r.closesbranch() and r.branch() == branch:
1385 ui.status(_('reopening closed branch head %d\n') % r)
1392 ui.status(_('reopening closed branch head %d\n') % r)
1386
1393
1387 if ui.debugflag:
1394 if ui.debugflag:
1388 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1395 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1389 elif ui.verbose:
1396 elif ui.verbose:
1390 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1397 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1391
1398
1392 @command('copy|cp',
1399 @command('copy|cp',
1393 [('A', 'after', None, _('record a copy that has already occurred')),
1400 [('A', 'after', None, _('record a copy that has already occurred')),
1394 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1401 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1395 ] + walkopts + dryrunopts,
1402 ] + walkopts + dryrunopts,
1396 _('[OPTION]... [SOURCE]... DEST'))
1403 _('[OPTION]... [SOURCE]... DEST'))
1397 def copy(ui, repo, *pats, **opts):
1404 def copy(ui, repo, *pats, **opts):
1398 """mark files as copied for the next commit
1405 """mark files as copied for the next commit
1399
1406
1400 Mark dest as having copies of source files. If dest is a
1407 Mark dest as having copies of source files. If dest is a
1401 directory, copies are put in that directory. If dest is a file,
1408 directory, copies are put in that directory. If dest is a file,
1402 the source must be a single file.
1409 the source must be a single file.
1403
1410
1404 By default, this command copies the contents of files as they
1411 By default, this command copies the contents of files as they
1405 exist in the working directory. If invoked with -A/--after, the
1412 exist in the working directory. If invoked with -A/--after, the
1406 operation is recorded, but no copying is performed.
1413 operation is recorded, but no copying is performed.
1407
1414
1408 This command takes effect with the next commit. To undo a copy
1415 This command takes effect with the next commit. To undo a copy
1409 before that, see :hg:`revert`.
1416 before that, see :hg:`revert`.
1410
1417
1411 Returns 0 on success, 1 if errors are encountered.
1418 Returns 0 on success, 1 if errors are encountered.
1412 """
1419 """
1413 wlock = repo.wlock(False)
1420 wlock = repo.wlock(False)
1414 try:
1421 try:
1415 return cmdutil.copy(ui, repo, pats, opts)
1422 return cmdutil.copy(ui, repo, pats, opts)
1416 finally:
1423 finally:
1417 wlock.release()
1424 wlock.release()
1418
1425
1419 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1426 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1420 def debugancestor(ui, repo, *args):
1427 def debugancestor(ui, repo, *args):
1421 """find the ancestor revision of two revisions in a given index"""
1428 """find the ancestor revision of two revisions in a given index"""
1422 if len(args) == 3:
1429 if len(args) == 3:
1423 index, rev1, rev2 = args
1430 index, rev1, rev2 = args
1424 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1431 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1425 lookup = r.lookup
1432 lookup = r.lookup
1426 elif len(args) == 2:
1433 elif len(args) == 2:
1427 if not repo:
1434 if not repo:
1428 raise util.Abort(_("there is no Mercurial repository here "
1435 raise util.Abort(_("there is no Mercurial repository here "
1429 "(.hg not found)"))
1436 "(.hg not found)"))
1430 rev1, rev2 = args
1437 rev1, rev2 = args
1431 r = repo.changelog
1438 r = repo.changelog
1432 lookup = repo.lookup
1439 lookup = repo.lookup
1433 else:
1440 else:
1434 raise util.Abort(_('either two or three arguments required'))
1441 raise util.Abort(_('either two or three arguments required'))
1435 a = r.ancestor(lookup(rev1), lookup(rev2))
1442 a = r.ancestor(lookup(rev1), lookup(rev2))
1436 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1443 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1437
1444
1438 @command('debugbuilddag',
1445 @command('debugbuilddag',
1439 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1446 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1440 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1447 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1441 ('n', 'new-file', None, _('add new file at each rev'))],
1448 ('n', 'new-file', None, _('add new file at each rev'))],
1442 _('[OPTION]... [TEXT]'))
1449 _('[OPTION]... [TEXT]'))
1443 def debugbuilddag(ui, repo, text=None,
1450 def debugbuilddag(ui, repo, text=None,
1444 mergeable_file=False,
1451 mergeable_file=False,
1445 overwritten_file=False,
1452 overwritten_file=False,
1446 new_file=False):
1453 new_file=False):
1447 """builds a repo with a given DAG from scratch in the current empty repo
1454 """builds a repo with a given DAG from scratch in the current empty repo
1448
1455
1449 The description of the DAG is read from stdin if not given on the
1456 The description of the DAG is read from stdin if not given on the
1450 command line.
1457 command line.
1451
1458
1452 Elements:
1459 Elements:
1453
1460
1454 - "+n" is a linear run of n nodes based on the current default parent
1461 - "+n" is a linear run of n nodes based on the current default parent
1455 - "." is a single node based on the current default parent
1462 - "." is a single node based on the current default parent
1456 - "$" resets the default parent to null (implied at the start);
1463 - "$" resets the default parent to null (implied at the start);
1457 otherwise the default parent is always the last node created
1464 otherwise the default parent is always the last node created
1458 - "<p" sets the default parent to the backref p
1465 - "<p" sets the default parent to the backref p
1459 - "*p" is a fork at parent p, which is a backref
1466 - "*p" is a fork at parent p, which is a backref
1460 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1467 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1461 - "/p2" is a merge of the preceding node and p2
1468 - "/p2" is a merge of the preceding node and p2
1462 - ":tag" defines a local tag for the preceding node
1469 - ":tag" defines a local tag for the preceding node
1463 - "@branch" sets the named branch for subsequent nodes
1470 - "@branch" sets the named branch for subsequent nodes
1464 - "#...\\n" is a comment up to the end of the line
1471 - "#...\\n" is a comment up to the end of the line
1465
1472
1466 Whitespace between the above elements is ignored.
1473 Whitespace between the above elements is ignored.
1467
1474
1468 A backref is either
1475 A backref is either
1469
1476
1470 - a number n, which references the node curr-n, where curr is the current
1477 - a number n, which references the node curr-n, where curr is the current
1471 node, or
1478 node, or
1472 - the name of a local tag you placed earlier using ":tag", or
1479 - the name of a local tag you placed earlier using ":tag", or
1473 - empty to denote the default parent.
1480 - empty to denote the default parent.
1474
1481
1475 All string valued-elements are either strictly alphanumeric, or must
1482 All string valued-elements are either strictly alphanumeric, or must
1476 be enclosed in double quotes ("..."), with "\\" as escape character.
1483 be enclosed in double quotes ("..."), with "\\" as escape character.
1477 """
1484 """
1478
1485
1479 if text is None:
1486 if text is None:
1480 ui.status(_("reading DAG from stdin\n"))
1487 ui.status(_("reading DAG from stdin\n"))
1481 text = ui.fin.read()
1488 text = ui.fin.read()
1482
1489
1483 cl = repo.changelog
1490 cl = repo.changelog
1484 if len(cl) > 0:
1491 if len(cl) > 0:
1485 raise util.Abort(_('repository is not empty'))
1492 raise util.Abort(_('repository is not empty'))
1486
1493
1487 # determine number of revs in DAG
1494 # determine number of revs in DAG
1488 total = 0
1495 total = 0
1489 for type, data in dagparser.parsedag(text):
1496 for type, data in dagparser.parsedag(text):
1490 if type == 'n':
1497 if type == 'n':
1491 total += 1
1498 total += 1
1492
1499
1493 if mergeable_file:
1500 if mergeable_file:
1494 linesperrev = 2
1501 linesperrev = 2
1495 # make a file with k lines per rev
1502 # make a file with k lines per rev
1496 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1503 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1497 initialmergedlines.append("")
1504 initialmergedlines.append("")
1498
1505
1499 tags = []
1506 tags = []
1500
1507
1501 lock = tr = None
1508 lock = tr = None
1502 try:
1509 try:
1503 lock = repo.lock()
1510 lock = repo.lock()
1504 tr = repo.transaction("builddag")
1511 tr = repo.transaction("builddag")
1505
1512
1506 at = -1
1513 at = -1
1507 atbranch = 'default'
1514 atbranch = 'default'
1508 nodeids = []
1515 nodeids = []
1509 id = 0
1516 id = 0
1510 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1517 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1511 for type, data in dagparser.parsedag(text):
1518 for type, data in dagparser.parsedag(text):
1512 if type == 'n':
1519 if type == 'n':
1513 ui.note('node %s\n' % str(data))
1520 ui.note('node %s\n' % str(data))
1514 id, ps = data
1521 id, ps = data
1515
1522
1516 files = []
1523 files = []
1517 fctxs = {}
1524 fctxs = {}
1518
1525
1519 p2 = None
1526 p2 = None
1520 if mergeable_file:
1527 if mergeable_file:
1521 fn = "mf"
1528 fn = "mf"
1522 p1 = repo[ps[0]]
1529 p1 = repo[ps[0]]
1523 if len(ps) > 1:
1530 if len(ps) > 1:
1524 p2 = repo[ps[1]]
1531 p2 = repo[ps[1]]
1525 pa = p1.ancestor(p2)
1532 pa = p1.ancestor(p2)
1526 base, local, other = [x[fn].data() for x in pa, p1, p2]
1533 base, local, other = [x[fn].data() for x in pa, p1, p2]
1527 m3 = simplemerge.Merge3Text(base, local, other)
1534 m3 = simplemerge.Merge3Text(base, local, other)
1528 ml = [l.strip() for l in m3.merge_lines()]
1535 ml = [l.strip() for l in m3.merge_lines()]
1529 ml.append("")
1536 ml.append("")
1530 elif at > 0:
1537 elif at > 0:
1531 ml = p1[fn].data().split("\n")
1538 ml = p1[fn].data().split("\n")
1532 else:
1539 else:
1533 ml = initialmergedlines
1540 ml = initialmergedlines
1534 ml[id * linesperrev] += " r%i" % id
1541 ml[id * linesperrev] += " r%i" % id
1535 mergedtext = "\n".join(ml)
1542 mergedtext = "\n".join(ml)
1536 files.append(fn)
1543 files.append(fn)
1537 fctxs[fn] = context.memfilectx(fn, mergedtext)
1544 fctxs[fn] = context.memfilectx(fn, mergedtext)
1538
1545
1539 if overwritten_file:
1546 if overwritten_file:
1540 fn = "of"
1547 fn = "of"
1541 files.append(fn)
1548 files.append(fn)
1542 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1549 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1543
1550
1544 if new_file:
1551 if new_file:
1545 fn = "nf%i" % id
1552 fn = "nf%i" % id
1546 files.append(fn)
1553 files.append(fn)
1547 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1554 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1548 if len(ps) > 1:
1555 if len(ps) > 1:
1549 if not p2:
1556 if not p2:
1550 p2 = repo[ps[1]]
1557 p2 = repo[ps[1]]
1551 for fn in p2:
1558 for fn in p2:
1552 if fn.startswith("nf"):
1559 if fn.startswith("nf"):
1553 files.append(fn)
1560 files.append(fn)
1554 fctxs[fn] = p2[fn]
1561 fctxs[fn] = p2[fn]
1555
1562
1556 def fctxfn(repo, cx, path):
1563 def fctxfn(repo, cx, path):
1557 return fctxs.get(path)
1564 return fctxs.get(path)
1558
1565
1559 if len(ps) == 0 or ps[0] < 0:
1566 if len(ps) == 0 or ps[0] < 0:
1560 pars = [None, None]
1567 pars = [None, None]
1561 elif len(ps) == 1:
1568 elif len(ps) == 1:
1562 pars = [nodeids[ps[0]], None]
1569 pars = [nodeids[ps[0]], None]
1563 else:
1570 else:
1564 pars = [nodeids[p] for p in ps]
1571 pars = [nodeids[p] for p in ps]
1565 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1572 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1566 date=(id, 0),
1573 date=(id, 0),
1567 user="debugbuilddag",
1574 user="debugbuilddag",
1568 extra={'branch': atbranch})
1575 extra={'branch': atbranch})
1569 nodeid = repo.commitctx(cx)
1576 nodeid = repo.commitctx(cx)
1570 nodeids.append(nodeid)
1577 nodeids.append(nodeid)
1571 at = id
1578 at = id
1572 elif type == 'l':
1579 elif type == 'l':
1573 id, name = data
1580 id, name = data
1574 ui.note('tag %s\n' % name)
1581 ui.note('tag %s\n' % name)
1575 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1582 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1576 elif type == 'a':
1583 elif type == 'a':
1577 ui.note('branch %s\n' % data)
1584 ui.note('branch %s\n' % data)
1578 atbranch = data
1585 atbranch = data
1579 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1586 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1580 tr.close()
1587 tr.close()
1581
1588
1582 if tags:
1589 if tags:
1583 repo.opener.write("localtags", "".join(tags))
1590 repo.opener.write("localtags", "".join(tags))
1584 finally:
1591 finally:
1585 ui.progress(_('building'), None)
1592 ui.progress(_('building'), None)
1586 release(tr, lock)
1593 release(tr, lock)
1587
1594
1588 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1595 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1589 def debugbundle(ui, bundlepath, all=None, **opts):
1596 def debugbundle(ui, bundlepath, all=None, **opts):
1590 """lists the contents of a bundle"""
1597 """lists the contents of a bundle"""
1591 f = url.open(ui, bundlepath)
1598 f = url.open(ui, bundlepath)
1592 try:
1599 try:
1593 gen = changegroup.readbundle(f, bundlepath)
1600 gen = changegroup.readbundle(f, bundlepath)
1594 if all:
1601 if all:
1595 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1602 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1596
1603
1597 def showchunks(named):
1604 def showchunks(named):
1598 ui.write("\n%s\n" % named)
1605 ui.write("\n%s\n" % named)
1599 chain = None
1606 chain = None
1600 while True:
1607 while True:
1601 chunkdata = gen.deltachunk(chain)
1608 chunkdata = gen.deltachunk(chain)
1602 if not chunkdata:
1609 if not chunkdata:
1603 break
1610 break
1604 node = chunkdata['node']
1611 node = chunkdata['node']
1605 p1 = chunkdata['p1']
1612 p1 = chunkdata['p1']
1606 p2 = chunkdata['p2']
1613 p2 = chunkdata['p2']
1607 cs = chunkdata['cs']
1614 cs = chunkdata['cs']
1608 deltabase = chunkdata['deltabase']
1615 deltabase = chunkdata['deltabase']
1609 delta = chunkdata['delta']
1616 delta = chunkdata['delta']
1610 ui.write("%s %s %s %s %s %s\n" %
1617 ui.write("%s %s %s %s %s %s\n" %
1611 (hex(node), hex(p1), hex(p2),
1618 (hex(node), hex(p1), hex(p2),
1612 hex(cs), hex(deltabase), len(delta)))
1619 hex(cs), hex(deltabase), len(delta)))
1613 chain = node
1620 chain = node
1614
1621
1615 chunkdata = gen.changelogheader()
1622 chunkdata = gen.changelogheader()
1616 showchunks("changelog")
1623 showchunks("changelog")
1617 chunkdata = gen.manifestheader()
1624 chunkdata = gen.manifestheader()
1618 showchunks("manifest")
1625 showchunks("manifest")
1619 while True:
1626 while True:
1620 chunkdata = gen.filelogheader()
1627 chunkdata = gen.filelogheader()
1621 if not chunkdata:
1628 if not chunkdata:
1622 break
1629 break
1623 fname = chunkdata['filename']
1630 fname = chunkdata['filename']
1624 showchunks(fname)
1631 showchunks(fname)
1625 else:
1632 else:
1626 chunkdata = gen.changelogheader()
1633 chunkdata = gen.changelogheader()
1627 chain = None
1634 chain = None
1628 while True:
1635 while True:
1629 chunkdata = gen.deltachunk(chain)
1636 chunkdata = gen.deltachunk(chain)
1630 if not chunkdata:
1637 if not chunkdata:
1631 break
1638 break
1632 node = chunkdata['node']
1639 node = chunkdata['node']
1633 ui.write("%s\n" % hex(node))
1640 ui.write("%s\n" % hex(node))
1634 chain = node
1641 chain = node
1635 finally:
1642 finally:
1636 f.close()
1643 f.close()
1637
1644
1638 @command('debugcheckstate', [], '')
1645 @command('debugcheckstate', [], '')
1639 def debugcheckstate(ui, repo):
1646 def debugcheckstate(ui, repo):
1640 """validate the correctness of the current dirstate"""
1647 """validate the correctness of the current dirstate"""
1641 parent1, parent2 = repo.dirstate.parents()
1648 parent1, parent2 = repo.dirstate.parents()
1642 m1 = repo[parent1].manifest()
1649 m1 = repo[parent1].manifest()
1643 m2 = repo[parent2].manifest()
1650 m2 = repo[parent2].manifest()
1644 errors = 0
1651 errors = 0
1645 for f in repo.dirstate:
1652 for f in repo.dirstate:
1646 state = repo.dirstate[f]
1653 state = repo.dirstate[f]
1647 if state in "nr" and f not in m1:
1654 if state in "nr" and f not in m1:
1648 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1655 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1649 errors += 1
1656 errors += 1
1650 if state in "a" and f in m1:
1657 if state in "a" and f in m1:
1651 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1658 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1652 errors += 1
1659 errors += 1
1653 if state in "m" and f not in m1 and f not in m2:
1660 if state in "m" and f not in m1 and f not in m2:
1654 ui.warn(_("%s in state %s, but not in either manifest\n") %
1661 ui.warn(_("%s in state %s, but not in either manifest\n") %
1655 (f, state))
1662 (f, state))
1656 errors += 1
1663 errors += 1
1657 for f in m1:
1664 for f in m1:
1658 state = repo.dirstate[f]
1665 state = repo.dirstate[f]
1659 if state not in "nrm":
1666 if state not in "nrm":
1660 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1667 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1661 errors += 1
1668 errors += 1
1662 if errors:
1669 if errors:
1663 error = _(".hg/dirstate inconsistent with current parent's manifest")
1670 error = _(".hg/dirstate inconsistent with current parent's manifest")
1664 raise util.Abort(error)
1671 raise util.Abort(error)
1665
1672
1666 @command('debugcommands', [], _('[COMMAND]'))
1673 @command('debugcommands', [], _('[COMMAND]'))
1667 def debugcommands(ui, cmd='', *args):
1674 def debugcommands(ui, cmd='', *args):
1668 """list all available commands and options"""
1675 """list all available commands and options"""
1669 for cmd, vals in sorted(table.iteritems()):
1676 for cmd, vals in sorted(table.iteritems()):
1670 cmd = cmd.split('|')[0].strip('^')
1677 cmd = cmd.split('|')[0].strip('^')
1671 opts = ', '.join([i[1] for i in vals[1]])
1678 opts = ', '.join([i[1] for i in vals[1]])
1672 ui.write('%s: %s\n' % (cmd, opts))
1679 ui.write('%s: %s\n' % (cmd, opts))
1673
1680
1674 @command('debugcomplete',
1681 @command('debugcomplete',
1675 [('o', 'options', None, _('show the command options'))],
1682 [('o', 'options', None, _('show the command options'))],
1676 _('[-o] CMD'))
1683 _('[-o] CMD'))
1677 def debugcomplete(ui, cmd='', **opts):
1684 def debugcomplete(ui, cmd='', **opts):
1678 """returns the completion list associated with the given command"""
1685 """returns the completion list associated with the given command"""
1679
1686
1680 if opts.get('options'):
1687 if opts.get('options'):
1681 options = []
1688 options = []
1682 otables = [globalopts]
1689 otables = [globalopts]
1683 if cmd:
1690 if cmd:
1684 aliases, entry = cmdutil.findcmd(cmd, table, False)
1691 aliases, entry = cmdutil.findcmd(cmd, table, False)
1685 otables.append(entry[1])
1692 otables.append(entry[1])
1686 for t in otables:
1693 for t in otables:
1687 for o in t:
1694 for o in t:
1688 if "(DEPRECATED)" in o[3]:
1695 if "(DEPRECATED)" in o[3]:
1689 continue
1696 continue
1690 if o[0]:
1697 if o[0]:
1691 options.append('-%s' % o[0])
1698 options.append('-%s' % o[0])
1692 options.append('--%s' % o[1])
1699 options.append('--%s' % o[1])
1693 ui.write("%s\n" % "\n".join(options))
1700 ui.write("%s\n" % "\n".join(options))
1694 return
1701 return
1695
1702
1696 cmdlist = cmdutil.findpossible(cmd, table)
1703 cmdlist = cmdutil.findpossible(cmd, table)
1697 if ui.verbose:
1704 if ui.verbose:
1698 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1705 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1699 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1706 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1700
1707
1701 @command('debugdag',
1708 @command('debugdag',
1702 [('t', 'tags', None, _('use tags as labels')),
1709 [('t', 'tags', None, _('use tags as labels')),
1703 ('b', 'branches', None, _('annotate with branch names')),
1710 ('b', 'branches', None, _('annotate with branch names')),
1704 ('', 'dots', None, _('use dots for runs')),
1711 ('', 'dots', None, _('use dots for runs')),
1705 ('s', 'spaces', None, _('separate elements by spaces'))],
1712 ('s', 'spaces', None, _('separate elements by spaces'))],
1706 _('[OPTION]... [FILE [REV]...]'))
1713 _('[OPTION]... [FILE [REV]...]'))
1707 def debugdag(ui, repo, file_=None, *revs, **opts):
1714 def debugdag(ui, repo, file_=None, *revs, **opts):
1708 """format the changelog or an index DAG as a concise textual description
1715 """format the changelog or an index DAG as a concise textual description
1709
1716
1710 If you pass a revlog index, the revlog's DAG is emitted. If you list
1717 If you pass a revlog index, the revlog's DAG is emitted. If you list
1711 revision numbers, they get labeled in the output as rN.
1718 revision numbers, they get labeled in the output as rN.
1712
1719
1713 Otherwise, the changelog DAG of the current repo is emitted.
1720 Otherwise, the changelog DAG of the current repo is emitted.
1714 """
1721 """
1715 spaces = opts.get('spaces')
1722 spaces = opts.get('spaces')
1716 dots = opts.get('dots')
1723 dots = opts.get('dots')
1717 if file_:
1724 if file_:
1718 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1725 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1719 revs = set((int(r) for r in revs))
1726 revs = set((int(r) for r in revs))
1720 def events():
1727 def events():
1721 for r in rlog:
1728 for r in rlog:
1722 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1729 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1723 if p != -1)))
1730 if p != -1)))
1724 if r in revs:
1731 if r in revs:
1725 yield 'l', (r, "r%i" % r)
1732 yield 'l', (r, "r%i" % r)
1726 elif repo:
1733 elif repo:
1727 cl = repo.changelog
1734 cl = repo.changelog
1728 tags = opts.get('tags')
1735 tags = opts.get('tags')
1729 branches = opts.get('branches')
1736 branches = opts.get('branches')
1730 if tags:
1737 if tags:
1731 labels = {}
1738 labels = {}
1732 for l, n in repo.tags().items():
1739 for l, n in repo.tags().items():
1733 labels.setdefault(cl.rev(n), []).append(l)
1740 labels.setdefault(cl.rev(n), []).append(l)
1734 def events():
1741 def events():
1735 b = "default"
1742 b = "default"
1736 for r in cl:
1743 for r in cl:
1737 if branches:
1744 if branches:
1738 newb = cl.read(cl.node(r))[5]['branch']
1745 newb = cl.read(cl.node(r))[5]['branch']
1739 if newb != b:
1746 if newb != b:
1740 yield 'a', newb
1747 yield 'a', newb
1741 b = newb
1748 b = newb
1742 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1749 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1743 if p != -1)))
1750 if p != -1)))
1744 if tags:
1751 if tags:
1745 ls = labels.get(r)
1752 ls = labels.get(r)
1746 if ls:
1753 if ls:
1747 for l in ls:
1754 for l in ls:
1748 yield 'l', (r, l)
1755 yield 'l', (r, l)
1749 else:
1756 else:
1750 raise util.Abort(_('need repo for changelog dag'))
1757 raise util.Abort(_('need repo for changelog dag'))
1751
1758
1752 for line in dagparser.dagtextlines(events(),
1759 for line in dagparser.dagtextlines(events(),
1753 addspaces=spaces,
1760 addspaces=spaces,
1754 wraplabels=True,
1761 wraplabels=True,
1755 wrapannotations=True,
1762 wrapannotations=True,
1756 wrapnonlinear=dots,
1763 wrapnonlinear=dots,
1757 usedots=dots,
1764 usedots=dots,
1758 maxlinewidth=70):
1765 maxlinewidth=70):
1759 ui.write(line)
1766 ui.write(line)
1760 ui.write("\n")
1767 ui.write("\n")
1761
1768
1762 @command('debugdata',
1769 @command('debugdata',
1763 [('c', 'changelog', False, _('open changelog')),
1770 [('c', 'changelog', False, _('open changelog')),
1764 ('m', 'manifest', False, _('open manifest'))],
1771 ('m', 'manifest', False, _('open manifest'))],
1765 _('-c|-m|FILE REV'))
1772 _('-c|-m|FILE REV'))
1766 def debugdata(ui, repo, file_, rev = None, **opts):
1773 def debugdata(ui, repo, file_, rev = None, **opts):
1767 """dump the contents of a data file revision"""
1774 """dump the contents of a data file revision"""
1768 if opts.get('changelog') or opts.get('manifest'):
1775 if opts.get('changelog') or opts.get('manifest'):
1769 file_, rev = None, file_
1776 file_, rev = None, file_
1770 elif rev is None:
1777 elif rev is None:
1771 raise error.CommandError('debugdata', _('invalid arguments'))
1778 raise error.CommandError('debugdata', _('invalid arguments'))
1772 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1779 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1773 try:
1780 try:
1774 ui.write(r.revision(r.lookup(rev)))
1781 ui.write(r.revision(r.lookup(rev)))
1775 except KeyError:
1782 except KeyError:
1776 raise util.Abort(_('invalid revision identifier %s') % rev)
1783 raise util.Abort(_('invalid revision identifier %s') % rev)
1777
1784
1778 @command('debugdate',
1785 @command('debugdate',
1779 [('e', 'extended', None, _('try extended date formats'))],
1786 [('e', 'extended', None, _('try extended date formats'))],
1780 _('[-e] DATE [RANGE]'))
1787 _('[-e] DATE [RANGE]'))
1781 def debugdate(ui, date, range=None, **opts):
1788 def debugdate(ui, date, range=None, **opts):
1782 """parse and display a date"""
1789 """parse and display a date"""
1783 if opts["extended"]:
1790 if opts["extended"]:
1784 d = util.parsedate(date, util.extendeddateformats)
1791 d = util.parsedate(date, util.extendeddateformats)
1785 else:
1792 else:
1786 d = util.parsedate(date)
1793 d = util.parsedate(date)
1787 ui.write("internal: %s %s\n" % d)
1794 ui.write("internal: %s %s\n" % d)
1788 ui.write("standard: %s\n" % util.datestr(d))
1795 ui.write("standard: %s\n" % util.datestr(d))
1789 if range:
1796 if range:
1790 m = util.matchdate(range)
1797 m = util.matchdate(range)
1791 ui.write("match: %s\n" % m(d[0]))
1798 ui.write("match: %s\n" % m(d[0]))
1792
1799
1793 @command('debugdiscovery',
1800 @command('debugdiscovery',
1794 [('', 'old', None, _('use old-style discovery')),
1801 [('', 'old', None, _('use old-style discovery')),
1795 ('', 'nonheads', None,
1802 ('', 'nonheads', None,
1796 _('use old-style discovery with non-heads included')),
1803 _('use old-style discovery with non-heads included')),
1797 ] + remoteopts,
1804 ] + remoteopts,
1798 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1805 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1799 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1806 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1800 """runs the changeset discovery protocol in isolation"""
1807 """runs the changeset discovery protocol in isolation"""
1801 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1808 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1802 opts.get('branch'))
1809 opts.get('branch'))
1803 remote = hg.peer(repo, opts, remoteurl)
1810 remote = hg.peer(repo, opts, remoteurl)
1804 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1811 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1805
1812
1806 # make sure tests are repeatable
1813 # make sure tests are repeatable
1807 random.seed(12323)
1814 random.seed(12323)
1808
1815
1809 def doit(localheads, remoteheads, remote=remote):
1816 def doit(localheads, remoteheads, remote=remote):
1810 if opts.get('old'):
1817 if opts.get('old'):
1811 if localheads:
1818 if localheads:
1812 raise util.Abort('cannot use localheads with old style '
1819 raise util.Abort('cannot use localheads with old style '
1813 'discovery')
1820 'discovery')
1814 if not util.safehasattr(remote, 'branches'):
1821 if not util.safehasattr(remote, 'branches'):
1815 # enable in-client legacy support
1822 # enable in-client legacy support
1816 remote = localrepo.locallegacypeer(remote.local())
1823 remote = localrepo.locallegacypeer(remote.local())
1817 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1824 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1818 force=True)
1825 force=True)
1819 common = set(common)
1826 common = set(common)
1820 if not opts.get('nonheads'):
1827 if not opts.get('nonheads'):
1821 ui.write("unpruned common: %s\n" % " ".join([short(n)
1828 ui.write("unpruned common: %s\n" % " ".join([short(n)
1822 for n in common]))
1829 for n in common]))
1823 dag = dagutil.revlogdag(repo.changelog)
1830 dag = dagutil.revlogdag(repo.changelog)
1824 all = dag.ancestorset(dag.internalizeall(common))
1831 all = dag.ancestorset(dag.internalizeall(common))
1825 common = dag.externalizeall(dag.headsetofconnecteds(all))
1832 common = dag.externalizeall(dag.headsetofconnecteds(all))
1826 else:
1833 else:
1827 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1834 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1828 common = set(common)
1835 common = set(common)
1829 rheads = set(hds)
1836 rheads = set(hds)
1830 lheads = set(repo.heads())
1837 lheads = set(repo.heads())
1831 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1838 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1832 if lheads <= common:
1839 if lheads <= common:
1833 ui.write("local is subset\n")
1840 ui.write("local is subset\n")
1834 elif rheads <= common:
1841 elif rheads <= common:
1835 ui.write("remote is subset\n")
1842 ui.write("remote is subset\n")
1836
1843
1837 serverlogs = opts.get('serverlog')
1844 serverlogs = opts.get('serverlog')
1838 if serverlogs:
1845 if serverlogs:
1839 for filename in serverlogs:
1846 for filename in serverlogs:
1840 logfile = open(filename, 'r')
1847 logfile = open(filename, 'r')
1841 try:
1848 try:
1842 line = logfile.readline()
1849 line = logfile.readline()
1843 while line:
1850 while line:
1844 parts = line.strip().split(';')
1851 parts = line.strip().split(';')
1845 op = parts[1]
1852 op = parts[1]
1846 if op == 'cg':
1853 if op == 'cg':
1847 pass
1854 pass
1848 elif op == 'cgss':
1855 elif op == 'cgss':
1849 doit(parts[2].split(' '), parts[3].split(' '))
1856 doit(parts[2].split(' '), parts[3].split(' '))
1850 elif op == 'unb':
1857 elif op == 'unb':
1851 doit(parts[3].split(' '), parts[2].split(' '))
1858 doit(parts[3].split(' '), parts[2].split(' '))
1852 line = logfile.readline()
1859 line = logfile.readline()
1853 finally:
1860 finally:
1854 logfile.close()
1861 logfile.close()
1855
1862
1856 else:
1863 else:
1857 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1864 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1858 opts.get('remote_head'))
1865 opts.get('remote_head'))
1859 localrevs = opts.get('local_head')
1866 localrevs = opts.get('local_head')
1860 doit(localrevs, remoterevs)
1867 doit(localrevs, remoterevs)
1861
1868
1862 @command('debugfileset',
1869 @command('debugfileset',
1863 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1870 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1864 _('[-r REV] FILESPEC'))
1871 _('[-r REV] FILESPEC'))
1865 def debugfileset(ui, repo, expr, **opts):
1872 def debugfileset(ui, repo, expr, **opts):
1866 '''parse and apply a fileset specification'''
1873 '''parse and apply a fileset specification'''
1867 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1874 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1868 if ui.verbose:
1875 if ui.verbose:
1869 tree = fileset.parse(expr)[0]
1876 tree = fileset.parse(expr)[0]
1870 ui.note(tree, "\n")
1877 ui.note(tree, "\n")
1871
1878
1872 for f in fileset.getfileset(ctx, expr):
1879 for f in fileset.getfileset(ctx, expr):
1873 ui.write("%s\n" % f)
1880 ui.write("%s\n" % f)
1874
1881
1875 @command('debugfsinfo', [], _('[PATH]'))
1882 @command('debugfsinfo', [], _('[PATH]'))
1876 def debugfsinfo(ui, path = "."):
1883 def debugfsinfo(ui, path = "."):
1877 """show information detected about current filesystem"""
1884 """show information detected about current filesystem"""
1878 util.writefile('.debugfsinfo', '')
1885 util.writefile('.debugfsinfo', '')
1879 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1886 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1880 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1887 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1881 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1888 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1882 and 'yes' or 'no'))
1889 and 'yes' or 'no'))
1883 os.unlink('.debugfsinfo')
1890 os.unlink('.debugfsinfo')
1884
1891
1885 @command('debuggetbundle',
1892 @command('debuggetbundle',
1886 [('H', 'head', [], _('id of head node'), _('ID')),
1893 [('H', 'head', [], _('id of head node'), _('ID')),
1887 ('C', 'common', [], _('id of common node'), _('ID')),
1894 ('C', 'common', [], _('id of common node'), _('ID')),
1888 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1895 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1889 _('REPO FILE [-H|-C ID]...'))
1896 _('REPO FILE [-H|-C ID]...'))
1890 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1897 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1891 """retrieves a bundle from a repo
1898 """retrieves a bundle from a repo
1892
1899
1893 Every ID must be a full-length hex node id string. Saves the bundle to the
1900 Every ID must be a full-length hex node id string. Saves the bundle to the
1894 given file.
1901 given file.
1895 """
1902 """
1896 repo = hg.peer(ui, opts, repopath)
1903 repo = hg.peer(ui, opts, repopath)
1897 if not repo.capable('getbundle'):
1904 if not repo.capable('getbundle'):
1898 raise util.Abort("getbundle() not supported by target repository")
1905 raise util.Abort("getbundle() not supported by target repository")
1899 args = {}
1906 args = {}
1900 if common:
1907 if common:
1901 args['common'] = [bin(s) for s in common]
1908 args['common'] = [bin(s) for s in common]
1902 if head:
1909 if head:
1903 args['heads'] = [bin(s) for s in head]
1910 args['heads'] = [bin(s) for s in head]
1904 bundle = repo.getbundle('debug', **args)
1911 bundle = repo.getbundle('debug', **args)
1905
1912
1906 bundletype = opts.get('type', 'bzip2').lower()
1913 bundletype = opts.get('type', 'bzip2').lower()
1907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1914 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1908 bundletype = btypes.get(bundletype)
1915 bundletype = btypes.get(bundletype)
1909 if bundletype not in changegroup.bundletypes:
1916 if bundletype not in changegroup.bundletypes:
1910 raise util.Abort(_('unknown bundle type specified with --type'))
1917 raise util.Abort(_('unknown bundle type specified with --type'))
1911 changegroup.writebundle(bundle, bundlepath, bundletype)
1918 changegroup.writebundle(bundle, bundlepath, bundletype)
1912
1919
1913 @command('debugignore', [], '')
1920 @command('debugignore', [], '')
1914 def debugignore(ui, repo, *values, **opts):
1921 def debugignore(ui, repo, *values, **opts):
1915 """display the combined ignore pattern"""
1922 """display the combined ignore pattern"""
1916 ignore = repo.dirstate._ignore
1923 ignore = repo.dirstate._ignore
1917 includepat = getattr(ignore, 'includepat', None)
1924 includepat = getattr(ignore, 'includepat', None)
1918 if includepat is not None:
1925 if includepat is not None:
1919 ui.write("%s\n" % includepat)
1926 ui.write("%s\n" % includepat)
1920 else:
1927 else:
1921 raise util.Abort(_("no ignore patterns found"))
1928 raise util.Abort(_("no ignore patterns found"))
1922
1929
1923 @command('debugindex',
1930 @command('debugindex',
1924 [('c', 'changelog', False, _('open changelog')),
1931 [('c', 'changelog', False, _('open changelog')),
1925 ('m', 'manifest', False, _('open manifest')),
1932 ('m', 'manifest', False, _('open manifest')),
1926 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1933 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1927 _('[-f FORMAT] -c|-m|FILE'))
1934 _('[-f FORMAT] -c|-m|FILE'))
1928 def debugindex(ui, repo, file_ = None, **opts):
1935 def debugindex(ui, repo, file_ = None, **opts):
1929 """dump the contents of an index file"""
1936 """dump the contents of an index file"""
1930 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1937 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1931 format = opts.get('format', 0)
1938 format = opts.get('format', 0)
1932 if format not in (0, 1):
1939 if format not in (0, 1):
1933 raise util.Abort(_("unknown format %d") % format)
1940 raise util.Abort(_("unknown format %d") % format)
1934
1941
1935 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1942 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1936 if generaldelta:
1943 if generaldelta:
1937 basehdr = ' delta'
1944 basehdr = ' delta'
1938 else:
1945 else:
1939 basehdr = ' base'
1946 basehdr = ' base'
1940
1947
1941 if format == 0:
1948 if format == 0:
1942 ui.write(" rev offset length " + basehdr + " linkrev"
1949 ui.write(" rev offset length " + basehdr + " linkrev"
1943 " nodeid p1 p2\n")
1950 " nodeid p1 p2\n")
1944 elif format == 1:
1951 elif format == 1:
1945 ui.write(" rev flag offset length"
1952 ui.write(" rev flag offset length"
1946 " size " + basehdr + " link p1 p2"
1953 " size " + basehdr + " link p1 p2"
1947 " nodeid\n")
1954 " nodeid\n")
1948
1955
1949 for i in r:
1956 for i in r:
1950 node = r.node(i)
1957 node = r.node(i)
1951 if generaldelta:
1958 if generaldelta:
1952 base = r.deltaparent(i)
1959 base = r.deltaparent(i)
1953 else:
1960 else:
1954 base = r.chainbase(i)
1961 base = r.chainbase(i)
1955 if format == 0:
1962 if format == 0:
1956 try:
1963 try:
1957 pp = r.parents(node)
1964 pp = r.parents(node)
1958 except Exception:
1965 except Exception:
1959 pp = [nullid, nullid]
1966 pp = [nullid, nullid]
1960 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1967 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1961 i, r.start(i), r.length(i), base, r.linkrev(i),
1968 i, r.start(i), r.length(i), base, r.linkrev(i),
1962 short(node), short(pp[0]), short(pp[1])))
1969 short(node), short(pp[0]), short(pp[1])))
1963 elif format == 1:
1970 elif format == 1:
1964 pr = r.parentrevs(i)
1971 pr = r.parentrevs(i)
1965 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1972 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1966 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1973 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1967 base, r.linkrev(i), pr[0], pr[1], short(node)))
1974 base, r.linkrev(i), pr[0], pr[1], short(node)))
1968
1975
1969 @command('debugindexdot', [], _('FILE'))
1976 @command('debugindexdot', [], _('FILE'))
1970 def debugindexdot(ui, repo, file_):
1977 def debugindexdot(ui, repo, file_):
1971 """dump an index DAG as a graphviz dot file"""
1978 """dump an index DAG as a graphviz dot file"""
1972 r = None
1979 r = None
1973 if repo:
1980 if repo:
1974 filelog = repo.file(file_)
1981 filelog = repo.file(file_)
1975 if len(filelog):
1982 if len(filelog):
1976 r = filelog
1983 r = filelog
1977 if not r:
1984 if not r:
1978 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1985 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1979 ui.write("digraph G {\n")
1986 ui.write("digraph G {\n")
1980 for i in r:
1987 for i in r:
1981 node = r.node(i)
1988 node = r.node(i)
1982 pp = r.parents(node)
1989 pp = r.parents(node)
1983 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1990 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1984 if pp[1] != nullid:
1991 if pp[1] != nullid:
1985 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1992 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1986 ui.write("}\n")
1993 ui.write("}\n")
1987
1994
1988 @command('debuginstall', [], '')
1995 @command('debuginstall', [], '')
1989 def debuginstall(ui):
1996 def debuginstall(ui):
1990 '''test Mercurial installation
1997 '''test Mercurial installation
1991
1998
1992 Returns 0 on success.
1999 Returns 0 on success.
1993 '''
2000 '''
1994
2001
1995 def writetemp(contents):
2002 def writetemp(contents):
1996 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2003 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1997 f = os.fdopen(fd, "wb")
2004 f = os.fdopen(fd, "wb")
1998 f.write(contents)
2005 f.write(contents)
1999 f.close()
2006 f.close()
2000 return name
2007 return name
2001
2008
2002 problems = 0
2009 problems = 0
2003
2010
2004 # encoding
2011 # encoding
2005 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2012 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2006 try:
2013 try:
2007 encoding.fromlocal("test")
2014 encoding.fromlocal("test")
2008 except util.Abort, inst:
2015 except util.Abort, inst:
2009 ui.write(" %s\n" % inst)
2016 ui.write(" %s\n" % inst)
2010 ui.write(_(" (check that your locale is properly set)\n"))
2017 ui.write(_(" (check that your locale is properly set)\n"))
2011 problems += 1
2018 problems += 1
2012
2019
2013 # Python lib
2020 # Python lib
2014 ui.status(_("checking Python lib (%s)...\n")
2021 ui.status(_("checking Python lib (%s)...\n")
2015 % os.path.dirname(os.__file__))
2022 % os.path.dirname(os.__file__))
2016
2023
2017 # compiled modules
2024 # compiled modules
2018 ui.status(_("checking installed modules (%s)...\n")
2025 ui.status(_("checking installed modules (%s)...\n")
2019 % os.path.dirname(__file__))
2026 % os.path.dirname(__file__))
2020 try:
2027 try:
2021 import bdiff, mpatch, base85, osutil
2028 import bdiff, mpatch, base85, osutil
2022 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2029 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2023 except Exception, inst:
2030 except Exception, inst:
2024 ui.write(" %s\n" % inst)
2031 ui.write(" %s\n" % inst)
2025 ui.write(_(" One or more extensions could not be found"))
2032 ui.write(_(" One or more extensions could not be found"))
2026 ui.write(_(" (check that you compiled the extensions)\n"))
2033 ui.write(_(" (check that you compiled the extensions)\n"))
2027 problems += 1
2034 problems += 1
2028
2035
2029 # templates
2036 # templates
2030 import templater
2037 import templater
2031 p = templater.templatepath()
2038 p = templater.templatepath()
2032 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2039 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2033 try:
2040 try:
2034 templater.templater(templater.templatepath("map-cmdline.default"))
2041 templater.templater(templater.templatepath("map-cmdline.default"))
2035 except Exception, inst:
2042 except Exception, inst:
2036 ui.write(" %s\n" % inst)
2043 ui.write(" %s\n" % inst)
2037 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2044 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2038 problems += 1
2045 problems += 1
2039
2046
2040 # editor
2047 # editor
2041 ui.status(_("checking commit editor...\n"))
2048 ui.status(_("checking commit editor...\n"))
2042 editor = ui.geteditor()
2049 editor = ui.geteditor()
2043 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2050 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2044 if not cmdpath:
2051 if not cmdpath:
2045 if editor == 'vi':
2052 if editor == 'vi':
2046 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2053 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2047 ui.write(_(" (specify a commit editor in your configuration"
2054 ui.write(_(" (specify a commit editor in your configuration"
2048 " file)\n"))
2055 " file)\n"))
2049 else:
2056 else:
2050 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2057 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2051 ui.write(_(" (specify a commit editor in your configuration"
2058 ui.write(_(" (specify a commit editor in your configuration"
2052 " file)\n"))
2059 " file)\n"))
2053 problems += 1
2060 problems += 1
2054
2061
2055 # check username
2062 # check username
2056 ui.status(_("checking username...\n"))
2063 ui.status(_("checking username...\n"))
2057 try:
2064 try:
2058 ui.username()
2065 ui.username()
2059 except util.Abort, e:
2066 except util.Abort, e:
2060 ui.write(" %s\n" % e)
2067 ui.write(" %s\n" % e)
2061 ui.write(_(" (specify a username in your configuration file)\n"))
2068 ui.write(_(" (specify a username in your configuration file)\n"))
2062 problems += 1
2069 problems += 1
2063
2070
2064 if not problems:
2071 if not problems:
2065 ui.status(_("no problems detected\n"))
2072 ui.status(_("no problems detected\n"))
2066 else:
2073 else:
2067 ui.write(_("%s problems detected,"
2074 ui.write(_("%s problems detected,"
2068 " please check your install!\n") % problems)
2075 " please check your install!\n") % problems)
2069
2076
2070 return problems
2077 return problems
2071
2078
2072 @command('debugknown', [], _('REPO ID...'))
2079 @command('debugknown', [], _('REPO ID...'))
2073 def debugknown(ui, repopath, *ids, **opts):
2080 def debugknown(ui, repopath, *ids, **opts):
2074 """test whether node ids are known to a repo
2081 """test whether node ids are known to a repo
2075
2082
2076 Every ID must be a full-length hex node id string. Returns a list of 0s
2083 Every ID must be a full-length hex node id string. Returns a list of 0s
2077 and 1s indicating unknown/known.
2084 and 1s indicating unknown/known.
2078 """
2085 """
2079 repo = hg.peer(ui, opts, repopath)
2086 repo = hg.peer(ui, opts, repopath)
2080 if not repo.capable('known'):
2087 if not repo.capable('known'):
2081 raise util.Abort("known() not supported by target repository")
2088 raise util.Abort("known() not supported by target repository")
2082 flags = repo.known([bin(s) for s in ids])
2089 flags = repo.known([bin(s) for s in ids])
2083 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2090 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2084
2091
2085 @command('debugobsolete', [] + commitopts2,
2092 @command('debugobsolete', [] + commitopts2,
2086 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2093 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2087 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2094 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2088 """create arbitrary obsolete marker"""
2095 """create arbitrary obsolete marker"""
2089 def parsenodeid(s):
2096 def parsenodeid(s):
2090 try:
2097 try:
2091 # We do not use revsingle/revrange functions here to accept
2098 # We do not use revsingle/revrange functions here to accept
2092 # arbitrary node identifiers, possibly not present in the
2099 # arbitrary node identifiers, possibly not present in the
2093 # local repository.
2100 # local repository.
2094 n = bin(s)
2101 n = bin(s)
2095 if len(n) != len(nullid):
2102 if len(n) != len(nullid):
2096 raise TypeError()
2103 raise TypeError()
2097 return n
2104 return n
2098 except TypeError:
2105 except TypeError:
2099 raise util.Abort('changeset references must be full hexadecimal '
2106 raise util.Abort('changeset references must be full hexadecimal '
2100 'node identifiers')
2107 'node identifiers')
2101
2108
2102 if precursor is not None:
2109 if precursor is not None:
2103 metadata = {}
2110 metadata = {}
2104 if 'date' in opts:
2111 if 'date' in opts:
2105 metadata['date'] = opts['date']
2112 metadata['date'] = opts['date']
2106 metadata['user'] = opts['user'] or ui.username()
2113 metadata['user'] = opts['user'] or ui.username()
2107 succs = tuple(parsenodeid(succ) for succ in successors)
2114 succs = tuple(parsenodeid(succ) for succ in successors)
2108 l = repo.lock()
2115 l = repo.lock()
2109 try:
2116 try:
2110 tr = repo.transaction('debugobsolete')
2117 tr = repo.transaction('debugobsolete')
2111 try:
2118 try:
2112 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2119 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2113 metadata)
2120 metadata)
2114 tr.close()
2121 tr.close()
2115 finally:
2122 finally:
2116 tr.release()
2123 tr.release()
2117 finally:
2124 finally:
2118 l.release()
2125 l.release()
2119 else:
2126 else:
2120 for m in obsolete.allmarkers(repo):
2127 for m in obsolete.allmarkers(repo):
2121 ui.write(hex(m.precnode()))
2128 ui.write(hex(m.precnode()))
2122 for repl in m.succnodes():
2129 for repl in m.succnodes():
2123 ui.write(' ')
2130 ui.write(' ')
2124 ui.write(hex(repl))
2131 ui.write(hex(repl))
2125 ui.write(' %X ' % m._data[2])
2132 ui.write(' %X ' % m._data[2])
2126 ui.write(m.metadata())
2133 ui.write(m.metadata())
2127 ui.write('\n')
2134 ui.write('\n')
2128
2135
2129 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2136 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2130 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2137 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2131 '''access the pushkey key/value protocol
2138 '''access the pushkey key/value protocol
2132
2139
2133 With two args, list the keys in the given namespace.
2140 With two args, list the keys in the given namespace.
2134
2141
2135 With five args, set a key to new if it currently is set to old.
2142 With five args, set a key to new if it currently is set to old.
2136 Reports success or failure.
2143 Reports success or failure.
2137 '''
2144 '''
2138
2145
2139 target = hg.peer(ui, {}, repopath)
2146 target = hg.peer(ui, {}, repopath)
2140 if keyinfo:
2147 if keyinfo:
2141 key, old, new = keyinfo
2148 key, old, new = keyinfo
2142 r = target.pushkey(namespace, key, old, new)
2149 r = target.pushkey(namespace, key, old, new)
2143 ui.status(str(r) + '\n')
2150 ui.status(str(r) + '\n')
2144 return not r
2151 return not r
2145 else:
2152 else:
2146 for k, v in target.listkeys(namespace).iteritems():
2153 for k, v in target.listkeys(namespace).iteritems():
2147 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2154 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2148 v.encode('string-escape')))
2155 v.encode('string-escape')))
2149
2156
2150 @command('debugpvec', [], _('A B'))
2157 @command('debugpvec', [], _('A B'))
2151 def debugpvec(ui, repo, a, b=None):
2158 def debugpvec(ui, repo, a, b=None):
2152 ca = scmutil.revsingle(repo, a)
2159 ca = scmutil.revsingle(repo, a)
2153 cb = scmutil.revsingle(repo, b)
2160 cb = scmutil.revsingle(repo, b)
2154 pa = pvec.ctxpvec(ca)
2161 pa = pvec.ctxpvec(ca)
2155 pb = pvec.ctxpvec(cb)
2162 pb = pvec.ctxpvec(cb)
2156 if pa == pb:
2163 if pa == pb:
2157 rel = "="
2164 rel = "="
2158 elif pa > pb:
2165 elif pa > pb:
2159 rel = ">"
2166 rel = ">"
2160 elif pa < pb:
2167 elif pa < pb:
2161 rel = "<"
2168 rel = "<"
2162 elif pa | pb:
2169 elif pa | pb:
2163 rel = "|"
2170 rel = "|"
2164 ui.write(_("a: %s\n") % pa)
2171 ui.write(_("a: %s\n") % pa)
2165 ui.write(_("b: %s\n") % pb)
2172 ui.write(_("b: %s\n") % pb)
2166 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2173 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2167 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2174 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2168 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2175 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2169 pa.distance(pb), rel))
2176 pa.distance(pb), rel))
2170
2177
2171 @command('debugrebuildstate',
2178 @command('debugrebuildstate',
2172 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2179 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2173 _('[-r REV] [REV]'))
2180 _('[-r REV] [REV]'))
2174 def debugrebuildstate(ui, repo, rev="tip"):
2181 def debugrebuildstate(ui, repo, rev="tip"):
2175 """rebuild the dirstate as it would look like for the given revision"""
2182 """rebuild the dirstate as it would look like for the given revision"""
2176 ctx = scmutil.revsingle(repo, rev)
2183 ctx = scmutil.revsingle(repo, rev)
2177 wlock = repo.wlock()
2184 wlock = repo.wlock()
2178 try:
2185 try:
2179 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2186 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2180 finally:
2187 finally:
2181 wlock.release()
2188 wlock.release()
2182
2189
2183 @command('debugrename',
2190 @command('debugrename',
2184 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2191 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2185 _('[-r REV] FILE'))
2192 _('[-r REV] FILE'))
2186 def debugrename(ui, repo, file1, *pats, **opts):
2193 def debugrename(ui, repo, file1, *pats, **opts):
2187 """dump rename information"""
2194 """dump rename information"""
2188
2195
2189 ctx = scmutil.revsingle(repo, opts.get('rev'))
2196 ctx = scmutil.revsingle(repo, opts.get('rev'))
2190 m = scmutil.match(ctx, (file1,) + pats, opts)
2197 m = scmutil.match(ctx, (file1,) + pats, opts)
2191 for abs in ctx.walk(m):
2198 for abs in ctx.walk(m):
2192 fctx = ctx[abs]
2199 fctx = ctx[abs]
2193 o = fctx.filelog().renamed(fctx.filenode())
2200 o = fctx.filelog().renamed(fctx.filenode())
2194 rel = m.rel(abs)
2201 rel = m.rel(abs)
2195 if o:
2202 if o:
2196 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2203 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2197 else:
2204 else:
2198 ui.write(_("%s not renamed\n") % rel)
2205 ui.write(_("%s not renamed\n") % rel)
2199
2206
2200 @command('debugrevlog',
2207 @command('debugrevlog',
2201 [('c', 'changelog', False, _('open changelog')),
2208 [('c', 'changelog', False, _('open changelog')),
2202 ('m', 'manifest', False, _('open manifest')),
2209 ('m', 'manifest', False, _('open manifest')),
2203 ('d', 'dump', False, _('dump index data'))],
2210 ('d', 'dump', False, _('dump index data'))],
2204 _('-c|-m|FILE'))
2211 _('-c|-m|FILE'))
2205 def debugrevlog(ui, repo, file_ = None, **opts):
2212 def debugrevlog(ui, repo, file_ = None, **opts):
2206 """show data and statistics about a revlog"""
2213 """show data and statistics about a revlog"""
2207 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2214 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2208
2215
2209 if opts.get("dump"):
2216 if opts.get("dump"):
2210 numrevs = len(r)
2217 numrevs = len(r)
2211 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2218 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2212 " rawsize totalsize compression heads\n")
2219 " rawsize totalsize compression heads\n")
2213 ts = 0
2220 ts = 0
2214 heads = set()
2221 heads = set()
2215 for rev in xrange(numrevs):
2222 for rev in xrange(numrevs):
2216 dbase = r.deltaparent(rev)
2223 dbase = r.deltaparent(rev)
2217 if dbase == -1:
2224 if dbase == -1:
2218 dbase = rev
2225 dbase = rev
2219 cbase = r.chainbase(rev)
2226 cbase = r.chainbase(rev)
2220 p1, p2 = r.parentrevs(rev)
2227 p1, p2 = r.parentrevs(rev)
2221 rs = r.rawsize(rev)
2228 rs = r.rawsize(rev)
2222 ts = ts + rs
2229 ts = ts + rs
2223 heads -= set(r.parentrevs(rev))
2230 heads -= set(r.parentrevs(rev))
2224 heads.add(rev)
2231 heads.add(rev)
2225 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2232 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2226 (rev, p1, p2, r.start(rev), r.end(rev),
2233 (rev, p1, p2, r.start(rev), r.end(rev),
2227 r.start(dbase), r.start(cbase),
2234 r.start(dbase), r.start(cbase),
2228 r.start(p1), r.start(p2),
2235 r.start(p1), r.start(p2),
2229 rs, ts, ts / r.end(rev), len(heads)))
2236 rs, ts, ts / r.end(rev), len(heads)))
2230 return 0
2237 return 0
2231
2238
2232 v = r.version
2239 v = r.version
2233 format = v & 0xFFFF
2240 format = v & 0xFFFF
2234 flags = []
2241 flags = []
2235 gdelta = False
2242 gdelta = False
2236 if v & revlog.REVLOGNGINLINEDATA:
2243 if v & revlog.REVLOGNGINLINEDATA:
2237 flags.append('inline')
2244 flags.append('inline')
2238 if v & revlog.REVLOGGENERALDELTA:
2245 if v & revlog.REVLOGGENERALDELTA:
2239 gdelta = True
2246 gdelta = True
2240 flags.append('generaldelta')
2247 flags.append('generaldelta')
2241 if not flags:
2248 if not flags:
2242 flags = ['(none)']
2249 flags = ['(none)']
2243
2250
2244 nummerges = 0
2251 nummerges = 0
2245 numfull = 0
2252 numfull = 0
2246 numprev = 0
2253 numprev = 0
2247 nump1 = 0
2254 nump1 = 0
2248 nump2 = 0
2255 nump2 = 0
2249 numother = 0
2256 numother = 0
2250 nump1prev = 0
2257 nump1prev = 0
2251 nump2prev = 0
2258 nump2prev = 0
2252 chainlengths = []
2259 chainlengths = []
2253
2260
2254 datasize = [None, 0, 0L]
2261 datasize = [None, 0, 0L]
2255 fullsize = [None, 0, 0L]
2262 fullsize = [None, 0, 0L]
2256 deltasize = [None, 0, 0L]
2263 deltasize = [None, 0, 0L]
2257
2264
2258 def addsize(size, l):
2265 def addsize(size, l):
2259 if l[0] is None or size < l[0]:
2266 if l[0] is None or size < l[0]:
2260 l[0] = size
2267 l[0] = size
2261 if size > l[1]:
2268 if size > l[1]:
2262 l[1] = size
2269 l[1] = size
2263 l[2] += size
2270 l[2] += size
2264
2271
2265 numrevs = len(r)
2272 numrevs = len(r)
2266 for rev in xrange(numrevs):
2273 for rev in xrange(numrevs):
2267 p1, p2 = r.parentrevs(rev)
2274 p1, p2 = r.parentrevs(rev)
2268 delta = r.deltaparent(rev)
2275 delta = r.deltaparent(rev)
2269 if format > 0:
2276 if format > 0:
2270 addsize(r.rawsize(rev), datasize)
2277 addsize(r.rawsize(rev), datasize)
2271 if p2 != nullrev:
2278 if p2 != nullrev:
2272 nummerges += 1
2279 nummerges += 1
2273 size = r.length(rev)
2280 size = r.length(rev)
2274 if delta == nullrev:
2281 if delta == nullrev:
2275 chainlengths.append(0)
2282 chainlengths.append(0)
2276 numfull += 1
2283 numfull += 1
2277 addsize(size, fullsize)
2284 addsize(size, fullsize)
2278 else:
2285 else:
2279 chainlengths.append(chainlengths[delta] + 1)
2286 chainlengths.append(chainlengths[delta] + 1)
2280 addsize(size, deltasize)
2287 addsize(size, deltasize)
2281 if delta == rev - 1:
2288 if delta == rev - 1:
2282 numprev += 1
2289 numprev += 1
2283 if delta == p1:
2290 if delta == p1:
2284 nump1prev += 1
2291 nump1prev += 1
2285 elif delta == p2:
2292 elif delta == p2:
2286 nump2prev += 1
2293 nump2prev += 1
2287 elif delta == p1:
2294 elif delta == p1:
2288 nump1 += 1
2295 nump1 += 1
2289 elif delta == p2:
2296 elif delta == p2:
2290 nump2 += 1
2297 nump2 += 1
2291 elif delta != nullrev:
2298 elif delta != nullrev:
2292 numother += 1
2299 numother += 1
2293
2300
2294 # Adjust size min value for empty cases
2301 # Adjust size min value for empty cases
2295 for size in (datasize, fullsize, deltasize):
2302 for size in (datasize, fullsize, deltasize):
2296 if size[0] is None:
2303 if size[0] is None:
2297 size[0] = 0
2304 size[0] = 0
2298
2305
2299 numdeltas = numrevs - numfull
2306 numdeltas = numrevs - numfull
2300 numoprev = numprev - nump1prev - nump2prev
2307 numoprev = numprev - nump1prev - nump2prev
2301 totalrawsize = datasize[2]
2308 totalrawsize = datasize[2]
2302 datasize[2] /= numrevs
2309 datasize[2] /= numrevs
2303 fulltotal = fullsize[2]
2310 fulltotal = fullsize[2]
2304 fullsize[2] /= numfull
2311 fullsize[2] /= numfull
2305 deltatotal = deltasize[2]
2312 deltatotal = deltasize[2]
2306 if numrevs - numfull > 0:
2313 if numrevs - numfull > 0:
2307 deltasize[2] /= numrevs - numfull
2314 deltasize[2] /= numrevs - numfull
2308 totalsize = fulltotal + deltatotal
2315 totalsize = fulltotal + deltatotal
2309 avgchainlen = sum(chainlengths) / numrevs
2316 avgchainlen = sum(chainlengths) / numrevs
2310 compratio = totalrawsize / totalsize
2317 compratio = totalrawsize / totalsize
2311
2318
2312 basedfmtstr = '%%%dd\n'
2319 basedfmtstr = '%%%dd\n'
2313 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2320 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2314
2321
2315 def dfmtstr(max):
2322 def dfmtstr(max):
2316 return basedfmtstr % len(str(max))
2323 return basedfmtstr % len(str(max))
2317 def pcfmtstr(max, padding=0):
2324 def pcfmtstr(max, padding=0):
2318 return basepcfmtstr % (len(str(max)), ' ' * padding)
2325 return basepcfmtstr % (len(str(max)), ' ' * padding)
2319
2326
2320 def pcfmt(value, total):
2327 def pcfmt(value, total):
2321 return (value, 100 * float(value) / total)
2328 return (value, 100 * float(value) / total)
2322
2329
2323 ui.write('format : %d\n' % format)
2330 ui.write('format : %d\n' % format)
2324 ui.write('flags : %s\n' % ', '.join(flags))
2331 ui.write('flags : %s\n' % ', '.join(flags))
2325
2332
2326 ui.write('\n')
2333 ui.write('\n')
2327 fmt = pcfmtstr(totalsize)
2334 fmt = pcfmtstr(totalsize)
2328 fmt2 = dfmtstr(totalsize)
2335 fmt2 = dfmtstr(totalsize)
2329 ui.write('revisions : ' + fmt2 % numrevs)
2336 ui.write('revisions : ' + fmt2 % numrevs)
2330 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2337 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2331 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2338 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2332 ui.write('revisions : ' + fmt2 % numrevs)
2339 ui.write('revisions : ' + fmt2 % numrevs)
2333 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2340 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2334 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2341 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2335 ui.write('revision size : ' + fmt2 % totalsize)
2342 ui.write('revision size : ' + fmt2 % totalsize)
2336 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2343 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2337 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2344 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2338
2345
2339 ui.write('\n')
2346 ui.write('\n')
2340 fmt = dfmtstr(max(avgchainlen, compratio))
2347 fmt = dfmtstr(max(avgchainlen, compratio))
2341 ui.write('avg chain length : ' + fmt % avgchainlen)
2348 ui.write('avg chain length : ' + fmt % avgchainlen)
2342 ui.write('compression ratio : ' + fmt % compratio)
2349 ui.write('compression ratio : ' + fmt % compratio)
2343
2350
2344 if format > 0:
2351 if format > 0:
2345 ui.write('\n')
2352 ui.write('\n')
2346 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2353 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2347 % tuple(datasize))
2354 % tuple(datasize))
2348 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2355 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2349 % tuple(fullsize))
2356 % tuple(fullsize))
2350 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2357 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2351 % tuple(deltasize))
2358 % tuple(deltasize))
2352
2359
2353 if numdeltas > 0:
2360 if numdeltas > 0:
2354 ui.write('\n')
2361 ui.write('\n')
2355 fmt = pcfmtstr(numdeltas)
2362 fmt = pcfmtstr(numdeltas)
2356 fmt2 = pcfmtstr(numdeltas, 4)
2363 fmt2 = pcfmtstr(numdeltas, 4)
2357 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2364 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2358 if numprev > 0:
2365 if numprev > 0:
2359 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2366 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2360 numprev))
2367 numprev))
2361 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2368 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2362 numprev))
2369 numprev))
2363 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2370 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2364 numprev))
2371 numprev))
2365 if gdelta:
2372 if gdelta:
2366 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2373 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2367 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2374 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2368 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2375 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2369 numdeltas))
2376 numdeltas))
2370
2377
2371 @command('debugrevspec', [], ('REVSPEC'))
2378 @command('debugrevspec', [], ('REVSPEC'))
2372 def debugrevspec(ui, repo, expr):
2379 def debugrevspec(ui, repo, expr):
2373 """parse and apply a revision specification
2380 """parse and apply a revision specification
2374
2381
2375 Use --verbose to print the parsed tree before and after aliases
2382 Use --verbose to print the parsed tree before and after aliases
2376 expansion.
2383 expansion.
2377 """
2384 """
2378 if ui.verbose:
2385 if ui.verbose:
2379 tree = revset.parse(expr)[0]
2386 tree = revset.parse(expr)[0]
2380 ui.note(revset.prettyformat(tree), "\n")
2387 ui.note(revset.prettyformat(tree), "\n")
2381 newtree = revset.findaliases(ui, tree)
2388 newtree = revset.findaliases(ui, tree)
2382 if newtree != tree:
2389 if newtree != tree:
2383 ui.note(revset.prettyformat(newtree), "\n")
2390 ui.note(revset.prettyformat(newtree), "\n")
2384 func = revset.match(ui, expr)
2391 func = revset.match(ui, expr)
2385 for c in func(repo, range(len(repo))):
2392 for c in func(repo, range(len(repo))):
2386 ui.write("%s\n" % c)
2393 ui.write("%s\n" % c)
2387
2394
2388 @command('debugsetparents', [], _('REV1 [REV2]'))
2395 @command('debugsetparents', [], _('REV1 [REV2]'))
2389 def debugsetparents(ui, repo, rev1, rev2=None):
2396 def debugsetparents(ui, repo, rev1, rev2=None):
2390 """manually set the parents of the current working directory
2397 """manually set the parents of the current working directory
2391
2398
2392 This is useful for writing repository conversion tools, but should
2399 This is useful for writing repository conversion tools, but should
2393 be used with care.
2400 be used with care.
2394
2401
2395 Returns 0 on success.
2402 Returns 0 on success.
2396 """
2403 """
2397
2404
2398 r1 = scmutil.revsingle(repo, rev1).node()
2405 r1 = scmutil.revsingle(repo, rev1).node()
2399 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2406 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2400
2407
2401 wlock = repo.wlock()
2408 wlock = repo.wlock()
2402 try:
2409 try:
2403 repo.setparents(r1, r2)
2410 repo.setparents(r1, r2)
2404 finally:
2411 finally:
2405 wlock.release()
2412 wlock.release()
2406
2413
2407 @command('debugstate',
2414 @command('debugstate',
2408 [('', 'nodates', None, _('do not display the saved mtime')),
2415 [('', 'nodates', None, _('do not display the saved mtime')),
2409 ('', 'datesort', None, _('sort by saved mtime'))],
2416 ('', 'datesort', None, _('sort by saved mtime'))],
2410 _('[OPTION]...'))
2417 _('[OPTION]...'))
2411 def debugstate(ui, repo, nodates=None, datesort=None):
2418 def debugstate(ui, repo, nodates=None, datesort=None):
2412 """show the contents of the current dirstate"""
2419 """show the contents of the current dirstate"""
2413 timestr = ""
2420 timestr = ""
2414 showdate = not nodates
2421 showdate = not nodates
2415 if datesort:
2422 if datesort:
2416 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2423 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2417 else:
2424 else:
2418 keyfunc = None # sort by filename
2425 keyfunc = None # sort by filename
2419 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2426 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2420 if showdate:
2427 if showdate:
2421 if ent[3] == -1:
2428 if ent[3] == -1:
2422 # Pad or slice to locale representation
2429 # Pad or slice to locale representation
2423 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2430 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2424 time.localtime(0)))
2431 time.localtime(0)))
2425 timestr = 'unset'
2432 timestr = 'unset'
2426 timestr = (timestr[:locale_len] +
2433 timestr = (timestr[:locale_len] +
2427 ' ' * (locale_len - len(timestr)))
2434 ' ' * (locale_len - len(timestr)))
2428 else:
2435 else:
2429 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2436 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2430 time.localtime(ent[3]))
2437 time.localtime(ent[3]))
2431 if ent[1] & 020000:
2438 if ent[1] & 020000:
2432 mode = 'lnk'
2439 mode = 'lnk'
2433 else:
2440 else:
2434 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2441 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2435 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2442 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2436 for f in repo.dirstate.copies():
2443 for f in repo.dirstate.copies():
2437 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2444 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2438
2445
2439 @command('debugsub',
2446 @command('debugsub',
2440 [('r', 'rev', '',
2447 [('r', 'rev', '',
2441 _('revision to check'), _('REV'))],
2448 _('revision to check'), _('REV'))],
2442 _('[-r REV] [REV]'))
2449 _('[-r REV] [REV]'))
2443 def debugsub(ui, repo, rev=None):
2450 def debugsub(ui, repo, rev=None):
2444 ctx = scmutil.revsingle(repo, rev, None)
2451 ctx = scmutil.revsingle(repo, rev, None)
2445 for k, v in sorted(ctx.substate.items()):
2452 for k, v in sorted(ctx.substate.items()):
2446 ui.write('path %s\n' % k)
2453 ui.write('path %s\n' % k)
2447 ui.write(' source %s\n' % v[0])
2454 ui.write(' source %s\n' % v[0])
2448 ui.write(' revision %s\n' % v[1])
2455 ui.write(' revision %s\n' % v[1])
2449
2456
2450 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2457 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2451 def debugwalk(ui, repo, *pats, **opts):
2458 def debugwalk(ui, repo, *pats, **opts):
2452 """show how files match on given patterns"""
2459 """show how files match on given patterns"""
2453 m = scmutil.match(repo[None], pats, opts)
2460 m = scmutil.match(repo[None], pats, opts)
2454 items = list(repo.walk(m))
2461 items = list(repo.walk(m))
2455 if not items:
2462 if not items:
2456 return
2463 return
2457 f = lambda fn: fn
2464 f = lambda fn: fn
2458 if ui.configbool('ui', 'slash') and os.sep != '/':
2465 if ui.configbool('ui', 'slash') and os.sep != '/':
2459 f = lambda fn: util.normpath(fn)
2466 f = lambda fn: util.normpath(fn)
2460 fmt = 'f %%-%ds %%-%ds %%s' % (
2467 fmt = 'f %%-%ds %%-%ds %%s' % (
2461 max([len(abs) for abs in items]),
2468 max([len(abs) for abs in items]),
2462 max([len(m.rel(abs)) for abs in items]))
2469 max([len(m.rel(abs)) for abs in items]))
2463 for abs in items:
2470 for abs in items:
2464 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2471 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2465 ui.write("%s\n" % line.rstrip())
2472 ui.write("%s\n" % line.rstrip())
2466
2473
2467 @command('debugwireargs',
2474 @command('debugwireargs',
2468 [('', 'three', '', 'three'),
2475 [('', 'three', '', 'three'),
2469 ('', 'four', '', 'four'),
2476 ('', 'four', '', 'four'),
2470 ('', 'five', '', 'five'),
2477 ('', 'five', '', 'five'),
2471 ] + remoteopts,
2478 ] + remoteopts,
2472 _('REPO [OPTIONS]... [ONE [TWO]]'))
2479 _('REPO [OPTIONS]... [ONE [TWO]]'))
2473 def debugwireargs(ui, repopath, *vals, **opts):
2480 def debugwireargs(ui, repopath, *vals, **opts):
2474 repo = hg.peer(ui, opts, repopath)
2481 repo = hg.peer(ui, opts, repopath)
2475 for opt in remoteopts:
2482 for opt in remoteopts:
2476 del opts[opt[1]]
2483 del opts[opt[1]]
2477 args = {}
2484 args = {}
2478 for k, v in opts.iteritems():
2485 for k, v in opts.iteritems():
2479 if v:
2486 if v:
2480 args[k] = v
2487 args[k] = v
2481 # run twice to check that we don't mess up the stream for the next command
2488 # run twice to check that we don't mess up the stream for the next command
2482 res1 = repo.debugwireargs(*vals, **args)
2489 res1 = repo.debugwireargs(*vals, **args)
2483 res2 = repo.debugwireargs(*vals, **args)
2490 res2 = repo.debugwireargs(*vals, **args)
2484 ui.write("%s\n" % res1)
2491 ui.write("%s\n" % res1)
2485 if res1 != res2:
2492 if res1 != res2:
2486 ui.warn("%s\n" % res2)
2493 ui.warn("%s\n" % res2)
2487
2494
2488 @command('^diff',
2495 @command('^diff',
2489 [('r', 'rev', [], _('revision'), _('REV')),
2496 [('r', 'rev', [], _('revision'), _('REV')),
2490 ('c', 'change', '', _('change made by revision'), _('REV'))
2497 ('c', 'change', '', _('change made by revision'), _('REV'))
2491 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2498 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2492 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2499 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2493 def diff(ui, repo, *pats, **opts):
2500 def diff(ui, repo, *pats, **opts):
2494 """diff repository (or selected files)
2501 """diff repository (or selected files)
2495
2502
2496 Show differences between revisions for the specified files.
2503 Show differences between revisions for the specified files.
2497
2504
2498 Differences between files are shown using the unified diff format.
2505 Differences between files are shown using the unified diff format.
2499
2506
2500 .. note::
2507 .. note::
2501 diff may generate unexpected results for merges, as it will
2508 diff may generate unexpected results for merges, as it will
2502 default to comparing against the working directory's first
2509 default to comparing against the working directory's first
2503 parent changeset if no revisions are specified.
2510 parent changeset if no revisions are specified.
2504
2511
2505 When two revision arguments are given, then changes are shown
2512 When two revision arguments are given, then changes are shown
2506 between those revisions. If only one revision is specified then
2513 between those revisions. If only one revision is specified then
2507 that revision is compared to the working directory, and, when no
2514 that revision is compared to the working directory, and, when no
2508 revisions are specified, the working directory files are compared
2515 revisions are specified, the working directory files are compared
2509 to its parent.
2516 to its parent.
2510
2517
2511 Alternatively you can specify -c/--change with a revision to see
2518 Alternatively you can specify -c/--change with a revision to see
2512 the changes in that changeset relative to its first parent.
2519 the changes in that changeset relative to its first parent.
2513
2520
2514 Without the -a/--text option, diff will avoid generating diffs of
2521 Without the -a/--text option, diff will avoid generating diffs of
2515 files it detects as binary. With -a, diff will generate a diff
2522 files it detects as binary. With -a, diff will generate a diff
2516 anyway, probably with undesirable results.
2523 anyway, probably with undesirable results.
2517
2524
2518 Use the -g/--git option to generate diffs in the git extended diff
2525 Use the -g/--git option to generate diffs in the git extended diff
2519 format. For more information, read :hg:`help diffs`.
2526 format. For more information, read :hg:`help diffs`.
2520
2527
2521 .. container:: verbose
2528 .. container:: verbose
2522
2529
2523 Examples:
2530 Examples:
2524
2531
2525 - compare a file in the current working directory to its parent::
2532 - compare a file in the current working directory to its parent::
2526
2533
2527 hg diff foo.c
2534 hg diff foo.c
2528
2535
2529 - compare two historical versions of a directory, with rename info::
2536 - compare two historical versions of a directory, with rename info::
2530
2537
2531 hg diff --git -r 1.0:1.2 lib/
2538 hg diff --git -r 1.0:1.2 lib/
2532
2539
2533 - get change stats relative to the last change on some date::
2540 - get change stats relative to the last change on some date::
2534
2541
2535 hg diff --stat -r "date('may 2')"
2542 hg diff --stat -r "date('may 2')"
2536
2543
2537 - diff all newly-added files that contain a keyword::
2544 - diff all newly-added files that contain a keyword::
2538
2545
2539 hg diff "set:added() and grep(GNU)"
2546 hg diff "set:added() and grep(GNU)"
2540
2547
2541 - compare a revision and its parents::
2548 - compare a revision and its parents::
2542
2549
2543 hg diff -c 9353 # compare against first parent
2550 hg diff -c 9353 # compare against first parent
2544 hg diff -r 9353^:9353 # same using revset syntax
2551 hg diff -r 9353^:9353 # same using revset syntax
2545 hg diff -r 9353^2:9353 # compare against the second parent
2552 hg diff -r 9353^2:9353 # compare against the second parent
2546
2553
2547 Returns 0 on success.
2554 Returns 0 on success.
2548 """
2555 """
2549
2556
2550 revs = opts.get('rev')
2557 revs = opts.get('rev')
2551 change = opts.get('change')
2558 change = opts.get('change')
2552 stat = opts.get('stat')
2559 stat = opts.get('stat')
2553 reverse = opts.get('reverse')
2560 reverse = opts.get('reverse')
2554
2561
2555 if revs and change:
2562 if revs and change:
2556 msg = _('cannot specify --rev and --change at the same time')
2563 msg = _('cannot specify --rev and --change at the same time')
2557 raise util.Abort(msg)
2564 raise util.Abort(msg)
2558 elif change:
2565 elif change:
2559 node2 = scmutil.revsingle(repo, change, None).node()
2566 node2 = scmutil.revsingle(repo, change, None).node()
2560 node1 = repo[node2].p1().node()
2567 node1 = repo[node2].p1().node()
2561 else:
2568 else:
2562 node1, node2 = scmutil.revpair(repo, revs)
2569 node1, node2 = scmutil.revpair(repo, revs)
2563
2570
2564 if reverse:
2571 if reverse:
2565 node1, node2 = node2, node1
2572 node1, node2 = node2, node1
2566
2573
2567 diffopts = patch.diffopts(ui, opts)
2574 diffopts = patch.diffopts(ui, opts)
2568 m = scmutil.match(repo[node2], pats, opts)
2575 m = scmutil.match(repo[node2], pats, opts)
2569 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2576 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2570 listsubrepos=opts.get('subrepos'))
2577 listsubrepos=opts.get('subrepos'))
2571
2578
2572 @command('^export',
2579 @command('^export',
2573 [('o', 'output', '',
2580 [('o', 'output', '',
2574 _('print output to file with formatted name'), _('FORMAT')),
2581 _('print output to file with formatted name'), _('FORMAT')),
2575 ('', 'switch-parent', None, _('diff against the second parent')),
2582 ('', 'switch-parent', None, _('diff against the second parent')),
2576 ('r', 'rev', [], _('revisions to export'), _('REV')),
2583 ('r', 'rev', [], _('revisions to export'), _('REV')),
2577 ] + diffopts,
2584 ] + diffopts,
2578 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2585 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2579 def export(ui, repo, *changesets, **opts):
2586 def export(ui, repo, *changesets, **opts):
2580 """dump the header and diffs for one or more changesets
2587 """dump the header and diffs for one or more changesets
2581
2588
2582 Print the changeset header and diffs for one or more revisions.
2589 Print the changeset header and diffs for one or more revisions.
2583
2590
2584 The information shown in the changeset header is: author, date,
2591 The information shown in the changeset header is: author, date,
2585 branch name (if non-default), changeset hash, parent(s) and commit
2592 branch name (if non-default), changeset hash, parent(s) and commit
2586 comment.
2593 comment.
2587
2594
2588 .. note::
2595 .. note::
2589 export may generate unexpected diff output for merge
2596 export may generate unexpected diff output for merge
2590 changesets, as it will compare the merge changeset against its
2597 changesets, as it will compare the merge changeset against its
2591 first parent only.
2598 first parent only.
2592
2599
2593 Output may be to a file, in which case the name of the file is
2600 Output may be to a file, in which case the name of the file is
2594 given using a format string. The formatting rules are as follows:
2601 given using a format string. The formatting rules are as follows:
2595
2602
2596 :``%%``: literal "%" character
2603 :``%%``: literal "%" character
2597 :``%H``: changeset hash (40 hexadecimal digits)
2604 :``%H``: changeset hash (40 hexadecimal digits)
2598 :``%N``: number of patches being generated
2605 :``%N``: number of patches being generated
2599 :``%R``: changeset revision number
2606 :``%R``: changeset revision number
2600 :``%b``: basename of the exporting repository
2607 :``%b``: basename of the exporting repository
2601 :``%h``: short-form changeset hash (12 hexadecimal digits)
2608 :``%h``: short-form changeset hash (12 hexadecimal digits)
2602 :``%m``: first line of the commit message (only alphanumeric characters)
2609 :``%m``: first line of the commit message (only alphanumeric characters)
2603 :``%n``: zero-padded sequence number, starting at 1
2610 :``%n``: zero-padded sequence number, starting at 1
2604 :``%r``: zero-padded changeset revision number
2611 :``%r``: zero-padded changeset revision number
2605
2612
2606 Without the -a/--text option, export will avoid generating diffs
2613 Without the -a/--text option, export will avoid generating diffs
2607 of files it detects as binary. With -a, export will generate a
2614 of files it detects as binary. With -a, export will generate a
2608 diff anyway, probably with undesirable results.
2615 diff anyway, probably with undesirable results.
2609
2616
2610 Use the -g/--git option to generate diffs in the git extended diff
2617 Use the -g/--git option to generate diffs in the git extended diff
2611 format. See :hg:`help diffs` for more information.
2618 format. See :hg:`help diffs` for more information.
2612
2619
2613 With the --switch-parent option, the diff will be against the
2620 With the --switch-parent option, the diff will be against the
2614 second parent. It can be useful to review a merge.
2621 second parent. It can be useful to review a merge.
2615
2622
2616 .. container:: verbose
2623 .. container:: verbose
2617
2624
2618 Examples:
2625 Examples:
2619
2626
2620 - use export and import to transplant a bugfix to the current
2627 - use export and import to transplant a bugfix to the current
2621 branch::
2628 branch::
2622
2629
2623 hg export -r 9353 | hg import -
2630 hg export -r 9353 | hg import -
2624
2631
2625 - export all the changesets between two revisions to a file with
2632 - export all the changesets between two revisions to a file with
2626 rename information::
2633 rename information::
2627
2634
2628 hg export --git -r 123:150 > changes.txt
2635 hg export --git -r 123:150 > changes.txt
2629
2636
2630 - split outgoing changes into a series of patches with
2637 - split outgoing changes into a series of patches with
2631 descriptive names::
2638 descriptive names::
2632
2639
2633 hg export -r "outgoing()" -o "%n-%m.patch"
2640 hg export -r "outgoing()" -o "%n-%m.patch"
2634
2641
2635 Returns 0 on success.
2642 Returns 0 on success.
2636 """
2643 """
2637 changesets += tuple(opts.get('rev', []))
2644 changesets += tuple(opts.get('rev', []))
2638 revs = scmutil.revrange(repo, changesets)
2645 revs = scmutil.revrange(repo, changesets)
2639 if not revs:
2646 if not revs:
2640 raise util.Abort(_("export requires at least one changeset"))
2647 raise util.Abort(_("export requires at least one changeset"))
2641 if len(revs) > 1:
2648 if len(revs) > 1:
2642 ui.note(_('exporting patches:\n'))
2649 ui.note(_('exporting patches:\n'))
2643 else:
2650 else:
2644 ui.note(_('exporting patch:\n'))
2651 ui.note(_('exporting patch:\n'))
2645 cmdutil.export(repo, revs, template=opts.get('output'),
2652 cmdutil.export(repo, revs, template=opts.get('output'),
2646 switch_parent=opts.get('switch_parent'),
2653 switch_parent=opts.get('switch_parent'),
2647 opts=patch.diffopts(ui, opts))
2654 opts=patch.diffopts(ui, opts))
2648
2655
2649 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2656 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2650 def forget(ui, repo, *pats, **opts):
2657 def forget(ui, repo, *pats, **opts):
2651 """forget the specified files on the next commit
2658 """forget the specified files on the next commit
2652
2659
2653 Mark the specified files so they will no longer be tracked
2660 Mark the specified files so they will no longer be tracked
2654 after the next commit.
2661 after the next commit.
2655
2662
2656 This only removes files from the current branch, not from the
2663 This only removes files from the current branch, not from the
2657 entire project history, and it does not delete them from the
2664 entire project history, and it does not delete them from the
2658 working directory.
2665 working directory.
2659
2666
2660 To undo a forget before the next commit, see :hg:`add`.
2667 To undo a forget before the next commit, see :hg:`add`.
2661
2668
2662 .. container:: verbose
2669 .. container:: verbose
2663
2670
2664 Examples:
2671 Examples:
2665
2672
2666 - forget newly-added binary files::
2673 - forget newly-added binary files::
2667
2674
2668 hg forget "set:added() and binary()"
2675 hg forget "set:added() and binary()"
2669
2676
2670 - forget files that would be excluded by .hgignore::
2677 - forget files that would be excluded by .hgignore::
2671
2678
2672 hg forget "set:hgignore()"
2679 hg forget "set:hgignore()"
2673
2680
2674 Returns 0 on success.
2681 Returns 0 on success.
2675 """
2682 """
2676
2683
2677 if not pats:
2684 if not pats:
2678 raise util.Abort(_('no files specified'))
2685 raise util.Abort(_('no files specified'))
2679
2686
2680 m = scmutil.match(repo[None], pats, opts)
2687 m = scmutil.match(repo[None], pats, opts)
2681 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2688 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2682 return rejected and 1 or 0
2689 return rejected and 1 or 0
2683
2690
2684 @command(
2691 @command(
2685 'graft',
2692 'graft',
2686 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2693 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2687 ('c', 'continue', False, _('resume interrupted graft')),
2694 ('c', 'continue', False, _('resume interrupted graft')),
2688 ('e', 'edit', False, _('invoke editor on commit messages')),
2695 ('e', 'edit', False, _('invoke editor on commit messages')),
2689 ('', 'log', None, _('append graft info to log message')),
2696 ('', 'log', None, _('append graft info to log message')),
2690 ('D', 'currentdate', False,
2697 ('D', 'currentdate', False,
2691 _('record the current date as commit date')),
2698 _('record the current date as commit date')),
2692 ('U', 'currentuser', False,
2699 ('U', 'currentuser', False,
2693 _('record the current user as committer'), _('DATE'))]
2700 _('record the current user as committer'), _('DATE'))]
2694 + commitopts2 + mergetoolopts + dryrunopts,
2701 + commitopts2 + mergetoolopts + dryrunopts,
2695 _('[OPTION]... [-r] REV...'))
2702 _('[OPTION]... [-r] REV...'))
2696 def graft(ui, repo, *revs, **opts):
2703 def graft(ui, repo, *revs, **opts):
2697 '''copy changes from other branches onto the current branch
2704 '''copy changes from other branches onto the current branch
2698
2705
2699 This command uses Mercurial's merge logic to copy individual
2706 This command uses Mercurial's merge logic to copy individual
2700 changes from other branches without merging branches in the
2707 changes from other branches without merging branches in the
2701 history graph. This is sometimes known as 'backporting' or
2708 history graph. This is sometimes known as 'backporting' or
2702 'cherry-picking'. By default, graft will copy user, date, and
2709 'cherry-picking'. By default, graft will copy user, date, and
2703 description from the source changesets.
2710 description from the source changesets.
2704
2711
2705 Changesets that are ancestors of the current revision, that have
2712 Changesets that are ancestors of the current revision, that have
2706 already been grafted, or that are merges will be skipped.
2713 already been grafted, or that are merges will be skipped.
2707
2714
2708 If --log is specified, log messages will have a comment appended
2715 If --log is specified, log messages will have a comment appended
2709 of the form::
2716 of the form::
2710
2717
2711 (grafted from CHANGESETHASH)
2718 (grafted from CHANGESETHASH)
2712
2719
2713 If a graft merge results in conflicts, the graft process is
2720 If a graft merge results in conflicts, the graft process is
2714 interrupted so that the current merge can be manually resolved.
2721 interrupted so that the current merge can be manually resolved.
2715 Once all conflicts are addressed, the graft process can be
2722 Once all conflicts are addressed, the graft process can be
2716 continued with the -c/--continue option.
2723 continued with the -c/--continue option.
2717
2724
2718 .. note::
2725 .. note::
2719 The -c/--continue option does not reapply earlier options.
2726 The -c/--continue option does not reapply earlier options.
2720
2727
2721 .. container:: verbose
2728 .. container:: verbose
2722
2729
2723 Examples:
2730 Examples:
2724
2731
2725 - copy a single change to the stable branch and edit its description::
2732 - copy a single change to the stable branch and edit its description::
2726
2733
2727 hg update stable
2734 hg update stable
2728 hg graft --edit 9393
2735 hg graft --edit 9393
2729
2736
2730 - graft a range of changesets with one exception, updating dates::
2737 - graft a range of changesets with one exception, updating dates::
2731
2738
2732 hg graft -D "2085::2093 and not 2091"
2739 hg graft -D "2085::2093 and not 2091"
2733
2740
2734 - continue a graft after resolving conflicts::
2741 - continue a graft after resolving conflicts::
2735
2742
2736 hg graft -c
2743 hg graft -c
2737
2744
2738 - show the source of a grafted changeset::
2745 - show the source of a grafted changeset::
2739
2746
2740 hg log --debug -r tip
2747 hg log --debug -r tip
2741
2748
2742 Returns 0 on successful completion.
2749 Returns 0 on successful completion.
2743 '''
2750 '''
2744
2751
2745 revs = list(revs)
2752 revs = list(revs)
2746 revs.extend(opts['rev'])
2753 revs.extend(opts['rev'])
2747
2754
2748 if not opts.get('user') and opts.get('currentuser'):
2755 if not opts.get('user') and opts.get('currentuser'):
2749 opts['user'] = ui.username()
2756 opts['user'] = ui.username()
2750 if not opts.get('date') and opts.get('currentdate'):
2757 if not opts.get('date') and opts.get('currentdate'):
2751 opts['date'] = "%d %d" % util.makedate()
2758 opts['date'] = "%d %d" % util.makedate()
2752
2759
2753 editor = None
2760 editor = None
2754 if opts.get('edit'):
2761 if opts.get('edit'):
2755 editor = cmdutil.commitforceeditor
2762 editor = cmdutil.commitforceeditor
2756
2763
2757 cont = False
2764 cont = False
2758 if opts['continue']:
2765 if opts['continue']:
2759 cont = True
2766 cont = True
2760 if revs:
2767 if revs:
2761 raise util.Abort(_("can't specify --continue and revisions"))
2768 raise util.Abort(_("can't specify --continue and revisions"))
2762 # read in unfinished revisions
2769 # read in unfinished revisions
2763 try:
2770 try:
2764 nodes = repo.opener.read('graftstate').splitlines()
2771 nodes = repo.opener.read('graftstate').splitlines()
2765 revs = [repo[node].rev() for node in nodes]
2772 revs = [repo[node].rev() for node in nodes]
2766 except IOError, inst:
2773 except IOError, inst:
2767 if inst.errno != errno.ENOENT:
2774 if inst.errno != errno.ENOENT:
2768 raise
2775 raise
2769 raise util.Abort(_("no graft state found, can't continue"))
2776 raise util.Abort(_("no graft state found, can't continue"))
2770 else:
2777 else:
2771 cmdutil.bailifchanged(repo)
2778 cmdutil.bailifchanged(repo)
2772 if not revs:
2779 if not revs:
2773 raise util.Abort(_('no revisions specified'))
2780 raise util.Abort(_('no revisions specified'))
2774 revs = scmutil.revrange(repo, revs)
2781 revs = scmutil.revrange(repo, revs)
2775
2782
2776 # check for merges
2783 # check for merges
2777 for rev in repo.revs('%ld and merge()', revs):
2784 for rev in repo.revs('%ld and merge()', revs):
2778 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2785 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2779 revs.remove(rev)
2786 revs.remove(rev)
2780 if not revs:
2787 if not revs:
2781 return -1
2788 return -1
2782
2789
2783 # check for ancestors of dest branch
2790 # check for ancestors of dest branch
2784 for rev in repo.revs('::. and %ld', revs):
2791 for rev in repo.revs('::. and %ld', revs):
2785 ui.warn(_('skipping ancestor revision %s\n') % rev)
2792 ui.warn(_('skipping ancestor revision %s\n') % rev)
2786 revs.remove(rev)
2793 revs.remove(rev)
2787 if not revs:
2794 if not revs:
2788 return -1
2795 return -1
2789
2796
2790 # analyze revs for earlier grafts
2797 # analyze revs for earlier grafts
2791 ids = {}
2798 ids = {}
2792 for ctx in repo.set("%ld", revs):
2799 for ctx in repo.set("%ld", revs):
2793 ids[ctx.hex()] = ctx.rev()
2800 ids[ctx.hex()] = ctx.rev()
2794 n = ctx.extra().get('source')
2801 n = ctx.extra().get('source')
2795 if n:
2802 if n:
2796 ids[n] = ctx.rev()
2803 ids[n] = ctx.rev()
2797
2804
2798 # check ancestors for earlier grafts
2805 # check ancestors for earlier grafts
2799 ui.debug('scanning for duplicate grafts\n')
2806 ui.debug('scanning for duplicate grafts\n')
2800 for ctx in repo.set("::. - ::%ld", revs):
2807 for ctx in repo.set("::. - ::%ld", revs):
2801 n = ctx.extra().get('source')
2808 n = ctx.extra().get('source')
2802 if n in ids:
2809 if n in ids:
2803 r = repo[n].rev()
2810 r = repo[n].rev()
2804 if r in revs:
2811 if r in revs:
2805 ui.warn(_('skipping already grafted revision %s\n') % r)
2812 ui.warn(_('skipping already grafted revision %s\n') % r)
2806 revs.remove(r)
2813 revs.remove(r)
2807 elif ids[n] in revs:
2814 elif ids[n] in revs:
2808 ui.warn(_('skipping already grafted revision %s '
2815 ui.warn(_('skipping already grafted revision %s '
2809 '(same origin %d)\n') % (ids[n], r))
2816 '(same origin %d)\n') % (ids[n], r))
2810 revs.remove(ids[n])
2817 revs.remove(ids[n])
2811 elif ctx.hex() in ids:
2818 elif ctx.hex() in ids:
2812 r = ids[ctx.hex()]
2819 r = ids[ctx.hex()]
2813 ui.warn(_('skipping already grafted revision %s '
2820 ui.warn(_('skipping already grafted revision %s '
2814 '(was grafted from %d)\n') % (r, ctx.rev()))
2821 '(was grafted from %d)\n') % (r, ctx.rev()))
2815 revs.remove(r)
2822 revs.remove(r)
2816 if not revs:
2823 if not revs:
2817 return -1
2824 return -1
2818
2825
2819 wlock = repo.wlock()
2826 wlock = repo.wlock()
2820 try:
2827 try:
2821 for pos, ctx in enumerate(repo.set("%ld", revs)):
2828 for pos, ctx in enumerate(repo.set("%ld", revs)):
2822 current = repo['.']
2829 current = repo['.']
2823
2830
2824 ui.status(_('grafting revision %s\n') % ctx.rev())
2831 ui.status(_('grafting revision %s\n') % ctx.rev())
2825 if opts.get('dry_run'):
2832 if opts.get('dry_run'):
2826 continue
2833 continue
2827
2834
2828 # we don't merge the first commit when continuing
2835 # we don't merge the first commit when continuing
2829 if not cont:
2836 if not cont:
2830 # perform the graft merge with p1(rev) as 'ancestor'
2837 # perform the graft merge with p1(rev) as 'ancestor'
2831 try:
2838 try:
2832 # ui.forcemerge is an internal variable, do not document
2839 # ui.forcemerge is an internal variable, do not document
2833 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2840 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2834 stats = mergemod.update(repo, ctx.node(), True, True, False,
2841 stats = mergemod.update(repo, ctx.node(), True, True, False,
2835 ctx.p1().node())
2842 ctx.p1().node())
2836 finally:
2843 finally:
2837 repo.ui.setconfig('ui', 'forcemerge', '')
2844 repo.ui.setconfig('ui', 'forcemerge', '')
2838 # report any conflicts
2845 # report any conflicts
2839 if stats and stats[3] > 0:
2846 if stats and stats[3] > 0:
2840 # write out state for --continue
2847 # write out state for --continue
2841 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2848 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2842 repo.opener.write('graftstate', ''.join(nodelines))
2849 repo.opener.write('graftstate', ''.join(nodelines))
2843 raise util.Abort(
2850 raise util.Abort(
2844 _("unresolved conflicts, can't continue"),
2851 _("unresolved conflicts, can't continue"),
2845 hint=_('use hg resolve and hg graft --continue'))
2852 hint=_('use hg resolve and hg graft --continue'))
2846 else:
2853 else:
2847 cont = False
2854 cont = False
2848
2855
2849 # drop the second merge parent
2856 # drop the second merge parent
2850 repo.setparents(current.node(), nullid)
2857 repo.setparents(current.node(), nullid)
2851 repo.dirstate.write()
2858 repo.dirstate.write()
2852 # fix up dirstate for copies and renames
2859 # fix up dirstate for copies and renames
2853 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2860 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2854
2861
2855 # commit
2862 # commit
2856 source = ctx.extra().get('source')
2863 source = ctx.extra().get('source')
2857 if not source:
2864 if not source:
2858 source = ctx.hex()
2865 source = ctx.hex()
2859 extra = {'source': source}
2866 extra = {'source': source}
2860 user = ctx.user()
2867 user = ctx.user()
2861 if opts.get('user'):
2868 if opts.get('user'):
2862 user = opts['user']
2869 user = opts['user']
2863 date = ctx.date()
2870 date = ctx.date()
2864 if opts.get('date'):
2871 if opts.get('date'):
2865 date = opts['date']
2872 date = opts['date']
2866 message = ctx.description()
2873 message = ctx.description()
2867 if opts.get('log'):
2874 if opts.get('log'):
2868 message += '\n(grafted from %s)' % ctx.hex()
2875 message += '\n(grafted from %s)' % ctx.hex()
2869 node = repo.commit(text=message, user=user,
2876 node = repo.commit(text=message, user=user,
2870 date=date, extra=extra, editor=editor)
2877 date=date, extra=extra, editor=editor)
2871 if node is None:
2878 if node is None:
2872 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2879 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2873 finally:
2880 finally:
2874 wlock.release()
2881 wlock.release()
2875
2882
2876 # remove state when we complete successfully
2883 # remove state when we complete successfully
2877 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2884 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2878 util.unlinkpath(repo.join('graftstate'))
2885 util.unlinkpath(repo.join('graftstate'))
2879
2886
2880 return 0
2887 return 0
2881
2888
2882 @command('grep',
2889 @command('grep',
2883 [('0', 'print0', None, _('end fields with NUL')),
2890 [('0', 'print0', None, _('end fields with NUL')),
2884 ('', 'all', None, _('print all revisions that match')),
2891 ('', 'all', None, _('print all revisions that match')),
2885 ('a', 'text', None, _('treat all files as text')),
2892 ('a', 'text', None, _('treat all files as text')),
2886 ('f', 'follow', None,
2893 ('f', 'follow', None,
2887 _('follow changeset history,'
2894 _('follow changeset history,'
2888 ' or file history across copies and renames')),
2895 ' or file history across copies and renames')),
2889 ('i', 'ignore-case', None, _('ignore case when matching')),
2896 ('i', 'ignore-case', None, _('ignore case when matching')),
2890 ('l', 'files-with-matches', None,
2897 ('l', 'files-with-matches', None,
2891 _('print only filenames and revisions that match')),
2898 _('print only filenames and revisions that match')),
2892 ('n', 'line-number', None, _('print matching line numbers')),
2899 ('n', 'line-number', None, _('print matching line numbers')),
2893 ('r', 'rev', [],
2900 ('r', 'rev', [],
2894 _('only search files changed within revision range'), _('REV')),
2901 _('only search files changed within revision range'), _('REV')),
2895 ('u', 'user', None, _('list the author (long with -v)')),
2902 ('u', 'user', None, _('list the author (long with -v)')),
2896 ('d', 'date', None, _('list the date (short with -q)')),
2903 ('d', 'date', None, _('list the date (short with -q)')),
2897 ] + walkopts,
2904 ] + walkopts,
2898 _('[OPTION]... PATTERN [FILE]...'))
2905 _('[OPTION]... PATTERN [FILE]...'))
2899 def grep(ui, repo, pattern, *pats, **opts):
2906 def grep(ui, repo, pattern, *pats, **opts):
2900 """search for a pattern in specified files and revisions
2907 """search for a pattern in specified files and revisions
2901
2908
2902 Search revisions of files for a regular expression.
2909 Search revisions of files for a regular expression.
2903
2910
2904 This command behaves differently than Unix grep. It only accepts
2911 This command behaves differently than Unix grep. It only accepts
2905 Python/Perl regexps. It searches repository history, not the
2912 Python/Perl regexps. It searches repository history, not the
2906 working directory. It always prints the revision number in which a
2913 working directory. It always prints the revision number in which a
2907 match appears.
2914 match appears.
2908
2915
2909 By default, grep only prints output for the first revision of a
2916 By default, grep only prints output for the first revision of a
2910 file in which it finds a match. To get it to print every revision
2917 file in which it finds a match. To get it to print every revision
2911 that contains a change in match status ("-" for a match that
2918 that contains a change in match status ("-" for a match that
2912 becomes a non-match, or "+" for a non-match that becomes a match),
2919 becomes a non-match, or "+" for a non-match that becomes a match),
2913 use the --all flag.
2920 use the --all flag.
2914
2921
2915 Returns 0 if a match is found, 1 otherwise.
2922 Returns 0 if a match is found, 1 otherwise.
2916 """
2923 """
2917 reflags = re.M
2924 reflags = re.M
2918 if opts.get('ignore_case'):
2925 if opts.get('ignore_case'):
2919 reflags |= re.I
2926 reflags |= re.I
2920 try:
2927 try:
2921 regexp = re.compile(pattern, reflags)
2928 regexp = re.compile(pattern, reflags)
2922 except re.error, inst:
2929 except re.error, inst:
2923 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2930 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2924 return 1
2931 return 1
2925 sep, eol = ':', '\n'
2932 sep, eol = ':', '\n'
2926 if opts.get('print0'):
2933 if opts.get('print0'):
2927 sep = eol = '\0'
2934 sep = eol = '\0'
2928
2935
2929 getfile = util.lrucachefunc(repo.file)
2936 getfile = util.lrucachefunc(repo.file)
2930
2937
2931 def matchlines(body):
2938 def matchlines(body):
2932 begin = 0
2939 begin = 0
2933 linenum = 0
2940 linenum = 0
2934 while True:
2941 while True:
2935 match = regexp.search(body, begin)
2942 match = regexp.search(body, begin)
2936 if not match:
2943 if not match:
2937 break
2944 break
2938 mstart, mend = match.span()
2945 mstart, mend = match.span()
2939 linenum += body.count('\n', begin, mstart) + 1
2946 linenum += body.count('\n', begin, mstart) + 1
2940 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2947 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2941 begin = body.find('\n', mend) + 1 or len(body) + 1
2948 begin = body.find('\n', mend) + 1 or len(body) + 1
2942 lend = begin - 1
2949 lend = begin - 1
2943 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2950 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2944
2951
2945 class linestate(object):
2952 class linestate(object):
2946 def __init__(self, line, linenum, colstart, colend):
2953 def __init__(self, line, linenum, colstart, colend):
2947 self.line = line
2954 self.line = line
2948 self.linenum = linenum
2955 self.linenum = linenum
2949 self.colstart = colstart
2956 self.colstart = colstart
2950 self.colend = colend
2957 self.colend = colend
2951
2958
2952 def __hash__(self):
2959 def __hash__(self):
2953 return hash((self.linenum, self.line))
2960 return hash((self.linenum, self.line))
2954
2961
2955 def __eq__(self, other):
2962 def __eq__(self, other):
2956 return self.line == other.line
2963 return self.line == other.line
2957
2964
2958 matches = {}
2965 matches = {}
2959 copies = {}
2966 copies = {}
2960 def grepbody(fn, rev, body):
2967 def grepbody(fn, rev, body):
2961 matches[rev].setdefault(fn, [])
2968 matches[rev].setdefault(fn, [])
2962 m = matches[rev][fn]
2969 m = matches[rev][fn]
2963 for lnum, cstart, cend, line in matchlines(body):
2970 for lnum, cstart, cend, line in matchlines(body):
2964 s = linestate(line, lnum, cstart, cend)
2971 s = linestate(line, lnum, cstart, cend)
2965 m.append(s)
2972 m.append(s)
2966
2973
2967 def difflinestates(a, b):
2974 def difflinestates(a, b):
2968 sm = difflib.SequenceMatcher(None, a, b)
2975 sm = difflib.SequenceMatcher(None, a, b)
2969 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2976 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2970 if tag == 'insert':
2977 if tag == 'insert':
2971 for i in xrange(blo, bhi):
2978 for i in xrange(blo, bhi):
2972 yield ('+', b[i])
2979 yield ('+', b[i])
2973 elif tag == 'delete':
2980 elif tag == 'delete':
2974 for i in xrange(alo, ahi):
2981 for i in xrange(alo, ahi):
2975 yield ('-', a[i])
2982 yield ('-', a[i])
2976 elif tag == 'replace':
2983 elif tag == 'replace':
2977 for i in xrange(alo, ahi):
2984 for i in xrange(alo, ahi):
2978 yield ('-', a[i])
2985 yield ('-', a[i])
2979 for i in xrange(blo, bhi):
2986 for i in xrange(blo, bhi):
2980 yield ('+', b[i])
2987 yield ('+', b[i])
2981
2988
2982 def display(fn, ctx, pstates, states):
2989 def display(fn, ctx, pstates, states):
2983 rev = ctx.rev()
2990 rev = ctx.rev()
2984 datefunc = ui.quiet and util.shortdate or util.datestr
2991 datefunc = ui.quiet and util.shortdate or util.datestr
2985 found = False
2992 found = False
2986 filerevmatches = {}
2993 filerevmatches = {}
2987 def binary():
2994 def binary():
2988 flog = getfile(fn)
2995 flog = getfile(fn)
2989 return util.binary(flog.read(ctx.filenode(fn)))
2996 return util.binary(flog.read(ctx.filenode(fn)))
2990
2997
2991 if opts.get('all'):
2998 if opts.get('all'):
2992 iter = difflinestates(pstates, states)
2999 iter = difflinestates(pstates, states)
2993 else:
3000 else:
2994 iter = [('', l) for l in states]
3001 iter = [('', l) for l in states]
2995 for change, l in iter:
3002 for change, l in iter:
2996 cols = [fn, str(rev)]
3003 cols = [fn, str(rev)]
2997 before, match, after = None, None, None
3004 before, match, after = None, None, None
2998 if opts.get('line_number'):
3005 if opts.get('line_number'):
2999 cols.append(str(l.linenum))
3006 cols.append(str(l.linenum))
3000 if opts.get('all'):
3007 if opts.get('all'):
3001 cols.append(change)
3008 cols.append(change)
3002 if opts.get('user'):
3009 if opts.get('user'):
3003 cols.append(ui.shortuser(ctx.user()))
3010 cols.append(ui.shortuser(ctx.user()))
3004 if opts.get('date'):
3011 if opts.get('date'):
3005 cols.append(datefunc(ctx.date()))
3012 cols.append(datefunc(ctx.date()))
3006 if opts.get('files_with_matches'):
3013 if opts.get('files_with_matches'):
3007 c = (fn, rev)
3014 c = (fn, rev)
3008 if c in filerevmatches:
3015 if c in filerevmatches:
3009 continue
3016 continue
3010 filerevmatches[c] = 1
3017 filerevmatches[c] = 1
3011 else:
3018 else:
3012 before = l.line[:l.colstart]
3019 before = l.line[:l.colstart]
3013 match = l.line[l.colstart:l.colend]
3020 match = l.line[l.colstart:l.colend]
3014 after = l.line[l.colend:]
3021 after = l.line[l.colend:]
3015 ui.write(sep.join(cols))
3022 ui.write(sep.join(cols))
3016 if before is not None:
3023 if before is not None:
3017 if not opts.get('text') and binary():
3024 if not opts.get('text') and binary():
3018 ui.write(sep + " Binary file matches")
3025 ui.write(sep + " Binary file matches")
3019 else:
3026 else:
3020 ui.write(sep + before)
3027 ui.write(sep + before)
3021 ui.write(match, label='grep.match')
3028 ui.write(match, label='grep.match')
3022 ui.write(after)
3029 ui.write(after)
3023 ui.write(eol)
3030 ui.write(eol)
3024 found = True
3031 found = True
3025 return found
3032 return found
3026
3033
3027 skip = {}
3034 skip = {}
3028 revfiles = {}
3035 revfiles = {}
3029 matchfn = scmutil.match(repo[None], pats, opts)
3036 matchfn = scmutil.match(repo[None], pats, opts)
3030 found = False
3037 found = False
3031 follow = opts.get('follow')
3038 follow = opts.get('follow')
3032
3039
3033 def prep(ctx, fns):
3040 def prep(ctx, fns):
3034 rev = ctx.rev()
3041 rev = ctx.rev()
3035 pctx = ctx.p1()
3042 pctx = ctx.p1()
3036 parent = pctx.rev()
3043 parent = pctx.rev()
3037 matches.setdefault(rev, {})
3044 matches.setdefault(rev, {})
3038 matches.setdefault(parent, {})
3045 matches.setdefault(parent, {})
3039 files = revfiles.setdefault(rev, [])
3046 files = revfiles.setdefault(rev, [])
3040 for fn in fns:
3047 for fn in fns:
3041 flog = getfile(fn)
3048 flog = getfile(fn)
3042 try:
3049 try:
3043 fnode = ctx.filenode(fn)
3050 fnode = ctx.filenode(fn)
3044 except error.LookupError:
3051 except error.LookupError:
3045 continue
3052 continue
3046
3053
3047 copied = flog.renamed(fnode)
3054 copied = flog.renamed(fnode)
3048 copy = follow and copied and copied[0]
3055 copy = follow and copied and copied[0]
3049 if copy:
3056 if copy:
3050 copies.setdefault(rev, {})[fn] = copy
3057 copies.setdefault(rev, {})[fn] = copy
3051 if fn in skip:
3058 if fn in skip:
3052 if copy:
3059 if copy:
3053 skip[copy] = True
3060 skip[copy] = True
3054 continue
3061 continue
3055 files.append(fn)
3062 files.append(fn)
3056
3063
3057 if fn not in matches[rev]:
3064 if fn not in matches[rev]:
3058 grepbody(fn, rev, flog.read(fnode))
3065 grepbody(fn, rev, flog.read(fnode))
3059
3066
3060 pfn = copy or fn
3067 pfn = copy or fn
3061 if pfn not in matches[parent]:
3068 if pfn not in matches[parent]:
3062 try:
3069 try:
3063 fnode = pctx.filenode(pfn)
3070 fnode = pctx.filenode(pfn)
3064 grepbody(pfn, parent, flog.read(fnode))
3071 grepbody(pfn, parent, flog.read(fnode))
3065 except error.LookupError:
3072 except error.LookupError:
3066 pass
3073 pass
3067
3074
3068 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3075 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3069 rev = ctx.rev()
3076 rev = ctx.rev()
3070 parent = ctx.p1().rev()
3077 parent = ctx.p1().rev()
3071 for fn in sorted(revfiles.get(rev, [])):
3078 for fn in sorted(revfiles.get(rev, [])):
3072 states = matches[rev][fn]
3079 states = matches[rev][fn]
3073 copy = copies.get(rev, {}).get(fn)
3080 copy = copies.get(rev, {}).get(fn)
3074 if fn in skip:
3081 if fn in skip:
3075 if copy:
3082 if copy:
3076 skip[copy] = True
3083 skip[copy] = True
3077 continue
3084 continue
3078 pstates = matches.get(parent, {}).get(copy or fn, [])
3085 pstates = matches.get(parent, {}).get(copy or fn, [])
3079 if pstates or states:
3086 if pstates or states:
3080 r = display(fn, ctx, pstates, states)
3087 r = display(fn, ctx, pstates, states)
3081 found = found or r
3088 found = found or r
3082 if r and not opts.get('all'):
3089 if r and not opts.get('all'):
3083 skip[fn] = True
3090 skip[fn] = True
3084 if copy:
3091 if copy:
3085 skip[copy] = True
3092 skip[copy] = True
3086 del matches[rev]
3093 del matches[rev]
3087 del revfiles[rev]
3094 del revfiles[rev]
3088
3095
3089 return not found
3096 return not found
3090
3097
3091 @command('heads',
3098 @command('heads',
3092 [('r', 'rev', '',
3099 [('r', 'rev', '',
3093 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3100 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3094 ('t', 'topo', False, _('show topological heads only')),
3101 ('t', 'topo', False, _('show topological heads only')),
3095 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3102 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3096 ('c', 'closed', False, _('show normal and closed branch heads')),
3103 ('c', 'closed', False, _('show normal and closed branch heads')),
3097 ] + templateopts,
3104 ] + templateopts,
3098 _('[-ct] [-r STARTREV] [REV]...'))
3105 _('[-ct] [-r STARTREV] [REV]...'))
3099 def heads(ui, repo, *branchrevs, **opts):
3106 def heads(ui, repo, *branchrevs, **opts):
3100 """show current repository heads or show branch heads
3107 """show current repository heads or show branch heads
3101
3108
3102 With no arguments, show all repository branch heads.
3109 With no arguments, show all repository branch heads.
3103
3110
3104 Repository "heads" are changesets with no child changesets. They are
3111 Repository "heads" are changesets with no child changesets. They are
3105 where development generally takes place and are the usual targets
3112 where development generally takes place and are the usual targets
3106 for update and merge operations. Branch heads are changesets that have
3113 for update and merge operations. Branch heads are changesets that have
3107 no child changeset on the same branch.
3114 no child changeset on the same branch.
3108
3115
3109 If one or more REVs are given, only branch heads on the branches
3116 If one or more REVs are given, only branch heads on the branches
3110 associated with the specified changesets are shown. This means
3117 associated with the specified changesets are shown. This means
3111 that you can use :hg:`heads foo` to see the heads on a branch
3118 that you can use :hg:`heads foo` to see the heads on a branch
3112 named ``foo``.
3119 named ``foo``.
3113
3120
3114 If -c/--closed is specified, also show branch heads marked closed
3121 If -c/--closed is specified, also show branch heads marked closed
3115 (see :hg:`commit --close-branch`).
3122 (see :hg:`commit --close-branch`).
3116
3123
3117 If STARTREV is specified, only those heads that are descendants of
3124 If STARTREV is specified, only those heads that are descendants of
3118 STARTREV will be displayed.
3125 STARTREV will be displayed.
3119
3126
3120 If -t/--topo is specified, named branch mechanics will be ignored and only
3127 If -t/--topo is specified, named branch mechanics will be ignored and only
3121 changesets without children will be shown.
3128 changesets without children will be shown.
3122
3129
3123 Returns 0 if matching heads are found, 1 if not.
3130 Returns 0 if matching heads are found, 1 if not.
3124 """
3131 """
3125
3132
3126 start = None
3133 start = None
3127 if 'rev' in opts:
3134 if 'rev' in opts:
3128 start = scmutil.revsingle(repo, opts['rev'], None).node()
3135 start = scmutil.revsingle(repo, opts['rev'], None).node()
3129
3136
3130 if opts.get('topo'):
3137 if opts.get('topo'):
3131 heads = [repo[h] for h in repo.heads(start)]
3138 heads = [repo[h] for h in repo.heads(start)]
3132 else:
3139 else:
3133 heads = []
3140 heads = []
3134 for branch in repo.branchmap():
3141 for branch in repo.branchmap():
3135 heads += repo.branchheads(branch, start, opts.get('closed'))
3142 heads += repo.branchheads(branch, start, opts.get('closed'))
3136 heads = [repo[h] for h in heads]
3143 heads = [repo[h] for h in heads]
3137
3144
3138 if branchrevs:
3145 if branchrevs:
3139 branches = set(repo[br].branch() for br in branchrevs)
3146 branches = set(repo[br].branch() for br in branchrevs)
3140 heads = [h for h in heads if h.branch() in branches]
3147 heads = [h for h in heads if h.branch() in branches]
3141
3148
3142 if opts.get('active') and branchrevs:
3149 if opts.get('active') and branchrevs:
3143 dagheads = repo.heads(start)
3150 dagheads = repo.heads(start)
3144 heads = [h for h in heads if h.node() in dagheads]
3151 heads = [h for h in heads if h.node() in dagheads]
3145
3152
3146 if branchrevs:
3153 if branchrevs:
3147 haveheads = set(h.branch() for h in heads)
3154 haveheads = set(h.branch() for h in heads)
3148 if branches - haveheads:
3155 if branches - haveheads:
3149 headless = ', '.join(b for b in branches - haveheads)
3156 headless = ', '.join(b for b in branches - haveheads)
3150 msg = _('no open branch heads found on branches %s')
3157 msg = _('no open branch heads found on branches %s')
3151 if opts.get('rev'):
3158 if opts.get('rev'):
3152 msg += _(' (started at %s)') % opts['rev']
3159 msg += _(' (started at %s)') % opts['rev']
3153 ui.warn((msg + '\n') % headless)
3160 ui.warn((msg + '\n') % headless)
3154
3161
3155 if not heads:
3162 if not heads:
3156 return 1
3163 return 1
3157
3164
3158 heads = sorted(heads, key=lambda x: -x.rev())
3165 heads = sorted(heads, key=lambda x: -x.rev())
3159 displayer = cmdutil.show_changeset(ui, repo, opts)
3166 displayer = cmdutil.show_changeset(ui, repo, opts)
3160 for ctx in heads:
3167 for ctx in heads:
3161 displayer.show(ctx)
3168 displayer.show(ctx)
3162 displayer.close()
3169 displayer.close()
3163
3170
3164 @command('help',
3171 @command('help',
3165 [('e', 'extension', None, _('show only help for extensions')),
3172 [('e', 'extension', None, _('show only help for extensions')),
3166 ('c', 'command', None, _('show only help for commands')),
3173 ('c', 'command', None, _('show only help for commands')),
3167 ('k', 'keyword', '', _('show topics matching keyword')),
3174 ('k', 'keyword', '', _('show topics matching keyword')),
3168 ],
3175 ],
3169 _('[-ec] [TOPIC]'))
3176 _('[-ec] [TOPIC]'))
3170 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3177 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3171 """show help for a given topic or a help overview
3178 """show help for a given topic or a help overview
3172
3179
3173 With no arguments, print a list of commands with short help messages.
3180 With no arguments, print a list of commands with short help messages.
3174
3181
3175 Given a topic, extension, or command name, print help for that
3182 Given a topic, extension, or command name, print help for that
3176 topic.
3183 topic.
3177
3184
3178 Returns 0 if successful.
3185 Returns 0 if successful.
3179 """
3186 """
3180
3187
3181 textwidth = min(ui.termwidth(), 80) - 2
3188 textwidth = min(ui.termwidth(), 80) - 2
3182
3189
3183 def helpcmd(name):
3190 def helpcmd(name):
3184 try:
3191 try:
3185 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3192 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3186 except error.AmbiguousCommand, inst:
3193 except error.AmbiguousCommand, inst:
3187 # py3k fix: except vars can't be used outside the scope of the
3194 # py3k fix: except vars can't be used outside the scope of the
3188 # except block, nor can be used inside a lambda. python issue4617
3195 # except block, nor can be used inside a lambda. python issue4617
3189 prefix = inst.args[0]
3196 prefix = inst.args[0]
3190 select = lambda c: c.lstrip('^').startswith(prefix)
3197 select = lambda c: c.lstrip('^').startswith(prefix)
3191 rst = helplist(select)
3198 rst = helplist(select)
3192 return rst
3199 return rst
3193
3200
3194 rst = []
3201 rst = []
3195
3202
3196 # check if it's an invalid alias and display its error if it is
3203 # check if it's an invalid alias and display its error if it is
3197 if getattr(entry[0], 'badalias', False):
3204 if getattr(entry[0], 'badalias', False):
3198 if not unknowncmd:
3205 if not unknowncmd:
3199 ui.pushbuffer()
3206 ui.pushbuffer()
3200 entry[0](ui)
3207 entry[0](ui)
3201 rst.append(ui.popbuffer())
3208 rst.append(ui.popbuffer())
3202 return rst
3209 return rst
3203
3210
3204 # synopsis
3211 # synopsis
3205 if len(entry) > 2:
3212 if len(entry) > 2:
3206 if entry[2].startswith('hg'):
3213 if entry[2].startswith('hg'):
3207 rst.append("%s\n" % entry[2])
3214 rst.append("%s\n" % entry[2])
3208 else:
3215 else:
3209 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3216 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3210 else:
3217 else:
3211 rst.append('hg %s\n' % aliases[0])
3218 rst.append('hg %s\n' % aliases[0])
3212 # aliases
3219 # aliases
3213 if full and not ui.quiet and len(aliases) > 1:
3220 if full and not ui.quiet and len(aliases) > 1:
3214 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3221 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3215 rst.append('\n')
3222 rst.append('\n')
3216
3223
3217 # description
3224 # description
3218 doc = gettext(entry[0].__doc__)
3225 doc = gettext(entry[0].__doc__)
3219 if not doc:
3226 if not doc:
3220 doc = _("(no help text available)")
3227 doc = _("(no help text available)")
3221 if util.safehasattr(entry[0], 'definition'): # aliased command
3228 if util.safehasattr(entry[0], 'definition'): # aliased command
3222 if entry[0].definition.startswith('!'): # shell alias
3229 if entry[0].definition.startswith('!'): # shell alias
3223 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3230 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3224 else:
3231 else:
3225 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3232 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3226 doc = doc.splitlines(True)
3233 doc = doc.splitlines(True)
3227 if ui.quiet or not full:
3234 if ui.quiet or not full:
3228 rst.append(doc[0])
3235 rst.append(doc[0])
3229 else:
3236 else:
3230 rst.extend(doc)
3237 rst.extend(doc)
3231 rst.append('\n')
3238 rst.append('\n')
3232
3239
3233 # check if this command shadows a non-trivial (multi-line)
3240 # check if this command shadows a non-trivial (multi-line)
3234 # extension help text
3241 # extension help text
3235 try:
3242 try:
3236 mod = extensions.find(name)
3243 mod = extensions.find(name)
3237 doc = gettext(mod.__doc__) or ''
3244 doc = gettext(mod.__doc__) or ''
3238 if '\n' in doc.strip():
3245 if '\n' in doc.strip():
3239 msg = _('use "hg help -e %s" to show help for '
3246 msg = _('use "hg help -e %s" to show help for '
3240 'the %s extension') % (name, name)
3247 'the %s extension') % (name, name)
3241 rst.append('\n%s\n' % msg)
3248 rst.append('\n%s\n' % msg)
3242 except KeyError:
3249 except KeyError:
3243 pass
3250 pass
3244
3251
3245 # options
3252 # options
3246 if not ui.quiet and entry[1]:
3253 if not ui.quiet and entry[1]:
3247 rst.append('\n%s\n\n' % _("options:"))
3254 rst.append('\n%s\n\n' % _("options:"))
3248 rst.append(help.optrst(entry[1], ui.verbose))
3255 rst.append(help.optrst(entry[1], ui.verbose))
3249
3256
3250 if ui.verbose:
3257 if ui.verbose:
3251 rst.append('\n%s\n\n' % _("global options:"))
3258 rst.append('\n%s\n\n' % _("global options:"))
3252 rst.append(help.optrst(globalopts, ui.verbose))
3259 rst.append(help.optrst(globalopts, ui.verbose))
3253
3260
3254 if not ui.verbose:
3261 if not ui.verbose:
3255 if not full:
3262 if not full:
3256 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3263 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3257 % name)
3264 % name)
3258 elif not ui.quiet:
3265 elif not ui.quiet:
3259 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3266 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3260 % name)
3267 % name)
3261 return rst
3268 return rst
3262
3269
3263
3270
3264 def helplist(select=None):
3271 def helplist(select=None):
3265 # list of commands
3272 # list of commands
3266 if name == "shortlist":
3273 if name == "shortlist":
3267 header = _('basic commands:\n\n')
3274 header = _('basic commands:\n\n')
3268 else:
3275 else:
3269 header = _('list of commands:\n\n')
3276 header = _('list of commands:\n\n')
3270
3277
3271 h = {}
3278 h = {}
3272 cmds = {}
3279 cmds = {}
3273 for c, e in table.iteritems():
3280 for c, e in table.iteritems():
3274 f = c.split("|", 1)[0]
3281 f = c.split("|", 1)[0]
3275 if select and not select(f):
3282 if select and not select(f):
3276 continue
3283 continue
3277 if (not select and name != 'shortlist' and
3284 if (not select and name != 'shortlist' and
3278 e[0].__module__ != __name__):
3285 e[0].__module__ != __name__):
3279 continue
3286 continue
3280 if name == "shortlist" and not f.startswith("^"):
3287 if name == "shortlist" and not f.startswith("^"):
3281 continue
3288 continue
3282 f = f.lstrip("^")
3289 f = f.lstrip("^")
3283 if not ui.debugflag and f.startswith("debug"):
3290 if not ui.debugflag and f.startswith("debug"):
3284 continue
3291 continue
3285 doc = e[0].__doc__
3292 doc = e[0].__doc__
3286 if doc and 'DEPRECATED' in doc and not ui.verbose:
3293 if doc and 'DEPRECATED' in doc and not ui.verbose:
3287 continue
3294 continue
3288 doc = gettext(doc)
3295 doc = gettext(doc)
3289 if not doc:
3296 if not doc:
3290 doc = _("(no help text available)")
3297 doc = _("(no help text available)")
3291 h[f] = doc.splitlines()[0].rstrip()
3298 h[f] = doc.splitlines()[0].rstrip()
3292 cmds[f] = c.lstrip("^")
3299 cmds[f] = c.lstrip("^")
3293
3300
3294 rst = []
3301 rst = []
3295 if not h:
3302 if not h:
3296 if not ui.quiet:
3303 if not ui.quiet:
3297 rst.append(_('no commands defined\n'))
3304 rst.append(_('no commands defined\n'))
3298 return rst
3305 return rst
3299
3306
3300 if not ui.quiet:
3307 if not ui.quiet:
3301 rst.append(header)
3308 rst.append(header)
3302 fns = sorted(h)
3309 fns = sorted(h)
3303 for f in fns:
3310 for f in fns:
3304 if ui.verbose:
3311 if ui.verbose:
3305 commands = cmds[f].replace("|",", ")
3312 commands = cmds[f].replace("|",", ")
3306 rst.append(" :%s: %s\n" % (commands, h[f]))
3313 rst.append(" :%s: %s\n" % (commands, h[f]))
3307 else:
3314 else:
3308 rst.append(' :%s: %s\n' % (f, h[f]))
3315 rst.append(' :%s: %s\n' % (f, h[f]))
3309
3316
3310 if not name:
3317 if not name:
3311 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3318 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3312 if exts:
3319 if exts:
3313 rst.append('\n')
3320 rst.append('\n')
3314 rst.extend(exts)
3321 rst.extend(exts)
3315
3322
3316 rst.append(_("\nadditional help topics:\n\n"))
3323 rst.append(_("\nadditional help topics:\n\n"))
3317 topics = []
3324 topics = []
3318 for names, header, doc in help.helptable:
3325 for names, header, doc in help.helptable:
3319 topics.append((names[0], header))
3326 topics.append((names[0], header))
3320 for t, desc in topics:
3327 for t, desc in topics:
3321 rst.append(" :%s: %s\n" % (t, desc))
3328 rst.append(" :%s: %s\n" % (t, desc))
3322
3329
3323 optlist = []
3330 optlist = []
3324 if not ui.quiet:
3331 if not ui.quiet:
3325 if ui.verbose:
3332 if ui.verbose:
3326 optlist.append((_("global options:"), globalopts))
3333 optlist.append((_("global options:"), globalopts))
3327 if name == 'shortlist':
3334 if name == 'shortlist':
3328 optlist.append((_('use "hg help" for the full list '
3335 optlist.append((_('use "hg help" for the full list '
3329 'of commands'), ()))
3336 'of commands'), ()))
3330 else:
3337 else:
3331 if name == 'shortlist':
3338 if name == 'shortlist':
3332 msg = _('use "hg help" for the full list of commands '
3339 msg = _('use "hg help" for the full list of commands '
3333 'or "hg -v" for details')
3340 'or "hg -v" for details')
3334 elif name and not full:
3341 elif name and not full:
3335 msg = _('use "hg help %s" to show the full help '
3342 msg = _('use "hg help %s" to show the full help '
3336 'text') % name
3343 'text') % name
3337 else:
3344 else:
3338 msg = _('use "hg -v help%s" to show builtin aliases and '
3345 msg = _('use "hg -v help%s" to show builtin aliases and '
3339 'global options') % (name and " " + name or "")
3346 'global options') % (name and " " + name or "")
3340 optlist.append((msg, ()))
3347 optlist.append((msg, ()))
3341
3348
3342 if optlist:
3349 if optlist:
3343 for title, options in optlist:
3350 for title, options in optlist:
3344 rst.append('\n%s\n' % title)
3351 rst.append('\n%s\n' % title)
3345 if options:
3352 if options:
3346 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3353 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3347 return rst
3354 return rst
3348
3355
3349 def helptopic(name):
3356 def helptopic(name):
3350 for names, header, doc in help.helptable:
3357 for names, header, doc in help.helptable:
3351 if name in names:
3358 if name in names:
3352 break
3359 break
3353 else:
3360 else:
3354 raise error.UnknownCommand(name)
3361 raise error.UnknownCommand(name)
3355
3362
3356 rst = ["%s\n\n" % header]
3363 rst = ["%s\n\n" % header]
3357 # description
3364 # description
3358 if not doc:
3365 if not doc:
3359 rst.append(" %s\n" % _("(no help text available)"))
3366 rst.append(" %s\n" % _("(no help text available)"))
3360 if util.safehasattr(doc, '__call__'):
3367 if util.safehasattr(doc, '__call__'):
3361 rst += [" %s\n" % l for l in doc().splitlines()]
3368 rst += [" %s\n" % l for l in doc().splitlines()]
3362
3369
3363 try:
3370 try:
3364 cmdutil.findcmd(name, table)
3371 cmdutil.findcmd(name, table)
3365 rst.append(_('\nuse "hg help -c %s" to see help for '
3372 rst.append(_('\nuse "hg help -c %s" to see help for '
3366 'the %s command\n') % (name, name))
3373 'the %s command\n') % (name, name))
3367 except error.UnknownCommand:
3374 except error.UnknownCommand:
3368 pass
3375 pass
3369 return rst
3376 return rst
3370
3377
3371 def helpext(name):
3378 def helpext(name):
3372 try:
3379 try:
3373 mod = extensions.find(name)
3380 mod = extensions.find(name)
3374 doc = gettext(mod.__doc__) or _('no help text available')
3381 doc = gettext(mod.__doc__) or _('no help text available')
3375 except KeyError:
3382 except KeyError:
3376 mod = None
3383 mod = None
3377 doc = extensions.disabledext(name)
3384 doc = extensions.disabledext(name)
3378 if not doc:
3385 if not doc:
3379 raise error.UnknownCommand(name)
3386 raise error.UnknownCommand(name)
3380
3387
3381 if '\n' not in doc:
3388 if '\n' not in doc:
3382 head, tail = doc, ""
3389 head, tail = doc, ""
3383 else:
3390 else:
3384 head, tail = doc.split('\n', 1)
3391 head, tail = doc.split('\n', 1)
3385 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3392 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3386 if tail:
3393 if tail:
3387 rst.extend(tail.splitlines(True))
3394 rst.extend(tail.splitlines(True))
3388 rst.append('\n')
3395 rst.append('\n')
3389
3396
3390 if mod:
3397 if mod:
3391 try:
3398 try:
3392 ct = mod.cmdtable
3399 ct = mod.cmdtable
3393 except AttributeError:
3400 except AttributeError:
3394 ct = {}
3401 ct = {}
3395 modcmds = set([c.split('|', 1)[0] for c in ct])
3402 modcmds = set([c.split('|', 1)[0] for c in ct])
3396 rst.extend(helplist(modcmds.__contains__))
3403 rst.extend(helplist(modcmds.__contains__))
3397 else:
3404 else:
3398 rst.append(_('use "hg help extensions" for information on enabling '
3405 rst.append(_('use "hg help extensions" for information on enabling '
3399 'extensions\n'))
3406 'extensions\n'))
3400 return rst
3407 return rst
3401
3408
3402 def helpextcmd(name):
3409 def helpextcmd(name):
3403 cmd, ext, mod = extensions.disabledcmd(ui, name,
3410 cmd, ext, mod = extensions.disabledcmd(ui, name,
3404 ui.configbool('ui', 'strict'))
3411 ui.configbool('ui', 'strict'))
3405 doc = gettext(mod.__doc__).splitlines()[0]
3412 doc = gettext(mod.__doc__).splitlines()[0]
3406
3413
3407 rst = help.listexts(_("'%s' is provided by the following "
3414 rst = help.listexts(_("'%s' is provided by the following "
3408 "extension:") % cmd, {ext: doc}, indent=4)
3415 "extension:") % cmd, {ext: doc}, indent=4)
3409 rst.append('\n')
3416 rst.append('\n')
3410 rst.append(_('use "hg help extensions" for information on enabling '
3417 rst.append(_('use "hg help extensions" for information on enabling '
3411 'extensions\n'))
3418 'extensions\n'))
3412 return rst
3419 return rst
3413
3420
3414
3421
3415 rst = []
3422 rst = []
3416 kw = opts.get('keyword')
3423 kw = opts.get('keyword')
3417 if kw:
3424 if kw:
3418 matches = help.topicmatch(kw)
3425 matches = help.topicmatch(kw)
3419 for t, title in (('topics', _('Topics')),
3426 for t, title in (('topics', _('Topics')),
3420 ('commands', _('Commands')),
3427 ('commands', _('Commands')),
3421 ('extensions', _('Extensions')),
3428 ('extensions', _('Extensions')),
3422 ('extensioncommands', _('Extension Commands'))):
3429 ('extensioncommands', _('Extension Commands'))):
3423 if matches[t]:
3430 if matches[t]:
3424 rst.append('%s:\n\n' % title)
3431 rst.append('%s:\n\n' % title)
3425 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3432 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3426 rst.append('\n')
3433 rst.append('\n')
3427 elif name and name != 'shortlist':
3434 elif name and name != 'shortlist':
3428 i = None
3435 i = None
3429 if unknowncmd:
3436 if unknowncmd:
3430 queries = (helpextcmd,)
3437 queries = (helpextcmd,)
3431 elif opts.get('extension'):
3438 elif opts.get('extension'):
3432 queries = (helpext,)
3439 queries = (helpext,)
3433 elif opts.get('command'):
3440 elif opts.get('command'):
3434 queries = (helpcmd,)
3441 queries = (helpcmd,)
3435 else:
3442 else:
3436 queries = (helptopic, helpcmd, helpext, helpextcmd)
3443 queries = (helptopic, helpcmd, helpext, helpextcmd)
3437 for f in queries:
3444 for f in queries:
3438 try:
3445 try:
3439 rst = f(name)
3446 rst = f(name)
3440 i = None
3447 i = None
3441 break
3448 break
3442 except error.UnknownCommand, inst:
3449 except error.UnknownCommand, inst:
3443 i = inst
3450 i = inst
3444 if i:
3451 if i:
3445 raise i
3452 raise i
3446 else:
3453 else:
3447 # program name
3454 # program name
3448 if not ui.quiet:
3455 if not ui.quiet:
3449 rst = [_("Mercurial Distributed SCM\n"), '\n']
3456 rst = [_("Mercurial Distributed SCM\n"), '\n']
3450 rst.extend(helplist())
3457 rst.extend(helplist())
3451
3458
3452 keep = ui.verbose and ['verbose'] or []
3459 keep = ui.verbose and ['verbose'] or []
3453 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3460 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3454 ui.write(formatted)
3461 ui.write(formatted)
3455
3462
3456
3463
3457 @command('identify|id',
3464 @command('identify|id',
3458 [('r', 'rev', '',
3465 [('r', 'rev', '',
3459 _('identify the specified revision'), _('REV')),
3466 _('identify the specified revision'), _('REV')),
3460 ('n', 'num', None, _('show local revision number')),
3467 ('n', 'num', None, _('show local revision number')),
3461 ('i', 'id', None, _('show global revision id')),
3468 ('i', 'id', None, _('show global revision id')),
3462 ('b', 'branch', None, _('show branch')),
3469 ('b', 'branch', None, _('show branch')),
3463 ('t', 'tags', None, _('show tags')),
3470 ('t', 'tags', None, _('show tags')),
3464 ('B', 'bookmarks', None, _('show bookmarks')),
3471 ('B', 'bookmarks', None, _('show bookmarks')),
3465 ] + remoteopts,
3472 ] + remoteopts,
3466 _('[-nibtB] [-r REV] [SOURCE]'))
3473 _('[-nibtB] [-r REV] [SOURCE]'))
3467 def identify(ui, repo, source=None, rev=None,
3474 def identify(ui, repo, source=None, rev=None,
3468 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3475 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3469 """identify the working copy or specified revision
3476 """identify the working copy or specified revision
3470
3477
3471 Print a summary identifying the repository state at REV using one or
3478 Print a summary identifying the repository state at REV using one or
3472 two parent hash identifiers, followed by a "+" if the working
3479 two parent hash identifiers, followed by a "+" if the working
3473 directory has uncommitted changes, the branch name (if not default),
3480 directory has uncommitted changes, the branch name (if not default),
3474 a list of tags, and a list of bookmarks.
3481 a list of tags, and a list of bookmarks.
3475
3482
3476 When REV is not given, print a summary of the current state of the
3483 When REV is not given, print a summary of the current state of the
3477 repository.
3484 repository.
3478
3485
3479 Specifying a path to a repository root or Mercurial bundle will
3486 Specifying a path to a repository root or Mercurial bundle will
3480 cause lookup to operate on that repository/bundle.
3487 cause lookup to operate on that repository/bundle.
3481
3488
3482 .. container:: verbose
3489 .. container:: verbose
3483
3490
3484 Examples:
3491 Examples:
3485
3492
3486 - generate a build identifier for the working directory::
3493 - generate a build identifier for the working directory::
3487
3494
3488 hg id --id > build-id.dat
3495 hg id --id > build-id.dat
3489
3496
3490 - find the revision corresponding to a tag::
3497 - find the revision corresponding to a tag::
3491
3498
3492 hg id -n -r 1.3
3499 hg id -n -r 1.3
3493
3500
3494 - check the most recent revision of a remote repository::
3501 - check the most recent revision of a remote repository::
3495
3502
3496 hg id -r tip http://selenic.com/hg/
3503 hg id -r tip http://selenic.com/hg/
3497
3504
3498 Returns 0 if successful.
3505 Returns 0 if successful.
3499 """
3506 """
3500
3507
3501 if not repo and not source:
3508 if not repo and not source:
3502 raise util.Abort(_("there is no Mercurial repository here "
3509 raise util.Abort(_("there is no Mercurial repository here "
3503 "(.hg not found)"))
3510 "(.hg not found)"))
3504
3511
3505 hexfunc = ui.debugflag and hex or short
3512 hexfunc = ui.debugflag and hex or short
3506 default = not (num or id or branch or tags or bookmarks)
3513 default = not (num or id or branch or tags or bookmarks)
3507 output = []
3514 output = []
3508 revs = []
3515 revs = []
3509
3516
3510 if source:
3517 if source:
3511 source, branches = hg.parseurl(ui.expandpath(source))
3518 source, branches = hg.parseurl(ui.expandpath(source))
3512 peer = hg.peer(ui, opts, source)
3519 peer = hg.peer(ui, opts, source)
3513 repo = peer.local()
3520 repo = peer.local()
3514 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3521 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3515
3522
3516 if not repo:
3523 if not repo:
3517 if num or branch or tags:
3524 if num or branch or tags:
3518 raise util.Abort(
3525 raise util.Abort(
3519 _("can't query remote revision number, branch, or tags"))
3526 _("can't query remote revision number, branch, or tags"))
3520 if not rev and revs:
3527 if not rev and revs:
3521 rev = revs[0]
3528 rev = revs[0]
3522 if not rev:
3529 if not rev:
3523 rev = "tip"
3530 rev = "tip"
3524
3531
3525 remoterev = peer.lookup(rev)
3532 remoterev = peer.lookup(rev)
3526 if default or id:
3533 if default or id:
3527 output = [hexfunc(remoterev)]
3534 output = [hexfunc(remoterev)]
3528
3535
3529 def getbms():
3536 def getbms():
3530 bms = []
3537 bms = []
3531
3538
3532 if 'bookmarks' in peer.listkeys('namespaces'):
3539 if 'bookmarks' in peer.listkeys('namespaces'):
3533 hexremoterev = hex(remoterev)
3540 hexremoterev = hex(remoterev)
3534 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3541 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3535 if bmr == hexremoterev]
3542 if bmr == hexremoterev]
3536
3543
3537 return bms
3544 return bms
3538
3545
3539 if bookmarks:
3546 if bookmarks:
3540 output.extend(getbms())
3547 output.extend(getbms())
3541 elif default and not ui.quiet:
3548 elif default and not ui.quiet:
3542 # multiple bookmarks for a single parent separated by '/'
3549 # multiple bookmarks for a single parent separated by '/'
3543 bm = '/'.join(getbms())
3550 bm = '/'.join(getbms())
3544 if bm:
3551 if bm:
3545 output.append(bm)
3552 output.append(bm)
3546 else:
3553 else:
3547 if not rev:
3554 if not rev:
3548 ctx = repo[None]
3555 ctx = repo[None]
3549 parents = ctx.parents()
3556 parents = ctx.parents()
3550 changed = ""
3557 changed = ""
3551 if default or id or num:
3558 if default or id or num:
3552 if (util.any(repo.status())
3559 if (util.any(repo.status())
3553 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3560 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3554 changed = '+'
3561 changed = '+'
3555 if default or id:
3562 if default or id:
3556 output = ["%s%s" %
3563 output = ["%s%s" %
3557 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3564 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3558 if num:
3565 if num:
3559 output.append("%s%s" %
3566 output.append("%s%s" %
3560 ('+'.join([str(p.rev()) for p in parents]), changed))
3567 ('+'.join([str(p.rev()) for p in parents]), changed))
3561 else:
3568 else:
3562 ctx = scmutil.revsingle(repo, rev)
3569 ctx = scmutil.revsingle(repo, rev)
3563 if default or id:
3570 if default or id:
3564 output = [hexfunc(ctx.node())]
3571 output = [hexfunc(ctx.node())]
3565 if num:
3572 if num:
3566 output.append(str(ctx.rev()))
3573 output.append(str(ctx.rev()))
3567
3574
3568 if default and not ui.quiet:
3575 if default and not ui.quiet:
3569 b = ctx.branch()
3576 b = ctx.branch()
3570 if b != 'default':
3577 if b != 'default':
3571 output.append("(%s)" % b)
3578 output.append("(%s)" % b)
3572
3579
3573 # multiple tags for a single parent separated by '/'
3580 # multiple tags for a single parent separated by '/'
3574 t = '/'.join(ctx.tags())
3581 t = '/'.join(ctx.tags())
3575 if t:
3582 if t:
3576 output.append(t)
3583 output.append(t)
3577
3584
3578 # multiple bookmarks for a single parent separated by '/'
3585 # multiple bookmarks for a single parent separated by '/'
3579 bm = '/'.join(ctx.bookmarks())
3586 bm = '/'.join(ctx.bookmarks())
3580 if bm:
3587 if bm:
3581 output.append(bm)
3588 output.append(bm)
3582 else:
3589 else:
3583 if branch:
3590 if branch:
3584 output.append(ctx.branch())
3591 output.append(ctx.branch())
3585
3592
3586 if tags:
3593 if tags:
3587 output.extend(ctx.tags())
3594 output.extend(ctx.tags())
3588
3595
3589 if bookmarks:
3596 if bookmarks:
3590 output.extend(ctx.bookmarks())
3597 output.extend(ctx.bookmarks())
3591
3598
3592 ui.write("%s\n" % ' '.join(output))
3599 ui.write("%s\n" % ' '.join(output))
3593
3600
3594 @command('import|patch',
3601 @command('import|patch',
3595 [('p', 'strip', 1,
3602 [('p', 'strip', 1,
3596 _('directory strip option for patch. This has the same '
3603 _('directory strip option for patch. This has the same '
3597 'meaning as the corresponding patch option'), _('NUM')),
3604 'meaning as the corresponding patch option'), _('NUM')),
3598 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3605 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3599 ('e', 'edit', False, _('invoke editor on commit messages')),
3606 ('e', 'edit', False, _('invoke editor on commit messages')),
3600 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3607 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3601 ('', 'no-commit', None,
3608 ('', 'no-commit', None,
3602 _("don't commit, just update the working directory")),
3609 _("don't commit, just update the working directory")),
3603 ('', 'bypass', None,
3610 ('', 'bypass', None,
3604 _("apply patch without touching the working directory")),
3611 _("apply patch without touching the working directory")),
3605 ('', 'exact', None,
3612 ('', 'exact', None,
3606 _('apply patch to the nodes from which it was generated')),
3613 _('apply patch to the nodes from which it was generated')),
3607 ('', 'import-branch', None,
3614 ('', 'import-branch', None,
3608 _('use any branch information in patch (implied by --exact)'))] +
3615 _('use any branch information in patch (implied by --exact)'))] +
3609 commitopts + commitopts2 + similarityopts,
3616 commitopts + commitopts2 + similarityopts,
3610 _('[OPTION]... PATCH...'))
3617 _('[OPTION]... PATCH...'))
3611 def import_(ui, repo, patch1=None, *patches, **opts):
3618 def import_(ui, repo, patch1=None, *patches, **opts):
3612 """import an ordered set of patches
3619 """import an ordered set of patches
3613
3620
3614 Import a list of patches and commit them individually (unless
3621 Import a list of patches and commit them individually (unless
3615 --no-commit is specified).
3622 --no-commit is specified).
3616
3623
3617 If there are outstanding changes in the working directory, import
3624 If there are outstanding changes in the working directory, import
3618 will abort unless given the -f/--force flag.
3625 will abort unless given the -f/--force flag.
3619
3626
3620 You can import a patch straight from a mail message. Even patches
3627 You can import a patch straight from a mail message. Even patches
3621 as attachments work (to use the body part, it must have type
3628 as attachments work (to use the body part, it must have type
3622 text/plain or text/x-patch). From and Subject headers of email
3629 text/plain or text/x-patch). From and Subject headers of email
3623 message are used as default committer and commit message. All
3630 message are used as default committer and commit message. All
3624 text/plain body parts before first diff are added to commit
3631 text/plain body parts before first diff are added to commit
3625 message.
3632 message.
3626
3633
3627 If the imported patch was generated by :hg:`export`, user and
3634 If the imported patch was generated by :hg:`export`, user and
3628 description from patch override values from message headers and
3635 description from patch override values from message headers and
3629 body. Values given on command line with -m/--message and -u/--user
3636 body. Values given on command line with -m/--message and -u/--user
3630 override these.
3637 override these.
3631
3638
3632 If --exact is specified, import will set the working directory to
3639 If --exact is specified, import will set the working directory to
3633 the parent of each patch before applying it, and will abort if the
3640 the parent of each patch before applying it, and will abort if the
3634 resulting changeset has a different ID than the one recorded in
3641 resulting changeset has a different ID than the one recorded in
3635 the patch. This may happen due to character set problems or other
3642 the patch. This may happen due to character set problems or other
3636 deficiencies in the text patch format.
3643 deficiencies in the text patch format.
3637
3644
3638 Use --bypass to apply and commit patches directly to the
3645 Use --bypass to apply and commit patches directly to the
3639 repository, not touching the working directory. Without --exact,
3646 repository, not touching the working directory. Without --exact,
3640 patches will be applied on top of the working directory parent
3647 patches will be applied on top of the working directory parent
3641 revision.
3648 revision.
3642
3649
3643 With -s/--similarity, hg will attempt to discover renames and
3650 With -s/--similarity, hg will attempt to discover renames and
3644 copies in the patch in the same way as :hg:`addremove`.
3651 copies in the patch in the same way as :hg:`addremove`.
3645
3652
3646 To read a patch from standard input, use "-" as the patch name. If
3653 To read a patch from standard input, use "-" as the patch name. If
3647 a URL is specified, the patch will be downloaded from it.
3654 a URL is specified, the patch will be downloaded from it.
3648 See :hg:`help dates` for a list of formats valid for -d/--date.
3655 See :hg:`help dates` for a list of formats valid for -d/--date.
3649
3656
3650 .. container:: verbose
3657 .. container:: verbose
3651
3658
3652 Examples:
3659 Examples:
3653
3660
3654 - import a traditional patch from a website and detect renames::
3661 - import a traditional patch from a website and detect renames::
3655
3662
3656 hg import -s 80 http://example.com/bugfix.patch
3663 hg import -s 80 http://example.com/bugfix.patch
3657
3664
3658 - import a changeset from an hgweb server::
3665 - import a changeset from an hgweb server::
3659
3666
3660 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3667 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3661
3668
3662 - import all the patches in an Unix-style mbox::
3669 - import all the patches in an Unix-style mbox::
3663
3670
3664 hg import incoming-patches.mbox
3671 hg import incoming-patches.mbox
3665
3672
3666 - attempt to exactly restore an exported changeset (not always
3673 - attempt to exactly restore an exported changeset (not always
3667 possible)::
3674 possible)::
3668
3675
3669 hg import --exact proposed-fix.patch
3676 hg import --exact proposed-fix.patch
3670
3677
3671 Returns 0 on success.
3678 Returns 0 on success.
3672 """
3679 """
3673
3680
3674 if not patch1:
3681 if not patch1:
3675 raise util.Abort(_('need at least one patch to import'))
3682 raise util.Abort(_('need at least one patch to import'))
3676
3683
3677 patches = (patch1,) + patches
3684 patches = (patch1,) + patches
3678
3685
3679 date = opts.get('date')
3686 date = opts.get('date')
3680 if date:
3687 if date:
3681 opts['date'] = util.parsedate(date)
3688 opts['date'] = util.parsedate(date)
3682
3689
3683 editor = cmdutil.commiteditor
3690 editor = cmdutil.commiteditor
3684 if opts.get('edit'):
3691 if opts.get('edit'):
3685 editor = cmdutil.commitforceeditor
3692 editor = cmdutil.commitforceeditor
3686
3693
3687 update = not opts.get('bypass')
3694 update = not opts.get('bypass')
3688 if not update and opts.get('no_commit'):
3695 if not update and opts.get('no_commit'):
3689 raise util.Abort(_('cannot use --no-commit with --bypass'))
3696 raise util.Abort(_('cannot use --no-commit with --bypass'))
3690 try:
3697 try:
3691 sim = float(opts.get('similarity') or 0)
3698 sim = float(opts.get('similarity') or 0)
3692 except ValueError:
3699 except ValueError:
3693 raise util.Abort(_('similarity must be a number'))
3700 raise util.Abort(_('similarity must be a number'))
3694 if sim < 0 or sim > 100:
3701 if sim < 0 or sim > 100:
3695 raise util.Abort(_('similarity must be between 0 and 100'))
3702 raise util.Abort(_('similarity must be between 0 and 100'))
3696 if sim and not update:
3703 if sim and not update:
3697 raise util.Abort(_('cannot use --similarity with --bypass'))
3704 raise util.Abort(_('cannot use --similarity with --bypass'))
3698
3705
3699 if (opts.get('exact') or not opts.get('force')) and update:
3706 if (opts.get('exact') or not opts.get('force')) and update:
3700 cmdutil.bailifchanged(repo)
3707 cmdutil.bailifchanged(repo)
3701
3708
3702 base = opts["base"]
3709 base = opts["base"]
3703 strip = opts["strip"]
3710 strip = opts["strip"]
3704 wlock = lock = tr = None
3711 wlock = lock = tr = None
3705 msgs = []
3712 msgs = []
3706
3713
3707 def checkexact(repo, n, nodeid):
3714 def checkexact(repo, n, nodeid):
3708 if opts.get('exact') and hex(n) != nodeid:
3715 if opts.get('exact') and hex(n) != nodeid:
3709 repo.rollback()
3716 repo.rollback()
3710 raise util.Abort(_('patch is damaged or loses information'))
3717 raise util.Abort(_('patch is damaged or loses information'))
3711
3718
3712 def tryone(ui, hunk, parents):
3719 def tryone(ui, hunk, parents):
3713 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3720 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3714 patch.extract(ui, hunk)
3721 patch.extract(ui, hunk)
3715
3722
3716 if not tmpname:
3723 if not tmpname:
3717 return (None, None)
3724 return (None, None)
3718 msg = _('applied to working directory')
3725 msg = _('applied to working directory')
3719
3726
3720 try:
3727 try:
3721 cmdline_message = cmdutil.logmessage(ui, opts)
3728 cmdline_message = cmdutil.logmessage(ui, opts)
3722 if cmdline_message:
3729 if cmdline_message:
3723 # pickup the cmdline msg
3730 # pickup the cmdline msg
3724 message = cmdline_message
3731 message = cmdline_message
3725 elif message:
3732 elif message:
3726 # pickup the patch msg
3733 # pickup the patch msg
3727 message = message.strip()
3734 message = message.strip()
3728 else:
3735 else:
3729 # launch the editor
3736 # launch the editor
3730 message = None
3737 message = None
3731 ui.debug('message:\n%s\n' % message)
3738 ui.debug('message:\n%s\n' % message)
3732
3739
3733 if len(parents) == 1:
3740 if len(parents) == 1:
3734 parents.append(repo[nullid])
3741 parents.append(repo[nullid])
3735 if opts.get('exact'):
3742 if opts.get('exact'):
3736 if not nodeid or not p1:
3743 if not nodeid or not p1:
3737 raise util.Abort(_('not a Mercurial patch'))
3744 raise util.Abort(_('not a Mercurial patch'))
3738 p1 = repo[p1]
3745 p1 = repo[p1]
3739 p2 = repo[p2 or nullid]
3746 p2 = repo[p2 or nullid]
3740 elif p2:
3747 elif p2:
3741 try:
3748 try:
3742 p1 = repo[p1]
3749 p1 = repo[p1]
3743 p2 = repo[p2]
3750 p2 = repo[p2]
3744 # Without any options, consider p2 only if the
3751 # Without any options, consider p2 only if the
3745 # patch is being applied on top of the recorded
3752 # patch is being applied on top of the recorded
3746 # first parent.
3753 # first parent.
3747 if p1 != parents[0]:
3754 if p1 != parents[0]:
3748 p1 = parents[0]
3755 p1 = parents[0]
3749 p2 = repo[nullid]
3756 p2 = repo[nullid]
3750 except error.RepoError:
3757 except error.RepoError:
3751 p1, p2 = parents
3758 p1, p2 = parents
3752 else:
3759 else:
3753 p1, p2 = parents
3760 p1, p2 = parents
3754
3761
3755 n = None
3762 n = None
3756 if update:
3763 if update:
3757 if p1 != parents[0]:
3764 if p1 != parents[0]:
3758 hg.clean(repo, p1.node())
3765 hg.clean(repo, p1.node())
3759 if p2 != parents[1]:
3766 if p2 != parents[1]:
3760 repo.setparents(p1.node(), p2.node())
3767 repo.setparents(p1.node(), p2.node())
3761
3768
3762 if opts.get('exact') or opts.get('import_branch'):
3769 if opts.get('exact') or opts.get('import_branch'):
3763 repo.dirstate.setbranch(branch or 'default')
3770 repo.dirstate.setbranch(branch or 'default')
3764
3771
3765 files = set()
3772 files = set()
3766 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3773 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3767 eolmode=None, similarity=sim / 100.0)
3774 eolmode=None, similarity=sim / 100.0)
3768 files = list(files)
3775 files = list(files)
3769 if opts.get('no_commit'):
3776 if opts.get('no_commit'):
3770 if message:
3777 if message:
3771 msgs.append(message)
3778 msgs.append(message)
3772 else:
3779 else:
3773 if opts.get('exact') or p2:
3780 if opts.get('exact') or p2:
3774 # If you got here, you either use --force and know what
3781 # If you got here, you either use --force and know what
3775 # you are doing or used --exact or a merge patch while
3782 # you are doing or used --exact or a merge patch while
3776 # being updated to its first parent.
3783 # being updated to its first parent.
3777 m = None
3784 m = None
3778 else:
3785 else:
3779 m = scmutil.matchfiles(repo, files or [])
3786 m = scmutil.matchfiles(repo, files or [])
3780 n = repo.commit(message, opts.get('user') or user,
3787 n = repo.commit(message, opts.get('user') or user,
3781 opts.get('date') or date, match=m,
3788 opts.get('date') or date, match=m,
3782 editor=editor)
3789 editor=editor)
3783 checkexact(repo, n, nodeid)
3790 checkexact(repo, n, nodeid)
3784 else:
3791 else:
3785 if opts.get('exact') or opts.get('import_branch'):
3792 if opts.get('exact') or opts.get('import_branch'):
3786 branch = branch or 'default'
3793 branch = branch or 'default'
3787 else:
3794 else:
3788 branch = p1.branch()
3795 branch = p1.branch()
3789 store = patch.filestore()
3796 store = patch.filestore()
3790 try:
3797 try:
3791 files = set()
3798 files = set()
3792 try:
3799 try:
3793 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3800 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3794 files, eolmode=None)
3801 files, eolmode=None)
3795 except patch.PatchError, e:
3802 except patch.PatchError, e:
3796 raise util.Abort(str(e))
3803 raise util.Abort(str(e))
3797 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3804 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3798 message,
3805 message,
3799 opts.get('user') or user,
3806 opts.get('user') or user,
3800 opts.get('date') or date,
3807 opts.get('date') or date,
3801 branch, files, store,
3808 branch, files, store,
3802 editor=cmdutil.commiteditor)
3809 editor=cmdutil.commiteditor)
3803 repo.savecommitmessage(memctx.description())
3810 repo.savecommitmessage(memctx.description())
3804 n = memctx.commit()
3811 n = memctx.commit()
3805 checkexact(repo, n, nodeid)
3812 checkexact(repo, n, nodeid)
3806 finally:
3813 finally:
3807 store.close()
3814 store.close()
3808 if n:
3815 if n:
3809 # i18n: refers to a short changeset id
3816 # i18n: refers to a short changeset id
3810 msg = _('created %s') % short(n)
3817 msg = _('created %s') % short(n)
3811 return (msg, n)
3818 return (msg, n)
3812 finally:
3819 finally:
3813 os.unlink(tmpname)
3820 os.unlink(tmpname)
3814
3821
3815 try:
3822 try:
3816 try:
3823 try:
3817 wlock = repo.wlock()
3824 wlock = repo.wlock()
3818 if not opts.get('no_commit'):
3825 if not opts.get('no_commit'):
3819 lock = repo.lock()
3826 lock = repo.lock()
3820 tr = repo.transaction('import')
3827 tr = repo.transaction('import')
3821 parents = repo.parents()
3828 parents = repo.parents()
3822 for patchurl in patches:
3829 for patchurl in patches:
3823 if patchurl == '-':
3830 if patchurl == '-':
3824 ui.status(_('applying patch from stdin\n'))
3831 ui.status(_('applying patch from stdin\n'))
3825 patchfile = ui.fin
3832 patchfile = ui.fin
3826 patchurl = 'stdin' # for error message
3833 patchurl = 'stdin' # for error message
3827 else:
3834 else:
3828 patchurl = os.path.join(base, patchurl)
3835 patchurl = os.path.join(base, patchurl)
3829 ui.status(_('applying %s\n') % patchurl)
3836 ui.status(_('applying %s\n') % patchurl)
3830 patchfile = url.open(ui, patchurl)
3837 patchfile = url.open(ui, patchurl)
3831
3838
3832 haspatch = False
3839 haspatch = False
3833 for hunk in patch.split(patchfile):
3840 for hunk in patch.split(patchfile):
3834 (msg, node) = tryone(ui, hunk, parents)
3841 (msg, node) = tryone(ui, hunk, parents)
3835 if msg:
3842 if msg:
3836 haspatch = True
3843 haspatch = True
3837 ui.note(msg + '\n')
3844 ui.note(msg + '\n')
3838 if update or opts.get('exact'):
3845 if update or opts.get('exact'):
3839 parents = repo.parents()
3846 parents = repo.parents()
3840 else:
3847 else:
3841 parents = [repo[node]]
3848 parents = [repo[node]]
3842
3849
3843 if not haspatch:
3850 if not haspatch:
3844 raise util.Abort(_('%s: no diffs found') % patchurl)
3851 raise util.Abort(_('%s: no diffs found') % patchurl)
3845
3852
3846 if tr:
3853 if tr:
3847 tr.close()
3854 tr.close()
3848 if msgs:
3855 if msgs:
3849 repo.savecommitmessage('\n* * *\n'.join(msgs))
3856 repo.savecommitmessage('\n* * *\n'.join(msgs))
3850 except: # re-raises
3857 except: # re-raises
3851 # wlock.release() indirectly calls dirstate.write(): since
3858 # wlock.release() indirectly calls dirstate.write(): since
3852 # we're crashing, we do not want to change the working dir
3859 # we're crashing, we do not want to change the working dir
3853 # parent after all, so make sure it writes nothing
3860 # parent after all, so make sure it writes nothing
3854 repo.dirstate.invalidate()
3861 repo.dirstate.invalidate()
3855 raise
3862 raise
3856 finally:
3863 finally:
3857 if tr:
3864 if tr:
3858 tr.release()
3865 tr.release()
3859 release(lock, wlock)
3866 release(lock, wlock)
3860
3867
3861 @command('incoming|in',
3868 @command('incoming|in',
3862 [('f', 'force', None,
3869 [('f', 'force', None,
3863 _('run even if remote repository is unrelated')),
3870 _('run even if remote repository is unrelated')),
3864 ('n', 'newest-first', None, _('show newest record first')),
3871 ('n', 'newest-first', None, _('show newest record first')),
3865 ('', 'bundle', '',
3872 ('', 'bundle', '',
3866 _('file to store the bundles into'), _('FILE')),
3873 _('file to store the bundles into'), _('FILE')),
3867 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3874 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3868 ('B', 'bookmarks', False, _("compare bookmarks")),
3875 ('B', 'bookmarks', False, _("compare bookmarks")),
3869 ('b', 'branch', [],
3876 ('b', 'branch', [],
3870 _('a specific branch you would like to pull'), _('BRANCH')),
3877 _('a specific branch you would like to pull'), _('BRANCH')),
3871 ] + logopts + remoteopts + subrepoopts,
3878 ] + logopts + remoteopts + subrepoopts,
3872 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3879 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3873 def incoming(ui, repo, source="default", **opts):
3880 def incoming(ui, repo, source="default", **opts):
3874 """show new changesets found in source
3881 """show new changesets found in source
3875
3882
3876 Show new changesets found in the specified path/URL or the default
3883 Show new changesets found in the specified path/URL or the default
3877 pull location. These are the changesets that would have been pulled
3884 pull location. These are the changesets that would have been pulled
3878 if a pull at the time you issued this command.
3885 if a pull at the time you issued this command.
3879
3886
3880 For remote repository, using --bundle avoids downloading the
3887 For remote repository, using --bundle avoids downloading the
3881 changesets twice if the incoming is followed by a pull.
3888 changesets twice if the incoming is followed by a pull.
3882
3889
3883 See pull for valid source format details.
3890 See pull for valid source format details.
3884
3891
3885 Returns 0 if there are incoming changes, 1 otherwise.
3892 Returns 0 if there are incoming changes, 1 otherwise.
3886 """
3893 """
3887 if opts.get('graph'):
3894 if opts.get('graph'):
3888 cmdutil.checkunsupportedgraphflags([], opts)
3895 cmdutil.checkunsupportedgraphflags([], opts)
3889 def display(other, chlist, displayer):
3896 def display(other, chlist, displayer):
3890 revdag = cmdutil.graphrevs(other, chlist, opts)
3897 revdag = cmdutil.graphrevs(other, chlist, opts)
3891 showparents = [ctx.node() for ctx in repo[None].parents()]
3898 showparents = [ctx.node() for ctx in repo[None].parents()]
3892 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3899 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3893 graphmod.asciiedges)
3900 graphmod.asciiedges)
3894
3901
3895 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3902 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3896 return 0
3903 return 0
3897
3904
3898 if opts.get('bundle') and opts.get('subrepos'):
3905 if opts.get('bundle') and opts.get('subrepos'):
3899 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3906 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3900
3907
3901 if opts.get('bookmarks'):
3908 if opts.get('bookmarks'):
3902 source, branches = hg.parseurl(ui.expandpath(source),
3909 source, branches = hg.parseurl(ui.expandpath(source),
3903 opts.get('branch'))
3910 opts.get('branch'))
3904 other = hg.peer(repo, opts, source)
3911 other = hg.peer(repo, opts, source)
3905 if 'bookmarks' not in other.listkeys('namespaces'):
3912 if 'bookmarks' not in other.listkeys('namespaces'):
3906 ui.warn(_("remote doesn't support bookmarks\n"))
3913 ui.warn(_("remote doesn't support bookmarks\n"))
3907 return 0
3914 return 0
3908 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3915 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3909 return bookmarks.diff(ui, repo, other)
3916 return bookmarks.diff(ui, repo, other)
3910
3917
3911 repo._subtoppath = ui.expandpath(source)
3918 repo._subtoppath = ui.expandpath(source)
3912 try:
3919 try:
3913 return hg.incoming(ui, repo, source, opts)
3920 return hg.incoming(ui, repo, source, opts)
3914 finally:
3921 finally:
3915 del repo._subtoppath
3922 del repo._subtoppath
3916
3923
3917
3924
3918 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3925 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3919 def init(ui, dest=".", **opts):
3926 def init(ui, dest=".", **opts):
3920 """create a new repository in the given directory
3927 """create a new repository in the given directory
3921
3928
3922 Initialize a new repository in the given directory. If the given
3929 Initialize a new repository in the given directory. If the given
3923 directory does not exist, it will be created.
3930 directory does not exist, it will be created.
3924
3931
3925 If no directory is given, the current directory is used.
3932 If no directory is given, the current directory is used.
3926
3933
3927 It is possible to specify an ``ssh://`` URL as the destination.
3934 It is possible to specify an ``ssh://`` URL as the destination.
3928 See :hg:`help urls` for more information.
3935 See :hg:`help urls` for more information.
3929
3936
3930 Returns 0 on success.
3937 Returns 0 on success.
3931 """
3938 """
3932 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3939 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3933
3940
3934 @command('locate',
3941 @command('locate',
3935 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3942 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3936 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3943 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3937 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3944 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3938 ] + walkopts,
3945 ] + walkopts,
3939 _('[OPTION]... [PATTERN]...'))
3946 _('[OPTION]... [PATTERN]...'))
3940 def locate(ui, repo, *pats, **opts):
3947 def locate(ui, repo, *pats, **opts):
3941 """locate files matching specific patterns
3948 """locate files matching specific patterns
3942
3949
3943 Print files under Mercurial control in the working directory whose
3950 Print files under Mercurial control in the working directory whose
3944 names match the given patterns.
3951 names match the given patterns.
3945
3952
3946 By default, this command searches all directories in the working
3953 By default, this command searches all directories in the working
3947 directory. To search just the current directory and its
3954 directory. To search just the current directory and its
3948 subdirectories, use "--include .".
3955 subdirectories, use "--include .".
3949
3956
3950 If no patterns are given to match, this command prints the names
3957 If no patterns are given to match, this command prints the names
3951 of all files under Mercurial control in the working directory.
3958 of all files under Mercurial control in the working directory.
3952
3959
3953 If you want to feed the output of this command into the "xargs"
3960 If you want to feed the output of this command into the "xargs"
3954 command, use the -0 option to both this command and "xargs". This
3961 command, use the -0 option to both this command and "xargs". This
3955 will avoid the problem of "xargs" treating single filenames that
3962 will avoid the problem of "xargs" treating single filenames that
3956 contain whitespace as multiple filenames.
3963 contain whitespace as multiple filenames.
3957
3964
3958 Returns 0 if a match is found, 1 otherwise.
3965 Returns 0 if a match is found, 1 otherwise.
3959 """
3966 """
3960 end = opts.get('print0') and '\0' or '\n'
3967 end = opts.get('print0') and '\0' or '\n'
3961 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3968 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3962
3969
3963 ret = 1
3970 ret = 1
3964 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3971 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3965 m.bad = lambda x, y: False
3972 m.bad = lambda x, y: False
3966 for abs in repo[rev].walk(m):
3973 for abs in repo[rev].walk(m):
3967 if not rev and abs not in repo.dirstate:
3974 if not rev and abs not in repo.dirstate:
3968 continue
3975 continue
3969 if opts.get('fullpath'):
3976 if opts.get('fullpath'):
3970 ui.write(repo.wjoin(abs), end)
3977 ui.write(repo.wjoin(abs), end)
3971 else:
3978 else:
3972 ui.write(((pats and m.rel(abs)) or abs), end)
3979 ui.write(((pats and m.rel(abs)) or abs), end)
3973 ret = 0
3980 ret = 0
3974
3981
3975 return ret
3982 return ret
3976
3983
3977 @command('^log|history',
3984 @command('^log|history',
3978 [('f', 'follow', None,
3985 [('f', 'follow', None,
3979 _('follow changeset history, or file history across copies and renames')),
3986 _('follow changeset history, or file history across copies and renames')),
3980 ('', 'follow-first', None,
3987 ('', 'follow-first', None,
3981 _('only follow the first parent of merge changesets (DEPRECATED)')),
3988 _('only follow the first parent of merge changesets (DEPRECATED)')),
3982 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3989 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3983 ('C', 'copies', None, _('show copied files')),
3990 ('C', 'copies', None, _('show copied files')),
3984 ('k', 'keyword', [],
3991 ('k', 'keyword', [],
3985 _('do case-insensitive search for a given text'), _('TEXT')),
3992 _('do case-insensitive search for a given text'), _('TEXT')),
3986 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3993 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3987 ('', 'removed', None, _('include revisions where files were removed')),
3994 ('', 'removed', None, _('include revisions where files were removed')),
3988 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3995 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3989 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3996 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3990 ('', 'only-branch', [],
3997 ('', 'only-branch', [],
3991 _('show only changesets within the given named branch (DEPRECATED)'),
3998 _('show only changesets within the given named branch (DEPRECATED)'),
3992 _('BRANCH')),
3999 _('BRANCH')),
3993 ('b', 'branch', [],
4000 ('b', 'branch', [],
3994 _('show changesets within the given named branch'), _('BRANCH')),
4001 _('show changesets within the given named branch'), _('BRANCH')),
3995 ('P', 'prune', [],
4002 ('P', 'prune', [],
3996 _('do not display revision or any of its ancestors'), _('REV')),
4003 _('do not display revision or any of its ancestors'), _('REV')),
3997 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
4004 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3998 ] + logopts + walkopts,
4005 ] + logopts + walkopts,
3999 _('[OPTION]... [FILE]'))
4006 _('[OPTION]... [FILE]'))
4000 def log(ui, repo, *pats, **opts):
4007 def log(ui, repo, *pats, **opts):
4001 """show revision history of entire repository or files
4008 """show revision history of entire repository or files
4002
4009
4003 Print the revision history of the specified files or the entire
4010 Print the revision history of the specified files or the entire
4004 project.
4011 project.
4005
4012
4006 If no revision range is specified, the default is ``tip:0`` unless
4013 If no revision range is specified, the default is ``tip:0`` unless
4007 --follow is set, in which case the working directory parent is
4014 --follow is set, in which case the working directory parent is
4008 used as the starting revision.
4015 used as the starting revision.
4009
4016
4010 File history is shown without following rename or copy history of
4017 File history is shown without following rename or copy history of
4011 files. Use -f/--follow with a filename to follow history across
4018 files. Use -f/--follow with a filename to follow history across
4012 renames and copies. --follow without a filename will only show
4019 renames and copies. --follow without a filename will only show
4013 ancestors or descendants of the starting revision.
4020 ancestors or descendants of the starting revision.
4014
4021
4015 By default this command prints revision number and changeset id,
4022 By default this command prints revision number and changeset id,
4016 tags, non-trivial parents, user, date and time, and a summary for
4023 tags, non-trivial parents, user, date and time, and a summary for
4017 each commit. When the -v/--verbose switch is used, the list of
4024 each commit. When the -v/--verbose switch is used, the list of
4018 changed files and full commit message are shown.
4025 changed files and full commit message are shown.
4019
4026
4020 .. note::
4027 .. note::
4021 log -p/--patch may generate unexpected diff output for merge
4028 log -p/--patch may generate unexpected diff output for merge
4022 changesets, as it will only compare the merge changeset against
4029 changesets, as it will only compare the merge changeset against
4023 its first parent. Also, only files different from BOTH parents
4030 its first parent. Also, only files different from BOTH parents
4024 will appear in files:.
4031 will appear in files:.
4025
4032
4026 .. note::
4033 .. note::
4027 for performance reasons, log FILE may omit duplicate changes
4034 for performance reasons, log FILE may omit duplicate changes
4028 made on branches and will not show deletions. To see all
4035 made on branches and will not show deletions. To see all
4029 changes including duplicates and deletions, use the --removed
4036 changes including duplicates and deletions, use the --removed
4030 switch.
4037 switch.
4031
4038
4032 .. container:: verbose
4039 .. container:: verbose
4033
4040
4034 Some examples:
4041 Some examples:
4035
4042
4036 - changesets with full descriptions and file lists::
4043 - changesets with full descriptions and file lists::
4037
4044
4038 hg log -v
4045 hg log -v
4039
4046
4040 - changesets ancestral to the working directory::
4047 - changesets ancestral to the working directory::
4041
4048
4042 hg log -f
4049 hg log -f
4043
4050
4044 - last 10 commits on the current branch::
4051 - last 10 commits on the current branch::
4045
4052
4046 hg log -l 10 -b .
4053 hg log -l 10 -b .
4047
4054
4048 - changesets showing all modifications of a file, including removals::
4055 - changesets showing all modifications of a file, including removals::
4049
4056
4050 hg log --removed file.c
4057 hg log --removed file.c
4051
4058
4052 - all changesets that touch a directory, with diffs, excluding merges::
4059 - all changesets that touch a directory, with diffs, excluding merges::
4053
4060
4054 hg log -Mp lib/
4061 hg log -Mp lib/
4055
4062
4056 - all revision numbers that match a keyword::
4063 - all revision numbers that match a keyword::
4057
4064
4058 hg log -k bug --template "{rev}\\n"
4065 hg log -k bug --template "{rev}\\n"
4059
4066
4060 - check if a given changeset is included is a tagged release::
4067 - check if a given changeset is included is a tagged release::
4061
4068
4062 hg log -r "a21ccf and ancestor(1.9)"
4069 hg log -r "a21ccf and ancestor(1.9)"
4063
4070
4064 - find all changesets by some user in a date range::
4071 - find all changesets by some user in a date range::
4065
4072
4066 hg log -k alice -d "may 2008 to jul 2008"
4073 hg log -k alice -d "may 2008 to jul 2008"
4067
4074
4068 - summary of all changesets after the last tag::
4075 - summary of all changesets after the last tag::
4069
4076
4070 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4077 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4071
4078
4072 See :hg:`help dates` for a list of formats valid for -d/--date.
4079 See :hg:`help dates` for a list of formats valid for -d/--date.
4073
4080
4074 See :hg:`help revisions` and :hg:`help revsets` for more about
4081 See :hg:`help revisions` and :hg:`help revsets` for more about
4075 specifying revisions.
4082 specifying revisions.
4076
4083
4077 See :hg:`help templates` for more about pre-packaged styles and
4084 See :hg:`help templates` for more about pre-packaged styles and
4078 specifying custom templates.
4085 specifying custom templates.
4079
4086
4080 Returns 0 on success.
4087 Returns 0 on success.
4081 """
4088 """
4082 if opts.get('graph'):
4089 if opts.get('graph'):
4083 return cmdutil.graphlog(ui, repo, *pats, **opts)
4090 return cmdutil.graphlog(ui, repo, *pats, **opts)
4084
4091
4085 matchfn = scmutil.match(repo[None], pats, opts)
4092 matchfn = scmutil.match(repo[None], pats, opts)
4086 limit = cmdutil.loglimit(opts)
4093 limit = cmdutil.loglimit(opts)
4087 count = 0
4094 count = 0
4088
4095
4089 getrenamed, endrev = None, None
4096 getrenamed, endrev = None, None
4090 if opts.get('copies'):
4097 if opts.get('copies'):
4091 if opts.get('rev'):
4098 if opts.get('rev'):
4092 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4099 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4093 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4100 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4094
4101
4095 df = False
4102 df = False
4096 if opts.get("date"):
4103 if opts.get("date"):
4097 df = util.matchdate(opts["date"])
4104 df = util.matchdate(opts["date"])
4098
4105
4099 branches = opts.get('branch', []) + opts.get('only_branch', [])
4106 branches = opts.get('branch', []) + opts.get('only_branch', [])
4100 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4107 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4101
4108
4102 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4109 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4103 def prep(ctx, fns):
4110 def prep(ctx, fns):
4104 rev = ctx.rev()
4111 rev = ctx.rev()
4105 parents = [p for p in repo.changelog.parentrevs(rev)
4112 parents = [p for p in repo.changelog.parentrevs(rev)
4106 if p != nullrev]
4113 if p != nullrev]
4107 if opts.get('no_merges') and len(parents) == 2:
4114 if opts.get('no_merges') and len(parents) == 2:
4108 return
4115 return
4109 if opts.get('only_merges') and len(parents) != 2:
4116 if opts.get('only_merges') and len(parents) != 2:
4110 return
4117 return
4111 if opts.get('branch') and ctx.branch() not in opts['branch']:
4118 if opts.get('branch') and ctx.branch() not in opts['branch']:
4112 return
4119 return
4113 if not opts.get('hidden') and ctx.hidden():
4120 if not opts.get('hidden') and ctx.hidden():
4114 return
4121 return
4115 if df and not df(ctx.date()[0]):
4122 if df and not df(ctx.date()[0]):
4116 return
4123 return
4117
4124
4118 lower = encoding.lower
4125 lower = encoding.lower
4119 if opts.get('user'):
4126 if opts.get('user'):
4120 luser = lower(ctx.user())
4127 luser = lower(ctx.user())
4121 for k in [lower(x) for x in opts['user']]:
4128 for k in [lower(x) for x in opts['user']]:
4122 if (k in luser):
4129 if (k in luser):
4123 break
4130 break
4124 else:
4131 else:
4125 return
4132 return
4126 if opts.get('keyword'):
4133 if opts.get('keyword'):
4127 luser = lower(ctx.user())
4134 luser = lower(ctx.user())
4128 ldesc = lower(ctx.description())
4135 ldesc = lower(ctx.description())
4129 lfiles = lower(" ".join(ctx.files()))
4136 lfiles = lower(" ".join(ctx.files()))
4130 for k in [lower(x) for x in opts['keyword']]:
4137 for k in [lower(x) for x in opts['keyword']]:
4131 if (k in luser or k in ldesc or k in lfiles):
4138 if (k in luser or k in ldesc or k in lfiles):
4132 break
4139 break
4133 else:
4140 else:
4134 return
4141 return
4135
4142
4136 copies = None
4143 copies = None
4137 if getrenamed is not None and rev:
4144 if getrenamed is not None and rev:
4138 copies = []
4145 copies = []
4139 for fn in ctx.files():
4146 for fn in ctx.files():
4140 rename = getrenamed(fn, rev)
4147 rename = getrenamed(fn, rev)
4141 if rename:
4148 if rename:
4142 copies.append((fn, rename[0]))
4149 copies.append((fn, rename[0]))
4143
4150
4144 revmatchfn = None
4151 revmatchfn = None
4145 if opts.get('patch') or opts.get('stat'):
4152 if opts.get('patch') or opts.get('stat'):
4146 if opts.get('follow') or opts.get('follow_first'):
4153 if opts.get('follow') or opts.get('follow_first'):
4147 # note: this might be wrong when following through merges
4154 # note: this might be wrong when following through merges
4148 revmatchfn = scmutil.match(repo[None], fns, default='path')
4155 revmatchfn = scmutil.match(repo[None], fns, default='path')
4149 else:
4156 else:
4150 revmatchfn = matchfn
4157 revmatchfn = matchfn
4151
4158
4152 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4159 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4153
4160
4154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4161 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4155 if count == limit:
4162 if count == limit:
4156 break
4163 break
4157 if displayer.flush(ctx.rev()):
4164 if displayer.flush(ctx.rev()):
4158 count += 1
4165 count += 1
4159 displayer.close()
4166 displayer.close()
4160
4167
4161 @command('manifest',
4168 @command('manifest',
4162 [('r', 'rev', '', _('revision to display'), _('REV')),
4169 [('r', 'rev', '', _('revision to display'), _('REV')),
4163 ('', 'all', False, _("list files from all revisions"))],
4170 ('', 'all', False, _("list files from all revisions"))],
4164 _('[-r REV]'))
4171 _('[-r REV]'))
4165 def manifest(ui, repo, node=None, rev=None, **opts):
4172 def manifest(ui, repo, node=None, rev=None, **opts):
4166 """output the current or given revision of the project manifest
4173 """output the current or given revision of the project manifest
4167
4174
4168 Print a list of version controlled files for the given revision.
4175 Print a list of version controlled files for the given revision.
4169 If no revision is given, the first parent of the working directory
4176 If no revision is given, the first parent of the working directory
4170 is used, or the null revision if no revision is checked out.
4177 is used, or the null revision if no revision is checked out.
4171
4178
4172 With -v, print file permissions, symlink and executable bits.
4179 With -v, print file permissions, symlink and executable bits.
4173 With --debug, print file revision hashes.
4180 With --debug, print file revision hashes.
4174
4181
4175 If option --all is specified, the list of all files from all revisions
4182 If option --all is specified, the list of all files from all revisions
4176 is printed. This includes deleted and renamed files.
4183 is printed. This includes deleted and renamed files.
4177
4184
4178 Returns 0 on success.
4185 Returns 0 on success.
4179 """
4186 """
4180 if opts.get('all'):
4187 if opts.get('all'):
4181 if rev or node:
4188 if rev or node:
4182 raise util.Abort(_("can't specify a revision with --all"))
4189 raise util.Abort(_("can't specify a revision with --all"))
4183
4190
4184 res = []
4191 res = []
4185 prefix = "data/"
4192 prefix = "data/"
4186 suffix = ".i"
4193 suffix = ".i"
4187 plen = len(prefix)
4194 plen = len(prefix)
4188 slen = len(suffix)
4195 slen = len(suffix)
4189 lock = repo.lock()
4196 lock = repo.lock()
4190 try:
4197 try:
4191 for fn, b, size in repo.store.datafiles():
4198 for fn, b, size in repo.store.datafiles():
4192 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4199 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4193 res.append(fn[plen:-slen])
4200 res.append(fn[plen:-slen])
4194 finally:
4201 finally:
4195 lock.release()
4202 lock.release()
4196 for f in res:
4203 for f in res:
4197 ui.write("%s\n" % f)
4204 ui.write("%s\n" % f)
4198 return
4205 return
4199
4206
4200 if rev and node:
4207 if rev and node:
4201 raise util.Abort(_("please specify just one revision"))
4208 raise util.Abort(_("please specify just one revision"))
4202
4209
4203 if not node:
4210 if not node:
4204 node = rev
4211 node = rev
4205
4212
4206 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4213 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4207 ctx = scmutil.revsingle(repo, node)
4214 ctx = scmutil.revsingle(repo, node)
4208 for f in ctx:
4215 for f in ctx:
4209 if ui.debugflag:
4216 if ui.debugflag:
4210 ui.write("%40s " % hex(ctx.manifest()[f]))
4217 ui.write("%40s " % hex(ctx.manifest()[f]))
4211 if ui.verbose:
4218 if ui.verbose:
4212 ui.write(decor[ctx.flags(f)])
4219 ui.write(decor[ctx.flags(f)])
4213 ui.write("%s\n" % f)
4220 ui.write("%s\n" % f)
4214
4221
4215 @command('^merge',
4222 @command('^merge',
4216 [('f', 'force', None, _('force a merge with outstanding changes')),
4223 [('f', 'force', None, _('force a merge with outstanding changes')),
4217 ('r', 'rev', '', _('revision to merge'), _('REV')),
4224 ('r', 'rev', '', _('revision to merge'), _('REV')),
4218 ('P', 'preview', None,
4225 ('P', 'preview', None,
4219 _('review revisions to merge (no merge is performed)'))
4226 _('review revisions to merge (no merge is performed)'))
4220 ] + mergetoolopts,
4227 ] + mergetoolopts,
4221 _('[-P] [-f] [[-r] REV]'))
4228 _('[-P] [-f] [[-r] REV]'))
4222 def merge(ui, repo, node=None, **opts):
4229 def merge(ui, repo, node=None, **opts):
4223 """merge working directory with another revision
4230 """merge working directory with another revision
4224
4231
4225 The current working directory is updated with all changes made in
4232 The current working directory is updated with all changes made in
4226 the requested revision since the last common predecessor revision.
4233 the requested revision since the last common predecessor revision.
4227
4234
4228 Files that changed between either parent are marked as changed for
4235 Files that changed between either parent are marked as changed for
4229 the next commit and a commit must be performed before any further
4236 the next commit and a commit must be performed before any further
4230 updates to the repository are allowed. The next commit will have
4237 updates to the repository are allowed. The next commit will have
4231 two parents.
4238 two parents.
4232
4239
4233 ``--tool`` can be used to specify the merge tool used for file
4240 ``--tool`` can be used to specify the merge tool used for file
4234 merges. It overrides the HGMERGE environment variable and your
4241 merges. It overrides the HGMERGE environment variable and your
4235 configuration files. See :hg:`help merge-tools` for options.
4242 configuration files. See :hg:`help merge-tools` for options.
4236
4243
4237 If no revision is specified, the working directory's parent is a
4244 If no revision is specified, the working directory's parent is a
4238 head revision, and the current branch contains exactly one other
4245 head revision, and the current branch contains exactly one other
4239 head, the other head is merged with by default. Otherwise, an
4246 head, the other head is merged with by default. Otherwise, an
4240 explicit revision with which to merge with must be provided.
4247 explicit revision with which to merge with must be provided.
4241
4248
4242 :hg:`resolve` must be used to resolve unresolved files.
4249 :hg:`resolve` must be used to resolve unresolved files.
4243
4250
4244 To undo an uncommitted merge, use :hg:`update --clean .` which
4251 To undo an uncommitted merge, use :hg:`update --clean .` which
4245 will check out a clean copy of the original merge parent, losing
4252 will check out a clean copy of the original merge parent, losing
4246 all changes.
4253 all changes.
4247
4254
4248 Returns 0 on success, 1 if there are unresolved files.
4255 Returns 0 on success, 1 if there are unresolved files.
4249 """
4256 """
4250
4257
4251 if opts.get('rev') and node:
4258 if opts.get('rev') and node:
4252 raise util.Abort(_("please specify just one revision"))
4259 raise util.Abort(_("please specify just one revision"))
4253 if not node:
4260 if not node:
4254 node = opts.get('rev')
4261 node = opts.get('rev')
4255
4262
4256 if node:
4263 if node:
4257 node = scmutil.revsingle(repo, node).node()
4264 node = scmutil.revsingle(repo, node).node()
4258
4265
4259 if not node and repo._bookmarkcurrent:
4266 if not node and repo._bookmarkcurrent:
4260 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4267 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4261 curhead = repo[repo._bookmarkcurrent]
4268 curhead = repo[repo._bookmarkcurrent]
4262 if len(bmheads) == 2:
4269 if len(bmheads) == 2:
4263 if curhead == bmheads[0]:
4270 if curhead == bmheads[0]:
4264 node = bmheads[1]
4271 node = bmheads[1]
4265 else:
4272 else:
4266 node = bmheads[0]
4273 node = bmheads[0]
4267 elif len(bmheads) > 2:
4274 elif len(bmheads) > 2:
4268 raise util.Abort(_("multiple matching bookmarks to merge - "
4275 raise util.Abort(_("multiple matching bookmarks to merge - "
4269 "please merge with an explicit rev or bookmark"),
4276 "please merge with an explicit rev or bookmark"),
4270 hint=_("run 'hg heads' to see all heads"))
4277 hint=_("run 'hg heads' to see all heads"))
4271 elif len(bmheads) <= 1:
4278 elif len(bmheads) <= 1:
4272 raise util.Abort(_("no matching bookmark to merge - "
4279 raise util.Abort(_("no matching bookmark to merge - "
4273 "please merge with an explicit rev or bookmark"),
4280 "please merge with an explicit rev or bookmark"),
4274 hint=_("run 'hg heads' to see all heads"))
4281 hint=_("run 'hg heads' to see all heads"))
4275
4282
4276 if not node and not repo._bookmarkcurrent:
4283 if not node and not repo._bookmarkcurrent:
4277 branch = repo[None].branch()
4284 branch = repo[None].branch()
4278 bheads = repo.branchheads(branch)
4285 bheads = repo.branchheads(branch)
4279 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4286 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4280
4287
4281 if len(nbhs) > 2:
4288 if len(nbhs) > 2:
4282 raise util.Abort(_("branch '%s' has %d heads - "
4289 raise util.Abort(_("branch '%s' has %d heads - "
4283 "please merge with an explicit rev")
4290 "please merge with an explicit rev")
4284 % (branch, len(bheads)),
4291 % (branch, len(bheads)),
4285 hint=_("run 'hg heads .' to see heads"))
4292 hint=_("run 'hg heads .' to see heads"))
4286
4293
4287 parent = repo.dirstate.p1()
4294 parent = repo.dirstate.p1()
4288 if len(nbhs) <= 1:
4295 if len(nbhs) <= 1:
4289 if len(bheads) > 1:
4296 if len(bheads) > 1:
4290 raise util.Abort(_("heads are bookmarked - "
4297 raise util.Abort(_("heads are bookmarked - "
4291 "please merge with an explicit rev"),
4298 "please merge with an explicit rev"),
4292 hint=_("run 'hg heads' to see all heads"))
4299 hint=_("run 'hg heads' to see all heads"))
4293 if len(repo.heads()) > 1:
4300 if len(repo.heads()) > 1:
4294 raise util.Abort(_("branch '%s' has one head - "
4301 raise util.Abort(_("branch '%s' has one head - "
4295 "please merge with an explicit rev")
4302 "please merge with an explicit rev")
4296 % branch,
4303 % branch,
4297 hint=_("run 'hg heads' to see all heads"))
4304 hint=_("run 'hg heads' to see all heads"))
4298 msg, hint = _('nothing to merge'), None
4305 msg, hint = _('nothing to merge'), None
4299 if parent != repo.lookup(branch):
4306 if parent != repo.lookup(branch):
4300 hint = _("use 'hg update' instead")
4307 hint = _("use 'hg update' instead")
4301 raise util.Abort(msg, hint=hint)
4308 raise util.Abort(msg, hint=hint)
4302
4309
4303 if parent not in bheads:
4310 if parent not in bheads:
4304 raise util.Abort(_('working directory not at a head revision'),
4311 raise util.Abort(_('working directory not at a head revision'),
4305 hint=_("use 'hg update' or merge with an "
4312 hint=_("use 'hg update' or merge with an "
4306 "explicit revision"))
4313 "explicit revision"))
4307 if parent == nbhs[0]:
4314 if parent == nbhs[0]:
4308 node = nbhs[-1]
4315 node = nbhs[-1]
4309 else:
4316 else:
4310 node = nbhs[0]
4317 node = nbhs[0]
4311
4318
4312 if opts.get('preview'):
4319 if opts.get('preview'):
4313 # find nodes that are ancestors of p2 but not of p1
4320 # find nodes that are ancestors of p2 but not of p1
4314 p1 = repo.lookup('.')
4321 p1 = repo.lookup('.')
4315 p2 = repo.lookup(node)
4322 p2 = repo.lookup(node)
4316 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4323 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4317
4324
4318 displayer = cmdutil.show_changeset(ui, repo, opts)
4325 displayer = cmdutil.show_changeset(ui, repo, opts)
4319 for node in nodes:
4326 for node in nodes:
4320 displayer.show(repo[node])
4327 displayer.show(repo[node])
4321 displayer.close()
4328 displayer.close()
4322 return 0
4329 return 0
4323
4330
4324 try:
4331 try:
4325 # ui.forcemerge is an internal variable, do not document
4332 # ui.forcemerge is an internal variable, do not document
4326 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4333 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4327 return hg.merge(repo, node, force=opts.get('force'))
4334 return hg.merge(repo, node, force=opts.get('force'))
4328 finally:
4335 finally:
4329 ui.setconfig('ui', 'forcemerge', '')
4336 ui.setconfig('ui', 'forcemerge', '')
4330
4337
4331 @command('outgoing|out',
4338 @command('outgoing|out',
4332 [('f', 'force', None, _('run even when the destination is unrelated')),
4339 [('f', 'force', None, _('run even when the destination is unrelated')),
4333 ('r', 'rev', [],
4340 ('r', 'rev', [],
4334 _('a changeset intended to be included in the destination'), _('REV')),
4341 _('a changeset intended to be included in the destination'), _('REV')),
4335 ('n', 'newest-first', None, _('show newest record first')),
4342 ('n', 'newest-first', None, _('show newest record first')),
4336 ('B', 'bookmarks', False, _('compare bookmarks')),
4343 ('B', 'bookmarks', False, _('compare bookmarks')),
4337 ('b', 'branch', [], _('a specific branch you would like to push'),
4344 ('b', 'branch', [], _('a specific branch you would like to push'),
4338 _('BRANCH')),
4345 _('BRANCH')),
4339 ] + logopts + remoteopts + subrepoopts,
4346 ] + logopts + remoteopts + subrepoopts,
4340 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4347 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4341 def outgoing(ui, repo, dest=None, **opts):
4348 def outgoing(ui, repo, dest=None, **opts):
4342 """show changesets not found in the destination
4349 """show changesets not found in the destination
4343
4350
4344 Show changesets not found in the specified destination repository
4351 Show changesets not found in the specified destination repository
4345 or the default push location. These are the changesets that would
4352 or the default push location. These are the changesets that would
4346 be pushed if a push was requested.
4353 be pushed if a push was requested.
4347
4354
4348 See pull for details of valid destination formats.
4355 See pull for details of valid destination formats.
4349
4356
4350 Returns 0 if there are outgoing changes, 1 otherwise.
4357 Returns 0 if there are outgoing changes, 1 otherwise.
4351 """
4358 """
4352 if opts.get('graph'):
4359 if opts.get('graph'):
4353 cmdutil.checkunsupportedgraphflags([], opts)
4360 cmdutil.checkunsupportedgraphflags([], opts)
4354 o = hg._outgoing(ui, repo, dest, opts)
4361 o = hg._outgoing(ui, repo, dest, opts)
4355 if o is None:
4362 if o is None:
4356 return
4363 return
4357
4364
4358 revdag = cmdutil.graphrevs(repo, o, opts)
4365 revdag = cmdutil.graphrevs(repo, o, opts)
4359 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4366 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4360 showparents = [ctx.node() for ctx in repo[None].parents()]
4367 showparents = [ctx.node() for ctx in repo[None].parents()]
4361 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4368 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4362 graphmod.asciiedges)
4369 graphmod.asciiedges)
4363 return 0
4370 return 0
4364
4371
4365 if opts.get('bookmarks'):
4372 if opts.get('bookmarks'):
4366 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4373 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4367 dest, branches = hg.parseurl(dest, opts.get('branch'))
4374 dest, branches = hg.parseurl(dest, opts.get('branch'))
4368 other = hg.peer(repo, opts, dest)
4375 other = hg.peer(repo, opts, dest)
4369 if 'bookmarks' not in other.listkeys('namespaces'):
4376 if 'bookmarks' not in other.listkeys('namespaces'):
4370 ui.warn(_("remote doesn't support bookmarks\n"))
4377 ui.warn(_("remote doesn't support bookmarks\n"))
4371 return 0
4378 return 0
4372 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4379 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4373 return bookmarks.diff(ui, other, repo)
4380 return bookmarks.diff(ui, other, repo)
4374
4381
4375 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4382 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4376 try:
4383 try:
4377 return hg.outgoing(ui, repo, dest, opts)
4384 return hg.outgoing(ui, repo, dest, opts)
4378 finally:
4385 finally:
4379 del repo._subtoppath
4386 del repo._subtoppath
4380
4387
4381 @command('parents',
4388 @command('parents',
4382 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4389 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4383 ] + templateopts,
4390 ] + templateopts,
4384 _('[-r REV] [FILE]'))
4391 _('[-r REV] [FILE]'))
4385 def parents(ui, repo, file_=None, **opts):
4392 def parents(ui, repo, file_=None, **opts):
4386 """show the parents of the working directory or revision
4393 """show the parents of the working directory or revision
4387
4394
4388 Print the working directory's parent revisions. If a revision is
4395 Print the working directory's parent revisions. If a revision is
4389 given via -r/--rev, the parent of that revision will be printed.
4396 given via -r/--rev, the parent of that revision will be printed.
4390 If a file argument is given, the revision in which the file was
4397 If a file argument is given, the revision in which the file was
4391 last changed (before the working directory revision or the
4398 last changed (before the working directory revision or the
4392 argument to --rev if given) is printed.
4399 argument to --rev if given) is printed.
4393
4400
4394 Returns 0 on success.
4401 Returns 0 on success.
4395 """
4402 """
4396
4403
4397 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4404 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4398
4405
4399 if file_:
4406 if file_:
4400 m = scmutil.match(ctx, (file_,), opts)
4407 m = scmutil.match(ctx, (file_,), opts)
4401 if m.anypats() or len(m.files()) != 1:
4408 if m.anypats() or len(m.files()) != 1:
4402 raise util.Abort(_('can only specify an explicit filename'))
4409 raise util.Abort(_('can only specify an explicit filename'))
4403 file_ = m.files()[0]
4410 file_ = m.files()[0]
4404 filenodes = []
4411 filenodes = []
4405 for cp in ctx.parents():
4412 for cp in ctx.parents():
4406 if not cp:
4413 if not cp:
4407 continue
4414 continue
4408 try:
4415 try:
4409 filenodes.append(cp.filenode(file_))
4416 filenodes.append(cp.filenode(file_))
4410 except error.LookupError:
4417 except error.LookupError:
4411 pass
4418 pass
4412 if not filenodes:
4419 if not filenodes:
4413 raise util.Abort(_("'%s' not found in manifest!") % file_)
4420 raise util.Abort(_("'%s' not found in manifest!") % file_)
4414 fl = repo.file(file_)
4421 fl = repo.file(file_)
4415 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4422 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4416 else:
4423 else:
4417 p = [cp.node() for cp in ctx.parents()]
4424 p = [cp.node() for cp in ctx.parents()]
4418
4425
4419 displayer = cmdutil.show_changeset(ui, repo, opts)
4426 displayer = cmdutil.show_changeset(ui, repo, opts)
4420 for n in p:
4427 for n in p:
4421 if n != nullid:
4428 if n != nullid:
4422 displayer.show(repo[n])
4429 displayer.show(repo[n])
4423 displayer.close()
4430 displayer.close()
4424
4431
4425 @command('paths', [], _('[NAME]'))
4432 @command('paths', [], _('[NAME]'))
4426 def paths(ui, repo, search=None):
4433 def paths(ui, repo, search=None):
4427 """show aliases for remote repositories
4434 """show aliases for remote repositories
4428
4435
4429 Show definition of symbolic path name NAME. If no name is given,
4436 Show definition of symbolic path name NAME. If no name is given,
4430 show definition of all available names.
4437 show definition of all available names.
4431
4438
4432 Option -q/--quiet suppresses all output when searching for NAME
4439 Option -q/--quiet suppresses all output when searching for NAME
4433 and shows only the path names when listing all definitions.
4440 and shows only the path names when listing all definitions.
4434
4441
4435 Path names are defined in the [paths] section of your
4442 Path names are defined in the [paths] section of your
4436 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4443 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4437 repository, ``.hg/hgrc`` is used, too.
4444 repository, ``.hg/hgrc`` is used, too.
4438
4445
4439 The path names ``default`` and ``default-push`` have a special
4446 The path names ``default`` and ``default-push`` have a special
4440 meaning. When performing a push or pull operation, they are used
4447 meaning. When performing a push or pull operation, they are used
4441 as fallbacks if no location is specified on the command-line.
4448 as fallbacks if no location is specified on the command-line.
4442 When ``default-push`` is set, it will be used for push and
4449 When ``default-push`` is set, it will be used for push and
4443 ``default`` will be used for pull; otherwise ``default`` is used
4450 ``default`` will be used for pull; otherwise ``default`` is used
4444 as the fallback for both. When cloning a repository, the clone
4451 as the fallback for both. When cloning a repository, the clone
4445 source is written as ``default`` in ``.hg/hgrc``. Note that
4452 source is written as ``default`` in ``.hg/hgrc``. Note that
4446 ``default`` and ``default-push`` apply to all inbound (e.g.
4453 ``default`` and ``default-push`` apply to all inbound (e.g.
4447 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4454 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4448 :hg:`bundle`) operations.
4455 :hg:`bundle`) operations.
4449
4456
4450 See :hg:`help urls` for more information.
4457 See :hg:`help urls` for more information.
4451
4458
4452 Returns 0 on success.
4459 Returns 0 on success.
4453 """
4460 """
4454 if search:
4461 if search:
4455 for name, path in ui.configitems("paths"):
4462 for name, path in ui.configitems("paths"):
4456 if name == search:
4463 if name == search:
4457 ui.status("%s\n" % util.hidepassword(path))
4464 ui.status("%s\n" % util.hidepassword(path))
4458 return
4465 return
4459 if not ui.quiet:
4466 if not ui.quiet:
4460 ui.warn(_("not found!\n"))
4467 ui.warn(_("not found!\n"))
4461 return 1
4468 return 1
4462 else:
4469 else:
4463 for name, path in ui.configitems("paths"):
4470 for name, path in ui.configitems("paths"):
4464 if ui.quiet:
4471 if ui.quiet:
4465 ui.write("%s\n" % name)
4472 ui.write("%s\n" % name)
4466 else:
4473 else:
4467 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4474 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4468
4475
4469 @command('^phase',
4476 @command('^phase',
4470 [('p', 'public', False, _('set changeset phase to public')),
4477 [('p', 'public', False, _('set changeset phase to public')),
4471 ('d', 'draft', False, _('set changeset phase to draft')),
4478 ('d', 'draft', False, _('set changeset phase to draft')),
4472 ('s', 'secret', False, _('set changeset phase to secret')),
4479 ('s', 'secret', False, _('set changeset phase to secret')),
4473 ('f', 'force', False, _('allow to move boundary backward')),
4480 ('f', 'force', False, _('allow to move boundary backward')),
4474 ('r', 'rev', [], _('target revision'), _('REV')),
4481 ('r', 'rev', [], _('target revision'), _('REV')),
4475 ],
4482 ],
4476 _('[-p|-d|-s] [-f] [-r] REV...'))
4483 _('[-p|-d|-s] [-f] [-r] REV...'))
4477 def phase(ui, repo, *revs, **opts):
4484 def phase(ui, repo, *revs, **opts):
4478 """set or show the current phase name
4485 """set or show the current phase name
4479
4486
4480 With no argument, show the phase name of specified revisions.
4487 With no argument, show the phase name of specified revisions.
4481
4488
4482 With one of -p/--public, -d/--draft or -s/--secret, change the
4489 With one of -p/--public, -d/--draft or -s/--secret, change the
4483 phase value of the specified revisions.
4490 phase value of the specified revisions.
4484
4491
4485 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4492 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4486 lower phase to an higher phase. Phases are ordered as follows::
4493 lower phase to an higher phase. Phases are ordered as follows::
4487
4494
4488 public < draft < secret
4495 public < draft < secret
4489
4496
4490 Return 0 on success, 1 if no phases were changed or some could not
4497 Return 0 on success, 1 if no phases were changed or some could not
4491 be changed.
4498 be changed.
4492 """
4499 """
4493 # search for a unique phase argument
4500 # search for a unique phase argument
4494 targetphase = None
4501 targetphase = None
4495 for idx, name in enumerate(phases.phasenames):
4502 for idx, name in enumerate(phases.phasenames):
4496 if opts[name]:
4503 if opts[name]:
4497 if targetphase is not None:
4504 if targetphase is not None:
4498 raise util.Abort(_('only one phase can be specified'))
4505 raise util.Abort(_('only one phase can be specified'))
4499 targetphase = idx
4506 targetphase = idx
4500
4507
4501 # look for specified revision
4508 # look for specified revision
4502 revs = list(revs)
4509 revs = list(revs)
4503 revs.extend(opts['rev'])
4510 revs.extend(opts['rev'])
4504 if not revs:
4511 if not revs:
4505 raise util.Abort(_('no revisions specified'))
4512 raise util.Abort(_('no revisions specified'))
4506
4513
4507 revs = scmutil.revrange(repo, revs)
4514 revs = scmutil.revrange(repo, revs)
4508
4515
4509 lock = None
4516 lock = None
4510 ret = 0
4517 ret = 0
4511 if targetphase is None:
4518 if targetphase is None:
4512 # display
4519 # display
4513 for r in revs:
4520 for r in revs:
4514 ctx = repo[r]
4521 ctx = repo[r]
4515 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4522 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4516 else:
4523 else:
4517 lock = repo.lock()
4524 lock = repo.lock()
4518 try:
4525 try:
4519 # set phase
4526 # set phase
4520 if not revs:
4527 if not revs:
4521 raise util.Abort(_('empty revision set'))
4528 raise util.Abort(_('empty revision set'))
4522 nodes = [repo[r].node() for r in revs]
4529 nodes = [repo[r].node() for r in revs]
4523 olddata = repo._phasecache.getphaserevs(repo)[:]
4530 olddata = repo._phasecache.getphaserevs(repo)[:]
4524 phases.advanceboundary(repo, targetphase, nodes)
4531 phases.advanceboundary(repo, targetphase, nodes)
4525 if opts['force']:
4532 if opts['force']:
4526 phases.retractboundary(repo, targetphase, nodes)
4533 phases.retractboundary(repo, targetphase, nodes)
4527 finally:
4534 finally:
4528 lock.release()
4535 lock.release()
4529 newdata = repo._phasecache.getphaserevs(repo)
4536 newdata = repo._phasecache.getphaserevs(repo)
4530 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4537 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4531 rejected = [n for n in nodes
4538 rejected = [n for n in nodes
4532 if newdata[repo[n].rev()] < targetphase]
4539 if newdata[repo[n].rev()] < targetphase]
4533 if rejected:
4540 if rejected:
4534 ui.warn(_('cannot move %i changesets to a more permissive '
4541 ui.warn(_('cannot move %i changesets to a more permissive '
4535 'phase, use --force\n') % len(rejected))
4542 'phase, use --force\n') % len(rejected))
4536 ret = 1
4543 ret = 1
4537 if changes:
4544 if changes:
4538 msg = _('phase changed for %i changesets\n') % changes
4545 msg = _('phase changed for %i changesets\n') % changes
4539 if ret:
4546 if ret:
4540 ui.status(msg)
4547 ui.status(msg)
4541 else:
4548 else:
4542 ui.note(msg)
4549 ui.note(msg)
4543 else:
4550 else:
4544 ui.warn(_('no phases changed\n'))
4551 ui.warn(_('no phases changed\n'))
4545 ret = 1
4552 ret = 1
4546 return ret
4553 return ret
4547
4554
4548 def postincoming(ui, repo, modheads, optupdate, checkout):
4555 def postincoming(ui, repo, modheads, optupdate, checkout):
4549 if modheads == 0:
4556 if modheads == 0:
4550 return
4557 return
4551 if optupdate:
4558 if optupdate:
4552 movemarkfrom = repo['.'].node()
4559 movemarkfrom = repo['.'].node()
4553 try:
4560 try:
4554 ret = hg.update(repo, checkout)
4561 ret = hg.update(repo, checkout)
4555 except util.Abort, inst:
4562 except util.Abort, inst:
4556 ui.warn(_("not updating: %s\n") % str(inst))
4563 ui.warn(_("not updating: %s\n") % str(inst))
4557 return 0
4564 return 0
4558 if not ret and not checkout:
4565 if not ret and not checkout:
4559 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4566 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4560 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4567 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4561 return ret
4568 return ret
4562 if modheads > 1:
4569 if modheads > 1:
4563 currentbranchheads = len(repo.branchheads())
4570 currentbranchheads = len(repo.branchheads())
4564 if currentbranchheads == modheads:
4571 if currentbranchheads == modheads:
4565 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4572 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4566 elif currentbranchheads > 1:
4573 elif currentbranchheads > 1:
4567 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4574 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4568 "merge)\n"))
4575 "merge)\n"))
4569 else:
4576 else:
4570 ui.status(_("(run 'hg heads' to see heads)\n"))
4577 ui.status(_("(run 'hg heads' to see heads)\n"))
4571 else:
4578 else:
4572 ui.status(_("(run 'hg update' to get a working copy)\n"))
4579 ui.status(_("(run 'hg update' to get a working copy)\n"))
4573
4580
4574 @command('^pull',
4581 @command('^pull',
4575 [('u', 'update', None,
4582 [('u', 'update', None,
4576 _('update to new branch head if changesets were pulled')),
4583 _('update to new branch head if changesets were pulled')),
4577 ('f', 'force', None, _('run even when remote repository is unrelated')),
4584 ('f', 'force', None, _('run even when remote repository is unrelated')),
4578 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4585 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4579 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4586 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4580 ('b', 'branch', [], _('a specific branch you would like to pull'),
4587 ('b', 'branch', [], _('a specific branch you would like to pull'),
4581 _('BRANCH')),
4588 _('BRANCH')),
4582 ] + remoteopts,
4589 ] + remoteopts,
4583 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4590 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4584 def pull(ui, repo, source="default", **opts):
4591 def pull(ui, repo, source="default", **opts):
4585 """pull changes from the specified source
4592 """pull changes from the specified source
4586
4593
4587 Pull changes from a remote repository to a local one.
4594 Pull changes from a remote repository to a local one.
4588
4595
4589 This finds all changes from the repository at the specified path
4596 This finds all changes from the repository at the specified path
4590 or URL and adds them to a local repository (the current one unless
4597 or URL and adds them to a local repository (the current one unless
4591 -R is specified). By default, this does not update the copy of the
4598 -R is specified). By default, this does not update the copy of the
4592 project in the working directory.
4599 project in the working directory.
4593
4600
4594 Use :hg:`incoming` if you want to see what would have been added
4601 Use :hg:`incoming` if you want to see what would have been added
4595 by a pull at the time you issued this command. If you then decide
4602 by a pull at the time you issued this command. If you then decide
4596 to add those changes to the repository, you should use :hg:`pull
4603 to add those changes to the repository, you should use :hg:`pull
4597 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4604 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4598
4605
4599 If SOURCE is omitted, the 'default' path will be used.
4606 If SOURCE is omitted, the 'default' path will be used.
4600 See :hg:`help urls` for more information.
4607 See :hg:`help urls` for more information.
4601
4608
4602 Returns 0 on success, 1 if an update had unresolved files.
4609 Returns 0 on success, 1 if an update had unresolved files.
4603 """
4610 """
4604 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4611 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4605 other = hg.peer(repo, opts, source)
4612 other = hg.peer(repo, opts, source)
4606 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4613 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4607 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4614 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4608
4615
4609 if opts.get('bookmark'):
4616 if opts.get('bookmark'):
4610 if not revs:
4617 if not revs:
4611 revs = []
4618 revs = []
4612 rb = other.listkeys('bookmarks')
4619 rb = other.listkeys('bookmarks')
4613 for b in opts['bookmark']:
4620 for b in opts['bookmark']:
4614 if b not in rb:
4621 if b not in rb:
4615 raise util.Abort(_('remote bookmark %s not found!') % b)
4622 raise util.Abort(_('remote bookmark %s not found!') % b)
4616 revs.append(rb[b])
4623 revs.append(rb[b])
4617
4624
4618 if revs:
4625 if revs:
4619 try:
4626 try:
4620 revs = [other.lookup(rev) for rev in revs]
4627 revs = [other.lookup(rev) for rev in revs]
4621 except error.CapabilityError:
4628 except error.CapabilityError:
4622 err = _("other repository doesn't support revision lookup, "
4629 err = _("other repository doesn't support revision lookup, "
4623 "so a rev cannot be specified.")
4630 "so a rev cannot be specified.")
4624 raise util.Abort(err)
4631 raise util.Abort(err)
4625
4632
4626 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4633 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4627 bookmarks.updatefromremote(ui, repo, other, source)
4634 bookmarks.updatefromremote(ui, repo, other, source)
4628 if checkout:
4635 if checkout:
4629 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4636 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4630 repo._subtoppath = source
4637 repo._subtoppath = source
4631 try:
4638 try:
4632 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4639 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4633
4640
4634 finally:
4641 finally:
4635 del repo._subtoppath
4642 del repo._subtoppath
4636
4643
4637 # update specified bookmarks
4644 # update specified bookmarks
4638 if opts.get('bookmark'):
4645 if opts.get('bookmark'):
4639 for b in opts['bookmark']:
4646 for b in opts['bookmark']:
4640 # explicit pull overrides local bookmark if any
4647 # explicit pull overrides local bookmark if any
4641 ui.status(_("importing bookmark %s\n") % b)
4648 ui.status(_("importing bookmark %s\n") % b)
4642 repo._bookmarks[b] = repo[rb[b]].node()
4649 repo._bookmarks[b] = repo[rb[b]].node()
4643 bookmarks.write(repo)
4650 bookmarks.write(repo)
4644
4651
4645 return ret
4652 return ret
4646
4653
4647 @command('^push',
4654 @command('^push',
4648 [('f', 'force', None, _('force push')),
4655 [('f', 'force', None, _('force push')),
4649 ('r', 'rev', [],
4656 ('r', 'rev', [],
4650 _('a changeset intended to be included in the destination'),
4657 _('a changeset intended to be included in the destination'),
4651 _('REV')),
4658 _('REV')),
4652 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4659 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4653 ('b', 'branch', [],
4660 ('b', 'branch', [],
4654 _('a specific branch you would like to push'), _('BRANCH')),
4661 _('a specific branch you would like to push'), _('BRANCH')),
4655 ('', 'new-branch', False, _('allow pushing a new branch')),
4662 ('', 'new-branch', False, _('allow pushing a new branch')),
4656 ] + remoteopts,
4663 ] + remoteopts,
4657 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4664 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4658 def push(ui, repo, dest=None, **opts):
4665 def push(ui, repo, dest=None, **opts):
4659 """push changes to the specified destination
4666 """push changes to the specified destination
4660
4667
4661 Push changesets from the local repository to the specified
4668 Push changesets from the local repository to the specified
4662 destination.
4669 destination.
4663
4670
4664 This operation is symmetrical to pull: it is identical to a pull
4671 This operation is symmetrical to pull: it is identical to a pull
4665 in the destination repository from the current one.
4672 in the destination repository from the current one.
4666
4673
4667 By default, push will not allow creation of new heads at the
4674 By default, push will not allow creation of new heads at the
4668 destination, since multiple heads would make it unclear which head
4675 destination, since multiple heads would make it unclear which head
4669 to use. In this situation, it is recommended to pull and merge
4676 to use. In this situation, it is recommended to pull and merge
4670 before pushing.
4677 before pushing.
4671
4678
4672 Use --new-branch if you want to allow push to create a new named
4679 Use --new-branch if you want to allow push to create a new named
4673 branch that is not present at the destination. This allows you to
4680 branch that is not present at the destination. This allows you to
4674 only create a new branch without forcing other changes.
4681 only create a new branch without forcing other changes.
4675
4682
4676 Use -f/--force to override the default behavior and push all
4683 Use -f/--force to override the default behavior and push all
4677 changesets on all branches.
4684 changesets on all branches.
4678
4685
4679 If -r/--rev is used, the specified revision and all its ancestors
4686 If -r/--rev is used, the specified revision and all its ancestors
4680 will be pushed to the remote repository.
4687 will be pushed to the remote repository.
4681
4688
4682 If -B/--bookmark is used, the specified bookmarked revision, its
4689 If -B/--bookmark is used, the specified bookmarked revision, its
4683 ancestors, and the bookmark will be pushed to the remote
4690 ancestors, and the bookmark will be pushed to the remote
4684 repository.
4691 repository.
4685
4692
4686 Please see :hg:`help urls` for important details about ``ssh://``
4693 Please see :hg:`help urls` for important details about ``ssh://``
4687 URLs. If DESTINATION is omitted, a default path will be used.
4694 URLs. If DESTINATION is omitted, a default path will be used.
4688
4695
4689 Returns 0 if push was successful, 1 if nothing to push.
4696 Returns 0 if push was successful, 1 if nothing to push.
4690 """
4697 """
4691
4698
4692 if opts.get('bookmark'):
4699 if opts.get('bookmark'):
4693 for b in opts['bookmark']:
4700 for b in opts['bookmark']:
4694 # translate -B options to -r so changesets get pushed
4701 # translate -B options to -r so changesets get pushed
4695 if b in repo._bookmarks:
4702 if b in repo._bookmarks:
4696 opts.setdefault('rev', []).append(b)
4703 opts.setdefault('rev', []).append(b)
4697 else:
4704 else:
4698 # if we try to push a deleted bookmark, translate it to null
4705 # if we try to push a deleted bookmark, translate it to null
4699 # this lets simultaneous -r, -b options continue working
4706 # this lets simultaneous -r, -b options continue working
4700 opts.setdefault('rev', []).append("null")
4707 opts.setdefault('rev', []).append("null")
4701
4708
4702 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4709 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4703 dest, branches = hg.parseurl(dest, opts.get('branch'))
4710 dest, branches = hg.parseurl(dest, opts.get('branch'))
4704 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4711 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4705 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4712 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4706 other = hg.peer(repo, opts, dest)
4713 other = hg.peer(repo, opts, dest)
4707 if revs:
4714 if revs:
4708 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4715 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4709
4716
4710 repo._subtoppath = dest
4717 repo._subtoppath = dest
4711 try:
4718 try:
4712 # push subrepos depth-first for coherent ordering
4719 # push subrepos depth-first for coherent ordering
4713 c = repo['']
4720 c = repo['']
4714 subs = c.substate # only repos that are committed
4721 subs = c.substate # only repos that are committed
4715 for s in sorted(subs):
4722 for s in sorted(subs):
4716 if c.sub(s).push(opts) == 0:
4723 if c.sub(s).push(opts) == 0:
4717 return False
4724 return False
4718 finally:
4725 finally:
4719 del repo._subtoppath
4726 del repo._subtoppath
4720 result = repo.push(other, opts.get('force'), revs=revs,
4727 result = repo.push(other, opts.get('force'), revs=revs,
4721 newbranch=opts.get('new_branch'))
4728 newbranch=opts.get('new_branch'))
4722
4729
4723 result = not result
4730 result = not result
4724
4731
4725 if opts.get('bookmark'):
4732 if opts.get('bookmark'):
4726 rb = other.listkeys('bookmarks')
4733 rb = other.listkeys('bookmarks')
4727 for b in opts['bookmark']:
4734 for b in opts['bookmark']:
4728 # explicit push overrides remote bookmark if any
4735 # explicit push overrides remote bookmark if any
4729 if b in repo._bookmarks:
4736 if b in repo._bookmarks:
4730 ui.status(_("exporting bookmark %s\n") % b)
4737 ui.status(_("exporting bookmark %s\n") % b)
4731 new = repo[b].hex()
4738 new = repo[b].hex()
4732 elif b in rb:
4739 elif b in rb:
4733 ui.status(_("deleting remote bookmark %s\n") % b)
4740 ui.status(_("deleting remote bookmark %s\n") % b)
4734 new = '' # delete
4741 new = '' # delete
4735 else:
4742 else:
4736 ui.warn(_('bookmark %s does not exist on the local '
4743 ui.warn(_('bookmark %s does not exist on the local '
4737 'or remote repository!\n') % b)
4744 'or remote repository!\n') % b)
4738 return 2
4745 return 2
4739 old = rb.get(b, '')
4746 old = rb.get(b, '')
4740 r = other.pushkey('bookmarks', b, old, new)
4747 r = other.pushkey('bookmarks', b, old, new)
4741 if not r:
4748 if not r:
4742 ui.warn(_('updating bookmark %s failed!\n') % b)
4749 ui.warn(_('updating bookmark %s failed!\n') % b)
4743 if not result:
4750 if not result:
4744 result = 2
4751 result = 2
4745
4752
4746 return result
4753 return result
4747
4754
4748 @command('recover', [])
4755 @command('recover', [])
4749 def recover(ui, repo):
4756 def recover(ui, repo):
4750 """roll back an interrupted transaction
4757 """roll back an interrupted transaction
4751
4758
4752 Recover from an interrupted commit or pull.
4759 Recover from an interrupted commit or pull.
4753
4760
4754 This command tries to fix the repository status after an
4761 This command tries to fix the repository status after an
4755 interrupted operation. It should only be necessary when Mercurial
4762 interrupted operation. It should only be necessary when Mercurial
4756 suggests it.
4763 suggests it.
4757
4764
4758 Returns 0 if successful, 1 if nothing to recover or verify fails.
4765 Returns 0 if successful, 1 if nothing to recover or verify fails.
4759 """
4766 """
4760 if repo.recover():
4767 if repo.recover():
4761 return hg.verify(repo)
4768 return hg.verify(repo)
4762 return 1
4769 return 1
4763
4770
4764 @command('^remove|rm',
4771 @command('^remove|rm',
4765 [('A', 'after', None, _('record delete for missing files')),
4772 [('A', 'after', None, _('record delete for missing files')),
4766 ('f', 'force', None,
4773 ('f', 'force', None,
4767 _('remove (and delete) file even if added or modified')),
4774 _('remove (and delete) file even if added or modified')),
4768 ] + walkopts,
4775 ] + walkopts,
4769 _('[OPTION]... FILE...'))
4776 _('[OPTION]... FILE...'))
4770 def remove(ui, repo, *pats, **opts):
4777 def remove(ui, repo, *pats, **opts):
4771 """remove the specified files on the next commit
4778 """remove the specified files on the next commit
4772
4779
4773 Schedule the indicated files for removal from the current branch.
4780 Schedule the indicated files for removal from the current branch.
4774
4781
4775 This command schedules the files to be removed at the next commit.
4782 This command schedules the files to be removed at the next commit.
4776 To undo a remove before that, see :hg:`revert`. To undo added
4783 To undo a remove before that, see :hg:`revert`. To undo added
4777 files, see :hg:`forget`.
4784 files, see :hg:`forget`.
4778
4785
4779 .. container:: verbose
4786 .. container:: verbose
4780
4787
4781 -A/--after can be used to remove only files that have already
4788 -A/--after can be used to remove only files that have already
4782 been deleted, -f/--force can be used to force deletion, and -Af
4789 been deleted, -f/--force can be used to force deletion, and -Af
4783 can be used to remove files from the next revision without
4790 can be used to remove files from the next revision without
4784 deleting them from the working directory.
4791 deleting them from the working directory.
4785
4792
4786 The following table details the behavior of remove for different
4793 The following table details the behavior of remove for different
4787 file states (columns) and option combinations (rows). The file
4794 file states (columns) and option combinations (rows). The file
4788 states are Added [A], Clean [C], Modified [M] and Missing [!]
4795 states are Added [A], Clean [C], Modified [M] and Missing [!]
4789 (as reported by :hg:`status`). The actions are Warn, Remove
4796 (as reported by :hg:`status`). The actions are Warn, Remove
4790 (from branch) and Delete (from disk):
4797 (from branch) and Delete (from disk):
4791
4798
4792 ======= == == == ==
4799 ======= == == == ==
4793 A C M !
4800 A C M !
4794 ======= == == == ==
4801 ======= == == == ==
4795 none W RD W R
4802 none W RD W R
4796 -f R RD RD R
4803 -f R RD RD R
4797 -A W W W R
4804 -A W W W R
4798 -Af R R R R
4805 -Af R R R R
4799 ======= == == == ==
4806 ======= == == == ==
4800
4807
4801 Note that remove never deletes files in Added [A] state from the
4808 Note that remove never deletes files in Added [A] state from the
4802 working directory, not even if option --force is specified.
4809 working directory, not even if option --force is specified.
4803
4810
4804 Returns 0 on success, 1 if any warnings encountered.
4811 Returns 0 on success, 1 if any warnings encountered.
4805 """
4812 """
4806
4813
4807 ret = 0
4814 ret = 0
4808 after, force = opts.get('after'), opts.get('force')
4815 after, force = opts.get('after'), opts.get('force')
4809 if not pats and not after:
4816 if not pats and not after:
4810 raise util.Abort(_('no files specified'))
4817 raise util.Abort(_('no files specified'))
4811
4818
4812 m = scmutil.match(repo[None], pats, opts)
4819 m = scmutil.match(repo[None], pats, opts)
4813 s = repo.status(match=m, clean=True)
4820 s = repo.status(match=m, clean=True)
4814 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4821 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4815
4822
4816 for f in m.files():
4823 for f in m.files():
4817 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4824 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4818 if os.path.exists(m.rel(f)):
4825 if os.path.exists(m.rel(f)):
4819 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4826 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4820 ret = 1
4827 ret = 1
4821
4828
4822 if force:
4829 if force:
4823 list = modified + deleted + clean + added
4830 list = modified + deleted + clean + added
4824 elif after:
4831 elif after:
4825 list = deleted
4832 list = deleted
4826 for f in modified + added + clean:
4833 for f in modified + added + clean:
4827 ui.warn(_('not removing %s: file still exists (use -f'
4834 ui.warn(_('not removing %s: file still exists (use -f'
4828 ' to force removal)\n') % m.rel(f))
4835 ' to force removal)\n') % m.rel(f))
4829 ret = 1
4836 ret = 1
4830 else:
4837 else:
4831 list = deleted + clean
4838 list = deleted + clean
4832 for f in modified:
4839 for f in modified:
4833 ui.warn(_('not removing %s: file is modified (use -f'
4840 ui.warn(_('not removing %s: file is modified (use -f'
4834 ' to force removal)\n') % m.rel(f))
4841 ' to force removal)\n') % m.rel(f))
4835 ret = 1
4842 ret = 1
4836 for f in added:
4843 for f in added:
4837 ui.warn(_('not removing %s: file has been marked for add'
4844 ui.warn(_('not removing %s: file has been marked for add'
4838 ' (use forget to undo)\n') % m.rel(f))
4845 ' (use forget to undo)\n') % m.rel(f))
4839 ret = 1
4846 ret = 1
4840
4847
4841 for f in sorted(list):
4848 for f in sorted(list):
4842 if ui.verbose or not m.exact(f):
4849 if ui.verbose or not m.exact(f):
4843 ui.status(_('removing %s\n') % m.rel(f))
4850 ui.status(_('removing %s\n') % m.rel(f))
4844
4851
4845 wlock = repo.wlock()
4852 wlock = repo.wlock()
4846 try:
4853 try:
4847 if not after:
4854 if not after:
4848 for f in list:
4855 for f in list:
4849 if f in added:
4856 if f in added:
4850 continue # we never unlink added files on remove
4857 continue # we never unlink added files on remove
4851 try:
4858 try:
4852 util.unlinkpath(repo.wjoin(f))
4859 util.unlinkpath(repo.wjoin(f))
4853 except OSError, inst:
4860 except OSError, inst:
4854 if inst.errno != errno.ENOENT:
4861 if inst.errno != errno.ENOENT:
4855 raise
4862 raise
4856 repo[None].forget(list)
4863 repo[None].forget(list)
4857 finally:
4864 finally:
4858 wlock.release()
4865 wlock.release()
4859
4866
4860 return ret
4867 return ret
4861
4868
4862 @command('rename|move|mv',
4869 @command('rename|move|mv',
4863 [('A', 'after', None, _('record a rename that has already occurred')),
4870 [('A', 'after', None, _('record a rename that has already occurred')),
4864 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4871 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4865 ] + walkopts + dryrunopts,
4872 ] + walkopts + dryrunopts,
4866 _('[OPTION]... SOURCE... DEST'))
4873 _('[OPTION]... SOURCE... DEST'))
4867 def rename(ui, repo, *pats, **opts):
4874 def rename(ui, repo, *pats, **opts):
4868 """rename files; equivalent of copy + remove
4875 """rename files; equivalent of copy + remove
4869
4876
4870 Mark dest as copies of sources; mark sources for deletion. If dest
4877 Mark dest as copies of sources; mark sources for deletion. If dest
4871 is a directory, copies are put in that directory. If dest is a
4878 is a directory, copies are put in that directory. If dest is a
4872 file, there can only be one source.
4879 file, there can only be one source.
4873
4880
4874 By default, this command copies the contents of files as they
4881 By default, this command copies the contents of files as they
4875 exist in the working directory. If invoked with -A/--after, the
4882 exist in the working directory. If invoked with -A/--after, the
4876 operation is recorded, but no copying is performed.
4883 operation is recorded, but no copying is performed.
4877
4884
4878 This command takes effect at the next commit. To undo a rename
4885 This command takes effect at the next commit. To undo a rename
4879 before that, see :hg:`revert`.
4886 before that, see :hg:`revert`.
4880
4887
4881 Returns 0 on success, 1 if errors are encountered.
4888 Returns 0 on success, 1 if errors are encountered.
4882 """
4889 """
4883 wlock = repo.wlock(False)
4890 wlock = repo.wlock(False)
4884 try:
4891 try:
4885 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4892 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4886 finally:
4893 finally:
4887 wlock.release()
4894 wlock.release()
4888
4895
4889 @command('resolve',
4896 @command('resolve',
4890 [('a', 'all', None, _('select all unresolved files')),
4897 [('a', 'all', None, _('select all unresolved files')),
4891 ('l', 'list', None, _('list state of files needing merge')),
4898 ('l', 'list', None, _('list state of files needing merge')),
4892 ('m', 'mark', None, _('mark files as resolved')),
4899 ('m', 'mark', None, _('mark files as resolved')),
4893 ('u', 'unmark', None, _('mark files as unresolved')),
4900 ('u', 'unmark', None, _('mark files as unresolved')),
4894 ('n', 'no-status', None, _('hide status prefix'))]
4901 ('n', 'no-status', None, _('hide status prefix'))]
4895 + mergetoolopts + walkopts,
4902 + mergetoolopts + walkopts,
4896 _('[OPTION]... [FILE]...'))
4903 _('[OPTION]... [FILE]...'))
4897 def resolve(ui, repo, *pats, **opts):
4904 def resolve(ui, repo, *pats, **opts):
4898 """redo merges or set/view the merge status of files
4905 """redo merges or set/view the merge status of files
4899
4906
4900 Merges with unresolved conflicts are often the result of
4907 Merges with unresolved conflicts are often the result of
4901 non-interactive merging using the ``internal:merge`` configuration
4908 non-interactive merging using the ``internal:merge`` configuration
4902 setting, or a command-line merge tool like ``diff3``. The resolve
4909 setting, or a command-line merge tool like ``diff3``. The resolve
4903 command is used to manage the files involved in a merge, after
4910 command is used to manage the files involved in a merge, after
4904 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4911 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4905 working directory must have two parents). See :hg:`help
4912 working directory must have two parents). See :hg:`help
4906 merge-tools` for information on configuring merge tools.
4913 merge-tools` for information on configuring merge tools.
4907
4914
4908 The resolve command can be used in the following ways:
4915 The resolve command can be used in the following ways:
4909
4916
4910 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4917 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4911 files, discarding any previous merge attempts. Re-merging is not
4918 files, discarding any previous merge attempts. Re-merging is not
4912 performed for files already marked as resolved. Use ``--all/-a``
4919 performed for files already marked as resolved. Use ``--all/-a``
4913 to select all unresolved files. ``--tool`` can be used to specify
4920 to select all unresolved files. ``--tool`` can be used to specify
4914 the merge tool used for the given files. It overrides the HGMERGE
4921 the merge tool used for the given files. It overrides the HGMERGE
4915 environment variable and your configuration files. Previous file
4922 environment variable and your configuration files. Previous file
4916 contents are saved with a ``.orig`` suffix.
4923 contents are saved with a ``.orig`` suffix.
4917
4924
4918 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4925 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4919 (e.g. after having manually fixed-up the files). The default is
4926 (e.g. after having manually fixed-up the files). The default is
4920 to mark all unresolved files.
4927 to mark all unresolved files.
4921
4928
4922 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4929 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4923 default is to mark all resolved files.
4930 default is to mark all resolved files.
4924
4931
4925 - :hg:`resolve -l`: list files which had or still have conflicts.
4932 - :hg:`resolve -l`: list files which had or still have conflicts.
4926 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4933 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4927
4934
4928 Note that Mercurial will not let you commit files with unresolved
4935 Note that Mercurial will not let you commit files with unresolved
4929 merge conflicts. You must use :hg:`resolve -m ...` before you can
4936 merge conflicts. You must use :hg:`resolve -m ...` before you can
4930 commit after a conflicting merge.
4937 commit after a conflicting merge.
4931
4938
4932 Returns 0 on success, 1 if any files fail a resolve attempt.
4939 Returns 0 on success, 1 if any files fail a resolve attempt.
4933 """
4940 """
4934
4941
4935 all, mark, unmark, show, nostatus = \
4942 all, mark, unmark, show, nostatus = \
4936 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4943 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4937
4944
4938 if (show and (mark or unmark)) or (mark and unmark):
4945 if (show and (mark or unmark)) or (mark and unmark):
4939 raise util.Abort(_("too many options specified"))
4946 raise util.Abort(_("too many options specified"))
4940 if pats and all:
4947 if pats and all:
4941 raise util.Abort(_("can't specify --all and patterns"))
4948 raise util.Abort(_("can't specify --all and patterns"))
4942 if not (all or pats or show or mark or unmark):
4949 if not (all or pats or show or mark or unmark):
4943 raise util.Abort(_('no files or directories specified; '
4950 raise util.Abort(_('no files or directories specified; '
4944 'use --all to remerge all files'))
4951 'use --all to remerge all files'))
4945
4952
4946 ms = mergemod.mergestate(repo)
4953 ms = mergemod.mergestate(repo)
4947 m = scmutil.match(repo[None], pats, opts)
4954 m = scmutil.match(repo[None], pats, opts)
4948 ret = 0
4955 ret = 0
4949
4956
4950 for f in ms:
4957 for f in ms:
4951 if m(f):
4958 if m(f):
4952 if show:
4959 if show:
4953 if nostatus:
4960 if nostatus:
4954 ui.write("%s\n" % f)
4961 ui.write("%s\n" % f)
4955 else:
4962 else:
4956 ui.write("%s %s\n" % (ms[f].upper(), f),
4963 ui.write("%s %s\n" % (ms[f].upper(), f),
4957 label='resolve.' +
4964 label='resolve.' +
4958 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4965 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4959 elif mark:
4966 elif mark:
4960 ms.mark(f, "r")
4967 ms.mark(f, "r")
4961 elif unmark:
4968 elif unmark:
4962 ms.mark(f, "u")
4969 ms.mark(f, "u")
4963 else:
4970 else:
4964 wctx = repo[None]
4971 wctx = repo[None]
4965 mctx = wctx.parents()[-1]
4972 mctx = wctx.parents()[-1]
4966
4973
4967 # backup pre-resolve (merge uses .orig for its own purposes)
4974 # backup pre-resolve (merge uses .orig for its own purposes)
4968 a = repo.wjoin(f)
4975 a = repo.wjoin(f)
4969 util.copyfile(a, a + ".resolve")
4976 util.copyfile(a, a + ".resolve")
4970
4977
4971 try:
4978 try:
4972 # resolve file
4979 # resolve file
4973 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4980 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4974 if ms.resolve(f, wctx, mctx):
4981 if ms.resolve(f, wctx, mctx):
4975 ret = 1
4982 ret = 1
4976 finally:
4983 finally:
4977 ui.setconfig('ui', 'forcemerge', '')
4984 ui.setconfig('ui', 'forcemerge', '')
4978 ms.commit()
4985 ms.commit()
4979
4986
4980 # replace filemerge's .orig file with our resolve file
4987 # replace filemerge's .orig file with our resolve file
4981 util.rename(a + ".resolve", a + ".orig")
4988 util.rename(a + ".resolve", a + ".orig")
4982
4989
4983 ms.commit()
4990 ms.commit()
4984 return ret
4991 return ret
4985
4992
4986 @command('revert',
4993 @command('revert',
4987 [('a', 'all', None, _('revert all changes when no arguments given')),
4994 [('a', 'all', None, _('revert all changes when no arguments given')),
4988 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4995 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4989 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4996 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4990 ('C', 'no-backup', None, _('do not save backup copies of files')),
4997 ('C', 'no-backup', None, _('do not save backup copies of files')),
4991 ] + walkopts + dryrunopts,
4998 ] + walkopts + dryrunopts,
4992 _('[OPTION]... [-r REV] [NAME]...'))
4999 _('[OPTION]... [-r REV] [NAME]...'))
4993 def revert(ui, repo, *pats, **opts):
5000 def revert(ui, repo, *pats, **opts):
4994 """restore files to their checkout state
5001 """restore files to their checkout state
4995
5002
4996 .. note::
5003 .. note::
4997
5004
4998 To check out earlier revisions, you should use :hg:`update REV`.
5005 To check out earlier revisions, you should use :hg:`update REV`.
4999 To cancel an uncommitted merge (and lose your changes), use
5006 To cancel an uncommitted merge (and lose your changes), use
5000 :hg:`update --clean .`.
5007 :hg:`update --clean .`.
5001
5008
5002 With no revision specified, revert the specified files or directories
5009 With no revision specified, revert the specified files or directories
5003 to the contents they had in the parent of the working directory.
5010 to the contents they had in the parent of the working directory.
5004 This restores the contents of files to an unmodified
5011 This restores the contents of files to an unmodified
5005 state and unschedules adds, removes, copies, and renames. If the
5012 state and unschedules adds, removes, copies, and renames. If the
5006 working directory has two parents, you must explicitly specify a
5013 working directory has two parents, you must explicitly specify a
5007 revision.
5014 revision.
5008
5015
5009 Using the -r/--rev or -d/--date options, revert the given files or
5016 Using the -r/--rev or -d/--date options, revert the given files or
5010 directories to their states as of a specific revision. Because
5017 directories to their states as of a specific revision. Because
5011 revert does not change the working directory parents, this will
5018 revert does not change the working directory parents, this will
5012 cause these files to appear modified. This can be helpful to "back
5019 cause these files to appear modified. This can be helpful to "back
5013 out" some or all of an earlier change. See :hg:`backout` for a
5020 out" some or all of an earlier change. See :hg:`backout` for a
5014 related method.
5021 related method.
5015
5022
5016 Modified files are saved with a .orig suffix before reverting.
5023 Modified files are saved with a .orig suffix before reverting.
5017 To disable these backups, use --no-backup.
5024 To disable these backups, use --no-backup.
5018
5025
5019 See :hg:`help dates` for a list of formats valid for -d/--date.
5026 See :hg:`help dates` for a list of formats valid for -d/--date.
5020
5027
5021 Returns 0 on success.
5028 Returns 0 on success.
5022 """
5029 """
5023
5030
5024 if opts.get("date"):
5031 if opts.get("date"):
5025 if opts.get("rev"):
5032 if opts.get("rev"):
5026 raise util.Abort(_("you can't specify a revision and a date"))
5033 raise util.Abort(_("you can't specify a revision and a date"))
5027 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5034 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5028
5035
5029 parent, p2 = repo.dirstate.parents()
5036 parent, p2 = repo.dirstate.parents()
5030 if not opts.get('rev') and p2 != nullid:
5037 if not opts.get('rev') and p2 != nullid:
5031 # revert after merge is a trap for new users (issue2915)
5038 # revert after merge is a trap for new users (issue2915)
5032 raise util.Abort(_('uncommitted merge with no revision specified'),
5039 raise util.Abort(_('uncommitted merge with no revision specified'),
5033 hint=_('use "hg update" or see "hg help revert"'))
5040 hint=_('use "hg update" or see "hg help revert"'))
5034
5041
5035 ctx = scmutil.revsingle(repo, opts.get('rev'))
5042 ctx = scmutil.revsingle(repo, opts.get('rev'))
5036
5043
5037 if not pats and not opts.get('all'):
5044 if not pats and not opts.get('all'):
5038 msg = _("no files or directories specified")
5045 msg = _("no files or directories specified")
5039 if p2 != nullid:
5046 if p2 != nullid:
5040 hint = _("uncommitted merge, use --all to discard all changes,"
5047 hint = _("uncommitted merge, use --all to discard all changes,"
5041 " or 'hg update -C .' to abort the merge")
5048 " or 'hg update -C .' to abort the merge")
5042 raise util.Abort(msg, hint=hint)
5049 raise util.Abort(msg, hint=hint)
5043 dirty = util.any(repo.status())
5050 dirty = util.any(repo.status())
5044 node = ctx.node()
5051 node = ctx.node()
5045 if node != parent:
5052 if node != parent:
5046 if dirty:
5053 if dirty:
5047 hint = _("uncommitted changes, use --all to discard all"
5054 hint = _("uncommitted changes, use --all to discard all"
5048 " changes, or 'hg update %s' to update") % ctx.rev()
5055 " changes, or 'hg update %s' to update") % ctx.rev()
5049 else:
5056 else:
5050 hint = _("use --all to revert all files,"
5057 hint = _("use --all to revert all files,"
5051 " or 'hg update %s' to update") % ctx.rev()
5058 " or 'hg update %s' to update") % ctx.rev()
5052 elif dirty:
5059 elif dirty:
5053 hint = _("uncommitted changes, use --all to discard all changes")
5060 hint = _("uncommitted changes, use --all to discard all changes")
5054 else:
5061 else:
5055 hint = _("use --all to revert all files")
5062 hint = _("use --all to revert all files")
5056 raise util.Abort(msg, hint=hint)
5063 raise util.Abort(msg, hint=hint)
5057
5064
5058 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5065 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5059
5066
5060 @command('rollback', dryrunopts +
5067 @command('rollback', dryrunopts +
5061 [('f', 'force', False, _('ignore safety measures'))])
5068 [('f', 'force', False, _('ignore safety measures'))])
5062 def rollback(ui, repo, **opts):
5069 def rollback(ui, repo, **opts):
5063 """roll back the last transaction (dangerous)
5070 """roll back the last transaction (dangerous)
5064
5071
5065 This command should be used with care. There is only one level of
5072 This command should be used with care. There is only one level of
5066 rollback, and there is no way to undo a rollback. It will also
5073 rollback, and there is no way to undo a rollback. It will also
5067 restore the dirstate at the time of the last transaction, losing
5074 restore the dirstate at the time of the last transaction, losing
5068 any dirstate changes since that time. This command does not alter
5075 any dirstate changes since that time. This command does not alter
5069 the working directory.
5076 the working directory.
5070
5077
5071 Transactions are used to encapsulate the effects of all commands
5078 Transactions are used to encapsulate the effects of all commands
5072 that create new changesets or propagate existing changesets into a
5079 that create new changesets or propagate existing changesets into a
5073 repository.
5080 repository.
5074
5081
5075 .. container:: verbose
5082 .. container:: verbose
5076
5083
5077 For example, the following commands are transactional, and their
5084 For example, the following commands are transactional, and their
5078 effects can be rolled back:
5085 effects can be rolled back:
5079
5086
5080 - commit
5087 - commit
5081 - import
5088 - import
5082 - pull
5089 - pull
5083 - push (with this repository as the destination)
5090 - push (with this repository as the destination)
5084 - unbundle
5091 - unbundle
5085
5092
5086 To avoid permanent data loss, rollback will refuse to rollback a
5093 To avoid permanent data loss, rollback will refuse to rollback a
5087 commit transaction if it isn't checked out. Use --force to
5094 commit transaction if it isn't checked out. Use --force to
5088 override this protection.
5095 override this protection.
5089
5096
5090 This command is not intended for use on public repositories. Once
5097 This command is not intended for use on public repositories. Once
5091 changes are visible for pull by other users, rolling a transaction
5098 changes are visible for pull by other users, rolling a transaction
5092 back locally is ineffective (someone else may already have pulled
5099 back locally is ineffective (someone else may already have pulled
5093 the changes). Furthermore, a race is possible with readers of the
5100 the changes). Furthermore, a race is possible with readers of the
5094 repository; for example an in-progress pull from the repository
5101 repository; for example an in-progress pull from the repository
5095 may fail if a rollback is performed.
5102 may fail if a rollback is performed.
5096
5103
5097 Returns 0 on success, 1 if no rollback data is available.
5104 Returns 0 on success, 1 if no rollback data is available.
5098 """
5105 """
5099 return repo.rollback(dryrun=opts.get('dry_run'),
5106 return repo.rollback(dryrun=opts.get('dry_run'),
5100 force=opts.get('force'))
5107 force=opts.get('force'))
5101
5108
5102 @command('root', [])
5109 @command('root', [])
5103 def root(ui, repo):
5110 def root(ui, repo):
5104 """print the root (top) of the current working directory
5111 """print the root (top) of the current working directory
5105
5112
5106 Print the root directory of the current repository.
5113 Print the root directory of the current repository.
5107
5114
5108 Returns 0 on success.
5115 Returns 0 on success.
5109 """
5116 """
5110 ui.write(repo.root + "\n")
5117 ui.write(repo.root + "\n")
5111
5118
5112 @command('^serve',
5119 @command('^serve',
5113 [('A', 'accesslog', '', _('name of access log file to write to'),
5120 [('A', 'accesslog', '', _('name of access log file to write to'),
5114 _('FILE')),
5121 _('FILE')),
5115 ('d', 'daemon', None, _('run server in background')),
5122 ('d', 'daemon', None, _('run server in background')),
5116 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5123 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5117 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5124 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5118 # use string type, then we can check if something was passed
5125 # use string type, then we can check if something was passed
5119 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5126 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5120 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5127 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5121 _('ADDR')),
5128 _('ADDR')),
5122 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5129 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5123 _('PREFIX')),
5130 _('PREFIX')),
5124 ('n', 'name', '',
5131 ('n', 'name', '',
5125 _('name to show in web pages (default: working directory)'), _('NAME')),
5132 _('name to show in web pages (default: working directory)'), _('NAME')),
5126 ('', 'web-conf', '',
5133 ('', 'web-conf', '',
5127 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5134 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5128 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5135 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5129 _('FILE')),
5136 _('FILE')),
5130 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5137 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5131 ('', 'stdio', None, _('for remote clients')),
5138 ('', 'stdio', None, _('for remote clients')),
5132 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5139 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5133 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5140 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5134 ('', 'style', '', _('template style to use'), _('STYLE')),
5141 ('', 'style', '', _('template style to use'), _('STYLE')),
5135 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5142 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5136 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5143 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5137 _('[OPTION]...'))
5144 _('[OPTION]...'))
5138 def serve(ui, repo, **opts):
5145 def serve(ui, repo, **opts):
5139 """start stand-alone webserver
5146 """start stand-alone webserver
5140
5147
5141 Start a local HTTP repository browser and pull server. You can use
5148 Start a local HTTP repository browser and pull server. You can use
5142 this for ad-hoc sharing and browsing of repositories. It is
5149 this for ad-hoc sharing and browsing of repositories. It is
5143 recommended to use a real web server to serve a repository for
5150 recommended to use a real web server to serve a repository for
5144 longer periods of time.
5151 longer periods of time.
5145
5152
5146 Please note that the server does not implement access control.
5153 Please note that the server does not implement access control.
5147 This means that, by default, anybody can read from the server and
5154 This means that, by default, anybody can read from the server and
5148 nobody can write to it by default. Set the ``web.allow_push``
5155 nobody can write to it by default. Set the ``web.allow_push``
5149 option to ``*`` to allow everybody to push to the server. You
5156 option to ``*`` to allow everybody to push to the server. You
5150 should use a real web server if you need to authenticate users.
5157 should use a real web server if you need to authenticate users.
5151
5158
5152 By default, the server logs accesses to stdout and errors to
5159 By default, the server logs accesses to stdout and errors to
5153 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5160 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5154 files.
5161 files.
5155
5162
5156 To have the server choose a free port number to listen on, specify
5163 To have the server choose a free port number to listen on, specify
5157 a port number of 0; in this case, the server will print the port
5164 a port number of 0; in this case, the server will print the port
5158 number it uses.
5165 number it uses.
5159
5166
5160 Returns 0 on success.
5167 Returns 0 on success.
5161 """
5168 """
5162
5169
5163 if opts["stdio"] and opts["cmdserver"]:
5170 if opts["stdio"] and opts["cmdserver"]:
5164 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5171 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5165
5172
5166 def checkrepo():
5173 def checkrepo():
5167 if repo is None:
5174 if repo is None:
5168 raise error.RepoError(_("there is no Mercurial repository here"
5175 raise error.RepoError(_("there is no Mercurial repository here"
5169 " (.hg not found)"))
5176 " (.hg not found)"))
5170
5177
5171 if opts["stdio"]:
5178 if opts["stdio"]:
5172 checkrepo()
5179 checkrepo()
5173 s = sshserver.sshserver(ui, repo)
5180 s = sshserver.sshserver(ui, repo)
5174 s.serve_forever()
5181 s.serve_forever()
5175
5182
5176 if opts["cmdserver"]:
5183 if opts["cmdserver"]:
5177 checkrepo()
5184 checkrepo()
5178 s = commandserver.server(ui, repo, opts["cmdserver"])
5185 s = commandserver.server(ui, repo, opts["cmdserver"])
5179 return s.serve()
5186 return s.serve()
5180
5187
5181 # this way we can check if something was given in the command-line
5188 # this way we can check if something was given in the command-line
5182 if opts.get('port'):
5189 if opts.get('port'):
5183 opts['port'] = util.getport(opts.get('port'))
5190 opts['port'] = util.getport(opts.get('port'))
5184
5191
5185 baseui = repo and repo.baseui or ui
5192 baseui = repo and repo.baseui or ui
5186 optlist = ("name templates style address port prefix ipv6"
5193 optlist = ("name templates style address port prefix ipv6"
5187 " accesslog errorlog certificate encoding")
5194 " accesslog errorlog certificate encoding")
5188 for o in optlist.split():
5195 for o in optlist.split():
5189 val = opts.get(o, '')
5196 val = opts.get(o, '')
5190 if val in (None, ''): # should check against default options instead
5197 if val in (None, ''): # should check against default options instead
5191 continue
5198 continue
5192 baseui.setconfig("web", o, val)
5199 baseui.setconfig("web", o, val)
5193 if repo and repo.ui != baseui:
5200 if repo and repo.ui != baseui:
5194 repo.ui.setconfig("web", o, val)
5201 repo.ui.setconfig("web", o, val)
5195
5202
5196 o = opts.get('web_conf') or opts.get('webdir_conf')
5203 o = opts.get('web_conf') or opts.get('webdir_conf')
5197 if not o:
5204 if not o:
5198 if not repo:
5205 if not repo:
5199 raise error.RepoError(_("there is no Mercurial repository"
5206 raise error.RepoError(_("there is no Mercurial repository"
5200 " here (.hg not found)"))
5207 " here (.hg not found)"))
5201 o = repo.root
5208 o = repo.root
5202
5209
5203 app = hgweb.hgweb(o, baseui=ui)
5210 app = hgweb.hgweb(o, baseui=ui)
5204
5211
5205 class service(object):
5212 class service(object):
5206 def init(self):
5213 def init(self):
5207 util.setsignalhandler()
5214 util.setsignalhandler()
5208 self.httpd = hgweb.server.create_server(ui, app)
5215 self.httpd = hgweb.server.create_server(ui, app)
5209
5216
5210 if opts['port'] and not ui.verbose:
5217 if opts['port'] and not ui.verbose:
5211 return
5218 return
5212
5219
5213 if self.httpd.prefix:
5220 if self.httpd.prefix:
5214 prefix = self.httpd.prefix.strip('/') + '/'
5221 prefix = self.httpd.prefix.strip('/') + '/'
5215 else:
5222 else:
5216 prefix = ''
5223 prefix = ''
5217
5224
5218 port = ':%d' % self.httpd.port
5225 port = ':%d' % self.httpd.port
5219 if port == ':80':
5226 if port == ':80':
5220 port = ''
5227 port = ''
5221
5228
5222 bindaddr = self.httpd.addr
5229 bindaddr = self.httpd.addr
5223 if bindaddr == '0.0.0.0':
5230 if bindaddr == '0.0.0.0':
5224 bindaddr = '*'
5231 bindaddr = '*'
5225 elif ':' in bindaddr: # IPv6
5232 elif ':' in bindaddr: # IPv6
5226 bindaddr = '[%s]' % bindaddr
5233 bindaddr = '[%s]' % bindaddr
5227
5234
5228 fqaddr = self.httpd.fqaddr
5235 fqaddr = self.httpd.fqaddr
5229 if ':' in fqaddr:
5236 if ':' in fqaddr:
5230 fqaddr = '[%s]' % fqaddr
5237 fqaddr = '[%s]' % fqaddr
5231 if opts['port']:
5238 if opts['port']:
5232 write = ui.status
5239 write = ui.status
5233 else:
5240 else:
5234 write = ui.write
5241 write = ui.write
5235 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5242 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5236 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5243 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5237
5244
5238 def run(self):
5245 def run(self):
5239 self.httpd.serve_forever()
5246 self.httpd.serve_forever()
5240
5247
5241 service = service()
5248 service = service()
5242
5249
5243 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5250 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5244
5251
5245 @command('showconfig|debugconfig',
5252 @command('showconfig|debugconfig',
5246 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5253 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5247 _('[-u] [NAME]...'))
5254 _('[-u] [NAME]...'))
5248 def showconfig(ui, repo, *values, **opts):
5255 def showconfig(ui, repo, *values, **opts):
5249 """show combined config settings from all hgrc files
5256 """show combined config settings from all hgrc files
5250
5257
5251 With no arguments, print names and values of all config items.
5258 With no arguments, print names and values of all config items.
5252
5259
5253 With one argument of the form section.name, print just the value
5260 With one argument of the form section.name, print just the value
5254 of that config item.
5261 of that config item.
5255
5262
5256 With multiple arguments, print names and values of all config
5263 With multiple arguments, print names and values of all config
5257 items with matching section names.
5264 items with matching section names.
5258
5265
5259 With --debug, the source (filename and line number) is printed
5266 With --debug, the source (filename and line number) is printed
5260 for each config item.
5267 for each config item.
5261
5268
5262 Returns 0 on success.
5269 Returns 0 on success.
5263 """
5270 """
5264
5271
5265 for f in scmutil.rcpath():
5272 for f in scmutil.rcpath():
5266 ui.debug('read config from: %s\n' % f)
5273 ui.debug('read config from: %s\n' % f)
5267 untrusted = bool(opts.get('untrusted'))
5274 untrusted = bool(opts.get('untrusted'))
5268 if values:
5275 if values:
5269 sections = [v for v in values if '.' not in v]
5276 sections = [v for v in values if '.' not in v]
5270 items = [v for v in values if '.' in v]
5277 items = [v for v in values if '.' in v]
5271 if len(items) > 1 or items and sections:
5278 if len(items) > 1 or items and sections:
5272 raise util.Abort(_('only one config item permitted'))
5279 raise util.Abort(_('only one config item permitted'))
5273 for section, name, value in ui.walkconfig(untrusted=untrusted):
5280 for section, name, value in ui.walkconfig(untrusted=untrusted):
5274 value = str(value).replace('\n', '\\n')
5281 value = str(value).replace('\n', '\\n')
5275 sectname = section + '.' + name
5282 sectname = section + '.' + name
5276 if values:
5283 if values:
5277 for v in values:
5284 for v in values:
5278 if v == section:
5285 if v == section:
5279 ui.debug('%s: ' %
5286 ui.debug('%s: ' %
5280 ui.configsource(section, name, untrusted))
5287 ui.configsource(section, name, untrusted))
5281 ui.write('%s=%s\n' % (sectname, value))
5288 ui.write('%s=%s\n' % (sectname, value))
5282 elif v == sectname:
5289 elif v == sectname:
5283 ui.debug('%s: ' %
5290 ui.debug('%s: ' %
5284 ui.configsource(section, name, untrusted))
5291 ui.configsource(section, name, untrusted))
5285 ui.write(value, '\n')
5292 ui.write(value, '\n')
5286 else:
5293 else:
5287 ui.debug('%s: ' %
5294 ui.debug('%s: ' %
5288 ui.configsource(section, name, untrusted))
5295 ui.configsource(section, name, untrusted))
5289 ui.write('%s=%s\n' % (sectname, value))
5296 ui.write('%s=%s\n' % (sectname, value))
5290
5297
5291 @command('^status|st',
5298 @command('^status|st',
5292 [('A', 'all', None, _('show status of all files')),
5299 [('A', 'all', None, _('show status of all files')),
5293 ('m', 'modified', None, _('show only modified files')),
5300 ('m', 'modified', None, _('show only modified files')),
5294 ('a', 'added', None, _('show only added files')),
5301 ('a', 'added', None, _('show only added files')),
5295 ('r', 'removed', None, _('show only removed files')),
5302 ('r', 'removed', None, _('show only removed files')),
5296 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5303 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5297 ('c', 'clean', None, _('show only files without changes')),
5304 ('c', 'clean', None, _('show only files without changes')),
5298 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5305 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5299 ('i', 'ignored', None, _('show only ignored files')),
5306 ('i', 'ignored', None, _('show only ignored files')),
5300 ('n', 'no-status', None, _('hide status prefix')),
5307 ('n', 'no-status', None, _('hide status prefix')),
5301 ('C', 'copies', None, _('show source of copied files')),
5308 ('C', 'copies', None, _('show source of copied files')),
5302 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5309 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5303 ('', 'rev', [], _('show difference from revision'), _('REV')),
5310 ('', 'rev', [], _('show difference from revision'), _('REV')),
5304 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5311 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5305 ] + walkopts + subrepoopts,
5312 ] + walkopts + subrepoopts,
5306 _('[OPTION]... [FILE]...'))
5313 _('[OPTION]... [FILE]...'))
5307 def status(ui, repo, *pats, **opts):
5314 def status(ui, repo, *pats, **opts):
5308 """show changed files in the working directory
5315 """show changed files in the working directory
5309
5316
5310 Show status of files in the repository. If names are given, only
5317 Show status of files in the repository. If names are given, only
5311 files that match are shown. Files that are clean or ignored or
5318 files that match are shown. Files that are clean or ignored or
5312 the source of a copy/move operation, are not listed unless
5319 the source of a copy/move operation, are not listed unless
5313 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5320 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5314 Unless options described with "show only ..." are given, the
5321 Unless options described with "show only ..." are given, the
5315 options -mardu are used.
5322 options -mardu are used.
5316
5323
5317 Option -q/--quiet hides untracked (unknown and ignored) files
5324 Option -q/--quiet hides untracked (unknown and ignored) files
5318 unless explicitly requested with -u/--unknown or -i/--ignored.
5325 unless explicitly requested with -u/--unknown or -i/--ignored.
5319
5326
5320 .. note::
5327 .. note::
5321 status may appear to disagree with diff if permissions have
5328 status may appear to disagree with diff if permissions have
5322 changed or a merge has occurred. The standard diff format does
5329 changed or a merge has occurred. The standard diff format does
5323 not report permission changes and diff only reports changes
5330 not report permission changes and diff only reports changes
5324 relative to one merge parent.
5331 relative to one merge parent.
5325
5332
5326 If one revision is given, it is used as the base revision.
5333 If one revision is given, it is used as the base revision.
5327 If two revisions are given, the differences between them are
5334 If two revisions are given, the differences between them are
5328 shown. The --change option can also be used as a shortcut to list
5335 shown. The --change option can also be used as a shortcut to list
5329 the changed files of a revision from its first parent.
5336 the changed files of a revision from its first parent.
5330
5337
5331 The codes used to show the status of files are::
5338 The codes used to show the status of files are::
5332
5339
5333 M = modified
5340 M = modified
5334 A = added
5341 A = added
5335 R = removed
5342 R = removed
5336 C = clean
5343 C = clean
5337 ! = missing (deleted by non-hg command, but still tracked)
5344 ! = missing (deleted by non-hg command, but still tracked)
5338 ? = not tracked
5345 ? = not tracked
5339 I = ignored
5346 I = ignored
5340 = origin of the previous file listed as A (added)
5347 = origin of the previous file listed as A (added)
5341
5348
5342 .. container:: verbose
5349 .. container:: verbose
5343
5350
5344 Examples:
5351 Examples:
5345
5352
5346 - show changes in the working directory relative to a
5353 - show changes in the working directory relative to a
5347 changeset::
5354 changeset::
5348
5355
5349 hg status --rev 9353
5356 hg status --rev 9353
5350
5357
5351 - show all changes including copies in an existing changeset::
5358 - show all changes including copies in an existing changeset::
5352
5359
5353 hg status --copies --change 9353
5360 hg status --copies --change 9353
5354
5361
5355 - get a NUL separated list of added files, suitable for xargs::
5362 - get a NUL separated list of added files, suitable for xargs::
5356
5363
5357 hg status -an0
5364 hg status -an0
5358
5365
5359 Returns 0 on success.
5366 Returns 0 on success.
5360 """
5367 """
5361
5368
5362 revs = opts.get('rev')
5369 revs = opts.get('rev')
5363 change = opts.get('change')
5370 change = opts.get('change')
5364
5371
5365 if revs and change:
5372 if revs and change:
5366 msg = _('cannot specify --rev and --change at the same time')
5373 msg = _('cannot specify --rev and --change at the same time')
5367 raise util.Abort(msg)
5374 raise util.Abort(msg)
5368 elif change:
5375 elif change:
5369 node2 = scmutil.revsingle(repo, change, None).node()
5376 node2 = scmutil.revsingle(repo, change, None).node()
5370 node1 = repo[node2].p1().node()
5377 node1 = repo[node2].p1().node()
5371 else:
5378 else:
5372 node1, node2 = scmutil.revpair(repo, revs)
5379 node1, node2 = scmutil.revpair(repo, revs)
5373
5380
5374 cwd = (pats and repo.getcwd()) or ''
5381 cwd = (pats and repo.getcwd()) or ''
5375 end = opts.get('print0') and '\0' or '\n'
5382 end = opts.get('print0') and '\0' or '\n'
5376 copy = {}
5383 copy = {}
5377 states = 'modified added removed deleted unknown ignored clean'.split()
5384 states = 'modified added removed deleted unknown ignored clean'.split()
5378 show = [k for k in states if opts.get(k)]
5385 show = [k for k in states if opts.get(k)]
5379 if opts.get('all'):
5386 if opts.get('all'):
5380 show += ui.quiet and (states[:4] + ['clean']) or states
5387 show += ui.quiet and (states[:4] + ['clean']) or states
5381 if not show:
5388 if not show:
5382 show = ui.quiet and states[:4] or states[:5]
5389 show = ui.quiet and states[:4] or states[:5]
5383
5390
5384 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5391 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5385 'ignored' in show, 'clean' in show, 'unknown' in show,
5392 'ignored' in show, 'clean' in show, 'unknown' in show,
5386 opts.get('subrepos'))
5393 opts.get('subrepos'))
5387 changestates = zip(states, 'MAR!?IC', stat)
5394 changestates = zip(states, 'MAR!?IC', stat)
5388
5395
5389 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5396 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5390 copy = copies.pathcopies(repo[node1], repo[node2])
5397 copy = copies.pathcopies(repo[node1], repo[node2])
5391
5398
5392 fm = ui.formatter('status', opts)
5399 fm = ui.formatter('status', opts)
5393 format = '%s %s' + end
5400 format = '%s %s' + end
5394 if opts.get('no_status'):
5401 if opts.get('no_status'):
5395 format = '%.0s%s' + end
5402 format = '%.0s%s' + end
5396
5403
5397 for state, char, files in changestates:
5404 for state, char, files in changestates:
5398 if state in show:
5405 if state in show:
5399 label = 'status.' + state
5406 label = 'status.' + state
5400 for f in files:
5407 for f in files:
5401 fm.startitem()
5408 fm.startitem()
5402 fm.write("status path", format, char,
5409 fm.write("status path", format, char,
5403 repo.pathto(f, cwd), label=label)
5410 repo.pathto(f, cwd), label=label)
5404 if f in copy:
5411 if f in copy:
5405 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5412 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5406 label='status.copied')
5413 label='status.copied')
5407 fm.end()
5414 fm.end()
5408
5415
5409 @command('^summary|sum',
5416 @command('^summary|sum',
5410 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5417 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5411 def summary(ui, repo, **opts):
5418 def summary(ui, repo, **opts):
5412 """summarize working directory state
5419 """summarize working directory state
5413
5420
5414 This generates a brief summary of the working directory state,
5421 This generates a brief summary of the working directory state,
5415 including parents, branch, commit status, and available updates.
5422 including parents, branch, commit status, and available updates.
5416
5423
5417 With the --remote option, this will check the default paths for
5424 With the --remote option, this will check the default paths for
5418 incoming and outgoing changes. This can be time-consuming.
5425 incoming and outgoing changes. This can be time-consuming.
5419
5426
5420 Returns 0 on success.
5427 Returns 0 on success.
5421 """
5428 """
5422
5429
5423 ctx = repo[None]
5430 ctx = repo[None]
5424 parents = ctx.parents()
5431 parents = ctx.parents()
5425 pnode = parents[0].node()
5432 pnode = parents[0].node()
5426 marks = []
5433 marks = []
5427
5434
5428 for p in parents:
5435 for p in parents:
5429 # label with log.changeset (instead of log.parent) since this
5436 # label with log.changeset (instead of log.parent) since this
5430 # shows a working directory parent *changeset*:
5437 # shows a working directory parent *changeset*:
5431 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5438 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5432 label='log.changeset changeset.%s' % p.phasestr())
5439 label='log.changeset changeset.%s' % p.phasestr())
5433 ui.write(' '.join(p.tags()), label='log.tag')
5440 ui.write(' '.join(p.tags()), label='log.tag')
5434 if p.bookmarks():
5441 if p.bookmarks():
5435 marks.extend(p.bookmarks())
5442 marks.extend(p.bookmarks())
5436 if p.rev() == -1:
5443 if p.rev() == -1:
5437 if not len(repo):
5444 if not len(repo):
5438 ui.write(_(' (empty repository)'))
5445 ui.write(_(' (empty repository)'))
5439 else:
5446 else:
5440 ui.write(_(' (no revision checked out)'))
5447 ui.write(_(' (no revision checked out)'))
5441 ui.write('\n')
5448 ui.write('\n')
5442 if p.description():
5449 if p.description():
5443 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5450 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5444 label='log.summary')
5451 label='log.summary')
5445
5452
5446 branch = ctx.branch()
5453 branch = ctx.branch()
5447 bheads = repo.branchheads(branch)
5454 bheads = repo.branchheads(branch)
5448 m = _('branch: %s\n') % branch
5455 m = _('branch: %s\n') % branch
5449 if branch != 'default':
5456 if branch != 'default':
5450 ui.write(m, label='log.branch')
5457 ui.write(m, label='log.branch')
5451 else:
5458 else:
5452 ui.status(m, label='log.branch')
5459 ui.status(m, label='log.branch')
5453
5460
5454 if marks:
5461 if marks:
5455 current = repo._bookmarkcurrent
5462 current = repo._bookmarkcurrent
5456 ui.write(_('bookmarks:'), label='log.bookmark')
5463 ui.write(_('bookmarks:'), label='log.bookmark')
5457 if current is not None:
5464 if current is not None:
5458 try:
5465 try:
5459 marks.remove(current)
5466 marks.remove(current)
5460 ui.write(' *' + current, label='bookmarks.current')
5467 ui.write(' *' + current, label='bookmarks.current')
5461 except ValueError:
5468 except ValueError:
5462 # current bookmark not in parent ctx marks
5469 # current bookmark not in parent ctx marks
5463 pass
5470 pass
5464 for m in marks:
5471 for m in marks:
5465 ui.write(' ' + m, label='log.bookmark')
5472 ui.write(' ' + m, label='log.bookmark')
5466 ui.write('\n', label='log.bookmark')
5473 ui.write('\n', label='log.bookmark')
5467
5474
5468 st = list(repo.status(unknown=True))[:6]
5475 st = list(repo.status(unknown=True))[:6]
5469
5476
5470 c = repo.dirstate.copies()
5477 c = repo.dirstate.copies()
5471 copied, renamed = [], []
5478 copied, renamed = [], []
5472 for d, s in c.iteritems():
5479 for d, s in c.iteritems():
5473 if s in st[2]:
5480 if s in st[2]:
5474 st[2].remove(s)
5481 st[2].remove(s)
5475 renamed.append(d)
5482 renamed.append(d)
5476 else:
5483 else:
5477 copied.append(d)
5484 copied.append(d)
5478 if d in st[1]:
5485 if d in st[1]:
5479 st[1].remove(d)
5486 st[1].remove(d)
5480 st.insert(3, renamed)
5487 st.insert(3, renamed)
5481 st.insert(4, copied)
5488 st.insert(4, copied)
5482
5489
5483 ms = mergemod.mergestate(repo)
5490 ms = mergemod.mergestate(repo)
5484 st.append([f for f in ms if ms[f] == 'u'])
5491 st.append([f for f in ms if ms[f] == 'u'])
5485
5492
5486 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5493 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5487 st.append(subs)
5494 st.append(subs)
5488
5495
5489 labels = [ui.label(_('%d modified'), 'status.modified'),
5496 labels = [ui.label(_('%d modified'), 'status.modified'),
5490 ui.label(_('%d added'), 'status.added'),
5497 ui.label(_('%d added'), 'status.added'),
5491 ui.label(_('%d removed'), 'status.removed'),
5498 ui.label(_('%d removed'), 'status.removed'),
5492 ui.label(_('%d renamed'), 'status.copied'),
5499 ui.label(_('%d renamed'), 'status.copied'),
5493 ui.label(_('%d copied'), 'status.copied'),
5500 ui.label(_('%d copied'), 'status.copied'),
5494 ui.label(_('%d deleted'), 'status.deleted'),
5501 ui.label(_('%d deleted'), 'status.deleted'),
5495 ui.label(_('%d unknown'), 'status.unknown'),
5502 ui.label(_('%d unknown'), 'status.unknown'),
5496 ui.label(_('%d ignored'), 'status.ignored'),
5503 ui.label(_('%d ignored'), 'status.ignored'),
5497 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5504 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5498 ui.label(_('%d subrepos'), 'status.modified')]
5505 ui.label(_('%d subrepos'), 'status.modified')]
5499 t = []
5506 t = []
5500 for s, l in zip(st, labels):
5507 for s, l in zip(st, labels):
5501 if s:
5508 if s:
5502 t.append(l % len(s))
5509 t.append(l % len(s))
5503
5510
5504 t = ', '.join(t)
5511 t = ', '.join(t)
5505 cleanworkdir = False
5512 cleanworkdir = False
5506
5513
5507 if len(parents) > 1:
5514 if len(parents) > 1:
5508 t += _(' (merge)')
5515 t += _(' (merge)')
5509 elif branch != parents[0].branch():
5516 elif branch != parents[0].branch():
5510 t += _(' (new branch)')
5517 t += _(' (new branch)')
5511 elif (parents[0].closesbranch() and
5518 elif (parents[0].closesbranch() and
5512 pnode in repo.branchheads(branch, closed=True)):
5519 pnode in repo.branchheads(branch, closed=True)):
5513 t += _(' (head closed)')
5520 t += _(' (head closed)')
5514 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5521 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5515 t += _(' (clean)')
5522 t += _(' (clean)')
5516 cleanworkdir = True
5523 cleanworkdir = True
5517 elif pnode not in bheads:
5524 elif pnode not in bheads:
5518 t += _(' (new branch head)')
5525 t += _(' (new branch head)')
5519
5526
5520 if cleanworkdir:
5527 if cleanworkdir:
5521 ui.status(_('commit: %s\n') % t.strip())
5528 ui.status(_('commit: %s\n') % t.strip())
5522 else:
5529 else:
5523 ui.write(_('commit: %s\n') % t.strip())
5530 ui.write(_('commit: %s\n') % t.strip())
5524
5531
5525 # all ancestors of branch heads - all ancestors of parent = new csets
5532 # all ancestors of branch heads - all ancestors of parent = new csets
5526 new = [0] * len(repo)
5533 new = [0] * len(repo)
5527 cl = repo.changelog
5534 cl = repo.changelog
5528 for a in [cl.rev(n) for n in bheads]:
5535 for a in [cl.rev(n) for n in bheads]:
5529 new[a] = 1
5536 new[a] = 1
5530 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5537 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5531 new[a] = 1
5538 new[a] = 1
5532 for a in [p.rev() for p in parents]:
5539 for a in [p.rev() for p in parents]:
5533 if a >= 0:
5540 if a >= 0:
5534 new[a] = 0
5541 new[a] = 0
5535 for a in cl.ancestors([p.rev() for p in parents]):
5542 for a in cl.ancestors([p.rev() for p in parents]):
5536 new[a] = 0
5543 new[a] = 0
5537 new = sum(new)
5544 new = sum(new)
5538
5545
5539 if new == 0:
5546 if new == 0:
5540 ui.status(_('update: (current)\n'))
5547 ui.status(_('update: (current)\n'))
5541 elif pnode not in bheads:
5548 elif pnode not in bheads:
5542 ui.write(_('update: %d new changesets (update)\n') % new)
5549 ui.write(_('update: %d new changesets (update)\n') % new)
5543 else:
5550 else:
5544 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5551 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5545 (new, len(bheads)))
5552 (new, len(bheads)))
5546
5553
5547 if opts.get('remote'):
5554 if opts.get('remote'):
5548 t = []
5555 t = []
5549 source, branches = hg.parseurl(ui.expandpath('default'))
5556 source, branches = hg.parseurl(ui.expandpath('default'))
5550 other = hg.peer(repo, {}, source)
5557 other = hg.peer(repo, {}, source)
5551 revs, checkout = hg.addbranchrevs(repo, other, branches,
5558 revs, checkout = hg.addbranchrevs(repo, other, branches,
5552 opts.get('rev'))
5559 opts.get('rev'))
5553 ui.debug('comparing with %s\n' % util.hidepassword(source))
5560 ui.debug('comparing with %s\n' % util.hidepassword(source))
5554 repo.ui.pushbuffer()
5561 repo.ui.pushbuffer()
5555 commoninc = discovery.findcommonincoming(repo, other)
5562 commoninc = discovery.findcommonincoming(repo, other)
5556 _common, incoming, _rheads = commoninc
5563 _common, incoming, _rheads = commoninc
5557 repo.ui.popbuffer()
5564 repo.ui.popbuffer()
5558 if incoming:
5565 if incoming:
5559 t.append(_('1 or more incoming'))
5566 t.append(_('1 or more incoming'))
5560
5567
5561 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5568 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5562 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5569 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5563 if source != dest:
5570 if source != dest:
5564 other = hg.peer(repo, {}, dest)
5571 other = hg.peer(repo, {}, dest)
5565 commoninc = None
5572 commoninc = None
5566 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5573 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5567 repo.ui.pushbuffer()
5574 repo.ui.pushbuffer()
5568 outgoing = discovery.findcommonoutgoing(repo, other,
5575 outgoing = discovery.findcommonoutgoing(repo, other,
5569 commoninc=commoninc)
5576 commoninc=commoninc)
5570 repo.ui.popbuffer()
5577 repo.ui.popbuffer()
5571 o = outgoing.missing
5578 o = outgoing.missing
5572 if o:
5579 if o:
5573 t.append(_('%d outgoing') % len(o))
5580 t.append(_('%d outgoing') % len(o))
5574 if 'bookmarks' in other.listkeys('namespaces'):
5581 if 'bookmarks' in other.listkeys('namespaces'):
5575 lmarks = repo.listkeys('bookmarks')
5582 lmarks = repo.listkeys('bookmarks')
5576 rmarks = other.listkeys('bookmarks')
5583 rmarks = other.listkeys('bookmarks')
5577 diff = set(rmarks) - set(lmarks)
5584 diff = set(rmarks) - set(lmarks)
5578 if len(diff) > 0:
5585 if len(diff) > 0:
5579 t.append(_('%d incoming bookmarks') % len(diff))
5586 t.append(_('%d incoming bookmarks') % len(diff))
5580 diff = set(lmarks) - set(rmarks)
5587 diff = set(lmarks) - set(rmarks)
5581 if len(diff) > 0:
5588 if len(diff) > 0:
5582 t.append(_('%d outgoing bookmarks') % len(diff))
5589 t.append(_('%d outgoing bookmarks') % len(diff))
5583
5590
5584 if t:
5591 if t:
5585 ui.write(_('remote: %s\n') % (', '.join(t)))
5592 ui.write(_('remote: %s\n') % (', '.join(t)))
5586 else:
5593 else:
5587 ui.status(_('remote: (synced)\n'))
5594 ui.status(_('remote: (synced)\n'))
5588
5595
5589 @command('tag',
5596 @command('tag',
5590 [('f', 'force', None, _('force tag')),
5597 [('f', 'force', None, _('force tag')),
5591 ('l', 'local', None, _('make the tag local')),
5598 ('l', 'local', None, _('make the tag local')),
5592 ('r', 'rev', '', _('revision to tag'), _('REV')),
5599 ('r', 'rev', '', _('revision to tag'), _('REV')),
5593 ('', 'remove', None, _('remove a tag')),
5600 ('', 'remove', None, _('remove a tag')),
5594 # -l/--local is already there, commitopts cannot be used
5601 # -l/--local is already there, commitopts cannot be used
5595 ('e', 'edit', None, _('edit commit message')),
5602 ('e', 'edit', None, _('edit commit message')),
5596 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5603 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5597 ] + commitopts2,
5604 ] + commitopts2,
5598 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5605 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5599 def tag(ui, repo, name1, *names, **opts):
5606 def tag(ui, repo, name1, *names, **opts):
5600 """add one or more tags for the current or given revision
5607 """add one or more tags for the current or given revision
5601
5608
5602 Name a particular revision using <name>.
5609 Name a particular revision using <name>.
5603
5610
5604 Tags are used to name particular revisions of the repository and are
5611 Tags are used to name particular revisions of the repository and are
5605 very useful to compare different revisions, to go back to significant
5612 very useful to compare different revisions, to go back to significant
5606 earlier versions or to mark branch points as releases, etc. Changing
5613 earlier versions or to mark branch points as releases, etc. Changing
5607 an existing tag is normally disallowed; use -f/--force to override.
5614 an existing tag is normally disallowed; use -f/--force to override.
5608
5615
5609 If no revision is given, the parent of the working directory is
5616 If no revision is given, the parent of the working directory is
5610 used, or tip if no revision is checked out.
5617 used, or tip if no revision is checked out.
5611
5618
5612 To facilitate version control, distribution, and merging of tags,
5619 To facilitate version control, distribution, and merging of tags,
5613 they are stored as a file named ".hgtags" which is managed similarly
5620 they are stored as a file named ".hgtags" which is managed similarly
5614 to other project files and can be hand-edited if necessary. This
5621 to other project files and can be hand-edited if necessary. This
5615 also means that tagging creates a new commit. The file
5622 also means that tagging creates a new commit. The file
5616 ".hg/localtags" is used for local tags (not shared among
5623 ".hg/localtags" is used for local tags (not shared among
5617 repositories).
5624 repositories).
5618
5625
5619 Tag commits are usually made at the head of a branch. If the parent
5626 Tag commits are usually made at the head of a branch. If the parent
5620 of the working directory is not a branch head, :hg:`tag` aborts; use
5627 of the working directory is not a branch head, :hg:`tag` aborts; use
5621 -f/--force to force the tag commit to be based on a non-head
5628 -f/--force to force the tag commit to be based on a non-head
5622 changeset.
5629 changeset.
5623
5630
5624 See :hg:`help dates` for a list of formats valid for -d/--date.
5631 See :hg:`help dates` for a list of formats valid for -d/--date.
5625
5632
5626 Since tag names have priority over branch names during revision
5633 Since tag names have priority over branch names during revision
5627 lookup, using an existing branch name as a tag name is discouraged.
5634 lookup, using an existing branch name as a tag name is discouraged.
5628
5635
5629 Returns 0 on success.
5636 Returns 0 on success.
5630 """
5637 """
5631 wlock = lock = None
5638 wlock = lock = None
5632 try:
5639 try:
5633 wlock = repo.wlock()
5640 wlock = repo.wlock()
5634 lock = repo.lock()
5641 lock = repo.lock()
5635 rev_ = "."
5642 rev_ = "."
5636 names = [t.strip() for t in (name1,) + names]
5643 names = [t.strip() for t in (name1,) + names]
5637 if len(names) != len(set(names)):
5644 if len(names) != len(set(names)):
5638 raise util.Abort(_('tag names must be unique'))
5645 raise util.Abort(_('tag names must be unique'))
5639 for n in names:
5646 for n in names:
5640 if n in ['tip', '.', 'null']:
5647 if n in ['tip', '.', 'null']:
5641 raise util.Abort(_("the name '%s' is reserved") % n)
5648 raise util.Abort(_("the name '%s' is reserved") % n)
5642 if not n:
5649 if not n:
5643 raise util.Abort(_('tag names cannot consist entirely of '
5650 raise util.Abort(_('tag names cannot consist entirely of '
5644 'whitespace'))
5651 'whitespace'))
5645 if opts.get('rev') and opts.get('remove'):
5652 if opts.get('rev') and opts.get('remove'):
5646 raise util.Abort(_("--rev and --remove are incompatible"))
5653 raise util.Abort(_("--rev and --remove are incompatible"))
5647 if opts.get('rev'):
5654 if opts.get('rev'):
5648 rev_ = opts['rev']
5655 rev_ = opts['rev']
5649 message = opts.get('message')
5656 message = opts.get('message')
5650 if opts.get('remove'):
5657 if opts.get('remove'):
5651 expectedtype = opts.get('local') and 'local' or 'global'
5658 expectedtype = opts.get('local') and 'local' or 'global'
5652 for n in names:
5659 for n in names:
5653 if not repo.tagtype(n):
5660 if not repo.tagtype(n):
5654 raise util.Abort(_("tag '%s' does not exist") % n)
5661 raise util.Abort(_("tag '%s' does not exist") % n)
5655 if repo.tagtype(n) != expectedtype:
5662 if repo.tagtype(n) != expectedtype:
5656 if expectedtype == 'global':
5663 if expectedtype == 'global':
5657 raise util.Abort(_("tag '%s' is not a global tag") % n)
5664 raise util.Abort(_("tag '%s' is not a global tag") % n)
5658 else:
5665 else:
5659 raise util.Abort(_("tag '%s' is not a local tag") % n)
5666 raise util.Abort(_("tag '%s' is not a local tag") % n)
5660 rev_ = nullid
5667 rev_ = nullid
5661 if not message:
5668 if not message:
5662 # we don't translate commit messages
5669 # we don't translate commit messages
5663 message = 'Removed tag %s' % ', '.join(names)
5670 message = 'Removed tag %s' % ', '.join(names)
5664 elif not opts.get('force'):
5671 elif not opts.get('force'):
5665 for n in names:
5672 for n in names:
5666 if n in repo.tags():
5673 if n in repo.tags():
5667 raise util.Abort(_("tag '%s' already exists "
5674 raise util.Abort(_("tag '%s' already exists "
5668 "(use -f to force)") % n)
5675 "(use -f to force)") % n)
5669 if not opts.get('local'):
5676 if not opts.get('local'):
5670 p1, p2 = repo.dirstate.parents()
5677 p1, p2 = repo.dirstate.parents()
5671 if p2 != nullid:
5678 if p2 != nullid:
5672 raise util.Abort(_('uncommitted merge'))
5679 raise util.Abort(_('uncommitted merge'))
5673 bheads = repo.branchheads()
5680 bheads = repo.branchheads()
5674 if not opts.get('force') and bheads and p1 not in bheads:
5681 if not opts.get('force') and bheads and p1 not in bheads:
5675 raise util.Abort(_('not at a branch head (use -f to force)'))
5682 raise util.Abort(_('not at a branch head (use -f to force)'))
5676 r = scmutil.revsingle(repo, rev_).node()
5683 r = scmutil.revsingle(repo, rev_).node()
5677
5684
5678 if not message:
5685 if not message:
5679 # we don't translate commit messages
5686 # we don't translate commit messages
5680 message = ('Added tag %s for changeset %s' %
5687 message = ('Added tag %s for changeset %s' %
5681 (', '.join(names), short(r)))
5688 (', '.join(names), short(r)))
5682
5689
5683 date = opts.get('date')
5690 date = opts.get('date')
5684 if date:
5691 if date:
5685 date = util.parsedate(date)
5692 date = util.parsedate(date)
5686
5693
5687 if opts.get('edit'):
5694 if opts.get('edit'):
5688 message = ui.edit(message, ui.username())
5695 message = ui.edit(message, ui.username())
5689
5696
5690 # don't allow tagging the null rev
5697 # don't allow tagging the null rev
5691 if (not opts.get('remove') and
5698 if (not opts.get('remove') and
5692 scmutil.revsingle(repo, rev_).rev() == nullrev):
5699 scmutil.revsingle(repo, rev_).rev() == nullrev):
5693 raise util.Abort(_("null revision specified"))
5700 raise util.Abort(_("null revision specified"))
5694
5701
5695 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5702 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5696 finally:
5703 finally:
5697 release(lock, wlock)
5704 release(lock, wlock)
5698
5705
5699 @command('tags', [], '')
5706 @command('tags', [], '')
5700 def tags(ui, repo):
5707 def tags(ui, repo):
5701 """list repository tags
5708 """list repository tags
5702
5709
5703 This lists both regular and local tags. When the -v/--verbose
5710 This lists both regular and local tags. When the -v/--verbose
5704 switch is used, a third column "local" is printed for local tags.
5711 switch is used, a third column "local" is printed for local tags.
5705
5712
5706 Returns 0 on success.
5713 Returns 0 on success.
5707 """
5714 """
5708
5715
5709 hexfunc = ui.debugflag and hex or short
5716 hexfunc = ui.debugflag and hex or short
5710 tagtype = ""
5717 tagtype = ""
5711
5718
5712 for t, n in reversed(repo.tagslist()):
5719 for t, n in reversed(repo.tagslist()):
5713 if ui.quiet:
5720 if ui.quiet:
5714 ui.write("%s\n" % t, label='tags.normal')
5721 ui.write("%s\n" % t, label='tags.normal')
5715 continue
5722 continue
5716
5723
5717 hn = hexfunc(n)
5724 hn = hexfunc(n)
5718 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5725 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5719 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5726 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5720 spaces = " " * (30 - encoding.colwidth(t))
5727 spaces = " " * (30 - encoding.colwidth(t))
5721
5728
5722 tag = ui.label(t, 'tags.normal')
5729 tag = ui.label(t, 'tags.normal')
5723 if ui.verbose:
5730 if ui.verbose:
5724 if repo.tagtype(t) == 'local':
5731 if repo.tagtype(t) == 'local':
5725 tagtype = " local"
5732 tagtype = " local"
5726 tag = ui.label(t, 'tags.local')
5733 tag = ui.label(t, 'tags.local')
5727 else:
5734 else:
5728 tagtype = ""
5735 tagtype = ""
5729 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5736 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5730
5737
5731 @command('tip',
5738 @command('tip',
5732 [('p', 'patch', None, _('show patch')),
5739 [('p', 'patch', None, _('show patch')),
5733 ('g', 'git', None, _('use git extended diff format')),
5740 ('g', 'git', None, _('use git extended diff format')),
5734 ] + templateopts,
5741 ] + templateopts,
5735 _('[-p] [-g]'))
5742 _('[-p] [-g]'))
5736 def tip(ui, repo, **opts):
5743 def tip(ui, repo, **opts):
5737 """show the tip revision
5744 """show the tip revision
5738
5745
5739 The tip revision (usually just called the tip) is the changeset
5746 The tip revision (usually just called the tip) is the changeset
5740 most recently added to the repository (and therefore the most
5747 most recently added to the repository (and therefore the most
5741 recently changed head).
5748 recently changed head).
5742
5749
5743 If you have just made a commit, that commit will be the tip. If
5750 If you have just made a commit, that commit will be the tip. If
5744 you have just pulled changes from another repository, the tip of
5751 you have just pulled changes from another repository, the tip of
5745 that repository becomes the current tip. The "tip" tag is special
5752 that repository becomes the current tip. The "tip" tag is special
5746 and cannot be renamed or assigned to a different changeset.
5753 and cannot be renamed or assigned to a different changeset.
5747
5754
5748 Returns 0 on success.
5755 Returns 0 on success.
5749 """
5756 """
5750 displayer = cmdutil.show_changeset(ui, repo, opts)
5757 displayer = cmdutil.show_changeset(ui, repo, opts)
5751 displayer.show(repo[len(repo) - 1])
5758 displayer.show(repo[len(repo) - 1])
5752 displayer.close()
5759 displayer.close()
5753
5760
5754 @command('unbundle',
5761 @command('unbundle',
5755 [('u', 'update', None,
5762 [('u', 'update', None,
5756 _('update to new branch head if changesets were unbundled'))],
5763 _('update to new branch head if changesets were unbundled'))],
5757 _('[-u] FILE...'))
5764 _('[-u] FILE...'))
5758 def unbundle(ui, repo, fname1, *fnames, **opts):
5765 def unbundle(ui, repo, fname1, *fnames, **opts):
5759 """apply one or more changegroup files
5766 """apply one or more changegroup files
5760
5767
5761 Apply one or more compressed changegroup files generated by the
5768 Apply one or more compressed changegroup files generated by the
5762 bundle command.
5769 bundle command.
5763
5770
5764 Returns 0 on success, 1 if an update has unresolved files.
5771 Returns 0 on success, 1 if an update has unresolved files.
5765 """
5772 """
5766 fnames = (fname1,) + fnames
5773 fnames = (fname1,) + fnames
5767
5774
5768 lock = repo.lock()
5775 lock = repo.lock()
5769 wc = repo['.']
5776 wc = repo['.']
5770 try:
5777 try:
5771 for fname in fnames:
5778 for fname in fnames:
5772 f = url.open(ui, fname)
5779 f = url.open(ui, fname)
5773 gen = changegroup.readbundle(f, fname)
5780 gen = changegroup.readbundle(f, fname)
5774 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5781 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5775 finally:
5782 finally:
5776 lock.release()
5783 lock.release()
5777 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5784 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5778 return postincoming(ui, repo, modheads, opts.get('update'), None)
5785 return postincoming(ui, repo, modheads, opts.get('update'), None)
5779
5786
5780 @command('^update|up|checkout|co',
5787 @command('^update|up|checkout|co',
5781 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5788 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5782 ('c', 'check', None,
5789 ('c', 'check', None,
5783 _('update across branches if no uncommitted changes')),
5790 _('update across branches if no uncommitted changes')),
5784 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5791 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5785 ('r', 'rev', '', _('revision'), _('REV'))],
5792 ('r', 'rev', '', _('revision'), _('REV'))],
5786 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5793 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5787 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5794 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5788 """update working directory (or switch revisions)
5795 """update working directory (or switch revisions)
5789
5796
5790 Update the repository's working directory to the specified
5797 Update the repository's working directory to the specified
5791 changeset. If no changeset is specified, update to the tip of the
5798 changeset. If no changeset is specified, update to the tip of the
5792 current named branch and move the current bookmark (see :hg:`help
5799 current named branch and move the current bookmark (see :hg:`help
5793 bookmarks`).
5800 bookmarks`).
5794
5801
5795 Update sets the working directory's parent revision to the specified
5802 Update sets the working directory's parent revision to the specified
5796 changeset (see :hg:`help parents`).
5803 changeset (see :hg:`help parents`).
5797
5804
5798 If the changeset is not a descendant or ancestor of the working
5805 If the changeset is not a descendant or ancestor of the working
5799 directory's parent, the update is aborted. With the -c/--check
5806 directory's parent, the update is aborted. With the -c/--check
5800 option, the working directory is checked for uncommitted changes; if
5807 option, the working directory is checked for uncommitted changes; if
5801 none are found, the working directory is updated to the specified
5808 none are found, the working directory is updated to the specified
5802 changeset.
5809 changeset.
5803
5810
5804 .. container:: verbose
5811 .. container:: verbose
5805
5812
5806 The following rules apply when the working directory contains
5813 The following rules apply when the working directory contains
5807 uncommitted changes:
5814 uncommitted changes:
5808
5815
5809 1. If neither -c/--check nor -C/--clean is specified, and if
5816 1. If neither -c/--check nor -C/--clean is specified, and if
5810 the requested changeset is an ancestor or descendant of
5817 the requested changeset is an ancestor or descendant of
5811 the working directory's parent, the uncommitted changes
5818 the working directory's parent, the uncommitted changes
5812 are merged into the requested changeset and the merged
5819 are merged into the requested changeset and the merged
5813 result is left uncommitted. If the requested changeset is
5820 result is left uncommitted. If the requested changeset is
5814 not an ancestor or descendant (that is, it is on another
5821 not an ancestor or descendant (that is, it is on another
5815 branch), the update is aborted and the uncommitted changes
5822 branch), the update is aborted and the uncommitted changes
5816 are preserved.
5823 are preserved.
5817
5824
5818 2. With the -c/--check option, the update is aborted and the
5825 2. With the -c/--check option, the update is aborted and the
5819 uncommitted changes are preserved.
5826 uncommitted changes are preserved.
5820
5827
5821 3. With the -C/--clean option, uncommitted changes are discarded and
5828 3. With the -C/--clean option, uncommitted changes are discarded and
5822 the working directory is updated to the requested changeset.
5829 the working directory is updated to the requested changeset.
5823
5830
5824 To cancel an uncommitted merge (and lose your changes), use
5831 To cancel an uncommitted merge (and lose your changes), use
5825 :hg:`update --clean .`.
5832 :hg:`update --clean .`.
5826
5833
5827 Use null as the changeset to remove the working directory (like
5834 Use null as the changeset to remove the working directory (like
5828 :hg:`clone -U`).
5835 :hg:`clone -U`).
5829
5836
5830 If you want to revert just one file to an older revision, use
5837 If you want to revert just one file to an older revision, use
5831 :hg:`revert [-r REV] NAME`.
5838 :hg:`revert [-r REV] NAME`.
5832
5839
5833 See :hg:`help dates` for a list of formats valid for -d/--date.
5840 See :hg:`help dates` for a list of formats valid for -d/--date.
5834
5841
5835 Returns 0 on success, 1 if there are unresolved files.
5842 Returns 0 on success, 1 if there are unresolved files.
5836 """
5843 """
5837 if rev and node:
5844 if rev and node:
5838 raise util.Abort(_("please specify just one revision"))
5845 raise util.Abort(_("please specify just one revision"))
5839
5846
5840 if rev is None or rev == '':
5847 if rev is None or rev == '':
5841 rev = node
5848 rev = node
5842
5849
5843 # with no argument, we also move the current bookmark, if any
5850 # with no argument, we also move the current bookmark, if any
5844 movemarkfrom = None
5851 movemarkfrom = None
5845 if rev is None or node == '':
5852 if rev is None or node == '':
5846 movemarkfrom = repo['.'].node()
5853 movemarkfrom = repo['.'].node()
5847
5854
5848 # if we defined a bookmark, we have to remember the original bookmark name
5855 # if we defined a bookmark, we have to remember the original bookmark name
5849 brev = rev
5856 brev = rev
5850 rev = scmutil.revsingle(repo, rev, rev).rev()
5857 rev = scmutil.revsingle(repo, rev, rev).rev()
5851
5858
5852 if check and clean:
5859 if check and clean:
5853 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5860 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5854
5861
5855 if date:
5862 if date:
5856 if rev is not None:
5863 if rev is not None:
5857 raise util.Abort(_("you can't specify a revision and a date"))
5864 raise util.Abort(_("you can't specify a revision and a date"))
5858 rev = cmdutil.finddate(ui, repo, date)
5865 rev = cmdutil.finddate(ui, repo, date)
5859
5866
5860 if check:
5867 if check:
5861 c = repo[None]
5868 c = repo[None]
5862 if c.dirty(merge=False, branch=False):
5869 if c.dirty(merge=False, branch=False):
5863 raise util.Abort(_("uncommitted local changes"))
5870 raise util.Abort(_("uncommitted local changes"))
5864 if rev is None:
5871 if rev is None:
5865 rev = repo[repo[None].branch()].rev()
5872 rev = repo[repo[None].branch()].rev()
5866 mergemod._checkunknown(repo, repo[None], repo[rev])
5873 mergemod._checkunknown(repo, repo[None], repo[rev])
5867
5874
5868 if clean:
5875 if clean:
5869 ret = hg.clean(repo, rev)
5876 ret = hg.clean(repo, rev)
5870 else:
5877 else:
5871 ret = hg.update(repo, rev)
5878 ret = hg.update(repo, rev)
5872
5879
5873 if not ret and movemarkfrom:
5880 if not ret and movemarkfrom:
5874 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5881 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5875 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5882 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5876 elif brev in repo._bookmarks:
5883 elif brev in repo._bookmarks:
5877 bookmarks.setcurrent(repo, brev)
5884 bookmarks.setcurrent(repo, brev)
5878 elif brev:
5885 elif brev:
5879 bookmarks.unsetcurrent(repo)
5886 bookmarks.unsetcurrent(repo)
5880
5887
5881 return ret
5888 return ret
5882
5889
5883 @command('verify', [])
5890 @command('verify', [])
5884 def verify(ui, repo):
5891 def verify(ui, repo):
5885 """verify the integrity of the repository
5892 """verify the integrity of the repository
5886
5893
5887 Verify the integrity of the current repository.
5894 Verify the integrity of the current repository.
5888
5895
5889 This will perform an extensive check of the repository's
5896 This will perform an extensive check of the repository's
5890 integrity, validating the hashes and checksums of each entry in
5897 integrity, validating the hashes and checksums of each entry in
5891 the changelog, manifest, and tracked files, as well as the
5898 the changelog, manifest, and tracked files, as well as the
5892 integrity of their crosslinks and indices.
5899 integrity of their crosslinks and indices.
5893
5900
5894 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5901 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5895 for more information about recovery from corruption of the
5902 for more information about recovery from corruption of the
5896 repository.
5903 repository.
5897
5904
5898 Returns 0 on success, 1 if errors are encountered.
5905 Returns 0 on success, 1 if errors are encountered.
5899 """
5906 """
5900 return hg.verify(repo)
5907 return hg.verify(repo)
5901
5908
5902 @command('version', [])
5909 @command('version', [])
5903 def version_(ui):
5910 def version_(ui):
5904 """output version and copyright information"""
5911 """output version and copyright information"""
5905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5912 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5906 % util.version())
5913 % util.version())
5907 ui.status(_(
5914 ui.status(_(
5908 "(see http://mercurial.selenic.com for more information)\n"
5915 "(see http://mercurial.selenic.com for more information)\n"
5909 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5916 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5910 "This is free software; see the source for copying conditions. "
5917 "This is free software; see the source for copying conditions. "
5911 "There is NO\nwarranty; "
5918 "There is NO\nwarranty; "
5912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5919 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5913 ))
5920 ))
5914
5921
5915 norepo = ("clone init version help debugcommands debugcomplete"
5922 norepo = ("clone init version help debugcommands debugcomplete"
5916 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5923 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5917 " debugknown debuggetbundle debugbundle")
5924 " debugknown debuggetbundle debugbundle")
5918 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5925 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5919 " debugdata debugindex debugindexdot debugrevlog")
5926 " debugdata debugindex debugindexdot debugrevlog")
5920 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5927 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5921 " remove resolve status debugwalk")
5928 " remove resolve status debugwalk")
@@ -1,506 +1,520
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0
43 second bookmark for rev 0
44
44
45 $ hg bookmark X2
45 $ hg bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg log -r 'bookmark("re:X")'
87 $ hg log -r 'bookmark("re:X")'
88 changeset: 0:f7b1eb17ad24
88 changeset: 0:f7b1eb17ad24
89 bookmark: X
89 bookmark: X
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: 0
92 summary: 0
93
93
94 changeset: 1:925d80f479bb
94 changeset: 1:925d80f479bb
95 bookmark: X2
95 bookmark: X2
96 tag: tip
96 tag: tip
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: 1
99 summary: 1
100
100
101 $ hg log -r 'bookmark(unknown)'
101 $ hg log -r 'bookmark(unknown)'
102 abort: bookmark 'unknown' does not exist
102 abort: bookmark 'unknown' does not exist
103 [255]
103 [255]
104
104
105 $ hg help revsets | grep 'bookmark('
105 $ hg help revsets | grep 'bookmark('
106 "bookmark([name])"
106 "bookmark([name])"
107
107
108 bookmarks X and X2 moved to rev 1, Y at rev -1
108 bookmarks X and X2 moved to rev 1, Y at rev -1
109
109
110 $ hg bookmarks
110 $ hg bookmarks
111 X 0:f7b1eb17ad24
111 X 0:f7b1eb17ad24
112 * X2 1:925d80f479bb
112 * X2 1:925d80f479bb
113 Y -1:000000000000
113 Y -1:000000000000
114
114
115 bookmark rev 0 again
115 bookmark rev 0 again
116
116
117 $ hg bookmark -r 0 Z
117 $ hg bookmark -r 0 Z
118
118
119 $ hg update X
119 $ hg update X
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 $ echo c > c
121 $ echo c > c
122 $ hg add c
122 $ hg add c
123 $ hg commit -m 2
123 $ hg commit -m 2
124 created new head
124 created new head
125
125
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
127
127
128 $ hg bookmarks
128 $ hg bookmarks
129 * X 2:db815d6d32e6
129 * X 2:db815d6d32e6
130 X2 1:925d80f479bb
130 X2 1:925d80f479bb
131 Y -1:000000000000
131 Y -1:000000000000
132 Z 0:f7b1eb17ad24
132 Z 0:f7b1eb17ad24
133
133
134 rename nonexistent bookmark
134 rename nonexistent bookmark
135
135
136 $ hg bookmark -m A B
136 $ hg bookmark -m A B
137 abort: bookmark 'A' does not exist
137 abort: bookmark 'A' does not exist
138 [255]
138 [255]
139
139
140 rename to existent bookmark
140 rename to existent bookmark
141
141
142 $ hg bookmark -m X Y
142 $ hg bookmark -m X Y
143 abort: bookmark 'Y' already exists (use -f to force)
143 abort: bookmark 'Y' already exists (use -f to force)
144 [255]
144 [255]
145
145
146 force rename to existent bookmark
146 force rename to existent bookmark
147
147
148 $ hg bookmark -f -m X Y
148 $ hg bookmark -f -m X Y
149
149
150 list bookmarks
150 list bookmarks
151
151
152 $ hg bookmark
152 $ hg bookmark
153 X2 1:925d80f479bb
153 X2 1:925d80f479bb
154 * Y 2:db815d6d32e6
154 * Y 2:db815d6d32e6
155 Z 0:f7b1eb17ad24
155 Z 0:f7b1eb17ad24
156
156
157 bookmarks from a revset
157 bookmarks from a revset
158 $ hg bookmark -r '.^1' REVSET
158 $ hg bookmark -r '.^1' REVSET
159 $ hg bookmark -r ':tip' TIP
159 $ hg bookmark -r ':tip' TIP
160 $ hg bookmarks
160 $ hg bookmarks
161 REVSET 0:f7b1eb17ad24
161 REVSET 0:f7b1eb17ad24
162 * TIP 2:db815d6d32e6
162 * TIP 2:db815d6d32e6
163 X2 1:925d80f479bb
163 X2 1:925d80f479bb
164 Y 2:db815d6d32e6
164 Y 2:db815d6d32e6
165 Z 0:f7b1eb17ad24
165 Z 0:f7b1eb17ad24
166
166
167 $ hg bookmark -d REVSET
167 $ hg bookmark -d REVSET
168 $ hg bookmark -d TIP
168 $ hg bookmark -d TIP
169
169
170 rename without new name
170 rename without new name
171
171
172 $ hg bookmark -m Y
172 $ hg bookmark -m Y
173 abort: new bookmark name required
173 abort: new bookmark name required
174 [255]
174 [255]
175
175
176 delete without name
176 delete without name
177
177
178 $ hg bookmark -d
178 $ hg bookmark -d
179 abort: bookmark name required
179 abort: bookmark name required
180 [255]
180 [255]
181
181
182 delete nonexistent bookmark
182 delete nonexistent bookmark
183
183
184 $ hg bookmark -d A
184 $ hg bookmark -d A
185 abort: bookmark 'A' does not exist
185 abort: bookmark 'A' does not exist
186 [255]
186 [255]
187
187
188 bookmark name with spaces should be stripped
188 bookmark name with spaces should be stripped
189
189
190 $ hg bookmark ' x y '
190 $ hg bookmark ' x y '
191
191
192 list bookmarks
192 list bookmarks
193
193
194 $ hg bookmarks
194 $ hg bookmarks
195 X2 1:925d80f479bb
195 X2 1:925d80f479bb
196 Y 2:db815d6d32e6
196 Y 2:db815d6d32e6
197 Z 0:f7b1eb17ad24
197 Z 0:f7b1eb17ad24
198 * x y 2:db815d6d32e6
198 * x y 2:db815d6d32e6
199
199
200 look up stripped bookmark name
200 look up stripped bookmark name
201
201
202 $ hg log -r '"x y"'
202 $ hg log -r '"x y"'
203 changeset: 2:db815d6d32e6
203 changeset: 2:db815d6d32e6
204 bookmark: Y
204 bookmark: Y
205 bookmark: x y
205 bookmark: x y
206 tag: tip
206 tag: tip
207 parent: 0:f7b1eb17ad24
207 parent: 0:f7b1eb17ad24
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: 2
210 summary: 2
211
211
212
212
213 reject bookmark name with newline
213 reject bookmark name with newline
214
214
215 $ hg bookmark '
215 $ hg bookmark '
216 > '
216 > '
217 abort: bookmark name cannot contain newlines
217 abort: bookmark name cannot contain newlines
218 [255]
218 [255]
219
219
220 $ hg bookmark -m Z '
220 $ hg bookmark -m Z '
221 > '
221 > '
222 abort: bookmark name cannot contain newlines
222 abort: bookmark name cannot contain newlines
223 [255]
223 [255]
224
224
225 bookmark with existing name
225 bookmark with existing name
226
226
227 $ hg bookmark Z
227 $ hg bookmark Z
228 abort: bookmark 'Z' already exists (use -f to force)
228 abort: bookmark 'Z' already exists (use -f to force)
229 [255]
229 [255]
230
230
231 $ hg bookmark -m Y Z
231 $ hg bookmark -m Y Z
232 abort: bookmark 'Z' already exists (use -f to force)
232 abort: bookmark 'Z' already exists (use -f to force)
233 [255]
233 [255]
234
234
235 bookmark with name of branch
235 bookmark with name of branch
236
236
237 $ hg bookmark default
237 $ hg bookmark default
238 abort: a bookmark cannot have the name of an existing branch
238 abort: a bookmark cannot have the name of an existing branch
239 [255]
239 [255]
240
240
241 $ hg bookmark -m Y default
241 $ hg bookmark -m Y default
242 abort: a bookmark cannot have the name of an existing branch
242 abort: a bookmark cannot have the name of an existing branch
243 [255]
243 [255]
244
244
245 incompatible options
246
247 $ hg bookmark -m Y -d Z
248 abort: --delete and --rename are incompatible
249 [255]
250
251 $ hg bookmark -r 1 -d Z
252 abort: --rev is incompatible with --delete
253 [255]
254
255 $ hg bookmark -r 1 -m Z Y
256 abort: --rev is incompatible with --rename
257 [255]
258
245 force bookmark with existing name
259 force bookmark with existing name
246
260
247 $ hg bookmark -f Z
261 $ hg bookmark -f Z
248
262
249 list bookmarks
263 list bookmarks
250
264
251 $ hg bookmark
265 $ hg bookmark
252 X2 1:925d80f479bb
266 X2 1:925d80f479bb
253 Y 2:db815d6d32e6
267 Y 2:db815d6d32e6
254 * Z 2:db815d6d32e6
268 * Z 2:db815d6d32e6
255 x y 2:db815d6d32e6
269 x y 2:db815d6d32e6
256
270
257 revision but no bookmark name
271 revision but no bookmark name
258
272
259 $ hg bookmark -r .
273 $ hg bookmark -r .
260 abort: bookmark name required
274 abort: bookmark name required
261 [255]
275 [255]
262
276
263 bookmark name with whitespace only
277 bookmark name with whitespace only
264
278
265 $ hg bookmark ' '
279 $ hg bookmark ' '
266 abort: bookmark names cannot consist entirely of whitespace
280 abort: bookmark names cannot consist entirely of whitespace
267 [255]
281 [255]
268
282
269 $ hg bookmark -m Y ' '
283 $ hg bookmark -m Y ' '
270 abort: bookmark names cannot consist entirely of whitespace
284 abort: bookmark names cannot consist entirely of whitespace
271 [255]
285 [255]
272
286
273 invalid bookmark
287 invalid bookmark
274
288
275 $ hg bookmark 'foo:bar'
289 $ hg bookmark 'foo:bar'
276 abort: bookmark 'foo:bar' contains illegal character
290 abort: bookmark 'foo:bar' contains illegal character
277 [255]
291 [255]
278
292
279 the bookmark extension should be ignored now that it is part of core
293 the bookmark extension should be ignored now that it is part of core
280
294
281 $ echo "[extensions]" >> $HGRCPATH
295 $ echo "[extensions]" >> $HGRCPATH
282 $ echo "bookmarks=" >> $HGRCPATH
296 $ echo "bookmarks=" >> $HGRCPATH
283 $ hg bookmarks
297 $ hg bookmarks
284 X2 1:925d80f479bb
298 X2 1:925d80f479bb
285 Y 2:db815d6d32e6
299 Y 2:db815d6d32e6
286 * Z 2:db815d6d32e6
300 * Z 2:db815d6d32e6
287 x y 2:db815d6d32e6
301 x y 2:db815d6d32e6
288
302
289 test summary
303 test summary
290
304
291 $ hg summary
305 $ hg summary
292 parent: 2:db815d6d32e6 tip
306 parent: 2:db815d6d32e6 tip
293 2
307 2
294 branch: default
308 branch: default
295 bookmarks: *Z Y x y
309 bookmarks: *Z Y x y
296 commit: (clean)
310 commit: (clean)
297 update: 1 new changesets, 2 branch heads (merge)
311 update: 1 new changesets, 2 branch heads (merge)
298
312
299 test id
313 test id
300
314
301 $ hg id
315 $ hg id
302 db815d6d32e6 tip Y/Z/x y
316 db815d6d32e6 tip Y/Z/x y
303
317
304 test rollback
318 test rollback
305
319
306 $ echo foo > f1
320 $ echo foo > f1
307 $ hg ci -Amr
321 $ hg ci -Amr
308 adding f1
322 adding f1
309 $ hg bookmark -f Y -r 1
323 $ hg bookmark -f Y -r 1
310 $ hg bookmark -f Z -r 1
324 $ hg bookmark -f Z -r 1
311 $ hg rollback
325 $ hg rollback
312 repository tip rolled back to revision 2 (undo commit)
326 repository tip rolled back to revision 2 (undo commit)
313 working directory now based on revision 2
327 working directory now based on revision 2
314 $ hg bookmarks
328 $ hg bookmarks
315 X2 1:925d80f479bb
329 X2 1:925d80f479bb
316 Y 2:db815d6d32e6
330 Y 2:db815d6d32e6
317 * Z 2:db815d6d32e6
331 * Z 2:db815d6d32e6
318 x y 2:db815d6d32e6
332 x y 2:db815d6d32e6
319
333
320 test clone
334 test clone
321
335
322 $ hg bookmark -r 2 -i @
336 $ hg bookmark -r 2 -i @
323 $ hg bookmark -r 2 -i a@
337 $ hg bookmark -r 2 -i a@
324 $ hg bookmarks
338 $ hg bookmarks
325 @ 2:db815d6d32e6
339 @ 2:db815d6d32e6
326 X2 1:925d80f479bb
340 X2 1:925d80f479bb
327 Y 2:db815d6d32e6
341 Y 2:db815d6d32e6
328 * Z 2:db815d6d32e6
342 * Z 2:db815d6d32e6
329 a@ 2:db815d6d32e6
343 a@ 2:db815d6d32e6
330 x y 2:db815d6d32e6
344 x y 2:db815d6d32e6
331 $ hg clone . cloned-bookmarks
345 $ hg clone . cloned-bookmarks
332 updating to branch default
346 updating to branch default
333 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 $ hg -R cloned-bookmarks bookmarks
348 $ hg -R cloned-bookmarks bookmarks
335 @ 2:db815d6d32e6
349 @ 2:db815d6d32e6
336 X2 1:925d80f479bb
350 X2 1:925d80f479bb
337 Y 2:db815d6d32e6
351 Y 2:db815d6d32e6
338 Z 2:db815d6d32e6
352 Z 2:db815d6d32e6
339 a@ 2:db815d6d32e6
353 a@ 2:db815d6d32e6
340 x y 2:db815d6d32e6
354 x y 2:db815d6d32e6
341
355
342 test clone with pull protocol
356 test clone with pull protocol
343
357
344 $ hg clone --pull . cloned-bookmarks-pull
358 $ hg clone --pull . cloned-bookmarks-pull
345 requesting all changes
359 requesting all changes
346 adding changesets
360 adding changesets
347 adding manifests
361 adding manifests
348 adding file changes
362 adding file changes
349 added 3 changesets with 3 changes to 3 files (+1 heads)
363 added 3 changesets with 3 changes to 3 files (+1 heads)
350 updating to branch default
364 updating to branch default
351 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
365 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 $ hg -R cloned-bookmarks-pull bookmarks
366 $ hg -R cloned-bookmarks-pull bookmarks
353 @ 2:db815d6d32e6
367 @ 2:db815d6d32e6
354 X2 1:925d80f479bb
368 X2 1:925d80f479bb
355 Y 2:db815d6d32e6
369 Y 2:db815d6d32e6
356 Z 2:db815d6d32e6
370 Z 2:db815d6d32e6
357 a@ 2:db815d6d32e6
371 a@ 2:db815d6d32e6
358 x y 2:db815d6d32e6
372 x y 2:db815d6d32e6
359
373
360 $ hg bookmark -d @
374 $ hg bookmark -d @
361 $ hg bookmark -d a@
375 $ hg bookmark -d a@
362
376
363 test clone with a specific revision
377 test clone with a specific revision
364
378
365 $ hg clone -r 925d80 . cloned-bookmarks-rev
379 $ hg clone -r 925d80 . cloned-bookmarks-rev
366 adding changesets
380 adding changesets
367 adding manifests
381 adding manifests
368 adding file changes
382 adding file changes
369 added 2 changesets with 2 changes to 2 files
383 added 2 changesets with 2 changes to 2 files
370 updating to branch default
384 updating to branch default
371 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
372 $ hg -R cloned-bookmarks-rev bookmarks
386 $ hg -R cloned-bookmarks-rev bookmarks
373 X2 1:925d80f479bb
387 X2 1:925d80f479bb
374
388
375 test clone with update to a bookmark
389 test clone with update to a bookmark
376
390
377 $ hg clone -u Z . cloned-bookmarks-update
391 $ hg clone -u Z . cloned-bookmarks-update
378 updating to branch default
392 updating to branch default
379 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
380 $ hg -R cloned-bookmarks-update bookmarks
394 $ hg -R cloned-bookmarks-update bookmarks
381 X2 1:925d80f479bb
395 X2 1:925d80f479bb
382 Y 2:db815d6d32e6
396 Y 2:db815d6d32e6
383 * Z 2:db815d6d32e6
397 * Z 2:db815d6d32e6
384 x y 2:db815d6d32e6
398 x y 2:db815d6d32e6
385
399
386 create bundle with two heads
400 create bundle with two heads
387
401
388 $ hg clone . tobundle
402 $ hg clone . tobundle
389 updating to branch default
403 updating to branch default
390 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 $ echo x > tobundle/x
405 $ echo x > tobundle/x
392 $ hg -R tobundle add tobundle/x
406 $ hg -R tobundle add tobundle/x
393 $ hg -R tobundle commit -m'x'
407 $ hg -R tobundle commit -m'x'
394 $ hg -R tobundle update -r -2
408 $ hg -R tobundle update -r -2
395 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
396 $ echo y > tobundle/y
410 $ echo y > tobundle/y
397 $ hg -R tobundle branch test
411 $ hg -R tobundle branch test
398 marked working directory as branch test
412 marked working directory as branch test
399 (branches are permanent and global, did you want a bookmark?)
413 (branches are permanent and global, did you want a bookmark?)
400 $ hg -R tobundle add tobundle/y
414 $ hg -R tobundle add tobundle/y
401 $ hg -R tobundle commit -m'y'
415 $ hg -R tobundle commit -m'y'
402 $ hg -R tobundle bundle tobundle.hg
416 $ hg -R tobundle bundle tobundle.hg
403 searching for changes
417 searching for changes
404 2 changesets found
418 2 changesets found
405 $ hg unbundle tobundle.hg
419 $ hg unbundle tobundle.hg
406 adding changesets
420 adding changesets
407 adding manifests
421 adding manifests
408 adding file changes
422 adding file changes
409 added 2 changesets with 2 changes to 2 files (+1 heads)
423 added 2 changesets with 2 changes to 2 files (+1 heads)
410 (run 'hg heads' to see heads, 'hg merge' to merge)
424 (run 'hg heads' to see heads, 'hg merge' to merge)
411 $ hg update
425 $ hg update
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
413 $ hg bookmarks
427 $ hg bookmarks
414 X2 1:925d80f479bb
428 X2 1:925d80f479bb
415 Y 2:db815d6d32e6
429 Y 2:db815d6d32e6
416 * Z 3:125c9a1d6df6
430 * Z 3:125c9a1d6df6
417 x y 2:db815d6d32e6
431 x y 2:db815d6d32e6
418
432
419 test wrongly formated bookmark
433 test wrongly formated bookmark
420
434
421 $ echo '' >> .hg/bookmarks
435 $ echo '' >> .hg/bookmarks
422 $ hg bookmarks
436 $ hg bookmarks
423 X2 1:925d80f479bb
437 X2 1:925d80f479bb
424 Y 2:db815d6d32e6
438 Y 2:db815d6d32e6
425 * Z 3:125c9a1d6df6
439 * Z 3:125c9a1d6df6
426 x y 2:db815d6d32e6
440 x y 2:db815d6d32e6
427 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
441 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
428 $ hg bookmarks
442 $ hg bookmarks
429 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
443 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
430 X2 1:925d80f479bb
444 X2 1:925d80f479bb
431 Y 2:db815d6d32e6
445 Y 2:db815d6d32e6
432 * Z 3:125c9a1d6df6
446 * Z 3:125c9a1d6df6
433 x y 2:db815d6d32e6
447 x y 2:db815d6d32e6
434
448
435 test missing revisions
449 test missing revisions
436
450
437 $ echo "925d80f479bc z" > .hg/bookmarks
451 $ echo "925d80f479bc z" > .hg/bookmarks
438 $ hg book
452 $ hg book
439 no bookmarks set
453 no bookmarks set
440
454
441 test stripping a non-checked-out but bookmarked revision
455 test stripping a non-checked-out but bookmarked revision
442
456
443 $ hg --config extensions.graphlog= log --graph
457 $ hg --config extensions.graphlog= log --graph
444 o changeset: 4:9ba5f110a0b3
458 o changeset: 4:9ba5f110a0b3
445 | branch: test
459 | branch: test
446 | tag: tip
460 | tag: tip
447 | parent: 2:db815d6d32e6
461 | parent: 2:db815d6d32e6
448 | user: test
462 | user: test
449 | date: Thu Jan 01 00:00:00 1970 +0000
463 | date: Thu Jan 01 00:00:00 1970 +0000
450 | summary: y
464 | summary: y
451 |
465 |
452 | @ changeset: 3:125c9a1d6df6
466 | @ changeset: 3:125c9a1d6df6
453 |/ user: test
467 |/ user: test
454 | date: Thu Jan 01 00:00:00 1970 +0000
468 | date: Thu Jan 01 00:00:00 1970 +0000
455 | summary: x
469 | summary: x
456 |
470 |
457 o changeset: 2:db815d6d32e6
471 o changeset: 2:db815d6d32e6
458 | parent: 0:f7b1eb17ad24
472 | parent: 0:f7b1eb17ad24
459 | user: test
473 | user: test
460 | date: Thu Jan 01 00:00:00 1970 +0000
474 | date: Thu Jan 01 00:00:00 1970 +0000
461 | summary: 2
475 | summary: 2
462 |
476 |
463 | o changeset: 1:925d80f479bb
477 | o changeset: 1:925d80f479bb
464 |/ user: test
478 |/ user: test
465 | date: Thu Jan 01 00:00:00 1970 +0000
479 | date: Thu Jan 01 00:00:00 1970 +0000
466 | summary: 1
480 | summary: 1
467 |
481 |
468 o changeset: 0:f7b1eb17ad24
482 o changeset: 0:f7b1eb17ad24
469 user: test
483 user: test
470 date: Thu Jan 01 00:00:00 1970 +0000
484 date: Thu Jan 01 00:00:00 1970 +0000
471 summary: 0
485 summary: 0
472
486
473 $ hg book should-end-on-two
487 $ hg book should-end-on-two
474 $ hg co --clean 4
488 $ hg co --clean 4
475 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
489 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
476 $ hg book four
490 $ hg book four
477 $ hg --config extensions.mq= strip 3
491 $ hg --config extensions.mq= strip 3
478 saved backup bundle to * (glob)
492 saved backup bundle to * (glob)
479 should-end-on-two should end up pointing to revision 2, as that's the
493 should-end-on-two should end up pointing to revision 2, as that's the
480 tipmost surviving ancestor of the stripped revision.
494 tipmost surviving ancestor of the stripped revision.
481 $ hg --config extensions.graphlog= log --graph
495 $ hg --config extensions.graphlog= log --graph
482 @ changeset: 3:9ba5f110a0b3
496 @ changeset: 3:9ba5f110a0b3
483 | branch: test
497 | branch: test
484 | bookmark: four
498 | bookmark: four
485 | tag: tip
499 | tag: tip
486 | user: test
500 | user: test
487 | date: Thu Jan 01 00:00:00 1970 +0000
501 | date: Thu Jan 01 00:00:00 1970 +0000
488 | summary: y
502 | summary: y
489 |
503 |
490 o changeset: 2:db815d6d32e6
504 o changeset: 2:db815d6d32e6
491 | bookmark: should-end-on-two
505 | bookmark: should-end-on-two
492 | parent: 0:f7b1eb17ad24
506 | parent: 0:f7b1eb17ad24
493 | user: test
507 | user: test
494 | date: Thu Jan 01 00:00:00 1970 +0000
508 | date: Thu Jan 01 00:00:00 1970 +0000
495 | summary: 2
509 | summary: 2
496 |
510 |
497 | o changeset: 1:925d80f479bb
511 | o changeset: 1:925d80f479bb
498 |/ user: test
512 |/ user: test
499 | date: Thu Jan 01 00:00:00 1970 +0000
513 | date: Thu Jan 01 00:00:00 1970 +0000
500 | summary: 1
514 | summary: 1
501 |
515 |
502 o changeset: 0:f7b1eb17ad24
516 o changeset: 0:f7b1eb17ad24
503 user: test
517 user: test
504 date: Thu Jan 01 00:00:00 1970 +0000
518 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: 0
519 summary: 0
506
520
General Comments 0
You need to be logged in to leave comments. Login now