##// END OF EJS Templates
log: do not display hidden changeset...
Pierre-Yves David -
r14645:e4cfdff6 default
parent child Browse files
Show More
@@ -1,5129 +1,5132 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, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset, fileset
16 import minirst, revset, fileset
17 import dagparser, context, simplemerge
17 import dagparser, context, simplemerge
18 import random, setdiscovery, treediscovery, dagutil
18 import random, setdiscovery, treediscovery, dagutil
19
19
20 table = {}
20 table = {}
21
21
22 command = cmdutil.command(table)
22 command = cmdutil.command(table)
23
23
24 # common command options
24 # common command options
25
25
26 globalopts = [
26 globalopts = [
27 ('R', 'repository', '',
27 ('R', 'repository', '',
28 _('repository root directory or name of overlay bundle file'),
28 _('repository root directory or name of overlay bundle file'),
29 _('REPO')),
29 _('REPO')),
30 ('', 'cwd', '',
30 ('', 'cwd', '',
31 _('change working directory'), _('DIR')),
31 _('change working directory'), _('DIR')),
32 ('y', 'noninteractive', None,
32 ('y', 'noninteractive', None,
33 _('do not prompt, assume \'yes\' for any required answers')),
33 _('do not prompt, assume \'yes\' for any required answers')),
34 ('q', 'quiet', None, _('suppress output')),
34 ('q', 'quiet', None, _('suppress output')),
35 ('v', 'verbose', None, _('enable additional output')),
35 ('v', 'verbose', None, _('enable additional output')),
36 ('', 'config', [],
36 ('', 'config', [],
37 _('set/override config option (use \'section.name=value\')'),
37 _('set/override config option (use \'section.name=value\')'),
38 _('CONFIG')),
38 _('CONFIG')),
39 ('', 'debug', None, _('enable debugging output')),
39 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debugger', None, _('start debugger')),
40 ('', 'debugger', None, _('start debugger')),
41 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
41 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 _('ENCODE')),
42 _('ENCODE')),
43 ('', 'encodingmode', encoding.encodingmode,
43 ('', 'encodingmode', encoding.encodingmode,
44 _('set the charset encoding mode'), _('MODE')),
44 _('set the charset encoding mode'), _('MODE')),
45 ('', 'traceback', None, _('always print a traceback on exception')),
45 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'time', None, _('time how long the command takes')),
46 ('', 'time', None, _('time how long the command takes')),
47 ('', 'profile', None, _('print command execution profile')),
47 ('', 'profile', None, _('print command execution profile')),
48 ('', 'version', None, _('output version information and exit')),
48 ('', 'version', None, _('output version information and exit')),
49 ('h', 'help', None, _('display help and exit')),
49 ('h', 'help', None, _('display help and exit')),
50 ]
50 ]
51
51
52 dryrunopts = [('n', 'dry-run', None,
52 dryrunopts = [('n', 'dry-run', None,
53 _('do not perform actions, just print output'))]
53 _('do not perform actions, just print output'))]
54
54
55 remoteopts = [
55 remoteopts = [
56 ('e', 'ssh', '',
56 ('e', 'ssh', '',
57 _('specify ssh command to use'), _('CMD')),
57 _('specify ssh command to use'), _('CMD')),
58 ('', 'remotecmd', '',
58 ('', 'remotecmd', '',
59 _('specify hg command to run on the remote side'), _('CMD')),
59 _('specify hg command to run on the remote side'), _('CMD')),
60 ('', 'insecure', None,
60 ('', 'insecure', None,
61 _('do not verify server certificate (ignoring web.cacerts config)')),
61 _('do not verify server certificate (ignoring web.cacerts config)')),
62 ]
62 ]
63
63
64 walkopts = [
64 walkopts = [
65 ('I', 'include', [],
65 ('I', 'include', [],
66 _('include names matching the given patterns'), _('PATTERN')),
66 _('include names matching the given patterns'), _('PATTERN')),
67 ('X', 'exclude', [],
67 ('X', 'exclude', [],
68 _('exclude names matching the given patterns'), _('PATTERN')),
68 _('exclude names matching the given patterns'), _('PATTERN')),
69 ]
69 ]
70
70
71 commitopts = [
71 commitopts = [
72 ('m', 'message', '',
72 ('m', 'message', '',
73 _('use text as commit message'), _('TEXT')),
73 _('use text as commit message'), _('TEXT')),
74 ('l', 'logfile', '',
74 ('l', 'logfile', '',
75 _('read commit message from file'), _('FILE')),
75 _('read commit message from file'), _('FILE')),
76 ]
76 ]
77
77
78 commitopts2 = [
78 commitopts2 = [
79 ('d', 'date', '',
79 ('d', 'date', '',
80 _('record the specified date as commit date'), _('DATE')),
80 _('record the specified date as commit date'), _('DATE')),
81 ('u', 'user', '',
81 ('u', 'user', '',
82 _('record the specified user as committer'), _('USER')),
82 _('record the specified user as committer'), _('USER')),
83 ]
83 ]
84
84
85 templateopts = [
85 templateopts = [
86 ('', 'style', '',
86 ('', 'style', '',
87 _('display using template map file'), _('STYLE')),
87 _('display using template map file'), _('STYLE')),
88 ('', 'template', '',
88 ('', 'template', '',
89 _('display with template'), _('TEMPLATE')),
89 _('display with template'), _('TEMPLATE')),
90 ]
90 ]
91
91
92 logopts = [
92 logopts = [
93 ('p', 'patch', None, _('show patch')),
93 ('p', 'patch', None, _('show patch')),
94 ('g', 'git', None, _('use git extended diff format')),
94 ('g', 'git', None, _('use git extended diff format')),
95 ('l', 'limit', '',
95 ('l', 'limit', '',
96 _('limit number of changes displayed'), _('NUM')),
96 _('limit number of changes displayed'), _('NUM')),
97 ('M', 'no-merges', None, _('do not show merges')),
97 ('M', 'no-merges', None, _('do not show merges')),
98 ('', 'stat', None, _('output diffstat-style summary of changes')),
98 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ] + templateopts
99 ] + templateopts
100
100
101 diffopts = [
101 diffopts = [
102 ('a', 'text', None, _('treat all files as text')),
102 ('a', 'text', None, _('treat all files as text')),
103 ('g', 'git', None, _('use git extended diff format')),
103 ('g', 'git', None, _('use git extended diff format')),
104 ('', 'nodates', None, _('omit dates from diff headers'))
104 ('', 'nodates', None, _('omit dates from diff headers'))
105 ]
105 ]
106
106
107 diffopts2 = [
107 diffopts2 = [
108 ('p', 'show-function', None, _('show which function each change is in')),
108 ('p', 'show-function', None, _('show which function each change is in')),
109 ('', 'reverse', None, _('produce a diff that undoes the changes')),
109 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ('U', 'unified', '',
116 ('U', 'unified', '',
117 _('number of lines of context to show'), _('NUM')),
117 _('number of lines of context to show'), _('NUM')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ]
119 ]
120
120
121 similarityopts = [
121 similarityopts = [
122 ('s', 'similarity', '',
122 ('s', 'similarity', '',
123 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
123 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
124 ]
124 ]
125
125
126 subrepoopts = [
126 subrepoopts = [
127 ('S', 'subrepos', None,
127 ('S', 'subrepos', None,
128 _('recurse into subrepositories'))
128 _('recurse into subrepositories'))
129 ]
129 ]
130
130
131 # Commands start here, listed alphabetically
131 # Commands start here, listed alphabetically
132
132
133 @command('^add',
133 @command('^add',
134 walkopts + subrepoopts + dryrunopts,
134 walkopts + subrepoopts + dryrunopts,
135 _('[OPTION]... [FILE]...'))
135 _('[OPTION]... [FILE]...'))
136 def add(ui, repo, *pats, **opts):
136 def add(ui, repo, *pats, **opts):
137 """add the specified files on the next commit
137 """add the specified files on the next commit
138
138
139 Schedule files to be version controlled and added to the
139 Schedule files to be version controlled and added to the
140 repository.
140 repository.
141
141
142 The files will be added to the repository at the next commit. To
142 The files will be added to the repository at the next commit. To
143 undo an add before that, see :hg:`forget`.
143 undo an add before that, see :hg:`forget`.
144
144
145 If no names are given, add all files to the repository.
145 If no names are given, add all files to the repository.
146
146
147 .. container:: verbose
147 .. container:: verbose
148
148
149 An example showing how new (unknown) files are added
149 An example showing how new (unknown) files are added
150 automatically by :hg:`add`::
150 automatically by :hg:`add`::
151
151
152 $ ls
152 $ ls
153 foo.c
153 foo.c
154 $ hg status
154 $ hg status
155 ? foo.c
155 ? foo.c
156 $ hg add
156 $ hg add
157 adding foo.c
157 adding foo.c
158 $ hg status
158 $ hg status
159 A foo.c
159 A foo.c
160
160
161 Returns 0 if all files are successfully added.
161 Returns 0 if all files are successfully added.
162 """
162 """
163
163
164 m = scmutil.match(repo, pats, opts)
164 m = scmutil.match(repo, pats, opts)
165 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
165 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
166 opts.get('subrepos'), prefix="")
166 opts.get('subrepos'), prefix="")
167 return rejected and 1 or 0
167 return rejected and 1 or 0
168
168
169 @command('addremove',
169 @command('addremove',
170 similarityopts + walkopts + dryrunopts,
170 similarityopts + walkopts + dryrunopts,
171 _('[OPTION]... [FILE]...'))
171 _('[OPTION]... [FILE]...'))
172 def addremove(ui, repo, *pats, **opts):
172 def addremove(ui, repo, *pats, **opts):
173 """add all new files, delete all missing files
173 """add all new files, delete all missing files
174
174
175 Add all new files and remove all missing files from the
175 Add all new files and remove all missing files from the
176 repository.
176 repository.
177
177
178 New files are ignored if they match any of the patterns in
178 New files are ignored if they match any of the patterns in
179 ``.hgignore``. As with add, these changes take effect at the next
179 ``.hgignore``. As with add, these changes take effect at the next
180 commit.
180 commit.
181
181
182 Use the -s/--similarity option to detect renamed files. With a
182 Use the -s/--similarity option to detect renamed files. With a
183 parameter greater than 0, this compares every removed file with
183 parameter greater than 0, this compares every removed file with
184 every added file and records those similar enough as renames. This
184 every added file and records those similar enough as renames. This
185 option takes a percentage between 0 (disabled) and 100 (files must
185 option takes a percentage between 0 (disabled) and 100 (files must
186 be identical) as its parameter. Detecting renamed files this way
186 be identical) as its parameter. Detecting renamed files this way
187 can be expensive. After using this option, :hg:`status -C` can be
187 can be expensive. After using this option, :hg:`status -C` can be
188 used to check which files were identified as moved or renamed.
188 used to check which files were identified as moved or renamed.
189
189
190 Returns 0 if all files are successfully added.
190 Returns 0 if all files are successfully added.
191 """
191 """
192 try:
192 try:
193 sim = float(opts.get('similarity') or 100)
193 sim = float(opts.get('similarity') or 100)
194 except ValueError:
194 except ValueError:
195 raise util.Abort(_('similarity must be a number'))
195 raise util.Abort(_('similarity must be a number'))
196 if sim < 0 or sim > 100:
196 if sim < 0 or sim > 100:
197 raise util.Abort(_('similarity must be between 0 and 100'))
197 raise util.Abort(_('similarity must be between 0 and 100'))
198 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
198 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
199
199
200 @command('^annotate|blame',
200 @command('^annotate|blame',
201 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
201 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
202 ('', 'follow', None,
202 ('', 'follow', None,
203 _('follow copies/renames and list the filename (DEPRECATED)')),
203 _('follow copies/renames and list the filename (DEPRECATED)')),
204 ('', 'no-follow', None, _("don't follow copies and renames")),
204 ('', 'no-follow', None, _("don't follow copies and renames")),
205 ('a', 'text', None, _('treat all files as text')),
205 ('a', 'text', None, _('treat all files as text')),
206 ('u', 'user', None, _('list the author (long with -v)')),
206 ('u', 'user', None, _('list the author (long with -v)')),
207 ('f', 'file', None, _('list the filename')),
207 ('f', 'file', None, _('list the filename')),
208 ('d', 'date', None, _('list the date (short with -q)')),
208 ('d', 'date', None, _('list the date (short with -q)')),
209 ('n', 'number', None, _('list the revision number (default)')),
209 ('n', 'number', None, _('list the revision number (default)')),
210 ('c', 'changeset', None, _('list the changeset')),
210 ('c', 'changeset', None, _('list the changeset')),
211 ('l', 'line-number', None, _('show line number at the first appearance'))
211 ('l', 'line-number', None, _('show line number at the first appearance'))
212 ] + walkopts,
212 ] + walkopts,
213 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
213 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
214 def annotate(ui, repo, *pats, **opts):
214 def annotate(ui, repo, *pats, **opts):
215 """show changeset information by line for each file
215 """show changeset information by line for each file
216
216
217 List changes in files, showing the revision id responsible for
217 List changes in files, showing the revision id responsible for
218 each line
218 each line
219
219
220 This command is useful for discovering when a change was made and
220 This command is useful for discovering when a change was made and
221 by whom.
221 by whom.
222
222
223 Without the -a/--text option, annotate will avoid processing files
223 Without the -a/--text option, annotate will avoid processing files
224 it detects as binary. With -a, annotate will annotate the file
224 it detects as binary. With -a, annotate will annotate the file
225 anyway, although the results will probably be neither useful
225 anyway, although the results will probably be neither useful
226 nor desirable.
226 nor desirable.
227
227
228 Returns 0 on success.
228 Returns 0 on success.
229 """
229 """
230 if opts.get('follow'):
230 if opts.get('follow'):
231 # --follow is deprecated and now just an alias for -f/--file
231 # --follow is deprecated and now just an alias for -f/--file
232 # to mimic the behavior of Mercurial before version 1.5
232 # to mimic the behavior of Mercurial before version 1.5
233 opts['file'] = True
233 opts['file'] = True
234
234
235 datefunc = ui.quiet and util.shortdate or util.datestr
235 datefunc = ui.quiet and util.shortdate or util.datestr
236 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
236 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
237
237
238 if not pats:
238 if not pats:
239 raise util.Abort(_('at least one filename or pattern is required'))
239 raise util.Abort(_('at least one filename or pattern is required'))
240
240
241 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
241 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
242 ('number', ' ', lambda x: str(x[0].rev())),
242 ('number', ' ', lambda x: str(x[0].rev())),
243 ('changeset', ' ', lambda x: short(x[0].node())),
243 ('changeset', ' ', lambda x: short(x[0].node())),
244 ('date', ' ', getdate),
244 ('date', ' ', getdate),
245 ('file', ' ', lambda x: x[0].path()),
245 ('file', ' ', lambda x: x[0].path()),
246 ('line_number', ':', lambda x: str(x[1])),
246 ('line_number', ':', lambda x: str(x[1])),
247 ]
247 ]
248
248
249 if (not opts.get('user') and not opts.get('changeset')
249 if (not opts.get('user') and not opts.get('changeset')
250 and not opts.get('date') and not opts.get('file')):
250 and not opts.get('date') and not opts.get('file')):
251 opts['number'] = True
251 opts['number'] = True
252
252
253 linenumber = opts.get('line_number') is not None
253 linenumber = opts.get('line_number') is not None
254 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
254 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
255 raise util.Abort(_('at least one of -n/-c is required for -l'))
255 raise util.Abort(_('at least one of -n/-c is required for -l'))
256
256
257 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
257 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
258 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
258 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
259
259
260 def bad(x, y):
260 def bad(x, y):
261 raise util.Abort("%s: %s" % (x, y))
261 raise util.Abort("%s: %s" % (x, y))
262
262
263 ctx = scmutil.revsingle(repo, opts.get('rev'))
263 ctx = scmutil.revsingle(repo, opts.get('rev'))
264 m = scmutil.match(repo, pats, opts)
264 m = scmutil.match(repo, pats, opts)
265 m.bad = bad
265 m.bad = bad
266 follow = not opts.get('no_follow')
266 follow = not opts.get('no_follow')
267 for abs in ctx.walk(m):
267 for abs in ctx.walk(m):
268 fctx = ctx[abs]
268 fctx = ctx[abs]
269 if not opts.get('text') and util.binary(fctx.data()):
269 if not opts.get('text') and util.binary(fctx.data()):
270 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
270 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
271 continue
271 continue
272
272
273 lines = fctx.annotate(follow=follow, linenumber=linenumber)
273 lines = fctx.annotate(follow=follow, linenumber=linenumber)
274 pieces = []
274 pieces = []
275
275
276 for f, sep in funcmap:
276 for f, sep in funcmap:
277 l = [f(n) for n, dummy in lines]
277 l = [f(n) for n, dummy in lines]
278 if l:
278 if l:
279 sized = [(x, encoding.colwidth(x)) for x in l]
279 sized = [(x, encoding.colwidth(x)) for x in l]
280 ml = max([w for x, w in sized])
280 ml = max([w for x, w in sized])
281 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
281 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
282 for x, w in sized])
282 for x, w in sized])
283
283
284 if pieces:
284 if pieces:
285 for p, l in zip(zip(*pieces), lines):
285 for p, l in zip(zip(*pieces), lines):
286 ui.write("%s: %s" % ("".join(p), l[1]))
286 ui.write("%s: %s" % ("".join(p), l[1]))
287
287
288 @command('archive',
288 @command('archive',
289 [('', 'no-decode', None, _('do not pass files through decoders')),
289 [('', 'no-decode', None, _('do not pass files through decoders')),
290 ('p', 'prefix', '', _('directory prefix for files in archive'),
290 ('p', 'prefix', '', _('directory prefix for files in archive'),
291 _('PREFIX')),
291 _('PREFIX')),
292 ('r', 'rev', '', _('revision to distribute'), _('REV')),
292 ('r', 'rev', '', _('revision to distribute'), _('REV')),
293 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
293 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
294 ] + subrepoopts + walkopts,
294 ] + subrepoopts + walkopts,
295 _('[OPTION]... DEST'))
295 _('[OPTION]... DEST'))
296 def archive(ui, repo, dest, **opts):
296 def archive(ui, repo, dest, **opts):
297 '''create an unversioned archive of a repository revision
297 '''create an unversioned archive of a repository revision
298
298
299 By default, the revision used is the parent of the working
299 By default, the revision used is the parent of the working
300 directory; use -r/--rev to specify a different revision.
300 directory; use -r/--rev to specify a different revision.
301
301
302 The archive type is automatically detected based on file
302 The archive type is automatically detected based on file
303 extension (or override using -t/--type).
303 extension (or override using -t/--type).
304
304
305 Valid types are:
305 Valid types are:
306
306
307 :``files``: a directory full of files (default)
307 :``files``: a directory full of files (default)
308 :``tar``: tar archive, uncompressed
308 :``tar``: tar archive, uncompressed
309 :``tbz2``: tar archive, compressed using bzip2
309 :``tbz2``: tar archive, compressed using bzip2
310 :``tgz``: tar archive, compressed using gzip
310 :``tgz``: tar archive, compressed using gzip
311 :``uzip``: zip archive, uncompressed
311 :``uzip``: zip archive, uncompressed
312 :``zip``: zip archive, compressed using deflate
312 :``zip``: zip archive, compressed using deflate
313
313
314 The exact name of the destination archive or directory is given
314 The exact name of the destination archive or directory is given
315 using a format string; see :hg:`help export` for details.
315 using a format string; see :hg:`help export` for details.
316
316
317 Each member added to an archive file has a directory prefix
317 Each member added to an archive file has a directory prefix
318 prepended. Use -p/--prefix to specify a format string for the
318 prepended. Use -p/--prefix to specify a format string for the
319 prefix. The default is the basename of the archive, with suffixes
319 prefix. The default is the basename of the archive, with suffixes
320 removed.
320 removed.
321
321
322 Returns 0 on success.
322 Returns 0 on success.
323 '''
323 '''
324
324
325 ctx = scmutil.revsingle(repo, opts.get('rev'))
325 ctx = scmutil.revsingle(repo, opts.get('rev'))
326 if not ctx:
326 if not ctx:
327 raise util.Abort(_('no working directory: please specify a revision'))
327 raise util.Abort(_('no working directory: please specify a revision'))
328 node = ctx.node()
328 node = ctx.node()
329 dest = cmdutil.makefilename(repo, dest, node)
329 dest = cmdutil.makefilename(repo, dest, node)
330 if os.path.realpath(dest) == repo.root:
330 if os.path.realpath(dest) == repo.root:
331 raise util.Abort(_('repository root cannot be destination'))
331 raise util.Abort(_('repository root cannot be destination'))
332
332
333 kind = opts.get('type') or archival.guesskind(dest) or 'files'
333 kind = opts.get('type') or archival.guesskind(dest) or 'files'
334 prefix = opts.get('prefix')
334 prefix = opts.get('prefix')
335
335
336 if dest == '-':
336 if dest == '-':
337 if kind == 'files':
337 if kind == 'files':
338 raise util.Abort(_('cannot archive plain files to stdout'))
338 raise util.Abort(_('cannot archive plain files to stdout'))
339 dest = ui.fout
339 dest = ui.fout
340 if not prefix:
340 if not prefix:
341 prefix = os.path.basename(repo.root) + '-%h'
341 prefix = os.path.basename(repo.root) + '-%h'
342
342
343 prefix = cmdutil.makefilename(repo, prefix, node)
343 prefix = cmdutil.makefilename(repo, prefix, node)
344 matchfn = scmutil.match(repo, [], opts)
344 matchfn = scmutil.match(repo, [], opts)
345 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
345 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
346 matchfn, prefix, subrepos=opts.get('subrepos'))
346 matchfn, prefix, subrepos=opts.get('subrepos'))
347
347
348 @command('backout',
348 @command('backout',
349 [('', 'merge', None, _('merge with old dirstate parent after backout')),
349 [('', 'merge', None, _('merge with old dirstate parent after backout')),
350 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
350 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
351 ('t', 'tool', '', _('specify merge tool')),
351 ('t', 'tool', '', _('specify merge tool')),
352 ('r', 'rev', '', _('revision to backout'), _('REV')),
352 ('r', 'rev', '', _('revision to backout'), _('REV')),
353 ] + walkopts + commitopts + commitopts2,
353 ] + walkopts + commitopts + commitopts2,
354 _('[OPTION]... [-r] REV'))
354 _('[OPTION]... [-r] REV'))
355 def backout(ui, repo, node=None, rev=None, **opts):
355 def backout(ui, repo, node=None, rev=None, **opts):
356 '''reverse effect of earlier changeset
356 '''reverse effect of earlier changeset
357
357
358 Prepare a new changeset with the effect of REV undone in the
358 Prepare a new changeset with the effect of REV undone in the
359 current working directory.
359 current working directory.
360
360
361 If REV is the parent of the working directory, then this new changeset
361 If REV is the parent of the working directory, then this new changeset
362 is committed automatically. Otherwise, hg needs to merge the
362 is committed automatically. Otherwise, hg needs to merge the
363 changes and the merged result is left uncommitted.
363 changes and the merged result is left uncommitted.
364
364
365 By default, the pending changeset will have one parent,
365 By default, the pending changeset will have one parent,
366 maintaining a linear history. With --merge, the pending changeset
366 maintaining a linear history. With --merge, the pending changeset
367 will instead have two parents: the old parent of the working
367 will instead have two parents: the old parent of the working
368 directory and a new child of REV that simply undoes REV.
368 directory and a new child of REV that simply undoes REV.
369
369
370 Before version 1.7, the behavior without --merge was equivalent to
370 Before version 1.7, the behavior without --merge was equivalent to
371 specifying --merge followed by :hg:`update --clean .` to cancel
371 specifying --merge followed by :hg:`update --clean .` to cancel
372 the merge and leave the child of REV as a head to be merged
372 the merge and leave the child of REV as a head to be merged
373 separately.
373 separately.
374
374
375 See :hg:`help dates` for a list of formats valid for -d/--date.
375 See :hg:`help dates` for a list of formats valid for -d/--date.
376
376
377 Returns 0 on success.
377 Returns 0 on success.
378 '''
378 '''
379 if rev and node:
379 if rev and node:
380 raise util.Abort(_("please specify just one revision"))
380 raise util.Abort(_("please specify just one revision"))
381
381
382 if not rev:
382 if not rev:
383 rev = node
383 rev = node
384
384
385 if not rev:
385 if not rev:
386 raise util.Abort(_("please specify a revision to backout"))
386 raise util.Abort(_("please specify a revision to backout"))
387
387
388 date = opts.get('date')
388 date = opts.get('date')
389 if date:
389 if date:
390 opts['date'] = util.parsedate(date)
390 opts['date'] = util.parsedate(date)
391
391
392 cmdutil.bailifchanged(repo)
392 cmdutil.bailifchanged(repo)
393 node = scmutil.revsingle(repo, rev).node()
393 node = scmutil.revsingle(repo, rev).node()
394
394
395 op1, op2 = repo.dirstate.parents()
395 op1, op2 = repo.dirstate.parents()
396 a = repo.changelog.ancestor(op1, node)
396 a = repo.changelog.ancestor(op1, node)
397 if a != node:
397 if a != node:
398 raise util.Abort(_('cannot backout change on a different branch'))
398 raise util.Abort(_('cannot backout change on a different branch'))
399
399
400 p1, p2 = repo.changelog.parents(node)
400 p1, p2 = repo.changelog.parents(node)
401 if p1 == nullid:
401 if p1 == nullid:
402 raise util.Abort(_('cannot backout a change with no parents'))
402 raise util.Abort(_('cannot backout a change with no parents'))
403 if p2 != nullid:
403 if p2 != nullid:
404 if not opts.get('parent'):
404 if not opts.get('parent'):
405 raise util.Abort(_('cannot backout a merge changeset without '
405 raise util.Abort(_('cannot backout a merge changeset without '
406 '--parent'))
406 '--parent'))
407 p = repo.lookup(opts['parent'])
407 p = repo.lookup(opts['parent'])
408 if p not in (p1, p2):
408 if p not in (p1, p2):
409 raise util.Abort(_('%s is not a parent of %s') %
409 raise util.Abort(_('%s is not a parent of %s') %
410 (short(p), short(node)))
410 (short(p), short(node)))
411 parent = p
411 parent = p
412 else:
412 else:
413 if opts.get('parent'):
413 if opts.get('parent'):
414 raise util.Abort(_('cannot use --parent on non-merge changeset'))
414 raise util.Abort(_('cannot use --parent on non-merge changeset'))
415 parent = p1
415 parent = p1
416
416
417 # the backout should appear on the same branch
417 # the backout should appear on the same branch
418 branch = repo.dirstate.branch()
418 branch = repo.dirstate.branch()
419 hg.clean(repo, node, show_stats=False)
419 hg.clean(repo, node, show_stats=False)
420 repo.dirstate.setbranch(branch)
420 repo.dirstate.setbranch(branch)
421 revert_opts = opts.copy()
421 revert_opts = opts.copy()
422 revert_opts['date'] = None
422 revert_opts['date'] = None
423 revert_opts['all'] = True
423 revert_opts['all'] = True
424 revert_opts['rev'] = hex(parent)
424 revert_opts['rev'] = hex(parent)
425 revert_opts['no_backup'] = None
425 revert_opts['no_backup'] = None
426 revert(ui, repo, **revert_opts)
426 revert(ui, repo, **revert_opts)
427 if not opts.get('merge') and op1 != node:
427 if not opts.get('merge') and op1 != node:
428 try:
428 try:
429 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
429 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
430 return hg.update(repo, op1)
430 return hg.update(repo, op1)
431 finally:
431 finally:
432 ui.setconfig('ui', 'forcemerge', '')
432 ui.setconfig('ui', 'forcemerge', '')
433
433
434 commit_opts = opts.copy()
434 commit_opts = opts.copy()
435 commit_opts['addremove'] = False
435 commit_opts['addremove'] = False
436 if not commit_opts['message'] and not commit_opts['logfile']:
436 if not commit_opts['message'] and not commit_opts['logfile']:
437 # we don't translate commit messages
437 # we don't translate commit messages
438 commit_opts['message'] = "Backed out changeset %s" % short(node)
438 commit_opts['message'] = "Backed out changeset %s" % short(node)
439 commit_opts['force_editor'] = True
439 commit_opts['force_editor'] = True
440 commit(ui, repo, **commit_opts)
440 commit(ui, repo, **commit_opts)
441 def nice(node):
441 def nice(node):
442 return '%d:%s' % (repo.changelog.rev(node), short(node))
442 return '%d:%s' % (repo.changelog.rev(node), short(node))
443 ui.status(_('changeset %s backs out changeset %s\n') %
443 ui.status(_('changeset %s backs out changeset %s\n') %
444 (nice(repo.changelog.tip()), nice(node)))
444 (nice(repo.changelog.tip()), nice(node)))
445 if opts.get('merge') and op1 != node:
445 if opts.get('merge') and op1 != node:
446 hg.clean(repo, op1, show_stats=False)
446 hg.clean(repo, op1, show_stats=False)
447 ui.status(_('merging with changeset %s\n')
447 ui.status(_('merging with changeset %s\n')
448 % nice(repo.changelog.tip()))
448 % nice(repo.changelog.tip()))
449 try:
449 try:
450 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
450 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
451 return hg.merge(repo, hex(repo.changelog.tip()))
451 return hg.merge(repo, hex(repo.changelog.tip()))
452 finally:
452 finally:
453 ui.setconfig('ui', 'forcemerge', '')
453 ui.setconfig('ui', 'forcemerge', '')
454 return 0
454 return 0
455
455
456 @command('bisect',
456 @command('bisect',
457 [('r', 'reset', False, _('reset bisect state')),
457 [('r', 'reset', False, _('reset bisect state')),
458 ('g', 'good', False, _('mark changeset good')),
458 ('g', 'good', False, _('mark changeset good')),
459 ('b', 'bad', False, _('mark changeset bad')),
459 ('b', 'bad', False, _('mark changeset bad')),
460 ('s', 'skip', False, _('skip testing changeset')),
460 ('s', 'skip', False, _('skip testing changeset')),
461 ('e', 'extend', False, _('extend the bisect range')),
461 ('e', 'extend', False, _('extend the bisect range')),
462 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
462 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
463 ('U', 'noupdate', False, _('do not update to target'))],
463 ('U', 'noupdate', False, _('do not update to target'))],
464 _("[-gbsr] [-U] [-c CMD] [REV]"))
464 _("[-gbsr] [-U] [-c CMD] [REV]"))
465 def bisect(ui, repo, rev=None, extra=None, command=None,
465 def bisect(ui, repo, rev=None, extra=None, command=None,
466 reset=None, good=None, bad=None, skip=None, extend=None,
466 reset=None, good=None, bad=None, skip=None, extend=None,
467 noupdate=None):
467 noupdate=None):
468 """subdivision search of changesets
468 """subdivision search of changesets
469
469
470 This command helps to find changesets which introduce problems. To
470 This command helps to find changesets which introduce problems. To
471 use, mark the earliest changeset you know exhibits the problem as
471 use, mark the earliest changeset you know exhibits the problem as
472 bad, then mark the latest changeset which is free from the problem
472 bad, then mark the latest changeset which is free from the problem
473 as good. Bisect will update your working directory to a revision
473 as good. Bisect will update your working directory to a revision
474 for testing (unless the -U/--noupdate option is specified). Once
474 for testing (unless the -U/--noupdate option is specified). Once
475 you have performed tests, mark the working directory as good or
475 you have performed tests, mark the working directory as good or
476 bad, and bisect will either update to another candidate changeset
476 bad, and bisect will either update to another candidate changeset
477 or announce that it has found the bad revision.
477 or announce that it has found the bad revision.
478
478
479 As a shortcut, you can also use the revision argument to mark a
479 As a shortcut, you can also use the revision argument to mark a
480 revision as good or bad without checking it out first.
480 revision as good or bad without checking it out first.
481
481
482 If you supply a command, it will be used for automatic bisection.
482 If you supply a command, it will be used for automatic bisection.
483 Its exit status will be used to mark revisions as good or bad:
483 Its exit status will be used to mark revisions as good or bad:
484 status 0 means good, 125 means to skip the revision, 127
484 status 0 means good, 125 means to skip the revision, 127
485 (command not found) will abort the bisection, and any other
485 (command not found) will abort the bisection, and any other
486 non-zero exit status means the revision is bad.
486 non-zero exit status means the revision is bad.
487
487
488 Returns 0 on success.
488 Returns 0 on success.
489 """
489 """
490 def extendbisectrange(nodes, good):
490 def extendbisectrange(nodes, good):
491 # bisect is incomplete when it ends on a merge node and
491 # bisect is incomplete when it ends on a merge node and
492 # one of the parent was not checked.
492 # one of the parent was not checked.
493 parents = repo[nodes[0]].parents()
493 parents = repo[nodes[0]].parents()
494 if len(parents) > 1:
494 if len(parents) > 1:
495 side = good and state['bad'] or state['good']
495 side = good and state['bad'] or state['good']
496 num = len(set(i.node() for i in parents) & set(side))
496 num = len(set(i.node() for i in parents) & set(side))
497 if num == 1:
497 if num == 1:
498 return parents[0].ancestor(parents[1])
498 return parents[0].ancestor(parents[1])
499 return None
499 return None
500
500
501 def print_result(nodes, good):
501 def print_result(nodes, good):
502 displayer = cmdutil.show_changeset(ui, repo, {})
502 displayer = cmdutil.show_changeset(ui, repo, {})
503 if len(nodes) == 1:
503 if len(nodes) == 1:
504 # narrowed it down to a single revision
504 # narrowed it down to a single revision
505 if good:
505 if good:
506 ui.write(_("The first good revision is:\n"))
506 ui.write(_("The first good revision is:\n"))
507 else:
507 else:
508 ui.write(_("The first bad revision is:\n"))
508 ui.write(_("The first bad revision is:\n"))
509 displayer.show(repo[nodes[0]])
509 displayer.show(repo[nodes[0]])
510 extendnode = extendbisectrange(nodes, good)
510 extendnode = extendbisectrange(nodes, good)
511 if extendnode is not None:
511 if extendnode is not None:
512 ui.write(_('Not all ancestors of this changeset have been'
512 ui.write(_('Not all ancestors of this changeset have been'
513 ' checked.\nUse bisect --extend to continue the '
513 ' checked.\nUse bisect --extend to continue the '
514 'bisection from\nthe common ancestor, %s.\n')
514 'bisection from\nthe common ancestor, %s.\n')
515 % extendnode)
515 % extendnode)
516 else:
516 else:
517 # multiple possible revisions
517 # multiple possible revisions
518 if good:
518 if good:
519 ui.write(_("Due to skipped revisions, the first "
519 ui.write(_("Due to skipped revisions, the first "
520 "good revision could be any of:\n"))
520 "good revision could be any of:\n"))
521 else:
521 else:
522 ui.write(_("Due to skipped revisions, the first "
522 ui.write(_("Due to skipped revisions, the first "
523 "bad revision could be any of:\n"))
523 "bad revision could be any of:\n"))
524 for n in nodes:
524 for n in nodes:
525 displayer.show(repo[n])
525 displayer.show(repo[n])
526 displayer.close()
526 displayer.close()
527
527
528 def check_state(state, interactive=True):
528 def check_state(state, interactive=True):
529 if not state['good'] or not state['bad']:
529 if not state['good'] or not state['bad']:
530 if (good or bad or skip or reset) and interactive:
530 if (good or bad or skip or reset) and interactive:
531 return
531 return
532 if not state['good']:
532 if not state['good']:
533 raise util.Abort(_('cannot bisect (no known good revisions)'))
533 raise util.Abort(_('cannot bisect (no known good revisions)'))
534 else:
534 else:
535 raise util.Abort(_('cannot bisect (no known bad revisions)'))
535 raise util.Abort(_('cannot bisect (no known bad revisions)'))
536 return True
536 return True
537
537
538 # backward compatibility
538 # backward compatibility
539 if rev in "good bad reset init".split():
539 if rev in "good bad reset init".split():
540 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
540 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
541 cmd, rev, extra = rev, extra, None
541 cmd, rev, extra = rev, extra, None
542 if cmd == "good":
542 if cmd == "good":
543 good = True
543 good = True
544 elif cmd == "bad":
544 elif cmd == "bad":
545 bad = True
545 bad = True
546 else:
546 else:
547 reset = True
547 reset = True
548 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
548 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
549 raise util.Abort(_('incompatible arguments'))
549 raise util.Abort(_('incompatible arguments'))
550
550
551 if reset:
551 if reset:
552 p = repo.join("bisect.state")
552 p = repo.join("bisect.state")
553 if os.path.exists(p):
553 if os.path.exists(p):
554 os.unlink(p)
554 os.unlink(p)
555 return
555 return
556
556
557 state = hbisect.load_state(repo)
557 state = hbisect.load_state(repo)
558
558
559 if command:
559 if command:
560 changesets = 1
560 changesets = 1
561 try:
561 try:
562 while changesets:
562 while changesets:
563 # update state
563 # update state
564 status = util.system(command)
564 status = util.system(command)
565 if status == 125:
565 if status == 125:
566 transition = "skip"
566 transition = "skip"
567 elif status == 0:
567 elif status == 0:
568 transition = "good"
568 transition = "good"
569 # status < 0 means process was killed
569 # status < 0 means process was killed
570 elif status == 127:
570 elif status == 127:
571 raise util.Abort(_("failed to execute %s") % command)
571 raise util.Abort(_("failed to execute %s") % command)
572 elif status < 0:
572 elif status < 0:
573 raise util.Abort(_("%s killed") % command)
573 raise util.Abort(_("%s killed") % command)
574 else:
574 else:
575 transition = "bad"
575 transition = "bad"
576 ctx = scmutil.revsingle(repo, rev)
576 ctx = scmutil.revsingle(repo, rev)
577 rev = None # clear for future iterations
577 rev = None # clear for future iterations
578 state[transition].append(ctx.node())
578 state[transition].append(ctx.node())
579 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
579 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
580 check_state(state, interactive=False)
580 check_state(state, interactive=False)
581 # bisect
581 # bisect
582 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
582 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
583 # update to next check
583 # update to next check
584 cmdutil.bailifchanged(repo)
584 cmdutil.bailifchanged(repo)
585 hg.clean(repo, nodes[0], show_stats=False)
585 hg.clean(repo, nodes[0], show_stats=False)
586 finally:
586 finally:
587 hbisect.save_state(repo, state)
587 hbisect.save_state(repo, state)
588 print_result(nodes, good)
588 print_result(nodes, good)
589 return
589 return
590
590
591 # update state
591 # update state
592
592
593 if rev:
593 if rev:
594 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
594 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
595 else:
595 else:
596 nodes = [repo.lookup('.')]
596 nodes = [repo.lookup('.')]
597
597
598 if good or bad or skip:
598 if good or bad or skip:
599 if good:
599 if good:
600 state['good'] += nodes
600 state['good'] += nodes
601 elif bad:
601 elif bad:
602 state['bad'] += nodes
602 state['bad'] += nodes
603 elif skip:
603 elif skip:
604 state['skip'] += nodes
604 state['skip'] += nodes
605 hbisect.save_state(repo, state)
605 hbisect.save_state(repo, state)
606
606
607 if not check_state(state):
607 if not check_state(state):
608 return
608 return
609
609
610 # actually bisect
610 # actually bisect
611 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
611 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
612 if extend:
612 if extend:
613 if not changesets:
613 if not changesets:
614 extendnode = extendbisectrange(nodes, good)
614 extendnode = extendbisectrange(nodes, good)
615 if extendnode is not None:
615 if extendnode is not None:
616 ui.write(_("Extending search to changeset %d:%s\n"
616 ui.write(_("Extending search to changeset %d:%s\n"
617 % (extendnode.rev(), extendnode)))
617 % (extendnode.rev(), extendnode)))
618 if noupdate:
618 if noupdate:
619 return
619 return
620 cmdutil.bailifchanged(repo)
620 cmdutil.bailifchanged(repo)
621 return hg.clean(repo, extendnode.node())
621 return hg.clean(repo, extendnode.node())
622 raise util.Abort(_("nothing to extend"))
622 raise util.Abort(_("nothing to extend"))
623
623
624 if changesets == 0:
624 if changesets == 0:
625 print_result(nodes, good)
625 print_result(nodes, good)
626 else:
626 else:
627 assert len(nodes) == 1 # only a single node can be tested next
627 assert len(nodes) == 1 # only a single node can be tested next
628 node = nodes[0]
628 node = nodes[0]
629 # compute the approximate number of remaining tests
629 # compute the approximate number of remaining tests
630 tests, size = 0, 2
630 tests, size = 0, 2
631 while size <= changesets:
631 while size <= changesets:
632 tests, size = tests + 1, size * 2
632 tests, size = tests + 1, size * 2
633 rev = repo.changelog.rev(node)
633 rev = repo.changelog.rev(node)
634 ui.write(_("Testing changeset %d:%s "
634 ui.write(_("Testing changeset %d:%s "
635 "(%d changesets remaining, ~%d tests)\n")
635 "(%d changesets remaining, ~%d tests)\n")
636 % (rev, short(node), changesets, tests))
636 % (rev, short(node), changesets, tests))
637 if not noupdate:
637 if not noupdate:
638 cmdutil.bailifchanged(repo)
638 cmdutil.bailifchanged(repo)
639 return hg.clean(repo, node)
639 return hg.clean(repo, node)
640
640
641 @command('bookmarks',
641 @command('bookmarks',
642 [('f', 'force', False, _('force')),
642 [('f', 'force', False, _('force')),
643 ('r', 'rev', '', _('revision'), _('REV')),
643 ('r', 'rev', '', _('revision'), _('REV')),
644 ('d', 'delete', False, _('delete a given bookmark')),
644 ('d', 'delete', False, _('delete a given bookmark')),
645 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
645 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
646 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
646 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
647 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
647 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
648 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
648 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
649 rename=None, inactive=False):
649 rename=None, inactive=False):
650 '''track a line of development with movable markers
650 '''track a line of development with movable markers
651
651
652 Bookmarks are pointers to certain commits that move when
652 Bookmarks are pointers to certain commits that move when
653 committing. Bookmarks are local. They can be renamed, copied and
653 committing. Bookmarks are local. They can be renamed, copied and
654 deleted. It is possible to use bookmark names in :hg:`merge` and
654 deleted. It is possible to use bookmark names in :hg:`merge` and
655 :hg:`update` to merge and update respectively to a given bookmark.
655 :hg:`update` to merge and update respectively to a given bookmark.
656
656
657 You can use :hg:`bookmark NAME` to set a bookmark on the working
657 You can use :hg:`bookmark NAME` to set a bookmark on the working
658 directory's parent revision with the given name. If you specify
658 directory's parent revision with the given name. If you specify
659 a revision using -r REV (where REV may be an existing bookmark),
659 a revision using -r REV (where REV may be an existing bookmark),
660 the bookmark is assigned to that revision.
660 the bookmark is assigned to that revision.
661
661
662 Bookmarks can be pushed and pulled between repositories (see :hg:`help
662 Bookmarks can be pushed and pulled between repositories (see :hg:`help
663 push` and :hg:`help pull`). This requires both the local and remote
663 push` and :hg:`help pull`). This requires both the local and remote
664 repositories to support bookmarks. For versions prior to 1.8, this means
664 repositories to support bookmarks. For versions prior to 1.8, this means
665 the bookmarks extension must be enabled.
665 the bookmarks extension must be enabled.
666 '''
666 '''
667 hexfn = ui.debugflag and hex or short
667 hexfn = ui.debugflag and hex or short
668 marks = repo._bookmarks
668 marks = repo._bookmarks
669 cur = repo.changectx('.').node()
669 cur = repo.changectx('.').node()
670
670
671 if rename:
671 if rename:
672 if rename not in marks:
672 if rename not in marks:
673 raise util.Abort(_("bookmark '%s' does not exist") % rename)
673 raise util.Abort(_("bookmark '%s' does not exist") % rename)
674 if mark in marks and not force:
674 if mark in marks and not force:
675 raise util.Abort(_("bookmark '%s' already exists "
675 raise util.Abort(_("bookmark '%s' already exists "
676 "(use -f to force)") % mark)
676 "(use -f to force)") % mark)
677 if mark is None:
677 if mark is None:
678 raise util.Abort(_("new bookmark name required"))
678 raise util.Abort(_("new bookmark name required"))
679 marks[mark] = marks[rename]
679 marks[mark] = marks[rename]
680 if repo._bookmarkcurrent == rename and not inactive:
680 if repo._bookmarkcurrent == rename and not inactive:
681 bookmarks.setcurrent(repo, mark)
681 bookmarks.setcurrent(repo, mark)
682 del marks[rename]
682 del marks[rename]
683 bookmarks.write(repo)
683 bookmarks.write(repo)
684 return
684 return
685
685
686 if delete:
686 if delete:
687 if mark is None:
687 if mark is None:
688 raise util.Abort(_("bookmark name required"))
688 raise util.Abort(_("bookmark name required"))
689 if mark not in marks:
689 if mark not in marks:
690 raise util.Abort(_("bookmark '%s' does not exist") % mark)
690 raise util.Abort(_("bookmark '%s' does not exist") % mark)
691 if mark == repo._bookmarkcurrent:
691 if mark == repo._bookmarkcurrent:
692 bookmarks.setcurrent(repo, None)
692 bookmarks.setcurrent(repo, None)
693 del marks[mark]
693 del marks[mark]
694 bookmarks.write(repo)
694 bookmarks.write(repo)
695 return
695 return
696
696
697 if mark is not None:
697 if mark is not None:
698 if "\n" in mark:
698 if "\n" in mark:
699 raise util.Abort(_("bookmark name cannot contain newlines"))
699 raise util.Abort(_("bookmark name cannot contain newlines"))
700 mark = mark.strip()
700 mark = mark.strip()
701 if not mark:
701 if not mark:
702 raise util.Abort(_("bookmark names cannot consist entirely of "
702 raise util.Abort(_("bookmark names cannot consist entirely of "
703 "whitespace"))
703 "whitespace"))
704 if inactive and mark == repo._bookmarkcurrent:
704 if inactive and mark == repo._bookmarkcurrent:
705 bookmarks.setcurrent(repo, None)
705 bookmarks.setcurrent(repo, None)
706 return
706 return
707 if mark in marks and not force:
707 if mark in marks and not force:
708 raise util.Abort(_("bookmark '%s' already exists "
708 raise util.Abort(_("bookmark '%s' already exists "
709 "(use -f to force)") % mark)
709 "(use -f to force)") % mark)
710 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
710 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
711 and not force):
711 and not force):
712 raise util.Abort(
712 raise util.Abort(
713 _("a bookmark cannot have the name of an existing branch"))
713 _("a bookmark cannot have the name of an existing branch"))
714 if rev:
714 if rev:
715 marks[mark] = repo.lookup(rev)
715 marks[mark] = repo.lookup(rev)
716 else:
716 else:
717 marks[mark] = repo.changectx('.').node()
717 marks[mark] = repo.changectx('.').node()
718 if not inactive and repo.changectx('.').node() == marks[mark]:
718 if not inactive and repo.changectx('.').node() == marks[mark]:
719 bookmarks.setcurrent(repo, mark)
719 bookmarks.setcurrent(repo, mark)
720 bookmarks.write(repo)
720 bookmarks.write(repo)
721 return
721 return
722
722
723 if mark is None:
723 if mark is None:
724 if rev:
724 if rev:
725 raise util.Abort(_("bookmark name required"))
725 raise util.Abort(_("bookmark name required"))
726 if len(marks) == 0:
726 if len(marks) == 0:
727 ui.status(_("no bookmarks set\n"))
727 ui.status(_("no bookmarks set\n"))
728 else:
728 else:
729 for bmark, n in sorted(marks.iteritems()):
729 for bmark, n in sorted(marks.iteritems()):
730 current = repo._bookmarkcurrent
730 current = repo._bookmarkcurrent
731 if bmark == current and n == cur:
731 if bmark == current and n == cur:
732 prefix, label = '*', 'bookmarks.current'
732 prefix, label = '*', 'bookmarks.current'
733 else:
733 else:
734 prefix, label = ' ', ''
734 prefix, label = ' ', ''
735
735
736 if ui.quiet:
736 if ui.quiet:
737 ui.write("%s\n" % bmark, label=label)
737 ui.write("%s\n" % bmark, label=label)
738 else:
738 else:
739 ui.write(" %s %-25s %d:%s\n" % (
739 ui.write(" %s %-25s %d:%s\n" % (
740 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
740 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
741 label=label)
741 label=label)
742 return
742 return
743
743
744 @command('branch',
744 @command('branch',
745 [('f', 'force', None,
745 [('f', 'force', None,
746 _('set branch name even if it shadows an existing branch')),
746 _('set branch name even if it shadows an existing branch')),
747 ('C', 'clean', None, _('reset branch name to parent branch name'))],
747 ('C', 'clean', None, _('reset branch name to parent branch name'))],
748 _('[-fC] [NAME]'))
748 _('[-fC] [NAME]'))
749 def branch(ui, repo, label=None, **opts):
749 def branch(ui, repo, label=None, **opts):
750 """set or show the current branch name
750 """set or show the current branch name
751
751
752 With no argument, show the current branch name. With one argument,
752 With no argument, show the current branch name. With one argument,
753 set the working directory branch name (the branch will not exist
753 set the working directory branch name (the branch will not exist
754 in the repository until the next commit). Standard practice
754 in the repository until the next commit). Standard practice
755 recommends that primary development take place on the 'default'
755 recommends that primary development take place on the 'default'
756 branch.
756 branch.
757
757
758 Unless -f/--force is specified, branch will not let you set a
758 Unless -f/--force is specified, branch will not let you set a
759 branch name that already exists, even if it's inactive.
759 branch name that already exists, even if it's inactive.
760
760
761 Use -C/--clean to reset the working directory branch to that of
761 Use -C/--clean to reset the working directory branch to that of
762 the parent of the working directory, negating a previous branch
762 the parent of the working directory, negating a previous branch
763 change.
763 change.
764
764
765 Use the command :hg:`update` to switch to an existing branch. Use
765 Use the command :hg:`update` to switch to an existing branch. Use
766 :hg:`commit --close-branch` to mark this branch as closed.
766 :hg:`commit --close-branch` to mark this branch as closed.
767
767
768 .. note::
768 .. note::
769
769
770 Branch names are permanent. Use :hg:`bookmark` to create a
770 Branch names are permanent. Use :hg:`bookmark` to create a
771 light-weight bookmark instead. See :hg:`help glossary` for more
771 light-weight bookmark instead. See :hg:`help glossary` for more
772 information about named branches and bookmarks.
772 information about named branches and bookmarks.
773
773
774 Returns 0 on success.
774 Returns 0 on success.
775 """
775 """
776
776
777 if opts.get('clean'):
777 if opts.get('clean'):
778 label = repo[None].p1().branch()
778 label = repo[None].p1().branch()
779 repo.dirstate.setbranch(label)
779 repo.dirstate.setbranch(label)
780 ui.status(_('reset working directory to branch %s\n') % label)
780 ui.status(_('reset working directory to branch %s\n') % label)
781 elif label:
781 elif label:
782 if not opts.get('force') and label in repo.branchtags():
782 if not opts.get('force') and label in repo.branchtags():
783 if label not in [p.branch() for p in repo.parents()]:
783 if label not in [p.branch() for p in repo.parents()]:
784 raise util.Abort(_('a branch of the same name already exists'),
784 raise util.Abort(_('a branch of the same name already exists'),
785 # i18n: "it" refers to an existing branch
785 # i18n: "it" refers to an existing branch
786 hint=_("use 'hg update' to switch to it"))
786 hint=_("use 'hg update' to switch to it"))
787 repo.dirstate.setbranch(label)
787 repo.dirstate.setbranch(label)
788 ui.status(_('marked working directory as branch %s\n') % label)
788 ui.status(_('marked working directory as branch %s\n') % label)
789 else:
789 else:
790 ui.write("%s\n" % repo.dirstate.branch())
790 ui.write("%s\n" % repo.dirstate.branch())
791
791
792 @command('branches',
792 @command('branches',
793 [('a', 'active', False, _('show only branches that have unmerged heads')),
793 [('a', 'active', False, _('show only branches that have unmerged heads')),
794 ('c', 'closed', False, _('show normal and closed branches'))],
794 ('c', 'closed', False, _('show normal and closed branches'))],
795 _('[-ac]'))
795 _('[-ac]'))
796 def branches(ui, repo, active=False, closed=False):
796 def branches(ui, repo, active=False, closed=False):
797 """list repository named branches
797 """list repository named branches
798
798
799 List the repository's named branches, indicating which ones are
799 List the repository's named branches, indicating which ones are
800 inactive. If -c/--closed is specified, also list branches which have
800 inactive. If -c/--closed is specified, also list branches which have
801 been marked closed (see :hg:`commit --close-branch`).
801 been marked closed (see :hg:`commit --close-branch`).
802
802
803 If -a/--active is specified, only show active branches. A branch
803 If -a/--active is specified, only show active branches. A branch
804 is considered active if it contains repository heads.
804 is considered active if it contains repository heads.
805
805
806 Use the command :hg:`update` to switch to an existing branch.
806 Use the command :hg:`update` to switch to an existing branch.
807
807
808 Returns 0.
808 Returns 0.
809 """
809 """
810
810
811 hexfunc = ui.debugflag and hex or short
811 hexfunc = ui.debugflag and hex or short
812 activebranches = [repo[n].branch() for n in repo.heads()]
812 activebranches = [repo[n].branch() for n in repo.heads()]
813 def testactive(tag, node):
813 def testactive(tag, node):
814 realhead = tag in activebranches
814 realhead = tag in activebranches
815 open = node in repo.branchheads(tag, closed=False)
815 open = node in repo.branchheads(tag, closed=False)
816 return realhead and open
816 return realhead and open
817 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
817 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
818 for tag, node in repo.branchtags().items()],
818 for tag, node in repo.branchtags().items()],
819 reverse=True)
819 reverse=True)
820
820
821 for isactive, node, tag in branches:
821 for isactive, node, tag in branches:
822 if (not active) or isactive:
822 if (not active) or isactive:
823 if ui.quiet:
823 if ui.quiet:
824 ui.write("%s\n" % tag)
824 ui.write("%s\n" % tag)
825 else:
825 else:
826 hn = repo.lookup(node)
826 hn = repo.lookup(node)
827 if isactive:
827 if isactive:
828 label = 'branches.active'
828 label = 'branches.active'
829 notice = ''
829 notice = ''
830 elif hn not in repo.branchheads(tag, closed=False):
830 elif hn not in repo.branchheads(tag, closed=False):
831 if not closed:
831 if not closed:
832 continue
832 continue
833 label = 'branches.closed'
833 label = 'branches.closed'
834 notice = _(' (closed)')
834 notice = _(' (closed)')
835 else:
835 else:
836 label = 'branches.inactive'
836 label = 'branches.inactive'
837 notice = _(' (inactive)')
837 notice = _(' (inactive)')
838 if tag == repo.dirstate.branch():
838 if tag == repo.dirstate.branch():
839 label = 'branches.current'
839 label = 'branches.current'
840 rev = str(node).rjust(31 - encoding.colwidth(tag))
840 rev = str(node).rjust(31 - encoding.colwidth(tag))
841 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
841 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
842 tag = ui.label(tag, label)
842 tag = ui.label(tag, label)
843 ui.write("%s %s%s\n" % (tag, rev, notice))
843 ui.write("%s %s%s\n" % (tag, rev, notice))
844
844
845 @command('bundle',
845 @command('bundle',
846 [('f', 'force', None, _('run even when the destination is unrelated')),
846 [('f', 'force', None, _('run even when the destination is unrelated')),
847 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
847 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
848 _('REV')),
848 _('REV')),
849 ('b', 'branch', [], _('a specific branch you would like to bundle'),
849 ('b', 'branch', [], _('a specific branch you would like to bundle'),
850 _('BRANCH')),
850 _('BRANCH')),
851 ('', 'base', [],
851 ('', 'base', [],
852 _('a base changeset assumed to be available at the destination'),
852 _('a base changeset assumed to be available at the destination'),
853 _('REV')),
853 _('REV')),
854 ('a', 'all', None, _('bundle all changesets in the repository')),
854 ('a', 'all', None, _('bundle all changesets in the repository')),
855 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
855 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
856 ] + remoteopts,
856 ] + remoteopts,
857 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
857 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
858 def bundle(ui, repo, fname, dest=None, **opts):
858 def bundle(ui, repo, fname, dest=None, **opts):
859 """create a changegroup file
859 """create a changegroup file
860
860
861 Generate a compressed changegroup file collecting changesets not
861 Generate a compressed changegroup file collecting changesets not
862 known to be in another repository.
862 known to be in another repository.
863
863
864 If you omit the destination repository, then hg assumes the
864 If you omit the destination repository, then hg assumes the
865 destination will have all the nodes you specify with --base
865 destination will have all the nodes you specify with --base
866 parameters. To create a bundle containing all changesets, use
866 parameters. To create a bundle containing all changesets, use
867 -a/--all (or --base null).
867 -a/--all (or --base null).
868
868
869 You can change compression method with the -t/--type option.
869 You can change compression method with the -t/--type option.
870 The available compression methods are: none, bzip2, and
870 The available compression methods are: none, bzip2, and
871 gzip (by default, bundles are compressed using bzip2).
871 gzip (by default, bundles are compressed using bzip2).
872
872
873 The bundle file can then be transferred using conventional means
873 The bundle file can then be transferred using conventional means
874 and applied to another repository with the unbundle or pull
874 and applied to another repository with the unbundle or pull
875 command. This is useful when direct push and pull are not
875 command. This is useful when direct push and pull are not
876 available or when exporting an entire repository is undesirable.
876 available or when exporting an entire repository is undesirable.
877
877
878 Applying bundles preserves all changeset contents including
878 Applying bundles preserves all changeset contents including
879 permissions, copy/rename information, and revision history.
879 permissions, copy/rename information, and revision history.
880
880
881 Returns 0 on success, 1 if no changes found.
881 Returns 0 on success, 1 if no changes found.
882 """
882 """
883 revs = None
883 revs = None
884 if 'rev' in opts:
884 if 'rev' in opts:
885 revs = scmutil.revrange(repo, opts['rev'])
885 revs = scmutil.revrange(repo, opts['rev'])
886
886
887 if opts.get('all'):
887 if opts.get('all'):
888 base = ['null']
888 base = ['null']
889 else:
889 else:
890 base = scmutil.revrange(repo, opts.get('base'))
890 base = scmutil.revrange(repo, opts.get('base'))
891 if base:
891 if base:
892 if dest:
892 if dest:
893 raise util.Abort(_("--base is incompatible with specifying "
893 raise util.Abort(_("--base is incompatible with specifying "
894 "a destination"))
894 "a destination"))
895 common = [repo.lookup(rev) for rev in base]
895 common = [repo.lookup(rev) for rev in base]
896 heads = revs and map(repo.lookup, revs) or revs
896 heads = revs and map(repo.lookup, revs) or revs
897 else:
897 else:
898 dest = ui.expandpath(dest or 'default-push', dest or 'default')
898 dest = ui.expandpath(dest or 'default-push', dest or 'default')
899 dest, branches = hg.parseurl(dest, opts.get('branch'))
899 dest, branches = hg.parseurl(dest, opts.get('branch'))
900 other = hg.peer(repo, opts, dest)
900 other = hg.peer(repo, opts, dest)
901 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
901 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
902 heads = revs and map(repo.lookup, revs) or revs
902 heads = revs and map(repo.lookup, revs) or revs
903 common, outheads = discovery.findcommonoutgoing(repo, other,
903 common, outheads = discovery.findcommonoutgoing(repo, other,
904 onlyheads=heads,
904 onlyheads=heads,
905 force=opts.get('force'))
905 force=opts.get('force'))
906
906
907 cg = repo.getbundle('bundle', common=common, heads=heads)
907 cg = repo.getbundle('bundle', common=common, heads=heads)
908 if not cg:
908 if not cg:
909 ui.status(_("no changes found\n"))
909 ui.status(_("no changes found\n"))
910 return 1
910 return 1
911
911
912 bundletype = opts.get('type', 'bzip2').lower()
912 bundletype = opts.get('type', 'bzip2').lower()
913 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
913 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
914 bundletype = btypes.get(bundletype)
914 bundletype = btypes.get(bundletype)
915 if bundletype not in changegroup.bundletypes:
915 if bundletype not in changegroup.bundletypes:
916 raise util.Abort(_('unknown bundle type specified with --type'))
916 raise util.Abort(_('unknown bundle type specified with --type'))
917
917
918 changegroup.writebundle(cg, fname, bundletype)
918 changegroup.writebundle(cg, fname, bundletype)
919
919
920 @command('cat',
920 @command('cat',
921 [('o', 'output', '',
921 [('o', 'output', '',
922 _('print output to file with formatted name'), _('FORMAT')),
922 _('print output to file with formatted name'), _('FORMAT')),
923 ('r', 'rev', '', _('print the given revision'), _('REV')),
923 ('r', 'rev', '', _('print the given revision'), _('REV')),
924 ('', 'decode', None, _('apply any matching decode filter')),
924 ('', 'decode', None, _('apply any matching decode filter')),
925 ] + walkopts,
925 ] + walkopts,
926 _('[OPTION]... FILE...'))
926 _('[OPTION]... FILE...'))
927 def cat(ui, repo, file1, *pats, **opts):
927 def cat(ui, repo, file1, *pats, **opts):
928 """output the current or given revision of files
928 """output the current or given revision of files
929
929
930 Print the specified files as they were at the given revision. If
930 Print the specified files as they were at the given revision. If
931 no revision is given, the parent of the working directory is used,
931 no revision is given, the parent of the working directory is used,
932 or tip if no revision is checked out.
932 or tip if no revision is checked out.
933
933
934 Output may be to a file, in which case the name of the file is
934 Output may be to a file, in which case the name of the file is
935 given using a format string. The formatting rules are the same as
935 given using a format string. The formatting rules are the same as
936 for the export command, with the following additions:
936 for the export command, with the following additions:
937
937
938 :``%s``: basename of file being printed
938 :``%s``: basename of file being printed
939 :``%d``: dirname of file being printed, or '.' if in repository root
939 :``%d``: dirname of file being printed, or '.' if in repository root
940 :``%p``: root-relative path name of file being printed
940 :``%p``: root-relative path name of file being printed
941
941
942 Returns 0 on success.
942 Returns 0 on success.
943 """
943 """
944 ctx = scmutil.revsingle(repo, opts.get('rev'))
944 ctx = scmutil.revsingle(repo, opts.get('rev'))
945 err = 1
945 err = 1
946 m = scmutil.match(repo, (file1,) + pats, opts)
946 m = scmutil.match(repo, (file1,) + pats, opts)
947 for abs in ctx.walk(m):
947 for abs in ctx.walk(m):
948 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
948 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
949 pathname=abs)
949 pathname=abs)
950 data = ctx[abs].data()
950 data = ctx[abs].data()
951 if opts.get('decode'):
951 if opts.get('decode'):
952 data = repo.wwritedata(abs, data)
952 data = repo.wwritedata(abs, data)
953 fp.write(data)
953 fp.write(data)
954 fp.close()
954 fp.close()
955 err = 0
955 err = 0
956 return err
956 return err
957
957
958 @command('^clone',
958 @command('^clone',
959 [('U', 'noupdate', None,
959 [('U', 'noupdate', None,
960 _('the clone will include an empty working copy (only a repository)')),
960 _('the clone will include an empty working copy (only a repository)')),
961 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
961 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
962 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
962 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
963 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
963 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
964 ('', 'pull', None, _('use pull protocol to copy metadata')),
964 ('', 'pull', None, _('use pull protocol to copy metadata')),
965 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
965 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
966 ] + remoteopts,
966 ] + remoteopts,
967 _('[OPTION]... SOURCE [DEST]'))
967 _('[OPTION]... SOURCE [DEST]'))
968 def clone(ui, source, dest=None, **opts):
968 def clone(ui, source, dest=None, **opts):
969 """make a copy of an existing repository
969 """make a copy of an existing repository
970
970
971 Create a copy of an existing repository in a new directory.
971 Create a copy of an existing repository in a new directory.
972
972
973 If no destination directory name is specified, it defaults to the
973 If no destination directory name is specified, it defaults to the
974 basename of the source.
974 basename of the source.
975
975
976 The location of the source is added to the new repository's
976 The location of the source is added to the new repository's
977 ``.hg/hgrc`` file, as the default to be used for future pulls.
977 ``.hg/hgrc`` file, as the default to be used for future pulls.
978
978
979 See :hg:`help urls` for valid source format details.
979 See :hg:`help urls` for valid source format details.
980
980
981 It is possible to specify an ``ssh://`` URL as the destination, but no
981 It is possible to specify an ``ssh://`` URL as the destination, but no
982 ``.hg/hgrc`` and working directory will be created on the remote side.
982 ``.hg/hgrc`` and working directory will be created on the remote side.
983 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
983 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
984
984
985 A set of changesets (tags, or branch names) to pull may be specified
985 A set of changesets (tags, or branch names) to pull may be specified
986 by listing each changeset (tag, or branch name) with -r/--rev.
986 by listing each changeset (tag, or branch name) with -r/--rev.
987 If -r/--rev is used, the cloned repository will contain only a subset
987 If -r/--rev is used, the cloned repository will contain only a subset
988 of the changesets of the source repository. Only the set of changesets
988 of the changesets of the source repository. Only the set of changesets
989 defined by all -r/--rev options (including all their ancestors)
989 defined by all -r/--rev options (including all their ancestors)
990 will be pulled into the destination repository.
990 will be pulled into the destination repository.
991 No subsequent changesets (including subsequent tags) will be present
991 No subsequent changesets (including subsequent tags) will be present
992 in the destination.
992 in the destination.
993
993
994 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
994 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
995 local source repositories.
995 local source repositories.
996
996
997 For efficiency, hardlinks are used for cloning whenever the source
997 For efficiency, hardlinks are used for cloning whenever the source
998 and destination are on the same filesystem (note this applies only
998 and destination are on the same filesystem (note this applies only
999 to the repository data, not to the working directory). Some
999 to the repository data, not to the working directory). Some
1000 filesystems, such as AFS, implement hardlinking incorrectly, but
1000 filesystems, such as AFS, implement hardlinking incorrectly, but
1001 do not report errors. In these cases, use the --pull option to
1001 do not report errors. In these cases, use the --pull option to
1002 avoid hardlinking.
1002 avoid hardlinking.
1003
1003
1004 In some cases, you can clone repositories and the working directory
1004 In some cases, you can clone repositories and the working directory
1005 using full hardlinks with ::
1005 using full hardlinks with ::
1006
1006
1007 $ cp -al REPO REPOCLONE
1007 $ cp -al REPO REPOCLONE
1008
1008
1009 This is the fastest way to clone, but it is not always safe. The
1009 This is the fastest way to clone, but it is not always safe. The
1010 operation is not atomic (making sure REPO is not modified during
1010 operation is not atomic (making sure REPO is not modified during
1011 the operation is up to you) and you have to make sure your editor
1011 the operation is up to you) and you have to make sure your editor
1012 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1012 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1013 this is not compatible with certain extensions that place their
1013 this is not compatible with certain extensions that place their
1014 metadata under the .hg directory, such as mq.
1014 metadata under the .hg directory, such as mq.
1015
1015
1016 Mercurial will update the working directory to the first applicable
1016 Mercurial will update the working directory to the first applicable
1017 revision from this list:
1017 revision from this list:
1018
1018
1019 a) null if -U or the source repository has no changesets
1019 a) null if -U or the source repository has no changesets
1020 b) if -u . and the source repository is local, the first parent of
1020 b) if -u . and the source repository is local, the first parent of
1021 the source repository's working directory
1021 the source repository's working directory
1022 c) the changeset specified with -u (if a branch name, this means the
1022 c) the changeset specified with -u (if a branch name, this means the
1023 latest head of that branch)
1023 latest head of that branch)
1024 d) the changeset specified with -r
1024 d) the changeset specified with -r
1025 e) the tipmost head specified with -b
1025 e) the tipmost head specified with -b
1026 f) the tipmost head specified with the url#branch source syntax
1026 f) the tipmost head specified with the url#branch source syntax
1027 g) the tipmost head of the default branch
1027 g) the tipmost head of the default branch
1028 h) tip
1028 h) tip
1029
1029
1030 Returns 0 on success.
1030 Returns 0 on success.
1031 """
1031 """
1032 if opts.get('noupdate') and opts.get('updaterev'):
1032 if opts.get('noupdate') and opts.get('updaterev'):
1033 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1033 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1034
1034
1035 r = hg.clone(ui, opts, source, dest,
1035 r = hg.clone(ui, opts, source, dest,
1036 pull=opts.get('pull'),
1036 pull=opts.get('pull'),
1037 stream=opts.get('uncompressed'),
1037 stream=opts.get('uncompressed'),
1038 rev=opts.get('rev'),
1038 rev=opts.get('rev'),
1039 update=opts.get('updaterev') or not opts.get('noupdate'),
1039 update=opts.get('updaterev') or not opts.get('noupdate'),
1040 branch=opts.get('branch'))
1040 branch=opts.get('branch'))
1041
1041
1042 return r is None
1042 return r is None
1043
1043
1044 @command('^commit|ci',
1044 @command('^commit|ci',
1045 [('A', 'addremove', None,
1045 [('A', 'addremove', None,
1046 _('mark new/missing files as added/removed before committing')),
1046 _('mark new/missing files as added/removed before committing')),
1047 ('', 'close-branch', None,
1047 ('', 'close-branch', None,
1048 _('mark a branch as closed, hiding it from the branch list')),
1048 _('mark a branch as closed, hiding it from the branch list')),
1049 ] + walkopts + commitopts + commitopts2,
1049 ] + walkopts + commitopts + commitopts2,
1050 _('[OPTION]... [FILE]...'))
1050 _('[OPTION]... [FILE]...'))
1051 def commit(ui, repo, *pats, **opts):
1051 def commit(ui, repo, *pats, **opts):
1052 """commit the specified files or all outstanding changes
1052 """commit the specified files or all outstanding changes
1053
1053
1054 Commit changes to the given files into the repository. Unlike a
1054 Commit changes to the given files into the repository. Unlike a
1055 centralized SCM, this operation is a local operation. See
1055 centralized SCM, this operation is a local operation. See
1056 :hg:`push` for a way to actively distribute your changes.
1056 :hg:`push` for a way to actively distribute your changes.
1057
1057
1058 If a list of files is omitted, all changes reported by :hg:`status`
1058 If a list of files is omitted, all changes reported by :hg:`status`
1059 will be committed.
1059 will be committed.
1060
1060
1061 If you are committing the result of a merge, do not provide any
1061 If you are committing the result of a merge, do not provide any
1062 filenames or -I/-X filters.
1062 filenames or -I/-X filters.
1063
1063
1064 If no commit message is specified, Mercurial starts your
1064 If no commit message is specified, Mercurial starts your
1065 configured editor where you can enter a message. In case your
1065 configured editor where you can enter a message. In case your
1066 commit fails, you will find a backup of your message in
1066 commit fails, you will find a backup of your message in
1067 ``.hg/last-message.txt``.
1067 ``.hg/last-message.txt``.
1068
1068
1069 See :hg:`help dates` for a list of formats valid for -d/--date.
1069 See :hg:`help dates` for a list of formats valid for -d/--date.
1070
1070
1071 Returns 0 on success, 1 if nothing changed.
1071 Returns 0 on success, 1 if nothing changed.
1072 """
1072 """
1073 extra = {}
1073 extra = {}
1074 if opts.get('close_branch'):
1074 if opts.get('close_branch'):
1075 if repo['.'].node() not in repo.branchheads():
1075 if repo['.'].node() not in repo.branchheads():
1076 # The topo heads set is included in the branch heads set of the
1076 # The topo heads set is included in the branch heads set of the
1077 # current branch, so it's sufficient to test branchheads
1077 # current branch, so it's sufficient to test branchheads
1078 raise util.Abort(_('can only close branch heads'))
1078 raise util.Abort(_('can only close branch heads'))
1079 extra['close'] = 1
1079 extra['close'] = 1
1080 e = cmdutil.commiteditor
1080 e = cmdutil.commiteditor
1081 if opts.get('force_editor'):
1081 if opts.get('force_editor'):
1082 e = cmdutil.commitforceeditor
1082 e = cmdutil.commitforceeditor
1083
1083
1084 def commitfunc(ui, repo, message, match, opts):
1084 def commitfunc(ui, repo, message, match, opts):
1085 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1085 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1086 editor=e, extra=extra)
1086 editor=e, extra=extra)
1087
1087
1088 branch = repo[None].branch()
1088 branch = repo[None].branch()
1089 bheads = repo.branchheads(branch)
1089 bheads = repo.branchheads(branch)
1090
1090
1091 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1091 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1092 if not node:
1092 if not node:
1093 stat = repo.status(match=scmutil.match(repo, pats, opts))
1093 stat = repo.status(match=scmutil.match(repo, pats, opts))
1094 if stat[3]:
1094 if stat[3]:
1095 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1095 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1096 % len(stat[3]))
1096 % len(stat[3]))
1097 else:
1097 else:
1098 ui.status(_("nothing changed\n"))
1098 ui.status(_("nothing changed\n"))
1099 return 1
1099 return 1
1100
1100
1101 ctx = repo[node]
1101 ctx = repo[node]
1102 parents = ctx.parents()
1102 parents = ctx.parents()
1103
1103
1104 if bheads and not [x for x in parents
1104 if bheads and not [x for x in parents
1105 if x.node() in bheads and x.branch() == branch]:
1105 if x.node() in bheads and x.branch() == branch]:
1106 ui.status(_('created new head\n'))
1106 ui.status(_('created new head\n'))
1107 # The message is not printed for initial roots. For the other
1107 # The message is not printed for initial roots. For the other
1108 # changesets, it is printed in the following situations:
1108 # changesets, it is printed in the following situations:
1109 #
1109 #
1110 # Par column: for the 2 parents with ...
1110 # Par column: for the 2 parents with ...
1111 # N: null or no parent
1111 # N: null or no parent
1112 # B: parent is on another named branch
1112 # B: parent is on another named branch
1113 # C: parent is a regular non head changeset
1113 # C: parent is a regular non head changeset
1114 # H: parent was a branch head of the current branch
1114 # H: parent was a branch head of the current branch
1115 # Msg column: whether we print "created new head" message
1115 # Msg column: whether we print "created new head" message
1116 # In the following, it is assumed that there already exists some
1116 # In the following, it is assumed that there already exists some
1117 # initial branch heads of the current branch, otherwise nothing is
1117 # initial branch heads of the current branch, otherwise nothing is
1118 # printed anyway.
1118 # printed anyway.
1119 #
1119 #
1120 # Par Msg Comment
1120 # Par Msg Comment
1121 # NN y additional topo root
1121 # NN y additional topo root
1122 #
1122 #
1123 # BN y additional branch root
1123 # BN y additional branch root
1124 # CN y additional topo head
1124 # CN y additional topo head
1125 # HN n usual case
1125 # HN n usual case
1126 #
1126 #
1127 # BB y weird additional branch root
1127 # BB y weird additional branch root
1128 # CB y branch merge
1128 # CB y branch merge
1129 # HB n merge with named branch
1129 # HB n merge with named branch
1130 #
1130 #
1131 # CC y additional head from merge
1131 # CC y additional head from merge
1132 # CH n merge with a head
1132 # CH n merge with a head
1133 #
1133 #
1134 # HH n head merge: head count decreases
1134 # HH n head merge: head count decreases
1135
1135
1136 if not opts.get('close_branch'):
1136 if not opts.get('close_branch'):
1137 for r in parents:
1137 for r in parents:
1138 if r.extra().get('close') and r.branch() == branch:
1138 if r.extra().get('close') and r.branch() == branch:
1139 ui.status(_('reopening closed branch head %d\n') % r)
1139 ui.status(_('reopening closed branch head %d\n') % r)
1140
1140
1141 if ui.debugflag:
1141 if ui.debugflag:
1142 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1142 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1143 elif ui.verbose:
1143 elif ui.verbose:
1144 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1144 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1145
1145
1146 @command('copy|cp',
1146 @command('copy|cp',
1147 [('A', 'after', None, _('record a copy that has already occurred')),
1147 [('A', 'after', None, _('record a copy that has already occurred')),
1148 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1148 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1149 ] + walkopts + dryrunopts,
1149 ] + walkopts + dryrunopts,
1150 _('[OPTION]... [SOURCE]... DEST'))
1150 _('[OPTION]... [SOURCE]... DEST'))
1151 def copy(ui, repo, *pats, **opts):
1151 def copy(ui, repo, *pats, **opts):
1152 """mark files as copied for the next commit
1152 """mark files as copied for the next commit
1153
1153
1154 Mark dest as having copies of source files. If dest is a
1154 Mark dest as having copies of source files. If dest is a
1155 directory, copies are put in that directory. If dest is a file,
1155 directory, copies are put in that directory. If dest is a file,
1156 the source must be a single file.
1156 the source must be a single file.
1157
1157
1158 By default, this command copies the contents of files as they
1158 By default, this command copies the contents of files as they
1159 exist in the working directory. If invoked with -A/--after, the
1159 exist in the working directory. If invoked with -A/--after, the
1160 operation is recorded, but no copying is performed.
1160 operation is recorded, but no copying is performed.
1161
1161
1162 This command takes effect with the next commit. To undo a copy
1162 This command takes effect with the next commit. To undo a copy
1163 before that, see :hg:`revert`.
1163 before that, see :hg:`revert`.
1164
1164
1165 Returns 0 on success, 1 if errors are encountered.
1165 Returns 0 on success, 1 if errors are encountered.
1166 """
1166 """
1167 wlock = repo.wlock(False)
1167 wlock = repo.wlock(False)
1168 try:
1168 try:
1169 return cmdutil.copy(ui, repo, pats, opts)
1169 return cmdutil.copy(ui, repo, pats, opts)
1170 finally:
1170 finally:
1171 wlock.release()
1171 wlock.release()
1172
1172
1173 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1173 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1174 def debugancestor(ui, repo, *args):
1174 def debugancestor(ui, repo, *args):
1175 """find the ancestor revision of two revisions in a given index"""
1175 """find the ancestor revision of two revisions in a given index"""
1176 if len(args) == 3:
1176 if len(args) == 3:
1177 index, rev1, rev2 = args
1177 index, rev1, rev2 = args
1178 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1178 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1179 lookup = r.lookup
1179 lookup = r.lookup
1180 elif len(args) == 2:
1180 elif len(args) == 2:
1181 if not repo:
1181 if not repo:
1182 raise util.Abort(_("there is no Mercurial repository here "
1182 raise util.Abort(_("there is no Mercurial repository here "
1183 "(.hg not found)"))
1183 "(.hg not found)"))
1184 rev1, rev2 = args
1184 rev1, rev2 = args
1185 r = repo.changelog
1185 r = repo.changelog
1186 lookup = repo.lookup
1186 lookup = repo.lookup
1187 else:
1187 else:
1188 raise util.Abort(_('either two or three arguments required'))
1188 raise util.Abort(_('either two or three arguments required'))
1189 a = r.ancestor(lookup(rev1), lookup(rev2))
1189 a = r.ancestor(lookup(rev1), lookup(rev2))
1190 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1190 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1191
1191
1192 @command('debugbuilddag',
1192 @command('debugbuilddag',
1193 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1193 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1194 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1194 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1195 ('n', 'new-file', None, _('add new file at each rev'))],
1195 ('n', 'new-file', None, _('add new file at each rev'))],
1196 _('[OPTION]... [TEXT]'))
1196 _('[OPTION]... [TEXT]'))
1197 def debugbuilddag(ui, repo, text=None,
1197 def debugbuilddag(ui, repo, text=None,
1198 mergeable_file=False,
1198 mergeable_file=False,
1199 overwritten_file=False,
1199 overwritten_file=False,
1200 new_file=False):
1200 new_file=False):
1201 """builds a repo with a given DAG from scratch in the current empty repo
1201 """builds a repo with a given DAG from scratch in the current empty repo
1202
1202
1203 The description of the DAG is read from stdin if not given on the
1203 The description of the DAG is read from stdin if not given on the
1204 command line.
1204 command line.
1205
1205
1206 Elements:
1206 Elements:
1207
1207
1208 - "+n" is a linear run of n nodes based on the current default parent
1208 - "+n" is a linear run of n nodes based on the current default parent
1209 - "." is a single node based on the current default parent
1209 - "." is a single node based on the current default parent
1210 - "$" resets the default parent to null (implied at the start);
1210 - "$" resets the default parent to null (implied at the start);
1211 otherwise the default parent is always the last node created
1211 otherwise the default parent is always the last node created
1212 - "<p" sets the default parent to the backref p
1212 - "<p" sets the default parent to the backref p
1213 - "*p" is a fork at parent p, which is a backref
1213 - "*p" is a fork at parent p, which is a backref
1214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1215 - "/p2" is a merge of the preceding node and p2
1215 - "/p2" is a merge of the preceding node and p2
1216 - ":tag" defines a local tag for the preceding node
1216 - ":tag" defines a local tag for the preceding node
1217 - "@branch" sets the named branch for subsequent nodes
1217 - "@branch" sets the named branch for subsequent nodes
1218 - "#...\\n" is a comment up to the end of the line
1218 - "#...\\n" is a comment up to the end of the line
1219
1219
1220 Whitespace between the above elements is ignored.
1220 Whitespace between the above elements is ignored.
1221
1221
1222 A backref is either
1222 A backref is either
1223
1223
1224 - a number n, which references the node curr-n, where curr is the current
1224 - a number n, which references the node curr-n, where curr is the current
1225 node, or
1225 node, or
1226 - the name of a local tag you placed earlier using ":tag", or
1226 - the name of a local tag you placed earlier using ":tag", or
1227 - empty to denote the default parent.
1227 - empty to denote the default parent.
1228
1228
1229 All string valued-elements are either strictly alphanumeric, or must
1229 All string valued-elements are either strictly alphanumeric, or must
1230 be enclosed in double quotes ("..."), with "\\" as escape character.
1230 be enclosed in double quotes ("..."), with "\\" as escape character.
1231 """
1231 """
1232
1232
1233 if text is None:
1233 if text is None:
1234 ui.status(_("reading DAG from stdin\n"))
1234 ui.status(_("reading DAG from stdin\n"))
1235 text = ui.fin.read()
1235 text = ui.fin.read()
1236
1236
1237 cl = repo.changelog
1237 cl = repo.changelog
1238 if len(cl) > 0:
1238 if len(cl) > 0:
1239 raise util.Abort(_('repository is not empty'))
1239 raise util.Abort(_('repository is not empty'))
1240
1240
1241 # determine number of revs in DAG
1241 # determine number of revs in DAG
1242 total = 0
1242 total = 0
1243 for type, data in dagparser.parsedag(text):
1243 for type, data in dagparser.parsedag(text):
1244 if type == 'n':
1244 if type == 'n':
1245 total += 1
1245 total += 1
1246
1246
1247 if mergeable_file:
1247 if mergeable_file:
1248 linesperrev = 2
1248 linesperrev = 2
1249 # make a file with k lines per rev
1249 # make a file with k lines per rev
1250 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1250 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1251 initialmergedlines.append("")
1251 initialmergedlines.append("")
1252
1252
1253 tags = []
1253 tags = []
1254
1254
1255 tr = repo.transaction("builddag")
1255 tr = repo.transaction("builddag")
1256 try:
1256 try:
1257
1257
1258 at = -1
1258 at = -1
1259 atbranch = 'default'
1259 atbranch = 'default'
1260 nodeids = []
1260 nodeids = []
1261 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1261 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1262 for type, data in dagparser.parsedag(text):
1262 for type, data in dagparser.parsedag(text):
1263 if type == 'n':
1263 if type == 'n':
1264 ui.note('node %s\n' % str(data))
1264 ui.note('node %s\n' % str(data))
1265 id, ps = data
1265 id, ps = data
1266
1266
1267 files = []
1267 files = []
1268 fctxs = {}
1268 fctxs = {}
1269
1269
1270 p2 = None
1270 p2 = None
1271 if mergeable_file:
1271 if mergeable_file:
1272 fn = "mf"
1272 fn = "mf"
1273 p1 = repo[ps[0]]
1273 p1 = repo[ps[0]]
1274 if len(ps) > 1:
1274 if len(ps) > 1:
1275 p2 = repo[ps[1]]
1275 p2 = repo[ps[1]]
1276 pa = p1.ancestor(p2)
1276 pa = p1.ancestor(p2)
1277 base, local, other = [x[fn].data() for x in pa, p1, p2]
1277 base, local, other = [x[fn].data() for x in pa, p1, p2]
1278 m3 = simplemerge.Merge3Text(base, local, other)
1278 m3 = simplemerge.Merge3Text(base, local, other)
1279 ml = [l.strip() for l in m3.merge_lines()]
1279 ml = [l.strip() for l in m3.merge_lines()]
1280 ml.append("")
1280 ml.append("")
1281 elif at > 0:
1281 elif at > 0:
1282 ml = p1[fn].data().split("\n")
1282 ml = p1[fn].data().split("\n")
1283 else:
1283 else:
1284 ml = initialmergedlines
1284 ml = initialmergedlines
1285 ml[id * linesperrev] += " r%i" % id
1285 ml[id * linesperrev] += " r%i" % id
1286 mergedtext = "\n".join(ml)
1286 mergedtext = "\n".join(ml)
1287 files.append(fn)
1287 files.append(fn)
1288 fctxs[fn] = context.memfilectx(fn, mergedtext)
1288 fctxs[fn] = context.memfilectx(fn, mergedtext)
1289
1289
1290 if overwritten_file:
1290 if overwritten_file:
1291 fn = "of"
1291 fn = "of"
1292 files.append(fn)
1292 files.append(fn)
1293 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1293 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1294
1294
1295 if new_file:
1295 if new_file:
1296 fn = "nf%i" % id
1296 fn = "nf%i" % id
1297 files.append(fn)
1297 files.append(fn)
1298 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1298 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1299 if len(ps) > 1:
1299 if len(ps) > 1:
1300 if not p2:
1300 if not p2:
1301 p2 = repo[ps[1]]
1301 p2 = repo[ps[1]]
1302 for fn in p2:
1302 for fn in p2:
1303 if fn.startswith("nf"):
1303 if fn.startswith("nf"):
1304 files.append(fn)
1304 files.append(fn)
1305 fctxs[fn] = p2[fn]
1305 fctxs[fn] = p2[fn]
1306
1306
1307 def fctxfn(repo, cx, path):
1307 def fctxfn(repo, cx, path):
1308 return fctxs.get(path)
1308 return fctxs.get(path)
1309
1309
1310 if len(ps) == 0 or ps[0] < 0:
1310 if len(ps) == 0 or ps[0] < 0:
1311 pars = [None, None]
1311 pars = [None, None]
1312 elif len(ps) == 1:
1312 elif len(ps) == 1:
1313 pars = [nodeids[ps[0]], None]
1313 pars = [nodeids[ps[0]], None]
1314 else:
1314 else:
1315 pars = [nodeids[p] for p in ps]
1315 pars = [nodeids[p] for p in ps]
1316 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1316 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1317 date=(id, 0),
1317 date=(id, 0),
1318 user="debugbuilddag",
1318 user="debugbuilddag",
1319 extra={'branch': atbranch})
1319 extra={'branch': atbranch})
1320 nodeid = repo.commitctx(cx)
1320 nodeid = repo.commitctx(cx)
1321 nodeids.append(nodeid)
1321 nodeids.append(nodeid)
1322 at = id
1322 at = id
1323 elif type == 'l':
1323 elif type == 'l':
1324 id, name = data
1324 id, name = data
1325 ui.note('tag %s\n' % name)
1325 ui.note('tag %s\n' % name)
1326 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1326 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1327 elif type == 'a':
1327 elif type == 'a':
1328 ui.note('branch %s\n' % data)
1328 ui.note('branch %s\n' % data)
1329 atbranch = data
1329 atbranch = data
1330 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1330 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1331 tr.close()
1331 tr.close()
1332 finally:
1332 finally:
1333 ui.progress(_('building'), None)
1333 ui.progress(_('building'), None)
1334 tr.release()
1334 tr.release()
1335
1335
1336 if tags:
1336 if tags:
1337 repo.opener.write("localtags", "".join(tags))
1337 repo.opener.write("localtags", "".join(tags))
1338
1338
1339 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1339 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1340 def debugbundle(ui, bundlepath, all=None, **opts):
1340 def debugbundle(ui, bundlepath, all=None, **opts):
1341 """lists the contents of a bundle"""
1341 """lists the contents of a bundle"""
1342 f = url.open(ui, bundlepath)
1342 f = url.open(ui, bundlepath)
1343 try:
1343 try:
1344 gen = changegroup.readbundle(f, bundlepath)
1344 gen = changegroup.readbundle(f, bundlepath)
1345 if all:
1345 if all:
1346 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1346 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1347
1347
1348 def showchunks(named):
1348 def showchunks(named):
1349 ui.write("\n%s\n" % named)
1349 ui.write("\n%s\n" % named)
1350 chain = None
1350 chain = None
1351 while True:
1351 while True:
1352 chunkdata = gen.deltachunk(chain)
1352 chunkdata = gen.deltachunk(chain)
1353 if not chunkdata:
1353 if not chunkdata:
1354 break
1354 break
1355 node = chunkdata['node']
1355 node = chunkdata['node']
1356 p1 = chunkdata['p1']
1356 p1 = chunkdata['p1']
1357 p2 = chunkdata['p2']
1357 p2 = chunkdata['p2']
1358 cs = chunkdata['cs']
1358 cs = chunkdata['cs']
1359 deltabase = chunkdata['deltabase']
1359 deltabase = chunkdata['deltabase']
1360 delta = chunkdata['delta']
1360 delta = chunkdata['delta']
1361 ui.write("%s %s %s %s %s %s\n" %
1361 ui.write("%s %s %s %s %s %s\n" %
1362 (hex(node), hex(p1), hex(p2),
1362 (hex(node), hex(p1), hex(p2),
1363 hex(cs), hex(deltabase), len(delta)))
1363 hex(cs), hex(deltabase), len(delta)))
1364 chain = node
1364 chain = node
1365
1365
1366 chunkdata = gen.changelogheader()
1366 chunkdata = gen.changelogheader()
1367 showchunks("changelog")
1367 showchunks("changelog")
1368 chunkdata = gen.manifestheader()
1368 chunkdata = gen.manifestheader()
1369 showchunks("manifest")
1369 showchunks("manifest")
1370 while True:
1370 while True:
1371 chunkdata = gen.filelogheader()
1371 chunkdata = gen.filelogheader()
1372 if not chunkdata:
1372 if not chunkdata:
1373 break
1373 break
1374 fname = chunkdata['filename']
1374 fname = chunkdata['filename']
1375 showchunks(fname)
1375 showchunks(fname)
1376 else:
1376 else:
1377 chunkdata = gen.changelogheader()
1377 chunkdata = gen.changelogheader()
1378 chain = None
1378 chain = None
1379 while True:
1379 while True:
1380 chunkdata = gen.deltachunk(chain)
1380 chunkdata = gen.deltachunk(chain)
1381 if not chunkdata:
1381 if not chunkdata:
1382 break
1382 break
1383 node = chunkdata['node']
1383 node = chunkdata['node']
1384 ui.write("%s\n" % hex(node))
1384 ui.write("%s\n" % hex(node))
1385 chain = node
1385 chain = node
1386 finally:
1386 finally:
1387 f.close()
1387 f.close()
1388
1388
1389 @command('debugcheckstate', [], '')
1389 @command('debugcheckstate', [], '')
1390 def debugcheckstate(ui, repo):
1390 def debugcheckstate(ui, repo):
1391 """validate the correctness of the current dirstate"""
1391 """validate the correctness of the current dirstate"""
1392 parent1, parent2 = repo.dirstate.parents()
1392 parent1, parent2 = repo.dirstate.parents()
1393 m1 = repo[parent1].manifest()
1393 m1 = repo[parent1].manifest()
1394 m2 = repo[parent2].manifest()
1394 m2 = repo[parent2].manifest()
1395 errors = 0
1395 errors = 0
1396 for f in repo.dirstate:
1396 for f in repo.dirstate:
1397 state = repo.dirstate[f]
1397 state = repo.dirstate[f]
1398 if state in "nr" and f not in m1:
1398 if state in "nr" and f not in m1:
1399 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1399 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1400 errors += 1
1400 errors += 1
1401 if state in "a" and f in m1:
1401 if state in "a" and f in m1:
1402 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1402 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1403 errors += 1
1403 errors += 1
1404 if state in "m" and f not in m1 and f not in m2:
1404 if state in "m" and f not in m1 and f not in m2:
1405 ui.warn(_("%s in state %s, but not in either manifest\n") %
1405 ui.warn(_("%s in state %s, but not in either manifest\n") %
1406 (f, state))
1406 (f, state))
1407 errors += 1
1407 errors += 1
1408 for f in m1:
1408 for f in m1:
1409 state = repo.dirstate[f]
1409 state = repo.dirstate[f]
1410 if state not in "nrm":
1410 if state not in "nrm":
1411 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1411 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1412 errors += 1
1412 errors += 1
1413 if errors:
1413 if errors:
1414 error = _(".hg/dirstate inconsistent with current parent's manifest")
1414 error = _(".hg/dirstate inconsistent with current parent's manifest")
1415 raise util.Abort(error)
1415 raise util.Abort(error)
1416
1416
1417 @command('debugcommands', [], _('[COMMAND]'))
1417 @command('debugcommands', [], _('[COMMAND]'))
1418 def debugcommands(ui, cmd='', *args):
1418 def debugcommands(ui, cmd='', *args):
1419 """list all available commands and options"""
1419 """list all available commands and options"""
1420 for cmd, vals in sorted(table.iteritems()):
1420 for cmd, vals in sorted(table.iteritems()):
1421 cmd = cmd.split('|')[0].strip('^')
1421 cmd = cmd.split('|')[0].strip('^')
1422 opts = ', '.join([i[1] for i in vals[1]])
1422 opts = ', '.join([i[1] for i in vals[1]])
1423 ui.write('%s: %s\n' % (cmd, opts))
1423 ui.write('%s: %s\n' % (cmd, opts))
1424
1424
1425 @command('debugcomplete',
1425 @command('debugcomplete',
1426 [('o', 'options', None, _('show the command options'))],
1426 [('o', 'options', None, _('show the command options'))],
1427 _('[-o] CMD'))
1427 _('[-o] CMD'))
1428 def debugcomplete(ui, cmd='', **opts):
1428 def debugcomplete(ui, cmd='', **opts):
1429 """returns the completion list associated with the given command"""
1429 """returns the completion list associated with the given command"""
1430
1430
1431 if opts.get('options'):
1431 if opts.get('options'):
1432 options = []
1432 options = []
1433 otables = [globalopts]
1433 otables = [globalopts]
1434 if cmd:
1434 if cmd:
1435 aliases, entry = cmdutil.findcmd(cmd, table, False)
1435 aliases, entry = cmdutil.findcmd(cmd, table, False)
1436 otables.append(entry[1])
1436 otables.append(entry[1])
1437 for t in otables:
1437 for t in otables:
1438 for o in t:
1438 for o in t:
1439 if "(DEPRECATED)" in o[3]:
1439 if "(DEPRECATED)" in o[3]:
1440 continue
1440 continue
1441 if o[0]:
1441 if o[0]:
1442 options.append('-%s' % o[0])
1442 options.append('-%s' % o[0])
1443 options.append('--%s' % o[1])
1443 options.append('--%s' % o[1])
1444 ui.write("%s\n" % "\n".join(options))
1444 ui.write("%s\n" % "\n".join(options))
1445 return
1445 return
1446
1446
1447 cmdlist = cmdutil.findpossible(cmd, table)
1447 cmdlist = cmdutil.findpossible(cmd, table)
1448 if ui.verbose:
1448 if ui.verbose:
1449 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1449 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1450 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1450 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1451
1451
1452 @command('debugdag',
1452 @command('debugdag',
1453 [('t', 'tags', None, _('use tags as labels')),
1453 [('t', 'tags', None, _('use tags as labels')),
1454 ('b', 'branches', None, _('annotate with branch names')),
1454 ('b', 'branches', None, _('annotate with branch names')),
1455 ('', 'dots', None, _('use dots for runs')),
1455 ('', 'dots', None, _('use dots for runs')),
1456 ('s', 'spaces', None, _('separate elements by spaces'))],
1456 ('s', 'spaces', None, _('separate elements by spaces'))],
1457 _('[OPTION]... [FILE [REV]...]'))
1457 _('[OPTION]... [FILE [REV]...]'))
1458 def debugdag(ui, repo, file_=None, *revs, **opts):
1458 def debugdag(ui, repo, file_=None, *revs, **opts):
1459 """format the changelog or an index DAG as a concise textual description
1459 """format the changelog or an index DAG as a concise textual description
1460
1460
1461 If you pass a revlog index, the revlog's DAG is emitted. If you list
1461 If you pass a revlog index, the revlog's DAG is emitted. If you list
1462 revision numbers, they get labelled in the output as rN.
1462 revision numbers, they get labelled in the output as rN.
1463
1463
1464 Otherwise, the changelog DAG of the current repo is emitted.
1464 Otherwise, the changelog DAG of the current repo is emitted.
1465 """
1465 """
1466 spaces = opts.get('spaces')
1466 spaces = opts.get('spaces')
1467 dots = opts.get('dots')
1467 dots = opts.get('dots')
1468 if file_:
1468 if file_:
1469 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1469 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1470 revs = set((int(r) for r in revs))
1470 revs = set((int(r) for r in revs))
1471 def events():
1471 def events():
1472 for r in rlog:
1472 for r in rlog:
1473 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1473 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1474 if r in revs:
1474 if r in revs:
1475 yield 'l', (r, "r%i" % r)
1475 yield 'l', (r, "r%i" % r)
1476 elif repo:
1476 elif repo:
1477 cl = repo.changelog
1477 cl = repo.changelog
1478 tags = opts.get('tags')
1478 tags = opts.get('tags')
1479 branches = opts.get('branches')
1479 branches = opts.get('branches')
1480 if tags:
1480 if tags:
1481 labels = {}
1481 labels = {}
1482 for l, n in repo.tags().items():
1482 for l, n in repo.tags().items():
1483 labels.setdefault(cl.rev(n), []).append(l)
1483 labels.setdefault(cl.rev(n), []).append(l)
1484 def events():
1484 def events():
1485 b = "default"
1485 b = "default"
1486 for r in cl:
1486 for r in cl:
1487 if branches:
1487 if branches:
1488 newb = cl.read(cl.node(r))[5]['branch']
1488 newb = cl.read(cl.node(r))[5]['branch']
1489 if newb != b:
1489 if newb != b:
1490 yield 'a', newb
1490 yield 'a', newb
1491 b = newb
1491 b = newb
1492 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1492 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1493 if tags:
1493 if tags:
1494 ls = labels.get(r)
1494 ls = labels.get(r)
1495 if ls:
1495 if ls:
1496 for l in ls:
1496 for l in ls:
1497 yield 'l', (r, l)
1497 yield 'l', (r, l)
1498 else:
1498 else:
1499 raise util.Abort(_('need repo for changelog dag'))
1499 raise util.Abort(_('need repo for changelog dag'))
1500
1500
1501 for line in dagparser.dagtextlines(events(),
1501 for line in dagparser.dagtextlines(events(),
1502 addspaces=spaces,
1502 addspaces=spaces,
1503 wraplabels=True,
1503 wraplabels=True,
1504 wrapannotations=True,
1504 wrapannotations=True,
1505 wrapnonlinear=dots,
1505 wrapnonlinear=dots,
1506 usedots=dots,
1506 usedots=dots,
1507 maxlinewidth=70):
1507 maxlinewidth=70):
1508 ui.write(line)
1508 ui.write(line)
1509 ui.write("\n")
1509 ui.write("\n")
1510
1510
1511 @command('debugdata',
1511 @command('debugdata',
1512 [('c', 'changelog', False, _('open changelog')),
1512 [('c', 'changelog', False, _('open changelog')),
1513 ('m', 'manifest', False, _('open manifest'))],
1513 ('m', 'manifest', False, _('open manifest'))],
1514 _('-c|-m|FILE REV'))
1514 _('-c|-m|FILE REV'))
1515 def debugdata(ui, repo, file_, rev = None, **opts):
1515 def debugdata(ui, repo, file_, rev = None, **opts):
1516 """dump the contents of a data file revision"""
1516 """dump the contents of a data file revision"""
1517 if opts.get('changelog') or opts.get('manifest'):
1517 if opts.get('changelog') or opts.get('manifest'):
1518 file_, rev = None, file_
1518 file_, rev = None, file_
1519 elif rev is None:
1519 elif rev is None:
1520 raise error.CommandError('debugdata', _('invalid arguments'))
1520 raise error.CommandError('debugdata', _('invalid arguments'))
1521 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1521 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1522 try:
1522 try:
1523 ui.write(r.revision(r.lookup(rev)))
1523 ui.write(r.revision(r.lookup(rev)))
1524 except KeyError:
1524 except KeyError:
1525 raise util.Abort(_('invalid revision identifier %s') % rev)
1525 raise util.Abort(_('invalid revision identifier %s') % rev)
1526
1526
1527 @command('debugdate',
1527 @command('debugdate',
1528 [('e', 'extended', None, _('try extended date formats'))],
1528 [('e', 'extended', None, _('try extended date formats'))],
1529 _('[-e] DATE [RANGE]'))
1529 _('[-e] DATE [RANGE]'))
1530 def debugdate(ui, date, range=None, **opts):
1530 def debugdate(ui, date, range=None, **opts):
1531 """parse and display a date"""
1531 """parse and display a date"""
1532 if opts["extended"]:
1532 if opts["extended"]:
1533 d = util.parsedate(date, util.extendeddateformats)
1533 d = util.parsedate(date, util.extendeddateformats)
1534 else:
1534 else:
1535 d = util.parsedate(date)
1535 d = util.parsedate(date)
1536 ui.write("internal: %s %s\n" % d)
1536 ui.write("internal: %s %s\n" % d)
1537 ui.write("standard: %s\n" % util.datestr(d))
1537 ui.write("standard: %s\n" % util.datestr(d))
1538 if range:
1538 if range:
1539 m = util.matchdate(range)
1539 m = util.matchdate(range)
1540 ui.write("match: %s\n" % m(d[0]))
1540 ui.write("match: %s\n" % m(d[0]))
1541
1541
1542 @command('debugdiscovery',
1542 @command('debugdiscovery',
1543 [('', 'old', None, _('use old-style discovery')),
1543 [('', 'old', None, _('use old-style discovery')),
1544 ('', 'nonheads', None,
1544 ('', 'nonheads', None,
1545 _('use old-style discovery with non-heads included')),
1545 _('use old-style discovery with non-heads included')),
1546 ] + remoteopts,
1546 ] + remoteopts,
1547 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1547 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1548 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1548 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1549 """runs the changeset discovery protocol in isolation"""
1549 """runs the changeset discovery protocol in isolation"""
1550 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1550 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1551 remote = hg.peer(repo, opts, remoteurl)
1551 remote = hg.peer(repo, opts, remoteurl)
1552 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1552 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1553
1553
1554 # make sure tests are repeatable
1554 # make sure tests are repeatable
1555 random.seed(12323)
1555 random.seed(12323)
1556
1556
1557 def doit(localheads, remoteheads):
1557 def doit(localheads, remoteheads):
1558 if opts.get('old'):
1558 if opts.get('old'):
1559 if localheads:
1559 if localheads:
1560 raise util.Abort('cannot use localheads with old style discovery')
1560 raise util.Abort('cannot use localheads with old style discovery')
1561 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1561 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1562 force=True)
1562 force=True)
1563 common = set(common)
1563 common = set(common)
1564 if not opts.get('nonheads'):
1564 if not opts.get('nonheads'):
1565 ui.write("unpruned common: %s\n" % " ".join([short(n)
1565 ui.write("unpruned common: %s\n" % " ".join([short(n)
1566 for n in common]))
1566 for n in common]))
1567 dag = dagutil.revlogdag(repo.changelog)
1567 dag = dagutil.revlogdag(repo.changelog)
1568 all = dag.ancestorset(dag.internalizeall(common))
1568 all = dag.ancestorset(dag.internalizeall(common))
1569 common = dag.externalizeall(dag.headsetofconnecteds(all))
1569 common = dag.externalizeall(dag.headsetofconnecteds(all))
1570 else:
1570 else:
1571 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1571 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1572 common = set(common)
1572 common = set(common)
1573 rheads = set(hds)
1573 rheads = set(hds)
1574 lheads = set(repo.heads())
1574 lheads = set(repo.heads())
1575 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1575 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1576 if lheads <= common:
1576 if lheads <= common:
1577 ui.write("local is subset\n")
1577 ui.write("local is subset\n")
1578 elif rheads <= common:
1578 elif rheads <= common:
1579 ui.write("remote is subset\n")
1579 ui.write("remote is subset\n")
1580
1580
1581 serverlogs = opts.get('serverlog')
1581 serverlogs = opts.get('serverlog')
1582 if serverlogs:
1582 if serverlogs:
1583 for filename in serverlogs:
1583 for filename in serverlogs:
1584 logfile = open(filename, 'r')
1584 logfile = open(filename, 'r')
1585 try:
1585 try:
1586 line = logfile.readline()
1586 line = logfile.readline()
1587 while line:
1587 while line:
1588 parts = line.strip().split(';')
1588 parts = line.strip().split(';')
1589 op = parts[1]
1589 op = parts[1]
1590 if op == 'cg':
1590 if op == 'cg':
1591 pass
1591 pass
1592 elif op == 'cgss':
1592 elif op == 'cgss':
1593 doit(parts[2].split(' '), parts[3].split(' '))
1593 doit(parts[2].split(' '), parts[3].split(' '))
1594 elif op == 'unb':
1594 elif op == 'unb':
1595 doit(parts[3].split(' '), parts[2].split(' '))
1595 doit(parts[3].split(' '), parts[2].split(' '))
1596 line = logfile.readline()
1596 line = logfile.readline()
1597 finally:
1597 finally:
1598 logfile.close()
1598 logfile.close()
1599
1599
1600 else:
1600 else:
1601 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1601 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1602 opts.get('remote_head'))
1602 opts.get('remote_head'))
1603 localrevs = opts.get('local_head')
1603 localrevs = opts.get('local_head')
1604 doit(localrevs, remoterevs)
1604 doit(localrevs, remoterevs)
1605
1605
1606 @command('debugfileset', [], ('REVSPEC'))
1606 @command('debugfileset', [], ('REVSPEC'))
1607 def debugfileset(ui, repo, expr):
1607 def debugfileset(ui, repo, expr):
1608 '''parse and apply a fileset specification'''
1608 '''parse and apply a fileset specification'''
1609 if ui.verbose:
1609 if ui.verbose:
1610 tree = fileset.parse(expr)[0]
1610 tree = fileset.parse(expr)[0]
1611 ui.note(tree, "\n")
1611 ui.note(tree, "\n")
1612 matcher = lambda x: scmutil.match(repo, x, default='glob')
1612 matcher = lambda x: scmutil.match(repo, x, default='glob')
1613
1613
1614 for f in fileset.getfileset(repo[None], matcher, expr):
1614 for f in fileset.getfileset(repo[None], matcher, expr):
1615 ui.write("%s\n" % f)
1615 ui.write("%s\n" % f)
1616
1616
1617 @command('debugfsinfo', [], _('[PATH]'))
1617 @command('debugfsinfo', [], _('[PATH]'))
1618 def debugfsinfo(ui, path = "."):
1618 def debugfsinfo(ui, path = "."):
1619 """show information detected about current filesystem"""
1619 """show information detected about current filesystem"""
1620 util.writefile('.debugfsinfo', '')
1620 util.writefile('.debugfsinfo', '')
1621 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1621 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1622 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1622 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1623 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1623 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1624 and 'yes' or 'no'))
1624 and 'yes' or 'no'))
1625 os.unlink('.debugfsinfo')
1625 os.unlink('.debugfsinfo')
1626
1626
1627 @command('debuggetbundle',
1627 @command('debuggetbundle',
1628 [('H', 'head', [], _('id of head node'), _('ID')),
1628 [('H', 'head', [], _('id of head node'), _('ID')),
1629 ('C', 'common', [], _('id of common node'), _('ID')),
1629 ('C', 'common', [], _('id of common node'), _('ID')),
1630 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1630 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1631 _('REPO FILE [-H|-C ID]...'))
1631 _('REPO FILE [-H|-C ID]...'))
1632 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1632 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1633 """retrieves a bundle from a repo
1633 """retrieves a bundle from a repo
1634
1634
1635 Every ID must be a full-length hex node id string. Saves the bundle to the
1635 Every ID must be a full-length hex node id string. Saves the bundle to the
1636 given file.
1636 given file.
1637 """
1637 """
1638 repo = hg.peer(ui, opts, repopath)
1638 repo = hg.peer(ui, opts, repopath)
1639 if not repo.capable('getbundle'):
1639 if not repo.capable('getbundle'):
1640 raise util.Abort("getbundle() not supported by target repository")
1640 raise util.Abort("getbundle() not supported by target repository")
1641 args = {}
1641 args = {}
1642 if common:
1642 if common:
1643 args['common'] = [bin(s) for s in common]
1643 args['common'] = [bin(s) for s in common]
1644 if head:
1644 if head:
1645 args['heads'] = [bin(s) for s in head]
1645 args['heads'] = [bin(s) for s in head]
1646 bundle = repo.getbundle('debug', **args)
1646 bundle = repo.getbundle('debug', **args)
1647
1647
1648 bundletype = opts.get('type', 'bzip2').lower()
1648 bundletype = opts.get('type', 'bzip2').lower()
1649 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1649 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1650 bundletype = btypes.get(bundletype)
1650 bundletype = btypes.get(bundletype)
1651 if bundletype not in changegroup.bundletypes:
1651 if bundletype not in changegroup.bundletypes:
1652 raise util.Abort(_('unknown bundle type specified with --type'))
1652 raise util.Abort(_('unknown bundle type specified with --type'))
1653 changegroup.writebundle(bundle, bundlepath, bundletype)
1653 changegroup.writebundle(bundle, bundlepath, bundletype)
1654
1654
1655 @command('debugignore', [], '')
1655 @command('debugignore', [], '')
1656 def debugignore(ui, repo, *values, **opts):
1656 def debugignore(ui, repo, *values, **opts):
1657 """display the combined ignore pattern"""
1657 """display the combined ignore pattern"""
1658 ignore = repo.dirstate._ignore
1658 ignore = repo.dirstate._ignore
1659 if hasattr(ignore, 'includepat'):
1659 if hasattr(ignore, 'includepat'):
1660 ui.write("%s\n" % ignore.includepat)
1660 ui.write("%s\n" % ignore.includepat)
1661 else:
1661 else:
1662 raise util.Abort(_("no ignore patterns found"))
1662 raise util.Abort(_("no ignore patterns found"))
1663
1663
1664 @command('debugindex',
1664 @command('debugindex',
1665 [('c', 'changelog', False, _('open changelog')),
1665 [('c', 'changelog', False, _('open changelog')),
1666 ('m', 'manifest', False, _('open manifest')),
1666 ('m', 'manifest', False, _('open manifest')),
1667 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1667 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1668 _('[-f FORMAT] -c|-m|FILE'))
1668 _('[-f FORMAT] -c|-m|FILE'))
1669 def debugindex(ui, repo, file_ = None, **opts):
1669 def debugindex(ui, repo, file_ = None, **opts):
1670 """dump the contents of an index file"""
1670 """dump the contents of an index file"""
1671 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1671 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1672 format = opts.get('format', 0)
1672 format = opts.get('format', 0)
1673 if format not in (0, 1):
1673 if format not in (0, 1):
1674 raise util.Abort(_("unknown format %d") % format)
1674 raise util.Abort(_("unknown format %d") % format)
1675
1675
1676 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1676 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1677 if generaldelta:
1677 if generaldelta:
1678 basehdr = ' delta'
1678 basehdr = ' delta'
1679 else:
1679 else:
1680 basehdr = ' base'
1680 basehdr = ' base'
1681
1681
1682 if format == 0:
1682 if format == 0:
1683 ui.write(" rev offset length " + basehdr + " linkrev"
1683 ui.write(" rev offset length " + basehdr + " linkrev"
1684 " nodeid p1 p2\n")
1684 " nodeid p1 p2\n")
1685 elif format == 1:
1685 elif format == 1:
1686 ui.write(" rev flag offset length"
1686 ui.write(" rev flag offset length"
1687 " size " + basehdr + " link p1 p2 nodeid\n")
1687 " size " + basehdr + " link p1 p2 nodeid\n")
1688
1688
1689 for i in r:
1689 for i in r:
1690 node = r.node(i)
1690 node = r.node(i)
1691 if generaldelta:
1691 if generaldelta:
1692 base = r.deltaparent(i)
1692 base = r.deltaparent(i)
1693 else:
1693 else:
1694 base = r.chainbase(i)
1694 base = r.chainbase(i)
1695 if format == 0:
1695 if format == 0:
1696 try:
1696 try:
1697 pp = r.parents(node)
1697 pp = r.parents(node)
1698 except:
1698 except:
1699 pp = [nullid, nullid]
1699 pp = [nullid, nullid]
1700 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1700 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1701 i, r.start(i), r.length(i), base, r.linkrev(i),
1701 i, r.start(i), r.length(i), base, r.linkrev(i),
1702 short(node), short(pp[0]), short(pp[1])))
1702 short(node), short(pp[0]), short(pp[1])))
1703 elif format == 1:
1703 elif format == 1:
1704 pr = r.parentrevs(i)
1704 pr = r.parentrevs(i)
1705 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1705 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1706 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1706 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1707 base, r.linkrev(i), pr[0], pr[1], short(node)))
1707 base, r.linkrev(i), pr[0], pr[1], short(node)))
1708
1708
1709 @command('debugindexdot', [], _('FILE'))
1709 @command('debugindexdot', [], _('FILE'))
1710 def debugindexdot(ui, repo, file_):
1710 def debugindexdot(ui, repo, file_):
1711 """dump an index DAG as a graphviz dot file"""
1711 """dump an index DAG as a graphviz dot file"""
1712 r = None
1712 r = None
1713 if repo:
1713 if repo:
1714 filelog = repo.file(file_)
1714 filelog = repo.file(file_)
1715 if len(filelog):
1715 if len(filelog):
1716 r = filelog
1716 r = filelog
1717 if not r:
1717 if not r:
1718 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1718 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1719 ui.write("digraph G {\n")
1719 ui.write("digraph G {\n")
1720 for i in r:
1720 for i in r:
1721 node = r.node(i)
1721 node = r.node(i)
1722 pp = r.parents(node)
1722 pp = r.parents(node)
1723 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1723 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1724 if pp[1] != nullid:
1724 if pp[1] != nullid:
1725 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1725 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1726 ui.write("}\n")
1726 ui.write("}\n")
1727
1727
1728 @command('debuginstall', [], '')
1728 @command('debuginstall', [], '')
1729 def debuginstall(ui):
1729 def debuginstall(ui):
1730 '''test Mercurial installation
1730 '''test Mercurial installation
1731
1731
1732 Returns 0 on success.
1732 Returns 0 on success.
1733 '''
1733 '''
1734
1734
1735 def writetemp(contents):
1735 def writetemp(contents):
1736 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1736 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1737 f = os.fdopen(fd, "wb")
1737 f = os.fdopen(fd, "wb")
1738 f.write(contents)
1738 f.write(contents)
1739 f.close()
1739 f.close()
1740 return name
1740 return name
1741
1741
1742 problems = 0
1742 problems = 0
1743
1743
1744 # encoding
1744 # encoding
1745 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1745 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1746 try:
1746 try:
1747 encoding.fromlocal("test")
1747 encoding.fromlocal("test")
1748 except util.Abort, inst:
1748 except util.Abort, inst:
1749 ui.write(" %s\n" % inst)
1749 ui.write(" %s\n" % inst)
1750 ui.write(_(" (check that your locale is properly set)\n"))
1750 ui.write(_(" (check that your locale is properly set)\n"))
1751 problems += 1
1751 problems += 1
1752
1752
1753 # compiled modules
1753 # compiled modules
1754 ui.status(_("Checking installed modules (%s)...\n")
1754 ui.status(_("Checking installed modules (%s)...\n")
1755 % os.path.dirname(__file__))
1755 % os.path.dirname(__file__))
1756 try:
1756 try:
1757 import bdiff, mpatch, base85, osutil
1757 import bdiff, mpatch, base85, osutil
1758 except Exception, inst:
1758 except Exception, inst:
1759 ui.write(" %s\n" % inst)
1759 ui.write(" %s\n" % inst)
1760 ui.write(_(" One or more extensions could not be found"))
1760 ui.write(_(" One or more extensions could not be found"))
1761 ui.write(_(" (check that you compiled the extensions)\n"))
1761 ui.write(_(" (check that you compiled the extensions)\n"))
1762 problems += 1
1762 problems += 1
1763
1763
1764 # templates
1764 # templates
1765 ui.status(_("Checking templates...\n"))
1765 ui.status(_("Checking templates...\n"))
1766 try:
1766 try:
1767 import templater
1767 import templater
1768 templater.templater(templater.templatepath("map-cmdline.default"))
1768 templater.templater(templater.templatepath("map-cmdline.default"))
1769 except Exception, inst:
1769 except Exception, inst:
1770 ui.write(" %s\n" % inst)
1770 ui.write(" %s\n" % inst)
1771 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1771 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1772 problems += 1
1772 problems += 1
1773
1773
1774 # editor
1774 # editor
1775 ui.status(_("Checking commit editor...\n"))
1775 ui.status(_("Checking commit editor...\n"))
1776 editor = ui.geteditor()
1776 editor = ui.geteditor()
1777 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1777 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1778 if not cmdpath:
1778 if not cmdpath:
1779 if editor == 'vi':
1779 if editor == 'vi':
1780 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1780 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1781 ui.write(_(" (specify a commit editor in your configuration"
1781 ui.write(_(" (specify a commit editor in your configuration"
1782 " file)\n"))
1782 " file)\n"))
1783 else:
1783 else:
1784 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1784 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1785 ui.write(_(" (specify a commit editor in your configuration"
1785 ui.write(_(" (specify a commit editor in your configuration"
1786 " file)\n"))
1786 " file)\n"))
1787 problems += 1
1787 problems += 1
1788
1788
1789 # check username
1789 # check username
1790 ui.status(_("Checking username...\n"))
1790 ui.status(_("Checking username...\n"))
1791 try:
1791 try:
1792 ui.username()
1792 ui.username()
1793 except util.Abort, e:
1793 except util.Abort, e:
1794 ui.write(" %s\n" % e)
1794 ui.write(" %s\n" % e)
1795 ui.write(_(" (specify a username in your configuration file)\n"))
1795 ui.write(_(" (specify a username in your configuration file)\n"))
1796 problems += 1
1796 problems += 1
1797
1797
1798 if not problems:
1798 if not problems:
1799 ui.status(_("No problems detected\n"))
1799 ui.status(_("No problems detected\n"))
1800 else:
1800 else:
1801 ui.write(_("%s problems detected,"
1801 ui.write(_("%s problems detected,"
1802 " please check your install!\n") % problems)
1802 " please check your install!\n") % problems)
1803
1803
1804 return problems
1804 return problems
1805
1805
1806 @command('debugknown', [], _('REPO ID...'))
1806 @command('debugknown', [], _('REPO ID...'))
1807 def debugknown(ui, repopath, *ids, **opts):
1807 def debugknown(ui, repopath, *ids, **opts):
1808 """test whether node ids are known to a repo
1808 """test whether node ids are known to a repo
1809
1809
1810 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1810 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1811 indicating unknown/known.
1811 indicating unknown/known.
1812 """
1812 """
1813 repo = hg.peer(ui, opts, repopath)
1813 repo = hg.peer(ui, opts, repopath)
1814 if not repo.capable('known'):
1814 if not repo.capable('known'):
1815 raise util.Abort("known() not supported by target repository")
1815 raise util.Abort("known() not supported by target repository")
1816 flags = repo.known([bin(s) for s in ids])
1816 flags = repo.known([bin(s) for s in ids])
1817 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1817 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1818
1818
1819 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1819 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1820 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1820 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1821 '''access the pushkey key/value protocol
1821 '''access the pushkey key/value protocol
1822
1822
1823 With two args, list the keys in the given namespace.
1823 With two args, list the keys in the given namespace.
1824
1824
1825 With five args, set a key to new if it currently is set to old.
1825 With five args, set a key to new if it currently is set to old.
1826 Reports success or failure.
1826 Reports success or failure.
1827 '''
1827 '''
1828
1828
1829 target = hg.peer(ui, {}, repopath)
1829 target = hg.peer(ui, {}, repopath)
1830 if keyinfo:
1830 if keyinfo:
1831 key, old, new = keyinfo
1831 key, old, new = keyinfo
1832 r = target.pushkey(namespace, key, old, new)
1832 r = target.pushkey(namespace, key, old, new)
1833 ui.status(str(r) + '\n')
1833 ui.status(str(r) + '\n')
1834 return not r
1834 return not r
1835 else:
1835 else:
1836 for k, v in target.listkeys(namespace).iteritems():
1836 for k, v in target.listkeys(namespace).iteritems():
1837 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1837 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1838 v.encode('string-escape')))
1838 v.encode('string-escape')))
1839
1839
1840 @command('debugrebuildstate',
1840 @command('debugrebuildstate',
1841 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1841 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1842 _('[-r REV] [REV]'))
1842 _('[-r REV] [REV]'))
1843 def debugrebuildstate(ui, repo, rev="tip"):
1843 def debugrebuildstate(ui, repo, rev="tip"):
1844 """rebuild the dirstate as it would look like for the given revision"""
1844 """rebuild the dirstate as it would look like for the given revision"""
1845 ctx = scmutil.revsingle(repo, rev)
1845 ctx = scmutil.revsingle(repo, rev)
1846 wlock = repo.wlock()
1846 wlock = repo.wlock()
1847 try:
1847 try:
1848 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1848 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1849 finally:
1849 finally:
1850 wlock.release()
1850 wlock.release()
1851
1851
1852 @command('debugrename',
1852 @command('debugrename',
1853 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1853 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1854 _('[-r REV] FILE'))
1854 _('[-r REV] FILE'))
1855 def debugrename(ui, repo, file1, *pats, **opts):
1855 def debugrename(ui, repo, file1, *pats, **opts):
1856 """dump rename information"""
1856 """dump rename information"""
1857
1857
1858 ctx = scmutil.revsingle(repo, opts.get('rev'))
1858 ctx = scmutil.revsingle(repo, opts.get('rev'))
1859 m = scmutil.match(repo, (file1,) + pats, opts)
1859 m = scmutil.match(repo, (file1,) + pats, opts)
1860 for abs in ctx.walk(m):
1860 for abs in ctx.walk(m):
1861 fctx = ctx[abs]
1861 fctx = ctx[abs]
1862 o = fctx.filelog().renamed(fctx.filenode())
1862 o = fctx.filelog().renamed(fctx.filenode())
1863 rel = m.rel(abs)
1863 rel = m.rel(abs)
1864 if o:
1864 if o:
1865 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1865 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1866 else:
1866 else:
1867 ui.write(_("%s not renamed\n") % rel)
1867 ui.write(_("%s not renamed\n") % rel)
1868
1868
1869 @command('debugrevlog',
1869 @command('debugrevlog',
1870 [('c', 'changelog', False, _('open changelog')),
1870 [('c', 'changelog', False, _('open changelog')),
1871 ('m', 'manifest', False, _('open manifest')),
1871 ('m', 'manifest', False, _('open manifest')),
1872 ('d', 'dump', False, _('dump index data'))],
1872 ('d', 'dump', False, _('dump index data'))],
1873 _('-c|-m|FILE'))
1873 _('-c|-m|FILE'))
1874 def debugrevlog(ui, repo, file_ = None, **opts):
1874 def debugrevlog(ui, repo, file_ = None, **opts):
1875 """show data and statistics about a revlog"""
1875 """show data and statistics about a revlog"""
1876 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1876 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1877
1877
1878 if opts.get("dump"):
1878 if opts.get("dump"):
1879 numrevs = len(r)
1879 numrevs = len(r)
1880 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1880 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1881 " rawsize totalsize compression heads\n")
1881 " rawsize totalsize compression heads\n")
1882 ts = 0
1882 ts = 0
1883 heads = set()
1883 heads = set()
1884 for rev in xrange(numrevs):
1884 for rev in xrange(numrevs):
1885 dbase = r.deltaparent(rev)
1885 dbase = r.deltaparent(rev)
1886 if dbase == -1:
1886 if dbase == -1:
1887 dbase = rev
1887 dbase = rev
1888 cbase = r.chainbase(rev)
1888 cbase = r.chainbase(rev)
1889 p1, p2 = r.parentrevs(rev)
1889 p1, p2 = r.parentrevs(rev)
1890 rs = r.rawsize(rev)
1890 rs = r.rawsize(rev)
1891 ts = ts + rs
1891 ts = ts + rs
1892 heads -= set(r.parentrevs(rev))
1892 heads -= set(r.parentrevs(rev))
1893 heads.add(rev)
1893 heads.add(rev)
1894 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1894 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1895 (rev, p1, p2, r.start(rev), r.end(rev),
1895 (rev, p1, p2, r.start(rev), r.end(rev),
1896 r.start(dbase), r.start(cbase),
1896 r.start(dbase), r.start(cbase),
1897 r.start(p1), r.start(p2),
1897 r.start(p1), r.start(p2),
1898 rs, ts, ts / r.end(rev), len(heads)))
1898 rs, ts, ts / r.end(rev), len(heads)))
1899 return 0
1899 return 0
1900
1900
1901 v = r.version
1901 v = r.version
1902 format = v & 0xFFFF
1902 format = v & 0xFFFF
1903 flags = []
1903 flags = []
1904 gdelta = False
1904 gdelta = False
1905 if v & revlog.REVLOGNGINLINEDATA:
1905 if v & revlog.REVLOGNGINLINEDATA:
1906 flags.append('inline')
1906 flags.append('inline')
1907 if v & revlog.REVLOGGENERALDELTA:
1907 if v & revlog.REVLOGGENERALDELTA:
1908 gdelta = True
1908 gdelta = True
1909 flags.append('generaldelta')
1909 flags.append('generaldelta')
1910 if not flags:
1910 if not flags:
1911 flags = ['(none)']
1911 flags = ['(none)']
1912
1912
1913 nummerges = 0
1913 nummerges = 0
1914 numfull = 0
1914 numfull = 0
1915 numprev = 0
1915 numprev = 0
1916 nump1 = 0
1916 nump1 = 0
1917 nump2 = 0
1917 nump2 = 0
1918 numother = 0
1918 numother = 0
1919 nump1prev = 0
1919 nump1prev = 0
1920 nump2prev = 0
1920 nump2prev = 0
1921 chainlengths = []
1921 chainlengths = []
1922
1922
1923 datasize = [None, 0, 0L]
1923 datasize = [None, 0, 0L]
1924 fullsize = [None, 0, 0L]
1924 fullsize = [None, 0, 0L]
1925 deltasize = [None, 0, 0L]
1925 deltasize = [None, 0, 0L]
1926
1926
1927 def addsize(size, l):
1927 def addsize(size, l):
1928 if l[0] is None or size < l[0]:
1928 if l[0] is None or size < l[0]:
1929 l[0] = size
1929 l[0] = size
1930 if size > l[1]:
1930 if size > l[1]:
1931 l[1] = size
1931 l[1] = size
1932 l[2] += size
1932 l[2] += size
1933
1933
1934 numrevs = len(r)
1934 numrevs = len(r)
1935 for rev in xrange(numrevs):
1935 for rev in xrange(numrevs):
1936 p1, p2 = r.parentrevs(rev)
1936 p1, p2 = r.parentrevs(rev)
1937 delta = r.deltaparent(rev)
1937 delta = r.deltaparent(rev)
1938 if format > 0:
1938 if format > 0:
1939 addsize(r.rawsize(rev), datasize)
1939 addsize(r.rawsize(rev), datasize)
1940 if p2 != nullrev:
1940 if p2 != nullrev:
1941 nummerges += 1
1941 nummerges += 1
1942 size = r.length(rev)
1942 size = r.length(rev)
1943 if delta == nullrev:
1943 if delta == nullrev:
1944 chainlengths.append(0)
1944 chainlengths.append(0)
1945 numfull += 1
1945 numfull += 1
1946 addsize(size, fullsize)
1946 addsize(size, fullsize)
1947 else:
1947 else:
1948 chainlengths.append(chainlengths[delta] + 1)
1948 chainlengths.append(chainlengths[delta] + 1)
1949 addsize(size, deltasize)
1949 addsize(size, deltasize)
1950 if delta == rev - 1:
1950 if delta == rev - 1:
1951 numprev += 1
1951 numprev += 1
1952 if delta == p1:
1952 if delta == p1:
1953 nump1prev += 1
1953 nump1prev += 1
1954 elif delta == p2:
1954 elif delta == p2:
1955 nump2prev += 1
1955 nump2prev += 1
1956 elif delta == p1:
1956 elif delta == p1:
1957 nump1 += 1
1957 nump1 += 1
1958 elif delta == p2:
1958 elif delta == p2:
1959 nump2 += 1
1959 nump2 += 1
1960 elif delta != nullrev:
1960 elif delta != nullrev:
1961 numother += 1
1961 numother += 1
1962
1962
1963 numdeltas = numrevs - numfull
1963 numdeltas = numrevs - numfull
1964 numoprev = numprev - nump1prev - nump2prev
1964 numoprev = numprev - nump1prev - nump2prev
1965 totalrawsize = datasize[2]
1965 totalrawsize = datasize[2]
1966 datasize[2] /= numrevs
1966 datasize[2] /= numrevs
1967 fulltotal = fullsize[2]
1967 fulltotal = fullsize[2]
1968 fullsize[2] /= numfull
1968 fullsize[2] /= numfull
1969 deltatotal = deltasize[2]
1969 deltatotal = deltasize[2]
1970 deltasize[2] /= numrevs - numfull
1970 deltasize[2] /= numrevs - numfull
1971 totalsize = fulltotal + deltatotal
1971 totalsize = fulltotal + deltatotal
1972 avgchainlen = sum(chainlengths) / numrevs
1972 avgchainlen = sum(chainlengths) / numrevs
1973 compratio = totalrawsize / totalsize
1973 compratio = totalrawsize / totalsize
1974
1974
1975 basedfmtstr = '%%%dd\n'
1975 basedfmtstr = '%%%dd\n'
1976 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1976 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1977
1977
1978 def dfmtstr(max):
1978 def dfmtstr(max):
1979 return basedfmtstr % len(str(max))
1979 return basedfmtstr % len(str(max))
1980 def pcfmtstr(max, padding=0):
1980 def pcfmtstr(max, padding=0):
1981 return basepcfmtstr % (len(str(max)), ' ' * padding)
1981 return basepcfmtstr % (len(str(max)), ' ' * padding)
1982
1982
1983 def pcfmt(value, total):
1983 def pcfmt(value, total):
1984 return (value, 100 * float(value) / total)
1984 return (value, 100 * float(value) / total)
1985
1985
1986 ui.write('format : %d\n' % format)
1986 ui.write('format : %d\n' % format)
1987 ui.write('flags : %s\n' % ', '.join(flags))
1987 ui.write('flags : %s\n' % ', '.join(flags))
1988
1988
1989 ui.write('\n')
1989 ui.write('\n')
1990 fmt = pcfmtstr(totalsize)
1990 fmt = pcfmtstr(totalsize)
1991 fmt2 = dfmtstr(totalsize)
1991 fmt2 = dfmtstr(totalsize)
1992 ui.write('revisions : ' + fmt2 % numrevs)
1992 ui.write('revisions : ' + fmt2 % numrevs)
1993 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
1993 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
1994 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
1994 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
1995 ui.write('revisions : ' + fmt2 % numrevs)
1995 ui.write('revisions : ' + fmt2 % numrevs)
1996 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
1996 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
1997 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
1997 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
1998 ui.write('revision size : ' + fmt2 % totalsize)
1998 ui.write('revision size : ' + fmt2 % totalsize)
1999 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
1999 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2000 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2000 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2001
2001
2002 ui.write('\n')
2002 ui.write('\n')
2003 fmt = dfmtstr(max(avgchainlen, compratio))
2003 fmt = dfmtstr(max(avgchainlen, compratio))
2004 ui.write('avg chain length : ' + fmt % avgchainlen)
2004 ui.write('avg chain length : ' + fmt % avgchainlen)
2005 ui.write('compression ratio : ' + fmt % compratio)
2005 ui.write('compression ratio : ' + fmt % compratio)
2006
2006
2007 if format > 0:
2007 if format > 0:
2008 ui.write('\n')
2008 ui.write('\n')
2009 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2009 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2010 % tuple(datasize))
2010 % tuple(datasize))
2011 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2011 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2012 % tuple(fullsize))
2012 % tuple(fullsize))
2013 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2013 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2014 % tuple(deltasize))
2014 % tuple(deltasize))
2015
2015
2016 if numdeltas > 0:
2016 if numdeltas > 0:
2017 ui.write('\n')
2017 ui.write('\n')
2018 fmt = pcfmtstr(numdeltas)
2018 fmt = pcfmtstr(numdeltas)
2019 fmt2 = pcfmtstr(numdeltas, 4)
2019 fmt2 = pcfmtstr(numdeltas, 4)
2020 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2020 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2021 if numprev > 0:
2021 if numprev > 0:
2022 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2022 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2023 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2023 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2024 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2024 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2025 if gdelta:
2025 if gdelta:
2026 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2026 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2027 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2027 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2028 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2028 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2029
2029
2030 @command('debugrevspec', [], ('REVSPEC'))
2030 @command('debugrevspec', [], ('REVSPEC'))
2031 def debugrevspec(ui, repo, expr):
2031 def debugrevspec(ui, repo, expr):
2032 '''parse and apply a revision specification'''
2032 '''parse and apply a revision specification'''
2033 if ui.verbose:
2033 if ui.verbose:
2034 tree = revset.parse(expr)[0]
2034 tree = revset.parse(expr)[0]
2035 ui.note(tree, "\n")
2035 ui.note(tree, "\n")
2036 newtree = revset.findaliases(ui, tree)
2036 newtree = revset.findaliases(ui, tree)
2037 if newtree != tree:
2037 if newtree != tree:
2038 ui.note(newtree, "\n")
2038 ui.note(newtree, "\n")
2039 func = revset.match(ui, expr)
2039 func = revset.match(ui, expr)
2040 for c in func(repo, range(len(repo))):
2040 for c in func(repo, range(len(repo))):
2041 ui.write("%s\n" % c)
2041 ui.write("%s\n" % c)
2042
2042
2043 @command('debugsetparents', [], _('REV1 [REV2]'))
2043 @command('debugsetparents', [], _('REV1 [REV2]'))
2044 def debugsetparents(ui, repo, rev1, rev2=None):
2044 def debugsetparents(ui, repo, rev1, rev2=None):
2045 """manually set the parents of the current working directory
2045 """manually set the parents of the current working directory
2046
2046
2047 This is useful for writing repository conversion tools, but should
2047 This is useful for writing repository conversion tools, but should
2048 be used with care.
2048 be used with care.
2049
2049
2050 Returns 0 on success.
2050 Returns 0 on success.
2051 """
2051 """
2052
2052
2053 r1 = scmutil.revsingle(repo, rev1).node()
2053 r1 = scmutil.revsingle(repo, rev1).node()
2054 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2054 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2055
2055
2056 wlock = repo.wlock()
2056 wlock = repo.wlock()
2057 try:
2057 try:
2058 repo.dirstate.setparents(r1, r2)
2058 repo.dirstate.setparents(r1, r2)
2059 finally:
2059 finally:
2060 wlock.release()
2060 wlock.release()
2061
2061
2062 @command('debugstate',
2062 @command('debugstate',
2063 [('', 'nodates', None, _('do not display the saved mtime')),
2063 [('', 'nodates', None, _('do not display the saved mtime')),
2064 ('', 'datesort', None, _('sort by saved mtime'))],
2064 ('', 'datesort', None, _('sort by saved mtime'))],
2065 _('[OPTION]...'))
2065 _('[OPTION]...'))
2066 def debugstate(ui, repo, nodates=None, datesort=None):
2066 def debugstate(ui, repo, nodates=None, datesort=None):
2067 """show the contents of the current dirstate"""
2067 """show the contents of the current dirstate"""
2068 timestr = ""
2068 timestr = ""
2069 showdate = not nodates
2069 showdate = not nodates
2070 if datesort:
2070 if datesort:
2071 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2071 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2072 else:
2072 else:
2073 keyfunc = None # sort by filename
2073 keyfunc = None # sort by filename
2074 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2074 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2075 if showdate:
2075 if showdate:
2076 if ent[3] == -1:
2076 if ent[3] == -1:
2077 # Pad or slice to locale representation
2077 # Pad or slice to locale representation
2078 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2078 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2079 time.localtime(0)))
2079 time.localtime(0)))
2080 timestr = 'unset'
2080 timestr = 'unset'
2081 timestr = (timestr[:locale_len] +
2081 timestr = (timestr[:locale_len] +
2082 ' ' * (locale_len - len(timestr)))
2082 ' ' * (locale_len - len(timestr)))
2083 else:
2083 else:
2084 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2084 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2085 time.localtime(ent[3]))
2085 time.localtime(ent[3]))
2086 if ent[1] & 020000:
2086 if ent[1] & 020000:
2087 mode = 'lnk'
2087 mode = 'lnk'
2088 else:
2088 else:
2089 mode = '%3o' % (ent[1] & 0777)
2089 mode = '%3o' % (ent[1] & 0777)
2090 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2090 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2091 for f in repo.dirstate.copies():
2091 for f in repo.dirstate.copies():
2092 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2092 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2093
2093
2094 @command('debugsub',
2094 @command('debugsub',
2095 [('r', 'rev', '',
2095 [('r', 'rev', '',
2096 _('revision to check'), _('REV'))],
2096 _('revision to check'), _('REV'))],
2097 _('[-r REV] [REV]'))
2097 _('[-r REV] [REV]'))
2098 def debugsub(ui, repo, rev=None):
2098 def debugsub(ui, repo, rev=None):
2099 ctx = scmutil.revsingle(repo, rev, None)
2099 ctx = scmutil.revsingle(repo, rev, None)
2100 for k, v in sorted(ctx.substate.items()):
2100 for k, v in sorted(ctx.substate.items()):
2101 ui.write('path %s\n' % k)
2101 ui.write('path %s\n' % k)
2102 ui.write(' source %s\n' % v[0])
2102 ui.write(' source %s\n' % v[0])
2103 ui.write(' revision %s\n' % v[1])
2103 ui.write(' revision %s\n' % v[1])
2104
2104
2105 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2105 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2106 def debugwalk(ui, repo, *pats, **opts):
2106 def debugwalk(ui, repo, *pats, **opts):
2107 """show how files match on given patterns"""
2107 """show how files match on given patterns"""
2108 m = scmutil.match(repo, pats, opts)
2108 m = scmutil.match(repo, pats, opts)
2109 items = list(repo.walk(m))
2109 items = list(repo.walk(m))
2110 if not items:
2110 if not items:
2111 return
2111 return
2112 fmt = 'f %%-%ds %%-%ds %%s' % (
2112 fmt = 'f %%-%ds %%-%ds %%s' % (
2113 max([len(abs) for abs in items]),
2113 max([len(abs) for abs in items]),
2114 max([len(m.rel(abs)) for abs in items]))
2114 max([len(m.rel(abs)) for abs in items]))
2115 for abs in items:
2115 for abs in items:
2116 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2116 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2117 ui.write("%s\n" % line.rstrip())
2117 ui.write("%s\n" % line.rstrip())
2118
2118
2119 @command('debugwireargs',
2119 @command('debugwireargs',
2120 [('', 'three', '', 'three'),
2120 [('', 'three', '', 'three'),
2121 ('', 'four', '', 'four'),
2121 ('', 'four', '', 'four'),
2122 ('', 'five', '', 'five'),
2122 ('', 'five', '', 'five'),
2123 ] + remoteopts,
2123 ] + remoteopts,
2124 _('REPO [OPTIONS]... [ONE [TWO]]'))
2124 _('REPO [OPTIONS]... [ONE [TWO]]'))
2125 def debugwireargs(ui, repopath, *vals, **opts):
2125 def debugwireargs(ui, repopath, *vals, **opts):
2126 repo = hg.peer(ui, opts, repopath)
2126 repo = hg.peer(ui, opts, repopath)
2127 for opt in remoteopts:
2127 for opt in remoteopts:
2128 del opts[opt[1]]
2128 del opts[opt[1]]
2129 args = {}
2129 args = {}
2130 for k, v in opts.iteritems():
2130 for k, v in opts.iteritems():
2131 if v:
2131 if v:
2132 args[k] = v
2132 args[k] = v
2133 # run twice to check that we don't mess up the stream for the next command
2133 # run twice to check that we don't mess up the stream for the next command
2134 res1 = repo.debugwireargs(*vals, **args)
2134 res1 = repo.debugwireargs(*vals, **args)
2135 res2 = repo.debugwireargs(*vals, **args)
2135 res2 = repo.debugwireargs(*vals, **args)
2136 ui.write("%s\n" % res1)
2136 ui.write("%s\n" % res1)
2137 if res1 != res2:
2137 if res1 != res2:
2138 ui.warn("%s\n" % res2)
2138 ui.warn("%s\n" % res2)
2139
2139
2140 @command('^diff',
2140 @command('^diff',
2141 [('r', 'rev', [], _('revision'), _('REV')),
2141 [('r', 'rev', [], _('revision'), _('REV')),
2142 ('c', 'change', '', _('change made by revision'), _('REV'))
2142 ('c', 'change', '', _('change made by revision'), _('REV'))
2143 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2143 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2144 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2144 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2145 def diff(ui, repo, *pats, **opts):
2145 def diff(ui, repo, *pats, **opts):
2146 """diff repository (or selected files)
2146 """diff repository (or selected files)
2147
2147
2148 Show differences between revisions for the specified files.
2148 Show differences between revisions for the specified files.
2149
2149
2150 Differences between files are shown using the unified diff format.
2150 Differences between files are shown using the unified diff format.
2151
2151
2152 .. note::
2152 .. note::
2153 diff may generate unexpected results for merges, as it will
2153 diff may generate unexpected results for merges, as it will
2154 default to comparing against the working directory's first
2154 default to comparing against the working directory's first
2155 parent changeset if no revisions are specified.
2155 parent changeset if no revisions are specified.
2156
2156
2157 When two revision arguments are given, then changes are shown
2157 When two revision arguments are given, then changes are shown
2158 between those revisions. If only one revision is specified then
2158 between those revisions. If only one revision is specified then
2159 that revision is compared to the working directory, and, when no
2159 that revision is compared to the working directory, and, when no
2160 revisions are specified, the working directory files are compared
2160 revisions are specified, the working directory files are compared
2161 to its parent.
2161 to its parent.
2162
2162
2163 Alternatively you can specify -c/--change with a revision to see
2163 Alternatively you can specify -c/--change with a revision to see
2164 the changes in that changeset relative to its first parent.
2164 the changes in that changeset relative to its first parent.
2165
2165
2166 Without the -a/--text option, diff will avoid generating diffs of
2166 Without the -a/--text option, diff will avoid generating diffs of
2167 files it detects as binary. With -a, diff will generate a diff
2167 files it detects as binary. With -a, diff will generate a diff
2168 anyway, probably with undesirable results.
2168 anyway, probably with undesirable results.
2169
2169
2170 Use the -g/--git option to generate diffs in the git extended diff
2170 Use the -g/--git option to generate diffs in the git extended diff
2171 format. For more information, read :hg:`help diffs`.
2171 format. For more information, read :hg:`help diffs`.
2172
2172
2173 Returns 0 on success.
2173 Returns 0 on success.
2174 """
2174 """
2175
2175
2176 revs = opts.get('rev')
2176 revs = opts.get('rev')
2177 change = opts.get('change')
2177 change = opts.get('change')
2178 stat = opts.get('stat')
2178 stat = opts.get('stat')
2179 reverse = opts.get('reverse')
2179 reverse = opts.get('reverse')
2180
2180
2181 if revs and change:
2181 if revs and change:
2182 msg = _('cannot specify --rev and --change at the same time')
2182 msg = _('cannot specify --rev and --change at the same time')
2183 raise util.Abort(msg)
2183 raise util.Abort(msg)
2184 elif change:
2184 elif change:
2185 node2 = scmutil.revsingle(repo, change, None).node()
2185 node2 = scmutil.revsingle(repo, change, None).node()
2186 node1 = repo[node2].p1().node()
2186 node1 = repo[node2].p1().node()
2187 else:
2187 else:
2188 node1, node2 = scmutil.revpair(repo, revs)
2188 node1, node2 = scmutil.revpair(repo, revs)
2189
2189
2190 if reverse:
2190 if reverse:
2191 node1, node2 = node2, node1
2191 node1, node2 = node2, node1
2192
2192
2193 diffopts = patch.diffopts(ui, opts)
2193 diffopts = patch.diffopts(ui, opts)
2194 m = scmutil.match(repo, pats, opts)
2194 m = scmutil.match(repo, pats, opts)
2195 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2195 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2196 listsubrepos=opts.get('subrepos'))
2196 listsubrepos=opts.get('subrepos'))
2197
2197
2198 @command('^export',
2198 @command('^export',
2199 [('o', 'output', '',
2199 [('o', 'output', '',
2200 _('print output to file with formatted name'), _('FORMAT')),
2200 _('print output to file with formatted name'), _('FORMAT')),
2201 ('', 'switch-parent', None, _('diff against the second parent')),
2201 ('', 'switch-parent', None, _('diff against the second parent')),
2202 ('r', 'rev', [], _('revisions to export'), _('REV')),
2202 ('r', 'rev', [], _('revisions to export'), _('REV')),
2203 ] + diffopts,
2203 ] + diffopts,
2204 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2204 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2205 def export(ui, repo, *changesets, **opts):
2205 def export(ui, repo, *changesets, **opts):
2206 """dump the header and diffs for one or more changesets
2206 """dump the header and diffs for one or more changesets
2207
2207
2208 Print the changeset header and diffs for one or more revisions.
2208 Print the changeset header and diffs for one or more revisions.
2209
2209
2210 The information shown in the changeset header is: author, date,
2210 The information shown in the changeset header is: author, date,
2211 branch name (if non-default), changeset hash, parent(s) and commit
2211 branch name (if non-default), changeset hash, parent(s) and commit
2212 comment.
2212 comment.
2213
2213
2214 .. note::
2214 .. note::
2215 export may generate unexpected diff output for merge
2215 export may generate unexpected diff output for merge
2216 changesets, as it will compare the merge changeset against its
2216 changesets, as it will compare the merge changeset against its
2217 first parent only.
2217 first parent only.
2218
2218
2219 Output may be to a file, in which case the name of the file is
2219 Output may be to a file, in which case the name of the file is
2220 given using a format string. The formatting rules are as follows:
2220 given using a format string. The formatting rules are as follows:
2221
2221
2222 :``%%``: literal "%" character
2222 :``%%``: literal "%" character
2223 :``%H``: changeset hash (40 hexadecimal digits)
2223 :``%H``: changeset hash (40 hexadecimal digits)
2224 :``%N``: number of patches being generated
2224 :``%N``: number of patches being generated
2225 :``%R``: changeset revision number
2225 :``%R``: changeset revision number
2226 :``%b``: basename of the exporting repository
2226 :``%b``: basename of the exporting repository
2227 :``%h``: short-form changeset hash (12 hexadecimal digits)
2227 :``%h``: short-form changeset hash (12 hexadecimal digits)
2228 :``%n``: zero-padded sequence number, starting at 1
2228 :``%n``: zero-padded sequence number, starting at 1
2229 :``%r``: zero-padded changeset revision number
2229 :``%r``: zero-padded changeset revision number
2230
2230
2231 Without the -a/--text option, export will avoid generating diffs
2231 Without the -a/--text option, export will avoid generating diffs
2232 of files it detects as binary. With -a, export will generate a
2232 of files it detects as binary. With -a, export will generate a
2233 diff anyway, probably with undesirable results.
2233 diff anyway, probably with undesirable results.
2234
2234
2235 Use the -g/--git option to generate diffs in the git extended diff
2235 Use the -g/--git option to generate diffs in the git extended diff
2236 format. See :hg:`help diffs` for more information.
2236 format. See :hg:`help diffs` for more information.
2237
2237
2238 With the --switch-parent option, the diff will be against the
2238 With the --switch-parent option, the diff will be against the
2239 second parent. It can be useful to review a merge.
2239 second parent. It can be useful to review a merge.
2240
2240
2241 Returns 0 on success.
2241 Returns 0 on success.
2242 """
2242 """
2243 changesets += tuple(opts.get('rev', []))
2243 changesets += tuple(opts.get('rev', []))
2244 if not changesets:
2244 if not changesets:
2245 raise util.Abort(_("export requires at least one changeset"))
2245 raise util.Abort(_("export requires at least one changeset"))
2246 revs = scmutil.revrange(repo, changesets)
2246 revs = scmutil.revrange(repo, changesets)
2247 if len(revs) > 1:
2247 if len(revs) > 1:
2248 ui.note(_('exporting patches:\n'))
2248 ui.note(_('exporting patches:\n'))
2249 else:
2249 else:
2250 ui.note(_('exporting patch:\n'))
2250 ui.note(_('exporting patch:\n'))
2251 cmdutil.export(repo, revs, template=opts.get('output'),
2251 cmdutil.export(repo, revs, template=opts.get('output'),
2252 switch_parent=opts.get('switch_parent'),
2252 switch_parent=opts.get('switch_parent'),
2253 opts=patch.diffopts(ui, opts))
2253 opts=patch.diffopts(ui, opts))
2254
2254
2255 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2255 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2256 def forget(ui, repo, *pats, **opts):
2256 def forget(ui, repo, *pats, **opts):
2257 """forget the specified files on the next commit
2257 """forget the specified files on the next commit
2258
2258
2259 Mark the specified files so they will no longer be tracked
2259 Mark the specified files so they will no longer be tracked
2260 after the next commit.
2260 after the next commit.
2261
2261
2262 This only removes files from the current branch, not from the
2262 This only removes files from the current branch, not from the
2263 entire project history, and it does not delete them from the
2263 entire project history, and it does not delete them from the
2264 working directory.
2264 working directory.
2265
2265
2266 To undo a forget before the next commit, see :hg:`add`.
2266 To undo a forget before the next commit, see :hg:`add`.
2267
2267
2268 Returns 0 on success.
2268 Returns 0 on success.
2269 """
2269 """
2270
2270
2271 if not pats:
2271 if not pats:
2272 raise util.Abort(_('no files specified'))
2272 raise util.Abort(_('no files specified'))
2273
2273
2274 m = scmutil.match(repo, pats, opts)
2274 m = scmutil.match(repo, pats, opts)
2275 s = repo.status(match=m, clean=True)
2275 s = repo.status(match=m, clean=True)
2276 forget = sorted(s[0] + s[1] + s[3] + s[6])
2276 forget = sorted(s[0] + s[1] + s[3] + s[6])
2277 errs = 0
2277 errs = 0
2278
2278
2279 for f in m.files():
2279 for f in m.files():
2280 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2280 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2281 if os.path.exists(m.rel(f)):
2281 if os.path.exists(m.rel(f)):
2282 ui.warn(_('not removing %s: file is already untracked\n')
2282 ui.warn(_('not removing %s: file is already untracked\n')
2283 % m.rel(f))
2283 % m.rel(f))
2284 errs = 1
2284 errs = 1
2285
2285
2286 for f in forget:
2286 for f in forget:
2287 if ui.verbose or not m.exact(f):
2287 if ui.verbose or not m.exact(f):
2288 ui.status(_('removing %s\n') % m.rel(f))
2288 ui.status(_('removing %s\n') % m.rel(f))
2289
2289
2290 repo[None].forget(forget)
2290 repo[None].forget(forget)
2291 return errs
2291 return errs
2292
2292
2293 @command('grep',
2293 @command('grep',
2294 [('0', 'print0', None, _('end fields with NUL')),
2294 [('0', 'print0', None, _('end fields with NUL')),
2295 ('', 'all', None, _('print all revisions that match')),
2295 ('', 'all', None, _('print all revisions that match')),
2296 ('a', 'text', None, _('treat all files as text')),
2296 ('a', 'text', None, _('treat all files as text')),
2297 ('f', 'follow', None,
2297 ('f', 'follow', None,
2298 _('follow changeset history,'
2298 _('follow changeset history,'
2299 ' or file history across copies and renames')),
2299 ' or file history across copies and renames')),
2300 ('i', 'ignore-case', None, _('ignore case when matching')),
2300 ('i', 'ignore-case', None, _('ignore case when matching')),
2301 ('l', 'files-with-matches', None,
2301 ('l', 'files-with-matches', None,
2302 _('print only filenames and revisions that match')),
2302 _('print only filenames and revisions that match')),
2303 ('n', 'line-number', None, _('print matching line numbers')),
2303 ('n', 'line-number', None, _('print matching line numbers')),
2304 ('r', 'rev', [],
2304 ('r', 'rev', [],
2305 _('only search files changed within revision range'), _('REV')),
2305 _('only search files changed within revision range'), _('REV')),
2306 ('u', 'user', None, _('list the author (long with -v)')),
2306 ('u', 'user', None, _('list the author (long with -v)')),
2307 ('d', 'date', None, _('list the date (short with -q)')),
2307 ('d', 'date', None, _('list the date (short with -q)')),
2308 ] + walkopts,
2308 ] + walkopts,
2309 _('[OPTION]... PATTERN [FILE]...'))
2309 _('[OPTION]... PATTERN [FILE]...'))
2310 def grep(ui, repo, pattern, *pats, **opts):
2310 def grep(ui, repo, pattern, *pats, **opts):
2311 """search for a pattern in specified files and revisions
2311 """search for a pattern in specified files and revisions
2312
2312
2313 Search revisions of files for a regular expression.
2313 Search revisions of files for a regular expression.
2314
2314
2315 This command behaves differently than Unix grep. It only accepts
2315 This command behaves differently than Unix grep. It only accepts
2316 Python/Perl regexps. It searches repository history, not the
2316 Python/Perl regexps. It searches repository history, not the
2317 working directory. It always prints the revision number in which a
2317 working directory. It always prints the revision number in which a
2318 match appears.
2318 match appears.
2319
2319
2320 By default, grep only prints output for the first revision of a
2320 By default, grep only prints output for the first revision of a
2321 file in which it finds a match. To get it to print every revision
2321 file in which it finds a match. To get it to print every revision
2322 that contains a change in match status ("-" for a match that
2322 that contains a change in match status ("-" for a match that
2323 becomes a non-match, or "+" for a non-match that becomes a match),
2323 becomes a non-match, or "+" for a non-match that becomes a match),
2324 use the --all flag.
2324 use the --all flag.
2325
2325
2326 Returns 0 if a match is found, 1 otherwise.
2326 Returns 0 if a match is found, 1 otherwise.
2327 """
2327 """
2328 reflags = 0
2328 reflags = 0
2329 if opts.get('ignore_case'):
2329 if opts.get('ignore_case'):
2330 reflags |= re.I
2330 reflags |= re.I
2331 try:
2331 try:
2332 regexp = re.compile(pattern, reflags)
2332 regexp = re.compile(pattern, reflags)
2333 except re.error, inst:
2333 except re.error, inst:
2334 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2334 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2335 return 1
2335 return 1
2336 sep, eol = ':', '\n'
2336 sep, eol = ':', '\n'
2337 if opts.get('print0'):
2337 if opts.get('print0'):
2338 sep = eol = '\0'
2338 sep = eol = '\0'
2339
2339
2340 getfile = util.lrucachefunc(repo.file)
2340 getfile = util.lrucachefunc(repo.file)
2341
2341
2342 def matchlines(body):
2342 def matchlines(body):
2343 begin = 0
2343 begin = 0
2344 linenum = 0
2344 linenum = 0
2345 while True:
2345 while True:
2346 match = regexp.search(body, begin)
2346 match = regexp.search(body, begin)
2347 if not match:
2347 if not match:
2348 break
2348 break
2349 mstart, mend = match.span()
2349 mstart, mend = match.span()
2350 linenum += body.count('\n', begin, mstart) + 1
2350 linenum += body.count('\n', begin, mstart) + 1
2351 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2351 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2352 begin = body.find('\n', mend) + 1 or len(body)
2352 begin = body.find('\n', mend) + 1 or len(body)
2353 lend = begin - 1
2353 lend = begin - 1
2354 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2354 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2355
2355
2356 class linestate(object):
2356 class linestate(object):
2357 def __init__(self, line, linenum, colstart, colend):
2357 def __init__(self, line, linenum, colstart, colend):
2358 self.line = line
2358 self.line = line
2359 self.linenum = linenum
2359 self.linenum = linenum
2360 self.colstart = colstart
2360 self.colstart = colstart
2361 self.colend = colend
2361 self.colend = colend
2362
2362
2363 def __hash__(self):
2363 def __hash__(self):
2364 return hash((self.linenum, self.line))
2364 return hash((self.linenum, self.line))
2365
2365
2366 def __eq__(self, other):
2366 def __eq__(self, other):
2367 return self.line == other.line
2367 return self.line == other.line
2368
2368
2369 matches = {}
2369 matches = {}
2370 copies = {}
2370 copies = {}
2371 def grepbody(fn, rev, body):
2371 def grepbody(fn, rev, body):
2372 matches[rev].setdefault(fn, [])
2372 matches[rev].setdefault(fn, [])
2373 m = matches[rev][fn]
2373 m = matches[rev][fn]
2374 for lnum, cstart, cend, line in matchlines(body):
2374 for lnum, cstart, cend, line in matchlines(body):
2375 s = linestate(line, lnum, cstart, cend)
2375 s = linestate(line, lnum, cstart, cend)
2376 m.append(s)
2376 m.append(s)
2377
2377
2378 def difflinestates(a, b):
2378 def difflinestates(a, b):
2379 sm = difflib.SequenceMatcher(None, a, b)
2379 sm = difflib.SequenceMatcher(None, a, b)
2380 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2380 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2381 if tag == 'insert':
2381 if tag == 'insert':
2382 for i in xrange(blo, bhi):
2382 for i in xrange(blo, bhi):
2383 yield ('+', b[i])
2383 yield ('+', b[i])
2384 elif tag == 'delete':
2384 elif tag == 'delete':
2385 for i in xrange(alo, ahi):
2385 for i in xrange(alo, ahi):
2386 yield ('-', a[i])
2386 yield ('-', a[i])
2387 elif tag == 'replace':
2387 elif tag == 'replace':
2388 for i in xrange(alo, ahi):
2388 for i in xrange(alo, ahi):
2389 yield ('-', a[i])
2389 yield ('-', a[i])
2390 for i in xrange(blo, bhi):
2390 for i in xrange(blo, bhi):
2391 yield ('+', b[i])
2391 yield ('+', b[i])
2392
2392
2393 def display(fn, ctx, pstates, states):
2393 def display(fn, ctx, pstates, states):
2394 rev = ctx.rev()
2394 rev = ctx.rev()
2395 datefunc = ui.quiet and util.shortdate or util.datestr
2395 datefunc = ui.quiet and util.shortdate or util.datestr
2396 found = False
2396 found = False
2397 filerevmatches = {}
2397 filerevmatches = {}
2398 def binary():
2398 def binary():
2399 flog = getfile(fn)
2399 flog = getfile(fn)
2400 return util.binary(flog.read(ctx.filenode(fn)))
2400 return util.binary(flog.read(ctx.filenode(fn)))
2401
2401
2402 if opts.get('all'):
2402 if opts.get('all'):
2403 iter = difflinestates(pstates, states)
2403 iter = difflinestates(pstates, states)
2404 else:
2404 else:
2405 iter = [('', l) for l in states]
2405 iter = [('', l) for l in states]
2406 for change, l in iter:
2406 for change, l in iter:
2407 cols = [fn, str(rev)]
2407 cols = [fn, str(rev)]
2408 before, match, after = None, None, None
2408 before, match, after = None, None, None
2409 if opts.get('line_number'):
2409 if opts.get('line_number'):
2410 cols.append(str(l.linenum))
2410 cols.append(str(l.linenum))
2411 if opts.get('all'):
2411 if opts.get('all'):
2412 cols.append(change)
2412 cols.append(change)
2413 if opts.get('user'):
2413 if opts.get('user'):
2414 cols.append(ui.shortuser(ctx.user()))
2414 cols.append(ui.shortuser(ctx.user()))
2415 if opts.get('date'):
2415 if opts.get('date'):
2416 cols.append(datefunc(ctx.date()))
2416 cols.append(datefunc(ctx.date()))
2417 if opts.get('files_with_matches'):
2417 if opts.get('files_with_matches'):
2418 c = (fn, rev)
2418 c = (fn, rev)
2419 if c in filerevmatches:
2419 if c in filerevmatches:
2420 continue
2420 continue
2421 filerevmatches[c] = 1
2421 filerevmatches[c] = 1
2422 else:
2422 else:
2423 before = l.line[:l.colstart]
2423 before = l.line[:l.colstart]
2424 match = l.line[l.colstart:l.colend]
2424 match = l.line[l.colstart:l.colend]
2425 after = l.line[l.colend:]
2425 after = l.line[l.colend:]
2426 ui.write(sep.join(cols))
2426 ui.write(sep.join(cols))
2427 if before is not None:
2427 if before is not None:
2428 if not opts.get('text') and binary():
2428 if not opts.get('text') and binary():
2429 ui.write(sep + " Binary file matches")
2429 ui.write(sep + " Binary file matches")
2430 else:
2430 else:
2431 ui.write(sep + before)
2431 ui.write(sep + before)
2432 ui.write(match, label='grep.match')
2432 ui.write(match, label='grep.match')
2433 ui.write(after)
2433 ui.write(after)
2434 ui.write(eol)
2434 ui.write(eol)
2435 found = True
2435 found = True
2436 return found
2436 return found
2437
2437
2438 skip = {}
2438 skip = {}
2439 revfiles = {}
2439 revfiles = {}
2440 matchfn = scmutil.match(repo, pats, opts)
2440 matchfn = scmutil.match(repo, pats, opts)
2441 found = False
2441 found = False
2442 follow = opts.get('follow')
2442 follow = opts.get('follow')
2443
2443
2444 def prep(ctx, fns):
2444 def prep(ctx, fns):
2445 rev = ctx.rev()
2445 rev = ctx.rev()
2446 pctx = ctx.p1()
2446 pctx = ctx.p1()
2447 parent = pctx.rev()
2447 parent = pctx.rev()
2448 matches.setdefault(rev, {})
2448 matches.setdefault(rev, {})
2449 matches.setdefault(parent, {})
2449 matches.setdefault(parent, {})
2450 files = revfiles.setdefault(rev, [])
2450 files = revfiles.setdefault(rev, [])
2451 for fn in fns:
2451 for fn in fns:
2452 flog = getfile(fn)
2452 flog = getfile(fn)
2453 try:
2453 try:
2454 fnode = ctx.filenode(fn)
2454 fnode = ctx.filenode(fn)
2455 except error.LookupError:
2455 except error.LookupError:
2456 continue
2456 continue
2457
2457
2458 copied = flog.renamed(fnode)
2458 copied = flog.renamed(fnode)
2459 copy = follow and copied and copied[0]
2459 copy = follow and copied and copied[0]
2460 if copy:
2460 if copy:
2461 copies.setdefault(rev, {})[fn] = copy
2461 copies.setdefault(rev, {})[fn] = copy
2462 if fn in skip:
2462 if fn in skip:
2463 if copy:
2463 if copy:
2464 skip[copy] = True
2464 skip[copy] = True
2465 continue
2465 continue
2466 files.append(fn)
2466 files.append(fn)
2467
2467
2468 if fn not in matches[rev]:
2468 if fn not in matches[rev]:
2469 grepbody(fn, rev, flog.read(fnode))
2469 grepbody(fn, rev, flog.read(fnode))
2470
2470
2471 pfn = copy or fn
2471 pfn = copy or fn
2472 if pfn not in matches[parent]:
2472 if pfn not in matches[parent]:
2473 try:
2473 try:
2474 fnode = pctx.filenode(pfn)
2474 fnode = pctx.filenode(pfn)
2475 grepbody(pfn, parent, flog.read(fnode))
2475 grepbody(pfn, parent, flog.read(fnode))
2476 except error.LookupError:
2476 except error.LookupError:
2477 pass
2477 pass
2478
2478
2479 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2479 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2480 rev = ctx.rev()
2480 rev = ctx.rev()
2481 parent = ctx.p1().rev()
2481 parent = ctx.p1().rev()
2482 for fn in sorted(revfiles.get(rev, [])):
2482 for fn in sorted(revfiles.get(rev, [])):
2483 states = matches[rev][fn]
2483 states = matches[rev][fn]
2484 copy = copies.get(rev, {}).get(fn)
2484 copy = copies.get(rev, {}).get(fn)
2485 if fn in skip:
2485 if fn in skip:
2486 if copy:
2486 if copy:
2487 skip[copy] = True
2487 skip[copy] = True
2488 continue
2488 continue
2489 pstates = matches.get(parent, {}).get(copy or fn, [])
2489 pstates = matches.get(parent, {}).get(copy or fn, [])
2490 if pstates or states:
2490 if pstates or states:
2491 r = display(fn, ctx, pstates, states)
2491 r = display(fn, ctx, pstates, states)
2492 found = found or r
2492 found = found or r
2493 if r and not opts.get('all'):
2493 if r and not opts.get('all'):
2494 skip[fn] = True
2494 skip[fn] = True
2495 if copy:
2495 if copy:
2496 skip[copy] = True
2496 skip[copy] = True
2497 del matches[rev]
2497 del matches[rev]
2498 del revfiles[rev]
2498 del revfiles[rev]
2499
2499
2500 return not found
2500 return not found
2501
2501
2502 @command('heads',
2502 @command('heads',
2503 [('r', 'rev', '',
2503 [('r', 'rev', '',
2504 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2504 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2505 ('t', 'topo', False, _('show topological heads only')),
2505 ('t', 'topo', False, _('show topological heads only')),
2506 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2506 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2507 ('c', 'closed', False, _('show normal and closed branch heads')),
2507 ('c', 'closed', False, _('show normal and closed branch heads')),
2508 ] + templateopts,
2508 ] + templateopts,
2509 _('[-ac] [-r STARTREV] [REV]...'))
2509 _('[-ac] [-r STARTREV] [REV]...'))
2510 def heads(ui, repo, *branchrevs, **opts):
2510 def heads(ui, repo, *branchrevs, **opts):
2511 """show current repository heads or show branch heads
2511 """show current repository heads or show branch heads
2512
2512
2513 With no arguments, show all repository branch heads.
2513 With no arguments, show all repository branch heads.
2514
2514
2515 Repository "heads" are changesets with no child changesets. They are
2515 Repository "heads" are changesets with no child changesets. They are
2516 where development generally takes place and are the usual targets
2516 where development generally takes place and are the usual targets
2517 for update and merge operations. Branch heads are changesets that have
2517 for update and merge operations. Branch heads are changesets that have
2518 no child changeset on the same branch.
2518 no child changeset on the same branch.
2519
2519
2520 If one or more REVs are given, only branch heads on the branches
2520 If one or more REVs are given, only branch heads on the branches
2521 associated with the specified changesets are shown.
2521 associated with the specified changesets are shown.
2522
2522
2523 If -c/--closed is specified, also show branch heads marked closed
2523 If -c/--closed is specified, also show branch heads marked closed
2524 (see :hg:`commit --close-branch`).
2524 (see :hg:`commit --close-branch`).
2525
2525
2526 If STARTREV is specified, only those heads that are descendants of
2526 If STARTREV is specified, only those heads that are descendants of
2527 STARTREV will be displayed.
2527 STARTREV will be displayed.
2528
2528
2529 If -t/--topo is specified, named branch mechanics will be ignored and only
2529 If -t/--topo is specified, named branch mechanics will be ignored and only
2530 changesets without children will be shown.
2530 changesets without children will be shown.
2531
2531
2532 Returns 0 if matching heads are found, 1 if not.
2532 Returns 0 if matching heads are found, 1 if not.
2533 """
2533 """
2534
2534
2535 start = None
2535 start = None
2536 if 'rev' in opts:
2536 if 'rev' in opts:
2537 start = scmutil.revsingle(repo, opts['rev'], None).node()
2537 start = scmutil.revsingle(repo, opts['rev'], None).node()
2538
2538
2539 if opts.get('topo'):
2539 if opts.get('topo'):
2540 heads = [repo[h] for h in repo.heads(start)]
2540 heads = [repo[h] for h in repo.heads(start)]
2541 else:
2541 else:
2542 heads = []
2542 heads = []
2543 for branch in repo.branchmap():
2543 for branch in repo.branchmap():
2544 heads += repo.branchheads(branch, start, opts.get('closed'))
2544 heads += repo.branchheads(branch, start, opts.get('closed'))
2545 heads = [repo[h] for h in heads]
2545 heads = [repo[h] for h in heads]
2546
2546
2547 if branchrevs:
2547 if branchrevs:
2548 branches = set(repo[br].branch() for br in branchrevs)
2548 branches = set(repo[br].branch() for br in branchrevs)
2549 heads = [h for h in heads if h.branch() in branches]
2549 heads = [h for h in heads if h.branch() in branches]
2550
2550
2551 if opts.get('active') and branchrevs:
2551 if opts.get('active') and branchrevs:
2552 dagheads = repo.heads(start)
2552 dagheads = repo.heads(start)
2553 heads = [h for h in heads if h.node() in dagheads]
2553 heads = [h for h in heads if h.node() in dagheads]
2554
2554
2555 if branchrevs:
2555 if branchrevs:
2556 haveheads = set(h.branch() for h in heads)
2556 haveheads = set(h.branch() for h in heads)
2557 if branches - haveheads:
2557 if branches - haveheads:
2558 headless = ', '.join(b for b in branches - haveheads)
2558 headless = ', '.join(b for b in branches - haveheads)
2559 msg = _('no open branch heads found on branches %s')
2559 msg = _('no open branch heads found on branches %s')
2560 if opts.get('rev'):
2560 if opts.get('rev'):
2561 msg += _(' (started at %s)' % opts['rev'])
2561 msg += _(' (started at %s)' % opts['rev'])
2562 ui.warn((msg + '\n') % headless)
2562 ui.warn((msg + '\n') % headless)
2563
2563
2564 if not heads:
2564 if not heads:
2565 return 1
2565 return 1
2566
2566
2567 heads = sorted(heads, key=lambda x: -x.rev())
2567 heads = sorted(heads, key=lambda x: -x.rev())
2568 displayer = cmdutil.show_changeset(ui, repo, opts)
2568 displayer = cmdutil.show_changeset(ui, repo, opts)
2569 for ctx in heads:
2569 for ctx in heads:
2570 displayer.show(ctx)
2570 displayer.show(ctx)
2571 displayer.close()
2571 displayer.close()
2572
2572
2573 @command('help',
2573 @command('help',
2574 [('e', 'extension', None, _('show only help for extensions')),
2574 [('e', 'extension', None, _('show only help for extensions')),
2575 ('c', 'command', None, _('show only help for commands'))],
2575 ('c', 'command', None, _('show only help for commands'))],
2576 _('[-ec] [TOPIC]'))
2576 _('[-ec] [TOPIC]'))
2577 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2577 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2578 """show help for a given topic or a help overview
2578 """show help for a given topic or a help overview
2579
2579
2580 With no arguments, print a list of commands with short help messages.
2580 With no arguments, print a list of commands with short help messages.
2581
2581
2582 Given a topic, extension, or command name, print help for that
2582 Given a topic, extension, or command name, print help for that
2583 topic.
2583 topic.
2584
2584
2585 Returns 0 if successful.
2585 Returns 0 if successful.
2586 """
2586 """
2587 option_lists = []
2587 option_lists = []
2588 textwidth = min(ui.termwidth(), 80) - 2
2588 textwidth = min(ui.termwidth(), 80) - 2
2589
2589
2590 def addglobalopts(aliases):
2590 def addglobalopts(aliases):
2591 if ui.verbose:
2591 if ui.verbose:
2592 option_lists.append((_("global options:"), globalopts))
2592 option_lists.append((_("global options:"), globalopts))
2593 if name == 'shortlist':
2593 if name == 'shortlist':
2594 option_lists.append((_('use "hg help" for the full list '
2594 option_lists.append((_('use "hg help" for the full list '
2595 'of commands'), ()))
2595 'of commands'), ()))
2596 else:
2596 else:
2597 if name == 'shortlist':
2597 if name == 'shortlist':
2598 msg = _('use "hg help" for the full list of commands '
2598 msg = _('use "hg help" for the full list of commands '
2599 'or "hg -v" for details')
2599 'or "hg -v" for details')
2600 elif name and not full:
2600 elif name and not full:
2601 msg = _('use "hg help %s" to show the full help text' % name)
2601 msg = _('use "hg help %s" to show the full help text' % name)
2602 elif aliases:
2602 elif aliases:
2603 msg = _('use "hg -v help%s" to show builtin aliases and '
2603 msg = _('use "hg -v help%s" to show builtin aliases and '
2604 'global options') % (name and " " + name or "")
2604 'global options') % (name and " " + name or "")
2605 else:
2605 else:
2606 msg = _('use "hg -v help %s" to show global options') % name
2606 msg = _('use "hg -v help %s" to show global options') % name
2607 option_lists.append((msg, ()))
2607 option_lists.append((msg, ()))
2608
2608
2609 def helpcmd(name):
2609 def helpcmd(name):
2610 if with_version:
2610 if with_version:
2611 version_(ui)
2611 version_(ui)
2612 ui.write('\n')
2612 ui.write('\n')
2613
2613
2614 try:
2614 try:
2615 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2615 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2616 except error.AmbiguousCommand, inst:
2616 except error.AmbiguousCommand, inst:
2617 # py3k fix: except vars can't be used outside the scope of the
2617 # py3k fix: except vars can't be used outside the scope of the
2618 # except block, nor can be used inside a lambda. python issue4617
2618 # except block, nor can be used inside a lambda. python issue4617
2619 prefix = inst.args[0]
2619 prefix = inst.args[0]
2620 select = lambda c: c.lstrip('^').startswith(prefix)
2620 select = lambda c: c.lstrip('^').startswith(prefix)
2621 helplist(_('list of commands:\n\n'), select)
2621 helplist(_('list of commands:\n\n'), select)
2622 return
2622 return
2623
2623
2624 # check if it's an invalid alias and display its error if it is
2624 # check if it's an invalid alias and display its error if it is
2625 if getattr(entry[0], 'badalias', False):
2625 if getattr(entry[0], 'badalias', False):
2626 if not unknowncmd:
2626 if not unknowncmd:
2627 entry[0](ui)
2627 entry[0](ui)
2628 return
2628 return
2629
2629
2630 # synopsis
2630 # synopsis
2631 if len(entry) > 2:
2631 if len(entry) > 2:
2632 if entry[2].startswith('hg'):
2632 if entry[2].startswith('hg'):
2633 ui.write("%s\n" % entry[2])
2633 ui.write("%s\n" % entry[2])
2634 else:
2634 else:
2635 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2635 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2636 else:
2636 else:
2637 ui.write('hg %s\n' % aliases[0])
2637 ui.write('hg %s\n' % aliases[0])
2638
2638
2639 # aliases
2639 # aliases
2640 if full and not ui.quiet and len(aliases) > 1:
2640 if full and not ui.quiet and len(aliases) > 1:
2641 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2641 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2642
2642
2643 # description
2643 # description
2644 doc = gettext(entry[0].__doc__)
2644 doc = gettext(entry[0].__doc__)
2645 if not doc:
2645 if not doc:
2646 doc = _("(no help text available)")
2646 doc = _("(no help text available)")
2647 if hasattr(entry[0], 'definition'): # aliased command
2647 if hasattr(entry[0], 'definition'): # aliased command
2648 if entry[0].definition.startswith('!'): # shell alias
2648 if entry[0].definition.startswith('!'): # shell alias
2649 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2649 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2650 else:
2650 else:
2651 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2651 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2652 if ui.quiet or not full:
2652 if ui.quiet or not full:
2653 doc = doc.splitlines()[0]
2653 doc = doc.splitlines()[0]
2654 keep = ui.verbose and ['verbose'] or []
2654 keep = ui.verbose and ['verbose'] or []
2655 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2655 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2656 ui.write("\n%s\n" % formatted)
2656 ui.write("\n%s\n" % formatted)
2657 if pruned:
2657 if pruned:
2658 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2658 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2659
2659
2660 if not ui.quiet:
2660 if not ui.quiet:
2661 # options
2661 # options
2662 if entry[1]:
2662 if entry[1]:
2663 option_lists.append((_("options:\n"), entry[1]))
2663 option_lists.append((_("options:\n"), entry[1]))
2664
2664
2665 addglobalopts(False)
2665 addglobalopts(False)
2666
2666
2667 # check if this command shadows a non-trivial (multi-line)
2667 # check if this command shadows a non-trivial (multi-line)
2668 # extension help text
2668 # extension help text
2669 try:
2669 try:
2670 mod = extensions.find(name)
2670 mod = extensions.find(name)
2671 doc = gettext(mod.__doc__) or ''
2671 doc = gettext(mod.__doc__) or ''
2672 if '\n' in doc.strip():
2672 if '\n' in doc.strip():
2673 msg = _('use "hg help -e %s" to show help for '
2673 msg = _('use "hg help -e %s" to show help for '
2674 'the %s extension') % (name, name)
2674 'the %s extension') % (name, name)
2675 ui.write('\n%s\n' % msg)
2675 ui.write('\n%s\n' % msg)
2676 except KeyError:
2676 except KeyError:
2677 pass
2677 pass
2678
2678
2679 def helplist(header, select=None):
2679 def helplist(header, select=None):
2680 h = {}
2680 h = {}
2681 cmds = {}
2681 cmds = {}
2682 for c, e in table.iteritems():
2682 for c, e in table.iteritems():
2683 f = c.split("|", 1)[0]
2683 f = c.split("|", 1)[0]
2684 if select and not select(f):
2684 if select and not select(f):
2685 continue
2685 continue
2686 if (not select and name != 'shortlist' and
2686 if (not select and name != 'shortlist' and
2687 e[0].__module__ != __name__):
2687 e[0].__module__ != __name__):
2688 continue
2688 continue
2689 if name == "shortlist" and not f.startswith("^"):
2689 if name == "shortlist" and not f.startswith("^"):
2690 continue
2690 continue
2691 f = f.lstrip("^")
2691 f = f.lstrip("^")
2692 if not ui.debugflag and f.startswith("debug"):
2692 if not ui.debugflag and f.startswith("debug"):
2693 continue
2693 continue
2694 doc = e[0].__doc__
2694 doc = e[0].__doc__
2695 if doc and 'DEPRECATED' in doc and not ui.verbose:
2695 if doc and 'DEPRECATED' in doc and not ui.verbose:
2696 continue
2696 continue
2697 doc = gettext(doc)
2697 doc = gettext(doc)
2698 if not doc:
2698 if not doc:
2699 doc = _("(no help text available)")
2699 doc = _("(no help text available)")
2700 h[f] = doc.splitlines()[0].rstrip()
2700 h[f] = doc.splitlines()[0].rstrip()
2701 cmds[f] = c.lstrip("^")
2701 cmds[f] = c.lstrip("^")
2702
2702
2703 if not h:
2703 if not h:
2704 ui.status(_('no commands defined\n'))
2704 ui.status(_('no commands defined\n'))
2705 return
2705 return
2706
2706
2707 ui.status(header)
2707 ui.status(header)
2708 fns = sorted(h)
2708 fns = sorted(h)
2709 m = max(map(len, fns))
2709 m = max(map(len, fns))
2710 for f in fns:
2710 for f in fns:
2711 if ui.verbose:
2711 if ui.verbose:
2712 commands = cmds[f].replace("|",", ")
2712 commands = cmds[f].replace("|",", ")
2713 ui.write(" %s:\n %s\n"%(commands, h[f]))
2713 ui.write(" %s:\n %s\n"%(commands, h[f]))
2714 else:
2714 else:
2715 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2715 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2716 initindent=' %-*s ' % (m, f),
2716 initindent=' %-*s ' % (m, f),
2717 hangindent=' ' * (m + 4))))
2717 hangindent=' ' * (m + 4))))
2718
2718
2719 if not ui.quiet:
2719 if not ui.quiet:
2720 addglobalopts(True)
2720 addglobalopts(True)
2721
2721
2722 def helptopic(name):
2722 def helptopic(name):
2723 for names, header, doc in help.helptable:
2723 for names, header, doc in help.helptable:
2724 if name in names:
2724 if name in names:
2725 break
2725 break
2726 else:
2726 else:
2727 raise error.UnknownCommand(name)
2727 raise error.UnknownCommand(name)
2728
2728
2729 # description
2729 # description
2730 if not doc:
2730 if not doc:
2731 doc = _("(no help text available)")
2731 doc = _("(no help text available)")
2732 if hasattr(doc, '__call__'):
2732 if hasattr(doc, '__call__'):
2733 doc = doc()
2733 doc = doc()
2734
2734
2735 ui.write("%s\n\n" % header)
2735 ui.write("%s\n\n" % header)
2736 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2736 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2737 try:
2737 try:
2738 cmdutil.findcmd(name, table)
2738 cmdutil.findcmd(name, table)
2739 ui.write(_('\nuse "hg help -c %s" to see help for '
2739 ui.write(_('\nuse "hg help -c %s" to see help for '
2740 'the %s command\n') % (name, name))
2740 'the %s command\n') % (name, name))
2741 except error.UnknownCommand:
2741 except error.UnknownCommand:
2742 pass
2742 pass
2743
2743
2744 def helpext(name):
2744 def helpext(name):
2745 try:
2745 try:
2746 mod = extensions.find(name)
2746 mod = extensions.find(name)
2747 doc = gettext(mod.__doc__) or _('no help text available')
2747 doc = gettext(mod.__doc__) or _('no help text available')
2748 except KeyError:
2748 except KeyError:
2749 mod = None
2749 mod = None
2750 doc = extensions.disabledext(name)
2750 doc = extensions.disabledext(name)
2751 if not doc:
2751 if not doc:
2752 raise error.UnknownCommand(name)
2752 raise error.UnknownCommand(name)
2753
2753
2754 if '\n' not in doc:
2754 if '\n' not in doc:
2755 head, tail = doc, ""
2755 head, tail = doc, ""
2756 else:
2756 else:
2757 head, tail = doc.split('\n', 1)
2757 head, tail = doc.split('\n', 1)
2758 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2758 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2759 if tail:
2759 if tail:
2760 ui.write(minirst.format(tail, textwidth))
2760 ui.write(minirst.format(tail, textwidth))
2761 ui.status('\n\n')
2761 ui.status('\n\n')
2762
2762
2763 if mod:
2763 if mod:
2764 try:
2764 try:
2765 ct = mod.cmdtable
2765 ct = mod.cmdtable
2766 except AttributeError:
2766 except AttributeError:
2767 ct = {}
2767 ct = {}
2768 modcmds = set([c.split('|', 1)[0] for c in ct])
2768 modcmds = set([c.split('|', 1)[0] for c in ct])
2769 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2769 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2770 else:
2770 else:
2771 ui.write(_('use "hg help extensions" for information on enabling '
2771 ui.write(_('use "hg help extensions" for information on enabling '
2772 'extensions\n'))
2772 'extensions\n'))
2773
2773
2774 def helpextcmd(name):
2774 def helpextcmd(name):
2775 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2775 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2776 doc = gettext(mod.__doc__).splitlines()[0]
2776 doc = gettext(mod.__doc__).splitlines()[0]
2777
2777
2778 msg = help.listexts(_("'%s' is provided by the following "
2778 msg = help.listexts(_("'%s' is provided by the following "
2779 "extension:") % cmd, {ext: doc}, indent=4)
2779 "extension:") % cmd, {ext: doc}, indent=4)
2780 ui.write(minirst.format(msg, textwidth))
2780 ui.write(minirst.format(msg, textwidth))
2781 ui.write('\n\n')
2781 ui.write('\n\n')
2782 ui.write(_('use "hg help extensions" for information on enabling '
2782 ui.write(_('use "hg help extensions" for information on enabling '
2783 'extensions\n'))
2783 'extensions\n'))
2784
2784
2785 if name and name != 'shortlist':
2785 if name and name != 'shortlist':
2786 i = None
2786 i = None
2787 if unknowncmd:
2787 if unknowncmd:
2788 queries = (helpextcmd,)
2788 queries = (helpextcmd,)
2789 elif opts.get('extension'):
2789 elif opts.get('extension'):
2790 queries = (helpext,)
2790 queries = (helpext,)
2791 elif opts.get('command'):
2791 elif opts.get('command'):
2792 queries = (helpcmd,)
2792 queries = (helpcmd,)
2793 else:
2793 else:
2794 queries = (helptopic, helpcmd, helpext, helpextcmd)
2794 queries = (helptopic, helpcmd, helpext, helpextcmd)
2795 for f in queries:
2795 for f in queries:
2796 try:
2796 try:
2797 f(name)
2797 f(name)
2798 i = None
2798 i = None
2799 break
2799 break
2800 except error.UnknownCommand, inst:
2800 except error.UnknownCommand, inst:
2801 i = inst
2801 i = inst
2802 if i:
2802 if i:
2803 raise i
2803 raise i
2804
2804
2805 else:
2805 else:
2806 # program name
2806 # program name
2807 if ui.verbose or with_version:
2807 if ui.verbose or with_version:
2808 version_(ui)
2808 version_(ui)
2809 else:
2809 else:
2810 ui.status(_("Mercurial Distributed SCM\n"))
2810 ui.status(_("Mercurial Distributed SCM\n"))
2811 ui.status('\n')
2811 ui.status('\n')
2812
2812
2813 # list of commands
2813 # list of commands
2814 if name == "shortlist":
2814 if name == "shortlist":
2815 header = _('basic commands:\n\n')
2815 header = _('basic commands:\n\n')
2816 else:
2816 else:
2817 header = _('list of commands:\n\n')
2817 header = _('list of commands:\n\n')
2818
2818
2819 helplist(header)
2819 helplist(header)
2820 if name != 'shortlist':
2820 if name != 'shortlist':
2821 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2821 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2822 if text:
2822 if text:
2823 ui.write("\n%s\n" % minirst.format(text, textwidth))
2823 ui.write("\n%s\n" % minirst.format(text, textwidth))
2824
2824
2825 # list all option lists
2825 # list all option lists
2826 opt_output = []
2826 opt_output = []
2827 multioccur = False
2827 multioccur = False
2828 for title, options in option_lists:
2828 for title, options in option_lists:
2829 opt_output.append(("\n%s" % title, None))
2829 opt_output.append(("\n%s" % title, None))
2830 for option in options:
2830 for option in options:
2831 if len(option) == 5:
2831 if len(option) == 5:
2832 shortopt, longopt, default, desc, optlabel = option
2832 shortopt, longopt, default, desc, optlabel = option
2833 else:
2833 else:
2834 shortopt, longopt, default, desc = option
2834 shortopt, longopt, default, desc = option
2835 optlabel = _("VALUE") # default label
2835 optlabel = _("VALUE") # default label
2836
2836
2837 if _("DEPRECATED") in desc and not ui.verbose:
2837 if _("DEPRECATED") in desc and not ui.verbose:
2838 continue
2838 continue
2839 if isinstance(default, list):
2839 if isinstance(default, list):
2840 numqualifier = " %s [+]" % optlabel
2840 numqualifier = " %s [+]" % optlabel
2841 multioccur = True
2841 multioccur = True
2842 elif (default is not None) and not isinstance(default, bool):
2842 elif (default is not None) and not isinstance(default, bool):
2843 numqualifier = " %s" % optlabel
2843 numqualifier = " %s" % optlabel
2844 else:
2844 else:
2845 numqualifier = ""
2845 numqualifier = ""
2846 opt_output.append(("%2s%s" %
2846 opt_output.append(("%2s%s" %
2847 (shortopt and "-%s" % shortopt,
2847 (shortopt and "-%s" % shortopt,
2848 longopt and " --%s%s" %
2848 longopt and " --%s%s" %
2849 (longopt, numqualifier)),
2849 (longopt, numqualifier)),
2850 "%s%s" % (desc,
2850 "%s%s" % (desc,
2851 default
2851 default
2852 and _(" (default: %s)") % default
2852 and _(" (default: %s)") % default
2853 or "")))
2853 or "")))
2854 if multioccur:
2854 if multioccur:
2855 msg = _("\n[+] marked option can be specified multiple times")
2855 msg = _("\n[+] marked option can be specified multiple times")
2856 if ui.verbose and name != 'shortlist':
2856 if ui.verbose and name != 'shortlist':
2857 opt_output.append((msg, None))
2857 opt_output.append((msg, None))
2858 else:
2858 else:
2859 opt_output.insert(-1, (msg, None))
2859 opt_output.insert(-1, (msg, None))
2860
2860
2861 if not name:
2861 if not name:
2862 ui.write(_("\nadditional help topics:\n\n"))
2862 ui.write(_("\nadditional help topics:\n\n"))
2863 topics = []
2863 topics = []
2864 for names, header, doc in help.helptable:
2864 for names, header, doc in help.helptable:
2865 topics.append((sorted(names, key=len, reverse=True)[0], header))
2865 topics.append((sorted(names, key=len, reverse=True)[0], header))
2866 topics_len = max([len(s[0]) for s in topics])
2866 topics_len = max([len(s[0]) for s in topics])
2867 for t, desc in topics:
2867 for t, desc in topics:
2868 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2868 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2869
2869
2870 if opt_output:
2870 if opt_output:
2871 colwidth = encoding.colwidth
2871 colwidth = encoding.colwidth
2872 # normalize: (opt or message, desc or None, width of opt)
2872 # normalize: (opt or message, desc or None, width of opt)
2873 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2873 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2874 for opt, desc in opt_output]
2874 for opt, desc in opt_output]
2875 hanging = max([e[2] for e in entries])
2875 hanging = max([e[2] for e in entries])
2876 for opt, desc, width in entries:
2876 for opt, desc, width in entries:
2877 if desc:
2877 if desc:
2878 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2878 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2879 hangindent = ' ' * (hanging + 3)
2879 hangindent = ' ' * (hanging + 3)
2880 ui.write('%s\n' % (util.wrap(desc, textwidth,
2880 ui.write('%s\n' % (util.wrap(desc, textwidth,
2881 initindent=initindent,
2881 initindent=initindent,
2882 hangindent=hangindent)))
2882 hangindent=hangindent)))
2883 else:
2883 else:
2884 ui.write("%s\n" % opt)
2884 ui.write("%s\n" % opt)
2885
2885
2886 @command('identify|id',
2886 @command('identify|id',
2887 [('r', 'rev', '',
2887 [('r', 'rev', '',
2888 _('identify the specified revision'), _('REV')),
2888 _('identify the specified revision'), _('REV')),
2889 ('n', 'num', None, _('show local revision number')),
2889 ('n', 'num', None, _('show local revision number')),
2890 ('i', 'id', None, _('show global revision id')),
2890 ('i', 'id', None, _('show global revision id')),
2891 ('b', 'branch', None, _('show branch')),
2891 ('b', 'branch', None, _('show branch')),
2892 ('t', 'tags', None, _('show tags')),
2892 ('t', 'tags', None, _('show tags')),
2893 ('B', 'bookmarks', None, _('show bookmarks'))],
2893 ('B', 'bookmarks', None, _('show bookmarks'))],
2894 _('[-nibtB] [-r REV] [SOURCE]'))
2894 _('[-nibtB] [-r REV] [SOURCE]'))
2895 def identify(ui, repo, source=None, rev=None,
2895 def identify(ui, repo, source=None, rev=None,
2896 num=None, id=None, branch=None, tags=None, bookmarks=None):
2896 num=None, id=None, branch=None, tags=None, bookmarks=None):
2897 """identify the working copy or specified revision
2897 """identify the working copy or specified revision
2898
2898
2899 Print a summary identifying the repository state at REV using one or
2899 Print a summary identifying the repository state at REV using one or
2900 two parent hash identifiers, followed by a "+" if the working
2900 two parent hash identifiers, followed by a "+" if the working
2901 directory has uncommitted changes, the branch name (if not default),
2901 directory has uncommitted changes, the branch name (if not default),
2902 a list of tags, and a list of bookmarks.
2902 a list of tags, and a list of bookmarks.
2903
2903
2904 When REV is not given, print a summary of the current state of the
2904 When REV is not given, print a summary of the current state of the
2905 repository.
2905 repository.
2906
2906
2907 Specifying a path to a repository root or Mercurial bundle will
2907 Specifying a path to a repository root or Mercurial bundle will
2908 cause lookup to operate on that repository/bundle.
2908 cause lookup to operate on that repository/bundle.
2909
2909
2910 Returns 0 if successful.
2910 Returns 0 if successful.
2911 """
2911 """
2912
2912
2913 if not repo and not source:
2913 if not repo and not source:
2914 raise util.Abort(_("there is no Mercurial repository here "
2914 raise util.Abort(_("there is no Mercurial repository here "
2915 "(.hg not found)"))
2915 "(.hg not found)"))
2916
2916
2917 hexfunc = ui.debugflag and hex or short
2917 hexfunc = ui.debugflag and hex or short
2918 default = not (num or id or branch or tags or bookmarks)
2918 default = not (num or id or branch or tags or bookmarks)
2919 output = []
2919 output = []
2920 revs = []
2920 revs = []
2921
2921
2922 if source:
2922 if source:
2923 source, branches = hg.parseurl(ui.expandpath(source))
2923 source, branches = hg.parseurl(ui.expandpath(source))
2924 repo = hg.peer(ui, {}, source)
2924 repo = hg.peer(ui, {}, source)
2925 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2925 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2926
2926
2927 if not repo.local():
2927 if not repo.local():
2928 if num or branch or tags:
2928 if num or branch or tags:
2929 raise util.Abort(
2929 raise util.Abort(
2930 _("can't query remote revision number, branch, or tags"))
2930 _("can't query remote revision number, branch, or tags"))
2931 if not rev and revs:
2931 if not rev and revs:
2932 rev = revs[0]
2932 rev = revs[0]
2933 if not rev:
2933 if not rev:
2934 rev = "tip"
2934 rev = "tip"
2935
2935
2936 remoterev = repo.lookup(rev)
2936 remoterev = repo.lookup(rev)
2937 if default or id:
2937 if default or id:
2938 output = [hexfunc(remoterev)]
2938 output = [hexfunc(remoterev)]
2939
2939
2940 def getbms():
2940 def getbms():
2941 bms = []
2941 bms = []
2942
2942
2943 if 'bookmarks' in repo.listkeys('namespaces'):
2943 if 'bookmarks' in repo.listkeys('namespaces'):
2944 hexremoterev = hex(remoterev)
2944 hexremoterev = hex(remoterev)
2945 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2945 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2946 if bmr == hexremoterev]
2946 if bmr == hexremoterev]
2947
2947
2948 return bms
2948 return bms
2949
2949
2950 if bookmarks:
2950 if bookmarks:
2951 output.extend(getbms())
2951 output.extend(getbms())
2952 elif default and not ui.quiet:
2952 elif default and not ui.quiet:
2953 # multiple bookmarks for a single parent separated by '/'
2953 # multiple bookmarks for a single parent separated by '/'
2954 bm = '/'.join(getbms())
2954 bm = '/'.join(getbms())
2955 if bm:
2955 if bm:
2956 output.append(bm)
2956 output.append(bm)
2957 else:
2957 else:
2958 if not rev:
2958 if not rev:
2959 ctx = repo[None]
2959 ctx = repo[None]
2960 parents = ctx.parents()
2960 parents = ctx.parents()
2961 changed = ""
2961 changed = ""
2962 if default or id or num:
2962 if default or id or num:
2963 changed = util.any(repo.status()) and "+" or ""
2963 changed = util.any(repo.status()) and "+" or ""
2964 if default or id:
2964 if default or id:
2965 output = ["%s%s" %
2965 output = ["%s%s" %
2966 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2966 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2967 if num:
2967 if num:
2968 output.append("%s%s" %
2968 output.append("%s%s" %
2969 ('+'.join([str(p.rev()) for p in parents]), changed))
2969 ('+'.join([str(p.rev()) for p in parents]), changed))
2970 else:
2970 else:
2971 ctx = scmutil.revsingle(repo, rev)
2971 ctx = scmutil.revsingle(repo, rev)
2972 if default or id:
2972 if default or id:
2973 output = [hexfunc(ctx.node())]
2973 output = [hexfunc(ctx.node())]
2974 if num:
2974 if num:
2975 output.append(str(ctx.rev()))
2975 output.append(str(ctx.rev()))
2976
2976
2977 if default and not ui.quiet:
2977 if default and not ui.quiet:
2978 b = ctx.branch()
2978 b = ctx.branch()
2979 if b != 'default':
2979 if b != 'default':
2980 output.append("(%s)" % b)
2980 output.append("(%s)" % b)
2981
2981
2982 # multiple tags for a single parent separated by '/'
2982 # multiple tags for a single parent separated by '/'
2983 t = '/'.join(ctx.tags())
2983 t = '/'.join(ctx.tags())
2984 if t:
2984 if t:
2985 output.append(t)
2985 output.append(t)
2986
2986
2987 # multiple bookmarks for a single parent separated by '/'
2987 # multiple bookmarks for a single parent separated by '/'
2988 bm = '/'.join(ctx.bookmarks())
2988 bm = '/'.join(ctx.bookmarks())
2989 if bm:
2989 if bm:
2990 output.append(bm)
2990 output.append(bm)
2991 else:
2991 else:
2992 if branch:
2992 if branch:
2993 output.append(ctx.branch())
2993 output.append(ctx.branch())
2994
2994
2995 if tags:
2995 if tags:
2996 output.extend(ctx.tags())
2996 output.extend(ctx.tags())
2997
2997
2998 if bookmarks:
2998 if bookmarks:
2999 output.extend(ctx.bookmarks())
2999 output.extend(ctx.bookmarks())
3000
3000
3001 ui.write("%s\n" % ' '.join(output))
3001 ui.write("%s\n" % ' '.join(output))
3002
3002
3003 @command('import|patch',
3003 @command('import|patch',
3004 [('p', 'strip', 1,
3004 [('p', 'strip', 1,
3005 _('directory strip option for patch. This has the same '
3005 _('directory strip option for patch. This has the same '
3006 'meaning as the corresponding patch option'), _('NUM')),
3006 'meaning as the corresponding patch option'), _('NUM')),
3007 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3007 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3008 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3008 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3009 ('', 'no-commit', None,
3009 ('', 'no-commit', None,
3010 _("don't commit, just update the working directory")),
3010 _("don't commit, just update the working directory")),
3011 ('', 'bypass', None,
3011 ('', 'bypass', None,
3012 _("apply patch without touching the working directory")),
3012 _("apply patch without touching the working directory")),
3013 ('', 'exact', None,
3013 ('', 'exact', None,
3014 _('apply patch to the nodes from which it was generated')),
3014 _('apply patch to the nodes from which it was generated')),
3015 ('', 'import-branch', None,
3015 ('', 'import-branch', None,
3016 _('use any branch information in patch (implied by --exact)'))] +
3016 _('use any branch information in patch (implied by --exact)'))] +
3017 commitopts + commitopts2 + similarityopts,
3017 commitopts + commitopts2 + similarityopts,
3018 _('[OPTION]... PATCH...'))
3018 _('[OPTION]... PATCH...'))
3019 def import_(ui, repo, patch1, *patches, **opts):
3019 def import_(ui, repo, patch1, *patches, **opts):
3020 """import an ordered set of patches
3020 """import an ordered set of patches
3021
3021
3022 Import a list of patches and commit them individually (unless
3022 Import a list of patches and commit them individually (unless
3023 --no-commit is specified).
3023 --no-commit is specified).
3024
3024
3025 If there are outstanding changes in the working directory, import
3025 If there are outstanding changes in the working directory, import
3026 will abort unless given the -f/--force flag.
3026 will abort unless given the -f/--force flag.
3027
3027
3028 You can import a patch straight from a mail message. Even patches
3028 You can import a patch straight from a mail message. Even patches
3029 as attachments work (to use the body part, it must have type
3029 as attachments work (to use the body part, it must have type
3030 text/plain or text/x-patch). From and Subject headers of email
3030 text/plain or text/x-patch). From and Subject headers of email
3031 message are used as default committer and commit message. All
3031 message are used as default committer and commit message. All
3032 text/plain body parts before first diff are added to commit
3032 text/plain body parts before first diff are added to commit
3033 message.
3033 message.
3034
3034
3035 If the imported patch was generated by :hg:`export`, user and
3035 If the imported patch was generated by :hg:`export`, user and
3036 description from patch override values from message headers and
3036 description from patch override values from message headers and
3037 body. Values given on command line with -m/--message and -u/--user
3037 body. Values given on command line with -m/--message and -u/--user
3038 override these.
3038 override these.
3039
3039
3040 If --exact is specified, import will set the working directory to
3040 If --exact is specified, import will set the working directory to
3041 the parent of each patch before applying it, and will abort if the
3041 the parent of each patch before applying it, and will abort if the
3042 resulting changeset has a different ID than the one recorded in
3042 resulting changeset has a different ID than the one recorded in
3043 the patch. This may happen due to character set problems or other
3043 the patch. This may happen due to character set problems or other
3044 deficiencies in the text patch format.
3044 deficiencies in the text patch format.
3045
3045
3046 Use --bypass to apply and commit patches directly to the
3046 Use --bypass to apply and commit patches directly to the
3047 repository, not touching the working directory. Without --exact,
3047 repository, not touching the working directory. Without --exact,
3048 patches will be applied on top of the working directory parent
3048 patches will be applied on top of the working directory parent
3049 revision.
3049 revision.
3050
3050
3051 With -s/--similarity, hg will attempt to discover renames and
3051 With -s/--similarity, hg will attempt to discover renames and
3052 copies in the patch in the same way as 'addremove'.
3052 copies in the patch in the same way as 'addremove'.
3053
3053
3054 To read a patch from standard input, use "-" as the patch name. If
3054 To read a patch from standard input, use "-" as the patch name. If
3055 a URL is specified, the patch will be downloaded from it.
3055 a URL is specified, the patch will be downloaded from it.
3056 See :hg:`help dates` for a list of formats valid for -d/--date.
3056 See :hg:`help dates` for a list of formats valid for -d/--date.
3057
3057
3058 Returns 0 on success.
3058 Returns 0 on success.
3059 """
3059 """
3060 patches = (patch1,) + patches
3060 patches = (patch1,) + patches
3061
3061
3062 date = opts.get('date')
3062 date = opts.get('date')
3063 if date:
3063 if date:
3064 opts['date'] = util.parsedate(date)
3064 opts['date'] = util.parsedate(date)
3065
3065
3066 update = not opts.get('bypass')
3066 update = not opts.get('bypass')
3067 if not update and opts.get('no_commit'):
3067 if not update and opts.get('no_commit'):
3068 raise util.Abort(_('cannot use --no-commit with --bypass'))
3068 raise util.Abort(_('cannot use --no-commit with --bypass'))
3069 try:
3069 try:
3070 sim = float(opts.get('similarity') or 0)
3070 sim = float(opts.get('similarity') or 0)
3071 except ValueError:
3071 except ValueError:
3072 raise util.Abort(_('similarity must be a number'))
3072 raise util.Abort(_('similarity must be a number'))
3073 if sim < 0 or sim > 100:
3073 if sim < 0 or sim > 100:
3074 raise util.Abort(_('similarity must be between 0 and 100'))
3074 raise util.Abort(_('similarity must be between 0 and 100'))
3075 if sim and not update:
3075 if sim and not update:
3076 raise util.Abort(_('cannot use --similarity with --bypass'))
3076 raise util.Abort(_('cannot use --similarity with --bypass'))
3077
3077
3078 if (opts.get('exact') or not opts.get('force')) and update:
3078 if (opts.get('exact') or not opts.get('force')) and update:
3079 cmdutil.bailifchanged(repo)
3079 cmdutil.bailifchanged(repo)
3080
3080
3081 d = opts["base"]
3081 d = opts["base"]
3082 strip = opts["strip"]
3082 strip = opts["strip"]
3083 wlock = lock = None
3083 wlock = lock = None
3084 msgs = []
3084 msgs = []
3085
3085
3086 def checkexact(repo, n, nodeid):
3086 def checkexact(repo, n, nodeid):
3087 if opts.get('exact') and hex(n) != nodeid:
3087 if opts.get('exact') and hex(n) != nodeid:
3088 repo.rollback()
3088 repo.rollback()
3089 raise util.Abort(_('patch is damaged or loses information'))
3089 raise util.Abort(_('patch is damaged or loses information'))
3090
3090
3091 def tryone(ui, hunk, parents):
3091 def tryone(ui, hunk, parents):
3092 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3092 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3093 patch.extract(ui, hunk)
3093 patch.extract(ui, hunk)
3094
3094
3095 if not tmpname:
3095 if not tmpname:
3096 return None
3096 return None
3097 commitid = _('to working directory')
3097 commitid = _('to working directory')
3098
3098
3099 try:
3099 try:
3100 cmdline_message = cmdutil.logmessage(ui, opts)
3100 cmdline_message = cmdutil.logmessage(ui, opts)
3101 if cmdline_message:
3101 if cmdline_message:
3102 # pickup the cmdline msg
3102 # pickup the cmdline msg
3103 message = cmdline_message
3103 message = cmdline_message
3104 elif message:
3104 elif message:
3105 # pickup the patch msg
3105 # pickup the patch msg
3106 message = message.strip()
3106 message = message.strip()
3107 else:
3107 else:
3108 # launch the editor
3108 # launch the editor
3109 message = None
3109 message = None
3110 ui.debug('message:\n%s\n' % message)
3110 ui.debug('message:\n%s\n' % message)
3111
3111
3112 if len(parents) == 1:
3112 if len(parents) == 1:
3113 parents.append(repo[nullid])
3113 parents.append(repo[nullid])
3114 if opts.get('exact'):
3114 if opts.get('exact'):
3115 if not nodeid or not p1:
3115 if not nodeid or not p1:
3116 raise util.Abort(_('not a Mercurial patch'))
3116 raise util.Abort(_('not a Mercurial patch'))
3117 p1 = repo[p1]
3117 p1 = repo[p1]
3118 p2 = repo[p2 or nullid]
3118 p2 = repo[p2 or nullid]
3119 elif p2:
3119 elif p2:
3120 try:
3120 try:
3121 p1 = repo[p1]
3121 p1 = repo[p1]
3122 p2 = repo[p2]
3122 p2 = repo[p2]
3123 except error.RepoError:
3123 except error.RepoError:
3124 p1, p2 = parents
3124 p1, p2 = parents
3125 else:
3125 else:
3126 p1, p2 = parents
3126 p1, p2 = parents
3127
3127
3128 n = None
3128 n = None
3129 if update:
3129 if update:
3130 if opts.get('exact') and p1 != parents[0]:
3130 if opts.get('exact') and p1 != parents[0]:
3131 hg.clean(repo, p1.node())
3131 hg.clean(repo, p1.node())
3132 if p1 != parents[0] and p2 != parents[1]:
3132 if p1 != parents[0] and p2 != parents[1]:
3133 repo.dirstate.setparents(p1.node(), p2.node())
3133 repo.dirstate.setparents(p1.node(), p2.node())
3134
3134
3135 if opts.get('exact') or opts.get('import_branch'):
3135 if opts.get('exact') or opts.get('import_branch'):
3136 repo.dirstate.setbranch(branch or 'default')
3136 repo.dirstate.setbranch(branch or 'default')
3137
3137
3138 files = set()
3138 files = set()
3139 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3139 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3140 eolmode=None, similarity=sim / 100.0)
3140 eolmode=None, similarity=sim / 100.0)
3141 files = list(files)
3141 files = list(files)
3142 if opts.get('no_commit'):
3142 if opts.get('no_commit'):
3143 if message:
3143 if message:
3144 msgs.append(message)
3144 msgs.append(message)
3145 else:
3145 else:
3146 if opts.get('exact'):
3146 if opts.get('exact'):
3147 m = None
3147 m = None
3148 else:
3148 else:
3149 m = scmutil.matchfiles(repo, files or [])
3149 m = scmutil.matchfiles(repo, files or [])
3150 n = repo.commit(message, opts.get('user') or user,
3150 n = repo.commit(message, opts.get('user') or user,
3151 opts.get('date') or date, match=m,
3151 opts.get('date') or date, match=m,
3152 editor=cmdutil.commiteditor)
3152 editor=cmdutil.commiteditor)
3153 checkexact(repo, n, nodeid)
3153 checkexact(repo, n, nodeid)
3154 # Force a dirstate write so that the next transaction
3154 # Force a dirstate write so that the next transaction
3155 # backups an up-to-date file.
3155 # backups an up-to-date file.
3156 repo.dirstate.write()
3156 repo.dirstate.write()
3157 else:
3157 else:
3158 if opts.get('exact') or opts.get('import_branch'):
3158 if opts.get('exact') or opts.get('import_branch'):
3159 branch = branch or 'default'
3159 branch = branch or 'default'
3160 else:
3160 else:
3161 branch = p1.branch()
3161 branch = p1.branch()
3162 store = patch.filestore()
3162 store = patch.filestore()
3163 try:
3163 try:
3164 files = set()
3164 files = set()
3165 try:
3165 try:
3166 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3166 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3167 files, eolmode=None)
3167 files, eolmode=None)
3168 except patch.PatchError, e:
3168 except patch.PatchError, e:
3169 raise util.Abort(str(e))
3169 raise util.Abort(str(e))
3170 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3170 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3171 message,
3171 message,
3172 opts.get('user') or user,
3172 opts.get('user') or user,
3173 opts.get('date') or date,
3173 opts.get('date') or date,
3174 branch, files, store,
3174 branch, files, store,
3175 editor=cmdutil.commiteditor)
3175 editor=cmdutil.commiteditor)
3176 repo.savecommitmessage(memctx.description())
3176 repo.savecommitmessage(memctx.description())
3177 n = memctx.commit()
3177 n = memctx.commit()
3178 checkexact(repo, n, nodeid)
3178 checkexact(repo, n, nodeid)
3179 finally:
3179 finally:
3180 store.close()
3180 store.close()
3181 if n:
3181 if n:
3182 commitid = short(n)
3182 commitid = short(n)
3183 return commitid
3183 return commitid
3184 finally:
3184 finally:
3185 os.unlink(tmpname)
3185 os.unlink(tmpname)
3186
3186
3187 try:
3187 try:
3188 wlock = repo.wlock()
3188 wlock = repo.wlock()
3189 lock = repo.lock()
3189 lock = repo.lock()
3190 parents = repo.parents()
3190 parents = repo.parents()
3191 lastcommit = None
3191 lastcommit = None
3192 for p in patches:
3192 for p in patches:
3193 pf = os.path.join(d, p)
3193 pf = os.path.join(d, p)
3194
3194
3195 if pf == '-':
3195 if pf == '-':
3196 ui.status(_("applying patch from stdin\n"))
3196 ui.status(_("applying patch from stdin\n"))
3197 pf = ui.fin
3197 pf = ui.fin
3198 else:
3198 else:
3199 ui.status(_("applying %s\n") % p)
3199 ui.status(_("applying %s\n") % p)
3200 pf = url.open(ui, pf)
3200 pf = url.open(ui, pf)
3201
3201
3202 haspatch = False
3202 haspatch = False
3203 for hunk in patch.split(pf):
3203 for hunk in patch.split(pf):
3204 commitid = tryone(ui, hunk, parents)
3204 commitid = tryone(ui, hunk, parents)
3205 if commitid:
3205 if commitid:
3206 haspatch = True
3206 haspatch = True
3207 if lastcommit:
3207 if lastcommit:
3208 ui.status(_('applied %s\n') % lastcommit)
3208 ui.status(_('applied %s\n') % lastcommit)
3209 lastcommit = commitid
3209 lastcommit = commitid
3210 if update or opts.get('exact'):
3210 if update or opts.get('exact'):
3211 parents = repo.parents()
3211 parents = repo.parents()
3212 else:
3212 else:
3213 parents = [repo[commitid]]
3213 parents = [repo[commitid]]
3214
3214
3215 if not haspatch:
3215 if not haspatch:
3216 raise util.Abort(_('no diffs found'))
3216 raise util.Abort(_('no diffs found'))
3217
3217
3218 if msgs:
3218 if msgs:
3219 repo.savecommitmessage('\n* * *\n'.join(msgs))
3219 repo.savecommitmessage('\n* * *\n'.join(msgs))
3220 finally:
3220 finally:
3221 release(lock, wlock)
3221 release(lock, wlock)
3222
3222
3223 @command('incoming|in',
3223 @command('incoming|in',
3224 [('f', 'force', None,
3224 [('f', 'force', None,
3225 _('run even if remote repository is unrelated')),
3225 _('run even if remote repository is unrelated')),
3226 ('n', 'newest-first', None, _('show newest record first')),
3226 ('n', 'newest-first', None, _('show newest record first')),
3227 ('', 'bundle', '',
3227 ('', 'bundle', '',
3228 _('file to store the bundles into'), _('FILE')),
3228 _('file to store the bundles into'), _('FILE')),
3229 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3229 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3230 ('B', 'bookmarks', False, _("compare bookmarks")),
3230 ('B', 'bookmarks', False, _("compare bookmarks")),
3231 ('b', 'branch', [],
3231 ('b', 'branch', [],
3232 _('a specific branch you would like to pull'), _('BRANCH')),
3232 _('a specific branch you would like to pull'), _('BRANCH')),
3233 ] + logopts + remoteopts + subrepoopts,
3233 ] + logopts + remoteopts + subrepoopts,
3234 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3234 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3235 def incoming(ui, repo, source="default", **opts):
3235 def incoming(ui, repo, source="default", **opts):
3236 """show new changesets found in source
3236 """show new changesets found in source
3237
3237
3238 Show new changesets found in the specified path/URL or the default
3238 Show new changesets found in the specified path/URL or the default
3239 pull location. These are the changesets that would have been pulled
3239 pull location. These are the changesets that would have been pulled
3240 if a pull at the time you issued this command.
3240 if a pull at the time you issued this command.
3241
3241
3242 For remote repository, using --bundle avoids downloading the
3242 For remote repository, using --bundle avoids downloading the
3243 changesets twice if the incoming is followed by a pull.
3243 changesets twice if the incoming is followed by a pull.
3244
3244
3245 See pull for valid source format details.
3245 See pull for valid source format details.
3246
3246
3247 Returns 0 if there are incoming changes, 1 otherwise.
3247 Returns 0 if there are incoming changes, 1 otherwise.
3248 """
3248 """
3249 if opts.get('bundle') and opts.get('subrepos'):
3249 if opts.get('bundle') and opts.get('subrepos'):
3250 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3250 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3251
3251
3252 if opts.get('bookmarks'):
3252 if opts.get('bookmarks'):
3253 source, branches = hg.parseurl(ui.expandpath(source),
3253 source, branches = hg.parseurl(ui.expandpath(source),
3254 opts.get('branch'))
3254 opts.get('branch'))
3255 other = hg.peer(repo, opts, source)
3255 other = hg.peer(repo, opts, source)
3256 if 'bookmarks' not in other.listkeys('namespaces'):
3256 if 'bookmarks' not in other.listkeys('namespaces'):
3257 ui.warn(_("remote doesn't support bookmarks\n"))
3257 ui.warn(_("remote doesn't support bookmarks\n"))
3258 return 0
3258 return 0
3259 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3259 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3260 return bookmarks.diff(ui, repo, other)
3260 return bookmarks.diff(ui, repo, other)
3261
3261
3262 repo._subtoppath = ui.expandpath(source)
3262 repo._subtoppath = ui.expandpath(source)
3263 try:
3263 try:
3264 return hg.incoming(ui, repo, source, opts)
3264 return hg.incoming(ui, repo, source, opts)
3265 finally:
3265 finally:
3266 del repo._subtoppath
3266 del repo._subtoppath
3267
3267
3268
3268
3269 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3269 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3270 def init(ui, dest=".", **opts):
3270 def init(ui, dest=".", **opts):
3271 """create a new repository in the given directory
3271 """create a new repository in the given directory
3272
3272
3273 Initialize a new repository in the given directory. If the given
3273 Initialize a new repository in the given directory. If the given
3274 directory does not exist, it will be created.
3274 directory does not exist, it will be created.
3275
3275
3276 If no directory is given, the current directory is used.
3276 If no directory is given, the current directory is used.
3277
3277
3278 It is possible to specify an ``ssh://`` URL as the destination.
3278 It is possible to specify an ``ssh://`` URL as the destination.
3279 See :hg:`help urls` for more information.
3279 See :hg:`help urls` for more information.
3280
3280
3281 Returns 0 on success.
3281 Returns 0 on success.
3282 """
3282 """
3283 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3283 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3284
3284
3285 @command('locate',
3285 @command('locate',
3286 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3286 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3287 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3287 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3288 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3288 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3289 ] + walkopts,
3289 ] + walkopts,
3290 _('[OPTION]... [PATTERN]...'))
3290 _('[OPTION]... [PATTERN]...'))
3291 def locate(ui, repo, *pats, **opts):
3291 def locate(ui, repo, *pats, **opts):
3292 """locate files matching specific patterns
3292 """locate files matching specific patterns
3293
3293
3294 Print files under Mercurial control in the working directory whose
3294 Print files under Mercurial control in the working directory whose
3295 names match the given patterns.
3295 names match the given patterns.
3296
3296
3297 By default, this command searches all directories in the working
3297 By default, this command searches all directories in the working
3298 directory. To search just the current directory and its
3298 directory. To search just the current directory and its
3299 subdirectories, use "--include .".
3299 subdirectories, use "--include .".
3300
3300
3301 If no patterns are given to match, this command prints the names
3301 If no patterns are given to match, this command prints the names
3302 of all files under Mercurial control in the working directory.
3302 of all files under Mercurial control in the working directory.
3303
3303
3304 If you want to feed the output of this command into the "xargs"
3304 If you want to feed the output of this command into the "xargs"
3305 command, use the -0 option to both this command and "xargs". This
3305 command, use the -0 option to both this command and "xargs". This
3306 will avoid the problem of "xargs" treating single filenames that
3306 will avoid the problem of "xargs" treating single filenames that
3307 contain whitespace as multiple filenames.
3307 contain whitespace as multiple filenames.
3308
3308
3309 Returns 0 if a match is found, 1 otherwise.
3309 Returns 0 if a match is found, 1 otherwise.
3310 """
3310 """
3311 end = opts.get('print0') and '\0' or '\n'
3311 end = opts.get('print0') and '\0' or '\n'
3312 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3312 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3313
3313
3314 ret = 1
3314 ret = 1
3315 m = scmutil.match(repo, pats, opts, default='relglob')
3315 m = scmutil.match(repo, pats, opts, default='relglob')
3316 m.bad = lambda x, y: False
3316 m.bad = lambda x, y: False
3317 for abs in repo[rev].walk(m):
3317 for abs in repo[rev].walk(m):
3318 if not rev and abs not in repo.dirstate:
3318 if not rev and abs not in repo.dirstate:
3319 continue
3319 continue
3320 if opts.get('fullpath'):
3320 if opts.get('fullpath'):
3321 ui.write(repo.wjoin(abs), end)
3321 ui.write(repo.wjoin(abs), end)
3322 else:
3322 else:
3323 ui.write(((pats and m.rel(abs)) or abs), end)
3323 ui.write(((pats and m.rel(abs)) or abs), end)
3324 ret = 0
3324 ret = 0
3325
3325
3326 return ret
3326 return ret
3327
3327
3328 @command('^log|history',
3328 @command('^log|history',
3329 [('f', 'follow', None,
3329 [('f', 'follow', None,
3330 _('follow changeset history, or file history across copies and renames')),
3330 _('follow changeset history, or file history across copies and renames')),
3331 ('', 'follow-first', None,
3331 ('', 'follow-first', None,
3332 _('only follow the first parent of merge changesets')),
3332 _('only follow the first parent of merge changesets')),
3333 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3333 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3334 ('C', 'copies', None, _('show copied files')),
3334 ('C', 'copies', None, _('show copied files')),
3335 ('k', 'keyword', [],
3335 ('k', 'keyword', [],
3336 _('do case-insensitive search for a given text'), _('TEXT')),
3336 _('do case-insensitive search for a given text'), _('TEXT')),
3337 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3337 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3338 ('', 'removed', None, _('include revisions where files were removed')),
3338 ('', 'removed', None, _('include revisions where files were removed')),
3339 ('m', 'only-merges', None, _('show only merges')),
3339 ('m', 'only-merges', None, _('show only merges')),
3340 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3340 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3341 ('', 'only-branch', [],
3341 ('', 'only-branch', [],
3342 _('show only changesets within the given named branch (DEPRECATED)'),
3342 _('show only changesets within the given named branch (DEPRECATED)'),
3343 _('BRANCH')),
3343 _('BRANCH')),
3344 ('b', 'branch', [],
3344 ('b', 'branch', [],
3345 _('show changesets within the given named branch'), _('BRANCH')),
3345 _('show changesets within the given named branch'), _('BRANCH')),
3346 ('P', 'prune', [],
3346 ('P', 'prune', [],
3347 _('do not display revision or any of its ancestors'), _('REV')),
3347 _('do not display revision or any of its ancestors'), _('REV')),
3348 ('h', 'hidden', False, _('show hidden changesets')),
3348 ] + logopts + walkopts,
3349 ] + logopts + walkopts,
3349 _('[OPTION]... [FILE]'))
3350 _('[OPTION]... [FILE]'))
3350 def log(ui, repo, *pats, **opts):
3351 def log(ui, repo, *pats, **opts):
3351 """show revision history of entire repository or files
3352 """show revision history of entire repository or files
3352
3353
3353 Print the revision history of the specified files or the entire
3354 Print the revision history of the specified files or the entire
3354 project.
3355 project.
3355
3356
3356 File history is shown without following rename or copy history of
3357 File history is shown without following rename or copy history of
3357 files. Use -f/--follow with a filename to follow history across
3358 files. Use -f/--follow with a filename to follow history across
3358 renames and copies. --follow without a filename will only show
3359 renames and copies. --follow without a filename will only show
3359 ancestors or descendants of the starting revision. --follow-first
3360 ancestors or descendants of the starting revision. --follow-first
3360 only follows the first parent of merge revisions.
3361 only follows the first parent of merge revisions.
3361
3362
3362 If no revision range is specified, the default is ``tip:0`` unless
3363 If no revision range is specified, the default is ``tip:0`` unless
3363 --follow is set, in which case the working directory parent is
3364 --follow is set, in which case the working directory parent is
3364 used as the starting revision. You can specify a revision set for
3365 used as the starting revision. You can specify a revision set for
3365 log, see :hg:`help revsets` for more information.
3366 log, see :hg:`help revsets` for more information.
3366
3367
3367 See :hg:`help dates` for a list of formats valid for -d/--date.
3368 See :hg:`help dates` for a list of formats valid for -d/--date.
3368
3369
3369 By default this command prints revision number and changeset id,
3370 By default this command prints revision number and changeset id,
3370 tags, non-trivial parents, user, date and time, and a summary for
3371 tags, non-trivial parents, user, date and time, and a summary for
3371 each commit. When the -v/--verbose switch is used, the list of
3372 each commit. When the -v/--verbose switch is used, the list of
3372 changed files and full commit message are shown.
3373 changed files and full commit message are shown.
3373
3374
3374 .. note::
3375 .. note::
3375 log -p/--patch may generate unexpected diff output for merge
3376 log -p/--patch may generate unexpected diff output for merge
3376 changesets, as it will only compare the merge changeset against
3377 changesets, as it will only compare the merge changeset against
3377 its first parent. Also, only files different from BOTH parents
3378 its first parent. Also, only files different from BOTH parents
3378 will appear in files:.
3379 will appear in files:.
3379
3380
3380 Returns 0 on success.
3381 Returns 0 on success.
3381 """
3382 """
3382
3383
3383 matchfn = scmutil.match(repo, pats, opts)
3384 matchfn = scmutil.match(repo, pats, opts)
3384 limit = cmdutil.loglimit(opts)
3385 limit = cmdutil.loglimit(opts)
3385 count = 0
3386 count = 0
3386
3387
3387 endrev = None
3388 endrev = None
3388 if opts.get('copies') and opts.get('rev'):
3389 if opts.get('copies') and opts.get('rev'):
3389 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3390 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3390
3391
3391 df = False
3392 df = False
3392 if opts["date"]:
3393 if opts["date"]:
3393 df = util.matchdate(opts["date"])
3394 df = util.matchdate(opts["date"])
3394
3395
3395 branches = opts.get('branch', []) + opts.get('only_branch', [])
3396 branches = opts.get('branch', []) + opts.get('only_branch', [])
3396 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3397 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3397
3398
3398 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3399 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3399 def prep(ctx, fns):
3400 def prep(ctx, fns):
3400 rev = ctx.rev()
3401 rev = ctx.rev()
3401 parents = [p for p in repo.changelog.parentrevs(rev)
3402 parents = [p for p in repo.changelog.parentrevs(rev)
3402 if p != nullrev]
3403 if p != nullrev]
3403 if opts.get('no_merges') and len(parents) == 2:
3404 if opts.get('no_merges') and len(parents) == 2:
3404 return
3405 return
3405 if opts.get('only_merges') and len(parents) != 2:
3406 if opts.get('only_merges') and len(parents) != 2:
3406 return
3407 return
3407 if opts.get('branch') and ctx.branch() not in opts['branch']:
3408 if opts.get('branch') and ctx.branch() not in opts['branch']:
3408 return
3409 return
3410 if not opts.get('hidden') and ctx.hidden():
3411 return
3409 if df and not df(ctx.date()[0]):
3412 if df and not df(ctx.date()[0]):
3410 return
3413 return
3411 if opts['user'] and not [k for k in opts['user']
3414 if opts['user'] and not [k for k in opts['user']
3412 if k.lower() in ctx.user().lower()]:
3415 if k.lower() in ctx.user().lower()]:
3413 return
3416 return
3414 if opts.get('keyword'):
3417 if opts.get('keyword'):
3415 for k in [kw.lower() for kw in opts['keyword']]:
3418 for k in [kw.lower() for kw in opts['keyword']]:
3416 if (k in ctx.user().lower() or
3419 if (k in ctx.user().lower() or
3417 k in ctx.description().lower() or
3420 k in ctx.description().lower() or
3418 k in " ".join(ctx.files()).lower()):
3421 k in " ".join(ctx.files()).lower()):
3419 break
3422 break
3420 else:
3423 else:
3421 return
3424 return
3422
3425
3423 copies = None
3426 copies = None
3424 if opts.get('copies') and rev:
3427 if opts.get('copies') and rev:
3425 copies = []
3428 copies = []
3426 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3429 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3427 for fn in ctx.files():
3430 for fn in ctx.files():
3428 rename = getrenamed(fn, rev)
3431 rename = getrenamed(fn, rev)
3429 if rename:
3432 if rename:
3430 copies.append((fn, rename[0]))
3433 copies.append((fn, rename[0]))
3431
3434
3432 revmatchfn = None
3435 revmatchfn = None
3433 if opts.get('patch') or opts.get('stat'):
3436 if opts.get('patch') or opts.get('stat'):
3434 if opts.get('follow') or opts.get('follow_first'):
3437 if opts.get('follow') or opts.get('follow_first'):
3435 # note: this might be wrong when following through merges
3438 # note: this might be wrong when following through merges
3436 revmatchfn = scmutil.match(repo, fns, default='path')
3439 revmatchfn = scmutil.match(repo, fns, default='path')
3437 else:
3440 else:
3438 revmatchfn = matchfn
3441 revmatchfn = matchfn
3439
3442
3440 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3443 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3441
3444
3442 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3445 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3443 if count == limit:
3446 if count == limit:
3444 break
3447 break
3445 if displayer.flush(ctx.rev()):
3448 if displayer.flush(ctx.rev()):
3446 count += 1
3449 count += 1
3447 displayer.close()
3450 displayer.close()
3448
3451
3449 @command('manifest',
3452 @command('manifest',
3450 [('r', 'rev', '', _('revision to display'), _('REV')),
3453 [('r', 'rev', '', _('revision to display'), _('REV')),
3451 ('', 'all', False, _("list files from all revisions"))],
3454 ('', 'all', False, _("list files from all revisions"))],
3452 _('[-r REV]'))
3455 _('[-r REV]'))
3453 def manifest(ui, repo, node=None, rev=None, **opts):
3456 def manifest(ui, repo, node=None, rev=None, **opts):
3454 """output the current or given revision of the project manifest
3457 """output the current or given revision of the project manifest
3455
3458
3456 Print a list of version controlled files for the given revision.
3459 Print a list of version controlled files for the given revision.
3457 If no revision is given, the first parent of the working directory
3460 If no revision is given, the first parent of the working directory
3458 is used, or the null revision if no revision is checked out.
3461 is used, or the null revision if no revision is checked out.
3459
3462
3460 With -v, print file permissions, symlink and executable bits.
3463 With -v, print file permissions, symlink and executable bits.
3461 With --debug, print file revision hashes.
3464 With --debug, print file revision hashes.
3462
3465
3463 If option --all is specified, the list of all files from all revisions
3466 If option --all is specified, the list of all files from all revisions
3464 is printed. This includes deleted and renamed files.
3467 is printed. This includes deleted and renamed files.
3465
3468
3466 Returns 0 on success.
3469 Returns 0 on success.
3467 """
3470 """
3468 if opts.get('all'):
3471 if opts.get('all'):
3469 if rev or node:
3472 if rev or node:
3470 raise util.Abort(_("can't specify a revision with --all"))
3473 raise util.Abort(_("can't specify a revision with --all"))
3471
3474
3472 res = []
3475 res = []
3473 prefix = "data/"
3476 prefix = "data/"
3474 suffix = ".i"
3477 suffix = ".i"
3475 plen = len(prefix)
3478 plen = len(prefix)
3476 slen = len(suffix)
3479 slen = len(suffix)
3477 lock = repo.lock()
3480 lock = repo.lock()
3478 try:
3481 try:
3479 for fn, b, size in repo.store.datafiles():
3482 for fn, b, size in repo.store.datafiles():
3480 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3483 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3481 res.append(fn[plen:-slen])
3484 res.append(fn[plen:-slen])
3482 finally:
3485 finally:
3483 lock.release()
3486 lock.release()
3484 for f in sorted(res):
3487 for f in sorted(res):
3485 ui.write("%s\n" % f)
3488 ui.write("%s\n" % f)
3486 return
3489 return
3487
3490
3488 if rev and node:
3491 if rev and node:
3489 raise util.Abort(_("please specify just one revision"))
3492 raise util.Abort(_("please specify just one revision"))
3490
3493
3491 if not node:
3494 if not node:
3492 node = rev
3495 node = rev
3493
3496
3494 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3497 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3495 ctx = scmutil.revsingle(repo, node)
3498 ctx = scmutil.revsingle(repo, node)
3496 for f in ctx:
3499 for f in ctx:
3497 if ui.debugflag:
3500 if ui.debugflag:
3498 ui.write("%40s " % hex(ctx.manifest()[f]))
3501 ui.write("%40s " % hex(ctx.manifest()[f]))
3499 if ui.verbose:
3502 if ui.verbose:
3500 ui.write(decor[ctx.flags(f)])
3503 ui.write(decor[ctx.flags(f)])
3501 ui.write("%s\n" % f)
3504 ui.write("%s\n" % f)
3502
3505
3503 @command('^merge',
3506 @command('^merge',
3504 [('f', 'force', None, _('force a merge with outstanding changes')),
3507 [('f', 'force', None, _('force a merge with outstanding changes')),
3505 ('t', 'tool', '', _('specify merge tool')),
3508 ('t', 'tool', '', _('specify merge tool')),
3506 ('r', 'rev', '', _('revision to merge'), _('REV')),
3509 ('r', 'rev', '', _('revision to merge'), _('REV')),
3507 ('P', 'preview', None,
3510 ('P', 'preview', None,
3508 _('review revisions to merge (no merge is performed)'))],
3511 _('review revisions to merge (no merge is performed)'))],
3509 _('[-P] [-f] [[-r] REV]'))
3512 _('[-P] [-f] [[-r] REV]'))
3510 def merge(ui, repo, node=None, **opts):
3513 def merge(ui, repo, node=None, **opts):
3511 """merge working directory with another revision
3514 """merge working directory with another revision
3512
3515
3513 The current working directory is updated with all changes made in
3516 The current working directory is updated with all changes made in
3514 the requested revision since the last common predecessor revision.
3517 the requested revision since the last common predecessor revision.
3515
3518
3516 Files that changed between either parent are marked as changed for
3519 Files that changed between either parent are marked as changed for
3517 the next commit and a commit must be performed before any further
3520 the next commit and a commit must be performed before any further
3518 updates to the repository are allowed. The next commit will have
3521 updates to the repository are allowed. The next commit will have
3519 two parents.
3522 two parents.
3520
3523
3521 ``--tool`` can be used to specify the merge tool used for file
3524 ``--tool`` can be used to specify the merge tool used for file
3522 merges. It overrides the HGMERGE environment variable and your
3525 merges. It overrides the HGMERGE environment variable and your
3523 configuration files. See :hg:`help merge-tools` for options.
3526 configuration files. See :hg:`help merge-tools` for options.
3524
3527
3525 If no revision is specified, the working directory's parent is a
3528 If no revision is specified, the working directory's parent is a
3526 head revision, and the current branch contains exactly one other
3529 head revision, and the current branch contains exactly one other
3527 head, the other head is merged with by default. Otherwise, an
3530 head, the other head is merged with by default. Otherwise, an
3528 explicit revision with which to merge with must be provided.
3531 explicit revision with which to merge with must be provided.
3529
3532
3530 :hg:`resolve` must be used to resolve unresolved files.
3533 :hg:`resolve` must be used to resolve unresolved files.
3531
3534
3532 To undo an uncommitted merge, use :hg:`update --clean .` which
3535 To undo an uncommitted merge, use :hg:`update --clean .` which
3533 will check out a clean copy of the original merge parent, losing
3536 will check out a clean copy of the original merge parent, losing
3534 all changes.
3537 all changes.
3535
3538
3536 Returns 0 on success, 1 if there are unresolved files.
3539 Returns 0 on success, 1 if there are unresolved files.
3537 """
3540 """
3538
3541
3539 if opts.get('rev') and node:
3542 if opts.get('rev') and node:
3540 raise util.Abort(_("please specify just one revision"))
3543 raise util.Abort(_("please specify just one revision"))
3541 if not node:
3544 if not node:
3542 node = opts.get('rev')
3545 node = opts.get('rev')
3543
3546
3544 if not node:
3547 if not node:
3545 branch = repo[None].branch()
3548 branch = repo[None].branch()
3546 bheads = repo.branchheads(branch)
3549 bheads = repo.branchheads(branch)
3547 if len(bheads) > 2:
3550 if len(bheads) > 2:
3548 raise util.Abort(_("branch '%s' has %d heads - "
3551 raise util.Abort(_("branch '%s' has %d heads - "
3549 "please merge with an explicit rev")
3552 "please merge with an explicit rev")
3550 % (branch, len(bheads)),
3553 % (branch, len(bheads)),
3551 hint=_("run 'hg heads .' to see heads"))
3554 hint=_("run 'hg heads .' to see heads"))
3552
3555
3553 parent = repo.dirstate.p1()
3556 parent = repo.dirstate.p1()
3554 if len(bheads) == 1:
3557 if len(bheads) == 1:
3555 if len(repo.heads()) > 1:
3558 if len(repo.heads()) > 1:
3556 raise util.Abort(_("branch '%s' has one head - "
3559 raise util.Abort(_("branch '%s' has one head - "
3557 "please merge with an explicit rev")
3560 "please merge with an explicit rev")
3558 % branch,
3561 % branch,
3559 hint=_("run 'hg heads' to see all heads"))
3562 hint=_("run 'hg heads' to see all heads"))
3560 msg = _('there is nothing to merge')
3563 msg = _('there is nothing to merge')
3561 if parent != repo.lookup(repo[None].branch()):
3564 if parent != repo.lookup(repo[None].branch()):
3562 msg = _('%s - use "hg update" instead') % msg
3565 msg = _('%s - use "hg update" instead') % msg
3563 raise util.Abort(msg)
3566 raise util.Abort(msg)
3564
3567
3565 if parent not in bheads:
3568 if parent not in bheads:
3566 raise util.Abort(_('working directory not at a head revision'),
3569 raise util.Abort(_('working directory not at a head revision'),
3567 hint=_("use 'hg update' or merge with an "
3570 hint=_("use 'hg update' or merge with an "
3568 "explicit revision"))
3571 "explicit revision"))
3569 node = parent == bheads[0] and bheads[-1] or bheads[0]
3572 node = parent == bheads[0] and bheads[-1] or bheads[0]
3570 else:
3573 else:
3571 node = scmutil.revsingle(repo, node).node()
3574 node = scmutil.revsingle(repo, node).node()
3572
3575
3573 if opts.get('preview'):
3576 if opts.get('preview'):
3574 # find nodes that are ancestors of p2 but not of p1
3577 # find nodes that are ancestors of p2 but not of p1
3575 p1 = repo.lookup('.')
3578 p1 = repo.lookup('.')
3576 p2 = repo.lookup(node)
3579 p2 = repo.lookup(node)
3577 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3580 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3578
3581
3579 displayer = cmdutil.show_changeset(ui, repo, opts)
3582 displayer = cmdutil.show_changeset(ui, repo, opts)
3580 for node in nodes:
3583 for node in nodes:
3581 displayer.show(repo[node])
3584 displayer.show(repo[node])
3582 displayer.close()
3585 displayer.close()
3583 return 0
3586 return 0
3584
3587
3585 try:
3588 try:
3586 # ui.forcemerge is an internal variable, do not document
3589 # ui.forcemerge is an internal variable, do not document
3587 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3590 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3588 return hg.merge(repo, node, force=opts.get('force'))
3591 return hg.merge(repo, node, force=opts.get('force'))
3589 finally:
3592 finally:
3590 ui.setconfig('ui', 'forcemerge', '')
3593 ui.setconfig('ui', 'forcemerge', '')
3591
3594
3592 @command('outgoing|out',
3595 @command('outgoing|out',
3593 [('f', 'force', None, _('run even when the destination is unrelated')),
3596 [('f', 'force', None, _('run even when the destination is unrelated')),
3594 ('r', 'rev', [],
3597 ('r', 'rev', [],
3595 _('a changeset intended to be included in the destination'), _('REV')),
3598 _('a changeset intended to be included in the destination'), _('REV')),
3596 ('n', 'newest-first', None, _('show newest record first')),
3599 ('n', 'newest-first', None, _('show newest record first')),
3597 ('B', 'bookmarks', False, _('compare bookmarks')),
3600 ('B', 'bookmarks', False, _('compare bookmarks')),
3598 ('b', 'branch', [], _('a specific branch you would like to push'),
3601 ('b', 'branch', [], _('a specific branch you would like to push'),
3599 _('BRANCH')),
3602 _('BRANCH')),
3600 ] + logopts + remoteopts + subrepoopts,
3603 ] + logopts + remoteopts + subrepoopts,
3601 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3604 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3602 def outgoing(ui, repo, dest=None, **opts):
3605 def outgoing(ui, repo, dest=None, **opts):
3603 """show changesets not found in the destination
3606 """show changesets not found in the destination
3604
3607
3605 Show changesets not found in the specified destination repository
3608 Show changesets not found in the specified destination repository
3606 or the default push location. These are the changesets that would
3609 or the default push location. These are the changesets that would
3607 be pushed if a push was requested.
3610 be pushed if a push was requested.
3608
3611
3609 See pull for details of valid destination formats.
3612 See pull for details of valid destination formats.
3610
3613
3611 Returns 0 if there are outgoing changes, 1 otherwise.
3614 Returns 0 if there are outgoing changes, 1 otherwise.
3612 """
3615 """
3613
3616
3614 if opts.get('bookmarks'):
3617 if opts.get('bookmarks'):
3615 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3618 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3616 dest, branches = hg.parseurl(dest, opts.get('branch'))
3619 dest, branches = hg.parseurl(dest, opts.get('branch'))
3617 other = hg.peer(repo, opts, dest)
3620 other = hg.peer(repo, opts, dest)
3618 if 'bookmarks' not in other.listkeys('namespaces'):
3621 if 'bookmarks' not in other.listkeys('namespaces'):
3619 ui.warn(_("remote doesn't support bookmarks\n"))
3622 ui.warn(_("remote doesn't support bookmarks\n"))
3620 return 0
3623 return 0
3621 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3624 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3622 return bookmarks.diff(ui, other, repo)
3625 return bookmarks.diff(ui, other, repo)
3623
3626
3624 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3627 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3625 try:
3628 try:
3626 return hg.outgoing(ui, repo, dest, opts)
3629 return hg.outgoing(ui, repo, dest, opts)
3627 finally:
3630 finally:
3628 del repo._subtoppath
3631 del repo._subtoppath
3629
3632
3630 @command('parents',
3633 @command('parents',
3631 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3634 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3632 ] + templateopts,
3635 ] + templateopts,
3633 _('[-r REV] [FILE]'))
3636 _('[-r REV] [FILE]'))
3634 def parents(ui, repo, file_=None, **opts):
3637 def parents(ui, repo, file_=None, **opts):
3635 """show the parents of the working directory or revision
3638 """show the parents of the working directory or revision
3636
3639
3637 Print the working directory's parent revisions. If a revision is
3640 Print the working directory's parent revisions. If a revision is
3638 given via -r/--rev, the parent of that revision will be printed.
3641 given via -r/--rev, the parent of that revision will be printed.
3639 If a file argument is given, the revision in which the file was
3642 If a file argument is given, the revision in which the file was
3640 last changed (before the working directory revision or the
3643 last changed (before the working directory revision or the
3641 argument to --rev if given) is printed.
3644 argument to --rev if given) is printed.
3642
3645
3643 Returns 0 on success.
3646 Returns 0 on success.
3644 """
3647 """
3645
3648
3646 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3649 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3647
3650
3648 if file_:
3651 if file_:
3649 m = scmutil.match(repo, (file_,), opts)
3652 m = scmutil.match(repo, (file_,), opts)
3650 if m.anypats() or len(m.files()) != 1:
3653 if m.anypats() or len(m.files()) != 1:
3651 raise util.Abort(_('can only specify an explicit filename'))
3654 raise util.Abort(_('can only specify an explicit filename'))
3652 file_ = m.files()[0]
3655 file_ = m.files()[0]
3653 filenodes = []
3656 filenodes = []
3654 for cp in ctx.parents():
3657 for cp in ctx.parents():
3655 if not cp:
3658 if not cp:
3656 continue
3659 continue
3657 try:
3660 try:
3658 filenodes.append(cp.filenode(file_))
3661 filenodes.append(cp.filenode(file_))
3659 except error.LookupError:
3662 except error.LookupError:
3660 pass
3663 pass
3661 if not filenodes:
3664 if not filenodes:
3662 raise util.Abort(_("'%s' not found in manifest!") % file_)
3665 raise util.Abort(_("'%s' not found in manifest!") % file_)
3663 fl = repo.file(file_)
3666 fl = repo.file(file_)
3664 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3667 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3665 else:
3668 else:
3666 p = [cp.node() for cp in ctx.parents()]
3669 p = [cp.node() for cp in ctx.parents()]
3667
3670
3668 displayer = cmdutil.show_changeset(ui, repo, opts)
3671 displayer = cmdutil.show_changeset(ui, repo, opts)
3669 for n in p:
3672 for n in p:
3670 if n != nullid:
3673 if n != nullid:
3671 displayer.show(repo[n])
3674 displayer.show(repo[n])
3672 displayer.close()
3675 displayer.close()
3673
3676
3674 @command('paths', [], _('[NAME]'))
3677 @command('paths', [], _('[NAME]'))
3675 def paths(ui, repo, search=None):
3678 def paths(ui, repo, search=None):
3676 """show aliases for remote repositories
3679 """show aliases for remote repositories
3677
3680
3678 Show definition of symbolic path name NAME. If no name is given,
3681 Show definition of symbolic path name NAME. If no name is given,
3679 show definition of all available names.
3682 show definition of all available names.
3680
3683
3681 Option -q/--quiet suppresses all output when searching for NAME
3684 Option -q/--quiet suppresses all output when searching for NAME
3682 and shows only the path names when listing all definitions.
3685 and shows only the path names when listing all definitions.
3683
3686
3684 Path names are defined in the [paths] section of your
3687 Path names are defined in the [paths] section of your
3685 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3688 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3686 repository, ``.hg/hgrc`` is used, too.
3689 repository, ``.hg/hgrc`` is used, too.
3687
3690
3688 The path names ``default`` and ``default-push`` have a special
3691 The path names ``default`` and ``default-push`` have a special
3689 meaning. When performing a push or pull operation, they are used
3692 meaning. When performing a push or pull operation, they are used
3690 as fallbacks if no location is specified on the command-line.
3693 as fallbacks if no location is specified on the command-line.
3691 When ``default-push`` is set, it will be used for push and
3694 When ``default-push`` is set, it will be used for push and
3692 ``default`` will be used for pull; otherwise ``default`` is used
3695 ``default`` will be used for pull; otherwise ``default`` is used
3693 as the fallback for both. When cloning a repository, the clone
3696 as the fallback for both. When cloning a repository, the clone
3694 source is written as ``default`` in ``.hg/hgrc``. Note that
3697 source is written as ``default`` in ``.hg/hgrc``. Note that
3695 ``default`` and ``default-push`` apply to all inbound (e.g.
3698 ``default`` and ``default-push`` apply to all inbound (e.g.
3696 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3699 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3697 :hg:`bundle`) operations.
3700 :hg:`bundle`) operations.
3698
3701
3699 See :hg:`help urls` for more information.
3702 See :hg:`help urls` for more information.
3700
3703
3701 Returns 0 on success.
3704 Returns 0 on success.
3702 """
3705 """
3703 if search:
3706 if search:
3704 for name, path in ui.configitems("paths"):
3707 for name, path in ui.configitems("paths"):
3705 if name == search:
3708 if name == search:
3706 ui.status("%s\n" % util.hidepassword(path))
3709 ui.status("%s\n" % util.hidepassword(path))
3707 return
3710 return
3708 if not ui.quiet:
3711 if not ui.quiet:
3709 ui.warn(_("not found!\n"))
3712 ui.warn(_("not found!\n"))
3710 return 1
3713 return 1
3711 else:
3714 else:
3712 for name, path in ui.configitems("paths"):
3715 for name, path in ui.configitems("paths"):
3713 if ui.quiet:
3716 if ui.quiet:
3714 ui.write("%s\n" % name)
3717 ui.write("%s\n" % name)
3715 else:
3718 else:
3716 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3719 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3717
3720
3718 def postincoming(ui, repo, modheads, optupdate, checkout):
3721 def postincoming(ui, repo, modheads, optupdate, checkout):
3719 if modheads == 0:
3722 if modheads == 0:
3720 return
3723 return
3721 if optupdate:
3724 if optupdate:
3722 try:
3725 try:
3723 return hg.update(repo, checkout)
3726 return hg.update(repo, checkout)
3724 except util.Abort, inst:
3727 except util.Abort, inst:
3725 ui.warn(_("not updating: %s\n" % str(inst)))
3728 ui.warn(_("not updating: %s\n" % str(inst)))
3726 return 0
3729 return 0
3727 if modheads > 1:
3730 if modheads > 1:
3728 currentbranchheads = len(repo.branchheads())
3731 currentbranchheads = len(repo.branchheads())
3729 if currentbranchheads == modheads:
3732 if currentbranchheads == modheads:
3730 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3733 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3731 elif currentbranchheads > 1:
3734 elif currentbranchheads > 1:
3732 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3735 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3733 else:
3736 else:
3734 ui.status(_("(run 'hg heads' to see heads)\n"))
3737 ui.status(_("(run 'hg heads' to see heads)\n"))
3735 else:
3738 else:
3736 ui.status(_("(run 'hg update' to get a working copy)\n"))
3739 ui.status(_("(run 'hg update' to get a working copy)\n"))
3737
3740
3738 @command('^pull',
3741 @command('^pull',
3739 [('u', 'update', None,
3742 [('u', 'update', None,
3740 _('update to new branch head if changesets were pulled')),
3743 _('update to new branch head if changesets were pulled')),
3741 ('f', 'force', None, _('run even when remote repository is unrelated')),
3744 ('f', 'force', None, _('run even when remote repository is unrelated')),
3742 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3745 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3743 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3746 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3744 ('b', 'branch', [], _('a specific branch you would like to pull'),
3747 ('b', 'branch', [], _('a specific branch you would like to pull'),
3745 _('BRANCH')),
3748 _('BRANCH')),
3746 ] + remoteopts,
3749 ] + remoteopts,
3747 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3750 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3748 def pull(ui, repo, source="default", **opts):
3751 def pull(ui, repo, source="default", **opts):
3749 """pull changes from the specified source
3752 """pull changes from the specified source
3750
3753
3751 Pull changes from a remote repository to a local one.
3754 Pull changes from a remote repository to a local one.
3752
3755
3753 This finds all changes from the repository at the specified path
3756 This finds all changes from the repository at the specified path
3754 or URL and adds them to a local repository (the current one unless
3757 or URL and adds them to a local repository (the current one unless
3755 -R is specified). By default, this does not update the copy of the
3758 -R is specified). By default, this does not update the copy of the
3756 project in the working directory.
3759 project in the working directory.
3757
3760
3758 Use :hg:`incoming` if you want to see what would have been added
3761 Use :hg:`incoming` if you want to see what would have been added
3759 by a pull at the time you issued this command. If you then decide
3762 by a pull at the time you issued this command. If you then decide
3760 to add those changes to the repository, you should use :hg:`pull
3763 to add those changes to the repository, you should use :hg:`pull
3761 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3764 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3762
3765
3763 If SOURCE is omitted, the 'default' path will be used.
3766 If SOURCE is omitted, the 'default' path will be used.
3764 See :hg:`help urls` for more information.
3767 See :hg:`help urls` for more information.
3765
3768
3766 Returns 0 on success, 1 if an update had unresolved files.
3769 Returns 0 on success, 1 if an update had unresolved files.
3767 """
3770 """
3768 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3771 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3769 other = hg.peer(repo, opts, source)
3772 other = hg.peer(repo, opts, source)
3770 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3773 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3771 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3774 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3772
3775
3773 if opts.get('bookmark'):
3776 if opts.get('bookmark'):
3774 if not revs:
3777 if not revs:
3775 revs = []
3778 revs = []
3776 rb = other.listkeys('bookmarks')
3779 rb = other.listkeys('bookmarks')
3777 for b in opts['bookmark']:
3780 for b in opts['bookmark']:
3778 if b not in rb:
3781 if b not in rb:
3779 raise util.Abort(_('remote bookmark %s not found!') % b)
3782 raise util.Abort(_('remote bookmark %s not found!') % b)
3780 revs.append(rb[b])
3783 revs.append(rb[b])
3781
3784
3782 if revs:
3785 if revs:
3783 try:
3786 try:
3784 revs = [other.lookup(rev) for rev in revs]
3787 revs = [other.lookup(rev) for rev in revs]
3785 except error.CapabilityError:
3788 except error.CapabilityError:
3786 err = _("other repository doesn't support revision lookup, "
3789 err = _("other repository doesn't support revision lookup, "
3787 "so a rev cannot be specified.")
3790 "so a rev cannot be specified.")
3788 raise util.Abort(err)
3791 raise util.Abort(err)
3789
3792
3790 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3793 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3791 bookmarks.updatefromremote(ui, repo, other)
3794 bookmarks.updatefromremote(ui, repo, other)
3792 if checkout:
3795 if checkout:
3793 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3796 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3794 repo._subtoppath = source
3797 repo._subtoppath = source
3795 try:
3798 try:
3796 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3799 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3797
3800
3798 finally:
3801 finally:
3799 del repo._subtoppath
3802 del repo._subtoppath
3800
3803
3801 # update specified bookmarks
3804 # update specified bookmarks
3802 if opts.get('bookmark'):
3805 if opts.get('bookmark'):
3803 for b in opts['bookmark']:
3806 for b in opts['bookmark']:
3804 # explicit pull overrides local bookmark if any
3807 # explicit pull overrides local bookmark if any
3805 ui.status(_("importing bookmark %s\n") % b)
3808 ui.status(_("importing bookmark %s\n") % b)
3806 repo._bookmarks[b] = repo[rb[b]].node()
3809 repo._bookmarks[b] = repo[rb[b]].node()
3807 bookmarks.write(repo)
3810 bookmarks.write(repo)
3808
3811
3809 return ret
3812 return ret
3810
3813
3811 @command('^push',
3814 @command('^push',
3812 [('f', 'force', None, _('force push')),
3815 [('f', 'force', None, _('force push')),
3813 ('r', 'rev', [],
3816 ('r', 'rev', [],
3814 _('a changeset intended to be included in the destination'),
3817 _('a changeset intended to be included in the destination'),
3815 _('REV')),
3818 _('REV')),
3816 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3819 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3817 ('b', 'branch', [],
3820 ('b', 'branch', [],
3818 _('a specific branch you would like to push'), _('BRANCH')),
3821 _('a specific branch you would like to push'), _('BRANCH')),
3819 ('', 'new-branch', False, _('allow pushing a new branch')),
3822 ('', 'new-branch', False, _('allow pushing a new branch')),
3820 ] + remoteopts,
3823 ] + remoteopts,
3821 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3824 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3822 def push(ui, repo, dest=None, **opts):
3825 def push(ui, repo, dest=None, **opts):
3823 """push changes to the specified destination
3826 """push changes to the specified destination
3824
3827
3825 Push changesets from the local repository to the specified
3828 Push changesets from the local repository to the specified
3826 destination.
3829 destination.
3827
3830
3828 This operation is symmetrical to pull: it is identical to a pull
3831 This operation is symmetrical to pull: it is identical to a pull
3829 in the destination repository from the current one.
3832 in the destination repository from the current one.
3830
3833
3831 By default, push will not allow creation of new heads at the
3834 By default, push will not allow creation of new heads at the
3832 destination, since multiple heads would make it unclear which head
3835 destination, since multiple heads would make it unclear which head
3833 to use. In this situation, it is recommended to pull and merge
3836 to use. In this situation, it is recommended to pull and merge
3834 before pushing.
3837 before pushing.
3835
3838
3836 Use --new-branch if you want to allow push to create a new named
3839 Use --new-branch if you want to allow push to create a new named
3837 branch that is not present at the destination. This allows you to
3840 branch that is not present at the destination. This allows you to
3838 only create a new branch without forcing other changes.
3841 only create a new branch without forcing other changes.
3839
3842
3840 Use -f/--force to override the default behavior and push all
3843 Use -f/--force to override the default behavior and push all
3841 changesets on all branches.
3844 changesets on all branches.
3842
3845
3843 If -r/--rev is used, the specified revision and all its ancestors
3846 If -r/--rev is used, the specified revision and all its ancestors
3844 will be pushed to the remote repository.
3847 will be pushed to the remote repository.
3845
3848
3846 Please see :hg:`help urls` for important details about ``ssh://``
3849 Please see :hg:`help urls` for important details about ``ssh://``
3847 URLs. If DESTINATION is omitted, a default path will be used.
3850 URLs. If DESTINATION is omitted, a default path will be used.
3848
3851
3849 Returns 0 if push was successful, 1 if nothing to push.
3852 Returns 0 if push was successful, 1 if nothing to push.
3850 """
3853 """
3851
3854
3852 if opts.get('bookmark'):
3855 if opts.get('bookmark'):
3853 for b in opts['bookmark']:
3856 for b in opts['bookmark']:
3854 # translate -B options to -r so changesets get pushed
3857 # translate -B options to -r so changesets get pushed
3855 if b in repo._bookmarks:
3858 if b in repo._bookmarks:
3856 opts.setdefault('rev', []).append(b)
3859 opts.setdefault('rev', []).append(b)
3857 else:
3860 else:
3858 # if we try to push a deleted bookmark, translate it to null
3861 # if we try to push a deleted bookmark, translate it to null
3859 # this lets simultaneous -r, -b options continue working
3862 # this lets simultaneous -r, -b options continue working
3860 opts.setdefault('rev', []).append("null")
3863 opts.setdefault('rev', []).append("null")
3861
3864
3862 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3865 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3863 dest, branches = hg.parseurl(dest, opts.get('branch'))
3866 dest, branches = hg.parseurl(dest, opts.get('branch'))
3864 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3867 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3865 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3868 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3866 other = hg.peer(repo, opts, dest)
3869 other = hg.peer(repo, opts, dest)
3867 if revs:
3870 if revs:
3868 revs = [repo.lookup(rev) for rev in revs]
3871 revs = [repo.lookup(rev) for rev in revs]
3869
3872
3870 repo._subtoppath = dest
3873 repo._subtoppath = dest
3871 try:
3874 try:
3872 # push subrepos depth-first for coherent ordering
3875 # push subrepos depth-first for coherent ordering
3873 c = repo['']
3876 c = repo['']
3874 subs = c.substate # only repos that are committed
3877 subs = c.substate # only repos that are committed
3875 for s in sorted(subs):
3878 for s in sorted(subs):
3876 if not c.sub(s).push(opts.get('force')):
3879 if not c.sub(s).push(opts.get('force')):
3877 return False
3880 return False
3878 finally:
3881 finally:
3879 del repo._subtoppath
3882 del repo._subtoppath
3880 result = repo.push(other, opts.get('force'), revs=revs,
3883 result = repo.push(other, opts.get('force'), revs=revs,
3881 newbranch=opts.get('new_branch'))
3884 newbranch=opts.get('new_branch'))
3882
3885
3883 result = (result == 0)
3886 result = (result == 0)
3884
3887
3885 if opts.get('bookmark'):
3888 if opts.get('bookmark'):
3886 rb = other.listkeys('bookmarks')
3889 rb = other.listkeys('bookmarks')
3887 for b in opts['bookmark']:
3890 for b in opts['bookmark']:
3888 # explicit push overrides remote bookmark if any
3891 # explicit push overrides remote bookmark if any
3889 if b in repo._bookmarks:
3892 if b in repo._bookmarks:
3890 ui.status(_("exporting bookmark %s\n") % b)
3893 ui.status(_("exporting bookmark %s\n") % b)
3891 new = repo[b].hex()
3894 new = repo[b].hex()
3892 elif b in rb:
3895 elif b in rb:
3893 ui.status(_("deleting remote bookmark %s\n") % b)
3896 ui.status(_("deleting remote bookmark %s\n") % b)
3894 new = '' # delete
3897 new = '' # delete
3895 else:
3898 else:
3896 ui.warn(_('bookmark %s does not exist on the local '
3899 ui.warn(_('bookmark %s does not exist on the local '
3897 'or remote repository!\n') % b)
3900 'or remote repository!\n') % b)
3898 return 2
3901 return 2
3899 old = rb.get(b, '')
3902 old = rb.get(b, '')
3900 r = other.pushkey('bookmarks', b, old, new)
3903 r = other.pushkey('bookmarks', b, old, new)
3901 if not r:
3904 if not r:
3902 ui.warn(_('updating bookmark %s failed!\n') % b)
3905 ui.warn(_('updating bookmark %s failed!\n') % b)
3903 if not result:
3906 if not result:
3904 result = 2
3907 result = 2
3905
3908
3906 return result
3909 return result
3907
3910
3908 @command('recover', [])
3911 @command('recover', [])
3909 def recover(ui, repo):
3912 def recover(ui, repo):
3910 """roll back an interrupted transaction
3913 """roll back an interrupted transaction
3911
3914
3912 Recover from an interrupted commit or pull.
3915 Recover from an interrupted commit or pull.
3913
3916
3914 This command tries to fix the repository status after an
3917 This command tries to fix the repository status after an
3915 interrupted operation. It should only be necessary when Mercurial
3918 interrupted operation. It should only be necessary when Mercurial
3916 suggests it.
3919 suggests it.
3917
3920
3918 Returns 0 if successful, 1 if nothing to recover or verify fails.
3921 Returns 0 if successful, 1 if nothing to recover or verify fails.
3919 """
3922 """
3920 if repo.recover():
3923 if repo.recover():
3921 return hg.verify(repo)
3924 return hg.verify(repo)
3922 return 1
3925 return 1
3923
3926
3924 @command('^remove|rm',
3927 @command('^remove|rm',
3925 [('A', 'after', None, _('record delete for missing files')),
3928 [('A', 'after', None, _('record delete for missing files')),
3926 ('f', 'force', None,
3929 ('f', 'force', None,
3927 _('remove (and delete) file even if added or modified')),
3930 _('remove (and delete) file even if added or modified')),
3928 ] + walkopts,
3931 ] + walkopts,
3929 _('[OPTION]... FILE...'))
3932 _('[OPTION]... FILE...'))
3930 def remove(ui, repo, *pats, **opts):
3933 def remove(ui, repo, *pats, **opts):
3931 """remove the specified files on the next commit
3934 """remove the specified files on the next commit
3932
3935
3933 Schedule the indicated files for removal from the repository.
3936 Schedule the indicated files for removal from the repository.
3934
3937
3935 This only removes files from the current branch, not from the
3938 This only removes files from the current branch, not from the
3936 entire project history. -A/--after can be used to remove only
3939 entire project history. -A/--after can be used to remove only
3937 files that have already been deleted, -f/--force can be used to
3940 files that have already been deleted, -f/--force can be used to
3938 force deletion, and -Af can be used to remove files from the next
3941 force deletion, and -Af can be used to remove files from the next
3939 revision without deleting them from the working directory.
3942 revision without deleting them from the working directory.
3940
3943
3941 The following table details the behavior of remove for different
3944 The following table details the behavior of remove for different
3942 file states (columns) and option combinations (rows). The file
3945 file states (columns) and option combinations (rows). The file
3943 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3946 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3944 reported by :hg:`status`). The actions are Warn, Remove (from
3947 reported by :hg:`status`). The actions are Warn, Remove (from
3945 branch) and Delete (from disk)::
3948 branch) and Delete (from disk)::
3946
3949
3947 A C M !
3950 A C M !
3948 none W RD W R
3951 none W RD W R
3949 -f R RD RD R
3952 -f R RD RD R
3950 -A W W W R
3953 -A W W W R
3951 -Af R R R R
3954 -Af R R R R
3952
3955
3953 Note that remove never deletes files in Added [A] state from the
3956 Note that remove never deletes files in Added [A] state from the
3954 working directory, not even if option --force is specified.
3957 working directory, not even if option --force is specified.
3955
3958
3956 This command schedules the files to be removed at the next commit.
3959 This command schedules the files to be removed at the next commit.
3957 To undo a remove before that, see :hg:`revert`.
3960 To undo a remove before that, see :hg:`revert`.
3958
3961
3959 Returns 0 on success, 1 if any warnings encountered.
3962 Returns 0 on success, 1 if any warnings encountered.
3960 """
3963 """
3961
3964
3962 ret = 0
3965 ret = 0
3963 after, force = opts.get('after'), opts.get('force')
3966 after, force = opts.get('after'), opts.get('force')
3964 if not pats and not after:
3967 if not pats and not after:
3965 raise util.Abort(_('no files specified'))
3968 raise util.Abort(_('no files specified'))
3966
3969
3967 m = scmutil.match(repo, pats, opts)
3970 m = scmutil.match(repo, pats, opts)
3968 s = repo.status(match=m, clean=True)
3971 s = repo.status(match=m, clean=True)
3969 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3972 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3970
3973
3971 for f in m.files():
3974 for f in m.files():
3972 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3975 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3973 if os.path.exists(m.rel(f)):
3976 if os.path.exists(m.rel(f)):
3974 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3977 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3975 ret = 1
3978 ret = 1
3976
3979
3977 if force:
3980 if force:
3978 list = modified + deleted + clean + added
3981 list = modified + deleted + clean + added
3979 elif after:
3982 elif after:
3980 list = deleted
3983 list = deleted
3981 for f in modified + added + clean:
3984 for f in modified + added + clean:
3982 ui.warn(_('not removing %s: file still exists (use -f'
3985 ui.warn(_('not removing %s: file still exists (use -f'
3983 ' to force removal)\n') % m.rel(f))
3986 ' to force removal)\n') % m.rel(f))
3984 ret = 1
3987 ret = 1
3985 else:
3988 else:
3986 list = deleted + clean
3989 list = deleted + clean
3987 for f in modified:
3990 for f in modified:
3988 ui.warn(_('not removing %s: file is modified (use -f'
3991 ui.warn(_('not removing %s: file is modified (use -f'
3989 ' to force removal)\n') % m.rel(f))
3992 ' to force removal)\n') % m.rel(f))
3990 ret = 1
3993 ret = 1
3991 for f in added:
3994 for f in added:
3992 ui.warn(_('not removing %s: file has been marked for add (use -f'
3995 ui.warn(_('not removing %s: file has been marked for add (use -f'
3993 ' to force removal)\n') % m.rel(f))
3996 ' to force removal)\n') % m.rel(f))
3994 ret = 1
3997 ret = 1
3995
3998
3996 for f in sorted(list):
3999 for f in sorted(list):
3997 if ui.verbose or not m.exact(f):
4000 if ui.verbose or not m.exact(f):
3998 ui.status(_('removing %s\n') % m.rel(f))
4001 ui.status(_('removing %s\n') % m.rel(f))
3999
4002
4000 wlock = repo.wlock()
4003 wlock = repo.wlock()
4001 try:
4004 try:
4002 if not after:
4005 if not after:
4003 for f in list:
4006 for f in list:
4004 if f in added:
4007 if f in added:
4005 continue # we never unlink added files on remove
4008 continue # we never unlink added files on remove
4006 try:
4009 try:
4007 util.unlinkpath(repo.wjoin(f))
4010 util.unlinkpath(repo.wjoin(f))
4008 except OSError, inst:
4011 except OSError, inst:
4009 if inst.errno != errno.ENOENT:
4012 if inst.errno != errno.ENOENT:
4010 raise
4013 raise
4011 repo[None].forget(list)
4014 repo[None].forget(list)
4012 finally:
4015 finally:
4013 wlock.release()
4016 wlock.release()
4014
4017
4015 return ret
4018 return ret
4016
4019
4017 @command('rename|move|mv',
4020 @command('rename|move|mv',
4018 [('A', 'after', None, _('record a rename that has already occurred')),
4021 [('A', 'after', None, _('record a rename that has already occurred')),
4019 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4022 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4020 ] + walkopts + dryrunopts,
4023 ] + walkopts + dryrunopts,
4021 _('[OPTION]... SOURCE... DEST'))
4024 _('[OPTION]... SOURCE... DEST'))
4022 def rename(ui, repo, *pats, **opts):
4025 def rename(ui, repo, *pats, **opts):
4023 """rename files; equivalent of copy + remove
4026 """rename files; equivalent of copy + remove
4024
4027
4025 Mark dest as copies of sources; mark sources for deletion. If dest
4028 Mark dest as copies of sources; mark sources for deletion. If dest
4026 is a directory, copies are put in that directory. If dest is a
4029 is a directory, copies are put in that directory. If dest is a
4027 file, there can only be one source.
4030 file, there can only be one source.
4028
4031
4029 By default, this command copies the contents of files as they
4032 By default, this command copies the contents of files as they
4030 exist in the working directory. If invoked with -A/--after, the
4033 exist in the working directory. If invoked with -A/--after, the
4031 operation is recorded, but no copying is performed.
4034 operation is recorded, but no copying is performed.
4032
4035
4033 This command takes effect at the next commit. To undo a rename
4036 This command takes effect at the next commit. To undo a rename
4034 before that, see :hg:`revert`.
4037 before that, see :hg:`revert`.
4035
4038
4036 Returns 0 on success, 1 if errors are encountered.
4039 Returns 0 on success, 1 if errors are encountered.
4037 """
4040 """
4038 wlock = repo.wlock(False)
4041 wlock = repo.wlock(False)
4039 try:
4042 try:
4040 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4043 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4041 finally:
4044 finally:
4042 wlock.release()
4045 wlock.release()
4043
4046
4044 @command('resolve',
4047 @command('resolve',
4045 [('a', 'all', None, _('select all unresolved files')),
4048 [('a', 'all', None, _('select all unresolved files')),
4046 ('l', 'list', None, _('list state of files needing merge')),
4049 ('l', 'list', None, _('list state of files needing merge')),
4047 ('m', 'mark', None, _('mark files as resolved')),
4050 ('m', 'mark', None, _('mark files as resolved')),
4048 ('u', 'unmark', None, _('mark files as unresolved')),
4051 ('u', 'unmark', None, _('mark files as unresolved')),
4049 ('t', 'tool', '', _('specify merge tool')),
4052 ('t', 'tool', '', _('specify merge tool')),
4050 ('n', 'no-status', None, _('hide status prefix'))]
4053 ('n', 'no-status', None, _('hide status prefix'))]
4051 + walkopts,
4054 + walkopts,
4052 _('[OPTION]... [FILE]...'))
4055 _('[OPTION]... [FILE]...'))
4053 def resolve(ui, repo, *pats, **opts):
4056 def resolve(ui, repo, *pats, **opts):
4054 """redo merges or set/view the merge status of files
4057 """redo merges or set/view the merge status of files
4055
4058
4056 Merges with unresolved conflicts are often the result of
4059 Merges with unresolved conflicts are often the result of
4057 non-interactive merging using the ``internal:merge`` configuration
4060 non-interactive merging using the ``internal:merge`` configuration
4058 setting, or a command-line merge tool like ``diff3``. The resolve
4061 setting, or a command-line merge tool like ``diff3``. The resolve
4059 command is used to manage the files involved in a merge, after
4062 command is used to manage the files involved in a merge, after
4060 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4063 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4061 working directory must have two parents).
4064 working directory must have two parents).
4062
4065
4063 The resolve command can be used in the following ways:
4066 The resolve command can be used in the following ways:
4064
4067
4065 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4068 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4066 files, discarding any previous merge attempts. Re-merging is not
4069 files, discarding any previous merge attempts. Re-merging is not
4067 performed for files already marked as resolved. Use ``--all/-a``
4070 performed for files already marked as resolved. Use ``--all/-a``
4068 to selects all unresolved files. ``--tool`` can be used to specify
4071 to selects all unresolved files. ``--tool`` can be used to specify
4069 the merge tool used for the given files. It overrides the HGMERGE
4072 the merge tool used for the given files. It overrides the HGMERGE
4070 environment variable and your configuration files.
4073 environment variable and your configuration files.
4071
4074
4072 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4075 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4073 (e.g. after having manually fixed-up the files). The default is
4076 (e.g. after having manually fixed-up the files). The default is
4074 to mark all unresolved files.
4077 to mark all unresolved files.
4075
4078
4076 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4079 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4077 default is to mark all resolved files.
4080 default is to mark all resolved files.
4078
4081
4079 - :hg:`resolve -l`: list files which had or still have conflicts.
4082 - :hg:`resolve -l`: list files which had or still have conflicts.
4080 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4083 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4081
4084
4082 Note that Mercurial will not let you commit files with unresolved
4085 Note that Mercurial will not let you commit files with unresolved
4083 merge conflicts. You must use :hg:`resolve -m ...` before you can
4086 merge conflicts. You must use :hg:`resolve -m ...` before you can
4084 commit after a conflicting merge.
4087 commit after a conflicting merge.
4085
4088
4086 Returns 0 on success, 1 if any files fail a resolve attempt.
4089 Returns 0 on success, 1 if any files fail a resolve attempt.
4087 """
4090 """
4088
4091
4089 all, mark, unmark, show, nostatus = \
4092 all, mark, unmark, show, nostatus = \
4090 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4093 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4091
4094
4092 if (show and (mark or unmark)) or (mark and unmark):
4095 if (show and (mark or unmark)) or (mark and unmark):
4093 raise util.Abort(_("too many options specified"))
4096 raise util.Abort(_("too many options specified"))
4094 if pats and all:
4097 if pats and all:
4095 raise util.Abort(_("can't specify --all and patterns"))
4098 raise util.Abort(_("can't specify --all and patterns"))
4096 if not (all or pats or show or mark or unmark):
4099 if not (all or pats or show or mark or unmark):
4097 raise util.Abort(_('no files or directories specified; '
4100 raise util.Abort(_('no files or directories specified; '
4098 'use --all to remerge all files'))
4101 'use --all to remerge all files'))
4099
4102
4100 ms = mergemod.mergestate(repo)
4103 ms = mergemod.mergestate(repo)
4101 m = scmutil.match(repo, pats, opts)
4104 m = scmutil.match(repo, pats, opts)
4102 ret = 0
4105 ret = 0
4103
4106
4104 for f in ms:
4107 for f in ms:
4105 if m(f):
4108 if m(f):
4106 if show:
4109 if show:
4107 if nostatus:
4110 if nostatus:
4108 ui.write("%s\n" % f)
4111 ui.write("%s\n" % f)
4109 else:
4112 else:
4110 ui.write("%s %s\n" % (ms[f].upper(), f),
4113 ui.write("%s %s\n" % (ms[f].upper(), f),
4111 label='resolve.' +
4114 label='resolve.' +
4112 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4115 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4113 elif mark:
4116 elif mark:
4114 ms.mark(f, "r")
4117 ms.mark(f, "r")
4115 elif unmark:
4118 elif unmark:
4116 ms.mark(f, "u")
4119 ms.mark(f, "u")
4117 else:
4120 else:
4118 wctx = repo[None]
4121 wctx = repo[None]
4119 mctx = wctx.parents()[-1]
4122 mctx = wctx.parents()[-1]
4120
4123
4121 # backup pre-resolve (merge uses .orig for its own purposes)
4124 # backup pre-resolve (merge uses .orig for its own purposes)
4122 a = repo.wjoin(f)
4125 a = repo.wjoin(f)
4123 util.copyfile(a, a + ".resolve")
4126 util.copyfile(a, a + ".resolve")
4124
4127
4125 try:
4128 try:
4126 # resolve file
4129 # resolve file
4127 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4130 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4128 if ms.resolve(f, wctx, mctx):
4131 if ms.resolve(f, wctx, mctx):
4129 ret = 1
4132 ret = 1
4130 finally:
4133 finally:
4131 ui.setconfig('ui', 'forcemerge', '')
4134 ui.setconfig('ui', 'forcemerge', '')
4132
4135
4133 # replace filemerge's .orig file with our resolve file
4136 # replace filemerge's .orig file with our resolve file
4134 util.rename(a + ".resolve", a + ".orig")
4137 util.rename(a + ".resolve", a + ".orig")
4135
4138
4136 ms.commit()
4139 ms.commit()
4137 return ret
4140 return ret
4138
4141
4139 @command('revert',
4142 @command('revert',
4140 [('a', 'all', None, _('revert all changes when no arguments given')),
4143 [('a', 'all', None, _('revert all changes when no arguments given')),
4141 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4144 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4142 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4145 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4143 ('', 'no-backup', None, _('do not save backup copies of files')),
4146 ('', 'no-backup', None, _('do not save backup copies of files')),
4144 ] + walkopts + dryrunopts,
4147 ] + walkopts + dryrunopts,
4145 _('[OPTION]... [-r REV] [NAME]...'))
4148 _('[OPTION]... [-r REV] [NAME]...'))
4146 def revert(ui, repo, *pats, **opts):
4149 def revert(ui, repo, *pats, **opts):
4147 """restore files to their checkout state
4150 """restore files to their checkout state
4148
4151
4149 .. note::
4152 .. note::
4150 To check out earlier revisions, you should use :hg:`update REV`.
4153 To check out earlier revisions, you should use :hg:`update REV`.
4151 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4154 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4152
4155
4153 With no revision specified, revert the specified files or directories
4156 With no revision specified, revert the specified files or directories
4154 to the state they had in the first parent of the working directory.
4157 to the state they had in the first parent of the working directory.
4155 This restores the contents of files to an unmodified
4158 This restores the contents of files to an unmodified
4156 state and unschedules adds, removes, copies, and renames.
4159 state and unschedules adds, removes, copies, and renames.
4157
4160
4158 Using the -r/--rev or -d/--date options, revert the given files or
4161 Using the -r/--rev or -d/--date options, revert the given files or
4159 directories to their states as of a specific revision. Because
4162 directories to their states as of a specific revision. Because
4160 revert does not change the working directory parents, this will
4163 revert does not change the working directory parents, this will
4161 cause these files to appear modified. This can be helpful to "back
4164 cause these files to appear modified. This can be helpful to "back
4162 out" some or all of an earlier change. See :hg:`backout` for a
4165 out" some or all of an earlier change. See :hg:`backout` for a
4163 related method.
4166 related method.
4164
4167
4165 Modified files are saved with a .orig suffix before reverting.
4168 Modified files are saved with a .orig suffix before reverting.
4166 To disable these backups, use --no-backup.
4169 To disable these backups, use --no-backup.
4167
4170
4168 See :hg:`help dates` for a list of formats valid for -d/--date.
4171 See :hg:`help dates` for a list of formats valid for -d/--date.
4169
4172
4170 Returns 0 on success.
4173 Returns 0 on success.
4171 """
4174 """
4172
4175
4173 if opts.get("date"):
4176 if opts.get("date"):
4174 if opts.get("rev"):
4177 if opts.get("rev"):
4175 raise util.Abort(_("you can't specify a revision and a date"))
4178 raise util.Abort(_("you can't specify a revision and a date"))
4176 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4179 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4177
4180
4178 parent, p2 = repo.dirstate.parents()
4181 parent, p2 = repo.dirstate.parents()
4179
4182
4180 if not pats and not opts.get('all'):
4183 if not pats and not opts.get('all'):
4181 raise util.Abort(_('no files or directories specified'),
4184 raise util.Abort(_('no files or directories specified'),
4182 hint=_('use --all to revert all files'))
4185 hint=_('use --all to revert all files'))
4183
4186
4184 ctx = scmutil.revsingle(repo, opts.get('rev'))
4187 ctx = scmutil.revsingle(repo, opts.get('rev'))
4185 node = ctx.node()
4188 node = ctx.node()
4186 mf = ctx.manifest()
4189 mf = ctx.manifest()
4187 if node == parent:
4190 if node == parent:
4188 pmf = mf
4191 pmf = mf
4189 else:
4192 else:
4190 pmf = None
4193 pmf = None
4191
4194
4192 # need all matching names in dirstate and manifest of target rev,
4195 # need all matching names in dirstate and manifest of target rev,
4193 # so have to walk both. do not print errors if files exist in one
4196 # so have to walk both. do not print errors if files exist in one
4194 # but not other.
4197 # but not other.
4195
4198
4196 names = {}
4199 names = {}
4197
4200
4198 wlock = repo.wlock()
4201 wlock = repo.wlock()
4199 try:
4202 try:
4200 # walk dirstate.
4203 # walk dirstate.
4201
4204
4202 m = scmutil.match(repo, pats, opts)
4205 m = scmutil.match(repo, pats, opts)
4203 m.bad = lambda x, y: False
4206 m.bad = lambda x, y: False
4204 for abs in repo.walk(m):
4207 for abs in repo.walk(m):
4205 names[abs] = m.rel(abs), m.exact(abs)
4208 names[abs] = m.rel(abs), m.exact(abs)
4206
4209
4207 # walk target manifest.
4210 # walk target manifest.
4208
4211
4209 def badfn(path, msg):
4212 def badfn(path, msg):
4210 if path in names:
4213 if path in names:
4211 return
4214 return
4212 path_ = path + '/'
4215 path_ = path + '/'
4213 for f in names:
4216 for f in names:
4214 if f.startswith(path_):
4217 if f.startswith(path_):
4215 return
4218 return
4216 ui.warn("%s: %s\n" % (m.rel(path), msg))
4219 ui.warn("%s: %s\n" % (m.rel(path), msg))
4217
4220
4218 m = scmutil.match(repo, pats, opts)
4221 m = scmutil.match(repo, pats, opts)
4219 m.bad = badfn
4222 m.bad = badfn
4220 for abs in repo[node].walk(m):
4223 for abs in repo[node].walk(m):
4221 if abs not in names:
4224 if abs not in names:
4222 names[abs] = m.rel(abs), m.exact(abs)
4225 names[abs] = m.rel(abs), m.exact(abs)
4223
4226
4224 m = scmutil.matchfiles(repo, names)
4227 m = scmutil.matchfiles(repo, names)
4225 changes = repo.status(match=m)[:4]
4228 changes = repo.status(match=m)[:4]
4226 modified, added, removed, deleted = map(set, changes)
4229 modified, added, removed, deleted = map(set, changes)
4227
4230
4228 # if f is a rename, also revert the source
4231 # if f is a rename, also revert the source
4229 cwd = repo.getcwd()
4232 cwd = repo.getcwd()
4230 for f in added:
4233 for f in added:
4231 src = repo.dirstate.copied(f)
4234 src = repo.dirstate.copied(f)
4232 if src and src not in names and repo.dirstate[src] == 'r':
4235 if src and src not in names and repo.dirstate[src] == 'r':
4233 removed.add(src)
4236 removed.add(src)
4234 names[src] = (repo.pathto(src, cwd), True)
4237 names[src] = (repo.pathto(src, cwd), True)
4235
4238
4236 def removeforget(abs):
4239 def removeforget(abs):
4237 if repo.dirstate[abs] == 'a':
4240 if repo.dirstate[abs] == 'a':
4238 return _('forgetting %s\n')
4241 return _('forgetting %s\n')
4239 return _('removing %s\n')
4242 return _('removing %s\n')
4240
4243
4241 revert = ([], _('reverting %s\n'))
4244 revert = ([], _('reverting %s\n'))
4242 add = ([], _('adding %s\n'))
4245 add = ([], _('adding %s\n'))
4243 remove = ([], removeforget)
4246 remove = ([], removeforget)
4244 undelete = ([], _('undeleting %s\n'))
4247 undelete = ([], _('undeleting %s\n'))
4245
4248
4246 disptable = (
4249 disptable = (
4247 # dispatch table:
4250 # dispatch table:
4248 # file state
4251 # file state
4249 # action if in target manifest
4252 # action if in target manifest
4250 # action if not in target manifest
4253 # action if not in target manifest
4251 # make backup if in target manifest
4254 # make backup if in target manifest
4252 # make backup if not in target manifest
4255 # make backup if not in target manifest
4253 (modified, revert, remove, True, True),
4256 (modified, revert, remove, True, True),
4254 (added, revert, remove, True, False),
4257 (added, revert, remove, True, False),
4255 (removed, undelete, None, False, False),
4258 (removed, undelete, None, False, False),
4256 (deleted, revert, remove, False, False),
4259 (deleted, revert, remove, False, False),
4257 )
4260 )
4258
4261
4259 for abs, (rel, exact) in sorted(names.items()):
4262 for abs, (rel, exact) in sorted(names.items()):
4260 mfentry = mf.get(abs)
4263 mfentry = mf.get(abs)
4261 target = repo.wjoin(abs)
4264 target = repo.wjoin(abs)
4262 def handle(xlist, dobackup):
4265 def handle(xlist, dobackup):
4263 xlist[0].append(abs)
4266 xlist[0].append(abs)
4264 if (dobackup and not opts.get('no_backup') and
4267 if (dobackup and not opts.get('no_backup') and
4265 os.path.lexists(target)):
4268 os.path.lexists(target)):
4266 bakname = "%s.orig" % rel
4269 bakname = "%s.orig" % rel
4267 ui.note(_('saving current version of %s as %s\n') %
4270 ui.note(_('saving current version of %s as %s\n') %
4268 (rel, bakname))
4271 (rel, bakname))
4269 if not opts.get('dry_run'):
4272 if not opts.get('dry_run'):
4270 util.rename(target, bakname)
4273 util.rename(target, bakname)
4271 if ui.verbose or not exact:
4274 if ui.verbose or not exact:
4272 msg = xlist[1]
4275 msg = xlist[1]
4273 if not isinstance(msg, basestring):
4276 if not isinstance(msg, basestring):
4274 msg = msg(abs)
4277 msg = msg(abs)
4275 ui.status(msg % rel)
4278 ui.status(msg % rel)
4276 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4279 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4277 if abs not in table:
4280 if abs not in table:
4278 continue
4281 continue
4279 # file has changed in dirstate
4282 # file has changed in dirstate
4280 if mfentry:
4283 if mfentry:
4281 handle(hitlist, backuphit)
4284 handle(hitlist, backuphit)
4282 elif misslist is not None:
4285 elif misslist is not None:
4283 handle(misslist, backupmiss)
4286 handle(misslist, backupmiss)
4284 break
4287 break
4285 else:
4288 else:
4286 if abs not in repo.dirstate:
4289 if abs not in repo.dirstate:
4287 if mfentry:
4290 if mfentry:
4288 handle(add, True)
4291 handle(add, True)
4289 elif exact:
4292 elif exact:
4290 ui.warn(_('file not managed: %s\n') % rel)
4293 ui.warn(_('file not managed: %s\n') % rel)
4291 continue
4294 continue
4292 # file has not changed in dirstate
4295 # file has not changed in dirstate
4293 if node == parent:
4296 if node == parent:
4294 if exact:
4297 if exact:
4295 ui.warn(_('no changes needed to %s\n') % rel)
4298 ui.warn(_('no changes needed to %s\n') % rel)
4296 continue
4299 continue
4297 if pmf is None:
4300 if pmf is None:
4298 # only need parent manifest in this unlikely case,
4301 # only need parent manifest in this unlikely case,
4299 # so do not read by default
4302 # so do not read by default
4300 pmf = repo[parent].manifest()
4303 pmf = repo[parent].manifest()
4301 if abs in pmf:
4304 if abs in pmf:
4302 if mfentry:
4305 if mfentry:
4303 # if version of file is same in parent and target
4306 # if version of file is same in parent and target
4304 # manifests, do nothing
4307 # manifests, do nothing
4305 if (pmf[abs] != mfentry or
4308 if (pmf[abs] != mfentry or
4306 pmf.flags(abs) != mf.flags(abs)):
4309 pmf.flags(abs) != mf.flags(abs)):
4307 handle(revert, False)
4310 handle(revert, False)
4308 else:
4311 else:
4309 handle(remove, False)
4312 handle(remove, False)
4310
4313
4311 if not opts.get('dry_run'):
4314 if not opts.get('dry_run'):
4312 def checkout(f):
4315 def checkout(f):
4313 fc = ctx[f]
4316 fc = ctx[f]
4314 repo.wwrite(f, fc.data(), fc.flags())
4317 repo.wwrite(f, fc.data(), fc.flags())
4315
4318
4316 audit_path = scmutil.pathauditor(repo.root)
4319 audit_path = scmutil.pathauditor(repo.root)
4317 for f in remove[0]:
4320 for f in remove[0]:
4318 if repo.dirstate[f] == 'a':
4321 if repo.dirstate[f] == 'a':
4319 repo.dirstate.drop(f)
4322 repo.dirstate.drop(f)
4320 continue
4323 continue
4321 audit_path(f)
4324 audit_path(f)
4322 try:
4325 try:
4323 util.unlinkpath(repo.wjoin(f))
4326 util.unlinkpath(repo.wjoin(f))
4324 except OSError:
4327 except OSError:
4325 pass
4328 pass
4326 repo.dirstate.remove(f)
4329 repo.dirstate.remove(f)
4327
4330
4328 normal = None
4331 normal = None
4329 if node == parent:
4332 if node == parent:
4330 # We're reverting to our parent. If possible, we'd like status
4333 # We're reverting to our parent. If possible, we'd like status
4331 # to report the file as clean. We have to use normallookup for
4334 # to report the file as clean. We have to use normallookup for
4332 # merges to avoid losing information about merged/dirty files.
4335 # merges to avoid losing information about merged/dirty files.
4333 if p2 != nullid:
4336 if p2 != nullid:
4334 normal = repo.dirstate.normallookup
4337 normal = repo.dirstate.normallookup
4335 else:
4338 else:
4336 normal = repo.dirstate.normal
4339 normal = repo.dirstate.normal
4337 for f in revert[0]:
4340 for f in revert[0]:
4338 checkout(f)
4341 checkout(f)
4339 if normal:
4342 if normal:
4340 normal(f)
4343 normal(f)
4341
4344
4342 for f in add[0]:
4345 for f in add[0]:
4343 checkout(f)
4346 checkout(f)
4344 repo.dirstate.add(f)
4347 repo.dirstate.add(f)
4345
4348
4346 normal = repo.dirstate.normallookup
4349 normal = repo.dirstate.normallookup
4347 if node == parent and p2 == nullid:
4350 if node == parent and p2 == nullid:
4348 normal = repo.dirstate.normal
4351 normal = repo.dirstate.normal
4349 for f in undelete[0]:
4352 for f in undelete[0]:
4350 checkout(f)
4353 checkout(f)
4351 normal(f)
4354 normal(f)
4352
4355
4353 finally:
4356 finally:
4354 wlock.release()
4357 wlock.release()
4355
4358
4356 @command('rollback', dryrunopts)
4359 @command('rollback', dryrunopts)
4357 def rollback(ui, repo, **opts):
4360 def rollback(ui, repo, **opts):
4358 """roll back the last transaction (dangerous)
4361 """roll back the last transaction (dangerous)
4359
4362
4360 This command should be used with care. There is only one level of
4363 This command should be used with care. There is only one level of
4361 rollback, and there is no way to undo a rollback. It will also
4364 rollback, and there is no way to undo a rollback. It will also
4362 restore the dirstate at the time of the last transaction, losing
4365 restore the dirstate at the time of the last transaction, losing
4363 any dirstate changes since that time. This command does not alter
4366 any dirstate changes since that time. This command does not alter
4364 the working directory.
4367 the working directory.
4365
4368
4366 Transactions are used to encapsulate the effects of all commands
4369 Transactions are used to encapsulate the effects of all commands
4367 that create new changesets or propagate existing changesets into a
4370 that create new changesets or propagate existing changesets into a
4368 repository. For example, the following commands are transactional,
4371 repository. For example, the following commands are transactional,
4369 and their effects can be rolled back:
4372 and their effects can be rolled back:
4370
4373
4371 - commit
4374 - commit
4372 - import
4375 - import
4373 - pull
4376 - pull
4374 - push (with this repository as the destination)
4377 - push (with this repository as the destination)
4375 - unbundle
4378 - unbundle
4376
4379
4377 This command is not intended for use on public repositories. Once
4380 This command is not intended for use on public repositories. Once
4378 changes are visible for pull by other users, rolling a transaction
4381 changes are visible for pull by other users, rolling a transaction
4379 back locally is ineffective (someone else may already have pulled
4382 back locally is ineffective (someone else may already have pulled
4380 the changes). Furthermore, a race is possible with readers of the
4383 the changes). Furthermore, a race is possible with readers of the
4381 repository; for example an in-progress pull from the repository
4384 repository; for example an in-progress pull from the repository
4382 may fail if a rollback is performed.
4385 may fail if a rollback is performed.
4383
4386
4384 Returns 0 on success, 1 if no rollback data is available.
4387 Returns 0 on success, 1 if no rollback data is available.
4385 """
4388 """
4386 return repo.rollback(opts.get('dry_run'))
4389 return repo.rollback(opts.get('dry_run'))
4387
4390
4388 @command('root', [])
4391 @command('root', [])
4389 def root(ui, repo):
4392 def root(ui, repo):
4390 """print the root (top) of the current working directory
4393 """print the root (top) of the current working directory
4391
4394
4392 Print the root directory of the current repository.
4395 Print the root directory of the current repository.
4393
4396
4394 Returns 0 on success.
4397 Returns 0 on success.
4395 """
4398 """
4396 ui.write(repo.root + "\n")
4399 ui.write(repo.root + "\n")
4397
4400
4398 @command('^serve',
4401 @command('^serve',
4399 [('A', 'accesslog', '', _('name of access log file to write to'),
4402 [('A', 'accesslog', '', _('name of access log file to write to'),
4400 _('FILE')),
4403 _('FILE')),
4401 ('d', 'daemon', None, _('run server in background')),
4404 ('d', 'daemon', None, _('run server in background')),
4402 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4405 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4403 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4406 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4404 # use string type, then we can check if something was passed
4407 # use string type, then we can check if something was passed
4405 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4408 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4406 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4409 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4407 _('ADDR')),
4410 _('ADDR')),
4408 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4411 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4409 _('PREFIX')),
4412 _('PREFIX')),
4410 ('n', 'name', '',
4413 ('n', 'name', '',
4411 _('name to show in web pages (default: working directory)'), _('NAME')),
4414 _('name to show in web pages (default: working directory)'), _('NAME')),
4412 ('', 'web-conf', '',
4415 ('', 'web-conf', '',
4413 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4416 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4414 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4417 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4415 _('FILE')),
4418 _('FILE')),
4416 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4419 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4417 ('', 'stdio', None, _('for remote clients')),
4420 ('', 'stdio', None, _('for remote clients')),
4418 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4421 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4419 ('', 'style', '', _('template style to use'), _('STYLE')),
4422 ('', 'style', '', _('template style to use'), _('STYLE')),
4420 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4423 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4421 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4424 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4422 _('[OPTION]...'))
4425 _('[OPTION]...'))
4423 def serve(ui, repo, **opts):
4426 def serve(ui, repo, **opts):
4424 """start stand-alone webserver
4427 """start stand-alone webserver
4425
4428
4426 Start a local HTTP repository browser and pull server. You can use
4429 Start a local HTTP repository browser and pull server. You can use
4427 this for ad-hoc sharing and browsing of repositories. It is
4430 this for ad-hoc sharing and browsing of repositories. It is
4428 recommended to use a real web server to serve a repository for
4431 recommended to use a real web server to serve a repository for
4429 longer periods of time.
4432 longer periods of time.
4430
4433
4431 Please note that the server does not implement access control.
4434 Please note that the server does not implement access control.
4432 This means that, by default, anybody can read from the server and
4435 This means that, by default, anybody can read from the server and
4433 nobody can write to it by default. Set the ``web.allow_push``
4436 nobody can write to it by default. Set the ``web.allow_push``
4434 option to ``*`` to allow everybody to push to the server. You
4437 option to ``*`` to allow everybody to push to the server. You
4435 should use a real web server if you need to authenticate users.
4438 should use a real web server if you need to authenticate users.
4436
4439
4437 By default, the server logs accesses to stdout and errors to
4440 By default, the server logs accesses to stdout and errors to
4438 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4441 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4439 files.
4442 files.
4440
4443
4441 To have the server choose a free port number to listen on, specify
4444 To have the server choose a free port number to listen on, specify
4442 a port number of 0; in this case, the server will print the port
4445 a port number of 0; in this case, the server will print the port
4443 number it uses.
4446 number it uses.
4444
4447
4445 Returns 0 on success.
4448 Returns 0 on success.
4446 """
4449 """
4447
4450
4448 if opts["stdio"]:
4451 if opts["stdio"]:
4449 if repo is None:
4452 if repo is None:
4450 raise error.RepoError(_("There is no Mercurial repository here"
4453 raise error.RepoError(_("There is no Mercurial repository here"
4451 " (.hg not found)"))
4454 " (.hg not found)"))
4452 s = sshserver.sshserver(ui, repo)
4455 s = sshserver.sshserver(ui, repo)
4453 s.serve_forever()
4456 s.serve_forever()
4454
4457
4455 # this way we can check if something was given in the command-line
4458 # this way we can check if something was given in the command-line
4456 if opts.get('port'):
4459 if opts.get('port'):
4457 opts['port'] = util.getport(opts.get('port'))
4460 opts['port'] = util.getport(opts.get('port'))
4458
4461
4459 baseui = repo and repo.baseui or ui
4462 baseui = repo and repo.baseui or ui
4460 optlist = ("name templates style address port prefix ipv6"
4463 optlist = ("name templates style address port prefix ipv6"
4461 " accesslog errorlog certificate encoding")
4464 " accesslog errorlog certificate encoding")
4462 for o in optlist.split():
4465 for o in optlist.split():
4463 val = opts.get(o, '')
4466 val = opts.get(o, '')
4464 if val in (None, ''): # should check against default options instead
4467 if val in (None, ''): # should check against default options instead
4465 continue
4468 continue
4466 baseui.setconfig("web", o, val)
4469 baseui.setconfig("web", o, val)
4467 if repo and repo.ui != baseui:
4470 if repo and repo.ui != baseui:
4468 repo.ui.setconfig("web", o, val)
4471 repo.ui.setconfig("web", o, val)
4469
4472
4470 o = opts.get('web_conf') or opts.get('webdir_conf')
4473 o = opts.get('web_conf') or opts.get('webdir_conf')
4471 if not o:
4474 if not o:
4472 if not repo:
4475 if not repo:
4473 raise error.RepoError(_("There is no Mercurial repository"
4476 raise error.RepoError(_("There is no Mercurial repository"
4474 " here (.hg not found)"))
4477 " here (.hg not found)"))
4475 o = repo.root
4478 o = repo.root
4476
4479
4477 app = hgweb.hgweb(o, baseui=ui)
4480 app = hgweb.hgweb(o, baseui=ui)
4478
4481
4479 class service(object):
4482 class service(object):
4480 def init(self):
4483 def init(self):
4481 util.setsignalhandler()
4484 util.setsignalhandler()
4482 self.httpd = hgweb.server.create_server(ui, app)
4485 self.httpd = hgweb.server.create_server(ui, app)
4483
4486
4484 if opts['port'] and not ui.verbose:
4487 if opts['port'] and not ui.verbose:
4485 return
4488 return
4486
4489
4487 if self.httpd.prefix:
4490 if self.httpd.prefix:
4488 prefix = self.httpd.prefix.strip('/') + '/'
4491 prefix = self.httpd.prefix.strip('/') + '/'
4489 else:
4492 else:
4490 prefix = ''
4493 prefix = ''
4491
4494
4492 port = ':%d' % self.httpd.port
4495 port = ':%d' % self.httpd.port
4493 if port == ':80':
4496 if port == ':80':
4494 port = ''
4497 port = ''
4495
4498
4496 bindaddr = self.httpd.addr
4499 bindaddr = self.httpd.addr
4497 if bindaddr == '0.0.0.0':
4500 if bindaddr == '0.0.0.0':
4498 bindaddr = '*'
4501 bindaddr = '*'
4499 elif ':' in bindaddr: # IPv6
4502 elif ':' in bindaddr: # IPv6
4500 bindaddr = '[%s]' % bindaddr
4503 bindaddr = '[%s]' % bindaddr
4501
4504
4502 fqaddr = self.httpd.fqaddr
4505 fqaddr = self.httpd.fqaddr
4503 if ':' in fqaddr:
4506 if ':' in fqaddr:
4504 fqaddr = '[%s]' % fqaddr
4507 fqaddr = '[%s]' % fqaddr
4505 if opts['port']:
4508 if opts['port']:
4506 write = ui.status
4509 write = ui.status
4507 else:
4510 else:
4508 write = ui.write
4511 write = ui.write
4509 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4512 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4510 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4513 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4511
4514
4512 def run(self):
4515 def run(self):
4513 self.httpd.serve_forever()
4516 self.httpd.serve_forever()
4514
4517
4515 service = service()
4518 service = service()
4516
4519
4517 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4520 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4518
4521
4519 @command('showconfig|debugconfig',
4522 @command('showconfig|debugconfig',
4520 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4523 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4521 _('[-u] [NAME]...'))
4524 _('[-u] [NAME]...'))
4522 def showconfig(ui, repo, *values, **opts):
4525 def showconfig(ui, repo, *values, **opts):
4523 """show combined config settings from all hgrc files
4526 """show combined config settings from all hgrc files
4524
4527
4525 With no arguments, print names and values of all config items.
4528 With no arguments, print names and values of all config items.
4526
4529
4527 With one argument of the form section.name, print just the value
4530 With one argument of the form section.name, print just the value
4528 of that config item.
4531 of that config item.
4529
4532
4530 With multiple arguments, print names and values of all config
4533 With multiple arguments, print names and values of all config
4531 items with matching section names.
4534 items with matching section names.
4532
4535
4533 With --debug, the source (filename and line number) is printed
4536 With --debug, the source (filename and line number) is printed
4534 for each config item.
4537 for each config item.
4535
4538
4536 Returns 0 on success.
4539 Returns 0 on success.
4537 """
4540 """
4538
4541
4539 for f in scmutil.rcpath():
4542 for f in scmutil.rcpath():
4540 ui.debug(_('read config from: %s\n') % f)
4543 ui.debug(_('read config from: %s\n') % f)
4541 untrusted = bool(opts.get('untrusted'))
4544 untrusted = bool(opts.get('untrusted'))
4542 if values:
4545 if values:
4543 sections = [v for v in values if '.' not in v]
4546 sections = [v for v in values if '.' not in v]
4544 items = [v for v in values if '.' in v]
4547 items = [v for v in values if '.' in v]
4545 if len(items) > 1 or items and sections:
4548 if len(items) > 1 or items and sections:
4546 raise util.Abort(_('only one config item permitted'))
4549 raise util.Abort(_('only one config item permitted'))
4547 for section, name, value in ui.walkconfig(untrusted=untrusted):
4550 for section, name, value in ui.walkconfig(untrusted=untrusted):
4548 value = str(value).replace('\n', '\\n')
4551 value = str(value).replace('\n', '\\n')
4549 sectname = section + '.' + name
4552 sectname = section + '.' + name
4550 if values:
4553 if values:
4551 for v in values:
4554 for v in values:
4552 if v == section:
4555 if v == section:
4553 ui.debug('%s: ' %
4556 ui.debug('%s: ' %
4554 ui.configsource(section, name, untrusted))
4557 ui.configsource(section, name, untrusted))
4555 ui.write('%s=%s\n' % (sectname, value))
4558 ui.write('%s=%s\n' % (sectname, value))
4556 elif v == sectname:
4559 elif v == sectname:
4557 ui.debug('%s: ' %
4560 ui.debug('%s: ' %
4558 ui.configsource(section, name, untrusted))
4561 ui.configsource(section, name, untrusted))
4559 ui.write(value, '\n')
4562 ui.write(value, '\n')
4560 else:
4563 else:
4561 ui.debug('%s: ' %
4564 ui.debug('%s: ' %
4562 ui.configsource(section, name, untrusted))
4565 ui.configsource(section, name, untrusted))
4563 ui.write('%s=%s\n' % (sectname, value))
4566 ui.write('%s=%s\n' % (sectname, value))
4564
4567
4565 @command('^status|st',
4568 @command('^status|st',
4566 [('A', 'all', None, _('show status of all files')),
4569 [('A', 'all', None, _('show status of all files')),
4567 ('m', 'modified', None, _('show only modified files')),
4570 ('m', 'modified', None, _('show only modified files')),
4568 ('a', 'added', None, _('show only added files')),
4571 ('a', 'added', None, _('show only added files')),
4569 ('r', 'removed', None, _('show only removed files')),
4572 ('r', 'removed', None, _('show only removed files')),
4570 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4573 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4571 ('c', 'clean', None, _('show only files without changes')),
4574 ('c', 'clean', None, _('show only files without changes')),
4572 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4575 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4573 ('i', 'ignored', None, _('show only ignored files')),
4576 ('i', 'ignored', None, _('show only ignored files')),
4574 ('n', 'no-status', None, _('hide status prefix')),
4577 ('n', 'no-status', None, _('hide status prefix')),
4575 ('C', 'copies', None, _('show source of copied files')),
4578 ('C', 'copies', None, _('show source of copied files')),
4576 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4579 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4577 ('', 'rev', [], _('show difference from revision'), _('REV')),
4580 ('', 'rev', [], _('show difference from revision'), _('REV')),
4578 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4581 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4579 ] + walkopts + subrepoopts,
4582 ] + walkopts + subrepoopts,
4580 _('[OPTION]... [FILE]...'))
4583 _('[OPTION]... [FILE]...'))
4581 def status(ui, repo, *pats, **opts):
4584 def status(ui, repo, *pats, **opts):
4582 """show changed files in the working directory
4585 """show changed files in the working directory
4583
4586
4584 Show status of files in the repository. If names are given, only
4587 Show status of files in the repository. If names are given, only
4585 files that match are shown. Files that are clean or ignored or
4588 files that match are shown. Files that are clean or ignored or
4586 the source of a copy/move operation, are not listed unless
4589 the source of a copy/move operation, are not listed unless
4587 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4590 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4588 Unless options described with "show only ..." are given, the
4591 Unless options described with "show only ..." are given, the
4589 options -mardu are used.
4592 options -mardu are used.
4590
4593
4591 Option -q/--quiet hides untracked (unknown and ignored) files
4594 Option -q/--quiet hides untracked (unknown and ignored) files
4592 unless explicitly requested with -u/--unknown or -i/--ignored.
4595 unless explicitly requested with -u/--unknown or -i/--ignored.
4593
4596
4594 .. note::
4597 .. note::
4595 status may appear to disagree with diff if permissions have
4598 status may appear to disagree with diff if permissions have
4596 changed or a merge has occurred. The standard diff format does
4599 changed or a merge has occurred. The standard diff format does
4597 not report permission changes and diff only reports changes
4600 not report permission changes and diff only reports changes
4598 relative to one merge parent.
4601 relative to one merge parent.
4599
4602
4600 If one revision is given, it is used as the base revision.
4603 If one revision is given, it is used as the base revision.
4601 If two revisions are given, the differences between them are
4604 If two revisions are given, the differences between them are
4602 shown. The --change option can also be used as a shortcut to list
4605 shown. The --change option can also be used as a shortcut to list
4603 the changed files of a revision from its first parent.
4606 the changed files of a revision from its first parent.
4604
4607
4605 The codes used to show the status of files are::
4608 The codes used to show the status of files are::
4606
4609
4607 M = modified
4610 M = modified
4608 A = added
4611 A = added
4609 R = removed
4612 R = removed
4610 C = clean
4613 C = clean
4611 ! = missing (deleted by non-hg command, but still tracked)
4614 ! = missing (deleted by non-hg command, but still tracked)
4612 ? = not tracked
4615 ? = not tracked
4613 I = ignored
4616 I = ignored
4614 = origin of the previous file listed as A (added)
4617 = origin of the previous file listed as A (added)
4615
4618
4616 Returns 0 on success.
4619 Returns 0 on success.
4617 """
4620 """
4618
4621
4619 revs = opts.get('rev')
4622 revs = opts.get('rev')
4620 change = opts.get('change')
4623 change = opts.get('change')
4621
4624
4622 if revs and change:
4625 if revs and change:
4623 msg = _('cannot specify --rev and --change at the same time')
4626 msg = _('cannot specify --rev and --change at the same time')
4624 raise util.Abort(msg)
4627 raise util.Abort(msg)
4625 elif change:
4628 elif change:
4626 node2 = repo.lookup(change)
4629 node2 = repo.lookup(change)
4627 node1 = repo[node2].p1().node()
4630 node1 = repo[node2].p1().node()
4628 else:
4631 else:
4629 node1, node2 = scmutil.revpair(repo, revs)
4632 node1, node2 = scmutil.revpair(repo, revs)
4630
4633
4631 cwd = (pats and repo.getcwd()) or ''
4634 cwd = (pats and repo.getcwd()) or ''
4632 end = opts.get('print0') and '\0' or '\n'
4635 end = opts.get('print0') and '\0' or '\n'
4633 copy = {}
4636 copy = {}
4634 states = 'modified added removed deleted unknown ignored clean'.split()
4637 states = 'modified added removed deleted unknown ignored clean'.split()
4635 show = [k for k in states if opts.get(k)]
4638 show = [k for k in states if opts.get(k)]
4636 if opts.get('all'):
4639 if opts.get('all'):
4637 show += ui.quiet and (states[:4] + ['clean']) or states
4640 show += ui.quiet and (states[:4] + ['clean']) or states
4638 if not show:
4641 if not show:
4639 show = ui.quiet and states[:4] or states[:5]
4642 show = ui.quiet and states[:4] or states[:5]
4640
4643
4641 stat = repo.status(node1, node2, scmutil.match(repo, pats, opts),
4644 stat = repo.status(node1, node2, scmutil.match(repo, pats, opts),
4642 'ignored' in show, 'clean' in show, 'unknown' in show,
4645 'ignored' in show, 'clean' in show, 'unknown' in show,
4643 opts.get('subrepos'))
4646 opts.get('subrepos'))
4644 changestates = zip(states, 'MAR!?IC', stat)
4647 changestates = zip(states, 'MAR!?IC', stat)
4645
4648
4646 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4649 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4647 ctxn = repo[nullid]
4650 ctxn = repo[nullid]
4648 ctx1 = repo[node1]
4651 ctx1 = repo[node1]
4649 ctx2 = repo[node2]
4652 ctx2 = repo[node2]
4650 added = stat[1]
4653 added = stat[1]
4651 if node2 is None:
4654 if node2 is None:
4652 added = stat[0] + stat[1] # merged?
4655 added = stat[0] + stat[1] # merged?
4653
4656
4654 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4657 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4655 if k in added:
4658 if k in added:
4656 copy[k] = v
4659 copy[k] = v
4657 elif v in added:
4660 elif v in added:
4658 copy[v] = k
4661 copy[v] = k
4659
4662
4660 for state, char, files in changestates:
4663 for state, char, files in changestates:
4661 if state in show:
4664 if state in show:
4662 format = "%s %%s%s" % (char, end)
4665 format = "%s %%s%s" % (char, end)
4663 if opts.get('no_status'):
4666 if opts.get('no_status'):
4664 format = "%%s%s" % end
4667 format = "%%s%s" % end
4665
4668
4666 for f in files:
4669 for f in files:
4667 ui.write(format % repo.pathto(f, cwd),
4670 ui.write(format % repo.pathto(f, cwd),
4668 label='status.' + state)
4671 label='status.' + state)
4669 if f in copy:
4672 if f in copy:
4670 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4673 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4671 label='status.copied')
4674 label='status.copied')
4672
4675
4673 @command('^summary|sum',
4676 @command('^summary|sum',
4674 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4677 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4675 def summary(ui, repo, **opts):
4678 def summary(ui, repo, **opts):
4676 """summarize working directory state
4679 """summarize working directory state
4677
4680
4678 This generates a brief summary of the working directory state,
4681 This generates a brief summary of the working directory state,
4679 including parents, branch, commit status, and available updates.
4682 including parents, branch, commit status, and available updates.
4680
4683
4681 With the --remote option, this will check the default paths for
4684 With the --remote option, this will check the default paths for
4682 incoming and outgoing changes. This can be time-consuming.
4685 incoming and outgoing changes. This can be time-consuming.
4683
4686
4684 Returns 0 on success.
4687 Returns 0 on success.
4685 """
4688 """
4686
4689
4687 ctx = repo[None]
4690 ctx = repo[None]
4688 parents = ctx.parents()
4691 parents = ctx.parents()
4689 pnode = parents[0].node()
4692 pnode = parents[0].node()
4690
4693
4691 for p in parents:
4694 for p in parents:
4692 # label with log.changeset (instead of log.parent) since this
4695 # label with log.changeset (instead of log.parent) since this
4693 # shows a working directory parent *changeset*:
4696 # shows a working directory parent *changeset*:
4694 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4697 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4695 label='log.changeset')
4698 label='log.changeset')
4696 ui.write(' '.join(p.tags()), label='log.tag')
4699 ui.write(' '.join(p.tags()), label='log.tag')
4697 if p.bookmarks():
4700 if p.bookmarks():
4698 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
4701 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
4699 if p.rev() == -1:
4702 if p.rev() == -1:
4700 if not len(repo):
4703 if not len(repo):
4701 ui.write(_(' (empty repository)'))
4704 ui.write(_(' (empty repository)'))
4702 else:
4705 else:
4703 ui.write(_(' (no revision checked out)'))
4706 ui.write(_(' (no revision checked out)'))
4704 ui.write('\n')
4707 ui.write('\n')
4705 if p.description():
4708 if p.description():
4706 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4709 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4707 label='log.summary')
4710 label='log.summary')
4708
4711
4709 branch = ctx.branch()
4712 branch = ctx.branch()
4710 bheads = repo.branchheads(branch)
4713 bheads = repo.branchheads(branch)
4711 m = _('branch: %s\n') % branch
4714 m = _('branch: %s\n') % branch
4712 if branch != 'default':
4715 if branch != 'default':
4713 ui.write(m, label='log.branch')
4716 ui.write(m, label='log.branch')
4714 else:
4717 else:
4715 ui.status(m, label='log.branch')
4718 ui.status(m, label='log.branch')
4716
4719
4717 st = list(repo.status(unknown=True))[:6]
4720 st = list(repo.status(unknown=True))[:6]
4718
4721
4719 c = repo.dirstate.copies()
4722 c = repo.dirstate.copies()
4720 copied, renamed = [], []
4723 copied, renamed = [], []
4721 for d, s in c.iteritems():
4724 for d, s in c.iteritems():
4722 if s in st[2]:
4725 if s in st[2]:
4723 st[2].remove(s)
4726 st[2].remove(s)
4724 renamed.append(d)
4727 renamed.append(d)
4725 else:
4728 else:
4726 copied.append(d)
4729 copied.append(d)
4727 if d in st[1]:
4730 if d in st[1]:
4728 st[1].remove(d)
4731 st[1].remove(d)
4729 st.insert(3, renamed)
4732 st.insert(3, renamed)
4730 st.insert(4, copied)
4733 st.insert(4, copied)
4731
4734
4732 ms = mergemod.mergestate(repo)
4735 ms = mergemod.mergestate(repo)
4733 st.append([f for f in ms if ms[f] == 'u'])
4736 st.append([f for f in ms if ms[f] == 'u'])
4734
4737
4735 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4738 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4736 st.append(subs)
4739 st.append(subs)
4737
4740
4738 labels = [ui.label(_('%d modified'), 'status.modified'),
4741 labels = [ui.label(_('%d modified'), 'status.modified'),
4739 ui.label(_('%d added'), 'status.added'),
4742 ui.label(_('%d added'), 'status.added'),
4740 ui.label(_('%d removed'), 'status.removed'),
4743 ui.label(_('%d removed'), 'status.removed'),
4741 ui.label(_('%d renamed'), 'status.copied'),
4744 ui.label(_('%d renamed'), 'status.copied'),
4742 ui.label(_('%d copied'), 'status.copied'),
4745 ui.label(_('%d copied'), 'status.copied'),
4743 ui.label(_('%d deleted'), 'status.deleted'),
4746 ui.label(_('%d deleted'), 'status.deleted'),
4744 ui.label(_('%d unknown'), 'status.unknown'),
4747 ui.label(_('%d unknown'), 'status.unknown'),
4745 ui.label(_('%d ignored'), 'status.ignored'),
4748 ui.label(_('%d ignored'), 'status.ignored'),
4746 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4749 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4747 ui.label(_('%d subrepos'), 'status.modified')]
4750 ui.label(_('%d subrepos'), 'status.modified')]
4748 t = []
4751 t = []
4749 for s, l in zip(st, labels):
4752 for s, l in zip(st, labels):
4750 if s:
4753 if s:
4751 t.append(l % len(s))
4754 t.append(l % len(s))
4752
4755
4753 t = ', '.join(t)
4756 t = ', '.join(t)
4754 cleanworkdir = False
4757 cleanworkdir = False
4755
4758
4756 if len(parents) > 1:
4759 if len(parents) > 1:
4757 t += _(' (merge)')
4760 t += _(' (merge)')
4758 elif branch != parents[0].branch():
4761 elif branch != parents[0].branch():
4759 t += _(' (new branch)')
4762 t += _(' (new branch)')
4760 elif (parents[0].extra().get('close') and
4763 elif (parents[0].extra().get('close') and
4761 pnode in repo.branchheads(branch, closed=True)):
4764 pnode in repo.branchheads(branch, closed=True)):
4762 t += _(' (head closed)')
4765 t += _(' (head closed)')
4763 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4766 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4764 t += _(' (clean)')
4767 t += _(' (clean)')
4765 cleanworkdir = True
4768 cleanworkdir = True
4766 elif pnode not in bheads:
4769 elif pnode not in bheads:
4767 t += _(' (new branch head)')
4770 t += _(' (new branch head)')
4768
4771
4769 if cleanworkdir:
4772 if cleanworkdir:
4770 ui.status(_('commit: %s\n') % t.strip())
4773 ui.status(_('commit: %s\n') % t.strip())
4771 else:
4774 else:
4772 ui.write(_('commit: %s\n') % t.strip())
4775 ui.write(_('commit: %s\n') % t.strip())
4773
4776
4774 # all ancestors of branch heads - all ancestors of parent = new csets
4777 # all ancestors of branch heads - all ancestors of parent = new csets
4775 new = [0] * len(repo)
4778 new = [0] * len(repo)
4776 cl = repo.changelog
4779 cl = repo.changelog
4777 for a in [cl.rev(n) for n in bheads]:
4780 for a in [cl.rev(n) for n in bheads]:
4778 new[a] = 1
4781 new[a] = 1
4779 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4782 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4780 new[a] = 1
4783 new[a] = 1
4781 for a in [p.rev() for p in parents]:
4784 for a in [p.rev() for p in parents]:
4782 if a >= 0:
4785 if a >= 0:
4783 new[a] = 0
4786 new[a] = 0
4784 for a in cl.ancestors(*[p.rev() for p in parents]):
4787 for a in cl.ancestors(*[p.rev() for p in parents]):
4785 new[a] = 0
4788 new[a] = 0
4786 new = sum(new)
4789 new = sum(new)
4787
4790
4788 if new == 0:
4791 if new == 0:
4789 ui.status(_('update: (current)\n'))
4792 ui.status(_('update: (current)\n'))
4790 elif pnode not in bheads:
4793 elif pnode not in bheads:
4791 ui.write(_('update: %d new changesets (update)\n') % new)
4794 ui.write(_('update: %d new changesets (update)\n') % new)
4792 else:
4795 else:
4793 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4796 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4794 (new, len(bheads)))
4797 (new, len(bheads)))
4795
4798
4796 if opts.get('remote'):
4799 if opts.get('remote'):
4797 t = []
4800 t = []
4798 source, branches = hg.parseurl(ui.expandpath('default'))
4801 source, branches = hg.parseurl(ui.expandpath('default'))
4799 other = hg.peer(repo, {}, source)
4802 other = hg.peer(repo, {}, source)
4800 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4803 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4801 ui.debug('comparing with %s\n' % util.hidepassword(source))
4804 ui.debug('comparing with %s\n' % util.hidepassword(source))
4802 repo.ui.pushbuffer()
4805 repo.ui.pushbuffer()
4803 commoninc = discovery.findcommonincoming(repo, other)
4806 commoninc = discovery.findcommonincoming(repo, other)
4804 _common, incoming, _rheads = commoninc
4807 _common, incoming, _rheads = commoninc
4805 repo.ui.popbuffer()
4808 repo.ui.popbuffer()
4806 if incoming:
4809 if incoming:
4807 t.append(_('1 or more incoming'))
4810 t.append(_('1 or more incoming'))
4808
4811
4809 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4812 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4810 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4813 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4811 if source != dest:
4814 if source != dest:
4812 other = hg.peer(repo, {}, dest)
4815 other = hg.peer(repo, {}, dest)
4813 commoninc = None
4816 commoninc = None
4814 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4817 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4815 repo.ui.pushbuffer()
4818 repo.ui.pushbuffer()
4816 common, outheads = discovery.findcommonoutgoing(repo, other,
4819 common, outheads = discovery.findcommonoutgoing(repo, other,
4817 commoninc=commoninc)
4820 commoninc=commoninc)
4818 repo.ui.popbuffer()
4821 repo.ui.popbuffer()
4819 o = repo.changelog.findmissing(common=common, heads=outheads)
4822 o = repo.changelog.findmissing(common=common, heads=outheads)
4820 if o:
4823 if o:
4821 t.append(_('%d outgoing') % len(o))
4824 t.append(_('%d outgoing') % len(o))
4822 if 'bookmarks' in other.listkeys('namespaces'):
4825 if 'bookmarks' in other.listkeys('namespaces'):
4823 lmarks = repo.listkeys('bookmarks')
4826 lmarks = repo.listkeys('bookmarks')
4824 rmarks = other.listkeys('bookmarks')
4827 rmarks = other.listkeys('bookmarks')
4825 diff = set(rmarks) - set(lmarks)
4828 diff = set(rmarks) - set(lmarks)
4826 if len(diff) > 0:
4829 if len(diff) > 0:
4827 t.append(_('%d incoming bookmarks') % len(diff))
4830 t.append(_('%d incoming bookmarks') % len(diff))
4828 diff = set(lmarks) - set(rmarks)
4831 diff = set(lmarks) - set(rmarks)
4829 if len(diff) > 0:
4832 if len(diff) > 0:
4830 t.append(_('%d outgoing bookmarks') % len(diff))
4833 t.append(_('%d outgoing bookmarks') % len(diff))
4831
4834
4832 if t:
4835 if t:
4833 ui.write(_('remote: %s\n') % (', '.join(t)))
4836 ui.write(_('remote: %s\n') % (', '.join(t)))
4834 else:
4837 else:
4835 ui.status(_('remote: (synced)\n'))
4838 ui.status(_('remote: (synced)\n'))
4836
4839
4837 @command('tag',
4840 @command('tag',
4838 [('f', 'force', None, _('force tag')),
4841 [('f', 'force', None, _('force tag')),
4839 ('l', 'local', None, _('make the tag local')),
4842 ('l', 'local', None, _('make the tag local')),
4840 ('r', 'rev', '', _('revision to tag'), _('REV')),
4843 ('r', 'rev', '', _('revision to tag'), _('REV')),
4841 ('', 'remove', None, _('remove a tag')),
4844 ('', 'remove', None, _('remove a tag')),
4842 # -l/--local is already there, commitopts cannot be used
4845 # -l/--local is already there, commitopts cannot be used
4843 ('e', 'edit', None, _('edit commit message')),
4846 ('e', 'edit', None, _('edit commit message')),
4844 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
4847 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
4845 ] + commitopts2,
4848 ] + commitopts2,
4846 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
4849 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
4847 def tag(ui, repo, name1, *names, **opts):
4850 def tag(ui, repo, name1, *names, **opts):
4848 """add one or more tags for the current or given revision
4851 """add one or more tags for the current or given revision
4849
4852
4850 Name a particular revision using <name>.
4853 Name a particular revision using <name>.
4851
4854
4852 Tags are used to name particular revisions of the repository and are
4855 Tags are used to name particular revisions of the repository and are
4853 very useful to compare different revisions, to go back to significant
4856 very useful to compare different revisions, to go back to significant
4854 earlier versions or to mark branch points as releases, etc. Changing
4857 earlier versions or to mark branch points as releases, etc. Changing
4855 an existing tag is normally disallowed; use -f/--force to override.
4858 an existing tag is normally disallowed; use -f/--force to override.
4856
4859
4857 If no revision is given, the parent of the working directory is
4860 If no revision is given, the parent of the working directory is
4858 used, or tip if no revision is checked out.
4861 used, or tip if no revision is checked out.
4859
4862
4860 To facilitate version control, distribution, and merging of tags,
4863 To facilitate version control, distribution, and merging of tags,
4861 they are stored as a file named ".hgtags" which is managed similarly
4864 they are stored as a file named ".hgtags" which is managed similarly
4862 to other project files and can be hand-edited if necessary. This
4865 to other project files and can be hand-edited if necessary. This
4863 also means that tagging creates a new commit. The file
4866 also means that tagging creates a new commit. The file
4864 ".hg/localtags" is used for local tags (not shared among
4867 ".hg/localtags" is used for local tags (not shared among
4865 repositories).
4868 repositories).
4866
4869
4867 Tag commits are usually made at the head of a branch. If the parent
4870 Tag commits are usually made at the head of a branch. If the parent
4868 of the working directory is not a branch head, :hg:`tag` aborts; use
4871 of the working directory is not a branch head, :hg:`tag` aborts; use
4869 -f/--force to force the tag commit to be based on a non-head
4872 -f/--force to force the tag commit to be based on a non-head
4870 changeset.
4873 changeset.
4871
4874
4872 See :hg:`help dates` for a list of formats valid for -d/--date.
4875 See :hg:`help dates` for a list of formats valid for -d/--date.
4873
4876
4874 Since tag names have priority over branch names during revision
4877 Since tag names have priority over branch names during revision
4875 lookup, using an existing branch name as a tag name is discouraged.
4878 lookup, using an existing branch name as a tag name is discouraged.
4876
4879
4877 Returns 0 on success.
4880 Returns 0 on success.
4878 """
4881 """
4879
4882
4880 rev_ = "."
4883 rev_ = "."
4881 names = [t.strip() for t in (name1,) + names]
4884 names = [t.strip() for t in (name1,) + names]
4882 if len(names) != len(set(names)):
4885 if len(names) != len(set(names)):
4883 raise util.Abort(_('tag names must be unique'))
4886 raise util.Abort(_('tag names must be unique'))
4884 for n in names:
4887 for n in names:
4885 if n in ['tip', '.', 'null']:
4888 if n in ['tip', '.', 'null']:
4886 raise util.Abort(_("the name '%s' is reserved") % n)
4889 raise util.Abort(_("the name '%s' is reserved") % n)
4887 if not n:
4890 if not n:
4888 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4891 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4889 if opts.get('rev') and opts.get('remove'):
4892 if opts.get('rev') and opts.get('remove'):
4890 raise util.Abort(_("--rev and --remove are incompatible"))
4893 raise util.Abort(_("--rev and --remove are incompatible"))
4891 if opts.get('rev'):
4894 if opts.get('rev'):
4892 rev_ = opts['rev']
4895 rev_ = opts['rev']
4893 message = opts.get('message')
4896 message = opts.get('message')
4894 if opts.get('remove'):
4897 if opts.get('remove'):
4895 expectedtype = opts.get('local') and 'local' or 'global'
4898 expectedtype = opts.get('local') and 'local' or 'global'
4896 for n in names:
4899 for n in names:
4897 if not repo.tagtype(n):
4900 if not repo.tagtype(n):
4898 raise util.Abort(_("tag '%s' does not exist") % n)
4901 raise util.Abort(_("tag '%s' does not exist") % n)
4899 if repo.tagtype(n) != expectedtype:
4902 if repo.tagtype(n) != expectedtype:
4900 if expectedtype == 'global':
4903 if expectedtype == 'global':
4901 raise util.Abort(_("tag '%s' is not a global tag") % n)
4904 raise util.Abort(_("tag '%s' is not a global tag") % n)
4902 else:
4905 else:
4903 raise util.Abort(_("tag '%s' is not a local tag") % n)
4906 raise util.Abort(_("tag '%s' is not a local tag") % n)
4904 rev_ = nullid
4907 rev_ = nullid
4905 if not message:
4908 if not message:
4906 # we don't translate commit messages
4909 # we don't translate commit messages
4907 message = 'Removed tag %s' % ', '.join(names)
4910 message = 'Removed tag %s' % ', '.join(names)
4908 elif not opts.get('force'):
4911 elif not opts.get('force'):
4909 for n in names:
4912 for n in names:
4910 if n in repo.tags():
4913 if n in repo.tags():
4911 raise util.Abort(_("tag '%s' already exists "
4914 raise util.Abort(_("tag '%s' already exists "
4912 "(use -f to force)") % n)
4915 "(use -f to force)") % n)
4913 if not opts.get('local'):
4916 if not opts.get('local'):
4914 p1, p2 = repo.dirstate.parents()
4917 p1, p2 = repo.dirstate.parents()
4915 if p2 != nullid:
4918 if p2 != nullid:
4916 raise util.Abort(_('uncommitted merge'))
4919 raise util.Abort(_('uncommitted merge'))
4917 bheads = repo.branchheads()
4920 bheads = repo.branchheads()
4918 if not opts.get('force') and bheads and p1 not in bheads:
4921 if not opts.get('force') and bheads and p1 not in bheads:
4919 raise util.Abort(_('not at a branch head (use -f to force)'))
4922 raise util.Abort(_('not at a branch head (use -f to force)'))
4920 r = scmutil.revsingle(repo, rev_).node()
4923 r = scmutil.revsingle(repo, rev_).node()
4921
4924
4922 if not message:
4925 if not message:
4923 # we don't translate commit messages
4926 # we don't translate commit messages
4924 message = ('Added tag %s for changeset %s' %
4927 message = ('Added tag %s for changeset %s' %
4925 (', '.join(names), short(r)))
4928 (', '.join(names), short(r)))
4926
4929
4927 date = opts.get('date')
4930 date = opts.get('date')
4928 if date:
4931 if date:
4929 date = util.parsedate(date)
4932 date = util.parsedate(date)
4930
4933
4931 if opts.get('edit'):
4934 if opts.get('edit'):
4932 message = ui.edit(message, ui.username())
4935 message = ui.edit(message, ui.username())
4933
4936
4934 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4937 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4935
4938
4936 @command('tags', [], '')
4939 @command('tags', [], '')
4937 def tags(ui, repo):
4940 def tags(ui, repo):
4938 """list repository tags
4941 """list repository tags
4939
4942
4940 This lists both regular and local tags. When the -v/--verbose
4943 This lists both regular and local tags. When the -v/--verbose
4941 switch is used, a third column "local" is printed for local tags.
4944 switch is used, a third column "local" is printed for local tags.
4942
4945
4943 Returns 0 on success.
4946 Returns 0 on success.
4944 """
4947 """
4945
4948
4946 hexfunc = ui.debugflag and hex or short
4949 hexfunc = ui.debugflag and hex or short
4947 tagtype = ""
4950 tagtype = ""
4948
4951
4949 for t, n in reversed(repo.tagslist()):
4952 for t, n in reversed(repo.tagslist()):
4950 if ui.quiet:
4953 if ui.quiet:
4951 ui.write("%s\n" % t)
4954 ui.write("%s\n" % t)
4952 continue
4955 continue
4953
4956
4954 hn = hexfunc(n)
4957 hn = hexfunc(n)
4955 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4958 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4956 spaces = " " * (30 - encoding.colwidth(t))
4959 spaces = " " * (30 - encoding.colwidth(t))
4957
4960
4958 if ui.verbose:
4961 if ui.verbose:
4959 if repo.tagtype(t) == 'local':
4962 if repo.tagtype(t) == 'local':
4960 tagtype = " local"
4963 tagtype = " local"
4961 else:
4964 else:
4962 tagtype = ""
4965 tagtype = ""
4963 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4966 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4964
4967
4965 @command('tip',
4968 @command('tip',
4966 [('p', 'patch', None, _('show patch')),
4969 [('p', 'patch', None, _('show patch')),
4967 ('g', 'git', None, _('use git extended diff format')),
4970 ('g', 'git', None, _('use git extended diff format')),
4968 ] + templateopts,
4971 ] + templateopts,
4969 _('[-p] [-g]'))
4972 _('[-p] [-g]'))
4970 def tip(ui, repo, **opts):
4973 def tip(ui, repo, **opts):
4971 """show the tip revision
4974 """show the tip revision
4972
4975
4973 The tip revision (usually just called the tip) is the changeset
4976 The tip revision (usually just called the tip) is the changeset
4974 most recently added to the repository (and therefore the most
4977 most recently added to the repository (and therefore the most
4975 recently changed head).
4978 recently changed head).
4976
4979
4977 If you have just made a commit, that commit will be the tip. If
4980 If you have just made a commit, that commit will be the tip. If
4978 you have just pulled changes from another repository, the tip of
4981 you have just pulled changes from another repository, the tip of
4979 that repository becomes the current tip. The "tip" tag is special
4982 that repository becomes the current tip. The "tip" tag is special
4980 and cannot be renamed or assigned to a different changeset.
4983 and cannot be renamed or assigned to a different changeset.
4981
4984
4982 Returns 0 on success.
4985 Returns 0 on success.
4983 """
4986 """
4984 displayer = cmdutil.show_changeset(ui, repo, opts)
4987 displayer = cmdutil.show_changeset(ui, repo, opts)
4985 displayer.show(repo[len(repo) - 1])
4988 displayer.show(repo[len(repo) - 1])
4986 displayer.close()
4989 displayer.close()
4987
4990
4988 @command('unbundle',
4991 @command('unbundle',
4989 [('u', 'update', None,
4992 [('u', 'update', None,
4990 _('update to new branch head if changesets were unbundled'))],
4993 _('update to new branch head if changesets were unbundled'))],
4991 _('[-u] FILE...'))
4994 _('[-u] FILE...'))
4992 def unbundle(ui, repo, fname1, *fnames, **opts):
4995 def unbundle(ui, repo, fname1, *fnames, **opts):
4993 """apply one or more changegroup files
4996 """apply one or more changegroup files
4994
4997
4995 Apply one or more compressed changegroup files generated by the
4998 Apply one or more compressed changegroup files generated by the
4996 bundle command.
4999 bundle command.
4997
5000
4998 Returns 0 on success, 1 if an update has unresolved files.
5001 Returns 0 on success, 1 if an update has unresolved files.
4999 """
5002 """
5000 fnames = (fname1,) + fnames
5003 fnames = (fname1,) + fnames
5001
5004
5002 lock = repo.lock()
5005 lock = repo.lock()
5003 wc = repo['.']
5006 wc = repo['.']
5004 try:
5007 try:
5005 for fname in fnames:
5008 for fname in fnames:
5006 f = url.open(ui, fname)
5009 f = url.open(ui, fname)
5007 gen = changegroup.readbundle(f, fname)
5010 gen = changegroup.readbundle(f, fname)
5008 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5011 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5009 lock=lock)
5012 lock=lock)
5010 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5013 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5011 finally:
5014 finally:
5012 lock.release()
5015 lock.release()
5013 return postincoming(ui, repo, modheads, opts.get('update'), None)
5016 return postincoming(ui, repo, modheads, opts.get('update'), None)
5014
5017
5015 @command('^update|up|checkout|co',
5018 @command('^update|up|checkout|co',
5016 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5019 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5017 ('c', 'check', None,
5020 ('c', 'check', None,
5018 _('update across branches if no uncommitted changes')),
5021 _('update across branches if no uncommitted changes')),
5019 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5022 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5020 ('r', 'rev', '', _('revision'), _('REV'))],
5023 ('r', 'rev', '', _('revision'), _('REV'))],
5021 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5024 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5022 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5025 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5023 """update working directory (or switch revisions)
5026 """update working directory (or switch revisions)
5024
5027
5025 Update the repository's working directory to the specified
5028 Update the repository's working directory to the specified
5026 changeset. If no changeset is specified, update to the tip of the
5029 changeset. If no changeset is specified, update to the tip of the
5027 current named branch.
5030 current named branch.
5028
5031
5029 If the changeset is not a descendant of the working directory's
5032 If the changeset is not a descendant of the working directory's
5030 parent, the update is aborted. With the -c/--check option, the
5033 parent, the update is aborted. With the -c/--check option, the
5031 working directory is checked for uncommitted changes; if none are
5034 working directory is checked for uncommitted changes; if none are
5032 found, the working directory is updated to the specified
5035 found, the working directory is updated to the specified
5033 changeset.
5036 changeset.
5034
5037
5035 The following rules apply when the working directory contains
5038 The following rules apply when the working directory contains
5036 uncommitted changes:
5039 uncommitted changes:
5037
5040
5038 1. If neither -c/--check nor -C/--clean is specified, and if
5041 1. If neither -c/--check nor -C/--clean is specified, and if
5039 the requested changeset is an ancestor or descendant of
5042 the requested changeset is an ancestor or descendant of
5040 the working directory's parent, the uncommitted changes
5043 the working directory's parent, the uncommitted changes
5041 are merged into the requested changeset and the merged
5044 are merged into the requested changeset and the merged
5042 result is left uncommitted. If the requested changeset is
5045 result is left uncommitted. If the requested changeset is
5043 not an ancestor or descendant (that is, it is on another
5046 not an ancestor or descendant (that is, it is on another
5044 branch), the update is aborted and the uncommitted changes
5047 branch), the update is aborted and the uncommitted changes
5045 are preserved.
5048 are preserved.
5046
5049
5047 2. With the -c/--check option, the update is aborted and the
5050 2. With the -c/--check option, the update is aborted and the
5048 uncommitted changes are preserved.
5051 uncommitted changes are preserved.
5049
5052
5050 3. With the -C/--clean option, uncommitted changes are discarded and
5053 3. With the -C/--clean option, uncommitted changes are discarded and
5051 the working directory is updated to the requested changeset.
5054 the working directory is updated to the requested changeset.
5052
5055
5053 Use null as the changeset to remove the working directory (like
5056 Use null as the changeset to remove the working directory (like
5054 :hg:`clone -U`).
5057 :hg:`clone -U`).
5055
5058
5056 If you want to update just one file to an older changeset, use
5059 If you want to update just one file to an older changeset, use
5057 :hg:`revert`.
5060 :hg:`revert`.
5058
5061
5059 See :hg:`help dates` for a list of formats valid for -d/--date.
5062 See :hg:`help dates` for a list of formats valid for -d/--date.
5060
5063
5061 Returns 0 on success, 1 if there are unresolved files.
5064 Returns 0 on success, 1 if there are unresolved files.
5062 """
5065 """
5063 if rev and node:
5066 if rev and node:
5064 raise util.Abort(_("please specify just one revision"))
5067 raise util.Abort(_("please specify just one revision"))
5065
5068
5066 if rev is None or rev == '':
5069 if rev is None or rev == '':
5067 rev = node
5070 rev = node
5068
5071
5069 # if we defined a bookmark, we have to remember the original bookmark name
5072 # if we defined a bookmark, we have to remember the original bookmark name
5070 brev = rev
5073 brev = rev
5071 rev = scmutil.revsingle(repo, rev, rev).rev()
5074 rev = scmutil.revsingle(repo, rev, rev).rev()
5072
5075
5073 if check and clean:
5076 if check and clean:
5074 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5077 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5075
5078
5076 if check:
5079 if check:
5077 # we could use dirty() but we can ignore merge and branch trivia
5080 # we could use dirty() but we can ignore merge and branch trivia
5078 c = repo[None]
5081 c = repo[None]
5079 if c.modified() or c.added() or c.removed():
5082 if c.modified() or c.added() or c.removed():
5080 raise util.Abort(_("uncommitted local changes"))
5083 raise util.Abort(_("uncommitted local changes"))
5081
5084
5082 if date:
5085 if date:
5083 if rev is not None:
5086 if rev is not None:
5084 raise util.Abort(_("you can't specify a revision and a date"))
5087 raise util.Abort(_("you can't specify a revision and a date"))
5085 rev = cmdutil.finddate(ui, repo, date)
5088 rev = cmdutil.finddate(ui, repo, date)
5086
5089
5087 if clean or check:
5090 if clean or check:
5088 ret = hg.clean(repo, rev)
5091 ret = hg.clean(repo, rev)
5089 else:
5092 else:
5090 ret = hg.update(repo, rev)
5093 ret = hg.update(repo, rev)
5091
5094
5092 if brev in repo._bookmarks:
5095 if brev in repo._bookmarks:
5093 bookmarks.setcurrent(repo, brev)
5096 bookmarks.setcurrent(repo, brev)
5094
5097
5095 return ret
5098 return ret
5096
5099
5097 @command('verify', [])
5100 @command('verify', [])
5098 def verify(ui, repo):
5101 def verify(ui, repo):
5099 """verify the integrity of the repository
5102 """verify the integrity of the repository
5100
5103
5101 Verify the integrity of the current repository.
5104 Verify the integrity of the current repository.
5102
5105
5103 This will perform an extensive check of the repository's
5106 This will perform an extensive check of the repository's
5104 integrity, validating the hashes and checksums of each entry in
5107 integrity, validating the hashes and checksums of each entry in
5105 the changelog, manifest, and tracked files, as well as the
5108 the changelog, manifest, and tracked files, as well as the
5106 integrity of their crosslinks and indices.
5109 integrity of their crosslinks and indices.
5107
5110
5108 Returns 0 on success, 1 if errors are encountered.
5111 Returns 0 on success, 1 if errors are encountered.
5109 """
5112 """
5110 return hg.verify(repo)
5113 return hg.verify(repo)
5111
5114
5112 @command('version', [])
5115 @command('version', [])
5113 def version_(ui):
5116 def version_(ui):
5114 """output version and copyright information"""
5117 """output version and copyright information"""
5115 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5118 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5116 % util.version())
5119 % util.version())
5117 ui.status(_(
5120 ui.status(_(
5118 "(see http://mercurial.selenic.com for more information)\n"
5121 "(see http://mercurial.selenic.com for more information)\n"
5119 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5122 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5120 "This is free software; see the source for copying conditions. "
5123 "This is free software; see the source for copying conditions. "
5121 "There is NO\nwarranty; "
5124 "There is NO\nwarranty; "
5122 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5125 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5123 ))
5126 ))
5124
5127
5125 norepo = ("clone init version help debugcommands debugcomplete"
5128 norepo = ("clone init version help debugcommands debugcomplete"
5126 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5129 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5127 " debugknown debuggetbundle debugbundle")
5130 " debugknown debuggetbundle debugbundle")
5128 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5131 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5129 " debugdata debugindex debugindexdot debugrevlog")
5132 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,267 +1,267 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 copy
16 copy
17 diff
17 diff
18 export
18 export
19 forget
19 forget
20 grep
20 grep
21 heads
21 heads
22 help
22 help
23 identify
23 identify
24 import
24 import
25 incoming
25 incoming
26 init
26 init
27 locate
27 locate
28 log
28 log
29 manifest
29 manifest
30 merge
30 merge
31 outgoing
31 outgoing
32 parents
32 parents
33 paths
33 paths
34 pull
34 pull
35 push
35 push
36 recover
36 recover
37 remove
37 remove
38 rename
38 rename
39 resolve
39 resolve
40 revert
40 revert
41 rollback
41 rollback
42 root
42 root
43 serve
43 serve
44 showconfig
44 showconfig
45 status
45 status
46 summary
46 summary
47 tag
47 tag
48 tags
48 tags
49 tip
49 tip
50 unbundle
50 unbundle
51 update
51 update
52 verify
52 verify
53 version
53 version
54
54
55 Show all commands that start with "a"
55 Show all commands that start with "a"
56 $ hg debugcomplete a
56 $ hg debugcomplete a
57 add
57 add
58 addremove
58 addremove
59 annotate
59 annotate
60 archive
60 archive
61
61
62 Do not show debug commands if there are other candidates
62 Do not show debug commands if there are other candidates
63 $ hg debugcomplete d
63 $ hg debugcomplete d
64 diff
64 diff
65
65
66 Show debug commands if there are no other candidates
66 Show debug commands if there are no other candidates
67 $ hg debugcomplete debug
67 $ hg debugcomplete debug
68 debugancestor
68 debugancestor
69 debugbuilddag
69 debugbuilddag
70 debugbundle
70 debugbundle
71 debugcheckstate
71 debugcheckstate
72 debugcommands
72 debugcommands
73 debugcomplete
73 debugcomplete
74 debugconfig
74 debugconfig
75 debugdag
75 debugdag
76 debugdata
76 debugdata
77 debugdate
77 debugdate
78 debugdiscovery
78 debugdiscovery
79 debugfileset
79 debugfileset
80 debugfsinfo
80 debugfsinfo
81 debuggetbundle
81 debuggetbundle
82 debugignore
82 debugignore
83 debugindex
83 debugindex
84 debugindexdot
84 debugindexdot
85 debuginstall
85 debuginstall
86 debugknown
86 debugknown
87 debugpushkey
87 debugpushkey
88 debugrebuildstate
88 debugrebuildstate
89 debugrename
89 debugrename
90 debugrevlog
90 debugrevlog
91 debugrevspec
91 debugrevspec
92 debugsetparents
92 debugsetparents
93 debugstate
93 debugstate
94 debugsub
94 debugsub
95 debugwalk
95 debugwalk
96 debugwireargs
96 debugwireargs
97
97
98 Do not show the alias of a debug command if there are other candidates
98 Do not show the alias of a debug command if there are other candidates
99 (this should hide rawcommit)
99 (this should hide rawcommit)
100 $ hg debugcomplete r
100 $ hg debugcomplete r
101 recover
101 recover
102 remove
102 remove
103 rename
103 rename
104 resolve
104 resolve
105 revert
105 revert
106 rollback
106 rollback
107 root
107 root
108 Show the alias of a debug command if there are no other candidates
108 Show the alias of a debug command if there are no other candidates
109 $ hg debugcomplete rawc
109 $ hg debugcomplete rawc
110
110
111
111
112 Show the global options
112 Show the global options
113 $ hg debugcomplete --options | sort
113 $ hg debugcomplete --options | sort
114 --config
114 --config
115 --cwd
115 --cwd
116 --debug
116 --debug
117 --debugger
117 --debugger
118 --encoding
118 --encoding
119 --encodingmode
119 --encodingmode
120 --help
120 --help
121 --noninteractive
121 --noninteractive
122 --profile
122 --profile
123 --quiet
123 --quiet
124 --repository
124 --repository
125 --time
125 --time
126 --traceback
126 --traceback
127 --verbose
127 --verbose
128 --version
128 --version
129 -R
129 -R
130 -h
130 -h
131 -q
131 -q
132 -v
132 -v
133 -y
133 -y
134
134
135 Show the options for the "serve" command
135 Show the options for the "serve" command
136 $ hg debugcomplete --options serve | sort
136 $ hg debugcomplete --options serve | sort
137 --accesslog
137 --accesslog
138 --address
138 --address
139 --certificate
139 --certificate
140 --config
140 --config
141 --cwd
141 --cwd
142 --daemon
142 --daemon
143 --daemon-pipefds
143 --daemon-pipefds
144 --debug
144 --debug
145 --debugger
145 --debugger
146 --encoding
146 --encoding
147 --encodingmode
147 --encodingmode
148 --errorlog
148 --errorlog
149 --help
149 --help
150 --ipv6
150 --ipv6
151 --name
151 --name
152 --noninteractive
152 --noninteractive
153 --pid-file
153 --pid-file
154 --port
154 --port
155 --prefix
155 --prefix
156 --profile
156 --profile
157 --quiet
157 --quiet
158 --repository
158 --repository
159 --stdio
159 --stdio
160 --style
160 --style
161 --templates
161 --templates
162 --time
162 --time
163 --traceback
163 --traceback
164 --verbose
164 --verbose
165 --version
165 --version
166 --web-conf
166 --web-conf
167 -6
167 -6
168 -A
168 -A
169 -E
169 -E
170 -R
170 -R
171 -a
171 -a
172 -d
172 -d
173 -h
173 -h
174 -n
174 -n
175 -p
175 -p
176 -q
176 -q
177 -t
177 -t
178 -v
178 -v
179 -y
179 -y
180
180
181 Show an error if we use --options with an ambiguous abbreviation
181 Show an error if we use --options with an ambiguous abbreviation
182 $ hg debugcomplete --options s
182 $ hg debugcomplete --options s
183 hg: command 's' is ambiguous:
183 hg: command 's' is ambiguous:
184 serve showconfig status summary
184 serve showconfig status summary
185 [255]
185 [255]
186
186
187 Show all commands + options
187 Show all commands + options
188 $ hg debugcommands
188 $ hg debugcommands
189 add: include, exclude, subrepos, dry-run
189 add: include, exclude, subrepos, dry-run
190 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
190 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
191 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
191 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
192 commit: addremove, close-branch, include, exclude, message, logfile, date, user
192 commit: addremove, close-branch, include, exclude, message, logfile, date, user
193 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
193 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
194 export: output, switch-parent, rev, text, git, nodates
194 export: output, switch-parent, rev, text, git, nodates
195 forget: include, exclude
195 forget: include, exclude
196 init: ssh, remotecmd, insecure
196 init: ssh, remotecmd, insecure
197 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
197 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
198 merge: force, tool, rev, preview
198 merge: force, tool, rev, preview
199 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
199 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
200 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
200 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
201 remove: after, force, include, exclude
201 remove: after, force, include, exclude
202 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
202 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
203 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
203 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
204 summary: remote
204 summary: remote
205 update: clean, check, date, rev
205 update: clean, check, date, rev
206 addremove: similarity, include, exclude, dry-run
206 addremove: similarity, include, exclude, dry-run
207 archive: no-decode, prefix, rev, type, subrepos, include, exclude
207 archive: no-decode, prefix, rev, type, subrepos, include, exclude
208 backout: merge, parent, tool, rev, include, exclude, message, logfile, date, user
208 backout: merge, parent, tool, rev, include, exclude, message, logfile, date, user
209 bisect: reset, good, bad, skip, extend, command, noupdate
209 bisect: reset, good, bad, skip, extend, command, noupdate
210 bookmarks: force, rev, delete, rename, inactive
210 bookmarks: force, rev, delete, rename, inactive
211 branch: force, clean
211 branch: force, clean
212 branches: active, closed
212 branches: active, closed
213 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
213 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
214 cat: output, rev, decode, include, exclude
214 cat: output, rev, decode, include, exclude
215 copy: after, force, include, exclude, dry-run
215 copy: after, force, include, exclude, dry-run
216 debugancestor:
216 debugancestor:
217 debugbuilddag: mergeable-file, overwritten-file, new-file
217 debugbuilddag: mergeable-file, overwritten-file, new-file
218 debugbundle: all
218 debugbundle: all
219 debugcheckstate:
219 debugcheckstate:
220 debugcommands:
220 debugcommands:
221 debugcomplete: options
221 debugcomplete: options
222 debugdag: tags, branches, dots, spaces
222 debugdag: tags, branches, dots, spaces
223 debugdata: changelog, manifest
223 debugdata: changelog, manifest
224 debugdate: extended
224 debugdate: extended
225 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
225 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
226 debugfileset:
226 debugfileset:
227 debugfsinfo:
227 debugfsinfo:
228 debuggetbundle: head, common, type
228 debuggetbundle: head, common, type
229 debugignore:
229 debugignore:
230 debugindex: changelog, manifest, format
230 debugindex: changelog, manifest, format
231 debugindexdot:
231 debugindexdot:
232 debuginstall:
232 debuginstall:
233 debugknown:
233 debugknown:
234 debugpushkey:
234 debugpushkey:
235 debugrebuildstate: rev
235 debugrebuildstate: rev
236 debugrename: rev
236 debugrename: rev
237 debugrevlog: changelog, manifest, dump
237 debugrevlog: changelog, manifest, dump
238 debugrevspec:
238 debugrevspec:
239 debugsetparents:
239 debugsetparents:
240 debugstate: nodates, datesort
240 debugstate: nodates, datesort
241 debugsub: rev
241 debugsub: rev
242 debugwalk: include, exclude
242 debugwalk: include, exclude
243 debugwireargs: three, four, five, ssh, remotecmd, insecure
243 debugwireargs: three, four, five, ssh, remotecmd, insecure
244 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
244 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
245 heads: rev, topo, active, closed, style, template
245 heads: rev, topo, active, closed, style, template
246 help: extension, command
246 help: extension, command
247 identify: rev, num, id, branch, tags, bookmarks
247 identify: rev, num, id, branch, tags, bookmarks
248 import: strip, base, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
248 import: strip, base, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
249 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
249 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
250 locate: rev, print0, fullpath, include, exclude
250 locate: rev, print0, fullpath, include, exclude
251 manifest: rev, all
251 manifest: rev, all
252 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
252 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
253 parents: rev, style, template
253 parents: rev, style, template
254 paths:
254 paths:
255 recover:
255 recover:
256 rename: after, force, include, exclude, dry-run
256 rename: after, force, include, exclude, dry-run
257 resolve: all, list, mark, unmark, tool, no-status, include, exclude
257 resolve: all, list, mark, unmark, tool, no-status, include, exclude
258 revert: all, date, rev, no-backup, include, exclude, dry-run
258 revert: all, date, rev, no-backup, include, exclude, dry-run
259 rollback: dry-run
259 rollback: dry-run
260 root:
260 root:
261 showconfig: untrusted
261 showconfig: untrusted
262 tag: force, local, rev, remove, edit, message, date, user
262 tag: force, local, rev, remove, edit, message, date, user
263 tags:
263 tags:
264 tip: patch, git, style, template
264 tip: patch, git, style, template
265 unbundle: update
265 unbundle: update
266 verify:
266 verify:
267 version:
267 version:
@@ -1,1140 +1,1158 b''
1 $ hg init a
1 $ hg init a
2
2
3 $ cd a
3 $ cd a
4 $ echo a > a
4 $ echo a > a
5 $ hg ci -Ama -d '1 0'
5 $ hg ci -Ama -d '1 0'
6 adding a
6 adding a
7
7
8 $ hg cp a b
8 $ hg cp a b
9 $ hg ci -mb -d '2 0'
9 $ hg ci -mb -d '2 0'
10
10
11 $ mkdir dir
11 $ mkdir dir
12 $ hg mv b dir
12 $ hg mv b dir
13 $ hg ci -mc -d '3 0'
13 $ hg ci -mc -d '3 0'
14
14
15 $ hg mv a b
15 $ hg mv a b
16 $ echo a > d
16 $ echo a > d
17 $ hg add d
17 $ hg add d
18 $ hg ci -md -d '4 0'
18 $ hg ci -md -d '4 0'
19
19
20 $ hg mv dir/b e
20 $ hg mv dir/b e
21 $ hg ci -me -d '5 0'
21 $ hg ci -me -d '5 0'
22
22
23 $ hg log a
23 $ hg log a
24 changeset: 0:8580ff50825a
24 changeset: 0:8580ff50825a
25 user: test
25 user: test
26 date: Thu Jan 01 00:00:01 1970 +0000
26 date: Thu Jan 01 00:00:01 1970 +0000
27 summary: a
27 summary: a
28
28
29
29
30 -f, directory
30 -f, directory
31
31
32 $ hg log -f dir
32 $ hg log -f dir
33 abort: cannot follow nonexistent file: "dir"
33 abort: cannot follow nonexistent file: "dir"
34 [255]
34 [255]
35
35
36 -f, but no args
36 -f, but no args
37
37
38 $ hg log -f
38 $ hg log -f
39 changeset: 4:66c1345dc4f9
39 changeset: 4:66c1345dc4f9
40 tag: tip
40 tag: tip
41 user: test
41 user: test
42 date: Thu Jan 01 00:00:05 1970 +0000
42 date: Thu Jan 01 00:00:05 1970 +0000
43 summary: e
43 summary: e
44
44
45 changeset: 3:7c6c671bb7cc
45 changeset: 3:7c6c671bb7cc
46 user: test
46 user: test
47 date: Thu Jan 01 00:00:04 1970 +0000
47 date: Thu Jan 01 00:00:04 1970 +0000
48 summary: d
48 summary: d
49
49
50 changeset: 2:41dd4284081e
50 changeset: 2:41dd4284081e
51 user: test
51 user: test
52 date: Thu Jan 01 00:00:03 1970 +0000
52 date: Thu Jan 01 00:00:03 1970 +0000
53 summary: c
53 summary: c
54
54
55 changeset: 1:784de7cef101
55 changeset: 1:784de7cef101
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:02 1970 +0000
57 date: Thu Jan 01 00:00:02 1970 +0000
58 summary: b
58 summary: b
59
59
60 changeset: 0:8580ff50825a
60 changeset: 0:8580ff50825a
61 user: test
61 user: test
62 date: Thu Jan 01 00:00:01 1970 +0000
62 date: Thu Jan 01 00:00:01 1970 +0000
63 summary: a
63 summary: a
64
64
65
65
66 one rename
66 one rename
67
67
68 $ hg log -vf a
68 $ hg log -vf a
69 changeset: 0:8580ff50825a
69 changeset: 0:8580ff50825a
70 user: test
70 user: test
71 date: Thu Jan 01 00:00:01 1970 +0000
71 date: Thu Jan 01 00:00:01 1970 +0000
72 files: a
72 files: a
73 description:
73 description:
74 a
74 a
75
75
76
76
77
77
78 many renames
78 many renames
79
79
80 $ hg log -vf e
80 $ hg log -vf e
81 changeset: 4:66c1345dc4f9
81 changeset: 4:66c1345dc4f9
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:05 1970 +0000
84 date: Thu Jan 01 00:00:05 1970 +0000
85 files: dir/b e
85 files: dir/b e
86 description:
86 description:
87 e
87 e
88
88
89
89
90 changeset: 2:41dd4284081e
90 changeset: 2:41dd4284081e
91 user: test
91 user: test
92 date: Thu Jan 01 00:00:03 1970 +0000
92 date: Thu Jan 01 00:00:03 1970 +0000
93 files: b dir/b
93 files: b dir/b
94 description:
94 description:
95 c
95 c
96
96
97
97
98 changeset: 1:784de7cef101
98 changeset: 1:784de7cef101
99 user: test
99 user: test
100 date: Thu Jan 01 00:00:02 1970 +0000
100 date: Thu Jan 01 00:00:02 1970 +0000
101 files: b
101 files: b
102 description:
102 description:
103 b
103 b
104
104
105
105
106 changeset: 0:8580ff50825a
106 changeset: 0:8580ff50825a
107 user: test
107 user: test
108 date: Thu Jan 01 00:00:01 1970 +0000
108 date: Thu Jan 01 00:00:01 1970 +0000
109 files: a
109 files: a
110 description:
110 description:
111 a
111 a
112
112
113
113
114
114
115
115
116 log -pf dir/b
116 log -pf dir/b
117
117
118 $ hg log -pf dir/b
118 $ hg log -pf dir/b
119 changeset: 2:41dd4284081e
119 changeset: 2:41dd4284081e
120 user: test
120 user: test
121 date: Thu Jan 01 00:00:03 1970 +0000
121 date: Thu Jan 01 00:00:03 1970 +0000
122 summary: c
122 summary: c
123
123
124 diff -r 784de7cef101 -r 41dd4284081e dir/b
124 diff -r 784de7cef101 -r 41dd4284081e dir/b
125 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
126 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
127 @@ -0,0 +1,1 @@
127 @@ -0,0 +1,1 @@
128 +a
128 +a
129
129
130 changeset: 1:784de7cef101
130 changeset: 1:784de7cef101
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:02 1970 +0000
132 date: Thu Jan 01 00:00:02 1970 +0000
133 summary: b
133 summary: b
134
134
135 diff -r 8580ff50825a -r 784de7cef101 b
135 diff -r 8580ff50825a -r 784de7cef101 b
136 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
136 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
137 +++ b/b Thu Jan 01 00:00:02 1970 +0000
137 +++ b/b Thu Jan 01 00:00:02 1970 +0000
138 @@ -0,0 +1,1 @@
138 @@ -0,0 +1,1 @@
139 +a
139 +a
140
140
141 changeset: 0:8580ff50825a
141 changeset: 0:8580ff50825a
142 user: test
142 user: test
143 date: Thu Jan 01 00:00:01 1970 +0000
143 date: Thu Jan 01 00:00:01 1970 +0000
144 summary: a
144 summary: a
145
145
146 diff -r 000000000000 -r 8580ff50825a a
146 diff -r 000000000000 -r 8580ff50825a a
147 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
147 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148 +++ b/a Thu Jan 01 00:00:01 1970 +0000
148 +++ b/a Thu Jan 01 00:00:01 1970 +0000
149 @@ -0,0 +1,1 @@
149 @@ -0,0 +1,1 @@
150 +a
150 +a
151
151
152
152
153 log -vf dir/b
153 log -vf dir/b
154
154
155 $ hg log -vf dir/b
155 $ hg log -vf dir/b
156 changeset: 2:41dd4284081e
156 changeset: 2:41dd4284081e
157 user: test
157 user: test
158 date: Thu Jan 01 00:00:03 1970 +0000
158 date: Thu Jan 01 00:00:03 1970 +0000
159 files: b dir/b
159 files: b dir/b
160 description:
160 description:
161 c
161 c
162
162
163
163
164 changeset: 1:784de7cef101
164 changeset: 1:784de7cef101
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:02 1970 +0000
166 date: Thu Jan 01 00:00:02 1970 +0000
167 files: b
167 files: b
168 description:
168 description:
169 b
169 b
170
170
171
171
172 changeset: 0:8580ff50825a
172 changeset: 0:8580ff50825a
173 user: test
173 user: test
174 date: Thu Jan 01 00:00:01 1970 +0000
174 date: Thu Jan 01 00:00:01 1970 +0000
175 files: a
175 files: a
176 description:
176 description:
177 a
177 a
178
178
179
179
180
180
181
181
182 log copies with --copies
182 log copies with --copies
183
183
184 $ hg log -vC --template '{rev} {file_copies}\n'
184 $ hg log -vC --template '{rev} {file_copies}\n'
185 4 e (dir/b)
185 4 e (dir/b)
186 3 b (a)
186 3 b (a)
187 2 dir/b (b)
187 2 dir/b (b)
188 1 b (a)
188 1 b (a)
189 0
189 0
190
190
191 log copies switch without --copies, with old filecopy template
191 log copies switch without --copies, with old filecopy template
192
192
193 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
193 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
194 4
194 4
195 3
195 3
196 2
196 2
197 1
197 1
198 0
198 0
199
199
200 log copies switch with --copies
200 log copies switch with --copies
201
201
202 $ hg log -vC --template '{rev} {file_copies_switch}\n'
202 $ hg log -vC --template '{rev} {file_copies_switch}\n'
203 4 e (dir/b)
203 4 e (dir/b)
204 3 b (a)
204 3 b (a)
205 2 dir/b (b)
205 2 dir/b (b)
206 1 b (a)
206 1 b (a)
207 0
207 0
208
208
209
209
210 log copies with hardcoded style and with --style=default
210 log copies with hardcoded style and with --style=default
211
211
212 $ hg log -vC -r4
212 $ hg log -vC -r4
213 changeset: 4:66c1345dc4f9
213 changeset: 4:66c1345dc4f9
214 tag: tip
214 tag: tip
215 user: test
215 user: test
216 date: Thu Jan 01 00:00:05 1970 +0000
216 date: Thu Jan 01 00:00:05 1970 +0000
217 files: dir/b e
217 files: dir/b e
218 copies: e (dir/b)
218 copies: e (dir/b)
219 description:
219 description:
220 e
220 e
221
221
222
222
223 $ hg log -vC -r4 --style=default
223 $ hg log -vC -r4 --style=default
224 changeset: 4:66c1345dc4f9
224 changeset: 4:66c1345dc4f9
225 tag: tip
225 tag: tip
226 user: test
226 user: test
227 date: Thu Jan 01 00:00:05 1970 +0000
227 date: Thu Jan 01 00:00:05 1970 +0000
228 files: dir/b e
228 files: dir/b e
229 copies: e (dir/b)
229 copies: e (dir/b)
230 description:
230 description:
231 e
231 e
232
232
233
233
234
234
235
235
236 log copies, non-linear manifest
236 log copies, non-linear manifest
237
237
238 $ hg up -C 3
238 $ hg up -C 3
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
240 $ hg mv dir/b e
240 $ hg mv dir/b e
241 $ echo foo > foo
241 $ echo foo > foo
242 $ hg ci -Ame2 -d '6 0'
242 $ hg ci -Ame2 -d '6 0'
243 adding foo
243 adding foo
244 created new head
244 created new head
245 $ hg log -v --template '{rev} {file_copies}\n' -r 5
245 $ hg log -v --template '{rev} {file_copies}\n' -r 5
246 5 e (dir/b)
246 5 e (dir/b)
247
247
248
248
249 log copies, execute bit set
249 log copies, execute bit set
250
250
251 $ chmod +x e
251 $ chmod +x e
252 $ hg ci -me3 -d '7 0'
252 $ hg ci -me3 -d '7 0'
253 $ hg log -v --template '{rev} {file_copies}\n' -r 6
253 $ hg log -v --template '{rev} {file_copies}\n' -r 6
254 6
254 6
255
255
256
256
257 log -p d
257 log -p d
258
258
259 $ hg log -pv d
259 $ hg log -pv d
260 changeset: 3:7c6c671bb7cc
260 changeset: 3:7c6c671bb7cc
261 user: test
261 user: test
262 date: Thu Jan 01 00:00:04 1970 +0000
262 date: Thu Jan 01 00:00:04 1970 +0000
263 files: a b d
263 files: a b d
264 description:
264 description:
265 d
265 d
266
266
267
267
268 diff -r 41dd4284081e -r 7c6c671bb7cc d
268 diff -r 41dd4284081e -r 7c6c671bb7cc d
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270 +++ b/d Thu Jan 01 00:00:04 1970 +0000
270 +++ b/d Thu Jan 01 00:00:04 1970 +0000
271 @@ -0,0 +1,1 @@
271 @@ -0,0 +1,1 @@
272 +a
272 +a
273
273
274
274
275
275
276 log --removed file
276 log --removed file
277
277
278 $ hg log --removed -v a
278 $ hg log --removed -v a
279 changeset: 3:7c6c671bb7cc
279 changeset: 3:7c6c671bb7cc
280 user: test
280 user: test
281 date: Thu Jan 01 00:00:04 1970 +0000
281 date: Thu Jan 01 00:00:04 1970 +0000
282 files: a b d
282 files: a b d
283 description:
283 description:
284 d
284 d
285
285
286
286
287 changeset: 0:8580ff50825a
287 changeset: 0:8580ff50825a
288 user: test
288 user: test
289 date: Thu Jan 01 00:00:01 1970 +0000
289 date: Thu Jan 01 00:00:01 1970 +0000
290 files: a
290 files: a
291 description:
291 description:
292 a
292 a
293
293
294
294
295
295
296 log --removed revrange file
296 log --removed revrange file
297
297
298 $ hg log --removed -v -r0:2 a
298 $ hg log --removed -v -r0:2 a
299 changeset: 0:8580ff50825a
299 changeset: 0:8580ff50825a
300 user: test
300 user: test
301 date: Thu Jan 01 00:00:01 1970 +0000
301 date: Thu Jan 01 00:00:01 1970 +0000
302 files: a
302 files: a
303 description:
303 description:
304 a
304 a
305
305
306
306
307
307
308
308
309 log --follow tests
309 log --follow tests
310
310
311 $ hg init ../follow
311 $ hg init ../follow
312 $ cd ../follow
312 $ cd ../follow
313
313
314 $ echo base > base
314 $ echo base > base
315 $ hg ci -Ambase -d '1 0'
315 $ hg ci -Ambase -d '1 0'
316 adding base
316 adding base
317
317
318 $ echo r1 >> base
318 $ echo r1 >> base
319 $ hg ci -Amr1 -d '1 0'
319 $ hg ci -Amr1 -d '1 0'
320 $ echo r2 >> base
320 $ echo r2 >> base
321 $ hg ci -Amr2 -d '1 0'
321 $ hg ci -Amr2 -d '1 0'
322
322
323 $ hg up -C 1
323 $ hg up -C 1
324 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
324 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
325 $ echo b1 > b1
325 $ echo b1 > b1
326 $ hg ci -Amb1 -d '1 0'
326 $ hg ci -Amb1 -d '1 0'
327 adding b1
327 adding b1
328 created new head
328 created new head
329
329
330
330
331 log -f
331 log -f
332
332
333 $ hg log -f
333 $ hg log -f
334 changeset: 3:e62f78d544b4
334 changeset: 3:e62f78d544b4
335 tag: tip
335 tag: tip
336 parent: 1:3d5bf5654eda
336 parent: 1:3d5bf5654eda
337 user: test
337 user: test
338 date: Thu Jan 01 00:00:01 1970 +0000
338 date: Thu Jan 01 00:00:01 1970 +0000
339 summary: b1
339 summary: b1
340
340
341 changeset: 1:3d5bf5654eda
341 changeset: 1:3d5bf5654eda
342 user: test
342 user: test
343 date: Thu Jan 01 00:00:01 1970 +0000
343 date: Thu Jan 01 00:00:01 1970 +0000
344 summary: r1
344 summary: r1
345
345
346 changeset: 0:67e992f2c4f3
346 changeset: 0:67e992f2c4f3
347 user: test
347 user: test
348 date: Thu Jan 01 00:00:01 1970 +0000
348 date: Thu Jan 01 00:00:01 1970 +0000
349 summary: base
349 summary: base
350
350
351
351
352
352
353 log -f -r 1:tip
353 log -f -r 1:tip
354
354
355 $ hg up -C 0
355 $ hg up -C 0
356 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
356 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
357 $ echo b2 > b2
357 $ echo b2 > b2
358 $ hg ci -Amb2 -d '1 0'
358 $ hg ci -Amb2 -d '1 0'
359 adding b2
359 adding b2
360 created new head
360 created new head
361 $ hg log -f -r 1:tip
361 $ hg log -f -r 1:tip
362 changeset: 1:3d5bf5654eda
362 changeset: 1:3d5bf5654eda
363 user: test
363 user: test
364 date: Thu Jan 01 00:00:01 1970 +0000
364 date: Thu Jan 01 00:00:01 1970 +0000
365 summary: r1
365 summary: r1
366
366
367 changeset: 2:60c670bf5b30
367 changeset: 2:60c670bf5b30
368 user: test
368 user: test
369 date: Thu Jan 01 00:00:01 1970 +0000
369 date: Thu Jan 01 00:00:01 1970 +0000
370 summary: r2
370 summary: r2
371
371
372 changeset: 3:e62f78d544b4
372 changeset: 3:e62f78d544b4
373 parent: 1:3d5bf5654eda
373 parent: 1:3d5bf5654eda
374 user: test
374 user: test
375 date: Thu Jan 01 00:00:01 1970 +0000
375 date: Thu Jan 01 00:00:01 1970 +0000
376 summary: b1
376 summary: b1
377
377
378
378
379
379
380 log -r . with two parents
380 log -r . with two parents
381
381
382 $ hg up -C 3
382 $ hg up -C 3
383 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
383 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
384 $ hg merge tip
384 $ hg merge tip
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 (branch merge, don't forget to commit)
386 (branch merge, don't forget to commit)
387 $ hg log -r .
387 $ hg log -r .
388 changeset: 3:e62f78d544b4
388 changeset: 3:e62f78d544b4
389 parent: 1:3d5bf5654eda
389 parent: 1:3d5bf5654eda
390 user: test
390 user: test
391 date: Thu Jan 01 00:00:01 1970 +0000
391 date: Thu Jan 01 00:00:01 1970 +0000
392 summary: b1
392 summary: b1
393
393
394
394
395
395
396 log -r . with one parent
396 log -r . with one parent
397
397
398 $ hg ci -mm12 -d '1 0'
398 $ hg ci -mm12 -d '1 0'
399 $ hg log -r .
399 $ hg log -r .
400 changeset: 5:302e9dd6890d
400 changeset: 5:302e9dd6890d
401 tag: tip
401 tag: tip
402 parent: 3:e62f78d544b4
402 parent: 3:e62f78d544b4
403 parent: 4:ddb82e70d1a1
403 parent: 4:ddb82e70d1a1
404 user: test
404 user: test
405 date: Thu Jan 01 00:00:01 1970 +0000
405 date: Thu Jan 01 00:00:01 1970 +0000
406 summary: m12
406 summary: m12
407
407
408
408
409 $ echo postm >> b1
409 $ echo postm >> b1
410 $ hg ci -Amb1.1 -d'1 0'
410 $ hg ci -Amb1.1 -d'1 0'
411
411
412
412
413 log --follow-first
413 log --follow-first
414
414
415 $ hg log --follow-first
415 $ hg log --follow-first
416 changeset: 6:2404bbcab562
416 changeset: 6:2404bbcab562
417 tag: tip
417 tag: tip
418 user: test
418 user: test
419 date: Thu Jan 01 00:00:01 1970 +0000
419 date: Thu Jan 01 00:00:01 1970 +0000
420 summary: b1.1
420 summary: b1.1
421
421
422 changeset: 5:302e9dd6890d
422 changeset: 5:302e9dd6890d
423 parent: 3:e62f78d544b4
423 parent: 3:e62f78d544b4
424 parent: 4:ddb82e70d1a1
424 parent: 4:ddb82e70d1a1
425 user: test
425 user: test
426 date: Thu Jan 01 00:00:01 1970 +0000
426 date: Thu Jan 01 00:00:01 1970 +0000
427 summary: m12
427 summary: m12
428
428
429 changeset: 3:e62f78d544b4
429 changeset: 3:e62f78d544b4
430 parent: 1:3d5bf5654eda
430 parent: 1:3d5bf5654eda
431 user: test
431 user: test
432 date: Thu Jan 01 00:00:01 1970 +0000
432 date: Thu Jan 01 00:00:01 1970 +0000
433 summary: b1
433 summary: b1
434
434
435 changeset: 1:3d5bf5654eda
435 changeset: 1:3d5bf5654eda
436 user: test
436 user: test
437 date: Thu Jan 01 00:00:01 1970 +0000
437 date: Thu Jan 01 00:00:01 1970 +0000
438 summary: r1
438 summary: r1
439
439
440 changeset: 0:67e992f2c4f3
440 changeset: 0:67e992f2c4f3
441 user: test
441 user: test
442 date: Thu Jan 01 00:00:01 1970 +0000
442 date: Thu Jan 01 00:00:01 1970 +0000
443 summary: base
443 summary: base
444
444
445
445
446
446
447 log -P 2
447 log -P 2
448
448
449 $ hg log -P 2
449 $ hg log -P 2
450 changeset: 6:2404bbcab562
450 changeset: 6:2404bbcab562
451 tag: tip
451 tag: tip
452 user: test
452 user: test
453 date: Thu Jan 01 00:00:01 1970 +0000
453 date: Thu Jan 01 00:00:01 1970 +0000
454 summary: b1.1
454 summary: b1.1
455
455
456 changeset: 5:302e9dd6890d
456 changeset: 5:302e9dd6890d
457 parent: 3:e62f78d544b4
457 parent: 3:e62f78d544b4
458 parent: 4:ddb82e70d1a1
458 parent: 4:ddb82e70d1a1
459 user: test
459 user: test
460 date: Thu Jan 01 00:00:01 1970 +0000
460 date: Thu Jan 01 00:00:01 1970 +0000
461 summary: m12
461 summary: m12
462
462
463 changeset: 4:ddb82e70d1a1
463 changeset: 4:ddb82e70d1a1
464 parent: 0:67e992f2c4f3
464 parent: 0:67e992f2c4f3
465 user: test
465 user: test
466 date: Thu Jan 01 00:00:01 1970 +0000
466 date: Thu Jan 01 00:00:01 1970 +0000
467 summary: b2
467 summary: b2
468
468
469 changeset: 3:e62f78d544b4
469 changeset: 3:e62f78d544b4
470 parent: 1:3d5bf5654eda
470 parent: 1:3d5bf5654eda
471 user: test
471 user: test
472 date: Thu Jan 01 00:00:01 1970 +0000
472 date: Thu Jan 01 00:00:01 1970 +0000
473 summary: b1
473 summary: b1
474
474
475
475
476
476
477 log -r tip -p --git
477 log -r tip -p --git
478
478
479 $ hg log -r tip -p --git
479 $ hg log -r tip -p --git
480 changeset: 6:2404bbcab562
480 changeset: 6:2404bbcab562
481 tag: tip
481 tag: tip
482 user: test
482 user: test
483 date: Thu Jan 01 00:00:01 1970 +0000
483 date: Thu Jan 01 00:00:01 1970 +0000
484 summary: b1.1
484 summary: b1.1
485
485
486 diff --git a/b1 b/b1
486 diff --git a/b1 b/b1
487 --- a/b1
487 --- a/b1
488 +++ b/b1
488 +++ b/b1
489 @@ -1,1 +1,2 @@
489 @@ -1,1 +1,2 @@
490 b1
490 b1
491 +postm
491 +postm
492
492
493
493
494
494
495 log -r ""
495 log -r ""
496
496
497 $ hg log -r ''
497 $ hg log -r ''
498 hg: parse error: empty query
498 hg: parse error: empty query
499 [255]
499 [255]
500
500
501 log -r <some unknown node id>
501 log -r <some unknown node id>
502
502
503 $ hg log -r 1000000000000000000000000000000000000000
503 $ hg log -r 1000000000000000000000000000000000000000
504 abort: unknown revision '1000000000000000000000000000000000000000'!
504 abort: unknown revision '1000000000000000000000000000000000000000'!
505 [255]
505 [255]
506
506
507 log -k r1
507 log -k r1
508
508
509 $ hg log -k r1
509 $ hg log -k r1
510 changeset: 1:3d5bf5654eda
510 changeset: 1:3d5bf5654eda
511 user: test
511 user: test
512 date: Thu Jan 01 00:00:01 1970 +0000
512 date: Thu Jan 01 00:00:01 1970 +0000
513 summary: r1
513 summary: r1
514
514
515 log -d " " (whitespaces only)
515 log -d " " (whitespaces only)
516
516
517 $ hg log -d " "
517 $ hg log -d " "
518 abort: dates cannot consist entirely of whitespace
518 abort: dates cannot consist entirely of whitespace
519 [255]
519 [255]
520
520
521 log -d -1
521 log -d -1
522
522
523 $ hg log -d -1
523 $ hg log -d -1
524
524
525 log -d ">"
525 log -d ">"
526
526
527 $ hg log -d ">"
527 $ hg log -d ">"
528 abort: invalid day spec, use '>DATE'
528 abort: invalid day spec, use '>DATE'
529 [255]
529 [255]
530
530
531 log -d "<"
531 log -d "<"
532
532
533 $ hg log -d "<"
533 $ hg log -d "<"
534 abort: invalid day spec, use '<DATE'
534 abort: invalid day spec, use '<DATE'
535 [255]
535 [255]
536
536
537 Negative ranges
537 Negative ranges
538 $ hg log -d "--2"
538 $ hg log -d "--2"
539 abort: -2 must be nonnegative (see 'hg help dates')
539 abort: -2 must be nonnegative (see 'hg help dates')
540 [255]
540 [255]
541
541
542
542
543 log -p -l2 --color=always
543 log -p -l2 --color=always
544
544
545 $ hg --config extensions.color= --config color.mode=ansi \
545 $ hg --config extensions.color= --config color.mode=ansi \
546 > log -p -l2 --color=always
546 > log -p -l2 --color=always
547 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
547 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
548 tag: tip
548 tag: tip
549 user: test
549 user: test
550 date: Thu Jan 01 00:00:01 1970 +0000
550 date: Thu Jan 01 00:00:01 1970 +0000
551 summary: b1.1
551 summary: b1.1
552
552
553 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
553 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
554 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
554 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
555 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
555 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
556 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
556 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
557 b1
557 b1
558 \x1b[0;32m+postm\x1b[0m (esc)
558 \x1b[0;32m+postm\x1b[0m (esc)
559
559
560 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
560 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
561 parent: 3:e62f78d544b4
561 parent: 3:e62f78d544b4
562 parent: 4:ddb82e70d1a1
562 parent: 4:ddb82e70d1a1
563 user: test
563 user: test
564 date: Thu Jan 01 00:00:01 1970 +0000
564 date: Thu Jan 01 00:00:01 1970 +0000
565 summary: m12
565 summary: m12
566
566
567 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
567 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
568 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
568 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
569 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
569 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
570 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
570 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
571 \x1b[0;32m+b2\x1b[0m (esc)
571 \x1b[0;32m+b2\x1b[0m (esc)
572
572
573
573
574
574
575 log -r tip --stat
575 log -r tip --stat
576
576
577 $ hg log -r tip --stat
577 $ hg log -r tip --stat
578 changeset: 6:2404bbcab562
578 changeset: 6:2404bbcab562
579 tag: tip
579 tag: tip
580 user: test
580 user: test
581 date: Thu Jan 01 00:00:01 1970 +0000
581 date: Thu Jan 01 00:00:01 1970 +0000
582 summary: b1.1
582 summary: b1.1
583
583
584 b1 | 1 +
584 b1 | 1 +
585 1 files changed, 1 insertions(+), 0 deletions(-)
585 1 files changed, 1 insertions(+), 0 deletions(-)
586
586
587
587
588 $ cd ..
588 $ cd ..
589
589
590 $ hg init usertest
590 $ hg init usertest
591 $ cd usertest
591 $ cd usertest
592
592
593 $ echo a > a
593 $ echo a > a
594 $ hg ci -A -m "a" -u "User One <user1@example.org>"
594 $ hg ci -A -m "a" -u "User One <user1@example.org>"
595 adding a
595 adding a
596 $ echo b > b
596 $ echo b > b
597 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
597 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
598 adding b
598 adding b
599
599
600 $ hg log -u "User One <user1@example.org>"
600 $ hg log -u "User One <user1@example.org>"
601 changeset: 0:29a4c94f1924
601 changeset: 0:29a4c94f1924
602 user: User One <user1@example.org>
602 user: User One <user1@example.org>
603 date: Thu Jan 01 00:00:00 1970 +0000
603 date: Thu Jan 01 00:00:00 1970 +0000
604 summary: a
604 summary: a
605
605
606 $ hg log -u "user1" -u "user2"
606 $ hg log -u "user1" -u "user2"
607 changeset: 1:e834b5e69c0e
607 changeset: 1:e834b5e69c0e
608 tag: tip
608 tag: tip
609 user: User Two <user2@example.org>
609 user: User Two <user2@example.org>
610 date: Thu Jan 01 00:00:00 1970 +0000
610 date: Thu Jan 01 00:00:00 1970 +0000
611 summary: b
611 summary: b
612
612
613 changeset: 0:29a4c94f1924
613 changeset: 0:29a4c94f1924
614 user: User One <user1@example.org>
614 user: User One <user1@example.org>
615 date: Thu Jan 01 00:00:00 1970 +0000
615 date: Thu Jan 01 00:00:00 1970 +0000
616 summary: a
616 summary: a
617
617
618 $ hg log -u "user3"
618 $ hg log -u "user3"
619
619
620 $ cd ..
620 $ cd ..
621
621
622 $ hg init branches
622 $ hg init branches
623 $ cd branches
623 $ cd branches
624
624
625 $ echo a > a
625 $ echo a > a
626 $ hg ci -A -m "commit on default"
626 $ hg ci -A -m "commit on default"
627 adding a
627 adding a
628 $ hg branch test
628 $ hg branch test
629 marked working directory as branch test
629 marked working directory as branch test
630 $ echo b > b
630 $ echo b > b
631 $ hg ci -A -m "commit on test"
631 $ hg ci -A -m "commit on test"
632 adding b
632 adding b
633
633
634 $ hg up default
634 $ hg up default
635 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
635 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
636 $ echo c > c
636 $ echo c > c
637 $ hg ci -A -m "commit on default"
637 $ hg ci -A -m "commit on default"
638 adding c
638 adding c
639 $ hg up test
639 $ hg up test
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
641 $ echo c > c
641 $ echo c > c
642 $ hg ci -A -m "commit on test"
642 $ hg ci -A -m "commit on test"
643 adding c
643 adding c
644
644
645
645
646 log -b default
646 log -b default
647
647
648 $ hg log -b default
648 $ hg log -b default
649 changeset: 2:c3a4f03cc9a7
649 changeset: 2:c3a4f03cc9a7
650 parent: 0:24427303d56f
650 parent: 0:24427303d56f
651 user: test
651 user: test
652 date: Thu Jan 01 00:00:00 1970 +0000
652 date: Thu Jan 01 00:00:00 1970 +0000
653 summary: commit on default
653 summary: commit on default
654
654
655 changeset: 0:24427303d56f
655 changeset: 0:24427303d56f
656 user: test
656 user: test
657 date: Thu Jan 01 00:00:00 1970 +0000
657 date: Thu Jan 01 00:00:00 1970 +0000
658 summary: commit on default
658 summary: commit on default
659
659
660
660
661
661
662 log -b test
662 log -b test
663
663
664 $ hg log -b test
664 $ hg log -b test
665 changeset: 3:f5d8de11c2e2
665 changeset: 3:f5d8de11c2e2
666 branch: test
666 branch: test
667 tag: tip
667 tag: tip
668 parent: 1:d32277701ccb
668 parent: 1:d32277701ccb
669 user: test
669 user: test
670 date: Thu Jan 01 00:00:00 1970 +0000
670 date: Thu Jan 01 00:00:00 1970 +0000
671 summary: commit on test
671 summary: commit on test
672
672
673 changeset: 1:d32277701ccb
673 changeset: 1:d32277701ccb
674 branch: test
674 branch: test
675 user: test
675 user: test
676 date: Thu Jan 01 00:00:00 1970 +0000
676 date: Thu Jan 01 00:00:00 1970 +0000
677 summary: commit on test
677 summary: commit on test
678
678
679
679
680
680
681 log -b dummy
681 log -b dummy
682
682
683 $ hg log -b dummy
683 $ hg log -b dummy
684 abort: unknown revision 'dummy'!
684 abort: unknown revision 'dummy'!
685 [255]
685 [255]
686
686
687
687
688 log -b .
688 log -b .
689
689
690 $ hg log -b .
690 $ hg log -b .
691 changeset: 3:f5d8de11c2e2
691 changeset: 3:f5d8de11c2e2
692 branch: test
692 branch: test
693 tag: tip
693 tag: tip
694 parent: 1:d32277701ccb
694 parent: 1:d32277701ccb
695 user: test
695 user: test
696 date: Thu Jan 01 00:00:00 1970 +0000
696 date: Thu Jan 01 00:00:00 1970 +0000
697 summary: commit on test
697 summary: commit on test
698
698
699 changeset: 1:d32277701ccb
699 changeset: 1:d32277701ccb
700 branch: test
700 branch: test
701 user: test
701 user: test
702 date: Thu Jan 01 00:00:00 1970 +0000
702 date: Thu Jan 01 00:00:00 1970 +0000
703 summary: commit on test
703 summary: commit on test
704
704
705
705
706
706
707 log -b default -b test
707 log -b default -b test
708
708
709 $ hg log -b default -b test
709 $ hg log -b default -b test
710 changeset: 3:f5d8de11c2e2
710 changeset: 3:f5d8de11c2e2
711 branch: test
711 branch: test
712 tag: tip
712 tag: tip
713 parent: 1:d32277701ccb
713 parent: 1:d32277701ccb
714 user: test
714 user: test
715 date: Thu Jan 01 00:00:00 1970 +0000
715 date: Thu Jan 01 00:00:00 1970 +0000
716 summary: commit on test
716 summary: commit on test
717
717
718 changeset: 2:c3a4f03cc9a7
718 changeset: 2:c3a4f03cc9a7
719 parent: 0:24427303d56f
719 parent: 0:24427303d56f
720 user: test
720 user: test
721 date: Thu Jan 01 00:00:00 1970 +0000
721 date: Thu Jan 01 00:00:00 1970 +0000
722 summary: commit on default
722 summary: commit on default
723
723
724 changeset: 1:d32277701ccb
724 changeset: 1:d32277701ccb
725 branch: test
725 branch: test
726 user: test
726 user: test
727 date: Thu Jan 01 00:00:00 1970 +0000
727 date: Thu Jan 01 00:00:00 1970 +0000
728 summary: commit on test
728 summary: commit on test
729
729
730 changeset: 0:24427303d56f
730 changeset: 0:24427303d56f
731 user: test
731 user: test
732 date: Thu Jan 01 00:00:00 1970 +0000
732 date: Thu Jan 01 00:00:00 1970 +0000
733 summary: commit on default
733 summary: commit on default
734
734
735
735
736
736
737 log -b default -b .
737 log -b default -b .
738
738
739 $ hg log -b default -b .
739 $ hg log -b default -b .
740 changeset: 3:f5d8de11c2e2
740 changeset: 3:f5d8de11c2e2
741 branch: test
741 branch: test
742 tag: tip
742 tag: tip
743 parent: 1:d32277701ccb
743 parent: 1:d32277701ccb
744 user: test
744 user: test
745 date: Thu Jan 01 00:00:00 1970 +0000
745 date: Thu Jan 01 00:00:00 1970 +0000
746 summary: commit on test
746 summary: commit on test
747
747
748 changeset: 2:c3a4f03cc9a7
748 changeset: 2:c3a4f03cc9a7
749 parent: 0:24427303d56f
749 parent: 0:24427303d56f
750 user: test
750 user: test
751 date: Thu Jan 01 00:00:00 1970 +0000
751 date: Thu Jan 01 00:00:00 1970 +0000
752 summary: commit on default
752 summary: commit on default
753
753
754 changeset: 1:d32277701ccb
754 changeset: 1:d32277701ccb
755 branch: test
755 branch: test
756 user: test
756 user: test
757 date: Thu Jan 01 00:00:00 1970 +0000
757 date: Thu Jan 01 00:00:00 1970 +0000
758 summary: commit on test
758 summary: commit on test
759
759
760 changeset: 0:24427303d56f
760 changeset: 0:24427303d56f
761 user: test
761 user: test
762 date: Thu Jan 01 00:00:00 1970 +0000
762 date: Thu Jan 01 00:00:00 1970 +0000
763 summary: commit on default
763 summary: commit on default
764
764
765
765
766
766
767 log -b . -b test
767 log -b . -b test
768
768
769 $ hg log -b . -b test
769 $ hg log -b . -b test
770 changeset: 3:f5d8de11c2e2
770 changeset: 3:f5d8de11c2e2
771 branch: test
771 branch: test
772 tag: tip
772 tag: tip
773 parent: 1:d32277701ccb
773 parent: 1:d32277701ccb
774 user: test
774 user: test
775 date: Thu Jan 01 00:00:00 1970 +0000
775 date: Thu Jan 01 00:00:00 1970 +0000
776 summary: commit on test
776 summary: commit on test
777
777
778 changeset: 1:d32277701ccb
778 changeset: 1:d32277701ccb
779 branch: test
779 branch: test
780 user: test
780 user: test
781 date: Thu Jan 01 00:00:00 1970 +0000
781 date: Thu Jan 01 00:00:00 1970 +0000
782 summary: commit on test
782 summary: commit on test
783
783
784
784
785
785
786 log -b 2
786 log -b 2
787
787
788 $ hg log -b 2
788 $ hg log -b 2
789 changeset: 2:c3a4f03cc9a7
789 changeset: 2:c3a4f03cc9a7
790 parent: 0:24427303d56f
790 parent: 0:24427303d56f
791 user: test
791 user: test
792 date: Thu Jan 01 00:00:00 1970 +0000
792 date: Thu Jan 01 00:00:00 1970 +0000
793 summary: commit on default
793 summary: commit on default
794
794
795 changeset: 0:24427303d56f
795 changeset: 0:24427303d56f
796 user: test
796 user: test
797 date: Thu Jan 01 00:00:00 1970 +0000
797 date: Thu Jan 01 00:00:00 1970 +0000
798 summary: commit on default
798 summary: commit on default
799
799
800
800
801
801
802 log -p --cwd dir (in subdir)
802 log -p --cwd dir (in subdir)
803
803
804 $ mkdir dir
804 $ mkdir dir
805 $ hg log -p --cwd dir
805 $ hg log -p --cwd dir
806 changeset: 3:f5d8de11c2e2
806 changeset: 3:f5d8de11c2e2
807 branch: test
807 branch: test
808 tag: tip
808 tag: tip
809 parent: 1:d32277701ccb
809 parent: 1:d32277701ccb
810 user: test
810 user: test
811 date: Thu Jan 01 00:00:00 1970 +0000
811 date: Thu Jan 01 00:00:00 1970 +0000
812 summary: commit on test
812 summary: commit on test
813
813
814 diff -r d32277701ccb -r f5d8de11c2e2 c
814 diff -r d32277701ccb -r f5d8de11c2e2 c
815 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
815 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
816 +++ b/c Thu Jan 01 00:00:00 1970 +0000
816 +++ b/c Thu Jan 01 00:00:00 1970 +0000
817 @@ -0,0 +1,1 @@
817 @@ -0,0 +1,1 @@
818 +c
818 +c
819
819
820 changeset: 2:c3a4f03cc9a7
820 changeset: 2:c3a4f03cc9a7
821 parent: 0:24427303d56f
821 parent: 0:24427303d56f
822 user: test
822 user: test
823 date: Thu Jan 01 00:00:00 1970 +0000
823 date: Thu Jan 01 00:00:00 1970 +0000
824 summary: commit on default
824 summary: commit on default
825
825
826 diff -r 24427303d56f -r c3a4f03cc9a7 c
826 diff -r 24427303d56f -r c3a4f03cc9a7 c
827 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
827 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
828 +++ b/c Thu Jan 01 00:00:00 1970 +0000
828 +++ b/c Thu Jan 01 00:00:00 1970 +0000
829 @@ -0,0 +1,1 @@
829 @@ -0,0 +1,1 @@
830 +c
830 +c
831
831
832 changeset: 1:d32277701ccb
832 changeset: 1:d32277701ccb
833 branch: test
833 branch: test
834 user: test
834 user: test
835 date: Thu Jan 01 00:00:00 1970 +0000
835 date: Thu Jan 01 00:00:00 1970 +0000
836 summary: commit on test
836 summary: commit on test
837
837
838 diff -r 24427303d56f -r d32277701ccb b
838 diff -r 24427303d56f -r d32277701ccb b
839 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
839 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
840 +++ b/b Thu Jan 01 00:00:00 1970 +0000
840 +++ b/b Thu Jan 01 00:00:00 1970 +0000
841 @@ -0,0 +1,1 @@
841 @@ -0,0 +1,1 @@
842 +b
842 +b
843
843
844 changeset: 0:24427303d56f
844 changeset: 0:24427303d56f
845 user: test
845 user: test
846 date: Thu Jan 01 00:00:00 1970 +0000
846 date: Thu Jan 01 00:00:00 1970 +0000
847 summary: commit on default
847 summary: commit on default
848
848
849 diff -r 000000000000 -r 24427303d56f a
849 diff -r 000000000000 -r 24427303d56f a
850 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
850 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
851 +++ b/a Thu Jan 01 00:00:00 1970 +0000
851 +++ b/a Thu Jan 01 00:00:00 1970 +0000
852 @@ -0,0 +1,1 @@
852 @@ -0,0 +1,1 @@
853 +a
853 +a
854
854
855
855
856
856
857 log -p -R repo
857 log -p -R repo
858
858
859 $ cd dir
859 $ cd dir
860 $ hg log -p -R .. ../a
860 $ hg log -p -R .. ../a
861 changeset: 0:24427303d56f
861 changeset: 0:24427303d56f
862 user: test
862 user: test
863 date: Thu Jan 01 00:00:00 1970 +0000
863 date: Thu Jan 01 00:00:00 1970 +0000
864 summary: commit on default
864 summary: commit on default
865
865
866 diff -r 000000000000 -r 24427303d56f a
866 diff -r 000000000000 -r 24427303d56f a
867 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
867 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
868 +++ b/a Thu Jan 01 00:00:00 1970 +0000
868 +++ b/a Thu Jan 01 00:00:00 1970 +0000
869 @@ -0,0 +1,1 @@
869 @@ -0,0 +1,1 @@
870 +a
870 +a
871
871
872
872
873
873
874 $ cd ..
874 $ cd ..
875 $ hg init follow2
875 $ hg init follow2
876 $ cd follow2
876 $ cd follow2
877
877
878
878
879 # Build the following history:
879 # Build the following history:
880 # tip - o - x - o - x - x
880 # tip - o - x - o - x - x
881 # \ /
881 # \ /
882 # o - o - o - x
882 # o - o - o - x
883 # \ /
883 # \ /
884 # o
884 # o
885 #
885 #
886 # Where "o" is a revision containing "foo" and
886 # Where "o" is a revision containing "foo" and
887 # "x" is a revision without "foo"
887 # "x" is a revision without "foo"
888
888
889 $ touch init
889 $ touch init
890 $ hg ci -A -m "init, unrelated"
890 $ hg ci -A -m "init, unrelated"
891 adding init
891 adding init
892 $ echo 'foo' > init
892 $ echo 'foo' > init
893 $ hg ci -m "change, unrelated"
893 $ hg ci -m "change, unrelated"
894 $ echo 'foo' > foo
894 $ echo 'foo' > foo
895 $ hg ci -A -m "add unrelated old foo"
895 $ hg ci -A -m "add unrelated old foo"
896 adding foo
896 adding foo
897 $ hg rm foo
897 $ hg rm foo
898 $ hg ci -m "delete foo, unrelated"
898 $ hg ci -m "delete foo, unrelated"
899 $ echo 'related' > foo
899 $ echo 'related' > foo
900 $ hg ci -A -m "add foo, related"
900 $ hg ci -A -m "add foo, related"
901 adding foo
901 adding foo
902
902
903 $ hg up 0
903 $ hg up 0
904 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
904 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
905 $ touch branch
905 $ touch branch
906 $ hg ci -A -m "first branch, unrelated"
906 $ hg ci -A -m "first branch, unrelated"
907 adding branch
907 adding branch
908 created new head
908 created new head
909 $ touch foo
909 $ touch foo
910 $ hg ci -A -m "create foo, related"
910 $ hg ci -A -m "create foo, related"
911 adding foo
911 adding foo
912 $ echo 'change' > foo
912 $ echo 'change' > foo
913 $ hg ci -m "change foo, related"
913 $ hg ci -m "change foo, related"
914
914
915 $ hg up 6
915 $ hg up 6
916 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
916 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
917 $ echo 'change foo in branch' > foo
917 $ echo 'change foo in branch' > foo
918 $ hg ci -m "change foo in branch, related"
918 $ hg ci -m "change foo in branch, related"
919 created new head
919 created new head
920 $ hg merge 7
920 $ hg merge 7
921 merging foo
921 merging foo
922 warning: conflicts during merge.
922 warning: conflicts during merge.
923 merging foo failed!
923 merging foo failed!
924 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
924 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
925 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
925 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
926 [1]
926 [1]
927 $ echo 'merge 1' > foo
927 $ echo 'merge 1' > foo
928 $ hg resolve -m foo
928 $ hg resolve -m foo
929 $ hg ci -m "First merge, related"
929 $ hg ci -m "First merge, related"
930
930
931 $ hg merge 4
931 $ hg merge 4
932 merging foo
932 merging foo
933 warning: conflicts during merge.
933 warning: conflicts during merge.
934 merging foo failed!
934 merging foo failed!
935 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
935 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
936 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
936 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
937 [1]
937 [1]
938 $ echo 'merge 2' > foo
938 $ echo 'merge 2' > foo
939 $ hg resolve -m foo
939 $ hg resolve -m foo
940 $ hg ci -m "Last merge, related"
940 $ hg ci -m "Last merge, related"
941
941
942 $ hg --config "extensions.graphlog=" glog
942 $ hg --config "extensions.graphlog=" glog
943 @ changeset: 10:4dae8563d2c5
943 @ changeset: 10:4dae8563d2c5
944 |\ tag: tip
944 |\ tag: tip
945 | | parent: 9:7b35701b003e
945 | | parent: 9:7b35701b003e
946 | | parent: 4:88176d361b69
946 | | parent: 4:88176d361b69
947 | | user: test
947 | | user: test
948 | | date: Thu Jan 01 00:00:00 1970 +0000
948 | | date: Thu Jan 01 00:00:00 1970 +0000
949 | | summary: Last merge, related
949 | | summary: Last merge, related
950 | |
950 | |
951 | o changeset: 9:7b35701b003e
951 | o changeset: 9:7b35701b003e
952 | |\ parent: 8:e5416ad8a855
952 | |\ parent: 8:e5416ad8a855
953 | | | parent: 7:87fe3144dcfa
953 | | | parent: 7:87fe3144dcfa
954 | | | user: test
954 | | | user: test
955 | | | date: Thu Jan 01 00:00:00 1970 +0000
955 | | | date: Thu Jan 01 00:00:00 1970 +0000
956 | | | summary: First merge, related
956 | | | summary: First merge, related
957 | | |
957 | | |
958 | | o changeset: 8:e5416ad8a855
958 | | o changeset: 8:e5416ad8a855
959 | | | parent: 6:dc6c325fe5ee
959 | | | parent: 6:dc6c325fe5ee
960 | | | user: test
960 | | | user: test
961 | | | date: Thu Jan 01 00:00:00 1970 +0000
961 | | | date: Thu Jan 01 00:00:00 1970 +0000
962 | | | summary: change foo in branch, related
962 | | | summary: change foo in branch, related
963 | | |
963 | | |
964 | o | changeset: 7:87fe3144dcfa
964 | o | changeset: 7:87fe3144dcfa
965 | |/ user: test
965 | |/ user: test
966 | | date: Thu Jan 01 00:00:00 1970 +0000
966 | | date: Thu Jan 01 00:00:00 1970 +0000
967 | | summary: change foo, related
967 | | summary: change foo, related
968 | |
968 | |
969 | o changeset: 6:dc6c325fe5ee
969 | o changeset: 6:dc6c325fe5ee
970 | | user: test
970 | | user: test
971 | | date: Thu Jan 01 00:00:00 1970 +0000
971 | | date: Thu Jan 01 00:00:00 1970 +0000
972 | | summary: create foo, related
972 | | summary: create foo, related
973 | |
973 | |
974 | o changeset: 5:73db34516eb9
974 | o changeset: 5:73db34516eb9
975 | | parent: 0:e87515fd044a
975 | | parent: 0:e87515fd044a
976 | | user: test
976 | | user: test
977 | | date: Thu Jan 01 00:00:00 1970 +0000
977 | | date: Thu Jan 01 00:00:00 1970 +0000
978 | | summary: first branch, unrelated
978 | | summary: first branch, unrelated
979 | |
979 | |
980 o | changeset: 4:88176d361b69
980 o | changeset: 4:88176d361b69
981 | | user: test
981 | | user: test
982 | | date: Thu Jan 01 00:00:00 1970 +0000
982 | | date: Thu Jan 01 00:00:00 1970 +0000
983 | | summary: add foo, related
983 | | summary: add foo, related
984 | |
984 | |
985 o | changeset: 3:dd78ae4afb56
985 o | changeset: 3:dd78ae4afb56
986 | | user: test
986 | | user: test
987 | | date: Thu Jan 01 00:00:00 1970 +0000
987 | | date: Thu Jan 01 00:00:00 1970 +0000
988 | | summary: delete foo, unrelated
988 | | summary: delete foo, unrelated
989 | |
989 | |
990 o | changeset: 2:c4c64aedf0f7
990 o | changeset: 2:c4c64aedf0f7
991 | | user: test
991 | | user: test
992 | | date: Thu Jan 01 00:00:00 1970 +0000
992 | | date: Thu Jan 01 00:00:00 1970 +0000
993 | | summary: add unrelated old foo
993 | | summary: add unrelated old foo
994 | |
994 | |
995 o | changeset: 1:e5faa7440653
995 o | changeset: 1:e5faa7440653
996 |/ user: test
996 |/ user: test
997 | date: Thu Jan 01 00:00:00 1970 +0000
997 | date: Thu Jan 01 00:00:00 1970 +0000
998 | summary: change, unrelated
998 | summary: change, unrelated
999 |
999 |
1000 o changeset: 0:e87515fd044a
1000 o changeset: 0:e87515fd044a
1001 user: test
1001 user: test
1002 date: Thu Jan 01 00:00:00 1970 +0000
1002 date: Thu Jan 01 00:00:00 1970 +0000
1003 summary: init, unrelated
1003 summary: init, unrelated
1004
1004
1005
1005
1006 $ hg --traceback log -f foo
1006 $ hg --traceback log -f foo
1007 changeset: 10:4dae8563d2c5
1007 changeset: 10:4dae8563d2c5
1008 tag: tip
1008 tag: tip
1009 parent: 9:7b35701b003e
1009 parent: 9:7b35701b003e
1010 parent: 4:88176d361b69
1010 parent: 4:88176d361b69
1011 user: test
1011 user: test
1012 date: Thu Jan 01 00:00:00 1970 +0000
1012 date: Thu Jan 01 00:00:00 1970 +0000
1013 summary: Last merge, related
1013 summary: Last merge, related
1014
1014
1015 changeset: 9:7b35701b003e
1015 changeset: 9:7b35701b003e
1016 parent: 8:e5416ad8a855
1016 parent: 8:e5416ad8a855
1017 parent: 7:87fe3144dcfa
1017 parent: 7:87fe3144dcfa
1018 user: test
1018 user: test
1019 date: Thu Jan 01 00:00:00 1970 +0000
1019 date: Thu Jan 01 00:00:00 1970 +0000
1020 summary: First merge, related
1020 summary: First merge, related
1021
1021
1022 changeset: 8:e5416ad8a855
1022 changeset: 8:e5416ad8a855
1023 parent: 6:dc6c325fe5ee
1023 parent: 6:dc6c325fe5ee
1024 user: test
1024 user: test
1025 date: Thu Jan 01 00:00:00 1970 +0000
1025 date: Thu Jan 01 00:00:00 1970 +0000
1026 summary: change foo in branch, related
1026 summary: change foo in branch, related
1027
1027
1028 changeset: 7:87fe3144dcfa
1028 changeset: 7:87fe3144dcfa
1029 user: test
1029 user: test
1030 date: Thu Jan 01 00:00:00 1970 +0000
1030 date: Thu Jan 01 00:00:00 1970 +0000
1031 summary: change foo, related
1031 summary: change foo, related
1032
1032
1033 changeset: 6:dc6c325fe5ee
1033 changeset: 6:dc6c325fe5ee
1034 user: test
1034 user: test
1035 date: Thu Jan 01 00:00:00 1970 +0000
1035 date: Thu Jan 01 00:00:00 1970 +0000
1036 summary: create foo, related
1036 summary: create foo, related
1037
1037
1038 changeset: 4:88176d361b69
1038 changeset: 4:88176d361b69
1039 user: test
1039 user: test
1040 date: Thu Jan 01 00:00:00 1970 +0000
1040 date: Thu Jan 01 00:00:00 1970 +0000
1041 summary: add foo, related
1041 summary: add foo, related
1042
1042
1043
1043
1044 Also check when maxrev < lastrevfilelog
1044 Also check when maxrev < lastrevfilelog
1045
1045
1046 $ hg --traceback log -f -r4 foo
1046 $ hg --traceback log -f -r4 foo
1047 changeset: 4:88176d361b69
1047 changeset: 4:88176d361b69
1048 user: test
1048 user: test
1049 date: Thu Jan 01 00:00:00 1970 +0000
1049 date: Thu Jan 01 00:00:00 1970 +0000
1050 summary: add foo, related
1050 summary: add foo, related
1051
1051
1052
1052
1053 Issue2383: hg log showing _less_ differences than hg diff
1053 Issue2383: hg log showing _less_ differences than hg diff
1054
1054
1055 $ hg init issue2383
1055 $ hg init issue2383
1056 $ cd issue2383
1056 $ cd issue2383
1057
1057
1058 Create a test repo:
1058 Create a test repo:
1059
1059
1060 $ echo a > a
1060 $ echo a > a
1061 $ hg ci -Am0
1061 $ hg ci -Am0
1062 adding a
1062 adding a
1063 $ echo b > b
1063 $ echo b > b
1064 $ hg ci -Am1
1064 $ hg ci -Am1
1065 adding b
1065 adding b
1066 $ hg co 0
1066 $ hg co 0
1067 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1067 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1068 $ echo b > a
1068 $ echo b > a
1069 $ hg ci -m2
1069 $ hg ci -m2
1070 created new head
1070 created new head
1071
1071
1072 Merge:
1072 Merge:
1073
1073
1074 $ hg merge
1074 $ hg merge
1075 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1075 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1076 (branch merge, don't forget to commit)
1076 (branch merge, don't forget to commit)
1077
1077
1078 Make sure there's a file listed in the merge to trigger the bug:
1078 Make sure there's a file listed in the merge to trigger the bug:
1079
1079
1080 $ echo c > a
1080 $ echo c > a
1081 $ hg ci -m3
1081 $ hg ci -m3
1082
1082
1083 Two files shown here in diff:
1083 Two files shown here in diff:
1084
1084
1085 $ hg diff --rev 2:3
1085 $ hg diff --rev 2:3
1086 diff -r b09be438c43a -r 8e07aafe1edc a
1086 diff -r b09be438c43a -r 8e07aafe1edc a
1087 --- a/a Thu Jan 01 00:00:00 1970 +0000
1087 --- a/a Thu Jan 01 00:00:00 1970 +0000
1088 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1088 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1089 @@ -1,1 +1,1 @@
1089 @@ -1,1 +1,1 @@
1090 -b
1090 -b
1091 +c
1091 +c
1092 diff -r b09be438c43a -r 8e07aafe1edc b
1092 diff -r b09be438c43a -r 8e07aafe1edc b
1093 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1093 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1094 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1094 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1095 @@ -0,0 +1,1 @@
1095 @@ -0,0 +1,1 @@
1096 +b
1096 +b
1097
1097
1098 Diff here should be the same:
1098 Diff here should be the same:
1099
1099
1100 $ hg log -vpr 3
1100 $ hg log -vpr 3
1101 changeset: 3:8e07aafe1edc
1101 changeset: 3:8e07aafe1edc
1102 tag: tip
1102 tag: tip
1103 parent: 2:b09be438c43a
1103 parent: 2:b09be438c43a
1104 parent: 1:925d80f479bb
1104 parent: 1:925d80f479bb
1105 user: test
1105 user: test
1106 date: Thu Jan 01 00:00:00 1970 +0000
1106 date: Thu Jan 01 00:00:00 1970 +0000
1107 files: a
1107 files: a
1108 description:
1108 description:
1109 3
1109 3
1110
1110
1111
1111
1112 diff -r b09be438c43a -r 8e07aafe1edc a
1112 diff -r b09be438c43a -r 8e07aafe1edc a
1113 --- a/a Thu Jan 01 00:00:00 1970 +0000
1113 --- a/a Thu Jan 01 00:00:00 1970 +0000
1114 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1114 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1115 @@ -1,1 +1,1 @@
1115 @@ -1,1 +1,1 @@
1116 -b
1116 -b
1117 +c
1117 +c
1118 diff -r b09be438c43a -r 8e07aafe1edc b
1118 diff -r b09be438c43a -r 8e07aafe1edc b
1119 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1119 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1120 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1120 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1121 @@ -0,0 +1,1 @@
1121 @@ -0,0 +1,1 @@
1122 +b
1122 +b
1123
1123
1124 $ cd ..
1124 $ cd ..
1125
1125
1126 'hg log -r rev fn' when last(filelog(fn)) != rev
1126 'hg log -r rev fn' when last(filelog(fn)) != rev
1127
1127
1128 $ hg init simplelog; cd simplelog
1128 $ hg init simplelog; cd simplelog
1129 $ echo f > a
1129 $ echo f > a
1130 $ hg ci -Am'a' -d '0 0'
1130 $ hg ci -Am'a' -d '0 0'
1131 adding a
1131 adding a
1132 $ echo f >> a
1132 $ echo f >> a
1133 $ hg ci -Am'a bis' -d '1 0'
1133 $ hg ci -Am'a bis' -d '1 0'
1134
1134
1135 $ hg log -r0 a
1135 $ hg log -r0 a
1136 changeset: 0:9f758d63dcde
1136 changeset: 0:9f758d63dcde
1137 user: test
1137 user: test
1138 date: Thu Jan 01 00:00:00 1970 +0000
1138 date: Thu Jan 01 00:00:00 1970 +0000
1139 summary: a
1139 summary: a
1140
1140
1141 $ cat > $HGTMP/testhidden.py << EOF
1142 > def reposetup(ui, repo):
1143 > for line in repo.opener('hidden'):
1144 > ctx = repo[line.strip()]
1145 > repo.changelog.hiddenrevs.add(ctx.rev())
1146 > EOF
1147 $ echo '[extensions]' >> $HGRCPATH
1148 $ echo "hidden=$HGTMP/testhidden.py" >> $HGRCPATH
1149 $ touch .hg/hidden
1150 $ hg log --template='{rev}:{node}\n'
1151 1:a765632148dc55d38c35c4f247c618701886cb2f
1152 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1153 $ echo a765632148dc55d38c35c4f247c618701886cb2f > .hg/hidden
1154 $ hg log --template='{rev}:{node}\n'
1155 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1156 $ hg log --template='{rev}:{node}\n' --hidden
1157 1:a765632148dc55d38c35c4f247c618701886cb2f
1158 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
General Comments 0
You need to be logged in to leave comments. Login now