##// END OF EJS Templates
bookmarks: check bookmark format during rename (issue3662)
David Soria Parra -
r17789:4cfd02c2 default
parent child Browse files
Show More
@@ -1,5915 +1,5921 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, 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):
793 if "\n" in mark:
794 raise util.Abort(_("bookmark name cannot contain newlines"))
795 mark = mark.strip()
796 if not mark:
797 raise util.Abort(_("bookmark names cannot consist entirely of "
798 "whitespace"))
799 return mark
800
801 def checkconflict(repo, mark, force=False):
802 if mark in marks and not force:
803 raise util.Abort(_("bookmark '%s' already exists "
804 "(use -f to force)") % mark)
805 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
806 and not force):
807 raise util.Abort(
808 _("a bookmark cannot have the name of an existing branch"))
809
792 if delete:
810 if delete:
793 if mark is None:
811 if mark is None:
794 raise util.Abort(_("bookmark name required"))
812 raise util.Abort(_("bookmark name required"))
795 if mark not in marks:
813 if mark not in marks:
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
814 raise util.Abort(_("bookmark '%s' does not exist") % mark)
797 if mark == repo._bookmarkcurrent:
815 if mark == repo._bookmarkcurrent:
798 bookmarks.setcurrent(repo, None)
816 bookmarks.setcurrent(repo, None)
799 del marks[mark]
817 del marks[mark]
800 bookmarks.write(repo)
818 bookmarks.write(repo)
801 return
819 return
802
820
803 if rename:
821 if rename:
822 if mark is None:
823 raise util.Abort(_("new bookmark name required"))
824 mark = checkformat(mark)
804 if rename not in marks:
825 if rename not in marks:
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
826 raise util.Abort(_("bookmark '%s' does not exist") % rename)
806 if mark in marks and not force:
827 checkconflict(repo, mark, force)
807 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
809 if mark is None:
810 raise util.Abort(_("new bookmark name required"))
811 marks[mark] = marks[rename]
828 marks[mark] = marks[rename]
812 if repo._bookmarkcurrent == rename and not inactive:
829 if repo._bookmarkcurrent == rename and not inactive:
813 bookmarks.setcurrent(repo, mark)
830 bookmarks.setcurrent(repo, mark)
814 del marks[rename]
831 del marks[rename]
815 bookmarks.write(repo)
832 bookmarks.write(repo)
816 return
833 return
817
834
818 if mark is not None:
835 if mark is not None:
819 if "\n" in mark:
836 mark = checkformat(mark)
820 raise util.Abort(_("bookmark name cannot contain newlines"))
821 mark = mark.strip()
822 if not mark:
823 raise util.Abort(_("bookmark names cannot consist entirely of "
824 "whitespace"))
825 if inactive and mark == repo._bookmarkcurrent:
837 if inactive and mark == repo._bookmarkcurrent:
826 bookmarks.setcurrent(repo, None)
838 bookmarks.setcurrent(repo, None)
827 return
839 return
828 if mark in marks and not force:
840 checkconflict(repo, mark, force)
829 raise util.Abort(_("bookmark '%s' already exists "
830 "(use -f to force)") % mark)
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
832 and not force):
833 raise util.Abort(
834 _("a bookmark cannot have the name of an existing branch"))
835 if rev:
841 if rev:
836 marks[mark] = scmutil.revsingle(repo, rev).node()
842 marks[mark] = scmutil.revsingle(repo, rev).node()
837 else:
843 else:
838 marks[mark] = cur
844 marks[mark] = cur
839 if not inactive and cur == marks[mark]:
845 if not inactive and cur == marks[mark]:
840 bookmarks.setcurrent(repo, mark)
846 bookmarks.setcurrent(repo, mark)
841 bookmarks.write(repo)
847 bookmarks.write(repo)
842 return
848 return
843
849
844 if mark is None:
850 if mark is None:
845 if rev:
851 if rev:
846 raise util.Abort(_("bookmark name required"))
852 raise util.Abort(_("bookmark name required"))
847 if len(marks) == 0:
853 if len(marks) == 0:
848 ui.status(_("no bookmarks set\n"))
854 ui.status(_("no bookmarks set\n"))
849 if inactive:
855 if inactive:
850 if not repo._bookmarkcurrent:
856 if not repo._bookmarkcurrent:
851 ui.status(_("no active bookmark\n"))
857 ui.status(_("no active bookmark\n"))
852 else:
858 else:
853 bookmarks.setcurrent(repo, None)
859 bookmarks.setcurrent(repo, None)
854 return
860 return
855 else:
861 else:
856 for bmark, n in sorted(marks.iteritems()):
862 for bmark, n in sorted(marks.iteritems()):
857 current = repo._bookmarkcurrent
863 current = repo._bookmarkcurrent
858 if bmark == current and n == cur:
864 if bmark == current and n == cur:
859 prefix, label = '*', 'bookmarks.current'
865 prefix, label = '*', 'bookmarks.current'
860 else:
866 else:
861 prefix, label = ' ', ''
867 prefix, label = ' ', ''
862
868
863 if ui.quiet:
869 if ui.quiet:
864 ui.write("%s\n" % bmark, label=label)
870 ui.write("%s\n" % bmark, label=label)
865 else:
871 else:
866 ui.write(" %s %-25s %d:%s\n" % (
872 ui.write(" %s %-25s %d:%s\n" % (
867 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
873 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
868 label=label)
874 label=label)
869 return
875 return
870
876
871 @command('branch',
877 @command('branch',
872 [('f', 'force', None,
878 [('f', 'force', None,
873 _('set branch name even if it shadows an existing branch')),
879 _('set branch name even if it shadows an existing branch')),
874 ('C', 'clean', None, _('reset branch name to parent branch name'))],
880 ('C', 'clean', None, _('reset branch name to parent branch name'))],
875 _('[-fC] [NAME]'))
881 _('[-fC] [NAME]'))
876 def branch(ui, repo, label=None, **opts):
882 def branch(ui, repo, label=None, **opts):
877 """set or show the current branch name
883 """set or show the current branch name
878
884
879 .. note::
885 .. note::
880 Branch names are permanent and global. Use :hg:`bookmark` to create a
886 Branch names are permanent and global. Use :hg:`bookmark` to create a
881 light-weight bookmark instead. See :hg:`help glossary` for more
887 light-weight bookmark instead. See :hg:`help glossary` for more
882 information about named branches and bookmarks.
888 information about named branches and bookmarks.
883
889
884 With no argument, show the current branch name. With one argument,
890 With no argument, show the current branch name. With one argument,
885 set the working directory branch name (the branch will not exist
891 set the working directory branch name (the branch will not exist
886 in the repository until the next commit). Standard practice
892 in the repository until the next commit). Standard practice
887 recommends that primary development take place on the 'default'
893 recommends that primary development take place on the 'default'
888 branch.
894 branch.
889
895
890 Unless -f/--force is specified, branch will not let you set a
896 Unless -f/--force is specified, branch will not let you set a
891 branch name that already exists, even if it's inactive.
897 branch name that already exists, even if it's inactive.
892
898
893 Use -C/--clean to reset the working directory branch to that of
899 Use -C/--clean to reset the working directory branch to that of
894 the parent of the working directory, negating a previous branch
900 the parent of the working directory, negating a previous branch
895 change.
901 change.
896
902
897 Use the command :hg:`update` to switch to an existing branch. Use
903 Use the command :hg:`update` to switch to an existing branch. Use
898 :hg:`commit --close-branch` to mark this branch as closed.
904 :hg:`commit --close-branch` to mark this branch as closed.
899
905
900 Returns 0 on success.
906 Returns 0 on success.
901 """
907 """
902 if not opts.get('clean') and not label:
908 if not opts.get('clean') and not label:
903 ui.write("%s\n" % repo.dirstate.branch())
909 ui.write("%s\n" % repo.dirstate.branch())
904 return
910 return
905
911
906 wlock = repo.wlock()
912 wlock = repo.wlock()
907 try:
913 try:
908 if opts.get('clean'):
914 if opts.get('clean'):
909 label = repo[None].p1().branch()
915 label = repo[None].p1().branch()
910 repo.dirstate.setbranch(label)
916 repo.dirstate.setbranch(label)
911 ui.status(_('reset working directory to branch %s\n') % label)
917 ui.status(_('reset working directory to branch %s\n') % label)
912 elif label:
918 elif label:
913 if not opts.get('force') and label in repo.branchmap():
919 if not opts.get('force') and label in repo.branchmap():
914 if label not in [p.branch() for p in repo.parents()]:
920 if label not in [p.branch() for p in repo.parents()]:
915 raise util.Abort(_('a branch of the same name already'
921 raise util.Abort(_('a branch of the same name already'
916 ' exists'),
922 ' exists'),
917 # i18n: "it" refers to an existing branch
923 # i18n: "it" refers to an existing branch
918 hint=_("use 'hg update' to switch to it"))
924 hint=_("use 'hg update' to switch to it"))
919 repo.dirstate.setbranch(label)
925 repo.dirstate.setbranch(label)
920 ui.status(_('marked working directory as branch %s\n') % label)
926 ui.status(_('marked working directory as branch %s\n') % label)
921 ui.status(_('(branches are permanent and global, '
927 ui.status(_('(branches are permanent and global, '
922 'did you want a bookmark?)\n'))
928 'did you want a bookmark?)\n'))
923 finally:
929 finally:
924 wlock.release()
930 wlock.release()
925
931
926 @command('branches',
932 @command('branches',
927 [('a', 'active', False, _('show only branches that have unmerged heads')),
933 [('a', 'active', False, _('show only branches that have unmerged heads')),
928 ('c', 'closed', False, _('show normal and closed branches'))],
934 ('c', 'closed', False, _('show normal and closed branches'))],
929 _('[-ac]'))
935 _('[-ac]'))
930 def branches(ui, repo, active=False, closed=False):
936 def branches(ui, repo, active=False, closed=False):
931 """list repository named branches
937 """list repository named branches
932
938
933 List the repository's named branches, indicating which ones are
939 List the repository's named branches, indicating which ones are
934 inactive. If -c/--closed is specified, also list branches which have
940 inactive. If -c/--closed is specified, also list branches which have
935 been marked closed (see :hg:`commit --close-branch`).
941 been marked closed (see :hg:`commit --close-branch`).
936
942
937 If -a/--active is specified, only show active branches. A branch
943 If -a/--active is specified, only show active branches. A branch
938 is considered active if it contains repository heads.
944 is considered active if it contains repository heads.
939
945
940 Use the command :hg:`update` to switch to an existing branch.
946 Use the command :hg:`update` to switch to an existing branch.
941
947
942 Returns 0.
948 Returns 0.
943 """
949 """
944
950
945 hexfunc = ui.debugflag and hex or short
951 hexfunc = ui.debugflag and hex or short
946
952
947 activebranches = set([repo[n].branch() for n in repo.heads()])
953 activebranches = set([repo[n].branch() for n in repo.heads()])
948 branches = []
954 branches = []
949 for tag, heads in repo.branchmap().iteritems():
955 for tag, heads in repo.branchmap().iteritems():
950 for h in reversed(heads):
956 for h in reversed(heads):
951 ctx = repo[h]
957 ctx = repo[h]
952 isopen = not ctx.closesbranch()
958 isopen = not ctx.closesbranch()
953 if isopen:
959 if isopen:
954 tip = ctx
960 tip = ctx
955 break
961 break
956 else:
962 else:
957 tip = repo[heads[-1]]
963 tip = repo[heads[-1]]
958 isactive = tag in activebranches and isopen
964 isactive = tag in activebranches and isopen
959 branches.append((tip, isactive, isopen))
965 branches.append((tip, isactive, isopen))
960 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
966 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
961 reverse=True)
967 reverse=True)
962
968
963 for ctx, isactive, isopen in branches:
969 for ctx, isactive, isopen in branches:
964 if (not active) or isactive:
970 if (not active) or isactive:
965 if isactive:
971 if isactive:
966 label = 'branches.active'
972 label = 'branches.active'
967 notice = ''
973 notice = ''
968 elif not isopen:
974 elif not isopen:
969 if not closed:
975 if not closed:
970 continue
976 continue
971 label = 'branches.closed'
977 label = 'branches.closed'
972 notice = _(' (closed)')
978 notice = _(' (closed)')
973 else:
979 else:
974 label = 'branches.inactive'
980 label = 'branches.inactive'
975 notice = _(' (inactive)')
981 notice = _(' (inactive)')
976 if ctx.branch() == repo.dirstate.branch():
982 if ctx.branch() == repo.dirstate.branch():
977 label = 'branches.current'
983 label = 'branches.current'
978 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
984 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
979 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
985 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
980 'log.changeset changeset.%s' % ctx.phasestr())
986 'log.changeset changeset.%s' % ctx.phasestr())
981 tag = ui.label(ctx.branch(), label)
987 tag = ui.label(ctx.branch(), label)
982 if ui.quiet:
988 if ui.quiet:
983 ui.write("%s\n" % tag)
989 ui.write("%s\n" % tag)
984 else:
990 else:
985 ui.write("%s %s%s\n" % (tag, rev, notice))
991 ui.write("%s %s%s\n" % (tag, rev, notice))
986
992
987 @command('bundle',
993 @command('bundle',
988 [('f', 'force', None, _('run even when the destination is unrelated')),
994 [('f', 'force', None, _('run even when the destination is unrelated')),
989 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
995 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
990 _('REV')),
996 _('REV')),
991 ('b', 'branch', [], _('a specific branch you would like to bundle'),
997 ('b', 'branch', [], _('a specific branch you would like to bundle'),
992 _('BRANCH')),
998 _('BRANCH')),
993 ('', 'base', [],
999 ('', 'base', [],
994 _('a base changeset assumed to be available at the destination'),
1000 _('a base changeset assumed to be available at the destination'),
995 _('REV')),
1001 _('REV')),
996 ('a', 'all', None, _('bundle all changesets in the repository')),
1002 ('a', 'all', None, _('bundle all changesets in the repository')),
997 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1003 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
998 ] + remoteopts,
1004 ] + remoteopts,
999 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1005 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1000 def bundle(ui, repo, fname, dest=None, **opts):
1006 def bundle(ui, repo, fname, dest=None, **opts):
1001 """create a changegroup file
1007 """create a changegroup file
1002
1008
1003 Generate a compressed changegroup file collecting changesets not
1009 Generate a compressed changegroup file collecting changesets not
1004 known to be in another repository.
1010 known to be in another repository.
1005
1011
1006 If you omit the destination repository, then hg assumes the
1012 If you omit the destination repository, then hg assumes the
1007 destination will have all the nodes you specify with --base
1013 destination will have all the nodes you specify with --base
1008 parameters. To create a bundle containing all changesets, use
1014 parameters. To create a bundle containing all changesets, use
1009 -a/--all (or --base null).
1015 -a/--all (or --base null).
1010
1016
1011 You can change compression method with the -t/--type option.
1017 You can change compression method with the -t/--type option.
1012 The available compression methods are: none, bzip2, and
1018 The available compression methods are: none, bzip2, and
1013 gzip (by default, bundles are compressed using bzip2).
1019 gzip (by default, bundles are compressed using bzip2).
1014
1020
1015 The bundle file can then be transferred using conventional means
1021 The bundle file can then be transferred using conventional means
1016 and applied to another repository with the unbundle or pull
1022 and applied to another repository with the unbundle or pull
1017 command. This is useful when direct push and pull are not
1023 command. This is useful when direct push and pull are not
1018 available or when exporting an entire repository is undesirable.
1024 available or when exporting an entire repository is undesirable.
1019
1025
1020 Applying bundles preserves all changeset contents including
1026 Applying bundles preserves all changeset contents including
1021 permissions, copy/rename information, and revision history.
1027 permissions, copy/rename information, and revision history.
1022
1028
1023 Returns 0 on success, 1 if no changes found.
1029 Returns 0 on success, 1 if no changes found.
1024 """
1030 """
1025 revs = None
1031 revs = None
1026 if 'rev' in opts:
1032 if 'rev' in opts:
1027 revs = scmutil.revrange(repo, opts['rev'])
1033 revs = scmutil.revrange(repo, opts['rev'])
1028
1034
1029 bundletype = opts.get('type', 'bzip2').lower()
1035 bundletype = opts.get('type', 'bzip2').lower()
1030 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1036 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1031 bundletype = btypes.get(bundletype)
1037 bundletype = btypes.get(bundletype)
1032 if bundletype not in changegroup.bundletypes:
1038 if bundletype not in changegroup.bundletypes:
1033 raise util.Abort(_('unknown bundle type specified with --type'))
1039 raise util.Abort(_('unknown bundle type specified with --type'))
1034
1040
1035 if opts.get('all'):
1041 if opts.get('all'):
1036 base = ['null']
1042 base = ['null']
1037 else:
1043 else:
1038 base = scmutil.revrange(repo, opts.get('base'))
1044 base = scmutil.revrange(repo, opts.get('base'))
1039 if base:
1045 if base:
1040 if dest:
1046 if dest:
1041 raise util.Abort(_("--base is incompatible with specifying "
1047 raise util.Abort(_("--base is incompatible with specifying "
1042 "a destination"))
1048 "a destination"))
1043 common = [repo.lookup(rev) for rev in base]
1049 common = [repo.lookup(rev) for rev in base]
1044 heads = revs and map(repo.lookup, revs) or revs
1050 heads = revs and map(repo.lookup, revs) or revs
1045 cg = repo.getbundle('bundle', heads=heads, common=common)
1051 cg = repo.getbundle('bundle', heads=heads, common=common)
1046 outgoing = None
1052 outgoing = None
1047 else:
1053 else:
1048 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1054 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1049 dest, branches = hg.parseurl(dest, opts.get('branch'))
1055 dest, branches = hg.parseurl(dest, opts.get('branch'))
1050 other = hg.peer(repo, opts, dest)
1056 other = hg.peer(repo, opts, dest)
1051 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1057 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1052 heads = revs and map(repo.lookup, revs) or revs
1058 heads = revs and map(repo.lookup, revs) or revs
1053 outgoing = discovery.findcommonoutgoing(repo, other,
1059 outgoing = discovery.findcommonoutgoing(repo, other,
1054 onlyheads=heads,
1060 onlyheads=heads,
1055 force=opts.get('force'),
1061 force=opts.get('force'),
1056 portable=True)
1062 portable=True)
1057 cg = repo.getlocalbundle('bundle', outgoing)
1063 cg = repo.getlocalbundle('bundle', outgoing)
1058 if not cg:
1064 if not cg:
1059 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1065 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1060 return 1
1066 return 1
1061
1067
1062 changegroup.writebundle(cg, fname, bundletype)
1068 changegroup.writebundle(cg, fname, bundletype)
1063
1069
1064 @command('cat',
1070 @command('cat',
1065 [('o', 'output', '',
1071 [('o', 'output', '',
1066 _('print output to file with formatted name'), _('FORMAT')),
1072 _('print output to file with formatted name'), _('FORMAT')),
1067 ('r', 'rev', '', _('print the given revision'), _('REV')),
1073 ('r', 'rev', '', _('print the given revision'), _('REV')),
1068 ('', 'decode', None, _('apply any matching decode filter')),
1074 ('', 'decode', None, _('apply any matching decode filter')),
1069 ] + walkopts,
1075 ] + walkopts,
1070 _('[OPTION]... FILE...'))
1076 _('[OPTION]... FILE...'))
1071 def cat(ui, repo, file1, *pats, **opts):
1077 def cat(ui, repo, file1, *pats, **opts):
1072 """output the current or given revision of files
1078 """output the current or given revision of files
1073
1079
1074 Print the specified files as they were at the given revision. If
1080 Print the specified files as they were at the given revision. If
1075 no revision is given, the parent of the working directory is used,
1081 no revision is given, the parent of the working directory is used,
1076 or tip if no revision is checked out.
1082 or tip if no revision is checked out.
1077
1083
1078 Output may be to a file, in which case the name of the file is
1084 Output may be to a file, in which case the name of the file is
1079 given using a format string. The formatting rules are the same as
1085 given using a format string. The formatting rules are the same as
1080 for the export command, with the following additions:
1086 for the export command, with the following additions:
1081
1087
1082 :``%s``: basename of file being printed
1088 :``%s``: basename of file being printed
1083 :``%d``: dirname of file being printed, or '.' if in repository root
1089 :``%d``: dirname of file being printed, or '.' if in repository root
1084 :``%p``: root-relative path name of file being printed
1090 :``%p``: root-relative path name of file being printed
1085
1091
1086 Returns 0 on success.
1092 Returns 0 on success.
1087 """
1093 """
1088 ctx = scmutil.revsingle(repo, opts.get('rev'))
1094 ctx = scmutil.revsingle(repo, opts.get('rev'))
1089 err = 1
1095 err = 1
1090 m = scmutil.match(ctx, (file1,) + pats, opts)
1096 m = scmutil.match(ctx, (file1,) + pats, opts)
1091 for abs in ctx.walk(m):
1097 for abs in ctx.walk(m):
1092 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1098 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1093 pathname=abs)
1099 pathname=abs)
1094 data = ctx[abs].data()
1100 data = ctx[abs].data()
1095 if opts.get('decode'):
1101 if opts.get('decode'):
1096 data = repo.wwritedata(abs, data)
1102 data = repo.wwritedata(abs, data)
1097 fp.write(data)
1103 fp.write(data)
1098 fp.close()
1104 fp.close()
1099 err = 0
1105 err = 0
1100 return err
1106 return err
1101
1107
1102 @command('^clone',
1108 @command('^clone',
1103 [('U', 'noupdate', None,
1109 [('U', 'noupdate', None,
1104 _('the clone will include an empty working copy (only a repository)')),
1110 _('the clone will include an empty working copy (only a repository)')),
1105 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1111 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1106 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1112 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1107 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1113 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1108 ('', 'pull', None, _('use pull protocol to copy metadata')),
1114 ('', 'pull', None, _('use pull protocol to copy metadata')),
1109 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1115 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1110 ] + remoteopts,
1116 ] + remoteopts,
1111 _('[OPTION]... SOURCE [DEST]'))
1117 _('[OPTION]... SOURCE [DEST]'))
1112 def clone(ui, source, dest=None, **opts):
1118 def clone(ui, source, dest=None, **opts):
1113 """make a copy of an existing repository
1119 """make a copy of an existing repository
1114
1120
1115 Create a copy of an existing repository in a new directory.
1121 Create a copy of an existing repository in a new directory.
1116
1122
1117 If no destination directory name is specified, it defaults to the
1123 If no destination directory name is specified, it defaults to the
1118 basename of the source.
1124 basename of the source.
1119
1125
1120 The location of the source is added to the new repository's
1126 The location of the source is added to the new repository's
1121 ``.hg/hgrc`` file, as the default to be used for future pulls.
1127 ``.hg/hgrc`` file, as the default to be used for future pulls.
1122
1128
1123 Only local paths and ``ssh://`` URLs are supported as
1129 Only local paths and ``ssh://`` URLs are supported as
1124 destinations. For ``ssh://`` destinations, no working directory or
1130 destinations. For ``ssh://`` destinations, no working directory or
1125 ``.hg/hgrc`` will be created on the remote side.
1131 ``.hg/hgrc`` will be created on the remote side.
1126
1132
1127 To pull only a subset of changesets, specify one or more revisions
1133 To pull only a subset of changesets, specify one or more revisions
1128 identifiers with -r/--rev or branches with -b/--branch. The
1134 identifiers with -r/--rev or branches with -b/--branch. The
1129 resulting clone will contain only the specified changesets and
1135 resulting clone will contain only the specified changesets and
1130 their ancestors. These options (or 'clone src#rev dest') imply
1136 their ancestors. These options (or 'clone src#rev dest') imply
1131 --pull, even for local source repositories. Note that specifying a
1137 --pull, even for local source repositories. Note that specifying a
1132 tag will include the tagged changeset but not the changeset
1138 tag will include the tagged changeset but not the changeset
1133 containing the tag.
1139 containing the tag.
1134
1140
1135 To check out a particular version, use -u/--update, or
1141 To check out a particular version, use -u/--update, or
1136 -U/--noupdate to create a clone with no working directory.
1142 -U/--noupdate to create a clone with no working directory.
1137
1143
1138 .. container:: verbose
1144 .. container:: verbose
1139
1145
1140 For efficiency, hardlinks are used for cloning whenever the
1146 For efficiency, hardlinks are used for cloning whenever the
1141 source and destination are on the same filesystem (note this
1147 source and destination are on the same filesystem (note this
1142 applies only to the repository data, not to the working
1148 applies only to the repository data, not to the working
1143 directory). Some filesystems, such as AFS, implement hardlinking
1149 directory). Some filesystems, such as AFS, implement hardlinking
1144 incorrectly, but do not report errors. In these cases, use the
1150 incorrectly, but do not report errors. In these cases, use the
1145 --pull option to avoid hardlinking.
1151 --pull option to avoid hardlinking.
1146
1152
1147 In some cases, you can clone repositories and the working
1153 In some cases, you can clone repositories and the working
1148 directory using full hardlinks with ::
1154 directory using full hardlinks with ::
1149
1155
1150 $ cp -al REPO REPOCLONE
1156 $ cp -al REPO REPOCLONE
1151
1157
1152 This is the fastest way to clone, but it is not always safe. The
1158 This is the fastest way to clone, but it is not always safe. The
1153 operation is not atomic (making sure REPO is not modified during
1159 operation is not atomic (making sure REPO is not modified during
1154 the operation is up to you) and you have to make sure your
1160 the operation is up to you) and you have to make sure your
1155 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1161 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1156 so). Also, this is not compatible with certain extensions that
1162 so). Also, this is not compatible with certain extensions that
1157 place their metadata under the .hg directory, such as mq.
1163 place their metadata under the .hg directory, such as mq.
1158
1164
1159 Mercurial will update the working directory to the first applicable
1165 Mercurial will update the working directory to the first applicable
1160 revision from this list:
1166 revision from this list:
1161
1167
1162 a) null if -U or the source repository has no changesets
1168 a) null if -U or the source repository has no changesets
1163 b) if -u . and the source repository is local, the first parent of
1169 b) if -u . and the source repository is local, the first parent of
1164 the source repository's working directory
1170 the source repository's working directory
1165 c) the changeset specified with -u (if a branch name, this means the
1171 c) the changeset specified with -u (if a branch name, this means the
1166 latest head of that branch)
1172 latest head of that branch)
1167 d) the changeset specified with -r
1173 d) the changeset specified with -r
1168 e) the tipmost head specified with -b
1174 e) the tipmost head specified with -b
1169 f) the tipmost head specified with the url#branch source syntax
1175 f) the tipmost head specified with the url#branch source syntax
1170 g) the tipmost head of the default branch
1176 g) the tipmost head of the default branch
1171 h) tip
1177 h) tip
1172
1178
1173 Examples:
1179 Examples:
1174
1180
1175 - clone a remote repository to a new directory named hg/::
1181 - clone a remote repository to a new directory named hg/::
1176
1182
1177 hg clone http://selenic.com/hg
1183 hg clone http://selenic.com/hg
1178
1184
1179 - create a lightweight local clone::
1185 - create a lightweight local clone::
1180
1186
1181 hg clone project/ project-feature/
1187 hg clone project/ project-feature/
1182
1188
1183 - clone from an absolute path on an ssh server (note double-slash)::
1189 - clone from an absolute path on an ssh server (note double-slash)::
1184
1190
1185 hg clone ssh://user@server//home/projects/alpha/
1191 hg clone ssh://user@server//home/projects/alpha/
1186
1192
1187 - do a high-speed clone over a LAN while checking out a
1193 - do a high-speed clone over a LAN while checking out a
1188 specified version::
1194 specified version::
1189
1195
1190 hg clone --uncompressed http://server/repo -u 1.5
1196 hg clone --uncompressed http://server/repo -u 1.5
1191
1197
1192 - create a repository without changesets after a particular revision::
1198 - create a repository without changesets after a particular revision::
1193
1199
1194 hg clone -r 04e544 experimental/ good/
1200 hg clone -r 04e544 experimental/ good/
1195
1201
1196 - clone (and track) a particular named branch::
1202 - clone (and track) a particular named branch::
1197
1203
1198 hg clone http://selenic.com/hg#stable
1204 hg clone http://selenic.com/hg#stable
1199
1205
1200 See :hg:`help urls` for details on specifying URLs.
1206 See :hg:`help urls` for details on specifying URLs.
1201
1207
1202 Returns 0 on success.
1208 Returns 0 on success.
1203 """
1209 """
1204 if opts.get('noupdate') and opts.get('updaterev'):
1210 if opts.get('noupdate') and opts.get('updaterev'):
1205 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1211 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1206
1212
1207 r = hg.clone(ui, opts, source, dest,
1213 r = hg.clone(ui, opts, source, dest,
1208 pull=opts.get('pull'),
1214 pull=opts.get('pull'),
1209 stream=opts.get('uncompressed'),
1215 stream=opts.get('uncompressed'),
1210 rev=opts.get('rev'),
1216 rev=opts.get('rev'),
1211 update=opts.get('updaterev') or not opts.get('noupdate'),
1217 update=opts.get('updaterev') or not opts.get('noupdate'),
1212 branch=opts.get('branch'))
1218 branch=opts.get('branch'))
1213
1219
1214 return r is None
1220 return r is None
1215
1221
1216 @command('^commit|ci',
1222 @command('^commit|ci',
1217 [('A', 'addremove', None,
1223 [('A', 'addremove', None,
1218 _('mark new/missing files as added/removed before committing')),
1224 _('mark new/missing files as added/removed before committing')),
1219 ('', 'close-branch', None,
1225 ('', 'close-branch', None,
1220 _('mark a branch as closed, hiding it from the branch list')),
1226 _('mark a branch as closed, hiding it from the branch list')),
1221 ('', 'amend', None, _('amend the parent of the working dir')),
1227 ('', 'amend', None, _('amend the parent of the working dir')),
1222 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1228 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1223 _('[OPTION]... [FILE]...'))
1229 _('[OPTION]... [FILE]...'))
1224 def commit(ui, repo, *pats, **opts):
1230 def commit(ui, repo, *pats, **opts):
1225 """commit the specified files or all outstanding changes
1231 """commit the specified files or all outstanding changes
1226
1232
1227 Commit changes to the given files into the repository. Unlike a
1233 Commit changes to the given files into the repository. Unlike a
1228 centralized SCM, this operation is a local operation. See
1234 centralized SCM, this operation is a local operation. See
1229 :hg:`push` for a way to actively distribute your changes.
1235 :hg:`push` for a way to actively distribute your changes.
1230
1236
1231 If a list of files is omitted, all changes reported by :hg:`status`
1237 If a list of files is omitted, all changes reported by :hg:`status`
1232 will be committed.
1238 will be committed.
1233
1239
1234 If you are committing the result of a merge, do not provide any
1240 If you are committing the result of a merge, do not provide any
1235 filenames or -I/-X filters.
1241 filenames or -I/-X filters.
1236
1242
1237 If no commit message is specified, Mercurial starts your
1243 If no commit message is specified, Mercurial starts your
1238 configured editor where you can enter a message. In case your
1244 configured editor where you can enter a message. In case your
1239 commit fails, you will find a backup of your message in
1245 commit fails, you will find a backup of your message in
1240 ``.hg/last-message.txt``.
1246 ``.hg/last-message.txt``.
1241
1247
1242 The --amend flag can be used to amend the parent of the
1248 The --amend flag can be used to amend the parent of the
1243 working directory with a new commit that contains the changes
1249 working directory with a new commit that contains the changes
1244 in the parent in addition to those currently reported by :hg:`status`,
1250 in the parent in addition to those currently reported by :hg:`status`,
1245 if there are any. The old commit is stored in a backup bundle in
1251 if there are any. The old commit is stored in a backup bundle in
1246 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1252 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1247 on how to restore it).
1253 on how to restore it).
1248
1254
1249 Message, user and date are taken from the amended commit unless
1255 Message, user and date are taken from the amended commit unless
1250 specified. When a message isn't specified on the command line,
1256 specified. When a message isn't specified on the command line,
1251 the editor will open with the message of the amended commit.
1257 the editor will open with the message of the amended commit.
1252
1258
1253 It is not possible to amend public changesets (see :hg:`help phases`)
1259 It is not possible to amend public changesets (see :hg:`help phases`)
1254 or changesets that have children.
1260 or changesets that have children.
1255
1261
1256 See :hg:`help dates` for a list of formats valid for -d/--date.
1262 See :hg:`help dates` for a list of formats valid for -d/--date.
1257
1263
1258 Returns 0 on success, 1 if nothing changed.
1264 Returns 0 on success, 1 if nothing changed.
1259 """
1265 """
1260 if opts.get('subrepos'):
1266 if opts.get('subrepos'):
1261 # Let --subrepos on the command line override config setting.
1267 # Let --subrepos on the command line override config setting.
1262 ui.setconfig('ui', 'commitsubrepos', True)
1268 ui.setconfig('ui', 'commitsubrepos', True)
1263
1269
1264 extra = {}
1270 extra = {}
1265 if opts.get('close_branch'):
1271 if opts.get('close_branch'):
1266 if repo['.'].node() not in repo.branchheads():
1272 if repo['.'].node() not in repo.branchheads():
1267 # The topo heads set is included in the branch heads set of the
1273 # The topo heads set is included in the branch heads set of the
1268 # current branch, so it's sufficient to test branchheads
1274 # current branch, so it's sufficient to test branchheads
1269 raise util.Abort(_('can only close branch heads'))
1275 raise util.Abort(_('can only close branch heads'))
1270 extra['close'] = 1
1276 extra['close'] = 1
1271
1277
1272 branch = repo[None].branch()
1278 branch = repo[None].branch()
1273 bheads = repo.branchheads(branch)
1279 bheads = repo.branchheads(branch)
1274
1280
1275 if opts.get('amend'):
1281 if opts.get('amend'):
1276 if ui.configbool('ui', 'commitsubrepos'):
1282 if ui.configbool('ui', 'commitsubrepos'):
1277 raise util.Abort(_('cannot amend recursively'))
1283 raise util.Abort(_('cannot amend recursively'))
1278
1284
1279 old = repo['.']
1285 old = repo['.']
1280 if old.phase() == phases.public:
1286 if old.phase() == phases.public:
1281 raise util.Abort(_('cannot amend public changesets'))
1287 raise util.Abort(_('cannot amend public changesets'))
1282 if len(old.parents()) > 1:
1288 if len(old.parents()) > 1:
1283 raise util.Abort(_('cannot amend merge changesets'))
1289 raise util.Abort(_('cannot amend merge changesets'))
1284 if len(repo[None].parents()) > 1:
1290 if len(repo[None].parents()) > 1:
1285 raise util.Abort(_('cannot amend while merging'))
1291 raise util.Abort(_('cannot amend while merging'))
1286 if old.children():
1292 if old.children():
1287 raise util.Abort(_('cannot amend changeset with children'))
1293 raise util.Abort(_('cannot amend changeset with children'))
1288
1294
1289 e = cmdutil.commiteditor
1295 e = cmdutil.commiteditor
1290 if opts.get('force_editor'):
1296 if opts.get('force_editor'):
1291 e = cmdutil.commitforceeditor
1297 e = cmdutil.commitforceeditor
1292
1298
1293 def commitfunc(ui, repo, message, match, opts):
1299 def commitfunc(ui, repo, message, match, opts):
1294 editor = e
1300 editor = e
1295 # message contains text from -m or -l, if it's empty,
1301 # message contains text from -m or -l, if it's empty,
1296 # open the editor with the old message
1302 # open the editor with the old message
1297 if not message:
1303 if not message:
1298 message = old.description()
1304 message = old.description()
1299 editor = cmdutil.commitforceeditor
1305 editor = cmdutil.commitforceeditor
1300 return repo.commit(message,
1306 return repo.commit(message,
1301 opts.get('user') or old.user(),
1307 opts.get('user') or old.user(),
1302 opts.get('date') or old.date(),
1308 opts.get('date') or old.date(),
1303 match,
1309 match,
1304 editor=editor,
1310 editor=editor,
1305 extra=extra)
1311 extra=extra)
1306
1312
1307 current = repo._bookmarkcurrent
1313 current = repo._bookmarkcurrent
1308 marks = old.bookmarks()
1314 marks = old.bookmarks()
1309 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1315 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1310 if node == old.node():
1316 if node == old.node():
1311 ui.status(_("nothing changed\n"))
1317 ui.status(_("nothing changed\n"))
1312 return 1
1318 return 1
1313 elif marks:
1319 elif marks:
1314 ui.debug('moving bookmarks %r from %s to %s\n' %
1320 ui.debug('moving bookmarks %r from %s to %s\n' %
1315 (marks, old.hex(), hex(node)))
1321 (marks, old.hex(), hex(node)))
1316 for bm in marks:
1322 for bm in marks:
1317 repo._bookmarks[bm] = node
1323 repo._bookmarks[bm] = node
1318 if bm == current:
1324 if bm == current:
1319 bookmarks.setcurrent(repo, bm)
1325 bookmarks.setcurrent(repo, bm)
1320 bookmarks.write(repo)
1326 bookmarks.write(repo)
1321 else:
1327 else:
1322 e = cmdutil.commiteditor
1328 e = cmdutil.commiteditor
1323 if opts.get('force_editor'):
1329 if opts.get('force_editor'):
1324 e = cmdutil.commitforceeditor
1330 e = cmdutil.commitforceeditor
1325
1331
1326 def commitfunc(ui, repo, message, match, opts):
1332 def commitfunc(ui, repo, message, match, opts):
1327 return repo.commit(message, opts.get('user'), opts.get('date'),
1333 return repo.commit(message, opts.get('user'), opts.get('date'),
1328 match, editor=e, extra=extra)
1334 match, editor=e, extra=extra)
1329
1335
1330 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1336 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1331
1337
1332 if not node:
1338 if not node:
1333 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1339 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1334 if stat[3]:
1340 if stat[3]:
1335 ui.status(_("nothing changed (%d missing files, see "
1341 ui.status(_("nothing changed (%d missing files, see "
1336 "'hg status')\n") % len(stat[3]))
1342 "'hg status')\n") % len(stat[3]))
1337 else:
1343 else:
1338 ui.status(_("nothing changed\n"))
1344 ui.status(_("nothing changed\n"))
1339 return 1
1345 return 1
1340
1346
1341 ctx = repo[node]
1347 ctx = repo[node]
1342 parents = ctx.parents()
1348 parents = ctx.parents()
1343
1349
1344 if (not opts.get('amend') and bheads and node not in bheads and not
1350 if (not opts.get('amend') and bheads and node not in bheads and not
1345 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1351 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1346 ui.status(_('created new head\n'))
1352 ui.status(_('created new head\n'))
1347 # The message is not printed for initial roots. For the other
1353 # The message is not printed for initial roots. For the other
1348 # changesets, it is printed in the following situations:
1354 # changesets, it is printed in the following situations:
1349 #
1355 #
1350 # Par column: for the 2 parents with ...
1356 # Par column: for the 2 parents with ...
1351 # N: null or no parent
1357 # N: null or no parent
1352 # B: parent is on another named branch
1358 # B: parent is on another named branch
1353 # C: parent is a regular non head changeset
1359 # C: parent is a regular non head changeset
1354 # H: parent was a branch head of the current branch
1360 # H: parent was a branch head of the current branch
1355 # Msg column: whether we print "created new head" message
1361 # Msg column: whether we print "created new head" message
1356 # In the following, it is assumed that there already exists some
1362 # In the following, it is assumed that there already exists some
1357 # initial branch heads of the current branch, otherwise nothing is
1363 # initial branch heads of the current branch, otherwise nothing is
1358 # printed anyway.
1364 # printed anyway.
1359 #
1365 #
1360 # Par Msg Comment
1366 # Par Msg Comment
1361 # N N y additional topo root
1367 # N N y additional topo root
1362 #
1368 #
1363 # B N y additional branch root
1369 # B N y additional branch root
1364 # C N y additional topo head
1370 # C N y additional topo head
1365 # H N n usual case
1371 # H N n usual case
1366 #
1372 #
1367 # B B y weird additional branch root
1373 # B B y weird additional branch root
1368 # C B y branch merge
1374 # C B y branch merge
1369 # H B n merge with named branch
1375 # H B n merge with named branch
1370 #
1376 #
1371 # C C y additional head from merge
1377 # C C y additional head from merge
1372 # C H n merge with a head
1378 # C H n merge with a head
1373 #
1379 #
1374 # H H n head merge: head count decreases
1380 # H H n head merge: head count decreases
1375
1381
1376 if not opts.get('close_branch'):
1382 if not opts.get('close_branch'):
1377 for r in parents:
1383 for r in parents:
1378 if r.closesbranch() and r.branch() == branch:
1384 if r.closesbranch() and r.branch() == branch:
1379 ui.status(_('reopening closed branch head %d\n') % r)
1385 ui.status(_('reopening closed branch head %d\n') % r)
1380
1386
1381 if ui.debugflag:
1387 if ui.debugflag:
1382 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1388 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1383 elif ui.verbose:
1389 elif ui.verbose:
1384 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1390 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1385
1391
1386 @command('copy|cp',
1392 @command('copy|cp',
1387 [('A', 'after', None, _('record a copy that has already occurred')),
1393 [('A', 'after', None, _('record a copy that has already occurred')),
1388 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1394 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1389 ] + walkopts + dryrunopts,
1395 ] + walkopts + dryrunopts,
1390 _('[OPTION]... [SOURCE]... DEST'))
1396 _('[OPTION]... [SOURCE]... DEST'))
1391 def copy(ui, repo, *pats, **opts):
1397 def copy(ui, repo, *pats, **opts):
1392 """mark files as copied for the next commit
1398 """mark files as copied for the next commit
1393
1399
1394 Mark dest as having copies of source files. If dest is a
1400 Mark dest as having copies of source files. If dest is a
1395 directory, copies are put in that directory. If dest is a file,
1401 directory, copies are put in that directory. If dest is a file,
1396 the source must be a single file.
1402 the source must be a single file.
1397
1403
1398 By default, this command copies the contents of files as they
1404 By default, this command copies the contents of files as they
1399 exist in the working directory. If invoked with -A/--after, the
1405 exist in the working directory. If invoked with -A/--after, the
1400 operation is recorded, but no copying is performed.
1406 operation is recorded, but no copying is performed.
1401
1407
1402 This command takes effect with the next commit. To undo a copy
1408 This command takes effect with the next commit. To undo a copy
1403 before that, see :hg:`revert`.
1409 before that, see :hg:`revert`.
1404
1410
1405 Returns 0 on success, 1 if errors are encountered.
1411 Returns 0 on success, 1 if errors are encountered.
1406 """
1412 """
1407 wlock = repo.wlock(False)
1413 wlock = repo.wlock(False)
1408 try:
1414 try:
1409 return cmdutil.copy(ui, repo, pats, opts)
1415 return cmdutil.copy(ui, repo, pats, opts)
1410 finally:
1416 finally:
1411 wlock.release()
1417 wlock.release()
1412
1418
1413 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1419 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1414 def debugancestor(ui, repo, *args):
1420 def debugancestor(ui, repo, *args):
1415 """find the ancestor revision of two revisions in a given index"""
1421 """find the ancestor revision of two revisions in a given index"""
1416 if len(args) == 3:
1422 if len(args) == 3:
1417 index, rev1, rev2 = args
1423 index, rev1, rev2 = args
1418 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1424 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1419 lookup = r.lookup
1425 lookup = r.lookup
1420 elif len(args) == 2:
1426 elif len(args) == 2:
1421 if not repo:
1427 if not repo:
1422 raise util.Abort(_("there is no Mercurial repository here "
1428 raise util.Abort(_("there is no Mercurial repository here "
1423 "(.hg not found)"))
1429 "(.hg not found)"))
1424 rev1, rev2 = args
1430 rev1, rev2 = args
1425 r = repo.changelog
1431 r = repo.changelog
1426 lookup = repo.lookup
1432 lookup = repo.lookup
1427 else:
1433 else:
1428 raise util.Abort(_('either two or three arguments required'))
1434 raise util.Abort(_('either two or three arguments required'))
1429 a = r.ancestor(lookup(rev1), lookup(rev2))
1435 a = r.ancestor(lookup(rev1), lookup(rev2))
1430 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1436 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1431
1437
1432 @command('debugbuilddag',
1438 @command('debugbuilddag',
1433 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1439 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1434 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1440 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1435 ('n', 'new-file', None, _('add new file at each rev'))],
1441 ('n', 'new-file', None, _('add new file at each rev'))],
1436 _('[OPTION]... [TEXT]'))
1442 _('[OPTION]... [TEXT]'))
1437 def debugbuilddag(ui, repo, text=None,
1443 def debugbuilddag(ui, repo, text=None,
1438 mergeable_file=False,
1444 mergeable_file=False,
1439 overwritten_file=False,
1445 overwritten_file=False,
1440 new_file=False):
1446 new_file=False):
1441 """builds a repo with a given DAG from scratch in the current empty repo
1447 """builds a repo with a given DAG from scratch in the current empty repo
1442
1448
1443 The description of the DAG is read from stdin if not given on the
1449 The description of the DAG is read from stdin if not given on the
1444 command line.
1450 command line.
1445
1451
1446 Elements:
1452 Elements:
1447
1453
1448 - "+n" is a linear run of n nodes based on the current default parent
1454 - "+n" is a linear run of n nodes based on the current default parent
1449 - "." is a single node based on the current default parent
1455 - "." is a single node based on the current default parent
1450 - "$" resets the default parent to null (implied at the start);
1456 - "$" resets the default parent to null (implied at the start);
1451 otherwise the default parent is always the last node created
1457 otherwise the default parent is always the last node created
1452 - "<p" sets the default parent to the backref p
1458 - "<p" sets the default parent to the backref p
1453 - "*p" is a fork at parent p, which is a backref
1459 - "*p" is a fork at parent p, which is a backref
1454 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1460 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1455 - "/p2" is a merge of the preceding node and p2
1461 - "/p2" is a merge of the preceding node and p2
1456 - ":tag" defines a local tag for the preceding node
1462 - ":tag" defines a local tag for the preceding node
1457 - "@branch" sets the named branch for subsequent nodes
1463 - "@branch" sets the named branch for subsequent nodes
1458 - "#...\\n" is a comment up to the end of the line
1464 - "#...\\n" is a comment up to the end of the line
1459
1465
1460 Whitespace between the above elements is ignored.
1466 Whitespace between the above elements is ignored.
1461
1467
1462 A backref is either
1468 A backref is either
1463
1469
1464 - a number n, which references the node curr-n, where curr is the current
1470 - a number n, which references the node curr-n, where curr is the current
1465 node, or
1471 node, or
1466 - the name of a local tag you placed earlier using ":tag", or
1472 - the name of a local tag you placed earlier using ":tag", or
1467 - empty to denote the default parent.
1473 - empty to denote the default parent.
1468
1474
1469 All string valued-elements are either strictly alphanumeric, or must
1475 All string valued-elements are either strictly alphanumeric, or must
1470 be enclosed in double quotes ("..."), with "\\" as escape character.
1476 be enclosed in double quotes ("..."), with "\\" as escape character.
1471 """
1477 """
1472
1478
1473 if text is None:
1479 if text is None:
1474 ui.status(_("reading DAG from stdin\n"))
1480 ui.status(_("reading DAG from stdin\n"))
1475 text = ui.fin.read()
1481 text = ui.fin.read()
1476
1482
1477 cl = repo.changelog
1483 cl = repo.changelog
1478 if len(cl) > 0:
1484 if len(cl) > 0:
1479 raise util.Abort(_('repository is not empty'))
1485 raise util.Abort(_('repository is not empty'))
1480
1486
1481 # determine number of revs in DAG
1487 # determine number of revs in DAG
1482 total = 0
1488 total = 0
1483 for type, data in dagparser.parsedag(text):
1489 for type, data in dagparser.parsedag(text):
1484 if type == 'n':
1490 if type == 'n':
1485 total += 1
1491 total += 1
1486
1492
1487 if mergeable_file:
1493 if mergeable_file:
1488 linesperrev = 2
1494 linesperrev = 2
1489 # make a file with k lines per rev
1495 # make a file with k lines per rev
1490 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1496 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1491 initialmergedlines.append("")
1497 initialmergedlines.append("")
1492
1498
1493 tags = []
1499 tags = []
1494
1500
1495 lock = tr = None
1501 lock = tr = None
1496 try:
1502 try:
1497 lock = repo.lock()
1503 lock = repo.lock()
1498 tr = repo.transaction("builddag")
1504 tr = repo.transaction("builddag")
1499
1505
1500 at = -1
1506 at = -1
1501 atbranch = 'default'
1507 atbranch = 'default'
1502 nodeids = []
1508 nodeids = []
1503 id = 0
1509 id = 0
1504 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1510 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1505 for type, data in dagparser.parsedag(text):
1511 for type, data in dagparser.parsedag(text):
1506 if type == 'n':
1512 if type == 'n':
1507 ui.note('node %s\n' % str(data))
1513 ui.note('node %s\n' % str(data))
1508 id, ps = data
1514 id, ps = data
1509
1515
1510 files = []
1516 files = []
1511 fctxs = {}
1517 fctxs = {}
1512
1518
1513 p2 = None
1519 p2 = None
1514 if mergeable_file:
1520 if mergeable_file:
1515 fn = "mf"
1521 fn = "mf"
1516 p1 = repo[ps[0]]
1522 p1 = repo[ps[0]]
1517 if len(ps) > 1:
1523 if len(ps) > 1:
1518 p2 = repo[ps[1]]
1524 p2 = repo[ps[1]]
1519 pa = p1.ancestor(p2)
1525 pa = p1.ancestor(p2)
1520 base, local, other = [x[fn].data() for x in pa, p1, p2]
1526 base, local, other = [x[fn].data() for x in pa, p1, p2]
1521 m3 = simplemerge.Merge3Text(base, local, other)
1527 m3 = simplemerge.Merge3Text(base, local, other)
1522 ml = [l.strip() for l in m3.merge_lines()]
1528 ml = [l.strip() for l in m3.merge_lines()]
1523 ml.append("")
1529 ml.append("")
1524 elif at > 0:
1530 elif at > 0:
1525 ml = p1[fn].data().split("\n")
1531 ml = p1[fn].data().split("\n")
1526 else:
1532 else:
1527 ml = initialmergedlines
1533 ml = initialmergedlines
1528 ml[id * linesperrev] += " r%i" % id
1534 ml[id * linesperrev] += " r%i" % id
1529 mergedtext = "\n".join(ml)
1535 mergedtext = "\n".join(ml)
1530 files.append(fn)
1536 files.append(fn)
1531 fctxs[fn] = context.memfilectx(fn, mergedtext)
1537 fctxs[fn] = context.memfilectx(fn, mergedtext)
1532
1538
1533 if overwritten_file:
1539 if overwritten_file:
1534 fn = "of"
1540 fn = "of"
1535 files.append(fn)
1541 files.append(fn)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1542 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1537
1543
1538 if new_file:
1544 if new_file:
1539 fn = "nf%i" % id
1545 fn = "nf%i" % id
1540 files.append(fn)
1546 files.append(fn)
1541 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1547 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1542 if len(ps) > 1:
1548 if len(ps) > 1:
1543 if not p2:
1549 if not p2:
1544 p2 = repo[ps[1]]
1550 p2 = repo[ps[1]]
1545 for fn in p2:
1551 for fn in p2:
1546 if fn.startswith("nf"):
1552 if fn.startswith("nf"):
1547 files.append(fn)
1553 files.append(fn)
1548 fctxs[fn] = p2[fn]
1554 fctxs[fn] = p2[fn]
1549
1555
1550 def fctxfn(repo, cx, path):
1556 def fctxfn(repo, cx, path):
1551 return fctxs.get(path)
1557 return fctxs.get(path)
1552
1558
1553 if len(ps) == 0 or ps[0] < 0:
1559 if len(ps) == 0 or ps[0] < 0:
1554 pars = [None, None]
1560 pars = [None, None]
1555 elif len(ps) == 1:
1561 elif len(ps) == 1:
1556 pars = [nodeids[ps[0]], None]
1562 pars = [nodeids[ps[0]], None]
1557 else:
1563 else:
1558 pars = [nodeids[p] for p in ps]
1564 pars = [nodeids[p] for p in ps]
1559 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1565 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1560 date=(id, 0),
1566 date=(id, 0),
1561 user="debugbuilddag",
1567 user="debugbuilddag",
1562 extra={'branch': atbranch})
1568 extra={'branch': atbranch})
1563 nodeid = repo.commitctx(cx)
1569 nodeid = repo.commitctx(cx)
1564 nodeids.append(nodeid)
1570 nodeids.append(nodeid)
1565 at = id
1571 at = id
1566 elif type == 'l':
1572 elif type == 'l':
1567 id, name = data
1573 id, name = data
1568 ui.note('tag %s\n' % name)
1574 ui.note('tag %s\n' % name)
1569 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1575 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1570 elif type == 'a':
1576 elif type == 'a':
1571 ui.note('branch %s\n' % data)
1577 ui.note('branch %s\n' % data)
1572 atbranch = data
1578 atbranch = data
1573 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1579 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1574 tr.close()
1580 tr.close()
1575
1581
1576 if tags:
1582 if tags:
1577 repo.opener.write("localtags", "".join(tags))
1583 repo.opener.write("localtags", "".join(tags))
1578 finally:
1584 finally:
1579 ui.progress(_('building'), None)
1585 ui.progress(_('building'), None)
1580 release(tr, lock)
1586 release(tr, lock)
1581
1587
1582 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1588 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1583 def debugbundle(ui, bundlepath, all=None, **opts):
1589 def debugbundle(ui, bundlepath, all=None, **opts):
1584 """lists the contents of a bundle"""
1590 """lists the contents of a bundle"""
1585 f = url.open(ui, bundlepath)
1591 f = url.open(ui, bundlepath)
1586 try:
1592 try:
1587 gen = changegroup.readbundle(f, bundlepath)
1593 gen = changegroup.readbundle(f, bundlepath)
1588 if all:
1594 if all:
1589 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1595 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1590
1596
1591 def showchunks(named):
1597 def showchunks(named):
1592 ui.write("\n%s\n" % named)
1598 ui.write("\n%s\n" % named)
1593 chain = None
1599 chain = None
1594 while True:
1600 while True:
1595 chunkdata = gen.deltachunk(chain)
1601 chunkdata = gen.deltachunk(chain)
1596 if not chunkdata:
1602 if not chunkdata:
1597 break
1603 break
1598 node = chunkdata['node']
1604 node = chunkdata['node']
1599 p1 = chunkdata['p1']
1605 p1 = chunkdata['p1']
1600 p2 = chunkdata['p2']
1606 p2 = chunkdata['p2']
1601 cs = chunkdata['cs']
1607 cs = chunkdata['cs']
1602 deltabase = chunkdata['deltabase']
1608 deltabase = chunkdata['deltabase']
1603 delta = chunkdata['delta']
1609 delta = chunkdata['delta']
1604 ui.write("%s %s %s %s %s %s\n" %
1610 ui.write("%s %s %s %s %s %s\n" %
1605 (hex(node), hex(p1), hex(p2),
1611 (hex(node), hex(p1), hex(p2),
1606 hex(cs), hex(deltabase), len(delta)))
1612 hex(cs), hex(deltabase), len(delta)))
1607 chain = node
1613 chain = node
1608
1614
1609 chunkdata = gen.changelogheader()
1615 chunkdata = gen.changelogheader()
1610 showchunks("changelog")
1616 showchunks("changelog")
1611 chunkdata = gen.manifestheader()
1617 chunkdata = gen.manifestheader()
1612 showchunks("manifest")
1618 showchunks("manifest")
1613 while True:
1619 while True:
1614 chunkdata = gen.filelogheader()
1620 chunkdata = gen.filelogheader()
1615 if not chunkdata:
1621 if not chunkdata:
1616 break
1622 break
1617 fname = chunkdata['filename']
1623 fname = chunkdata['filename']
1618 showchunks(fname)
1624 showchunks(fname)
1619 else:
1625 else:
1620 chunkdata = gen.changelogheader()
1626 chunkdata = gen.changelogheader()
1621 chain = None
1627 chain = None
1622 while True:
1628 while True:
1623 chunkdata = gen.deltachunk(chain)
1629 chunkdata = gen.deltachunk(chain)
1624 if not chunkdata:
1630 if not chunkdata:
1625 break
1631 break
1626 node = chunkdata['node']
1632 node = chunkdata['node']
1627 ui.write("%s\n" % hex(node))
1633 ui.write("%s\n" % hex(node))
1628 chain = node
1634 chain = node
1629 finally:
1635 finally:
1630 f.close()
1636 f.close()
1631
1637
1632 @command('debugcheckstate', [], '')
1638 @command('debugcheckstate', [], '')
1633 def debugcheckstate(ui, repo):
1639 def debugcheckstate(ui, repo):
1634 """validate the correctness of the current dirstate"""
1640 """validate the correctness of the current dirstate"""
1635 parent1, parent2 = repo.dirstate.parents()
1641 parent1, parent2 = repo.dirstate.parents()
1636 m1 = repo[parent1].manifest()
1642 m1 = repo[parent1].manifest()
1637 m2 = repo[parent2].manifest()
1643 m2 = repo[parent2].manifest()
1638 errors = 0
1644 errors = 0
1639 for f in repo.dirstate:
1645 for f in repo.dirstate:
1640 state = repo.dirstate[f]
1646 state = repo.dirstate[f]
1641 if state in "nr" and f not in m1:
1647 if state in "nr" and f not in m1:
1642 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1648 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1643 errors += 1
1649 errors += 1
1644 if state in "a" and f in m1:
1650 if state in "a" and f in m1:
1645 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1651 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1646 errors += 1
1652 errors += 1
1647 if state in "m" and f not in m1 and f not in m2:
1653 if state in "m" and f not in m1 and f not in m2:
1648 ui.warn(_("%s in state %s, but not in either manifest\n") %
1654 ui.warn(_("%s in state %s, but not in either manifest\n") %
1649 (f, state))
1655 (f, state))
1650 errors += 1
1656 errors += 1
1651 for f in m1:
1657 for f in m1:
1652 state = repo.dirstate[f]
1658 state = repo.dirstate[f]
1653 if state not in "nrm":
1659 if state not in "nrm":
1654 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1660 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1655 errors += 1
1661 errors += 1
1656 if errors:
1662 if errors:
1657 error = _(".hg/dirstate inconsistent with current parent's manifest")
1663 error = _(".hg/dirstate inconsistent with current parent's manifest")
1658 raise util.Abort(error)
1664 raise util.Abort(error)
1659
1665
1660 @command('debugcommands', [], _('[COMMAND]'))
1666 @command('debugcommands', [], _('[COMMAND]'))
1661 def debugcommands(ui, cmd='', *args):
1667 def debugcommands(ui, cmd='', *args):
1662 """list all available commands and options"""
1668 """list all available commands and options"""
1663 for cmd, vals in sorted(table.iteritems()):
1669 for cmd, vals in sorted(table.iteritems()):
1664 cmd = cmd.split('|')[0].strip('^')
1670 cmd = cmd.split('|')[0].strip('^')
1665 opts = ', '.join([i[1] for i in vals[1]])
1671 opts = ', '.join([i[1] for i in vals[1]])
1666 ui.write('%s: %s\n' % (cmd, opts))
1672 ui.write('%s: %s\n' % (cmd, opts))
1667
1673
1668 @command('debugcomplete',
1674 @command('debugcomplete',
1669 [('o', 'options', None, _('show the command options'))],
1675 [('o', 'options', None, _('show the command options'))],
1670 _('[-o] CMD'))
1676 _('[-o] CMD'))
1671 def debugcomplete(ui, cmd='', **opts):
1677 def debugcomplete(ui, cmd='', **opts):
1672 """returns the completion list associated with the given command"""
1678 """returns the completion list associated with the given command"""
1673
1679
1674 if opts.get('options'):
1680 if opts.get('options'):
1675 options = []
1681 options = []
1676 otables = [globalopts]
1682 otables = [globalopts]
1677 if cmd:
1683 if cmd:
1678 aliases, entry = cmdutil.findcmd(cmd, table, False)
1684 aliases, entry = cmdutil.findcmd(cmd, table, False)
1679 otables.append(entry[1])
1685 otables.append(entry[1])
1680 for t in otables:
1686 for t in otables:
1681 for o in t:
1687 for o in t:
1682 if "(DEPRECATED)" in o[3]:
1688 if "(DEPRECATED)" in o[3]:
1683 continue
1689 continue
1684 if o[0]:
1690 if o[0]:
1685 options.append('-%s' % o[0])
1691 options.append('-%s' % o[0])
1686 options.append('--%s' % o[1])
1692 options.append('--%s' % o[1])
1687 ui.write("%s\n" % "\n".join(options))
1693 ui.write("%s\n" % "\n".join(options))
1688 return
1694 return
1689
1695
1690 cmdlist = cmdutil.findpossible(cmd, table)
1696 cmdlist = cmdutil.findpossible(cmd, table)
1691 if ui.verbose:
1697 if ui.verbose:
1692 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1698 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1693 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1699 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1694
1700
1695 @command('debugdag',
1701 @command('debugdag',
1696 [('t', 'tags', None, _('use tags as labels')),
1702 [('t', 'tags', None, _('use tags as labels')),
1697 ('b', 'branches', None, _('annotate with branch names')),
1703 ('b', 'branches', None, _('annotate with branch names')),
1698 ('', 'dots', None, _('use dots for runs')),
1704 ('', 'dots', None, _('use dots for runs')),
1699 ('s', 'spaces', None, _('separate elements by spaces'))],
1705 ('s', 'spaces', None, _('separate elements by spaces'))],
1700 _('[OPTION]... [FILE [REV]...]'))
1706 _('[OPTION]... [FILE [REV]...]'))
1701 def debugdag(ui, repo, file_=None, *revs, **opts):
1707 def debugdag(ui, repo, file_=None, *revs, **opts):
1702 """format the changelog or an index DAG as a concise textual description
1708 """format the changelog or an index DAG as a concise textual description
1703
1709
1704 If you pass a revlog index, the revlog's DAG is emitted. If you list
1710 If you pass a revlog index, the revlog's DAG is emitted. If you list
1705 revision numbers, they get labeled in the output as rN.
1711 revision numbers, they get labeled in the output as rN.
1706
1712
1707 Otherwise, the changelog DAG of the current repo is emitted.
1713 Otherwise, the changelog DAG of the current repo is emitted.
1708 """
1714 """
1709 spaces = opts.get('spaces')
1715 spaces = opts.get('spaces')
1710 dots = opts.get('dots')
1716 dots = opts.get('dots')
1711 if file_:
1717 if file_:
1712 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1718 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1713 revs = set((int(r) for r in revs))
1719 revs = set((int(r) for r in revs))
1714 def events():
1720 def events():
1715 for r in rlog:
1721 for r in rlog:
1716 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1722 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1717 if p != -1)))
1723 if p != -1)))
1718 if r in revs:
1724 if r in revs:
1719 yield 'l', (r, "r%i" % r)
1725 yield 'l', (r, "r%i" % r)
1720 elif repo:
1726 elif repo:
1721 cl = repo.changelog
1727 cl = repo.changelog
1722 tags = opts.get('tags')
1728 tags = opts.get('tags')
1723 branches = opts.get('branches')
1729 branches = opts.get('branches')
1724 if tags:
1730 if tags:
1725 labels = {}
1731 labels = {}
1726 for l, n in repo.tags().items():
1732 for l, n in repo.tags().items():
1727 labels.setdefault(cl.rev(n), []).append(l)
1733 labels.setdefault(cl.rev(n), []).append(l)
1728 def events():
1734 def events():
1729 b = "default"
1735 b = "default"
1730 for r in cl:
1736 for r in cl:
1731 if branches:
1737 if branches:
1732 newb = cl.read(cl.node(r))[5]['branch']
1738 newb = cl.read(cl.node(r))[5]['branch']
1733 if newb != b:
1739 if newb != b:
1734 yield 'a', newb
1740 yield 'a', newb
1735 b = newb
1741 b = newb
1736 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1742 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1737 if p != -1)))
1743 if p != -1)))
1738 if tags:
1744 if tags:
1739 ls = labels.get(r)
1745 ls = labels.get(r)
1740 if ls:
1746 if ls:
1741 for l in ls:
1747 for l in ls:
1742 yield 'l', (r, l)
1748 yield 'l', (r, l)
1743 else:
1749 else:
1744 raise util.Abort(_('need repo for changelog dag'))
1750 raise util.Abort(_('need repo for changelog dag'))
1745
1751
1746 for line in dagparser.dagtextlines(events(),
1752 for line in dagparser.dagtextlines(events(),
1747 addspaces=spaces,
1753 addspaces=spaces,
1748 wraplabels=True,
1754 wraplabels=True,
1749 wrapannotations=True,
1755 wrapannotations=True,
1750 wrapnonlinear=dots,
1756 wrapnonlinear=dots,
1751 usedots=dots,
1757 usedots=dots,
1752 maxlinewidth=70):
1758 maxlinewidth=70):
1753 ui.write(line)
1759 ui.write(line)
1754 ui.write("\n")
1760 ui.write("\n")
1755
1761
1756 @command('debugdata',
1762 @command('debugdata',
1757 [('c', 'changelog', False, _('open changelog')),
1763 [('c', 'changelog', False, _('open changelog')),
1758 ('m', 'manifest', False, _('open manifest'))],
1764 ('m', 'manifest', False, _('open manifest'))],
1759 _('-c|-m|FILE REV'))
1765 _('-c|-m|FILE REV'))
1760 def debugdata(ui, repo, file_, rev = None, **opts):
1766 def debugdata(ui, repo, file_, rev = None, **opts):
1761 """dump the contents of a data file revision"""
1767 """dump the contents of a data file revision"""
1762 if opts.get('changelog') or opts.get('manifest'):
1768 if opts.get('changelog') or opts.get('manifest'):
1763 file_, rev = None, file_
1769 file_, rev = None, file_
1764 elif rev is None:
1770 elif rev is None:
1765 raise error.CommandError('debugdata', _('invalid arguments'))
1771 raise error.CommandError('debugdata', _('invalid arguments'))
1766 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1772 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1767 try:
1773 try:
1768 ui.write(r.revision(r.lookup(rev)))
1774 ui.write(r.revision(r.lookup(rev)))
1769 except KeyError:
1775 except KeyError:
1770 raise util.Abort(_('invalid revision identifier %s') % rev)
1776 raise util.Abort(_('invalid revision identifier %s') % rev)
1771
1777
1772 @command('debugdate',
1778 @command('debugdate',
1773 [('e', 'extended', None, _('try extended date formats'))],
1779 [('e', 'extended', None, _('try extended date formats'))],
1774 _('[-e] DATE [RANGE]'))
1780 _('[-e] DATE [RANGE]'))
1775 def debugdate(ui, date, range=None, **opts):
1781 def debugdate(ui, date, range=None, **opts):
1776 """parse and display a date"""
1782 """parse and display a date"""
1777 if opts["extended"]:
1783 if opts["extended"]:
1778 d = util.parsedate(date, util.extendeddateformats)
1784 d = util.parsedate(date, util.extendeddateformats)
1779 else:
1785 else:
1780 d = util.parsedate(date)
1786 d = util.parsedate(date)
1781 ui.write("internal: %s %s\n" % d)
1787 ui.write("internal: %s %s\n" % d)
1782 ui.write("standard: %s\n" % util.datestr(d))
1788 ui.write("standard: %s\n" % util.datestr(d))
1783 if range:
1789 if range:
1784 m = util.matchdate(range)
1790 m = util.matchdate(range)
1785 ui.write("match: %s\n" % m(d[0]))
1791 ui.write("match: %s\n" % m(d[0]))
1786
1792
1787 @command('debugdiscovery',
1793 @command('debugdiscovery',
1788 [('', 'old', None, _('use old-style discovery')),
1794 [('', 'old', None, _('use old-style discovery')),
1789 ('', 'nonheads', None,
1795 ('', 'nonheads', None,
1790 _('use old-style discovery with non-heads included')),
1796 _('use old-style discovery with non-heads included')),
1791 ] + remoteopts,
1797 ] + remoteopts,
1792 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1798 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1793 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1799 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1794 """runs the changeset discovery protocol in isolation"""
1800 """runs the changeset discovery protocol in isolation"""
1795 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1801 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1796 opts.get('branch'))
1802 opts.get('branch'))
1797 remote = hg.peer(repo, opts, remoteurl)
1803 remote = hg.peer(repo, opts, remoteurl)
1798 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1804 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1799
1805
1800 # make sure tests are repeatable
1806 # make sure tests are repeatable
1801 random.seed(12323)
1807 random.seed(12323)
1802
1808
1803 def doit(localheads, remoteheads, remote=remote):
1809 def doit(localheads, remoteheads, remote=remote):
1804 if opts.get('old'):
1810 if opts.get('old'):
1805 if localheads:
1811 if localheads:
1806 raise util.Abort('cannot use localheads with old style '
1812 raise util.Abort('cannot use localheads with old style '
1807 'discovery')
1813 'discovery')
1808 if not util.safehasattr(remote, 'branches'):
1814 if not util.safehasattr(remote, 'branches'):
1809 # enable in-client legacy support
1815 # enable in-client legacy support
1810 remote = localrepo.locallegacypeer(remote.local())
1816 remote = localrepo.locallegacypeer(remote.local())
1811 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1817 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1812 force=True)
1818 force=True)
1813 common = set(common)
1819 common = set(common)
1814 if not opts.get('nonheads'):
1820 if not opts.get('nonheads'):
1815 ui.write("unpruned common: %s\n" % " ".join([short(n)
1821 ui.write("unpruned common: %s\n" % " ".join([short(n)
1816 for n in common]))
1822 for n in common]))
1817 dag = dagutil.revlogdag(repo.changelog)
1823 dag = dagutil.revlogdag(repo.changelog)
1818 all = dag.ancestorset(dag.internalizeall(common))
1824 all = dag.ancestorset(dag.internalizeall(common))
1819 common = dag.externalizeall(dag.headsetofconnecteds(all))
1825 common = dag.externalizeall(dag.headsetofconnecteds(all))
1820 else:
1826 else:
1821 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1827 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1822 common = set(common)
1828 common = set(common)
1823 rheads = set(hds)
1829 rheads = set(hds)
1824 lheads = set(repo.heads())
1830 lheads = set(repo.heads())
1825 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1831 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1826 if lheads <= common:
1832 if lheads <= common:
1827 ui.write("local is subset\n")
1833 ui.write("local is subset\n")
1828 elif rheads <= common:
1834 elif rheads <= common:
1829 ui.write("remote is subset\n")
1835 ui.write("remote is subset\n")
1830
1836
1831 serverlogs = opts.get('serverlog')
1837 serverlogs = opts.get('serverlog')
1832 if serverlogs:
1838 if serverlogs:
1833 for filename in serverlogs:
1839 for filename in serverlogs:
1834 logfile = open(filename, 'r')
1840 logfile = open(filename, 'r')
1835 try:
1841 try:
1836 line = logfile.readline()
1842 line = logfile.readline()
1837 while line:
1843 while line:
1838 parts = line.strip().split(';')
1844 parts = line.strip().split(';')
1839 op = parts[1]
1845 op = parts[1]
1840 if op == 'cg':
1846 if op == 'cg':
1841 pass
1847 pass
1842 elif op == 'cgss':
1848 elif op == 'cgss':
1843 doit(parts[2].split(' '), parts[3].split(' '))
1849 doit(parts[2].split(' '), parts[3].split(' '))
1844 elif op == 'unb':
1850 elif op == 'unb':
1845 doit(parts[3].split(' '), parts[2].split(' '))
1851 doit(parts[3].split(' '), parts[2].split(' '))
1846 line = logfile.readline()
1852 line = logfile.readline()
1847 finally:
1853 finally:
1848 logfile.close()
1854 logfile.close()
1849
1855
1850 else:
1856 else:
1851 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1857 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1852 opts.get('remote_head'))
1858 opts.get('remote_head'))
1853 localrevs = opts.get('local_head')
1859 localrevs = opts.get('local_head')
1854 doit(localrevs, remoterevs)
1860 doit(localrevs, remoterevs)
1855
1861
1856 @command('debugfileset',
1862 @command('debugfileset',
1857 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1863 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1858 _('[-r REV] FILESPEC'))
1864 _('[-r REV] FILESPEC'))
1859 def debugfileset(ui, repo, expr, **opts):
1865 def debugfileset(ui, repo, expr, **opts):
1860 '''parse and apply a fileset specification'''
1866 '''parse and apply a fileset specification'''
1861 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1867 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1862 if ui.verbose:
1868 if ui.verbose:
1863 tree = fileset.parse(expr)[0]
1869 tree = fileset.parse(expr)[0]
1864 ui.note(tree, "\n")
1870 ui.note(tree, "\n")
1865
1871
1866 for f in fileset.getfileset(ctx, expr):
1872 for f in fileset.getfileset(ctx, expr):
1867 ui.write("%s\n" % f)
1873 ui.write("%s\n" % f)
1868
1874
1869 @command('debugfsinfo', [], _('[PATH]'))
1875 @command('debugfsinfo', [], _('[PATH]'))
1870 def debugfsinfo(ui, path = "."):
1876 def debugfsinfo(ui, path = "."):
1871 """show information detected about current filesystem"""
1877 """show information detected about current filesystem"""
1872 util.writefile('.debugfsinfo', '')
1878 util.writefile('.debugfsinfo', '')
1873 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1879 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1874 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1880 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1875 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1881 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1876 and 'yes' or 'no'))
1882 and 'yes' or 'no'))
1877 os.unlink('.debugfsinfo')
1883 os.unlink('.debugfsinfo')
1878
1884
1879 @command('debuggetbundle',
1885 @command('debuggetbundle',
1880 [('H', 'head', [], _('id of head node'), _('ID')),
1886 [('H', 'head', [], _('id of head node'), _('ID')),
1881 ('C', 'common', [], _('id of common node'), _('ID')),
1887 ('C', 'common', [], _('id of common node'), _('ID')),
1882 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1888 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1883 _('REPO FILE [-H|-C ID]...'))
1889 _('REPO FILE [-H|-C ID]...'))
1884 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1890 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1885 """retrieves a bundle from a repo
1891 """retrieves a bundle from a repo
1886
1892
1887 Every ID must be a full-length hex node id string. Saves the bundle to the
1893 Every ID must be a full-length hex node id string. Saves the bundle to the
1888 given file.
1894 given file.
1889 """
1895 """
1890 repo = hg.peer(ui, opts, repopath)
1896 repo = hg.peer(ui, opts, repopath)
1891 if not repo.capable('getbundle'):
1897 if not repo.capable('getbundle'):
1892 raise util.Abort("getbundle() not supported by target repository")
1898 raise util.Abort("getbundle() not supported by target repository")
1893 args = {}
1899 args = {}
1894 if common:
1900 if common:
1895 args['common'] = [bin(s) for s in common]
1901 args['common'] = [bin(s) for s in common]
1896 if head:
1902 if head:
1897 args['heads'] = [bin(s) for s in head]
1903 args['heads'] = [bin(s) for s in head]
1898 bundle = repo.getbundle('debug', **args)
1904 bundle = repo.getbundle('debug', **args)
1899
1905
1900 bundletype = opts.get('type', 'bzip2').lower()
1906 bundletype = opts.get('type', 'bzip2').lower()
1901 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1902 bundletype = btypes.get(bundletype)
1908 bundletype = btypes.get(bundletype)
1903 if bundletype not in changegroup.bundletypes:
1909 if bundletype not in changegroup.bundletypes:
1904 raise util.Abort(_('unknown bundle type specified with --type'))
1910 raise util.Abort(_('unknown bundle type specified with --type'))
1905 changegroup.writebundle(bundle, bundlepath, bundletype)
1911 changegroup.writebundle(bundle, bundlepath, bundletype)
1906
1912
1907 @command('debugignore', [], '')
1913 @command('debugignore', [], '')
1908 def debugignore(ui, repo, *values, **opts):
1914 def debugignore(ui, repo, *values, **opts):
1909 """display the combined ignore pattern"""
1915 """display the combined ignore pattern"""
1910 ignore = repo.dirstate._ignore
1916 ignore = repo.dirstate._ignore
1911 includepat = getattr(ignore, 'includepat', None)
1917 includepat = getattr(ignore, 'includepat', None)
1912 if includepat is not None:
1918 if includepat is not None:
1913 ui.write("%s\n" % includepat)
1919 ui.write("%s\n" % includepat)
1914 else:
1920 else:
1915 raise util.Abort(_("no ignore patterns found"))
1921 raise util.Abort(_("no ignore patterns found"))
1916
1922
1917 @command('debugindex',
1923 @command('debugindex',
1918 [('c', 'changelog', False, _('open changelog')),
1924 [('c', 'changelog', False, _('open changelog')),
1919 ('m', 'manifest', False, _('open manifest')),
1925 ('m', 'manifest', False, _('open manifest')),
1920 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1926 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1921 _('[-f FORMAT] -c|-m|FILE'))
1927 _('[-f FORMAT] -c|-m|FILE'))
1922 def debugindex(ui, repo, file_ = None, **opts):
1928 def debugindex(ui, repo, file_ = None, **opts):
1923 """dump the contents of an index file"""
1929 """dump the contents of an index file"""
1924 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1930 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1925 format = opts.get('format', 0)
1931 format = opts.get('format', 0)
1926 if format not in (0, 1):
1932 if format not in (0, 1):
1927 raise util.Abort(_("unknown format %d") % format)
1933 raise util.Abort(_("unknown format %d") % format)
1928
1934
1929 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1935 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1930 if generaldelta:
1936 if generaldelta:
1931 basehdr = ' delta'
1937 basehdr = ' delta'
1932 else:
1938 else:
1933 basehdr = ' base'
1939 basehdr = ' base'
1934
1940
1935 if format == 0:
1941 if format == 0:
1936 ui.write(" rev offset length " + basehdr + " linkrev"
1942 ui.write(" rev offset length " + basehdr + " linkrev"
1937 " nodeid p1 p2\n")
1943 " nodeid p1 p2\n")
1938 elif format == 1:
1944 elif format == 1:
1939 ui.write(" rev flag offset length"
1945 ui.write(" rev flag offset length"
1940 " size " + basehdr + " link p1 p2"
1946 " size " + basehdr + " link p1 p2"
1941 " nodeid\n")
1947 " nodeid\n")
1942
1948
1943 for i in r:
1949 for i in r:
1944 node = r.node(i)
1950 node = r.node(i)
1945 if generaldelta:
1951 if generaldelta:
1946 base = r.deltaparent(i)
1952 base = r.deltaparent(i)
1947 else:
1953 else:
1948 base = r.chainbase(i)
1954 base = r.chainbase(i)
1949 if format == 0:
1955 if format == 0:
1950 try:
1956 try:
1951 pp = r.parents(node)
1957 pp = r.parents(node)
1952 except Exception:
1958 except Exception:
1953 pp = [nullid, nullid]
1959 pp = [nullid, nullid]
1954 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1960 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1955 i, r.start(i), r.length(i), base, r.linkrev(i),
1961 i, r.start(i), r.length(i), base, r.linkrev(i),
1956 short(node), short(pp[0]), short(pp[1])))
1962 short(node), short(pp[0]), short(pp[1])))
1957 elif format == 1:
1963 elif format == 1:
1958 pr = r.parentrevs(i)
1964 pr = r.parentrevs(i)
1959 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1965 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1960 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1966 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1961 base, r.linkrev(i), pr[0], pr[1], short(node)))
1967 base, r.linkrev(i), pr[0], pr[1], short(node)))
1962
1968
1963 @command('debugindexdot', [], _('FILE'))
1969 @command('debugindexdot', [], _('FILE'))
1964 def debugindexdot(ui, repo, file_):
1970 def debugindexdot(ui, repo, file_):
1965 """dump an index DAG as a graphviz dot file"""
1971 """dump an index DAG as a graphviz dot file"""
1966 r = None
1972 r = None
1967 if repo:
1973 if repo:
1968 filelog = repo.file(file_)
1974 filelog = repo.file(file_)
1969 if len(filelog):
1975 if len(filelog):
1970 r = filelog
1976 r = filelog
1971 if not r:
1977 if not r:
1972 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1978 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1973 ui.write("digraph G {\n")
1979 ui.write("digraph G {\n")
1974 for i in r:
1980 for i in r:
1975 node = r.node(i)
1981 node = r.node(i)
1976 pp = r.parents(node)
1982 pp = r.parents(node)
1977 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1983 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1978 if pp[1] != nullid:
1984 if pp[1] != nullid:
1979 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1985 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1980 ui.write("}\n")
1986 ui.write("}\n")
1981
1987
1982 @command('debuginstall', [], '')
1988 @command('debuginstall', [], '')
1983 def debuginstall(ui):
1989 def debuginstall(ui):
1984 '''test Mercurial installation
1990 '''test Mercurial installation
1985
1991
1986 Returns 0 on success.
1992 Returns 0 on success.
1987 '''
1993 '''
1988
1994
1989 def writetemp(contents):
1995 def writetemp(contents):
1990 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1996 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1991 f = os.fdopen(fd, "wb")
1997 f = os.fdopen(fd, "wb")
1992 f.write(contents)
1998 f.write(contents)
1993 f.close()
1999 f.close()
1994 return name
2000 return name
1995
2001
1996 problems = 0
2002 problems = 0
1997
2003
1998 # encoding
2004 # encoding
1999 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2005 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2000 try:
2006 try:
2001 encoding.fromlocal("test")
2007 encoding.fromlocal("test")
2002 except util.Abort, inst:
2008 except util.Abort, inst:
2003 ui.write(" %s\n" % inst)
2009 ui.write(" %s\n" % inst)
2004 ui.write(_(" (check that your locale is properly set)\n"))
2010 ui.write(_(" (check that your locale is properly set)\n"))
2005 problems += 1
2011 problems += 1
2006
2012
2007 # Python lib
2013 # Python lib
2008 ui.status(_("checking Python lib (%s)...\n")
2014 ui.status(_("checking Python lib (%s)...\n")
2009 % os.path.dirname(os.__file__))
2015 % os.path.dirname(os.__file__))
2010
2016
2011 # compiled modules
2017 # compiled modules
2012 ui.status(_("checking installed modules (%s)...\n")
2018 ui.status(_("checking installed modules (%s)...\n")
2013 % os.path.dirname(__file__))
2019 % os.path.dirname(__file__))
2014 try:
2020 try:
2015 import bdiff, mpatch, base85, osutil
2021 import bdiff, mpatch, base85, osutil
2016 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2022 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2017 except Exception, inst:
2023 except Exception, inst:
2018 ui.write(" %s\n" % inst)
2024 ui.write(" %s\n" % inst)
2019 ui.write(_(" One or more extensions could not be found"))
2025 ui.write(_(" One or more extensions could not be found"))
2020 ui.write(_(" (check that you compiled the extensions)\n"))
2026 ui.write(_(" (check that you compiled the extensions)\n"))
2021 problems += 1
2027 problems += 1
2022
2028
2023 # templates
2029 # templates
2024 import templater
2030 import templater
2025 p = templater.templatepath()
2031 p = templater.templatepath()
2026 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2032 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2027 try:
2033 try:
2028 templater.templater(templater.templatepath("map-cmdline.default"))
2034 templater.templater(templater.templatepath("map-cmdline.default"))
2029 except Exception, inst:
2035 except Exception, inst:
2030 ui.write(" %s\n" % inst)
2036 ui.write(" %s\n" % inst)
2031 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2037 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2032 problems += 1
2038 problems += 1
2033
2039
2034 # editor
2040 # editor
2035 ui.status(_("checking commit editor...\n"))
2041 ui.status(_("checking commit editor...\n"))
2036 editor = ui.geteditor()
2042 editor = ui.geteditor()
2037 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2043 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2038 if not cmdpath:
2044 if not cmdpath:
2039 if editor == 'vi':
2045 if editor == 'vi':
2040 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2046 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2041 ui.write(_(" (specify a commit editor in your configuration"
2047 ui.write(_(" (specify a commit editor in your configuration"
2042 " file)\n"))
2048 " file)\n"))
2043 else:
2049 else:
2044 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2050 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2045 ui.write(_(" (specify a commit editor in your configuration"
2051 ui.write(_(" (specify a commit editor in your configuration"
2046 " file)\n"))
2052 " file)\n"))
2047 problems += 1
2053 problems += 1
2048
2054
2049 # check username
2055 # check username
2050 ui.status(_("checking username...\n"))
2056 ui.status(_("checking username...\n"))
2051 try:
2057 try:
2052 ui.username()
2058 ui.username()
2053 except util.Abort, e:
2059 except util.Abort, e:
2054 ui.write(" %s\n" % e)
2060 ui.write(" %s\n" % e)
2055 ui.write(_(" (specify a username in your configuration file)\n"))
2061 ui.write(_(" (specify a username in your configuration file)\n"))
2056 problems += 1
2062 problems += 1
2057
2063
2058 if not problems:
2064 if not problems:
2059 ui.status(_("no problems detected\n"))
2065 ui.status(_("no problems detected\n"))
2060 else:
2066 else:
2061 ui.write(_("%s problems detected,"
2067 ui.write(_("%s problems detected,"
2062 " please check your install!\n") % problems)
2068 " please check your install!\n") % problems)
2063
2069
2064 return problems
2070 return problems
2065
2071
2066 @command('debugknown', [], _('REPO ID...'))
2072 @command('debugknown', [], _('REPO ID...'))
2067 def debugknown(ui, repopath, *ids, **opts):
2073 def debugknown(ui, repopath, *ids, **opts):
2068 """test whether node ids are known to a repo
2074 """test whether node ids are known to a repo
2069
2075
2070 Every ID must be a full-length hex node id string. Returns a list of 0s
2076 Every ID must be a full-length hex node id string. Returns a list of 0s
2071 and 1s indicating unknown/known.
2077 and 1s indicating unknown/known.
2072 """
2078 """
2073 repo = hg.peer(ui, opts, repopath)
2079 repo = hg.peer(ui, opts, repopath)
2074 if not repo.capable('known'):
2080 if not repo.capable('known'):
2075 raise util.Abort("known() not supported by target repository")
2081 raise util.Abort("known() not supported by target repository")
2076 flags = repo.known([bin(s) for s in ids])
2082 flags = repo.known([bin(s) for s in ids])
2077 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2083 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2078
2084
2079 @command('debugobsolete', [] + commitopts2,
2085 @command('debugobsolete', [] + commitopts2,
2080 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2086 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2081 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2087 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2082 """create arbitrary obsolete marker"""
2088 """create arbitrary obsolete marker"""
2083 def parsenodeid(s):
2089 def parsenodeid(s):
2084 try:
2090 try:
2085 # We do not use revsingle/revrange functions here to accept
2091 # We do not use revsingle/revrange functions here to accept
2086 # arbitrary node identifiers, possibly not present in the
2092 # arbitrary node identifiers, possibly not present in the
2087 # local repository.
2093 # local repository.
2088 n = bin(s)
2094 n = bin(s)
2089 if len(n) != len(nullid):
2095 if len(n) != len(nullid):
2090 raise TypeError()
2096 raise TypeError()
2091 return n
2097 return n
2092 except TypeError:
2098 except TypeError:
2093 raise util.Abort('changeset references must be full hexadecimal '
2099 raise util.Abort('changeset references must be full hexadecimal '
2094 'node identifiers')
2100 'node identifiers')
2095
2101
2096 if precursor is not None:
2102 if precursor is not None:
2097 metadata = {}
2103 metadata = {}
2098 if 'date' in opts:
2104 if 'date' in opts:
2099 metadata['date'] = opts['date']
2105 metadata['date'] = opts['date']
2100 metadata['user'] = opts['user'] or ui.username()
2106 metadata['user'] = opts['user'] or ui.username()
2101 succs = tuple(parsenodeid(succ) for succ in successors)
2107 succs = tuple(parsenodeid(succ) for succ in successors)
2102 l = repo.lock()
2108 l = repo.lock()
2103 try:
2109 try:
2104 tr = repo.transaction('debugobsolete')
2110 tr = repo.transaction('debugobsolete')
2105 try:
2111 try:
2106 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2112 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2107 metadata)
2113 metadata)
2108 tr.close()
2114 tr.close()
2109 finally:
2115 finally:
2110 tr.release()
2116 tr.release()
2111 finally:
2117 finally:
2112 l.release()
2118 l.release()
2113 else:
2119 else:
2114 for m in obsolete.allmarkers(repo):
2120 for m in obsolete.allmarkers(repo):
2115 ui.write(hex(m.precnode()))
2121 ui.write(hex(m.precnode()))
2116 for repl in m.succnodes():
2122 for repl in m.succnodes():
2117 ui.write(' ')
2123 ui.write(' ')
2118 ui.write(hex(repl))
2124 ui.write(hex(repl))
2119 ui.write(' %X ' % m._data[2])
2125 ui.write(' %X ' % m._data[2])
2120 ui.write(m.metadata())
2126 ui.write(m.metadata())
2121 ui.write('\n')
2127 ui.write('\n')
2122
2128
2123 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2129 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2124 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2130 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2125 '''access the pushkey key/value protocol
2131 '''access the pushkey key/value protocol
2126
2132
2127 With two args, list the keys in the given namespace.
2133 With two args, list the keys in the given namespace.
2128
2134
2129 With five args, set a key to new if it currently is set to old.
2135 With five args, set a key to new if it currently is set to old.
2130 Reports success or failure.
2136 Reports success or failure.
2131 '''
2137 '''
2132
2138
2133 target = hg.peer(ui, {}, repopath)
2139 target = hg.peer(ui, {}, repopath)
2134 if keyinfo:
2140 if keyinfo:
2135 key, old, new = keyinfo
2141 key, old, new = keyinfo
2136 r = target.pushkey(namespace, key, old, new)
2142 r = target.pushkey(namespace, key, old, new)
2137 ui.status(str(r) + '\n')
2143 ui.status(str(r) + '\n')
2138 return not r
2144 return not r
2139 else:
2145 else:
2140 for k, v in target.listkeys(namespace).iteritems():
2146 for k, v in target.listkeys(namespace).iteritems():
2141 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2147 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2142 v.encode('string-escape')))
2148 v.encode('string-escape')))
2143
2149
2144 @command('debugpvec', [], _('A B'))
2150 @command('debugpvec', [], _('A B'))
2145 def debugpvec(ui, repo, a, b=None):
2151 def debugpvec(ui, repo, a, b=None):
2146 ca = scmutil.revsingle(repo, a)
2152 ca = scmutil.revsingle(repo, a)
2147 cb = scmutil.revsingle(repo, b)
2153 cb = scmutil.revsingle(repo, b)
2148 pa = pvec.ctxpvec(ca)
2154 pa = pvec.ctxpvec(ca)
2149 pb = pvec.ctxpvec(cb)
2155 pb = pvec.ctxpvec(cb)
2150 if pa == pb:
2156 if pa == pb:
2151 rel = "="
2157 rel = "="
2152 elif pa > pb:
2158 elif pa > pb:
2153 rel = ">"
2159 rel = ">"
2154 elif pa < pb:
2160 elif pa < pb:
2155 rel = "<"
2161 rel = "<"
2156 elif pa | pb:
2162 elif pa | pb:
2157 rel = "|"
2163 rel = "|"
2158 ui.write(_("a: %s\n") % pa)
2164 ui.write(_("a: %s\n") % pa)
2159 ui.write(_("b: %s\n") % pb)
2165 ui.write(_("b: %s\n") % pb)
2160 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2166 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2161 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2167 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2162 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2168 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2163 pa.distance(pb), rel))
2169 pa.distance(pb), rel))
2164
2170
2165 @command('debugrebuildstate',
2171 @command('debugrebuildstate',
2166 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2172 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2167 _('[-r REV] [REV]'))
2173 _('[-r REV] [REV]'))
2168 def debugrebuildstate(ui, repo, rev="tip"):
2174 def debugrebuildstate(ui, repo, rev="tip"):
2169 """rebuild the dirstate as it would look like for the given revision"""
2175 """rebuild the dirstate as it would look like for the given revision"""
2170 ctx = scmutil.revsingle(repo, rev)
2176 ctx = scmutil.revsingle(repo, rev)
2171 wlock = repo.wlock()
2177 wlock = repo.wlock()
2172 try:
2178 try:
2173 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2179 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2174 finally:
2180 finally:
2175 wlock.release()
2181 wlock.release()
2176
2182
2177 @command('debugrename',
2183 @command('debugrename',
2178 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2184 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2179 _('[-r REV] FILE'))
2185 _('[-r REV] FILE'))
2180 def debugrename(ui, repo, file1, *pats, **opts):
2186 def debugrename(ui, repo, file1, *pats, **opts):
2181 """dump rename information"""
2187 """dump rename information"""
2182
2188
2183 ctx = scmutil.revsingle(repo, opts.get('rev'))
2189 ctx = scmutil.revsingle(repo, opts.get('rev'))
2184 m = scmutil.match(ctx, (file1,) + pats, opts)
2190 m = scmutil.match(ctx, (file1,) + pats, opts)
2185 for abs in ctx.walk(m):
2191 for abs in ctx.walk(m):
2186 fctx = ctx[abs]
2192 fctx = ctx[abs]
2187 o = fctx.filelog().renamed(fctx.filenode())
2193 o = fctx.filelog().renamed(fctx.filenode())
2188 rel = m.rel(abs)
2194 rel = m.rel(abs)
2189 if o:
2195 if o:
2190 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2196 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2191 else:
2197 else:
2192 ui.write(_("%s not renamed\n") % rel)
2198 ui.write(_("%s not renamed\n") % rel)
2193
2199
2194 @command('debugrevlog',
2200 @command('debugrevlog',
2195 [('c', 'changelog', False, _('open changelog')),
2201 [('c', 'changelog', False, _('open changelog')),
2196 ('m', 'manifest', False, _('open manifest')),
2202 ('m', 'manifest', False, _('open manifest')),
2197 ('d', 'dump', False, _('dump index data'))],
2203 ('d', 'dump', False, _('dump index data'))],
2198 _('-c|-m|FILE'))
2204 _('-c|-m|FILE'))
2199 def debugrevlog(ui, repo, file_ = None, **opts):
2205 def debugrevlog(ui, repo, file_ = None, **opts):
2200 """show data and statistics about a revlog"""
2206 """show data and statistics about a revlog"""
2201 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2207 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2202
2208
2203 if opts.get("dump"):
2209 if opts.get("dump"):
2204 numrevs = len(r)
2210 numrevs = len(r)
2205 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2211 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2206 " rawsize totalsize compression heads\n")
2212 " rawsize totalsize compression heads\n")
2207 ts = 0
2213 ts = 0
2208 heads = set()
2214 heads = set()
2209 for rev in xrange(numrevs):
2215 for rev in xrange(numrevs):
2210 dbase = r.deltaparent(rev)
2216 dbase = r.deltaparent(rev)
2211 if dbase == -1:
2217 if dbase == -1:
2212 dbase = rev
2218 dbase = rev
2213 cbase = r.chainbase(rev)
2219 cbase = r.chainbase(rev)
2214 p1, p2 = r.parentrevs(rev)
2220 p1, p2 = r.parentrevs(rev)
2215 rs = r.rawsize(rev)
2221 rs = r.rawsize(rev)
2216 ts = ts + rs
2222 ts = ts + rs
2217 heads -= set(r.parentrevs(rev))
2223 heads -= set(r.parentrevs(rev))
2218 heads.add(rev)
2224 heads.add(rev)
2219 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2225 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2220 (rev, p1, p2, r.start(rev), r.end(rev),
2226 (rev, p1, p2, r.start(rev), r.end(rev),
2221 r.start(dbase), r.start(cbase),
2227 r.start(dbase), r.start(cbase),
2222 r.start(p1), r.start(p2),
2228 r.start(p1), r.start(p2),
2223 rs, ts, ts / r.end(rev), len(heads)))
2229 rs, ts, ts / r.end(rev), len(heads)))
2224 return 0
2230 return 0
2225
2231
2226 v = r.version
2232 v = r.version
2227 format = v & 0xFFFF
2233 format = v & 0xFFFF
2228 flags = []
2234 flags = []
2229 gdelta = False
2235 gdelta = False
2230 if v & revlog.REVLOGNGINLINEDATA:
2236 if v & revlog.REVLOGNGINLINEDATA:
2231 flags.append('inline')
2237 flags.append('inline')
2232 if v & revlog.REVLOGGENERALDELTA:
2238 if v & revlog.REVLOGGENERALDELTA:
2233 gdelta = True
2239 gdelta = True
2234 flags.append('generaldelta')
2240 flags.append('generaldelta')
2235 if not flags:
2241 if not flags:
2236 flags = ['(none)']
2242 flags = ['(none)']
2237
2243
2238 nummerges = 0
2244 nummerges = 0
2239 numfull = 0
2245 numfull = 0
2240 numprev = 0
2246 numprev = 0
2241 nump1 = 0
2247 nump1 = 0
2242 nump2 = 0
2248 nump2 = 0
2243 numother = 0
2249 numother = 0
2244 nump1prev = 0
2250 nump1prev = 0
2245 nump2prev = 0
2251 nump2prev = 0
2246 chainlengths = []
2252 chainlengths = []
2247
2253
2248 datasize = [None, 0, 0L]
2254 datasize = [None, 0, 0L]
2249 fullsize = [None, 0, 0L]
2255 fullsize = [None, 0, 0L]
2250 deltasize = [None, 0, 0L]
2256 deltasize = [None, 0, 0L]
2251
2257
2252 def addsize(size, l):
2258 def addsize(size, l):
2253 if l[0] is None or size < l[0]:
2259 if l[0] is None or size < l[0]:
2254 l[0] = size
2260 l[0] = size
2255 if size > l[1]:
2261 if size > l[1]:
2256 l[1] = size
2262 l[1] = size
2257 l[2] += size
2263 l[2] += size
2258
2264
2259 numrevs = len(r)
2265 numrevs = len(r)
2260 for rev in xrange(numrevs):
2266 for rev in xrange(numrevs):
2261 p1, p2 = r.parentrevs(rev)
2267 p1, p2 = r.parentrevs(rev)
2262 delta = r.deltaparent(rev)
2268 delta = r.deltaparent(rev)
2263 if format > 0:
2269 if format > 0:
2264 addsize(r.rawsize(rev), datasize)
2270 addsize(r.rawsize(rev), datasize)
2265 if p2 != nullrev:
2271 if p2 != nullrev:
2266 nummerges += 1
2272 nummerges += 1
2267 size = r.length(rev)
2273 size = r.length(rev)
2268 if delta == nullrev:
2274 if delta == nullrev:
2269 chainlengths.append(0)
2275 chainlengths.append(0)
2270 numfull += 1
2276 numfull += 1
2271 addsize(size, fullsize)
2277 addsize(size, fullsize)
2272 else:
2278 else:
2273 chainlengths.append(chainlengths[delta] + 1)
2279 chainlengths.append(chainlengths[delta] + 1)
2274 addsize(size, deltasize)
2280 addsize(size, deltasize)
2275 if delta == rev - 1:
2281 if delta == rev - 1:
2276 numprev += 1
2282 numprev += 1
2277 if delta == p1:
2283 if delta == p1:
2278 nump1prev += 1
2284 nump1prev += 1
2279 elif delta == p2:
2285 elif delta == p2:
2280 nump2prev += 1
2286 nump2prev += 1
2281 elif delta == p1:
2287 elif delta == p1:
2282 nump1 += 1
2288 nump1 += 1
2283 elif delta == p2:
2289 elif delta == p2:
2284 nump2 += 1
2290 nump2 += 1
2285 elif delta != nullrev:
2291 elif delta != nullrev:
2286 numother += 1
2292 numother += 1
2287
2293
2288 # Adjust size min value for empty cases
2294 # Adjust size min value for empty cases
2289 for size in (datasize, fullsize, deltasize):
2295 for size in (datasize, fullsize, deltasize):
2290 if size[0] is None:
2296 if size[0] is None:
2291 size[0] = 0
2297 size[0] = 0
2292
2298
2293 numdeltas = numrevs - numfull
2299 numdeltas = numrevs - numfull
2294 numoprev = numprev - nump1prev - nump2prev
2300 numoprev = numprev - nump1prev - nump2prev
2295 totalrawsize = datasize[2]
2301 totalrawsize = datasize[2]
2296 datasize[2] /= numrevs
2302 datasize[2] /= numrevs
2297 fulltotal = fullsize[2]
2303 fulltotal = fullsize[2]
2298 fullsize[2] /= numfull
2304 fullsize[2] /= numfull
2299 deltatotal = deltasize[2]
2305 deltatotal = deltasize[2]
2300 if numrevs - numfull > 0:
2306 if numrevs - numfull > 0:
2301 deltasize[2] /= numrevs - numfull
2307 deltasize[2] /= numrevs - numfull
2302 totalsize = fulltotal + deltatotal
2308 totalsize = fulltotal + deltatotal
2303 avgchainlen = sum(chainlengths) / numrevs
2309 avgchainlen = sum(chainlengths) / numrevs
2304 compratio = totalrawsize / totalsize
2310 compratio = totalrawsize / totalsize
2305
2311
2306 basedfmtstr = '%%%dd\n'
2312 basedfmtstr = '%%%dd\n'
2307 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2313 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2308
2314
2309 def dfmtstr(max):
2315 def dfmtstr(max):
2310 return basedfmtstr % len(str(max))
2316 return basedfmtstr % len(str(max))
2311 def pcfmtstr(max, padding=0):
2317 def pcfmtstr(max, padding=0):
2312 return basepcfmtstr % (len(str(max)), ' ' * padding)
2318 return basepcfmtstr % (len(str(max)), ' ' * padding)
2313
2319
2314 def pcfmt(value, total):
2320 def pcfmt(value, total):
2315 return (value, 100 * float(value) / total)
2321 return (value, 100 * float(value) / total)
2316
2322
2317 ui.write('format : %d\n' % format)
2323 ui.write('format : %d\n' % format)
2318 ui.write('flags : %s\n' % ', '.join(flags))
2324 ui.write('flags : %s\n' % ', '.join(flags))
2319
2325
2320 ui.write('\n')
2326 ui.write('\n')
2321 fmt = pcfmtstr(totalsize)
2327 fmt = pcfmtstr(totalsize)
2322 fmt2 = dfmtstr(totalsize)
2328 fmt2 = dfmtstr(totalsize)
2323 ui.write('revisions : ' + fmt2 % numrevs)
2329 ui.write('revisions : ' + fmt2 % numrevs)
2324 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2330 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2325 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2331 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2326 ui.write('revisions : ' + fmt2 % numrevs)
2332 ui.write('revisions : ' + fmt2 % numrevs)
2327 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2333 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2328 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2334 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2329 ui.write('revision size : ' + fmt2 % totalsize)
2335 ui.write('revision size : ' + fmt2 % totalsize)
2330 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2336 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2331 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2337 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2332
2338
2333 ui.write('\n')
2339 ui.write('\n')
2334 fmt = dfmtstr(max(avgchainlen, compratio))
2340 fmt = dfmtstr(max(avgchainlen, compratio))
2335 ui.write('avg chain length : ' + fmt % avgchainlen)
2341 ui.write('avg chain length : ' + fmt % avgchainlen)
2336 ui.write('compression ratio : ' + fmt % compratio)
2342 ui.write('compression ratio : ' + fmt % compratio)
2337
2343
2338 if format > 0:
2344 if format > 0:
2339 ui.write('\n')
2345 ui.write('\n')
2340 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2346 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2341 % tuple(datasize))
2347 % tuple(datasize))
2342 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2348 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2343 % tuple(fullsize))
2349 % tuple(fullsize))
2344 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2350 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2345 % tuple(deltasize))
2351 % tuple(deltasize))
2346
2352
2347 if numdeltas > 0:
2353 if numdeltas > 0:
2348 ui.write('\n')
2354 ui.write('\n')
2349 fmt = pcfmtstr(numdeltas)
2355 fmt = pcfmtstr(numdeltas)
2350 fmt2 = pcfmtstr(numdeltas, 4)
2356 fmt2 = pcfmtstr(numdeltas, 4)
2351 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2357 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2352 if numprev > 0:
2358 if numprev > 0:
2353 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2359 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2354 numprev))
2360 numprev))
2355 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2361 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2356 numprev))
2362 numprev))
2357 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2363 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2358 numprev))
2364 numprev))
2359 if gdelta:
2365 if gdelta:
2360 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2366 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2361 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2367 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2362 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2368 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2363 numdeltas))
2369 numdeltas))
2364
2370
2365 @command('debugrevspec', [], ('REVSPEC'))
2371 @command('debugrevspec', [], ('REVSPEC'))
2366 def debugrevspec(ui, repo, expr):
2372 def debugrevspec(ui, repo, expr):
2367 """parse and apply a revision specification
2373 """parse and apply a revision specification
2368
2374
2369 Use --verbose to print the parsed tree before and after aliases
2375 Use --verbose to print the parsed tree before and after aliases
2370 expansion.
2376 expansion.
2371 """
2377 """
2372 if ui.verbose:
2378 if ui.verbose:
2373 tree = revset.parse(expr)[0]
2379 tree = revset.parse(expr)[0]
2374 ui.note(revset.prettyformat(tree), "\n")
2380 ui.note(revset.prettyformat(tree), "\n")
2375 newtree = revset.findaliases(ui, tree)
2381 newtree = revset.findaliases(ui, tree)
2376 if newtree != tree:
2382 if newtree != tree:
2377 ui.note(revset.prettyformat(newtree), "\n")
2383 ui.note(revset.prettyformat(newtree), "\n")
2378 func = revset.match(ui, expr)
2384 func = revset.match(ui, expr)
2379 for c in func(repo, range(len(repo))):
2385 for c in func(repo, range(len(repo))):
2380 ui.write("%s\n" % c)
2386 ui.write("%s\n" % c)
2381
2387
2382 @command('debugsetparents', [], _('REV1 [REV2]'))
2388 @command('debugsetparents', [], _('REV1 [REV2]'))
2383 def debugsetparents(ui, repo, rev1, rev2=None):
2389 def debugsetparents(ui, repo, rev1, rev2=None):
2384 """manually set the parents of the current working directory
2390 """manually set the parents of the current working directory
2385
2391
2386 This is useful for writing repository conversion tools, but should
2392 This is useful for writing repository conversion tools, but should
2387 be used with care.
2393 be used with care.
2388
2394
2389 Returns 0 on success.
2395 Returns 0 on success.
2390 """
2396 """
2391
2397
2392 r1 = scmutil.revsingle(repo, rev1).node()
2398 r1 = scmutil.revsingle(repo, rev1).node()
2393 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2399 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2394
2400
2395 wlock = repo.wlock()
2401 wlock = repo.wlock()
2396 try:
2402 try:
2397 repo.setparents(r1, r2)
2403 repo.setparents(r1, r2)
2398 finally:
2404 finally:
2399 wlock.release()
2405 wlock.release()
2400
2406
2401 @command('debugstate',
2407 @command('debugstate',
2402 [('', 'nodates', None, _('do not display the saved mtime')),
2408 [('', 'nodates', None, _('do not display the saved mtime')),
2403 ('', 'datesort', None, _('sort by saved mtime'))],
2409 ('', 'datesort', None, _('sort by saved mtime'))],
2404 _('[OPTION]...'))
2410 _('[OPTION]...'))
2405 def debugstate(ui, repo, nodates=None, datesort=None):
2411 def debugstate(ui, repo, nodates=None, datesort=None):
2406 """show the contents of the current dirstate"""
2412 """show the contents of the current dirstate"""
2407 timestr = ""
2413 timestr = ""
2408 showdate = not nodates
2414 showdate = not nodates
2409 if datesort:
2415 if datesort:
2410 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2416 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2411 else:
2417 else:
2412 keyfunc = None # sort by filename
2418 keyfunc = None # sort by filename
2413 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2419 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2414 if showdate:
2420 if showdate:
2415 if ent[3] == -1:
2421 if ent[3] == -1:
2416 # Pad or slice to locale representation
2422 # Pad or slice to locale representation
2417 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2423 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2418 time.localtime(0)))
2424 time.localtime(0)))
2419 timestr = 'unset'
2425 timestr = 'unset'
2420 timestr = (timestr[:locale_len] +
2426 timestr = (timestr[:locale_len] +
2421 ' ' * (locale_len - len(timestr)))
2427 ' ' * (locale_len - len(timestr)))
2422 else:
2428 else:
2423 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2429 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2424 time.localtime(ent[3]))
2430 time.localtime(ent[3]))
2425 if ent[1] & 020000:
2431 if ent[1] & 020000:
2426 mode = 'lnk'
2432 mode = 'lnk'
2427 else:
2433 else:
2428 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2434 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2429 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2435 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2430 for f in repo.dirstate.copies():
2436 for f in repo.dirstate.copies():
2431 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2437 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2432
2438
2433 @command('debugsub',
2439 @command('debugsub',
2434 [('r', 'rev', '',
2440 [('r', 'rev', '',
2435 _('revision to check'), _('REV'))],
2441 _('revision to check'), _('REV'))],
2436 _('[-r REV] [REV]'))
2442 _('[-r REV] [REV]'))
2437 def debugsub(ui, repo, rev=None):
2443 def debugsub(ui, repo, rev=None):
2438 ctx = scmutil.revsingle(repo, rev, None)
2444 ctx = scmutil.revsingle(repo, rev, None)
2439 for k, v in sorted(ctx.substate.items()):
2445 for k, v in sorted(ctx.substate.items()):
2440 ui.write('path %s\n' % k)
2446 ui.write('path %s\n' % k)
2441 ui.write(' source %s\n' % v[0])
2447 ui.write(' source %s\n' % v[0])
2442 ui.write(' revision %s\n' % v[1])
2448 ui.write(' revision %s\n' % v[1])
2443
2449
2444 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2450 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2445 def debugwalk(ui, repo, *pats, **opts):
2451 def debugwalk(ui, repo, *pats, **opts):
2446 """show how files match on given patterns"""
2452 """show how files match on given patterns"""
2447 m = scmutil.match(repo[None], pats, opts)
2453 m = scmutil.match(repo[None], pats, opts)
2448 items = list(repo.walk(m))
2454 items = list(repo.walk(m))
2449 if not items:
2455 if not items:
2450 return
2456 return
2451 f = lambda fn: fn
2457 f = lambda fn: fn
2452 if ui.configbool('ui', 'slash') and os.sep != '/':
2458 if ui.configbool('ui', 'slash') and os.sep != '/':
2453 f = lambda fn: util.normpath(fn)
2459 f = lambda fn: util.normpath(fn)
2454 fmt = 'f %%-%ds %%-%ds %%s' % (
2460 fmt = 'f %%-%ds %%-%ds %%s' % (
2455 max([len(abs) for abs in items]),
2461 max([len(abs) for abs in items]),
2456 max([len(m.rel(abs)) for abs in items]))
2462 max([len(m.rel(abs)) for abs in items]))
2457 for abs in items:
2463 for abs in items:
2458 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2464 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2459 ui.write("%s\n" % line.rstrip())
2465 ui.write("%s\n" % line.rstrip())
2460
2466
2461 @command('debugwireargs',
2467 @command('debugwireargs',
2462 [('', 'three', '', 'three'),
2468 [('', 'three', '', 'three'),
2463 ('', 'four', '', 'four'),
2469 ('', 'four', '', 'four'),
2464 ('', 'five', '', 'five'),
2470 ('', 'five', '', 'five'),
2465 ] + remoteopts,
2471 ] + remoteopts,
2466 _('REPO [OPTIONS]... [ONE [TWO]]'))
2472 _('REPO [OPTIONS]... [ONE [TWO]]'))
2467 def debugwireargs(ui, repopath, *vals, **opts):
2473 def debugwireargs(ui, repopath, *vals, **opts):
2468 repo = hg.peer(ui, opts, repopath)
2474 repo = hg.peer(ui, opts, repopath)
2469 for opt in remoteopts:
2475 for opt in remoteopts:
2470 del opts[opt[1]]
2476 del opts[opt[1]]
2471 args = {}
2477 args = {}
2472 for k, v in opts.iteritems():
2478 for k, v in opts.iteritems():
2473 if v:
2479 if v:
2474 args[k] = v
2480 args[k] = v
2475 # run twice to check that we don't mess up the stream for the next command
2481 # run twice to check that we don't mess up the stream for the next command
2476 res1 = repo.debugwireargs(*vals, **args)
2482 res1 = repo.debugwireargs(*vals, **args)
2477 res2 = repo.debugwireargs(*vals, **args)
2483 res2 = repo.debugwireargs(*vals, **args)
2478 ui.write("%s\n" % res1)
2484 ui.write("%s\n" % res1)
2479 if res1 != res2:
2485 if res1 != res2:
2480 ui.warn("%s\n" % res2)
2486 ui.warn("%s\n" % res2)
2481
2487
2482 @command('^diff',
2488 @command('^diff',
2483 [('r', 'rev', [], _('revision'), _('REV')),
2489 [('r', 'rev', [], _('revision'), _('REV')),
2484 ('c', 'change', '', _('change made by revision'), _('REV'))
2490 ('c', 'change', '', _('change made by revision'), _('REV'))
2485 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2491 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2486 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2492 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2487 def diff(ui, repo, *pats, **opts):
2493 def diff(ui, repo, *pats, **opts):
2488 """diff repository (or selected files)
2494 """diff repository (or selected files)
2489
2495
2490 Show differences between revisions for the specified files.
2496 Show differences between revisions for the specified files.
2491
2497
2492 Differences between files are shown using the unified diff format.
2498 Differences between files are shown using the unified diff format.
2493
2499
2494 .. note::
2500 .. note::
2495 diff may generate unexpected results for merges, as it will
2501 diff may generate unexpected results for merges, as it will
2496 default to comparing against the working directory's first
2502 default to comparing against the working directory's first
2497 parent changeset if no revisions are specified.
2503 parent changeset if no revisions are specified.
2498
2504
2499 When two revision arguments are given, then changes are shown
2505 When two revision arguments are given, then changes are shown
2500 between those revisions. If only one revision is specified then
2506 between those revisions. If only one revision is specified then
2501 that revision is compared to the working directory, and, when no
2507 that revision is compared to the working directory, and, when no
2502 revisions are specified, the working directory files are compared
2508 revisions are specified, the working directory files are compared
2503 to its parent.
2509 to its parent.
2504
2510
2505 Alternatively you can specify -c/--change with a revision to see
2511 Alternatively you can specify -c/--change with a revision to see
2506 the changes in that changeset relative to its first parent.
2512 the changes in that changeset relative to its first parent.
2507
2513
2508 Without the -a/--text option, diff will avoid generating diffs of
2514 Without the -a/--text option, diff will avoid generating diffs of
2509 files it detects as binary. With -a, diff will generate a diff
2515 files it detects as binary. With -a, diff will generate a diff
2510 anyway, probably with undesirable results.
2516 anyway, probably with undesirable results.
2511
2517
2512 Use the -g/--git option to generate diffs in the git extended diff
2518 Use the -g/--git option to generate diffs in the git extended diff
2513 format. For more information, read :hg:`help diffs`.
2519 format. For more information, read :hg:`help diffs`.
2514
2520
2515 .. container:: verbose
2521 .. container:: verbose
2516
2522
2517 Examples:
2523 Examples:
2518
2524
2519 - compare a file in the current working directory to its parent::
2525 - compare a file in the current working directory to its parent::
2520
2526
2521 hg diff foo.c
2527 hg diff foo.c
2522
2528
2523 - compare two historical versions of a directory, with rename info::
2529 - compare two historical versions of a directory, with rename info::
2524
2530
2525 hg diff --git -r 1.0:1.2 lib/
2531 hg diff --git -r 1.0:1.2 lib/
2526
2532
2527 - get change stats relative to the last change on some date::
2533 - get change stats relative to the last change on some date::
2528
2534
2529 hg diff --stat -r "date('may 2')"
2535 hg diff --stat -r "date('may 2')"
2530
2536
2531 - diff all newly-added files that contain a keyword::
2537 - diff all newly-added files that contain a keyword::
2532
2538
2533 hg diff "set:added() and grep(GNU)"
2539 hg diff "set:added() and grep(GNU)"
2534
2540
2535 - compare a revision and its parents::
2541 - compare a revision and its parents::
2536
2542
2537 hg diff -c 9353 # compare against first parent
2543 hg diff -c 9353 # compare against first parent
2538 hg diff -r 9353^:9353 # same using revset syntax
2544 hg diff -r 9353^:9353 # same using revset syntax
2539 hg diff -r 9353^2:9353 # compare against the second parent
2545 hg diff -r 9353^2:9353 # compare against the second parent
2540
2546
2541 Returns 0 on success.
2547 Returns 0 on success.
2542 """
2548 """
2543
2549
2544 revs = opts.get('rev')
2550 revs = opts.get('rev')
2545 change = opts.get('change')
2551 change = opts.get('change')
2546 stat = opts.get('stat')
2552 stat = opts.get('stat')
2547 reverse = opts.get('reverse')
2553 reverse = opts.get('reverse')
2548
2554
2549 if revs and change:
2555 if revs and change:
2550 msg = _('cannot specify --rev and --change at the same time')
2556 msg = _('cannot specify --rev and --change at the same time')
2551 raise util.Abort(msg)
2557 raise util.Abort(msg)
2552 elif change:
2558 elif change:
2553 node2 = scmutil.revsingle(repo, change, None).node()
2559 node2 = scmutil.revsingle(repo, change, None).node()
2554 node1 = repo[node2].p1().node()
2560 node1 = repo[node2].p1().node()
2555 else:
2561 else:
2556 node1, node2 = scmutil.revpair(repo, revs)
2562 node1, node2 = scmutil.revpair(repo, revs)
2557
2563
2558 if reverse:
2564 if reverse:
2559 node1, node2 = node2, node1
2565 node1, node2 = node2, node1
2560
2566
2561 diffopts = patch.diffopts(ui, opts)
2567 diffopts = patch.diffopts(ui, opts)
2562 m = scmutil.match(repo[node2], pats, opts)
2568 m = scmutil.match(repo[node2], pats, opts)
2563 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2569 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2564 listsubrepos=opts.get('subrepos'))
2570 listsubrepos=opts.get('subrepos'))
2565
2571
2566 @command('^export',
2572 @command('^export',
2567 [('o', 'output', '',
2573 [('o', 'output', '',
2568 _('print output to file with formatted name'), _('FORMAT')),
2574 _('print output to file with formatted name'), _('FORMAT')),
2569 ('', 'switch-parent', None, _('diff against the second parent')),
2575 ('', 'switch-parent', None, _('diff against the second parent')),
2570 ('r', 'rev', [], _('revisions to export'), _('REV')),
2576 ('r', 'rev', [], _('revisions to export'), _('REV')),
2571 ] + diffopts,
2577 ] + diffopts,
2572 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2578 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2573 def export(ui, repo, *changesets, **opts):
2579 def export(ui, repo, *changesets, **opts):
2574 """dump the header and diffs for one or more changesets
2580 """dump the header and diffs for one or more changesets
2575
2581
2576 Print the changeset header and diffs for one or more revisions.
2582 Print the changeset header and diffs for one or more revisions.
2577
2583
2578 The information shown in the changeset header is: author, date,
2584 The information shown in the changeset header is: author, date,
2579 branch name (if non-default), changeset hash, parent(s) and commit
2585 branch name (if non-default), changeset hash, parent(s) and commit
2580 comment.
2586 comment.
2581
2587
2582 .. note::
2588 .. note::
2583 export may generate unexpected diff output for merge
2589 export may generate unexpected diff output for merge
2584 changesets, as it will compare the merge changeset against its
2590 changesets, as it will compare the merge changeset against its
2585 first parent only.
2591 first parent only.
2586
2592
2587 Output may be to a file, in which case the name of the file is
2593 Output may be to a file, in which case the name of the file is
2588 given using a format string. The formatting rules are as follows:
2594 given using a format string. The formatting rules are as follows:
2589
2595
2590 :``%%``: literal "%" character
2596 :``%%``: literal "%" character
2591 :``%H``: changeset hash (40 hexadecimal digits)
2597 :``%H``: changeset hash (40 hexadecimal digits)
2592 :``%N``: number of patches being generated
2598 :``%N``: number of patches being generated
2593 :``%R``: changeset revision number
2599 :``%R``: changeset revision number
2594 :``%b``: basename of the exporting repository
2600 :``%b``: basename of the exporting repository
2595 :``%h``: short-form changeset hash (12 hexadecimal digits)
2601 :``%h``: short-form changeset hash (12 hexadecimal digits)
2596 :``%m``: first line of the commit message (only alphanumeric characters)
2602 :``%m``: first line of the commit message (only alphanumeric characters)
2597 :``%n``: zero-padded sequence number, starting at 1
2603 :``%n``: zero-padded sequence number, starting at 1
2598 :``%r``: zero-padded changeset revision number
2604 :``%r``: zero-padded changeset revision number
2599
2605
2600 Without the -a/--text option, export will avoid generating diffs
2606 Without the -a/--text option, export will avoid generating diffs
2601 of files it detects as binary. With -a, export will generate a
2607 of files it detects as binary. With -a, export will generate a
2602 diff anyway, probably with undesirable results.
2608 diff anyway, probably with undesirable results.
2603
2609
2604 Use the -g/--git option to generate diffs in the git extended diff
2610 Use the -g/--git option to generate diffs in the git extended diff
2605 format. See :hg:`help diffs` for more information.
2611 format. See :hg:`help diffs` for more information.
2606
2612
2607 With the --switch-parent option, the diff will be against the
2613 With the --switch-parent option, the diff will be against the
2608 second parent. It can be useful to review a merge.
2614 second parent. It can be useful to review a merge.
2609
2615
2610 .. container:: verbose
2616 .. container:: verbose
2611
2617
2612 Examples:
2618 Examples:
2613
2619
2614 - use export and import to transplant a bugfix to the current
2620 - use export and import to transplant a bugfix to the current
2615 branch::
2621 branch::
2616
2622
2617 hg export -r 9353 | hg import -
2623 hg export -r 9353 | hg import -
2618
2624
2619 - export all the changesets between two revisions to a file with
2625 - export all the changesets between two revisions to a file with
2620 rename information::
2626 rename information::
2621
2627
2622 hg export --git -r 123:150 > changes.txt
2628 hg export --git -r 123:150 > changes.txt
2623
2629
2624 - split outgoing changes into a series of patches with
2630 - split outgoing changes into a series of patches with
2625 descriptive names::
2631 descriptive names::
2626
2632
2627 hg export -r "outgoing()" -o "%n-%m.patch"
2633 hg export -r "outgoing()" -o "%n-%m.patch"
2628
2634
2629 Returns 0 on success.
2635 Returns 0 on success.
2630 """
2636 """
2631 changesets += tuple(opts.get('rev', []))
2637 changesets += tuple(opts.get('rev', []))
2632 revs = scmutil.revrange(repo, changesets)
2638 revs = scmutil.revrange(repo, changesets)
2633 if not revs:
2639 if not revs:
2634 raise util.Abort(_("export requires at least one changeset"))
2640 raise util.Abort(_("export requires at least one changeset"))
2635 if len(revs) > 1:
2641 if len(revs) > 1:
2636 ui.note(_('exporting patches:\n'))
2642 ui.note(_('exporting patches:\n'))
2637 else:
2643 else:
2638 ui.note(_('exporting patch:\n'))
2644 ui.note(_('exporting patch:\n'))
2639 cmdutil.export(repo, revs, template=opts.get('output'),
2645 cmdutil.export(repo, revs, template=opts.get('output'),
2640 switch_parent=opts.get('switch_parent'),
2646 switch_parent=opts.get('switch_parent'),
2641 opts=patch.diffopts(ui, opts))
2647 opts=patch.diffopts(ui, opts))
2642
2648
2643 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2649 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2644 def forget(ui, repo, *pats, **opts):
2650 def forget(ui, repo, *pats, **opts):
2645 """forget the specified files on the next commit
2651 """forget the specified files on the next commit
2646
2652
2647 Mark the specified files so they will no longer be tracked
2653 Mark the specified files so they will no longer be tracked
2648 after the next commit.
2654 after the next commit.
2649
2655
2650 This only removes files from the current branch, not from the
2656 This only removes files from the current branch, not from the
2651 entire project history, and it does not delete them from the
2657 entire project history, and it does not delete them from the
2652 working directory.
2658 working directory.
2653
2659
2654 To undo a forget before the next commit, see :hg:`add`.
2660 To undo a forget before the next commit, see :hg:`add`.
2655
2661
2656 .. container:: verbose
2662 .. container:: verbose
2657
2663
2658 Examples:
2664 Examples:
2659
2665
2660 - forget newly-added binary files::
2666 - forget newly-added binary files::
2661
2667
2662 hg forget "set:added() and binary()"
2668 hg forget "set:added() and binary()"
2663
2669
2664 - forget files that would be excluded by .hgignore::
2670 - forget files that would be excluded by .hgignore::
2665
2671
2666 hg forget "set:hgignore()"
2672 hg forget "set:hgignore()"
2667
2673
2668 Returns 0 on success.
2674 Returns 0 on success.
2669 """
2675 """
2670
2676
2671 if not pats:
2677 if not pats:
2672 raise util.Abort(_('no files specified'))
2678 raise util.Abort(_('no files specified'))
2673
2679
2674 m = scmutil.match(repo[None], pats, opts)
2680 m = scmutil.match(repo[None], pats, opts)
2675 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2681 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2676 return rejected and 1 or 0
2682 return rejected and 1 or 0
2677
2683
2678 @command(
2684 @command(
2679 'graft',
2685 'graft',
2680 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2686 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2681 ('c', 'continue', False, _('resume interrupted graft')),
2687 ('c', 'continue', False, _('resume interrupted graft')),
2682 ('e', 'edit', False, _('invoke editor on commit messages')),
2688 ('e', 'edit', False, _('invoke editor on commit messages')),
2683 ('', 'log', None, _('append graft info to log message')),
2689 ('', 'log', None, _('append graft info to log message')),
2684 ('D', 'currentdate', False,
2690 ('D', 'currentdate', False,
2685 _('record the current date as commit date')),
2691 _('record the current date as commit date')),
2686 ('U', 'currentuser', False,
2692 ('U', 'currentuser', False,
2687 _('record the current user as committer'), _('DATE'))]
2693 _('record the current user as committer'), _('DATE'))]
2688 + commitopts2 + mergetoolopts + dryrunopts,
2694 + commitopts2 + mergetoolopts + dryrunopts,
2689 _('[OPTION]... [-r] REV...'))
2695 _('[OPTION]... [-r] REV...'))
2690 def graft(ui, repo, *revs, **opts):
2696 def graft(ui, repo, *revs, **opts):
2691 '''copy changes from other branches onto the current branch
2697 '''copy changes from other branches onto the current branch
2692
2698
2693 This command uses Mercurial's merge logic to copy individual
2699 This command uses Mercurial's merge logic to copy individual
2694 changes from other branches without merging branches in the
2700 changes from other branches without merging branches in the
2695 history graph. This is sometimes known as 'backporting' or
2701 history graph. This is sometimes known as 'backporting' or
2696 'cherry-picking'. By default, graft will copy user, date, and
2702 'cherry-picking'. By default, graft will copy user, date, and
2697 description from the source changesets.
2703 description from the source changesets.
2698
2704
2699 Changesets that are ancestors of the current revision, that have
2705 Changesets that are ancestors of the current revision, that have
2700 already been grafted, or that are merges will be skipped.
2706 already been grafted, or that are merges will be skipped.
2701
2707
2702 If --log is specified, log messages will have a comment appended
2708 If --log is specified, log messages will have a comment appended
2703 of the form::
2709 of the form::
2704
2710
2705 (grafted from CHANGESETHASH)
2711 (grafted from CHANGESETHASH)
2706
2712
2707 If a graft merge results in conflicts, the graft process is
2713 If a graft merge results in conflicts, the graft process is
2708 interrupted so that the current merge can be manually resolved.
2714 interrupted so that the current merge can be manually resolved.
2709 Once all conflicts are addressed, the graft process can be
2715 Once all conflicts are addressed, the graft process can be
2710 continued with the -c/--continue option.
2716 continued with the -c/--continue option.
2711
2717
2712 .. note::
2718 .. note::
2713 The -c/--continue option does not reapply earlier options.
2719 The -c/--continue option does not reapply earlier options.
2714
2720
2715 .. container:: verbose
2721 .. container:: verbose
2716
2722
2717 Examples:
2723 Examples:
2718
2724
2719 - copy a single change to the stable branch and edit its description::
2725 - copy a single change to the stable branch and edit its description::
2720
2726
2721 hg update stable
2727 hg update stable
2722 hg graft --edit 9393
2728 hg graft --edit 9393
2723
2729
2724 - graft a range of changesets with one exception, updating dates::
2730 - graft a range of changesets with one exception, updating dates::
2725
2731
2726 hg graft -D "2085::2093 and not 2091"
2732 hg graft -D "2085::2093 and not 2091"
2727
2733
2728 - continue a graft after resolving conflicts::
2734 - continue a graft after resolving conflicts::
2729
2735
2730 hg graft -c
2736 hg graft -c
2731
2737
2732 - show the source of a grafted changeset::
2738 - show the source of a grafted changeset::
2733
2739
2734 hg log --debug -r tip
2740 hg log --debug -r tip
2735
2741
2736 Returns 0 on successful completion.
2742 Returns 0 on successful completion.
2737 '''
2743 '''
2738
2744
2739 revs = list(revs)
2745 revs = list(revs)
2740 revs.extend(opts['rev'])
2746 revs.extend(opts['rev'])
2741
2747
2742 if not opts.get('user') and opts.get('currentuser'):
2748 if not opts.get('user') and opts.get('currentuser'):
2743 opts['user'] = ui.username()
2749 opts['user'] = ui.username()
2744 if not opts.get('date') and opts.get('currentdate'):
2750 if not opts.get('date') and opts.get('currentdate'):
2745 opts['date'] = "%d %d" % util.makedate()
2751 opts['date'] = "%d %d" % util.makedate()
2746
2752
2747 editor = None
2753 editor = None
2748 if opts.get('edit'):
2754 if opts.get('edit'):
2749 editor = cmdutil.commitforceeditor
2755 editor = cmdutil.commitforceeditor
2750
2756
2751 cont = False
2757 cont = False
2752 if opts['continue']:
2758 if opts['continue']:
2753 cont = True
2759 cont = True
2754 if revs:
2760 if revs:
2755 raise util.Abort(_("can't specify --continue and revisions"))
2761 raise util.Abort(_("can't specify --continue and revisions"))
2756 # read in unfinished revisions
2762 # read in unfinished revisions
2757 try:
2763 try:
2758 nodes = repo.opener.read('graftstate').splitlines()
2764 nodes = repo.opener.read('graftstate').splitlines()
2759 revs = [repo[node].rev() for node in nodes]
2765 revs = [repo[node].rev() for node in nodes]
2760 except IOError, inst:
2766 except IOError, inst:
2761 if inst.errno != errno.ENOENT:
2767 if inst.errno != errno.ENOENT:
2762 raise
2768 raise
2763 raise util.Abort(_("no graft state found, can't continue"))
2769 raise util.Abort(_("no graft state found, can't continue"))
2764 else:
2770 else:
2765 cmdutil.bailifchanged(repo)
2771 cmdutil.bailifchanged(repo)
2766 if not revs:
2772 if not revs:
2767 raise util.Abort(_('no revisions specified'))
2773 raise util.Abort(_('no revisions specified'))
2768 revs = scmutil.revrange(repo, revs)
2774 revs = scmutil.revrange(repo, revs)
2769
2775
2770 # check for merges
2776 # check for merges
2771 for rev in repo.revs('%ld and merge()', revs):
2777 for rev in repo.revs('%ld and merge()', revs):
2772 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2778 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2773 revs.remove(rev)
2779 revs.remove(rev)
2774 if not revs:
2780 if not revs:
2775 return -1
2781 return -1
2776
2782
2777 # check for ancestors of dest branch
2783 # check for ancestors of dest branch
2778 for rev in repo.revs('::. and %ld', revs):
2784 for rev in repo.revs('::. and %ld', revs):
2779 ui.warn(_('skipping ancestor revision %s\n') % rev)
2785 ui.warn(_('skipping ancestor revision %s\n') % rev)
2780 revs.remove(rev)
2786 revs.remove(rev)
2781 if not revs:
2787 if not revs:
2782 return -1
2788 return -1
2783
2789
2784 # analyze revs for earlier grafts
2790 # analyze revs for earlier grafts
2785 ids = {}
2791 ids = {}
2786 for ctx in repo.set("%ld", revs):
2792 for ctx in repo.set("%ld", revs):
2787 ids[ctx.hex()] = ctx.rev()
2793 ids[ctx.hex()] = ctx.rev()
2788 n = ctx.extra().get('source')
2794 n = ctx.extra().get('source')
2789 if n:
2795 if n:
2790 ids[n] = ctx.rev()
2796 ids[n] = ctx.rev()
2791
2797
2792 # check ancestors for earlier grafts
2798 # check ancestors for earlier grafts
2793 ui.debug('scanning for duplicate grafts\n')
2799 ui.debug('scanning for duplicate grafts\n')
2794 for ctx in repo.set("::. - ::%ld", revs):
2800 for ctx in repo.set("::. - ::%ld", revs):
2795 n = ctx.extra().get('source')
2801 n = ctx.extra().get('source')
2796 if n in ids:
2802 if n in ids:
2797 r = repo[n].rev()
2803 r = repo[n].rev()
2798 if r in revs:
2804 if r in revs:
2799 ui.warn(_('skipping already grafted revision %s\n') % r)
2805 ui.warn(_('skipping already grafted revision %s\n') % r)
2800 revs.remove(r)
2806 revs.remove(r)
2801 elif ids[n] in revs:
2807 elif ids[n] in revs:
2802 ui.warn(_('skipping already grafted revision %s '
2808 ui.warn(_('skipping already grafted revision %s '
2803 '(same origin %d)\n') % (ids[n], r))
2809 '(same origin %d)\n') % (ids[n], r))
2804 revs.remove(ids[n])
2810 revs.remove(ids[n])
2805 elif ctx.hex() in ids:
2811 elif ctx.hex() in ids:
2806 r = ids[ctx.hex()]
2812 r = ids[ctx.hex()]
2807 ui.warn(_('skipping already grafted revision %s '
2813 ui.warn(_('skipping already grafted revision %s '
2808 '(was grafted from %d)\n') % (r, ctx.rev()))
2814 '(was grafted from %d)\n') % (r, ctx.rev()))
2809 revs.remove(r)
2815 revs.remove(r)
2810 if not revs:
2816 if not revs:
2811 return -1
2817 return -1
2812
2818
2813 wlock = repo.wlock()
2819 wlock = repo.wlock()
2814 try:
2820 try:
2815 for pos, ctx in enumerate(repo.set("%ld", revs)):
2821 for pos, ctx in enumerate(repo.set("%ld", revs)):
2816 current = repo['.']
2822 current = repo['.']
2817
2823
2818 ui.status(_('grafting revision %s\n') % ctx.rev())
2824 ui.status(_('grafting revision %s\n') % ctx.rev())
2819 if opts.get('dry_run'):
2825 if opts.get('dry_run'):
2820 continue
2826 continue
2821
2827
2822 # we don't merge the first commit when continuing
2828 # we don't merge the first commit when continuing
2823 if not cont:
2829 if not cont:
2824 # perform the graft merge with p1(rev) as 'ancestor'
2830 # perform the graft merge with p1(rev) as 'ancestor'
2825 try:
2831 try:
2826 # ui.forcemerge is an internal variable, do not document
2832 # ui.forcemerge is an internal variable, do not document
2827 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2833 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2828 stats = mergemod.update(repo, ctx.node(), True, True, False,
2834 stats = mergemod.update(repo, ctx.node(), True, True, False,
2829 ctx.p1().node())
2835 ctx.p1().node())
2830 finally:
2836 finally:
2831 repo.ui.setconfig('ui', 'forcemerge', '')
2837 repo.ui.setconfig('ui', 'forcemerge', '')
2832 # report any conflicts
2838 # report any conflicts
2833 if stats and stats[3] > 0:
2839 if stats and stats[3] > 0:
2834 # write out state for --continue
2840 # write out state for --continue
2835 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2841 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2836 repo.opener.write('graftstate', ''.join(nodelines))
2842 repo.opener.write('graftstate', ''.join(nodelines))
2837 raise util.Abort(
2843 raise util.Abort(
2838 _("unresolved conflicts, can't continue"),
2844 _("unresolved conflicts, can't continue"),
2839 hint=_('use hg resolve and hg graft --continue'))
2845 hint=_('use hg resolve and hg graft --continue'))
2840 else:
2846 else:
2841 cont = False
2847 cont = False
2842
2848
2843 # drop the second merge parent
2849 # drop the second merge parent
2844 repo.setparents(current.node(), nullid)
2850 repo.setparents(current.node(), nullid)
2845 repo.dirstate.write()
2851 repo.dirstate.write()
2846 # fix up dirstate for copies and renames
2852 # fix up dirstate for copies and renames
2847 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2853 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2848
2854
2849 # commit
2855 # commit
2850 source = ctx.extra().get('source')
2856 source = ctx.extra().get('source')
2851 if not source:
2857 if not source:
2852 source = ctx.hex()
2858 source = ctx.hex()
2853 extra = {'source': source}
2859 extra = {'source': source}
2854 user = ctx.user()
2860 user = ctx.user()
2855 if opts.get('user'):
2861 if opts.get('user'):
2856 user = opts['user']
2862 user = opts['user']
2857 date = ctx.date()
2863 date = ctx.date()
2858 if opts.get('date'):
2864 if opts.get('date'):
2859 date = opts['date']
2865 date = opts['date']
2860 message = ctx.description()
2866 message = ctx.description()
2861 if opts.get('log'):
2867 if opts.get('log'):
2862 message += '\n(grafted from %s)' % ctx.hex()
2868 message += '\n(grafted from %s)' % ctx.hex()
2863 node = repo.commit(text=message, user=user,
2869 node = repo.commit(text=message, user=user,
2864 date=date, extra=extra, editor=editor)
2870 date=date, extra=extra, editor=editor)
2865 if node is None:
2871 if node is None:
2866 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2872 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2867 finally:
2873 finally:
2868 wlock.release()
2874 wlock.release()
2869
2875
2870 # remove state when we complete successfully
2876 # remove state when we complete successfully
2871 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2877 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2872 util.unlinkpath(repo.join('graftstate'))
2878 util.unlinkpath(repo.join('graftstate'))
2873
2879
2874 return 0
2880 return 0
2875
2881
2876 @command('grep',
2882 @command('grep',
2877 [('0', 'print0', None, _('end fields with NUL')),
2883 [('0', 'print0', None, _('end fields with NUL')),
2878 ('', 'all', None, _('print all revisions that match')),
2884 ('', 'all', None, _('print all revisions that match')),
2879 ('a', 'text', None, _('treat all files as text')),
2885 ('a', 'text', None, _('treat all files as text')),
2880 ('f', 'follow', None,
2886 ('f', 'follow', None,
2881 _('follow changeset history,'
2887 _('follow changeset history,'
2882 ' or file history across copies and renames')),
2888 ' or file history across copies and renames')),
2883 ('i', 'ignore-case', None, _('ignore case when matching')),
2889 ('i', 'ignore-case', None, _('ignore case when matching')),
2884 ('l', 'files-with-matches', None,
2890 ('l', 'files-with-matches', None,
2885 _('print only filenames and revisions that match')),
2891 _('print only filenames and revisions that match')),
2886 ('n', 'line-number', None, _('print matching line numbers')),
2892 ('n', 'line-number', None, _('print matching line numbers')),
2887 ('r', 'rev', [],
2893 ('r', 'rev', [],
2888 _('only search files changed within revision range'), _('REV')),
2894 _('only search files changed within revision range'), _('REV')),
2889 ('u', 'user', None, _('list the author (long with -v)')),
2895 ('u', 'user', None, _('list the author (long with -v)')),
2890 ('d', 'date', None, _('list the date (short with -q)')),
2896 ('d', 'date', None, _('list the date (short with -q)')),
2891 ] + walkopts,
2897 ] + walkopts,
2892 _('[OPTION]... PATTERN [FILE]...'))
2898 _('[OPTION]... PATTERN [FILE]...'))
2893 def grep(ui, repo, pattern, *pats, **opts):
2899 def grep(ui, repo, pattern, *pats, **opts):
2894 """search for a pattern in specified files and revisions
2900 """search for a pattern in specified files and revisions
2895
2901
2896 Search revisions of files for a regular expression.
2902 Search revisions of files for a regular expression.
2897
2903
2898 This command behaves differently than Unix grep. It only accepts
2904 This command behaves differently than Unix grep. It only accepts
2899 Python/Perl regexps. It searches repository history, not the
2905 Python/Perl regexps. It searches repository history, not the
2900 working directory. It always prints the revision number in which a
2906 working directory. It always prints the revision number in which a
2901 match appears.
2907 match appears.
2902
2908
2903 By default, grep only prints output for the first revision of a
2909 By default, grep only prints output for the first revision of a
2904 file in which it finds a match. To get it to print every revision
2910 file in which it finds a match. To get it to print every revision
2905 that contains a change in match status ("-" for a match that
2911 that contains a change in match status ("-" for a match that
2906 becomes a non-match, or "+" for a non-match that becomes a match),
2912 becomes a non-match, or "+" for a non-match that becomes a match),
2907 use the --all flag.
2913 use the --all flag.
2908
2914
2909 Returns 0 if a match is found, 1 otherwise.
2915 Returns 0 if a match is found, 1 otherwise.
2910 """
2916 """
2911 reflags = re.M
2917 reflags = re.M
2912 if opts.get('ignore_case'):
2918 if opts.get('ignore_case'):
2913 reflags |= re.I
2919 reflags |= re.I
2914 try:
2920 try:
2915 regexp = re.compile(pattern, reflags)
2921 regexp = re.compile(pattern, reflags)
2916 except re.error, inst:
2922 except re.error, inst:
2917 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2923 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2918 return 1
2924 return 1
2919 sep, eol = ':', '\n'
2925 sep, eol = ':', '\n'
2920 if opts.get('print0'):
2926 if opts.get('print0'):
2921 sep = eol = '\0'
2927 sep = eol = '\0'
2922
2928
2923 getfile = util.lrucachefunc(repo.file)
2929 getfile = util.lrucachefunc(repo.file)
2924
2930
2925 def matchlines(body):
2931 def matchlines(body):
2926 begin = 0
2932 begin = 0
2927 linenum = 0
2933 linenum = 0
2928 while True:
2934 while True:
2929 match = regexp.search(body, begin)
2935 match = regexp.search(body, begin)
2930 if not match:
2936 if not match:
2931 break
2937 break
2932 mstart, mend = match.span()
2938 mstart, mend = match.span()
2933 linenum += body.count('\n', begin, mstart) + 1
2939 linenum += body.count('\n', begin, mstart) + 1
2934 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2940 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2935 begin = body.find('\n', mend) + 1 or len(body) + 1
2941 begin = body.find('\n', mend) + 1 or len(body) + 1
2936 lend = begin - 1
2942 lend = begin - 1
2937 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2943 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2938
2944
2939 class linestate(object):
2945 class linestate(object):
2940 def __init__(self, line, linenum, colstart, colend):
2946 def __init__(self, line, linenum, colstart, colend):
2941 self.line = line
2947 self.line = line
2942 self.linenum = linenum
2948 self.linenum = linenum
2943 self.colstart = colstart
2949 self.colstart = colstart
2944 self.colend = colend
2950 self.colend = colend
2945
2951
2946 def __hash__(self):
2952 def __hash__(self):
2947 return hash((self.linenum, self.line))
2953 return hash((self.linenum, self.line))
2948
2954
2949 def __eq__(self, other):
2955 def __eq__(self, other):
2950 return self.line == other.line
2956 return self.line == other.line
2951
2957
2952 matches = {}
2958 matches = {}
2953 copies = {}
2959 copies = {}
2954 def grepbody(fn, rev, body):
2960 def grepbody(fn, rev, body):
2955 matches[rev].setdefault(fn, [])
2961 matches[rev].setdefault(fn, [])
2956 m = matches[rev][fn]
2962 m = matches[rev][fn]
2957 for lnum, cstart, cend, line in matchlines(body):
2963 for lnum, cstart, cend, line in matchlines(body):
2958 s = linestate(line, lnum, cstart, cend)
2964 s = linestate(line, lnum, cstart, cend)
2959 m.append(s)
2965 m.append(s)
2960
2966
2961 def difflinestates(a, b):
2967 def difflinestates(a, b):
2962 sm = difflib.SequenceMatcher(None, a, b)
2968 sm = difflib.SequenceMatcher(None, a, b)
2963 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2969 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2964 if tag == 'insert':
2970 if tag == 'insert':
2965 for i in xrange(blo, bhi):
2971 for i in xrange(blo, bhi):
2966 yield ('+', b[i])
2972 yield ('+', b[i])
2967 elif tag == 'delete':
2973 elif tag == 'delete':
2968 for i in xrange(alo, ahi):
2974 for i in xrange(alo, ahi):
2969 yield ('-', a[i])
2975 yield ('-', a[i])
2970 elif tag == 'replace':
2976 elif tag == 'replace':
2971 for i in xrange(alo, ahi):
2977 for i in xrange(alo, ahi):
2972 yield ('-', a[i])
2978 yield ('-', a[i])
2973 for i in xrange(blo, bhi):
2979 for i in xrange(blo, bhi):
2974 yield ('+', b[i])
2980 yield ('+', b[i])
2975
2981
2976 def display(fn, ctx, pstates, states):
2982 def display(fn, ctx, pstates, states):
2977 rev = ctx.rev()
2983 rev = ctx.rev()
2978 datefunc = ui.quiet and util.shortdate or util.datestr
2984 datefunc = ui.quiet and util.shortdate or util.datestr
2979 found = False
2985 found = False
2980 filerevmatches = {}
2986 filerevmatches = {}
2981 def binary():
2987 def binary():
2982 flog = getfile(fn)
2988 flog = getfile(fn)
2983 return util.binary(flog.read(ctx.filenode(fn)))
2989 return util.binary(flog.read(ctx.filenode(fn)))
2984
2990
2985 if opts.get('all'):
2991 if opts.get('all'):
2986 iter = difflinestates(pstates, states)
2992 iter = difflinestates(pstates, states)
2987 else:
2993 else:
2988 iter = [('', l) for l in states]
2994 iter = [('', l) for l in states]
2989 for change, l in iter:
2995 for change, l in iter:
2990 cols = [fn, str(rev)]
2996 cols = [fn, str(rev)]
2991 before, match, after = None, None, None
2997 before, match, after = None, None, None
2992 if opts.get('line_number'):
2998 if opts.get('line_number'):
2993 cols.append(str(l.linenum))
2999 cols.append(str(l.linenum))
2994 if opts.get('all'):
3000 if opts.get('all'):
2995 cols.append(change)
3001 cols.append(change)
2996 if opts.get('user'):
3002 if opts.get('user'):
2997 cols.append(ui.shortuser(ctx.user()))
3003 cols.append(ui.shortuser(ctx.user()))
2998 if opts.get('date'):
3004 if opts.get('date'):
2999 cols.append(datefunc(ctx.date()))
3005 cols.append(datefunc(ctx.date()))
3000 if opts.get('files_with_matches'):
3006 if opts.get('files_with_matches'):
3001 c = (fn, rev)
3007 c = (fn, rev)
3002 if c in filerevmatches:
3008 if c in filerevmatches:
3003 continue
3009 continue
3004 filerevmatches[c] = 1
3010 filerevmatches[c] = 1
3005 else:
3011 else:
3006 before = l.line[:l.colstart]
3012 before = l.line[:l.colstart]
3007 match = l.line[l.colstart:l.colend]
3013 match = l.line[l.colstart:l.colend]
3008 after = l.line[l.colend:]
3014 after = l.line[l.colend:]
3009 ui.write(sep.join(cols))
3015 ui.write(sep.join(cols))
3010 if before is not None:
3016 if before is not None:
3011 if not opts.get('text') and binary():
3017 if not opts.get('text') and binary():
3012 ui.write(sep + " Binary file matches")
3018 ui.write(sep + " Binary file matches")
3013 else:
3019 else:
3014 ui.write(sep + before)
3020 ui.write(sep + before)
3015 ui.write(match, label='grep.match')
3021 ui.write(match, label='grep.match')
3016 ui.write(after)
3022 ui.write(after)
3017 ui.write(eol)
3023 ui.write(eol)
3018 found = True
3024 found = True
3019 return found
3025 return found
3020
3026
3021 skip = {}
3027 skip = {}
3022 revfiles = {}
3028 revfiles = {}
3023 matchfn = scmutil.match(repo[None], pats, opts)
3029 matchfn = scmutil.match(repo[None], pats, opts)
3024 found = False
3030 found = False
3025 follow = opts.get('follow')
3031 follow = opts.get('follow')
3026
3032
3027 def prep(ctx, fns):
3033 def prep(ctx, fns):
3028 rev = ctx.rev()
3034 rev = ctx.rev()
3029 pctx = ctx.p1()
3035 pctx = ctx.p1()
3030 parent = pctx.rev()
3036 parent = pctx.rev()
3031 matches.setdefault(rev, {})
3037 matches.setdefault(rev, {})
3032 matches.setdefault(parent, {})
3038 matches.setdefault(parent, {})
3033 files = revfiles.setdefault(rev, [])
3039 files = revfiles.setdefault(rev, [])
3034 for fn in fns:
3040 for fn in fns:
3035 flog = getfile(fn)
3041 flog = getfile(fn)
3036 try:
3042 try:
3037 fnode = ctx.filenode(fn)
3043 fnode = ctx.filenode(fn)
3038 except error.LookupError:
3044 except error.LookupError:
3039 continue
3045 continue
3040
3046
3041 copied = flog.renamed(fnode)
3047 copied = flog.renamed(fnode)
3042 copy = follow and copied and copied[0]
3048 copy = follow and copied and copied[0]
3043 if copy:
3049 if copy:
3044 copies.setdefault(rev, {})[fn] = copy
3050 copies.setdefault(rev, {})[fn] = copy
3045 if fn in skip:
3051 if fn in skip:
3046 if copy:
3052 if copy:
3047 skip[copy] = True
3053 skip[copy] = True
3048 continue
3054 continue
3049 files.append(fn)
3055 files.append(fn)
3050
3056
3051 if fn not in matches[rev]:
3057 if fn not in matches[rev]:
3052 grepbody(fn, rev, flog.read(fnode))
3058 grepbody(fn, rev, flog.read(fnode))
3053
3059
3054 pfn = copy or fn
3060 pfn = copy or fn
3055 if pfn not in matches[parent]:
3061 if pfn not in matches[parent]:
3056 try:
3062 try:
3057 fnode = pctx.filenode(pfn)
3063 fnode = pctx.filenode(pfn)
3058 grepbody(pfn, parent, flog.read(fnode))
3064 grepbody(pfn, parent, flog.read(fnode))
3059 except error.LookupError:
3065 except error.LookupError:
3060 pass
3066 pass
3061
3067
3062 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3068 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3063 rev = ctx.rev()
3069 rev = ctx.rev()
3064 parent = ctx.p1().rev()
3070 parent = ctx.p1().rev()
3065 for fn in sorted(revfiles.get(rev, [])):
3071 for fn in sorted(revfiles.get(rev, [])):
3066 states = matches[rev][fn]
3072 states = matches[rev][fn]
3067 copy = copies.get(rev, {}).get(fn)
3073 copy = copies.get(rev, {}).get(fn)
3068 if fn in skip:
3074 if fn in skip:
3069 if copy:
3075 if copy:
3070 skip[copy] = True
3076 skip[copy] = True
3071 continue
3077 continue
3072 pstates = matches.get(parent, {}).get(copy or fn, [])
3078 pstates = matches.get(parent, {}).get(copy or fn, [])
3073 if pstates or states:
3079 if pstates or states:
3074 r = display(fn, ctx, pstates, states)
3080 r = display(fn, ctx, pstates, states)
3075 found = found or r
3081 found = found or r
3076 if r and not opts.get('all'):
3082 if r and not opts.get('all'):
3077 skip[fn] = True
3083 skip[fn] = True
3078 if copy:
3084 if copy:
3079 skip[copy] = True
3085 skip[copy] = True
3080 del matches[rev]
3086 del matches[rev]
3081 del revfiles[rev]
3087 del revfiles[rev]
3082
3088
3083 return not found
3089 return not found
3084
3090
3085 @command('heads',
3091 @command('heads',
3086 [('r', 'rev', '',
3092 [('r', 'rev', '',
3087 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3093 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3088 ('t', 'topo', False, _('show topological heads only')),
3094 ('t', 'topo', False, _('show topological heads only')),
3089 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3095 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3090 ('c', 'closed', False, _('show normal and closed branch heads')),
3096 ('c', 'closed', False, _('show normal and closed branch heads')),
3091 ] + templateopts,
3097 ] + templateopts,
3092 _('[-ct] [-r STARTREV] [REV]...'))
3098 _('[-ct] [-r STARTREV] [REV]...'))
3093 def heads(ui, repo, *branchrevs, **opts):
3099 def heads(ui, repo, *branchrevs, **opts):
3094 """show current repository heads or show branch heads
3100 """show current repository heads or show branch heads
3095
3101
3096 With no arguments, show all repository branch heads.
3102 With no arguments, show all repository branch heads.
3097
3103
3098 Repository "heads" are changesets with no child changesets. They are
3104 Repository "heads" are changesets with no child changesets. They are
3099 where development generally takes place and are the usual targets
3105 where development generally takes place and are the usual targets
3100 for update and merge operations. Branch heads are changesets that have
3106 for update and merge operations. Branch heads are changesets that have
3101 no child changeset on the same branch.
3107 no child changeset on the same branch.
3102
3108
3103 If one or more REVs are given, only branch heads on the branches
3109 If one or more REVs are given, only branch heads on the branches
3104 associated with the specified changesets are shown. This means
3110 associated with the specified changesets are shown. This means
3105 that you can use :hg:`heads foo` to see the heads on a branch
3111 that you can use :hg:`heads foo` to see the heads on a branch
3106 named ``foo``.
3112 named ``foo``.
3107
3113
3108 If -c/--closed is specified, also show branch heads marked closed
3114 If -c/--closed is specified, also show branch heads marked closed
3109 (see :hg:`commit --close-branch`).
3115 (see :hg:`commit --close-branch`).
3110
3116
3111 If STARTREV is specified, only those heads that are descendants of
3117 If STARTREV is specified, only those heads that are descendants of
3112 STARTREV will be displayed.
3118 STARTREV will be displayed.
3113
3119
3114 If -t/--topo is specified, named branch mechanics will be ignored and only
3120 If -t/--topo is specified, named branch mechanics will be ignored and only
3115 changesets without children will be shown.
3121 changesets without children will be shown.
3116
3122
3117 Returns 0 if matching heads are found, 1 if not.
3123 Returns 0 if matching heads are found, 1 if not.
3118 """
3124 """
3119
3125
3120 start = None
3126 start = None
3121 if 'rev' in opts:
3127 if 'rev' in opts:
3122 start = scmutil.revsingle(repo, opts['rev'], None).node()
3128 start = scmutil.revsingle(repo, opts['rev'], None).node()
3123
3129
3124 if opts.get('topo'):
3130 if opts.get('topo'):
3125 heads = [repo[h] for h in repo.heads(start)]
3131 heads = [repo[h] for h in repo.heads(start)]
3126 else:
3132 else:
3127 heads = []
3133 heads = []
3128 for branch in repo.branchmap():
3134 for branch in repo.branchmap():
3129 heads += repo.branchheads(branch, start, opts.get('closed'))
3135 heads += repo.branchheads(branch, start, opts.get('closed'))
3130 heads = [repo[h] for h in heads]
3136 heads = [repo[h] for h in heads]
3131
3137
3132 if branchrevs:
3138 if branchrevs:
3133 branches = set(repo[br].branch() for br in branchrevs)
3139 branches = set(repo[br].branch() for br in branchrevs)
3134 heads = [h for h in heads if h.branch() in branches]
3140 heads = [h for h in heads if h.branch() in branches]
3135
3141
3136 if opts.get('active') and branchrevs:
3142 if opts.get('active') and branchrevs:
3137 dagheads = repo.heads(start)
3143 dagheads = repo.heads(start)
3138 heads = [h for h in heads if h.node() in dagheads]
3144 heads = [h for h in heads if h.node() in dagheads]
3139
3145
3140 if branchrevs:
3146 if branchrevs:
3141 haveheads = set(h.branch() for h in heads)
3147 haveheads = set(h.branch() for h in heads)
3142 if branches - haveheads:
3148 if branches - haveheads:
3143 headless = ', '.join(b for b in branches - haveheads)
3149 headless = ', '.join(b for b in branches - haveheads)
3144 msg = _('no open branch heads found on branches %s')
3150 msg = _('no open branch heads found on branches %s')
3145 if opts.get('rev'):
3151 if opts.get('rev'):
3146 msg += _(' (started at %s)') % opts['rev']
3152 msg += _(' (started at %s)') % opts['rev']
3147 ui.warn((msg + '\n') % headless)
3153 ui.warn((msg + '\n') % headless)
3148
3154
3149 if not heads:
3155 if not heads:
3150 return 1
3156 return 1
3151
3157
3152 heads = sorted(heads, key=lambda x: -x.rev())
3158 heads = sorted(heads, key=lambda x: -x.rev())
3153 displayer = cmdutil.show_changeset(ui, repo, opts)
3159 displayer = cmdutil.show_changeset(ui, repo, opts)
3154 for ctx in heads:
3160 for ctx in heads:
3155 displayer.show(ctx)
3161 displayer.show(ctx)
3156 displayer.close()
3162 displayer.close()
3157
3163
3158 @command('help',
3164 @command('help',
3159 [('e', 'extension', None, _('show only help for extensions')),
3165 [('e', 'extension', None, _('show only help for extensions')),
3160 ('c', 'command', None, _('show only help for commands')),
3166 ('c', 'command', None, _('show only help for commands')),
3161 ('k', 'keyword', '', _('show topics matching keyword')),
3167 ('k', 'keyword', '', _('show topics matching keyword')),
3162 ],
3168 ],
3163 _('[-ec] [TOPIC]'))
3169 _('[-ec] [TOPIC]'))
3164 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3170 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3165 """show help for a given topic or a help overview
3171 """show help for a given topic or a help overview
3166
3172
3167 With no arguments, print a list of commands with short help messages.
3173 With no arguments, print a list of commands with short help messages.
3168
3174
3169 Given a topic, extension, or command name, print help for that
3175 Given a topic, extension, or command name, print help for that
3170 topic.
3176 topic.
3171
3177
3172 Returns 0 if successful.
3178 Returns 0 if successful.
3173 """
3179 """
3174
3180
3175 textwidth = min(ui.termwidth(), 80) - 2
3181 textwidth = min(ui.termwidth(), 80) - 2
3176
3182
3177 def helpcmd(name):
3183 def helpcmd(name):
3178 try:
3184 try:
3179 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3185 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3180 except error.AmbiguousCommand, inst:
3186 except error.AmbiguousCommand, inst:
3181 # py3k fix: except vars can't be used outside the scope of the
3187 # py3k fix: except vars can't be used outside the scope of the
3182 # except block, nor can be used inside a lambda. python issue4617
3188 # except block, nor can be used inside a lambda. python issue4617
3183 prefix = inst.args[0]
3189 prefix = inst.args[0]
3184 select = lambda c: c.lstrip('^').startswith(prefix)
3190 select = lambda c: c.lstrip('^').startswith(prefix)
3185 rst = helplist(select)
3191 rst = helplist(select)
3186 return rst
3192 return rst
3187
3193
3188 rst = []
3194 rst = []
3189
3195
3190 # check if it's an invalid alias and display its error if it is
3196 # check if it's an invalid alias and display its error if it is
3191 if getattr(entry[0], 'badalias', False):
3197 if getattr(entry[0], 'badalias', False):
3192 if not unknowncmd:
3198 if not unknowncmd:
3193 ui.pushbuffer()
3199 ui.pushbuffer()
3194 entry[0](ui)
3200 entry[0](ui)
3195 rst.append(ui.popbuffer())
3201 rst.append(ui.popbuffer())
3196 return rst
3202 return rst
3197
3203
3198 # synopsis
3204 # synopsis
3199 if len(entry) > 2:
3205 if len(entry) > 2:
3200 if entry[2].startswith('hg'):
3206 if entry[2].startswith('hg'):
3201 rst.append("%s\n" % entry[2])
3207 rst.append("%s\n" % entry[2])
3202 else:
3208 else:
3203 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3209 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3204 else:
3210 else:
3205 rst.append('hg %s\n' % aliases[0])
3211 rst.append('hg %s\n' % aliases[0])
3206 # aliases
3212 # aliases
3207 if full and not ui.quiet and len(aliases) > 1:
3213 if full and not ui.quiet and len(aliases) > 1:
3208 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3214 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3209 rst.append('\n')
3215 rst.append('\n')
3210
3216
3211 # description
3217 # description
3212 doc = gettext(entry[0].__doc__)
3218 doc = gettext(entry[0].__doc__)
3213 if not doc:
3219 if not doc:
3214 doc = _("(no help text available)")
3220 doc = _("(no help text available)")
3215 if util.safehasattr(entry[0], 'definition'): # aliased command
3221 if util.safehasattr(entry[0], 'definition'): # aliased command
3216 if entry[0].definition.startswith('!'): # shell alias
3222 if entry[0].definition.startswith('!'): # shell alias
3217 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3223 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3218 else:
3224 else:
3219 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3225 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3220 doc = doc.splitlines(True)
3226 doc = doc.splitlines(True)
3221 if ui.quiet or not full:
3227 if ui.quiet or not full:
3222 rst.append(doc[0])
3228 rst.append(doc[0])
3223 else:
3229 else:
3224 rst.extend(doc)
3230 rst.extend(doc)
3225 rst.append('\n')
3231 rst.append('\n')
3226
3232
3227 # check if this command shadows a non-trivial (multi-line)
3233 # check if this command shadows a non-trivial (multi-line)
3228 # extension help text
3234 # extension help text
3229 try:
3235 try:
3230 mod = extensions.find(name)
3236 mod = extensions.find(name)
3231 doc = gettext(mod.__doc__) or ''
3237 doc = gettext(mod.__doc__) or ''
3232 if '\n' in doc.strip():
3238 if '\n' in doc.strip():
3233 msg = _('use "hg help -e %s" to show help for '
3239 msg = _('use "hg help -e %s" to show help for '
3234 'the %s extension') % (name, name)
3240 'the %s extension') % (name, name)
3235 rst.append('\n%s\n' % msg)
3241 rst.append('\n%s\n' % msg)
3236 except KeyError:
3242 except KeyError:
3237 pass
3243 pass
3238
3244
3239 # options
3245 # options
3240 if not ui.quiet and entry[1]:
3246 if not ui.quiet and entry[1]:
3241 rst.append('\n%s\n\n' % _("options:"))
3247 rst.append('\n%s\n\n' % _("options:"))
3242 rst.append(help.optrst(entry[1], ui.verbose))
3248 rst.append(help.optrst(entry[1], ui.verbose))
3243
3249
3244 if ui.verbose:
3250 if ui.verbose:
3245 rst.append('\n%s\n\n' % _("global options:"))
3251 rst.append('\n%s\n\n' % _("global options:"))
3246 rst.append(help.optrst(globalopts, ui.verbose))
3252 rst.append(help.optrst(globalopts, ui.verbose))
3247
3253
3248 if not ui.verbose:
3254 if not ui.verbose:
3249 if not full:
3255 if not full:
3250 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3256 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3251 % name)
3257 % name)
3252 elif not ui.quiet:
3258 elif not ui.quiet:
3253 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3259 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3254 % name)
3260 % name)
3255 return rst
3261 return rst
3256
3262
3257
3263
3258 def helplist(select=None):
3264 def helplist(select=None):
3259 # list of commands
3265 # list of commands
3260 if name == "shortlist":
3266 if name == "shortlist":
3261 header = _('basic commands:\n\n')
3267 header = _('basic commands:\n\n')
3262 else:
3268 else:
3263 header = _('list of commands:\n\n')
3269 header = _('list of commands:\n\n')
3264
3270
3265 h = {}
3271 h = {}
3266 cmds = {}
3272 cmds = {}
3267 for c, e in table.iteritems():
3273 for c, e in table.iteritems():
3268 f = c.split("|", 1)[0]
3274 f = c.split("|", 1)[0]
3269 if select and not select(f):
3275 if select and not select(f):
3270 continue
3276 continue
3271 if (not select and name != 'shortlist' and
3277 if (not select and name != 'shortlist' and
3272 e[0].__module__ != __name__):
3278 e[0].__module__ != __name__):
3273 continue
3279 continue
3274 if name == "shortlist" and not f.startswith("^"):
3280 if name == "shortlist" and not f.startswith("^"):
3275 continue
3281 continue
3276 f = f.lstrip("^")
3282 f = f.lstrip("^")
3277 if not ui.debugflag and f.startswith("debug"):
3283 if not ui.debugflag and f.startswith("debug"):
3278 continue
3284 continue
3279 doc = e[0].__doc__
3285 doc = e[0].__doc__
3280 if doc and 'DEPRECATED' in doc and not ui.verbose:
3286 if doc and 'DEPRECATED' in doc and not ui.verbose:
3281 continue
3287 continue
3282 doc = gettext(doc)
3288 doc = gettext(doc)
3283 if not doc:
3289 if not doc:
3284 doc = _("(no help text available)")
3290 doc = _("(no help text available)")
3285 h[f] = doc.splitlines()[0].rstrip()
3291 h[f] = doc.splitlines()[0].rstrip()
3286 cmds[f] = c.lstrip("^")
3292 cmds[f] = c.lstrip("^")
3287
3293
3288 rst = []
3294 rst = []
3289 if not h:
3295 if not h:
3290 if not ui.quiet:
3296 if not ui.quiet:
3291 rst.append(_('no commands defined\n'))
3297 rst.append(_('no commands defined\n'))
3292 return rst
3298 return rst
3293
3299
3294 if not ui.quiet:
3300 if not ui.quiet:
3295 rst.append(header)
3301 rst.append(header)
3296 fns = sorted(h)
3302 fns = sorted(h)
3297 for f in fns:
3303 for f in fns:
3298 if ui.verbose:
3304 if ui.verbose:
3299 commands = cmds[f].replace("|",", ")
3305 commands = cmds[f].replace("|",", ")
3300 rst.append(" :%s: %s\n" % (commands, h[f]))
3306 rst.append(" :%s: %s\n" % (commands, h[f]))
3301 else:
3307 else:
3302 rst.append(' :%s: %s\n' % (f, h[f]))
3308 rst.append(' :%s: %s\n' % (f, h[f]))
3303
3309
3304 if not name:
3310 if not name:
3305 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3311 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3306 if exts:
3312 if exts:
3307 rst.append('\n')
3313 rst.append('\n')
3308 rst.extend(exts)
3314 rst.extend(exts)
3309
3315
3310 rst.append(_("\nadditional help topics:\n\n"))
3316 rst.append(_("\nadditional help topics:\n\n"))
3311 topics = []
3317 topics = []
3312 for names, header, doc in help.helptable:
3318 for names, header, doc in help.helptable:
3313 topics.append((names[0], header))
3319 topics.append((names[0], header))
3314 for t, desc in topics:
3320 for t, desc in topics:
3315 rst.append(" :%s: %s\n" % (t, desc))
3321 rst.append(" :%s: %s\n" % (t, desc))
3316
3322
3317 optlist = []
3323 optlist = []
3318 if not ui.quiet:
3324 if not ui.quiet:
3319 if ui.verbose:
3325 if ui.verbose:
3320 optlist.append((_("global options:"), globalopts))
3326 optlist.append((_("global options:"), globalopts))
3321 if name == 'shortlist':
3327 if name == 'shortlist':
3322 optlist.append((_('use "hg help" for the full list '
3328 optlist.append((_('use "hg help" for the full list '
3323 'of commands'), ()))
3329 'of commands'), ()))
3324 else:
3330 else:
3325 if name == 'shortlist':
3331 if name == 'shortlist':
3326 msg = _('use "hg help" for the full list of commands '
3332 msg = _('use "hg help" for the full list of commands '
3327 'or "hg -v" for details')
3333 'or "hg -v" for details')
3328 elif name and not full:
3334 elif name and not full:
3329 msg = _('use "hg help %s" to show the full help '
3335 msg = _('use "hg help %s" to show the full help '
3330 'text') % name
3336 'text') % name
3331 else:
3337 else:
3332 msg = _('use "hg -v help%s" to show builtin aliases and '
3338 msg = _('use "hg -v help%s" to show builtin aliases and '
3333 'global options') % (name and " " + name or "")
3339 'global options') % (name and " " + name or "")
3334 optlist.append((msg, ()))
3340 optlist.append((msg, ()))
3335
3341
3336 if optlist:
3342 if optlist:
3337 for title, options in optlist:
3343 for title, options in optlist:
3338 rst.append('\n%s\n' % title)
3344 rst.append('\n%s\n' % title)
3339 if options:
3345 if options:
3340 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3346 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3341 return rst
3347 return rst
3342
3348
3343 def helptopic(name):
3349 def helptopic(name):
3344 for names, header, doc in help.helptable:
3350 for names, header, doc in help.helptable:
3345 if name in names:
3351 if name in names:
3346 break
3352 break
3347 else:
3353 else:
3348 raise error.UnknownCommand(name)
3354 raise error.UnknownCommand(name)
3349
3355
3350 rst = ["%s\n\n" % header]
3356 rst = ["%s\n\n" % header]
3351 # description
3357 # description
3352 if not doc:
3358 if not doc:
3353 rst.append(" %s\n" % _("(no help text available)"))
3359 rst.append(" %s\n" % _("(no help text available)"))
3354 if util.safehasattr(doc, '__call__'):
3360 if util.safehasattr(doc, '__call__'):
3355 rst += [" %s\n" % l for l in doc().splitlines()]
3361 rst += [" %s\n" % l for l in doc().splitlines()]
3356
3362
3357 try:
3363 try:
3358 cmdutil.findcmd(name, table)
3364 cmdutil.findcmd(name, table)
3359 rst.append(_('\nuse "hg help -c %s" to see help for '
3365 rst.append(_('\nuse "hg help -c %s" to see help for '
3360 'the %s command\n') % (name, name))
3366 'the %s command\n') % (name, name))
3361 except error.UnknownCommand:
3367 except error.UnknownCommand:
3362 pass
3368 pass
3363 return rst
3369 return rst
3364
3370
3365 def helpext(name):
3371 def helpext(name):
3366 try:
3372 try:
3367 mod = extensions.find(name)
3373 mod = extensions.find(name)
3368 doc = gettext(mod.__doc__) or _('no help text available')
3374 doc = gettext(mod.__doc__) or _('no help text available')
3369 except KeyError:
3375 except KeyError:
3370 mod = None
3376 mod = None
3371 doc = extensions.disabledext(name)
3377 doc = extensions.disabledext(name)
3372 if not doc:
3378 if not doc:
3373 raise error.UnknownCommand(name)
3379 raise error.UnknownCommand(name)
3374
3380
3375 if '\n' not in doc:
3381 if '\n' not in doc:
3376 head, tail = doc, ""
3382 head, tail = doc, ""
3377 else:
3383 else:
3378 head, tail = doc.split('\n', 1)
3384 head, tail = doc.split('\n', 1)
3379 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3385 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3380 if tail:
3386 if tail:
3381 rst.extend(tail.splitlines(True))
3387 rst.extend(tail.splitlines(True))
3382 rst.append('\n')
3388 rst.append('\n')
3383
3389
3384 if mod:
3390 if mod:
3385 try:
3391 try:
3386 ct = mod.cmdtable
3392 ct = mod.cmdtable
3387 except AttributeError:
3393 except AttributeError:
3388 ct = {}
3394 ct = {}
3389 modcmds = set([c.split('|', 1)[0] for c in ct])
3395 modcmds = set([c.split('|', 1)[0] for c in ct])
3390 rst.extend(helplist(modcmds.__contains__))
3396 rst.extend(helplist(modcmds.__contains__))
3391 else:
3397 else:
3392 rst.append(_('use "hg help extensions" for information on enabling '
3398 rst.append(_('use "hg help extensions" for information on enabling '
3393 'extensions\n'))
3399 'extensions\n'))
3394 return rst
3400 return rst
3395
3401
3396 def helpextcmd(name):
3402 def helpextcmd(name):
3397 cmd, ext, mod = extensions.disabledcmd(ui, name,
3403 cmd, ext, mod = extensions.disabledcmd(ui, name,
3398 ui.configbool('ui', 'strict'))
3404 ui.configbool('ui', 'strict'))
3399 doc = gettext(mod.__doc__).splitlines()[0]
3405 doc = gettext(mod.__doc__).splitlines()[0]
3400
3406
3401 rst = help.listexts(_("'%s' is provided by the following "
3407 rst = help.listexts(_("'%s' is provided by the following "
3402 "extension:") % cmd, {ext: doc}, indent=4)
3408 "extension:") % cmd, {ext: doc}, indent=4)
3403 rst.append('\n')
3409 rst.append('\n')
3404 rst.append(_('use "hg help extensions" for information on enabling '
3410 rst.append(_('use "hg help extensions" for information on enabling '
3405 'extensions\n'))
3411 'extensions\n'))
3406 return rst
3412 return rst
3407
3413
3408
3414
3409 rst = []
3415 rst = []
3410 kw = opts.get('keyword')
3416 kw = opts.get('keyword')
3411 if kw:
3417 if kw:
3412 matches = help.topicmatch(kw)
3418 matches = help.topicmatch(kw)
3413 for t, title in (('topics', _('Topics')),
3419 for t, title in (('topics', _('Topics')),
3414 ('commands', _('Commands')),
3420 ('commands', _('Commands')),
3415 ('extensions', _('Extensions')),
3421 ('extensions', _('Extensions')),
3416 ('extensioncommands', _('Extension Commands'))):
3422 ('extensioncommands', _('Extension Commands'))):
3417 if matches[t]:
3423 if matches[t]:
3418 rst.append('%s:\n\n' % title)
3424 rst.append('%s:\n\n' % title)
3419 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3425 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3420 rst.append('\n')
3426 rst.append('\n')
3421 elif name and name != 'shortlist':
3427 elif name and name != 'shortlist':
3422 i = None
3428 i = None
3423 if unknowncmd:
3429 if unknowncmd:
3424 queries = (helpextcmd,)
3430 queries = (helpextcmd,)
3425 elif opts.get('extension'):
3431 elif opts.get('extension'):
3426 queries = (helpext,)
3432 queries = (helpext,)
3427 elif opts.get('command'):
3433 elif opts.get('command'):
3428 queries = (helpcmd,)
3434 queries = (helpcmd,)
3429 else:
3435 else:
3430 queries = (helptopic, helpcmd, helpext, helpextcmd)
3436 queries = (helptopic, helpcmd, helpext, helpextcmd)
3431 for f in queries:
3437 for f in queries:
3432 try:
3438 try:
3433 rst = f(name)
3439 rst = f(name)
3434 i = None
3440 i = None
3435 break
3441 break
3436 except error.UnknownCommand, inst:
3442 except error.UnknownCommand, inst:
3437 i = inst
3443 i = inst
3438 if i:
3444 if i:
3439 raise i
3445 raise i
3440 else:
3446 else:
3441 # program name
3447 # program name
3442 if not ui.quiet:
3448 if not ui.quiet:
3443 rst = [_("Mercurial Distributed SCM\n"), '\n']
3449 rst = [_("Mercurial Distributed SCM\n"), '\n']
3444 rst.extend(helplist())
3450 rst.extend(helplist())
3445
3451
3446 keep = ui.verbose and ['verbose'] or []
3452 keep = ui.verbose and ['verbose'] or []
3447 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3453 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3448 ui.write(formatted)
3454 ui.write(formatted)
3449
3455
3450
3456
3451 @command('identify|id',
3457 @command('identify|id',
3452 [('r', 'rev', '',
3458 [('r', 'rev', '',
3453 _('identify the specified revision'), _('REV')),
3459 _('identify the specified revision'), _('REV')),
3454 ('n', 'num', None, _('show local revision number')),
3460 ('n', 'num', None, _('show local revision number')),
3455 ('i', 'id', None, _('show global revision id')),
3461 ('i', 'id', None, _('show global revision id')),
3456 ('b', 'branch', None, _('show branch')),
3462 ('b', 'branch', None, _('show branch')),
3457 ('t', 'tags', None, _('show tags')),
3463 ('t', 'tags', None, _('show tags')),
3458 ('B', 'bookmarks', None, _('show bookmarks')),
3464 ('B', 'bookmarks', None, _('show bookmarks')),
3459 ] + remoteopts,
3465 ] + remoteopts,
3460 _('[-nibtB] [-r REV] [SOURCE]'))
3466 _('[-nibtB] [-r REV] [SOURCE]'))
3461 def identify(ui, repo, source=None, rev=None,
3467 def identify(ui, repo, source=None, rev=None,
3462 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3468 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3463 """identify the working copy or specified revision
3469 """identify the working copy or specified revision
3464
3470
3465 Print a summary identifying the repository state at REV using one or
3471 Print a summary identifying the repository state at REV using one or
3466 two parent hash identifiers, followed by a "+" if the working
3472 two parent hash identifiers, followed by a "+" if the working
3467 directory has uncommitted changes, the branch name (if not default),
3473 directory has uncommitted changes, the branch name (if not default),
3468 a list of tags, and a list of bookmarks.
3474 a list of tags, and a list of bookmarks.
3469
3475
3470 When REV is not given, print a summary of the current state of the
3476 When REV is not given, print a summary of the current state of the
3471 repository.
3477 repository.
3472
3478
3473 Specifying a path to a repository root or Mercurial bundle will
3479 Specifying a path to a repository root or Mercurial bundle will
3474 cause lookup to operate on that repository/bundle.
3480 cause lookup to operate on that repository/bundle.
3475
3481
3476 .. container:: verbose
3482 .. container:: verbose
3477
3483
3478 Examples:
3484 Examples:
3479
3485
3480 - generate a build identifier for the working directory::
3486 - generate a build identifier for the working directory::
3481
3487
3482 hg id --id > build-id.dat
3488 hg id --id > build-id.dat
3483
3489
3484 - find the revision corresponding to a tag::
3490 - find the revision corresponding to a tag::
3485
3491
3486 hg id -n -r 1.3
3492 hg id -n -r 1.3
3487
3493
3488 - check the most recent revision of a remote repository::
3494 - check the most recent revision of a remote repository::
3489
3495
3490 hg id -r tip http://selenic.com/hg/
3496 hg id -r tip http://selenic.com/hg/
3491
3497
3492 Returns 0 if successful.
3498 Returns 0 if successful.
3493 """
3499 """
3494
3500
3495 if not repo and not source:
3501 if not repo and not source:
3496 raise util.Abort(_("there is no Mercurial repository here "
3502 raise util.Abort(_("there is no Mercurial repository here "
3497 "(.hg not found)"))
3503 "(.hg not found)"))
3498
3504
3499 hexfunc = ui.debugflag and hex or short
3505 hexfunc = ui.debugflag and hex or short
3500 default = not (num or id or branch or tags or bookmarks)
3506 default = not (num or id or branch or tags or bookmarks)
3501 output = []
3507 output = []
3502 revs = []
3508 revs = []
3503
3509
3504 if source:
3510 if source:
3505 source, branches = hg.parseurl(ui.expandpath(source))
3511 source, branches = hg.parseurl(ui.expandpath(source))
3506 peer = hg.peer(ui, opts, source)
3512 peer = hg.peer(ui, opts, source)
3507 repo = peer.local()
3513 repo = peer.local()
3508 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3514 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3509
3515
3510 if not repo:
3516 if not repo:
3511 if num or branch or tags:
3517 if num or branch or tags:
3512 raise util.Abort(
3518 raise util.Abort(
3513 _("can't query remote revision number, branch, or tags"))
3519 _("can't query remote revision number, branch, or tags"))
3514 if not rev and revs:
3520 if not rev and revs:
3515 rev = revs[0]
3521 rev = revs[0]
3516 if not rev:
3522 if not rev:
3517 rev = "tip"
3523 rev = "tip"
3518
3524
3519 remoterev = peer.lookup(rev)
3525 remoterev = peer.lookup(rev)
3520 if default or id:
3526 if default or id:
3521 output = [hexfunc(remoterev)]
3527 output = [hexfunc(remoterev)]
3522
3528
3523 def getbms():
3529 def getbms():
3524 bms = []
3530 bms = []
3525
3531
3526 if 'bookmarks' in peer.listkeys('namespaces'):
3532 if 'bookmarks' in peer.listkeys('namespaces'):
3527 hexremoterev = hex(remoterev)
3533 hexremoterev = hex(remoterev)
3528 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3534 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3529 if bmr == hexremoterev]
3535 if bmr == hexremoterev]
3530
3536
3531 return bms
3537 return bms
3532
3538
3533 if bookmarks:
3539 if bookmarks:
3534 output.extend(getbms())
3540 output.extend(getbms())
3535 elif default and not ui.quiet:
3541 elif default and not ui.quiet:
3536 # multiple bookmarks for a single parent separated by '/'
3542 # multiple bookmarks for a single parent separated by '/'
3537 bm = '/'.join(getbms())
3543 bm = '/'.join(getbms())
3538 if bm:
3544 if bm:
3539 output.append(bm)
3545 output.append(bm)
3540 else:
3546 else:
3541 if not rev:
3547 if not rev:
3542 ctx = repo[None]
3548 ctx = repo[None]
3543 parents = ctx.parents()
3549 parents = ctx.parents()
3544 changed = ""
3550 changed = ""
3545 if default or id or num:
3551 if default or id or num:
3546 if (util.any(repo.status())
3552 if (util.any(repo.status())
3547 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3553 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3548 changed = '+'
3554 changed = '+'
3549 if default or id:
3555 if default or id:
3550 output = ["%s%s" %
3556 output = ["%s%s" %
3551 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3557 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3552 if num:
3558 if num:
3553 output.append("%s%s" %
3559 output.append("%s%s" %
3554 ('+'.join([str(p.rev()) for p in parents]), changed))
3560 ('+'.join([str(p.rev()) for p in parents]), changed))
3555 else:
3561 else:
3556 ctx = scmutil.revsingle(repo, rev)
3562 ctx = scmutil.revsingle(repo, rev)
3557 if default or id:
3563 if default or id:
3558 output = [hexfunc(ctx.node())]
3564 output = [hexfunc(ctx.node())]
3559 if num:
3565 if num:
3560 output.append(str(ctx.rev()))
3566 output.append(str(ctx.rev()))
3561
3567
3562 if default and not ui.quiet:
3568 if default and not ui.quiet:
3563 b = ctx.branch()
3569 b = ctx.branch()
3564 if b != 'default':
3570 if b != 'default':
3565 output.append("(%s)" % b)
3571 output.append("(%s)" % b)
3566
3572
3567 # multiple tags for a single parent separated by '/'
3573 # multiple tags for a single parent separated by '/'
3568 t = '/'.join(ctx.tags())
3574 t = '/'.join(ctx.tags())
3569 if t:
3575 if t:
3570 output.append(t)
3576 output.append(t)
3571
3577
3572 # multiple bookmarks for a single parent separated by '/'
3578 # multiple bookmarks for a single parent separated by '/'
3573 bm = '/'.join(ctx.bookmarks())
3579 bm = '/'.join(ctx.bookmarks())
3574 if bm:
3580 if bm:
3575 output.append(bm)
3581 output.append(bm)
3576 else:
3582 else:
3577 if branch:
3583 if branch:
3578 output.append(ctx.branch())
3584 output.append(ctx.branch())
3579
3585
3580 if tags:
3586 if tags:
3581 output.extend(ctx.tags())
3587 output.extend(ctx.tags())
3582
3588
3583 if bookmarks:
3589 if bookmarks:
3584 output.extend(ctx.bookmarks())
3590 output.extend(ctx.bookmarks())
3585
3591
3586 ui.write("%s\n" % ' '.join(output))
3592 ui.write("%s\n" % ' '.join(output))
3587
3593
3588 @command('import|patch',
3594 @command('import|patch',
3589 [('p', 'strip', 1,
3595 [('p', 'strip', 1,
3590 _('directory strip option for patch. This has the same '
3596 _('directory strip option for patch. This has the same '
3591 'meaning as the corresponding patch option'), _('NUM')),
3597 'meaning as the corresponding patch option'), _('NUM')),
3592 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3598 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3593 ('e', 'edit', False, _('invoke editor on commit messages')),
3599 ('e', 'edit', False, _('invoke editor on commit messages')),
3594 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3600 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3595 ('', 'no-commit', None,
3601 ('', 'no-commit', None,
3596 _("don't commit, just update the working directory")),
3602 _("don't commit, just update the working directory")),
3597 ('', 'bypass', None,
3603 ('', 'bypass', None,
3598 _("apply patch without touching the working directory")),
3604 _("apply patch without touching the working directory")),
3599 ('', 'exact', None,
3605 ('', 'exact', None,
3600 _('apply patch to the nodes from which it was generated')),
3606 _('apply patch to the nodes from which it was generated')),
3601 ('', 'import-branch', None,
3607 ('', 'import-branch', None,
3602 _('use any branch information in patch (implied by --exact)'))] +
3608 _('use any branch information in patch (implied by --exact)'))] +
3603 commitopts + commitopts2 + similarityopts,
3609 commitopts + commitopts2 + similarityopts,
3604 _('[OPTION]... PATCH...'))
3610 _('[OPTION]... PATCH...'))
3605 def import_(ui, repo, patch1=None, *patches, **opts):
3611 def import_(ui, repo, patch1=None, *patches, **opts):
3606 """import an ordered set of patches
3612 """import an ordered set of patches
3607
3613
3608 Import a list of patches and commit them individually (unless
3614 Import a list of patches and commit them individually (unless
3609 --no-commit is specified).
3615 --no-commit is specified).
3610
3616
3611 If there are outstanding changes in the working directory, import
3617 If there are outstanding changes in the working directory, import
3612 will abort unless given the -f/--force flag.
3618 will abort unless given the -f/--force flag.
3613
3619
3614 You can import a patch straight from a mail message. Even patches
3620 You can import a patch straight from a mail message. Even patches
3615 as attachments work (to use the body part, it must have type
3621 as attachments work (to use the body part, it must have type
3616 text/plain or text/x-patch). From and Subject headers of email
3622 text/plain or text/x-patch). From and Subject headers of email
3617 message are used as default committer and commit message. All
3623 message are used as default committer and commit message. All
3618 text/plain body parts before first diff are added to commit
3624 text/plain body parts before first diff are added to commit
3619 message.
3625 message.
3620
3626
3621 If the imported patch was generated by :hg:`export`, user and
3627 If the imported patch was generated by :hg:`export`, user and
3622 description from patch override values from message headers and
3628 description from patch override values from message headers and
3623 body. Values given on command line with -m/--message and -u/--user
3629 body. Values given on command line with -m/--message and -u/--user
3624 override these.
3630 override these.
3625
3631
3626 If --exact is specified, import will set the working directory to
3632 If --exact is specified, import will set the working directory to
3627 the parent of each patch before applying it, and will abort if the
3633 the parent of each patch before applying it, and will abort if the
3628 resulting changeset has a different ID than the one recorded in
3634 resulting changeset has a different ID than the one recorded in
3629 the patch. This may happen due to character set problems or other
3635 the patch. This may happen due to character set problems or other
3630 deficiencies in the text patch format.
3636 deficiencies in the text patch format.
3631
3637
3632 Use --bypass to apply and commit patches directly to the
3638 Use --bypass to apply and commit patches directly to the
3633 repository, not touching the working directory. Without --exact,
3639 repository, not touching the working directory. Without --exact,
3634 patches will be applied on top of the working directory parent
3640 patches will be applied on top of the working directory parent
3635 revision.
3641 revision.
3636
3642
3637 With -s/--similarity, hg will attempt to discover renames and
3643 With -s/--similarity, hg will attempt to discover renames and
3638 copies in the patch in the same way as :hg:`addremove`.
3644 copies in the patch in the same way as :hg:`addremove`.
3639
3645
3640 To read a patch from standard input, use "-" as the patch name. If
3646 To read a patch from standard input, use "-" as the patch name. If
3641 a URL is specified, the patch will be downloaded from it.
3647 a URL is specified, the patch will be downloaded from it.
3642 See :hg:`help dates` for a list of formats valid for -d/--date.
3648 See :hg:`help dates` for a list of formats valid for -d/--date.
3643
3649
3644 .. container:: verbose
3650 .. container:: verbose
3645
3651
3646 Examples:
3652 Examples:
3647
3653
3648 - import a traditional patch from a website and detect renames::
3654 - import a traditional patch from a website and detect renames::
3649
3655
3650 hg import -s 80 http://example.com/bugfix.patch
3656 hg import -s 80 http://example.com/bugfix.patch
3651
3657
3652 - import a changeset from an hgweb server::
3658 - import a changeset from an hgweb server::
3653
3659
3654 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3660 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3655
3661
3656 - import all the patches in an Unix-style mbox::
3662 - import all the patches in an Unix-style mbox::
3657
3663
3658 hg import incoming-patches.mbox
3664 hg import incoming-patches.mbox
3659
3665
3660 - attempt to exactly restore an exported changeset (not always
3666 - attempt to exactly restore an exported changeset (not always
3661 possible)::
3667 possible)::
3662
3668
3663 hg import --exact proposed-fix.patch
3669 hg import --exact proposed-fix.patch
3664
3670
3665 Returns 0 on success.
3671 Returns 0 on success.
3666 """
3672 """
3667
3673
3668 if not patch1:
3674 if not patch1:
3669 raise util.Abort(_('need at least one patch to import'))
3675 raise util.Abort(_('need at least one patch to import'))
3670
3676
3671 patches = (patch1,) + patches
3677 patches = (patch1,) + patches
3672
3678
3673 date = opts.get('date')
3679 date = opts.get('date')
3674 if date:
3680 if date:
3675 opts['date'] = util.parsedate(date)
3681 opts['date'] = util.parsedate(date)
3676
3682
3677 editor = cmdutil.commiteditor
3683 editor = cmdutil.commiteditor
3678 if opts.get('edit'):
3684 if opts.get('edit'):
3679 editor = cmdutil.commitforceeditor
3685 editor = cmdutil.commitforceeditor
3680
3686
3681 update = not opts.get('bypass')
3687 update = not opts.get('bypass')
3682 if not update and opts.get('no_commit'):
3688 if not update and opts.get('no_commit'):
3683 raise util.Abort(_('cannot use --no-commit with --bypass'))
3689 raise util.Abort(_('cannot use --no-commit with --bypass'))
3684 try:
3690 try:
3685 sim = float(opts.get('similarity') or 0)
3691 sim = float(opts.get('similarity') or 0)
3686 except ValueError:
3692 except ValueError:
3687 raise util.Abort(_('similarity must be a number'))
3693 raise util.Abort(_('similarity must be a number'))
3688 if sim < 0 or sim > 100:
3694 if sim < 0 or sim > 100:
3689 raise util.Abort(_('similarity must be between 0 and 100'))
3695 raise util.Abort(_('similarity must be between 0 and 100'))
3690 if sim and not update:
3696 if sim and not update:
3691 raise util.Abort(_('cannot use --similarity with --bypass'))
3697 raise util.Abort(_('cannot use --similarity with --bypass'))
3692
3698
3693 if (opts.get('exact') or not opts.get('force')) and update:
3699 if (opts.get('exact') or not opts.get('force')) and update:
3694 cmdutil.bailifchanged(repo)
3700 cmdutil.bailifchanged(repo)
3695
3701
3696 base = opts["base"]
3702 base = opts["base"]
3697 strip = opts["strip"]
3703 strip = opts["strip"]
3698 wlock = lock = tr = None
3704 wlock = lock = tr = None
3699 msgs = []
3705 msgs = []
3700
3706
3701 def checkexact(repo, n, nodeid):
3707 def checkexact(repo, n, nodeid):
3702 if opts.get('exact') and hex(n) != nodeid:
3708 if opts.get('exact') and hex(n) != nodeid:
3703 repo.rollback()
3709 repo.rollback()
3704 raise util.Abort(_('patch is damaged or loses information'))
3710 raise util.Abort(_('patch is damaged or loses information'))
3705
3711
3706 def tryone(ui, hunk, parents):
3712 def tryone(ui, hunk, parents):
3707 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3713 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3708 patch.extract(ui, hunk)
3714 patch.extract(ui, hunk)
3709
3715
3710 if not tmpname:
3716 if not tmpname:
3711 return (None, None)
3717 return (None, None)
3712 msg = _('applied to working directory')
3718 msg = _('applied to working directory')
3713
3719
3714 try:
3720 try:
3715 cmdline_message = cmdutil.logmessage(ui, opts)
3721 cmdline_message = cmdutil.logmessage(ui, opts)
3716 if cmdline_message:
3722 if cmdline_message:
3717 # pickup the cmdline msg
3723 # pickup the cmdline msg
3718 message = cmdline_message
3724 message = cmdline_message
3719 elif message:
3725 elif message:
3720 # pickup the patch msg
3726 # pickup the patch msg
3721 message = message.strip()
3727 message = message.strip()
3722 else:
3728 else:
3723 # launch the editor
3729 # launch the editor
3724 message = None
3730 message = None
3725 ui.debug('message:\n%s\n' % message)
3731 ui.debug('message:\n%s\n' % message)
3726
3732
3727 if len(parents) == 1:
3733 if len(parents) == 1:
3728 parents.append(repo[nullid])
3734 parents.append(repo[nullid])
3729 if opts.get('exact'):
3735 if opts.get('exact'):
3730 if not nodeid or not p1:
3736 if not nodeid or not p1:
3731 raise util.Abort(_('not a Mercurial patch'))
3737 raise util.Abort(_('not a Mercurial patch'))
3732 p1 = repo[p1]
3738 p1 = repo[p1]
3733 p2 = repo[p2 or nullid]
3739 p2 = repo[p2 or nullid]
3734 elif p2:
3740 elif p2:
3735 try:
3741 try:
3736 p1 = repo[p1]
3742 p1 = repo[p1]
3737 p2 = repo[p2]
3743 p2 = repo[p2]
3738 # Without any options, consider p2 only if the
3744 # Without any options, consider p2 only if the
3739 # patch is being applied on top of the recorded
3745 # patch is being applied on top of the recorded
3740 # first parent.
3746 # first parent.
3741 if p1 != parents[0]:
3747 if p1 != parents[0]:
3742 p1 = parents[0]
3748 p1 = parents[0]
3743 p2 = repo[nullid]
3749 p2 = repo[nullid]
3744 except error.RepoError:
3750 except error.RepoError:
3745 p1, p2 = parents
3751 p1, p2 = parents
3746 else:
3752 else:
3747 p1, p2 = parents
3753 p1, p2 = parents
3748
3754
3749 n = None
3755 n = None
3750 if update:
3756 if update:
3751 if p1 != parents[0]:
3757 if p1 != parents[0]:
3752 hg.clean(repo, p1.node())
3758 hg.clean(repo, p1.node())
3753 if p2 != parents[1]:
3759 if p2 != parents[1]:
3754 repo.setparents(p1.node(), p2.node())
3760 repo.setparents(p1.node(), p2.node())
3755
3761
3756 if opts.get('exact') or opts.get('import_branch'):
3762 if opts.get('exact') or opts.get('import_branch'):
3757 repo.dirstate.setbranch(branch or 'default')
3763 repo.dirstate.setbranch(branch or 'default')
3758
3764
3759 files = set()
3765 files = set()
3760 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3766 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3761 eolmode=None, similarity=sim / 100.0)
3767 eolmode=None, similarity=sim / 100.0)
3762 files = list(files)
3768 files = list(files)
3763 if opts.get('no_commit'):
3769 if opts.get('no_commit'):
3764 if message:
3770 if message:
3765 msgs.append(message)
3771 msgs.append(message)
3766 else:
3772 else:
3767 if opts.get('exact') or p2:
3773 if opts.get('exact') or p2:
3768 # If you got here, you either use --force and know what
3774 # If you got here, you either use --force and know what
3769 # you are doing or used --exact or a merge patch while
3775 # you are doing or used --exact or a merge patch while
3770 # being updated to its first parent.
3776 # being updated to its first parent.
3771 m = None
3777 m = None
3772 else:
3778 else:
3773 m = scmutil.matchfiles(repo, files or [])
3779 m = scmutil.matchfiles(repo, files or [])
3774 n = repo.commit(message, opts.get('user') or user,
3780 n = repo.commit(message, opts.get('user') or user,
3775 opts.get('date') or date, match=m,
3781 opts.get('date') or date, match=m,
3776 editor=editor)
3782 editor=editor)
3777 checkexact(repo, n, nodeid)
3783 checkexact(repo, n, nodeid)
3778 else:
3784 else:
3779 if opts.get('exact') or opts.get('import_branch'):
3785 if opts.get('exact') or opts.get('import_branch'):
3780 branch = branch or 'default'
3786 branch = branch or 'default'
3781 else:
3787 else:
3782 branch = p1.branch()
3788 branch = p1.branch()
3783 store = patch.filestore()
3789 store = patch.filestore()
3784 try:
3790 try:
3785 files = set()
3791 files = set()
3786 try:
3792 try:
3787 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3793 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3788 files, eolmode=None)
3794 files, eolmode=None)
3789 except patch.PatchError, e:
3795 except patch.PatchError, e:
3790 raise util.Abort(str(e))
3796 raise util.Abort(str(e))
3791 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3797 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3792 message,
3798 message,
3793 opts.get('user') or user,
3799 opts.get('user') or user,
3794 opts.get('date') or date,
3800 opts.get('date') or date,
3795 branch, files, store,
3801 branch, files, store,
3796 editor=cmdutil.commiteditor)
3802 editor=cmdutil.commiteditor)
3797 repo.savecommitmessage(memctx.description())
3803 repo.savecommitmessage(memctx.description())
3798 n = memctx.commit()
3804 n = memctx.commit()
3799 checkexact(repo, n, nodeid)
3805 checkexact(repo, n, nodeid)
3800 finally:
3806 finally:
3801 store.close()
3807 store.close()
3802 if n:
3808 if n:
3803 # i18n: refers to a short changeset id
3809 # i18n: refers to a short changeset id
3804 msg = _('created %s') % short(n)
3810 msg = _('created %s') % short(n)
3805 return (msg, n)
3811 return (msg, n)
3806 finally:
3812 finally:
3807 os.unlink(tmpname)
3813 os.unlink(tmpname)
3808
3814
3809 try:
3815 try:
3810 try:
3816 try:
3811 wlock = repo.wlock()
3817 wlock = repo.wlock()
3812 if not opts.get('no_commit'):
3818 if not opts.get('no_commit'):
3813 lock = repo.lock()
3819 lock = repo.lock()
3814 tr = repo.transaction('import')
3820 tr = repo.transaction('import')
3815 parents = repo.parents()
3821 parents = repo.parents()
3816 for patchurl in patches:
3822 for patchurl in patches:
3817 if patchurl == '-':
3823 if patchurl == '-':
3818 ui.status(_('applying patch from stdin\n'))
3824 ui.status(_('applying patch from stdin\n'))
3819 patchfile = ui.fin
3825 patchfile = ui.fin
3820 patchurl = 'stdin' # for error message
3826 patchurl = 'stdin' # for error message
3821 else:
3827 else:
3822 patchurl = os.path.join(base, patchurl)
3828 patchurl = os.path.join(base, patchurl)
3823 ui.status(_('applying %s\n') % patchurl)
3829 ui.status(_('applying %s\n') % patchurl)
3824 patchfile = url.open(ui, patchurl)
3830 patchfile = url.open(ui, patchurl)
3825
3831
3826 haspatch = False
3832 haspatch = False
3827 for hunk in patch.split(patchfile):
3833 for hunk in patch.split(patchfile):
3828 (msg, node) = tryone(ui, hunk, parents)
3834 (msg, node) = tryone(ui, hunk, parents)
3829 if msg:
3835 if msg:
3830 haspatch = True
3836 haspatch = True
3831 ui.note(msg + '\n')
3837 ui.note(msg + '\n')
3832 if update or opts.get('exact'):
3838 if update or opts.get('exact'):
3833 parents = repo.parents()
3839 parents = repo.parents()
3834 else:
3840 else:
3835 parents = [repo[node]]
3841 parents = [repo[node]]
3836
3842
3837 if not haspatch:
3843 if not haspatch:
3838 raise util.Abort(_('%s: no diffs found') % patchurl)
3844 raise util.Abort(_('%s: no diffs found') % patchurl)
3839
3845
3840 if tr:
3846 if tr:
3841 tr.close()
3847 tr.close()
3842 if msgs:
3848 if msgs:
3843 repo.savecommitmessage('\n* * *\n'.join(msgs))
3849 repo.savecommitmessage('\n* * *\n'.join(msgs))
3844 except: # re-raises
3850 except: # re-raises
3845 # wlock.release() indirectly calls dirstate.write(): since
3851 # wlock.release() indirectly calls dirstate.write(): since
3846 # we're crashing, we do not want to change the working dir
3852 # we're crashing, we do not want to change the working dir
3847 # parent after all, so make sure it writes nothing
3853 # parent after all, so make sure it writes nothing
3848 repo.dirstate.invalidate()
3854 repo.dirstate.invalidate()
3849 raise
3855 raise
3850 finally:
3856 finally:
3851 if tr:
3857 if tr:
3852 tr.release()
3858 tr.release()
3853 release(lock, wlock)
3859 release(lock, wlock)
3854
3860
3855 @command('incoming|in',
3861 @command('incoming|in',
3856 [('f', 'force', None,
3862 [('f', 'force', None,
3857 _('run even if remote repository is unrelated')),
3863 _('run even if remote repository is unrelated')),
3858 ('n', 'newest-first', None, _('show newest record first')),
3864 ('n', 'newest-first', None, _('show newest record first')),
3859 ('', 'bundle', '',
3865 ('', 'bundle', '',
3860 _('file to store the bundles into'), _('FILE')),
3866 _('file to store the bundles into'), _('FILE')),
3861 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3867 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3862 ('B', 'bookmarks', False, _("compare bookmarks")),
3868 ('B', 'bookmarks', False, _("compare bookmarks")),
3863 ('b', 'branch', [],
3869 ('b', 'branch', [],
3864 _('a specific branch you would like to pull'), _('BRANCH')),
3870 _('a specific branch you would like to pull'), _('BRANCH')),
3865 ] + logopts + remoteopts + subrepoopts,
3871 ] + logopts + remoteopts + subrepoopts,
3866 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3872 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3867 def incoming(ui, repo, source="default", **opts):
3873 def incoming(ui, repo, source="default", **opts):
3868 """show new changesets found in source
3874 """show new changesets found in source
3869
3875
3870 Show new changesets found in the specified path/URL or the default
3876 Show new changesets found in the specified path/URL or the default
3871 pull location. These are the changesets that would have been pulled
3877 pull location. These are the changesets that would have been pulled
3872 if a pull at the time you issued this command.
3878 if a pull at the time you issued this command.
3873
3879
3874 For remote repository, using --bundle avoids downloading the
3880 For remote repository, using --bundle avoids downloading the
3875 changesets twice if the incoming is followed by a pull.
3881 changesets twice if the incoming is followed by a pull.
3876
3882
3877 See pull for valid source format details.
3883 See pull for valid source format details.
3878
3884
3879 Returns 0 if there are incoming changes, 1 otherwise.
3885 Returns 0 if there are incoming changes, 1 otherwise.
3880 """
3886 """
3881 if opts.get('graph'):
3887 if opts.get('graph'):
3882 cmdutil.checkunsupportedgraphflags([], opts)
3888 cmdutil.checkunsupportedgraphflags([], opts)
3883 def display(other, chlist, displayer):
3889 def display(other, chlist, displayer):
3884 revdag = cmdutil.graphrevs(other, chlist, opts)
3890 revdag = cmdutil.graphrevs(other, chlist, opts)
3885 showparents = [ctx.node() for ctx in repo[None].parents()]
3891 showparents = [ctx.node() for ctx in repo[None].parents()]
3886 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3892 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3887 graphmod.asciiedges)
3893 graphmod.asciiedges)
3888
3894
3889 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3895 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3890 return 0
3896 return 0
3891
3897
3892 if opts.get('bundle') and opts.get('subrepos'):
3898 if opts.get('bundle') and opts.get('subrepos'):
3893 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3899 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3894
3900
3895 if opts.get('bookmarks'):
3901 if opts.get('bookmarks'):
3896 source, branches = hg.parseurl(ui.expandpath(source),
3902 source, branches = hg.parseurl(ui.expandpath(source),
3897 opts.get('branch'))
3903 opts.get('branch'))
3898 other = hg.peer(repo, opts, source)
3904 other = hg.peer(repo, opts, source)
3899 if 'bookmarks' not in other.listkeys('namespaces'):
3905 if 'bookmarks' not in other.listkeys('namespaces'):
3900 ui.warn(_("remote doesn't support bookmarks\n"))
3906 ui.warn(_("remote doesn't support bookmarks\n"))
3901 return 0
3907 return 0
3902 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3908 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3903 return bookmarks.diff(ui, repo, other)
3909 return bookmarks.diff(ui, repo, other)
3904
3910
3905 repo._subtoppath = ui.expandpath(source)
3911 repo._subtoppath = ui.expandpath(source)
3906 try:
3912 try:
3907 return hg.incoming(ui, repo, source, opts)
3913 return hg.incoming(ui, repo, source, opts)
3908 finally:
3914 finally:
3909 del repo._subtoppath
3915 del repo._subtoppath
3910
3916
3911
3917
3912 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3918 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3913 def init(ui, dest=".", **opts):
3919 def init(ui, dest=".", **opts):
3914 """create a new repository in the given directory
3920 """create a new repository in the given directory
3915
3921
3916 Initialize a new repository in the given directory. If the given
3922 Initialize a new repository in the given directory. If the given
3917 directory does not exist, it will be created.
3923 directory does not exist, it will be created.
3918
3924
3919 If no directory is given, the current directory is used.
3925 If no directory is given, the current directory is used.
3920
3926
3921 It is possible to specify an ``ssh://`` URL as the destination.
3927 It is possible to specify an ``ssh://`` URL as the destination.
3922 See :hg:`help urls` for more information.
3928 See :hg:`help urls` for more information.
3923
3929
3924 Returns 0 on success.
3930 Returns 0 on success.
3925 """
3931 """
3926 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3932 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3927
3933
3928 @command('locate',
3934 @command('locate',
3929 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3935 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3930 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3936 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3931 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3937 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3932 ] + walkopts,
3938 ] + walkopts,
3933 _('[OPTION]... [PATTERN]...'))
3939 _('[OPTION]... [PATTERN]...'))
3934 def locate(ui, repo, *pats, **opts):
3940 def locate(ui, repo, *pats, **opts):
3935 """locate files matching specific patterns
3941 """locate files matching specific patterns
3936
3942
3937 Print files under Mercurial control in the working directory whose
3943 Print files under Mercurial control in the working directory whose
3938 names match the given patterns.
3944 names match the given patterns.
3939
3945
3940 By default, this command searches all directories in the working
3946 By default, this command searches all directories in the working
3941 directory. To search just the current directory and its
3947 directory. To search just the current directory and its
3942 subdirectories, use "--include .".
3948 subdirectories, use "--include .".
3943
3949
3944 If no patterns are given to match, this command prints the names
3950 If no patterns are given to match, this command prints the names
3945 of all files under Mercurial control in the working directory.
3951 of all files under Mercurial control in the working directory.
3946
3952
3947 If you want to feed the output of this command into the "xargs"
3953 If you want to feed the output of this command into the "xargs"
3948 command, use the -0 option to both this command and "xargs". This
3954 command, use the -0 option to both this command and "xargs". This
3949 will avoid the problem of "xargs" treating single filenames that
3955 will avoid the problem of "xargs" treating single filenames that
3950 contain whitespace as multiple filenames.
3956 contain whitespace as multiple filenames.
3951
3957
3952 Returns 0 if a match is found, 1 otherwise.
3958 Returns 0 if a match is found, 1 otherwise.
3953 """
3959 """
3954 end = opts.get('print0') and '\0' or '\n'
3960 end = opts.get('print0') and '\0' or '\n'
3955 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3961 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3956
3962
3957 ret = 1
3963 ret = 1
3958 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3964 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3959 m.bad = lambda x, y: False
3965 m.bad = lambda x, y: False
3960 for abs in repo[rev].walk(m):
3966 for abs in repo[rev].walk(m):
3961 if not rev and abs not in repo.dirstate:
3967 if not rev and abs not in repo.dirstate:
3962 continue
3968 continue
3963 if opts.get('fullpath'):
3969 if opts.get('fullpath'):
3964 ui.write(repo.wjoin(abs), end)
3970 ui.write(repo.wjoin(abs), end)
3965 else:
3971 else:
3966 ui.write(((pats and m.rel(abs)) or abs), end)
3972 ui.write(((pats and m.rel(abs)) or abs), end)
3967 ret = 0
3973 ret = 0
3968
3974
3969 return ret
3975 return ret
3970
3976
3971 @command('^log|history',
3977 @command('^log|history',
3972 [('f', 'follow', None,
3978 [('f', 'follow', None,
3973 _('follow changeset history, or file history across copies and renames')),
3979 _('follow changeset history, or file history across copies and renames')),
3974 ('', 'follow-first', None,
3980 ('', 'follow-first', None,
3975 _('only follow the first parent of merge changesets (DEPRECATED)')),
3981 _('only follow the first parent of merge changesets (DEPRECATED)')),
3976 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3982 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3977 ('C', 'copies', None, _('show copied files')),
3983 ('C', 'copies', None, _('show copied files')),
3978 ('k', 'keyword', [],
3984 ('k', 'keyword', [],
3979 _('do case-insensitive search for a given text'), _('TEXT')),
3985 _('do case-insensitive search for a given text'), _('TEXT')),
3980 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3986 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3981 ('', 'removed', None, _('include revisions where files were removed')),
3987 ('', 'removed', None, _('include revisions where files were removed')),
3982 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3988 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3983 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3989 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3984 ('', 'only-branch', [],
3990 ('', 'only-branch', [],
3985 _('show only changesets within the given named branch (DEPRECATED)'),
3991 _('show only changesets within the given named branch (DEPRECATED)'),
3986 _('BRANCH')),
3992 _('BRANCH')),
3987 ('b', 'branch', [],
3993 ('b', 'branch', [],
3988 _('show changesets within the given named branch'), _('BRANCH')),
3994 _('show changesets within the given named branch'), _('BRANCH')),
3989 ('P', 'prune', [],
3995 ('P', 'prune', [],
3990 _('do not display revision or any of its ancestors'), _('REV')),
3996 _('do not display revision or any of its ancestors'), _('REV')),
3991 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3997 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3992 ] + logopts + walkopts,
3998 ] + logopts + walkopts,
3993 _('[OPTION]... [FILE]'))
3999 _('[OPTION]... [FILE]'))
3994 def log(ui, repo, *pats, **opts):
4000 def log(ui, repo, *pats, **opts):
3995 """show revision history of entire repository or files
4001 """show revision history of entire repository or files
3996
4002
3997 Print the revision history of the specified files or the entire
4003 Print the revision history of the specified files or the entire
3998 project.
4004 project.
3999
4005
4000 If no revision range is specified, the default is ``tip:0`` unless
4006 If no revision range is specified, the default is ``tip:0`` unless
4001 --follow is set, in which case the working directory parent is
4007 --follow is set, in which case the working directory parent is
4002 used as the starting revision.
4008 used as the starting revision.
4003
4009
4004 File history is shown without following rename or copy history of
4010 File history is shown without following rename or copy history of
4005 files. Use -f/--follow with a filename to follow history across
4011 files. Use -f/--follow with a filename to follow history across
4006 renames and copies. --follow without a filename will only show
4012 renames and copies. --follow without a filename will only show
4007 ancestors or descendants of the starting revision.
4013 ancestors or descendants of the starting revision.
4008
4014
4009 By default this command prints revision number and changeset id,
4015 By default this command prints revision number and changeset id,
4010 tags, non-trivial parents, user, date and time, and a summary for
4016 tags, non-trivial parents, user, date and time, and a summary for
4011 each commit. When the -v/--verbose switch is used, the list of
4017 each commit. When the -v/--verbose switch is used, the list of
4012 changed files and full commit message are shown.
4018 changed files and full commit message are shown.
4013
4019
4014 .. note::
4020 .. note::
4015 log -p/--patch may generate unexpected diff output for merge
4021 log -p/--patch may generate unexpected diff output for merge
4016 changesets, as it will only compare the merge changeset against
4022 changesets, as it will only compare the merge changeset against
4017 its first parent. Also, only files different from BOTH parents
4023 its first parent. Also, only files different from BOTH parents
4018 will appear in files:.
4024 will appear in files:.
4019
4025
4020 .. note::
4026 .. note::
4021 for performance reasons, log FILE may omit duplicate changes
4027 for performance reasons, log FILE may omit duplicate changes
4022 made on branches and will not show deletions. To see all
4028 made on branches and will not show deletions. To see all
4023 changes including duplicates and deletions, use the --removed
4029 changes including duplicates and deletions, use the --removed
4024 switch.
4030 switch.
4025
4031
4026 .. container:: verbose
4032 .. container:: verbose
4027
4033
4028 Some examples:
4034 Some examples:
4029
4035
4030 - changesets with full descriptions and file lists::
4036 - changesets with full descriptions and file lists::
4031
4037
4032 hg log -v
4038 hg log -v
4033
4039
4034 - changesets ancestral to the working directory::
4040 - changesets ancestral to the working directory::
4035
4041
4036 hg log -f
4042 hg log -f
4037
4043
4038 - last 10 commits on the current branch::
4044 - last 10 commits on the current branch::
4039
4045
4040 hg log -l 10 -b .
4046 hg log -l 10 -b .
4041
4047
4042 - changesets showing all modifications of a file, including removals::
4048 - changesets showing all modifications of a file, including removals::
4043
4049
4044 hg log --removed file.c
4050 hg log --removed file.c
4045
4051
4046 - all changesets that touch a directory, with diffs, excluding merges::
4052 - all changesets that touch a directory, with diffs, excluding merges::
4047
4053
4048 hg log -Mp lib/
4054 hg log -Mp lib/
4049
4055
4050 - all revision numbers that match a keyword::
4056 - all revision numbers that match a keyword::
4051
4057
4052 hg log -k bug --template "{rev}\\n"
4058 hg log -k bug --template "{rev}\\n"
4053
4059
4054 - check if a given changeset is included is a tagged release::
4060 - check if a given changeset is included is a tagged release::
4055
4061
4056 hg log -r "a21ccf and ancestor(1.9)"
4062 hg log -r "a21ccf and ancestor(1.9)"
4057
4063
4058 - find all changesets by some user in a date range::
4064 - find all changesets by some user in a date range::
4059
4065
4060 hg log -k alice -d "may 2008 to jul 2008"
4066 hg log -k alice -d "may 2008 to jul 2008"
4061
4067
4062 - summary of all changesets after the last tag::
4068 - summary of all changesets after the last tag::
4063
4069
4064 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4070 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4065
4071
4066 See :hg:`help dates` for a list of formats valid for -d/--date.
4072 See :hg:`help dates` for a list of formats valid for -d/--date.
4067
4073
4068 See :hg:`help revisions` and :hg:`help revsets` for more about
4074 See :hg:`help revisions` and :hg:`help revsets` for more about
4069 specifying revisions.
4075 specifying revisions.
4070
4076
4071 See :hg:`help templates` for more about pre-packaged styles and
4077 See :hg:`help templates` for more about pre-packaged styles and
4072 specifying custom templates.
4078 specifying custom templates.
4073
4079
4074 Returns 0 on success.
4080 Returns 0 on success.
4075 """
4081 """
4076 if opts.get('graph'):
4082 if opts.get('graph'):
4077 return cmdutil.graphlog(ui, repo, *pats, **opts)
4083 return cmdutil.graphlog(ui, repo, *pats, **opts)
4078
4084
4079 matchfn = scmutil.match(repo[None], pats, opts)
4085 matchfn = scmutil.match(repo[None], pats, opts)
4080 limit = cmdutil.loglimit(opts)
4086 limit = cmdutil.loglimit(opts)
4081 count = 0
4087 count = 0
4082
4088
4083 getrenamed, endrev = None, None
4089 getrenamed, endrev = None, None
4084 if opts.get('copies'):
4090 if opts.get('copies'):
4085 if opts.get('rev'):
4091 if opts.get('rev'):
4086 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4092 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4087 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4093 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4088
4094
4089 df = False
4095 df = False
4090 if opts.get("date"):
4096 if opts.get("date"):
4091 df = util.matchdate(opts["date"])
4097 df = util.matchdate(opts["date"])
4092
4098
4093 branches = opts.get('branch', []) + opts.get('only_branch', [])
4099 branches = opts.get('branch', []) + opts.get('only_branch', [])
4094 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4100 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4095
4101
4096 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4102 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4097 def prep(ctx, fns):
4103 def prep(ctx, fns):
4098 rev = ctx.rev()
4104 rev = ctx.rev()
4099 parents = [p for p in repo.changelog.parentrevs(rev)
4105 parents = [p for p in repo.changelog.parentrevs(rev)
4100 if p != nullrev]
4106 if p != nullrev]
4101 if opts.get('no_merges') and len(parents) == 2:
4107 if opts.get('no_merges') and len(parents) == 2:
4102 return
4108 return
4103 if opts.get('only_merges') and len(parents) != 2:
4109 if opts.get('only_merges') and len(parents) != 2:
4104 return
4110 return
4105 if opts.get('branch') and ctx.branch() not in opts['branch']:
4111 if opts.get('branch') and ctx.branch() not in opts['branch']:
4106 return
4112 return
4107 if not opts.get('hidden') and ctx.hidden():
4113 if not opts.get('hidden') and ctx.hidden():
4108 return
4114 return
4109 if df and not df(ctx.date()[0]):
4115 if df and not df(ctx.date()[0]):
4110 return
4116 return
4111
4117
4112 lower = encoding.lower
4118 lower = encoding.lower
4113 if opts.get('user'):
4119 if opts.get('user'):
4114 luser = lower(ctx.user())
4120 luser = lower(ctx.user())
4115 for k in [lower(x) for x in opts['user']]:
4121 for k in [lower(x) for x in opts['user']]:
4116 if (k in luser):
4122 if (k in luser):
4117 break
4123 break
4118 else:
4124 else:
4119 return
4125 return
4120 if opts.get('keyword'):
4126 if opts.get('keyword'):
4121 luser = lower(ctx.user())
4127 luser = lower(ctx.user())
4122 ldesc = lower(ctx.description())
4128 ldesc = lower(ctx.description())
4123 lfiles = lower(" ".join(ctx.files()))
4129 lfiles = lower(" ".join(ctx.files()))
4124 for k in [lower(x) for x in opts['keyword']]:
4130 for k in [lower(x) for x in opts['keyword']]:
4125 if (k in luser or k in ldesc or k in lfiles):
4131 if (k in luser or k in ldesc or k in lfiles):
4126 break
4132 break
4127 else:
4133 else:
4128 return
4134 return
4129
4135
4130 copies = None
4136 copies = None
4131 if getrenamed is not None and rev:
4137 if getrenamed is not None and rev:
4132 copies = []
4138 copies = []
4133 for fn in ctx.files():
4139 for fn in ctx.files():
4134 rename = getrenamed(fn, rev)
4140 rename = getrenamed(fn, rev)
4135 if rename:
4141 if rename:
4136 copies.append((fn, rename[0]))
4142 copies.append((fn, rename[0]))
4137
4143
4138 revmatchfn = None
4144 revmatchfn = None
4139 if opts.get('patch') or opts.get('stat'):
4145 if opts.get('patch') or opts.get('stat'):
4140 if opts.get('follow') or opts.get('follow_first'):
4146 if opts.get('follow') or opts.get('follow_first'):
4141 # note: this might be wrong when following through merges
4147 # note: this might be wrong when following through merges
4142 revmatchfn = scmutil.match(repo[None], fns, default='path')
4148 revmatchfn = scmutil.match(repo[None], fns, default='path')
4143 else:
4149 else:
4144 revmatchfn = matchfn
4150 revmatchfn = matchfn
4145
4151
4146 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4152 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4147
4153
4148 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4149 if count == limit:
4155 if count == limit:
4150 break
4156 break
4151 if displayer.flush(ctx.rev()):
4157 if displayer.flush(ctx.rev()):
4152 count += 1
4158 count += 1
4153 displayer.close()
4159 displayer.close()
4154
4160
4155 @command('manifest',
4161 @command('manifest',
4156 [('r', 'rev', '', _('revision to display'), _('REV')),
4162 [('r', 'rev', '', _('revision to display'), _('REV')),
4157 ('', 'all', False, _("list files from all revisions"))],
4163 ('', 'all', False, _("list files from all revisions"))],
4158 _('[-r REV]'))
4164 _('[-r REV]'))
4159 def manifest(ui, repo, node=None, rev=None, **opts):
4165 def manifest(ui, repo, node=None, rev=None, **opts):
4160 """output the current or given revision of the project manifest
4166 """output the current or given revision of the project manifest
4161
4167
4162 Print a list of version controlled files for the given revision.
4168 Print a list of version controlled files for the given revision.
4163 If no revision is given, the first parent of the working directory
4169 If no revision is given, the first parent of the working directory
4164 is used, or the null revision if no revision is checked out.
4170 is used, or the null revision if no revision is checked out.
4165
4171
4166 With -v, print file permissions, symlink and executable bits.
4172 With -v, print file permissions, symlink and executable bits.
4167 With --debug, print file revision hashes.
4173 With --debug, print file revision hashes.
4168
4174
4169 If option --all is specified, the list of all files from all revisions
4175 If option --all is specified, the list of all files from all revisions
4170 is printed. This includes deleted and renamed files.
4176 is printed. This includes deleted and renamed files.
4171
4177
4172 Returns 0 on success.
4178 Returns 0 on success.
4173 """
4179 """
4174 if opts.get('all'):
4180 if opts.get('all'):
4175 if rev or node:
4181 if rev or node:
4176 raise util.Abort(_("can't specify a revision with --all"))
4182 raise util.Abort(_("can't specify a revision with --all"))
4177
4183
4178 res = []
4184 res = []
4179 prefix = "data/"
4185 prefix = "data/"
4180 suffix = ".i"
4186 suffix = ".i"
4181 plen = len(prefix)
4187 plen = len(prefix)
4182 slen = len(suffix)
4188 slen = len(suffix)
4183 lock = repo.lock()
4189 lock = repo.lock()
4184 try:
4190 try:
4185 for fn, b, size in repo.store.datafiles():
4191 for fn, b, size in repo.store.datafiles():
4186 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4192 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4187 res.append(fn[plen:-slen])
4193 res.append(fn[plen:-slen])
4188 finally:
4194 finally:
4189 lock.release()
4195 lock.release()
4190 for f in res:
4196 for f in res:
4191 ui.write("%s\n" % f)
4197 ui.write("%s\n" % f)
4192 return
4198 return
4193
4199
4194 if rev and node:
4200 if rev and node:
4195 raise util.Abort(_("please specify just one revision"))
4201 raise util.Abort(_("please specify just one revision"))
4196
4202
4197 if not node:
4203 if not node:
4198 node = rev
4204 node = rev
4199
4205
4200 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4206 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4201 ctx = scmutil.revsingle(repo, node)
4207 ctx = scmutil.revsingle(repo, node)
4202 for f in ctx:
4208 for f in ctx:
4203 if ui.debugflag:
4209 if ui.debugflag:
4204 ui.write("%40s " % hex(ctx.manifest()[f]))
4210 ui.write("%40s " % hex(ctx.manifest()[f]))
4205 if ui.verbose:
4211 if ui.verbose:
4206 ui.write(decor[ctx.flags(f)])
4212 ui.write(decor[ctx.flags(f)])
4207 ui.write("%s\n" % f)
4213 ui.write("%s\n" % f)
4208
4214
4209 @command('^merge',
4215 @command('^merge',
4210 [('f', 'force', None, _('force a merge with outstanding changes')),
4216 [('f', 'force', None, _('force a merge with outstanding changes')),
4211 ('r', 'rev', '', _('revision to merge'), _('REV')),
4217 ('r', 'rev', '', _('revision to merge'), _('REV')),
4212 ('P', 'preview', None,
4218 ('P', 'preview', None,
4213 _('review revisions to merge (no merge is performed)'))
4219 _('review revisions to merge (no merge is performed)'))
4214 ] + mergetoolopts,
4220 ] + mergetoolopts,
4215 _('[-P] [-f] [[-r] REV]'))
4221 _('[-P] [-f] [[-r] REV]'))
4216 def merge(ui, repo, node=None, **opts):
4222 def merge(ui, repo, node=None, **opts):
4217 """merge working directory with another revision
4223 """merge working directory with another revision
4218
4224
4219 The current working directory is updated with all changes made in
4225 The current working directory is updated with all changes made in
4220 the requested revision since the last common predecessor revision.
4226 the requested revision since the last common predecessor revision.
4221
4227
4222 Files that changed between either parent are marked as changed for
4228 Files that changed between either parent are marked as changed for
4223 the next commit and a commit must be performed before any further
4229 the next commit and a commit must be performed before any further
4224 updates to the repository are allowed. The next commit will have
4230 updates to the repository are allowed. The next commit will have
4225 two parents.
4231 two parents.
4226
4232
4227 ``--tool`` can be used to specify the merge tool used for file
4233 ``--tool`` can be used to specify the merge tool used for file
4228 merges. It overrides the HGMERGE environment variable and your
4234 merges. It overrides the HGMERGE environment variable and your
4229 configuration files. See :hg:`help merge-tools` for options.
4235 configuration files. See :hg:`help merge-tools` for options.
4230
4236
4231 If no revision is specified, the working directory's parent is a
4237 If no revision is specified, the working directory's parent is a
4232 head revision, and the current branch contains exactly one other
4238 head revision, and the current branch contains exactly one other
4233 head, the other head is merged with by default. Otherwise, an
4239 head, the other head is merged with by default. Otherwise, an
4234 explicit revision with which to merge with must be provided.
4240 explicit revision with which to merge with must be provided.
4235
4241
4236 :hg:`resolve` must be used to resolve unresolved files.
4242 :hg:`resolve` must be used to resolve unresolved files.
4237
4243
4238 To undo an uncommitted merge, use :hg:`update --clean .` which
4244 To undo an uncommitted merge, use :hg:`update --clean .` which
4239 will check out a clean copy of the original merge parent, losing
4245 will check out a clean copy of the original merge parent, losing
4240 all changes.
4246 all changes.
4241
4247
4242 Returns 0 on success, 1 if there are unresolved files.
4248 Returns 0 on success, 1 if there are unresolved files.
4243 """
4249 """
4244
4250
4245 if opts.get('rev') and node:
4251 if opts.get('rev') and node:
4246 raise util.Abort(_("please specify just one revision"))
4252 raise util.Abort(_("please specify just one revision"))
4247 if not node:
4253 if not node:
4248 node = opts.get('rev')
4254 node = opts.get('rev')
4249
4255
4250 if node:
4256 if node:
4251 node = scmutil.revsingle(repo, node).node()
4257 node = scmutil.revsingle(repo, node).node()
4252
4258
4253 if not node and repo._bookmarkcurrent:
4259 if not node and repo._bookmarkcurrent:
4254 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4260 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4255 curhead = repo[repo._bookmarkcurrent]
4261 curhead = repo[repo._bookmarkcurrent]
4256 if len(bmheads) == 2:
4262 if len(bmheads) == 2:
4257 if curhead == bmheads[0]:
4263 if curhead == bmheads[0]:
4258 node = bmheads[1]
4264 node = bmheads[1]
4259 else:
4265 else:
4260 node = bmheads[0]
4266 node = bmheads[0]
4261 elif len(bmheads) > 2:
4267 elif len(bmheads) > 2:
4262 raise util.Abort(_("multiple matching bookmarks to merge - "
4268 raise util.Abort(_("multiple matching bookmarks to merge - "
4263 "please merge with an explicit rev or bookmark"),
4269 "please merge with an explicit rev or bookmark"),
4264 hint=_("run 'hg heads' to see all heads"))
4270 hint=_("run 'hg heads' to see all heads"))
4265 elif len(bmheads) <= 1:
4271 elif len(bmheads) <= 1:
4266 raise util.Abort(_("no matching bookmark to merge - "
4272 raise util.Abort(_("no matching bookmark to merge - "
4267 "please merge with an explicit rev or bookmark"),
4273 "please merge with an explicit rev or bookmark"),
4268 hint=_("run 'hg heads' to see all heads"))
4274 hint=_("run 'hg heads' to see all heads"))
4269
4275
4270 if not node and not repo._bookmarkcurrent:
4276 if not node and not repo._bookmarkcurrent:
4271 branch = repo[None].branch()
4277 branch = repo[None].branch()
4272 bheads = repo.branchheads(branch)
4278 bheads = repo.branchheads(branch)
4273 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4279 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4274
4280
4275 if len(nbhs) > 2:
4281 if len(nbhs) > 2:
4276 raise util.Abort(_("branch '%s' has %d heads - "
4282 raise util.Abort(_("branch '%s' has %d heads - "
4277 "please merge with an explicit rev")
4283 "please merge with an explicit rev")
4278 % (branch, len(bheads)),
4284 % (branch, len(bheads)),
4279 hint=_("run 'hg heads .' to see heads"))
4285 hint=_("run 'hg heads .' to see heads"))
4280
4286
4281 parent = repo.dirstate.p1()
4287 parent = repo.dirstate.p1()
4282 if len(nbhs) <= 1:
4288 if len(nbhs) <= 1:
4283 if len(bheads) > 1:
4289 if len(bheads) > 1:
4284 raise util.Abort(_("heads are bookmarked - "
4290 raise util.Abort(_("heads are bookmarked - "
4285 "please merge with an explicit rev"),
4291 "please merge with an explicit rev"),
4286 hint=_("run 'hg heads' to see all heads"))
4292 hint=_("run 'hg heads' to see all heads"))
4287 if len(repo.heads()) > 1:
4293 if len(repo.heads()) > 1:
4288 raise util.Abort(_("branch '%s' has one head - "
4294 raise util.Abort(_("branch '%s' has one head - "
4289 "please merge with an explicit rev")
4295 "please merge with an explicit rev")
4290 % branch,
4296 % branch,
4291 hint=_("run 'hg heads' to see all heads"))
4297 hint=_("run 'hg heads' to see all heads"))
4292 msg, hint = _('nothing to merge'), None
4298 msg, hint = _('nothing to merge'), None
4293 if parent != repo.lookup(branch):
4299 if parent != repo.lookup(branch):
4294 hint = _("use 'hg update' instead")
4300 hint = _("use 'hg update' instead")
4295 raise util.Abort(msg, hint=hint)
4301 raise util.Abort(msg, hint=hint)
4296
4302
4297 if parent not in bheads:
4303 if parent not in bheads:
4298 raise util.Abort(_('working directory not at a head revision'),
4304 raise util.Abort(_('working directory not at a head revision'),
4299 hint=_("use 'hg update' or merge with an "
4305 hint=_("use 'hg update' or merge with an "
4300 "explicit revision"))
4306 "explicit revision"))
4301 if parent == nbhs[0]:
4307 if parent == nbhs[0]:
4302 node = nbhs[-1]
4308 node = nbhs[-1]
4303 else:
4309 else:
4304 node = nbhs[0]
4310 node = nbhs[0]
4305
4311
4306 if opts.get('preview'):
4312 if opts.get('preview'):
4307 # find nodes that are ancestors of p2 but not of p1
4313 # find nodes that are ancestors of p2 but not of p1
4308 p1 = repo.lookup('.')
4314 p1 = repo.lookup('.')
4309 p2 = repo.lookup(node)
4315 p2 = repo.lookup(node)
4310 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4316 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4311
4317
4312 displayer = cmdutil.show_changeset(ui, repo, opts)
4318 displayer = cmdutil.show_changeset(ui, repo, opts)
4313 for node in nodes:
4319 for node in nodes:
4314 displayer.show(repo[node])
4320 displayer.show(repo[node])
4315 displayer.close()
4321 displayer.close()
4316 return 0
4322 return 0
4317
4323
4318 try:
4324 try:
4319 # ui.forcemerge is an internal variable, do not document
4325 # ui.forcemerge is an internal variable, do not document
4320 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4326 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4321 return hg.merge(repo, node, force=opts.get('force'))
4327 return hg.merge(repo, node, force=opts.get('force'))
4322 finally:
4328 finally:
4323 ui.setconfig('ui', 'forcemerge', '')
4329 ui.setconfig('ui', 'forcemerge', '')
4324
4330
4325 @command('outgoing|out',
4331 @command('outgoing|out',
4326 [('f', 'force', None, _('run even when the destination is unrelated')),
4332 [('f', 'force', None, _('run even when the destination is unrelated')),
4327 ('r', 'rev', [],
4333 ('r', 'rev', [],
4328 _('a changeset intended to be included in the destination'), _('REV')),
4334 _('a changeset intended to be included in the destination'), _('REV')),
4329 ('n', 'newest-first', None, _('show newest record first')),
4335 ('n', 'newest-first', None, _('show newest record first')),
4330 ('B', 'bookmarks', False, _('compare bookmarks')),
4336 ('B', 'bookmarks', False, _('compare bookmarks')),
4331 ('b', 'branch', [], _('a specific branch you would like to push'),
4337 ('b', 'branch', [], _('a specific branch you would like to push'),
4332 _('BRANCH')),
4338 _('BRANCH')),
4333 ] + logopts + remoteopts + subrepoopts,
4339 ] + logopts + remoteopts + subrepoopts,
4334 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4340 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4335 def outgoing(ui, repo, dest=None, **opts):
4341 def outgoing(ui, repo, dest=None, **opts):
4336 """show changesets not found in the destination
4342 """show changesets not found in the destination
4337
4343
4338 Show changesets not found in the specified destination repository
4344 Show changesets not found in the specified destination repository
4339 or the default push location. These are the changesets that would
4345 or the default push location. These are the changesets that would
4340 be pushed if a push was requested.
4346 be pushed if a push was requested.
4341
4347
4342 See pull for details of valid destination formats.
4348 See pull for details of valid destination formats.
4343
4349
4344 Returns 0 if there are outgoing changes, 1 otherwise.
4350 Returns 0 if there are outgoing changes, 1 otherwise.
4345 """
4351 """
4346 if opts.get('graph'):
4352 if opts.get('graph'):
4347 cmdutil.checkunsupportedgraphflags([], opts)
4353 cmdutil.checkunsupportedgraphflags([], opts)
4348 o = hg._outgoing(ui, repo, dest, opts)
4354 o = hg._outgoing(ui, repo, dest, opts)
4349 if o is None:
4355 if o is None:
4350 return
4356 return
4351
4357
4352 revdag = cmdutil.graphrevs(repo, o, opts)
4358 revdag = cmdutil.graphrevs(repo, o, opts)
4353 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4359 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4354 showparents = [ctx.node() for ctx in repo[None].parents()]
4360 showparents = [ctx.node() for ctx in repo[None].parents()]
4355 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4361 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4356 graphmod.asciiedges)
4362 graphmod.asciiedges)
4357 return 0
4363 return 0
4358
4364
4359 if opts.get('bookmarks'):
4365 if opts.get('bookmarks'):
4360 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4366 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4361 dest, branches = hg.parseurl(dest, opts.get('branch'))
4367 dest, branches = hg.parseurl(dest, opts.get('branch'))
4362 other = hg.peer(repo, opts, dest)
4368 other = hg.peer(repo, opts, dest)
4363 if 'bookmarks' not in other.listkeys('namespaces'):
4369 if 'bookmarks' not in other.listkeys('namespaces'):
4364 ui.warn(_("remote doesn't support bookmarks\n"))
4370 ui.warn(_("remote doesn't support bookmarks\n"))
4365 return 0
4371 return 0
4366 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4372 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4367 return bookmarks.diff(ui, other, repo)
4373 return bookmarks.diff(ui, other, repo)
4368
4374
4369 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4375 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4370 try:
4376 try:
4371 return hg.outgoing(ui, repo, dest, opts)
4377 return hg.outgoing(ui, repo, dest, opts)
4372 finally:
4378 finally:
4373 del repo._subtoppath
4379 del repo._subtoppath
4374
4380
4375 @command('parents',
4381 @command('parents',
4376 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4382 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4377 ] + templateopts,
4383 ] + templateopts,
4378 _('[-r REV] [FILE]'))
4384 _('[-r REV] [FILE]'))
4379 def parents(ui, repo, file_=None, **opts):
4385 def parents(ui, repo, file_=None, **opts):
4380 """show the parents of the working directory or revision
4386 """show the parents of the working directory or revision
4381
4387
4382 Print the working directory's parent revisions. If a revision is
4388 Print the working directory's parent revisions. If a revision is
4383 given via -r/--rev, the parent of that revision will be printed.
4389 given via -r/--rev, the parent of that revision will be printed.
4384 If a file argument is given, the revision in which the file was
4390 If a file argument is given, the revision in which the file was
4385 last changed (before the working directory revision or the
4391 last changed (before the working directory revision or the
4386 argument to --rev if given) is printed.
4392 argument to --rev if given) is printed.
4387
4393
4388 Returns 0 on success.
4394 Returns 0 on success.
4389 """
4395 """
4390
4396
4391 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4397 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4392
4398
4393 if file_:
4399 if file_:
4394 m = scmutil.match(ctx, (file_,), opts)
4400 m = scmutil.match(ctx, (file_,), opts)
4395 if m.anypats() or len(m.files()) != 1:
4401 if m.anypats() or len(m.files()) != 1:
4396 raise util.Abort(_('can only specify an explicit filename'))
4402 raise util.Abort(_('can only specify an explicit filename'))
4397 file_ = m.files()[0]
4403 file_ = m.files()[0]
4398 filenodes = []
4404 filenodes = []
4399 for cp in ctx.parents():
4405 for cp in ctx.parents():
4400 if not cp:
4406 if not cp:
4401 continue
4407 continue
4402 try:
4408 try:
4403 filenodes.append(cp.filenode(file_))
4409 filenodes.append(cp.filenode(file_))
4404 except error.LookupError:
4410 except error.LookupError:
4405 pass
4411 pass
4406 if not filenodes:
4412 if not filenodes:
4407 raise util.Abort(_("'%s' not found in manifest!") % file_)
4413 raise util.Abort(_("'%s' not found in manifest!") % file_)
4408 fl = repo.file(file_)
4414 fl = repo.file(file_)
4409 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4415 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4410 else:
4416 else:
4411 p = [cp.node() for cp in ctx.parents()]
4417 p = [cp.node() for cp in ctx.parents()]
4412
4418
4413 displayer = cmdutil.show_changeset(ui, repo, opts)
4419 displayer = cmdutil.show_changeset(ui, repo, opts)
4414 for n in p:
4420 for n in p:
4415 if n != nullid:
4421 if n != nullid:
4416 displayer.show(repo[n])
4422 displayer.show(repo[n])
4417 displayer.close()
4423 displayer.close()
4418
4424
4419 @command('paths', [], _('[NAME]'))
4425 @command('paths', [], _('[NAME]'))
4420 def paths(ui, repo, search=None):
4426 def paths(ui, repo, search=None):
4421 """show aliases for remote repositories
4427 """show aliases for remote repositories
4422
4428
4423 Show definition of symbolic path name NAME. If no name is given,
4429 Show definition of symbolic path name NAME. If no name is given,
4424 show definition of all available names.
4430 show definition of all available names.
4425
4431
4426 Option -q/--quiet suppresses all output when searching for NAME
4432 Option -q/--quiet suppresses all output when searching for NAME
4427 and shows only the path names when listing all definitions.
4433 and shows only the path names when listing all definitions.
4428
4434
4429 Path names are defined in the [paths] section of your
4435 Path names are defined in the [paths] section of your
4430 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4436 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4431 repository, ``.hg/hgrc`` is used, too.
4437 repository, ``.hg/hgrc`` is used, too.
4432
4438
4433 The path names ``default`` and ``default-push`` have a special
4439 The path names ``default`` and ``default-push`` have a special
4434 meaning. When performing a push or pull operation, they are used
4440 meaning. When performing a push or pull operation, they are used
4435 as fallbacks if no location is specified on the command-line.
4441 as fallbacks if no location is specified on the command-line.
4436 When ``default-push`` is set, it will be used for push and
4442 When ``default-push`` is set, it will be used for push and
4437 ``default`` will be used for pull; otherwise ``default`` is used
4443 ``default`` will be used for pull; otherwise ``default`` is used
4438 as the fallback for both. When cloning a repository, the clone
4444 as the fallback for both. When cloning a repository, the clone
4439 source is written as ``default`` in ``.hg/hgrc``. Note that
4445 source is written as ``default`` in ``.hg/hgrc``. Note that
4440 ``default`` and ``default-push`` apply to all inbound (e.g.
4446 ``default`` and ``default-push`` apply to all inbound (e.g.
4441 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4447 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4442 :hg:`bundle`) operations.
4448 :hg:`bundle`) operations.
4443
4449
4444 See :hg:`help urls` for more information.
4450 See :hg:`help urls` for more information.
4445
4451
4446 Returns 0 on success.
4452 Returns 0 on success.
4447 """
4453 """
4448 if search:
4454 if search:
4449 for name, path in ui.configitems("paths"):
4455 for name, path in ui.configitems("paths"):
4450 if name == search:
4456 if name == search:
4451 ui.status("%s\n" % util.hidepassword(path))
4457 ui.status("%s\n" % util.hidepassword(path))
4452 return
4458 return
4453 if not ui.quiet:
4459 if not ui.quiet:
4454 ui.warn(_("not found!\n"))
4460 ui.warn(_("not found!\n"))
4455 return 1
4461 return 1
4456 else:
4462 else:
4457 for name, path in ui.configitems("paths"):
4463 for name, path in ui.configitems("paths"):
4458 if ui.quiet:
4464 if ui.quiet:
4459 ui.write("%s\n" % name)
4465 ui.write("%s\n" % name)
4460 else:
4466 else:
4461 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4467 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4462
4468
4463 @command('^phase',
4469 @command('^phase',
4464 [('p', 'public', False, _('set changeset phase to public')),
4470 [('p', 'public', False, _('set changeset phase to public')),
4465 ('d', 'draft', False, _('set changeset phase to draft')),
4471 ('d', 'draft', False, _('set changeset phase to draft')),
4466 ('s', 'secret', False, _('set changeset phase to secret')),
4472 ('s', 'secret', False, _('set changeset phase to secret')),
4467 ('f', 'force', False, _('allow to move boundary backward')),
4473 ('f', 'force', False, _('allow to move boundary backward')),
4468 ('r', 'rev', [], _('target revision'), _('REV')),
4474 ('r', 'rev', [], _('target revision'), _('REV')),
4469 ],
4475 ],
4470 _('[-p|-d|-s] [-f] [-r] REV...'))
4476 _('[-p|-d|-s] [-f] [-r] REV...'))
4471 def phase(ui, repo, *revs, **opts):
4477 def phase(ui, repo, *revs, **opts):
4472 """set or show the current phase name
4478 """set or show the current phase name
4473
4479
4474 With no argument, show the phase name of specified revisions.
4480 With no argument, show the phase name of specified revisions.
4475
4481
4476 With one of -p/--public, -d/--draft or -s/--secret, change the
4482 With one of -p/--public, -d/--draft or -s/--secret, change the
4477 phase value of the specified revisions.
4483 phase value of the specified revisions.
4478
4484
4479 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4485 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4480 lower phase to an higher phase. Phases are ordered as follows::
4486 lower phase to an higher phase. Phases are ordered as follows::
4481
4487
4482 public < draft < secret
4488 public < draft < secret
4483
4489
4484 Return 0 on success, 1 if no phases were changed or some could not
4490 Return 0 on success, 1 if no phases were changed or some could not
4485 be changed.
4491 be changed.
4486 """
4492 """
4487 # search for a unique phase argument
4493 # search for a unique phase argument
4488 targetphase = None
4494 targetphase = None
4489 for idx, name in enumerate(phases.phasenames):
4495 for idx, name in enumerate(phases.phasenames):
4490 if opts[name]:
4496 if opts[name]:
4491 if targetphase is not None:
4497 if targetphase is not None:
4492 raise util.Abort(_('only one phase can be specified'))
4498 raise util.Abort(_('only one phase can be specified'))
4493 targetphase = idx
4499 targetphase = idx
4494
4500
4495 # look for specified revision
4501 # look for specified revision
4496 revs = list(revs)
4502 revs = list(revs)
4497 revs.extend(opts['rev'])
4503 revs.extend(opts['rev'])
4498 if not revs:
4504 if not revs:
4499 raise util.Abort(_('no revisions specified'))
4505 raise util.Abort(_('no revisions specified'))
4500
4506
4501 revs = scmutil.revrange(repo, revs)
4507 revs = scmutil.revrange(repo, revs)
4502
4508
4503 lock = None
4509 lock = None
4504 ret = 0
4510 ret = 0
4505 if targetphase is None:
4511 if targetphase is None:
4506 # display
4512 # display
4507 for r in revs:
4513 for r in revs:
4508 ctx = repo[r]
4514 ctx = repo[r]
4509 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4515 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4510 else:
4516 else:
4511 lock = repo.lock()
4517 lock = repo.lock()
4512 try:
4518 try:
4513 # set phase
4519 # set phase
4514 if not revs:
4520 if not revs:
4515 raise util.Abort(_('empty revision set'))
4521 raise util.Abort(_('empty revision set'))
4516 nodes = [repo[r].node() for r in revs]
4522 nodes = [repo[r].node() for r in revs]
4517 olddata = repo._phasecache.getphaserevs(repo)[:]
4523 olddata = repo._phasecache.getphaserevs(repo)[:]
4518 phases.advanceboundary(repo, targetphase, nodes)
4524 phases.advanceboundary(repo, targetphase, nodes)
4519 if opts['force']:
4525 if opts['force']:
4520 phases.retractboundary(repo, targetphase, nodes)
4526 phases.retractboundary(repo, targetphase, nodes)
4521 finally:
4527 finally:
4522 lock.release()
4528 lock.release()
4523 newdata = repo._phasecache.getphaserevs(repo)
4529 newdata = repo._phasecache.getphaserevs(repo)
4524 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4530 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4525 rejected = [n for n in nodes
4531 rejected = [n for n in nodes
4526 if newdata[repo[n].rev()] < targetphase]
4532 if newdata[repo[n].rev()] < targetphase]
4527 if rejected:
4533 if rejected:
4528 ui.warn(_('cannot move %i changesets to a more permissive '
4534 ui.warn(_('cannot move %i changesets to a more permissive '
4529 'phase, use --force\n') % len(rejected))
4535 'phase, use --force\n') % len(rejected))
4530 ret = 1
4536 ret = 1
4531 if changes:
4537 if changes:
4532 msg = _('phase changed for %i changesets\n') % changes
4538 msg = _('phase changed for %i changesets\n') % changes
4533 if ret:
4539 if ret:
4534 ui.status(msg)
4540 ui.status(msg)
4535 else:
4541 else:
4536 ui.note(msg)
4542 ui.note(msg)
4537 else:
4543 else:
4538 ui.warn(_('no phases changed\n'))
4544 ui.warn(_('no phases changed\n'))
4539 ret = 1
4545 ret = 1
4540 return ret
4546 return ret
4541
4547
4542 def postincoming(ui, repo, modheads, optupdate, checkout):
4548 def postincoming(ui, repo, modheads, optupdate, checkout):
4543 if modheads == 0:
4549 if modheads == 0:
4544 return
4550 return
4545 if optupdate:
4551 if optupdate:
4546 movemarkfrom = repo['.'].node()
4552 movemarkfrom = repo['.'].node()
4547 try:
4553 try:
4548 ret = hg.update(repo, checkout)
4554 ret = hg.update(repo, checkout)
4549 except util.Abort, inst:
4555 except util.Abort, inst:
4550 ui.warn(_("not updating: %s\n") % str(inst))
4556 ui.warn(_("not updating: %s\n") % str(inst))
4551 return 0
4557 return 0
4552 if not ret and not checkout:
4558 if not ret and not checkout:
4553 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4559 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4554 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4560 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4555 return ret
4561 return ret
4556 if modheads > 1:
4562 if modheads > 1:
4557 currentbranchheads = len(repo.branchheads())
4563 currentbranchheads = len(repo.branchheads())
4558 if currentbranchheads == modheads:
4564 if currentbranchheads == modheads:
4559 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4565 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4560 elif currentbranchheads > 1:
4566 elif currentbranchheads > 1:
4561 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4567 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4562 "merge)\n"))
4568 "merge)\n"))
4563 else:
4569 else:
4564 ui.status(_("(run 'hg heads' to see heads)\n"))
4570 ui.status(_("(run 'hg heads' to see heads)\n"))
4565 else:
4571 else:
4566 ui.status(_("(run 'hg update' to get a working copy)\n"))
4572 ui.status(_("(run 'hg update' to get a working copy)\n"))
4567
4573
4568 @command('^pull',
4574 @command('^pull',
4569 [('u', 'update', None,
4575 [('u', 'update', None,
4570 _('update to new branch head if changesets were pulled')),
4576 _('update to new branch head if changesets were pulled')),
4571 ('f', 'force', None, _('run even when remote repository is unrelated')),
4577 ('f', 'force', None, _('run even when remote repository is unrelated')),
4572 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4578 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4573 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4579 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4574 ('b', 'branch', [], _('a specific branch you would like to pull'),
4580 ('b', 'branch', [], _('a specific branch you would like to pull'),
4575 _('BRANCH')),
4581 _('BRANCH')),
4576 ] + remoteopts,
4582 ] + remoteopts,
4577 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4583 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4578 def pull(ui, repo, source="default", **opts):
4584 def pull(ui, repo, source="default", **opts):
4579 """pull changes from the specified source
4585 """pull changes from the specified source
4580
4586
4581 Pull changes from a remote repository to a local one.
4587 Pull changes from a remote repository to a local one.
4582
4588
4583 This finds all changes from the repository at the specified path
4589 This finds all changes from the repository at the specified path
4584 or URL and adds them to a local repository (the current one unless
4590 or URL and adds them to a local repository (the current one unless
4585 -R is specified). By default, this does not update the copy of the
4591 -R is specified). By default, this does not update the copy of the
4586 project in the working directory.
4592 project in the working directory.
4587
4593
4588 Use :hg:`incoming` if you want to see what would have been added
4594 Use :hg:`incoming` if you want to see what would have been added
4589 by a pull at the time you issued this command. If you then decide
4595 by a pull at the time you issued this command. If you then decide
4590 to add those changes to the repository, you should use :hg:`pull
4596 to add those changes to the repository, you should use :hg:`pull
4591 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4597 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4592
4598
4593 If SOURCE is omitted, the 'default' path will be used.
4599 If SOURCE is omitted, the 'default' path will be used.
4594 See :hg:`help urls` for more information.
4600 See :hg:`help urls` for more information.
4595
4601
4596 Returns 0 on success, 1 if an update had unresolved files.
4602 Returns 0 on success, 1 if an update had unresolved files.
4597 """
4603 """
4598 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4604 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4599 other = hg.peer(repo, opts, source)
4605 other = hg.peer(repo, opts, source)
4600 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4606 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4601 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4607 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4602
4608
4603 if opts.get('bookmark'):
4609 if opts.get('bookmark'):
4604 if not revs:
4610 if not revs:
4605 revs = []
4611 revs = []
4606 rb = other.listkeys('bookmarks')
4612 rb = other.listkeys('bookmarks')
4607 for b in opts['bookmark']:
4613 for b in opts['bookmark']:
4608 if b not in rb:
4614 if b not in rb:
4609 raise util.Abort(_('remote bookmark %s not found!') % b)
4615 raise util.Abort(_('remote bookmark %s not found!') % b)
4610 revs.append(rb[b])
4616 revs.append(rb[b])
4611
4617
4612 if revs:
4618 if revs:
4613 try:
4619 try:
4614 revs = [other.lookup(rev) for rev in revs]
4620 revs = [other.lookup(rev) for rev in revs]
4615 except error.CapabilityError:
4621 except error.CapabilityError:
4616 err = _("other repository doesn't support revision lookup, "
4622 err = _("other repository doesn't support revision lookup, "
4617 "so a rev cannot be specified.")
4623 "so a rev cannot be specified.")
4618 raise util.Abort(err)
4624 raise util.Abort(err)
4619
4625
4620 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4626 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4621 bookmarks.updatefromremote(ui, repo, other, source)
4627 bookmarks.updatefromremote(ui, repo, other, source)
4622 if checkout:
4628 if checkout:
4623 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4629 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4624 repo._subtoppath = source
4630 repo._subtoppath = source
4625 try:
4631 try:
4626 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4632 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4627
4633
4628 finally:
4634 finally:
4629 del repo._subtoppath
4635 del repo._subtoppath
4630
4636
4631 # update specified bookmarks
4637 # update specified bookmarks
4632 if opts.get('bookmark'):
4638 if opts.get('bookmark'):
4633 for b in opts['bookmark']:
4639 for b in opts['bookmark']:
4634 # explicit pull overrides local bookmark if any
4640 # explicit pull overrides local bookmark if any
4635 ui.status(_("importing bookmark %s\n") % b)
4641 ui.status(_("importing bookmark %s\n") % b)
4636 repo._bookmarks[b] = repo[rb[b]].node()
4642 repo._bookmarks[b] = repo[rb[b]].node()
4637 bookmarks.write(repo)
4643 bookmarks.write(repo)
4638
4644
4639 return ret
4645 return ret
4640
4646
4641 @command('^push',
4647 @command('^push',
4642 [('f', 'force', None, _('force push')),
4648 [('f', 'force', None, _('force push')),
4643 ('r', 'rev', [],
4649 ('r', 'rev', [],
4644 _('a changeset intended to be included in the destination'),
4650 _('a changeset intended to be included in the destination'),
4645 _('REV')),
4651 _('REV')),
4646 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4652 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4647 ('b', 'branch', [],
4653 ('b', 'branch', [],
4648 _('a specific branch you would like to push'), _('BRANCH')),
4654 _('a specific branch you would like to push'), _('BRANCH')),
4649 ('', 'new-branch', False, _('allow pushing a new branch')),
4655 ('', 'new-branch', False, _('allow pushing a new branch')),
4650 ] + remoteopts,
4656 ] + remoteopts,
4651 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4657 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4652 def push(ui, repo, dest=None, **opts):
4658 def push(ui, repo, dest=None, **opts):
4653 """push changes to the specified destination
4659 """push changes to the specified destination
4654
4660
4655 Push changesets from the local repository to the specified
4661 Push changesets from the local repository to the specified
4656 destination.
4662 destination.
4657
4663
4658 This operation is symmetrical to pull: it is identical to a pull
4664 This operation is symmetrical to pull: it is identical to a pull
4659 in the destination repository from the current one.
4665 in the destination repository from the current one.
4660
4666
4661 By default, push will not allow creation of new heads at the
4667 By default, push will not allow creation of new heads at the
4662 destination, since multiple heads would make it unclear which head
4668 destination, since multiple heads would make it unclear which head
4663 to use. In this situation, it is recommended to pull and merge
4669 to use. In this situation, it is recommended to pull and merge
4664 before pushing.
4670 before pushing.
4665
4671
4666 Use --new-branch if you want to allow push to create a new named
4672 Use --new-branch if you want to allow push to create a new named
4667 branch that is not present at the destination. This allows you to
4673 branch that is not present at the destination. This allows you to
4668 only create a new branch without forcing other changes.
4674 only create a new branch without forcing other changes.
4669
4675
4670 Use -f/--force to override the default behavior and push all
4676 Use -f/--force to override the default behavior and push all
4671 changesets on all branches.
4677 changesets on all branches.
4672
4678
4673 If -r/--rev is used, the specified revision and all its ancestors
4679 If -r/--rev is used, the specified revision and all its ancestors
4674 will be pushed to the remote repository.
4680 will be pushed to the remote repository.
4675
4681
4676 If -B/--bookmark is used, the specified bookmarked revision, its
4682 If -B/--bookmark is used, the specified bookmarked revision, its
4677 ancestors, and the bookmark will be pushed to the remote
4683 ancestors, and the bookmark will be pushed to the remote
4678 repository.
4684 repository.
4679
4685
4680 Please see :hg:`help urls` for important details about ``ssh://``
4686 Please see :hg:`help urls` for important details about ``ssh://``
4681 URLs. If DESTINATION is omitted, a default path will be used.
4687 URLs. If DESTINATION is omitted, a default path will be used.
4682
4688
4683 Returns 0 if push was successful, 1 if nothing to push.
4689 Returns 0 if push was successful, 1 if nothing to push.
4684 """
4690 """
4685
4691
4686 if opts.get('bookmark'):
4692 if opts.get('bookmark'):
4687 for b in opts['bookmark']:
4693 for b in opts['bookmark']:
4688 # translate -B options to -r so changesets get pushed
4694 # translate -B options to -r so changesets get pushed
4689 if b in repo._bookmarks:
4695 if b in repo._bookmarks:
4690 opts.setdefault('rev', []).append(b)
4696 opts.setdefault('rev', []).append(b)
4691 else:
4697 else:
4692 # if we try to push a deleted bookmark, translate it to null
4698 # if we try to push a deleted bookmark, translate it to null
4693 # this lets simultaneous -r, -b options continue working
4699 # this lets simultaneous -r, -b options continue working
4694 opts.setdefault('rev', []).append("null")
4700 opts.setdefault('rev', []).append("null")
4695
4701
4696 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4702 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4697 dest, branches = hg.parseurl(dest, opts.get('branch'))
4703 dest, branches = hg.parseurl(dest, opts.get('branch'))
4698 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4704 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4699 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4705 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4700 other = hg.peer(repo, opts, dest)
4706 other = hg.peer(repo, opts, dest)
4701 if revs:
4707 if revs:
4702 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4708 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4703
4709
4704 repo._subtoppath = dest
4710 repo._subtoppath = dest
4705 try:
4711 try:
4706 # push subrepos depth-first for coherent ordering
4712 # push subrepos depth-first for coherent ordering
4707 c = repo['']
4713 c = repo['']
4708 subs = c.substate # only repos that are committed
4714 subs = c.substate # only repos that are committed
4709 for s in sorted(subs):
4715 for s in sorted(subs):
4710 if c.sub(s).push(opts) == 0:
4716 if c.sub(s).push(opts) == 0:
4711 return False
4717 return False
4712 finally:
4718 finally:
4713 del repo._subtoppath
4719 del repo._subtoppath
4714 result = repo.push(other, opts.get('force'), revs=revs,
4720 result = repo.push(other, opts.get('force'), revs=revs,
4715 newbranch=opts.get('new_branch'))
4721 newbranch=opts.get('new_branch'))
4716
4722
4717 result = not result
4723 result = not result
4718
4724
4719 if opts.get('bookmark'):
4725 if opts.get('bookmark'):
4720 rb = other.listkeys('bookmarks')
4726 rb = other.listkeys('bookmarks')
4721 for b in opts['bookmark']:
4727 for b in opts['bookmark']:
4722 # explicit push overrides remote bookmark if any
4728 # explicit push overrides remote bookmark if any
4723 if b in repo._bookmarks:
4729 if b in repo._bookmarks:
4724 ui.status(_("exporting bookmark %s\n") % b)
4730 ui.status(_("exporting bookmark %s\n") % b)
4725 new = repo[b].hex()
4731 new = repo[b].hex()
4726 elif b in rb:
4732 elif b in rb:
4727 ui.status(_("deleting remote bookmark %s\n") % b)
4733 ui.status(_("deleting remote bookmark %s\n") % b)
4728 new = '' # delete
4734 new = '' # delete
4729 else:
4735 else:
4730 ui.warn(_('bookmark %s does not exist on the local '
4736 ui.warn(_('bookmark %s does not exist on the local '
4731 'or remote repository!\n') % b)
4737 'or remote repository!\n') % b)
4732 return 2
4738 return 2
4733 old = rb.get(b, '')
4739 old = rb.get(b, '')
4734 r = other.pushkey('bookmarks', b, old, new)
4740 r = other.pushkey('bookmarks', b, old, new)
4735 if not r:
4741 if not r:
4736 ui.warn(_('updating bookmark %s failed!\n') % b)
4742 ui.warn(_('updating bookmark %s failed!\n') % b)
4737 if not result:
4743 if not result:
4738 result = 2
4744 result = 2
4739
4745
4740 return result
4746 return result
4741
4747
4742 @command('recover', [])
4748 @command('recover', [])
4743 def recover(ui, repo):
4749 def recover(ui, repo):
4744 """roll back an interrupted transaction
4750 """roll back an interrupted transaction
4745
4751
4746 Recover from an interrupted commit or pull.
4752 Recover from an interrupted commit or pull.
4747
4753
4748 This command tries to fix the repository status after an
4754 This command tries to fix the repository status after an
4749 interrupted operation. It should only be necessary when Mercurial
4755 interrupted operation. It should only be necessary when Mercurial
4750 suggests it.
4756 suggests it.
4751
4757
4752 Returns 0 if successful, 1 if nothing to recover or verify fails.
4758 Returns 0 if successful, 1 if nothing to recover or verify fails.
4753 """
4759 """
4754 if repo.recover():
4760 if repo.recover():
4755 return hg.verify(repo)
4761 return hg.verify(repo)
4756 return 1
4762 return 1
4757
4763
4758 @command('^remove|rm',
4764 @command('^remove|rm',
4759 [('A', 'after', None, _('record delete for missing files')),
4765 [('A', 'after', None, _('record delete for missing files')),
4760 ('f', 'force', None,
4766 ('f', 'force', None,
4761 _('remove (and delete) file even if added or modified')),
4767 _('remove (and delete) file even if added or modified')),
4762 ] + walkopts,
4768 ] + walkopts,
4763 _('[OPTION]... FILE...'))
4769 _('[OPTION]... FILE...'))
4764 def remove(ui, repo, *pats, **opts):
4770 def remove(ui, repo, *pats, **opts):
4765 """remove the specified files on the next commit
4771 """remove the specified files on the next commit
4766
4772
4767 Schedule the indicated files for removal from the current branch.
4773 Schedule the indicated files for removal from the current branch.
4768
4774
4769 This command schedules the files to be removed at the next commit.
4775 This command schedules the files to be removed at the next commit.
4770 To undo a remove before that, see :hg:`revert`. To undo added
4776 To undo a remove before that, see :hg:`revert`. To undo added
4771 files, see :hg:`forget`.
4777 files, see :hg:`forget`.
4772
4778
4773 .. container:: verbose
4779 .. container:: verbose
4774
4780
4775 -A/--after can be used to remove only files that have already
4781 -A/--after can be used to remove only files that have already
4776 been deleted, -f/--force can be used to force deletion, and -Af
4782 been deleted, -f/--force can be used to force deletion, and -Af
4777 can be used to remove files from the next revision without
4783 can be used to remove files from the next revision without
4778 deleting them from the working directory.
4784 deleting them from the working directory.
4779
4785
4780 The following table details the behavior of remove for different
4786 The following table details the behavior of remove for different
4781 file states (columns) and option combinations (rows). The file
4787 file states (columns) and option combinations (rows). The file
4782 states are Added [A], Clean [C], Modified [M] and Missing [!]
4788 states are Added [A], Clean [C], Modified [M] and Missing [!]
4783 (as reported by :hg:`status`). The actions are Warn, Remove
4789 (as reported by :hg:`status`). The actions are Warn, Remove
4784 (from branch) and Delete (from disk):
4790 (from branch) and Delete (from disk):
4785
4791
4786 ======= == == == ==
4792 ======= == == == ==
4787 A C M !
4793 A C M !
4788 ======= == == == ==
4794 ======= == == == ==
4789 none W RD W R
4795 none W RD W R
4790 -f R RD RD R
4796 -f R RD RD R
4791 -A W W W R
4797 -A W W W R
4792 -Af R R R R
4798 -Af R R R R
4793 ======= == == == ==
4799 ======= == == == ==
4794
4800
4795 Note that remove never deletes files in Added [A] state from the
4801 Note that remove never deletes files in Added [A] state from the
4796 working directory, not even if option --force is specified.
4802 working directory, not even if option --force is specified.
4797
4803
4798 Returns 0 on success, 1 if any warnings encountered.
4804 Returns 0 on success, 1 if any warnings encountered.
4799 """
4805 """
4800
4806
4801 ret = 0
4807 ret = 0
4802 after, force = opts.get('after'), opts.get('force')
4808 after, force = opts.get('after'), opts.get('force')
4803 if not pats and not after:
4809 if not pats and not after:
4804 raise util.Abort(_('no files specified'))
4810 raise util.Abort(_('no files specified'))
4805
4811
4806 m = scmutil.match(repo[None], pats, opts)
4812 m = scmutil.match(repo[None], pats, opts)
4807 s = repo.status(match=m, clean=True)
4813 s = repo.status(match=m, clean=True)
4808 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4814 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4809
4815
4810 for f in m.files():
4816 for f in m.files():
4811 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4817 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4812 if os.path.exists(m.rel(f)):
4818 if os.path.exists(m.rel(f)):
4813 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4819 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4814 ret = 1
4820 ret = 1
4815
4821
4816 if force:
4822 if force:
4817 list = modified + deleted + clean + added
4823 list = modified + deleted + clean + added
4818 elif after:
4824 elif after:
4819 list = deleted
4825 list = deleted
4820 for f in modified + added + clean:
4826 for f in modified + added + clean:
4821 ui.warn(_('not removing %s: file still exists (use -f'
4827 ui.warn(_('not removing %s: file still exists (use -f'
4822 ' to force removal)\n') % m.rel(f))
4828 ' to force removal)\n') % m.rel(f))
4823 ret = 1
4829 ret = 1
4824 else:
4830 else:
4825 list = deleted + clean
4831 list = deleted + clean
4826 for f in modified:
4832 for f in modified:
4827 ui.warn(_('not removing %s: file is modified (use -f'
4833 ui.warn(_('not removing %s: file is modified (use -f'
4828 ' to force removal)\n') % m.rel(f))
4834 ' to force removal)\n') % m.rel(f))
4829 ret = 1
4835 ret = 1
4830 for f in added:
4836 for f in added:
4831 ui.warn(_('not removing %s: file has been marked for add'
4837 ui.warn(_('not removing %s: file has been marked for add'
4832 ' (use forget to undo)\n') % m.rel(f))
4838 ' (use forget to undo)\n') % m.rel(f))
4833 ret = 1
4839 ret = 1
4834
4840
4835 for f in sorted(list):
4841 for f in sorted(list):
4836 if ui.verbose or not m.exact(f):
4842 if ui.verbose or not m.exact(f):
4837 ui.status(_('removing %s\n') % m.rel(f))
4843 ui.status(_('removing %s\n') % m.rel(f))
4838
4844
4839 wlock = repo.wlock()
4845 wlock = repo.wlock()
4840 try:
4846 try:
4841 if not after:
4847 if not after:
4842 for f in list:
4848 for f in list:
4843 if f in added:
4849 if f in added:
4844 continue # we never unlink added files on remove
4850 continue # we never unlink added files on remove
4845 try:
4851 try:
4846 util.unlinkpath(repo.wjoin(f))
4852 util.unlinkpath(repo.wjoin(f))
4847 except OSError, inst:
4853 except OSError, inst:
4848 if inst.errno != errno.ENOENT:
4854 if inst.errno != errno.ENOENT:
4849 raise
4855 raise
4850 repo[None].forget(list)
4856 repo[None].forget(list)
4851 finally:
4857 finally:
4852 wlock.release()
4858 wlock.release()
4853
4859
4854 return ret
4860 return ret
4855
4861
4856 @command('rename|move|mv',
4862 @command('rename|move|mv',
4857 [('A', 'after', None, _('record a rename that has already occurred')),
4863 [('A', 'after', None, _('record a rename that has already occurred')),
4858 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4864 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4859 ] + walkopts + dryrunopts,
4865 ] + walkopts + dryrunopts,
4860 _('[OPTION]... SOURCE... DEST'))
4866 _('[OPTION]... SOURCE... DEST'))
4861 def rename(ui, repo, *pats, **opts):
4867 def rename(ui, repo, *pats, **opts):
4862 """rename files; equivalent of copy + remove
4868 """rename files; equivalent of copy + remove
4863
4869
4864 Mark dest as copies of sources; mark sources for deletion. If dest
4870 Mark dest as copies of sources; mark sources for deletion. If dest
4865 is a directory, copies are put in that directory. If dest is a
4871 is a directory, copies are put in that directory. If dest is a
4866 file, there can only be one source.
4872 file, there can only be one source.
4867
4873
4868 By default, this command copies the contents of files as they
4874 By default, this command copies the contents of files as they
4869 exist in the working directory. If invoked with -A/--after, the
4875 exist in the working directory. If invoked with -A/--after, the
4870 operation is recorded, but no copying is performed.
4876 operation is recorded, but no copying is performed.
4871
4877
4872 This command takes effect at the next commit. To undo a rename
4878 This command takes effect at the next commit. To undo a rename
4873 before that, see :hg:`revert`.
4879 before that, see :hg:`revert`.
4874
4880
4875 Returns 0 on success, 1 if errors are encountered.
4881 Returns 0 on success, 1 if errors are encountered.
4876 """
4882 """
4877 wlock = repo.wlock(False)
4883 wlock = repo.wlock(False)
4878 try:
4884 try:
4879 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4885 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4880 finally:
4886 finally:
4881 wlock.release()
4887 wlock.release()
4882
4888
4883 @command('resolve',
4889 @command('resolve',
4884 [('a', 'all', None, _('select all unresolved files')),
4890 [('a', 'all', None, _('select all unresolved files')),
4885 ('l', 'list', None, _('list state of files needing merge')),
4891 ('l', 'list', None, _('list state of files needing merge')),
4886 ('m', 'mark', None, _('mark files as resolved')),
4892 ('m', 'mark', None, _('mark files as resolved')),
4887 ('u', 'unmark', None, _('mark files as unresolved')),
4893 ('u', 'unmark', None, _('mark files as unresolved')),
4888 ('n', 'no-status', None, _('hide status prefix'))]
4894 ('n', 'no-status', None, _('hide status prefix'))]
4889 + mergetoolopts + walkopts,
4895 + mergetoolopts + walkopts,
4890 _('[OPTION]... [FILE]...'))
4896 _('[OPTION]... [FILE]...'))
4891 def resolve(ui, repo, *pats, **opts):
4897 def resolve(ui, repo, *pats, **opts):
4892 """redo merges or set/view the merge status of files
4898 """redo merges or set/view the merge status of files
4893
4899
4894 Merges with unresolved conflicts are often the result of
4900 Merges with unresolved conflicts are often the result of
4895 non-interactive merging using the ``internal:merge`` configuration
4901 non-interactive merging using the ``internal:merge`` configuration
4896 setting, or a command-line merge tool like ``diff3``. The resolve
4902 setting, or a command-line merge tool like ``diff3``. The resolve
4897 command is used to manage the files involved in a merge, after
4903 command is used to manage the files involved in a merge, after
4898 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4904 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4899 working directory must have two parents). See :hg:`help
4905 working directory must have two parents). See :hg:`help
4900 merge-tools` for information on configuring merge tools.
4906 merge-tools` for information on configuring merge tools.
4901
4907
4902 The resolve command can be used in the following ways:
4908 The resolve command can be used in the following ways:
4903
4909
4904 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4910 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4905 files, discarding any previous merge attempts. Re-merging is not
4911 files, discarding any previous merge attempts. Re-merging is not
4906 performed for files already marked as resolved. Use ``--all/-a``
4912 performed for files already marked as resolved. Use ``--all/-a``
4907 to select all unresolved files. ``--tool`` can be used to specify
4913 to select all unresolved files. ``--tool`` can be used to specify
4908 the merge tool used for the given files. It overrides the HGMERGE
4914 the merge tool used for the given files. It overrides the HGMERGE
4909 environment variable and your configuration files. Previous file
4915 environment variable and your configuration files. Previous file
4910 contents are saved with a ``.orig`` suffix.
4916 contents are saved with a ``.orig`` suffix.
4911
4917
4912 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4918 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4913 (e.g. after having manually fixed-up the files). The default is
4919 (e.g. after having manually fixed-up the files). The default is
4914 to mark all unresolved files.
4920 to mark all unresolved files.
4915
4921
4916 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4922 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4917 default is to mark all resolved files.
4923 default is to mark all resolved files.
4918
4924
4919 - :hg:`resolve -l`: list files which had or still have conflicts.
4925 - :hg:`resolve -l`: list files which had or still have conflicts.
4920 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4926 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4921
4927
4922 Note that Mercurial will not let you commit files with unresolved
4928 Note that Mercurial will not let you commit files with unresolved
4923 merge conflicts. You must use :hg:`resolve -m ...` before you can
4929 merge conflicts. You must use :hg:`resolve -m ...` before you can
4924 commit after a conflicting merge.
4930 commit after a conflicting merge.
4925
4931
4926 Returns 0 on success, 1 if any files fail a resolve attempt.
4932 Returns 0 on success, 1 if any files fail a resolve attempt.
4927 """
4933 """
4928
4934
4929 all, mark, unmark, show, nostatus = \
4935 all, mark, unmark, show, nostatus = \
4930 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4936 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4931
4937
4932 if (show and (mark or unmark)) or (mark and unmark):
4938 if (show and (mark or unmark)) or (mark and unmark):
4933 raise util.Abort(_("too many options specified"))
4939 raise util.Abort(_("too many options specified"))
4934 if pats and all:
4940 if pats and all:
4935 raise util.Abort(_("can't specify --all and patterns"))
4941 raise util.Abort(_("can't specify --all and patterns"))
4936 if not (all or pats or show or mark or unmark):
4942 if not (all or pats or show or mark or unmark):
4937 raise util.Abort(_('no files or directories specified; '
4943 raise util.Abort(_('no files or directories specified; '
4938 'use --all to remerge all files'))
4944 'use --all to remerge all files'))
4939
4945
4940 ms = mergemod.mergestate(repo)
4946 ms = mergemod.mergestate(repo)
4941 m = scmutil.match(repo[None], pats, opts)
4947 m = scmutil.match(repo[None], pats, opts)
4942 ret = 0
4948 ret = 0
4943
4949
4944 for f in ms:
4950 for f in ms:
4945 if m(f):
4951 if m(f):
4946 if show:
4952 if show:
4947 if nostatus:
4953 if nostatus:
4948 ui.write("%s\n" % f)
4954 ui.write("%s\n" % f)
4949 else:
4955 else:
4950 ui.write("%s %s\n" % (ms[f].upper(), f),
4956 ui.write("%s %s\n" % (ms[f].upper(), f),
4951 label='resolve.' +
4957 label='resolve.' +
4952 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4958 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4953 elif mark:
4959 elif mark:
4954 ms.mark(f, "r")
4960 ms.mark(f, "r")
4955 elif unmark:
4961 elif unmark:
4956 ms.mark(f, "u")
4962 ms.mark(f, "u")
4957 else:
4963 else:
4958 wctx = repo[None]
4964 wctx = repo[None]
4959 mctx = wctx.parents()[-1]
4965 mctx = wctx.parents()[-1]
4960
4966
4961 # backup pre-resolve (merge uses .orig for its own purposes)
4967 # backup pre-resolve (merge uses .orig for its own purposes)
4962 a = repo.wjoin(f)
4968 a = repo.wjoin(f)
4963 util.copyfile(a, a + ".resolve")
4969 util.copyfile(a, a + ".resolve")
4964
4970
4965 try:
4971 try:
4966 # resolve file
4972 # resolve file
4967 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4973 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4968 if ms.resolve(f, wctx, mctx):
4974 if ms.resolve(f, wctx, mctx):
4969 ret = 1
4975 ret = 1
4970 finally:
4976 finally:
4971 ui.setconfig('ui', 'forcemerge', '')
4977 ui.setconfig('ui', 'forcemerge', '')
4972 ms.commit()
4978 ms.commit()
4973
4979
4974 # replace filemerge's .orig file with our resolve file
4980 # replace filemerge's .orig file with our resolve file
4975 util.rename(a + ".resolve", a + ".orig")
4981 util.rename(a + ".resolve", a + ".orig")
4976
4982
4977 ms.commit()
4983 ms.commit()
4978 return ret
4984 return ret
4979
4985
4980 @command('revert',
4986 @command('revert',
4981 [('a', 'all', None, _('revert all changes when no arguments given')),
4987 [('a', 'all', None, _('revert all changes when no arguments given')),
4982 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4988 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4983 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4989 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4984 ('C', 'no-backup', None, _('do not save backup copies of files')),
4990 ('C', 'no-backup', None, _('do not save backup copies of files')),
4985 ] + walkopts + dryrunopts,
4991 ] + walkopts + dryrunopts,
4986 _('[OPTION]... [-r REV] [NAME]...'))
4992 _('[OPTION]... [-r REV] [NAME]...'))
4987 def revert(ui, repo, *pats, **opts):
4993 def revert(ui, repo, *pats, **opts):
4988 """restore files to their checkout state
4994 """restore files to their checkout state
4989
4995
4990 .. note::
4996 .. note::
4991
4997
4992 To check out earlier revisions, you should use :hg:`update REV`.
4998 To check out earlier revisions, you should use :hg:`update REV`.
4993 To cancel an uncommitted merge (and lose your changes), use
4999 To cancel an uncommitted merge (and lose your changes), use
4994 :hg:`update --clean .`.
5000 :hg:`update --clean .`.
4995
5001
4996 With no revision specified, revert the specified files or directories
5002 With no revision specified, revert the specified files or directories
4997 to the contents they had in the parent of the working directory.
5003 to the contents they had in the parent of the working directory.
4998 This restores the contents of files to an unmodified
5004 This restores the contents of files to an unmodified
4999 state and unschedules adds, removes, copies, and renames. If the
5005 state and unschedules adds, removes, copies, and renames. If the
5000 working directory has two parents, you must explicitly specify a
5006 working directory has two parents, you must explicitly specify a
5001 revision.
5007 revision.
5002
5008
5003 Using the -r/--rev or -d/--date options, revert the given files or
5009 Using the -r/--rev or -d/--date options, revert the given files or
5004 directories to their states as of a specific revision. Because
5010 directories to their states as of a specific revision. Because
5005 revert does not change the working directory parents, this will
5011 revert does not change the working directory parents, this will
5006 cause these files to appear modified. This can be helpful to "back
5012 cause these files to appear modified. This can be helpful to "back
5007 out" some or all of an earlier change. See :hg:`backout` for a
5013 out" some or all of an earlier change. See :hg:`backout` for a
5008 related method.
5014 related method.
5009
5015
5010 Modified files are saved with a .orig suffix before reverting.
5016 Modified files are saved with a .orig suffix before reverting.
5011 To disable these backups, use --no-backup.
5017 To disable these backups, use --no-backup.
5012
5018
5013 See :hg:`help dates` for a list of formats valid for -d/--date.
5019 See :hg:`help dates` for a list of formats valid for -d/--date.
5014
5020
5015 Returns 0 on success.
5021 Returns 0 on success.
5016 """
5022 """
5017
5023
5018 if opts.get("date"):
5024 if opts.get("date"):
5019 if opts.get("rev"):
5025 if opts.get("rev"):
5020 raise util.Abort(_("you can't specify a revision and a date"))
5026 raise util.Abort(_("you can't specify a revision and a date"))
5021 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5027 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5022
5028
5023 parent, p2 = repo.dirstate.parents()
5029 parent, p2 = repo.dirstate.parents()
5024 if not opts.get('rev') and p2 != nullid:
5030 if not opts.get('rev') and p2 != nullid:
5025 # revert after merge is a trap for new users (issue2915)
5031 # revert after merge is a trap for new users (issue2915)
5026 raise util.Abort(_('uncommitted merge with no revision specified'),
5032 raise util.Abort(_('uncommitted merge with no revision specified'),
5027 hint=_('use "hg update" or see "hg help revert"'))
5033 hint=_('use "hg update" or see "hg help revert"'))
5028
5034
5029 ctx = scmutil.revsingle(repo, opts.get('rev'))
5035 ctx = scmutil.revsingle(repo, opts.get('rev'))
5030
5036
5031 if not pats and not opts.get('all'):
5037 if not pats and not opts.get('all'):
5032 msg = _("no files or directories specified")
5038 msg = _("no files or directories specified")
5033 if p2 != nullid:
5039 if p2 != nullid:
5034 hint = _("uncommitted merge, use --all to discard all changes,"
5040 hint = _("uncommitted merge, use --all to discard all changes,"
5035 " or 'hg update -C .' to abort the merge")
5041 " or 'hg update -C .' to abort the merge")
5036 raise util.Abort(msg, hint=hint)
5042 raise util.Abort(msg, hint=hint)
5037 dirty = util.any(repo.status())
5043 dirty = util.any(repo.status())
5038 node = ctx.node()
5044 node = ctx.node()
5039 if node != parent:
5045 if node != parent:
5040 if dirty:
5046 if dirty:
5041 hint = _("uncommitted changes, use --all to discard all"
5047 hint = _("uncommitted changes, use --all to discard all"
5042 " changes, or 'hg update %s' to update") % ctx.rev()
5048 " changes, or 'hg update %s' to update") % ctx.rev()
5043 else:
5049 else:
5044 hint = _("use --all to revert all files,"
5050 hint = _("use --all to revert all files,"
5045 " or 'hg update %s' to update") % ctx.rev()
5051 " or 'hg update %s' to update") % ctx.rev()
5046 elif dirty:
5052 elif dirty:
5047 hint = _("uncommitted changes, use --all to discard all changes")
5053 hint = _("uncommitted changes, use --all to discard all changes")
5048 else:
5054 else:
5049 hint = _("use --all to revert all files")
5055 hint = _("use --all to revert all files")
5050 raise util.Abort(msg, hint=hint)
5056 raise util.Abort(msg, hint=hint)
5051
5057
5052 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5058 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5053
5059
5054 @command('rollback', dryrunopts +
5060 @command('rollback', dryrunopts +
5055 [('f', 'force', False, _('ignore safety measures'))])
5061 [('f', 'force', False, _('ignore safety measures'))])
5056 def rollback(ui, repo, **opts):
5062 def rollback(ui, repo, **opts):
5057 """roll back the last transaction (dangerous)
5063 """roll back the last transaction (dangerous)
5058
5064
5059 This command should be used with care. There is only one level of
5065 This command should be used with care. There is only one level of
5060 rollback, and there is no way to undo a rollback. It will also
5066 rollback, and there is no way to undo a rollback. It will also
5061 restore the dirstate at the time of the last transaction, losing
5067 restore the dirstate at the time of the last transaction, losing
5062 any dirstate changes since that time. This command does not alter
5068 any dirstate changes since that time. This command does not alter
5063 the working directory.
5069 the working directory.
5064
5070
5065 Transactions are used to encapsulate the effects of all commands
5071 Transactions are used to encapsulate the effects of all commands
5066 that create new changesets or propagate existing changesets into a
5072 that create new changesets or propagate existing changesets into a
5067 repository.
5073 repository.
5068
5074
5069 .. container:: verbose
5075 .. container:: verbose
5070
5076
5071 For example, the following commands are transactional, and their
5077 For example, the following commands are transactional, and their
5072 effects can be rolled back:
5078 effects can be rolled back:
5073
5079
5074 - commit
5080 - commit
5075 - import
5081 - import
5076 - pull
5082 - pull
5077 - push (with this repository as the destination)
5083 - push (with this repository as the destination)
5078 - unbundle
5084 - unbundle
5079
5085
5080 To avoid permanent data loss, rollback will refuse to rollback a
5086 To avoid permanent data loss, rollback will refuse to rollback a
5081 commit transaction if it isn't checked out. Use --force to
5087 commit transaction if it isn't checked out. Use --force to
5082 override this protection.
5088 override this protection.
5083
5089
5084 This command is not intended for use on public repositories. Once
5090 This command is not intended for use on public repositories. Once
5085 changes are visible for pull by other users, rolling a transaction
5091 changes are visible for pull by other users, rolling a transaction
5086 back locally is ineffective (someone else may already have pulled
5092 back locally is ineffective (someone else may already have pulled
5087 the changes). Furthermore, a race is possible with readers of the
5093 the changes). Furthermore, a race is possible with readers of the
5088 repository; for example an in-progress pull from the repository
5094 repository; for example an in-progress pull from the repository
5089 may fail if a rollback is performed.
5095 may fail if a rollback is performed.
5090
5096
5091 Returns 0 on success, 1 if no rollback data is available.
5097 Returns 0 on success, 1 if no rollback data is available.
5092 """
5098 """
5093 return repo.rollback(dryrun=opts.get('dry_run'),
5099 return repo.rollback(dryrun=opts.get('dry_run'),
5094 force=opts.get('force'))
5100 force=opts.get('force'))
5095
5101
5096 @command('root', [])
5102 @command('root', [])
5097 def root(ui, repo):
5103 def root(ui, repo):
5098 """print the root (top) of the current working directory
5104 """print the root (top) of the current working directory
5099
5105
5100 Print the root directory of the current repository.
5106 Print the root directory of the current repository.
5101
5107
5102 Returns 0 on success.
5108 Returns 0 on success.
5103 """
5109 """
5104 ui.write(repo.root + "\n")
5110 ui.write(repo.root + "\n")
5105
5111
5106 @command('^serve',
5112 @command('^serve',
5107 [('A', 'accesslog', '', _('name of access log file to write to'),
5113 [('A', 'accesslog', '', _('name of access log file to write to'),
5108 _('FILE')),
5114 _('FILE')),
5109 ('d', 'daemon', None, _('run server in background')),
5115 ('d', 'daemon', None, _('run server in background')),
5110 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5116 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5111 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5117 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5112 # use string type, then we can check if something was passed
5118 # use string type, then we can check if something was passed
5113 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5119 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5114 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5120 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5115 _('ADDR')),
5121 _('ADDR')),
5116 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5122 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5117 _('PREFIX')),
5123 _('PREFIX')),
5118 ('n', 'name', '',
5124 ('n', 'name', '',
5119 _('name to show in web pages (default: working directory)'), _('NAME')),
5125 _('name to show in web pages (default: working directory)'), _('NAME')),
5120 ('', 'web-conf', '',
5126 ('', 'web-conf', '',
5121 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5127 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5122 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5128 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5123 _('FILE')),
5129 _('FILE')),
5124 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5130 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5125 ('', 'stdio', None, _('for remote clients')),
5131 ('', 'stdio', None, _('for remote clients')),
5126 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5132 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5127 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5133 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5128 ('', 'style', '', _('template style to use'), _('STYLE')),
5134 ('', 'style', '', _('template style to use'), _('STYLE')),
5129 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5135 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5130 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5136 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5131 _('[OPTION]...'))
5137 _('[OPTION]...'))
5132 def serve(ui, repo, **opts):
5138 def serve(ui, repo, **opts):
5133 """start stand-alone webserver
5139 """start stand-alone webserver
5134
5140
5135 Start a local HTTP repository browser and pull server. You can use
5141 Start a local HTTP repository browser and pull server. You can use
5136 this for ad-hoc sharing and browsing of repositories. It is
5142 this for ad-hoc sharing and browsing of repositories. It is
5137 recommended to use a real web server to serve a repository for
5143 recommended to use a real web server to serve a repository for
5138 longer periods of time.
5144 longer periods of time.
5139
5145
5140 Please note that the server does not implement access control.
5146 Please note that the server does not implement access control.
5141 This means that, by default, anybody can read from the server and
5147 This means that, by default, anybody can read from the server and
5142 nobody can write to it by default. Set the ``web.allow_push``
5148 nobody can write to it by default. Set the ``web.allow_push``
5143 option to ``*`` to allow everybody to push to the server. You
5149 option to ``*`` to allow everybody to push to the server. You
5144 should use a real web server if you need to authenticate users.
5150 should use a real web server if you need to authenticate users.
5145
5151
5146 By default, the server logs accesses to stdout and errors to
5152 By default, the server logs accesses to stdout and errors to
5147 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5153 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5148 files.
5154 files.
5149
5155
5150 To have the server choose a free port number to listen on, specify
5156 To have the server choose a free port number to listen on, specify
5151 a port number of 0; in this case, the server will print the port
5157 a port number of 0; in this case, the server will print the port
5152 number it uses.
5158 number it uses.
5153
5159
5154 Returns 0 on success.
5160 Returns 0 on success.
5155 """
5161 """
5156
5162
5157 if opts["stdio"] and opts["cmdserver"]:
5163 if opts["stdio"] and opts["cmdserver"]:
5158 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5164 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5159
5165
5160 def checkrepo():
5166 def checkrepo():
5161 if repo is None:
5167 if repo is None:
5162 raise error.RepoError(_("there is no Mercurial repository here"
5168 raise error.RepoError(_("there is no Mercurial repository here"
5163 " (.hg not found)"))
5169 " (.hg not found)"))
5164
5170
5165 if opts["stdio"]:
5171 if opts["stdio"]:
5166 checkrepo()
5172 checkrepo()
5167 s = sshserver.sshserver(ui, repo)
5173 s = sshserver.sshserver(ui, repo)
5168 s.serve_forever()
5174 s.serve_forever()
5169
5175
5170 if opts["cmdserver"]:
5176 if opts["cmdserver"]:
5171 checkrepo()
5177 checkrepo()
5172 s = commandserver.server(ui, repo, opts["cmdserver"])
5178 s = commandserver.server(ui, repo, opts["cmdserver"])
5173 return s.serve()
5179 return s.serve()
5174
5180
5175 # this way we can check if something was given in the command-line
5181 # this way we can check if something was given in the command-line
5176 if opts.get('port'):
5182 if opts.get('port'):
5177 opts['port'] = util.getport(opts.get('port'))
5183 opts['port'] = util.getport(opts.get('port'))
5178
5184
5179 baseui = repo and repo.baseui or ui
5185 baseui = repo and repo.baseui or ui
5180 optlist = ("name templates style address port prefix ipv6"
5186 optlist = ("name templates style address port prefix ipv6"
5181 " accesslog errorlog certificate encoding")
5187 " accesslog errorlog certificate encoding")
5182 for o in optlist.split():
5188 for o in optlist.split():
5183 val = opts.get(o, '')
5189 val = opts.get(o, '')
5184 if val in (None, ''): # should check against default options instead
5190 if val in (None, ''): # should check against default options instead
5185 continue
5191 continue
5186 baseui.setconfig("web", o, val)
5192 baseui.setconfig("web", o, val)
5187 if repo and repo.ui != baseui:
5193 if repo and repo.ui != baseui:
5188 repo.ui.setconfig("web", o, val)
5194 repo.ui.setconfig("web", o, val)
5189
5195
5190 o = opts.get('web_conf') or opts.get('webdir_conf')
5196 o = opts.get('web_conf') or opts.get('webdir_conf')
5191 if not o:
5197 if not o:
5192 if not repo:
5198 if not repo:
5193 raise error.RepoError(_("there is no Mercurial repository"
5199 raise error.RepoError(_("there is no Mercurial repository"
5194 " here (.hg not found)"))
5200 " here (.hg not found)"))
5195 o = repo.root
5201 o = repo.root
5196
5202
5197 app = hgweb.hgweb(o, baseui=ui)
5203 app = hgweb.hgweb(o, baseui=ui)
5198
5204
5199 class service(object):
5205 class service(object):
5200 def init(self):
5206 def init(self):
5201 util.setsignalhandler()
5207 util.setsignalhandler()
5202 self.httpd = hgweb.server.create_server(ui, app)
5208 self.httpd = hgweb.server.create_server(ui, app)
5203
5209
5204 if opts['port'] and not ui.verbose:
5210 if opts['port'] and not ui.verbose:
5205 return
5211 return
5206
5212
5207 if self.httpd.prefix:
5213 if self.httpd.prefix:
5208 prefix = self.httpd.prefix.strip('/') + '/'
5214 prefix = self.httpd.prefix.strip('/') + '/'
5209 else:
5215 else:
5210 prefix = ''
5216 prefix = ''
5211
5217
5212 port = ':%d' % self.httpd.port
5218 port = ':%d' % self.httpd.port
5213 if port == ':80':
5219 if port == ':80':
5214 port = ''
5220 port = ''
5215
5221
5216 bindaddr = self.httpd.addr
5222 bindaddr = self.httpd.addr
5217 if bindaddr == '0.0.0.0':
5223 if bindaddr == '0.0.0.0':
5218 bindaddr = '*'
5224 bindaddr = '*'
5219 elif ':' in bindaddr: # IPv6
5225 elif ':' in bindaddr: # IPv6
5220 bindaddr = '[%s]' % bindaddr
5226 bindaddr = '[%s]' % bindaddr
5221
5227
5222 fqaddr = self.httpd.fqaddr
5228 fqaddr = self.httpd.fqaddr
5223 if ':' in fqaddr:
5229 if ':' in fqaddr:
5224 fqaddr = '[%s]' % fqaddr
5230 fqaddr = '[%s]' % fqaddr
5225 if opts['port']:
5231 if opts['port']:
5226 write = ui.status
5232 write = ui.status
5227 else:
5233 else:
5228 write = ui.write
5234 write = ui.write
5229 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5235 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5230 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5236 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5231
5237
5232 def run(self):
5238 def run(self):
5233 self.httpd.serve_forever()
5239 self.httpd.serve_forever()
5234
5240
5235 service = service()
5241 service = service()
5236
5242
5237 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5243 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5238
5244
5239 @command('showconfig|debugconfig',
5245 @command('showconfig|debugconfig',
5240 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5246 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5241 _('[-u] [NAME]...'))
5247 _('[-u] [NAME]...'))
5242 def showconfig(ui, repo, *values, **opts):
5248 def showconfig(ui, repo, *values, **opts):
5243 """show combined config settings from all hgrc files
5249 """show combined config settings from all hgrc files
5244
5250
5245 With no arguments, print names and values of all config items.
5251 With no arguments, print names and values of all config items.
5246
5252
5247 With one argument of the form section.name, print just the value
5253 With one argument of the form section.name, print just the value
5248 of that config item.
5254 of that config item.
5249
5255
5250 With multiple arguments, print names and values of all config
5256 With multiple arguments, print names and values of all config
5251 items with matching section names.
5257 items with matching section names.
5252
5258
5253 With --debug, the source (filename and line number) is printed
5259 With --debug, the source (filename and line number) is printed
5254 for each config item.
5260 for each config item.
5255
5261
5256 Returns 0 on success.
5262 Returns 0 on success.
5257 """
5263 """
5258
5264
5259 for f in scmutil.rcpath():
5265 for f in scmutil.rcpath():
5260 ui.debug('read config from: %s\n' % f)
5266 ui.debug('read config from: %s\n' % f)
5261 untrusted = bool(opts.get('untrusted'))
5267 untrusted = bool(opts.get('untrusted'))
5262 if values:
5268 if values:
5263 sections = [v for v in values if '.' not in v]
5269 sections = [v for v in values if '.' not in v]
5264 items = [v for v in values if '.' in v]
5270 items = [v for v in values if '.' in v]
5265 if len(items) > 1 or items and sections:
5271 if len(items) > 1 or items and sections:
5266 raise util.Abort(_('only one config item permitted'))
5272 raise util.Abort(_('only one config item permitted'))
5267 for section, name, value in ui.walkconfig(untrusted=untrusted):
5273 for section, name, value in ui.walkconfig(untrusted=untrusted):
5268 value = str(value).replace('\n', '\\n')
5274 value = str(value).replace('\n', '\\n')
5269 sectname = section + '.' + name
5275 sectname = section + '.' + name
5270 if values:
5276 if values:
5271 for v in values:
5277 for v in values:
5272 if v == section:
5278 if v == section:
5273 ui.debug('%s: ' %
5279 ui.debug('%s: ' %
5274 ui.configsource(section, name, untrusted))
5280 ui.configsource(section, name, untrusted))
5275 ui.write('%s=%s\n' % (sectname, value))
5281 ui.write('%s=%s\n' % (sectname, value))
5276 elif v == sectname:
5282 elif v == sectname:
5277 ui.debug('%s: ' %
5283 ui.debug('%s: ' %
5278 ui.configsource(section, name, untrusted))
5284 ui.configsource(section, name, untrusted))
5279 ui.write(value, '\n')
5285 ui.write(value, '\n')
5280 else:
5286 else:
5281 ui.debug('%s: ' %
5287 ui.debug('%s: ' %
5282 ui.configsource(section, name, untrusted))
5288 ui.configsource(section, name, untrusted))
5283 ui.write('%s=%s\n' % (sectname, value))
5289 ui.write('%s=%s\n' % (sectname, value))
5284
5290
5285 @command('^status|st',
5291 @command('^status|st',
5286 [('A', 'all', None, _('show status of all files')),
5292 [('A', 'all', None, _('show status of all files')),
5287 ('m', 'modified', None, _('show only modified files')),
5293 ('m', 'modified', None, _('show only modified files')),
5288 ('a', 'added', None, _('show only added files')),
5294 ('a', 'added', None, _('show only added files')),
5289 ('r', 'removed', None, _('show only removed files')),
5295 ('r', 'removed', None, _('show only removed files')),
5290 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5296 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5291 ('c', 'clean', None, _('show only files without changes')),
5297 ('c', 'clean', None, _('show only files without changes')),
5292 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5298 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5293 ('i', 'ignored', None, _('show only ignored files')),
5299 ('i', 'ignored', None, _('show only ignored files')),
5294 ('n', 'no-status', None, _('hide status prefix')),
5300 ('n', 'no-status', None, _('hide status prefix')),
5295 ('C', 'copies', None, _('show source of copied files')),
5301 ('C', 'copies', None, _('show source of copied files')),
5296 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5302 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5297 ('', 'rev', [], _('show difference from revision'), _('REV')),
5303 ('', 'rev', [], _('show difference from revision'), _('REV')),
5298 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5304 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5299 ] + walkopts + subrepoopts,
5305 ] + walkopts + subrepoopts,
5300 _('[OPTION]... [FILE]...'))
5306 _('[OPTION]... [FILE]...'))
5301 def status(ui, repo, *pats, **opts):
5307 def status(ui, repo, *pats, **opts):
5302 """show changed files in the working directory
5308 """show changed files in the working directory
5303
5309
5304 Show status of files in the repository. If names are given, only
5310 Show status of files in the repository. If names are given, only
5305 files that match are shown. Files that are clean or ignored or
5311 files that match are shown. Files that are clean or ignored or
5306 the source of a copy/move operation, are not listed unless
5312 the source of a copy/move operation, are not listed unless
5307 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5313 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5308 Unless options described with "show only ..." are given, the
5314 Unless options described with "show only ..." are given, the
5309 options -mardu are used.
5315 options -mardu are used.
5310
5316
5311 Option -q/--quiet hides untracked (unknown and ignored) files
5317 Option -q/--quiet hides untracked (unknown and ignored) files
5312 unless explicitly requested with -u/--unknown or -i/--ignored.
5318 unless explicitly requested with -u/--unknown or -i/--ignored.
5313
5319
5314 .. note::
5320 .. note::
5315 status may appear to disagree with diff if permissions have
5321 status may appear to disagree with diff if permissions have
5316 changed or a merge has occurred. The standard diff format does
5322 changed or a merge has occurred. The standard diff format does
5317 not report permission changes and diff only reports changes
5323 not report permission changes and diff only reports changes
5318 relative to one merge parent.
5324 relative to one merge parent.
5319
5325
5320 If one revision is given, it is used as the base revision.
5326 If one revision is given, it is used as the base revision.
5321 If two revisions are given, the differences between them are
5327 If two revisions are given, the differences between them are
5322 shown. The --change option can also be used as a shortcut to list
5328 shown. The --change option can also be used as a shortcut to list
5323 the changed files of a revision from its first parent.
5329 the changed files of a revision from its first parent.
5324
5330
5325 The codes used to show the status of files are::
5331 The codes used to show the status of files are::
5326
5332
5327 M = modified
5333 M = modified
5328 A = added
5334 A = added
5329 R = removed
5335 R = removed
5330 C = clean
5336 C = clean
5331 ! = missing (deleted by non-hg command, but still tracked)
5337 ! = missing (deleted by non-hg command, but still tracked)
5332 ? = not tracked
5338 ? = not tracked
5333 I = ignored
5339 I = ignored
5334 = origin of the previous file listed as A (added)
5340 = origin of the previous file listed as A (added)
5335
5341
5336 .. container:: verbose
5342 .. container:: verbose
5337
5343
5338 Examples:
5344 Examples:
5339
5345
5340 - show changes in the working directory relative to a
5346 - show changes in the working directory relative to a
5341 changeset::
5347 changeset::
5342
5348
5343 hg status --rev 9353
5349 hg status --rev 9353
5344
5350
5345 - show all changes including copies in an existing changeset::
5351 - show all changes including copies in an existing changeset::
5346
5352
5347 hg status --copies --change 9353
5353 hg status --copies --change 9353
5348
5354
5349 - get a NUL separated list of added files, suitable for xargs::
5355 - get a NUL separated list of added files, suitable for xargs::
5350
5356
5351 hg status -an0
5357 hg status -an0
5352
5358
5353 Returns 0 on success.
5359 Returns 0 on success.
5354 """
5360 """
5355
5361
5356 revs = opts.get('rev')
5362 revs = opts.get('rev')
5357 change = opts.get('change')
5363 change = opts.get('change')
5358
5364
5359 if revs and change:
5365 if revs and change:
5360 msg = _('cannot specify --rev and --change at the same time')
5366 msg = _('cannot specify --rev and --change at the same time')
5361 raise util.Abort(msg)
5367 raise util.Abort(msg)
5362 elif change:
5368 elif change:
5363 node2 = scmutil.revsingle(repo, change, None).node()
5369 node2 = scmutil.revsingle(repo, change, None).node()
5364 node1 = repo[node2].p1().node()
5370 node1 = repo[node2].p1().node()
5365 else:
5371 else:
5366 node1, node2 = scmutil.revpair(repo, revs)
5372 node1, node2 = scmutil.revpair(repo, revs)
5367
5373
5368 cwd = (pats and repo.getcwd()) or ''
5374 cwd = (pats and repo.getcwd()) or ''
5369 end = opts.get('print0') and '\0' or '\n'
5375 end = opts.get('print0') and '\0' or '\n'
5370 copy = {}
5376 copy = {}
5371 states = 'modified added removed deleted unknown ignored clean'.split()
5377 states = 'modified added removed deleted unknown ignored clean'.split()
5372 show = [k for k in states if opts.get(k)]
5378 show = [k for k in states if opts.get(k)]
5373 if opts.get('all'):
5379 if opts.get('all'):
5374 show += ui.quiet and (states[:4] + ['clean']) or states
5380 show += ui.quiet and (states[:4] + ['clean']) or states
5375 if not show:
5381 if not show:
5376 show = ui.quiet and states[:4] or states[:5]
5382 show = ui.quiet and states[:4] or states[:5]
5377
5383
5378 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5384 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5379 'ignored' in show, 'clean' in show, 'unknown' in show,
5385 'ignored' in show, 'clean' in show, 'unknown' in show,
5380 opts.get('subrepos'))
5386 opts.get('subrepos'))
5381 changestates = zip(states, 'MAR!?IC', stat)
5387 changestates = zip(states, 'MAR!?IC', stat)
5382
5388
5383 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5389 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5384 copy = copies.pathcopies(repo[node1], repo[node2])
5390 copy = copies.pathcopies(repo[node1], repo[node2])
5385
5391
5386 fm = ui.formatter('status', opts)
5392 fm = ui.formatter('status', opts)
5387 format = '%s %s' + end
5393 format = '%s %s' + end
5388 if opts.get('no_status'):
5394 if opts.get('no_status'):
5389 format = '%.0s%s' + end
5395 format = '%.0s%s' + end
5390
5396
5391 for state, char, files in changestates:
5397 for state, char, files in changestates:
5392 if state in show:
5398 if state in show:
5393 label = 'status.' + state
5399 label = 'status.' + state
5394 for f in files:
5400 for f in files:
5395 fm.startitem()
5401 fm.startitem()
5396 fm.write("status path", format, char,
5402 fm.write("status path", format, char,
5397 repo.pathto(f, cwd), label=label)
5403 repo.pathto(f, cwd), label=label)
5398 if f in copy:
5404 if f in copy:
5399 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5405 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5400 label='status.copied')
5406 label='status.copied')
5401 fm.end()
5407 fm.end()
5402
5408
5403 @command('^summary|sum',
5409 @command('^summary|sum',
5404 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5410 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5405 def summary(ui, repo, **opts):
5411 def summary(ui, repo, **opts):
5406 """summarize working directory state
5412 """summarize working directory state
5407
5413
5408 This generates a brief summary of the working directory state,
5414 This generates a brief summary of the working directory state,
5409 including parents, branch, commit status, and available updates.
5415 including parents, branch, commit status, and available updates.
5410
5416
5411 With the --remote option, this will check the default paths for
5417 With the --remote option, this will check the default paths for
5412 incoming and outgoing changes. This can be time-consuming.
5418 incoming and outgoing changes. This can be time-consuming.
5413
5419
5414 Returns 0 on success.
5420 Returns 0 on success.
5415 """
5421 """
5416
5422
5417 ctx = repo[None]
5423 ctx = repo[None]
5418 parents = ctx.parents()
5424 parents = ctx.parents()
5419 pnode = parents[0].node()
5425 pnode = parents[0].node()
5420 marks = []
5426 marks = []
5421
5427
5422 for p in parents:
5428 for p in parents:
5423 # label with log.changeset (instead of log.parent) since this
5429 # label with log.changeset (instead of log.parent) since this
5424 # shows a working directory parent *changeset*:
5430 # shows a working directory parent *changeset*:
5425 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5431 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5426 label='log.changeset changeset.%s' % p.phasestr())
5432 label='log.changeset changeset.%s' % p.phasestr())
5427 ui.write(' '.join(p.tags()), label='log.tag')
5433 ui.write(' '.join(p.tags()), label='log.tag')
5428 if p.bookmarks():
5434 if p.bookmarks():
5429 marks.extend(p.bookmarks())
5435 marks.extend(p.bookmarks())
5430 if p.rev() == -1:
5436 if p.rev() == -1:
5431 if not len(repo):
5437 if not len(repo):
5432 ui.write(_(' (empty repository)'))
5438 ui.write(_(' (empty repository)'))
5433 else:
5439 else:
5434 ui.write(_(' (no revision checked out)'))
5440 ui.write(_(' (no revision checked out)'))
5435 ui.write('\n')
5441 ui.write('\n')
5436 if p.description():
5442 if p.description():
5437 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5443 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5438 label='log.summary')
5444 label='log.summary')
5439
5445
5440 branch = ctx.branch()
5446 branch = ctx.branch()
5441 bheads = repo.branchheads(branch)
5447 bheads = repo.branchheads(branch)
5442 m = _('branch: %s\n') % branch
5448 m = _('branch: %s\n') % branch
5443 if branch != 'default':
5449 if branch != 'default':
5444 ui.write(m, label='log.branch')
5450 ui.write(m, label='log.branch')
5445 else:
5451 else:
5446 ui.status(m, label='log.branch')
5452 ui.status(m, label='log.branch')
5447
5453
5448 if marks:
5454 if marks:
5449 current = repo._bookmarkcurrent
5455 current = repo._bookmarkcurrent
5450 ui.write(_('bookmarks:'), label='log.bookmark')
5456 ui.write(_('bookmarks:'), label='log.bookmark')
5451 if current is not None:
5457 if current is not None:
5452 try:
5458 try:
5453 marks.remove(current)
5459 marks.remove(current)
5454 ui.write(' *' + current, label='bookmarks.current')
5460 ui.write(' *' + current, label='bookmarks.current')
5455 except ValueError:
5461 except ValueError:
5456 # current bookmark not in parent ctx marks
5462 # current bookmark not in parent ctx marks
5457 pass
5463 pass
5458 for m in marks:
5464 for m in marks:
5459 ui.write(' ' + m, label='log.bookmark')
5465 ui.write(' ' + m, label='log.bookmark')
5460 ui.write('\n', label='log.bookmark')
5466 ui.write('\n', label='log.bookmark')
5461
5467
5462 st = list(repo.status(unknown=True))[:6]
5468 st = list(repo.status(unknown=True))[:6]
5463
5469
5464 c = repo.dirstate.copies()
5470 c = repo.dirstate.copies()
5465 copied, renamed = [], []
5471 copied, renamed = [], []
5466 for d, s in c.iteritems():
5472 for d, s in c.iteritems():
5467 if s in st[2]:
5473 if s in st[2]:
5468 st[2].remove(s)
5474 st[2].remove(s)
5469 renamed.append(d)
5475 renamed.append(d)
5470 else:
5476 else:
5471 copied.append(d)
5477 copied.append(d)
5472 if d in st[1]:
5478 if d in st[1]:
5473 st[1].remove(d)
5479 st[1].remove(d)
5474 st.insert(3, renamed)
5480 st.insert(3, renamed)
5475 st.insert(4, copied)
5481 st.insert(4, copied)
5476
5482
5477 ms = mergemod.mergestate(repo)
5483 ms = mergemod.mergestate(repo)
5478 st.append([f for f in ms if ms[f] == 'u'])
5484 st.append([f for f in ms if ms[f] == 'u'])
5479
5485
5480 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5486 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5481 st.append(subs)
5487 st.append(subs)
5482
5488
5483 labels = [ui.label(_('%d modified'), 'status.modified'),
5489 labels = [ui.label(_('%d modified'), 'status.modified'),
5484 ui.label(_('%d added'), 'status.added'),
5490 ui.label(_('%d added'), 'status.added'),
5485 ui.label(_('%d removed'), 'status.removed'),
5491 ui.label(_('%d removed'), 'status.removed'),
5486 ui.label(_('%d renamed'), 'status.copied'),
5492 ui.label(_('%d renamed'), 'status.copied'),
5487 ui.label(_('%d copied'), 'status.copied'),
5493 ui.label(_('%d copied'), 'status.copied'),
5488 ui.label(_('%d deleted'), 'status.deleted'),
5494 ui.label(_('%d deleted'), 'status.deleted'),
5489 ui.label(_('%d unknown'), 'status.unknown'),
5495 ui.label(_('%d unknown'), 'status.unknown'),
5490 ui.label(_('%d ignored'), 'status.ignored'),
5496 ui.label(_('%d ignored'), 'status.ignored'),
5491 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5497 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5492 ui.label(_('%d subrepos'), 'status.modified')]
5498 ui.label(_('%d subrepos'), 'status.modified')]
5493 t = []
5499 t = []
5494 for s, l in zip(st, labels):
5500 for s, l in zip(st, labels):
5495 if s:
5501 if s:
5496 t.append(l % len(s))
5502 t.append(l % len(s))
5497
5503
5498 t = ', '.join(t)
5504 t = ', '.join(t)
5499 cleanworkdir = False
5505 cleanworkdir = False
5500
5506
5501 if len(parents) > 1:
5507 if len(parents) > 1:
5502 t += _(' (merge)')
5508 t += _(' (merge)')
5503 elif branch != parents[0].branch():
5509 elif branch != parents[0].branch():
5504 t += _(' (new branch)')
5510 t += _(' (new branch)')
5505 elif (parents[0].closesbranch() and
5511 elif (parents[0].closesbranch() and
5506 pnode in repo.branchheads(branch, closed=True)):
5512 pnode in repo.branchheads(branch, closed=True)):
5507 t += _(' (head closed)')
5513 t += _(' (head closed)')
5508 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5514 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5509 t += _(' (clean)')
5515 t += _(' (clean)')
5510 cleanworkdir = True
5516 cleanworkdir = True
5511 elif pnode not in bheads:
5517 elif pnode not in bheads:
5512 t += _(' (new branch head)')
5518 t += _(' (new branch head)')
5513
5519
5514 if cleanworkdir:
5520 if cleanworkdir:
5515 ui.status(_('commit: %s\n') % t.strip())
5521 ui.status(_('commit: %s\n') % t.strip())
5516 else:
5522 else:
5517 ui.write(_('commit: %s\n') % t.strip())
5523 ui.write(_('commit: %s\n') % t.strip())
5518
5524
5519 # all ancestors of branch heads - all ancestors of parent = new csets
5525 # all ancestors of branch heads - all ancestors of parent = new csets
5520 new = [0] * len(repo)
5526 new = [0] * len(repo)
5521 cl = repo.changelog
5527 cl = repo.changelog
5522 for a in [cl.rev(n) for n in bheads]:
5528 for a in [cl.rev(n) for n in bheads]:
5523 new[a] = 1
5529 new[a] = 1
5524 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5530 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5525 new[a] = 1
5531 new[a] = 1
5526 for a in [p.rev() for p in parents]:
5532 for a in [p.rev() for p in parents]:
5527 if a >= 0:
5533 if a >= 0:
5528 new[a] = 0
5534 new[a] = 0
5529 for a in cl.ancestors([p.rev() for p in parents]):
5535 for a in cl.ancestors([p.rev() for p in parents]):
5530 new[a] = 0
5536 new[a] = 0
5531 new = sum(new)
5537 new = sum(new)
5532
5538
5533 if new == 0:
5539 if new == 0:
5534 ui.status(_('update: (current)\n'))
5540 ui.status(_('update: (current)\n'))
5535 elif pnode not in bheads:
5541 elif pnode not in bheads:
5536 ui.write(_('update: %d new changesets (update)\n') % new)
5542 ui.write(_('update: %d new changesets (update)\n') % new)
5537 else:
5543 else:
5538 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5544 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5539 (new, len(bheads)))
5545 (new, len(bheads)))
5540
5546
5541 if opts.get('remote'):
5547 if opts.get('remote'):
5542 t = []
5548 t = []
5543 source, branches = hg.parseurl(ui.expandpath('default'))
5549 source, branches = hg.parseurl(ui.expandpath('default'))
5544 other = hg.peer(repo, {}, source)
5550 other = hg.peer(repo, {}, source)
5545 revs, checkout = hg.addbranchrevs(repo, other, branches,
5551 revs, checkout = hg.addbranchrevs(repo, other, branches,
5546 opts.get('rev'))
5552 opts.get('rev'))
5547 ui.debug('comparing with %s\n' % util.hidepassword(source))
5553 ui.debug('comparing with %s\n' % util.hidepassword(source))
5548 repo.ui.pushbuffer()
5554 repo.ui.pushbuffer()
5549 commoninc = discovery.findcommonincoming(repo, other)
5555 commoninc = discovery.findcommonincoming(repo, other)
5550 _common, incoming, _rheads = commoninc
5556 _common, incoming, _rheads = commoninc
5551 repo.ui.popbuffer()
5557 repo.ui.popbuffer()
5552 if incoming:
5558 if incoming:
5553 t.append(_('1 or more incoming'))
5559 t.append(_('1 or more incoming'))
5554
5560
5555 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5561 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5556 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5562 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5557 if source != dest:
5563 if source != dest:
5558 other = hg.peer(repo, {}, dest)
5564 other = hg.peer(repo, {}, dest)
5559 commoninc = None
5565 commoninc = None
5560 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5566 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5561 repo.ui.pushbuffer()
5567 repo.ui.pushbuffer()
5562 outgoing = discovery.findcommonoutgoing(repo, other,
5568 outgoing = discovery.findcommonoutgoing(repo, other,
5563 commoninc=commoninc)
5569 commoninc=commoninc)
5564 repo.ui.popbuffer()
5570 repo.ui.popbuffer()
5565 o = outgoing.missing
5571 o = outgoing.missing
5566 if o:
5572 if o:
5567 t.append(_('%d outgoing') % len(o))
5573 t.append(_('%d outgoing') % len(o))
5568 if 'bookmarks' in other.listkeys('namespaces'):
5574 if 'bookmarks' in other.listkeys('namespaces'):
5569 lmarks = repo.listkeys('bookmarks')
5575 lmarks = repo.listkeys('bookmarks')
5570 rmarks = other.listkeys('bookmarks')
5576 rmarks = other.listkeys('bookmarks')
5571 diff = set(rmarks) - set(lmarks)
5577 diff = set(rmarks) - set(lmarks)
5572 if len(diff) > 0:
5578 if len(diff) > 0:
5573 t.append(_('%d incoming bookmarks') % len(diff))
5579 t.append(_('%d incoming bookmarks') % len(diff))
5574 diff = set(lmarks) - set(rmarks)
5580 diff = set(lmarks) - set(rmarks)
5575 if len(diff) > 0:
5581 if len(diff) > 0:
5576 t.append(_('%d outgoing bookmarks') % len(diff))
5582 t.append(_('%d outgoing bookmarks') % len(diff))
5577
5583
5578 if t:
5584 if t:
5579 ui.write(_('remote: %s\n') % (', '.join(t)))
5585 ui.write(_('remote: %s\n') % (', '.join(t)))
5580 else:
5586 else:
5581 ui.status(_('remote: (synced)\n'))
5587 ui.status(_('remote: (synced)\n'))
5582
5588
5583 @command('tag',
5589 @command('tag',
5584 [('f', 'force', None, _('force tag')),
5590 [('f', 'force', None, _('force tag')),
5585 ('l', 'local', None, _('make the tag local')),
5591 ('l', 'local', None, _('make the tag local')),
5586 ('r', 'rev', '', _('revision to tag'), _('REV')),
5592 ('r', 'rev', '', _('revision to tag'), _('REV')),
5587 ('', 'remove', None, _('remove a tag')),
5593 ('', 'remove', None, _('remove a tag')),
5588 # -l/--local is already there, commitopts cannot be used
5594 # -l/--local is already there, commitopts cannot be used
5589 ('e', 'edit', None, _('edit commit message')),
5595 ('e', 'edit', None, _('edit commit message')),
5590 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5596 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5591 ] + commitopts2,
5597 ] + commitopts2,
5592 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5598 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5593 def tag(ui, repo, name1, *names, **opts):
5599 def tag(ui, repo, name1, *names, **opts):
5594 """add one or more tags for the current or given revision
5600 """add one or more tags for the current or given revision
5595
5601
5596 Name a particular revision using <name>.
5602 Name a particular revision using <name>.
5597
5603
5598 Tags are used to name particular revisions of the repository and are
5604 Tags are used to name particular revisions of the repository and are
5599 very useful to compare different revisions, to go back to significant
5605 very useful to compare different revisions, to go back to significant
5600 earlier versions or to mark branch points as releases, etc. Changing
5606 earlier versions or to mark branch points as releases, etc. Changing
5601 an existing tag is normally disallowed; use -f/--force to override.
5607 an existing tag is normally disallowed; use -f/--force to override.
5602
5608
5603 If no revision is given, the parent of the working directory is
5609 If no revision is given, the parent of the working directory is
5604 used, or tip if no revision is checked out.
5610 used, or tip if no revision is checked out.
5605
5611
5606 To facilitate version control, distribution, and merging of tags,
5612 To facilitate version control, distribution, and merging of tags,
5607 they are stored as a file named ".hgtags" which is managed similarly
5613 they are stored as a file named ".hgtags" which is managed similarly
5608 to other project files and can be hand-edited if necessary. This
5614 to other project files and can be hand-edited if necessary. This
5609 also means that tagging creates a new commit. The file
5615 also means that tagging creates a new commit. The file
5610 ".hg/localtags" is used for local tags (not shared among
5616 ".hg/localtags" is used for local tags (not shared among
5611 repositories).
5617 repositories).
5612
5618
5613 Tag commits are usually made at the head of a branch. If the parent
5619 Tag commits are usually made at the head of a branch. If the parent
5614 of the working directory is not a branch head, :hg:`tag` aborts; use
5620 of the working directory is not a branch head, :hg:`tag` aborts; use
5615 -f/--force to force the tag commit to be based on a non-head
5621 -f/--force to force the tag commit to be based on a non-head
5616 changeset.
5622 changeset.
5617
5623
5618 See :hg:`help dates` for a list of formats valid for -d/--date.
5624 See :hg:`help dates` for a list of formats valid for -d/--date.
5619
5625
5620 Since tag names have priority over branch names during revision
5626 Since tag names have priority over branch names during revision
5621 lookup, using an existing branch name as a tag name is discouraged.
5627 lookup, using an existing branch name as a tag name is discouraged.
5622
5628
5623 Returns 0 on success.
5629 Returns 0 on success.
5624 """
5630 """
5625 wlock = lock = None
5631 wlock = lock = None
5626 try:
5632 try:
5627 wlock = repo.wlock()
5633 wlock = repo.wlock()
5628 lock = repo.lock()
5634 lock = repo.lock()
5629 rev_ = "."
5635 rev_ = "."
5630 names = [t.strip() for t in (name1,) + names]
5636 names = [t.strip() for t in (name1,) + names]
5631 if len(names) != len(set(names)):
5637 if len(names) != len(set(names)):
5632 raise util.Abort(_('tag names must be unique'))
5638 raise util.Abort(_('tag names must be unique'))
5633 for n in names:
5639 for n in names:
5634 if n in ['tip', '.', 'null']:
5640 if n in ['tip', '.', 'null']:
5635 raise util.Abort(_("the name '%s' is reserved") % n)
5641 raise util.Abort(_("the name '%s' is reserved") % n)
5636 if not n:
5642 if not n:
5637 raise util.Abort(_('tag names cannot consist entirely of '
5643 raise util.Abort(_('tag names cannot consist entirely of '
5638 'whitespace'))
5644 'whitespace'))
5639 if opts.get('rev') and opts.get('remove'):
5645 if opts.get('rev') and opts.get('remove'):
5640 raise util.Abort(_("--rev and --remove are incompatible"))
5646 raise util.Abort(_("--rev and --remove are incompatible"))
5641 if opts.get('rev'):
5647 if opts.get('rev'):
5642 rev_ = opts['rev']
5648 rev_ = opts['rev']
5643 message = opts.get('message')
5649 message = opts.get('message')
5644 if opts.get('remove'):
5650 if opts.get('remove'):
5645 expectedtype = opts.get('local') and 'local' or 'global'
5651 expectedtype = opts.get('local') and 'local' or 'global'
5646 for n in names:
5652 for n in names:
5647 if not repo.tagtype(n):
5653 if not repo.tagtype(n):
5648 raise util.Abort(_("tag '%s' does not exist") % n)
5654 raise util.Abort(_("tag '%s' does not exist") % n)
5649 if repo.tagtype(n) != expectedtype:
5655 if repo.tagtype(n) != expectedtype:
5650 if expectedtype == 'global':
5656 if expectedtype == 'global':
5651 raise util.Abort(_("tag '%s' is not a global tag") % n)
5657 raise util.Abort(_("tag '%s' is not a global tag") % n)
5652 else:
5658 else:
5653 raise util.Abort(_("tag '%s' is not a local tag") % n)
5659 raise util.Abort(_("tag '%s' is not a local tag") % n)
5654 rev_ = nullid
5660 rev_ = nullid
5655 if not message:
5661 if not message:
5656 # we don't translate commit messages
5662 # we don't translate commit messages
5657 message = 'Removed tag %s' % ', '.join(names)
5663 message = 'Removed tag %s' % ', '.join(names)
5658 elif not opts.get('force'):
5664 elif not opts.get('force'):
5659 for n in names:
5665 for n in names:
5660 if n in repo.tags():
5666 if n in repo.tags():
5661 raise util.Abort(_("tag '%s' already exists "
5667 raise util.Abort(_("tag '%s' already exists "
5662 "(use -f to force)") % n)
5668 "(use -f to force)") % n)
5663 if not opts.get('local'):
5669 if not opts.get('local'):
5664 p1, p2 = repo.dirstate.parents()
5670 p1, p2 = repo.dirstate.parents()
5665 if p2 != nullid:
5671 if p2 != nullid:
5666 raise util.Abort(_('uncommitted merge'))
5672 raise util.Abort(_('uncommitted merge'))
5667 bheads = repo.branchheads()
5673 bheads = repo.branchheads()
5668 if not opts.get('force') and bheads and p1 not in bheads:
5674 if not opts.get('force') and bheads and p1 not in bheads:
5669 raise util.Abort(_('not at a branch head (use -f to force)'))
5675 raise util.Abort(_('not at a branch head (use -f to force)'))
5670 r = scmutil.revsingle(repo, rev_).node()
5676 r = scmutil.revsingle(repo, rev_).node()
5671
5677
5672 if not message:
5678 if not message:
5673 # we don't translate commit messages
5679 # we don't translate commit messages
5674 message = ('Added tag %s for changeset %s' %
5680 message = ('Added tag %s for changeset %s' %
5675 (', '.join(names), short(r)))
5681 (', '.join(names), short(r)))
5676
5682
5677 date = opts.get('date')
5683 date = opts.get('date')
5678 if date:
5684 if date:
5679 date = util.parsedate(date)
5685 date = util.parsedate(date)
5680
5686
5681 if opts.get('edit'):
5687 if opts.get('edit'):
5682 message = ui.edit(message, ui.username())
5688 message = ui.edit(message, ui.username())
5683
5689
5684 # don't allow tagging the null rev
5690 # don't allow tagging the null rev
5685 if (not opts.get('remove') and
5691 if (not opts.get('remove') and
5686 scmutil.revsingle(repo, rev_).rev() == nullrev):
5692 scmutil.revsingle(repo, rev_).rev() == nullrev):
5687 raise util.Abort(_("null revision specified"))
5693 raise util.Abort(_("null revision specified"))
5688
5694
5689 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5695 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5690 finally:
5696 finally:
5691 release(lock, wlock)
5697 release(lock, wlock)
5692
5698
5693 @command('tags', [], '')
5699 @command('tags', [], '')
5694 def tags(ui, repo):
5700 def tags(ui, repo):
5695 """list repository tags
5701 """list repository tags
5696
5702
5697 This lists both regular and local tags. When the -v/--verbose
5703 This lists both regular and local tags. When the -v/--verbose
5698 switch is used, a third column "local" is printed for local tags.
5704 switch is used, a third column "local" is printed for local tags.
5699
5705
5700 Returns 0 on success.
5706 Returns 0 on success.
5701 """
5707 """
5702
5708
5703 hexfunc = ui.debugflag and hex or short
5709 hexfunc = ui.debugflag and hex or short
5704 tagtype = ""
5710 tagtype = ""
5705
5711
5706 for t, n in reversed(repo.tagslist()):
5712 for t, n in reversed(repo.tagslist()):
5707 if ui.quiet:
5713 if ui.quiet:
5708 ui.write("%s\n" % t, label='tags.normal')
5714 ui.write("%s\n" % t, label='tags.normal')
5709 continue
5715 continue
5710
5716
5711 hn = hexfunc(n)
5717 hn = hexfunc(n)
5712 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5718 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5713 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5719 rev = ui.label(r, 'log.changeset changeset.%s' % repo[n].phasestr())
5714 spaces = " " * (30 - encoding.colwidth(t))
5720 spaces = " " * (30 - encoding.colwidth(t))
5715
5721
5716 tag = ui.label(t, 'tags.normal')
5722 tag = ui.label(t, 'tags.normal')
5717 if ui.verbose:
5723 if ui.verbose:
5718 if repo.tagtype(t) == 'local':
5724 if repo.tagtype(t) == 'local':
5719 tagtype = " local"
5725 tagtype = " local"
5720 tag = ui.label(t, 'tags.local')
5726 tag = ui.label(t, 'tags.local')
5721 else:
5727 else:
5722 tagtype = ""
5728 tagtype = ""
5723 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5729 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5724
5730
5725 @command('tip',
5731 @command('tip',
5726 [('p', 'patch', None, _('show patch')),
5732 [('p', 'patch', None, _('show patch')),
5727 ('g', 'git', None, _('use git extended diff format')),
5733 ('g', 'git', None, _('use git extended diff format')),
5728 ] + templateopts,
5734 ] + templateopts,
5729 _('[-p] [-g]'))
5735 _('[-p] [-g]'))
5730 def tip(ui, repo, **opts):
5736 def tip(ui, repo, **opts):
5731 """show the tip revision
5737 """show the tip revision
5732
5738
5733 The tip revision (usually just called the tip) is the changeset
5739 The tip revision (usually just called the tip) is the changeset
5734 most recently added to the repository (and therefore the most
5740 most recently added to the repository (and therefore the most
5735 recently changed head).
5741 recently changed head).
5736
5742
5737 If you have just made a commit, that commit will be the tip. If
5743 If you have just made a commit, that commit will be the tip. If
5738 you have just pulled changes from another repository, the tip of
5744 you have just pulled changes from another repository, the tip of
5739 that repository becomes the current tip. The "tip" tag is special
5745 that repository becomes the current tip. The "tip" tag is special
5740 and cannot be renamed or assigned to a different changeset.
5746 and cannot be renamed or assigned to a different changeset.
5741
5747
5742 Returns 0 on success.
5748 Returns 0 on success.
5743 """
5749 """
5744 displayer = cmdutil.show_changeset(ui, repo, opts)
5750 displayer = cmdutil.show_changeset(ui, repo, opts)
5745 displayer.show(repo[len(repo) - 1])
5751 displayer.show(repo[len(repo) - 1])
5746 displayer.close()
5752 displayer.close()
5747
5753
5748 @command('unbundle',
5754 @command('unbundle',
5749 [('u', 'update', None,
5755 [('u', 'update', None,
5750 _('update to new branch head if changesets were unbundled'))],
5756 _('update to new branch head if changesets were unbundled'))],
5751 _('[-u] FILE...'))
5757 _('[-u] FILE...'))
5752 def unbundle(ui, repo, fname1, *fnames, **opts):
5758 def unbundle(ui, repo, fname1, *fnames, **opts):
5753 """apply one or more changegroup files
5759 """apply one or more changegroup files
5754
5760
5755 Apply one or more compressed changegroup files generated by the
5761 Apply one or more compressed changegroup files generated by the
5756 bundle command.
5762 bundle command.
5757
5763
5758 Returns 0 on success, 1 if an update has unresolved files.
5764 Returns 0 on success, 1 if an update has unresolved files.
5759 """
5765 """
5760 fnames = (fname1,) + fnames
5766 fnames = (fname1,) + fnames
5761
5767
5762 lock = repo.lock()
5768 lock = repo.lock()
5763 wc = repo['.']
5769 wc = repo['.']
5764 try:
5770 try:
5765 for fname in fnames:
5771 for fname in fnames:
5766 f = url.open(ui, fname)
5772 f = url.open(ui, fname)
5767 gen = changegroup.readbundle(f, fname)
5773 gen = changegroup.readbundle(f, fname)
5768 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5774 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5769 finally:
5775 finally:
5770 lock.release()
5776 lock.release()
5771 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5777 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5772 return postincoming(ui, repo, modheads, opts.get('update'), None)
5778 return postincoming(ui, repo, modheads, opts.get('update'), None)
5773
5779
5774 @command('^update|up|checkout|co',
5780 @command('^update|up|checkout|co',
5775 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5781 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5776 ('c', 'check', None,
5782 ('c', 'check', None,
5777 _('update across branches if no uncommitted changes')),
5783 _('update across branches if no uncommitted changes')),
5778 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5784 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5779 ('r', 'rev', '', _('revision'), _('REV'))],
5785 ('r', 'rev', '', _('revision'), _('REV'))],
5780 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5786 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5781 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5787 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5782 """update working directory (or switch revisions)
5788 """update working directory (or switch revisions)
5783
5789
5784 Update the repository's working directory to the specified
5790 Update the repository's working directory to the specified
5785 changeset. If no changeset is specified, update to the tip of the
5791 changeset. If no changeset is specified, update to the tip of the
5786 current named branch and move the current bookmark (see :hg:`help
5792 current named branch and move the current bookmark (see :hg:`help
5787 bookmarks`).
5793 bookmarks`).
5788
5794
5789 Update sets the working directory's parent revision to the specified
5795 Update sets the working directory's parent revision to the specified
5790 changeset (see :hg:`help parents`).
5796 changeset (see :hg:`help parents`).
5791
5797
5792 If the changeset is not a descendant or ancestor of the working
5798 If the changeset is not a descendant or ancestor of the working
5793 directory's parent, the update is aborted. With the -c/--check
5799 directory's parent, the update is aborted. With the -c/--check
5794 option, the working directory is checked for uncommitted changes; if
5800 option, the working directory is checked for uncommitted changes; if
5795 none are found, the working directory is updated to the specified
5801 none are found, the working directory is updated to the specified
5796 changeset.
5802 changeset.
5797
5803
5798 .. container:: verbose
5804 .. container:: verbose
5799
5805
5800 The following rules apply when the working directory contains
5806 The following rules apply when the working directory contains
5801 uncommitted changes:
5807 uncommitted changes:
5802
5808
5803 1. If neither -c/--check nor -C/--clean is specified, and if
5809 1. If neither -c/--check nor -C/--clean is specified, and if
5804 the requested changeset is an ancestor or descendant of
5810 the requested changeset is an ancestor or descendant of
5805 the working directory's parent, the uncommitted changes
5811 the working directory's parent, the uncommitted changes
5806 are merged into the requested changeset and the merged
5812 are merged into the requested changeset and the merged
5807 result is left uncommitted. If the requested changeset is
5813 result is left uncommitted. If the requested changeset is
5808 not an ancestor or descendant (that is, it is on another
5814 not an ancestor or descendant (that is, it is on another
5809 branch), the update is aborted and the uncommitted changes
5815 branch), the update is aborted and the uncommitted changes
5810 are preserved.
5816 are preserved.
5811
5817
5812 2. With the -c/--check option, the update is aborted and the
5818 2. With the -c/--check option, the update is aborted and the
5813 uncommitted changes are preserved.
5819 uncommitted changes are preserved.
5814
5820
5815 3. With the -C/--clean option, uncommitted changes are discarded and
5821 3. With the -C/--clean option, uncommitted changes are discarded and
5816 the working directory is updated to the requested changeset.
5822 the working directory is updated to the requested changeset.
5817
5823
5818 To cancel an uncommitted merge (and lose your changes), use
5824 To cancel an uncommitted merge (and lose your changes), use
5819 :hg:`update --clean .`.
5825 :hg:`update --clean .`.
5820
5826
5821 Use null as the changeset to remove the working directory (like
5827 Use null as the changeset to remove the working directory (like
5822 :hg:`clone -U`).
5828 :hg:`clone -U`).
5823
5829
5824 If you want to revert just one file to an older revision, use
5830 If you want to revert just one file to an older revision, use
5825 :hg:`revert [-r REV] NAME`.
5831 :hg:`revert [-r REV] NAME`.
5826
5832
5827 See :hg:`help dates` for a list of formats valid for -d/--date.
5833 See :hg:`help dates` for a list of formats valid for -d/--date.
5828
5834
5829 Returns 0 on success, 1 if there are unresolved files.
5835 Returns 0 on success, 1 if there are unresolved files.
5830 """
5836 """
5831 if rev and node:
5837 if rev and node:
5832 raise util.Abort(_("please specify just one revision"))
5838 raise util.Abort(_("please specify just one revision"))
5833
5839
5834 if rev is None or rev == '':
5840 if rev is None or rev == '':
5835 rev = node
5841 rev = node
5836
5842
5837 # with no argument, we also move the current bookmark, if any
5843 # with no argument, we also move the current bookmark, if any
5838 movemarkfrom = None
5844 movemarkfrom = None
5839 if rev is None or node == '':
5845 if rev is None or node == '':
5840 movemarkfrom = repo['.'].node()
5846 movemarkfrom = repo['.'].node()
5841
5847
5842 # if we defined a bookmark, we have to remember the original bookmark name
5848 # if we defined a bookmark, we have to remember the original bookmark name
5843 brev = rev
5849 brev = rev
5844 rev = scmutil.revsingle(repo, rev, rev).rev()
5850 rev = scmutil.revsingle(repo, rev, rev).rev()
5845
5851
5846 if check and clean:
5852 if check and clean:
5847 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5853 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5848
5854
5849 if date:
5855 if date:
5850 if rev is not None:
5856 if rev is not None:
5851 raise util.Abort(_("you can't specify a revision and a date"))
5857 raise util.Abort(_("you can't specify a revision and a date"))
5852 rev = cmdutil.finddate(ui, repo, date)
5858 rev = cmdutil.finddate(ui, repo, date)
5853
5859
5854 if check:
5860 if check:
5855 c = repo[None]
5861 c = repo[None]
5856 if c.dirty(merge=False, branch=False):
5862 if c.dirty(merge=False, branch=False):
5857 raise util.Abort(_("uncommitted local changes"))
5863 raise util.Abort(_("uncommitted local changes"))
5858 if rev is None:
5864 if rev is None:
5859 rev = repo[repo[None].branch()].rev()
5865 rev = repo[repo[None].branch()].rev()
5860 mergemod._checkunknown(repo, repo[None], repo[rev])
5866 mergemod._checkunknown(repo, repo[None], repo[rev])
5861
5867
5862 if clean:
5868 if clean:
5863 ret = hg.clean(repo, rev)
5869 ret = hg.clean(repo, rev)
5864 else:
5870 else:
5865 ret = hg.update(repo, rev)
5871 ret = hg.update(repo, rev)
5866
5872
5867 if not ret and movemarkfrom:
5873 if not ret and movemarkfrom:
5868 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5874 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5869 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5875 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5870 elif brev in repo._bookmarks:
5876 elif brev in repo._bookmarks:
5871 bookmarks.setcurrent(repo, brev)
5877 bookmarks.setcurrent(repo, brev)
5872 elif brev:
5878 elif brev:
5873 bookmarks.unsetcurrent(repo)
5879 bookmarks.unsetcurrent(repo)
5874
5880
5875 return ret
5881 return ret
5876
5882
5877 @command('verify', [])
5883 @command('verify', [])
5878 def verify(ui, repo):
5884 def verify(ui, repo):
5879 """verify the integrity of the repository
5885 """verify the integrity of the repository
5880
5886
5881 Verify the integrity of the current repository.
5887 Verify the integrity of the current repository.
5882
5888
5883 This will perform an extensive check of the repository's
5889 This will perform an extensive check of the repository's
5884 integrity, validating the hashes and checksums of each entry in
5890 integrity, validating the hashes and checksums of each entry in
5885 the changelog, manifest, and tracked files, as well as the
5891 the changelog, manifest, and tracked files, as well as the
5886 integrity of their crosslinks and indices.
5892 integrity of their crosslinks and indices.
5887
5893
5888 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5894 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5889 for more information about recovery from corruption of the
5895 for more information about recovery from corruption of the
5890 repository.
5896 repository.
5891
5897
5892 Returns 0 on success, 1 if errors are encountered.
5898 Returns 0 on success, 1 if errors are encountered.
5893 """
5899 """
5894 return hg.verify(repo)
5900 return hg.verify(repo)
5895
5901
5896 @command('version', [])
5902 @command('version', [])
5897 def version_(ui):
5903 def version_(ui):
5898 """output version and copyright information"""
5904 """output version and copyright information"""
5899 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5900 % util.version())
5906 % util.version())
5901 ui.status(_(
5907 ui.status(_(
5902 "(see http://mercurial.selenic.com for more information)\n"
5908 "(see http://mercurial.selenic.com for more information)\n"
5903 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5909 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5904 "This is free software; see the source for copying conditions. "
5910 "This is free software; see the source for copying conditions. "
5905 "There is NO\nwarranty; "
5911 "There is NO\nwarranty; "
5906 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5907 ))
5913 ))
5908
5914
5909 norepo = ("clone init version help debugcommands debugcomplete"
5915 norepo = ("clone init version help debugcommands debugcomplete"
5910 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5916 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5911 " debugknown debuggetbundle debugbundle")
5917 " debugknown debuggetbundle debugbundle")
5912 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5918 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5913 " debugdata debugindex debugindexdot debugrevlog")
5919 " debugdata debugindex debugindexdot debugrevlog")
5914 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5920 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5915 " remove resolve status debugwalk")
5921 " remove resolve status debugwalk")
@@ -1,483 +1,506 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0
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 '
221 > '
222 abort: bookmark name cannot contain newlines
223 [255]
224
220 bookmark with existing name
225 bookmark with existing name
221
226
222 $ hg bookmark Z
227 $ hg bookmark Z
223 abort: bookmark 'Z' already exists (use -f to force)
228 abort: bookmark 'Z' already exists (use -f to force)
224 [255]
229 [255]
225
230
231 $ hg bookmark -m Y Z
232 abort: bookmark 'Z' already exists (use -f to force)
233 [255]
234
235 bookmark with name of branch
236
237 $ hg bookmark default
238 abort: a bookmark cannot have the name of an existing branch
239 [255]
240
241 $ hg bookmark -m Y default
242 abort: a bookmark cannot have the name of an existing branch
243 [255]
244
226 force bookmark with existing name
245 force bookmark with existing name
227
246
228 $ hg bookmark -f Z
247 $ hg bookmark -f Z
229
248
230 list bookmarks
249 list bookmarks
231
250
232 $ hg bookmark
251 $ hg bookmark
233 X2 1:925d80f479bb
252 X2 1:925d80f479bb
234 Y 2:db815d6d32e6
253 Y 2:db815d6d32e6
235 * Z 2:db815d6d32e6
254 * Z 2:db815d6d32e6
236 x y 2:db815d6d32e6
255 x y 2:db815d6d32e6
237
256
238 revision but no bookmark name
257 revision but no bookmark name
239
258
240 $ hg bookmark -r .
259 $ hg bookmark -r .
241 abort: bookmark name required
260 abort: bookmark name required
242 [255]
261 [255]
243
262
244 bookmark name with whitespace only
263 bookmark name with whitespace only
245
264
246 $ hg bookmark ' '
265 $ hg bookmark ' '
247 abort: bookmark names cannot consist entirely of whitespace
266 abort: bookmark names cannot consist entirely of whitespace
248 [255]
267 [255]
249
268
269 $ hg bookmark -m Y ' '
270 abort: bookmark names cannot consist entirely of whitespace
271 [255]
272
250 invalid bookmark
273 invalid bookmark
251
274
252 $ hg bookmark 'foo:bar'
275 $ hg bookmark 'foo:bar'
253 abort: bookmark 'foo:bar' contains illegal character
276 abort: bookmark 'foo:bar' contains illegal character
254 [255]
277 [255]
255
278
256 the bookmark extension should be ignored now that it is part of core
279 the bookmark extension should be ignored now that it is part of core
257
280
258 $ echo "[extensions]" >> $HGRCPATH
281 $ echo "[extensions]" >> $HGRCPATH
259 $ echo "bookmarks=" >> $HGRCPATH
282 $ echo "bookmarks=" >> $HGRCPATH
260 $ hg bookmarks
283 $ hg bookmarks
261 X2 1:925d80f479bb
284 X2 1:925d80f479bb
262 Y 2:db815d6d32e6
285 Y 2:db815d6d32e6
263 * Z 2:db815d6d32e6
286 * Z 2:db815d6d32e6
264 x y 2:db815d6d32e6
287 x y 2:db815d6d32e6
265
288
266 test summary
289 test summary
267
290
268 $ hg summary
291 $ hg summary
269 parent: 2:db815d6d32e6 tip
292 parent: 2:db815d6d32e6 tip
270 2
293 2
271 branch: default
294 branch: default
272 bookmarks: *Z Y x y
295 bookmarks: *Z Y x y
273 commit: (clean)
296 commit: (clean)
274 update: 1 new changesets, 2 branch heads (merge)
297 update: 1 new changesets, 2 branch heads (merge)
275
298
276 test id
299 test id
277
300
278 $ hg id
301 $ hg id
279 db815d6d32e6 tip Y/Z/x y
302 db815d6d32e6 tip Y/Z/x y
280
303
281 test rollback
304 test rollback
282
305
283 $ echo foo > f1
306 $ echo foo > f1
284 $ hg ci -Amr
307 $ hg ci -Amr
285 adding f1
308 adding f1
286 $ hg bookmark -f Y -r 1
309 $ hg bookmark -f Y -r 1
287 $ hg bookmark -f Z -r 1
310 $ hg bookmark -f Z -r 1
288 $ hg rollback
311 $ hg rollback
289 repository tip rolled back to revision 2 (undo commit)
312 repository tip rolled back to revision 2 (undo commit)
290 working directory now based on revision 2
313 working directory now based on revision 2
291 $ hg bookmarks
314 $ hg bookmarks
292 X2 1:925d80f479bb
315 X2 1:925d80f479bb
293 Y 2:db815d6d32e6
316 Y 2:db815d6d32e6
294 * Z 2:db815d6d32e6
317 * Z 2:db815d6d32e6
295 x y 2:db815d6d32e6
318 x y 2:db815d6d32e6
296
319
297 test clone
320 test clone
298
321
299 $ hg bookmark -r 2 -i @
322 $ hg bookmark -r 2 -i @
300 $ hg bookmark -r 2 -i a@
323 $ hg bookmark -r 2 -i a@
301 $ hg bookmarks
324 $ hg bookmarks
302 @ 2:db815d6d32e6
325 @ 2:db815d6d32e6
303 X2 1:925d80f479bb
326 X2 1:925d80f479bb
304 Y 2:db815d6d32e6
327 Y 2:db815d6d32e6
305 * Z 2:db815d6d32e6
328 * Z 2:db815d6d32e6
306 a@ 2:db815d6d32e6
329 a@ 2:db815d6d32e6
307 x y 2:db815d6d32e6
330 x y 2:db815d6d32e6
308 $ hg clone . cloned-bookmarks
331 $ hg clone . cloned-bookmarks
309 updating to branch default
332 updating to branch default
310 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 $ hg -R cloned-bookmarks bookmarks
334 $ hg -R cloned-bookmarks bookmarks
312 @ 2:db815d6d32e6
335 @ 2:db815d6d32e6
313 X2 1:925d80f479bb
336 X2 1:925d80f479bb
314 Y 2:db815d6d32e6
337 Y 2:db815d6d32e6
315 Z 2:db815d6d32e6
338 Z 2:db815d6d32e6
316 a@ 2:db815d6d32e6
339 a@ 2:db815d6d32e6
317 x y 2:db815d6d32e6
340 x y 2:db815d6d32e6
318
341
319 test clone with pull protocol
342 test clone with pull protocol
320
343
321 $ hg clone --pull . cloned-bookmarks-pull
344 $ hg clone --pull . cloned-bookmarks-pull
322 requesting all changes
345 requesting all changes
323 adding changesets
346 adding changesets
324 adding manifests
347 adding manifests
325 adding file changes
348 adding file changes
326 added 3 changesets with 3 changes to 3 files (+1 heads)
349 added 3 changesets with 3 changes to 3 files (+1 heads)
327 updating to branch default
350 updating to branch default
328 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ hg -R cloned-bookmarks-pull bookmarks
352 $ hg -R cloned-bookmarks-pull bookmarks
330 @ 2:db815d6d32e6
353 @ 2:db815d6d32e6
331 X2 1:925d80f479bb
354 X2 1:925d80f479bb
332 Y 2:db815d6d32e6
355 Y 2:db815d6d32e6
333 Z 2:db815d6d32e6
356 Z 2:db815d6d32e6
334 a@ 2:db815d6d32e6
357 a@ 2:db815d6d32e6
335 x y 2:db815d6d32e6
358 x y 2:db815d6d32e6
336
359
337 $ hg bookmark -d @
360 $ hg bookmark -d @
338 $ hg bookmark -d a@
361 $ hg bookmark -d a@
339
362
340 test clone with a specific revision
363 test clone with a specific revision
341
364
342 $ hg clone -r 925d80 . cloned-bookmarks-rev
365 $ hg clone -r 925d80 . cloned-bookmarks-rev
343 adding changesets
366 adding changesets
344 adding manifests
367 adding manifests
345 adding file changes
368 adding file changes
346 added 2 changesets with 2 changes to 2 files
369 added 2 changesets with 2 changes to 2 files
347 updating to branch default
370 updating to branch default
348 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
371 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 $ hg -R cloned-bookmarks-rev bookmarks
372 $ hg -R cloned-bookmarks-rev bookmarks
350 X2 1:925d80f479bb
373 X2 1:925d80f479bb
351
374
352 test clone with update to a bookmark
375 test clone with update to a bookmark
353
376
354 $ hg clone -u Z . cloned-bookmarks-update
377 $ hg clone -u Z . cloned-bookmarks-update
355 updating to branch default
378 updating to branch default
356 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 $ hg -R cloned-bookmarks-update bookmarks
380 $ hg -R cloned-bookmarks-update bookmarks
358 X2 1:925d80f479bb
381 X2 1:925d80f479bb
359 Y 2:db815d6d32e6
382 Y 2:db815d6d32e6
360 * Z 2:db815d6d32e6
383 * Z 2:db815d6d32e6
361 x y 2:db815d6d32e6
384 x y 2:db815d6d32e6
362
385
363 create bundle with two heads
386 create bundle with two heads
364
387
365 $ hg clone . tobundle
388 $ hg clone . tobundle
366 updating to branch default
389 updating to branch default
367 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
390 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 $ echo x > tobundle/x
391 $ echo x > tobundle/x
369 $ hg -R tobundle add tobundle/x
392 $ hg -R tobundle add tobundle/x
370 $ hg -R tobundle commit -m'x'
393 $ hg -R tobundle commit -m'x'
371 $ hg -R tobundle update -r -2
394 $ hg -R tobundle update -r -2
372 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
395 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
373 $ echo y > tobundle/y
396 $ echo y > tobundle/y
374 $ hg -R tobundle branch test
397 $ hg -R tobundle branch test
375 marked working directory as branch test
398 marked working directory as branch test
376 (branches are permanent and global, did you want a bookmark?)
399 (branches are permanent and global, did you want a bookmark?)
377 $ hg -R tobundle add tobundle/y
400 $ hg -R tobundle add tobundle/y
378 $ hg -R tobundle commit -m'y'
401 $ hg -R tobundle commit -m'y'
379 $ hg -R tobundle bundle tobundle.hg
402 $ hg -R tobundle bundle tobundle.hg
380 searching for changes
403 searching for changes
381 2 changesets found
404 2 changesets found
382 $ hg unbundle tobundle.hg
405 $ hg unbundle tobundle.hg
383 adding changesets
406 adding changesets
384 adding manifests
407 adding manifests
385 adding file changes
408 adding file changes
386 added 2 changesets with 2 changes to 2 files (+1 heads)
409 added 2 changesets with 2 changes to 2 files (+1 heads)
387 (run 'hg heads' to see heads, 'hg merge' to merge)
410 (run 'hg heads' to see heads, 'hg merge' to merge)
388 $ hg update
411 $ hg update
389 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
390 $ hg bookmarks
413 $ hg bookmarks
391 X2 1:925d80f479bb
414 X2 1:925d80f479bb
392 Y 2:db815d6d32e6
415 Y 2:db815d6d32e6
393 * Z 3:125c9a1d6df6
416 * Z 3:125c9a1d6df6
394 x y 2:db815d6d32e6
417 x y 2:db815d6d32e6
395
418
396 test wrongly formated bookmark
419 test wrongly formated bookmark
397
420
398 $ echo '' >> .hg/bookmarks
421 $ echo '' >> .hg/bookmarks
399 $ hg bookmarks
422 $ hg bookmarks
400 X2 1:925d80f479bb
423 X2 1:925d80f479bb
401 Y 2:db815d6d32e6
424 Y 2:db815d6d32e6
402 * Z 3:125c9a1d6df6
425 * Z 3:125c9a1d6df6
403 x y 2:db815d6d32e6
426 x y 2:db815d6d32e6
404 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
427 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
405 $ hg bookmarks
428 $ hg bookmarks
406 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
429 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
407 X2 1:925d80f479bb
430 X2 1:925d80f479bb
408 Y 2:db815d6d32e6
431 Y 2:db815d6d32e6
409 * Z 3:125c9a1d6df6
432 * Z 3:125c9a1d6df6
410 x y 2:db815d6d32e6
433 x y 2:db815d6d32e6
411
434
412 test missing revisions
435 test missing revisions
413
436
414 $ echo "925d80f479bc z" > .hg/bookmarks
437 $ echo "925d80f479bc z" > .hg/bookmarks
415 $ hg book
438 $ hg book
416 no bookmarks set
439 no bookmarks set
417
440
418 test stripping a non-checked-out but bookmarked revision
441 test stripping a non-checked-out but bookmarked revision
419
442
420 $ hg --config extensions.graphlog= log --graph
443 $ hg --config extensions.graphlog= log --graph
421 o changeset: 4:9ba5f110a0b3
444 o changeset: 4:9ba5f110a0b3
422 | branch: test
445 | branch: test
423 | tag: tip
446 | tag: tip
424 | parent: 2:db815d6d32e6
447 | parent: 2:db815d6d32e6
425 | user: test
448 | user: test
426 | date: Thu Jan 01 00:00:00 1970 +0000
449 | date: Thu Jan 01 00:00:00 1970 +0000
427 | summary: y
450 | summary: y
428 |
451 |
429 | @ changeset: 3:125c9a1d6df6
452 | @ changeset: 3:125c9a1d6df6
430 |/ user: test
453 |/ user: test
431 | date: Thu Jan 01 00:00:00 1970 +0000
454 | date: Thu Jan 01 00:00:00 1970 +0000
432 | summary: x
455 | summary: x
433 |
456 |
434 o changeset: 2:db815d6d32e6
457 o changeset: 2:db815d6d32e6
435 | parent: 0:f7b1eb17ad24
458 | parent: 0:f7b1eb17ad24
436 | user: test
459 | user: test
437 | date: Thu Jan 01 00:00:00 1970 +0000
460 | date: Thu Jan 01 00:00:00 1970 +0000
438 | summary: 2
461 | summary: 2
439 |
462 |
440 | o changeset: 1:925d80f479bb
463 | o changeset: 1:925d80f479bb
441 |/ user: test
464 |/ user: test
442 | date: Thu Jan 01 00:00:00 1970 +0000
465 | date: Thu Jan 01 00:00:00 1970 +0000
443 | summary: 1
466 | summary: 1
444 |
467 |
445 o changeset: 0:f7b1eb17ad24
468 o changeset: 0:f7b1eb17ad24
446 user: test
469 user: test
447 date: Thu Jan 01 00:00:00 1970 +0000
470 date: Thu Jan 01 00:00:00 1970 +0000
448 summary: 0
471 summary: 0
449
472
450 $ hg book should-end-on-two
473 $ hg book should-end-on-two
451 $ hg co --clean 4
474 $ hg co --clean 4
452 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
475 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
453 $ hg book four
476 $ hg book four
454 $ hg --config extensions.mq= strip 3
477 $ hg --config extensions.mq= strip 3
455 saved backup bundle to * (glob)
478 saved backup bundle to * (glob)
456 should-end-on-two should end up pointing to revision 2, as that's the
479 should-end-on-two should end up pointing to revision 2, as that's the
457 tipmost surviving ancestor of the stripped revision.
480 tipmost surviving ancestor of the stripped revision.
458 $ hg --config extensions.graphlog= log --graph
481 $ hg --config extensions.graphlog= log --graph
459 @ changeset: 3:9ba5f110a0b3
482 @ changeset: 3:9ba5f110a0b3
460 | branch: test
483 | branch: test
461 | bookmark: four
484 | bookmark: four
462 | tag: tip
485 | tag: tip
463 | user: test
486 | user: test
464 | date: Thu Jan 01 00:00:00 1970 +0000
487 | date: Thu Jan 01 00:00:00 1970 +0000
465 | summary: y
488 | summary: y
466 |
489 |
467 o changeset: 2:db815d6d32e6
490 o changeset: 2:db815d6d32e6
468 | bookmark: should-end-on-two
491 | bookmark: should-end-on-two
469 | parent: 0:f7b1eb17ad24
492 | parent: 0:f7b1eb17ad24
470 | user: test
493 | user: test
471 | date: Thu Jan 01 00:00:00 1970 +0000
494 | date: Thu Jan 01 00:00:00 1970 +0000
472 | summary: 2
495 | summary: 2
473 |
496 |
474 | o changeset: 1:925d80f479bb
497 | o changeset: 1:925d80f479bb
475 |/ user: test
498 |/ user: test
476 | date: Thu Jan 01 00:00:00 1970 +0000
499 | date: Thu Jan 01 00:00:00 1970 +0000
477 | summary: 1
500 | summary: 1
478 |
501 |
479 o changeset: 0:f7b1eb17ad24
502 o changeset: 0:f7b1eb17ad24
480 user: test
503 user: test
481 date: Thu Jan 01 00:00:00 1970 +0000
504 date: Thu Jan 01 00:00:00 1970 +0000
482 summary: 0
505 summary: 0
483
506
General Comments 0
You need to be logged in to leave comments. Login now