##// END OF EJS Templates
bookmarks: deactivate current bookmark if no name is given...
Kevin Bullock -
r17735:605fe310 stable
parent child Browse files
Show More
@@ -1,5902 +1,5908 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 (eg. if
546 - mark the current revision, or a known revision, to be skipped (eg. if
547 that revision is not usable because of another issue)::
547 that revision is not usable because of another issue)::
548
548
549 hg bisect --skip
549 hg bisect --skip
550 hg bisect --skip 23
550 hg bisect --skip 23
551
551
552 - forget the current bisection::
552 - forget the current bisection::
553
553
554 hg bisect --reset
554 hg bisect --reset
555
555
556 - use 'make && make tests' to automatically find the first broken
556 - use 'make && make tests' to automatically find the first broken
557 revision::
557 revision::
558
558
559 hg bisect --reset
559 hg bisect --reset
560 hg bisect --bad 34
560 hg bisect --bad 34
561 hg bisect --good 12
561 hg bisect --good 12
562 hg bisect --command 'make && make tests'
562 hg bisect --command 'make && make tests'
563
563
564 - see all changesets whose states are already known in the current
564 - see all changesets whose states are already known in the current
565 bisection::
565 bisection::
566
566
567 hg log -r "bisect(pruned)"
567 hg log -r "bisect(pruned)"
568
568
569 - see the changeset currently being bisected (especially useful
569 - see the changeset currently being bisected (especially useful
570 if running with -U/--noupdate)::
570 if running with -U/--noupdate)::
571
571
572 hg log -r "bisect(current)"
572 hg log -r "bisect(current)"
573
573
574 - see all changesets that took part in the current bisection::
574 - see all changesets that took part in the current bisection::
575
575
576 hg log -r "bisect(range)"
576 hg log -r "bisect(range)"
577
577
578 - with the graphlog extension, you can even get a nice graph::
578 - with the graphlog extension, you can even get a nice graph::
579
579
580 hg log --graph -r "bisect(range)"
580 hg log --graph -r "bisect(range)"
581
581
582 See :hg:`help revsets` for more about the `bisect()` keyword.
582 See :hg:`help revsets` for more about the `bisect()` keyword.
583
583
584 Returns 0 on success.
584 Returns 0 on success.
585 """
585 """
586 def extendbisectrange(nodes, good):
586 def extendbisectrange(nodes, good):
587 # bisect is incomplete when it ends on a merge node and
587 # bisect is incomplete when it ends on a merge node and
588 # one of the parent was not checked.
588 # one of the parent was not checked.
589 parents = repo[nodes[0]].parents()
589 parents = repo[nodes[0]].parents()
590 if len(parents) > 1:
590 if len(parents) > 1:
591 side = good and state['bad'] or state['good']
591 side = good and state['bad'] or state['good']
592 num = len(set(i.node() for i in parents) & set(side))
592 num = len(set(i.node() for i in parents) & set(side))
593 if num == 1:
593 if num == 1:
594 return parents[0].ancestor(parents[1])
594 return parents[0].ancestor(parents[1])
595 return None
595 return None
596
596
597 def print_result(nodes, good):
597 def print_result(nodes, good):
598 displayer = cmdutil.show_changeset(ui, repo, {})
598 displayer = cmdutil.show_changeset(ui, repo, {})
599 if len(nodes) == 1:
599 if len(nodes) == 1:
600 # narrowed it down to a single revision
600 # narrowed it down to a single revision
601 if good:
601 if good:
602 ui.write(_("The first good revision is:\n"))
602 ui.write(_("The first good revision is:\n"))
603 else:
603 else:
604 ui.write(_("The first bad revision is:\n"))
604 ui.write(_("The first bad revision is:\n"))
605 displayer.show(repo[nodes[0]])
605 displayer.show(repo[nodes[0]])
606 extendnode = extendbisectrange(nodes, good)
606 extendnode = extendbisectrange(nodes, good)
607 if extendnode is not None:
607 if extendnode is not None:
608 ui.write(_('Not all ancestors of this changeset have been'
608 ui.write(_('Not all ancestors of this changeset have been'
609 ' checked.\nUse bisect --extend to continue the '
609 ' checked.\nUse bisect --extend to continue the '
610 'bisection from\nthe common ancestor, %s.\n')
610 'bisection from\nthe common ancestor, %s.\n')
611 % extendnode)
611 % extendnode)
612 else:
612 else:
613 # multiple possible revisions
613 # multiple possible revisions
614 if good:
614 if good:
615 ui.write(_("Due to skipped revisions, the first "
615 ui.write(_("Due to skipped revisions, the first "
616 "good revision could be any of:\n"))
616 "good revision could be any of:\n"))
617 else:
617 else:
618 ui.write(_("Due to skipped revisions, the first "
618 ui.write(_("Due to skipped revisions, the first "
619 "bad revision could be any of:\n"))
619 "bad revision could be any of:\n"))
620 for n in nodes:
620 for n in nodes:
621 displayer.show(repo[n])
621 displayer.show(repo[n])
622 displayer.close()
622 displayer.close()
623
623
624 def check_state(state, interactive=True):
624 def check_state(state, interactive=True):
625 if not state['good'] or not state['bad']:
625 if not state['good'] or not state['bad']:
626 if (good or bad or skip or reset) and interactive:
626 if (good or bad or skip or reset) and interactive:
627 return
627 return
628 if not state['good']:
628 if not state['good']:
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 raise util.Abort(_('cannot bisect (no known good revisions)'))
630 else:
630 else:
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 raise util.Abort(_('cannot bisect (no known bad revisions)'))
632 return True
632 return True
633
633
634 # backward compatibility
634 # backward compatibility
635 if rev in "good bad reset init".split():
635 if rev in "good bad reset init".split():
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
637 cmd, rev, extra = rev, extra, None
637 cmd, rev, extra = rev, extra, None
638 if cmd == "good":
638 if cmd == "good":
639 good = True
639 good = True
640 elif cmd == "bad":
640 elif cmd == "bad":
641 bad = True
641 bad = True
642 else:
642 else:
643 reset = True
643 reset = True
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
645 raise util.Abort(_('incompatible arguments'))
645 raise util.Abort(_('incompatible arguments'))
646
646
647 if reset:
647 if reset:
648 p = repo.join("bisect.state")
648 p = repo.join("bisect.state")
649 if os.path.exists(p):
649 if os.path.exists(p):
650 os.unlink(p)
650 os.unlink(p)
651 return
651 return
652
652
653 state = hbisect.load_state(repo)
653 state = hbisect.load_state(repo)
654
654
655 if command:
655 if command:
656 changesets = 1
656 changesets = 1
657 try:
657 try:
658 node = state['current'][0]
658 node = state['current'][0]
659 except LookupError:
659 except LookupError:
660 if noupdate:
660 if noupdate:
661 raise util.Abort(_('current bisect revision is unknown - '
661 raise util.Abort(_('current bisect revision is unknown - '
662 'start a new bisect to fix'))
662 'start a new bisect to fix'))
663 node, p2 = repo.dirstate.parents()
663 node, p2 = repo.dirstate.parents()
664 if p2 != nullid:
664 if p2 != nullid:
665 raise util.Abort(_('current bisect revision is a merge'))
665 raise util.Abort(_('current bisect revision is a merge'))
666 try:
666 try:
667 while changesets:
667 while changesets:
668 # update state
668 # update state
669 state['current'] = [node]
669 state['current'] = [node]
670 hbisect.save_state(repo, state)
670 hbisect.save_state(repo, state)
671 status = util.system(command,
671 status = util.system(command,
672 environ={'HG_NODE': hex(node)},
672 environ={'HG_NODE': hex(node)},
673 out=ui.fout)
673 out=ui.fout)
674 if status == 125:
674 if status == 125:
675 transition = "skip"
675 transition = "skip"
676 elif status == 0:
676 elif status == 0:
677 transition = "good"
677 transition = "good"
678 # status < 0 means process was killed
678 # status < 0 means process was killed
679 elif status == 127:
679 elif status == 127:
680 raise util.Abort(_("failed to execute %s") % command)
680 raise util.Abort(_("failed to execute %s") % command)
681 elif status < 0:
681 elif status < 0:
682 raise util.Abort(_("%s killed") % command)
682 raise util.Abort(_("%s killed") % command)
683 else:
683 else:
684 transition = "bad"
684 transition = "bad"
685 ctx = scmutil.revsingle(repo, rev, node)
685 ctx = scmutil.revsingle(repo, rev, node)
686 rev = None # clear for future iterations
686 rev = None # clear for future iterations
687 state[transition].append(ctx.node())
687 state[transition].append(ctx.node())
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
689 check_state(state, interactive=False)
689 check_state(state, interactive=False)
690 # bisect
690 # bisect
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
692 # update to next check
692 # update to next check
693 node = nodes[0]
693 node = nodes[0]
694 if not noupdate:
694 if not noupdate:
695 cmdutil.bailifchanged(repo)
695 cmdutil.bailifchanged(repo)
696 hg.clean(repo, node, show_stats=False)
696 hg.clean(repo, node, show_stats=False)
697 finally:
697 finally:
698 state['current'] = [node]
698 state['current'] = [node]
699 hbisect.save_state(repo, state)
699 hbisect.save_state(repo, state)
700 print_result(nodes, good)
700 print_result(nodes, good)
701 return
701 return
702
702
703 # update state
703 # update state
704
704
705 if rev:
705 if rev:
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
707 else:
707 else:
708 nodes = [repo.lookup('.')]
708 nodes = [repo.lookup('.')]
709
709
710 if good or bad or skip:
710 if good or bad or skip:
711 if good:
711 if good:
712 state['good'] += nodes
712 state['good'] += nodes
713 elif bad:
713 elif bad:
714 state['bad'] += nodes
714 state['bad'] += nodes
715 elif skip:
715 elif skip:
716 state['skip'] += nodes
716 state['skip'] += nodes
717 hbisect.save_state(repo, state)
717 hbisect.save_state(repo, state)
718
718
719 if not check_state(state):
719 if not check_state(state):
720 return
720 return
721
721
722 # actually bisect
722 # actually bisect
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
724 if extend:
724 if extend:
725 if not changesets:
725 if not changesets:
726 extendnode = extendbisectrange(nodes, good)
726 extendnode = extendbisectrange(nodes, good)
727 if extendnode is not None:
727 if extendnode is not None:
728 ui.write(_("Extending search to changeset %d:%s\n"
728 ui.write(_("Extending search to changeset %d:%s\n"
729 % (extendnode.rev(), extendnode)))
729 % (extendnode.rev(), extendnode)))
730 state['current'] = [extendnode.node()]
730 state['current'] = [extendnode.node()]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 if noupdate:
732 if noupdate:
733 return
733 return
734 cmdutil.bailifchanged(repo)
734 cmdutil.bailifchanged(repo)
735 return hg.clean(repo, extendnode.node())
735 return hg.clean(repo, extendnode.node())
736 raise util.Abort(_("nothing to extend"))
736 raise util.Abort(_("nothing to extend"))
737
737
738 if changesets == 0:
738 if changesets == 0:
739 print_result(nodes, good)
739 print_result(nodes, good)
740 else:
740 else:
741 assert len(nodes) == 1 # only a single node can be tested next
741 assert len(nodes) == 1 # only a single node can be tested next
742 node = nodes[0]
742 node = nodes[0]
743 # compute the approximate number of remaining tests
743 # compute the approximate number of remaining tests
744 tests, size = 0, 2
744 tests, size = 0, 2
745 while size <= changesets:
745 while size <= changesets:
746 tests, size = tests + 1, size * 2
746 tests, size = tests + 1, size * 2
747 rev = repo.changelog.rev(node)
747 rev = repo.changelog.rev(node)
748 ui.write(_("Testing changeset %d:%s "
748 ui.write(_("Testing changeset %d:%s "
749 "(%d changesets remaining, ~%d tests)\n")
749 "(%d changesets remaining, ~%d tests)\n")
750 % (rev, short(node), changesets, tests))
750 % (rev, short(node), changesets, tests))
751 state['current'] = [node]
751 state['current'] = [node]
752 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
753 if not noupdate:
753 if not noupdate:
754 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
755 return hg.clean(repo, node)
755 return hg.clean(repo, node)
756
756
757 @command('bookmarks',
757 @command('bookmarks',
758 [('f', 'force', False, _('force')),
758 [('f', 'force', False, _('force')),
759 ('r', 'rev', '', _('revision'), _('REV')),
759 ('r', 'rev', '', _('revision'), _('REV')),
760 ('d', 'delete', False, _('delete a given bookmark')),
760 ('d', 'delete', False, _('delete a given bookmark')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 ('i', 'inactive', False, _('mark a bookmark inactive'))],
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
765 rename=None, inactive=False):
765 rename=None, inactive=False):
766 '''track a line of development with movable markers
766 '''track a line of development with movable markers
767
767
768 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are pointers to certain commits that move when committing.
769 Bookmarks are local. They can be renamed, copied and deleted. It is
769 Bookmarks are local. They can be renamed, copied and deleted. It is
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 possible to use :hg:`merge NAME` to merge from a given bookmark, and
771 :hg:`update NAME` to update to a given bookmark.
771 :hg:`update NAME` to update to a given bookmark.
772
772
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 You can use :hg:`bookmark NAME` to set a bookmark on the working
774 directory's parent revision with the given name. If you specify
774 directory's parent revision with the given name. If you specify
775 a revision using -r REV (where REV may be an existing bookmark),
775 a revision using -r REV (where REV may be an existing bookmark),
776 the bookmark is assigned to that revision.
776 the bookmark is assigned to that revision.
777
777
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 Bookmarks can be pushed and pulled between repositories (see :hg:`help
779 push` and :hg:`help pull`). This requires both the local and remote
779 push` and :hg:`help pull`). This requires both the local and remote
780 repositories to support bookmarks. For versions prior to 1.8, this means
780 repositories to support bookmarks. For versions prior to 1.8, this means
781 the bookmarks extension must be enabled.
781 the bookmarks extension must be enabled.
782
782
783 With -i/--inactive, the new bookmark will not be made the active
783 With -i/--inactive, the new bookmark will not be made the active
784 bookmark. If -r/--rev is given, the new bookmark will not be made
784 bookmark. If -r/--rev is given, the new bookmark will not be made
785 active even if -i/--inactive is not given. If no NAME is given, the
785 active even if -i/--inactive is not given. If no NAME is given, the
786 current active bookmark will be marked inactive.
786 current active bookmark will be marked inactive.
787 '''
787 '''
788 hexfn = ui.debugflag and hex or short
788 hexfn = ui.debugflag and hex or short
789 marks = repo._bookmarks
789 marks = repo._bookmarks
790 cur = repo.changectx('.').node()
790 cur = repo.changectx('.').node()
791
791
792 if delete:
792 if delete:
793 if mark is None:
793 if mark is None:
794 raise util.Abort(_("bookmark name required"))
794 raise util.Abort(_("bookmark name required"))
795 if mark not in marks:
795 if mark not in marks:
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
796 raise util.Abort(_("bookmark '%s' does not exist") % mark)
797 if mark == repo._bookmarkcurrent:
797 if mark == repo._bookmarkcurrent:
798 bookmarks.setcurrent(repo, None)
798 bookmarks.setcurrent(repo, None)
799 del marks[mark]
799 del marks[mark]
800 bookmarks.write(repo)
800 bookmarks.write(repo)
801 return
801 return
802
802
803 if rename:
803 if rename:
804 if rename not in marks:
804 if rename not in marks:
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
805 raise util.Abort(_("bookmark '%s' does not exist") % rename)
806 if mark in marks and not force:
806 if mark in marks and not force:
807 raise util.Abort(_("bookmark '%s' already exists "
807 raise util.Abort(_("bookmark '%s' already exists "
808 "(use -f to force)") % mark)
808 "(use -f to force)") % mark)
809 if mark is None:
809 if mark is None:
810 raise util.Abort(_("new bookmark name required"))
810 raise util.Abort(_("new bookmark name required"))
811 marks[mark] = marks[rename]
811 marks[mark] = marks[rename]
812 if repo._bookmarkcurrent == rename and not inactive:
812 if repo._bookmarkcurrent == rename and not inactive:
813 bookmarks.setcurrent(repo, mark)
813 bookmarks.setcurrent(repo, mark)
814 del marks[rename]
814 del marks[rename]
815 bookmarks.write(repo)
815 bookmarks.write(repo)
816 return
816 return
817
817
818 if mark is not None:
818 if mark is not None:
819 if "\n" in mark:
819 if "\n" in mark:
820 raise util.Abort(_("bookmark name cannot contain newlines"))
820 raise util.Abort(_("bookmark name cannot contain newlines"))
821 mark = mark.strip()
821 mark = mark.strip()
822 if not mark:
822 if not mark:
823 raise util.Abort(_("bookmark names cannot consist entirely of "
823 raise util.Abort(_("bookmark names cannot consist entirely of "
824 "whitespace"))
824 "whitespace"))
825 if inactive and mark == repo._bookmarkcurrent:
825 if inactive and mark == repo._bookmarkcurrent:
826 bookmarks.setcurrent(repo, None)
826 bookmarks.setcurrent(repo, None)
827 return
827 return
828 if mark in marks and not force:
828 if mark in marks and not force:
829 raise util.Abort(_("bookmark '%s' already exists "
829 raise util.Abort(_("bookmark '%s' already exists "
830 "(use -f to force)") % mark)
830 "(use -f to force)") % mark)
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
831 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
832 and not force):
832 and not force):
833 raise util.Abort(
833 raise util.Abort(
834 _("a bookmark cannot have the name of an existing branch"))
834 _("a bookmark cannot have the name of an existing branch"))
835 if rev:
835 if rev:
836 marks[mark] = repo.lookup(rev)
836 marks[mark] = repo.lookup(rev)
837 else:
837 else:
838 marks[mark] = cur
838 marks[mark] = cur
839 if not inactive and cur == marks[mark]:
839 if not inactive and cur == marks[mark]:
840 bookmarks.setcurrent(repo, mark)
840 bookmarks.setcurrent(repo, mark)
841 bookmarks.write(repo)
841 bookmarks.write(repo)
842 return
842 return
843
843
844 if mark is None:
844 if mark is None:
845 if rev:
845 if rev:
846 raise util.Abort(_("bookmark name required"))
846 raise util.Abort(_("bookmark name required"))
847 if len(marks) == 0:
847 if len(marks) == 0:
848 ui.status(_("no bookmarks set\n"))
848 ui.status(_("no bookmarks set\n"))
849 if inactive:
850 if not repo._bookmarkcurrent:
851 ui.status(_("no active bookmark\n"))
852 else:
853 bookmarks.setcurrent(repo, None)
854 return
849 else:
855 else:
850 for bmark, n in sorted(marks.iteritems()):
856 for bmark, n in sorted(marks.iteritems()):
851 current = repo._bookmarkcurrent
857 current = repo._bookmarkcurrent
852 if bmark == current and n == cur:
858 if bmark == current and n == cur:
853 prefix, label = '*', 'bookmarks.current'
859 prefix, label = '*', 'bookmarks.current'
854 else:
860 else:
855 prefix, label = ' ', ''
861 prefix, label = ' ', ''
856
862
857 if ui.quiet:
863 if ui.quiet:
858 ui.write("%s\n" % bmark, label=label)
864 ui.write("%s\n" % bmark, label=label)
859 else:
865 else:
860 ui.write(" %s %-25s %d:%s\n" % (
866 ui.write(" %s %-25s %d:%s\n" % (
861 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
867 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
862 label=label)
868 label=label)
863 return
869 return
864
870
865 @command('branch',
871 @command('branch',
866 [('f', 'force', None,
872 [('f', 'force', None,
867 _('set branch name even if it shadows an existing branch')),
873 _('set branch name even if it shadows an existing branch')),
868 ('C', 'clean', None, _('reset branch name to parent branch name'))],
874 ('C', 'clean', None, _('reset branch name to parent branch name'))],
869 _('[-fC] [NAME]'))
875 _('[-fC] [NAME]'))
870 def branch(ui, repo, label=None, **opts):
876 def branch(ui, repo, label=None, **opts):
871 """set or show the current branch name
877 """set or show the current branch name
872
878
873 .. note::
879 .. note::
874 Branch names are permanent and global. Use :hg:`bookmark` to create a
880 Branch names are permanent and global. Use :hg:`bookmark` to create a
875 light-weight bookmark instead. See :hg:`help glossary` for more
881 light-weight bookmark instead. See :hg:`help glossary` for more
876 information about named branches and bookmarks.
882 information about named branches and bookmarks.
877
883
878 With no argument, show the current branch name. With one argument,
884 With no argument, show the current branch name. With one argument,
879 set the working directory branch name (the branch will not exist
885 set the working directory branch name (the branch will not exist
880 in the repository until the next commit). Standard practice
886 in the repository until the next commit). Standard practice
881 recommends that primary development take place on the 'default'
887 recommends that primary development take place on the 'default'
882 branch.
888 branch.
883
889
884 Unless -f/--force is specified, branch will not let you set a
890 Unless -f/--force is specified, branch will not let you set a
885 branch name that already exists, even if it's inactive.
891 branch name that already exists, even if it's inactive.
886
892
887 Use -C/--clean to reset the working directory branch to that of
893 Use -C/--clean to reset the working directory branch to that of
888 the parent of the working directory, negating a previous branch
894 the parent of the working directory, negating a previous branch
889 change.
895 change.
890
896
891 Use the command :hg:`update` to switch to an existing branch. Use
897 Use the command :hg:`update` to switch to an existing branch. Use
892 :hg:`commit --close-branch` to mark this branch as closed.
898 :hg:`commit --close-branch` to mark this branch as closed.
893
899
894 Returns 0 on success.
900 Returns 0 on success.
895 """
901 """
896 if not opts.get('clean') and not label:
902 if not opts.get('clean') and not label:
897 ui.write("%s\n" % repo.dirstate.branch())
903 ui.write("%s\n" % repo.dirstate.branch())
898 return
904 return
899
905
900 wlock = repo.wlock()
906 wlock = repo.wlock()
901 try:
907 try:
902 if opts.get('clean'):
908 if opts.get('clean'):
903 label = repo[None].p1().branch()
909 label = repo[None].p1().branch()
904 repo.dirstate.setbranch(label)
910 repo.dirstate.setbranch(label)
905 ui.status(_('reset working directory to branch %s\n') % label)
911 ui.status(_('reset working directory to branch %s\n') % label)
906 elif label:
912 elif label:
907 if not opts.get('force') and label in repo.branchmap():
913 if not opts.get('force') and label in repo.branchmap():
908 if label not in [p.branch() for p in repo.parents()]:
914 if label not in [p.branch() for p in repo.parents()]:
909 raise util.Abort(_('a branch of the same name already'
915 raise util.Abort(_('a branch of the same name already'
910 ' exists'),
916 ' exists'),
911 # i18n: "it" refers to an existing branch
917 # i18n: "it" refers to an existing branch
912 hint=_("use 'hg update' to switch to it"))
918 hint=_("use 'hg update' to switch to it"))
913 repo.dirstate.setbranch(label)
919 repo.dirstate.setbranch(label)
914 ui.status(_('marked working directory as branch %s\n') % label)
920 ui.status(_('marked working directory as branch %s\n') % label)
915 ui.status(_('(branches are permanent and global, '
921 ui.status(_('(branches are permanent and global, '
916 'did you want a bookmark?)\n'))
922 'did you want a bookmark?)\n'))
917 finally:
923 finally:
918 wlock.release()
924 wlock.release()
919
925
920 @command('branches',
926 @command('branches',
921 [('a', 'active', False, _('show only branches that have unmerged heads')),
927 [('a', 'active', False, _('show only branches that have unmerged heads')),
922 ('c', 'closed', False, _('show normal and closed branches'))],
928 ('c', 'closed', False, _('show normal and closed branches'))],
923 _('[-ac]'))
929 _('[-ac]'))
924 def branches(ui, repo, active=False, closed=False):
930 def branches(ui, repo, active=False, closed=False):
925 """list repository named branches
931 """list repository named branches
926
932
927 List the repository's named branches, indicating which ones are
933 List the repository's named branches, indicating which ones are
928 inactive. If -c/--closed is specified, also list branches which have
934 inactive. If -c/--closed is specified, also list branches which have
929 been marked closed (see :hg:`commit --close-branch`).
935 been marked closed (see :hg:`commit --close-branch`).
930
936
931 If -a/--active is specified, only show active branches. A branch
937 If -a/--active is specified, only show active branches. A branch
932 is considered active if it contains repository heads.
938 is considered active if it contains repository heads.
933
939
934 Use the command :hg:`update` to switch to an existing branch.
940 Use the command :hg:`update` to switch to an existing branch.
935
941
936 Returns 0.
942 Returns 0.
937 """
943 """
938
944
939 hexfunc = ui.debugflag and hex or short
945 hexfunc = ui.debugflag and hex or short
940
946
941 activebranches = set([repo[n].branch() for n in repo.heads()])
947 activebranches = set([repo[n].branch() for n in repo.heads()])
942 branches = []
948 branches = []
943 for tag, heads in repo.branchmap().iteritems():
949 for tag, heads in repo.branchmap().iteritems():
944 for h in reversed(heads):
950 for h in reversed(heads):
945 ctx = repo[h]
951 ctx = repo[h]
946 isopen = not ctx.closesbranch()
952 isopen = not ctx.closesbranch()
947 if isopen:
953 if isopen:
948 tip = ctx
954 tip = ctx
949 break
955 break
950 else:
956 else:
951 tip = repo[heads[-1]]
957 tip = repo[heads[-1]]
952 isactive = tag in activebranches and isopen
958 isactive = tag in activebranches and isopen
953 branches.append((tip, isactive, isopen))
959 branches.append((tip, isactive, isopen))
954 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
960 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
955 reverse=True)
961 reverse=True)
956
962
957 for ctx, isactive, isopen in branches:
963 for ctx, isactive, isopen in branches:
958 if (not active) or isactive:
964 if (not active) or isactive:
959 if isactive:
965 if isactive:
960 label = 'branches.active'
966 label = 'branches.active'
961 notice = ''
967 notice = ''
962 elif not isopen:
968 elif not isopen:
963 if not closed:
969 if not closed:
964 continue
970 continue
965 label = 'branches.closed'
971 label = 'branches.closed'
966 notice = _(' (closed)')
972 notice = _(' (closed)')
967 else:
973 else:
968 label = 'branches.inactive'
974 label = 'branches.inactive'
969 notice = _(' (inactive)')
975 notice = _(' (inactive)')
970 if ctx.branch() == repo.dirstate.branch():
976 if ctx.branch() == repo.dirstate.branch():
971 label = 'branches.current'
977 label = 'branches.current'
972 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
978 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
973 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
979 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
974 'log.changeset')
980 'log.changeset')
975 tag = ui.label(ctx.branch(), label)
981 tag = ui.label(ctx.branch(), label)
976 if ui.quiet:
982 if ui.quiet:
977 ui.write("%s\n" % tag)
983 ui.write("%s\n" % tag)
978 else:
984 else:
979 ui.write("%s %s%s\n" % (tag, rev, notice))
985 ui.write("%s %s%s\n" % (tag, rev, notice))
980
986
981 @command('bundle',
987 @command('bundle',
982 [('f', 'force', None, _('run even when the destination is unrelated')),
988 [('f', 'force', None, _('run even when the destination is unrelated')),
983 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
989 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
984 _('REV')),
990 _('REV')),
985 ('b', 'branch', [], _('a specific branch you would like to bundle'),
991 ('b', 'branch', [], _('a specific branch you would like to bundle'),
986 _('BRANCH')),
992 _('BRANCH')),
987 ('', 'base', [],
993 ('', 'base', [],
988 _('a base changeset assumed to be available at the destination'),
994 _('a base changeset assumed to be available at the destination'),
989 _('REV')),
995 _('REV')),
990 ('a', 'all', None, _('bundle all changesets in the repository')),
996 ('a', 'all', None, _('bundle all changesets in the repository')),
991 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
997 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
992 ] + remoteopts,
998 ] + remoteopts,
993 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
999 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
994 def bundle(ui, repo, fname, dest=None, **opts):
1000 def bundle(ui, repo, fname, dest=None, **opts):
995 """create a changegroup file
1001 """create a changegroup file
996
1002
997 Generate a compressed changegroup file collecting changesets not
1003 Generate a compressed changegroup file collecting changesets not
998 known to be in another repository.
1004 known to be in another repository.
999
1005
1000 If you omit the destination repository, then hg assumes the
1006 If you omit the destination repository, then hg assumes the
1001 destination will have all the nodes you specify with --base
1007 destination will have all the nodes you specify with --base
1002 parameters. To create a bundle containing all changesets, use
1008 parameters. To create a bundle containing all changesets, use
1003 -a/--all (or --base null).
1009 -a/--all (or --base null).
1004
1010
1005 You can change compression method with the -t/--type option.
1011 You can change compression method with the -t/--type option.
1006 The available compression methods are: none, bzip2, and
1012 The available compression methods are: none, bzip2, and
1007 gzip (by default, bundles are compressed using bzip2).
1013 gzip (by default, bundles are compressed using bzip2).
1008
1014
1009 The bundle file can then be transferred using conventional means
1015 The bundle file can then be transferred using conventional means
1010 and applied to another repository with the unbundle or pull
1016 and applied to another repository with the unbundle or pull
1011 command. This is useful when direct push and pull are not
1017 command. This is useful when direct push and pull are not
1012 available or when exporting an entire repository is undesirable.
1018 available or when exporting an entire repository is undesirable.
1013
1019
1014 Applying bundles preserves all changeset contents including
1020 Applying bundles preserves all changeset contents including
1015 permissions, copy/rename information, and revision history.
1021 permissions, copy/rename information, and revision history.
1016
1022
1017 Returns 0 on success, 1 if no changes found.
1023 Returns 0 on success, 1 if no changes found.
1018 """
1024 """
1019 revs = None
1025 revs = None
1020 if 'rev' in opts:
1026 if 'rev' in opts:
1021 revs = scmutil.revrange(repo, opts['rev'])
1027 revs = scmutil.revrange(repo, opts['rev'])
1022
1028
1023 bundletype = opts.get('type', 'bzip2').lower()
1029 bundletype = opts.get('type', 'bzip2').lower()
1024 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1030 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1025 bundletype = btypes.get(bundletype)
1031 bundletype = btypes.get(bundletype)
1026 if bundletype not in changegroup.bundletypes:
1032 if bundletype not in changegroup.bundletypes:
1027 raise util.Abort(_('unknown bundle type specified with --type'))
1033 raise util.Abort(_('unknown bundle type specified with --type'))
1028
1034
1029 if opts.get('all'):
1035 if opts.get('all'):
1030 base = ['null']
1036 base = ['null']
1031 else:
1037 else:
1032 base = scmutil.revrange(repo, opts.get('base'))
1038 base = scmutil.revrange(repo, opts.get('base'))
1033 if base:
1039 if base:
1034 if dest:
1040 if dest:
1035 raise util.Abort(_("--base is incompatible with specifying "
1041 raise util.Abort(_("--base is incompatible with specifying "
1036 "a destination"))
1042 "a destination"))
1037 common = [repo.lookup(rev) for rev in base]
1043 common = [repo.lookup(rev) for rev in base]
1038 heads = revs and map(repo.lookup, revs) or revs
1044 heads = revs and map(repo.lookup, revs) or revs
1039 cg = repo.getbundle('bundle', heads=heads, common=common)
1045 cg = repo.getbundle('bundle', heads=heads, common=common)
1040 outgoing = None
1046 outgoing = None
1041 else:
1047 else:
1042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1048 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1043 dest, branches = hg.parseurl(dest, opts.get('branch'))
1049 dest, branches = hg.parseurl(dest, opts.get('branch'))
1044 other = hg.peer(repo, opts, dest)
1050 other = hg.peer(repo, opts, dest)
1045 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1051 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1046 heads = revs and map(repo.lookup, revs) or revs
1052 heads = revs and map(repo.lookup, revs) or revs
1047 outgoing = discovery.findcommonoutgoing(repo, other,
1053 outgoing = discovery.findcommonoutgoing(repo, other,
1048 onlyheads=heads,
1054 onlyheads=heads,
1049 force=opts.get('force'),
1055 force=opts.get('force'),
1050 portable=True)
1056 portable=True)
1051 cg = repo.getlocalbundle('bundle', outgoing)
1057 cg = repo.getlocalbundle('bundle', outgoing)
1052 if not cg:
1058 if not cg:
1053 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1059 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1054 return 1
1060 return 1
1055
1061
1056 changegroup.writebundle(cg, fname, bundletype)
1062 changegroup.writebundle(cg, fname, bundletype)
1057
1063
1058 @command('cat',
1064 @command('cat',
1059 [('o', 'output', '',
1065 [('o', 'output', '',
1060 _('print output to file with formatted name'), _('FORMAT')),
1066 _('print output to file with formatted name'), _('FORMAT')),
1061 ('r', 'rev', '', _('print the given revision'), _('REV')),
1067 ('r', 'rev', '', _('print the given revision'), _('REV')),
1062 ('', 'decode', None, _('apply any matching decode filter')),
1068 ('', 'decode', None, _('apply any matching decode filter')),
1063 ] + walkopts,
1069 ] + walkopts,
1064 _('[OPTION]... FILE...'))
1070 _('[OPTION]... FILE...'))
1065 def cat(ui, repo, file1, *pats, **opts):
1071 def cat(ui, repo, file1, *pats, **opts):
1066 """output the current or given revision of files
1072 """output the current or given revision of files
1067
1073
1068 Print the specified files as they were at the given revision. If
1074 Print the specified files as they were at the given revision. If
1069 no revision is given, the parent of the working directory is used,
1075 no revision is given, the parent of the working directory is used,
1070 or tip if no revision is checked out.
1076 or tip if no revision is checked out.
1071
1077
1072 Output may be to a file, in which case the name of the file is
1078 Output may be to a file, in which case the name of the file is
1073 given using a format string. The formatting rules are the same as
1079 given using a format string. The formatting rules are the same as
1074 for the export command, with the following additions:
1080 for the export command, with the following additions:
1075
1081
1076 :``%s``: basename of file being printed
1082 :``%s``: basename of file being printed
1077 :``%d``: dirname of file being printed, or '.' if in repository root
1083 :``%d``: dirname of file being printed, or '.' if in repository root
1078 :``%p``: root-relative path name of file being printed
1084 :``%p``: root-relative path name of file being printed
1079
1085
1080 Returns 0 on success.
1086 Returns 0 on success.
1081 """
1087 """
1082 ctx = scmutil.revsingle(repo, opts.get('rev'))
1088 ctx = scmutil.revsingle(repo, opts.get('rev'))
1083 err = 1
1089 err = 1
1084 m = scmutil.match(ctx, (file1,) + pats, opts)
1090 m = scmutil.match(ctx, (file1,) + pats, opts)
1085 for abs in ctx.walk(m):
1091 for abs in ctx.walk(m):
1086 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1092 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1087 pathname=abs)
1093 pathname=abs)
1088 data = ctx[abs].data()
1094 data = ctx[abs].data()
1089 if opts.get('decode'):
1095 if opts.get('decode'):
1090 data = repo.wwritedata(abs, data)
1096 data = repo.wwritedata(abs, data)
1091 fp.write(data)
1097 fp.write(data)
1092 fp.close()
1098 fp.close()
1093 err = 0
1099 err = 0
1094 return err
1100 return err
1095
1101
1096 @command('^clone',
1102 @command('^clone',
1097 [('U', 'noupdate', None,
1103 [('U', 'noupdate', None,
1098 _('the clone will include an empty working copy (only a repository)')),
1104 _('the clone will include an empty working copy (only a repository)')),
1099 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1105 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1100 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1106 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1101 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1107 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1102 ('', 'pull', None, _('use pull protocol to copy metadata')),
1108 ('', 'pull', None, _('use pull protocol to copy metadata')),
1103 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1109 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1104 ] + remoteopts,
1110 ] + remoteopts,
1105 _('[OPTION]... SOURCE [DEST]'))
1111 _('[OPTION]... SOURCE [DEST]'))
1106 def clone(ui, source, dest=None, **opts):
1112 def clone(ui, source, dest=None, **opts):
1107 """make a copy of an existing repository
1113 """make a copy of an existing repository
1108
1114
1109 Create a copy of an existing repository in a new directory.
1115 Create a copy of an existing repository in a new directory.
1110
1116
1111 If no destination directory name is specified, it defaults to the
1117 If no destination directory name is specified, it defaults to the
1112 basename of the source.
1118 basename of the source.
1113
1119
1114 The location of the source is added to the new repository's
1120 The location of the source is added to the new repository's
1115 ``.hg/hgrc`` file, as the default to be used for future pulls.
1121 ``.hg/hgrc`` file, as the default to be used for future pulls.
1116
1122
1117 Only local paths and ``ssh://`` URLs are supported as
1123 Only local paths and ``ssh://`` URLs are supported as
1118 destinations. For ``ssh://`` destinations, no working directory or
1124 destinations. For ``ssh://`` destinations, no working directory or
1119 ``.hg/hgrc`` will be created on the remote side.
1125 ``.hg/hgrc`` will be created on the remote side.
1120
1126
1121 To pull only a subset of changesets, specify one or more revisions
1127 To pull only a subset of changesets, specify one or more revisions
1122 identifiers with -r/--rev or branches with -b/--branch. The
1128 identifiers with -r/--rev or branches with -b/--branch. The
1123 resulting clone will contain only the specified changesets and
1129 resulting clone will contain only the specified changesets and
1124 their ancestors. These options (or 'clone src#rev dest') imply
1130 their ancestors. These options (or 'clone src#rev dest') imply
1125 --pull, even for local source repositories. Note that specifying a
1131 --pull, even for local source repositories. Note that specifying a
1126 tag will include the tagged changeset but not the changeset
1132 tag will include the tagged changeset but not the changeset
1127 containing the tag.
1133 containing the tag.
1128
1134
1129 To check out a particular version, use -u/--update, or
1135 To check out a particular version, use -u/--update, or
1130 -U/--noupdate to create a clone with no working directory.
1136 -U/--noupdate to create a clone with no working directory.
1131
1137
1132 .. container:: verbose
1138 .. container:: verbose
1133
1139
1134 For efficiency, hardlinks are used for cloning whenever the
1140 For efficiency, hardlinks are used for cloning whenever the
1135 source and destination are on the same filesystem (note this
1141 source and destination are on the same filesystem (note this
1136 applies only to the repository data, not to the working
1142 applies only to the repository data, not to the working
1137 directory). Some filesystems, such as AFS, implement hardlinking
1143 directory). Some filesystems, such as AFS, implement hardlinking
1138 incorrectly, but do not report errors. In these cases, use the
1144 incorrectly, but do not report errors. In these cases, use the
1139 --pull option to avoid hardlinking.
1145 --pull option to avoid hardlinking.
1140
1146
1141 In some cases, you can clone repositories and the working
1147 In some cases, you can clone repositories and the working
1142 directory using full hardlinks with ::
1148 directory using full hardlinks with ::
1143
1149
1144 $ cp -al REPO REPOCLONE
1150 $ cp -al REPO REPOCLONE
1145
1151
1146 This is the fastest way to clone, but it is not always safe. The
1152 This is the fastest way to clone, but it is not always safe. The
1147 operation is not atomic (making sure REPO is not modified during
1153 operation is not atomic (making sure REPO is not modified during
1148 the operation is up to you) and you have to make sure your
1154 the operation is up to you) and you have to make sure your
1149 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1155 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1150 so). Also, this is not compatible with certain extensions that
1156 so). Also, this is not compatible with certain extensions that
1151 place their metadata under the .hg directory, such as mq.
1157 place their metadata under the .hg directory, such as mq.
1152
1158
1153 Mercurial will update the working directory to the first applicable
1159 Mercurial will update the working directory to the first applicable
1154 revision from this list:
1160 revision from this list:
1155
1161
1156 a) null if -U or the source repository has no changesets
1162 a) null if -U or the source repository has no changesets
1157 b) if -u . and the source repository is local, the first parent of
1163 b) if -u . and the source repository is local, the first parent of
1158 the source repository's working directory
1164 the source repository's working directory
1159 c) the changeset specified with -u (if a branch name, this means the
1165 c) the changeset specified with -u (if a branch name, this means the
1160 latest head of that branch)
1166 latest head of that branch)
1161 d) the changeset specified with -r
1167 d) the changeset specified with -r
1162 e) the tipmost head specified with -b
1168 e) the tipmost head specified with -b
1163 f) the tipmost head specified with the url#branch source syntax
1169 f) the tipmost head specified with the url#branch source syntax
1164 g) the tipmost head of the default branch
1170 g) the tipmost head of the default branch
1165 h) tip
1171 h) tip
1166
1172
1167 Examples:
1173 Examples:
1168
1174
1169 - clone a remote repository to a new directory named hg/::
1175 - clone a remote repository to a new directory named hg/::
1170
1176
1171 hg clone http://selenic.com/hg
1177 hg clone http://selenic.com/hg
1172
1178
1173 - create a lightweight local clone::
1179 - create a lightweight local clone::
1174
1180
1175 hg clone project/ project-feature/
1181 hg clone project/ project-feature/
1176
1182
1177 - clone from an absolute path on an ssh server (note double-slash)::
1183 - clone from an absolute path on an ssh server (note double-slash)::
1178
1184
1179 hg clone ssh://user@server//home/projects/alpha/
1185 hg clone ssh://user@server//home/projects/alpha/
1180
1186
1181 - do a high-speed clone over a LAN while checking out a
1187 - do a high-speed clone over a LAN while checking out a
1182 specified version::
1188 specified version::
1183
1189
1184 hg clone --uncompressed http://server/repo -u 1.5
1190 hg clone --uncompressed http://server/repo -u 1.5
1185
1191
1186 - create a repository without changesets after a particular revision::
1192 - create a repository without changesets after a particular revision::
1187
1193
1188 hg clone -r 04e544 experimental/ good/
1194 hg clone -r 04e544 experimental/ good/
1189
1195
1190 - clone (and track) a particular named branch::
1196 - clone (and track) a particular named branch::
1191
1197
1192 hg clone http://selenic.com/hg#stable
1198 hg clone http://selenic.com/hg#stable
1193
1199
1194 See :hg:`help urls` for details on specifying URLs.
1200 See :hg:`help urls` for details on specifying URLs.
1195
1201
1196 Returns 0 on success.
1202 Returns 0 on success.
1197 """
1203 """
1198 if opts.get('noupdate') and opts.get('updaterev'):
1204 if opts.get('noupdate') and opts.get('updaterev'):
1199 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1205 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1200
1206
1201 r = hg.clone(ui, opts, source, dest,
1207 r = hg.clone(ui, opts, source, dest,
1202 pull=opts.get('pull'),
1208 pull=opts.get('pull'),
1203 stream=opts.get('uncompressed'),
1209 stream=opts.get('uncompressed'),
1204 rev=opts.get('rev'),
1210 rev=opts.get('rev'),
1205 update=opts.get('updaterev') or not opts.get('noupdate'),
1211 update=opts.get('updaterev') or not opts.get('noupdate'),
1206 branch=opts.get('branch'))
1212 branch=opts.get('branch'))
1207
1213
1208 return r is None
1214 return r is None
1209
1215
1210 @command('^commit|ci',
1216 @command('^commit|ci',
1211 [('A', 'addremove', None,
1217 [('A', 'addremove', None,
1212 _('mark new/missing files as added/removed before committing')),
1218 _('mark new/missing files as added/removed before committing')),
1213 ('', 'close-branch', None,
1219 ('', 'close-branch', None,
1214 _('mark a branch as closed, hiding it from the branch list')),
1220 _('mark a branch as closed, hiding it from the branch list')),
1215 ('', 'amend', None, _('amend the parent of the working dir')),
1221 ('', 'amend', None, _('amend the parent of the working dir')),
1216 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1222 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1217 _('[OPTION]... [FILE]...'))
1223 _('[OPTION]... [FILE]...'))
1218 def commit(ui, repo, *pats, **opts):
1224 def commit(ui, repo, *pats, **opts):
1219 """commit the specified files or all outstanding changes
1225 """commit the specified files or all outstanding changes
1220
1226
1221 Commit changes to the given files into the repository. Unlike a
1227 Commit changes to the given files into the repository. Unlike a
1222 centralized SCM, this operation is a local operation. See
1228 centralized SCM, this operation is a local operation. See
1223 :hg:`push` for a way to actively distribute your changes.
1229 :hg:`push` for a way to actively distribute your changes.
1224
1230
1225 If a list of files is omitted, all changes reported by :hg:`status`
1231 If a list of files is omitted, all changes reported by :hg:`status`
1226 will be committed.
1232 will be committed.
1227
1233
1228 If you are committing the result of a merge, do not provide any
1234 If you are committing the result of a merge, do not provide any
1229 filenames or -I/-X filters.
1235 filenames or -I/-X filters.
1230
1236
1231 If no commit message is specified, Mercurial starts your
1237 If no commit message is specified, Mercurial starts your
1232 configured editor where you can enter a message. In case your
1238 configured editor where you can enter a message. In case your
1233 commit fails, you will find a backup of your message in
1239 commit fails, you will find a backup of your message in
1234 ``.hg/last-message.txt``.
1240 ``.hg/last-message.txt``.
1235
1241
1236 The --amend flag can be used to amend the parent of the
1242 The --amend flag can be used to amend the parent of the
1237 working directory with a new commit that contains the changes
1243 working directory with a new commit that contains the changes
1238 in the parent in addition to those currently reported by :hg:`status`,
1244 in the parent in addition to those currently reported by :hg:`status`,
1239 if there are any. The old commit is stored in a backup bundle in
1245 if there are any. The old commit is stored in a backup bundle in
1240 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1246 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1241 on how to restore it).
1247 on how to restore it).
1242
1248
1243 Message, user and date are taken from the amended commit unless
1249 Message, user and date are taken from the amended commit unless
1244 specified. When a message isn't specified on the command line,
1250 specified. When a message isn't specified on the command line,
1245 the editor will open with the message of the amended commit.
1251 the editor will open with the message of the amended commit.
1246
1252
1247 It is not possible to amend public changesets (see :hg:`help phases`)
1253 It is not possible to amend public changesets (see :hg:`help phases`)
1248 or changesets that have children.
1254 or changesets that have children.
1249
1255
1250 See :hg:`help dates` for a list of formats valid for -d/--date.
1256 See :hg:`help dates` for a list of formats valid for -d/--date.
1251
1257
1252 Returns 0 on success, 1 if nothing changed.
1258 Returns 0 on success, 1 if nothing changed.
1253 """
1259 """
1254 if opts.get('subrepos'):
1260 if opts.get('subrepos'):
1255 # Let --subrepos on the command line overide config setting.
1261 # Let --subrepos on the command line overide config setting.
1256 ui.setconfig('ui', 'commitsubrepos', True)
1262 ui.setconfig('ui', 'commitsubrepos', True)
1257
1263
1258 extra = {}
1264 extra = {}
1259 if opts.get('close_branch'):
1265 if opts.get('close_branch'):
1260 if repo['.'].node() not in repo.branchheads():
1266 if repo['.'].node() not in repo.branchheads():
1261 # The topo heads set is included in the branch heads set of the
1267 # The topo heads set is included in the branch heads set of the
1262 # current branch, so it's sufficient to test branchheads
1268 # current branch, so it's sufficient to test branchheads
1263 raise util.Abort(_('can only close branch heads'))
1269 raise util.Abort(_('can only close branch heads'))
1264 extra['close'] = 1
1270 extra['close'] = 1
1265
1271
1266 branch = repo[None].branch()
1272 branch = repo[None].branch()
1267 bheads = repo.branchheads(branch)
1273 bheads = repo.branchheads(branch)
1268
1274
1269 if opts.get('amend'):
1275 if opts.get('amend'):
1270 if ui.configbool('ui', 'commitsubrepos'):
1276 if ui.configbool('ui', 'commitsubrepos'):
1271 raise util.Abort(_('cannot amend recursively'))
1277 raise util.Abort(_('cannot amend recursively'))
1272
1278
1273 old = repo['.']
1279 old = repo['.']
1274 if old.phase() == phases.public:
1280 if old.phase() == phases.public:
1275 raise util.Abort(_('cannot amend public changesets'))
1281 raise util.Abort(_('cannot amend public changesets'))
1276 if len(old.parents()) > 1:
1282 if len(old.parents()) > 1:
1277 raise util.Abort(_('cannot amend merge changesets'))
1283 raise util.Abort(_('cannot amend merge changesets'))
1278 if len(repo[None].parents()) > 1:
1284 if len(repo[None].parents()) > 1:
1279 raise util.Abort(_('cannot amend while merging'))
1285 raise util.Abort(_('cannot amend while merging'))
1280 if old.children():
1286 if old.children():
1281 raise util.Abort(_('cannot amend changeset with children'))
1287 raise util.Abort(_('cannot amend changeset with children'))
1282
1288
1283 e = cmdutil.commiteditor
1289 e = cmdutil.commiteditor
1284 if opts.get('force_editor'):
1290 if opts.get('force_editor'):
1285 e = cmdutil.commitforceeditor
1291 e = cmdutil.commitforceeditor
1286
1292
1287 def commitfunc(ui, repo, message, match, opts):
1293 def commitfunc(ui, repo, message, match, opts):
1288 editor = e
1294 editor = e
1289 # message contains text from -m or -l, if it's empty,
1295 # message contains text from -m or -l, if it's empty,
1290 # open the editor with the old message
1296 # open the editor with the old message
1291 if not message:
1297 if not message:
1292 message = old.description()
1298 message = old.description()
1293 editor = cmdutil.commitforceeditor
1299 editor = cmdutil.commitforceeditor
1294 return repo.commit(message,
1300 return repo.commit(message,
1295 opts.get('user') or old.user(),
1301 opts.get('user') or old.user(),
1296 opts.get('date') or old.date(),
1302 opts.get('date') or old.date(),
1297 match,
1303 match,
1298 editor=editor,
1304 editor=editor,
1299 extra=extra)
1305 extra=extra)
1300
1306
1301 current = repo._bookmarkcurrent
1307 current = repo._bookmarkcurrent
1302 marks = old.bookmarks()
1308 marks = old.bookmarks()
1303 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1309 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1304 if node == old.node():
1310 if node == old.node():
1305 ui.status(_("nothing changed\n"))
1311 ui.status(_("nothing changed\n"))
1306 return 1
1312 return 1
1307 elif marks:
1313 elif marks:
1308 ui.debug('moving bookmarks %r from %s to %s\n' %
1314 ui.debug('moving bookmarks %r from %s to %s\n' %
1309 (marks, old.hex(), hex(node)))
1315 (marks, old.hex(), hex(node)))
1310 for bm in marks:
1316 for bm in marks:
1311 repo._bookmarks[bm] = node
1317 repo._bookmarks[bm] = node
1312 if bm == current:
1318 if bm == current:
1313 bookmarks.setcurrent(repo, bm)
1319 bookmarks.setcurrent(repo, bm)
1314 bookmarks.write(repo)
1320 bookmarks.write(repo)
1315 else:
1321 else:
1316 e = cmdutil.commiteditor
1322 e = cmdutil.commiteditor
1317 if opts.get('force_editor'):
1323 if opts.get('force_editor'):
1318 e = cmdutil.commitforceeditor
1324 e = cmdutil.commitforceeditor
1319
1325
1320 def commitfunc(ui, repo, message, match, opts):
1326 def commitfunc(ui, repo, message, match, opts):
1321 return repo.commit(message, opts.get('user'), opts.get('date'),
1327 return repo.commit(message, opts.get('user'), opts.get('date'),
1322 match, editor=e, extra=extra)
1328 match, editor=e, extra=extra)
1323
1329
1324 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1330 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1325
1331
1326 if not node:
1332 if not node:
1327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1333 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1328 if stat[3]:
1334 if stat[3]:
1329 ui.status(_("nothing changed (%d missing files, see "
1335 ui.status(_("nothing changed (%d missing files, see "
1330 "'hg status')\n") % len(stat[3]))
1336 "'hg status')\n") % len(stat[3]))
1331 else:
1337 else:
1332 ui.status(_("nothing changed\n"))
1338 ui.status(_("nothing changed\n"))
1333 return 1
1339 return 1
1334
1340
1335 ctx = repo[node]
1341 ctx = repo[node]
1336 parents = ctx.parents()
1342 parents = ctx.parents()
1337
1343
1338 if (not opts.get('amend') and bheads and node not in bheads and not
1344 if (not opts.get('amend') and bheads and node not in bheads and not
1339 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1345 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1340 ui.status(_('created new head\n'))
1346 ui.status(_('created new head\n'))
1341 # The message is not printed for initial roots. For the other
1347 # The message is not printed for initial roots. For the other
1342 # changesets, it is printed in the following situations:
1348 # changesets, it is printed in the following situations:
1343 #
1349 #
1344 # Par column: for the 2 parents with ...
1350 # Par column: for the 2 parents with ...
1345 # N: null or no parent
1351 # N: null or no parent
1346 # B: parent is on another named branch
1352 # B: parent is on another named branch
1347 # C: parent is a regular non head changeset
1353 # C: parent is a regular non head changeset
1348 # H: parent was a branch head of the current branch
1354 # H: parent was a branch head of the current branch
1349 # Msg column: whether we print "created new head" message
1355 # Msg column: whether we print "created new head" message
1350 # In the following, it is assumed that there already exists some
1356 # In the following, it is assumed that there already exists some
1351 # initial branch heads of the current branch, otherwise nothing is
1357 # initial branch heads of the current branch, otherwise nothing is
1352 # printed anyway.
1358 # printed anyway.
1353 #
1359 #
1354 # Par Msg Comment
1360 # Par Msg Comment
1355 # NN y additional topo root
1361 # NN y additional topo root
1356 #
1362 #
1357 # BN y additional branch root
1363 # BN y additional branch root
1358 # CN y additional topo head
1364 # CN y additional topo head
1359 # HN n usual case
1365 # HN n usual case
1360 #
1366 #
1361 # BB y weird additional branch root
1367 # BB y weird additional branch root
1362 # CB y branch merge
1368 # CB y branch merge
1363 # HB n merge with named branch
1369 # HB n merge with named branch
1364 #
1370 #
1365 # CC y additional head from merge
1371 # CC y additional head from merge
1366 # CH n merge with a head
1372 # CH n merge with a head
1367 #
1373 #
1368 # HH n head merge: head count decreases
1374 # HH n head merge: head count decreases
1369
1375
1370 if not opts.get('close_branch'):
1376 if not opts.get('close_branch'):
1371 for r in parents:
1377 for r in parents:
1372 if r.closesbranch() and r.branch() == branch:
1378 if r.closesbranch() and r.branch() == branch:
1373 ui.status(_('reopening closed branch head %d\n') % r)
1379 ui.status(_('reopening closed branch head %d\n') % r)
1374
1380
1375 if ui.debugflag:
1381 if ui.debugflag:
1376 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1382 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1377 elif ui.verbose:
1383 elif ui.verbose:
1378 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1384 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1379
1385
1380 @command('copy|cp',
1386 @command('copy|cp',
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1387 [('A', 'after', None, _('record a copy that has already occurred')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1388 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1383 ] + walkopts + dryrunopts,
1389 ] + walkopts + dryrunopts,
1384 _('[OPTION]... [SOURCE]... DEST'))
1390 _('[OPTION]... [SOURCE]... DEST'))
1385 def copy(ui, repo, *pats, **opts):
1391 def copy(ui, repo, *pats, **opts):
1386 """mark files as copied for the next commit
1392 """mark files as copied for the next commit
1387
1393
1388 Mark dest as having copies of source files. If dest is a
1394 Mark dest as having copies of source files. If dest is a
1389 directory, copies are put in that directory. If dest is a file,
1395 directory, copies are put in that directory. If dest is a file,
1390 the source must be a single file.
1396 the source must be a single file.
1391
1397
1392 By default, this command copies the contents of files as they
1398 By default, this command copies the contents of files as they
1393 exist in the working directory. If invoked with -A/--after, the
1399 exist in the working directory. If invoked with -A/--after, the
1394 operation is recorded, but no copying is performed.
1400 operation is recorded, but no copying is performed.
1395
1401
1396 This command takes effect with the next commit. To undo a copy
1402 This command takes effect with the next commit. To undo a copy
1397 before that, see :hg:`revert`.
1403 before that, see :hg:`revert`.
1398
1404
1399 Returns 0 on success, 1 if errors are encountered.
1405 Returns 0 on success, 1 if errors are encountered.
1400 """
1406 """
1401 wlock = repo.wlock(False)
1407 wlock = repo.wlock(False)
1402 try:
1408 try:
1403 return cmdutil.copy(ui, repo, pats, opts)
1409 return cmdutil.copy(ui, repo, pats, opts)
1404 finally:
1410 finally:
1405 wlock.release()
1411 wlock.release()
1406
1412
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1413 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1408 def debugancestor(ui, repo, *args):
1414 def debugancestor(ui, repo, *args):
1409 """find the ancestor revision of two revisions in a given index"""
1415 """find the ancestor revision of two revisions in a given index"""
1410 if len(args) == 3:
1416 if len(args) == 3:
1411 index, rev1, rev2 = args
1417 index, rev1, rev2 = args
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1418 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1413 lookup = r.lookup
1419 lookup = r.lookup
1414 elif len(args) == 2:
1420 elif len(args) == 2:
1415 if not repo:
1421 if not repo:
1416 raise util.Abort(_("there is no Mercurial repository here "
1422 raise util.Abort(_("there is no Mercurial repository here "
1417 "(.hg not found)"))
1423 "(.hg not found)"))
1418 rev1, rev2 = args
1424 rev1, rev2 = args
1419 r = repo.changelog
1425 r = repo.changelog
1420 lookup = repo.lookup
1426 lookup = repo.lookup
1421 else:
1427 else:
1422 raise util.Abort(_('either two or three arguments required'))
1428 raise util.Abort(_('either two or three arguments required'))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1429 a = r.ancestor(lookup(rev1), lookup(rev2))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1430 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1425
1431
1426 @command('debugbuilddag',
1432 @command('debugbuilddag',
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1433 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1434 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1435 ('n', 'new-file', None, _('add new file at each rev'))],
1430 _('[OPTION]... [TEXT]'))
1436 _('[OPTION]... [TEXT]'))
1431 def debugbuilddag(ui, repo, text=None,
1437 def debugbuilddag(ui, repo, text=None,
1432 mergeable_file=False,
1438 mergeable_file=False,
1433 overwritten_file=False,
1439 overwritten_file=False,
1434 new_file=False):
1440 new_file=False):
1435 """builds a repo with a given DAG from scratch in the current empty repo
1441 """builds a repo with a given DAG from scratch in the current empty repo
1436
1442
1437 The description of the DAG is read from stdin if not given on the
1443 The description of the DAG is read from stdin if not given on the
1438 command line.
1444 command line.
1439
1445
1440 Elements:
1446 Elements:
1441
1447
1442 - "+n" is a linear run of n nodes based on the current default parent
1448 - "+n" is a linear run of n nodes based on the current default parent
1443 - "." is a single node based on the current default parent
1449 - "." is a single node based on the current default parent
1444 - "$" resets the default parent to null (implied at the start);
1450 - "$" resets the default parent to null (implied at the start);
1445 otherwise the default parent is always the last node created
1451 otherwise the default parent is always the last node created
1446 - "<p" sets the default parent to the backref p
1452 - "<p" sets the default parent to the backref p
1447 - "*p" is a fork at parent p, which is a backref
1453 - "*p" is a fork at parent p, which is a backref
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1454 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1449 - "/p2" is a merge of the preceding node and p2
1455 - "/p2" is a merge of the preceding node and p2
1450 - ":tag" defines a local tag for the preceding node
1456 - ":tag" defines a local tag for the preceding node
1451 - "@branch" sets the named branch for subsequent nodes
1457 - "@branch" sets the named branch for subsequent nodes
1452 - "#...\\n" is a comment up to the end of the line
1458 - "#...\\n" is a comment up to the end of the line
1453
1459
1454 Whitespace between the above elements is ignored.
1460 Whitespace between the above elements is ignored.
1455
1461
1456 A backref is either
1462 A backref is either
1457
1463
1458 - a number n, which references the node curr-n, where curr is the current
1464 - a number n, which references the node curr-n, where curr is the current
1459 node, or
1465 node, or
1460 - the name of a local tag you placed earlier using ":tag", or
1466 - the name of a local tag you placed earlier using ":tag", or
1461 - empty to denote the default parent.
1467 - empty to denote the default parent.
1462
1468
1463 All string valued-elements are either strictly alphanumeric, or must
1469 All string valued-elements are either strictly alphanumeric, or must
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1470 be enclosed in double quotes ("..."), with "\\" as escape character.
1465 """
1471 """
1466
1472
1467 if text is None:
1473 if text is None:
1468 ui.status(_("reading DAG from stdin\n"))
1474 ui.status(_("reading DAG from stdin\n"))
1469 text = ui.fin.read()
1475 text = ui.fin.read()
1470
1476
1471 cl = repo.changelog
1477 cl = repo.changelog
1472 if len(cl) > 0:
1478 if len(cl) > 0:
1473 raise util.Abort(_('repository is not empty'))
1479 raise util.Abort(_('repository is not empty'))
1474
1480
1475 # determine number of revs in DAG
1481 # determine number of revs in DAG
1476 total = 0
1482 total = 0
1477 for type, data in dagparser.parsedag(text):
1483 for type, data in dagparser.parsedag(text):
1478 if type == 'n':
1484 if type == 'n':
1479 total += 1
1485 total += 1
1480
1486
1481 if mergeable_file:
1487 if mergeable_file:
1482 linesperrev = 2
1488 linesperrev = 2
1483 # make a file with k lines per rev
1489 # make a file with k lines per rev
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1490 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1485 initialmergedlines.append("")
1491 initialmergedlines.append("")
1486
1492
1487 tags = []
1493 tags = []
1488
1494
1489 lock = tr = None
1495 lock = tr = None
1490 try:
1496 try:
1491 lock = repo.lock()
1497 lock = repo.lock()
1492 tr = repo.transaction("builddag")
1498 tr = repo.transaction("builddag")
1493
1499
1494 at = -1
1500 at = -1
1495 atbranch = 'default'
1501 atbranch = 'default'
1496 nodeids = []
1502 nodeids = []
1497 id = 0
1503 id = 0
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1504 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1499 for type, data in dagparser.parsedag(text):
1505 for type, data in dagparser.parsedag(text):
1500 if type == 'n':
1506 if type == 'n':
1501 ui.note('node %s\n' % str(data))
1507 ui.note('node %s\n' % str(data))
1502 id, ps = data
1508 id, ps = data
1503
1509
1504 files = []
1510 files = []
1505 fctxs = {}
1511 fctxs = {}
1506
1512
1507 p2 = None
1513 p2 = None
1508 if mergeable_file:
1514 if mergeable_file:
1509 fn = "mf"
1515 fn = "mf"
1510 p1 = repo[ps[0]]
1516 p1 = repo[ps[0]]
1511 if len(ps) > 1:
1517 if len(ps) > 1:
1512 p2 = repo[ps[1]]
1518 p2 = repo[ps[1]]
1513 pa = p1.ancestor(p2)
1519 pa = p1.ancestor(p2)
1514 base, local, other = [x[fn].data() for x in pa, p1, p2]
1520 base, local, other = [x[fn].data() for x in pa, p1, p2]
1515 m3 = simplemerge.Merge3Text(base, local, other)
1521 m3 = simplemerge.Merge3Text(base, local, other)
1516 ml = [l.strip() for l in m3.merge_lines()]
1522 ml = [l.strip() for l in m3.merge_lines()]
1517 ml.append("")
1523 ml.append("")
1518 elif at > 0:
1524 elif at > 0:
1519 ml = p1[fn].data().split("\n")
1525 ml = p1[fn].data().split("\n")
1520 else:
1526 else:
1521 ml = initialmergedlines
1527 ml = initialmergedlines
1522 ml[id * linesperrev] += " r%i" % id
1528 ml[id * linesperrev] += " r%i" % id
1523 mergedtext = "\n".join(ml)
1529 mergedtext = "\n".join(ml)
1524 files.append(fn)
1530 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1531 fctxs[fn] = context.memfilectx(fn, mergedtext)
1526
1532
1527 if overwritten_file:
1533 if overwritten_file:
1528 fn = "of"
1534 fn = "of"
1529 files.append(fn)
1535 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531
1537
1532 if new_file:
1538 if new_file:
1533 fn = "nf%i" % id
1539 fn = "nf%i" % id
1534 files.append(fn)
1540 files.append(fn)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1541 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 if len(ps) > 1:
1542 if len(ps) > 1:
1537 if not p2:
1543 if not p2:
1538 p2 = repo[ps[1]]
1544 p2 = repo[ps[1]]
1539 for fn in p2:
1545 for fn in p2:
1540 if fn.startswith("nf"):
1546 if fn.startswith("nf"):
1541 files.append(fn)
1547 files.append(fn)
1542 fctxs[fn] = p2[fn]
1548 fctxs[fn] = p2[fn]
1543
1549
1544 def fctxfn(repo, cx, path):
1550 def fctxfn(repo, cx, path):
1545 return fctxs.get(path)
1551 return fctxs.get(path)
1546
1552
1547 if len(ps) == 0 or ps[0] < 0:
1553 if len(ps) == 0 or ps[0] < 0:
1548 pars = [None, None]
1554 pars = [None, None]
1549 elif len(ps) == 1:
1555 elif len(ps) == 1:
1550 pars = [nodeids[ps[0]], None]
1556 pars = [nodeids[ps[0]], None]
1551 else:
1557 else:
1552 pars = [nodeids[p] for p in ps]
1558 pars = [nodeids[p] for p in ps]
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1559 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1554 date=(id, 0),
1560 date=(id, 0),
1555 user="debugbuilddag",
1561 user="debugbuilddag",
1556 extra={'branch': atbranch})
1562 extra={'branch': atbranch})
1557 nodeid = repo.commitctx(cx)
1563 nodeid = repo.commitctx(cx)
1558 nodeids.append(nodeid)
1564 nodeids.append(nodeid)
1559 at = id
1565 at = id
1560 elif type == 'l':
1566 elif type == 'l':
1561 id, name = data
1567 id, name = data
1562 ui.note('tag %s\n' % name)
1568 ui.note('tag %s\n' % name)
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1569 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1564 elif type == 'a':
1570 elif type == 'a':
1565 ui.note('branch %s\n' % data)
1571 ui.note('branch %s\n' % data)
1566 atbranch = data
1572 atbranch = data
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1573 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 tr.close()
1574 tr.close()
1569
1575
1570 if tags:
1576 if tags:
1571 repo.opener.write("localtags", "".join(tags))
1577 repo.opener.write("localtags", "".join(tags))
1572 finally:
1578 finally:
1573 ui.progress(_('building'), None)
1579 ui.progress(_('building'), None)
1574 release(tr, lock)
1580 release(tr, lock)
1575
1581
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1582 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1583 def debugbundle(ui, bundlepath, all=None, **opts):
1578 """lists the contents of a bundle"""
1584 """lists the contents of a bundle"""
1579 f = url.open(ui, bundlepath)
1585 f = url.open(ui, bundlepath)
1580 try:
1586 try:
1581 gen = changegroup.readbundle(f, bundlepath)
1587 gen = changegroup.readbundle(f, bundlepath)
1582 if all:
1588 if all:
1583 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1589 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1584
1590
1585 def showchunks(named):
1591 def showchunks(named):
1586 ui.write("\n%s\n" % named)
1592 ui.write("\n%s\n" % named)
1587 chain = None
1593 chain = None
1588 while True:
1594 while True:
1589 chunkdata = gen.deltachunk(chain)
1595 chunkdata = gen.deltachunk(chain)
1590 if not chunkdata:
1596 if not chunkdata:
1591 break
1597 break
1592 node = chunkdata['node']
1598 node = chunkdata['node']
1593 p1 = chunkdata['p1']
1599 p1 = chunkdata['p1']
1594 p2 = chunkdata['p2']
1600 p2 = chunkdata['p2']
1595 cs = chunkdata['cs']
1601 cs = chunkdata['cs']
1596 deltabase = chunkdata['deltabase']
1602 deltabase = chunkdata['deltabase']
1597 delta = chunkdata['delta']
1603 delta = chunkdata['delta']
1598 ui.write("%s %s %s %s %s %s\n" %
1604 ui.write("%s %s %s %s %s %s\n" %
1599 (hex(node), hex(p1), hex(p2),
1605 (hex(node), hex(p1), hex(p2),
1600 hex(cs), hex(deltabase), len(delta)))
1606 hex(cs), hex(deltabase), len(delta)))
1601 chain = node
1607 chain = node
1602
1608
1603 chunkdata = gen.changelogheader()
1609 chunkdata = gen.changelogheader()
1604 showchunks("changelog")
1610 showchunks("changelog")
1605 chunkdata = gen.manifestheader()
1611 chunkdata = gen.manifestheader()
1606 showchunks("manifest")
1612 showchunks("manifest")
1607 while True:
1613 while True:
1608 chunkdata = gen.filelogheader()
1614 chunkdata = gen.filelogheader()
1609 if not chunkdata:
1615 if not chunkdata:
1610 break
1616 break
1611 fname = chunkdata['filename']
1617 fname = chunkdata['filename']
1612 showchunks(fname)
1618 showchunks(fname)
1613 else:
1619 else:
1614 chunkdata = gen.changelogheader()
1620 chunkdata = gen.changelogheader()
1615 chain = None
1621 chain = None
1616 while True:
1622 while True:
1617 chunkdata = gen.deltachunk(chain)
1623 chunkdata = gen.deltachunk(chain)
1618 if not chunkdata:
1624 if not chunkdata:
1619 break
1625 break
1620 node = chunkdata['node']
1626 node = chunkdata['node']
1621 ui.write("%s\n" % hex(node))
1627 ui.write("%s\n" % hex(node))
1622 chain = node
1628 chain = node
1623 finally:
1629 finally:
1624 f.close()
1630 f.close()
1625
1631
1626 @command('debugcheckstate', [], '')
1632 @command('debugcheckstate', [], '')
1627 def debugcheckstate(ui, repo):
1633 def debugcheckstate(ui, repo):
1628 """validate the correctness of the current dirstate"""
1634 """validate the correctness of the current dirstate"""
1629 parent1, parent2 = repo.dirstate.parents()
1635 parent1, parent2 = repo.dirstate.parents()
1630 m1 = repo[parent1].manifest()
1636 m1 = repo[parent1].manifest()
1631 m2 = repo[parent2].manifest()
1637 m2 = repo[parent2].manifest()
1632 errors = 0
1638 errors = 0
1633 for f in repo.dirstate:
1639 for f in repo.dirstate:
1634 state = repo.dirstate[f]
1640 state = repo.dirstate[f]
1635 if state in "nr" and f not in m1:
1641 if state in "nr" and f not in m1:
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1642 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1637 errors += 1
1643 errors += 1
1638 if state in "a" and f in m1:
1644 if state in "a" and f in m1:
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1645 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1640 errors += 1
1646 errors += 1
1641 if state in "m" and f not in m1 and f not in m2:
1647 if state in "m" and f not in m1 and f not in m2:
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1648 ui.warn(_("%s in state %s, but not in either manifest\n") %
1643 (f, state))
1649 (f, state))
1644 errors += 1
1650 errors += 1
1645 for f in m1:
1651 for f in m1:
1646 state = repo.dirstate[f]
1652 state = repo.dirstate[f]
1647 if state not in "nrm":
1653 if state not in "nrm":
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1654 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1649 errors += 1
1655 errors += 1
1650 if errors:
1656 if errors:
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1657 error = _(".hg/dirstate inconsistent with current parent's manifest")
1652 raise util.Abort(error)
1658 raise util.Abort(error)
1653
1659
1654 @command('debugcommands', [], _('[COMMAND]'))
1660 @command('debugcommands', [], _('[COMMAND]'))
1655 def debugcommands(ui, cmd='', *args):
1661 def debugcommands(ui, cmd='', *args):
1656 """list all available commands and options"""
1662 """list all available commands and options"""
1657 for cmd, vals in sorted(table.iteritems()):
1663 for cmd, vals in sorted(table.iteritems()):
1658 cmd = cmd.split('|')[0].strip('^')
1664 cmd = cmd.split('|')[0].strip('^')
1659 opts = ', '.join([i[1] for i in vals[1]])
1665 opts = ', '.join([i[1] for i in vals[1]])
1660 ui.write('%s: %s\n' % (cmd, opts))
1666 ui.write('%s: %s\n' % (cmd, opts))
1661
1667
1662 @command('debugcomplete',
1668 @command('debugcomplete',
1663 [('o', 'options', None, _('show the command options'))],
1669 [('o', 'options', None, _('show the command options'))],
1664 _('[-o] CMD'))
1670 _('[-o] CMD'))
1665 def debugcomplete(ui, cmd='', **opts):
1671 def debugcomplete(ui, cmd='', **opts):
1666 """returns the completion list associated with the given command"""
1672 """returns the completion list associated with the given command"""
1667
1673
1668 if opts.get('options'):
1674 if opts.get('options'):
1669 options = []
1675 options = []
1670 otables = [globalopts]
1676 otables = [globalopts]
1671 if cmd:
1677 if cmd:
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1678 aliases, entry = cmdutil.findcmd(cmd, table, False)
1673 otables.append(entry[1])
1679 otables.append(entry[1])
1674 for t in otables:
1680 for t in otables:
1675 for o in t:
1681 for o in t:
1676 if "(DEPRECATED)" in o[3]:
1682 if "(DEPRECATED)" in o[3]:
1677 continue
1683 continue
1678 if o[0]:
1684 if o[0]:
1679 options.append('-%s' % o[0])
1685 options.append('-%s' % o[0])
1680 options.append('--%s' % o[1])
1686 options.append('--%s' % o[1])
1681 ui.write("%s\n" % "\n".join(options))
1687 ui.write("%s\n" % "\n".join(options))
1682 return
1688 return
1683
1689
1684 cmdlist = cmdutil.findpossible(cmd, table)
1690 cmdlist = cmdutil.findpossible(cmd, table)
1685 if ui.verbose:
1691 if ui.verbose:
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1692 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1693 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1688
1694
1689 @command('debugdag',
1695 @command('debugdag',
1690 [('t', 'tags', None, _('use tags as labels')),
1696 [('t', 'tags', None, _('use tags as labels')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1697 ('b', 'branches', None, _('annotate with branch names')),
1692 ('', 'dots', None, _('use dots for runs')),
1698 ('', 'dots', None, _('use dots for runs')),
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1699 ('s', 'spaces', None, _('separate elements by spaces'))],
1694 _('[OPTION]... [FILE [REV]...]'))
1700 _('[OPTION]... [FILE [REV]...]'))
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1701 def debugdag(ui, repo, file_=None, *revs, **opts):
1696 """format the changelog or an index DAG as a concise textual description
1702 """format the changelog or an index DAG as a concise textual description
1697
1703
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1704 If you pass a revlog index, the revlog's DAG is emitted. If you list
1699 revision numbers, they get labelled in the output as rN.
1705 revision numbers, they get labelled in the output as rN.
1700
1706
1701 Otherwise, the changelog DAG of the current repo is emitted.
1707 Otherwise, the changelog DAG of the current repo is emitted.
1702 """
1708 """
1703 spaces = opts.get('spaces')
1709 spaces = opts.get('spaces')
1704 dots = opts.get('dots')
1710 dots = opts.get('dots')
1705 if file_:
1711 if file_:
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1712 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1707 revs = set((int(r) for r in revs))
1713 revs = set((int(r) for r in revs))
1708 def events():
1714 def events():
1709 for r in rlog:
1715 for r in rlog:
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1716 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1711 if p != -1)))
1717 if p != -1)))
1712 if r in revs:
1718 if r in revs:
1713 yield 'l', (r, "r%i" % r)
1719 yield 'l', (r, "r%i" % r)
1714 elif repo:
1720 elif repo:
1715 cl = repo.changelog
1721 cl = repo.changelog
1716 tags = opts.get('tags')
1722 tags = opts.get('tags')
1717 branches = opts.get('branches')
1723 branches = opts.get('branches')
1718 if tags:
1724 if tags:
1719 labels = {}
1725 labels = {}
1720 for l, n in repo.tags().items():
1726 for l, n in repo.tags().items():
1721 labels.setdefault(cl.rev(n), []).append(l)
1727 labels.setdefault(cl.rev(n), []).append(l)
1722 def events():
1728 def events():
1723 b = "default"
1729 b = "default"
1724 for r in cl:
1730 for r in cl:
1725 if branches:
1731 if branches:
1726 newb = cl.read(cl.node(r))[5]['branch']
1732 newb = cl.read(cl.node(r))[5]['branch']
1727 if newb != b:
1733 if newb != b:
1728 yield 'a', newb
1734 yield 'a', newb
1729 b = newb
1735 b = newb
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1736 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1731 if p != -1)))
1737 if p != -1)))
1732 if tags:
1738 if tags:
1733 ls = labels.get(r)
1739 ls = labels.get(r)
1734 if ls:
1740 if ls:
1735 for l in ls:
1741 for l in ls:
1736 yield 'l', (r, l)
1742 yield 'l', (r, l)
1737 else:
1743 else:
1738 raise util.Abort(_('need repo for changelog dag'))
1744 raise util.Abort(_('need repo for changelog dag'))
1739
1745
1740 for line in dagparser.dagtextlines(events(),
1746 for line in dagparser.dagtextlines(events(),
1741 addspaces=spaces,
1747 addspaces=spaces,
1742 wraplabels=True,
1748 wraplabels=True,
1743 wrapannotations=True,
1749 wrapannotations=True,
1744 wrapnonlinear=dots,
1750 wrapnonlinear=dots,
1745 usedots=dots,
1751 usedots=dots,
1746 maxlinewidth=70):
1752 maxlinewidth=70):
1747 ui.write(line)
1753 ui.write(line)
1748 ui.write("\n")
1754 ui.write("\n")
1749
1755
1750 @command('debugdata',
1756 @command('debugdata',
1751 [('c', 'changelog', False, _('open changelog')),
1757 [('c', 'changelog', False, _('open changelog')),
1752 ('m', 'manifest', False, _('open manifest'))],
1758 ('m', 'manifest', False, _('open manifest'))],
1753 _('-c|-m|FILE REV'))
1759 _('-c|-m|FILE REV'))
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1760 def debugdata(ui, repo, file_, rev = None, **opts):
1755 """dump the contents of a data file revision"""
1761 """dump the contents of a data file revision"""
1756 if opts.get('changelog') or opts.get('manifest'):
1762 if opts.get('changelog') or opts.get('manifest'):
1757 file_, rev = None, file_
1763 file_, rev = None, file_
1758 elif rev is None:
1764 elif rev is None:
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1765 raise error.CommandError('debugdata', _('invalid arguments'))
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1766 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1761 try:
1767 try:
1762 ui.write(r.revision(r.lookup(rev)))
1768 ui.write(r.revision(r.lookup(rev)))
1763 except KeyError:
1769 except KeyError:
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1770 raise util.Abort(_('invalid revision identifier %s') % rev)
1765
1771
1766 @command('debugdate',
1772 @command('debugdate',
1767 [('e', 'extended', None, _('try extended date formats'))],
1773 [('e', 'extended', None, _('try extended date formats'))],
1768 _('[-e] DATE [RANGE]'))
1774 _('[-e] DATE [RANGE]'))
1769 def debugdate(ui, date, range=None, **opts):
1775 def debugdate(ui, date, range=None, **opts):
1770 """parse and display a date"""
1776 """parse and display a date"""
1771 if opts["extended"]:
1777 if opts["extended"]:
1772 d = util.parsedate(date, util.extendeddateformats)
1778 d = util.parsedate(date, util.extendeddateformats)
1773 else:
1779 else:
1774 d = util.parsedate(date)
1780 d = util.parsedate(date)
1775 ui.write("internal: %s %s\n" % d)
1781 ui.write("internal: %s %s\n" % d)
1776 ui.write("standard: %s\n" % util.datestr(d))
1782 ui.write("standard: %s\n" % util.datestr(d))
1777 if range:
1783 if range:
1778 m = util.matchdate(range)
1784 m = util.matchdate(range)
1779 ui.write("match: %s\n" % m(d[0]))
1785 ui.write("match: %s\n" % m(d[0]))
1780
1786
1781 @command('debugdiscovery',
1787 @command('debugdiscovery',
1782 [('', 'old', None, _('use old-style discovery')),
1788 [('', 'old', None, _('use old-style discovery')),
1783 ('', 'nonheads', None,
1789 ('', 'nonheads', None,
1784 _('use old-style discovery with non-heads included')),
1790 _('use old-style discovery with non-heads included')),
1785 ] + remoteopts,
1791 ] + remoteopts,
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1792 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1793 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1788 """runs the changeset discovery protocol in isolation"""
1794 """runs the changeset discovery protocol in isolation"""
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1795 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1790 opts.get('branch'))
1796 opts.get('branch'))
1791 remote = hg.peer(repo, opts, remoteurl)
1797 remote = hg.peer(repo, opts, remoteurl)
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1798 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1793
1799
1794 # make sure tests are repeatable
1800 # make sure tests are repeatable
1795 random.seed(12323)
1801 random.seed(12323)
1796
1802
1797 def doit(localheads, remoteheads, remote=remote):
1803 def doit(localheads, remoteheads, remote=remote):
1798 if opts.get('old'):
1804 if opts.get('old'):
1799 if localheads:
1805 if localheads:
1800 raise util.Abort('cannot use localheads with old style '
1806 raise util.Abort('cannot use localheads with old style '
1801 'discovery')
1807 'discovery')
1802 if not util.safehasattr(remote, 'branches'):
1808 if not util.safehasattr(remote, 'branches'):
1803 # enable in-client legacy support
1809 # enable in-client legacy support
1804 remote = localrepo.locallegacypeer(remote.local())
1810 remote = localrepo.locallegacypeer(remote.local())
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1811 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1806 force=True)
1812 force=True)
1807 common = set(common)
1813 common = set(common)
1808 if not opts.get('nonheads'):
1814 if not opts.get('nonheads'):
1809 ui.write("unpruned common: %s\n" % " ".join([short(n)
1815 ui.write("unpruned common: %s\n" % " ".join([short(n)
1810 for n in common]))
1816 for n in common]))
1811 dag = dagutil.revlogdag(repo.changelog)
1817 dag = dagutil.revlogdag(repo.changelog)
1812 all = dag.ancestorset(dag.internalizeall(common))
1818 all = dag.ancestorset(dag.internalizeall(common))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1819 common = dag.externalizeall(dag.headsetofconnecteds(all))
1814 else:
1820 else:
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1821 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1816 common = set(common)
1822 common = set(common)
1817 rheads = set(hds)
1823 rheads = set(hds)
1818 lheads = set(repo.heads())
1824 lheads = set(repo.heads())
1819 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1825 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1820 if lheads <= common:
1826 if lheads <= common:
1821 ui.write("local is subset\n")
1827 ui.write("local is subset\n")
1822 elif rheads <= common:
1828 elif rheads <= common:
1823 ui.write("remote is subset\n")
1829 ui.write("remote is subset\n")
1824
1830
1825 serverlogs = opts.get('serverlog')
1831 serverlogs = opts.get('serverlog')
1826 if serverlogs:
1832 if serverlogs:
1827 for filename in serverlogs:
1833 for filename in serverlogs:
1828 logfile = open(filename, 'r')
1834 logfile = open(filename, 'r')
1829 try:
1835 try:
1830 line = logfile.readline()
1836 line = logfile.readline()
1831 while line:
1837 while line:
1832 parts = line.strip().split(';')
1838 parts = line.strip().split(';')
1833 op = parts[1]
1839 op = parts[1]
1834 if op == 'cg':
1840 if op == 'cg':
1835 pass
1841 pass
1836 elif op == 'cgss':
1842 elif op == 'cgss':
1837 doit(parts[2].split(' '), parts[3].split(' '))
1843 doit(parts[2].split(' '), parts[3].split(' '))
1838 elif op == 'unb':
1844 elif op == 'unb':
1839 doit(parts[3].split(' '), parts[2].split(' '))
1845 doit(parts[3].split(' '), parts[2].split(' '))
1840 line = logfile.readline()
1846 line = logfile.readline()
1841 finally:
1847 finally:
1842 logfile.close()
1848 logfile.close()
1843
1849
1844 else:
1850 else:
1845 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1851 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1846 opts.get('remote_head'))
1852 opts.get('remote_head'))
1847 localrevs = opts.get('local_head')
1853 localrevs = opts.get('local_head')
1848 doit(localrevs, remoterevs)
1854 doit(localrevs, remoterevs)
1849
1855
1850 @command('debugfileset',
1856 @command('debugfileset',
1851 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1857 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1852 _('[-r REV] FILESPEC'))
1858 _('[-r REV] FILESPEC'))
1853 def debugfileset(ui, repo, expr, **opts):
1859 def debugfileset(ui, repo, expr, **opts):
1854 '''parse and apply a fileset specification'''
1860 '''parse and apply a fileset specification'''
1855 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1861 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1856 if ui.verbose:
1862 if ui.verbose:
1857 tree = fileset.parse(expr)[0]
1863 tree = fileset.parse(expr)[0]
1858 ui.note(tree, "\n")
1864 ui.note(tree, "\n")
1859
1865
1860 for f in fileset.getfileset(ctx, expr):
1866 for f in fileset.getfileset(ctx, expr):
1861 ui.write("%s\n" % f)
1867 ui.write("%s\n" % f)
1862
1868
1863 @command('debugfsinfo', [], _('[PATH]'))
1869 @command('debugfsinfo', [], _('[PATH]'))
1864 def debugfsinfo(ui, path = "."):
1870 def debugfsinfo(ui, path = "."):
1865 """show information detected about current filesystem"""
1871 """show information detected about current filesystem"""
1866 util.writefile('.debugfsinfo', '')
1872 util.writefile('.debugfsinfo', '')
1867 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1873 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1868 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1874 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1869 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1875 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1870 and 'yes' or 'no'))
1876 and 'yes' or 'no'))
1871 os.unlink('.debugfsinfo')
1877 os.unlink('.debugfsinfo')
1872
1878
1873 @command('debuggetbundle',
1879 @command('debuggetbundle',
1874 [('H', 'head', [], _('id of head node'), _('ID')),
1880 [('H', 'head', [], _('id of head node'), _('ID')),
1875 ('C', 'common', [], _('id of common node'), _('ID')),
1881 ('C', 'common', [], _('id of common node'), _('ID')),
1876 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1882 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1877 _('REPO FILE [-H|-C ID]...'))
1883 _('REPO FILE [-H|-C ID]...'))
1878 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1884 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1879 """retrieves a bundle from a repo
1885 """retrieves a bundle from a repo
1880
1886
1881 Every ID must be a full-length hex node id string. Saves the bundle to the
1887 Every ID must be a full-length hex node id string. Saves the bundle to the
1882 given file.
1888 given file.
1883 """
1889 """
1884 repo = hg.peer(ui, opts, repopath)
1890 repo = hg.peer(ui, opts, repopath)
1885 if not repo.capable('getbundle'):
1891 if not repo.capable('getbundle'):
1886 raise util.Abort("getbundle() not supported by target repository")
1892 raise util.Abort("getbundle() not supported by target repository")
1887 args = {}
1893 args = {}
1888 if common:
1894 if common:
1889 args['common'] = [bin(s) for s in common]
1895 args['common'] = [bin(s) for s in common]
1890 if head:
1896 if head:
1891 args['heads'] = [bin(s) for s in head]
1897 args['heads'] = [bin(s) for s in head]
1892 bundle = repo.getbundle('debug', **args)
1898 bundle = repo.getbundle('debug', **args)
1893
1899
1894 bundletype = opts.get('type', 'bzip2').lower()
1900 bundletype = opts.get('type', 'bzip2').lower()
1895 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1901 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1896 bundletype = btypes.get(bundletype)
1902 bundletype = btypes.get(bundletype)
1897 if bundletype not in changegroup.bundletypes:
1903 if bundletype not in changegroup.bundletypes:
1898 raise util.Abort(_('unknown bundle type specified with --type'))
1904 raise util.Abort(_('unknown bundle type specified with --type'))
1899 changegroup.writebundle(bundle, bundlepath, bundletype)
1905 changegroup.writebundle(bundle, bundlepath, bundletype)
1900
1906
1901 @command('debugignore', [], '')
1907 @command('debugignore', [], '')
1902 def debugignore(ui, repo, *values, **opts):
1908 def debugignore(ui, repo, *values, **opts):
1903 """display the combined ignore pattern"""
1909 """display the combined ignore pattern"""
1904 ignore = repo.dirstate._ignore
1910 ignore = repo.dirstate._ignore
1905 includepat = getattr(ignore, 'includepat', None)
1911 includepat = getattr(ignore, 'includepat', None)
1906 if includepat is not None:
1912 if includepat is not None:
1907 ui.write("%s\n" % includepat)
1913 ui.write("%s\n" % includepat)
1908 else:
1914 else:
1909 raise util.Abort(_("no ignore patterns found"))
1915 raise util.Abort(_("no ignore patterns found"))
1910
1916
1911 @command('debugindex',
1917 @command('debugindex',
1912 [('c', 'changelog', False, _('open changelog')),
1918 [('c', 'changelog', False, _('open changelog')),
1913 ('m', 'manifest', False, _('open manifest')),
1919 ('m', 'manifest', False, _('open manifest')),
1914 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1920 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1915 _('[-f FORMAT] -c|-m|FILE'))
1921 _('[-f FORMAT] -c|-m|FILE'))
1916 def debugindex(ui, repo, file_ = None, **opts):
1922 def debugindex(ui, repo, file_ = None, **opts):
1917 """dump the contents of an index file"""
1923 """dump the contents of an index file"""
1918 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1924 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1919 format = opts.get('format', 0)
1925 format = opts.get('format', 0)
1920 if format not in (0, 1):
1926 if format not in (0, 1):
1921 raise util.Abort(_("unknown format %d") % format)
1927 raise util.Abort(_("unknown format %d") % format)
1922
1928
1923 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1929 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1924 if generaldelta:
1930 if generaldelta:
1925 basehdr = ' delta'
1931 basehdr = ' delta'
1926 else:
1932 else:
1927 basehdr = ' base'
1933 basehdr = ' base'
1928
1934
1929 if format == 0:
1935 if format == 0:
1930 ui.write(" rev offset length " + basehdr + " linkrev"
1936 ui.write(" rev offset length " + basehdr + " linkrev"
1931 " nodeid p1 p2\n")
1937 " nodeid p1 p2\n")
1932 elif format == 1:
1938 elif format == 1:
1933 ui.write(" rev flag offset length"
1939 ui.write(" rev flag offset length"
1934 " size " + basehdr + " link p1 p2"
1940 " size " + basehdr + " link p1 p2"
1935 " nodeid\n")
1941 " nodeid\n")
1936
1942
1937 for i in r:
1943 for i in r:
1938 node = r.node(i)
1944 node = r.node(i)
1939 if generaldelta:
1945 if generaldelta:
1940 base = r.deltaparent(i)
1946 base = r.deltaparent(i)
1941 else:
1947 else:
1942 base = r.chainbase(i)
1948 base = r.chainbase(i)
1943 if format == 0:
1949 if format == 0:
1944 try:
1950 try:
1945 pp = r.parents(node)
1951 pp = r.parents(node)
1946 except Exception:
1952 except Exception:
1947 pp = [nullid, nullid]
1953 pp = [nullid, nullid]
1948 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1954 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1949 i, r.start(i), r.length(i), base, r.linkrev(i),
1955 i, r.start(i), r.length(i), base, r.linkrev(i),
1950 short(node), short(pp[0]), short(pp[1])))
1956 short(node), short(pp[0]), short(pp[1])))
1951 elif format == 1:
1957 elif format == 1:
1952 pr = r.parentrevs(i)
1958 pr = r.parentrevs(i)
1953 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1959 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1954 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1960 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1955 base, r.linkrev(i), pr[0], pr[1], short(node)))
1961 base, r.linkrev(i), pr[0], pr[1], short(node)))
1956
1962
1957 @command('debugindexdot', [], _('FILE'))
1963 @command('debugindexdot', [], _('FILE'))
1958 def debugindexdot(ui, repo, file_):
1964 def debugindexdot(ui, repo, file_):
1959 """dump an index DAG as a graphviz dot file"""
1965 """dump an index DAG as a graphviz dot file"""
1960 r = None
1966 r = None
1961 if repo:
1967 if repo:
1962 filelog = repo.file(file_)
1968 filelog = repo.file(file_)
1963 if len(filelog):
1969 if len(filelog):
1964 r = filelog
1970 r = filelog
1965 if not r:
1971 if not r:
1966 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1972 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1967 ui.write("digraph G {\n")
1973 ui.write("digraph G {\n")
1968 for i in r:
1974 for i in r:
1969 node = r.node(i)
1975 node = r.node(i)
1970 pp = r.parents(node)
1976 pp = r.parents(node)
1971 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1977 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1972 if pp[1] != nullid:
1978 if pp[1] != nullid:
1973 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1979 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1974 ui.write("}\n")
1980 ui.write("}\n")
1975
1981
1976 @command('debuginstall', [], '')
1982 @command('debuginstall', [], '')
1977 def debuginstall(ui):
1983 def debuginstall(ui):
1978 '''test Mercurial installation
1984 '''test Mercurial installation
1979
1985
1980 Returns 0 on success.
1986 Returns 0 on success.
1981 '''
1987 '''
1982
1988
1983 def writetemp(contents):
1989 def writetemp(contents):
1984 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1990 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1985 f = os.fdopen(fd, "wb")
1991 f = os.fdopen(fd, "wb")
1986 f.write(contents)
1992 f.write(contents)
1987 f.close()
1993 f.close()
1988 return name
1994 return name
1989
1995
1990 problems = 0
1996 problems = 0
1991
1997
1992 # encoding
1998 # encoding
1993 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1999 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1994 try:
2000 try:
1995 encoding.fromlocal("test")
2001 encoding.fromlocal("test")
1996 except util.Abort, inst:
2002 except util.Abort, inst:
1997 ui.write(" %s\n" % inst)
2003 ui.write(" %s\n" % inst)
1998 ui.write(_(" (check that your locale is properly set)\n"))
2004 ui.write(_(" (check that your locale is properly set)\n"))
1999 problems += 1
2005 problems += 1
2000
2006
2001 # Python lib
2007 # Python lib
2002 ui.status(_("checking Python lib (%s)...\n")
2008 ui.status(_("checking Python lib (%s)...\n")
2003 % os.path.dirname(os.__file__))
2009 % os.path.dirname(os.__file__))
2004
2010
2005 # compiled modules
2011 # compiled modules
2006 ui.status(_("checking installed modules (%s)...\n")
2012 ui.status(_("checking installed modules (%s)...\n")
2007 % os.path.dirname(__file__))
2013 % os.path.dirname(__file__))
2008 try:
2014 try:
2009 import bdiff, mpatch, base85, osutil
2015 import bdiff, mpatch, base85, osutil
2010 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2016 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2011 except Exception, inst:
2017 except Exception, inst:
2012 ui.write(" %s\n" % inst)
2018 ui.write(" %s\n" % inst)
2013 ui.write(_(" One or more extensions could not be found"))
2019 ui.write(_(" One or more extensions could not be found"))
2014 ui.write(_(" (check that you compiled the extensions)\n"))
2020 ui.write(_(" (check that you compiled the extensions)\n"))
2015 problems += 1
2021 problems += 1
2016
2022
2017 # templates
2023 # templates
2018 import templater
2024 import templater
2019 p = templater.templatepath()
2025 p = templater.templatepath()
2020 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2026 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2021 try:
2027 try:
2022 templater.templater(templater.templatepath("map-cmdline.default"))
2028 templater.templater(templater.templatepath("map-cmdline.default"))
2023 except Exception, inst:
2029 except Exception, inst:
2024 ui.write(" %s\n" % inst)
2030 ui.write(" %s\n" % inst)
2025 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2031 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2026 problems += 1
2032 problems += 1
2027
2033
2028 # editor
2034 # editor
2029 ui.status(_("checking commit editor...\n"))
2035 ui.status(_("checking commit editor...\n"))
2030 editor = ui.geteditor()
2036 editor = ui.geteditor()
2031 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2037 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2032 if not cmdpath:
2038 if not cmdpath:
2033 if editor == 'vi':
2039 if editor == 'vi':
2034 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2040 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2035 ui.write(_(" (specify a commit editor in your configuration"
2041 ui.write(_(" (specify a commit editor in your configuration"
2036 " file)\n"))
2042 " file)\n"))
2037 else:
2043 else:
2038 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2044 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2039 ui.write(_(" (specify a commit editor in your configuration"
2045 ui.write(_(" (specify a commit editor in your configuration"
2040 " file)\n"))
2046 " file)\n"))
2041 problems += 1
2047 problems += 1
2042
2048
2043 # check username
2049 # check username
2044 ui.status(_("checking username...\n"))
2050 ui.status(_("checking username...\n"))
2045 try:
2051 try:
2046 ui.username()
2052 ui.username()
2047 except util.Abort, e:
2053 except util.Abort, e:
2048 ui.write(" %s\n" % e)
2054 ui.write(" %s\n" % e)
2049 ui.write(_(" (specify a username in your configuration file)\n"))
2055 ui.write(_(" (specify a username in your configuration file)\n"))
2050 problems += 1
2056 problems += 1
2051
2057
2052 if not problems:
2058 if not problems:
2053 ui.status(_("no problems detected\n"))
2059 ui.status(_("no problems detected\n"))
2054 else:
2060 else:
2055 ui.write(_("%s problems detected,"
2061 ui.write(_("%s problems detected,"
2056 " please check your install!\n") % problems)
2062 " please check your install!\n") % problems)
2057
2063
2058 return problems
2064 return problems
2059
2065
2060 @command('debugknown', [], _('REPO ID...'))
2066 @command('debugknown', [], _('REPO ID...'))
2061 def debugknown(ui, repopath, *ids, **opts):
2067 def debugknown(ui, repopath, *ids, **opts):
2062 """test whether node ids are known to a repo
2068 """test whether node ids are known to a repo
2063
2069
2064 Every ID must be a full-length hex node id string. Returns a list of 0s
2070 Every ID must be a full-length hex node id string. Returns a list of 0s
2065 and 1s indicating unknown/known.
2071 and 1s indicating unknown/known.
2066 """
2072 """
2067 repo = hg.peer(ui, opts, repopath)
2073 repo = hg.peer(ui, opts, repopath)
2068 if not repo.capable('known'):
2074 if not repo.capable('known'):
2069 raise util.Abort("known() not supported by target repository")
2075 raise util.Abort("known() not supported by target repository")
2070 flags = repo.known([bin(s) for s in ids])
2076 flags = repo.known([bin(s) for s in ids])
2071 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2077 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2072
2078
2073 @command('debugobsolete', [] + commitopts2,
2079 @command('debugobsolete', [] + commitopts2,
2074 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2080 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2075 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2081 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2076 """create arbitrary obsolete marker"""
2082 """create arbitrary obsolete marker"""
2077 def parsenodeid(s):
2083 def parsenodeid(s):
2078 try:
2084 try:
2079 # We do not use revsingle/revrange functions here to accept
2085 # We do not use revsingle/revrange functions here to accept
2080 # arbitrary node identifiers, possibly not present in the
2086 # arbitrary node identifiers, possibly not present in the
2081 # local repository.
2087 # local repository.
2082 n = bin(s)
2088 n = bin(s)
2083 if len(n) != len(nullid):
2089 if len(n) != len(nullid):
2084 raise TypeError()
2090 raise TypeError()
2085 return n
2091 return n
2086 except TypeError:
2092 except TypeError:
2087 raise util.Abort('changeset references must be full hexadecimal '
2093 raise util.Abort('changeset references must be full hexadecimal '
2088 'node identifiers')
2094 'node identifiers')
2089
2095
2090 if precursor is not None:
2096 if precursor is not None:
2091 metadata = {}
2097 metadata = {}
2092 if 'date' in opts:
2098 if 'date' in opts:
2093 metadata['date'] = opts['date']
2099 metadata['date'] = opts['date']
2094 metadata['user'] = opts['user'] or ui.username()
2100 metadata['user'] = opts['user'] or ui.username()
2095 succs = tuple(parsenodeid(succ) for succ in successors)
2101 succs = tuple(parsenodeid(succ) for succ in successors)
2096 l = repo.lock()
2102 l = repo.lock()
2097 try:
2103 try:
2098 tr = repo.transaction('debugobsolete')
2104 tr = repo.transaction('debugobsolete')
2099 try:
2105 try:
2100 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2106 repo.obsstore.create(tr, parsenodeid(precursor), succs, 0,
2101 metadata)
2107 metadata)
2102 tr.close()
2108 tr.close()
2103 finally:
2109 finally:
2104 tr.release()
2110 tr.release()
2105 finally:
2111 finally:
2106 l.release()
2112 l.release()
2107 else:
2113 else:
2108 for m in obsolete.allmarkers(repo):
2114 for m in obsolete.allmarkers(repo):
2109 ui.write(hex(m.precnode()))
2115 ui.write(hex(m.precnode()))
2110 for repl in m.succnodes():
2116 for repl in m.succnodes():
2111 ui.write(' ')
2117 ui.write(' ')
2112 ui.write(hex(repl))
2118 ui.write(hex(repl))
2113 ui.write(' %X ' % m._data[2])
2119 ui.write(' %X ' % m._data[2])
2114 ui.write(m.metadata())
2120 ui.write(m.metadata())
2115 ui.write('\n')
2121 ui.write('\n')
2116
2122
2117 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2123 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2118 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2124 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2119 '''access the pushkey key/value protocol
2125 '''access the pushkey key/value protocol
2120
2126
2121 With two args, list the keys in the given namespace.
2127 With two args, list the keys in the given namespace.
2122
2128
2123 With five args, set a key to new if it currently is set to old.
2129 With five args, set a key to new if it currently is set to old.
2124 Reports success or failure.
2130 Reports success or failure.
2125 '''
2131 '''
2126
2132
2127 target = hg.peer(ui, {}, repopath)
2133 target = hg.peer(ui, {}, repopath)
2128 if keyinfo:
2134 if keyinfo:
2129 key, old, new = keyinfo
2135 key, old, new = keyinfo
2130 r = target.pushkey(namespace, key, old, new)
2136 r = target.pushkey(namespace, key, old, new)
2131 ui.status(str(r) + '\n')
2137 ui.status(str(r) + '\n')
2132 return not r
2138 return not r
2133 else:
2139 else:
2134 for k, v in target.listkeys(namespace).iteritems():
2140 for k, v in target.listkeys(namespace).iteritems():
2135 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2141 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2136 v.encode('string-escape')))
2142 v.encode('string-escape')))
2137
2143
2138 @command('debugpvec', [], _('A B'))
2144 @command('debugpvec', [], _('A B'))
2139 def debugpvec(ui, repo, a, b=None):
2145 def debugpvec(ui, repo, a, b=None):
2140 ca = scmutil.revsingle(repo, a)
2146 ca = scmutil.revsingle(repo, a)
2141 cb = scmutil.revsingle(repo, b)
2147 cb = scmutil.revsingle(repo, b)
2142 pa = pvec.ctxpvec(ca)
2148 pa = pvec.ctxpvec(ca)
2143 pb = pvec.ctxpvec(cb)
2149 pb = pvec.ctxpvec(cb)
2144 if pa == pb:
2150 if pa == pb:
2145 rel = "="
2151 rel = "="
2146 elif pa > pb:
2152 elif pa > pb:
2147 rel = ">"
2153 rel = ">"
2148 elif pa < pb:
2154 elif pa < pb:
2149 rel = "<"
2155 rel = "<"
2150 elif pa | pb:
2156 elif pa | pb:
2151 rel = "|"
2157 rel = "|"
2152 ui.write(_("a: %s\n") % pa)
2158 ui.write(_("a: %s\n") % pa)
2153 ui.write(_("b: %s\n") % pb)
2159 ui.write(_("b: %s\n") % pb)
2154 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2160 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2155 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2161 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2156 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2162 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2157 pa.distance(pb), rel))
2163 pa.distance(pb), rel))
2158
2164
2159 @command('debugrebuildstate',
2165 @command('debugrebuildstate',
2160 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2166 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2161 _('[-r REV] [REV]'))
2167 _('[-r REV] [REV]'))
2162 def debugrebuildstate(ui, repo, rev="tip"):
2168 def debugrebuildstate(ui, repo, rev="tip"):
2163 """rebuild the dirstate as it would look like for the given revision"""
2169 """rebuild the dirstate as it would look like for the given revision"""
2164 ctx = scmutil.revsingle(repo, rev)
2170 ctx = scmutil.revsingle(repo, rev)
2165 wlock = repo.wlock()
2171 wlock = repo.wlock()
2166 try:
2172 try:
2167 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2173 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2168 finally:
2174 finally:
2169 wlock.release()
2175 wlock.release()
2170
2176
2171 @command('debugrename',
2177 @command('debugrename',
2172 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2178 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2173 _('[-r REV] FILE'))
2179 _('[-r REV] FILE'))
2174 def debugrename(ui, repo, file1, *pats, **opts):
2180 def debugrename(ui, repo, file1, *pats, **opts):
2175 """dump rename information"""
2181 """dump rename information"""
2176
2182
2177 ctx = scmutil.revsingle(repo, opts.get('rev'))
2183 ctx = scmutil.revsingle(repo, opts.get('rev'))
2178 m = scmutil.match(ctx, (file1,) + pats, opts)
2184 m = scmutil.match(ctx, (file1,) + pats, opts)
2179 for abs in ctx.walk(m):
2185 for abs in ctx.walk(m):
2180 fctx = ctx[abs]
2186 fctx = ctx[abs]
2181 o = fctx.filelog().renamed(fctx.filenode())
2187 o = fctx.filelog().renamed(fctx.filenode())
2182 rel = m.rel(abs)
2188 rel = m.rel(abs)
2183 if o:
2189 if o:
2184 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2190 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2185 else:
2191 else:
2186 ui.write(_("%s not renamed\n") % rel)
2192 ui.write(_("%s not renamed\n") % rel)
2187
2193
2188 @command('debugrevlog',
2194 @command('debugrevlog',
2189 [('c', 'changelog', False, _('open changelog')),
2195 [('c', 'changelog', False, _('open changelog')),
2190 ('m', 'manifest', False, _('open manifest')),
2196 ('m', 'manifest', False, _('open manifest')),
2191 ('d', 'dump', False, _('dump index data'))],
2197 ('d', 'dump', False, _('dump index data'))],
2192 _('-c|-m|FILE'))
2198 _('-c|-m|FILE'))
2193 def debugrevlog(ui, repo, file_ = None, **opts):
2199 def debugrevlog(ui, repo, file_ = None, **opts):
2194 """show data and statistics about a revlog"""
2200 """show data and statistics about a revlog"""
2195 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2201 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2196
2202
2197 if opts.get("dump"):
2203 if opts.get("dump"):
2198 numrevs = len(r)
2204 numrevs = len(r)
2199 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2205 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2200 " rawsize totalsize compression heads\n")
2206 " rawsize totalsize compression heads\n")
2201 ts = 0
2207 ts = 0
2202 heads = set()
2208 heads = set()
2203 for rev in xrange(numrevs):
2209 for rev in xrange(numrevs):
2204 dbase = r.deltaparent(rev)
2210 dbase = r.deltaparent(rev)
2205 if dbase == -1:
2211 if dbase == -1:
2206 dbase = rev
2212 dbase = rev
2207 cbase = r.chainbase(rev)
2213 cbase = r.chainbase(rev)
2208 p1, p2 = r.parentrevs(rev)
2214 p1, p2 = r.parentrevs(rev)
2209 rs = r.rawsize(rev)
2215 rs = r.rawsize(rev)
2210 ts = ts + rs
2216 ts = ts + rs
2211 heads -= set(r.parentrevs(rev))
2217 heads -= set(r.parentrevs(rev))
2212 heads.add(rev)
2218 heads.add(rev)
2213 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2219 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2214 (rev, p1, p2, r.start(rev), r.end(rev),
2220 (rev, p1, p2, r.start(rev), r.end(rev),
2215 r.start(dbase), r.start(cbase),
2221 r.start(dbase), r.start(cbase),
2216 r.start(p1), r.start(p2),
2222 r.start(p1), r.start(p2),
2217 rs, ts, ts / r.end(rev), len(heads)))
2223 rs, ts, ts / r.end(rev), len(heads)))
2218 return 0
2224 return 0
2219
2225
2220 v = r.version
2226 v = r.version
2221 format = v & 0xFFFF
2227 format = v & 0xFFFF
2222 flags = []
2228 flags = []
2223 gdelta = False
2229 gdelta = False
2224 if v & revlog.REVLOGNGINLINEDATA:
2230 if v & revlog.REVLOGNGINLINEDATA:
2225 flags.append('inline')
2231 flags.append('inline')
2226 if v & revlog.REVLOGGENERALDELTA:
2232 if v & revlog.REVLOGGENERALDELTA:
2227 gdelta = True
2233 gdelta = True
2228 flags.append('generaldelta')
2234 flags.append('generaldelta')
2229 if not flags:
2235 if not flags:
2230 flags = ['(none)']
2236 flags = ['(none)']
2231
2237
2232 nummerges = 0
2238 nummerges = 0
2233 numfull = 0
2239 numfull = 0
2234 numprev = 0
2240 numprev = 0
2235 nump1 = 0
2241 nump1 = 0
2236 nump2 = 0
2242 nump2 = 0
2237 numother = 0
2243 numother = 0
2238 nump1prev = 0
2244 nump1prev = 0
2239 nump2prev = 0
2245 nump2prev = 0
2240 chainlengths = []
2246 chainlengths = []
2241
2247
2242 datasize = [None, 0, 0L]
2248 datasize = [None, 0, 0L]
2243 fullsize = [None, 0, 0L]
2249 fullsize = [None, 0, 0L]
2244 deltasize = [None, 0, 0L]
2250 deltasize = [None, 0, 0L]
2245
2251
2246 def addsize(size, l):
2252 def addsize(size, l):
2247 if l[0] is None or size < l[0]:
2253 if l[0] is None or size < l[0]:
2248 l[0] = size
2254 l[0] = size
2249 if size > l[1]:
2255 if size > l[1]:
2250 l[1] = size
2256 l[1] = size
2251 l[2] += size
2257 l[2] += size
2252
2258
2253 numrevs = len(r)
2259 numrevs = len(r)
2254 for rev in xrange(numrevs):
2260 for rev in xrange(numrevs):
2255 p1, p2 = r.parentrevs(rev)
2261 p1, p2 = r.parentrevs(rev)
2256 delta = r.deltaparent(rev)
2262 delta = r.deltaparent(rev)
2257 if format > 0:
2263 if format > 0:
2258 addsize(r.rawsize(rev), datasize)
2264 addsize(r.rawsize(rev), datasize)
2259 if p2 != nullrev:
2265 if p2 != nullrev:
2260 nummerges += 1
2266 nummerges += 1
2261 size = r.length(rev)
2267 size = r.length(rev)
2262 if delta == nullrev:
2268 if delta == nullrev:
2263 chainlengths.append(0)
2269 chainlengths.append(0)
2264 numfull += 1
2270 numfull += 1
2265 addsize(size, fullsize)
2271 addsize(size, fullsize)
2266 else:
2272 else:
2267 chainlengths.append(chainlengths[delta] + 1)
2273 chainlengths.append(chainlengths[delta] + 1)
2268 addsize(size, deltasize)
2274 addsize(size, deltasize)
2269 if delta == rev - 1:
2275 if delta == rev - 1:
2270 numprev += 1
2276 numprev += 1
2271 if delta == p1:
2277 if delta == p1:
2272 nump1prev += 1
2278 nump1prev += 1
2273 elif delta == p2:
2279 elif delta == p2:
2274 nump2prev += 1
2280 nump2prev += 1
2275 elif delta == p1:
2281 elif delta == p1:
2276 nump1 += 1
2282 nump1 += 1
2277 elif delta == p2:
2283 elif delta == p2:
2278 nump2 += 1
2284 nump2 += 1
2279 elif delta != nullrev:
2285 elif delta != nullrev:
2280 numother += 1
2286 numother += 1
2281
2287
2282 # Adjust size min value for empty cases
2288 # Adjust size min value for empty cases
2283 for size in (datasize, fullsize, deltasize):
2289 for size in (datasize, fullsize, deltasize):
2284 if size[0] is None:
2290 if size[0] is None:
2285 size[0] = 0
2291 size[0] = 0
2286
2292
2287 numdeltas = numrevs - numfull
2293 numdeltas = numrevs - numfull
2288 numoprev = numprev - nump1prev - nump2prev
2294 numoprev = numprev - nump1prev - nump2prev
2289 totalrawsize = datasize[2]
2295 totalrawsize = datasize[2]
2290 datasize[2] /= numrevs
2296 datasize[2] /= numrevs
2291 fulltotal = fullsize[2]
2297 fulltotal = fullsize[2]
2292 fullsize[2] /= numfull
2298 fullsize[2] /= numfull
2293 deltatotal = deltasize[2]
2299 deltatotal = deltasize[2]
2294 if numrevs - numfull > 0:
2300 if numrevs - numfull > 0:
2295 deltasize[2] /= numrevs - numfull
2301 deltasize[2] /= numrevs - numfull
2296 totalsize = fulltotal + deltatotal
2302 totalsize = fulltotal + deltatotal
2297 avgchainlen = sum(chainlengths) / numrevs
2303 avgchainlen = sum(chainlengths) / numrevs
2298 compratio = totalrawsize / totalsize
2304 compratio = totalrawsize / totalsize
2299
2305
2300 basedfmtstr = '%%%dd\n'
2306 basedfmtstr = '%%%dd\n'
2301 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2307 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2302
2308
2303 def dfmtstr(max):
2309 def dfmtstr(max):
2304 return basedfmtstr % len(str(max))
2310 return basedfmtstr % len(str(max))
2305 def pcfmtstr(max, padding=0):
2311 def pcfmtstr(max, padding=0):
2306 return basepcfmtstr % (len(str(max)), ' ' * padding)
2312 return basepcfmtstr % (len(str(max)), ' ' * padding)
2307
2313
2308 def pcfmt(value, total):
2314 def pcfmt(value, total):
2309 return (value, 100 * float(value) / total)
2315 return (value, 100 * float(value) / total)
2310
2316
2311 ui.write('format : %d\n' % format)
2317 ui.write('format : %d\n' % format)
2312 ui.write('flags : %s\n' % ', '.join(flags))
2318 ui.write('flags : %s\n' % ', '.join(flags))
2313
2319
2314 ui.write('\n')
2320 ui.write('\n')
2315 fmt = pcfmtstr(totalsize)
2321 fmt = pcfmtstr(totalsize)
2316 fmt2 = dfmtstr(totalsize)
2322 fmt2 = dfmtstr(totalsize)
2317 ui.write('revisions : ' + fmt2 % numrevs)
2323 ui.write('revisions : ' + fmt2 % numrevs)
2318 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2324 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2319 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2325 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2320 ui.write('revisions : ' + fmt2 % numrevs)
2326 ui.write('revisions : ' + fmt2 % numrevs)
2321 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2327 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2322 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2328 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2323 ui.write('revision size : ' + fmt2 % totalsize)
2329 ui.write('revision size : ' + fmt2 % totalsize)
2324 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2330 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2325 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2331 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2326
2332
2327 ui.write('\n')
2333 ui.write('\n')
2328 fmt = dfmtstr(max(avgchainlen, compratio))
2334 fmt = dfmtstr(max(avgchainlen, compratio))
2329 ui.write('avg chain length : ' + fmt % avgchainlen)
2335 ui.write('avg chain length : ' + fmt % avgchainlen)
2330 ui.write('compression ratio : ' + fmt % compratio)
2336 ui.write('compression ratio : ' + fmt % compratio)
2331
2337
2332 if format > 0:
2338 if format > 0:
2333 ui.write('\n')
2339 ui.write('\n')
2334 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2340 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2335 % tuple(datasize))
2341 % tuple(datasize))
2336 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2342 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2337 % tuple(fullsize))
2343 % tuple(fullsize))
2338 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2344 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2339 % tuple(deltasize))
2345 % tuple(deltasize))
2340
2346
2341 if numdeltas > 0:
2347 if numdeltas > 0:
2342 ui.write('\n')
2348 ui.write('\n')
2343 fmt = pcfmtstr(numdeltas)
2349 fmt = pcfmtstr(numdeltas)
2344 fmt2 = pcfmtstr(numdeltas, 4)
2350 fmt2 = pcfmtstr(numdeltas, 4)
2345 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2351 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2346 if numprev > 0:
2352 if numprev > 0:
2347 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2353 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2348 numprev))
2354 numprev))
2349 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2355 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2350 numprev))
2356 numprev))
2351 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2357 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2352 numprev))
2358 numprev))
2353 if gdelta:
2359 if gdelta:
2354 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2360 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2355 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2361 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2356 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2362 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2357 numdeltas))
2363 numdeltas))
2358
2364
2359 @command('debugrevspec', [], ('REVSPEC'))
2365 @command('debugrevspec', [], ('REVSPEC'))
2360 def debugrevspec(ui, repo, expr):
2366 def debugrevspec(ui, repo, expr):
2361 """parse and apply a revision specification
2367 """parse and apply a revision specification
2362
2368
2363 Use --verbose to print the parsed tree before and after aliases
2369 Use --verbose to print the parsed tree before and after aliases
2364 expansion.
2370 expansion.
2365 """
2371 """
2366 if ui.verbose:
2372 if ui.verbose:
2367 tree = revset.parse(expr)[0]
2373 tree = revset.parse(expr)[0]
2368 ui.note(revset.prettyformat(tree), "\n")
2374 ui.note(revset.prettyformat(tree), "\n")
2369 newtree = revset.findaliases(ui, tree)
2375 newtree = revset.findaliases(ui, tree)
2370 if newtree != tree:
2376 if newtree != tree:
2371 ui.note(revset.prettyformat(newtree), "\n")
2377 ui.note(revset.prettyformat(newtree), "\n")
2372 func = revset.match(ui, expr)
2378 func = revset.match(ui, expr)
2373 for c in func(repo, range(len(repo))):
2379 for c in func(repo, range(len(repo))):
2374 ui.write("%s\n" % c)
2380 ui.write("%s\n" % c)
2375
2381
2376 @command('debugsetparents', [], _('REV1 [REV2]'))
2382 @command('debugsetparents', [], _('REV1 [REV2]'))
2377 def debugsetparents(ui, repo, rev1, rev2=None):
2383 def debugsetparents(ui, repo, rev1, rev2=None):
2378 """manually set the parents of the current working directory
2384 """manually set the parents of the current working directory
2379
2385
2380 This is useful for writing repository conversion tools, but should
2386 This is useful for writing repository conversion tools, but should
2381 be used with care.
2387 be used with care.
2382
2388
2383 Returns 0 on success.
2389 Returns 0 on success.
2384 """
2390 """
2385
2391
2386 r1 = scmutil.revsingle(repo, rev1).node()
2392 r1 = scmutil.revsingle(repo, rev1).node()
2387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2393 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2388
2394
2389 wlock = repo.wlock()
2395 wlock = repo.wlock()
2390 try:
2396 try:
2391 repo.setparents(r1, r2)
2397 repo.setparents(r1, r2)
2392 finally:
2398 finally:
2393 wlock.release()
2399 wlock.release()
2394
2400
2395 @command('debugstate',
2401 @command('debugstate',
2396 [('', 'nodates', None, _('do not display the saved mtime')),
2402 [('', 'nodates', None, _('do not display the saved mtime')),
2397 ('', 'datesort', None, _('sort by saved mtime'))],
2403 ('', 'datesort', None, _('sort by saved mtime'))],
2398 _('[OPTION]...'))
2404 _('[OPTION]...'))
2399 def debugstate(ui, repo, nodates=None, datesort=None):
2405 def debugstate(ui, repo, nodates=None, datesort=None):
2400 """show the contents of the current dirstate"""
2406 """show the contents of the current dirstate"""
2401 timestr = ""
2407 timestr = ""
2402 showdate = not nodates
2408 showdate = not nodates
2403 if datesort:
2409 if datesort:
2404 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2410 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2405 else:
2411 else:
2406 keyfunc = None # sort by filename
2412 keyfunc = None # sort by filename
2407 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2413 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2408 if showdate:
2414 if showdate:
2409 if ent[3] == -1:
2415 if ent[3] == -1:
2410 # Pad or slice to locale representation
2416 # Pad or slice to locale representation
2411 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2417 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2412 time.localtime(0)))
2418 time.localtime(0)))
2413 timestr = 'unset'
2419 timestr = 'unset'
2414 timestr = (timestr[:locale_len] +
2420 timestr = (timestr[:locale_len] +
2415 ' ' * (locale_len - len(timestr)))
2421 ' ' * (locale_len - len(timestr)))
2416 else:
2422 else:
2417 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2423 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2418 time.localtime(ent[3]))
2424 time.localtime(ent[3]))
2419 if ent[1] & 020000:
2425 if ent[1] & 020000:
2420 mode = 'lnk'
2426 mode = 'lnk'
2421 else:
2427 else:
2422 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2428 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2423 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2429 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2424 for f in repo.dirstate.copies():
2430 for f in repo.dirstate.copies():
2425 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2431 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2426
2432
2427 @command('debugsub',
2433 @command('debugsub',
2428 [('r', 'rev', '',
2434 [('r', 'rev', '',
2429 _('revision to check'), _('REV'))],
2435 _('revision to check'), _('REV'))],
2430 _('[-r REV] [REV]'))
2436 _('[-r REV] [REV]'))
2431 def debugsub(ui, repo, rev=None):
2437 def debugsub(ui, repo, rev=None):
2432 ctx = scmutil.revsingle(repo, rev, None)
2438 ctx = scmutil.revsingle(repo, rev, None)
2433 for k, v in sorted(ctx.substate.items()):
2439 for k, v in sorted(ctx.substate.items()):
2434 ui.write('path %s\n' % k)
2440 ui.write('path %s\n' % k)
2435 ui.write(' source %s\n' % v[0])
2441 ui.write(' source %s\n' % v[0])
2436 ui.write(' revision %s\n' % v[1])
2442 ui.write(' revision %s\n' % v[1])
2437
2443
2438 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2444 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2439 def debugwalk(ui, repo, *pats, **opts):
2445 def debugwalk(ui, repo, *pats, **opts):
2440 """show how files match on given patterns"""
2446 """show how files match on given patterns"""
2441 m = scmutil.match(repo[None], pats, opts)
2447 m = scmutil.match(repo[None], pats, opts)
2442 items = list(repo.walk(m))
2448 items = list(repo.walk(m))
2443 if not items:
2449 if not items:
2444 return
2450 return
2445 f = lambda fn: fn
2451 f = lambda fn: fn
2446 if ui.configbool('ui', 'slash') and os.sep != '/':
2452 if ui.configbool('ui', 'slash') and os.sep != '/':
2447 f = lambda fn: util.normpath(fn)
2453 f = lambda fn: util.normpath(fn)
2448 fmt = 'f %%-%ds %%-%ds %%s' % (
2454 fmt = 'f %%-%ds %%-%ds %%s' % (
2449 max([len(abs) for abs in items]),
2455 max([len(abs) for abs in items]),
2450 max([len(m.rel(abs)) for abs in items]))
2456 max([len(m.rel(abs)) for abs in items]))
2451 for abs in items:
2457 for abs in items:
2452 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2458 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2453 ui.write("%s\n" % line.rstrip())
2459 ui.write("%s\n" % line.rstrip())
2454
2460
2455 @command('debugwireargs',
2461 @command('debugwireargs',
2456 [('', 'three', '', 'three'),
2462 [('', 'three', '', 'three'),
2457 ('', 'four', '', 'four'),
2463 ('', 'four', '', 'four'),
2458 ('', 'five', '', 'five'),
2464 ('', 'five', '', 'five'),
2459 ] + remoteopts,
2465 ] + remoteopts,
2460 _('REPO [OPTIONS]... [ONE [TWO]]'))
2466 _('REPO [OPTIONS]... [ONE [TWO]]'))
2461 def debugwireargs(ui, repopath, *vals, **opts):
2467 def debugwireargs(ui, repopath, *vals, **opts):
2462 repo = hg.peer(ui, opts, repopath)
2468 repo = hg.peer(ui, opts, repopath)
2463 for opt in remoteopts:
2469 for opt in remoteopts:
2464 del opts[opt[1]]
2470 del opts[opt[1]]
2465 args = {}
2471 args = {}
2466 for k, v in opts.iteritems():
2472 for k, v in opts.iteritems():
2467 if v:
2473 if v:
2468 args[k] = v
2474 args[k] = v
2469 # run twice to check that we don't mess up the stream for the next command
2475 # run twice to check that we don't mess up the stream for the next command
2470 res1 = repo.debugwireargs(*vals, **args)
2476 res1 = repo.debugwireargs(*vals, **args)
2471 res2 = repo.debugwireargs(*vals, **args)
2477 res2 = repo.debugwireargs(*vals, **args)
2472 ui.write("%s\n" % res1)
2478 ui.write("%s\n" % res1)
2473 if res1 != res2:
2479 if res1 != res2:
2474 ui.warn("%s\n" % res2)
2480 ui.warn("%s\n" % res2)
2475
2481
2476 @command('^diff',
2482 @command('^diff',
2477 [('r', 'rev', [], _('revision'), _('REV')),
2483 [('r', 'rev', [], _('revision'), _('REV')),
2478 ('c', 'change', '', _('change made by revision'), _('REV'))
2484 ('c', 'change', '', _('change made by revision'), _('REV'))
2479 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2485 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2480 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2486 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2481 def diff(ui, repo, *pats, **opts):
2487 def diff(ui, repo, *pats, **opts):
2482 """diff repository (or selected files)
2488 """diff repository (or selected files)
2483
2489
2484 Show differences between revisions for the specified files.
2490 Show differences between revisions for the specified files.
2485
2491
2486 Differences between files are shown using the unified diff format.
2492 Differences between files are shown using the unified diff format.
2487
2493
2488 .. note::
2494 .. note::
2489 diff may generate unexpected results for merges, as it will
2495 diff may generate unexpected results for merges, as it will
2490 default to comparing against the working directory's first
2496 default to comparing against the working directory's first
2491 parent changeset if no revisions are specified.
2497 parent changeset if no revisions are specified.
2492
2498
2493 When two revision arguments are given, then changes are shown
2499 When two revision arguments are given, then changes are shown
2494 between those revisions. If only one revision is specified then
2500 between those revisions. If only one revision is specified then
2495 that revision is compared to the working directory, and, when no
2501 that revision is compared to the working directory, and, when no
2496 revisions are specified, the working directory files are compared
2502 revisions are specified, the working directory files are compared
2497 to its parent.
2503 to its parent.
2498
2504
2499 Alternatively you can specify -c/--change with a revision to see
2505 Alternatively you can specify -c/--change with a revision to see
2500 the changes in that changeset relative to its first parent.
2506 the changes in that changeset relative to its first parent.
2501
2507
2502 Without the -a/--text option, diff will avoid generating diffs of
2508 Without the -a/--text option, diff will avoid generating diffs of
2503 files it detects as binary. With -a, diff will generate a diff
2509 files it detects as binary. With -a, diff will generate a diff
2504 anyway, probably with undesirable results.
2510 anyway, probably with undesirable results.
2505
2511
2506 Use the -g/--git option to generate diffs in the git extended diff
2512 Use the -g/--git option to generate diffs in the git extended diff
2507 format. For more information, read :hg:`help diffs`.
2513 format. For more information, read :hg:`help diffs`.
2508
2514
2509 .. container:: verbose
2515 .. container:: verbose
2510
2516
2511 Examples:
2517 Examples:
2512
2518
2513 - compare a file in the current working directory to its parent::
2519 - compare a file in the current working directory to its parent::
2514
2520
2515 hg diff foo.c
2521 hg diff foo.c
2516
2522
2517 - compare two historical versions of a directory, with rename info::
2523 - compare two historical versions of a directory, with rename info::
2518
2524
2519 hg diff --git -r 1.0:1.2 lib/
2525 hg diff --git -r 1.0:1.2 lib/
2520
2526
2521 - get change stats relative to the last change on some date::
2527 - get change stats relative to the last change on some date::
2522
2528
2523 hg diff --stat -r "date('may 2')"
2529 hg diff --stat -r "date('may 2')"
2524
2530
2525 - diff all newly-added files that contain a keyword::
2531 - diff all newly-added files that contain a keyword::
2526
2532
2527 hg diff "set:added() and grep(GNU)"
2533 hg diff "set:added() and grep(GNU)"
2528
2534
2529 - compare a revision and its parents::
2535 - compare a revision and its parents::
2530
2536
2531 hg diff -c 9353 # compare against first parent
2537 hg diff -c 9353 # compare against first parent
2532 hg diff -r 9353^:9353 # same using revset syntax
2538 hg diff -r 9353^:9353 # same using revset syntax
2533 hg diff -r 9353^2:9353 # compare against the second parent
2539 hg diff -r 9353^2:9353 # compare against the second parent
2534
2540
2535 Returns 0 on success.
2541 Returns 0 on success.
2536 """
2542 """
2537
2543
2538 revs = opts.get('rev')
2544 revs = opts.get('rev')
2539 change = opts.get('change')
2545 change = opts.get('change')
2540 stat = opts.get('stat')
2546 stat = opts.get('stat')
2541 reverse = opts.get('reverse')
2547 reverse = opts.get('reverse')
2542
2548
2543 if revs and change:
2549 if revs and change:
2544 msg = _('cannot specify --rev and --change at the same time')
2550 msg = _('cannot specify --rev and --change at the same time')
2545 raise util.Abort(msg)
2551 raise util.Abort(msg)
2546 elif change:
2552 elif change:
2547 node2 = scmutil.revsingle(repo, change, None).node()
2553 node2 = scmutil.revsingle(repo, change, None).node()
2548 node1 = repo[node2].p1().node()
2554 node1 = repo[node2].p1().node()
2549 else:
2555 else:
2550 node1, node2 = scmutil.revpair(repo, revs)
2556 node1, node2 = scmutil.revpair(repo, revs)
2551
2557
2552 if reverse:
2558 if reverse:
2553 node1, node2 = node2, node1
2559 node1, node2 = node2, node1
2554
2560
2555 diffopts = patch.diffopts(ui, opts)
2561 diffopts = patch.diffopts(ui, opts)
2556 m = scmutil.match(repo[node2], pats, opts)
2562 m = scmutil.match(repo[node2], pats, opts)
2557 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2563 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2558 listsubrepos=opts.get('subrepos'))
2564 listsubrepos=opts.get('subrepos'))
2559
2565
2560 @command('^export',
2566 @command('^export',
2561 [('o', 'output', '',
2567 [('o', 'output', '',
2562 _('print output to file with formatted name'), _('FORMAT')),
2568 _('print output to file with formatted name'), _('FORMAT')),
2563 ('', 'switch-parent', None, _('diff against the second parent')),
2569 ('', 'switch-parent', None, _('diff against the second parent')),
2564 ('r', 'rev', [], _('revisions to export'), _('REV')),
2570 ('r', 'rev', [], _('revisions to export'), _('REV')),
2565 ] + diffopts,
2571 ] + diffopts,
2566 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2572 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2567 def export(ui, repo, *changesets, **opts):
2573 def export(ui, repo, *changesets, **opts):
2568 """dump the header and diffs for one or more changesets
2574 """dump the header and diffs for one or more changesets
2569
2575
2570 Print the changeset header and diffs for one or more revisions.
2576 Print the changeset header and diffs for one or more revisions.
2571
2577
2572 The information shown in the changeset header is: author, date,
2578 The information shown in the changeset header is: author, date,
2573 branch name (if non-default), changeset hash, parent(s) and commit
2579 branch name (if non-default), changeset hash, parent(s) and commit
2574 comment.
2580 comment.
2575
2581
2576 .. note::
2582 .. note::
2577 export may generate unexpected diff output for merge
2583 export may generate unexpected diff output for merge
2578 changesets, as it will compare the merge changeset against its
2584 changesets, as it will compare the merge changeset against its
2579 first parent only.
2585 first parent only.
2580
2586
2581 Output may be to a file, in which case the name of the file is
2587 Output may be to a file, in which case the name of the file is
2582 given using a format string. The formatting rules are as follows:
2588 given using a format string. The formatting rules are as follows:
2583
2589
2584 :``%%``: literal "%" character
2590 :``%%``: literal "%" character
2585 :``%H``: changeset hash (40 hexadecimal digits)
2591 :``%H``: changeset hash (40 hexadecimal digits)
2586 :``%N``: number of patches being generated
2592 :``%N``: number of patches being generated
2587 :``%R``: changeset revision number
2593 :``%R``: changeset revision number
2588 :``%b``: basename of the exporting repository
2594 :``%b``: basename of the exporting repository
2589 :``%h``: short-form changeset hash (12 hexadecimal digits)
2595 :``%h``: short-form changeset hash (12 hexadecimal digits)
2590 :``%m``: first line of the commit message (only alphanumeric characters)
2596 :``%m``: first line of the commit message (only alphanumeric characters)
2591 :``%n``: zero-padded sequence number, starting at 1
2597 :``%n``: zero-padded sequence number, starting at 1
2592 :``%r``: zero-padded changeset revision number
2598 :``%r``: zero-padded changeset revision number
2593
2599
2594 Without the -a/--text option, export will avoid generating diffs
2600 Without the -a/--text option, export will avoid generating diffs
2595 of files it detects as binary. With -a, export will generate a
2601 of files it detects as binary. With -a, export will generate a
2596 diff anyway, probably with undesirable results.
2602 diff anyway, probably with undesirable results.
2597
2603
2598 Use the -g/--git option to generate diffs in the git extended diff
2604 Use the -g/--git option to generate diffs in the git extended diff
2599 format. See :hg:`help diffs` for more information.
2605 format. See :hg:`help diffs` for more information.
2600
2606
2601 With the --switch-parent option, the diff will be against the
2607 With the --switch-parent option, the diff will be against the
2602 second parent. It can be useful to review a merge.
2608 second parent. It can be useful to review a merge.
2603
2609
2604 .. container:: verbose
2610 .. container:: verbose
2605
2611
2606 Examples:
2612 Examples:
2607
2613
2608 - use export and import to transplant a bugfix to the current
2614 - use export and import to transplant a bugfix to the current
2609 branch::
2615 branch::
2610
2616
2611 hg export -r 9353 | hg import -
2617 hg export -r 9353 | hg import -
2612
2618
2613 - export all the changesets between two revisions to a file with
2619 - export all the changesets between two revisions to a file with
2614 rename information::
2620 rename information::
2615
2621
2616 hg export --git -r 123:150 > changes.txt
2622 hg export --git -r 123:150 > changes.txt
2617
2623
2618 - split outgoing changes into a series of patches with
2624 - split outgoing changes into a series of patches with
2619 descriptive names::
2625 descriptive names::
2620
2626
2621 hg export -r "outgoing()" -o "%n-%m.patch"
2627 hg export -r "outgoing()" -o "%n-%m.patch"
2622
2628
2623 Returns 0 on success.
2629 Returns 0 on success.
2624 """
2630 """
2625 changesets += tuple(opts.get('rev', []))
2631 changesets += tuple(opts.get('rev', []))
2626 revs = scmutil.revrange(repo, changesets)
2632 revs = scmutil.revrange(repo, changesets)
2627 if not revs:
2633 if not revs:
2628 raise util.Abort(_("export requires at least one changeset"))
2634 raise util.Abort(_("export requires at least one changeset"))
2629 if len(revs) > 1:
2635 if len(revs) > 1:
2630 ui.note(_('exporting patches:\n'))
2636 ui.note(_('exporting patches:\n'))
2631 else:
2637 else:
2632 ui.note(_('exporting patch:\n'))
2638 ui.note(_('exporting patch:\n'))
2633 cmdutil.export(repo, revs, template=opts.get('output'),
2639 cmdutil.export(repo, revs, template=opts.get('output'),
2634 switch_parent=opts.get('switch_parent'),
2640 switch_parent=opts.get('switch_parent'),
2635 opts=patch.diffopts(ui, opts))
2641 opts=patch.diffopts(ui, opts))
2636
2642
2637 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2643 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2638 def forget(ui, repo, *pats, **opts):
2644 def forget(ui, repo, *pats, **opts):
2639 """forget the specified files on the next commit
2645 """forget the specified files on the next commit
2640
2646
2641 Mark the specified files so they will no longer be tracked
2647 Mark the specified files so they will no longer be tracked
2642 after the next commit.
2648 after the next commit.
2643
2649
2644 This only removes files from the current branch, not from the
2650 This only removes files from the current branch, not from the
2645 entire project history, and it does not delete them from the
2651 entire project history, and it does not delete them from the
2646 working directory.
2652 working directory.
2647
2653
2648 To undo a forget before the next commit, see :hg:`add`.
2654 To undo a forget before the next commit, see :hg:`add`.
2649
2655
2650 .. container:: verbose
2656 .. container:: verbose
2651
2657
2652 Examples:
2658 Examples:
2653
2659
2654 - forget newly-added binary files::
2660 - forget newly-added binary files::
2655
2661
2656 hg forget "set:added() and binary()"
2662 hg forget "set:added() and binary()"
2657
2663
2658 - forget files that would be excluded by .hgignore::
2664 - forget files that would be excluded by .hgignore::
2659
2665
2660 hg forget "set:hgignore()"
2666 hg forget "set:hgignore()"
2661
2667
2662 Returns 0 on success.
2668 Returns 0 on success.
2663 """
2669 """
2664
2670
2665 if not pats:
2671 if not pats:
2666 raise util.Abort(_('no files specified'))
2672 raise util.Abort(_('no files specified'))
2667
2673
2668 m = scmutil.match(repo[None], pats, opts)
2674 m = scmutil.match(repo[None], pats, opts)
2669 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2675 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2670 return rejected and 1 or 0
2676 return rejected and 1 or 0
2671
2677
2672 @command(
2678 @command(
2673 'graft',
2679 'graft',
2674 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2680 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2675 ('c', 'continue', False, _('resume interrupted graft')),
2681 ('c', 'continue', False, _('resume interrupted graft')),
2676 ('e', 'edit', False, _('invoke editor on commit messages')),
2682 ('e', 'edit', False, _('invoke editor on commit messages')),
2677 ('', 'log', None, _('append graft info to log message')),
2683 ('', 'log', None, _('append graft info to log message')),
2678 ('D', 'currentdate', False,
2684 ('D', 'currentdate', False,
2679 _('record the current date as commit date')),
2685 _('record the current date as commit date')),
2680 ('U', 'currentuser', False,
2686 ('U', 'currentuser', False,
2681 _('record the current user as committer'), _('DATE'))]
2687 _('record the current user as committer'), _('DATE'))]
2682 + commitopts2 + mergetoolopts + dryrunopts,
2688 + commitopts2 + mergetoolopts + dryrunopts,
2683 _('[OPTION]... [-r] REV...'))
2689 _('[OPTION]... [-r] REV...'))
2684 def graft(ui, repo, *revs, **opts):
2690 def graft(ui, repo, *revs, **opts):
2685 '''copy changes from other branches onto the current branch
2691 '''copy changes from other branches onto the current branch
2686
2692
2687 This command uses Mercurial's merge logic to copy individual
2693 This command uses Mercurial's merge logic to copy individual
2688 changes from other branches without merging branches in the
2694 changes from other branches without merging branches in the
2689 history graph. This is sometimes known as 'backporting' or
2695 history graph. This is sometimes known as 'backporting' or
2690 'cherry-picking'. By default, graft will copy user, date, and
2696 'cherry-picking'. By default, graft will copy user, date, and
2691 description from the source changesets.
2697 description from the source changesets.
2692
2698
2693 Changesets that are ancestors of the current revision, that have
2699 Changesets that are ancestors of the current revision, that have
2694 already been grafted, or that are merges will be skipped.
2700 already been grafted, or that are merges will be skipped.
2695
2701
2696 If --log is specified, log messages will have a comment appended
2702 If --log is specified, log messages will have a comment appended
2697 of the form::
2703 of the form::
2698
2704
2699 (grafted from CHANGESETHASH)
2705 (grafted from CHANGESETHASH)
2700
2706
2701 If a graft merge results in conflicts, the graft process is
2707 If a graft merge results in conflicts, the graft process is
2702 interrupted so that the current merge can be manually resolved.
2708 interrupted so that the current merge can be manually resolved.
2703 Once all conflicts are addressed, the graft process can be
2709 Once all conflicts are addressed, the graft process can be
2704 continued with the -c/--continue option.
2710 continued with the -c/--continue option.
2705
2711
2706 .. note::
2712 .. note::
2707 The -c/--continue option does not reapply earlier options.
2713 The -c/--continue option does not reapply earlier options.
2708
2714
2709 .. container:: verbose
2715 .. container:: verbose
2710
2716
2711 Examples:
2717 Examples:
2712
2718
2713 - copy a single change to the stable branch and edit its description::
2719 - copy a single change to the stable branch and edit its description::
2714
2720
2715 hg update stable
2721 hg update stable
2716 hg graft --edit 9393
2722 hg graft --edit 9393
2717
2723
2718 - graft a range of changesets with one exception, updating dates::
2724 - graft a range of changesets with one exception, updating dates::
2719
2725
2720 hg graft -D "2085::2093 and not 2091"
2726 hg graft -D "2085::2093 and not 2091"
2721
2727
2722 - continue a graft after resolving conflicts::
2728 - continue a graft after resolving conflicts::
2723
2729
2724 hg graft -c
2730 hg graft -c
2725
2731
2726 - show the source of a grafted changeset::
2732 - show the source of a grafted changeset::
2727
2733
2728 hg log --debug -r tip
2734 hg log --debug -r tip
2729
2735
2730 Returns 0 on successful completion.
2736 Returns 0 on successful completion.
2731 '''
2737 '''
2732
2738
2733 revs = list(revs)
2739 revs = list(revs)
2734 revs.extend(opts['rev'])
2740 revs.extend(opts['rev'])
2735
2741
2736 if not opts.get('user') and opts.get('currentuser'):
2742 if not opts.get('user') and opts.get('currentuser'):
2737 opts['user'] = ui.username()
2743 opts['user'] = ui.username()
2738 if not opts.get('date') and opts.get('currentdate'):
2744 if not opts.get('date') and opts.get('currentdate'):
2739 opts['date'] = "%d %d" % util.makedate()
2745 opts['date'] = "%d %d" % util.makedate()
2740
2746
2741 editor = None
2747 editor = None
2742 if opts.get('edit'):
2748 if opts.get('edit'):
2743 editor = cmdutil.commitforceeditor
2749 editor = cmdutil.commitforceeditor
2744
2750
2745 cont = False
2751 cont = False
2746 if opts['continue']:
2752 if opts['continue']:
2747 cont = True
2753 cont = True
2748 if revs:
2754 if revs:
2749 raise util.Abort(_("can't specify --continue and revisions"))
2755 raise util.Abort(_("can't specify --continue and revisions"))
2750 # read in unfinished revisions
2756 # read in unfinished revisions
2751 try:
2757 try:
2752 nodes = repo.opener.read('graftstate').splitlines()
2758 nodes = repo.opener.read('graftstate').splitlines()
2753 revs = [repo[node].rev() for node in nodes]
2759 revs = [repo[node].rev() for node in nodes]
2754 except IOError, inst:
2760 except IOError, inst:
2755 if inst.errno != errno.ENOENT:
2761 if inst.errno != errno.ENOENT:
2756 raise
2762 raise
2757 raise util.Abort(_("no graft state found, can't continue"))
2763 raise util.Abort(_("no graft state found, can't continue"))
2758 else:
2764 else:
2759 cmdutil.bailifchanged(repo)
2765 cmdutil.bailifchanged(repo)
2760 if not revs:
2766 if not revs:
2761 raise util.Abort(_('no revisions specified'))
2767 raise util.Abort(_('no revisions specified'))
2762 revs = scmutil.revrange(repo, revs)
2768 revs = scmutil.revrange(repo, revs)
2763
2769
2764 # check for merges
2770 # check for merges
2765 for rev in repo.revs('%ld and merge()', revs):
2771 for rev in repo.revs('%ld and merge()', revs):
2766 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2772 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2767 revs.remove(rev)
2773 revs.remove(rev)
2768 if not revs:
2774 if not revs:
2769 return -1
2775 return -1
2770
2776
2771 # check for ancestors of dest branch
2777 # check for ancestors of dest branch
2772 for rev in repo.revs('::. and %ld', revs):
2778 for rev in repo.revs('::. and %ld', revs):
2773 ui.warn(_('skipping ancestor revision %s\n') % rev)
2779 ui.warn(_('skipping ancestor revision %s\n') % rev)
2774 revs.remove(rev)
2780 revs.remove(rev)
2775 if not revs:
2781 if not revs:
2776 return -1
2782 return -1
2777
2783
2778 # analyze revs for earlier grafts
2784 # analyze revs for earlier grafts
2779 ids = {}
2785 ids = {}
2780 for ctx in repo.set("%ld", revs):
2786 for ctx in repo.set("%ld", revs):
2781 ids[ctx.hex()] = ctx.rev()
2787 ids[ctx.hex()] = ctx.rev()
2782 n = ctx.extra().get('source')
2788 n = ctx.extra().get('source')
2783 if n:
2789 if n:
2784 ids[n] = ctx.rev()
2790 ids[n] = ctx.rev()
2785
2791
2786 # check ancestors for earlier grafts
2792 # check ancestors for earlier grafts
2787 ui.debug('scanning for duplicate grafts\n')
2793 ui.debug('scanning for duplicate grafts\n')
2788 for ctx in repo.set("::. - ::%ld", revs):
2794 for ctx in repo.set("::. - ::%ld", revs):
2789 n = ctx.extra().get('source')
2795 n = ctx.extra().get('source')
2790 if n in ids:
2796 if n in ids:
2791 r = repo[n].rev()
2797 r = repo[n].rev()
2792 if r in revs:
2798 if r in revs:
2793 ui.warn(_('skipping already grafted revision %s\n') % r)
2799 ui.warn(_('skipping already grafted revision %s\n') % r)
2794 revs.remove(r)
2800 revs.remove(r)
2795 elif ids[n] in revs:
2801 elif ids[n] in revs:
2796 ui.warn(_('skipping already grafted revision %s '
2802 ui.warn(_('skipping already grafted revision %s '
2797 '(same origin %d)\n') % (ids[n], r))
2803 '(same origin %d)\n') % (ids[n], r))
2798 revs.remove(ids[n])
2804 revs.remove(ids[n])
2799 elif ctx.hex() in ids:
2805 elif ctx.hex() in ids:
2800 r = ids[ctx.hex()]
2806 r = ids[ctx.hex()]
2801 ui.warn(_('skipping already grafted revision %s '
2807 ui.warn(_('skipping already grafted revision %s '
2802 '(was grafted from %d)\n') % (r, ctx.rev()))
2808 '(was grafted from %d)\n') % (r, ctx.rev()))
2803 revs.remove(r)
2809 revs.remove(r)
2804 if not revs:
2810 if not revs:
2805 return -1
2811 return -1
2806
2812
2807 wlock = repo.wlock()
2813 wlock = repo.wlock()
2808 try:
2814 try:
2809 for pos, ctx in enumerate(repo.set("%ld", revs)):
2815 for pos, ctx in enumerate(repo.set("%ld", revs)):
2810 current = repo['.']
2816 current = repo['.']
2811
2817
2812 ui.status(_('grafting revision %s\n') % ctx.rev())
2818 ui.status(_('grafting revision %s\n') % ctx.rev())
2813 if opts.get('dry_run'):
2819 if opts.get('dry_run'):
2814 continue
2820 continue
2815
2821
2816 # we don't merge the first commit when continuing
2822 # we don't merge the first commit when continuing
2817 if not cont:
2823 if not cont:
2818 # perform the graft merge with p1(rev) as 'ancestor'
2824 # perform the graft merge with p1(rev) as 'ancestor'
2819 try:
2825 try:
2820 # ui.forcemerge is an internal variable, do not document
2826 # ui.forcemerge is an internal variable, do not document
2821 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2827 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2822 stats = mergemod.update(repo, ctx.node(), True, True, False,
2828 stats = mergemod.update(repo, ctx.node(), True, True, False,
2823 ctx.p1().node())
2829 ctx.p1().node())
2824 finally:
2830 finally:
2825 repo.ui.setconfig('ui', 'forcemerge', '')
2831 repo.ui.setconfig('ui', 'forcemerge', '')
2826 # report any conflicts
2832 # report any conflicts
2827 if stats and stats[3] > 0:
2833 if stats and stats[3] > 0:
2828 # write out state for --continue
2834 # write out state for --continue
2829 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2835 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2830 repo.opener.write('graftstate', ''.join(nodelines))
2836 repo.opener.write('graftstate', ''.join(nodelines))
2831 raise util.Abort(
2837 raise util.Abort(
2832 _("unresolved conflicts, can't continue"),
2838 _("unresolved conflicts, can't continue"),
2833 hint=_('use hg resolve and hg graft --continue'))
2839 hint=_('use hg resolve and hg graft --continue'))
2834 else:
2840 else:
2835 cont = False
2841 cont = False
2836
2842
2837 # drop the second merge parent
2843 # drop the second merge parent
2838 repo.setparents(current.node(), nullid)
2844 repo.setparents(current.node(), nullid)
2839 repo.dirstate.write()
2845 repo.dirstate.write()
2840 # fix up dirstate for copies and renames
2846 # fix up dirstate for copies and renames
2841 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2847 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2842
2848
2843 # commit
2849 # commit
2844 source = ctx.extra().get('source')
2850 source = ctx.extra().get('source')
2845 if not source:
2851 if not source:
2846 source = ctx.hex()
2852 source = ctx.hex()
2847 extra = {'source': source}
2853 extra = {'source': source}
2848 user = ctx.user()
2854 user = ctx.user()
2849 if opts.get('user'):
2855 if opts.get('user'):
2850 user = opts['user']
2856 user = opts['user']
2851 date = ctx.date()
2857 date = ctx.date()
2852 if opts.get('date'):
2858 if opts.get('date'):
2853 date = opts['date']
2859 date = opts['date']
2854 message = ctx.description()
2860 message = ctx.description()
2855 if opts.get('log'):
2861 if opts.get('log'):
2856 message += '\n(grafted from %s)' % ctx.hex()
2862 message += '\n(grafted from %s)' % ctx.hex()
2857 node = repo.commit(text=message, user=user,
2863 node = repo.commit(text=message, user=user,
2858 date=date, extra=extra, editor=editor)
2864 date=date, extra=extra, editor=editor)
2859 if node is None:
2865 if node is None:
2860 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2866 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2861 finally:
2867 finally:
2862 wlock.release()
2868 wlock.release()
2863
2869
2864 # remove state when we complete successfully
2870 # remove state when we complete successfully
2865 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2871 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2866 util.unlinkpath(repo.join('graftstate'))
2872 util.unlinkpath(repo.join('graftstate'))
2867
2873
2868 return 0
2874 return 0
2869
2875
2870 @command('grep',
2876 @command('grep',
2871 [('0', 'print0', None, _('end fields with NUL')),
2877 [('0', 'print0', None, _('end fields with NUL')),
2872 ('', 'all', None, _('print all revisions that match')),
2878 ('', 'all', None, _('print all revisions that match')),
2873 ('a', 'text', None, _('treat all files as text')),
2879 ('a', 'text', None, _('treat all files as text')),
2874 ('f', 'follow', None,
2880 ('f', 'follow', None,
2875 _('follow changeset history,'
2881 _('follow changeset history,'
2876 ' or file history across copies and renames')),
2882 ' or file history across copies and renames')),
2877 ('i', 'ignore-case', None, _('ignore case when matching')),
2883 ('i', 'ignore-case', None, _('ignore case when matching')),
2878 ('l', 'files-with-matches', None,
2884 ('l', 'files-with-matches', None,
2879 _('print only filenames and revisions that match')),
2885 _('print only filenames and revisions that match')),
2880 ('n', 'line-number', None, _('print matching line numbers')),
2886 ('n', 'line-number', None, _('print matching line numbers')),
2881 ('r', 'rev', [],
2887 ('r', 'rev', [],
2882 _('only search files changed within revision range'), _('REV')),
2888 _('only search files changed within revision range'), _('REV')),
2883 ('u', 'user', None, _('list the author (long with -v)')),
2889 ('u', 'user', None, _('list the author (long with -v)')),
2884 ('d', 'date', None, _('list the date (short with -q)')),
2890 ('d', 'date', None, _('list the date (short with -q)')),
2885 ] + walkopts,
2891 ] + walkopts,
2886 _('[OPTION]... PATTERN [FILE]...'))
2892 _('[OPTION]... PATTERN [FILE]...'))
2887 def grep(ui, repo, pattern, *pats, **opts):
2893 def grep(ui, repo, pattern, *pats, **opts):
2888 """search for a pattern in specified files and revisions
2894 """search for a pattern in specified files and revisions
2889
2895
2890 Search revisions of files for a regular expression.
2896 Search revisions of files for a regular expression.
2891
2897
2892 This command behaves differently than Unix grep. It only accepts
2898 This command behaves differently than Unix grep. It only accepts
2893 Python/Perl regexps. It searches repository history, not the
2899 Python/Perl regexps. It searches repository history, not the
2894 working directory. It always prints the revision number in which a
2900 working directory. It always prints the revision number in which a
2895 match appears.
2901 match appears.
2896
2902
2897 By default, grep only prints output for the first revision of a
2903 By default, grep only prints output for the first revision of a
2898 file in which it finds a match. To get it to print every revision
2904 file in which it finds a match. To get it to print every revision
2899 that contains a change in match status ("-" for a match that
2905 that contains a change in match status ("-" for a match that
2900 becomes a non-match, or "+" for a non-match that becomes a match),
2906 becomes a non-match, or "+" for a non-match that becomes a match),
2901 use the --all flag.
2907 use the --all flag.
2902
2908
2903 Returns 0 if a match is found, 1 otherwise.
2909 Returns 0 if a match is found, 1 otherwise.
2904 """
2910 """
2905 reflags = re.M
2911 reflags = re.M
2906 if opts.get('ignore_case'):
2912 if opts.get('ignore_case'):
2907 reflags |= re.I
2913 reflags |= re.I
2908 try:
2914 try:
2909 regexp = re.compile(pattern, reflags)
2915 regexp = re.compile(pattern, reflags)
2910 except re.error, inst:
2916 except re.error, inst:
2911 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2917 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2912 return 1
2918 return 1
2913 sep, eol = ':', '\n'
2919 sep, eol = ':', '\n'
2914 if opts.get('print0'):
2920 if opts.get('print0'):
2915 sep = eol = '\0'
2921 sep = eol = '\0'
2916
2922
2917 getfile = util.lrucachefunc(repo.file)
2923 getfile = util.lrucachefunc(repo.file)
2918
2924
2919 def matchlines(body):
2925 def matchlines(body):
2920 begin = 0
2926 begin = 0
2921 linenum = 0
2927 linenum = 0
2922 while True:
2928 while True:
2923 match = regexp.search(body, begin)
2929 match = regexp.search(body, begin)
2924 if not match:
2930 if not match:
2925 break
2931 break
2926 mstart, mend = match.span()
2932 mstart, mend = match.span()
2927 linenum += body.count('\n', begin, mstart) + 1
2933 linenum += body.count('\n', begin, mstart) + 1
2928 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2934 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2929 begin = body.find('\n', mend) + 1 or len(body) + 1
2935 begin = body.find('\n', mend) + 1 or len(body) + 1
2930 lend = begin - 1
2936 lend = begin - 1
2931 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2937 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2932
2938
2933 class linestate(object):
2939 class linestate(object):
2934 def __init__(self, line, linenum, colstart, colend):
2940 def __init__(self, line, linenum, colstart, colend):
2935 self.line = line
2941 self.line = line
2936 self.linenum = linenum
2942 self.linenum = linenum
2937 self.colstart = colstart
2943 self.colstart = colstart
2938 self.colend = colend
2944 self.colend = colend
2939
2945
2940 def __hash__(self):
2946 def __hash__(self):
2941 return hash((self.linenum, self.line))
2947 return hash((self.linenum, self.line))
2942
2948
2943 def __eq__(self, other):
2949 def __eq__(self, other):
2944 return self.line == other.line
2950 return self.line == other.line
2945
2951
2946 matches = {}
2952 matches = {}
2947 copies = {}
2953 copies = {}
2948 def grepbody(fn, rev, body):
2954 def grepbody(fn, rev, body):
2949 matches[rev].setdefault(fn, [])
2955 matches[rev].setdefault(fn, [])
2950 m = matches[rev][fn]
2956 m = matches[rev][fn]
2951 for lnum, cstart, cend, line in matchlines(body):
2957 for lnum, cstart, cend, line in matchlines(body):
2952 s = linestate(line, lnum, cstart, cend)
2958 s = linestate(line, lnum, cstart, cend)
2953 m.append(s)
2959 m.append(s)
2954
2960
2955 def difflinestates(a, b):
2961 def difflinestates(a, b):
2956 sm = difflib.SequenceMatcher(None, a, b)
2962 sm = difflib.SequenceMatcher(None, a, b)
2957 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2963 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2958 if tag == 'insert':
2964 if tag == 'insert':
2959 for i in xrange(blo, bhi):
2965 for i in xrange(blo, bhi):
2960 yield ('+', b[i])
2966 yield ('+', b[i])
2961 elif tag == 'delete':
2967 elif tag == 'delete':
2962 for i in xrange(alo, ahi):
2968 for i in xrange(alo, ahi):
2963 yield ('-', a[i])
2969 yield ('-', a[i])
2964 elif tag == 'replace':
2970 elif tag == 'replace':
2965 for i in xrange(alo, ahi):
2971 for i in xrange(alo, ahi):
2966 yield ('-', a[i])
2972 yield ('-', a[i])
2967 for i in xrange(blo, bhi):
2973 for i in xrange(blo, bhi):
2968 yield ('+', b[i])
2974 yield ('+', b[i])
2969
2975
2970 def display(fn, ctx, pstates, states):
2976 def display(fn, ctx, pstates, states):
2971 rev = ctx.rev()
2977 rev = ctx.rev()
2972 datefunc = ui.quiet and util.shortdate or util.datestr
2978 datefunc = ui.quiet and util.shortdate or util.datestr
2973 found = False
2979 found = False
2974 filerevmatches = {}
2980 filerevmatches = {}
2975 def binary():
2981 def binary():
2976 flog = getfile(fn)
2982 flog = getfile(fn)
2977 return util.binary(flog.read(ctx.filenode(fn)))
2983 return util.binary(flog.read(ctx.filenode(fn)))
2978
2984
2979 if opts.get('all'):
2985 if opts.get('all'):
2980 iter = difflinestates(pstates, states)
2986 iter = difflinestates(pstates, states)
2981 else:
2987 else:
2982 iter = [('', l) for l in states]
2988 iter = [('', l) for l in states]
2983 for change, l in iter:
2989 for change, l in iter:
2984 cols = [fn, str(rev)]
2990 cols = [fn, str(rev)]
2985 before, match, after = None, None, None
2991 before, match, after = None, None, None
2986 if opts.get('line_number'):
2992 if opts.get('line_number'):
2987 cols.append(str(l.linenum))
2993 cols.append(str(l.linenum))
2988 if opts.get('all'):
2994 if opts.get('all'):
2989 cols.append(change)
2995 cols.append(change)
2990 if opts.get('user'):
2996 if opts.get('user'):
2991 cols.append(ui.shortuser(ctx.user()))
2997 cols.append(ui.shortuser(ctx.user()))
2992 if opts.get('date'):
2998 if opts.get('date'):
2993 cols.append(datefunc(ctx.date()))
2999 cols.append(datefunc(ctx.date()))
2994 if opts.get('files_with_matches'):
3000 if opts.get('files_with_matches'):
2995 c = (fn, rev)
3001 c = (fn, rev)
2996 if c in filerevmatches:
3002 if c in filerevmatches:
2997 continue
3003 continue
2998 filerevmatches[c] = 1
3004 filerevmatches[c] = 1
2999 else:
3005 else:
3000 before = l.line[:l.colstart]
3006 before = l.line[:l.colstart]
3001 match = l.line[l.colstart:l.colend]
3007 match = l.line[l.colstart:l.colend]
3002 after = l.line[l.colend:]
3008 after = l.line[l.colend:]
3003 ui.write(sep.join(cols))
3009 ui.write(sep.join(cols))
3004 if before is not None:
3010 if before is not None:
3005 if not opts.get('text') and binary():
3011 if not opts.get('text') and binary():
3006 ui.write(sep + " Binary file matches")
3012 ui.write(sep + " Binary file matches")
3007 else:
3013 else:
3008 ui.write(sep + before)
3014 ui.write(sep + before)
3009 ui.write(match, label='grep.match')
3015 ui.write(match, label='grep.match')
3010 ui.write(after)
3016 ui.write(after)
3011 ui.write(eol)
3017 ui.write(eol)
3012 found = True
3018 found = True
3013 return found
3019 return found
3014
3020
3015 skip = {}
3021 skip = {}
3016 revfiles = {}
3022 revfiles = {}
3017 matchfn = scmutil.match(repo[None], pats, opts)
3023 matchfn = scmutil.match(repo[None], pats, opts)
3018 found = False
3024 found = False
3019 follow = opts.get('follow')
3025 follow = opts.get('follow')
3020
3026
3021 def prep(ctx, fns):
3027 def prep(ctx, fns):
3022 rev = ctx.rev()
3028 rev = ctx.rev()
3023 pctx = ctx.p1()
3029 pctx = ctx.p1()
3024 parent = pctx.rev()
3030 parent = pctx.rev()
3025 matches.setdefault(rev, {})
3031 matches.setdefault(rev, {})
3026 matches.setdefault(parent, {})
3032 matches.setdefault(parent, {})
3027 files = revfiles.setdefault(rev, [])
3033 files = revfiles.setdefault(rev, [])
3028 for fn in fns:
3034 for fn in fns:
3029 flog = getfile(fn)
3035 flog = getfile(fn)
3030 try:
3036 try:
3031 fnode = ctx.filenode(fn)
3037 fnode = ctx.filenode(fn)
3032 except error.LookupError:
3038 except error.LookupError:
3033 continue
3039 continue
3034
3040
3035 copied = flog.renamed(fnode)
3041 copied = flog.renamed(fnode)
3036 copy = follow and copied and copied[0]
3042 copy = follow and copied and copied[0]
3037 if copy:
3043 if copy:
3038 copies.setdefault(rev, {})[fn] = copy
3044 copies.setdefault(rev, {})[fn] = copy
3039 if fn in skip:
3045 if fn in skip:
3040 if copy:
3046 if copy:
3041 skip[copy] = True
3047 skip[copy] = True
3042 continue
3048 continue
3043 files.append(fn)
3049 files.append(fn)
3044
3050
3045 if fn not in matches[rev]:
3051 if fn not in matches[rev]:
3046 grepbody(fn, rev, flog.read(fnode))
3052 grepbody(fn, rev, flog.read(fnode))
3047
3053
3048 pfn = copy or fn
3054 pfn = copy or fn
3049 if pfn not in matches[parent]:
3055 if pfn not in matches[parent]:
3050 try:
3056 try:
3051 fnode = pctx.filenode(pfn)
3057 fnode = pctx.filenode(pfn)
3052 grepbody(pfn, parent, flog.read(fnode))
3058 grepbody(pfn, parent, flog.read(fnode))
3053 except error.LookupError:
3059 except error.LookupError:
3054 pass
3060 pass
3055
3061
3056 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3062 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3057 rev = ctx.rev()
3063 rev = ctx.rev()
3058 parent = ctx.p1().rev()
3064 parent = ctx.p1().rev()
3059 for fn in sorted(revfiles.get(rev, [])):
3065 for fn in sorted(revfiles.get(rev, [])):
3060 states = matches[rev][fn]
3066 states = matches[rev][fn]
3061 copy = copies.get(rev, {}).get(fn)
3067 copy = copies.get(rev, {}).get(fn)
3062 if fn in skip:
3068 if fn in skip:
3063 if copy:
3069 if copy:
3064 skip[copy] = True
3070 skip[copy] = True
3065 continue
3071 continue
3066 pstates = matches.get(parent, {}).get(copy or fn, [])
3072 pstates = matches.get(parent, {}).get(copy or fn, [])
3067 if pstates or states:
3073 if pstates or states:
3068 r = display(fn, ctx, pstates, states)
3074 r = display(fn, ctx, pstates, states)
3069 found = found or r
3075 found = found or r
3070 if r and not opts.get('all'):
3076 if r and not opts.get('all'):
3071 skip[fn] = True
3077 skip[fn] = True
3072 if copy:
3078 if copy:
3073 skip[copy] = True
3079 skip[copy] = True
3074 del matches[rev]
3080 del matches[rev]
3075 del revfiles[rev]
3081 del revfiles[rev]
3076
3082
3077 return not found
3083 return not found
3078
3084
3079 @command('heads',
3085 @command('heads',
3080 [('r', 'rev', '',
3086 [('r', 'rev', '',
3081 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3087 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3082 ('t', 'topo', False, _('show topological heads only')),
3088 ('t', 'topo', False, _('show topological heads only')),
3083 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3089 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3084 ('c', 'closed', False, _('show normal and closed branch heads')),
3090 ('c', 'closed', False, _('show normal and closed branch heads')),
3085 ] + templateopts,
3091 ] + templateopts,
3086 _('[-ct] [-r STARTREV] [REV]...'))
3092 _('[-ct] [-r STARTREV] [REV]...'))
3087 def heads(ui, repo, *branchrevs, **opts):
3093 def heads(ui, repo, *branchrevs, **opts):
3088 """show current repository heads or show branch heads
3094 """show current repository heads or show branch heads
3089
3095
3090 With no arguments, show all repository branch heads.
3096 With no arguments, show all repository branch heads.
3091
3097
3092 Repository "heads" are changesets with no child changesets. They are
3098 Repository "heads" are changesets with no child changesets. They are
3093 where development generally takes place and are the usual targets
3099 where development generally takes place and are the usual targets
3094 for update and merge operations. Branch heads are changesets that have
3100 for update and merge operations. Branch heads are changesets that have
3095 no child changeset on the same branch.
3101 no child changeset on the same branch.
3096
3102
3097 If one or more REVs are given, only branch heads on the branches
3103 If one or more REVs are given, only branch heads on the branches
3098 associated with the specified changesets are shown. This means
3104 associated with the specified changesets are shown. This means
3099 that you can use :hg:`heads foo` to see the heads on a branch
3105 that you can use :hg:`heads foo` to see the heads on a branch
3100 named ``foo``.
3106 named ``foo``.
3101
3107
3102 If -c/--closed is specified, also show branch heads marked closed
3108 If -c/--closed is specified, also show branch heads marked closed
3103 (see :hg:`commit --close-branch`).
3109 (see :hg:`commit --close-branch`).
3104
3110
3105 If STARTREV is specified, only those heads that are descendants of
3111 If STARTREV is specified, only those heads that are descendants of
3106 STARTREV will be displayed.
3112 STARTREV will be displayed.
3107
3113
3108 If -t/--topo is specified, named branch mechanics will be ignored and only
3114 If -t/--topo is specified, named branch mechanics will be ignored and only
3109 changesets without children will be shown.
3115 changesets without children will be shown.
3110
3116
3111 Returns 0 if matching heads are found, 1 if not.
3117 Returns 0 if matching heads are found, 1 if not.
3112 """
3118 """
3113
3119
3114 start = None
3120 start = None
3115 if 'rev' in opts:
3121 if 'rev' in opts:
3116 start = scmutil.revsingle(repo, opts['rev'], None).node()
3122 start = scmutil.revsingle(repo, opts['rev'], None).node()
3117
3123
3118 if opts.get('topo'):
3124 if opts.get('topo'):
3119 heads = [repo[h] for h in repo.heads(start)]
3125 heads = [repo[h] for h in repo.heads(start)]
3120 else:
3126 else:
3121 heads = []
3127 heads = []
3122 for branch in repo.branchmap():
3128 for branch in repo.branchmap():
3123 heads += repo.branchheads(branch, start, opts.get('closed'))
3129 heads += repo.branchheads(branch, start, opts.get('closed'))
3124 heads = [repo[h] for h in heads]
3130 heads = [repo[h] for h in heads]
3125
3131
3126 if branchrevs:
3132 if branchrevs:
3127 branches = set(repo[br].branch() for br in branchrevs)
3133 branches = set(repo[br].branch() for br in branchrevs)
3128 heads = [h for h in heads if h.branch() in branches]
3134 heads = [h for h in heads if h.branch() in branches]
3129
3135
3130 if opts.get('active') and branchrevs:
3136 if opts.get('active') and branchrevs:
3131 dagheads = repo.heads(start)
3137 dagheads = repo.heads(start)
3132 heads = [h for h in heads if h.node() in dagheads]
3138 heads = [h for h in heads if h.node() in dagheads]
3133
3139
3134 if branchrevs:
3140 if branchrevs:
3135 haveheads = set(h.branch() for h in heads)
3141 haveheads = set(h.branch() for h in heads)
3136 if branches - haveheads:
3142 if branches - haveheads:
3137 headless = ', '.join(b for b in branches - haveheads)
3143 headless = ', '.join(b for b in branches - haveheads)
3138 msg = _('no open branch heads found on branches %s')
3144 msg = _('no open branch heads found on branches %s')
3139 if opts.get('rev'):
3145 if opts.get('rev'):
3140 msg += _(' (started at %s)') % opts['rev']
3146 msg += _(' (started at %s)') % opts['rev']
3141 ui.warn((msg + '\n') % headless)
3147 ui.warn((msg + '\n') % headless)
3142
3148
3143 if not heads:
3149 if not heads:
3144 return 1
3150 return 1
3145
3151
3146 heads = sorted(heads, key=lambda x: -x.rev())
3152 heads = sorted(heads, key=lambda x: -x.rev())
3147 displayer = cmdutil.show_changeset(ui, repo, opts)
3153 displayer = cmdutil.show_changeset(ui, repo, opts)
3148 for ctx in heads:
3154 for ctx in heads:
3149 displayer.show(ctx)
3155 displayer.show(ctx)
3150 displayer.close()
3156 displayer.close()
3151
3157
3152 @command('help',
3158 @command('help',
3153 [('e', 'extension', None, _('show only help for extensions')),
3159 [('e', 'extension', None, _('show only help for extensions')),
3154 ('c', 'command', None, _('show only help for commands')),
3160 ('c', 'command', None, _('show only help for commands')),
3155 ('k', 'keyword', '', _('show topics matching keyword')),
3161 ('k', 'keyword', '', _('show topics matching keyword')),
3156 ],
3162 ],
3157 _('[-ec] [TOPIC]'))
3163 _('[-ec] [TOPIC]'))
3158 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3164 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3159 """show help for a given topic or a help overview
3165 """show help for a given topic or a help overview
3160
3166
3161 With no arguments, print a list of commands with short help messages.
3167 With no arguments, print a list of commands with short help messages.
3162
3168
3163 Given a topic, extension, or command name, print help for that
3169 Given a topic, extension, or command name, print help for that
3164 topic.
3170 topic.
3165
3171
3166 Returns 0 if successful.
3172 Returns 0 if successful.
3167 """
3173 """
3168
3174
3169 textwidth = min(ui.termwidth(), 80) - 2
3175 textwidth = min(ui.termwidth(), 80) - 2
3170
3176
3171 def helpcmd(name):
3177 def helpcmd(name):
3172 try:
3178 try:
3173 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3179 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3174 except error.AmbiguousCommand, inst:
3180 except error.AmbiguousCommand, inst:
3175 # py3k fix: except vars can't be used outside the scope of the
3181 # py3k fix: except vars can't be used outside the scope of the
3176 # except block, nor can be used inside a lambda. python issue4617
3182 # except block, nor can be used inside a lambda. python issue4617
3177 prefix = inst.args[0]
3183 prefix = inst.args[0]
3178 select = lambda c: c.lstrip('^').startswith(prefix)
3184 select = lambda c: c.lstrip('^').startswith(prefix)
3179 rst = helplist(select)
3185 rst = helplist(select)
3180 return rst
3186 return rst
3181
3187
3182 rst = []
3188 rst = []
3183
3189
3184 # check if it's an invalid alias and display its error if it is
3190 # check if it's an invalid alias and display its error if it is
3185 if getattr(entry[0], 'badalias', False):
3191 if getattr(entry[0], 'badalias', False):
3186 if not unknowncmd:
3192 if not unknowncmd:
3187 ui.pushbuffer()
3193 ui.pushbuffer()
3188 entry[0](ui)
3194 entry[0](ui)
3189 rst.append(ui.popbuffer())
3195 rst.append(ui.popbuffer())
3190 return rst
3196 return rst
3191
3197
3192 # synopsis
3198 # synopsis
3193 if len(entry) > 2:
3199 if len(entry) > 2:
3194 if entry[2].startswith('hg'):
3200 if entry[2].startswith('hg'):
3195 rst.append("%s\n" % entry[2])
3201 rst.append("%s\n" % entry[2])
3196 else:
3202 else:
3197 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3203 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3198 else:
3204 else:
3199 rst.append('hg %s\n' % aliases[0])
3205 rst.append('hg %s\n' % aliases[0])
3200 # aliases
3206 # aliases
3201 if full and not ui.quiet and len(aliases) > 1:
3207 if full and not ui.quiet and len(aliases) > 1:
3202 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3208 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3203 rst.append('\n')
3209 rst.append('\n')
3204
3210
3205 # description
3211 # description
3206 doc = gettext(entry[0].__doc__)
3212 doc = gettext(entry[0].__doc__)
3207 if not doc:
3213 if not doc:
3208 doc = _("(no help text available)")
3214 doc = _("(no help text available)")
3209 if util.safehasattr(entry[0], 'definition'): # aliased command
3215 if util.safehasattr(entry[0], 'definition'): # aliased command
3210 if entry[0].definition.startswith('!'): # shell alias
3216 if entry[0].definition.startswith('!'): # shell alias
3211 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3217 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3212 else:
3218 else:
3213 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3219 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3214 doc = doc.splitlines(True)
3220 doc = doc.splitlines(True)
3215 if ui.quiet or not full:
3221 if ui.quiet or not full:
3216 rst.append(doc[0])
3222 rst.append(doc[0])
3217 else:
3223 else:
3218 rst.extend(doc)
3224 rst.extend(doc)
3219 rst.append('\n')
3225 rst.append('\n')
3220
3226
3221 # check if this command shadows a non-trivial (multi-line)
3227 # check if this command shadows a non-trivial (multi-line)
3222 # extension help text
3228 # extension help text
3223 try:
3229 try:
3224 mod = extensions.find(name)
3230 mod = extensions.find(name)
3225 doc = gettext(mod.__doc__) or ''
3231 doc = gettext(mod.__doc__) or ''
3226 if '\n' in doc.strip():
3232 if '\n' in doc.strip():
3227 msg = _('use "hg help -e %s" to show help for '
3233 msg = _('use "hg help -e %s" to show help for '
3228 'the %s extension') % (name, name)
3234 'the %s extension') % (name, name)
3229 rst.append('\n%s\n' % msg)
3235 rst.append('\n%s\n' % msg)
3230 except KeyError:
3236 except KeyError:
3231 pass
3237 pass
3232
3238
3233 # options
3239 # options
3234 if not ui.quiet and entry[1]:
3240 if not ui.quiet and entry[1]:
3235 rst.append('\n%s\n\n' % _("options:"))
3241 rst.append('\n%s\n\n' % _("options:"))
3236 rst.append(help.optrst(entry[1], ui.verbose))
3242 rst.append(help.optrst(entry[1], ui.verbose))
3237
3243
3238 if ui.verbose:
3244 if ui.verbose:
3239 rst.append('\n%s\n\n' % _("global options:"))
3245 rst.append('\n%s\n\n' % _("global options:"))
3240 rst.append(help.optrst(globalopts, ui.verbose))
3246 rst.append(help.optrst(globalopts, ui.verbose))
3241
3247
3242 if not ui.verbose:
3248 if not ui.verbose:
3243 if not full:
3249 if not full:
3244 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3250 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3245 % name)
3251 % name)
3246 elif not ui.quiet:
3252 elif not ui.quiet:
3247 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3253 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3248 % name)
3254 % name)
3249 return rst
3255 return rst
3250
3256
3251
3257
3252 def helplist(select=None):
3258 def helplist(select=None):
3253 # list of commands
3259 # list of commands
3254 if name == "shortlist":
3260 if name == "shortlist":
3255 header = _('basic commands:\n\n')
3261 header = _('basic commands:\n\n')
3256 else:
3262 else:
3257 header = _('list of commands:\n\n')
3263 header = _('list of commands:\n\n')
3258
3264
3259 h = {}
3265 h = {}
3260 cmds = {}
3266 cmds = {}
3261 for c, e in table.iteritems():
3267 for c, e in table.iteritems():
3262 f = c.split("|", 1)[0]
3268 f = c.split("|", 1)[0]
3263 if select and not select(f):
3269 if select and not select(f):
3264 continue
3270 continue
3265 if (not select and name != 'shortlist' and
3271 if (not select and name != 'shortlist' and
3266 e[0].__module__ != __name__):
3272 e[0].__module__ != __name__):
3267 continue
3273 continue
3268 if name == "shortlist" and not f.startswith("^"):
3274 if name == "shortlist" and not f.startswith("^"):
3269 continue
3275 continue
3270 f = f.lstrip("^")
3276 f = f.lstrip("^")
3271 if not ui.debugflag and f.startswith("debug"):
3277 if not ui.debugflag and f.startswith("debug"):
3272 continue
3278 continue
3273 doc = e[0].__doc__
3279 doc = e[0].__doc__
3274 if doc and 'DEPRECATED' in doc and not ui.verbose:
3280 if doc and 'DEPRECATED' in doc and not ui.verbose:
3275 continue
3281 continue
3276 doc = gettext(doc)
3282 doc = gettext(doc)
3277 if not doc:
3283 if not doc:
3278 doc = _("(no help text available)")
3284 doc = _("(no help text available)")
3279 h[f] = doc.splitlines()[0].rstrip()
3285 h[f] = doc.splitlines()[0].rstrip()
3280 cmds[f] = c.lstrip("^")
3286 cmds[f] = c.lstrip("^")
3281
3287
3282 rst = []
3288 rst = []
3283 if not h:
3289 if not h:
3284 if not ui.quiet:
3290 if not ui.quiet:
3285 rst.append(_('no commands defined\n'))
3291 rst.append(_('no commands defined\n'))
3286 return rst
3292 return rst
3287
3293
3288 if not ui.quiet:
3294 if not ui.quiet:
3289 rst.append(header)
3295 rst.append(header)
3290 fns = sorted(h)
3296 fns = sorted(h)
3291 for f in fns:
3297 for f in fns:
3292 if ui.verbose:
3298 if ui.verbose:
3293 commands = cmds[f].replace("|",", ")
3299 commands = cmds[f].replace("|",", ")
3294 rst.append(" :%s: %s\n" % (commands, h[f]))
3300 rst.append(" :%s: %s\n" % (commands, h[f]))
3295 else:
3301 else:
3296 rst.append(' :%s: %s\n' % (f, h[f]))
3302 rst.append(' :%s: %s\n' % (f, h[f]))
3297
3303
3298 if not name:
3304 if not name:
3299 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3305 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3300 if exts:
3306 if exts:
3301 rst.append('\n')
3307 rst.append('\n')
3302 rst.extend(exts)
3308 rst.extend(exts)
3303
3309
3304 rst.append(_("\nadditional help topics:\n\n"))
3310 rst.append(_("\nadditional help topics:\n\n"))
3305 topics = []
3311 topics = []
3306 for names, header, doc in help.helptable:
3312 for names, header, doc in help.helptable:
3307 topics.append((names[0], header))
3313 topics.append((names[0], header))
3308 for t, desc in topics:
3314 for t, desc in topics:
3309 rst.append(" :%s: %s\n" % (t, desc))
3315 rst.append(" :%s: %s\n" % (t, desc))
3310
3316
3311 optlist = []
3317 optlist = []
3312 if not ui.quiet:
3318 if not ui.quiet:
3313 if ui.verbose:
3319 if ui.verbose:
3314 optlist.append((_("global options:"), globalopts))
3320 optlist.append((_("global options:"), globalopts))
3315 if name == 'shortlist':
3321 if name == 'shortlist':
3316 optlist.append((_('use "hg help" for the full list '
3322 optlist.append((_('use "hg help" for the full list '
3317 'of commands'), ()))
3323 'of commands'), ()))
3318 else:
3324 else:
3319 if name == 'shortlist':
3325 if name == 'shortlist':
3320 msg = _('use "hg help" for the full list of commands '
3326 msg = _('use "hg help" for the full list of commands '
3321 'or "hg -v" for details')
3327 'or "hg -v" for details')
3322 elif name and not full:
3328 elif name and not full:
3323 msg = _('use "hg help %s" to show the full help '
3329 msg = _('use "hg help %s" to show the full help '
3324 'text') % name
3330 'text') % name
3325 else:
3331 else:
3326 msg = _('use "hg -v help%s" to show builtin aliases and '
3332 msg = _('use "hg -v help%s" to show builtin aliases and '
3327 'global options') % (name and " " + name or "")
3333 'global options') % (name and " " + name or "")
3328 optlist.append((msg, ()))
3334 optlist.append((msg, ()))
3329
3335
3330 if optlist:
3336 if optlist:
3331 for title, options in optlist:
3337 for title, options in optlist:
3332 rst.append('\n%s\n' % title)
3338 rst.append('\n%s\n' % title)
3333 if options:
3339 if options:
3334 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3340 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3335 return rst
3341 return rst
3336
3342
3337 def helptopic(name):
3343 def helptopic(name):
3338 for names, header, doc in help.helptable:
3344 for names, header, doc in help.helptable:
3339 if name in names:
3345 if name in names:
3340 break
3346 break
3341 else:
3347 else:
3342 raise error.UnknownCommand(name)
3348 raise error.UnknownCommand(name)
3343
3349
3344 rst = ["%s\n\n" % header]
3350 rst = ["%s\n\n" % header]
3345 # description
3351 # description
3346 if not doc:
3352 if not doc:
3347 rst.append(" %s\n" % _("(no help text available)"))
3353 rst.append(" %s\n" % _("(no help text available)"))
3348 if util.safehasattr(doc, '__call__'):
3354 if util.safehasattr(doc, '__call__'):
3349 rst += [" %s\n" % l for l in doc().splitlines()]
3355 rst += [" %s\n" % l for l in doc().splitlines()]
3350
3356
3351 try:
3357 try:
3352 cmdutil.findcmd(name, table)
3358 cmdutil.findcmd(name, table)
3353 rst.append(_('\nuse "hg help -c %s" to see help for '
3359 rst.append(_('\nuse "hg help -c %s" to see help for '
3354 'the %s command\n') % (name, name))
3360 'the %s command\n') % (name, name))
3355 except error.UnknownCommand:
3361 except error.UnknownCommand:
3356 pass
3362 pass
3357 return rst
3363 return rst
3358
3364
3359 def helpext(name):
3365 def helpext(name):
3360 try:
3366 try:
3361 mod = extensions.find(name)
3367 mod = extensions.find(name)
3362 doc = gettext(mod.__doc__) or _('no help text available')
3368 doc = gettext(mod.__doc__) or _('no help text available')
3363 except KeyError:
3369 except KeyError:
3364 mod = None
3370 mod = None
3365 doc = extensions.disabledext(name)
3371 doc = extensions.disabledext(name)
3366 if not doc:
3372 if not doc:
3367 raise error.UnknownCommand(name)
3373 raise error.UnknownCommand(name)
3368
3374
3369 if '\n' not in doc:
3375 if '\n' not in doc:
3370 head, tail = doc, ""
3376 head, tail = doc, ""
3371 else:
3377 else:
3372 head, tail = doc.split('\n', 1)
3378 head, tail = doc.split('\n', 1)
3373 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3379 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3374 if tail:
3380 if tail:
3375 rst.extend(tail.splitlines(True))
3381 rst.extend(tail.splitlines(True))
3376 rst.append('\n')
3382 rst.append('\n')
3377
3383
3378 if mod:
3384 if mod:
3379 try:
3385 try:
3380 ct = mod.cmdtable
3386 ct = mod.cmdtable
3381 except AttributeError:
3387 except AttributeError:
3382 ct = {}
3388 ct = {}
3383 modcmds = set([c.split('|', 1)[0] for c in ct])
3389 modcmds = set([c.split('|', 1)[0] for c in ct])
3384 rst.extend(helplist(modcmds.__contains__))
3390 rst.extend(helplist(modcmds.__contains__))
3385 else:
3391 else:
3386 rst.append(_('use "hg help extensions" for information on enabling '
3392 rst.append(_('use "hg help extensions" for information on enabling '
3387 'extensions\n'))
3393 'extensions\n'))
3388 return rst
3394 return rst
3389
3395
3390 def helpextcmd(name):
3396 def helpextcmd(name):
3391 cmd, ext, mod = extensions.disabledcmd(ui, name,
3397 cmd, ext, mod = extensions.disabledcmd(ui, name,
3392 ui.configbool('ui', 'strict'))
3398 ui.configbool('ui', 'strict'))
3393 doc = gettext(mod.__doc__).splitlines()[0]
3399 doc = gettext(mod.__doc__).splitlines()[0]
3394
3400
3395 rst = help.listexts(_("'%s' is provided by the following "
3401 rst = help.listexts(_("'%s' is provided by the following "
3396 "extension:") % cmd, {ext: doc}, indent=4)
3402 "extension:") % cmd, {ext: doc}, indent=4)
3397 rst.append('\n')
3403 rst.append('\n')
3398 rst.append(_('use "hg help extensions" for information on enabling '
3404 rst.append(_('use "hg help extensions" for information on enabling '
3399 'extensions\n'))
3405 'extensions\n'))
3400 return rst
3406 return rst
3401
3407
3402
3408
3403 rst = []
3409 rst = []
3404 kw = opts.get('keyword')
3410 kw = opts.get('keyword')
3405 if kw:
3411 if kw:
3406 matches = help.topicmatch(kw)
3412 matches = help.topicmatch(kw)
3407 for t, title in (('topics', _('Topics')),
3413 for t, title in (('topics', _('Topics')),
3408 ('commands', _('Commands')),
3414 ('commands', _('Commands')),
3409 ('extensions', _('Extensions')),
3415 ('extensions', _('Extensions')),
3410 ('extensioncommands', _('Extension Commands'))):
3416 ('extensioncommands', _('Extension Commands'))):
3411 if matches[t]:
3417 if matches[t]:
3412 rst.append('%s:\n\n' % title)
3418 rst.append('%s:\n\n' % title)
3413 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3419 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3414 rst.append('\n')
3420 rst.append('\n')
3415 elif name and name != 'shortlist':
3421 elif name and name != 'shortlist':
3416 i = None
3422 i = None
3417 if unknowncmd:
3423 if unknowncmd:
3418 queries = (helpextcmd,)
3424 queries = (helpextcmd,)
3419 elif opts.get('extension'):
3425 elif opts.get('extension'):
3420 queries = (helpext,)
3426 queries = (helpext,)
3421 elif opts.get('command'):
3427 elif opts.get('command'):
3422 queries = (helpcmd,)
3428 queries = (helpcmd,)
3423 else:
3429 else:
3424 queries = (helptopic, helpcmd, helpext, helpextcmd)
3430 queries = (helptopic, helpcmd, helpext, helpextcmd)
3425 for f in queries:
3431 for f in queries:
3426 try:
3432 try:
3427 rst = f(name)
3433 rst = f(name)
3428 i = None
3434 i = None
3429 break
3435 break
3430 except error.UnknownCommand, inst:
3436 except error.UnknownCommand, inst:
3431 i = inst
3437 i = inst
3432 if i:
3438 if i:
3433 raise i
3439 raise i
3434 else:
3440 else:
3435 # program name
3441 # program name
3436 if not ui.quiet:
3442 if not ui.quiet:
3437 rst = [_("Mercurial Distributed SCM\n"), '\n']
3443 rst = [_("Mercurial Distributed SCM\n"), '\n']
3438 rst.extend(helplist())
3444 rst.extend(helplist())
3439
3445
3440 keep = ui.verbose and ['verbose'] or []
3446 keep = ui.verbose and ['verbose'] or []
3441 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3447 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3442 ui.write(formatted)
3448 ui.write(formatted)
3443
3449
3444
3450
3445 @command('identify|id',
3451 @command('identify|id',
3446 [('r', 'rev', '',
3452 [('r', 'rev', '',
3447 _('identify the specified revision'), _('REV')),
3453 _('identify the specified revision'), _('REV')),
3448 ('n', 'num', None, _('show local revision number')),
3454 ('n', 'num', None, _('show local revision number')),
3449 ('i', 'id', None, _('show global revision id')),
3455 ('i', 'id', None, _('show global revision id')),
3450 ('b', 'branch', None, _('show branch')),
3456 ('b', 'branch', None, _('show branch')),
3451 ('t', 'tags', None, _('show tags')),
3457 ('t', 'tags', None, _('show tags')),
3452 ('B', 'bookmarks', None, _('show bookmarks')),
3458 ('B', 'bookmarks', None, _('show bookmarks')),
3453 ] + remoteopts,
3459 ] + remoteopts,
3454 _('[-nibtB] [-r REV] [SOURCE]'))
3460 _('[-nibtB] [-r REV] [SOURCE]'))
3455 def identify(ui, repo, source=None, rev=None,
3461 def identify(ui, repo, source=None, rev=None,
3456 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3462 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3457 """identify the working copy or specified revision
3463 """identify the working copy or specified revision
3458
3464
3459 Print a summary identifying the repository state at REV using one or
3465 Print a summary identifying the repository state at REV using one or
3460 two parent hash identifiers, followed by a "+" if the working
3466 two parent hash identifiers, followed by a "+" if the working
3461 directory has uncommitted changes, the branch name (if not default),
3467 directory has uncommitted changes, the branch name (if not default),
3462 a list of tags, and a list of bookmarks.
3468 a list of tags, and a list of bookmarks.
3463
3469
3464 When REV is not given, print a summary of the current state of the
3470 When REV is not given, print a summary of the current state of the
3465 repository.
3471 repository.
3466
3472
3467 Specifying a path to a repository root or Mercurial bundle will
3473 Specifying a path to a repository root or Mercurial bundle will
3468 cause lookup to operate on that repository/bundle.
3474 cause lookup to operate on that repository/bundle.
3469
3475
3470 .. container:: verbose
3476 .. container:: verbose
3471
3477
3472 Examples:
3478 Examples:
3473
3479
3474 - generate a build identifier for the working directory::
3480 - generate a build identifier for the working directory::
3475
3481
3476 hg id --id > build-id.dat
3482 hg id --id > build-id.dat
3477
3483
3478 - find the revision corresponding to a tag::
3484 - find the revision corresponding to a tag::
3479
3485
3480 hg id -n -r 1.3
3486 hg id -n -r 1.3
3481
3487
3482 - check the most recent revision of a remote repository::
3488 - check the most recent revision of a remote repository::
3483
3489
3484 hg id -r tip http://selenic.com/hg/
3490 hg id -r tip http://selenic.com/hg/
3485
3491
3486 Returns 0 if successful.
3492 Returns 0 if successful.
3487 """
3493 """
3488
3494
3489 if not repo and not source:
3495 if not repo and not source:
3490 raise util.Abort(_("there is no Mercurial repository here "
3496 raise util.Abort(_("there is no Mercurial repository here "
3491 "(.hg not found)"))
3497 "(.hg not found)"))
3492
3498
3493 hexfunc = ui.debugflag and hex or short
3499 hexfunc = ui.debugflag and hex or short
3494 default = not (num or id or branch or tags or bookmarks)
3500 default = not (num or id or branch or tags or bookmarks)
3495 output = []
3501 output = []
3496 revs = []
3502 revs = []
3497
3503
3498 if source:
3504 if source:
3499 source, branches = hg.parseurl(ui.expandpath(source))
3505 source, branches = hg.parseurl(ui.expandpath(source))
3500 peer = hg.peer(ui, opts, source)
3506 peer = hg.peer(ui, opts, source)
3501 repo = peer.local()
3507 repo = peer.local()
3502 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3508 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3503
3509
3504 if not repo:
3510 if not repo:
3505 if num or branch or tags:
3511 if num or branch or tags:
3506 raise util.Abort(
3512 raise util.Abort(
3507 _("can't query remote revision number, branch, or tags"))
3513 _("can't query remote revision number, branch, or tags"))
3508 if not rev and revs:
3514 if not rev and revs:
3509 rev = revs[0]
3515 rev = revs[0]
3510 if not rev:
3516 if not rev:
3511 rev = "tip"
3517 rev = "tip"
3512
3518
3513 remoterev = peer.lookup(rev)
3519 remoterev = peer.lookup(rev)
3514 if default or id:
3520 if default or id:
3515 output = [hexfunc(remoterev)]
3521 output = [hexfunc(remoterev)]
3516
3522
3517 def getbms():
3523 def getbms():
3518 bms = []
3524 bms = []
3519
3525
3520 if 'bookmarks' in peer.listkeys('namespaces'):
3526 if 'bookmarks' in peer.listkeys('namespaces'):
3521 hexremoterev = hex(remoterev)
3527 hexremoterev = hex(remoterev)
3522 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3528 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3523 if bmr == hexremoterev]
3529 if bmr == hexremoterev]
3524
3530
3525 return bms
3531 return bms
3526
3532
3527 if bookmarks:
3533 if bookmarks:
3528 output.extend(getbms())
3534 output.extend(getbms())
3529 elif default and not ui.quiet:
3535 elif default and not ui.quiet:
3530 # multiple bookmarks for a single parent separated by '/'
3536 # multiple bookmarks for a single parent separated by '/'
3531 bm = '/'.join(getbms())
3537 bm = '/'.join(getbms())
3532 if bm:
3538 if bm:
3533 output.append(bm)
3539 output.append(bm)
3534 else:
3540 else:
3535 if not rev:
3541 if not rev:
3536 ctx = repo[None]
3542 ctx = repo[None]
3537 parents = ctx.parents()
3543 parents = ctx.parents()
3538 changed = ""
3544 changed = ""
3539 if default or id or num:
3545 if default or id or num:
3540 if (util.any(repo.status())
3546 if (util.any(repo.status())
3541 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3547 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3542 changed = '+'
3548 changed = '+'
3543 if default or id:
3549 if default or id:
3544 output = ["%s%s" %
3550 output = ["%s%s" %
3545 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3551 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3546 if num:
3552 if num:
3547 output.append("%s%s" %
3553 output.append("%s%s" %
3548 ('+'.join([str(p.rev()) for p in parents]), changed))
3554 ('+'.join([str(p.rev()) for p in parents]), changed))
3549 else:
3555 else:
3550 ctx = scmutil.revsingle(repo, rev)
3556 ctx = scmutil.revsingle(repo, rev)
3551 if default or id:
3557 if default or id:
3552 output = [hexfunc(ctx.node())]
3558 output = [hexfunc(ctx.node())]
3553 if num:
3559 if num:
3554 output.append(str(ctx.rev()))
3560 output.append(str(ctx.rev()))
3555
3561
3556 if default and not ui.quiet:
3562 if default and not ui.quiet:
3557 b = ctx.branch()
3563 b = ctx.branch()
3558 if b != 'default':
3564 if b != 'default':
3559 output.append("(%s)" % b)
3565 output.append("(%s)" % b)
3560
3566
3561 # multiple tags for a single parent separated by '/'
3567 # multiple tags for a single parent separated by '/'
3562 t = '/'.join(ctx.tags())
3568 t = '/'.join(ctx.tags())
3563 if t:
3569 if t:
3564 output.append(t)
3570 output.append(t)
3565
3571
3566 # multiple bookmarks for a single parent separated by '/'
3572 # multiple bookmarks for a single parent separated by '/'
3567 bm = '/'.join(ctx.bookmarks())
3573 bm = '/'.join(ctx.bookmarks())
3568 if bm:
3574 if bm:
3569 output.append(bm)
3575 output.append(bm)
3570 else:
3576 else:
3571 if branch:
3577 if branch:
3572 output.append(ctx.branch())
3578 output.append(ctx.branch())
3573
3579
3574 if tags:
3580 if tags:
3575 output.extend(ctx.tags())
3581 output.extend(ctx.tags())
3576
3582
3577 if bookmarks:
3583 if bookmarks:
3578 output.extend(ctx.bookmarks())
3584 output.extend(ctx.bookmarks())
3579
3585
3580 ui.write("%s\n" % ' '.join(output))
3586 ui.write("%s\n" % ' '.join(output))
3581
3587
3582 @command('import|patch',
3588 @command('import|patch',
3583 [('p', 'strip', 1,
3589 [('p', 'strip', 1,
3584 _('directory strip option for patch. This has the same '
3590 _('directory strip option for patch. This has the same '
3585 'meaning as the corresponding patch option'), _('NUM')),
3591 'meaning as the corresponding patch option'), _('NUM')),
3586 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3592 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3587 ('e', 'edit', False, _('invoke editor on commit messages')),
3593 ('e', 'edit', False, _('invoke editor on commit messages')),
3588 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3594 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3589 ('', 'no-commit', None,
3595 ('', 'no-commit', None,
3590 _("don't commit, just update the working directory")),
3596 _("don't commit, just update the working directory")),
3591 ('', 'bypass', None,
3597 ('', 'bypass', None,
3592 _("apply patch without touching the working directory")),
3598 _("apply patch without touching the working directory")),
3593 ('', 'exact', None,
3599 ('', 'exact', None,
3594 _('apply patch to the nodes from which it was generated')),
3600 _('apply patch to the nodes from which it was generated')),
3595 ('', 'import-branch', None,
3601 ('', 'import-branch', None,
3596 _('use any branch information in patch (implied by --exact)'))] +
3602 _('use any branch information in patch (implied by --exact)'))] +
3597 commitopts + commitopts2 + similarityopts,
3603 commitopts + commitopts2 + similarityopts,
3598 _('[OPTION]... PATCH...'))
3604 _('[OPTION]... PATCH...'))
3599 def import_(ui, repo, patch1=None, *patches, **opts):
3605 def import_(ui, repo, patch1=None, *patches, **opts):
3600 """import an ordered set of patches
3606 """import an ordered set of patches
3601
3607
3602 Import a list of patches and commit them individually (unless
3608 Import a list of patches and commit them individually (unless
3603 --no-commit is specified).
3609 --no-commit is specified).
3604
3610
3605 If there are outstanding changes in the working directory, import
3611 If there are outstanding changes in the working directory, import
3606 will abort unless given the -f/--force flag.
3612 will abort unless given the -f/--force flag.
3607
3613
3608 You can import a patch straight from a mail message. Even patches
3614 You can import a patch straight from a mail message. Even patches
3609 as attachments work (to use the body part, it must have type
3615 as attachments work (to use the body part, it must have type
3610 text/plain or text/x-patch). From and Subject headers of email
3616 text/plain or text/x-patch). From and Subject headers of email
3611 message are used as default committer and commit message. All
3617 message are used as default committer and commit message. All
3612 text/plain body parts before first diff are added to commit
3618 text/plain body parts before first diff are added to commit
3613 message.
3619 message.
3614
3620
3615 If the imported patch was generated by :hg:`export`, user and
3621 If the imported patch was generated by :hg:`export`, user and
3616 description from patch override values from message headers and
3622 description from patch override values from message headers and
3617 body. Values given on command line with -m/--message and -u/--user
3623 body. Values given on command line with -m/--message and -u/--user
3618 override these.
3624 override these.
3619
3625
3620 If --exact is specified, import will set the working directory to
3626 If --exact is specified, import will set the working directory to
3621 the parent of each patch before applying it, and will abort if the
3627 the parent of each patch before applying it, and will abort if the
3622 resulting changeset has a different ID than the one recorded in
3628 resulting changeset has a different ID than the one recorded in
3623 the patch. This may happen due to character set problems or other
3629 the patch. This may happen due to character set problems or other
3624 deficiencies in the text patch format.
3630 deficiencies in the text patch format.
3625
3631
3626 Use --bypass to apply and commit patches directly to the
3632 Use --bypass to apply and commit patches directly to the
3627 repository, not touching the working directory. Without --exact,
3633 repository, not touching the working directory. Without --exact,
3628 patches will be applied on top of the working directory parent
3634 patches will be applied on top of the working directory parent
3629 revision.
3635 revision.
3630
3636
3631 With -s/--similarity, hg will attempt to discover renames and
3637 With -s/--similarity, hg will attempt to discover renames and
3632 copies in the patch in the same way as :hg:`addremove`.
3638 copies in the patch in the same way as :hg:`addremove`.
3633
3639
3634 To read a patch from standard input, use "-" as the patch name. If
3640 To read a patch from standard input, use "-" as the patch name. If
3635 a URL is specified, the patch will be downloaded from it.
3641 a URL is specified, the patch will be downloaded from it.
3636 See :hg:`help dates` for a list of formats valid for -d/--date.
3642 See :hg:`help dates` for a list of formats valid for -d/--date.
3637
3643
3638 .. container:: verbose
3644 .. container:: verbose
3639
3645
3640 Examples:
3646 Examples:
3641
3647
3642 - import a traditional patch from a website and detect renames::
3648 - import a traditional patch from a website and detect renames::
3643
3649
3644 hg import -s 80 http://example.com/bugfix.patch
3650 hg import -s 80 http://example.com/bugfix.patch
3645
3651
3646 - import a changeset from an hgweb server::
3652 - import a changeset from an hgweb server::
3647
3653
3648 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3654 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3649
3655
3650 - import all the patches in an Unix-style mbox::
3656 - import all the patches in an Unix-style mbox::
3651
3657
3652 hg import incoming-patches.mbox
3658 hg import incoming-patches.mbox
3653
3659
3654 - attempt to exactly restore an exported changeset (not always
3660 - attempt to exactly restore an exported changeset (not always
3655 possible)::
3661 possible)::
3656
3662
3657 hg import --exact proposed-fix.patch
3663 hg import --exact proposed-fix.patch
3658
3664
3659 Returns 0 on success.
3665 Returns 0 on success.
3660 """
3666 """
3661
3667
3662 if not patch1:
3668 if not patch1:
3663 raise util.Abort(_('need at least one patch to import'))
3669 raise util.Abort(_('need at least one patch to import'))
3664
3670
3665 patches = (patch1,) + patches
3671 patches = (patch1,) + patches
3666
3672
3667 date = opts.get('date')
3673 date = opts.get('date')
3668 if date:
3674 if date:
3669 opts['date'] = util.parsedate(date)
3675 opts['date'] = util.parsedate(date)
3670
3676
3671 editor = cmdutil.commiteditor
3677 editor = cmdutil.commiteditor
3672 if opts.get('edit'):
3678 if opts.get('edit'):
3673 editor = cmdutil.commitforceeditor
3679 editor = cmdutil.commitforceeditor
3674
3680
3675 update = not opts.get('bypass')
3681 update = not opts.get('bypass')
3676 if not update and opts.get('no_commit'):
3682 if not update and opts.get('no_commit'):
3677 raise util.Abort(_('cannot use --no-commit with --bypass'))
3683 raise util.Abort(_('cannot use --no-commit with --bypass'))
3678 try:
3684 try:
3679 sim = float(opts.get('similarity') or 0)
3685 sim = float(opts.get('similarity') or 0)
3680 except ValueError:
3686 except ValueError:
3681 raise util.Abort(_('similarity must be a number'))
3687 raise util.Abort(_('similarity must be a number'))
3682 if sim < 0 or sim > 100:
3688 if sim < 0 or sim > 100:
3683 raise util.Abort(_('similarity must be between 0 and 100'))
3689 raise util.Abort(_('similarity must be between 0 and 100'))
3684 if sim and not update:
3690 if sim and not update:
3685 raise util.Abort(_('cannot use --similarity with --bypass'))
3691 raise util.Abort(_('cannot use --similarity with --bypass'))
3686
3692
3687 if (opts.get('exact') or not opts.get('force')) and update:
3693 if (opts.get('exact') or not opts.get('force')) and update:
3688 cmdutil.bailifchanged(repo)
3694 cmdutil.bailifchanged(repo)
3689
3695
3690 base = opts["base"]
3696 base = opts["base"]
3691 strip = opts["strip"]
3697 strip = opts["strip"]
3692 wlock = lock = tr = None
3698 wlock = lock = tr = None
3693 msgs = []
3699 msgs = []
3694
3700
3695 def checkexact(repo, n, nodeid):
3701 def checkexact(repo, n, nodeid):
3696 if opts.get('exact') and hex(n) != nodeid:
3702 if opts.get('exact') and hex(n) != nodeid:
3697 repo.rollback()
3703 repo.rollback()
3698 raise util.Abort(_('patch is damaged or loses information'))
3704 raise util.Abort(_('patch is damaged or loses information'))
3699
3705
3700 def tryone(ui, hunk, parents):
3706 def tryone(ui, hunk, parents):
3701 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3707 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3702 patch.extract(ui, hunk)
3708 patch.extract(ui, hunk)
3703
3709
3704 if not tmpname:
3710 if not tmpname:
3705 return (None, None)
3711 return (None, None)
3706 msg = _('applied to working directory')
3712 msg = _('applied to working directory')
3707
3713
3708 try:
3714 try:
3709 cmdline_message = cmdutil.logmessage(ui, opts)
3715 cmdline_message = cmdutil.logmessage(ui, opts)
3710 if cmdline_message:
3716 if cmdline_message:
3711 # pickup the cmdline msg
3717 # pickup the cmdline msg
3712 message = cmdline_message
3718 message = cmdline_message
3713 elif message:
3719 elif message:
3714 # pickup the patch msg
3720 # pickup the patch msg
3715 message = message.strip()
3721 message = message.strip()
3716 else:
3722 else:
3717 # launch the editor
3723 # launch the editor
3718 message = None
3724 message = None
3719 ui.debug('message:\n%s\n' % message)
3725 ui.debug('message:\n%s\n' % message)
3720
3726
3721 if len(parents) == 1:
3727 if len(parents) == 1:
3722 parents.append(repo[nullid])
3728 parents.append(repo[nullid])
3723 if opts.get('exact'):
3729 if opts.get('exact'):
3724 if not nodeid or not p1:
3730 if not nodeid or not p1:
3725 raise util.Abort(_('not a Mercurial patch'))
3731 raise util.Abort(_('not a Mercurial patch'))
3726 p1 = repo[p1]
3732 p1 = repo[p1]
3727 p2 = repo[p2 or nullid]
3733 p2 = repo[p2 or nullid]
3728 elif p2:
3734 elif p2:
3729 try:
3735 try:
3730 p1 = repo[p1]
3736 p1 = repo[p1]
3731 p2 = repo[p2]
3737 p2 = repo[p2]
3732 # Without any options, consider p2 only if the
3738 # Without any options, consider p2 only if the
3733 # patch is being applied on top of the recorded
3739 # patch is being applied on top of the recorded
3734 # first parent.
3740 # first parent.
3735 if p1 != parents[0]:
3741 if p1 != parents[0]:
3736 p1 = parents[0]
3742 p1 = parents[0]
3737 p2 = repo[nullid]
3743 p2 = repo[nullid]
3738 except error.RepoError:
3744 except error.RepoError:
3739 p1, p2 = parents
3745 p1, p2 = parents
3740 else:
3746 else:
3741 p1, p2 = parents
3747 p1, p2 = parents
3742
3748
3743 n = None
3749 n = None
3744 if update:
3750 if update:
3745 if p1 != parents[0]:
3751 if p1 != parents[0]:
3746 hg.clean(repo, p1.node())
3752 hg.clean(repo, p1.node())
3747 if p2 != parents[1]:
3753 if p2 != parents[1]:
3748 repo.setparents(p1.node(), p2.node())
3754 repo.setparents(p1.node(), p2.node())
3749
3755
3750 if opts.get('exact') or opts.get('import_branch'):
3756 if opts.get('exact') or opts.get('import_branch'):
3751 repo.dirstate.setbranch(branch or 'default')
3757 repo.dirstate.setbranch(branch or 'default')
3752
3758
3753 files = set()
3759 files = set()
3754 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3760 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3755 eolmode=None, similarity=sim / 100.0)
3761 eolmode=None, similarity=sim / 100.0)
3756 files = list(files)
3762 files = list(files)
3757 if opts.get('no_commit'):
3763 if opts.get('no_commit'):
3758 if message:
3764 if message:
3759 msgs.append(message)
3765 msgs.append(message)
3760 else:
3766 else:
3761 if opts.get('exact') or p2:
3767 if opts.get('exact') or p2:
3762 # If you got here, you either use --force and know what
3768 # If you got here, you either use --force and know what
3763 # you are doing or used --exact or a merge patch while
3769 # you are doing or used --exact or a merge patch while
3764 # being updated to its first parent.
3770 # being updated to its first parent.
3765 m = None
3771 m = None
3766 else:
3772 else:
3767 m = scmutil.matchfiles(repo, files or [])
3773 m = scmutil.matchfiles(repo, files or [])
3768 n = repo.commit(message, opts.get('user') or user,
3774 n = repo.commit(message, opts.get('user') or user,
3769 opts.get('date') or date, match=m,
3775 opts.get('date') or date, match=m,
3770 editor=editor)
3776 editor=editor)
3771 checkexact(repo, n, nodeid)
3777 checkexact(repo, n, nodeid)
3772 else:
3778 else:
3773 if opts.get('exact') or opts.get('import_branch'):
3779 if opts.get('exact') or opts.get('import_branch'):
3774 branch = branch or 'default'
3780 branch = branch or 'default'
3775 else:
3781 else:
3776 branch = p1.branch()
3782 branch = p1.branch()
3777 store = patch.filestore()
3783 store = patch.filestore()
3778 try:
3784 try:
3779 files = set()
3785 files = set()
3780 try:
3786 try:
3781 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3787 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3782 files, eolmode=None)
3788 files, eolmode=None)
3783 except patch.PatchError, e:
3789 except patch.PatchError, e:
3784 raise util.Abort(str(e))
3790 raise util.Abort(str(e))
3785 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3791 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3786 message,
3792 message,
3787 opts.get('user') or user,
3793 opts.get('user') or user,
3788 opts.get('date') or date,
3794 opts.get('date') or date,
3789 branch, files, store,
3795 branch, files, store,
3790 editor=cmdutil.commiteditor)
3796 editor=cmdutil.commiteditor)
3791 repo.savecommitmessage(memctx.description())
3797 repo.savecommitmessage(memctx.description())
3792 n = memctx.commit()
3798 n = memctx.commit()
3793 checkexact(repo, n, nodeid)
3799 checkexact(repo, n, nodeid)
3794 finally:
3800 finally:
3795 store.close()
3801 store.close()
3796 if n:
3802 if n:
3797 # i18n: refers to a short changeset id
3803 # i18n: refers to a short changeset id
3798 msg = _('created %s') % short(n)
3804 msg = _('created %s') % short(n)
3799 return (msg, n)
3805 return (msg, n)
3800 finally:
3806 finally:
3801 os.unlink(tmpname)
3807 os.unlink(tmpname)
3802
3808
3803 try:
3809 try:
3804 try:
3810 try:
3805 wlock = repo.wlock()
3811 wlock = repo.wlock()
3806 if not opts.get('no_commit'):
3812 if not opts.get('no_commit'):
3807 lock = repo.lock()
3813 lock = repo.lock()
3808 tr = repo.transaction('import')
3814 tr = repo.transaction('import')
3809 parents = repo.parents()
3815 parents = repo.parents()
3810 for patchurl in patches:
3816 for patchurl in patches:
3811 if patchurl == '-':
3817 if patchurl == '-':
3812 ui.status(_('applying patch from stdin\n'))
3818 ui.status(_('applying patch from stdin\n'))
3813 patchfile = ui.fin
3819 patchfile = ui.fin
3814 patchurl = 'stdin' # for error message
3820 patchurl = 'stdin' # for error message
3815 else:
3821 else:
3816 patchurl = os.path.join(base, patchurl)
3822 patchurl = os.path.join(base, patchurl)
3817 ui.status(_('applying %s\n') % patchurl)
3823 ui.status(_('applying %s\n') % patchurl)
3818 patchfile = url.open(ui, patchurl)
3824 patchfile = url.open(ui, patchurl)
3819
3825
3820 haspatch = False
3826 haspatch = False
3821 for hunk in patch.split(patchfile):
3827 for hunk in patch.split(patchfile):
3822 (msg, node) = tryone(ui, hunk, parents)
3828 (msg, node) = tryone(ui, hunk, parents)
3823 if msg:
3829 if msg:
3824 haspatch = True
3830 haspatch = True
3825 ui.note(msg + '\n')
3831 ui.note(msg + '\n')
3826 if update or opts.get('exact'):
3832 if update or opts.get('exact'):
3827 parents = repo.parents()
3833 parents = repo.parents()
3828 else:
3834 else:
3829 parents = [repo[node]]
3835 parents = [repo[node]]
3830
3836
3831 if not haspatch:
3837 if not haspatch:
3832 raise util.Abort(_('%s: no diffs found') % patchurl)
3838 raise util.Abort(_('%s: no diffs found') % patchurl)
3833
3839
3834 if tr:
3840 if tr:
3835 tr.close()
3841 tr.close()
3836 if msgs:
3842 if msgs:
3837 repo.savecommitmessage('\n* * *\n'.join(msgs))
3843 repo.savecommitmessage('\n* * *\n'.join(msgs))
3838 except: # re-raises
3844 except: # re-raises
3839 # wlock.release() indirectly calls dirstate.write(): since
3845 # wlock.release() indirectly calls dirstate.write(): since
3840 # we're crashing, we do not want to change the working dir
3846 # we're crashing, we do not want to change the working dir
3841 # parent after all, so make sure it writes nothing
3847 # parent after all, so make sure it writes nothing
3842 repo.dirstate.invalidate()
3848 repo.dirstate.invalidate()
3843 raise
3849 raise
3844 finally:
3850 finally:
3845 if tr:
3851 if tr:
3846 tr.release()
3852 tr.release()
3847 release(lock, wlock)
3853 release(lock, wlock)
3848
3854
3849 @command('incoming|in',
3855 @command('incoming|in',
3850 [('f', 'force', None,
3856 [('f', 'force', None,
3851 _('run even if remote repository is unrelated')),
3857 _('run even if remote repository is unrelated')),
3852 ('n', 'newest-first', None, _('show newest record first')),
3858 ('n', 'newest-first', None, _('show newest record first')),
3853 ('', 'bundle', '',
3859 ('', 'bundle', '',
3854 _('file to store the bundles into'), _('FILE')),
3860 _('file to store the bundles into'), _('FILE')),
3855 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3861 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3856 ('B', 'bookmarks', False, _("compare bookmarks")),
3862 ('B', 'bookmarks', False, _("compare bookmarks")),
3857 ('b', 'branch', [],
3863 ('b', 'branch', [],
3858 _('a specific branch you would like to pull'), _('BRANCH')),
3864 _('a specific branch you would like to pull'), _('BRANCH')),
3859 ] + logopts + remoteopts + subrepoopts,
3865 ] + logopts + remoteopts + subrepoopts,
3860 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3866 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3861 def incoming(ui, repo, source="default", **opts):
3867 def incoming(ui, repo, source="default", **opts):
3862 """show new changesets found in source
3868 """show new changesets found in source
3863
3869
3864 Show new changesets found in the specified path/URL or the default
3870 Show new changesets found in the specified path/URL or the default
3865 pull location. These are the changesets that would have been pulled
3871 pull location. These are the changesets that would have been pulled
3866 if a pull at the time you issued this command.
3872 if a pull at the time you issued this command.
3867
3873
3868 For remote repository, using --bundle avoids downloading the
3874 For remote repository, using --bundle avoids downloading the
3869 changesets twice if the incoming is followed by a pull.
3875 changesets twice if the incoming is followed by a pull.
3870
3876
3871 See pull for valid source format details.
3877 See pull for valid source format details.
3872
3878
3873 Returns 0 if there are incoming changes, 1 otherwise.
3879 Returns 0 if there are incoming changes, 1 otherwise.
3874 """
3880 """
3875 if opts.get('graph'):
3881 if opts.get('graph'):
3876 cmdutil.checkunsupportedgraphflags([], opts)
3882 cmdutil.checkunsupportedgraphflags([], opts)
3877 def display(other, chlist, displayer):
3883 def display(other, chlist, displayer):
3878 revdag = cmdutil.graphrevs(other, chlist, opts)
3884 revdag = cmdutil.graphrevs(other, chlist, opts)
3879 showparents = [ctx.node() for ctx in repo[None].parents()]
3885 showparents = [ctx.node() for ctx in repo[None].parents()]
3880 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3886 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3881 graphmod.asciiedges)
3887 graphmod.asciiedges)
3882
3888
3883 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3889 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3884 return 0
3890 return 0
3885
3891
3886 if opts.get('bundle') and opts.get('subrepos'):
3892 if opts.get('bundle') and opts.get('subrepos'):
3887 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3893 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3888
3894
3889 if opts.get('bookmarks'):
3895 if opts.get('bookmarks'):
3890 source, branches = hg.parseurl(ui.expandpath(source),
3896 source, branches = hg.parseurl(ui.expandpath(source),
3891 opts.get('branch'))
3897 opts.get('branch'))
3892 other = hg.peer(repo, opts, source)
3898 other = hg.peer(repo, opts, source)
3893 if 'bookmarks' not in other.listkeys('namespaces'):
3899 if 'bookmarks' not in other.listkeys('namespaces'):
3894 ui.warn(_("remote doesn't support bookmarks\n"))
3900 ui.warn(_("remote doesn't support bookmarks\n"))
3895 return 0
3901 return 0
3896 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3902 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3897 return bookmarks.diff(ui, repo, other)
3903 return bookmarks.diff(ui, repo, other)
3898
3904
3899 repo._subtoppath = ui.expandpath(source)
3905 repo._subtoppath = ui.expandpath(source)
3900 try:
3906 try:
3901 return hg.incoming(ui, repo, source, opts)
3907 return hg.incoming(ui, repo, source, opts)
3902 finally:
3908 finally:
3903 del repo._subtoppath
3909 del repo._subtoppath
3904
3910
3905
3911
3906 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3912 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3907 def init(ui, dest=".", **opts):
3913 def init(ui, dest=".", **opts):
3908 """create a new repository in the given directory
3914 """create a new repository in the given directory
3909
3915
3910 Initialize a new repository in the given directory. If the given
3916 Initialize a new repository in the given directory. If the given
3911 directory does not exist, it will be created.
3917 directory does not exist, it will be created.
3912
3918
3913 If no directory is given, the current directory is used.
3919 If no directory is given, the current directory is used.
3914
3920
3915 It is possible to specify an ``ssh://`` URL as the destination.
3921 It is possible to specify an ``ssh://`` URL as the destination.
3916 See :hg:`help urls` for more information.
3922 See :hg:`help urls` for more information.
3917
3923
3918 Returns 0 on success.
3924 Returns 0 on success.
3919 """
3925 """
3920 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3926 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3921
3927
3922 @command('locate',
3928 @command('locate',
3923 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3929 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3924 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3930 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3925 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3931 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3926 ] + walkopts,
3932 ] + walkopts,
3927 _('[OPTION]... [PATTERN]...'))
3933 _('[OPTION]... [PATTERN]...'))
3928 def locate(ui, repo, *pats, **opts):
3934 def locate(ui, repo, *pats, **opts):
3929 """locate files matching specific patterns
3935 """locate files matching specific patterns
3930
3936
3931 Print files under Mercurial control in the working directory whose
3937 Print files under Mercurial control in the working directory whose
3932 names match the given patterns.
3938 names match the given patterns.
3933
3939
3934 By default, this command searches all directories in the working
3940 By default, this command searches all directories in the working
3935 directory. To search just the current directory and its
3941 directory. To search just the current directory and its
3936 subdirectories, use "--include .".
3942 subdirectories, use "--include .".
3937
3943
3938 If no patterns are given to match, this command prints the names
3944 If no patterns are given to match, this command prints the names
3939 of all files under Mercurial control in the working directory.
3945 of all files under Mercurial control in the working directory.
3940
3946
3941 If you want to feed the output of this command into the "xargs"
3947 If you want to feed the output of this command into the "xargs"
3942 command, use the -0 option to both this command and "xargs". This
3948 command, use the -0 option to both this command and "xargs". This
3943 will avoid the problem of "xargs" treating single filenames that
3949 will avoid the problem of "xargs" treating single filenames that
3944 contain whitespace as multiple filenames.
3950 contain whitespace as multiple filenames.
3945
3951
3946 Returns 0 if a match is found, 1 otherwise.
3952 Returns 0 if a match is found, 1 otherwise.
3947 """
3953 """
3948 end = opts.get('print0') and '\0' or '\n'
3954 end = opts.get('print0') and '\0' or '\n'
3949 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3955 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3950
3956
3951 ret = 1
3957 ret = 1
3952 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3958 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3953 m.bad = lambda x, y: False
3959 m.bad = lambda x, y: False
3954 for abs in repo[rev].walk(m):
3960 for abs in repo[rev].walk(m):
3955 if not rev and abs not in repo.dirstate:
3961 if not rev and abs not in repo.dirstate:
3956 continue
3962 continue
3957 if opts.get('fullpath'):
3963 if opts.get('fullpath'):
3958 ui.write(repo.wjoin(abs), end)
3964 ui.write(repo.wjoin(abs), end)
3959 else:
3965 else:
3960 ui.write(((pats and m.rel(abs)) or abs), end)
3966 ui.write(((pats and m.rel(abs)) or abs), end)
3961 ret = 0
3967 ret = 0
3962
3968
3963 return ret
3969 return ret
3964
3970
3965 @command('^log|history',
3971 @command('^log|history',
3966 [('f', 'follow', None,
3972 [('f', 'follow', None,
3967 _('follow changeset history, or file history across copies and renames')),
3973 _('follow changeset history, or file history across copies and renames')),
3968 ('', 'follow-first', None,
3974 ('', 'follow-first', None,
3969 _('only follow the first parent of merge changesets (DEPRECATED)')),
3975 _('only follow the first parent of merge changesets (DEPRECATED)')),
3970 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3976 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3971 ('C', 'copies', None, _('show copied files')),
3977 ('C', 'copies', None, _('show copied files')),
3972 ('k', 'keyword', [],
3978 ('k', 'keyword', [],
3973 _('do case-insensitive search for a given text'), _('TEXT')),
3979 _('do case-insensitive search for a given text'), _('TEXT')),
3974 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3980 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3975 ('', 'removed', None, _('include revisions where files were removed')),
3981 ('', 'removed', None, _('include revisions where files were removed')),
3976 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3982 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3977 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3983 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3978 ('', 'only-branch', [],
3984 ('', 'only-branch', [],
3979 _('show only changesets within the given named branch (DEPRECATED)'),
3985 _('show only changesets within the given named branch (DEPRECATED)'),
3980 _('BRANCH')),
3986 _('BRANCH')),
3981 ('b', 'branch', [],
3987 ('b', 'branch', [],
3982 _('show changesets within the given named branch'), _('BRANCH')),
3988 _('show changesets within the given named branch'), _('BRANCH')),
3983 ('P', 'prune', [],
3989 ('P', 'prune', [],
3984 _('do not display revision or any of its ancestors'), _('REV')),
3990 _('do not display revision or any of its ancestors'), _('REV')),
3985 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3991 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3986 ] + logopts + walkopts,
3992 ] + logopts + walkopts,
3987 _('[OPTION]... [FILE]'))
3993 _('[OPTION]... [FILE]'))
3988 def log(ui, repo, *pats, **opts):
3994 def log(ui, repo, *pats, **opts):
3989 """show revision history of entire repository or files
3995 """show revision history of entire repository or files
3990
3996
3991 Print the revision history of the specified files or the entire
3997 Print the revision history of the specified files or the entire
3992 project.
3998 project.
3993
3999
3994 If no revision range is specified, the default is ``tip:0`` unless
4000 If no revision range is specified, the default is ``tip:0`` unless
3995 --follow is set, in which case the working directory parent is
4001 --follow is set, in which case the working directory parent is
3996 used as the starting revision.
4002 used as the starting revision.
3997
4003
3998 File history is shown without following rename or copy history of
4004 File history is shown without following rename or copy history of
3999 files. Use -f/--follow with a filename to follow history across
4005 files. Use -f/--follow with a filename to follow history across
4000 renames and copies. --follow without a filename will only show
4006 renames and copies. --follow without a filename will only show
4001 ancestors or descendants of the starting revision.
4007 ancestors or descendants of the starting revision.
4002
4008
4003 By default this command prints revision number and changeset id,
4009 By default this command prints revision number and changeset id,
4004 tags, non-trivial parents, user, date and time, and a summary for
4010 tags, non-trivial parents, user, date and time, and a summary for
4005 each commit. When the -v/--verbose switch is used, the list of
4011 each commit. When the -v/--verbose switch is used, the list of
4006 changed files and full commit message are shown.
4012 changed files and full commit message are shown.
4007
4013
4008 .. note::
4014 .. note::
4009 log -p/--patch may generate unexpected diff output for merge
4015 log -p/--patch may generate unexpected diff output for merge
4010 changesets, as it will only compare the merge changeset against
4016 changesets, as it will only compare the merge changeset against
4011 its first parent. Also, only files different from BOTH parents
4017 its first parent. Also, only files different from BOTH parents
4012 will appear in files:.
4018 will appear in files:.
4013
4019
4014 .. note::
4020 .. note::
4015 for performance reasons, log FILE may omit duplicate changes
4021 for performance reasons, log FILE may omit duplicate changes
4016 made on branches and will not show deletions. To see all
4022 made on branches and will not show deletions. To see all
4017 changes including duplicates and deletions, use the --removed
4023 changes including duplicates and deletions, use the --removed
4018 switch.
4024 switch.
4019
4025
4020 .. container:: verbose
4026 .. container:: verbose
4021
4027
4022 Some examples:
4028 Some examples:
4023
4029
4024 - changesets with full descriptions and file lists::
4030 - changesets with full descriptions and file lists::
4025
4031
4026 hg log -v
4032 hg log -v
4027
4033
4028 - changesets ancestral to the working directory::
4034 - changesets ancestral to the working directory::
4029
4035
4030 hg log -f
4036 hg log -f
4031
4037
4032 - last 10 commits on the current branch::
4038 - last 10 commits on the current branch::
4033
4039
4034 hg log -l 10 -b .
4040 hg log -l 10 -b .
4035
4041
4036 - changesets showing all modifications of a file, including removals::
4042 - changesets showing all modifications of a file, including removals::
4037
4043
4038 hg log --removed file.c
4044 hg log --removed file.c
4039
4045
4040 - all changesets that touch a directory, with diffs, excluding merges::
4046 - all changesets that touch a directory, with diffs, excluding merges::
4041
4047
4042 hg log -Mp lib/
4048 hg log -Mp lib/
4043
4049
4044 - all revision numbers that match a keyword::
4050 - all revision numbers that match a keyword::
4045
4051
4046 hg log -k bug --template "{rev}\\n"
4052 hg log -k bug --template "{rev}\\n"
4047
4053
4048 - check if a given changeset is included is a tagged release::
4054 - check if a given changeset is included is a tagged release::
4049
4055
4050 hg log -r "a21ccf and ancestor(1.9)"
4056 hg log -r "a21ccf and ancestor(1.9)"
4051
4057
4052 - find all changesets by some user in a date range::
4058 - find all changesets by some user in a date range::
4053
4059
4054 hg log -k alice -d "may 2008 to jul 2008"
4060 hg log -k alice -d "may 2008 to jul 2008"
4055
4061
4056 - summary of all changesets after the last tag::
4062 - summary of all changesets after the last tag::
4057
4063
4058 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4064 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4059
4065
4060 See :hg:`help dates` for a list of formats valid for -d/--date.
4066 See :hg:`help dates` for a list of formats valid for -d/--date.
4061
4067
4062 See :hg:`help revisions` and :hg:`help revsets` for more about
4068 See :hg:`help revisions` and :hg:`help revsets` for more about
4063 specifying revisions.
4069 specifying revisions.
4064
4070
4065 See :hg:`help templates` for more about pre-packaged styles and
4071 See :hg:`help templates` for more about pre-packaged styles and
4066 specifying custom templates.
4072 specifying custom templates.
4067
4073
4068 Returns 0 on success.
4074 Returns 0 on success.
4069 """
4075 """
4070 if opts.get('graph'):
4076 if opts.get('graph'):
4071 return cmdutil.graphlog(ui, repo, *pats, **opts)
4077 return cmdutil.graphlog(ui, repo, *pats, **opts)
4072
4078
4073 matchfn = scmutil.match(repo[None], pats, opts)
4079 matchfn = scmutil.match(repo[None], pats, opts)
4074 limit = cmdutil.loglimit(opts)
4080 limit = cmdutil.loglimit(opts)
4075 count = 0
4081 count = 0
4076
4082
4077 getrenamed, endrev = None, None
4083 getrenamed, endrev = None, None
4078 if opts.get('copies'):
4084 if opts.get('copies'):
4079 if opts.get('rev'):
4085 if opts.get('rev'):
4080 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4086 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4081 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4087 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4082
4088
4083 df = False
4089 df = False
4084 if opts.get("date"):
4090 if opts.get("date"):
4085 df = util.matchdate(opts["date"])
4091 df = util.matchdate(opts["date"])
4086
4092
4087 branches = opts.get('branch', []) + opts.get('only_branch', [])
4093 branches = opts.get('branch', []) + opts.get('only_branch', [])
4088 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4094 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4089
4095
4090 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4096 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4091 def prep(ctx, fns):
4097 def prep(ctx, fns):
4092 rev = ctx.rev()
4098 rev = ctx.rev()
4093 parents = [p for p in repo.changelog.parentrevs(rev)
4099 parents = [p for p in repo.changelog.parentrevs(rev)
4094 if p != nullrev]
4100 if p != nullrev]
4095 if opts.get('no_merges') and len(parents) == 2:
4101 if opts.get('no_merges') and len(parents) == 2:
4096 return
4102 return
4097 if opts.get('only_merges') and len(parents) != 2:
4103 if opts.get('only_merges') and len(parents) != 2:
4098 return
4104 return
4099 if opts.get('branch') and ctx.branch() not in opts['branch']:
4105 if opts.get('branch') and ctx.branch() not in opts['branch']:
4100 return
4106 return
4101 if not opts.get('hidden') and ctx.hidden():
4107 if not opts.get('hidden') and ctx.hidden():
4102 return
4108 return
4103 if df and not df(ctx.date()[0]):
4109 if df and not df(ctx.date()[0]):
4104 return
4110 return
4105
4111
4106 lower = encoding.lower
4112 lower = encoding.lower
4107 if opts.get('user'):
4113 if opts.get('user'):
4108 luser = lower(ctx.user())
4114 luser = lower(ctx.user())
4109 for k in [lower(x) for x in opts['user']]:
4115 for k in [lower(x) for x in opts['user']]:
4110 if (k in luser):
4116 if (k in luser):
4111 break
4117 break
4112 else:
4118 else:
4113 return
4119 return
4114 if opts.get('keyword'):
4120 if opts.get('keyword'):
4115 luser = lower(ctx.user())
4121 luser = lower(ctx.user())
4116 ldesc = lower(ctx.description())
4122 ldesc = lower(ctx.description())
4117 lfiles = lower(" ".join(ctx.files()))
4123 lfiles = lower(" ".join(ctx.files()))
4118 for k in [lower(x) for x in opts['keyword']]:
4124 for k in [lower(x) for x in opts['keyword']]:
4119 if (k in luser or k in ldesc or k in lfiles):
4125 if (k in luser or k in ldesc or k in lfiles):
4120 break
4126 break
4121 else:
4127 else:
4122 return
4128 return
4123
4129
4124 copies = None
4130 copies = None
4125 if getrenamed is not None and rev:
4131 if getrenamed is not None and rev:
4126 copies = []
4132 copies = []
4127 for fn in ctx.files():
4133 for fn in ctx.files():
4128 rename = getrenamed(fn, rev)
4134 rename = getrenamed(fn, rev)
4129 if rename:
4135 if rename:
4130 copies.append((fn, rename[0]))
4136 copies.append((fn, rename[0]))
4131
4137
4132 revmatchfn = None
4138 revmatchfn = None
4133 if opts.get('patch') or opts.get('stat'):
4139 if opts.get('patch') or opts.get('stat'):
4134 if opts.get('follow') or opts.get('follow_first'):
4140 if opts.get('follow') or opts.get('follow_first'):
4135 # note: this might be wrong when following through merges
4141 # note: this might be wrong when following through merges
4136 revmatchfn = scmutil.match(repo[None], fns, default='path')
4142 revmatchfn = scmutil.match(repo[None], fns, default='path')
4137 else:
4143 else:
4138 revmatchfn = matchfn
4144 revmatchfn = matchfn
4139
4145
4140 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4146 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4141
4147
4142 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4148 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4143 if count == limit:
4149 if count == limit:
4144 break
4150 break
4145 if displayer.flush(ctx.rev()):
4151 if displayer.flush(ctx.rev()):
4146 count += 1
4152 count += 1
4147 displayer.close()
4153 displayer.close()
4148
4154
4149 @command('manifest',
4155 @command('manifest',
4150 [('r', 'rev', '', _('revision to display'), _('REV')),
4156 [('r', 'rev', '', _('revision to display'), _('REV')),
4151 ('', 'all', False, _("list files from all revisions"))],
4157 ('', 'all', False, _("list files from all revisions"))],
4152 _('[-r REV]'))
4158 _('[-r REV]'))
4153 def manifest(ui, repo, node=None, rev=None, **opts):
4159 def manifest(ui, repo, node=None, rev=None, **opts):
4154 """output the current or given revision of the project manifest
4160 """output the current or given revision of the project manifest
4155
4161
4156 Print a list of version controlled files for the given revision.
4162 Print a list of version controlled files for the given revision.
4157 If no revision is given, the first parent of the working directory
4163 If no revision is given, the first parent of the working directory
4158 is used, or the null revision if no revision is checked out.
4164 is used, or the null revision if no revision is checked out.
4159
4165
4160 With -v, print file permissions, symlink and executable bits.
4166 With -v, print file permissions, symlink and executable bits.
4161 With --debug, print file revision hashes.
4167 With --debug, print file revision hashes.
4162
4168
4163 If option --all is specified, the list of all files from all revisions
4169 If option --all is specified, the list of all files from all revisions
4164 is printed. This includes deleted and renamed files.
4170 is printed. This includes deleted and renamed files.
4165
4171
4166 Returns 0 on success.
4172 Returns 0 on success.
4167 """
4173 """
4168 if opts.get('all'):
4174 if opts.get('all'):
4169 if rev or node:
4175 if rev or node:
4170 raise util.Abort(_("can't specify a revision with --all"))
4176 raise util.Abort(_("can't specify a revision with --all"))
4171
4177
4172 res = []
4178 res = []
4173 prefix = "data/"
4179 prefix = "data/"
4174 suffix = ".i"
4180 suffix = ".i"
4175 plen = len(prefix)
4181 plen = len(prefix)
4176 slen = len(suffix)
4182 slen = len(suffix)
4177 lock = repo.lock()
4183 lock = repo.lock()
4178 try:
4184 try:
4179 for fn, b, size in repo.store.datafiles():
4185 for fn, b, size in repo.store.datafiles():
4180 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4186 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4181 res.append(fn[plen:-slen])
4187 res.append(fn[plen:-slen])
4182 finally:
4188 finally:
4183 lock.release()
4189 lock.release()
4184 for f in sorted(res):
4190 for f in sorted(res):
4185 ui.write("%s\n" % f)
4191 ui.write("%s\n" % f)
4186 return
4192 return
4187
4193
4188 if rev and node:
4194 if rev and node:
4189 raise util.Abort(_("please specify just one revision"))
4195 raise util.Abort(_("please specify just one revision"))
4190
4196
4191 if not node:
4197 if not node:
4192 node = rev
4198 node = rev
4193
4199
4194 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4200 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4195 ctx = scmutil.revsingle(repo, node)
4201 ctx = scmutil.revsingle(repo, node)
4196 for f in ctx:
4202 for f in ctx:
4197 if ui.debugflag:
4203 if ui.debugflag:
4198 ui.write("%40s " % hex(ctx.manifest()[f]))
4204 ui.write("%40s " % hex(ctx.manifest()[f]))
4199 if ui.verbose:
4205 if ui.verbose:
4200 ui.write(decor[ctx.flags(f)])
4206 ui.write(decor[ctx.flags(f)])
4201 ui.write("%s\n" % f)
4207 ui.write("%s\n" % f)
4202
4208
4203 @command('^merge',
4209 @command('^merge',
4204 [('f', 'force', None, _('force a merge with outstanding changes')),
4210 [('f', 'force', None, _('force a merge with outstanding changes')),
4205 ('r', 'rev', '', _('revision to merge'), _('REV')),
4211 ('r', 'rev', '', _('revision to merge'), _('REV')),
4206 ('P', 'preview', None,
4212 ('P', 'preview', None,
4207 _('review revisions to merge (no merge is performed)'))
4213 _('review revisions to merge (no merge is performed)'))
4208 ] + mergetoolopts,
4214 ] + mergetoolopts,
4209 _('[-P] [-f] [[-r] REV]'))
4215 _('[-P] [-f] [[-r] REV]'))
4210 def merge(ui, repo, node=None, **opts):
4216 def merge(ui, repo, node=None, **opts):
4211 """merge working directory with another revision
4217 """merge working directory with another revision
4212
4218
4213 The current working directory is updated with all changes made in
4219 The current working directory is updated with all changes made in
4214 the requested revision since the last common predecessor revision.
4220 the requested revision since the last common predecessor revision.
4215
4221
4216 Files that changed between either parent are marked as changed for
4222 Files that changed between either parent are marked as changed for
4217 the next commit and a commit must be performed before any further
4223 the next commit and a commit must be performed before any further
4218 updates to the repository are allowed. The next commit will have
4224 updates to the repository are allowed. The next commit will have
4219 two parents.
4225 two parents.
4220
4226
4221 ``--tool`` can be used to specify the merge tool used for file
4227 ``--tool`` can be used to specify the merge tool used for file
4222 merges. It overrides the HGMERGE environment variable and your
4228 merges. It overrides the HGMERGE environment variable and your
4223 configuration files. See :hg:`help merge-tools` for options.
4229 configuration files. See :hg:`help merge-tools` for options.
4224
4230
4225 If no revision is specified, the working directory's parent is a
4231 If no revision is specified, the working directory's parent is a
4226 head revision, and the current branch contains exactly one other
4232 head revision, and the current branch contains exactly one other
4227 head, the other head is merged with by default. Otherwise, an
4233 head, the other head is merged with by default. Otherwise, an
4228 explicit revision with which to merge with must be provided.
4234 explicit revision with which to merge with must be provided.
4229
4235
4230 :hg:`resolve` must be used to resolve unresolved files.
4236 :hg:`resolve` must be used to resolve unresolved files.
4231
4237
4232 To undo an uncommitted merge, use :hg:`update --clean .` which
4238 To undo an uncommitted merge, use :hg:`update --clean .` which
4233 will check out a clean copy of the original merge parent, losing
4239 will check out a clean copy of the original merge parent, losing
4234 all changes.
4240 all changes.
4235
4241
4236 Returns 0 on success, 1 if there are unresolved files.
4242 Returns 0 on success, 1 if there are unresolved files.
4237 """
4243 """
4238
4244
4239 if opts.get('rev') and node:
4245 if opts.get('rev') and node:
4240 raise util.Abort(_("please specify just one revision"))
4246 raise util.Abort(_("please specify just one revision"))
4241 if not node:
4247 if not node:
4242 node = opts.get('rev')
4248 node = opts.get('rev')
4243
4249
4244 if node:
4250 if node:
4245 node = scmutil.revsingle(repo, node).node()
4251 node = scmutil.revsingle(repo, node).node()
4246
4252
4247 if not node and repo._bookmarkcurrent:
4253 if not node and repo._bookmarkcurrent:
4248 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4254 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4249 curhead = repo[repo._bookmarkcurrent]
4255 curhead = repo[repo._bookmarkcurrent]
4250 if len(bmheads) == 2:
4256 if len(bmheads) == 2:
4251 if curhead == bmheads[0]:
4257 if curhead == bmheads[0]:
4252 node = bmheads[1]
4258 node = bmheads[1]
4253 else:
4259 else:
4254 node = bmheads[0]
4260 node = bmheads[0]
4255 elif len(bmheads) > 2:
4261 elif len(bmheads) > 2:
4256 raise util.Abort(_("multiple matching bookmarks to merge - "
4262 raise util.Abort(_("multiple matching bookmarks to merge - "
4257 "please merge with an explicit rev or bookmark"),
4263 "please merge with an explicit rev or bookmark"),
4258 hint=_("run 'hg heads' to see all heads"))
4264 hint=_("run 'hg heads' to see all heads"))
4259 elif len(bmheads) <= 1:
4265 elif len(bmheads) <= 1:
4260 raise util.Abort(_("no matching bookmark to merge - "
4266 raise util.Abort(_("no matching bookmark to merge - "
4261 "please merge with an explicit rev or bookmark"),
4267 "please merge with an explicit rev or bookmark"),
4262 hint=_("run 'hg heads' to see all heads"))
4268 hint=_("run 'hg heads' to see all heads"))
4263
4269
4264 if not node and not repo._bookmarkcurrent:
4270 if not node and not repo._bookmarkcurrent:
4265 branch = repo[None].branch()
4271 branch = repo[None].branch()
4266 bheads = repo.branchheads(branch)
4272 bheads = repo.branchheads(branch)
4267 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4273 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4268
4274
4269 if len(nbhs) > 2:
4275 if len(nbhs) > 2:
4270 raise util.Abort(_("branch '%s' has %d heads - "
4276 raise util.Abort(_("branch '%s' has %d heads - "
4271 "please merge with an explicit rev")
4277 "please merge with an explicit rev")
4272 % (branch, len(bheads)),
4278 % (branch, len(bheads)),
4273 hint=_("run 'hg heads .' to see heads"))
4279 hint=_("run 'hg heads .' to see heads"))
4274
4280
4275 parent = repo.dirstate.p1()
4281 parent = repo.dirstate.p1()
4276 if len(nbhs) <= 1:
4282 if len(nbhs) <= 1:
4277 if len(bheads) > 1:
4283 if len(bheads) > 1:
4278 raise util.Abort(_("heads are bookmarked - "
4284 raise util.Abort(_("heads are bookmarked - "
4279 "please merge with an explicit rev"),
4285 "please merge with an explicit rev"),
4280 hint=_("run 'hg heads' to see all heads"))
4286 hint=_("run 'hg heads' to see all heads"))
4281 if len(repo.heads()) > 1:
4287 if len(repo.heads()) > 1:
4282 raise util.Abort(_("branch '%s' has one head - "
4288 raise util.Abort(_("branch '%s' has one head - "
4283 "please merge with an explicit rev")
4289 "please merge with an explicit rev")
4284 % branch,
4290 % branch,
4285 hint=_("run 'hg heads' to see all heads"))
4291 hint=_("run 'hg heads' to see all heads"))
4286 msg, hint = _('nothing to merge'), None
4292 msg, hint = _('nothing to merge'), None
4287 if parent != repo.lookup(branch):
4293 if parent != repo.lookup(branch):
4288 hint = _("use 'hg update' instead")
4294 hint = _("use 'hg update' instead")
4289 raise util.Abort(msg, hint=hint)
4295 raise util.Abort(msg, hint=hint)
4290
4296
4291 if parent not in bheads:
4297 if parent not in bheads:
4292 raise util.Abort(_('working directory not at a head revision'),
4298 raise util.Abort(_('working directory not at a head revision'),
4293 hint=_("use 'hg update' or merge with an "
4299 hint=_("use 'hg update' or merge with an "
4294 "explicit revision"))
4300 "explicit revision"))
4295 if parent == nbhs[0]:
4301 if parent == nbhs[0]:
4296 node = nbhs[-1]
4302 node = nbhs[-1]
4297 else:
4303 else:
4298 node = nbhs[0]
4304 node = nbhs[0]
4299
4305
4300 if opts.get('preview'):
4306 if opts.get('preview'):
4301 # find nodes that are ancestors of p2 but not of p1
4307 # find nodes that are ancestors of p2 but not of p1
4302 p1 = repo.lookup('.')
4308 p1 = repo.lookup('.')
4303 p2 = repo.lookup(node)
4309 p2 = repo.lookup(node)
4304 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4310 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4305
4311
4306 displayer = cmdutil.show_changeset(ui, repo, opts)
4312 displayer = cmdutil.show_changeset(ui, repo, opts)
4307 for node in nodes:
4313 for node in nodes:
4308 displayer.show(repo[node])
4314 displayer.show(repo[node])
4309 displayer.close()
4315 displayer.close()
4310 return 0
4316 return 0
4311
4317
4312 try:
4318 try:
4313 # ui.forcemerge is an internal variable, do not document
4319 # ui.forcemerge is an internal variable, do not document
4314 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4320 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4315 return hg.merge(repo, node, force=opts.get('force'))
4321 return hg.merge(repo, node, force=opts.get('force'))
4316 finally:
4322 finally:
4317 ui.setconfig('ui', 'forcemerge', '')
4323 ui.setconfig('ui', 'forcemerge', '')
4318
4324
4319 @command('outgoing|out',
4325 @command('outgoing|out',
4320 [('f', 'force', None, _('run even when the destination is unrelated')),
4326 [('f', 'force', None, _('run even when the destination is unrelated')),
4321 ('r', 'rev', [],
4327 ('r', 'rev', [],
4322 _('a changeset intended to be included in the destination'), _('REV')),
4328 _('a changeset intended to be included in the destination'), _('REV')),
4323 ('n', 'newest-first', None, _('show newest record first')),
4329 ('n', 'newest-first', None, _('show newest record first')),
4324 ('B', 'bookmarks', False, _('compare bookmarks')),
4330 ('B', 'bookmarks', False, _('compare bookmarks')),
4325 ('b', 'branch', [], _('a specific branch you would like to push'),
4331 ('b', 'branch', [], _('a specific branch you would like to push'),
4326 _('BRANCH')),
4332 _('BRANCH')),
4327 ] + logopts + remoteopts + subrepoopts,
4333 ] + logopts + remoteopts + subrepoopts,
4328 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4334 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4329 def outgoing(ui, repo, dest=None, **opts):
4335 def outgoing(ui, repo, dest=None, **opts):
4330 """show changesets not found in the destination
4336 """show changesets not found in the destination
4331
4337
4332 Show changesets not found in the specified destination repository
4338 Show changesets not found in the specified destination repository
4333 or the default push location. These are the changesets that would
4339 or the default push location. These are the changesets that would
4334 be pushed if a push was requested.
4340 be pushed if a push was requested.
4335
4341
4336 See pull for details of valid destination formats.
4342 See pull for details of valid destination formats.
4337
4343
4338 Returns 0 if there are outgoing changes, 1 otherwise.
4344 Returns 0 if there are outgoing changes, 1 otherwise.
4339 """
4345 """
4340 if opts.get('graph'):
4346 if opts.get('graph'):
4341 cmdutil.checkunsupportedgraphflags([], opts)
4347 cmdutil.checkunsupportedgraphflags([], opts)
4342 o = hg._outgoing(ui, repo, dest, opts)
4348 o = hg._outgoing(ui, repo, dest, opts)
4343 if o is None:
4349 if o is None:
4344 return
4350 return
4345
4351
4346 revdag = cmdutil.graphrevs(repo, o, opts)
4352 revdag = cmdutil.graphrevs(repo, o, opts)
4347 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4353 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4348 showparents = [ctx.node() for ctx in repo[None].parents()]
4354 showparents = [ctx.node() for ctx in repo[None].parents()]
4349 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4355 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4350 graphmod.asciiedges)
4356 graphmod.asciiedges)
4351 return 0
4357 return 0
4352
4358
4353 if opts.get('bookmarks'):
4359 if opts.get('bookmarks'):
4354 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4360 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4355 dest, branches = hg.parseurl(dest, opts.get('branch'))
4361 dest, branches = hg.parseurl(dest, opts.get('branch'))
4356 other = hg.peer(repo, opts, dest)
4362 other = hg.peer(repo, opts, dest)
4357 if 'bookmarks' not in other.listkeys('namespaces'):
4363 if 'bookmarks' not in other.listkeys('namespaces'):
4358 ui.warn(_("remote doesn't support bookmarks\n"))
4364 ui.warn(_("remote doesn't support bookmarks\n"))
4359 return 0
4365 return 0
4360 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4366 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4361 return bookmarks.diff(ui, other, repo)
4367 return bookmarks.diff(ui, other, repo)
4362
4368
4363 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4369 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4364 try:
4370 try:
4365 return hg.outgoing(ui, repo, dest, opts)
4371 return hg.outgoing(ui, repo, dest, opts)
4366 finally:
4372 finally:
4367 del repo._subtoppath
4373 del repo._subtoppath
4368
4374
4369 @command('parents',
4375 @command('parents',
4370 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4376 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4371 ] + templateopts,
4377 ] + templateopts,
4372 _('[-r REV] [FILE]'))
4378 _('[-r REV] [FILE]'))
4373 def parents(ui, repo, file_=None, **opts):
4379 def parents(ui, repo, file_=None, **opts):
4374 """show the parents of the working directory or revision
4380 """show the parents of the working directory or revision
4375
4381
4376 Print the working directory's parent revisions. If a revision is
4382 Print the working directory's parent revisions. If a revision is
4377 given via -r/--rev, the parent of that revision will be printed.
4383 given via -r/--rev, the parent of that revision will be printed.
4378 If a file argument is given, the revision in which the file was
4384 If a file argument is given, the revision in which the file was
4379 last changed (before the working directory revision or the
4385 last changed (before the working directory revision or the
4380 argument to --rev if given) is printed.
4386 argument to --rev if given) is printed.
4381
4387
4382 Returns 0 on success.
4388 Returns 0 on success.
4383 """
4389 """
4384
4390
4385 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4391 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4386
4392
4387 if file_:
4393 if file_:
4388 m = scmutil.match(ctx, (file_,), opts)
4394 m = scmutil.match(ctx, (file_,), opts)
4389 if m.anypats() or len(m.files()) != 1:
4395 if m.anypats() or len(m.files()) != 1:
4390 raise util.Abort(_('can only specify an explicit filename'))
4396 raise util.Abort(_('can only specify an explicit filename'))
4391 file_ = m.files()[0]
4397 file_ = m.files()[0]
4392 filenodes = []
4398 filenodes = []
4393 for cp in ctx.parents():
4399 for cp in ctx.parents():
4394 if not cp:
4400 if not cp:
4395 continue
4401 continue
4396 try:
4402 try:
4397 filenodes.append(cp.filenode(file_))
4403 filenodes.append(cp.filenode(file_))
4398 except error.LookupError:
4404 except error.LookupError:
4399 pass
4405 pass
4400 if not filenodes:
4406 if not filenodes:
4401 raise util.Abort(_("'%s' not found in manifest!") % file_)
4407 raise util.Abort(_("'%s' not found in manifest!") % file_)
4402 fl = repo.file(file_)
4408 fl = repo.file(file_)
4403 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4409 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4404 else:
4410 else:
4405 p = [cp.node() for cp in ctx.parents()]
4411 p = [cp.node() for cp in ctx.parents()]
4406
4412
4407 displayer = cmdutil.show_changeset(ui, repo, opts)
4413 displayer = cmdutil.show_changeset(ui, repo, opts)
4408 for n in p:
4414 for n in p:
4409 if n != nullid:
4415 if n != nullid:
4410 displayer.show(repo[n])
4416 displayer.show(repo[n])
4411 displayer.close()
4417 displayer.close()
4412
4418
4413 @command('paths', [], _('[NAME]'))
4419 @command('paths', [], _('[NAME]'))
4414 def paths(ui, repo, search=None):
4420 def paths(ui, repo, search=None):
4415 """show aliases for remote repositories
4421 """show aliases for remote repositories
4416
4422
4417 Show definition of symbolic path name NAME. If no name is given,
4423 Show definition of symbolic path name NAME. If no name is given,
4418 show definition of all available names.
4424 show definition of all available names.
4419
4425
4420 Option -q/--quiet suppresses all output when searching for NAME
4426 Option -q/--quiet suppresses all output when searching for NAME
4421 and shows only the path names when listing all definitions.
4427 and shows only the path names when listing all definitions.
4422
4428
4423 Path names are defined in the [paths] section of your
4429 Path names are defined in the [paths] section of your
4424 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4430 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4425 repository, ``.hg/hgrc`` is used, too.
4431 repository, ``.hg/hgrc`` is used, too.
4426
4432
4427 The path names ``default`` and ``default-push`` have a special
4433 The path names ``default`` and ``default-push`` have a special
4428 meaning. When performing a push or pull operation, they are used
4434 meaning. When performing a push or pull operation, they are used
4429 as fallbacks if no location is specified on the command-line.
4435 as fallbacks if no location is specified on the command-line.
4430 When ``default-push`` is set, it will be used for push and
4436 When ``default-push`` is set, it will be used for push and
4431 ``default`` will be used for pull; otherwise ``default`` is used
4437 ``default`` will be used for pull; otherwise ``default`` is used
4432 as the fallback for both. When cloning a repository, the clone
4438 as the fallback for both. When cloning a repository, the clone
4433 source is written as ``default`` in ``.hg/hgrc``. Note that
4439 source is written as ``default`` in ``.hg/hgrc``. Note that
4434 ``default`` and ``default-push`` apply to all inbound (e.g.
4440 ``default`` and ``default-push`` apply to all inbound (e.g.
4435 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4441 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4436 :hg:`bundle`) operations.
4442 :hg:`bundle`) operations.
4437
4443
4438 See :hg:`help urls` for more information.
4444 See :hg:`help urls` for more information.
4439
4445
4440 Returns 0 on success.
4446 Returns 0 on success.
4441 """
4447 """
4442 if search:
4448 if search:
4443 for name, path in ui.configitems("paths"):
4449 for name, path in ui.configitems("paths"):
4444 if name == search:
4450 if name == search:
4445 ui.status("%s\n" % util.hidepassword(path))
4451 ui.status("%s\n" % util.hidepassword(path))
4446 return
4452 return
4447 if not ui.quiet:
4453 if not ui.quiet:
4448 ui.warn(_("not found!\n"))
4454 ui.warn(_("not found!\n"))
4449 return 1
4455 return 1
4450 else:
4456 else:
4451 for name, path in ui.configitems("paths"):
4457 for name, path in ui.configitems("paths"):
4452 if ui.quiet:
4458 if ui.quiet:
4453 ui.write("%s\n" % name)
4459 ui.write("%s\n" % name)
4454 else:
4460 else:
4455 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4461 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4456
4462
4457 @command('^phase',
4463 @command('^phase',
4458 [('p', 'public', False, _('set changeset phase to public')),
4464 [('p', 'public', False, _('set changeset phase to public')),
4459 ('d', 'draft', False, _('set changeset phase to draft')),
4465 ('d', 'draft', False, _('set changeset phase to draft')),
4460 ('s', 'secret', False, _('set changeset phase to secret')),
4466 ('s', 'secret', False, _('set changeset phase to secret')),
4461 ('f', 'force', False, _('allow to move boundary backward')),
4467 ('f', 'force', False, _('allow to move boundary backward')),
4462 ('r', 'rev', [], _('target revision'), _('REV')),
4468 ('r', 'rev', [], _('target revision'), _('REV')),
4463 ],
4469 ],
4464 _('[-p|-d|-s] [-f] [-r] REV...'))
4470 _('[-p|-d|-s] [-f] [-r] REV...'))
4465 def phase(ui, repo, *revs, **opts):
4471 def phase(ui, repo, *revs, **opts):
4466 """set or show the current phase name
4472 """set or show the current phase name
4467
4473
4468 With no argument, show the phase name of specified revisions.
4474 With no argument, show the phase name of specified revisions.
4469
4475
4470 With one of -p/--public, -d/--draft or -s/--secret, change the
4476 With one of -p/--public, -d/--draft or -s/--secret, change the
4471 phase value of the specified revisions.
4477 phase value of the specified revisions.
4472
4478
4473 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4479 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4474 lower phase to an higher phase. Phases are ordered as follows::
4480 lower phase to an higher phase. Phases are ordered as follows::
4475
4481
4476 public < draft < secret
4482 public < draft < secret
4477
4483
4478 Return 0 on success, 1 if no phases were changed or some could not
4484 Return 0 on success, 1 if no phases were changed or some could not
4479 be changed.
4485 be changed.
4480 """
4486 """
4481 # search for a unique phase argument
4487 # search for a unique phase argument
4482 targetphase = None
4488 targetphase = None
4483 for idx, name in enumerate(phases.phasenames):
4489 for idx, name in enumerate(phases.phasenames):
4484 if opts[name]:
4490 if opts[name]:
4485 if targetphase is not None:
4491 if targetphase is not None:
4486 raise util.Abort(_('only one phase can be specified'))
4492 raise util.Abort(_('only one phase can be specified'))
4487 targetphase = idx
4493 targetphase = idx
4488
4494
4489 # look for specified revision
4495 # look for specified revision
4490 revs = list(revs)
4496 revs = list(revs)
4491 revs.extend(opts['rev'])
4497 revs.extend(opts['rev'])
4492 if not revs:
4498 if not revs:
4493 raise util.Abort(_('no revisions specified'))
4499 raise util.Abort(_('no revisions specified'))
4494
4500
4495 revs = scmutil.revrange(repo, revs)
4501 revs = scmutil.revrange(repo, revs)
4496
4502
4497 lock = None
4503 lock = None
4498 ret = 0
4504 ret = 0
4499 if targetphase is None:
4505 if targetphase is None:
4500 # display
4506 # display
4501 for r in revs:
4507 for r in revs:
4502 ctx = repo[r]
4508 ctx = repo[r]
4503 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4509 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4504 else:
4510 else:
4505 lock = repo.lock()
4511 lock = repo.lock()
4506 try:
4512 try:
4507 # set phase
4513 # set phase
4508 if not revs:
4514 if not revs:
4509 raise util.Abort(_('empty revision set'))
4515 raise util.Abort(_('empty revision set'))
4510 nodes = [repo[r].node() for r in revs]
4516 nodes = [repo[r].node() for r in revs]
4511 olddata = repo._phasecache.getphaserevs(repo)[:]
4517 olddata = repo._phasecache.getphaserevs(repo)[:]
4512 phases.advanceboundary(repo, targetphase, nodes)
4518 phases.advanceboundary(repo, targetphase, nodes)
4513 if opts['force']:
4519 if opts['force']:
4514 phases.retractboundary(repo, targetphase, nodes)
4520 phases.retractboundary(repo, targetphase, nodes)
4515 finally:
4521 finally:
4516 lock.release()
4522 lock.release()
4517 newdata = repo._phasecache.getphaserevs(repo)
4523 newdata = repo._phasecache.getphaserevs(repo)
4518 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4524 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4519 rejected = [n for n in nodes
4525 rejected = [n for n in nodes
4520 if newdata[repo[n].rev()] < targetphase]
4526 if newdata[repo[n].rev()] < targetphase]
4521 if rejected:
4527 if rejected:
4522 ui.warn(_('cannot move %i changesets to a more permissive '
4528 ui.warn(_('cannot move %i changesets to a more permissive '
4523 'phase, use --force\n') % len(rejected))
4529 'phase, use --force\n') % len(rejected))
4524 ret = 1
4530 ret = 1
4525 if changes:
4531 if changes:
4526 msg = _('phase changed for %i changesets\n') % changes
4532 msg = _('phase changed for %i changesets\n') % changes
4527 if ret:
4533 if ret:
4528 ui.status(msg)
4534 ui.status(msg)
4529 else:
4535 else:
4530 ui.note(msg)
4536 ui.note(msg)
4531 else:
4537 else:
4532 ui.warn(_('no phases changed\n'))
4538 ui.warn(_('no phases changed\n'))
4533 ret = 1
4539 ret = 1
4534 return ret
4540 return ret
4535
4541
4536 def postincoming(ui, repo, modheads, optupdate, checkout):
4542 def postincoming(ui, repo, modheads, optupdate, checkout):
4537 if modheads == 0:
4543 if modheads == 0:
4538 return
4544 return
4539 if optupdate:
4545 if optupdate:
4540 movemarkfrom = repo['.'].node()
4546 movemarkfrom = repo['.'].node()
4541 try:
4547 try:
4542 ret = hg.update(repo, checkout)
4548 ret = hg.update(repo, checkout)
4543 except util.Abort, inst:
4549 except util.Abort, inst:
4544 ui.warn(_("not updating: %s\n") % str(inst))
4550 ui.warn(_("not updating: %s\n") % str(inst))
4545 return 0
4551 return 0
4546 if not ret and not checkout:
4552 if not ret and not checkout:
4547 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4553 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4548 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4554 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4549 return ret
4555 return ret
4550 if modheads > 1:
4556 if modheads > 1:
4551 currentbranchheads = len(repo.branchheads())
4557 currentbranchheads = len(repo.branchheads())
4552 if currentbranchheads == modheads:
4558 if currentbranchheads == modheads:
4553 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4559 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4554 elif currentbranchheads > 1:
4560 elif currentbranchheads > 1:
4555 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4561 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4556 "merge)\n"))
4562 "merge)\n"))
4557 else:
4563 else:
4558 ui.status(_("(run 'hg heads' to see heads)\n"))
4564 ui.status(_("(run 'hg heads' to see heads)\n"))
4559 else:
4565 else:
4560 ui.status(_("(run 'hg update' to get a working copy)\n"))
4566 ui.status(_("(run 'hg update' to get a working copy)\n"))
4561
4567
4562 @command('^pull',
4568 @command('^pull',
4563 [('u', 'update', None,
4569 [('u', 'update', None,
4564 _('update to new branch head if changesets were pulled')),
4570 _('update to new branch head if changesets were pulled')),
4565 ('f', 'force', None, _('run even when remote repository is unrelated')),
4571 ('f', 'force', None, _('run even when remote repository is unrelated')),
4566 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4572 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4567 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4573 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4568 ('b', 'branch', [], _('a specific branch you would like to pull'),
4574 ('b', 'branch', [], _('a specific branch you would like to pull'),
4569 _('BRANCH')),
4575 _('BRANCH')),
4570 ] + remoteopts,
4576 ] + remoteopts,
4571 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4577 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4572 def pull(ui, repo, source="default", **opts):
4578 def pull(ui, repo, source="default", **opts):
4573 """pull changes from the specified source
4579 """pull changes from the specified source
4574
4580
4575 Pull changes from a remote repository to a local one.
4581 Pull changes from a remote repository to a local one.
4576
4582
4577 This finds all changes from the repository at the specified path
4583 This finds all changes from the repository at the specified path
4578 or URL and adds them to a local repository (the current one unless
4584 or URL and adds them to a local repository (the current one unless
4579 -R is specified). By default, this does not update the copy of the
4585 -R is specified). By default, this does not update the copy of the
4580 project in the working directory.
4586 project in the working directory.
4581
4587
4582 Use :hg:`incoming` if you want to see what would have been added
4588 Use :hg:`incoming` if you want to see what would have been added
4583 by a pull at the time you issued this command. If you then decide
4589 by a pull at the time you issued this command. If you then decide
4584 to add those changes to the repository, you should use :hg:`pull
4590 to add those changes to the repository, you should use :hg:`pull
4585 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4591 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4586
4592
4587 If SOURCE is omitted, the 'default' path will be used.
4593 If SOURCE is omitted, the 'default' path will be used.
4588 See :hg:`help urls` for more information.
4594 See :hg:`help urls` for more information.
4589
4595
4590 Returns 0 on success, 1 if an update had unresolved files.
4596 Returns 0 on success, 1 if an update had unresolved files.
4591 """
4597 """
4592 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4598 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4593 other = hg.peer(repo, opts, source)
4599 other = hg.peer(repo, opts, source)
4594 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4600 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4595 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4601 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4596
4602
4597 if opts.get('bookmark'):
4603 if opts.get('bookmark'):
4598 if not revs:
4604 if not revs:
4599 revs = []
4605 revs = []
4600 rb = other.listkeys('bookmarks')
4606 rb = other.listkeys('bookmarks')
4601 for b in opts['bookmark']:
4607 for b in opts['bookmark']:
4602 if b not in rb:
4608 if b not in rb:
4603 raise util.Abort(_('remote bookmark %s not found!') % b)
4609 raise util.Abort(_('remote bookmark %s not found!') % b)
4604 revs.append(rb[b])
4610 revs.append(rb[b])
4605
4611
4606 if revs:
4612 if revs:
4607 try:
4613 try:
4608 revs = [other.lookup(rev) for rev in revs]
4614 revs = [other.lookup(rev) for rev in revs]
4609 except error.CapabilityError:
4615 except error.CapabilityError:
4610 err = _("other repository doesn't support revision lookup, "
4616 err = _("other repository doesn't support revision lookup, "
4611 "so a rev cannot be specified.")
4617 "so a rev cannot be specified.")
4612 raise util.Abort(err)
4618 raise util.Abort(err)
4613
4619
4614 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4620 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4615 bookmarks.updatefromremote(ui, repo, other, source)
4621 bookmarks.updatefromremote(ui, repo, other, source)
4616 if checkout:
4622 if checkout:
4617 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4623 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4618 repo._subtoppath = source
4624 repo._subtoppath = source
4619 try:
4625 try:
4620 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4626 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4621
4627
4622 finally:
4628 finally:
4623 del repo._subtoppath
4629 del repo._subtoppath
4624
4630
4625 # update specified bookmarks
4631 # update specified bookmarks
4626 if opts.get('bookmark'):
4632 if opts.get('bookmark'):
4627 for b in opts['bookmark']:
4633 for b in opts['bookmark']:
4628 # explicit pull overrides local bookmark if any
4634 # explicit pull overrides local bookmark if any
4629 ui.status(_("importing bookmark %s\n") % b)
4635 ui.status(_("importing bookmark %s\n") % b)
4630 repo._bookmarks[b] = repo[rb[b]].node()
4636 repo._bookmarks[b] = repo[rb[b]].node()
4631 bookmarks.write(repo)
4637 bookmarks.write(repo)
4632
4638
4633 return ret
4639 return ret
4634
4640
4635 @command('^push',
4641 @command('^push',
4636 [('f', 'force', None, _('force push')),
4642 [('f', 'force', None, _('force push')),
4637 ('r', 'rev', [],
4643 ('r', 'rev', [],
4638 _('a changeset intended to be included in the destination'),
4644 _('a changeset intended to be included in the destination'),
4639 _('REV')),
4645 _('REV')),
4640 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4646 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4641 ('b', 'branch', [],
4647 ('b', 'branch', [],
4642 _('a specific branch you would like to push'), _('BRANCH')),
4648 _('a specific branch you would like to push'), _('BRANCH')),
4643 ('', 'new-branch', False, _('allow pushing a new branch')),
4649 ('', 'new-branch', False, _('allow pushing a new branch')),
4644 ] + remoteopts,
4650 ] + remoteopts,
4645 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4651 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4646 def push(ui, repo, dest=None, **opts):
4652 def push(ui, repo, dest=None, **opts):
4647 """push changes to the specified destination
4653 """push changes to the specified destination
4648
4654
4649 Push changesets from the local repository to the specified
4655 Push changesets from the local repository to the specified
4650 destination.
4656 destination.
4651
4657
4652 This operation is symmetrical to pull: it is identical to a pull
4658 This operation is symmetrical to pull: it is identical to a pull
4653 in the destination repository from the current one.
4659 in the destination repository from the current one.
4654
4660
4655 By default, push will not allow creation of new heads at the
4661 By default, push will not allow creation of new heads at the
4656 destination, since multiple heads would make it unclear which head
4662 destination, since multiple heads would make it unclear which head
4657 to use. In this situation, it is recommended to pull and merge
4663 to use. In this situation, it is recommended to pull and merge
4658 before pushing.
4664 before pushing.
4659
4665
4660 Use --new-branch if you want to allow push to create a new named
4666 Use --new-branch if you want to allow push to create a new named
4661 branch that is not present at the destination. This allows you to
4667 branch that is not present at the destination. This allows you to
4662 only create a new branch without forcing other changes.
4668 only create a new branch without forcing other changes.
4663
4669
4664 Use -f/--force to override the default behavior and push all
4670 Use -f/--force to override the default behavior and push all
4665 changesets on all branches.
4671 changesets on all branches.
4666
4672
4667 If -r/--rev is used, the specified revision and all its ancestors
4673 If -r/--rev is used, the specified revision and all its ancestors
4668 will be pushed to the remote repository.
4674 will be pushed to the remote repository.
4669
4675
4670 If -B/--bookmark is used, the specified bookmarked revision, its
4676 If -B/--bookmark is used, the specified bookmarked revision, its
4671 ancestors, and the bookmark will be pushed to the remote
4677 ancestors, and the bookmark will be pushed to the remote
4672 repository.
4678 repository.
4673
4679
4674 Please see :hg:`help urls` for important details about ``ssh://``
4680 Please see :hg:`help urls` for important details about ``ssh://``
4675 URLs. If DESTINATION is omitted, a default path will be used.
4681 URLs. If DESTINATION is omitted, a default path will be used.
4676
4682
4677 Returns 0 if push was successful, 1 if nothing to push.
4683 Returns 0 if push was successful, 1 if nothing to push.
4678 """
4684 """
4679
4685
4680 if opts.get('bookmark'):
4686 if opts.get('bookmark'):
4681 for b in opts['bookmark']:
4687 for b in opts['bookmark']:
4682 # translate -B options to -r so changesets get pushed
4688 # translate -B options to -r so changesets get pushed
4683 if b in repo._bookmarks:
4689 if b in repo._bookmarks:
4684 opts.setdefault('rev', []).append(b)
4690 opts.setdefault('rev', []).append(b)
4685 else:
4691 else:
4686 # if we try to push a deleted bookmark, translate it to null
4692 # if we try to push a deleted bookmark, translate it to null
4687 # this lets simultaneous -r, -b options continue working
4693 # this lets simultaneous -r, -b options continue working
4688 opts.setdefault('rev', []).append("null")
4694 opts.setdefault('rev', []).append("null")
4689
4695
4690 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4696 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4691 dest, branches = hg.parseurl(dest, opts.get('branch'))
4697 dest, branches = hg.parseurl(dest, opts.get('branch'))
4692 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4698 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4693 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4699 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4694 other = hg.peer(repo, opts, dest)
4700 other = hg.peer(repo, opts, dest)
4695 if revs:
4701 if revs:
4696 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4702 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4697
4703
4698 repo._subtoppath = dest
4704 repo._subtoppath = dest
4699 try:
4705 try:
4700 # push subrepos depth-first for coherent ordering
4706 # push subrepos depth-first for coherent ordering
4701 c = repo['']
4707 c = repo['']
4702 subs = c.substate # only repos that are committed
4708 subs = c.substate # only repos that are committed
4703 for s in sorted(subs):
4709 for s in sorted(subs):
4704 if c.sub(s).push(opts) == 0:
4710 if c.sub(s).push(opts) == 0:
4705 return False
4711 return False
4706 finally:
4712 finally:
4707 del repo._subtoppath
4713 del repo._subtoppath
4708 result = repo.push(other, opts.get('force'), revs=revs,
4714 result = repo.push(other, opts.get('force'), revs=revs,
4709 newbranch=opts.get('new_branch'))
4715 newbranch=opts.get('new_branch'))
4710
4716
4711 result = not result
4717 result = not result
4712
4718
4713 if opts.get('bookmark'):
4719 if opts.get('bookmark'):
4714 rb = other.listkeys('bookmarks')
4720 rb = other.listkeys('bookmarks')
4715 for b in opts['bookmark']:
4721 for b in opts['bookmark']:
4716 # explicit push overrides remote bookmark if any
4722 # explicit push overrides remote bookmark if any
4717 if b in repo._bookmarks:
4723 if b in repo._bookmarks:
4718 ui.status(_("exporting bookmark %s\n") % b)
4724 ui.status(_("exporting bookmark %s\n") % b)
4719 new = repo[b].hex()
4725 new = repo[b].hex()
4720 elif b in rb:
4726 elif b in rb:
4721 ui.status(_("deleting remote bookmark %s\n") % b)
4727 ui.status(_("deleting remote bookmark %s\n") % b)
4722 new = '' # delete
4728 new = '' # delete
4723 else:
4729 else:
4724 ui.warn(_('bookmark %s does not exist on the local '
4730 ui.warn(_('bookmark %s does not exist on the local '
4725 'or remote repository!\n') % b)
4731 'or remote repository!\n') % b)
4726 return 2
4732 return 2
4727 old = rb.get(b, '')
4733 old = rb.get(b, '')
4728 r = other.pushkey('bookmarks', b, old, new)
4734 r = other.pushkey('bookmarks', b, old, new)
4729 if not r:
4735 if not r:
4730 ui.warn(_('updating bookmark %s failed!\n') % b)
4736 ui.warn(_('updating bookmark %s failed!\n') % b)
4731 if not result:
4737 if not result:
4732 result = 2
4738 result = 2
4733
4739
4734 return result
4740 return result
4735
4741
4736 @command('recover', [])
4742 @command('recover', [])
4737 def recover(ui, repo):
4743 def recover(ui, repo):
4738 """roll back an interrupted transaction
4744 """roll back an interrupted transaction
4739
4745
4740 Recover from an interrupted commit or pull.
4746 Recover from an interrupted commit or pull.
4741
4747
4742 This command tries to fix the repository status after an
4748 This command tries to fix the repository status after an
4743 interrupted operation. It should only be necessary when Mercurial
4749 interrupted operation. It should only be necessary when Mercurial
4744 suggests it.
4750 suggests it.
4745
4751
4746 Returns 0 if successful, 1 if nothing to recover or verify fails.
4752 Returns 0 if successful, 1 if nothing to recover or verify fails.
4747 """
4753 """
4748 if repo.recover():
4754 if repo.recover():
4749 return hg.verify(repo)
4755 return hg.verify(repo)
4750 return 1
4756 return 1
4751
4757
4752 @command('^remove|rm',
4758 @command('^remove|rm',
4753 [('A', 'after', None, _('record delete for missing files')),
4759 [('A', 'after', None, _('record delete for missing files')),
4754 ('f', 'force', None,
4760 ('f', 'force', None,
4755 _('remove (and delete) file even if added or modified')),
4761 _('remove (and delete) file even if added or modified')),
4756 ] + walkopts,
4762 ] + walkopts,
4757 _('[OPTION]... FILE...'))
4763 _('[OPTION]... FILE...'))
4758 def remove(ui, repo, *pats, **opts):
4764 def remove(ui, repo, *pats, **opts):
4759 """remove the specified files on the next commit
4765 """remove the specified files on the next commit
4760
4766
4761 Schedule the indicated files for removal from the current branch.
4767 Schedule the indicated files for removal from the current branch.
4762
4768
4763 This command schedules the files to be removed at the next commit.
4769 This command schedules the files to be removed at the next commit.
4764 To undo a remove before that, see :hg:`revert`. To undo added
4770 To undo a remove before that, see :hg:`revert`. To undo added
4765 files, see :hg:`forget`.
4771 files, see :hg:`forget`.
4766
4772
4767 .. container:: verbose
4773 .. container:: verbose
4768
4774
4769 -A/--after can be used to remove only files that have already
4775 -A/--after can be used to remove only files that have already
4770 been deleted, -f/--force can be used to force deletion, and -Af
4776 been deleted, -f/--force can be used to force deletion, and -Af
4771 can be used to remove files from the next revision without
4777 can be used to remove files from the next revision without
4772 deleting them from the working directory.
4778 deleting them from the working directory.
4773
4779
4774 The following table details the behavior of remove for different
4780 The following table details the behavior of remove for different
4775 file states (columns) and option combinations (rows). The file
4781 file states (columns) and option combinations (rows). The file
4776 states are Added [A], Clean [C], Modified [M] and Missing [!]
4782 states are Added [A], Clean [C], Modified [M] and Missing [!]
4777 (as reported by :hg:`status`). The actions are Warn, Remove
4783 (as reported by :hg:`status`). The actions are Warn, Remove
4778 (from branch) and Delete (from disk):
4784 (from branch) and Delete (from disk):
4779
4785
4780 ======= == == == ==
4786 ======= == == == ==
4781 A C M !
4787 A C M !
4782 ======= == == == ==
4788 ======= == == == ==
4783 none W RD W R
4789 none W RD W R
4784 -f R RD RD R
4790 -f R RD RD R
4785 -A W W W R
4791 -A W W W R
4786 -Af R R R R
4792 -Af R R R R
4787 ======= == == == ==
4793 ======= == == == ==
4788
4794
4789 Note that remove never deletes files in Added [A] state from the
4795 Note that remove never deletes files in Added [A] state from the
4790 working directory, not even if option --force is specified.
4796 working directory, not even if option --force is specified.
4791
4797
4792 Returns 0 on success, 1 if any warnings encountered.
4798 Returns 0 on success, 1 if any warnings encountered.
4793 """
4799 """
4794
4800
4795 ret = 0
4801 ret = 0
4796 after, force = opts.get('after'), opts.get('force')
4802 after, force = opts.get('after'), opts.get('force')
4797 if not pats and not after:
4803 if not pats and not after:
4798 raise util.Abort(_('no files specified'))
4804 raise util.Abort(_('no files specified'))
4799
4805
4800 m = scmutil.match(repo[None], pats, opts)
4806 m = scmutil.match(repo[None], pats, opts)
4801 s = repo.status(match=m, clean=True)
4807 s = repo.status(match=m, clean=True)
4802 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4808 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4803
4809
4804 for f in m.files():
4810 for f in m.files():
4805 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4811 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4806 if os.path.exists(m.rel(f)):
4812 if os.path.exists(m.rel(f)):
4807 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4813 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4808 ret = 1
4814 ret = 1
4809
4815
4810 if force:
4816 if force:
4811 list = modified + deleted + clean + added
4817 list = modified + deleted + clean + added
4812 elif after:
4818 elif after:
4813 list = deleted
4819 list = deleted
4814 for f in modified + added + clean:
4820 for f in modified + added + clean:
4815 ui.warn(_('not removing %s: file still exists (use -f'
4821 ui.warn(_('not removing %s: file still exists (use -f'
4816 ' to force removal)\n') % m.rel(f))
4822 ' to force removal)\n') % m.rel(f))
4817 ret = 1
4823 ret = 1
4818 else:
4824 else:
4819 list = deleted + clean
4825 list = deleted + clean
4820 for f in modified:
4826 for f in modified:
4821 ui.warn(_('not removing %s: file is modified (use -f'
4827 ui.warn(_('not removing %s: file is modified (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 for f in added:
4830 for f in added:
4825 ui.warn(_('not removing %s: file has been marked for add'
4831 ui.warn(_('not removing %s: file has been marked for add'
4826 ' (use forget to undo)\n') % m.rel(f))
4832 ' (use forget to undo)\n') % m.rel(f))
4827 ret = 1
4833 ret = 1
4828
4834
4829 for f in sorted(list):
4835 for f in sorted(list):
4830 if ui.verbose or not m.exact(f):
4836 if ui.verbose or not m.exact(f):
4831 ui.status(_('removing %s\n') % m.rel(f))
4837 ui.status(_('removing %s\n') % m.rel(f))
4832
4838
4833 wlock = repo.wlock()
4839 wlock = repo.wlock()
4834 try:
4840 try:
4835 if not after:
4841 if not after:
4836 for f in list:
4842 for f in list:
4837 if f in added:
4843 if f in added:
4838 continue # we never unlink added files on remove
4844 continue # we never unlink added files on remove
4839 try:
4845 try:
4840 util.unlinkpath(repo.wjoin(f))
4846 util.unlinkpath(repo.wjoin(f))
4841 except OSError, inst:
4847 except OSError, inst:
4842 if inst.errno != errno.ENOENT:
4848 if inst.errno != errno.ENOENT:
4843 raise
4849 raise
4844 repo[None].forget(list)
4850 repo[None].forget(list)
4845 finally:
4851 finally:
4846 wlock.release()
4852 wlock.release()
4847
4853
4848 return ret
4854 return ret
4849
4855
4850 @command('rename|move|mv',
4856 @command('rename|move|mv',
4851 [('A', 'after', None, _('record a rename that has already occurred')),
4857 [('A', 'after', None, _('record a rename that has already occurred')),
4852 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4858 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4853 ] + walkopts + dryrunopts,
4859 ] + walkopts + dryrunopts,
4854 _('[OPTION]... SOURCE... DEST'))
4860 _('[OPTION]... SOURCE... DEST'))
4855 def rename(ui, repo, *pats, **opts):
4861 def rename(ui, repo, *pats, **opts):
4856 """rename files; equivalent of copy + remove
4862 """rename files; equivalent of copy + remove
4857
4863
4858 Mark dest as copies of sources; mark sources for deletion. If dest
4864 Mark dest as copies of sources; mark sources for deletion. If dest
4859 is a directory, copies are put in that directory. If dest is a
4865 is a directory, copies are put in that directory. If dest is a
4860 file, there can only be one source.
4866 file, there can only be one source.
4861
4867
4862 By default, this command copies the contents of files as they
4868 By default, this command copies the contents of files as they
4863 exist in the working directory. If invoked with -A/--after, the
4869 exist in the working directory. If invoked with -A/--after, the
4864 operation is recorded, but no copying is performed.
4870 operation is recorded, but no copying is performed.
4865
4871
4866 This command takes effect at the next commit. To undo a rename
4872 This command takes effect at the next commit. To undo a rename
4867 before that, see :hg:`revert`.
4873 before that, see :hg:`revert`.
4868
4874
4869 Returns 0 on success, 1 if errors are encountered.
4875 Returns 0 on success, 1 if errors are encountered.
4870 """
4876 """
4871 wlock = repo.wlock(False)
4877 wlock = repo.wlock(False)
4872 try:
4878 try:
4873 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4879 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4874 finally:
4880 finally:
4875 wlock.release()
4881 wlock.release()
4876
4882
4877 @command('resolve',
4883 @command('resolve',
4878 [('a', 'all', None, _('select all unresolved files')),
4884 [('a', 'all', None, _('select all unresolved files')),
4879 ('l', 'list', None, _('list state of files needing merge')),
4885 ('l', 'list', None, _('list state of files needing merge')),
4880 ('m', 'mark', None, _('mark files as resolved')),
4886 ('m', 'mark', None, _('mark files as resolved')),
4881 ('u', 'unmark', None, _('mark files as unresolved')),
4887 ('u', 'unmark', None, _('mark files as unresolved')),
4882 ('n', 'no-status', None, _('hide status prefix'))]
4888 ('n', 'no-status', None, _('hide status prefix'))]
4883 + mergetoolopts + walkopts,
4889 + mergetoolopts + walkopts,
4884 _('[OPTION]... [FILE]...'))
4890 _('[OPTION]... [FILE]...'))
4885 def resolve(ui, repo, *pats, **opts):
4891 def resolve(ui, repo, *pats, **opts):
4886 """redo merges or set/view the merge status of files
4892 """redo merges or set/view the merge status of files
4887
4893
4888 Merges with unresolved conflicts are often the result of
4894 Merges with unresolved conflicts are often the result of
4889 non-interactive merging using the ``internal:merge`` configuration
4895 non-interactive merging using the ``internal:merge`` configuration
4890 setting, or a command-line merge tool like ``diff3``. The resolve
4896 setting, or a command-line merge tool like ``diff3``. The resolve
4891 command is used to manage the files involved in a merge, after
4897 command is used to manage the files involved in a merge, after
4892 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4898 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4893 working directory must have two parents). See :hg:`help
4899 working directory must have two parents). See :hg:`help
4894 merge-tools` for information on configuring merge tools.
4900 merge-tools` for information on configuring merge tools.
4895
4901
4896 The resolve command can be used in the following ways:
4902 The resolve command can be used in the following ways:
4897
4903
4898 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4904 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4899 files, discarding any previous merge attempts. Re-merging is not
4905 files, discarding any previous merge attempts. Re-merging is not
4900 performed for files already marked as resolved. Use ``--all/-a``
4906 performed for files already marked as resolved. Use ``--all/-a``
4901 to select all unresolved files. ``--tool`` can be used to specify
4907 to select all unresolved files. ``--tool`` can be used to specify
4902 the merge tool used for the given files. It overrides the HGMERGE
4908 the merge tool used for the given files. It overrides the HGMERGE
4903 environment variable and your configuration files. Previous file
4909 environment variable and your configuration files. Previous file
4904 contents are saved with a ``.orig`` suffix.
4910 contents are saved with a ``.orig`` suffix.
4905
4911
4906 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4912 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4907 (e.g. after having manually fixed-up the files). The default is
4913 (e.g. after having manually fixed-up the files). The default is
4908 to mark all unresolved files.
4914 to mark all unresolved files.
4909
4915
4910 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4916 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4911 default is to mark all resolved files.
4917 default is to mark all resolved files.
4912
4918
4913 - :hg:`resolve -l`: list files which had or still have conflicts.
4919 - :hg:`resolve -l`: list files which had or still have conflicts.
4914 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4920 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4915
4921
4916 Note that Mercurial will not let you commit files with unresolved
4922 Note that Mercurial will not let you commit files with unresolved
4917 merge conflicts. You must use :hg:`resolve -m ...` before you can
4923 merge conflicts. You must use :hg:`resolve -m ...` before you can
4918 commit after a conflicting merge.
4924 commit after a conflicting merge.
4919
4925
4920 Returns 0 on success, 1 if any files fail a resolve attempt.
4926 Returns 0 on success, 1 if any files fail a resolve attempt.
4921 """
4927 """
4922
4928
4923 all, mark, unmark, show, nostatus = \
4929 all, mark, unmark, show, nostatus = \
4924 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4930 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4925
4931
4926 if (show and (mark or unmark)) or (mark and unmark):
4932 if (show and (mark or unmark)) or (mark and unmark):
4927 raise util.Abort(_("too many options specified"))
4933 raise util.Abort(_("too many options specified"))
4928 if pats and all:
4934 if pats and all:
4929 raise util.Abort(_("can't specify --all and patterns"))
4935 raise util.Abort(_("can't specify --all and patterns"))
4930 if not (all or pats or show or mark or unmark):
4936 if not (all or pats or show or mark or unmark):
4931 raise util.Abort(_('no files or directories specified; '
4937 raise util.Abort(_('no files or directories specified; '
4932 'use --all to remerge all files'))
4938 'use --all to remerge all files'))
4933
4939
4934 ms = mergemod.mergestate(repo)
4940 ms = mergemod.mergestate(repo)
4935 m = scmutil.match(repo[None], pats, opts)
4941 m = scmutil.match(repo[None], pats, opts)
4936 ret = 0
4942 ret = 0
4937
4943
4938 for f in ms:
4944 for f in ms:
4939 if m(f):
4945 if m(f):
4940 if show:
4946 if show:
4941 if nostatus:
4947 if nostatus:
4942 ui.write("%s\n" % f)
4948 ui.write("%s\n" % f)
4943 else:
4949 else:
4944 ui.write("%s %s\n" % (ms[f].upper(), f),
4950 ui.write("%s %s\n" % (ms[f].upper(), f),
4945 label='resolve.' +
4951 label='resolve.' +
4946 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4952 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4947 elif mark:
4953 elif mark:
4948 ms.mark(f, "r")
4954 ms.mark(f, "r")
4949 elif unmark:
4955 elif unmark:
4950 ms.mark(f, "u")
4956 ms.mark(f, "u")
4951 else:
4957 else:
4952 wctx = repo[None]
4958 wctx = repo[None]
4953 mctx = wctx.parents()[-1]
4959 mctx = wctx.parents()[-1]
4954
4960
4955 # backup pre-resolve (merge uses .orig for its own purposes)
4961 # backup pre-resolve (merge uses .orig for its own purposes)
4956 a = repo.wjoin(f)
4962 a = repo.wjoin(f)
4957 util.copyfile(a, a + ".resolve")
4963 util.copyfile(a, a + ".resolve")
4958
4964
4959 try:
4965 try:
4960 # resolve file
4966 # resolve file
4961 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4967 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4962 if ms.resolve(f, wctx, mctx):
4968 if ms.resolve(f, wctx, mctx):
4963 ret = 1
4969 ret = 1
4964 finally:
4970 finally:
4965 ui.setconfig('ui', 'forcemerge', '')
4971 ui.setconfig('ui', 'forcemerge', '')
4966
4972
4967 # replace filemerge's .orig file with our resolve file
4973 # replace filemerge's .orig file with our resolve file
4968 util.rename(a + ".resolve", a + ".orig")
4974 util.rename(a + ".resolve", a + ".orig")
4969
4975
4970 ms.commit()
4976 ms.commit()
4971 return ret
4977 return ret
4972
4978
4973 @command('revert',
4979 @command('revert',
4974 [('a', 'all', None, _('revert all changes when no arguments given')),
4980 [('a', 'all', None, _('revert all changes when no arguments given')),
4975 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4981 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4976 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4982 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4977 ('C', 'no-backup', None, _('do not save backup copies of files')),
4983 ('C', 'no-backup', None, _('do not save backup copies of files')),
4978 ] + walkopts + dryrunopts,
4984 ] + walkopts + dryrunopts,
4979 _('[OPTION]... [-r REV] [NAME]...'))
4985 _('[OPTION]... [-r REV] [NAME]...'))
4980 def revert(ui, repo, *pats, **opts):
4986 def revert(ui, repo, *pats, **opts):
4981 """restore files to their checkout state
4987 """restore files to their checkout state
4982
4988
4983 .. note::
4989 .. note::
4984
4990
4985 To check out earlier revisions, you should use :hg:`update REV`.
4991 To check out earlier revisions, you should use :hg:`update REV`.
4986 To cancel an uncommitted merge (and lose your changes), use
4992 To cancel an uncommitted merge (and lose your changes), use
4987 :hg:`update --clean .`.
4993 :hg:`update --clean .`.
4988
4994
4989 With no revision specified, revert the specified files or directories
4995 With no revision specified, revert the specified files or directories
4990 to the contents they had in the parent of the working directory.
4996 to the contents they had in the parent of the working directory.
4991 This restores the contents of files to an unmodified
4997 This restores the contents of files to an unmodified
4992 state and unschedules adds, removes, copies, and renames. If the
4998 state and unschedules adds, removes, copies, and renames. If the
4993 working directory has two parents, you must explicitly specify a
4999 working directory has two parents, you must explicitly specify a
4994 revision.
5000 revision.
4995
5001
4996 Using the -r/--rev or -d/--date options, revert the given files or
5002 Using the -r/--rev or -d/--date options, revert the given files or
4997 directories to their states as of a specific revision. Because
5003 directories to their states as of a specific revision. Because
4998 revert does not change the working directory parents, this will
5004 revert does not change the working directory parents, this will
4999 cause these files to appear modified. This can be helpful to "back
5005 cause these files to appear modified. This can be helpful to "back
5000 out" some or all of an earlier change. See :hg:`backout` for a
5006 out" some or all of an earlier change. See :hg:`backout` for a
5001 related method.
5007 related method.
5002
5008
5003 Modified files are saved with a .orig suffix before reverting.
5009 Modified files are saved with a .orig suffix before reverting.
5004 To disable these backups, use --no-backup.
5010 To disable these backups, use --no-backup.
5005
5011
5006 See :hg:`help dates` for a list of formats valid for -d/--date.
5012 See :hg:`help dates` for a list of formats valid for -d/--date.
5007
5013
5008 Returns 0 on success.
5014 Returns 0 on success.
5009 """
5015 """
5010
5016
5011 if opts.get("date"):
5017 if opts.get("date"):
5012 if opts.get("rev"):
5018 if opts.get("rev"):
5013 raise util.Abort(_("you can't specify a revision and a date"))
5019 raise util.Abort(_("you can't specify a revision and a date"))
5014 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5020 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5015
5021
5016 parent, p2 = repo.dirstate.parents()
5022 parent, p2 = repo.dirstate.parents()
5017 if not opts.get('rev') and p2 != nullid:
5023 if not opts.get('rev') and p2 != nullid:
5018 # revert after merge is a trap for new users (issue2915)
5024 # revert after merge is a trap for new users (issue2915)
5019 raise util.Abort(_('uncommitted merge with no revision specified'),
5025 raise util.Abort(_('uncommitted merge with no revision specified'),
5020 hint=_('use "hg update" or see "hg help revert"'))
5026 hint=_('use "hg update" or see "hg help revert"'))
5021
5027
5022 ctx = scmutil.revsingle(repo, opts.get('rev'))
5028 ctx = scmutil.revsingle(repo, opts.get('rev'))
5023
5029
5024 if not pats and not opts.get('all'):
5030 if not pats and not opts.get('all'):
5025 msg = _("no files or directories specified")
5031 msg = _("no files or directories specified")
5026 if p2 != nullid:
5032 if p2 != nullid:
5027 hint = _("uncommitted merge, use --all to discard all changes,"
5033 hint = _("uncommitted merge, use --all to discard all changes,"
5028 " or 'hg update -C .' to abort the merge")
5034 " or 'hg update -C .' to abort the merge")
5029 raise util.Abort(msg, hint=hint)
5035 raise util.Abort(msg, hint=hint)
5030 dirty = util.any(repo.status())
5036 dirty = util.any(repo.status())
5031 node = ctx.node()
5037 node = ctx.node()
5032 if node != parent:
5038 if node != parent:
5033 if dirty:
5039 if dirty:
5034 hint = _("uncommitted changes, use --all to discard all"
5040 hint = _("uncommitted changes, use --all to discard all"
5035 " changes, or 'hg update %s' to update") % ctx.rev()
5041 " changes, or 'hg update %s' to update") % ctx.rev()
5036 else:
5042 else:
5037 hint = _("use --all to revert all files,"
5043 hint = _("use --all to revert all files,"
5038 " or 'hg update %s' to update") % ctx.rev()
5044 " or 'hg update %s' to update") % ctx.rev()
5039 elif dirty:
5045 elif dirty:
5040 hint = _("uncommitted changes, use --all to discard all changes")
5046 hint = _("uncommitted changes, use --all to discard all changes")
5041 else:
5047 else:
5042 hint = _("use --all to revert all files")
5048 hint = _("use --all to revert all files")
5043 raise util.Abort(msg, hint=hint)
5049 raise util.Abort(msg, hint=hint)
5044
5050
5045 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5051 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5046
5052
5047 @command('rollback', dryrunopts +
5053 @command('rollback', dryrunopts +
5048 [('f', 'force', False, _('ignore safety measures'))])
5054 [('f', 'force', False, _('ignore safety measures'))])
5049 def rollback(ui, repo, **opts):
5055 def rollback(ui, repo, **opts):
5050 """roll back the last transaction (dangerous)
5056 """roll back the last transaction (dangerous)
5051
5057
5052 This command should be used with care. There is only one level of
5058 This command should be used with care. There is only one level of
5053 rollback, and there is no way to undo a rollback. It will also
5059 rollback, and there is no way to undo a rollback. It will also
5054 restore the dirstate at the time of the last transaction, losing
5060 restore the dirstate at the time of the last transaction, losing
5055 any dirstate changes since that time. This command does not alter
5061 any dirstate changes since that time. This command does not alter
5056 the working directory.
5062 the working directory.
5057
5063
5058 Transactions are used to encapsulate the effects of all commands
5064 Transactions are used to encapsulate the effects of all commands
5059 that create new changesets or propagate existing changesets into a
5065 that create new changesets or propagate existing changesets into a
5060 repository.
5066 repository.
5061
5067
5062 .. container:: verbose
5068 .. container:: verbose
5063
5069
5064 For example, the following commands are transactional, and their
5070 For example, the following commands are transactional, and their
5065 effects can be rolled back:
5071 effects can be rolled back:
5066
5072
5067 - commit
5073 - commit
5068 - import
5074 - import
5069 - pull
5075 - pull
5070 - push (with this repository as the destination)
5076 - push (with this repository as the destination)
5071 - unbundle
5077 - unbundle
5072
5078
5073 To avoid permanent data loss, rollback will refuse to rollback a
5079 To avoid permanent data loss, rollback will refuse to rollback a
5074 commit transaction if it isn't checked out. Use --force to
5080 commit transaction if it isn't checked out. Use --force to
5075 override this protection.
5081 override this protection.
5076
5082
5077 This command is not intended for use on public repositories. Once
5083 This command is not intended for use on public repositories. Once
5078 changes are visible for pull by other users, rolling a transaction
5084 changes are visible for pull by other users, rolling a transaction
5079 back locally is ineffective (someone else may already have pulled
5085 back locally is ineffective (someone else may already have pulled
5080 the changes). Furthermore, a race is possible with readers of the
5086 the changes). Furthermore, a race is possible with readers of the
5081 repository; for example an in-progress pull from the repository
5087 repository; for example an in-progress pull from the repository
5082 may fail if a rollback is performed.
5088 may fail if a rollback is performed.
5083
5089
5084 Returns 0 on success, 1 if no rollback data is available.
5090 Returns 0 on success, 1 if no rollback data is available.
5085 """
5091 """
5086 return repo.rollback(dryrun=opts.get('dry_run'),
5092 return repo.rollback(dryrun=opts.get('dry_run'),
5087 force=opts.get('force'))
5093 force=opts.get('force'))
5088
5094
5089 @command('root', [])
5095 @command('root', [])
5090 def root(ui, repo):
5096 def root(ui, repo):
5091 """print the root (top) of the current working directory
5097 """print the root (top) of the current working directory
5092
5098
5093 Print the root directory of the current repository.
5099 Print the root directory of the current repository.
5094
5100
5095 Returns 0 on success.
5101 Returns 0 on success.
5096 """
5102 """
5097 ui.write(repo.root + "\n")
5103 ui.write(repo.root + "\n")
5098
5104
5099 @command('^serve',
5105 @command('^serve',
5100 [('A', 'accesslog', '', _('name of access log file to write to'),
5106 [('A', 'accesslog', '', _('name of access log file to write to'),
5101 _('FILE')),
5107 _('FILE')),
5102 ('d', 'daemon', None, _('run server in background')),
5108 ('d', 'daemon', None, _('run server in background')),
5103 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5109 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5104 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5110 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5105 # use string type, then we can check if something was passed
5111 # use string type, then we can check if something was passed
5106 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5112 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5107 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5113 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5108 _('ADDR')),
5114 _('ADDR')),
5109 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5115 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5110 _('PREFIX')),
5116 _('PREFIX')),
5111 ('n', 'name', '',
5117 ('n', 'name', '',
5112 _('name to show in web pages (default: working directory)'), _('NAME')),
5118 _('name to show in web pages (default: working directory)'), _('NAME')),
5113 ('', 'web-conf', '',
5119 ('', 'web-conf', '',
5114 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5120 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5115 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5121 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5116 _('FILE')),
5122 _('FILE')),
5117 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5123 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5118 ('', 'stdio', None, _('for remote clients')),
5124 ('', 'stdio', None, _('for remote clients')),
5119 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5125 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5120 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5126 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5121 ('', 'style', '', _('template style to use'), _('STYLE')),
5127 ('', 'style', '', _('template style to use'), _('STYLE')),
5122 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5128 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5123 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5129 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5124 _('[OPTION]...'))
5130 _('[OPTION]...'))
5125 def serve(ui, repo, **opts):
5131 def serve(ui, repo, **opts):
5126 """start stand-alone webserver
5132 """start stand-alone webserver
5127
5133
5128 Start a local HTTP repository browser and pull server. You can use
5134 Start a local HTTP repository browser and pull server. You can use
5129 this for ad-hoc sharing and browsing of repositories. It is
5135 this for ad-hoc sharing and browsing of repositories. It is
5130 recommended to use a real web server to serve a repository for
5136 recommended to use a real web server to serve a repository for
5131 longer periods of time.
5137 longer periods of time.
5132
5138
5133 Please note that the server does not implement access control.
5139 Please note that the server does not implement access control.
5134 This means that, by default, anybody can read from the server and
5140 This means that, by default, anybody can read from the server and
5135 nobody can write to it by default. Set the ``web.allow_push``
5141 nobody can write to it by default. Set the ``web.allow_push``
5136 option to ``*`` to allow everybody to push to the server. You
5142 option to ``*`` to allow everybody to push to the server. You
5137 should use a real web server if you need to authenticate users.
5143 should use a real web server if you need to authenticate users.
5138
5144
5139 By default, the server logs accesses to stdout and errors to
5145 By default, the server logs accesses to stdout and errors to
5140 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5146 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5141 files.
5147 files.
5142
5148
5143 To have the server choose a free port number to listen on, specify
5149 To have the server choose a free port number to listen on, specify
5144 a port number of 0; in this case, the server will print the port
5150 a port number of 0; in this case, the server will print the port
5145 number it uses.
5151 number it uses.
5146
5152
5147 Returns 0 on success.
5153 Returns 0 on success.
5148 """
5154 """
5149
5155
5150 if opts["stdio"] and opts["cmdserver"]:
5156 if opts["stdio"] and opts["cmdserver"]:
5151 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5157 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5152
5158
5153 def checkrepo():
5159 def checkrepo():
5154 if repo is None:
5160 if repo is None:
5155 raise error.RepoError(_("there is no Mercurial repository here"
5161 raise error.RepoError(_("there is no Mercurial repository here"
5156 " (.hg not found)"))
5162 " (.hg not found)"))
5157
5163
5158 if opts["stdio"]:
5164 if opts["stdio"]:
5159 checkrepo()
5165 checkrepo()
5160 s = sshserver.sshserver(ui, repo)
5166 s = sshserver.sshserver(ui, repo)
5161 s.serve_forever()
5167 s.serve_forever()
5162
5168
5163 if opts["cmdserver"]:
5169 if opts["cmdserver"]:
5164 checkrepo()
5170 checkrepo()
5165 s = commandserver.server(ui, repo, opts["cmdserver"])
5171 s = commandserver.server(ui, repo, opts["cmdserver"])
5166 return s.serve()
5172 return s.serve()
5167
5173
5168 # this way we can check if something was given in the command-line
5174 # this way we can check if something was given in the command-line
5169 if opts.get('port'):
5175 if opts.get('port'):
5170 opts['port'] = util.getport(opts.get('port'))
5176 opts['port'] = util.getport(opts.get('port'))
5171
5177
5172 baseui = repo and repo.baseui or ui
5178 baseui = repo and repo.baseui or ui
5173 optlist = ("name templates style address port prefix ipv6"
5179 optlist = ("name templates style address port prefix ipv6"
5174 " accesslog errorlog certificate encoding")
5180 " accesslog errorlog certificate encoding")
5175 for o in optlist.split():
5181 for o in optlist.split():
5176 val = opts.get(o, '')
5182 val = opts.get(o, '')
5177 if val in (None, ''): # should check against default options instead
5183 if val in (None, ''): # should check against default options instead
5178 continue
5184 continue
5179 baseui.setconfig("web", o, val)
5185 baseui.setconfig("web", o, val)
5180 if repo and repo.ui != baseui:
5186 if repo and repo.ui != baseui:
5181 repo.ui.setconfig("web", o, val)
5187 repo.ui.setconfig("web", o, val)
5182
5188
5183 o = opts.get('web_conf') or opts.get('webdir_conf')
5189 o = opts.get('web_conf') or opts.get('webdir_conf')
5184 if not o:
5190 if not o:
5185 if not repo:
5191 if not repo:
5186 raise error.RepoError(_("there is no Mercurial repository"
5192 raise error.RepoError(_("there is no Mercurial repository"
5187 " here (.hg not found)"))
5193 " here (.hg not found)"))
5188 o = repo.root
5194 o = repo.root
5189
5195
5190 app = hgweb.hgweb(o, baseui=ui)
5196 app = hgweb.hgweb(o, baseui=ui)
5191
5197
5192 class service(object):
5198 class service(object):
5193 def init(self):
5199 def init(self):
5194 util.setsignalhandler()
5200 util.setsignalhandler()
5195 self.httpd = hgweb.server.create_server(ui, app)
5201 self.httpd = hgweb.server.create_server(ui, app)
5196
5202
5197 if opts['port'] and not ui.verbose:
5203 if opts['port'] and not ui.verbose:
5198 return
5204 return
5199
5205
5200 if self.httpd.prefix:
5206 if self.httpd.prefix:
5201 prefix = self.httpd.prefix.strip('/') + '/'
5207 prefix = self.httpd.prefix.strip('/') + '/'
5202 else:
5208 else:
5203 prefix = ''
5209 prefix = ''
5204
5210
5205 port = ':%d' % self.httpd.port
5211 port = ':%d' % self.httpd.port
5206 if port == ':80':
5212 if port == ':80':
5207 port = ''
5213 port = ''
5208
5214
5209 bindaddr = self.httpd.addr
5215 bindaddr = self.httpd.addr
5210 if bindaddr == '0.0.0.0':
5216 if bindaddr == '0.0.0.0':
5211 bindaddr = '*'
5217 bindaddr = '*'
5212 elif ':' in bindaddr: # IPv6
5218 elif ':' in bindaddr: # IPv6
5213 bindaddr = '[%s]' % bindaddr
5219 bindaddr = '[%s]' % bindaddr
5214
5220
5215 fqaddr = self.httpd.fqaddr
5221 fqaddr = self.httpd.fqaddr
5216 if ':' in fqaddr:
5222 if ':' in fqaddr:
5217 fqaddr = '[%s]' % fqaddr
5223 fqaddr = '[%s]' % fqaddr
5218 if opts['port']:
5224 if opts['port']:
5219 write = ui.status
5225 write = ui.status
5220 else:
5226 else:
5221 write = ui.write
5227 write = ui.write
5222 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5228 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5223 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5229 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5224
5230
5225 def run(self):
5231 def run(self):
5226 self.httpd.serve_forever()
5232 self.httpd.serve_forever()
5227
5233
5228 service = service()
5234 service = service()
5229
5235
5230 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5236 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5231
5237
5232 @command('showconfig|debugconfig',
5238 @command('showconfig|debugconfig',
5233 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5239 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5234 _('[-u] [NAME]...'))
5240 _('[-u] [NAME]...'))
5235 def showconfig(ui, repo, *values, **opts):
5241 def showconfig(ui, repo, *values, **opts):
5236 """show combined config settings from all hgrc files
5242 """show combined config settings from all hgrc files
5237
5243
5238 With no arguments, print names and values of all config items.
5244 With no arguments, print names and values of all config items.
5239
5245
5240 With one argument of the form section.name, print just the value
5246 With one argument of the form section.name, print just the value
5241 of that config item.
5247 of that config item.
5242
5248
5243 With multiple arguments, print names and values of all config
5249 With multiple arguments, print names and values of all config
5244 items with matching section names.
5250 items with matching section names.
5245
5251
5246 With --debug, the source (filename and line number) is printed
5252 With --debug, the source (filename and line number) is printed
5247 for each config item.
5253 for each config item.
5248
5254
5249 Returns 0 on success.
5255 Returns 0 on success.
5250 """
5256 """
5251
5257
5252 for f in scmutil.rcpath():
5258 for f in scmutil.rcpath():
5253 ui.debug('read config from: %s\n' % f)
5259 ui.debug('read config from: %s\n' % f)
5254 untrusted = bool(opts.get('untrusted'))
5260 untrusted = bool(opts.get('untrusted'))
5255 if values:
5261 if values:
5256 sections = [v for v in values if '.' not in v]
5262 sections = [v for v in values if '.' not in v]
5257 items = [v for v in values if '.' in v]
5263 items = [v for v in values if '.' in v]
5258 if len(items) > 1 or items and sections:
5264 if len(items) > 1 or items and sections:
5259 raise util.Abort(_('only one config item permitted'))
5265 raise util.Abort(_('only one config item permitted'))
5260 for section, name, value in ui.walkconfig(untrusted=untrusted):
5266 for section, name, value in ui.walkconfig(untrusted=untrusted):
5261 value = str(value).replace('\n', '\\n')
5267 value = str(value).replace('\n', '\\n')
5262 sectname = section + '.' + name
5268 sectname = section + '.' + name
5263 if values:
5269 if values:
5264 for v in values:
5270 for v in values:
5265 if v == section:
5271 if v == section:
5266 ui.debug('%s: ' %
5272 ui.debug('%s: ' %
5267 ui.configsource(section, name, untrusted))
5273 ui.configsource(section, name, untrusted))
5268 ui.write('%s=%s\n' % (sectname, value))
5274 ui.write('%s=%s\n' % (sectname, value))
5269 elif v == sectname:
5275 elif v == sectname:
5270 ui.debug('%s: ' %
5276 ui.debug('%s: ' %
5271 ui.configsource(section, name, untrusted))
5277 ui.configsource(section, name, untrusted))
5272 ui.write(value, '\n')
5278 ui.write(value, '\n')
5273 else:
5279 else:
5274 ui.debug('%s: ' %
5280 ui.debug('%s: ' %
5275 ui.configsource(section, name, untrusted))
5281 ui.configsource(section, name, untrusted))
5276 ui.write('%s=%s\n' % (sectname, value))
5282 ui.write('%s=%s\n' % (sectname, value))
5277
5283
5278 @command('^status|st',
5284 @command('^status|st',
5279 [('A', 'all', None, _('show status of all files')),
5285 [('A', 'all', None, _('show status of all files')),
5280 ('m', 'modified', None, _('show only modified files')),
5286 ('m', 'modified', None, _('show only modified files')),
5281 ('a', 'added', None, _('show only added files')),
5287 ('a', 'added', None, _('show only added files')),
5282 ('r', 'removed', None, _('show only removed files')),
5288 ('r', 'removed', None, _('show only removed files')),
5283 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5289 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5284 ('c', 'clean', None, _('show only files without changes')),
5290 ('c', 'clean', None, _('show only files without changes')),
5285 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5291 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5286 ('i', 'ignored', None, _('show only ignored files')),
5292 ('i', 'ignored', None, _('show only ignored files')),
5287 ('n', 'no-status', None, _('hide status prefix')),
5293 ('n', 'no-status', None, _('hide status prefix')),
5288 ('C', 'copies', None, _('show source of copied files')),
5294 ('C', 'copies', None, _('show source of copied files')),
5289 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5295 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5290 ('', 'rev', [], _('show difference from revision'), _('REV')),
5296 ('', 'rev', [], _('show difference from revision'), _('REV')),
5291 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5297 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5292 ] + walkopts + subrepoopts,
5298 ] + walkopts + subrepoopts,
5293 _('[OPTION]... [FILE]...'))
5299 _('[OPTION]... [FILE]...'))
5294 def status(ui, repo, *pats, **opts):
5300 def status(ui, repo, *pats, **opts):
5295 """show changed files in the working directory
5301 """show changed files in the working directory
5296
5302
5297 Show status of files in the repository. If names are given, only
5303 Show status of files in the repository. If names are given, only
5298 files that match are shown. Files that are clean or ignored or
5304 files that match are shown. Files that are clean or ignored or
5299 the source of a copy/move operation, are not listed unless
5305 the source of a copy/move operation, are not listed unless
5300 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5306 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5301 Unless options described with "show only ..." are given, the
5307 Unless options described with "show only ..." are given, the
5302 options -mardu are used.
5308 options -mardu are used.
5303
5309
5304 Option -q/--quiet hides untracked (unknown and ignored) files
5310 Option -q/--quiet hides untracked (unknown and ignored) files
5305 unless explicitly requested with -u/--unknown or -i/--ignored.
5311 unless explicitly requested with -u/--unknown or -i/--ignored.
5306
5312
5307 .. note::
5313 .. note::
5308 status may appear to disagree with diff if permissions have
5314 status may appear to disagree with diff if permissions have
5309 changed or a merge has occurred. The standard diff format does
5315 changed or a merge has occurred. The standard diff format does
5310 not report permission changes and diff only reports changes
5316 not report permission changes and diff only reports changes
5311 relative to one merge parent.
5317 relative to one merge parent.
5312
5318
5313 If one revision is given, it is used as the base revision.
5319 If one revision is given, it is used as the base revision.
5314 If two revisions are given, the differences between them are
5320 If two revisions are given, the differences between them are
5315 shown. The --change option can also be used as a shortcut to list
5321 shown. The --change option can also be used as a shortcut to list
5316 the changed files of a revision from its first parent.
5322 the changed files of a revision from its first parent.
5317
5323
5318 The codes used to show the status of files are::
5324 The codes used to show the status of files are::
5319
5325
5320 M = modified
5326 M = modified
5321 A = added
5327 A = added
5322 R = removed
5328 R = removed
5323 C = clean
5329 C = clean
5324 ! = missing (deleted by non-hg command, but still tracked)
5330 ! = missing (deleted by non-hg command, but still tracked)
5325 ? = not tracked
5331 ? = not tracked
5326 I = ignored
5332 I = ignored
5327 = origin of the previous file listed as A (added)
5333 = origin of the previous file listed as A (added)
5328
5334
5329 .. container:: verbose
5335 .. container:: verbose
5330
5336
5331 Examples:
5337 Examples:
5332
5338
5333 - show changes in the working directory relative to a
5339 - show changes in the working directory relative to a
5334 changeset::
5340 changeset::
5335
5341
5336 hg status --rev 9353
5342 hg status --rev 9353
5337
5343
5338 - show all changes including copies in an existing changeset::
5344 - show all changes including copies in an existing changeset::
5339
5345
5340 hg status --copies --change 9353
5346 hg status --copies --change 9353
5341
5347
5342 - get a NUL separated list of added files, suitable for xargs::
5348 - get a NUL separated list of added files, suitable for xargs::
5343
5349
5344 hg status -an0
5350 hg status -an0
5345
5351
5346 Returns 0 on success.
5352 Returns 0 on success.
5347 """
5353 """
5348
5354
5349 revs = opts.get('rev')
5355 revs = opts.get('rev')
5350 change = opts.get('change')
5356 change = opts.get('change')
5351
5357
5352 if revs and change:
5358 if revs and change:
5353 msg = _('cannot specify --rev and --change at the same time')
5359 msg = _('cannot specify --rev and --change at the same time')
5354 raise util.Abort(msg)
5360 raise util.Abort(msg)
5355 elif change:
5361 elif change:
5356 node2 = scmutil.revsingle(repo, change, None).node()
5362 node2 = scmutil.revsingle(repo, change, None).node()
5357 node1 = repo[node2].p1().node()
5363 node1 = repo[node2].p1().node()
5358 else:
5364 else:
5359 node1, node2 = scmutil.revpair(repo, revs)
5365 node1, node2 = scmutil.revpair(repo, revs)
5360
5366
5361 cwd = (pats and repo.getcwd()) or ''
5367 cwd = (pats and repo.getcwd()) or ''
5362 end = opts.get('print0') and '\0' or '\n'
5368 end = opts.get('print0') and '\0' or '\n'
5363 copy = {}
5369 copy = {}
5364 states = 'modified added removed deleted unknown ignored clean'.split()
5370 states = 'modified added removed deleted unknown ignored clean'.split()
5365 show = [k for k in states if opts.get(k)]
5371 show = [k for k in states if opts.get(k)]
5366 if opts.get('all'):
5372 if opts.get('all'):
5367 show += ui.quiet and (states[:4] + ['clean']) or states
5373 show += ui.quiet and (states[:4] + ['clean']) or states
5368 if not show:
5374 if not show:
5369 show = ui.quiet and states[:4] or states[:5]
5375 show = ui.quiet and states[:4] or states[:5]
5370
5376
5371 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5377 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5372 'ignored' in show, 'clean' in show, 'unknown' in show,
5378 'ignored' in show, 'clean' in show, 'unknown' in show,
5373 opts.get('subrepos'))
5379 opts.get('subrepos'))
5374 changestates = zip(states, 'MAR!?IC', stat)
5380 changestates = zip(states, 'MAR!?IC', stat)
5375
5381
5376 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5382 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5377 copy = copies.pathcopies(repo[node1], repo[node2])
5383 copy = copies.pathcopies(repo[node1], repo[node2])
5378
5384
5379 fm = ui.formatter('status', opts)
5385 fm = ui.formatter('status', opts)
5380 format = '%s %s' + end
5386 format = '%s %s' + end
5381 if opts.get('no_status'):
5387 if opts.get('no_status'):
5382 format = '%.0s%s' + end
5388 format = '%.0s%s' + end
5383
5389
5384 for state, char, files in changestates:
5390 for state, char, files in changestates:
5385 if state in show:
5391 if state in show:
5386 label = 'status.' + state
5392 label = 'status.' + state
5387 for f in files:
5393 for f in files:
5388 fm.startitem()
5394 fm.startitem()
5389 fm.write("status path", format, char,
5395 fm.write("status path", format, char,
5390 repo.pathto(f, cwd), label=label)
5396 repo.pathto(f, cwd), label=label)
5391 if f in copy:
5397 if f in copy:
5392 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5398 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5393 label='status.copied')
5399 label='status.copied')
5394 fm.end()
5400 fm.end()
5395
5401
5396 @command('^summary|sum',
5402 @command('^summary|sum',
5397 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5403 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5398 def summary(ui, repo, **opts):
5404 def summary(ui, repo, **opts):
5399 """summarize working directory state
5405 """summarize working directory state
5400
5406
5401 This generates a brief summary of the working directory state,
5407 This generates a brief summary of the working directory state,
5402 including parents, branch, commit status, and available updates.
5408 including parents, branch, commit status, and available updates.
5403
5409
5404 With the --remote option, this will check the default paths for
5410 With the --remote option, this will check the default paths for
5405 incoming and outgoing changes. This can be time-consuming.
5411 incoming and outgoing changes. This can be time-consuming.
5406
5412
5407 Returns 0 on success.
5413 Returns 0 on success.
5408 """
5414 """
5409
5415
5410 ctx = repo[None]
5416 ctx = repo[None]
5411 parents = ctx.parents()
5417 parents = ctx.parents()
5412 pnode = parents[0].node()
5418 pnode = parents[0].node()
5413 marks = []
5419 marks = []
5414
5420
5415 for p in parents:
5421 for p in parents:
5416 # label with log.changeset (instead of log.parent) since this
5422 # label with log.changeset (instead of log.parent) since this
5417 # shows a working directory parent *changeset*:
5423 # shows a working directory parent *changeset*:
5418 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5424 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5419 label='log.changeset')
5425 label='log.changeset')
5420 ui.write(' '.join(p.tags()), label='log.tag')
5426 ui.write(' '.join(p.tags()), label='log.tag')
5421 if p.bookmarks():
5427 if p.bookmarks():
5422 marks.extend(p.bookmarks())
5428 marks.extend(p.bookmarks())
5423 if p.rev() == -1:
5429 if p.rev() == -1:
5424 if not len(repo):
5430 if not len(repo):
5425 ui.write(_(' (empty repository)'))
5431 ui.write(_(' (empty repository)'))
5426 else:
5432 else:
5427 ui.write(_(' (no revision checked out)'))
5433 ui.write(_(' (no revision checked out)'))
5428 ui.write('\n')
5434 ui.write('\n')
5429 if p.description():
5435 if p.description():
5430 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5436 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5431 label='log.summary')
5437 label='log.summary')
5432
5438
5433 branch = ctx.branch()
5439 branch = ctx.branch()
5434 bheads = repo.branchheads(branch)
5440 bheads = repo.branchheads(branch)
5435 m = _('branch: %s\n') % branch
5441 m = _('branch: %s\n') % branch
5436 if branch != 'default':
5442 if branch != 'default':
5437 ui.write(m, label='log.branch')
5443 ui.write(m, label='log.branch')
5438 else:
5444 else:
5439 ui.status(m, label='log.branch')
5445 ui.status(m, label='log.branch')
5440
5446
5441 if marks:
5447 if marks:
5442 current = repo._bookmarkcurrent
5448 current = repo._bookmarkcurrent
5443 ui.write(_('bookmarks:'), label='log.bookmark')
5449 ui.write(_('bookmarks:'), label='log.bookmark')
5444 if current is not None:
5450 if current is not None:
5445 try:
5451 try:
5446 marks.remove(current)
5452 marks.remove(current)
5447 ui.write(' *' + current, label='bookmarks.current')
5453 ui.write(' *' + current, label='bookmarks.current')
5448 except ValueError:
5454 except ValueError:
5449 # current bookmark not in parent ctx marks
5455 # current bookmark not in parent ctx marks
5450 pass
5456 pass
5451 for m in marks:
5457 for m in marks:
5452 ui.write(' ' + m, label='log.bookmark')
5458 ui.write(' ' + m, label='log.bookmark')
5453 ui.write('\n', label='log.bookmark')
5459 ui.write('\n', label='log.bookmark')
5454
5460
5455 st = list(repo.status(unknown=True))[:6]
5461 st = list(repo.status(unknown=True))[:6]
5456
5462
5457 c = repo.dirstate.copies()
5463 c = repo.dirstate.copies()
5458 copied, renamed = [], []
5464 copied, renamed = [], []
5459 for d, s in c.iteritems():
5465 for d, s in c.iteritems():
5460 if s in st[2]:
5466 if s in st[2]:
5461 st[2].remove(s)
5467 st[2].remove(s)
5462 renamed.append(d)
5468 renamed.append(d)
5463 else:
5469 else:
5464 copied.append(d)
5470 copied.append(d)
5465 if d in st[1]:
5471 if d in st[1]:
5466 st[1].remove(d)
5472 st[1].remove(d)
5467 st.insert(3, renamed)
5473 st.insert(3, renamed)
5468 st.insert(4, copied)
5474 st.insert(4, copied)
5469
5475
5470 ms = mergemod.mergestate(repo)
5476 ms = mergemod.mergestate(repo)
5471 st.append([f for f in ms if ms[f] == 'u'])
5477 st.append([f for f in ms if ms[f] == 'u'])
5472
5478
5473 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5479 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5474 st.append(subs)
5480 st.append(subs)
5475
5481
5476 labels = [ui.label(_('%d modified'), 'status.modified'),
5482 labels = [ui.label(_('%d modified'), 'status.modified'),
5477 ui.label(_('%d added'), 'status.added'),
5483 ui.label(_('%d added'), 'status.added'),
5478 ui.label(_('%d removed'), 'status.removed'),
5484 ui.label(_('%d removed'), 'status.removed'),
5479 ui.label(_('%d renamed'), 'status.copied'),
5485 ui.label(_('%d renamed'), 'status.copied'),
5480 ui.label(_('%d copied'), 'status.copied'),
5486 ui.label(_('%d copied'), 'status.copied'),
5481 ui.label(_('%d deleted'), 'status.deleted'),
5487 ui.label(_('%d deleted'), 'status.deleted'),
5482 ui.label(_('%d unknown'), 'status.unknown'),
5488 ui.label(_('%d unknown'), 'status.unknown'),
5483 ui.label(_('%d ignored'), 'status.ignored'),
5489 ui.label(_('%d ignored'), 'status.ignored'),
5484 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5490 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5485 ui.label(_('%d subrepos'), 'status.modified')]
5491 ui.label(_('%d subrepos'), 'status.modified')]
5486 t = []
5492 t = []
5487 for s, l in zip(st, labels):
5493 for s, l in zip(st, labels):
5488 if s:
5494 if s:
5489 t.append(l % len(s))
5495 t.append(l % len(s))
5490
5496
5491 t = ', '.join(t)
5497 t = ', '.join(t)
5492 cleanworkdir = False
5498 cleanworkdir = False
5493
5499
5494 if len(parents) > 1:
5500 if len(parents) > 1:
5495 t += _(' (merge)')
5501 t += _(' (merge)')
5496 elif branch != parents[0].branch():
5502 elif branch != parents[0].branch():
5497 t += _(' (new branch)')
5503 t += _(' (new branch)')
5498 elif (parents[0].closesbranch() and
5504 elif (parents[0].closesbranch() and
5499 pnode in repo.branchheads(branch, closed=True)):
5505 pnode in repo.branchheads(branch, closed=True)):
5500 t += _(' (head closed)')
5506 t += _(' (head closed)')
5501 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5507 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5502 t += _(' (clean)')
5508 t += _(' (clean)')
5503 cleanworkdir = True
5509 cleanworkdir = True
5504 elif pnode not in bheads:
5510 elif pnode not in bheads:
5505 t += _(' (new branch head)')
5511 t += _(' (new branch head)')
5506
5512
5507 if cleanworkdir:
5513 if cleanworkdir:
5508 ui.status(_('commit: %s\n') % t.strip())
5514 ui.status(_('commit: %s\n') % t.strip())
5509 else:
5515 else:
5510 ui.write(_('commit: %s\n') % t.strip())
5516 ui.write(_('commit: %s\n') % t.strip())
5511
5517
5512 # all ancestors of branch heads - all ancestors of parent = new csets
5518 # all ancestors of branch heads - all ancestors of parent = new csets
5513 new = [0] * len(repo)
5519 new = [0] * len(repo)
5514 cl = repo.changelog
5520 cl = repo.changelog
5515 for a in [cl.rev(n) for n in bheads]:
5521 for a in [cl.rev(n) for n in bheads]:
5516 new[a] = 1
5522 new[a] = 1
5517 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5523 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5518 new[a] = 1
5524 new[a] = 1
5519 for a in [p.rev() for p in parents]:
5525 for a in [p.rev() for p in parents]:
5520 if a >= 0:
5526 if a >= 0:
5521 new[a] = 0
5527 new[a] = 0
5522 for a in cl.ancestors([p.rev() for p in parents]):
5528 for a in cl.ancestors([p.rev() for p in parents]):
5523 new[a] = 0
5529 new[a] = 0
5524 new = sum(new)
5530 new = sum(new)
5525
5531
5526 if new == 0:
5532 if new == 0:
5527 ui.status(_('update: (current)\n'))
5533 ui.status(_('update: (current)\n'))
5528 elif pnode not in bheads:
5534 elif pnode not in bheads:
5529 ui.write(_('update: %d new changesets (update)\n') % new)
5535 ui.write(_('update: %d new changesets (update)\n') % new)
5530 else:
5536 else:
5531 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5537 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5532 (new, len(bheads)))
5538 (new, len(bheads)))
5533
5539
5534 if opts.get('remote'):
5540 if opts.get('remote'):
5535 t = []
5541 t = []
5536 source, branches = hg.parseurl(ui.expandpath('default'))
5542 source, branches = hg.parseurl(ui.expandpath('default'))
5537 other = hg.peer(repo, {}, source)
5543 other = hg.peer(repo, {}, source)
5538 revs, checkout = hg.addbranchrevs(repo, other, branches,
5544 revs, checkout = hg.addbranchrevs(repo, other, branches,
5539 opts.get('rev'))
5545 opts.get('rev'))
5540 ui.debug('comparing with %s\n' % util.hidepassword(source))
5546 ui.debug('comparing with %s\n' % util.hidepassword(source))
5541 repo.ui.pushbuffer()
5547 repo.ui.pushbuffer()
5542 commoninc = discovery.findcommonincoming(repo, other)
5548 commoninc = discovery.findcommonincoming(repo, other)
5543 _common, incoming, _rheads = commoninc
5549 _common, incoming, _rheads = commoninc
5544 repo.ui.popbuffer()
5550 repo.ui.popbuffer()
5545 if incoming:
5551 if incoming:
5546 t.append(_('1 or more incoming'))
5552 t.append(_('1 or more incoming'))
5547
5553
5548 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5554 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5549 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5555 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5550 if source != dest:
5556 if source != dest:
5551 other = hg.peer(repo, {}, dest)
5557 other = hg.peer(repo, {}, dest)
5552 commoninc = None
5558 commoninc = None
5553 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5559 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5554 repo.ui.pushbuffer()
5560 repo.ui.pushbuffer()
5555 outgoing = discovery.findcommonoutgoing(repo, other,
5561 outgoing = discovery.findcommonoutgoing(repo, other,
5556 commoninc=commoninc)
5562 commoninc=commoninc)
5557 repo.ui.popbuffer()
5563 repo.ui.popbuffer()
5558 o = outgoing.missing
5564 o = outgoing.missing
5559 if o:
5565 if o:
5560 t.append(_('%d outgoing') % len(o))
5566 t.append(_('%d outgoing') % len(o))
5561 if 'bookmarks' in other.listkeys('namespaces'):
5567 if 'bookmarks' in other.listkeys('namespaces'):
5562 lmarks = repo.listkeys('bookmarks')
5568 lmarks = repo.listkeys('bookmarks')
5563 rmarks = other.listkeys('bookmarks')
5569 rmarks = other.listkeys('bookmarks')
5564 diff = set(rmarks) - set(lmarks)
5570 diff = set(rmarks) - set(lmarks)
5565 if len(diff) > 0:
5571 if len(diff) > 0:
5566 t.append(_('%d incoming bookmarks') % len(diff))
5572 t.append(_('%d incoming bookmarks') % len(diff))
5567 diff = set(lmarks) - set(rmarks)
5573 diff = set(lmarks) - set(rmarks)
5568 if len(diff) > 0:
5574 if len(diff) > 0:
5569 t.append(_('%d outgoing bookmarks') % len(diff))
5575 t.append(_('%d outgoing bookmarks') % len(diff))
5570
5576
5571 if t:
5577 if t:
5572 ui.write(_('remote: %s\n') % (', '.join(t)))
5578 ui.write(_('remote: %s\n') % (', '.join(t)))
5573 else:
5579 else:
5574 ui.status(_('remote: (synced)\n'))
5580 ui.status(_('remote: (synced)\n'))
5575
5581
5576 @command('tag',
5582 @command('tag',
5577 [('f', 'force', None, _('force tag')),
5583 [('f', 'force', None, _('force tag')),
5578 ('l', 'local', None, _('make the tag local')),
5584 ('l', 'local', None, _('make the tag local')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5585 ('r', 'rev', '', _('revision to tag'), _('REV')),
5580 ('', 'remove', None, _('remove a tag')),
5586 ('', 'remove', None, _('remove a tag')),
5581 # -l/--local is already there, commitopts cannot be used
5587 # -l/--local is already there, commitopts cannot be used
5582 ('e', 'edit', None, _('edit commit message')),
5588 ('e', 'edit', None, _('edit commit message')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5589 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5584 ] + commitopts2,
5590 ] + commitopts2,
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5591 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5586 def tag(ui, repo, name1, *names, **opts):
5592 def tag(ui, repo, name1, *names, **opts):
5587 """add one or more tags for the current or given revision
5593 """add one or more tags for the current or given revision
5588
5594
5589 Name a particular revision using <name>.
5595 Name a particular revision using <name>.
5590
5596
5591 Tags are used to name particular revisions of the repository and are
5597 Tags are used to name particular revisions of the repository and are
5592 very useful to compare different revisions, to go back to significant
5598 very useful to compare different revisions, to go back to significant
5593 earlier versions or to mark branch points as releases, etc. Changing
5599 earlier versions or to mark branch points as releases, etc. Changing
5594 an existing tag is normally disallowed; use -f/--force to override.
5600 an existing tag is normally disallowed; use -f/--force to override.
5595
5601
5596 If no revision is given, the parent of the working directory is
5602 If no revision is given, the parent of the working directory is
5597 used, or tip if no revision is checked out.
5603 used, or tip if no revision is checked out.
5598
5604
5599 To facilitate version control, distribution, and merging of tags,
5605 To facilitate version control, distribution, and merging of tags,
5600 they are stored as a file named ".hgtags" which is managed similarly
5606 they are stored as a file named ".hgtags" which is managed similarly
5601 to other project files and can be hand-edited if necessary. This
5607 to other project files and can be hand-edited if necessary. This
5602 also means that tagging creates a new commit. The file
5608 also means that tagging creates a new commit. The file
5603 ".hg/localtags" is used for local tags (not shared among
5609 ".hg/localtags" is used for local tags (not shared among
5604 repositories).
5610 repositories).
5605
5611
5606 Tag commits are usually made at the head of a branch. If the parent
5612 Tag commits are usually made at the head of a branch. If the parent
5607 of the working directory is not a branch head, :hg:`tag` aborts; use
5613 of the working directory is not a branch head, :hg:`tag` aborts; use
5608 -f/--force to force the tag commit to be based on a non-head
5614 -f/--force to force the tag commit to be based on a non-head
5609 changeset.
5615 changeset.
5610
5616
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5617 See :hg:`help dates` for a list of formats valid for -d/--date.
5612
5618
5613 Since tag names have priority over branch names during revision
5619 Since tag names have priority over branch names during revision
5614 lookup, using an existing branch name as a tag name is discouraged.
5620 lookup, using an existing branch name as a tag name is discouraged.
5615
5621
5616 Returns 0 on success.
5622 Returns 0 on success.
5617 """
5623 """
5618 wlock = lock = None
5624 wlock = lock = None
5619 try:
5625 try:
5620 wlock = repo.wlock()
5626 wlock = repo.wlock()
5621 lock = repo.lock()
5627 lock = repo.lock()
5622 rev_ = "."
5628 rev_ = "."
5623 names = [t.strip() for t in (name1,) + names]
5629 names = [t.strip() for t in (name1,) + names]
5624 if len(names) != len(set(names)):
5630 if len(names) != len(set(names)):
5625 raise util.Abort(_('tag names must be unique'))
5631 raise util.Abort(_('tag names must be unique'))
5626 for n in names:
5632 for n in names:
5627 if n in ['tip', '.', 'null']:
5633 if n in ['tip', '.', 'null']:
5628 raise util.Abort(_("the name '%s' is reserved") % n)
5634 raise util.Abort(_("the name '%s' is reserved") % n)
5629 if not n:
5635 if not n:
5630 raise util.Abort(_('tag names cannot consist entirely of '
5636 raise util.Abort(_('tag names cannot consist entirely of '
5631 'whitespace'))
5637 'whitespace'))
5632 if opts.get('rev') and opts.get('remove'):
5638 if opts.get('rev') and opts.get('remove'):
5633 raise util.Abort(_("--rev and --remove are incompatible"))
5639 raise util.Abort(_("--rev and --remove are incompatible"))
5634 if opts.get('rev'):
5640 if opts.get('rev'):
5635 rev_ = opts['rev']
5641 rev_ = opts['rev']
5636 message = opts.get('message')
5642 message = opts.get('message')
5637 if opts.get('remove'):
5643 if opts.get('remove'):
5638 expectedtype = opts.get('local') and 'local' or 'global'
5644 expectedtype = opts.get('local') and 'local' or 'global'
5639 for n in names:
5645 for n in names:
5640 if not repo.tagtype(n):
5646 if not repo.tagtype(n):
5641 raise util.Abort(_("tag '%s' does not exist") % n)
5647 raise util.Abort(_("tag '%s' does not exist") % n)
5642 if repo.tagtype(n) != expectedtype:
5648 if repo.tagtype(n) != expectedtype:
5643 if expectedtype == 'global':
5649 if expectedtype == 'global':
5644 raise util.Abort(_("tag '%s' is not a global tag") % n)
5650 raise util.Abort(_("tag '%s' is not a global tag") % n)
5645 else:
5651 else:
5646 raise util.Abort(_("tag '%s' is not a local tag") % n)
5652 raise util.Abort(_("tag '%s' is not a local tag") % n)
5647 rev_ = nullid
5653 rev_ = nullid
5648 if not message:
5654 if not message:
5649 # we don't translate commit messages
5655 # we don't translate commit messages
5650 message = 'Removed tag %s' % ', '.join(names)
5656 message = 'Removed tag %s' % ', '.join(names)
5651 elif not opts.get('force'):
5657 elif not opts.get('force'):
5652 for n in names:
5658 for n in names:
5653 if n in repo.tags():
5659 if n in repo.tags():
5654 raise util.Abort(_("tag '%s' already exists "
5660 raise util.Abort(_("tag '%s' already exists "
5655 "(use -f to force)") % n)
5661 "(use -f to force)") % n)
5656 if not opts.get('local'):
5662 if not opts.get('local'):
5657 p1, p2 = repo.dirstate.parents()
5663 p1, p2 = repo.dirstate.parents()
5658 if p2 != nullid:
5664 if p2 != nullid:
5659 raise util.Abort(_('uncommitted merge'))
5665 raise util.Abort(_('uncommitted merge'))
5660 bheads = repo.branchheads()
5666 bheads = repo.branchheads()
5661 if not opts.get('force') and bheads and p1 not in bheads:
5667 if not opts.get('force') and bheads and p1 not in bheads:
5662 raise util.Abort(_('not at a branch head (use -f to force)'))
5668 raise util.Abort(_('not at a branch head (use -f to force)'))
5663 r = scmutil.revsingle(repo, rev_).node()
5669 r = scmutil.revsingle(repo, rev_).node()
5664
5670
5665 if not message:
5671 if not message:
5666 # we don't translate commit messages
5672 # we don't translate commit messages
5667 message = ('Added tag %s for changeset %s' %
5673 message = ('Added tag %s for changeset %s' %
5668 (', '.join(names), short(r)))
5674 (', '.join(names), short(r)))
5669
5675
5670 date = opts.get('date')
5676 date = opts.get('date')
5671 if date:
5677 if date:
5672 date = util.parsedate(date)
5678 date = util.parsedate(date)
5673
5679
5674 if opts.get('edit'):
5680 if opts.get('edit'):
5675 message = ui.edit(message, ui.username())
5681 message = ui.edit(message, ui.username())
5676
5682
5677 # don't allow tagging the null rev
5683 # don't allow tagging the null rev
5678 if (not opts.get('remove') and
5684 if (not opts.get('remove') and
5679 scmutil.revsingle(repo, rev_).rev() == nullrev):
5685 scmutil.revsingle(repo, rev_).rev() == nullrev):
5680 raise util.Abort(_("null revision specified"))
5686 raise util.Abort(_("null revision specified"))
5681
5687
5682 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5688 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5683 finally:
5689 finally:
5684 release(lock, wlock)
5690 release(lock, wlock)
5685
5691
5686 @command('tags', [], '')
5692 @command('tags', [], '')
5687 def tags(ui, repo):
5693 def tags(ui, repo):
5688 """list repository tags
5694 """list repository tags
5689
5695
5690 This lists both regular and local tags. When the -v/--verbose
5696 This lists both regular and local tags. When the -v/--verbose
5691 switch is used, a third column "local" is printed for local tags.
5697 switch is used, a third column "local" is printed for local tags.
5692
5698
5693 Returns 0 on success.
5699 Returns 0 on success.
5694 """
5700 """
5695
5701
5696 hexfunc = ui.debugflag and hex or short
5702 hexfunc = ui.debugflag and hex or short
5697 tagtype = ""
5703 tagtype = ""
5698
5704
5699 for t, n in reversed(repo.tagslist()):
5705 for t, n in reversed(repo.tagslist()):
5700 if ui.quiet:
5706 if ui.quiet:
5701 ui.write("%s\n" % t, label='tags.normal')
5707 ui.write("%s\n" % t, label='tags.normal')
5702 continue
5708 continue
5703
5709
5704 hn = hexfunc(n)
5710 hn = hexfunc(n)
5705 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5711 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5706 rev = ui.label(r, 'log.changeset')
5712 rev = ui.label(r, 'log.changeset')
5707 spaces = " " * (30 - encoding.colwidth(t))
5713 spaces = " " * (30 - encoding.colwidth(t))
5708
5714
5709 tag = ui.label(t, 'tags.normal')
5715 tag = ui.label(t, 'tags.normal')
5710 if ui.verbose:
5716 if ui.verbose:
5711 if repo.tagtype(t) == 'local':
5717 if repo.tagtype(t) == 'local':
5712 tagtype = " local"
5718 tagtype = " local"
5713 tag = ui.label(t, 'tags.local')
5719 tag = ui.label(t, 'tags.local')
5714 else:
5720 else:
5715 tagtype = ""
5721 tagtype = ""
5716 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5722 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5717
5723
5718 @command('tip',
5724 @command('tip',
5719 [('p', 'patch', None, _('show patch')),
5725 [('p', 'patch', None, _('show patch')),
5720 ('g', 'git', None, _('use git extended diff format')),
5726 ('g', 'git', None, _('use git extended diff format')),
5721 ] + templateopts,
5727 ] + templateopts,
5722 _('[-p] [-g]'))
5728 _('[-p] [-g]'))
5723 def tip(ui, repo, **opts):
5729 def tip(ui, repo, **opts):
5724 """show the tip revision
5730 """show the tip revision
5725
5731
5726 The tip revision (usually just called the tip) is the changeset
5732 The tip revision (usually just called the tip) is the changeset
5727 most recently added to the repository (and therefore the most
5733 most recently added to the repository (and therefore the most
5728 recently changed head).
5734 recently changed head).
5729
5735
5730 If you have just made a commit, that commit will be the tip. If
5736 If you have just made a commit, that commit will be the tip. If
5731 you have just pulled changes from another repository, the tip of
5737 you have just pulled changes from another repository, the tip of
5732 that repository becomes the current tip. The "tip" tag is special
5738 that repository becomes the current tip. The "tip" tag is special
5733 and cannot be renamed or assigned to a different changeset.
5739 and cannot be renamed or assigned to a different changeset.
5734
5740
5735 Returns 0 on success.
5741 Returns 0 on success.
5736 """
5742 """
5737 displayer = cmdutil.show_changeset(ui, repo, opts)
5743 displayer = cmdutil.show_changeset(ui, repo, opts)
5738 displayer.show(repo[len(repo) - 1])
5744 displayer.show(repo[len(repo) - 1])
5739 displayer.close()
5745 displayer.close()
5740
5746
5741 @command('unbundle',
5747 @command('unbundle',
5742 [('u', 'update', None,
5748 [('u', 'update', None,
5743 _('update to new branch head if changesets were unbundled'))],
5749 _('update to new branch head if changesets were unbundled'))],
5744 _('[-u] FILE...'))
5750 _('[-u] FILE...'))
5745 def unbundle(ui, repo, fname1, *fnames, **opts):
5751 def unbundle(ui, repo, fname1, *fnames, **opts):
5746 """apply one or more changegroup files
5752 """apply one or more changegroup files
5747
5753
5748 Apply one or more compressed changegroup files generated by the
5754 Apply one or more compressed changegroup files generated by the
5749 bundle command.
5755 bundle command.
5750
5756
5751 Returns 0 on success, 1 if an update has unresolved files.
5757 Returns 0 on success, 1 if an update has unresolved files.
5752 """
5758 """
5753 fnames = (fname1,) + fnames
5759 fnames = (fname1,) + fnames
5754
5760
5755 lock = repo.lock()
5761 lock = repo.lock()
5756 wc = repo['.']
5762 wc = repo['.']
5757 try:
5763 try:
5758 for fname in fnames:
5764 for fname in fnames:
5759 f = url.open(ui, fname)
5765 f = url.open(ui, fname)
5760 gen = changegroup.readbundle(f, fname)
5766 gen = changegroup.readbundle(f, fname)
5761 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5767 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5762 finally:
5768 finally:
5763 lock.release()
5769 lock.release()
5764 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5770 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5765 return postincoming(ui, repo, modheads, opts.get('update'), None)
5771 return postincoming(ui, repo, modheads, opts.get('update'), None)
5766
5772
5767 @command('^update|up|checkout|co',
5773 @command('^update|up|checkout|co',
5768 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5774 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5769 ('c', 'check', None,
5775 ('c', 'check', None,
5770 _('update across branches if no uncommitted changes')),
5776 _('update across branches if no uncommitted changes')),
5771 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5777 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5772 ('r', 'rev', '', _('revision'), _('REV'))],
5778 ('r', 'rev', '', _('revision'), _('REV'))],
5773 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5779 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5774 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5780 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5775 """update working directory (or switch revisions)
5781 """update working directory (or switch revisions)
5776
5782
5777 Update the repository's working directory to the specified
5783 Update the repository's working directory to the specified
5778 changeset. If no changeset is specified, update to the tip of the
5784 changeset. If no changeset is specified, update to the tip of the
5779 current named branch and move the current bookmark (see :hg:`help
5785 current named branch and move the current bookmark (see :hg:`help
5780 bookmarks`).
5786 bookmarks`).
5781
5787
5782 Update sets the working directory's parent revision to the specified
5788 Update sets the working directory's parent revision to the specified
5783 changeset (see :hg:`help parents`).
5789 changeset (see :hg:`help parents`).
5784
5790
5785 If the changeset is not a descendant or ancestor of the working
5791 If the changeset is not a descendant or ancestor of the working
5786 directory's parent, the update is aborted. With the -c/--check
5792 directory's parent, the update is aborted. With the -c/--check
5787 option, the working directory is checked for uncommitted changes; if
5793 option, the working directory is checked for uncommitted changes; if
5788 none are found, the working directory is updated to the specified
5794 none are found, the working directory is updated to the specified
5789 changeset.
5795 changeset.
5790
5796
5791 .. container:: verbose
5797 .. container:: verbose
5792
5798
5793 The following rules apply when the working directory contains
5799 The following rules apply when the working directory contains
5794 uncommitted changes:
5800 uncommitted changes:
5795
5801
5796 1. If neither -c/--check nor -C/--clean is specified, and if
5802 1. If neither -c/--check nor -C/--clean is specified, and if
5797 the requested changeset is an ancestor or descendant of
5803 the requested changeset is an ancestor or descendant of
5798 the working directory's parent, the uncommitted changes
5804 the working directory's parent, the uncommitted changes
5799 are merged into the requested changeset and the merged
5805 are merged into the requested changeset and the merged
5800 result is left uncommitted. If the requested changeset is
5806 result is left uncommitted. If the requested changeset is
5801 not an ancestor or descendant (that is, it is on another
5807 not an ancestor or descendant (that is, it is on another
5802 branch), the update is aborted and the uncommitted changes
5808 branch), the update is aborted and the uncommitted changes
5803 are preserved.
5809 are preserved.
5804
5810
5805 2. With the -c/--check option, the update is aborted and the
5811 2. With the -c/--check option, the update is aborted and the
5806 uncommitted changes are preserved.
5812 uncommitted changes are preserved.
5807
5813
5808 3. With the -C/--clean option, uncommitted changes are discarded and
5814 3. With the -C/--clean option, uncommitted changes are discarded and
5809 the working directory is updated to the requested changeset.
5815 the working directory is updated to the requested changeset.
5810
5816
5811 To cancel an uncommitted merge (and lose your changes), use
5817 To cancel an uncommitted merge (and lose your changes), use
5812 :hg:`update --clean .`.
5818 :hg:`update --clean .`.
5813
5819
5814 Use null as the changeset to remove the working directory (like
5820 Use null as the changeset to remove the working directory (like
5815 :hg:`clone -U`).
5821 :hg:`clone -U`).
5816
5822
5817 If you want to revert just one file to an older revision, use
5823 If you want to revert just one file to an older revision, use
5818 :hg:`revert [-r REV] NAME`.
5824 :hg:`revert [-r REV] NAME`.
5819
5825
5820 See :hg:`help dates` for a list of formats valid for -d/--date.
5826 See :hg:`help dates` for a list of formats valid for -d/--date.
5821
5827
5822 Returns 0 on success, 1 if there are unresolved files.
5828 Returns 0 on success, 1 if there are unresolved files.
5823 """
5829 """
5824 if rev and node:
5830 if rev and node:
5825 raise util.Abort(_("please specify just one revision"))
5831 raise util.Abort(_("please specify just one revision"))
5826
5832
5827 if rev is None or rev == '':
5833 if rev is None or rev == '':
5828 rev = node
5834 rev = node
5829
5835
5830 # with no argument, we also move the current bookmark, if any
5836 # with no argument, we also move the current bookmark, if any
5831 movemarkfrom = None
5837 movemarkfrom = None
5832 if rev is None or node == '':
5838 if rev is None or node == '':
5833 movemarkfrom = repo['.'].node()
5839 movemarkfrom = repo['.'].node()
5834
5840
5835 # if we defined a bookmark, we have to remember the original bookmark name
5841 # if we defined a bookmark, we have to remember the original bookmark name
5836 brev = rev
5842 brev = rev
5837 rev = scmutil.revsingle(repo, rev, rev).rev()
5843 rev = scmutil.revsingle(repo, rev, rev).rev()
5838
5844
5839 if check and clean:
5845 if check and clean:
5840 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5846 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5841
5847
5842 if date:
5848 if date:
5843 if rev is not None:
5849 if rev is not None:
5844 raise util.Abort(_("you can't specify a revision and a date"))
5850 raise util.Abort(_("you can't specify a revision and a date"))
5845 rev = cmdutil.finddate(ui, repo, date)
5851 rev = cmdutil.finddate(ui, repo, date)
5846
5852
5847 if check:
5853 if check:
5848 c = repo[None]
5854 c = repo[None]
5849 if c.dirty(merge=False, branch=False):
5855 if c.dirty(merge=False, branch=False):
5850 raise util.Abort(_("uncommitted local changes"))
5856 raise util.Abort(_("uncommitted local changes"))
5851 if rev is None:
5857 if rev is None:
5852 rev = repo[repo[None].branch()].rev()
5858 rev = repo[repo[None].branch()].rev()
5853 mergemod._checkunknown(repo, repo[None], repo[rev])
5859 mergemod._checkunknown(repo, repo[None], repo[rev])
5854
5860
5855 if clean:
5861 if clean:
5856 ret = hg.clean(repo, rev)
5862 ret = hg.clean(repo, rev)
5857 else:
5863 else:
5858 ret = hg.update(repo, rev)
5864 ret = hg.update(repo, rev)
5859
5865
5860 if not ret and movemarkfrom:
5866 if not ret and movemarkfrom:
5861 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5867 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5862 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5868 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5863 elif brev in repo._bookmarks:
5869 elif brev in repo._bookmarks:
5864 bookmarks.setcurrent(repo, brev)
5870 bookmarks.setcurrent(repo, brev)
5865 elif brev:
5871 elif brev:
5866 bookmarks.unsetcurrent(repo)
5872 bookmarks.unsetcurrent(repo)
5867
5873
5868 return ret
5874 return ret
5869
5875
5870 @command('verify', [])
5876 @command('verify', [])
5871 def verify(ui, repo):
5877 def verify(ui, repo):
5872 """verify the integrity of the repository
5878 """verify the integrity of the repository
5873
5879
5874 Verify the integrity of the current repository.
5880 Verify the integrity of the current repository.
5875
5881
5876 This will perform an extensive check of the repository's
5882 This will perform an extensive check of the repository's
5877 integrity, validating the hashes and checksums of each entry in
5883 integrity, validating the hashes and checksums of each entry in
5878 the changelog, manifest, and tracked files, as well as the
5884 the changelog, manifest, and tracked files, as well as the
5879 integrity of their crosslinks and indices.
5885 integrity of their crosslinks and indices.
5880
5886
5881 Returns 0 on success, 1 if errors are encountered.
5887 Returns 0 on success, 1 if errors are encountered.
5882 """
5888 """
5883 return hg.verify(repo)
5889 return hg.verify(repo)
5884
5890
5885 @command('version', [])
5891 @command('version', [])
5886 def version_(ui):
5892 def version_(ui):
5887 """output version and copyright information"""
5893 """output version and copyright information"""
5888 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5894 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5889 % util.version())
5895 % util.version())
5890 ui.status(_(
5896 ui.status(_(
5891 "(see http://mercurial.selenic.com for more information)\n"
5897 "(see http://mercurial.selenic.com for more information)\n"
5892 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5898 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5893 "This is free software; see the source for copying conditions. "
5899 "This is free software; see the source for copying conditions. "
5894 "There is NO\nwarranty; "
5900 "There is NO\nwarranty; "
5895 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5901 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5896 ))
5902 ))
5897
5903
5898 norepo = ("clone init version help debugcommands debugcomplete"
5904 norepo = ("clone init version help debugcommands debugcomplete"
5899 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5905 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5900 " debugknown debuggetbundle debugbundle")
5906 " debugknown debuggetbundle debugbundle")
5901 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5907 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5902 " debugdata debugindex debugindexdot debugrevlog")
5908 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,170 +1,177 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 set bookmark X
8 set bookmark X
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmark
14 $ hg bookmark
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 > bookmark --color=always
20 > bookmark --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 update to bookmark X
23 update to bookmark X
24
24
25 $ hg update X
25 $ hg update X
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
27
27
28 list bookmarks
28 list bookmarks
29
29
30 $ hg bookmarks
30 $ hg bookmarks
31 * X -1:000000000000
31 * X -1:000000000000
32
32
33 rename
33 rename
34
34
35 $ hg bookmark -m X Z
35 $ hg bookmark -m X Z
36
36
37 list bookmarks
37 list bookmarks
38
38
39 $ cat .hg/bookmarks.current
39 $ cat .hg/bookmarks.current
40 Z (no-eol)
40 Z (no-eol)
41 $ cat .hg/bookmarks
41 $ cat .hg/bookmarks
42 0000000000000000000000000000000000000000 Z
42 0000000000000000000000000000000000000000 Z
43 $ hg bookmarks
43 $ hg bookmarks
44 * Z -1:000000000000
44 * Z -1:000000000000
45
45
46 new bookmark Y
46 new bookmark Y
47
47
48 $ hg bookmark Y
48 $ hg bookmark Y
49
49
50 list bookmarks
50 list bookmarks
51
51
52 $ hg bookmark
52 $ hg bookmark
53 * Y -1:000000000000
53 * Y -1:000000000000
54 Z -1:000000000000
54 Z -1:000000000000
55
55
56 commit
56 commit
57
57
58 $ echo 'b' > b
58 $ echo 'b' > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m'test'
60 $ hg commit -m'test'
61
61
62 list bookmarks
62 list bookmarks
63
63
64 $ hg bookmark
64 $ hg bookmark
65 * Y 0:719295282060
65 * Y 0:719295282060
66 Z -1:000000000000
66 Z -1:000000000000
67
67
68 Verify that switching to Z updates the current bookmark:
68 Verify that switching to Z updates the current bookmark:
69 $ hg update Z
69 $ hg update Z
70 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
70 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
71 $ hg bookmark
71 $ hg bookmark
72 Y 0:719295282060
72 Y 0:719295282060
73 * Z -1:000000000000
73 * Z -1:000000000000
74
74
75 Switch back to Y for the remaining tests in this file:
75 Switch back to Y for the remaining tests in this file:
76 $ hg update Y
76 $ hg update Y
77 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
78
78
79 delete bookmarks
79 delete bookmarks
80
80
81 $ hg bookmark -d Y
81 $ hg bookmark -d Y
82 $ hg bookmark -d Z
82 $ hg bookmark -d Z
83
83
84 list bookmarks
84 list bookmarks
85
85
86 $ hg bookmark
86 $ hg bookmark
87 no bookmarks set
87 no bookmarks set
88
88
89 update to tip
89 update to tip
90
90
91 $ hg update tip
91 $ hg update tip
92 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
93
93
94 set bookmark Y using -r .
94 set bookmark Y using -r .
95
95
96 $ hg bookmark -r . Y
96 $ hg bookmark -r . Y
97
97
98 list bookmarks
98 list bookmarks
99
99
100 $ hg bookmark
100 $ hg bookmark
101 * Y 0:719295282060
101 * Y 0:719295282060
102
102
103 set bookmark Z using -i
103 set bookmark Z using -i
104
104
105 $ hg bookmark -r . -i Z
105 $ hg bookmark -r . -i Z
106 $ hg bookmarks
106 $ hg bookmarks
107 * Y 0:719295282060
107 * Y 0:719295282060
108 Z 0:719295282060
108 Z 0:719295282060
109
109
110 deactivate current bookmark using -i
110 deactivate current bookmark using -i
111
111
112 $ hg bookmark -i Y
112 $ hg bookmark -i Y
113 $ hg bookmarks
113 $ hg bookmarks
114 Y 0:719295282060
114 Y 0:719295282060
115 Z 0:719295282060
115 Z 0:719295282060
116
116
117 $ hg up -q Y
117 $ hg up -q Y
118 $ hg bookmark -i
119 $ hg bookmarks
120 Y 0:719295282060
121 Z 0:719295282060
122 $ hg bookmark -i
123 no active bookmark
124 $ hg up -q Y
118 $ hg bookmarks
125 $ hg bookmarks
119 * Y 0:719295282060
126 * Y 0:719295282060
120 Z 0:719295282060
127 Z 0:719295282060
121
128
122 deactivate current bookmark while renaming
129 deactivate current bookmark while renaming
123
130
124 $ hg bookmark -i -m Y X
131 $ hg bookmark -i -m Y X
125 $ hg bookmarks
132 $ hg bookmarks
126 X 0:719295282060
133 X 0:719295282060
127 Z 0:719295282060
134 Z 0:719295282060
128
135
129 bare update moves the active bookmark forward
136 bare update moves the active bookmark forward
130
137
131 $ echo a > a
138 $ echo a > a
132 $ hg ci -Am1
139 $ hg ci -Am1
133 adding a
140 adding a
134 $ hg update X
141 $ hg update X
135 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
142 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
136 $ hg bookmarks
143 $ hg bookmarks
137 * X 0:719295282060
144 * X 0:719295282060
138 Z 0:719295282060
145 Z 0:719295282060
139 $ hg update
146 $ hg update
140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 updating bookmark X
148 updating bookmark X
142 $ hg bookmarks
149 $ hg bookmarks
143 * X 1:cc586d725fbe
150 * X 1:cc586d725fbe
144 Z 0:719295282060
151 Z 0:719295282060
145
152
146 test deleting .hg/bookmarks.current when explicitly updating
153 test deleting .hg/bookmarks.current when explicitly updating
147 to a revision
154 to a revision
148
155
149 $ echo a >> b
156 $ echo a >> b
150 $ hg ci -m.
157 $ hg ci -m.
151 $ hg up -q X
158 $ hg up -q X
152 $ test -f .hg/bookmarks.current
159 $ test -f .hg/bookmarks.current
153
160
154 try to update to it again to make sure we don't
161 try to update to it again to make sure we don't
155 set and then unset it
162 set and then unset it
156
163
157 $ hg up -q X
164 $ hg up -q X
158 $ test -f .hg/bookmarks.current
165 $ test -f .hg/bookmarks.current
159
166
160 $ hg up -q 1
167 $ hg up -q 1
161 $ test -f .hg/bookmarks.current
168 $ test -f .hg/bookmarks.current
162 [1]
169 [1]
163
170
164 when a bookmark is active, hg up -r . is
171 when a bookmark is active, hg up -r . is
165 analogus to hg book -i <active bookmark>
172 analogus to hg book -i <active bookmark>
166
173
167 $ hg up -q X
174 $ hg up -q X
168 $ hg up -q .
175 $ hg up -q .
169 $ test -f .hg/bookmarks.current
176 $ test -f .hg/bookmarks.current
170 [1]
177 [1]
General Comments 0
You need to be logged in to leave comments. Login now