##// END OF EJS Templates
tag: clarify cryptic error message when tagging null revision
Mads Kiilerich -
r18906:ef706817 default
parent child Browse files
Show More
@@ -1,5837 +1,5837 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 if bmctx.rev() in anc:
819 if bmctx.rev() in anc:
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
821 (mark, short(bmctx.node())))
821 (mark, short(bmctx.node())))
822 return
822 return
823 raise util.Abort(_("bookmark '%s' already exists "
823 raise util.Abort(_("bookmark '%s' already exists "
824 "(use -f to force)") % mark)
824 "(use -f to force)") % mark)
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
826 and not force):
826 and not force):
827 raise util.Abort(
827 raise util.Abort(
828 _("a bookmark cannot have the name of an existing branch"))
828 _("a bookmark cannot have the name of an existing branch"))
829
829
830 if delete and rename:
830 if delete and rename:
831 raise util.Abort(_("--delete and --rename are incompatible"))
831 raise util.Abort(_("--delete and --rename are incompatible"))
832 if delete and rev:
832 if delete and rev:
833 raise util.Abort(_("--rev is incompatible with --delete"))
833 raise util.Abort(_("--rev is incompatible with --delete"))
834 if rename and rev:
834 if rename and rev:
835 raise util.Abort(_("--rev is incompatible with --rename"))
835 raise util.Abort(_("--rev is incompatible with --rename"))
836 if mark is None and (delete or rev):
836 if mark is None and (delete or rev):
837 raise util.Abort(_("bookmark name required"))
837 raise util.Abort(_("bookmark name required"))
838
838
839 if delete:
839 if delete:
840 if mark not in marks:
840 if mark not in marks:
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
842 if mark == repo._bookmarkcurrent:
842 if mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
843 bookmarks.setcurrent(repo, None)
844 del marks[mark]
844 del marks[mark]
845 marks.write()
845 marks.write()
846
846
847 elif rename:
847 elif rename:
848 if mark is None:
848 if mark is None:
849 raise util.Abort(_("new bookmark name required"))
849 raise util.Abort(_("new bookmark name required"))
850 mark = checkformat(mark)
850 mark = checkformat(mark)
851 if rename not in marks:
851 if rename not in marks:
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 marks[mark] = marks[rename]
854 marks[mark] = marks[rename]
855 if repo._bookmarkcurrent == rename and not inactive:
855 if repo._bookmarkcurrent == rename and not inactive:
856 bookmarks.setcurrent(repo, mark)
856 bookmarks.setcurrent(repo, mark)
857 del marks[rename]
857 del marks[rename]
858 marks.write()
858 marks.write()
859
859
860 elif mark is not None:
860 elif mark is not None:
861 mark = checkformat(mark)
861 mark = checkformat(mark)
862 if inactive and mark == repo._bookmarkcurrent:
862 if inactive and mark == repo._bookmarkcurrent:
863 bookmarks.setcurrent(repo, None)
863 bookmarks.setcurrent(repo, None)
864 return
864 return
865 tgt = cur
865 tgt = cur
866 if rev:
866 if rev:
867 tgt = scmutil.revsingle(repo, rev).node()
867 tgt = scmutil.revsingle(repo, rev).node()
868 checkconflict(repo, mark, force, tgt)
868 checkconflict(repo, mark, force, tgt)
869 marks[mark] = tgt
869 marks[mark] = tgt
870 if not inactive and cur == marks[mark]:
870 if not inactive and cur == marks[mark]:
871 bookmarks.setcurrent(repo, mark)
871 bookmarks.setcurrent(repo, mark)
872 elif cur != tgt and mark == repo._bookmarkcurrent:
872 elif cur != tgt and mark == repo._bookmarkcurrent:
873 bookmarks.setcurrent(repo, None)
873 bookmarks.setcurrent(repo, None)
874 marks.write()
874 marks.write()
875
875
876 # Same message whether trying to deactivate the current bookmark (-i
876 # Same message whether trying to deactivate the current bookmark (-i
877 # with no NAME) or listing bookmarks
877 # with no NAME) or listing bookmarks
878 elif len(marks) == 0:
878 elif len(marks) == 0:
879 ui.status(_("no bookmarks set\n"))
879 ui.status(_("no bookmarks set\n"))
880
880
881 elif inactive:
881 elif inactive:
882 if not repo._bookmarkcurrent:
882 if not repo._bookmarkcurrent:
883 ui.status(_("no active bookmark\n"))
883 ui.status(_("no active bookmark\n"))
884 else:
884 else:
885 bookmarks.setcurrent(repo, None)
885 bookmarks.setcurrent(repo, None)
886
886
887 else: # show bookmarks
887 else: # show bookmarks
888 for bmark, n in sorted(marks.iteritems()):
888 for bmark, n in sorted(marks.iteritems()):
889 current = repo._bookmarkcurrent
889 current = repo._bookmarkcurrent
890 if bmark == current:
890 if bmark == current:
891 prefix, label = '*', 'bookmarks.current'
891 prefix, label = '*', 'bookmarks.current'
892 else:
892 else:
893 prefix, label = ' ', ''
893 prefix, label = ' ', ''
894
894
895 if ui.quiet:
895 if ui.quiet:
896 ui.write("%s\n" % bmark, label=label)
896 ui.write("%s\n" % bmark, label=label)
897 else:
897 else:
898 ui.write(" %s %-25s %d:%s\n" % (
898 ui.write(" %s %-25s %d:%s\n" % (
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
900 label=label)
900 label=label)
901
901
902 @command('branch',
902 @command('branch',
903 [('f', 'force', None,
903 [('f', 'force', None,
904 _('set branch name even if it shadows an existing branch')),
904 _('set branch name even if it shadows an existing branch')),
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
906 _('[-fC] [NAME]'))
906 _('[-fC] [NAME]'))
907 def branch(ui, repo, label=None, **opts):
907 def branch(ui, repo, label=None, **opts):
908 """set or show the current branch name
908 """set or show the current branch name
909
909
910 .. note::
910 .. note::
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
912 light-weight bookmark instead. See :hg:`help glossary` for more
912 light-weight bookmark instead. See :hg:`help glossary` for more
913 information about named branches and bookmarks.
913 information about named branches and bookmarks.
914
914
915 With no argument, show the current branch name. With one argument,
915 With no argument, show the current branch name. With one argument,
916 set the working directory branch name (the branch will not exist
916 set the working directory branch name (the branch will not exist
917 in the repository until the next commit). Standard practice
917 in the repository until the next commit). Standard practice
918 recommends that primary development take place on the 'default'
918 recommends that primary development take place on the 'default'
919 branch.
919 branch.
920
920
921 Unless -f/--force is specified, branch will not let you set a
921 Unless -f/--force is specified, branch will not let you set a
922 branch name that already exists, even if it's inactive.
922 branch name that already exists, even if it's inactive.
923
923
924 Use -C/--clean to reset the working directory branch to that of
924 Use -C/--clean to reset the working directory branch to that of
925 the parent of the working directory, negating a previous branch
925 the parent of the working directory, negating a previous branch
926 change.
926 change.
927
927
928 Use the command :hg:`update` to switch to an existing branch. Use
928 Use the command :hg:`update` to switch to an existing branch. Use
929 :hg:`commit --close-branch` to mark this branch as closed.
929 :hg:`commit --close-branch` to mark this branch as closed.
930
930
931 Returns 0 on success.
931 Returns 0 on success.
932 """
932 """
933 if not opts.get('clean') and not label:
933 if not opts.get('clean') and not label:
934 ui.write("%s\n" % repo.dirstate.branch())
934 ui.write("%s\n" % repo.dirstate.branch())
935 return
935 return
936
936
937 wlock = repo.wlock()
937 wlock = repo.wlock()
938 try:
938 try:
939 if opts.get('clean'):
939 if opts.get('clean'):
940 label = repo[None].p1().branch()
940 label = repo[None].p1().branch()
941 repo.dirstate.setbranch(label)
941 repo.dirstate.setbranch(label)
942 ui.status(_('reset working directory to branch %s\n') % label)
942 ui.status(_('reset working directory to branch %s\n') % label)
943 elif label:
943 elif label:
944 if not opts.get('force') and label in repo.branchmap():
944 if not opts.get('force') and label in repo.branchmap():
945 if label not in [p.branch() for p in repo.parents()]:
945 if label not in [p.branch() for p in repo.parents()]:
946 raise util.Abort(_('a branch of the same name already'
946 raise util.Abort(_('a branch of the same name already'
947 ' exists'),
947 ' exists'),
948 # i18n: "it" refers to an existing branch
948 # i18n: "it" refers to an existing branch
949 hint=_("use 'hg update' to switch to it"))
949 hint=_("use 'hg update' to switch to it"))
950 scmutil.checknewlabel(repo, label, 'branch')
950 scmutil.checknewlabel(repo, label, 'branch')
951 repo.dirstate.setbranch(label)
951 repo.dirstate.setbranch(label)
952 ui.status(_('marked working directory as branch %s\n') % label)
952 ui.status(_('marked working directory as branch %s\n') % label)
953 ui.status(_('(branches are permanent and global, '
953 ui.status(_('(branches are permanent and global, '
954 'did you want a bookmark?)\n'))
954 'did you want a bookmark?)\n'))
955 finally:
955 finally:
956 wlock.release()
956 wlock.release()
957
957
958 @command('branches',
958 @command('branches',
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
960 ('c', 'closed', False, _('show normal and closed branches'))],
960 ('c', 'closed', False, _('show normal and closed branches'))],
961 _('[-ac]'))
961 _('[-ac]'))
962 def branches(ui, repo, active=False, closed=False):
962 def branches(ui, repo, active=False, closed=False):
963 """list repository named branches
963 """list repository named branches
964
964
965 List the repository's named branches, indicating which ones are
965 List the repository's named branches, indicating which ones are
966 inactive. If -c/--closed is specified, also list branches which have
966 inactive. If -c/--closed is specified, also list branches which have
967 been marked closed (see :hg:`commit --close-branch`).
967 been marked closed (see :hg:`commit --close-branch`).
968
968
969 If -a/--active is specified, only show active branches. A branch
969 If -a/--active is specified, only show active branches. A branch
970 is considered active if it contains repository heads.
970 is considered active if it contains repository heads.
971
971
972 Use the command :hg:`update` to switch to an existing branch.
972 Use the command :hg:`update` to switch to an existing branch.
973
973
974 Returns 0.
974 Returns 0.
975 """
975 """
976
976
977 hexfunc = ui.debugflag and hex or short
977 hexfunc = ui.debugflag and hex or short
978
978
979 activebranches = set([repo[n].branch() for n in repo.heads()])
979 activebranches = set([repo[n].branch() for n in repo.heads()])
980 branches = []
980 branches = []
981 for tag, heads in repo.branchmap().iteritems():
981 for tag, heads in repo.branchmap().iteritems():
982 for h in reversed(heads):
982 for h in reversed(heads):
983 ctx = repo[h]
983 ctx = repo[h]
984 isopen = not ctx.closesbranch()
984 isopen = not ctx.closesbranch()
985 if isopen:
985 if isopen:
986 tip = ctx
986 tip = ctx
987 break
987 break
988 else:
988 else:
989 tip = repo[heads[-1]]
989 tip = repo[heads[-1]]
990 isactive = tag in activebranches and isopen
990 isactive = tag in activebranches and isopen
991 branches.append((tip, isactive, isopen))
991 branches.append((tip, isactive, isopen))
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
993 reverse=True)
993 reverse=True)
994
994
995 for ctx, isactive, isopen in branches:
995 for ctx, isactive, isopen in branches:
996 if (not active) or isactive:
996 if (not active) or isactive:
997 if isactive:
997 if isactive:
998 label = 'branches.active'
998 label = 'branches.active'
999 notice = ''
999 notice = ''
1000 elif not isopen:
1000 elif not isopen:
1001 if not closed:
1001 if not closed:
1002 continue
1002 continue
1003 label = 'branches.closed'
1003 label = 'branches.closed'
1004 notice = _(' (closed)')
1004 notice = _(' (closed)')
1005 else:
1005 else:
1006 label = 'branches.inactive'
1006 label = 'branches.inactive'
1007 notice = _(' (inactive)')
1007 notice = _(' (inactive)')
1008 if ctx.branch() == repo.dirstate.branch():
1008 if ctx.branch() == repo.dirstate.branch():
1009 label = 'branches.current'
1009 label = 'branches.current'
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1012 'log.changeset changeset.%s' % ctx.phasestr())
1012 'log.changeset changeset.%s' % ctx.phasestr())
1013 tag = ui.label(ctx.branch(), label)
1013 tag = ui.label(ctx.branch(), label)
1014 if ui.quiet:
1014 if ui.quiet:
1015 ui.write("%s\n" % tag)
1015 ui.write("%s\n" % tag)
1016 else:
1016 else:
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1018
1018
1019 @command('bundle',
1019 @command('bundle',
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1022 _('REV')),
1022 _('REV')),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1024 _('BRANCH')),
1024 _('BRANCH')),
1025 ('', 'base', [],
1025 ('', 'base', [],
1026 _('a base changeset assumed to be available at the destination'),
1026 _('a base changeset assumed to be available at the destination'),
1027 _('REV')),
1027 _('REV')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1032 def bundle(ui, repo, fname, dest=None, **opts):
1032 def bundle(ui, repo, fname, dest=None, **opts):
1033 """create a changegroup file
1033 """create a changegroup file
1034
1034
1035 Generate a compressed changegroup file collecting changesets not
1035 Generate a compressed changegroup file collecting changesets not
1036 known to be in another repository.
1036 known to be in another repository.
1037
1037
1038 If you omit the destination repository, then hg assumes the
1038 If you omit the destination repository, then hg assumes the
1039 destination will have all the nodes you specify with --base
1039 destination will have all the nodes you specify with --base
1040 parameters. To create a bundle containing all changesets, use
1040 parameters. To create a bundle containing all changesets, use
1041 -a/--all (or --base null).
1041 -a/--all (or --base null).
1042
1042
1043 You can change compression method with the -t/--type option.
1043 You can change compression method with the -t/--type option.
1044 The available compression methods are: none, bzip2, and
1044 The available compression methods are: none, bzip2, and
1045 gzip (by default, bundles are compressed using bzip2).
1045 gzip (by default, bundles are compressed using bzip2).
1046
1046
1047 The bundle file can then be transferred using conventional means
1047 The bundle file can then be transferred using conventional means
1048 and applied to another repository with the unbundle or pull
1048 and applied to another repository with the unbundle or pull
1049 command. This is useful when direct push and pull are not
1049 command. This is useful when direct push and pull are not
1050 available or when exporting an entire repository is undesirable.
1050 available or when exporting an entire repository is undesirable.
1051
1051
1052 Applying bundles preserves all changeset contents including
1052 Applying bundles preserves all changeset contents including
1053 permissions, copy/rename information, and revision history.
1053 permissions, copy/rename information, and revision history.
1054
1054
1055 Returns 0 on success, 1 if no changes found.
1055 Returns 0 on success, 1 if no changes found.
1056 """
1056 """
1057 revs = None
1057 revs = None
1058 if 'rev' in opts:
1058 if 'rev' in opts:
1059 revs = scmutil.revrange(repo, opts['rev'])
1059 revs = scmutil.revrange(repo, opts['rev'])
1060
1060
1061 bundletype = opts.get('type', 'bzip2').lower()
1061 bundletype = opts.get('type', 'bzip2').lower()
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1063 bundletype = btypes.get(bundletype)
1063 bundletype = btypes.get(bundletype)
1064 if bundletype not in changegroup.bundletypes:
1064 if bundletype not in changegroup.bundletypes:
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1066
1066
1067 if opts.get('all'):
1067 if opts.get('all'):
1068 base = ['null']
1068 base = ['null']
1069 else:
1069 else:
1070 base = scmutil.revrange(repo, opts.get('base'))
1070 base = scmutil.revrange(repo, opts.get('base'))
1071 if base:
1071 if base:
1072 if dest:
1072 if dest:
1073 raise util.Abort(_("--base is incompatible with specifying "
1073 raise util.Abort(_("--base is incompatible with specifying "
1074 "a destination"))
1074 "a destination"))
1075 common = [repo.lookup(rev) for rev in base]
1075 common = [repo.lookup(rev) for rev in base]
1076 heads = revs and map(repo.lookup, revs) or revs
1076 heads = revs and map(repo.lookup, revs) or revs
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1078 outgoing = None
1078 outgoing = None
1079 else:
1079 else:
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1082 other = hg.peer(repo, opts, dest)
1082 other = hg.peer(repo, opts, dest)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1084 heads = revs and map(repo.lookup, revs) or revs
1084 heads = revs and map(repo.lookup, revs) or revs
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1086 onlyheads=heads,
1086 onlyheads=heads,
1087 force=opts.get('force'),
1087 force=opts.get('force'),
1088 portable=True)
1088 portable=True)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1090 if not cg:
1090 if not cg:
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1092 return 1
1092 return 1
1093
1093
1094 changegroup.writebundle(cg, fname, bundletype)
1094 changegroup.writebundle(cg, fname, bundletype)
1095
1095
1096 @command('cat',
1096 @command('cat',
1097 [('o', 'output', '',
1097 [('o', 'output', '',
1098 _('print output to file with formatted name'), _('FORMAT')),
1098 _('print output to file with formatted name'), _('FORMAT')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1101 ] + walkopts,
1101 ] + walkopts,
1102 _('[OPTION]... FILE...'))
1102 _('[OPTION]... FILE...'))
1103 def cat(ui, repo, file1, *pats, **opts):
1103 def cat(ui, repo, file1, *pats, **opts):
1104 """output the current or given revision of files
1104 """output the current or given revision of files
1105
1105
1106 Print the specified files as they were at the given revision. If
1106 Print the specified files as they were at the given revision. If
1107 no revision is given, the parent of the working directory is used,
1107 no revision is given, the parent of the working directory is used,
1108 or tip if no revision is checked out.
1108 or tip if no revision is checked out.
1109
1109
1110 Output may be to a file, in which case the name of the file is
1110 Output may be to a file, in which case the name of the file is
1111 given using a format string. The formatting rules are the same as
1111 given using a format string. The formatting rules are the same as
1112 for the export command, with the following additions:
1112 for the export command, with the following additions:
1113
1113
1114 :``%s``: basename of file being printed
1114 :``%s``: basename of file being printed
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1116 :``%p``: root-relative path name of file being printed
1116 :``%p``: root-relative path name of file being printed
1117
1117
1118 Returns 0 on success.
1118 Returns 0 on success.
1119 """
1119 """
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1121 err = 1
1121 err = 1
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1123 for abs in ctx.walk(m):
1123 for abs in ctx.walk(m):
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1125 pathname=abs)
1125 pathname=abs)
1126 data = ctx[abs].data()
1126 data = ctx[abs].data()
1127 if opts.get('decode'):
1127 if opts.get('decode'):
1128 data = repo.wwritedata(abs, data)
1128 data = repo.wwritedata(abs, data)
1129 fp.write(data)
1129 fp.write(data)
1130 fp.close()
1130 fp.close()
1131 err = 0
1131 err = 0
1132 return err
1132 return err
1133
1133
1134 @command('^clone',
1134 @command('^clone',
1135 [('U', 'noupdate', None,
1135 [('U', 'noupdate', None,
1136 _('the clone will include an empty working copy (only a repository)')),
1136 _('the clone will include an empty working copy (only a repository)')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1142 ] + remoteopts,
1142 ] + remoteopts,
1143 _('[OPTION]... SOURCE [DEST]'))
1143 _('[OPTION]... SOURCE [DEST]'))
1144 def clone(ui, source, dest=None, **opts):
1144 def clone(ui, source, dest=None, **opts):
1145 """make a copy of an existing repository
1145 """make a copy of an existing repository
1146
1146
1147 Create a copy of an existing repository in a new directory.
1147 Create a copy of an existing repository in a new directory.
1148
1148
1149 If no destination directory name is specified, it defaults to the
1149 If no destination directory name is specified, it defaults to the
1150 basename of the source.
1150 basename of the source.
1151
1151
1152 The location of the source is added to the new repository's
1152 The location of the source is added to the new repository's
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1154
1154
1155 Only local paths and ``ssh://`` URLs are supported as
1155 Only local paths and ``ssh://`` URLs are supported as
1156 destinations. For ``ssh://`` destinations, no working directory or
1156 destinations. For ``ssh://`` destinations, no working directory or
1157 ``.hg/hgrc`` will be created on the remote side.
1157 ``.hg/hgrc`` will be created on the remote side.
1158
1158
1159 To pull only a subset of changesets, specify one or more revisions
1159 To pull only a subset of changesets, specify one or more revisions
1160 identifiers with -r/--rev or branches with -b/--branch. The
1160 identifiers with -r/--rev or branches with -b/--branch. The
1161 resulting clone will contain only the specified changesets and
1161 resulting clone will contain only the specified changesets and
1162 their ancestors. These options (or 'clone src#rev dest') imply
1162 their ancestors. These options (or 'clone src#rev dest') imply
1163 --pull, even for local source repositories. Note that specifying a
1163 --pull, even for local source repositories. Note that specifying a
1164 tag will include the tagged changeset but not the changeset
1164 tag will include the tagged changeset but not the changeset
1165 containing the tag.
1165 containing the tag.
1166
1166
1167 If the source repository has a bookmark called '@' set, that
1167 If the source repository has a bookmark called '@' set, that
1168 revision will be checked out in the new repository by default.
1168 revision will be checked out in the new repository by default.
1169
1169
1170 To check out a particular version, use -u/--update, or
1170 To check out a particular version, use -u/--update, or
1171 -U/--noupdate to create a clone with no working directory.
1171 -U/--noupdate to create a clone with no working directory.
1172
1172
1173 .. container:: verbose
1173 .. container:: verbose
1174
1174
1175 For efficiency, hardlinks are used for cloning whenever the
1175 For efficiency, hardlinks are used for cloning whenever the
1176 source and destination are on the same filesystem (note this
1176 source and destination are on the same filesystem (note this
1177 applies only to the repository data, not to the working
1177 applies only to the repository data, not to the working
1178 directory). Some filesystems, such as AFS, implement hardlinking
1178 directory). Some filesystems, such as AFS, implement hardlinking
1179 incorrectly, but do not report errors. In these cases, use the
1179 incorrectly, but do not report errors. In these cases, use the
1180 --pull option to avoid hardlinking.
1180 --pull option to avoid hardlinking.
1181
1181
1182 In some cases, you can clone repositories and the working
1182 In some cases, you can clone repositories and the working
1183 directory using full hardlinks with ::
1183 directory using full hardlinks with ::
1184
1184
1185 $ cp -al REPO REPOCLONE
1185 $ cp -al REPO REPOCLONE
1186
1186
1187 This is the fastest way to clone, but it is not always safe. The
1187 This is the fastest way to clone, but it is not always safe. The
1188 operation is not atomic (making sure REPO is not modified during
1188 operation is not atomic (making sure REPO is not modified during
1189 the operation is up to you) and you have to make sure your
1189 the operation is up to you) and you have to make sure your
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1191 so). Also, this is not compatible with certain extensions that
1191 so). Also, this is not compatible with certain extensions that
1192 place their metadata under the .hg directory, such as mq.
1192 place their metadata under the .hg directory, such as mq.
1193
1193
1194 Mercurial will update the working directory to the first applicable
1194 Mercurial will update the working directory to the first applicable
1195 revision from this list:
1195 revision from this list:
1196
1196
1197 a) null if -U or the source repository has no changesets
1197 a) null if -U or the source repository has no changesets
1198 b) if -u . and the source repository is local, the first parent of
1198 b) if -u . and the source repository is local, the first parent of
1199 the source repository's working directory
1199 the source repository's working directory
1200 c) the changeset specified with -u (if a branch name, this means the
1200 c) the changeset specified with -u (if a branch name, this means the
1201 latest head of that branch)
1201 latest head of that branch)
1202 d) the changeset specified with -r
1202 d) the changeset specified with -r
1203 e) the tipmost head specified with -b
1203 e) the tipmost head specified with -b
1204 f) the tipmost head specified with the url#branch source syntax
1204 f) the tipmost head specified with the url#branch source syntax
1205 g) the revision marked with the '@' bookmark, if present
1205 g) the revision marked with the '@' bookmark, if present
1206 h) the tipmost head of the default branch
1206 h) the tipmost head of the default branch
1207 i) tip
1207 i) tip
1208
1208
1209 Examples:
1209 Examples:
1210
1210
1211 - clone a remote repository to a new directory named hg/::
1211 - clone a remote repository to a new directory named hg/::
1212
1212
1213 hg clone http://selenic.com/hg
1213 hg clone http://selenic.com/hg
1214
1214
1215 - create a lightweight local clone::
1215 - create a lightweight local clone::
1216
1216
1217 hg clone project/ project-feature/
1217 hg clone project/ project-feature/
1218
1218
1219 - clone from an absolute path on an ssh server (note double-slash)::
1219 - clone from an absolute path on an ssh server (note double-slash)::
1220
1220
1221 hg clone ssh://user@server//home/projects/alpha/
1221 hg clone ssh://user@server//home/projects/alpha/
1222
1222
1223 - do a high-speed clone over a LAN while checking out a
1223 - do a high-speed clone over a LAN while checking out a
1224 specified version::
1224 specified version::
1225
1225
1226 hg clone --uncompressed http://server/repo -u 1.5
1226 hg clone --uncompressed http://server/repo -u 1.5
1227
1227
1228 - create a repository without changesets after a particular revision::
1228 - create a repository without changesets after a particular revision::
1229
1229
1230 hg clone -r 04e544 experimental/ good/
1230 hg clone -r 04e544 experimental/ good/
1231
1231
1232 - clone (and track) a particular named branch::
1232 - clone (and track) a particular named branch::
1233
1233
1234 hg clone http://selenic.com/hg#stable
1234 hg clone http://selenic.com/hg#stable
1235
1235
1236 See :hg:`help urls` for details on specifying URLs.
1236 See :hg:`help urls` for details on specifying URLs.
1237
1237
1238 Returns 0 on success.
1238 Returns 0 on success.
1239 """
1239 """
1240 if opts.get('noupdate') and opts.get('updaterev'):
1240 if opts.get('noupdate') and opts.get('updaterev'):
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1242
1242
1243 r = hg.clone(ui, opts, source, dest,
1243 r = hg.clone(ui, opts, source, dest,
1244 pull=opts.get('pull'),
1244 pull=opts.get('pull'),
1245 stream=opts.get('uncompressed'),
1245 stream=opts.get('uncompressed'),
1246 rev=opts.get('rev'),
1246 rev=opts.get('rev'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1248 branch=opts.get('branch'))
1248 branch=opts.get('branch'))
1249
1249
1250 return r is None
1250 return r is None
1251
1251
1252 @command('^commit|ci',
1252 @command('^commit|ci',
1253 [('A', 'addremove', None,
1253 [('A', 'addremove', None,
1254 _('mark new/missing files as added/removed before committing')),
1254 _('mark new/missing files as added/removed before committing')),
1255 ('', 'close-branch', None,
1255 ('', 'close-branch', None,
1256 _('mark a branch as closed, hiding it from the branch list')),
1256 _('mark a branch as closed, hiding it from the branch list')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1259 _('[OPTION]... [FILE]...'))
1259 _('[OPTION]... [FILE]...'))
1260 def commit(ui, repo, *pats, **opts):
1260 def commit(ui, repo, *pats, **opts):
1261 """commit the specified files or all outstanding changes
1261 """commit the specified files or all outstanding changes
1262
1262
1263 Commit changes to the given files into the repository. Unlike a
1263 Commit changes to the given files into the repository. Unlike a
1264 centralized SCM, this operation is a local operation. See
1264 centralized SCM, this operation is a local operation. See
1265 :hg:`push` for a way to actively distribute your changes.
1265 :hg:`push` for a way to actively distribute your changes.
1266
1266
1267 If a list of files is omitted, all changes reported by :hg:`status`
1267 If a list of files is omitted, all changes reported by :hg:`status`
1268 will be committed.
1268 will be committed.
1269
1269
1270 If you are committing the result of a merge, do not provide any
1270 If you are committing the result of a merge, do not provide any
1271 filenames or -I/-X filters.
1271 filenames or -I/-X filters.
1272
1272
1273 If no commit message is specified, Mercurial starts your
1273 If no commit message is specified, Mercurial starts your
1274 configured editor where you can enter a message. In case your
1274 configured editor where you can enter a message. In case your
1275 commit fails, you will find a backup of your message in
1275 commit fails, you will find a backup of your message in
1276 ``.hg/last-message.txt``.
1276 ``.hg/last-message.txt``.
1277
1277
1278 The --amend flag can be used to amend the parent of the
1278 The --amend flag can be used to amend the parent of the
1279 working directory with a new commit that contains the changes
1279 working directory with a new commit that contains the changes
1280 in the parent in addition to those currently reported by :hg:`status`,
1280 in the parent in addition to those currently reported by :hg:`status`,
1281 if there are any. The old commit is stored in a backup bundle in
1281 if there are any. The old commit is stored in a backup bundle in
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1283 on how to restore it).
1283 on how to restore it).
1284
1284
1285 Message, user and date are taken from the amended commit unless
1285 Message, user and date are taken from the amended commit unless
1286 specified. When a message isn't specified on the command line,
1286 specified. When a message isn't specified on the command line,
1287 the editor will open with the message of the amended commit.
1287 the editor will open with the message of the amended commit.
1288
1288
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1290 or changesets that have children.
1290 or changesets that have children.
1291
1291
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1293
1293
1294 Returns 0 on success, 1 if nothing changed.
1294 Returns 0 on success, 1 if nothing changed.
1295 """
1295 """
1296 if opts.get('subrepos'):
1296 if opts.get('subrepos'):
1297 # Let --subrepos on the command line override config setting.
1297 # Let --subrepos on the command line override config setting.
1298 ui.setconfig('ui', 'commitsubrepos', True)
1298 ui.setconfig('ui', 'commitsubrepos', True)
1299
1299
1300 extra = {}
1300 extra = {}
1301 if opts.get('close_branch'):
1301 if opts.get('close_branch'):
1302 if repo['.'].node() not in repo.branchheads():
1302 if repo['.'].node() not in repo.branchheads():
1303 # The topo heads set is included in the branch heads set of the
1303 # The topo heads set is included in the branch heads set of the
1304 # current branch, so it's sufficient to test branchheads
1304 # current branch, so it's sufficient to test branchheads
1305 raise util.Abort(_('can only close branch heads'))
1305 raise util.Abort(_('can only close branch heads'))
1306 extra['close'] = 1
1306 extra['close'] = 1
1307
1307
1308 branch = repo[None].branch()
1308 branch = repo[None].branch()
1309 bheads = repo.branchheads(branch)
1309 bheads = repo.branchheads(branch)
1310
1310
1311 if opts.get('amend'):
1311 if opts.get('amend'):
1312 if ui.configbool('ui', 'commitsubrepos'):
1312 if ui.configbool('ui', 'commitsubrepos'):
1313 raise util.Abort(_('cannot amend recursively'))
1313 raise util.Abort(_('cannot amend recursively'))
1314
1314
1315 old = repo['.']
1315 old = repo['.']
1316 if old.phase() == phases.public:
1316 if old.phase() == phases.public:
1317 raise util.Abort(_('cannot amend public changesets'))
1317 raise util.Abort(_('cannot amend public changesets'))
1318 if len(old.parents()) > 1:
1318 if len(old.parents()) > 1:
1319 raise util.Abort(_('cannot amend merge changesets'))
1319 raise util.Abort(_('cannot amend merge changesets'))
1320 if len(repo[None].parents()) > 1:
1320 if len(repo[None].parents()) > 1:
1321 raise util.Abort(_('cannot amend while merging'))
1321 raise util.Abort(_('cannot amend while merging'))
1322 if (not obsolete._enabled) and old.children():
1322 if (not obsolete._enabled) and old.children():
1323 raise util.Abort(_('cannot amend changeset with children'))
1323 raise util.Abort(_('cannot amend changeset with children'))
1324
1324
1325 e = cmdutil.commiteditor
1325 e = cmdutil.commiteditor
1326 if opts.get('force_editor'):
1326 if opts.get('force_editor'):
1327 e = cmdutil.commitforceeditor
1327 e = cmdutil.commitforceeditor
1328
1328
1329 def commitfunc(ui, repo, message, match, opts):
1329 def commitfunc(ui, repo, message, match, opts):
1330 editor = e
1330 editor = e
1331 # message contains text from -m or -l, if it's empty,
1331 # message contains text from -m or -l, if it's empty,
1332 # open the editor with the old message
1332 # open the editor with the old message
1333 if not message:
1333 if not message:
1334 message = old.description()
1334 message = old.description()
1335 editor = cmdutil.commitforceeditor
1335 editor = cmdutil.commitforceeditor
1336 return repo.commit(message,
1336 return repo.commit(message,
1337 opts.get('user') or old.user(),
1337 opts.get('user') or old.user(),
1338 opts.get('date') or old.date(),
1338 opts.get('date') or old.date(),
1339 match,
1339 match,
1340 editor=editor,
1340 editor=editor,
1341 extra=extra)
1341 extra=extra)
1342
1342
1343 current = repo._bookmarkcurrent
1343 current = repo._bookmarkcurrent
1344 marks = old.bookmarks()
1344 marks = old.bookmarks()
1345 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1345 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1346 if node == old.node():
1346 if node == old.node():
1347 ui.status(_("nothing changed\n"))
1347 ui.status(_("nothing changed\n"))
1348 return 1
1348 return 1
1349 elif marks:
1349 elif marks:
1350 ui.debug('moving bookmarks %r from %s to %s\n' %
1350 ui.debug('moving bookmarks %r from %s to %s\n' %
1351 (marks, old.hex(), hex(node)))
1351 (marks, old.hex(), hex(node)))
1352 newmarks = repo._bookmarks
1352 newmarks = repo._bookmarks
1353 for bm in marks:
1353 for bm in marks:
1354 newmarks[bm] = node
1354 newmarks[bm] = node
1355 if bm == current:
1355 if bm == current:
1356 bookmarks.setcurrent(repo, bm)
1356 bookmarks.setcurrent(repo, bm)
1357 newmarks.write()
1357 newmarks.write()
1358 else:
1358 else:
1359 e = cmdutil.commiteditor
1359 e = cmdutil.commiteditor
1360 if opts.get('force_editor'):
1360 if opts.get('force_editor'):
1361 e = cmdutil.commitforceeditor
1361 e = cmdutil.commitforceeditor
1362
1362
1363 def commitfunc(ui, repo, message, match, opts):
1363 def commitfunc(ui, repo, message, match, opts):
1364 return repo.commit(message, opts.get('user'), opts.get('date'),
1364 return repo.commit(message, opts.get('user'), opts.get('date'),
1365 match, editor=e, extra=extra)
1365 match, editor=e, extra=extra)
1366
1366
1367 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1367 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1368
1368
1369 if not node:
1369 if not node:
1370 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1370 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1371 if stat[3]:
1371 if stat[3]:
1372 ui.status(_("nothing changed (%d missing files, see "
1372 ui.status(_("nothing changed (%d missing files, see "
1373 "'hg status')\n") % len(stat[3]))
1373 "'hg status')\n") % len(stat[3]))
1374 else:
1374 else:
1375 ui.status(_("nothing changed\n"))
1375 ui.status(_("nothing changed\n"))
1376 return 1
1376 return 1
1377
1377
1378 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1378 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1379
1379
1380 @command('copy|cp',
1380 @command('copy|cp',
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1381 [('A', 'after', None, _('record a copy that has already occurred')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1382 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1383 ] + walkopts + dryrunopts,
1383 ] + walkopts + dryrunopts,
1384 _('[OPTION]... [SOURCE]... DEST'))
1384 _('[OPTION]... [SOURCE]... DEST'))
1385 def copy(ui, repo, *pats, **opts):
1385 def copy(ui, repo, *pats, **opts):
1386 """mark files as copied for the next commit
1386 """mark files as copied for the next commit
1387
1387
1388 Mark dest as having copies of source files. If dest is a
1388 Mark dest as having copies of source files. If dest is a
1389 directory, copies are put in that directory. If dest is a file,
1389 directory, copies are put in that directory. If dest is a file,
1390 the source must be a single file.
1390 the source must be a single file.
1391
1391
1392 By default, this command copies the contents of files as they
1392 By default, this command copies the contents of files as they
1393 exist in the working directory. If invoked with -A/--after, the
1393 exist in the working directory. If invoked with -A/--after, the
1394 operation is recorded, but no copying is performed.
1394 operation is recorded, but no copying is performed.
1395
1395
1396 This command takes effect with the next commit. To undo a copy
1396 This command takes effect with the next commit. To undo a copy
1397 before that, see :hg:`revert`.
1397 before that, see :hg:`revert`.
1398
1398
1399 Returns 0 on success, 1 if errors are encountered.
1399 Returns 0 on success, 1 if errors are encountered.
1400 """
1400 """
1401 wlock = repo.wlock(False)
1401 wlock = repo.wlock(False)
1402 try:
1402 try:
1403 return cmdutil.copy(ui, repo, pats, opts)
1403 return cmdutil.copy(ui, repo, pats, opts)
1404 finally:
1404 finally:
1405 wlock.release()
1405 wlock.release()
1406
1406
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1407 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1408 def debugancestor(ui, repo, *args):
1408 def debugancestor(ui, repo, *args):
1409 """find the ancestor revision of two revisions in a given index"""
1409 """find the ancestor revision of two revisions in a given index"""
1410 if len(args) == 3:
1410 if len(args) == 3:
1411 index, rev1, rev2 = args
1411 index, rev1, rev2 = args
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1412 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1413 lookup = r.lookup
1413 lookup = r.lookup
1414 elif len(args) == 2:
1414 elif len(args) == 2:
1415 if not repo:
1415 if not repo:
1416 raise util.Abort(_("there is no Mercurial repository here "
1416 raise util.Abort(_("there is no Mercurial repository here "
1417 "(.hg not found)"))
1417 "(.hg not found)"))
1418 rev1, rev2 = args
1418 rev1, rev2 = args
1419 r = repo.changelog
1419 r = repo.changelog
1420 lookup = repo.lookup
1420 lookup = repo.lookup
1421 else:
1421 else:
1422 raise util.Abort(_('either two or three arguments required'))
1422 raise util.Abort(_('either two or three arguments required'))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1423 a = r.ancestor(lookup(rev1), lookup(rev2))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1424 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1425
1425
1426 @command('debugbuilddag',
1426 @command('debugbuilddag',
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1427 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1428 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1429 ('n', 'new-file', None, _('add new file at each rev'))],
1430 _('[OPTION]... [TEXT]'))
1430 _('[OPTION]... [TEXT]'))
1431 def debugbuilddag(ui, repo, text=None,
1431 def debugbuilddag(ui, repo, text=None,
1432 mergeable_file=False,
1432 mergeable_file=False,
1433 overwritten_file=False,
1433 overwritten_file=False,
1434 new_file=False):
1434 new_file=False):
1435 """builds a repo with a given DAG from scratch in the current empty repo
1435 """builds a repo with a given DAG from scratch in the current empty repo
1436
1436
1437 The description of the DAG is read from stdin if not given on the
1437 The description of the DAG is read from stdin if not given on the
1438 command line.
1438 command line.
1439
1439
1440 Elements:
1440 Elements:
1441
1441
1442 - "+n" is a linear run of n nodes based on the current default parent
1442 - "+n" is a linear run of n nodes based on the current default parent
1443 - "." is a single node based on the current default parent
1443 - "." is a single node based on the current default parent
1444 - "$" resets the default parent to null (implied at the start);
1444 - "$" resets the default parent to null (implied at the start);
1445 otherwise the default parent is always the last node created
1445 otherwise the default parent is always the last node created
1446 - "<p" sets the default parent to the backref p
1446 - "<p" sets the default parent to the backref p
1447 - "*p" is a fork at parent p, which is a backref
1447 - "*p" is a fork at parent p, which is a backref
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1448 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1449 - "/p2" is a merge of the preceding node and p2
1449 - "/p2" is a merge of the preceding node and p2
1450 - ":tag" defines a local tag for the preceding node
1450 - ":tag" defines a local tag for the preceding node
1451 - "@branch" sets the named branch for subsequent nodes
1451 - "@branch" sets the named branch for subsequent nodes
1452 - "#...\\n" is a comment up to the end of the line
1452 - "#...\\n" is a comment up to the end of the line
1453
1453
1454 Whitespace between the above elements is ignored.
1454 Whitespace between the above elements is ignored.
1455
1455
1456 A backref is either
1456 A backref is either
1457
1457
1458 - a number n, which references the node curr-n, where curr is the current
1458 - a number n, which references the node curr-n, where curr is the current
1459 node, or
1459 node, or
1460 - the name of a local tag you placed earlier using ":tag", or
1460 - the name of a local tag you placed earlier using ":tag", or
1461 - empty to denote the default parent.
1461 - empty to denote the default parent.
1462
1462
1463 All string valued-elements are either strictly alphanumeric, or must
1463 All string valued-elements are either strictly alphanumeric, or must
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1464 be enclosed in double quotes ("..."), with "\\" as escape character.
1465 """
1465 """
1466
1466
1467 if text is None:
1467 if text is None:
1468 ui.status(_("reading DAG from stdin\n"))
1468 ui.status(_("reading DAG from stdin\n"))
1469 text = ui.fin.read()
1469 text = ui.fin.read()
1470
1470
1471 cl = repo.changelog
1471 cl = repo.changelog
1472 if len(cl) > 0:
1472 if len(cl) > 0:
1473 raise util.Abort(_('repository is not empty'))
1473 raise util.Abort(_('repository is not empty'))
1474
1474
1475 # determine number of revs in DAG
1475 # determine number of revs in DAG
1476 total = 0
1476 total = 0
1477 for type, data in dagparser.parsedag(text):
1477 for type, data in dagparser.parsedag(text):
1478 if type == 'n':
1478 if type == 'n':
1479 total += 1
1479 total += 1
1480
1480
1481 if mergeable_file:
1481 if mergeable_file:
1482 linesperrev = 2
1482 linesperrev = 2
1483 # make a file with k lines per rev
1483 # make a file with k lines per rev
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1484 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1485 initialmergedlines.append("")
1485 initialmergedlines.append("")
1486
1486
1487 tags = []
1487 tags = []
1488
1488
1489 lock = tr = None
1489 lock = tr = None
1490 try:
1490 try:
1491 lock = repo.lock()
1491 lock = repo.lock()
1492 tr = repo.transaction("builddag")
1492 tr = repo.transaction("builddag")
1493
1493
1494 at = -1
1494 at = -1
1495 atbranch = 'default'
1495 atbranch = 'default'
1496 nodeids = []
1496 nodeids = []
1497 id = 0
1497 id = 0
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1498 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1499 for type, data in dagparser.parsedag(text):
1499 for type, data in dagparser.parsedag(text):
1500 if type == 'n':
1500 if type == 'n':
1501 ui.note(('node %s\n' % str(data)))
1501 ui.note(('node %s\n' % str(data)))
1502 id, ps = data
1502 id, ps = data
1503
1503
1504 files = []
1504 files = []
1505 fctxs = {}
1505 fctxs = {}
1506
1506
1507 p2 = None
1507 p2 = None
1508 if mergeable_file:
1508 if mergeable_file:
1509 fn = "mf"
1509 fn = "mf"
1510 p1 = repo[ps[0]]
1510 p1 = repo[ps[0]]
1511 if len(ps) > 1:
1511 if len(ps) > 1:
1512 p2 = repo[ps[1]]
1512 p2 = repo[ps[1]]
1513 pa = p1.ancestor(p2)
1513 pa = p1.ancestor(p2)
1514 base, local, other = [x[fn].data() for x in (pa, p1,
1514 base, local, other = [x[fn].data() for x in (pa, p1,
1515 p2)]
1515 p2)]
1516 m3 = simplemerge.Merge3Text(base, local, other)
1516 m3 = simplemerge.Merge3Text(base, local, other)
1517 ml = [l.strip() for l in m3.merge_lines()]
1517 ml = [l.strip() for l in m3.merge_lines()]
1518 ml.append("")
1518 ml.append("")
1519 elif at > 0:
1519 elif at > 0:
1520 ml = p1[fn].data().split("\n")
1520 ml = p1[fn].data().split("\n")
1521 else:
1521 else:
1522 ml = initialmergedlines
1522 ml = initialmergedlines
1523 ml[id * linesperrev] += " r%i" % id
1523 ml[id * linesperrev] += " r%i" % id
1524 mergedtext = "\n".join(ml)
1524 mergedtext = "\n".join(ml)
1525 files.append(fn)
1525 files.append(fn)
1526 fctxs[fn] = context.memfilectx(fn, mergedtext)
1526 fctxs[fn] = context.memfilectx(fn, mergedtext)
1527
1527
1528 if overwritten_file:
1528 if overwritten_file:
1529 fn = "of"
1529 fn = "of"
1530 files.append(fn)
1530 files.append(fn)
1531 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1532
1532
1533 if new_file:
1533 if new_file:
1534 fn = "nf%i" % id
1534 fn = "nf%i" % id
1535 files.append(fn)
1535 files.append(fn)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1536 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1537 if len(ps) > 1:
1537 if len(ps) > 1:
1538 if not p2:
1538 if not p2:
1539 p2 = repo[ps[1]]
1539 p2 = repo[ps[1]]
1540 for fn in p2:
1540 for fn in p2:
1541 if fn.startswith("nf"):
1541 if fn.startswith("nf"):
1542 files.append(fn)
1542 files.append(fn)
1543 fctxs[fn] = p2[fn]
1543 fctxs[fn] = p2[fn]
1544
1544
1545 def fctxfn(repo, cx, path):
1545 def fctxfn(repo, cx, path):
1546 return fctxs.get(path)
1546 return fctxs.get(path)
1547
1547
1548 if len(ps) == 0 or ps[0] < 0:
1548 if len(ps) == 0 or ps[0] < 0:
1549 pars = [None, None]
1549 pars = [None, None]
1550 elif len(ps) == 1:
1550 elif len(ps) == 1:
1551 pars = [nodeids[ps[0]], None]
1551 pars = [nodeids[ps[0]], None]
1552 else:
1552 else:
1553 pars = [nodeids[p] for p in ps]
1553 pars = [nodeids[p] for p in ps]
1554 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1554 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1555 date=(id, 0),
1555 date=(id, 0),
1556 user="debugbuilddag",
1556 user="debugbuilddag",
1557 extra={'branch': atbranch})
1557 extra={'branch': atbranch})
1558 nodeid = repo.commitctx(cx)
1558 nodeid = repo.commitctx(cx)
1559 nodeids.append(nodeid)
1559 nodeids.append(nodeid)
1560 at = id
1560 at = id
1561 elif type == 'l':
1561 elif type == 'l':
1562 id, name = data
1562 id, name = data
1563 ui.note(('tag %s\n' % name))
1563 ui.note(('tag %s\n' % name))
1564 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1564 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1565 elif type == 'a':
1565 elif type == 'a':
1566 ui.note(('branch %s\n' % data))
1566 ui.note(('branch %s\n' % data))
1567 atbranch = data
1567 atbranch = data
1568 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1569 tr.close()
1569 tr.close()
1570
1570
1571 if tags:
1571 if tags:
1572 repo.opener.write("localtags", "".join(tags))
1572 repo.opener.write("localtags", "".join(tags))
1573 finally:
1573 finally:
1574 ui.progress(_('building'), None)
1574 ui.progress(_('building'), None)
1575 release(tr, lock)
1575 release(tr, lock)
1576
1576
1577 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1577 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1578 def debugbundle(ui, bundlepath, all=None, **opts):
1578 def debugbundle(ui, bundlepath, all=None, **opts):
1579 """lists the contents of a bundle"""
1579 """lists the contents of a bundle"""
1580 f = hg.openpath(ui, bundlepath)
1580 f = hg.openpath(ui, bundlepath)
1581 try:
1581 try:
1582 gen = changegroup.readbundle(f, bundlepath)
1582 gen = changegroup.readbundle(f, bundlepath)
1583 if all:
1583 if all:
1584 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1584 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1585
1585
1586 def showchunks(named):
1586 def showchunks(named):
1587 ui.write("\n%s\n" % named)
1587 ui.write("\n%s\n" % named)
1588 chain = None
1588 chain = None
1589 while True:
1589 while True:
1590 chunkdata = gen.deltachunk(chain)
1590 chunkdata = gen.deltachunk(chain)
1591 if not chunkdata:
1591 if not chunkdata:
1592 break
1592 break
1593 node = chunkdata['node']
1593 node = chunkdata['node']
1594 p1 = chunkdata['p1']
1594 p1 = chunkdata['p1']
1595 p2 = chunkdata['p2']
1595 p2 = chunkdata['p2']
1596 cs = chunkdata['cs']
1596 cs = chunkdata['cs']
1597 deltabase = chunkdata['deltabase']
1597 deltabase = chunkdata['deltabase']
1598 delta = chunkdata['delta']
1598 delta = chunkdata['delta']
1599 ui.write("%s %s %s %s %s %s\n" %
1599 ui.write("%s %s %s %s %s %s\n" %
1600 (hex(node), hex(p1), hex(p2),
1600 (hex(node), hex(p1), hex(p2),
1601 hex(cs), hex(deltabase), len(delta)))
1601 hex(cs), hex(deltabase), len(delta)))
1602 chain = node
1602 chain = node
1603
1603
1604 chunkdata = gen.changelogheader()
1604 chunkdata = gen.changelogheader()
1605 showchunks("changelog")
1605 showchunks("changelog")
1606 chunkdata = gen.manifestheader()
1606 chunkdata = gen.manifestheader()
1607 showchunks("manifest")
1607 showchunks("manifest")
1608 while True:
1608 while True:
1609 chunkdata = gen.filelogheader()
1609 chunkdata = gen.filelogheader()
1610 if not chunkdata:
1610 if not chunkdata:
1611 break
1611 break
1612 fname = chunkdata['filename']
1612 fname = chunkdata['filename']
1613 showchunks(fname)
1613 showchunks(fname)
1614 else:
1614 else:
1615 chunkdata = gen.changelogheader()
1615 chunkdata = gen.changelogheader()
1616 chain = None
1616 chain = None
1617 while True:
1617 while True:
1618 chunkdata = gen.deltachunk(chain)
1618 chunkdata = gen.deltachunk(chain)
1619 if not chunkdata:
1619 if not chunkdata:
1620 break
1620 break
1621 node = chunkdata['node']
1621 node = chunkdata['node']
1622 ui.write("%s\n" % hex(node))
1622 ui.write("%s\n" % hex(node))
1623 chain = node
1623 chain = node
1624 finally:
1624 finally:
1625 f.close()
1625 f.close()
1626
1626
1627 @command('debugcheckstate', [], '')
1627 @command('debugcheckstate', [], '')
1628 def debugcheckstate(ui, repo):
1628 def debugcheckstate(ui, repo):
1629 """validate the correctness of the current dirstate"""
1629 """validate the correctness of the current dirstate"""
1630 parent1, parent2 = repo.dirstate.parents()
1630 parent1, parent2 = repo.dirstate.parents()
1631 m1 = repo[parent1].manifest()
1631 m1 = repo[parent1].manifest()
1632 m2 = repo[parent2].manifest()
1632 m2 = repo[parent2].manifest()
1633 errors = 0
1633 errors = 0
1634 for f in repo.dirstate:
1634 for f in repo.dirstate:
1635 state = repo.dirstate[f]
1635 state = repo.dirstate[f]
1636 if state in "nr" and f not in m1:
1636 if state in "nr" and f not in m1:
1637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1638 errors += 1
1638 errors += 1
1639 if state in "a" and f in m1:
1639 if state in "a" and f in m1:
1640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1641 errors += 1
1641 errors += 1
1642 if state in "m" and f not in m1 and f not in m2:
1642 if state in "m" and f not in m1 and f not in m2:
1643 ui.warn(_("%s in state %s, but not in either manifest\n") %
1643 ui.warn(_("%s in state %s, but not in either manifest\n") %
1644 (f, state))
1644 (f, state))
1645 errors += 1
1645 errors += 1
1646 for f in m1:
1646 for f in m1:
1647 state = repo.dirstate[f]
1647 state = repo.dirstate[f]
1648 if state not in "nrm":
1648 if state not in "nrm":
1649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1650 errors += 1
1650 errors += 1
1651 if errors:
1651 if errors:
1652 error = _(".hg/dirstate inconsistent with current parent's manifest")
1652 error = _(".hg/dirstate inconsistent with current parent's manifest")
1653 raise util.Abort(error)
1653 raise util.Abort(error)
1654
1654
1655 @command('debugcommands', [], _('[COMMAND]'))
1655 @command('debugcommands', [], _('[COMMAND]'))
1656 def debugcommands(ui, cmd='', *args):
1656 def debugcommands(ui, cmd='', *args):
1657 """list all available commands and options"""
1657 """list all available commands and options"""
1658 for cmd, vals in sorted(table.iteritems()):
1658 for cmd, vals in sorted(table.iteritems()):
1659 cmd = cmd.split('|')[0].strip('^')
1659 cmd = cmd.split('|')[0].strip('^')
1660 opts = ', '.join([i[1] for i in vals[1]])
1660 opts = ', '.join([i[1] for i in vals[1]])
1661 ui.write('%s: %s\n' % (cmd, opts))
1661 ui.write('%s: %s\n' % (cmd, opts))
1662
1662
1663 @command('debugcomplete',
1663 @command('debugcomplete',
1664 [('o', 'options', None, _('show the command options'))],
1664 [('o', 'options', None, _('show the command options'))],
1665 _('[-o] CMD'))
1665 _('[-o] CMD'))
1666 def debugcomplete(ui, cmd='', **opts):
1666 def debugcomplete(ui, cmd='', **opts):
1667 """returns the completion list associated with the given command"""
1667 """returns the completion list associated with the given command"""
1668
1668
1669 if opts.get('options'):
1669 if opts.get('options'):
1670 options = []
1670 options = []
1671 otables = [globalopts]
1671 otables = [globalopts]
1672 if cmd:
1672 if cmd:
1673 aliases, entry = cmdutil.findcmd(cmd, table, False)
1673 aliases, entry = cmdutil.findcmd(cmd, table, False)
1674 otables.append(entry[1])
1674 otables.append(entry[1])
1675 for t in otables:
1675 for t in otables:
1676 for o in t:
1676 for o in t:
1677 if "(DEPRECATED)" in o[3]:
1677 if "(DEPRECATED)" in o[3]:
1678 continue
1678 continue
1679 if o[0]:
1679 if o[0]:
1680 options.append('-%s' % o[0])
1680 options.append('-%s' % o[0])
1681 options.append('--%s' % o[1])
1681 options.append('--%s' % o[1])
1682 ui.write("%s\n" % "\n".join(options))
1682 ui.write("%s\n" % "\n".join(options))
1683 return
1683 return
1684
1684
1685 cmdlist = cmdutil.findpossible(cmd, table)
1685 cmdlist = cmdutil.findpossible(cmd, table)
1686 if ui.verbose:
1686 if ui.verbose:
1687 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1687 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1688 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1688 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1689
1689
1690 @command('debugdag',
1690 @command('debugdag',
1691 [('t', 'tags', None, _('use tags as labels')),
1691 [('t', 'tags', None, _('use tags as labels')),
1692 ('b', 'branches', None, _('annotate with branch names')),
1692 ('b', 'branches', None, _('annotate with branch names')),
1693 ('', 'dots', None, _('use dots for runs')),
1693 ('', 'dots', None, _('use dots for runs')),
1694 ('s', 'spaces', None, _('separate elements by spaces'))],
1694 ('s', 'spaces', None, _('separate elements by spaces'))],
1695 _('[OPTION]... [FILE [REV]...]'))
1695 _('[OPTION]... [FILE [REV]...]'))
1696 def debugdag(ui, repo, file_=None, *revs, **opts):
1696 def debugdag(ui, repo, file_=None, *revs, **opts):
1697 """format the changelog or an index DAG as a concise textual description
1697 """format the changelog or an index DAG as a concise textual description
1698
1698
1699 If you pass a revlog index, the revlog's DAG is emitted. If you list
1699 If you pass a revlog index, the revlog's DAG is emitted. If you list
1700 revision numbers, they get labeled in the output as rN.
1700 revision numbers, they get labeled in the output as rN.
1701
1701
1702 Otherwise, the changelog DAG of the current repo is emitted.
1702 Otherwise, the changelog DAG of the current repo is emitted.
1703 """
1703 """
1704 spaces = opts.get('spaces')
1704 spaces = opts.get('spaces')
1705 dots = opts.get('dots')
1705 dots = opts.get('dots')
1706 if file_:
1706 if file_:
1707 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1707 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1708 revs = set((int(r) for r in revs))
1708 revs = set((int(r) for r in revs))
1709 def events():
1709 def events():
1710 for r in rlog:
1710 for r in rlog:
1711 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1711 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1712 if p != -1)))
1712 if p != -1)))
1713 if r in revs:
1713 if r in revs:
1714 yield 'l', (r, "r%i" % r)
1714 yield 'l', (r, "r%i" % r)
1715 elif repo:
1715 elif repo:
1716 cl = repo.changelog
1716 cl = repo.changelog
1717 tags = opts.get('tags')
1717 tags = opts.get('tags')
1718 branches = opts.get('branches')
1718 branches = opts.get('branches')
1719 if tags:
1719 if tags:
1720 labels = {}
1720 labels = {}
1721 for l, n in repo.tags().items():
1721 for l, n in repo.tags().items():
1722 labels.setdefault(cl.rev(n), []).append(l)
1722 labels.setdefault(cl.rev(n), []).append(l)
1723 def events():
1723 def events():
1724 b = "default"
1724 b = "default"
1725 for r in cl:
1725 for r in cl:
1726 if branches:
1726 if branches:
1727 newb = cl.read(cl.node(r))[5]['branch']
1727 newb = cl.read(cl.node(r))[5]['branch']
1728 if newb != b:
1728 if newb != b:
1729 yield 'a', newb
1729 yield 'a', newb
1730 b = newb
1730 b = newb
1731 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1731 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1732 if p != -1)))
1732 if p != -1)))
1733 if tags:
1733 if tags:
1734 ls = labels.get(r)
1734 ls = labels.get(r)
1735 if ls:
1735 if ls:
1736 for l in ls:
1736 for l in ls:
1737 yield 'l', (r, l)
1737 yield 'l', (r, l)
1738 else:
1738 else:
1739 raise util.Abort(_('need repo for changelog dag'))
1739 raise util.Abort(_('need repo for changelog dag'))
1740
1740
1741 for line in dagparser.dagtextlines(events(),
1741 for line in dagparser.dagtextlines(events(),
1742 addspaces=spaces,
1742 addspaces=spaces,
1743 wraplabels=True,
1743 wraplabels=True,
1744 wrapannotations=True,
1744 wrapannotations=True,
1745 wrapnonlinear=dots,
1745 wrapnonlinear=dots,
1746 usedots=dots,
1746 usedots=dots,
1747 maxlinewidth=70):
1747 maxlinewidth=70):
1748 ui.write(line)
1748 ui.write(line)
1749 ui.write("\n")
1749 ui.write("\n")
1750
1750
1751 @command('debugdata',
1751 @command('debugdata',
1752 [('c', 'changelog', False, _('open changelog')),
1752 [('c', 'changelog', False, _('open changelog')),
1753 ('m', 'manifest', False, _('open manifest'))],
1753 ('m', 'manifest', False, _('open manifest'))],
1754 _('-c|-m|FILE REV'))
1754 _('-c|-m|FILE REV'))
1755 def debugdata(ui, repo, file_, rev = None, **opts):
1755 def debugdata(ui, repo, file_, rev = None, **opts):
1756 """dump the contents of a data file revision"""
1756 """dump the contents of a data file revision"""
1757 if opts.get('changelog') or opts.get('manifest'):
1757 if opts.get('changelog') or opts.get('manifest'):
1758 file_, rev = None, file_
1758 file_, rev = None, file_
1759 elif rev is None:
1759 elif rev is None:
1760 raise error.CommandError('debugdata', _('invalid arguments'))
1760 raise error.CommandError('debugdata', _('invalid arguments'))
1761 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1761 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1762 try:
1762 try:
1763 ui.write(r.revision(r.lookup(rev)))
1763 ui.write(r.revision(r.lookup(rev)))
1764 except KeyError:
1764 except KeyError:
1765 raise util.Abort(_('invalid revision identifier %s') % rev)
1765 raise util.Abort(_('invalid revision identifier %s') % rev)
1766
1766
1767 @command('debugdate',
1767 @command('debugdate',
1768 [('e', 'extended', None, _('try extended date formats'))],
1768 [('e', 'extended', None, _('try extended date formats'))],
1769 _('[-e] DATE [RANGE]'))
1769 _('[-e] DATE [RANGE]'))
1770 def debugdate(ui, date, range=None, **opts):
1770 def debugdate(ui, date, range=None, **opts):
1771 """parse and display a date"""
1771 """parse and display a date"""
1772 if opts["extended"]:
1772 if opts["extended"]:
1773 d = util.parsedate(date, util.extendeddateformats)
1773 d = util.parsedate(date, util.extendeddateformats)
1774 else:
1774 else:
1775 d = util.parsedate(date)
1775 d = util.parsedate(date)
1776 ui.write(("internal: %s %s\n") % d)
1776 ui.write(("internal: %s %s\n") % d)
1777 ui.write(("standard: %s\n") % util.datestr(d))
1777 ui.write(("standard: %s\n") % util.datestr(d))
1778 if range:
1778 if range:
1779 m = util.matchdate(range)
1779 m = util.matchdate(range)
1780 ui.write(("match: %s\n") % m(d[0]))
1780 ui.write(("match: %s\n") % m(d[0]))
1781
1781
1782 @command('debugdiscovery',
1782 @command('debugdiscovery',
1783 [('', 'old', None, _('use old-style discovery')),
1783 [('', 'old', None, _('use old-style discovery')),
1784 ('', 'nonheads', None,
1784 ('', 'nonheads', None,
1785 _('use old-style discovery with non-heads included')),
1785 _('use old-style discovery with non-heads included')),
1786 ] + remoteopts,
1786 ] + remoteopts,
1787 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1787 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1788 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1788 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1789 """runs the changeset discovery protocol in isolation"""
1789 """runs the changeset discovery protocol in isolation"""
1790 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1790 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1791 opts.get('branch'))
1791 opts.get('branch'))
1792 remote = hg.peer(repo, opts, remoteurl)
1792 remote = hg.peer(repo, opts, remoteurl)
1793 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1793 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1794
1794
1795 # make sure tests are repeatable
1795 # make sure tests are repeatable
1796 random.seed(12323)
1796 random.seed(12323)
1797
1797
1798 def doit(localheads, remoteheads, remote=remote):
1798 def doit(localheads, remoteheads, remote=remote):
1799 if opts.get('old'):
1799 if opts.get('old'):
1800 if localheads:
1800 if localheads:
1801 raise util.Abort('cannot use localheads with old style '
1801 raise util.Abort('cannot use localheads with old style '
1802 'discovery')
1802 'discovery')
1803 if not util.safehasattr(remote, 'branches'):
1803 if not util.safehasattr(remote, 'branches'):
1804 # enable in-client legacy support
1804 # enable in-client legacy support
1805 remote = localrepo.locallegacypeer(remote.local())
1805 remote = localrepo.locallegacypeer(remote.local())
1806 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1806 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1807 force=True)
1807 force=True)
1808 common = set(common)
1808 common = set(common)
1809 if not opts.get('nonheads'):
1809 if not opts.get('nonheads'):
1810 ui.write(("unpruned common: %s\n") %
1810 ui.write(("unpruned common: %s\n") %
1811 " ".join(sorted(short(n) for n in common)))
1811 " ".join(sorted(short(n) for n in common)))
1812 dag = dagutil.revlogdag(repo.changelog)
1812 dag = dagutil.revlogdag(repo.changelog)
1813 all = dag.ancestorset(dag.internalizeall(common))
1813 all = dag.ancestorset(dag.internalizeall(common))
1814 common = dag.externalizeall(dag.headsetofconnecteds(all))
1814 common = dag.externalizeall(dag.headsetofconnecteds(all))
1815 else:
1815 else:
1816 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1816 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1817 common = set(common)
1817 common = set(common)
1818 rheads = set(hds)
1818 rheads = set(hds)
1819 lheads = set(repo.heads())
1819 lheads = set(repo.heads())
1820 ui.write(("common heads: %s\n") %
1820 ui.write(("common heads: %s\n") %
1821 " ".join(sorted(short(n) for n in common)))
1821 " ".join(sorted(short(n) for n in common)))
1822 if lheads <= common:
1822 if lheads <= common:
1823 ui.write(("local is subset\n"))
1823 ui.write(("local is subset\n"))
1824 elif rheads <= common:
1824 elif rheads <= common:
1825 ui.write(("remote is subset\n"))
1825 ui.write(("remote is subset\n"))
1826
1826
1827 serverlogs = opts.get('serverlog')
1827 serverlogs = opts.get('serverlog')
1828 if serverlogs:
1828 if serverlogs:
1829 for filename in serverlogs:
1829 for filename in serverlogs:
1830 logfile = open(filename, 'r')
1830 logfile = open(filename, 'r')
1831 try:
1831 try:
1832 line = logfile.readline()
1832 line = logfile.readline()
1833 while line:
1833 while line:
1834 parts = line.strip().split(';')
1834 parts = line.strip().split(';')
1835 op = parts[1]
1835 op = parts[1]
1836 if op == 'cg':
1836 if op == 'cg':
1837 pass
1837 pass
1838 elif op == 'cgss':
1838 elif op == 'cgss':
1839 doit(parts[2].split(' '), parts[3].split(' '))
1839 doit(parts[2].split(' '), parts[3].split(' '))
1840 elif op == 'unb':
1840 elif op == 'unb':
1841 doit(parts[3].split(' '), parts[2].split(' '))
1841 doit(parts[3].split(' '), parts[2].split(' '))
1842 line = logfile.readline()
1842 line = logfile.readline()
1843 finally:
1843 finally:
1844 logfile.close()
1844 logfile.close()
1845
1845
1846 else:
1846 else:
1847 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1847 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1848 opts.get('remote_head'))
1848 opts.get('remote_head'))
1849 localrevs = opts.get('local_head')
1849 localrevs = opts.get('local_head')
1850 doit(localrevs, remoterevs)
1850 doit(localrevs, remoterevs)
1851
1851
1852 @command('debugfileset',
1852 @command('debugfileset',
1853 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1853 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1854 _('[-r REV] FILESPEC'))
1854 _('[-r REV] FILESPEC'))
1855 def debugfileset(ui, repo, expr, **opts):
1855 def debugfileset(ui, repo, expr, **opts):
1856 '''parse and apply a fileset specification'''
1856 '''parse and apply a fileset specification'''
1857 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1857 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1858 if ui.verbose:
1858 if ui.verbose:
1859 tree = fileset.parse(expr)[0]
1859 tree = fileset.parse(expr)[0]
1860 ui.note(tree, "\n")
1860 ui.note(tree, "\n")
1861
1861
1862 for f in fileset.getfileset(ctx, expr):
1862 for f in fileset.getfileset(ctx, expr):
1863 ui.write("%s\n" % f)
1863 ui.write("%s\n" % f)
1864
1864
1865 @command('debugfsinfo', [], _('[PATH]'))
1865 @command('debugfsinfo', [], _('[PATH]'))
1866 def debugfsinfo(ui, path = "."):
1866 def debugfsinfo(ui, path = "."):
1867 """show information detected about current filesystem"""
1867 """show information detected about current filesystem"""
1868 util.writefile('.debugfsinfo', '')
1868 util.writefile('.debugfsinfo', '')
1869 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1869 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1870 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1870 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1871 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1871 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1872 and 'yes' or 'no'))
1872 and 'yes' or 'no'))
1873 os.unlink('.debugfsinfo')
1873 os.unlink('.debugfsinfo')
1874
1874
1875 @command('debuggetbundle',
1875 @command('debuggetbundle',
1876 [('H', 'head', [], _('id of head node'), _('ID')),
1876 [('H', 'head', [], _('id of head node'), _('ID')),
1877 ('C', 'common', [], _('id of common node'), _('ID')),
1877 ('C', 'common', [], _('id of common node'), _('ID')),
1878 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1878 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1879 _('REPO FILE [-H|-C ID]...'))
1879 _('REPO FILE [-H|-C ID]...'))
1880 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1880 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1881 """retrieves a bundle from a repo
1881 """retrieves a bundle from a repo
1882
1882
1883 Every ID must be a full-length hex node id string. Saves the bundle to the
1883 Every ID must be a full-length hex node id string. Saves the bundle to the
1884 given file.
1884 given file.
1885 """
1885 """
1886 repo = hg.peer(ui, opts, repopath)
1886 repo = hg.peer(ui, opts, repopath)
1887 if not repo.capable('getbundle'):
1887 if not repo.capable('getbundle'):
1888 raise util.Abort("getbundle() not supported by target repository")
1888 raise util.Abort("getbundle() not supported by target repository")
1889 args = {}
1889 args = {}
1890 if common:
1890 if common:
1891 args['common'] = [bin(s) for s in common]
1891 args['common'] = [bin(s) for s in common]
1892 if head:
1892 if head:
1893 args['heads'] = [bin(s) for s in head]
1893 args['heads'] = [bin(s) for s in head]
1894 bundle = repo.getbundle('debug', **args)
1894 bundle = repo.getbundle('debug', **args)
1895
1895
1896 bundletype = opts.get('type', 'bzip2').lower()
1896 bundletype = opts.get('type', 'bzip2').lower()
1897 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1897 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1898 bundletype = btypes.get(bundletype)
1898 bundletype = btypes.get(bundletype)
1899 if bundletype not in changegroup.bundletypes:
1899 if bundletype not in changegroup.bundletypes:
1900 raise util.Abort(_('unknown bundle type specified with --type'))
1900 raise util.Abort(_('unknown bundle type specified with --type'))
1901 changegroup.writebundle(bundle, bundlepath, bundletype)
1901 changegroup.writebundle(bundle, bundlepath, bundletype)
1902
1902
1903 @command('debugignore', [], '')
1903 @command('debugignore', [], '')
1904 def debugignore(ui, repo, *values, **opts):
1904 def debugignore(ui, repo, *values, **opts):
1905 """display the combined ignore pattern"""
1905 """display the combined ignore pattern"""
1906 ignore = repo.dirstate._ignore
1906 ignore = repo.dirstate._ignore
1907 includepat = getattr(ignore, 'includepat', None)
1907 includepat = getattr(ignore, 'includepat', None)
1908 if includepat is not None:
1908 if includepat is not None:
1909 ui.write("%s\n" % includepat)
1909 ui.write("%s\n" % includepat)
1910 else:
1910 else:
1911 raise util.Abort(_("no ignore patterns found"))
1911 raise util.Abort(_("no ignore patterns found"))
1912
1912
1913 @command('debugindex',
1913 @command('debugindex',
1914 [('c', 'changelog', False, _('open changelog')),
1914 [('c', 'changelog', False, _('open changelog')),
1915 ('m', 'manifest', False, _('open manifest')),
1915 ('m', 'manifest', False, _('open manifest')),
1916 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1916 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1917 _('[-f FORMAT] -c|-m|FILE'))
1917 _('[-f FORMAT] -c|-m|FILE'))
1918 def debugindex(ui, repo, file_ = None, **opts):
1918 def debugindex(ui, repo, file_ = None, **opts):
1919 """dump the contents of an index file"""
1919 """dump the contents of an index file"""
1920 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1920 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1921 format = opts.get('format', 0)
1921 format = opts.get('format', 0)
1922 if format not in (0, 1):
1922 if format not in (0, 1):
1923 raise util.Abort(_("unknown format %d") % format)
1923 raise util.Abort(_("unknown format %d") % format)
1924
1924
1925 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1925 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1926 if generaldelta:
1926 if generaldelta:
1927 basehdr = ' delta'
1927 basehdr = ' delta'
1928 else:
1928 else:
1929 basehdr = ' base'
1929 basehdr = ' base'
1930
1930
1931 if format == 0:
1931 if format == 0:
1932 ui.write(" rev offset length " + basehdr + " linkrev"
1932 ui.write(" rev offset length " + basehdr + " linkrev"
1933 " nodeid p1 p2\n")
1933 " nodeid p1 p2\n")
1934 elif format == 1:
1934 elif format == 1:
1935 ui.write(" rev flag offset length"
1935 ui.write(" rev flag offset length"
1936 " size " + basehdr + " link p1 p2"
1936 " size " + basehdr + " link p1 p2"
1937 " nodeid\n")
1937 " nodeid\n")
1938
1938
1939 for i in r:
1939 for i in r:
1940 node = r.node(i)
1940 node = r.node(i)
1941 if generaldelta:
1941 if generaldelta:
1942 base = r.deltaparent(i)
1942 base = r.deltaparent(i)
1943 else:
1943 else:
1944 base = r.chainbase(i)
1944 base = r.chainbase(i)
1945 if format == 0:
1945 if format == 0:
1946 try:
1946 try:
1947 pp = r.parents(node)
1947 pp = r.parents(node)
1948 except Exception:
1948 except Exception:
1949 pp = [nullid, nullid]
1949 pp = [nullid, nullid]
1950 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1950 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1951 i, r.start(i), r.length(i), base, r.linkrev(i),
1951 i, r.start(i), r.length(i), base, r.linkrev(i),
1952 short(node), short(pp[0]), short(pp[1])))
1952 short(node), short(pp[0]), short(pp[1])))
1953 elif format == 1:
1953 elif format == 1:
1954 pr = r.parentrevs(i)
1954 pr = r.parentrevs(i)
1955 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1955 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1956 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1956 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1957 base, r.linkrev(i), pr[0], pr[1], short(node)))
1957 base, r.linkrev(i), pr[0], pr[1], short(node)))
1958
1958
1959 @command('debugindexdot', [], _('FILE'))
1959 @command('debugindexdot', [], _('FILE'))
1960 def debugindexdot(ui, repo, file_):
1960 def debugindexdot(ui, repo, file_):
1961 """dump an index DAG as a graphviz dot file"""
1961 """dump an index DAG as a graphviz dot file"""
1962 r = None
1962 r = None
1963 if repo:
1963 if repo:
1964 filelog = repo.file(file_)
1964 filelog = repo.file(file_)
1965 if len(filelog):
1965 if len(filelog):
1966 r = filelog
1966 r = filelog
1967 if not r:
1967 if not r:
1968 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1968 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1969 ui.write(("digraph G {\n"))
1969 ui.write(("digraph G {\n"))
1970 for i in r:
1970 for i in r:
1971 node = r.node(i)
1971 node = r.node(i)
1972 pp = r.parents(node)
1972 pp = r.parents(node)
1973 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1973 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1974 if pp[1] != nullid:
1974 if pp[1] != nullid:
1975 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1975 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1976 ui.write("}\n")
1976 ui.write("}\n")
1977
1977
1978 @command('debuginstall', [], '')
1978 @command('debuginstall', [], '')
1979 def debuginstall(ui):
1979 def debuginstall(ui):
1980 '''test Mercurial installation
1980 '''test Mercurial installation
1981
1981
1982 Returns 0 on success.
1982 Returns 0 on success.
1983 '''
1983 '''
1984
1984
1985 def writetemp(contents):
1985 def writetemp(contents):
1986 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1986 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1987 f = os.fdopen(fd, "wb")
1987 f = os.fdopen(fd, "wb")
1988 f.write(contents)
1988 f.write(contents)
1989 f.close()
1989 f.close()
1990 return name
1990 return name
1991
1991
1992 problems = 0
1992 problems = 0
1993
1993
1994 # encoding
1994 # encoding
1995 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1995 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1996 try:
1996 try:
1997 encoding.fromlocal("test")
1997 encoding.fromlocal("test")
1998 except util.Abort, inst:
1998 except util.Abort, inst:
1999 ui.write(" %s\n" % inst)
1999 ui.write(" %s\n" % inst)
2000 ui.write(_(" (check that your locale is properly set)\n"))
2000 ui.write(_(" (check that your locale is properly set)\n"))
2001 problems += 1
2001 problems += 1
2002
2002
2003 # Python lib
2003 # Python lib
2004 ui.status(_("checking Python lib (%s)...\n")
2004 ui.status(_("checking Python lib (%s)...\n")
2005 % os.path.dirname(os.__file__))
2005 % os.path.dirname(os.__file__))
2006
2006
2007 # compiled modules
2007 # compiled modules
2008 ui.status(_("checking installed modules (%s)...\n")
2008 ui.status(_("checking installed modules (%s)...\n")
2009 % os.path.dirname(__file__))
2009 % os.path.dirname(__file__))
2010 try:
2010 try:
2011 import bdiff, mpatch, base85, osutil
2011 import bdiff, mpatch, base85, osutil
2012 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2012 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2013 except Exception, inst:
2013 except Exception, inst:
2014 ui.write(" %s\n" % inst)
2014 ui.write(" %s\n" % inst)
2015 ui.write(_(" One or more extensions could not be found"))
2015 ui.write(_(" One or more extensions could not be found"))
2016 ui.write(_(" (check that you compiled the extensions)\n"))
2016 ui.write(_(" (check that you compiled the extensions)\n"))
2017 problems += 1
2017 problems += 1
2018
2018
2019 # templates
2019 # templates
2020 import templater
2020 import templater
2021 p = templater.templatepath()
2021 p = templater.templatepath()
2022 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2022 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2023 try:
2023 try:
2024 templater.templater(templater.templatepath("map-cmdline.default"))
2024 templater.templater(templater.templatepath("map-cmdline.default"))
2025 except Exception, inst:
2025 except Exception, inst:
2026 ui.write(" %s\n" % inst)
2026 ui.write(" %s\n" % inst)
2027 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2027 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2028 problems += 1
2028 problems += 1
2029
2029
2030 # editor
2030 # editor
2031 ui.status(_("checking commit editor...\n"))
2031 ui.status(_("checking commit editor...\n"))
2032 editor = ui.geteditor()
2032 editor = ui.geteditor()
2033 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2033 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2034 if not cmdpath:
2034 if not cmdpath:
2035 if editor == 'vi':
2035 if editor == 'vi':
2036 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2036 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2037 ui.write(_(" (specify a commit editor in your configuration"
2037 ui.write(_(" (specify a commit editor in your configuration"
2038 " file)\n"))
2038 " file)\n"))
2039 else:
2039 else:
2040 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2040 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2041 ui.write(_(" (specify a commit editor in your configuration"
2041 ui.write(_(" (specify a commit editor in your configuration"
2042 " file)\n"))
2042 " file)\n"))
2043 problems += 1
2043 problems += 1
2044
2044
2045 # check username
2045 # check username
2046 ui.status(_("checking username...\n"))
2046 ui.status(_("checking username...\n"))
2047 try:
2047 try:
2048 ui.username()
2048 ui.username()
2049 except util.Abort, e:
2049 except util.Abort, e:
2050 ui.write(" %s\n" % e)
2050 ui.write(" %s\n" % e)
2051 ui.write(_(" (specify a username in your configuration file)\n"))
2051 ui.write(_(" (specify a username in your configuration file)\n"))
2052 problems += 1
2052 problems += 1
2053
2053
2054 if not problems:
2054 if not problems:
2055 ui.status(_("no problems detected\n"))
2055 ui.status(_("no problems detected\n"))
2056 else:
2056 else:
2057 ui.write(_("%s problems detected,"
2057 ui.write(_("%s problems detected,"
2058 " please check your install!\n") % problems)
2058 " please check your install!\n") % problems)
2059
2059
2060 return problems
2060 return problems
2061
2061
2062 @command('debugknown', [], _('REPO ID...'))
2062 @command('debugknown', [], _('REPO ID...'))
2063 def debugknown(ui, repopath, *ids, **opts):
2063 def debugknown(ui, repopath, *ids, **opts):
2064 """test whether node ids are known to a repo
2064 """test whether node ids are known to a repo
2065
2065
2066 Every ID must be a full-length hex node id string. Returns a list of 0s
2066 Every ID must be a full-length hex node id string. Returns a list of 0s
2067 and 1s indicating unknown/known.
2067 and 1s indicating unknown/known.
2068 """
2068 """
2069 repo = hg.peer(ui, opts, repopath)
2069 repo = hg.peer(ui, opts, repopath)
2070 if not repo.capable('known'):
2070 if not repo.capable('known'):
2071 raise util.Abort("known() not supported by target repository")
2071 raise util.Abort("known() not supported by target repository")
2072 flags = repo.known([bin(s) for s in ids])
2072 flags = repo.known([bin(s) for s in ids])
2073 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2073 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2074
2074
2075 @command('debuglabelcomplete', [], _('LABEL...'))
2075 @command('debuglabelcomplete', [], _('LABEL...'))
2076 def debuglabelcomplete(ui, repo, *args):
2076 def debuglabelcomplete(ui, repo, *args):
2077 '''complete "labels" - tags, open branch names, bookmark names'''
2077 '''complete "labels" - tags, open branch names, bookmark names'''
2078
2078
2079 labels = set()
2079 labels = set()
2080 labels.update(t[0] for t in repo.tagslist())
2080 labels.update(t[0] for t in repo.tagslist())
2081 labels.update(repo._bookmarks.keys())
2081 labels.update(repo._bookmarks.keys())
2082 for heads in repo.branchmap().itervalues():
2082 for heads in repo.branchmap().itervalues():
2083 for h in heads:
2083 for h in heads:
2084 ctx = repo[h]
2084 ctx = repo[h]
2085 if not ctx.closesbranch():
2085 if not ctx.closesbranch():
2086 labels.add(ctx.branch())
2086 labels.add(ctx.branch())
2087 completions = set()
2087 completions = set()
2088 if not args:
2088 if not args:
2089 args = ['']
2089 args = ['']
2090 for a in args:
2090 for a in args:
2091 completions.update(l for l in labels if l.startswith(a))
2091 completions.update(l for l in labels if l.startswith(a))
2092 ui.write('\n'.join(sorted(completions)))
2092 ui.write('\n'.join(sorted(completions)))
2093 ui.write('\n')
2093 ui.write('\n')
2094
2094
2095 @command('debugobsolete',
2095 @command('debugobsolete',
2096 [('', 'flags', 0, _('markers flag')),
2096 [('', 'flags', 0, _('markers flag')),
2097 ] + commitopts2,
2097 ] + commitopts2,
2098 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2098 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2099 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2099 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2100 """create arbitrary obsolete marker
2100 """create arbitrary obsolete marker
2101
2101
2102 With no arguments, displays the list of obsolescence markers."""
2102 With no arguments, displays the list of obsolescence markers."""
2103 def parsenodeid(s):
2103 def parsenodeid(s):
2104 try:
2104 try:
2105 # We do not use revsingle/revrange functions here to accept
2105 # We do not use revsingle/revrange functions here to accept
2106 # arbitrary node identifiers, possibly not present in the
2106 # arbitrary node identifiers, possibly not present in the
2107 # local repository.
2107 # local repository.
2108 n = bin(s)
2108 n = bin(s)
2109 if len(n) != len(nullid):
2109 if len(n) != len(nullid):
2110 raise TypeError()
2110 raise TypeError()
2111 return n
2111 return n
2112 except TypeError:
2112 except TypeError:
2113 raise util.Abort('changeset references must be full hexadecimal '
2113 raise util.Abort('changeset references must be full hexadecimal '
2114 'node identifiers')
2114 'node identifiers')
2115
2115
2116 if precursor is not None:
2116 if precursor is not None:
2117 metadata = {}
2117 metadata = {}
2118 if 'date' in opts:
2118 if 'date' in opts:
2119 metadata['date'] = opts['date']
2119 metadata['date'] = opts['date']
2120 metadata['user'] = opts['user'] or ui.username()
2120 metadata['user'] = opts['user'] or ui.username()
2121 succs = tuple(parsenodeid(succ) for succ in successors)
2121 succs = tuple(parsenodeid(succ) for succ in successors)
2122 l = repo.lock()
2122 l = repo.lock()
2123 try:
2123 try:
2124 tr = repo.transaction('debugobsolete')
2124 tr = repo.transaction('debugobsolete')
2125 try:
2125 try:
2126 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2126 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2127 opts['flags'], metadata)
2127 opts['flags'], metadata)
2128 tr.close()
2128 tr.close()
2129 finally:
2129 finally:
2130 tr.release()
2130 tr.release()
2131 finally:
2131 finally:
2132 l.release()
2132 l.release()
2133 else:
2133 else:
2134 for m in obsolete.allmarkers(repo):
2134 for m in obsolete.allmarkers(repo):
2135 ui.write(hex(m.precnode()))
2135 ui.write(hex(m.precnode()))
2136 for repl in m.succnodes():
2136 for repl in m.succnodes():
2137 ui.write(' ')
2137 ui.write(' ')
2138 ui.write(hex(repl))
2138 ui.write(hex(repl))
2139 ui.write(' %X ' % m._data[2])
2139 ui.write(' %X ' % m._data[2])
2140 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2140 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2141 sorted(m.metadata().items()))))
2141 sorted(m.metadata().items()))))
2142 ui.write('\n')
2142 ui.write('\n')
2143
2143
2144 @command('debugpathcomplete',
2144 @command('debugpathcomplete',
2145 [('f', 'full', None, _('complete an entire path')),
2145 [('f', 'full', None, _('complete an entire path')),
2146 ('n', 'normal', None, _('show only normal files')),
2146 ('n', 'normal', None, _('show only normal files')),
2147 ('a', 'added', None, _('show only added files')),
2147 ('a', 'added', None, _('show only added files')),
2148 ('r', 'removed', None, _('show only removed files'))],
2148 ('r', 'removed', None, _('show only removed files'))],
2149 _('FILESPEC...'))
2149 _('FILESPEC...'))
2150 def debugpathcomplete(ui, repo, *specs, **opts):
2150 def debugpathcomplete(ui, repo, *specs, **opts):
2151 '''complete part or all of a tracked path
2151 '''complete part or all of a tracked path
2152
2152
2153 This command supports shells that offer path name completion. It
2153 This command supports shells that offer path name completion. It
2154 currently completes only files already known to the dirstate.
2154 currently completes only files already known to the dirstate.
2155
2155
2156 Completion extends only to the next path segment unless
2156 Completion extends only to the next path segment unless
2157 --full is specified, in which case entire paths are used.'''
2157 --full is specified, in which case entire paths are used.'''
2158
2158
2159 def complete(path, acceptable):
2159 def complete(path, acceptable):
2160 dirstate = repo.dirstate
2160 dirstate = repo.dirstate
2161 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2161 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2162 rootdir = repo.root + os.sep
2162 rootdir = repo.root + os.sep
2163 if spec != repo.root and not spec.startswith(rootdir):
2163 if spec != repo.root and not spec.startswith(rootdir):
2164 return [], []
2164 return [], []
2165 if os.path.isdir(spec):
2165 if os.path.isdir(spec):
2166 spec += '/'
2166 spec += '/'
2167 spec = spec[len(rootdir):]
2167 spec = spec[len(rootdir):]
2168 fixpaths = os.sep != '/'
2168 fixpaths = os.sep != '/'
2169 if fixpaths:
2169 if fixpaths:
2170 spec = spec.replace(os.sep, '/')
2170 spec = spec.replace(os.sep, '/')
2171 speclen = len(spec)
2171 speclen = len(spec)
2172 fullpaths = opts['full']
2172 fullpaths = opts['full']
2173 files, dirs = set(), set()
2173 files, dirs = set(), set()
2174 adddir, addfile = dirs.add, files.add
2174 adddir, addfile = dirs.add, files.add
2175 for f, st in dirstate.iteritems():
2175 for f, st in dirstate.iteritems():
2176 if f.startswith(spec) and st[0] in acceptable:
2176 if f.startswith(spec) and st[0] in acceptable:
2177 if fixpaths:
2177 if fixpaths:
2178 f = f.replace('/', os.sep)
2178 f = f.replace('/', os.sep)
2179 if fullpaths:
2179 if fullpaths:
2180 addfile(f)
2180 addfile(f)
2181 continue
2181 continue
2182 s = f.find(os.sep, speclen)
2182 s = f.find(os.sep, speclen)
2183 if s >= 0:
2183 if s >= 0:
2184 adddir(f[:s + 1])
2184 adddir(f[:s + 1])
2185 else:
2185 else:
2186 addfile(f)
2186 addfile(f)
2187 return files, dirs
2187 return files, dirs
2188
2188
2189 acceptable = ''
2189 acceptable = ''
2190 if opts['normal']:
2190 if opts['normal']:
2191 acceptable += 'nm'
2191 acceptable += 'nm'
2192 if opts['added']:
2192 if opts['added']:
2193 acceptable += 'a'
2193 acceptable += 'a'
2194 if opts['removed']:
2194 if opts['removed']:
2195 acceptable += 'r'
2195 acceptable += 'r'
2196 cwd = repo.getcwd()
2196 cwd = repo.getcwd()
2197 if not specs:
2197 if not specs:
2198 specs = ['.']
2198 specs = ['.']
2199
2199
2200 files, dirs = set(), set()
2200 files, dirs = set(), set()
2201 for spec in specs:
2201 for spec in specs:
2202 f, d = complete(spec, acceptable or 'nmar')
2202 f, d = complete(spec, acceptable or 'nmar')
2203 files.update(f)
2203 files.update(f)
2204 dirs.update(d)
2204 dirs.update(d)
2205 if not files and len(dirs) == 1:
2205 if not files and len(dirs) == 1:
2206 # force the shell to consider a completion that matches one
2206 # force the shell to consider a completion that matches one
2207 # directory and zero files to be ambiguous
2207 # directory and zero files to be ambiguous
2208 dirs.add(iter(dirs).next() + '.')
2208 dirs.add(iter(dirs).next() + '.')
2209 files.update(dirs)
2209 files.update(dirs)
2210 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2210 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2211 ui.write('\n')
2211 ui.write('\n')
2212
2212
2213 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2213 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2214 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2214 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2215 '''access the pushkey key/value protocol
2215 '''access the pushkey key/value protocol
2216
2216
2217 With two args, list the keys in the given namespace.
2217 With two args, list the keys in the given namespace.
2218
2218
2219 With five args, set a key to new if it currently is set to old.
2219 With five args, set a key to new if it currently is set to old.
2220 Reports success or failure.
2220 Reports success or failure.
2221 '''
2221 '''
2222
2222
2223 target = hg.peer(ui, {}, repopath)
2223 target = hg.peer(ui, {}, repopath)
2224 if keyinfo:
2224 if keyinfo:
2225 key, old, new = keyinfo
2225 key, old, new = keyinfo
2226 r = target.pushkey(namespace, key, old, new)
2226 r = target.pushkey(namespace, key, old, new)
2227 ui.status(str(r) + '\n')
2227 ui.status(str(r) + '\n')
2228 return not r
2228 return not r
2229 else:
2229 else:
2230 for k, v in sorted(target.listkeys(namespace).iteritems()):
2230 for k, v in sorted(target.listkeys(namespace).iteritems()):
2231 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2231 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2232 v.encode('string-escape')))
2232 v.encode('string-escape')))
2233
2233
2234 @command('debugpvec', [], _('A B'))
2234 @command('debugpvec', [], _('A B'))
2235 def debugpvec(ui, repo, a, b=None):
2235 def debugpvec(ui, repo, a, b=None):
2236 ca = scmutil.revsingle(repo, a)
2236 ca = scmutil.revsingle(repo, a)
2237 cb = scmutil.revsingle(repo, b)
2237 cb = scmutil.revsingle(repo, b)
2238 pa = pvec.ctxpvec(ca)
2238 pa = pvec.ctxpvec(ca)
2239 pb = pvec.ctxpvec(cb)
2239 pb = pvec.ctxpvec(cb)
2240 if pa == pb:
2240 if pa == pb:
2241 rel = "="
2241 rel = "="
2242 elif pa > pb:
2242 elif pa > pb:
2243 rel = ">"
2243 rel = ">"
2244 elif pa < pb:
2244 elif pa < pb:
2245 rel = "<"
2245 rel = "<"
2246 elif pa | pb:
2246 elif pa | pb:
2247 rel = "|"
2247 rel = "|"
2248 ui.write(_("a: %s\n") % pa)
2248 ui.write(_("a: %s\n") % pa)
2249 ui.write(_("b: %s\n") % pb)
2249 ui.write(_("b: %s\n") % pb)
2250 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2250 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2251 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2251 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2252 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2252 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2253 pa.distance(pb), rel))
2253 pa.distance(pb), rel))
2254
2254
2255 @command('debugrebuildstate',
2255 @command('debugrebuildstate',
2256 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2256 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2257 _('[-r REV] [REV]'))
2257 _('[-r REV] [REV]'))
2258 def debugrebuildstate(ui, repo, rev="tip"):
2258 def debugrebuildstate(ui, repo, rev="tip"):
2259 """rebuild the dirstate as it would look like for the given revision"""
2259 """rebuild the dirstate as it would look like for the given revision"""
2260 ctx = scmutil.revsingle(repo, rev)
2260 ctx = scmutil.revsingle(repo, rev)
2261 wlock = repo.wlock()
2261 wlock = repo.wlock()
2262 try:
2262 try:
2263 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2263 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2264 finally:
2264 finally:
2265 wlock.release()
2265 wlock.release()
2266
2266
2267 @command('debugrename',
2267 @command('debugrename',
2268 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2268 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2269 _('[-r REV] FILE'))
2269 _('[-r REV] FILE'))
2270 def debugrename(ui, repo, file1, *pats, **opts):
2270 def debugrename(ui, repo, file1, *pats, **opts):
2271 """dump rename information"""
2271 """dump rename information"""
2272
2272
2273 ctx = scmutil.revsingle(repo, opts.get('rev'))
2273 ctx = scmutil.revsingle(repo, opts.get('rev'))
2274 m = scmutil.match(ctx, (file1,) + pats, opts)
2274 m = scmutil.match(ctx, (file1,) + pats, opts)
2275 for abs in ctx.walk(m):
2275 for abs in ctx.walk(m):
2276 fctx = ctx[abs]
2276 fctx = ctx[abs]
2277 o = fctx.filelog().renamed(fctx.filenode())
2277 o = fctx.filelog().renamed(fctx.filenode())
2278 rel = m.rel(abs)
2278 rel = m.rel(abs)
2279 if o:
2279 if o:
2280 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2280 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2281 else:
2281 else:
2282 ui.write(_("%s not renamed\n") % rel)
2282 ui.write(_("%s not renamed\n") % rel)
2283
2283
2284 @command('debugrevlog',
2284 @command('debugrevlog',
2285 [('c', 'changelog', False, _('open changelog')),
2285 [('c', 'changelog', False, _('open changelog')),
2286 ('m', 'manifest', False, _('open manifest')),
2286 ('m', 'manifest', False, _('open manifest')),
2287 ('d', 'dump', False, _('dump index data'))],
2287 ('d', 'dump', False, _('dump index data'))],
2288 _('-c|-m|FILE'))
2288 _('-c|-m|FILE'))
2289 def debugrevlog(ui, repo, file_ = None, **opts):
2289 def debugrevlog(ui, repo, file_ = None, **opts):
2290 """show data and statistics about a revlog"""
2290 """show data and statistics about a revlog"""
2291 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2291 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2292
2292
2293 if opts.get("dump"):
2293 if opts.get("dump"):
2294 numrevs = len(r)
2294 numrevs = len(r)
2295 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2295 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2296 " rawsize totalsize compression heads\n")
2296 " rawsize totalsize compression heads\n")
2297 ts = 0
2297 ts = 0
2298 heads = set()
2298 heads = set()
2299 for rev in xrange(numrevs):
2299 for rev in xrange(numrevs):
2300 dbase = r.deltaparent(rev)
2300 dbase = r.deltaparent(rev)
2301 if dbase == -1:
2301 if dbase == -1:
2302 dbase = rev
2302 dbase = rev
2303 cbase = r.chainbase(rev)
2303 cbase = r.chainbase(rev)
2304 p1, p2 = r.parentrevs(rev)
2304 p1, p2 = r.parentrevs(rev)
2305 rs = r.rawsize(rev)
2305 rs = r.rawsize(rev)
2306 ts = ts + rs
2306 ts = ts + rs
2307 heads -= set(r.parentrevs(rev))
2307 heads -= set(r.parentrevs(rev))
2308 heads.add(rev)
2308 heads.add(rev)
2309 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2309 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2310 (rev, p1, p2, r.start(rev), r.end(rev),
2310 (rev, p1, p2, r.start(rev), r.end(rev),
2311 r.start(dbase), r.start(cbase),
2311 r.start(dbase), r.start(cbase),
2312 r.start(p1), r.start(p2),
2312 r.start(p1), r.start(p2),
2313 rs, ts, ts / r.end(rev), len(heads)))
2313 rs, ts, ts / r.end(rev), len(heads)))
2314 return 0
2314 return 0
2315
2315
2316 v = r.version
2316 v = r.version
2317 format = v & 0xFFFF
2317 format = v & 0xFFFF
2318 flags = []
2318 flags = []
2319 gdelta = False
2319 gdelta = False
2320 if v & revlog.REVLOGNGINLINEDATA:
2320 if v & revlog.REVLOGNGINLINEDATA:
2321 flags.append('inline')
2321 flags.append('inline')
2322 if v & revlog.REVLOGGENERALDELTA:
2322 if v & revlog.REVLOGGENERALDELTA:
2323 gdelta = True
2323 gdelta = True
2324 flags.append('generaldelta')
2324 flags.append('generaldelta')
2325 if not flags:
2325 if not flags:
2326 flags = ['(none)']
2326 flags = ['(none)']
2327
2327
2328 nummerges = 0
2328 nummerges = 0
2329 numfull = 0
2329 numfull = 0
2330 numprev = 0
2330 numprev = 0
2331 nump1 = 0
2331 nump1 = 0
2332 nump2 = 0
2332 nump2 = 0
2333 numother = 0
2333 numother = 0
2334 nump1prev = 0
2334 nump1prev = 0
2335 nump2prev = 0
2335 nump2prev = 0
2336 chainlengths = []
2336 chainlengths = []
2337
2337
2338 datasize = [None, 0, 0L]
2338 datasize = [None, 0, 0L]
2339 fullsize = [None, 0, 0L]
2339 fullsize = [None, 0, 0L]
2340 deltasize = [None, 0, 0L]
2340 deltasize = [None, 0, 0L]
2341
2341
2342 def addsize(size, l):
2342 def addsize(size, l):
2343 if l[0] is None or size < l[0]:
2343 if l[0] is None or size < l[0]:
2344 l[0] = size
2344 l[0] = size
2345 if size > l[1]:
2345 if size > l[1]:
2346 l[1] = size
2346 l[1] = size
2347 l[2] += size
2347 l[2] += size
2348
2348
2349 numrevs = len(r)
2349 numrevs = len(r)
2350 for rev in xrange(numrevs):
2350 for rev in xrange(numrevs):
2351 p1, p2 = r.parentrevs(rev)
2351 p1, p2 = r.parentrevs(rev)
2352 delta = r.deltaparent(rev)
2352 delta = r.deltaparent(rev)
2353 if format > 0:
2353 if format > 0:
2354 addsize(r.rawsize(rev), datasize)
2354 addsize(r.rawsize(rev), datasize)
2355 if p2 != nullrev:
2355 if p2 != nullrev:
2356 nummerges += 1
2356 nummerges += 1
2357 size = r.length(rev)
2357 size = r.length(rev)
2358 if delta == nullrev:
2358 if delta == nullrev:
2359 chainlengths.append(0)
2359 chainlengths.append(0)
2360 numfull += 1
2360 numfull += 1
2361 addsize(size, fullsize)
2361 addsize(size, fullsize)
2362 else:
2362 else:
2363 chainlengths.append(chainlengths[delta] + 1)
2363 chainlengths.append(chainlengths[delta] + 1)
2364 addsize(size, deltasize)
2364 addsize(size, deltasize)
2365 if delta == rev - 1:
2365 if delta == rev - 1:
2366 numprev += 1
2366 numprev += 1
2367 if delta == p1:
2367 if delta == p1:
2368 nump1prev += 1
2368 nump1prev += 1
2369 elif delta == p2:
2369 elif delta == p2:
2370 nump2prev += 1
2370 nump2prev += 1
2371 elif delta == p1:
2371 elif delta == p1:
2372 nump1 += 1
2372 nump1 += 1
2373 elif delta == p2:
2373 elif delta == p2:
2374 nump2 += 1
2374 nump2 += 1
2375 elif delta != nullrev:
2375 elif delta != nullrev:
2376 numother += 1
2376 numother += 1
2377
2377
2378 # Adjust size min value for empty cases
2378 # Adjust size min value for empty cases
2379 for size in (datasize, fullsize, deltasize):
2379 for size in (datasize, fullsize, deltasize):
2380 if size[0] is None:
2380 if size[0] is None:
2381 size[0] = 0
2381 size[0] = 0
2382
2382
2383 numdeltas = numrevs - numfull
2383 numdeltas = numrevs - numfull
2384 numoprev = numprev - nump1prev - nump2prev
2384 numoprev = numprev - nump1prev - nump2prev
2385 totalrawsize = datasize[2]
2385 totalrawsize = datasize[2]
2386 datasize[2] /= numrevs
2386 datasize[2] /= numrevs
2387 fulltotal = fullsize[2]
2387 fulltotal = fullsize[2]
2388 fullsize[2] /= numfull
2388 fullsize[2] /= numfull
2389 deltatotal = deltasize[2]
2389 deltatotal = deltasize[2]
2390 if numrevs - numfull > 0:
2390 if numrevs - numfull > 0:
2391 deltasize[2] /= numrevs - numfull
2391 deltasize[2] /= numrevs - numfull
2392 totalsize = fulltotal + deltatotal
2392 totalsize = fulltotal + deltatotal
2393 avgchainlen = sum(chainlengths) / numrevs
2393 avgchainlen = sum(chainlengths) / numrevs
2394 compratio = totalrawsize / totalsize
2394 compratio = totalrawsize / totalsize
2395
2395
2396 basedfmtstr = '%%%dd\n'
2396 basedfmtstr = '%%%dd\n'
2397 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2397 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2398
2398
2399 def dfmtstr(max):
2399 def dfmtstr(max):
2400 return basedfmtstr % len(str(max))
2400 return basedfmtstr % len(str(max))
2401 def pcfmtstr(max, padding=0):
2401 def pcfmtstr(max, padding=0):
2402 return basepcfmtstr % (len(str(max)), ' ' * padding)
2402 return basepcfmtstr % (len(str(max)), ' ' * padding)
2403
2403
2404 def pcfmt(value, total):
2404 def pcfmt(value, total):
2405 return (value, 100 * float(value) / total)
2405 return (value, 100 * float(value) / total)
2406
2406
2407 ui.write(('format : %d\n') % format)
2407 ui.write(('format : %d\n') % format)
2408 ui.write(('flags : %s\n') % ', '.join(flags))
2408 ui.write(('flags : %s\n') % ', '.join(flags))
2409
2409
2410 ui.write('\n')
2410 ui.write('\n')
2411 fmt = pcfmtstr(totalsize)
2411 fmt = pcfmtstr(totalsize)
2412 fmt2 = dfmtstr(totalsize)
2412 fmt2 = dfmtstr(totalsize)
2413 ui.write(('revisions : ') + fmt2 % numrevs)
2413 ui.write(('revisions : ') + fmt2 % numrevs)
2414 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2414 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2415 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2415 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2416 ui.write(('revisions : ') + fmt2 % numrevs)
2416 ui.write(('revisions : ') + fmt2 % numrevs)
2417 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2417 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2418 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2418 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2419 ui.write(('revision size : ') + fmt2 % totalsize)
2419 ui.write(('revision size : ') + fmt2 % totalsize)
2420 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2420 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2421 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2421 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2422
2422
2423 ui.write('\n')
2423 ui.write('\n')
2424 fmt = dfmtstr(max(avgchainlen, compratio))
2424 fmt = dfmtstr(max(avgchainlen, compratio))
2425 ui.write(('avg chain length : ') + fmt % avgchainlen)
2425 ui.write(('avg chain length : ') + fmt % avgchainlen)
2426 ui.write(('compression ratio : ') + fmt % compratio)
2426 ui.write(('compression ratio : ') + fmt % compratio)
2427
2427
2428 if format > 0:
2428 if format > 0:
2429 ui.write('\n')
2429 ui.write('\n')
2430 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2430 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2431 % tuple(datasize))
2431 % tuple(datasize))
2432 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2432 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2433 % tuple(fullsize))
2433 % tuple(fullsize))
2434 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2434 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2435 % tuple(deltasize))
2435 % tuple(deltasize))
2436
2436
2437 if numdeltas > 0:
2437 if numdeltas > 0:
2438 ui.write('\n')
2438 ui.write('\n')
2439 fmt = pcfmtstr(numdeltas)
2439 fmt = pcfmtstr(numdeltas)
2440 fmt2 = pcfmtstr(numdeltas, 4)
2440 fmt2 = pcfmtstr(numdeltas, 4)
2441 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2441 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2442 if numprev > 0:
2442 if numprev > 0:
2443 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2443 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2444 numprev))
2444 numprev))
2445 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2445 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2446 numprev))
2446 numprev))
2447 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2447 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2448 numprev))
2448 numprev))
2449 if gdelta:
2449 if gdelta:
2450 ui.write(('deltas against p1 : ')
2450 ui.write(('deltas against p1 : ')
2451 + fmt % pcfmt(nump1, numdeltas))
2451 + fmt % pcfmt(nump1, numdeltas))
2452 ui.write(('deltas against p2 : ')
2452 ui.write(('deltas against p2 : ')
2453 + fmt % pcfmt(nump2, numdeltas))
2453 + fmt % pcfmt(nump2, numdeltas))
2454 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2454 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2455 numdeltas))
2455 numdeltas))
2456
2456
2457 @command('debugrevspec', [], ('REVSPEC'))
2457 @command('debugrevspec', [], ('REVSPEC'))
2458 def debugrevspec(ui, repo, expr):
2458 def debugrevspec(ui, repo, expr):
2459 """parse and apply a revision specification
2459 """parse and apply a revision specification
2460
2460
2461 Use --verbose to print the parsed tree before and after aliases
2461 Use --verbose to print the parsed tree before and after aliases
2462 expansion.
2462 expansion.
2463 """
2463 """
2464 if ui.verbose:
2464 if ui.verbose:
2465 tree = revset.parse(expr)[0]
2465 tree = revset.parse(expr)[0]
2466 ui.note(revset.prettyformat(tree), "\n")
2466 ui.note(revset.prettyformat(tree), "\n")
2467 newtree = revset.findaliases(ui, tree)
2467 newtree = revset.findaliases(ui, tree)
2468 if newtree != tree:
2468 if newtree != tree:
2469 ui.note(revset.prettyformat(newtree), "\n")
2469 ui.note(revset.prettyformat(newtree), "\n")
2470 func = revset.match(ui, expr)
2470 func = revset.match(ui, expr)
2471 for c in func(repo, range(len(repo))):
2471 for c in func(repo, range(len(repo))):
2472 ui.write("%s\n" % c)
2472 ui.write("%s\n" % c)
2473
2473
2474 @command('debugsetparents', [], _('REV1 [REV2]'))
2474 @command('debugsetparents', [], _('REV1 [REV2]'))
2475 def debugsetparents(ui, repo, rev1, rev2=None):
2475 def debugsetparents(ui, repo, rev1, rev2=None):
2476 """manually set the parents of the current working directory
2476 """manually set the parents of the current working directory
2477
2477
2478 This is useful for writing repository conversion tools, but should
2478 This is useful for writing repository conversion tools, but should
2479 be used with care.
2479 be used with care.
2480
2480
2481 Returns 0 on success.
2481 Returns 0 on success.
2482 """
2482 """
2483
2483
2484 r1 = scmutil.revsingle(repo, rev1).node()
2484 r1 = scmutil.revsingle(repo, rev1).node()
2485 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2485 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2486
2486
2487 wlock = repo.wlock()
2487 wlock = repo.wlock()
2488 try:
2488 try:
2489 repo.setparents(r1, r2)
2489 repo.setparents(r1, r2)
2490 finally:
2490 finally:
2491 wlock.release()
2491 wlock.release()
2492
2492
2493 @command('debugstate',
2493 @command('debugstate',
2494 [('', 'nodates', None, _('do not display the saved mtime')),
2494 [('', 'nodates', None, _('do not display the saved mtime')),
2495 ('', 'datesort', None, _('sort by saved mtime'))],
2495 ('', 'datesort', None, _('sort by saved mtime'))],
2496 _('[OPTION]...'))
2496 _('[OPTION]...'))
2497 def debugstate(ui, repo, nodates=None, datesort=None):
2497 def debugstate(ui, repo, nodates=None, datesort=None):
2498 """show the contents of the current dirstate"""
2498 """show the contents of the current dirstate"""
2499 timestr = ""
2499 timestr = ""
2500 showdate = not nodates
2500 showdate = not nodates
2501 if datesort:
2501 if datesort:
2502 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2502 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2503 else:
2503 else:
2504 keyfunc = None # sort by filename
2504 keyfunc = None # sort by filename
2505 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2505 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2506 if showdate:
2506 if showdate:
2507 if ent[3] == -1:
2507 if ent[3] == -1:
2508 # Pad or slice to locale representation
2508 # Pad or slice to locale representation
2509 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2509 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2510 time.localtime(0)))
2510 time.localtime(0)))
2511 timestr = 'unset'
2511 timestr = 'unset'
2512 timestr = (timestr[:locale_len] +
2512 timestr = (timestr[:locale_len] +
2513 ' ' * (locale_len - len(timestr)))
2513 ' ' * (locale_len - len(timestr)))
2514 else:
2514 else:
2515 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2515 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2516 time.localtime(ent[3]))
2516 time.localtime(ent[3]))
2517 if ent[1] & 020000:
2517 if ent[1] & 020000:
2518 mode = 'lnk'
2518 mode = 'lnk'
2519 else:
2519 else:
2520 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2520 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2521 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2521 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2522 for f in repo.dirstate.copies():
2522 for f in repo.dirstate.copies():
2523 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2523 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2524
2524
2525 @command('debugsub',
2525 @command('debugsub',
2526 [('r', 'rev', '',
2526 [('r', 'rev', '',
2527 _('revision to check'), _('REV'))],
2527 _('revision to check'), _('REV'))],
2528 _('[-r REV] [REV]'))
2528 _('[-r REV] [REV]'))
2529 def debugsub(ui, repo, rev=None):
2529 def debugsub(ui, repo, rev=None):
2530 ctx = scmutil.revsingle(repo, rev, None)
2530 ctx = scmutil.revsingle(repo, rev, None)
2531 for k, v in sorted(ctx.substate.items()):
2531 for k, v in sorted(ctx.substate.items()):
2532 ui.write(('path %s\n') % k)
2532 ui.write(('path %s\n') % k)
2533 ui.write((' source %s\n') % v[0])
2533 ui.write((' source %s\n') % v[0])
2534 ui.write((' revision %s\n') % v[1])
2534 ui.write((' revision %s\n') % v[1])
2535
2535
2536 @command('debugsuccessorssets',
2536 @command('debugsuccessorssets',
2537 [],
2537 [],
2538 _('[REV]'))
2538 _('[REV]'))
2539 def debugsuccessorssets(ui, repo, *revs):
2539 def debugsuccessorssets(ui, repo, *revs):
2540 """show set of successors for revision
2540 """show set of successors for revision
2541
2541
2542 A successors set of changeset A is a consistent group of revisions that
2542 A successors set of changeset A is a consistent group of revisions that
2543 succeed A. It contains non-obsolete changesets only.
2543 succeed A. It contains non-obsolete changesets only.
2544
2544
2545 In most cases a changeset A has a single successors set containing a single
2545 In most cases a changeset A has a single successors set containing a single
2546 successor (changeset A replaced by A').
2546 successor (changeset A replaced by A').
2547
2547
2548 A changeset that is made obsolete with no successors are called "pruned".
2548 A changeset that is made obsolete with no successors are called "pruned".
2549 Such changesets have no successors sets at all.
2549 Such changesets have no successors sets at all.
2550
2550
2551 A changeset that has been "split" will have a successors set containing
2551 A changeset that has been "split" will have a successors set containing
2552 more than one successor.
2552 more than one successor.
2553
2553
2554 A changeset that has been rewritten in multiple different ways is called
2554 A changeset that has been rewritten in multiple different ways is called
2555 "divergent". Such changesets have multiple successor sets (each of which
2555 "divergent". Such changesets have multiple successor sets (each of which
2556 may also be split, i.e. have multiple successors).
2556 may also be split, i.e. have multiple successors).
2557
2557
2558 Results are displayed as follows::
2558 Results are displayed as follows::
2559
2559
2560 <rev1>
2560 <rev1>
2561 <successors-1A>
2561 <successors-1A>
2562 <rev2>
2562 <rev2>
2563 <successors-2A>
2563 <successors-2A>
2564 <successors-2B1> <successors-2B2> <successors-2B3>
2564 <successors-2B1> <successors-2B2> <successors-2B3>
2565
2565
2566 Here rev2 has two possible (i.e. divergent) successors sets. The first
2566 Here rev2 has two possible (i.e. divergent) successors sets. The first
2567 holds one element, whereas the second holds three (i.e. the changeset has
2567 holds one element, whereas the second holds three (i.e. the changeset has
2568 been split).
2568 been split).
2569 """
2569 """
2570 # passed to successorssets caching computation from one call to another
2570 # passed to successorssets caching computation from one call to another
2571 cache = {}
2571 cache = {}
2572 ctx2str = str
2572 ctx2str = str
2573 node2str = short
2573 node2str = short
2574 if ui.debug():
2574 if ui.debug():
2575 def ctx2str(ctx):
2575 def ctx2str(ctx):
2576 return ctx.hex()
2576 return ctx.hex()
2577 node2str = hex
2577 node2str = hex
2578 for rev in scmutil.revrange(repo, revs):
2578 for rev in scmutil.revrange(repo, revs):
2579 ctx = repo[rev]
2579 ctx = repo[rev]
2580 ui.write('%s\n'% ctx2str(ctx))
2580 ui.write('%s\n'% ctx2str(ctx))
2581 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2581 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2582 if succsset:
2582 if succsset:
2583 ui.write(' ')
2583 ui.write(' ')
2584 ui.write(node2str(succsset[0]))
2584 ui.write(node2str(succsset[0]))
2585 for node in succsset[1:]:
2585 for node in succsset[1:]:
2586 ui.write(' ')
2586 ui.write(' ')
2587 ui.write(node2str(node))
2587 ui.write(node2str(node))
2588 ui.write('\n')
2588 ui.write('\n')
2589
2589
2590 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2590 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2591 def debugwalk(ui, repo, *pats, **opts):
2591 def debugwalk(ui, repo, *pats, **opts):
2592 """show how files match on given patterns"""
2592 """show how files match on given patterns"""
2593 m = scmutil.match(repo[None], pats, opts)
2593 m = scmutil.match(repo[None], pats, opts)
2594 items = list(repo.walk(m))
2594 items = list(repo.walk(m))
2595 if not items:
2595 if not items:
2596 return
2596 return
2597 f = lambda fn: fn
2597 f = lambda fn: fn
2598 if ui.configbool('ui', 'slash') and os.sep != '/':
2598 if ui.configbool('ui', 'slash') and os.sep != '/':
2599 f = lambda fn: util.normpath(fn)
2599 f = lambda fn: util.normpath(fn)
2600 fmt = 'f %%-%ds %%-%ds %%s' % (
2600 fmt = 'f %%-%ds %%-%ds %%s' % (
2601 max([len(abs) for abs in items]),
2601 max([len(abs) for abs in items]),
2602 max([len(m.rel(abs)) for abs in items]))
2602 max([len(m.rel(abs)) for abs in items]))
2603 for abs in items:
2603 for abs in items:
2604 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2604 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2605 ui.write("%s\n" % line.rstrip())
2605 ui.write("%s\n" % line.rstrip())
2606
2606
2607 @command('debugwireargs',
2607 @command('debugwireargs',
2608 [('', 'three', '', 'three'),
2608 [('', 'three', '', 'three'),
2609 ('', 'four', '', 'four'),
2609 ('', 'four', '', 'four'),
2610 ('', 'five', '', 'five'),
2610 ('', 'five', '', 'five'),
2611 ] + remoteopts,
2611 ] + remoteopts,
2612 _('REPO [OPTIONS]... [ONE [TWO]]'))
2612 _('REPO [OPTIONS]... [ONE [TWO]]'))
2613 def debugwireargs(ui, repopath, *vals, **opts):
2613 def debugwireargs(ui, repopath, *vals, **opts):
2614 repo = hg.peer(ui, opts, repopath)
2614 repo = hg.peer(ui, opts, repopath)
2615 for opt in remoteopts:
2615 for opt in remoteopts:
2616 del opts[opt[1]]
2616 del opts[opt[1]]
2617 args = {}
2617 args = {}
2618 for k, v in opts.iteritems():
2618 for k, v in opts.iteritems():
2619 if v:
2619 if v:
2620 args[k] = v
2620 args[k] = v
2621 # run twice to check that we don't mess up the stream for the next command
2621 # run twice to check that we don't mess up the stream for the next command
2622 res1 = repo.debugwireargs(*vals, **args)
2622 res1 = repo.debugwireargs(*vals, **args)
2623 res2 = repo.debugwireargs(*vals, **args)
2623 res2 = repo.debugwireargs(*vals, **args)
2624 ui.write("%s\n" % res1)
2624 ui.write("%s\n" % res1)
2625 if res1 != res2:
2625 if res1 != res2:
2626 ui.warn("%s\n" % res2)
2626 ui.warn("%s\n" % res2)
2627
2627
2628 @command('^diff',
2628 @command('^diff',
2629 [('r', 'rev', [], _('revision'), _('REV')),
2629 [('r', 'rev', [], _('revision'), _('REV')),
2630 ('c', 'change', '', _('change made by revision'), _('REV'))
2630 ('c', 'change', '', _('change made by revision'), _('REV'))
2631 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2631 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2632 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2632 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2633 def diff(ui, repo, *pats, **opts):
2633 def diff(ui, repo, *pats, **opts):
2634 """diff repository (or selected files)
2634 """diff repository (or selected files)
2635
2635
2636 Show differences between revisions for the specified files.
2636 Show differences between revisions for the specified files.
2637
2637
2638 Differences between files are shown using the unified diff format.
2638 Differences between files are shown using the unified diff format.
2639
2639
2640 .. note::
2640 .. note::
2641 diff may generate unexpected results for merges, as it will
2641 diff may generate unexpected results for merges, as it will
2642 default to comparing against the working directory's first
2642 default to comparing against the working directory's first
2643 parent changeset if no revisions are specified.
2643 parent changeset if no revisions are specified.
2644
2644
2645 When two revision arguments are given, then changes are shown
2645 When two revision arguments are given, then changes are shown
2646 between those revisions. If only one revision is specified then
2646 between those revisions. If only one revision is specified then
2647 that revision is compared to the working directory, and, when no
2647 that revision is compared to the working directory, and, when no
2648 revisions are specified, the working directory files are compared
2648 revisions are specified, the working directory files are compared
2649 to its parent.
2649 to its parent.
2650
2650
2651 Alternatively you can specify -c/--change with a revision to see
2651 Alternatively you can specify -c/--change with a revision to see
2652 the changes in that changeset relative to its first parent.
2652 the changes in that changeset relative to its first parent.
2653
2653
2654 Without the -a/--text option, diff will avoid generating diffs of
2654 Without the -a/--text option, diff will avoid generating diffs of
2655 files it detects as binary. With -a, diff will generate a diff
2655 files it detects as binary. With -a, diff will generate a diff
2656 anyway, probably with undesirable results.
2656 anyway, probably with undesirable results.
2657
2657
2658 Use the -g/--git option to generate diffs in the git extended diff
2658 Use the -g/--git option to generate diffs in the git extended diff
2659 format. For more information, read :hg:`help diffs`.
2659 format. For more information, read :hg:`help diffs`.
2660
2660
2661 .. container:: verbose
2661 .. container:: verbose
2662
2662
2663 Examples:
2663 Examples:
2664
2664
2665 - compare a file in the current working directory to its parent::
2665 - compare a file in the current working directory to its parent::
2666
2666
2667 hg diff foo.c
2667 hg diff foo.c
2668
2668
2669 - compare two historical versions of a directory, with rename info::
2669 - compare two historical versions of a directory, with rename info::
2670
2670
2671 hg diff --git -r 1.0:1.2 lib/
2671 hg diff --git -r 1.0:1.2 lib/
2672
2672
2673 - get change stats relative to the last change on some date::
2673 - get change stats relative to the last change on some date::
2674
2674
2675 hg diff --stat -r "date('may 2')"
2675 hg diff --stat -r "date('may 2')"
2676
2676
2677 - diff all newly-added files that contain a keyword::
2677 - diff all newly-added files that contain a keyword::
2678
2678
2679 hg diff "set:added() and grep(GNU)"
2679 hg diff "set:added() and grep(GNU)"
2680
2680
2681 - compare a revision and its parents::
2681 - compare a revision and its parents::
2682
2682
2683 hg diff -c 9353 # compare against first parent
2683 hg diff -c 9353 # compare against first parent
2684 hg diff -r 9353^:9353 # same using revset syntax
2684 hg diff -r 9353^:9353 # same using revset syntax
2685 hg diff -r 9353^2:9353 # compare against the second parent
2685 hg diff -r 9353^2:9353 # compare against the second parent
2686
2686
2687 Returns 0 on success.
2687 Returns 0 on success.
2688 """
2688 """
2689
2689
2690 revs = opts.get('rev')
2690 revs = opts.get('rev')
2691 change = opts.get('change')
2691 change = opts.get('change')
2692 stat = opts.get('stat')
2692 stat = opts.get('stat')
2693 reverse = opts.get('reverse')
2693 reverse = opts.get('reverse')
2694
2694
2695 if revs and change:
2695 if revs and change:
2696 msg = _('cannot specify --rev and --change at the same time')
2696 msg = _('cannot specify --rev and --change at the same time')
2697 raise util.Abort(msg)
2697 raise util.Abort(msg)
2698 elif change:
2698 elif change:
2699 node2 = scmutil.revsingle(repo, change, None).node()
2699 node2 = scmutil.revsingle(repo, change, None).node()
2700 node1 = repo[node2].p1().node()
2700 node1 = repo[node2].p1().node()
2701 else:
2701 else:
2702 node1, node2 = scmutil.revpair(repo, revs)
2702 node1, node2 = scmutil.revpair(repo, revs)
2703
2703
2704 if reverse:
2704 if reverse:
2705 node1, node2 = node2, node1
2705 node1, node2 = node2, node1
2706
2706
2707 diffopts = patch.diffopts(ui, opts)
2707 diffopts = patch.diffopts(ui, opts)
2708 m = scmutil.match(repo[node2], pats, opts)
2708 m = scmutil.match(repo[node2], pats, opts)
2709 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2709 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2710 listsubrepos=opts.get('subrepos'))
2710 listsubrepos=opts.get('subrepos'))
2711
2711
2712 @command('^export',
2712 @command('^export',
2713 [('o', 'output', '',
2713 [('o', 'output', '',
2714 _('print output to file with formatted name'), _('FORMAT')),
2714 _('print output to file with formatted name'), _('FORMAT')),
2715 ('', 'switch-parent', None, _('diff against the second parent')),
2715 ('', 'switch-parent', None, _('diff against the second parent')),
2716 ('r', 'rev', [], _('revisions to export'), _('REV')),
2716 ('r', 'rev', [], _('revisions to export'), _('REV')),
2717 ] + diffopts,
2717 ] + diffopts,
2718 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2718 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2719 def export(ui, repo, *changesets, **opts):
2719 def export(ui, repo, *changesets, **opts):
2720 """dump the header and diffs for one or more changesets
2720 """dump the header and diffs for one or more changesets
2721
2721
2722 Print the changeset header and diffs for one or more revisions.
2722 Print the changeset header and diffs for one or more revisions.
2723
2723
2724 The information shown in the changeset header is: author, date,
2724 The information shown in the changeset header is: author, date,
2725 branch name (if non-default), changeset hash, parent(s) and commit
2725 branch name (if non-default), changeset hash, parent(s) and commit
2726 comment.
2726 comment.
2727
2727
2728 .. note::
2728 .. note::
2729 export may generate unexpected diff output for merge
2729 export may generate unexpected diff output for merge
2730 changesets, as it will compare the merge changeset against its
2730 changesets, as it will compare the merge changeset against its
2731 first parent only.
2731 first parent only.
2732
2732
2733 Output may be to a file, in which case the name of the file is
2733 Output may be to a file, in which case the name of the file is
2734 given using a format string. The formatting rules are as follows:
2734 given using a format string. The formatting rules are as follows:
2735
2735
2736 :``%%``: literal "%" character
2736 :``%%``: literal "%" character
2737 :``%H``: changeset hash (40 hexadecimal digits)
2737 :``%H``: changeset hash (40 hexadecimal digits)
2738 :``%N``: number of patches being generated
2738 :``%N``: number of patches being generated
2739 :``%R``: changeset revision number
2739 :``%R``: changeset revision number
2740 :``%b``: basename of the exporting repository
2740 :``%b``: basename of the exporting repository
2741 :``%h``: short-form changeset hash (12 hexadecimal digits)
2741 :``%h``: short-form changeset hash (12 hexadecimal digits)
2742 :``%m``: first line of the commit message (only alphanumeric characters)
2742 :``%m``: first line of the commit message (only alphanumeric characters)
2743 :``%n``: zero-padded sequence number, starting at 1
2743 :``%n``: zero-padded sequence number, starting at 1
2744 :``%r``: zero-padded changeset revision number
2744 :``%r``: zero-padded changeset revision number
2745
2745
2746 Without the -a/--text option, export will avoid generating diffs
2746 Without the -a/--text option, export will avoid generating diffs
2747 of files it detects as binary. With -a, export will generate a
2747 of files it detects as binary. With -a, export will generate a
2748 diff anyway, probably with undesirable results.
2748 diff anyway, probably with undesirable results.
2749
2749
2750 Use the -g/--git option to generate diffs in the git extended diff
2750 Use the -g/--git option to generate diffs in the git extended diff
2751 format. See :hg:`help diffs` for more information.
2751 format. See :hg:`help diffs` for more information.
2752
2752
2753 With the --switch-parent option, the diff will be against the
2753 With the --switch-parent option, the diff will be against the
2754 second parent. It can be useful to review a merge.
2754 second parent. It can be useful to review a merge.
2755
2755
2756 .. container:: verbose
2756 .. container:: verbose
2757
2757
2758 Examples:
2758 Examples:
2759
2759
2760 - use export and import to transplant a bugfix to the current
2760 - use export and import to transplant a bugfix to the current
2761 branch::
2761 branch::
2762
2762
2763 hg export -r 9353 | hg import -
2763 hg export -r 9353 | hg import -
2764
2764
2765 - export all the changesets between two revisions to a file with
2765 - export all the changesets between two revisions to a file with
2766 rename information::
2766 rename information::
2767
2767
2768 hg export --git -r 123:150 > changes.txt
2768 hg export --git -r 123:150 > changes.txt
2769
2769
2770 - split outgoing changes into a series of patches with
2770 - split outgoing changes into a series of patches with
2771 descriptive names::
2771 descriptive names::
2772
2772
2773 hg export -r "outgoing()" -o "%n-%m.patch"
2773 hg export -r "outgoing()" -o "%n-%m.patch"
2774
2774
2775 Returns 0 on success.
2775 Returns 0 on success.
2776 """
2776 """
2777 changesets += tuple(opts.get('rev', []))
2777 changesets += tuple(opts.get('rev', []))
2778 revs = scmutil.revrange(repo, changesets)
2778 revs = scmutil.revrange(repo, changesets)
2779 if not revs:
2779 if not revs:
2780 raise util.Abort(_("export requires at least one changeset"))
2780 raise util.Abort(_("export requires at least one changeset"))
2781 if len(revs) > 1:
2781 if len(revs) > 1:
2782 ui.note(_('exporting patches:\n'))
2782 ui.note(_('exporting patches:\n'))
2783 else:
2783 else:
2784 ui.note(_('exporting patch:\n'))
2784 ui.note(_('exporting patch:\n'))
2785 cmdutil.export(repo, revs, template=opts.get('output'),
2785 cmdutil.export(repo, revs, template=opts.get('output'),
2786 switch_parent=opts.get('switch_parent'),
2786 switch_parent=opts.get('switch_parent'),
2787 opts=patch.diffopts(ui, opts))
2787 opts=patch.diffopts(ui, opts))
2788
2788
2789 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2789 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2790 def forget(ui, repo, *pats, **opts):
2790 def forget(ui, repo, *pats, **opts):
2791 """forget the specified files on the next commit
2791 """forget the specified files on the next commit
2792
2792
2793 Mark the specified files so they will no longer be tracked
2793 Mark the specified files so they will no longer be tracked
2794 after the next commit.
2794 after the next commit.
2795
2795
2796 This only removes files from the current branch, not from the
2796 This only removes files from the current branch, not from the
2797 entire project history, and it does not delete them from the
2797 entire project history, and it does not delete them from the
2798 working directory.
2798 working directory.
2799
2799
2800 To undo a forget before the next commit, see :hg:`add`.
2800 To undo a forget before the next commit, see :hg:`add`.
2801
2801
2802 .. container:: verbose
2802 .. container:: verbose
2803
2803
2804 Examples:
2804 Examples:
2805
2805
2806 - forget newly-added binary files::
2806 - forget newly-added binary files::
2807
2807
2808 hg forget "set:added() and binary()"
2808 hg forget "set:added() and binary()"
2809
2809
2810 - forget files that would be excluded by .hgignore::
2810 - forget files that would be excluded by .hgignore::
2811
2811
2812 hg forget "set:hgignore()"
2812 hg forget "set:hgignore()"
2813
2813
2814 Returns 0 on success.
2814 Returns 0 on success.
2815 """
2815 """
2816
2816
2817 if not pats:
2817 if not pats:
2818 raise util.Abort(_('no files specified'))
2818 raise util.Abort(_('no files specified'))
2819
2819
2820 m = scmutil.match(repo[None], pats, opts)
2820 m = scmutil.match(repo[None], pats, opts)
2821 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2821 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2822 return rejected and 1 or 0
2822 return rejected and 1 or 0
2823
2823
2824 @command(
2824 @command(
2825 'graft',
2825 'graft',
2826 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2826 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2827 ('c', 'continue', False, _('resume interrupted graft')),
2827 ('c', 'continue', False, _('resume interrupted graft')),
2828 ('e', 'edit', False, _('invoke editor on commit messages')),
2828 ('e', 'edit', False, _('invoke editor on commit messages')),
2829 ('', 'log', None, _('append graft info to log message')),
2829 ('', 'log', None, _('append graft info to log message')),
2830 ('D', 'currentdate', False,
2830 ('D', 'currentdate', False,
2831 _('record the current date as commit date')),
2831 _('record the current date as commit date')),
2832 ('U', 'currentuser', False,
2832 ('U', 'currentuser', False,
2833 _('record the current user as committer'), _('DATE'))]
2833 _('record the current user as committer'), _('DATE'))]
2834 + commitopts2 + mergetoolopts + dryrunopts,
2834 + commitopts2 + mergetoolopts + dryrunopts,
2835 _('[OPTION]... [-r] REV...'))
2835 _('[OPTION]... [-r] REV...'))
2836 def graft(ui, repo, *revs, **opts):
2836 def graft(ui, repo, *revs, **opts):
2837 '''copy changes from other branches onto the current branch
2837 '''copy changes from other branches onto the current branch
2838
2838
2839 This command uses Mercurial's merge logic to copy individual
2839 This command uses Mercurial's merge logic to copy individual
2840 changes from other branches without merging branches in the
2840 changes from other branches without merging branches in the
2841 history graph. This is sometimes known as 'backporting' or
2841 history graph. This is sometimes known as 'backporting' or
2842 'cherry-picking'. By default, graft will copy user, date, and
2842 'cherry-picking'. By default, graft will copy user, date, and
2843 description from the source changesets.
2843 description from the source changesets.
2844
2844
2845 Changesets that are ancestors of the current revision, that have
2845 Changesets that are ancestors of the current revision, that have
2846 already been grafted, or that are merges will be skipped.
2846 already been grafted, or that are merges will be skipped.
2847
2847
2848 If --log is specified, log messages will have a comment appended
2848 If --log is specified, log messages will have a comment appended
2849 of the form::
2849 of the form::
2850
2850
2851 (grafted from CHANGESETHASH)
2851 (grafted from CHANGESETHASH)
2852
2852
2853 If a graft merge results in conflicts, the graft process is
2853 If a graft merge results in conflicts, the graft process is
2854 interrupted so that the current merge can be manually resolved.
2854 interrupted so that the current merge can be manually resolved.
2855 Once all conflicts are addressed, the graft process can be
2855 Once all conflicts are addressed, the graft process can be
2856 continued with the -c/--continue option.
2856 continued with the -c/--continue option.
2857
2857
2858 .. note::
2858 .. note::
2859 The -c/--continue option does not reapply earlier options.
2859 The -c/--continue option does not reapply earlier options.
2860
2860
2861 .. container:: verbose
2861 .. container:: verbose
2862
2862
2863 Examples:
2863 Examples:
2864
2864
2865 - copy a single change to the stable branch and edit its description::
2865 - copy a single change to the stable branch and edit its description::
2866
2866
2867 hg update stable
2867 hg update stable
2868 hg graft --edit 9393
2868 hg graft --edit 9393
2869
2869
2870 - graft a range of changesets with one exception, updating dates::
2870 - graft a range of changesets with one exception, updating dates::
2871
2871
2872 hg graft -D "2085::2093 and not 2091"
2872 hg graft -D "2085::2093 and not 2091"
2873
2873
2874 - continue a graft after resolving conflicts::
2874 - continue a graft after resolving conflicts::
2875
2875
2876 hg graft -c
2876 hg graft -c
2877
2877
2878 - show the source of a grafted changeset::
2878 - show the source of a grafted changeset::
2879
2879
2880 hg log --debug -r tip
2880 hg log --debug -r tip
2881
2881
2882 Returns 0 on successful completion.
2882 Returns 0 on successful completion.
2883 '''
2883 '''
2884
2884
2885 revs = list(revs)
2885 revs = list(revs)
2886 revs.extend(opts['rev'])
2886 revs.extend(opts['rev'])
2887
2887
2888 if not opts.get('user') and opts.get('currentuser'):
2888 if not opts.get('user') and opts.get('currentuser'):
2889 opts['user'] = ui.username()
2889 opts['user'] = ui.username()
2890 if not opts.get('date') and opts.get('currentdate'):
2890 if not opts.get('date') and opts.get('currentdate'):
2891 opts['date'] = "%d %d" % util.makedate()
2891 opts['date'] = "%d %d" % util.makedate()
2892
2892
2893 editor = None
2893 editor = None
2894 if opts.get('edit'):
2894 if opts.get('edit'):
2895 editor = cmdutil.commitforceeditor
2895 editor = cmdutil.commitforceeditor
2896
2896
2897 cont = False
2897 cont = False
2898 if opts['continue']:
2898 if opts['continue']:
2899 cont = True
2899 cont = True
2900 if revs:
2900 if revs:
2901 raise util.Abort(_("can't specify --continue and revisions"))
2901 raise util.Abort(_("can't specify --continue and revisions"))
2902 # read in unfinished revisions
2902 # read in unfinished revisions
2903 try:
2903 try:
2904 nodes = repo.opener.read('graftstate').splitlines()
2904 nodes = repo.opener.read('graftstate').splitlines()
2905 revs = [repo[node].rev() for node in nodes]
2905 revs = [repo[node].rev() for node in nodes]
2906 except IOError, inst:
2906 except IOError, inst:
2907 if inst.errno != errno.ENOENT:
2907 if inst.errno != errno.ENOENT:
2908 raise
2908 raise
2909 raise util.Abort(_("no graft state found, can't continue"))
2909 raise util.Abort(_("no graft state found, can't continue"))
2910 else:
2910 else:
2911 cmdutil.bailifchanged(repo)
2911 cmdutil.bailifchanged(repo)
2912 if not revs:
2912 if not revs:
2913 raise util.Abort(_('no revisions specified'))
2913 raise util.Abort(_('no revisions specified'))
2914 revs = scmutil.revrange(repo, revs)
2914 revs = scmutil.revrange(repo, revs)
2915
2915
2916 # check for merges
2916 # check for merges
2917 for rev in repo.revs('%ld and merge()', revs):
2917 for rev in repo.revs('%ld and merge()', revs):
2918 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2918 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2919 revs.remove(rev)
2919 revs.remove(rev)
2920 if not revs:
2920 if not revs:
2921 return -1
2921 return -1
2922
2922
2923 # check for ancestors of dest branch
2923 # check for ancestors of dest branch
2924 crev = repo['.'].rev()
2924 crev = repo['.'].rev()
2925 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2925 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2926 # don't mutate while iterating, create a copy
2926 # don't mutate while iterating, create a copy
2927 for rev in list(revs):
2927 for rev in list(revs):
2928 if rev in ancestors:
2928 if rev in ancestors:
2929 ui.warn(_('skipping ancestor revision %s\n') % rev)
2929 ui.warn(_('skipping ancestor revision %s\n') % rev)
2930 revs.remove(rev)
2930 revs.remove(rev)
2931 if not revs:
2931 if not revs:
2932 return -1
2932 return -1
2933
2933
2934 # analyze revs for earlier grafts
2934 # analyze revs for earlier grafts
2935 ids = {}
2935 ids = {}
2936 for ctx in repo.set("%ld", revs):
2936 for ctx in repo.set("%ld", revs):
2937 ids[ctx.hex()] = ctx.rev()
2937 ids[ctx.hex()] = ctx.rev()
2938 n = ctx.extra().get('source')
2938 n = ctx.extra().get('source')
2939 if n:
2939 if n:
2940 ids[n] = ctx.rev()
2940 ids[n] = ctx.rev()
2941
2941
2942 # check ancestors for earlier grafts
2942 # check ancestors for earlier grafts
2943 ui.debug('scanning for duplicate grafts\n')
2943 ui.debug('scanning for duplicate grafts\n')
2944
2944
2945 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2945 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2946 ctx = repo[rev]
2946 ctx = repo[rev]
2947 n = ctx.extra().get('source')
2947 n = ctx.extra().get('source')
2948 if n in ids:
2948 if n in ids:
2949 r = repo[n].rev()
2949 r = repo[n].rev()
2950 if r in revs:
2950 if r in revs:
2951 ui.warn(_('skipping already grafted revision %s\n') % r)
2951 ui.warn(_('skipping already grafted revision %s\n') % r)
2952 revs.remove(r)
2952 revs.remove(r)
2953 elif ids[n] in revs:
2953 elif ids[n] in revs:
2954 ui.warn(_('skipping already grafted revision %s '
2954 ui.warn(_('skipping already grafted revision %s '
2955 '(same origin %d)\n') % (ids[n], r))
2955 '(same origin %d)\n') % (ids[n], r))
2956 revs.remove(ids[n])
2956 revs.remove(ids[n])
2957 elif ctx.hex() in ids:
2957 elif ctx.hex() in ids:
2958 r = ids[ctx.hex()]
2958 r = ids[ctx.hex()]
2959 ui.warn(_('skipping already grafted revision %s '
2959 ui.warn(_('skipping already grafted revision %s '
2960 '(was grafted from %d)\n') % (r, rev))
2960 '(was grafted from %d)\n') % (r, rev))
2961 revs.remove(r)
2961 revs.remove(r)
2962 if not revs:
2962 if not revs:
2963 return -1
2963 return -1
2964
2964
2965 wlock = repo.wlock()
2965 wlock = repo.wlock()
2966 try:
2966 try:
2967 current = repo['.']
2967 current = repo['.']
2968 for pos, ctx in enumerate(repo.set("%ld", revs)):
2968 for pos, ctx in enumerate(repo.set("%ld", revs)):
2969
2969
2970 ui.status(_('grafting revision %s\n') % ctx.rev())
2970 ui.status(_('grafting revision %s\n') % ctx.rev())
2971 if opts.get('dry_run'):
2971 if opts.get('dry_run'):
2972 continue
2972 continue
2973
2973
2974 source = ctx.extra().get('source')
2974 source = ctx.extra().get('source')
2975 if not source:
2975 if not source:
2976 source = ctx.hex()
2976 source = ctx.hex()
2977 extra = {'source': source}
2977 extra = {'source': source}
2978 user = ctx.user()
2978 user = ctx.user()
2979 if opts.get('user'):
2979 if opts.get('user'):
2980 user = opts['user']
2980 user = opts['user']
2981 date = ctx.date()
2981 date = ctx.date()
2982 if opts.get('date'):
2982 if opts.get('date'):
2983 date = opts['date']
2983 date = opts['date']
2984 message = ctx.description()
2984 message = ctx.description()
2985 if opts.get('log'):
2985 if opts.get('log'):
2986 message += '\n(grafted from %s)' % ctx.hex()
2986 message += '\n(grafted from %s)' % ctx.hex()
2987
2987
2988 # we don't merge the first commit when continuing
2988 # we don't merge the first commit when continuing
2989 if not cont:
2989 if not cont:
2990 # perform the graft merge with p1(rev) as 'ancestor'
2990 # perform the graft merge with p1(rev) as 'ancestor'
2991 try:
2991 try:
2992 # ui.forcemerge is an internal variable, do not document
2992 # ui.forcemerge is an internal variable, do not document
2993 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2993 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2994 stats = mergemod.update(repo, ctx.node(), True, True, False,
2994 stats = mergemod.update(repo, ctx.node(), True, True, False,
2995 ctx.p1().node())
2995 ctx.p1().node())
2996 finally:
2996 finally:
2997 repo.ui.setconfig('ui', 'forcemerge', '')
2997 repo.ui.setconfig('ui', 'forcemerge', '')
2998 # report any conflicts
2998 # report any conflicts
2999 if stats and stats[3] > 0:
2999 if stats and stats[3] > 0:
3000 # write out state for --continue
3000 # write out state for --continue
3001 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3001 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3002 repo.opener.write('graftstate', ''.join(nodelines))
3002 repo.opener.write('graftstate', ''.join(nodelines))
3003 raise util.Abort(
3003 raise util.Abort(
3004 _("unresolved conflicts, can't continue"),
3004 _("unresolved conflicts, can't continue"),
3005 hint=_('use hg resolve and hg graft --continue'))
3005 hint=_('use hg resolve and hg graft --continue'))
3006 else:
3006 else:
3007 cont = False
3007 cont = False
3008
3008
3009 # drop the second merge parent
3009 # drop the second merge parent
3010 repo.setparents(current.node(), nullid)
3010 repo.setparents(current.node(), nullid)
3011 repo.dirstate.write()
3011 repo.dirstate.write()
3012 # fix up dirstate for copies and renames
3012 # fix up dirstate for copies and renames
3013 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3013 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3014
3014
3015 # commit
3015 # commit
3016 node = repo.commit(text=message, user=user,
3016 node = repo.commit(text=message, user=user,
3017 date=date, extra=extra, editor=editor)
3017 date=date, extra=extra, editor=editor)
3018 if node is None:
3018 if node is None:
3019 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3019 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3020 else:
3020 else:
3021 current = repo[node]
3021 current = repo[node]
3022 finally:
3022 finally:
3023 wlock.release()
3023 wlock.release()
3024
3024
3025 # remove state when we complete successfully
3025 # remove state when we complete successfully
3026 if not opts.get('dry_run'):
3026 if not opts.get('dry_run'):
3027 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3027 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3028
3028
3029 return 0
3029 return 0
3030
3030
3031 @command('grep',
3031 @command('grep',
3032 [('0', 'print0', None, _('end fields with NUL')),
3032 [('0', 'print0', None, _('end fields with NUL')),
3033 ('', 'all', None, _('print all revisions that match')),
3033 ('', 'all', None, _('print all revisions that match')),
3034 ('a', 'text', None, _('treat all files as text')),
3034 ('a', 'text', None, _('treat all files as text')),
3035 ('f', 'follow', None,
3035 ('f', 'follow', None,
3036 _('follow changeset history,'
3036 _('follow changeset history,'
3037 ' or file history across copies and renames')),
3037 ' or file history across copies and renames')),
3038 ('i', 'ignore-case', None, _('ignore case when matching')),
3038 ('i', 'ignore-case', None, _('ignore case when matching')),
3039 ('l', 'files-with-matches', None,
3039 ('l', 'files-with-matches', None,
3040 _('print only filenames and revisions that match')),
3040 _('print only filenames and revisions that match')),
3041 ('n', 'line-number', None, _('print matching line numbers')),
3041 ('n', 'line-number', None, _('print matching line numbers')),
3042 ('r', 'rev', [],
3042 ('r', 'rev', [],
3043 _('only search files changed within revision range'), _('REV')),
3043 _('only search files changed within revision range'), _('REV')),
3044 ('u', 'user', None, _('list the author (long with -v)')),
3044 ('u', 'user', None, _('list the author (long with -v)')),
3045 ('d', 'date', None, _('list the date (short with -q)')),
3045 ('d', 'date', None, _('list the date (short with -q)')),
3046 ] + walkopts,
3046 ] + walkopts,
3047 _('[OPTION]... PATTERN [FILE]...'))
3047 _('[OPTION]... PATTERN [FILE]...'))
3048 def grep(ui, repo, pattern, *pats, **opts):
3048 def grep(ui, repo, pattern, *pats, **opts):
3049 """search for a pattern in specified files and revisions
3049 """search for a pattern in specified files and revisions
3050
3050
3051 Search revisions of files for a regular expression.
3051 Search revisions of files for a regular expression.
3052
3052
3053 This command behaves differently than Unix grep. It only accepts
3053 This command behaves differently than Unix grep. It only accepts
3054 Python/Perl regexps. It searches repository history, not the
3054 Python/Perl regexps. It searches repository history, not the
3055 working directory. It always prints the revision number in which a
3055 working directory. It always prints the revision number in which a
3056 match appears.
3056 match appears.
3057
3057
3058 By default, grep only prints output for the first revision of a
3058 By default, grep only prints output for the first revision of a
3059 file in which it finds a match. To get it to print every revision
3059 file in which it finds a match. To get it to print every revision
3060 that contains a change in match status ("-" for a match that
3060 that contains a change in match status ("-" for a match that
3061 becomes a non-match, or "+" for a non-match that becomes a match),
3061 becomes a non-match, or "+" for a non-match that becomes a match),
3062 use the --all flag.
3062 use the --all flag.
3063
3063
3064 Returns 0 if a match is found, 1 otherwise.
3064 Returns 0 if a match is found, 1 otherwise.
3065 """
3065 """
3066 reflags = re.M
3066 reflags = re.M
3067 if opts.get('ignore_case'):
3067 if opts.get('ignore_case'):
3068 reflags |= re.I
3068 reflags |= re.I
3069 try:
3069 try:
3070 regexp = util.compilere(pattern, reflags)
3070 regexp = util.compilere(pattern, reflags)
3071 except re.error, inst:
3071 except re.error, inst:
3072 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3072 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3073 return 1
3073 return 1
3074 sep, eol = ':', '\n'
3074 sep, eol = ':', '\n'
3075 if opts.get('print0'):
3075 if opts.get('print0'):
3076 sep = eol = '\0'
3076 sep = eol = '\0'
3077
3077
3078 getfile = util.lrucachefunc(repo.file)
3078 getfile = util.lrucachefunc(repo.file)
3079
3079
3080 def matchlines(body):
3080 def matchlines(body):
3081 begin = 0
3081 begin = 0
3082 linenum = 0
3082 linenum = 0
3083 while begin < len(body):
3083 while begin < len(body):
3084 match = regexp.search(body, begin)
3084 match = regexp.search(body, begin)
3085 if not match:
3085 if not match:
3086 break
3086 break
3087 mstart, mend = match.span()
3087 mstart, mend = match.span()
3088 linenum += body.count('\n', begin, mstart) + 1
3088 linenum += body.count('\n', begin, mstart) + 1
3089 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3089 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3090 begin = body.find('\n', mend) + 1 or len(body) + 1
3090 begin = body.find('\n', mend) + 1 or len(body) + 1
3091 lend = begin - 1
3091 lend = begin - 1
3092 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3092 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3093
3093
3094 class linestate(object):
3094 class linestate(object):
3095 def __init__(self, line, linenum, colstart, colend):
3095 def __init__(self, line, linenum, colstart, colend):
3096 self.line = line
3096 self.line = line
3097 self.linenum = linenum
3097 self.linenum = linenum
3098 self.colstart = colstart
3098 self.colstart = colstart
3099 self.colend = colend
3099 self.colend = colend
3100
3100
3101 def __hash__(self):
3101 def __hash__(self):
3102 return hash((self.linenum, self.line))
3102 return hash((self.linenum, self.line))
3103
3103
3104 def __eq__(self, other):
3104 def __eq__(self, other):
3105 return self.line == other.line
3105 return self.line == other.line
3106
3106
3107 matches = {}
3107 matches = {}
3108 copies = {}
3108 copies = {}
3109 def grepbody(fn, rev, body):
3109 def grepbody(fn, rev, body):
3110 matches[rev].setdefault(fn, [])
3110 matches[rev].setdefault(fn, [])
3111 m = matches[rev][fn]
3111 m = matches[rev][fn]
3112 for lnum, cstart, cend, line in matchlines(body):
3112 for lnum, cstart, cend, line in matchlines(body):
3113 s = linestate(line, lnum, cstart, cend)
3113 s = linestate(line, lnum, cstart, cend)
3114 m.append(s)
3114 m.append(s)
3115
3115
3116 def difflinestates(a, b):
3116 def difflinestates(a, b):
3117 sm = difflib.SequenceMatcher(None, a, b)
3117 sm = difflib.SequenceMatcher(None, a, b)
3118 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3118 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3119 if tag == 'insert':
3119 if tag == 'insert':
3120 for i in xrange(blo, bhi):
3120 for i in xrange(blo, bhi):
3121 yield ('+', b[i])
3121 yield ('+', b[i])
3122 elif tag == 'delete':
3122 elif tag == 'delete':
3123 for i in xrange(alo, ahi):
3123 for i in xrange(alo, ahi):
3124 yield ('-', a[i])
3124 yield ('-', a[i])
3125 elif tag == 'replace':
3125 elif tag == 'replace':
3126 for i in xrange(alo, ahi):
3126 for i in xrange(alo, ahi):
3127 yield ('-', a[i])
3127 yield ('-', a[i])
3128 for i in xrange(blo, bhi):
3128 for i in xrange(blo, bhi):
3129 yield ('+', b[i])
3129 yield ('+', b[i])
3130
3130
3131 def display(fn, ctx, pstates, states):
3131 def display(fn, ctx, pstates, states):
3132 rev = ctx.rev()
3132 rev = ctx.rev()
3133 datefunc = ui.quiet and util.shortdate or util.datestr
3133 datefunc = ui.quiet and util.shortdate or util.datestr
3134 found = False
3134 found = False
3135 filerevmatches = {}
3135 filerevmatches = {}
3136 def binary():
3136 def binary():
3137 flog = getfile(fn)
3137 flog = getfile(fn)
3138 return util.binary(flog.read(ctx.filenode(fn)))
3138 return util.binary(flog.read(ctx.filenode(fn)))
3139
3139
3140 if opts.get('all'):
3140 if opts.get('all'):
3141 iter = difflinestates(pstates, states)
3141 iter = difflinestates(pstates, states)
3142 else:
3142 else:
3143 iter = [('', l) for l in states]
3143 iter = [('', l) for l in states]
3144 for change, l in iter:
3144 for change, l in iter:
3145 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3145 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3146 before, match, after = None, None, None
3146 before, match, after = None, None, None
3147
3147
3148 if opts.get('line_number'):
3148 if opts.get('line_number'):
3149 cols.append((str(l.linenum), 'grep.linenumber'))
3149 cols.append((str(l.linenum), 'grep.linenumber'))
3150 if opts.get('all'):
3150 if opts.get('all'):
3151 cols.append((change, 'grep.change'))
3151 cols.append((change, 'grep.change'))
3152 if opts.get('user'):
3152 if opts.get('user'):
3153 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3153 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3154 if opts.get('date'):
3154 if opts.get('date'):
3155 cols.append((datefunc(ctx.date()), 'grep.date'))
3155 cols.append((datefunc(ctx.date()), 'grep.date'))
3156 if opts.get('files_with_matches'):
3156 if opts.get('files_with_matches'):
3157 c = (fn, rev)
3157 c = (fn, rev)
3158 if c in filerevmatches:
3158 if c in filerevmatches:
3159 continue
3159 continue
3160 filerevmatches[c] = 1
3160 filerevmatches[c] = 1
3161 else:
3161 else:
3162 before = l.line[:l.colstart]
3162 before = l.line[:l.colstart]
3163 match = l.line[l.colstart:l.colend]
3163 match = l.line[l.colstart:l.colend]
3164 after = l.line[l.colend:]
3164 after = l.line[l.colend:]
3165 for col, label in cols[:-1]:
3165 for col, label in cols[:-1]:
3166 ui.write(col, label=label)
3166 ui.write(col, label=label)
3167 ui.write(sep, label='grep.sep')
3167 ui.write(sep, label='grep.sep')
3168 ui.write(cols[-1][0], label=cols[-1][1])
3168 ui.write(cols[-1][0], label=cols[-1][1])
3169 if before is not None:
3169 if before is not None:
3170 ui.write(sep, label='grep.sep')
3170 ui.write(sep, label='grep.sep')
3171 if not opts.get('text') and binary():
3171 if not opts.get('text') and binary():
3172 ui.write(" Binary file matches")
3172 ui.write(" Binary file matches")
3173 else:
3173 else:
3174 ui.write(before)
3174 ui.write(before)
3175 ui.write(match, label='grep.match')
3175 ui.write(match, label='grep.match')
3176 ui.write(after)
3176 ui.write(after)
3177 ui.write(eol)
3177 ui.write(eol)
3178 found = True
3178 found = True
3179 return found
3179 return found
3180
3180
3181 skip = {}
3181 skip = {}
3182 revfiles = {}
3182 revfiles = {}
3183 matchfn = scmutil.match(repo[None], pats, opts)
3183 matchfn = scmutil.match(repo[None], pats, opts)
3184 found = False
3184 found = False
3185 follow = opts.get('follow')
3185 follow = opts.get('follow')
3186
3186
3187 def prep(ctx, fns):
3187 def prep(ctx, fns):
3188 rev = ctx.rev()
3188 rev = ctx.rev()
3189 pctx = ctx.p1()
3189 pctx = ctx.p1()
3190 parent = pctx.rev()
3190 parent = pctx.rev()
3191 matches.setdefault(rev, {})
3191 matches.setdefault(rev, {})
3192 matches.setdefault(parent, {})
3192 matches.setdefault(parent, {})
3193 files = revfiles.setdefault(rev, [])
3193 files = revfiles.setdefault(rev, [])
3194 for fn in fns:
3194 for fn in fns:
3195 flog = getfile(fn)
3195 flog = getfile(fn)
3196 try:
3196 try:
3197 fnode = ctx.filenode(fn)
3197 fnode = ctx.filenode(fn)
3198 except error.LookupError:
3198 except error.LookupError:
3199 continue
3199 continue
3200
3200
3201 copied = flog.renamed(fnode)
3201 copied = flog.renamed(fnode)
3202 copy = follow and copied and copied[0]
3202 copy = follow and copied and copied[0]
3203 if copy:
3203 if copy:
3204 copies.setdefault(rev, {})[fn] = copy
3204 copies.setdefault(rev, {})[fn] = copy
3205 if fn in skip:
3205 if fn in skip:
3206 if copy:
3206 if copy:
3207 skip[copy] = True
3207 skip[copy] = True
3208 continue
3208 continue
3209 files.append(fn)
3209 files.append(fn)
3210
3210
3211 if fn not in matches[rev]:
3211 if fn not in matches[rev]:
3212 grepbody(fn, rev, flog.read(fnode))
3212 grepbody(fn, rev, flog.read(fnode))
3213
3213
3214 pfn = copy or fn
3214 pfn = copy or fn
3215 if pfn not in matches[parent]:
3215 if pfn not in matches[parent]:
3216 try:
3216 try:
3217 fnode = pctx.filenode(pfn)
3217 fnode = pctx.filenode(pfn)
3218 grepbody(pfn, parent, flog.read(fnode))
3218 grepbody(pfn, parent, flog.read(fnode))
3219 except error.LookupError:
3219 except error.LookupError:
3220 pass
3220 pass
3221
3221
3222 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3222 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3223 rev = ctx.rev()
3223 rev = ctx.rev()
3224 parent = ctx.p1().rev()
3224 parent = ctx.p1().rev()
3225 for fn in sorted(revfiles.get(rev, [])):
3225 for fn in sorted(revfiles.get(rev, [])):
3226 states = matches[rev][fn]
3226 states = matches[rev][fn]
3227 copy = copies.get(rev, {}).get(fn)
3227 copy = copies.get(rev, {}).get(fn)
3228 if fn in skip:
3228 if fn in skip:
3229 if copy:
3229 if copy:
3230 skip[copy] = True
3230 skip[copy] = True
3231 continue
3231 continue
3232 pstates = matches.get(parent, {}).get(copy or fn, [])
3232 pstates = matches.get(parent, {}).get(copy or fn, [])
3233 if pstates or states:
3233 if pstates or states:
3234 r = display(fn, ctx, pstates, states)
3234 r = display(fn, ctx, pstates, states)
3235 found = found or r
3235 found = found or r
3236 if r and not opts.get('all'):
3236 if r and not opts.get('all'):
3237 skip[fn] = True
3237 skip[fn] = True
3238 if copy:
3238 if copy:
3239 skip[copy] = True
3239 skip[copy] = True
3240 del matches[rev]
3240 del matches[rev]
3241 del revfiles[rev]
3241 del revfiles[rev]
3242
3242
3243 return not found
3243 return not found
3244
3244
3245 @command('heads',
3245 @command('heads',
3246 [('r', 'rev', '',
3246 [('r', 'rev', '',
3247 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3247 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3248 ('t', 'topo', False, _('show topological heads only')),
3248 ('t', 'topo', False, _('show topological heads only')),
3249 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3249 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3250 ('c', 'closed', False, _('show normal and closed branch heads')),
3250 ('c', 'closed', False, _('show normal and closed branch heads')),
3251 ] + templateopts,
3251 ] + templateopts,
3252 _('[-ct] [-r STARTREV] [REV]...'))
3252 _('[-ct] [-r STARTREV] [REV]...'))
3253 def heads(ui, repo, *branchrevs, **opts):
3253 def heads(ui, repo, *branchrevs, **opts):
3254 """show current repository heads or show branch heads
3254 """show current repository heads or show branch heads
3255
3255
3256 With no arguments, show all repository branch heads.
3256 With no arguments, show all repository branch heads.
3257
3257
3258 Repository "heads" are changesets with no child changesets. They are
3258 Repository "heads" are changesets with no child changesets. They are
3259 where development generally takes place and are the usual targets
3259 where development generally takes place and are the usual targets
3260 for update and merge operations. Branch heads are changesets that have
3260 for update and merge operations. Branch heads are changesets that have
3261 no child changeset on the same branch.
3261 no child changeset on the same branch.
3262
3262
3263 If one or more REVs are given, only branch heads on the branches
3263 If one or more REVs are given, only branch heads on the branches
3264 associated with the specified changesets are shown. This means
3264 associated with the specified changesets are shown. This means
3265 that you can use :hg:`heads foo` to see the heads on a branch
3265 that you can use :hg:`heads foo` to see the heads on a branch
3266 named ``foo``.
3266 named ``foo``.
3267
3267
3268 If -c/--closed is specified, also show branch heads marked closed
3268 If -c/--closed is specified, also show branch heads marked closed
3269 (see :hg:`commit --close-branch`).
3269 (see :hg:`commit --close-branch`).
3270
3270
3271 If STARTREV is specified, only those heads that are descendants of
3271 If STARTREV is specified, only those heads that are descendants of
3272 STARTREV will be displayed.
3272 STARTREV will be displayed.
3273
3273
3274 If -t/--topo is specified, named branch mechanics will be ignored and only
3274 If -t/--topo is specified, named branch mechanics will be ignored and only
3275 changesets without children will be shown.
3275 changesets without children will be shown.
3276
3276
3277 Returns 0 if matching heads are found, 1 if not.
3277 Returns 0 if matching heads are found, 1 if not.
3278 """
3278 """
3279
3279
3280 start = None
3280 start = None
3281 if 'rev' in opts:
3281 if 'rev' in opts:
3282 start = scmutil.revsingle(repo, opts['rev'], None).node()
3282 start = scmutil.revsingle(repo, opts['rev'], None).node()
3283
3283
3284 if opts.get('topo'):
3284 if opts.get('topo'):
3285 heads = [repo[h] for h in repo.heads(start)]
3285 heads = [repo[h] for h in repo.heads(start)]
3286 else:
3286 else:
3287 heads = []
3287 heads = []
3288 for branch in repo.branchmap():
3288 for branch in repo.branchmap():
3289 heads += repo.branchheads(branch, start, opts.get('closed'))
3289 heads += repo.branchheads(branch, start, opts.get('closed'))
3290 heads = [repo[h] for h in heads]
3290 heads = [repo[h] for h in heads]
3291
3291
3292 if branchrevs:
3292 if branchrevs:
3293 branches = set(repo[br].branch() for br in branchrevs)
3293 branches = set(repo[br].branch() for br in branchrevs)
3294 heads = [h for h in heads if h.branch() in branches]
3294 heads = [h for h in heads if h.branch() in branches]
3295
3295
3296 if opts.get('active') and branchrevs:
3296 if opts.get('active') and branchrevs:
3297 dagheads = repo.heads(start)
3297 dagheads = repo.heads(start)
3298 heads = [h for h in heads if h.node() in dagheads]
3298 heads = [h for h in heads if h.node() in dagheads]
3299
3299
3300 if branchrevs:
3300 if branchrevs:
3301 haveheads = set(h.branch() for h in heads)
3301 haveheads = set(h.branch() for h in heads)
3302 if branches - haveheads:
3302 if branches - haveheads:
3303 headless = ', '.join(b for b in branches - haveheads)
3303 headless = ', '.join(b for b in branches - haveheads)
3304 msg = _('no open branch heads found on branches %s')
3304 msg = _('no open branch heads found on branches %s')
3305 if opts.get('rev'):
3305 if opts.get('rev'):
3306 msg += _(' (started at %s)') % opts['rev']
3306 msg += _(' (started at %s)') % opts['rev']
3307 ui.warn((msg + '\n') % headless)
3307 ui.warn((msg + '\n') % headless)
3308
3308
3309 if not heads:
3309 if not heads:
3310 return 1
3310 return 1
3311
3311
3312 heads = sorted(heads, key=lambda x: -x.rev())
3312 heads = sorted(heads, key=lambda x: -x.rev())
3313 displayer = cmdutil.show_changeset(ui, repo, opts)
3313 displayer = cmdutil.show_changeset(ui, repo, opts)
3314 for ctx in heads:
3314 for ctx in heads:
3315 displayer.show(ctx)
3315 displayer.show(ctx)
3316 displayer.close()
3316 displayer.close()
3317
3317
3318 @command('help',
3318 @command('help',
3319 [('e', 'extension', None, _('show only help for extensions')),
3319 [('e', 'extension', None, _('show only help for extensions')),
3320 ('c', 'command', None, _('show only help for commands')),
3320 ('c', 'command', None, _('show only help for commands')),
3321 ('k', 'keyword', '', _('show topics matching keyword')),
3321 ('k', 'keyword', '', _('show topics matching keyword')),
3322 ],
3322 ],
3323 _('[-ec] [TOPIC]'))
3323 _('[-ec] [TOPIC]'))
3324 def help_(ui, name=None, **opts):
3324 def help_(ui, name=None, **opts):
3325 """show help for a given topic or a help overview
3325 """show help for a given topic or a help overview
3326
3326
3327 With no arguments, print a list of commands with short help messages.
3327 With no arguments, print a list of commands with short help messages.
3328
3328
3329 Given a topic, extension, or command name, print help for that
3329 Given a topic, extension, or command name, print help for that
3330 topic.
3330 topic.
3331
3331
3332 Returns 0 if successful.
3332 Returns 0 if successful.
3333 """
3333 """
3334
3334
3335 textwidth = min(ui.termwidth(), 80) - 2
3335 textwidth = min(ui.termwidth(), 80) - 2
3336
3336
3337 keep = ui.verbose and ['verbose'] or []
3337 keep = ui.verbose and ['verbose'] or []
3338 text = help.help_(ui, name, **opts)
3338 text = help.help_(ui, name, **opts)
3339
3339
3340 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3340 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3341 if 'verbose' in pruned:
3341 if 'verbose' in pruned:
3342 keep.append('omitted')
3342 keep.append('omitted')
3343 else:
3343 else:
3344 keep.append('notomitted')
3344 keep.append('notomitted')
3345 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3345 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3346 ui.write(formatted)
3346 ui.write(formatted)
3347
3347
3348
3348
3349 @command('identify|id',
3349 @command('identify|id',
3350 [('r', 'rev', '',
3350 [('r', 'rev', '',
3351 _('identify the specified revision'), _('REV')),
3351 _('identify the specified revision'), _('REV')),
3352 ('n', 'num', None, _('show local revision number')),
3352 ('n', 'num', None, _('show local revision number')),
3353 ('i', 'id', None, _('show global revision id')),
3353 ('i', 'id', None, _('show global revision id')),
3354 ('b', 'branch', None, _('show branch')),
3354 ('b', 'branch', None, _('show branch')),
3355 ('t', 'tags', None, _('show tags')),
3355 ('t', 'tags', None, _('show tags')),
3356 ('B', 'bookmarks', None, _('show bookmarks')),
3356 ('B', 'bookmarks', None, _('show bookmarks')),
3357 ] + remoteopts,
3357 ] + remoteopts,
3358 _('[-nibtB] [-r REV] [SOURCE]'))
3358 _('[-nibtB] [-r REV] [SOURCE]'))
3359 def identify(ui, repo, source=None, rev=None,
3359 def identify(ui, repo, source=None, rev=None,
3360 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3360 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3361 """identify the working copy or specified revision
3361 """identify the working copy or specified revision
3362
3362
3363 Print a summary identifying the repository state at REV using one or
3363 Print a summary identifying the repository state at REV using one or
3364 two parent hash identifiers, followed by a "+" if the working
3364 two parent hash identifiers, followed by a "+" if the working
3365 directory has uncommitted changes, the branch name (if not default),
3365 directory has uncommitted changes, the branch name (if not default),
3366 a list of tags, and a list of bookmarks.
3366 a list of tags, and a list of bookmarks.
3367
3367
3368 When REV is not given, print a summary of the current state of the
3368 When REV is not given, print a summary of the current state of the
3369 repository.
3369 repository.
3370
3370
3371 Specifying a path to a repository root or Mercurial bundle will
3371 Specifying a path to a repository root or Mercurial bundle will
3372 cause lookup to operate on that repository/bundle.
3372 cause lookup to operate on that repository/bundle.
3373
3373
3374 .. container:: verbose
3374 .. container:: verbose
3375
3375
3376 Examples:
3376 Examples:
3377
3377
3378 - generate a build identifier for the working directory::
3378 - generate a build identifier for the working directory::
3379
3379
3380 hg id --id > build-id.dat
3380 hg id --id > build-id.dat
3381
3381
3382 - find the revision corresponding to a tag::
3382 - find the revision corresponding to a tag::
3383
3383
3384 hg id -n -r 1.3
3384 hg id -n -r 1.3
3385
3385
3386 - check the most recent revision of a remote repository::
3386 - check the most recent revision of a remote repository::
3387
3387
3388 hg id -r tip http://selenic.com/hg/
3388 hg id -r tip http://selenic.com/hg/
3389
3389
3390 Returns 0 if successful.
3390 Returns 0 if successful.
3391 """
3391 """
3392
3392
3393 if not repo and not source:
3393 if not repo and not source:
3394 raise util.Abort(_("there is no Mercurial repository here "
3394 raise util.Abort(_("there is no Mercurial repository here "
3395 "(.hg not found)"))
3395 "(.hg not found)"))
3396
3396
3397 hexfunc = ui.debugflag and hex or short
3397 hexfunc = ui.debugflag and hex or short
3398 default = not (num or id or branch or tags or bookmarks)
3398 default = not (num or id or branch or tags or bookmarks)
3399 output = []
3399 output = []
3400 revs = []
3400 revs = []
3401
3401
3402 if source:
3402 if source:
3403 source, branches = hg.parseurl(ui.expandpath(source))
3403 source, branches = hg.parseurl(ui.expandpath(source))
3404 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3404 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3405 repo = peer.local()
3405 repo = peer.local()
3406 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3406 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3407
3407
3408 if not repo:
3408 if not repo:
3409 if num or branch or tags:
3409 if num or branch or tags:
3410 raise util.Abort(
3410 raise util.Abort(
3411 _("can't query remote revision number, branch, or tags"))
3411 _("can't query remote revision number, branch, or tags"))
3412 if not rev and revs:
3412 if not rev and revs:
3413 rev = revs[0]
3413 rev = revs[0]
3414 if not rev:
3414 if not rev:
3415 rev = "tip"
3415 rev = "tip"
3416
3416
3417 remoterev = peer.lookup(rev)
3417 remoterev = peer.lookup(rev)
3418 if default or id:
3418 if default or id:
3419 output = [hexfunc(remoterev)]
3419 output = [hexfunc(remoterev)]
3420
3420
3421 def getbms():
3421 def getbms():
3422 bms = []
3422 bms = []
3423
3423
3424 if 'bookmarks' in peer.listkeys('namespaces'):
3424 if 'bookmarks' in peer.listkeys('namespaces'):
3425 hexremoterev = hex(remoterev)
3425 hexremoterev = hex(remoterev)
3426 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3426 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3427 if bmr == hexremoterev]
3427 if bmr == hexremoterev]
3428
3428
3429 return sorted(bms)
3429 return sorted(bms)
3430
3430
3431 if bookmarks:
3431 if bookmarks:
3432 output.extend(getbms())
3432 output.extend(getbms())
3433 elif default and not ui.quiet:
3433 elif default and not ui.quiet:
3434 # multiple bookmarks for a single parent separated by '/'
3434 # multiple bookmarks for a single parent separated by '/'
3435 bm = '/'.join(getbms())
3435 bm = '/'.join(getbms())
3436 if bm:
3436 if bm:
3437 output.append(bm)
3437 output.append(bm)
3438 else:
3438 else:
3439 if not rev:
3439 if not rev:
3440 ctx = repo[None]
3440 ctx = repo[None]
3441 parents = ctx.parents()
3441 parents = ctx.parents()
3442 changed = ""
3442 changed = ""
3443 if default or id or num:
3443 if default or id or num:
3444 if (util.any(repo.status())
3444 if (util.any(repo.status())
3445 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3445 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3446 changed = '+'
3446 changed = '+'
3447 if default or id:
3447 if default or id:
3448 output = ["%s%s" %
3448 output = ["%s%s" %
3449 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3449 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3450 if num:
3450 if num:
3451 output.append("%s%s" %
3451 output.append("%s%s" %
3452 ('+'.join([str(p.rev()) for p in parents]), changed))
3452 ('+'.join([str(p.rev()) for p in parents]), changed))
3453 else:
3453 else:
3454 ctx = scmutil.revsingle(repo, rev)
3454 ctx = scmutil.revsingle(repo, rev)
3455 if default or id:
3455 if default or id:
3456 output = [hexfunc(ctx.node())]
3456 output = [hexfunc(ctx.node())]
3457 if num:
3457 if num:
3458 output.append(str(ctx.rev()))
3458 output.append(str(ctx.rev()))
3459
3459
3460 if default and not ui.quiet:
3460 if default and not ui.quiet:
3461 b = ctx.branch()
3461 b = ctx.branch()
3462 if b != 'default':
3462 if b != 'default':
3463 output.append("(%s)" % b)
3463 output.append("(%s)" % b)
3464
3464
3465 # multiple tags for a single parent separated by '/'
3465 # multiple tags for a single parent separated by '/'
3466 t = '/'.join(ctx.tags())
3466 t = '/'.join(ctx.tags())
3467 if t:
3467 if t:
3468 output.append(t)
3468 output.append(t)
3469
3469
3470 # multiple bookmarks for a single parent separated by '/'
3470 # multiple bookmarks for a single parent separated by '/'
3471 bm = '/'.join(ctx.bookmarks())
3471 bm = '/'.join(ctx.bookmarks())
3472 if bm:
3472 if bm:
3473 output.append(bm)
3473 output.append(bm)
3474 else:
3474 else:
3475 if branch:
3475 if branch:
3476 output.append(ctx.branch())
3476 output.append(ctx.branch())
3477
3477
3478 if tags:
3478 if tags:
3479 output.extend(ctx.tags())
3479 output.extend(ctx.tags())
3480
3480
3481 if bookmarks:
3481 if bookmarks:
3482 output.extend(ctx.bookmarks())
3482 output.extend(ctx.bookmarks())
3483
3483
3484 ui.write("%s\n" % ' '.join(output))
3484 ui.write("%s\n" % ' '.join(output))
3485
3485
3486 @command('import|patch',
3486 @command('import|patch',
3487 [('p', 'strip', 1,
3487 [('p', 'strip', 1,
3488 _('directory strip option for patch. This has the same '
3488 _('directory strip option for patch. This has the same '
3489 'meaning as the corresponding patch option'), _('NUM')),
3489 'meaning as the corresponding patch option'), _('NUM')),
3490 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3490 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3491 ('e', 'edit', False, _('invoke editor on commit messages')),
3491 ('e', 'edit', False, _('invoke editor on commit messages')),
3492 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3492 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3493 ('', 'no-commit', None,
3493 ('', 'no-commit', None,
3494 _("don't commit, just update the working directory")),
3494 _("don't commit, just update the working directory")),
3495 ('', 'bypass', None,
3495 ('', 'bypass', None,
3496 _("apply patch without touching the working directory")),
3496 _("apply patch without touching the working directory")),
3497 ('', 'exact', None,
3497 ('', 'exact', None,
3498 _('apply patch to the nodes from which it was generated')),
3498 _('apply patch to the nodes from which it was generated')),
3499 ('', 'import-branch', None,
3499 ('', 'import-branch', None,
3500 _('use any branch information in patch (implied by --exact)'))] +
3500 _('use any branch information in patch (implied by --exact)'))] +
3501 commitopts + commitopts2 + similarityopts,
3501 commitopts + commitopts2 + similarityopts,
3502 _('[OPTION]... PATCH...'))
3502 _('[OPTION]... PATCH...'))
3503 def import_(ui, repo, patch1=None, *patches, **opts):
3503 def import_(ui, repo, patch1=None, *patches, **opts):
3504 """import an ordered set of patches
3504 """import an ordered set of patches
3505
3505
3506 Import a list of patches and commit them individually (unless
3506 Import a list of patches and commit them individually (unless
3507 --no-commit is specified).
3507 --no-commit is specified).
3508
3508
3509 If there are outstanding changes in the working directory, import
3509 If there are outstanding changes in the working directory, import
3510 will abort unless given the -f/--force flag.
3510 will abort unless given the -f/--force flag.
3511
3511
3512 You can import a patch straight from a mail message. Even patches
3512 You can import a patch straight from a mail message. Even patches
3513 as attachments work (to use the body part, it must have type
3513 as attachments work (to use the body part, it must have type
3514 text/plain or text/x-patch). From and Subject headers of email
3514 text/plain or text/x-patch). From and Subject headers of email
3515 message are used as default committer and commit message. All
3515 message are used as default committer and commit message. All
3516 text/plain body parts before first diff are added to commit
3516 text/plain body parts before first diff are added to commit
3517 message.
3517 message.
3518
3518
3519 If the imported patch was generated by :hg:`export`, user and
3519 If the imported patch was generated by :hg:`export`, user and
3520 description from patch override values from message headers and
3520 description from patch override values from message headers and
3521 body. Values given on command line with -m/--message and -u/--user
3521 body. Values given on command line with -m/--message and -u/--user
3522 override these.
3522 override these.
3523
3523
3524 If --exact is specified, import will set the working directory to
3524 If --exact is specified, import will set the working directory to
3525 the parent of each patch before applying it, and will abort if the
3525 the parent of each patch before applying it, and will abort if the
3526 resulting changeset has a different ID than the one recorded in
3526 resulting changeset has a different ID than the one recorded in
3527 the patch. This may happen due to character set problems or other
3527 the patch. This may happen due to character set problems or other
3528 deficiencies in the text patch format.
3528 deficiencies in the text patch format.
3529
3529
3530 Use --bypass to apply and commit patches directly to the
3530 Use --bypass to apply and commit patches directly to the
3531 repository, not touching the working directory. Without --exact,
3531 repository, not touching the working directory. Without --exact,
3532 patches will be applied on top of the working directory parent
3532 patches will be applied on top of the working directory parent
3533 revision.
3533 revision.
3534
3534
3535 With -s/--similarity, hg will attempt to discover renames and
3535 With -s/--similarity, hg will attempt to discover renames and
3536 copies in the patch in the same way as :hg:`addremove`.
3536 copies in the patch in the same way as :hg:`addremove`.
3537
3537
3538 To read a patch from standard input, use "-" as the patch name. If
3538 To read a patch from standard input, use "-" as the patch name. If
3539 a URL is specified, the patch will be downloaded from it.
3539 a URL is specified, the patch will be downloaded from it.
3540 See :hg:`help dates` for a list of formats valid for -d/--date.
3540 See :hg:`help dates` for a list of formats valid for -d/--date.
3541
3541
3542 .. container:: verbose
3542 .. container:: verbose
3543
3543
3544 Examples:
3544 Examples:
3545
3545
3546 - import a traditional patch from a website and detect renames::
3546 - import a traditional patch from a website and detect renames::
3547
3547
3548 hg import -s 80 http://example.com/bugfix.patch
3548 hg import -s 80 http://example.com/bugfix.patch
3549
3549
3550 - import a changeset from an hgweb server::
3550 - import a changeset from an hgweb server::
3551
3551
3552 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3552 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3553
3553
3554 - import all the patches in an Unix-style mbox::
3554 - import all the patches in an Unix-style mbox::
3555
3555
3556 hg import incoming-patches.mbox
3556 hg import incoming-patches.mbox
3557
3557
3558 - attempt to exactly restore an exported changeset (not always
3558 - attempt to exactly restore an exported changeset (not always
3559 possible)::
3559 possible)::
3560
3560
3561 hg import --exact proposed-fix.patch
3561 hg import --exact proposed-fix.patch
3562
3562
3563 Returns 0 on success.
3563 Returns 0 on success.
3564 """
3564 """
3565
3565
3566 if not patch1:
3566 if not patch1:
3567 raise util.Abort(_('need at least one patch to import'))
3567 raise util.Abort(_('need at least one patch to import'))
3568
3568
3569 patches = (patch1,) + patches
3569 patches = (patch1,) + patches
3570
3570
3571 date = opts.get('date')
3571 date = opts.get('date')
3572 if date:
3572 if date:
3573 opts['date'] = util.parsedate(date)
3573 opts['date'] = util.parsedate(date)
3574
3574
3575 editor = cmdutil.commiteditor
3575 editor = cmdutil.commiteditor
3576 if opts.get('edit'):
3576 if opts.get('edit'):
3577 editor = cmdutil.commitforceeditor
3577 editor = cmdutil.commitforceeditor
3578
3578
3579 update = not opts.get('bypass')
3579 update = not opts.get('bypass')
3580 if not update and opts.get('no_commit'):
3580 if not update and opts.get('no_commit'):
3581 raise util.Abort(_('cannot use --no-commit with --bypass'))
3581 raise util.Abort(_('cannot use --no-commit with --bypass'))
3582 try:
3582 try:
3583 sim = float(opts.get('similarity') or 0)
3583 sim = float(opts.get('similarity') or 0)
3584 except ValueError:
3584 except ValueError:
3585 raise util.Abort(_('similarity must be a number'))
3585 raise util.Abort(_('similarity must be a number'))
3586 if sim < 0 or sim > 100:
3586 if sim < 0 or sim > 100:
3587 raise util.Abort(_('similarity must be between 0 and 100'))
3587 raise util.Abort(_('similarity must be between 0 and 100'))
3588 if sim and not update:
3588 if sim and not update:
3589 raise util.Abort(_('cannot use --similarity with --bypass'))
3589 raise util.Abort(_('cannot use --similarity with --bypass'))
3590
3590
3591 if (opts.get('exact') or not opts.get('force')) and update:
3591 if (opts.get('exact') or not opts.get('force')) and update:
3592 cmdutil.bailifchanged(repo)
3592 cmdutil.bailifchanged(repo)
3593
3593
3594 base = opts["base"]
3594 base = opts["base"]
3595 strip = opts["strip"]
3595 strip = opts["strip"]
3596 wlock = lock = tr = None
3596 wlock = lock = tr = None
3597 msgs = []
3597 msgs = []
3598
3598
3599 def checkexact(repo, n, nodeid):
3599 def checkexact(repo, n, nodeid):
3600 if opts.get('exact') and hex(n) != nodeid:
3600 if opts.get('exact') and hex(n) != nodeid:
3601 raise util.Abort(_('patch is damaged or loses information'))
3601 raise util.Abort(_('patch is damaged or loses information'))
3602
3602
3603 def tryone(ui, hunk, parents):
3603 def tryone(ui, hunk, parents):
3604 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3604 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3605 patch.extract(ui, hunk)
3605 patch.extract(ui, hunk)
3606
3606
3607 if not tmpname:
3607 if not tmpname:
3608 return (None, None)
3608 return (None, None)
3609 msg = _('applied to working directory')
3609 msg = _('applied to working directory')
3610
3610
3611 try:
3611 try:
3612 cmdline_message = cmdutil.logmessage(ui, opts)
3612 cmdline_message = cmdutil.logmessage(ui, opts)
3613 if cmdline_message:
3613 if cmdline_message:
3614 # pickup the cmdline msg
3614 # pickup the cmdline msg
3615 message = cmdline_message
3615 message = cmdline_message
3616 elif message:
3616 elif message:
3617 # pickup the patch msg
3617 # pickup the patch msg
3618 message = message.strip()
3618 message = message.strip()
3619 else:
3619 else:
3620 # launch the editor
3620 # launch the editor
3621 message = None
3621 message = None
3622 ui.debug('message:\n%s\n' % message)
3622 ui.debug('message:\n%s\n' % message)
3623
3623
3624 if len(parents) == 1:
3624 if len(parents) == 1:
3625 parents.append(repo[nullid])
3625 parents.append(repo[nullid])
3626 if opts.get('exact'):
3626 if opts.get('exact'):
3627 if not nodeid or not p1:
3627 if not nodeid or not p1:
3628 raise util.Abort(_('not a Mercurial patch'))
3628 raise util.Abort(_('not a Mercurial patch'))
3629 p1 = repo[p1]
3629 p1 = repo[p1]
3630 p2 = repo[p2 or nullid]
3630 p2 = repo[p2 or nullid]
3631 elif p2:
3631 elif p2:
3632 try:
3632 try:
3633 p1 = repo[p1]
3633 p1 = repo[p1]
3634 p2 = repo[p2]
3634 p2 = repo[p2]
3635 # Without any options, consider p2 only if the
3635 # Without any options, consider p2 only if the
3636 # patch is being applied on top of the recorded
3636 # patch is being applied on top of the recorded
3637 # first parent.
3637 # first parent.
3638 if p1 != parents[0]:
3638 if p1 != parents[0]:
3639 p1 = parents[0]
3639 p1 = parents[0]
3640 p2 = repo[nullid]
3640 p2 = repo[nullid]
3641 except error.RepoError:
3641 except error.RepoError:
3642 p1, p2 = parents
3642 p1, p2 = parents
3643 else:
3643 else:
3644 p1, p2 = parents
3644 p1, p2 = parents
3645
3645
3646 n = None
3646 n = None
3647 if update:
3647 if update:
3648 if p1 != parents[0]:
3648 if p1 != parents[0]:
3649 hg.clean(repo, p1.node())
3649 hg.clean(repo, p1.node())
3650 if p2 != parents[1]:
3650 if p2 != parents[1]:
3651 repo.setparents(p1.node(), p2.node())
3651 repo.setparents(p1.node(), p2.node())
3652
3652
3653 if opts.get('exact') or opts.get('import_branch'):
3653 if opts.get('exact') or opts.get('import_branch'):
3654 repo.dirstate.setbranch(branch or 'default')
3654 repo.dirstate.setbranch(branch or 'default')
3655
3655
3656 files = set()
3656 files = set()
3657 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3657 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3658 eolmode=None, similarity=sim / 100.0)
3658 eolmode=None, similarity=sim / 100.0)
3659 files = list(files)
3659 files = list(files)
3660 if opts.get('no_commit'):
3660 if opts.get('no_commit'):
3661 if message:
3661 if message:
3662 msgs.append(message)
3662 msgs.append(message)
3663 else:
3663 else:
3664 if opts.get('exact') or p2:
3664 if opts.get('exact') or p2:
3665 # If you got here, you either use --force and know what
3665 # If you got here, you either use --force and know what
3666 # you are doing or used --exact or a merge patch while
3666 # you are doing or used --exact or a merge patch while
3667 # being updated to its first parent.
3667 # being updated to its first parent.
3668 m = None
3668 m = None
3669 else:
3669 else:
3670 m = scmutil.matchfiles(repo, files or [])
3670 m = scmutil.matchfiles(repo, files or [])
3671 n = repo.commit(message, opts.get('user') or user,
3671 n = repo.commit(message, opts.get('user') or user,
3672 opts.get('date') or date, match=m,
3672 opts.get('date') or date, match=m,
3673 editor=editor)
3673 editor=editor)
3674 checkexact(repo, n, nodeid)
3674 checkexact(repo, n, nodeid)
3675 else:
3675 else:
3676 if opts.get('exact') or opts.get('import_branch'):
3676 if opts.get('exact') or opts.get('import_branch'):
3677 branch = branch or 'default'
3677 branch = branch or 'default'
3678 else:
3678 else:
3679 branch = p1.branch()
3679 branch = p1.branch()
3680 store = patch.filestore()
3680 store = patch.filestore()
3681 try:
3681 try:
3682 files = set()
3682 files = set()
3683 try:
3683 try:
3684 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3684 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3685 files, eolmode=None)
3685 files, eolmode=None)
3686 except patch.PatchError, e:
3686 except patch.PatchError, e:
3687 raise util.Abort(str(e))
3687 raise util.Abort(str(e))
3688 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3688 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3689 message,
3689 message,
3690 opts.get('user') or user,
3690 opts.get('user') or user,
3691 opts.get('date') or date,
3691 opts.get('date') or date,
3692 branch, files, store,
3692 branch, files, store,
3693 editor=cmdutil.commiteditor)
3693 editor=cmdutil.commiteditor)
3694 repo.savecommitmessage(memctx.description())
3694 repo.savecommitmessage(memctx.description())
3695 n = memctx.commit()
3695 n = memctx.commit()
3696 checkexact(repo, n, nodeid)
3696 checkexact(repo, n, nodeid)
3697 finally:
3697 finally:
3698 store.close()
3698 store.close()
3699 if n:
3699 if n:
3700 # i18n: refers to a short changeset id
3700 # i18n: refers to a short changeset id
3701 msg = _('created %s') % short(n)
3701 msg = _('created %s') % short(n)
3702 return (msg, n)
3702 return (msg, n)
3703 finally:
3703 finally:
3704 os.unlink(tmpname)
3704 os.unlink(tmpname)
3705
3705
3706 try:
3706 try:
3707 try:
3707 try:
3708 wlock = repo.wlock()
3708 wlock = repo.wlock()
3709 if not opts.get('no_commit'):
3709 if not opts.get('no_commit'):
3710 lock = repo.lock()
3710 lock = repo.lock()
3711 tr = repo.transaction('import')
3711 tr = repo.transaction('import')
3712 parents = repo.parents()
3712 parents = repo.parents()
3713 for patchurl in patches:
3713 for patchurl in patches:
3714 if patchurl == '-':
3714 if patchurl == '-':
3715 ui.status(_('applying patch from stdin\n'))
3715 ui.status(_('applying patch from stdin\n'))
3716 patchfile = ui.fin
3716 patchfile = ui.fin
3717 patchurl = 'stdin' # for error message
3717 patchurl = 'stdin' # for error message
3718 else:
3718 else:
3719 patchurl = os.path.join(base, patchurl)
3719 patchurl = os.path.join(base, patchurl)
3720 ui.status(_('applying %s\n') % patchurl)
3720 ui.status(_('applying %s\n') % patchurl)
3721 patchfile = hg.openpath(ui, patchurl)
3721 patchfile = hg.openpath(ui, patchurl)
3722
3722
3723 haspatch = False
3723 haspatch = False
3724 for hunk in patch.split(patchfile):
3724 for hunk in patch.split(patchfile):
3725 (msg, node) = tryone(ui, hunk, parents)
3725 (msg, node) = tryone(ui, hunk, parents)
3726 if msg:
3726 if msg:
3727 haspatch = True
3727 haspatch = True
3728 ui.note(msg + '\n')
3728 ui.note(msg + '\n')
3729 if update or opts.get('exact'):
3729 if update or opts.get('exact'):
3730 parents = repo.parents()
3730 parents = repo.parents()
3731 else:
3731 else:
3732 parents = [repo[node]]
3732 parents = [repo[node]]
3733
3733
3734 if not haspatch:
3734 if not haspatch:
3735 raise util.Abort(_('%s: no diffs found') % patchurl)
3735 raise util.Abort(_('%s: no diffs found') % patchurl)
3736
3736
3737 if tr:
3737 if tr:
3738 tr.close()
3738 tr.close()
3739 if msgs:
3739 if msgs:
3740 repo.savecommitmessage('\n* * *\n'.join(msgs))
3740 repo.savecommitmessage('\n* * *\n'.join(msgs))
3741 except: # re-raises
3741 except: # re-raises
3742 # wlock.release() indirectly calls dirstate.write(): since
3742 # wlock.release() indirectly calls dirstate.write(): since
3743 # we're crashing, we do not want to change the working dir
3743 # we're crashing, we do not want to change the working dir
3744 # parent after all, so make sure it writes nothing
3744 # parent after all, so make sure it writes nothing
3745 repo.dirstate.invalidate()
3745 repo.dirstate.invalidate()
3746 raise
3746 raise
3747 finally:
3747 finally:
3748 if tr:
3748 if tr:
3749 tr.release()
3749 tr.release()
3750 release(lock, wlock)
3750 release(lock, wlock)
3751
3751
3752 @command('incoming|in',
3752 @command('incoming|in',
3753 [('f', 'force', None,
3753 [('f', 'force', None,
3754 _('run even if remote repository is unrelated')),
3754 _('run even if remote repository is unrelated')),
3755 ('n', 'newest-first', None, _('show newest record first')),
3755 ('n', 'newest-first', None, _('show newest record first')),
3756 ('', 'bundle', '',
3756 ('', 'bundle', '',
3757 _('file to store the bundles into'), _('FILE')),
3757 _('file to store the bundles into'), _('FILE')),
3758 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3758 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3759 ('B', 'bookmarks', False, _("compare bookmarks")),
3759 ('B', 'bookmarks', False, _("compare bookmarks")),
3760 ('b', 'branch', [],
3760 ('b', 'branch', [],
3761 _('a specific branch you would like to pull'), _('BRANCH')),
3761 _('a specific branch you would like to pull'), _('BRANCH')),
3762 ] + logopts + remoteopts + subrepoopts,
3762 ] + logopts + remoteopts + subrepoopts,
3763 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3763 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3764 def incoming(ui, repo, source="default", **opts):
3764 def incoming(ui, repo, source="default", **opts):
3765 """show new changesets found in source
3765 """show new changesets found in source
3766
3766
3767 Show new changesets found in the specified path/URL or the default
3767 Show new changesets found in the specified path/URL or the default
3768 pull location. These are the changesets that would have been pulled
3768 pull location. These are the changesets that would have been pulled
3769 if a pull at the time you issued this command.
3769 if a pull at the time you issued this command.
3770
3770
3771 For remote repository, using --bundle avoids downloading the
3771 For remote repository, using --bundle avoids downloading the
3772 changesets twice if the incoming is followed by a pull.
3772 changesets twice if the incoming is followed by a pull.
3773
3773
3774 See pull for valid source format details.
3774 See pull for valid source format details.
3775
3775
3776 Returns 0 if there are incoming changes, 1 otherwise.
3776 Returns 0 if there are incoming changes, 1 otherwise.
3777 """
3777 """
3778 if opts.get('graph'):
3778 if opts.get('graph'):
3779 cmdutil.checkunsupportedgraphflags([], opts)
3779 cmdutil.checkunsupportedgraphflags([], opts)
3780 def display(other, chlist, displayer):
3780 def display(other, chlist, displayer):
3781 revdag = cmdutil.graphrevs(other, chlist, opts)
3781 revdag = cmdutil.graphrevs(other, chlist, opts)
3782 showparents = [ctx.node() for ctx in repo[None].parents()]
3782 showparents = [ctx.node() for ctx in repo[None].parents()]
3783 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3783 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3784 graphmod.asciiedges)
3784 graphmod.asciiedges)
3785
3785
3786 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3786 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3787 return 0
3787 return 0
3788
3788
3789 if opts.get('bundle') and opts.get('subrepos'):
3789 if opts.get('bundle') and opts.get('subrepos'):
3790 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3790 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3791
3791
3792 if opts.get('bookmarks'):
3792 if opts.get('bookmarks'):
3793 source, branches = hg.parseurl(ui.expandpath(source),
3793 source, branches = hg.parseurl(ui.expandpath(source),
3794 opts.get('branch'))
3794 opts.get('branch'))
3795 other = hg.peer(repo, opts, source)
3795 other = hg.peer(repo, opts, source)
3796 if 'bookmarks' not in other.listkeys('namespaces'):
3796 if 'bookmarks' not in other.listkeys('namespaces'):
3797 ui.warn(_("remote doesn't support bookmarks\n"))
3797 ui.warn(_("remote doesn't support bookmarks\n"))
3798 return 0
3798 return 0
3799 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3799 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3800 return bookmarks.diff(ui, repo, other)
3800 return bookmarks.diff(ui, repo, other)
3801
3801
3802 repo._subtoppath = ui.expandpath(source)
3802 repo._subtoppath = ui.expandpath(source)
3803 try:
3803 try:
3804 return hg.incoming(ui, repo, source, opts)
3804 return hg.incoming(ui, repo, source, opts)
3805 finally:
3805 finally:
3806 del repo._subtoppath
3806 del repo._subtoppath
3807
3807
3808
3808
3809 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3809 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3810 def init(ui, dest=".", **opts):
3810 def init(ui, dest=".", **opts):
3811 """create a new repository in the given directory
3811 """create a new repository in the given directory
3812
3812
3813 Initialize a new repository in the given directory. If the given
3813 Initialize a new repository in the given directory. If the given
3814 directory does not exist, it will be created.
3814 directory does not exist, it will be created.
3815
3815
3816 If no directory is given, the current directory is used.
3816 If no directory is given, the current directory is used.
3817
3817
3818 It is possible to specify an ``ssh://`` URL as the destination.
3818 It is possible to specify an ``ssh://`` URL as the destination.
3819 See :hg:`help urls` for more information.
3819 See :hg:`help urls` for more information.
3820
3820
3821 Returns 0 on success.
3821 Returns 0 on success.
3822 """
3822 """
3823 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3823 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3824
3824
3825 @command('locate',
3825 @command('locate',
3826 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3826 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3827 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3827 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3828 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3828 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3829 ] + walkopts,
3829 ] + walkopts,
3830 _('[OPTION]... [PATTERN]...'))
3830 _('[OPTION]... [PATTERN]...'))
3831 def locate(ui, repo, *pats, **opts):
3831 def locate(ui, repo, *pats, **opts):
3832 """locate files matching specific patterns
3832 """locate files matching specific patterns
3833
3833
3834 Print files under Mercurial control in the working directory whose
3834 Print files under Mercurial control in the working directory whose
3835 names match the given patterns.
3835 names match the given patterns.
3836
3836
3837 By default, this command searches all directories in the working
3837 By default, this command searches all directories in the working
3838 directory. To search just the current directory and its
3838 directory. To search just the current directory and its
3839 subdirectories, use "--include .".
3839 subdirectories, use "--include .".
3840
3840
3841 If no patterns are given to match, this command prints the names
3841 If no patterns are given to match, this command prints the names
3842 of all files under Mercurial control in the working directory.
3842 of all files under Mercurial control in the working directory.
3843
3843
3844 If you want to feed the output of this command into the "xargs"
3844 If you want to feed the output of this command into the "xargs"
3845 command, use the -0 option to both this command and "xargs". This
3845 command, use the -0 option to both this command and "xargs". This
3846 will avoid the problem of "xargs" treating single filenames that
3846 will avoid the problem of "xargs" treating single filenames that
3847 contain whitespace as multiple filenames.
3847 contain whitespace as multiple filenames.
3848
3848
3849 Returns 0 if a match is found, 1 otherwise.
3849 Returns 0 if a match is found, 1 otherwise.
3850 """
3850 """
3851 end = opts.get('print0') and '\0' or '\n'
3851 end = opts.get('print0') and '\0' or '\n'
3852 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3852 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3853
3853
3854 ret = 1
3854 ret = 1
3855 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3855 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3856 m.bad = lambda x, y: False
3856 m.bad = lambda x, y: False
3857 for abs in repo[rev].walk(m):
3857 for abs in repo[rev].walk(m):
3858 if not rev and abs not in repo.dirstate:
3858 if not rev and abs not in repo.dirstate:
3859 continue
3859 continue
3860 if opts.get('fullpath'):
3860 if opts.get('fullpath'):
3861 ui.write(repo.wjoin(abs), end)
3861 ui.write(repo.wjoin(abs), end)
3862 else:
3862 else:
3863 ui.write(((pats and m.rel(abs)) or abs), end)
3863 ui.write(((pats and m.rel(abs)) or abs), end)
3864 ret = 0
3864 ret = 0
3865
3865
3866 return ret
3866 return ret
3867
3867
3868 @command('^log|history',
3868 @command('^log|history',
3869 [('f', 'follow', None,
3869 [('f', 'follow', None,
3870 _('follow changeset history, or file history across copies and renames')),
3870 _('follow changeset history, or file history across copies and renames')),
3871 ('', 'follow-first', None,
3871 ('', 'follow-first', None,
3872 _('only follow the first parent of merge changesets (DEPRECATED)')),
3872 _('only follow the first parent of merge changesets (DEPRECATED)')),
3873 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3873 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3874 ('C', 'copies', None, _('show copied files')),
3874 ('C', 'copies', None, _('show copied files')),
3875 ('k', 'keyword', [],
3875 ('k', 'keyword', [],
3876 _('do case-insensitive search for a given text'), _('TEXT')),
3876 _('do case-insensitive search for a given text'), _('TEXT')),
3877 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3877 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3878 ('', 'removed', None, _('include revisions where files were removed')),
3878 ('', 'removed', None, _('include revisions where files were removed')),
3879 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3879 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3880 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3880 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3881 ('', 'only-branch', [],
3881 ('', 'only-branch', [],
3882 _('show only changesets within the given named branch (DEPRECATED)'),
3882 _('show only changesets within the given named branch (DEPRECATED)'),
3883 _('BRANCH')),
3883 _('BRANCH')),
3884 ('b', 'branch', [],
3884 ('b', 'branch', [],
3885 _('show changesets within the given named branch'), _('BRANCH')),
3885 _('show changesets within the given named branch'), _('BRANCH')),
3886 ('P', 'prune', [],
3886 ('P', 'prune', [],
3887 _('do not display revision or any of its ancestors'), _('REV')),
3887 _('do not display revision or any of its ancestors'), _('REV')),
3888 ] + logopts + walkopts,
3888 ] + logopts + walkopts,
3889 _('[OPTION]... [FILE]'))
3889 _('[OPTION]... [FILE]'))
3890 def log(ui, repo, *pats, **opts):
3890 def log(ui, repo, *pats, **opts):
3891 """show revision history of entire repository or files
3891 """show revision history of entire repository or files
3892
3892
3893 Print the revision history of the specified files or the entire
3893 Print the revision history of the specified files or the entire
3894 project.
3894 project.
3895
3895
3896 If no revision range is specified, the default is ``tip:0`` unless
3896 If no revision range is specified, the default is ``tip:0`` unless
3897 --follow is set, in which case the working directory parent is
3897 --follow is set, in which case the working directory parent is
3898 used as the starting revision.
3898 used as the starting revision.
3899
3899
3900 File history is shown without following rename or copy history of
3900 File history is shown without following rename or copy history of
3901 files. Use -f/--follow with a filename to follow history across
3901 files. Use -f/--follow with a filename to follow history across
3902 renames and copies. --follow without a filename will only show
3902 renames and copies. --follow without a filename will only show
3903 ancestors or descendants of the starting revision.
3903 ancestors or descendants of the starting revision.
3904
3904
3905 By default this command prints revision number and changeset id,
3905 By default this command prints revision number and changeset id,
3906 tags, non-trivial parents, user, date and time, and a summary for
3906 tags, non-trivial parents, user, date and time, and a summary for
3907 each commit. When the -v/--verbose switch is used, the list of
3907 each commit. When the -v/--verbose switch is used, the list of
3908 changed files and full commit message are shown.
3908 changed files and full commit message are shown.
3909
3909
3910 .. note::
3910 .. note::
3911 log -p/--patch may generate unexpected diff output for merge
3911 log -p/--patch may generate unexpected diff output for merge
3912 changesets, as it will only compare the merge changeset against
3912 changesets, as it will only compare the merge changeset against
3913 its first parent. Also, only files different from BOTH parents
3913 its first parent. Also, only files different from BOTH parents
3914 will appear in files:.
3914 will appear in files:.
3915
3915
3916 .. note::
3916 .. note::
3917 for performance reasons, log FILE may omit duplicate changes
3917 for performance reasons, log FILE may omit duplicate changes
3918 made on branches and will not show deletions. To see all
3918 made on branches and will not show deletions. To see all
3919 changes including duplicates and deletions, use the --removed
3919 changes including duplicates and deletions, use the --removed
3920 switch.
3920 switch.
3921
3921
3922 .. container:: verbose
3922 .. container:: verbose
3923
3923
3924 Some examples:
3924 Some examples:
3925
3925
3926 - changesets with full descriptions and file lists::
3926 - changesets with full descriptions and file lists::
3927
3927
3928 hg log -v
3928 hg log -v
3929
3929
3930 - changesets ancestral to the working directory::
3930 - changesets ancestral to the working directory::
3931
3931
3932 hg log -f
3932 hg log -f
3933
3933
3934 - last 10 commits on the current branch::
3934 - last 10 commits on the current branch::
3935
3935
3936 hg log -l 10 -b .
3936 hg log -l 10 -b .
3937
3937
3938 - changesets showing all modifications of a file, including removals::
3938 - changesets showing all modifications of a file, including removals::
3939
3939
3940 hg log --removed file.c
3940 hg log --removed file.c
3941
3941
3942 - all changesets that touch a directory, with diffs, excluding merges::
3942 - all changesets that touch a directory, with diffs, excluding merges::
3943
3943
3944 hg log -Mp lib/
3944 hg log -Mp lib/
3945
3945
3946 - all revision numbers that match a keyword::
3946 - all revision numbers that match a keyword::
3947
3947
3948 hg log -k bug --template "{rev}\\n"
3948 hg log -k bug --template "{rev}\\n"
3949
3949
3950 - check if a given changeset is included is a tagged release::
3950 - check if a given changeset is included is a tagged release::
3951
3951
3952 hg log -r "a21ccf and ancestor(1.9)"
3952 hg log -r "a21ccf and ancestor(1.9)"
3953
3953
3954 - find all changesets by some user in a date range::
3954 - find all changesets by some user in a date range::
3955
3955
3956 hg log -k alice -d "may 2008 to jul 2008"
3956 hg log -k alice -d "may 2008 to jul 2008"
3957
3957
3958 - summary of all changesets after the last tag::
3958 - summary of all changesets after the last tag::
3959
3959
3960 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3960 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3961
3961
3962 See :hg:`help dates` for a list of formats valid for -d/--date.
3962 See :hg:`help dates` for a list of formats valid for -d/--date.
3963
3963
3964 See :hg:`help revisions` and :hg:`help revsets` for more about
3964 See :hg:`help revisions` and :hg:`help revsets` for more about
3965 specifying revisions.
3965 specifying revisions.
3966
3966
3967 See :hg:`help templates` for more about pre-packaged styles and
3967 See :hg:`help templates` for more about pre-packaged styles and
3968 specifying custom templates.
3968 specifying custom templates.
3969
3969
3970 Returns 0 on success.
3970 Returns 0 on success.
3971 """
3971 """
3972 if opts.get('graph'):
3972 if opts.get('graph'):
3973 return cmdutil.graphlog(ui, repo, *pats, **opts)
3973 return cmdutil.graphlog(ui, repo, *pats, **opts)
3974
3974
3975 matchfn = scmutil.match(repo[None], pats, opts)
3975 matchfn = scmutil.match(repo[None], pats, opts)
3976 limit = cmdutil.loglimit(opts)
3976 limit = cmdutil.loglimit(opts)
3977 count = 0
3977 count = 0
3978
3978
3979 getrenamed, endrev = None, None
3979 getrenamed, endrev = None, None
3980 if opts.get('copies'):
3980 if opts.get('copies'):
3981 if opts.get('rev'):
3981 if opts.get('rev'):
3982 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3982 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3983 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3983 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3984
3984
3985 df = False
3985 df = False
3986 if opts.get("date"):
3986 if opts.get("date"):
3987 df = util.matchdate(opts["date"])
3987 df = util.matchdate(opts["date"])
3988
3988
3989 branches = opts.get('branch', []) + opts.get('only_branch', [])
3989 branches = opts.get('branch', []) + opts.get('only_branch', [])
3990 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3990 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3991
3991
3992 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3992 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3993 def prep(ctx, fns):
3993 def prep(ctx, fns):
3994 rev = ctx.rev()
3994 rev = ctx.rev()
3995 parents = [p for p in repo.changelog.parentrevs(rev)
3995 parents = [p for p in repo.changelog.parentrevs(rev)
3996 if p != nullrev]
3996 if p != nullrev]
3997 if opts.get('no_merges') and len(parents) == 2:
3997 if opts.get('no_merges') and len(parents) == 2:
3998 return
3998 return
3999 if opts.get('only_merges') and len(parents) != 2:
3999 if opts.get('only_merges') and len(parents) != 2:
4000 return
4000 return
4001 if opts.get('branch') and ctx.branch() not in opts['branch']:
4001 if opts.get('branch') and ctx.branch() not in opts['branch']:
4002 return
4002 return
4003 if df and not df(ctx.date()[0]):
4003 if df and not df(ctx.date()[0]):
4004 return
4004 return
4005
4005
4006 lower = encoding.lower
4006 lower = encoding.lower
4007 if opts.get('user'):
4007 if opts.get('user'):
4008 luser = lower(ctx.user())
4008 luser = lower(ctx.user())
4009 for k in [lower(x) for x in opts['user']]:
4009 for k in [lower(x) for x in opts['user']]:
4010 if (k in luser):
4010 if (k in luser):
4011 break
4011 break
4012 else:
4012 else:
4013 return
4013 return
4014 if opts.get('keyword'):
4014 if opts.get('keyword'):
4015 luser = lower(ctx.user())
4015 luser = lower(ctx.user())
4016 ldesc = lower(ctx.description())
4016 ldesc = lower(ctx.description())
4017 lfiles = lower(" ".join(ctx.files()))
4017 lfiles = lower(" ".join(ctx.files()))
4018 for k in [lower(x) for x in opts['keyword']]:
4018 for k in [lower(x) for x in opts['keyword']]:
4019 if (k in luser or k in ldesc or k in lfiles):
4019 if (k in luser or k in ldesc or k in lfiles):
4020 break
4020 break
4021 else:
4021 else:
4022 return
4022 return
4023
4023
4024 copies = None
4024 copies = None
4025 if getrenamed is not None and rev:
4025 if getrenamed is not None and rev:
4026 copies = []
4026 copies = []
4027 for fn in ctx.files():
4027 for fn in ctx.files():
4028 rename = getrenamed(fn, rev)
4028 rename = getrenamed(fn, rev)
4029 if rename:
4029 if rename:
4030 copies.append((fn, rename[0]))
4030 copies.append((fn, rename[0]))
4031
4031
4032 revmatchfn = None
4032 revmatchfn = None
4033 if opts.get('patch') or opts.get('stat'):
4033 if opts.get('patch') or opts.get('stat'):
4034 if opts.get('follow') or opts.get('follow_first'):
4034 if opts.get('follow') or opts.get('follow_first'):
4035 # note: this might be wrong when following through merges
4035 # note: this might be wrong when following through merges
4036 revmatchfn = scmutil.match(repo[None], fns, default='path')
4036 revmatchfn = scmutil.match(repo[None], fns, default='path')
4037 else:
4037 else:
4038 revmatchfn = matchfn
4038 revmatchfn = matchfn
4039
4039
4040 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4040 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4041
4041
4042 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4042 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4043 if displayer.flush(ctx.rev()):
4043 if displayer.flush(ctx.rev()):
4044 count += 1
4044 count += 1
4045 if count == limit:
4045 if count == limit:
4046 break
4046 break
4047 displayer.close()
4047 displayer.close()
4048
4048
4049 @command('manifest',
4049 @command('manifest',
4050 [('r', 'rev', '', _('revision to display'), _('REV')),
4050 [('r', 'rev', '', _('revision to display'), _('REV')),
4051 ('', 'all', False, _("list files from all revisions"))],
4051 ('', 'all', False, _("list files from all revisions"))],
4052 _('[-r REV]'))
4052 _('[-r REV]'))
4053 def manifest(ui, repo, node=None, rev=None, **opts):
4053 def manifest(ui, repo, node=None, rev=None, **opts):
4054 """output the current or given revision of the project manifest
4054 """output the current or given revision of the project manifest
4055
4055
4056 Print a list of version controlled files for the given revision.
4056 Print a list of version controlled files for the given revision.
4057 If no revision is given, the first parent of the working directory
4057 If no revision is given, the first parent of the working directory
4058 is used, or the null revision if no revision is checked out.
4058 is used, or the null revision if no revision is checked out.
4059
4059
4060 With -v, print file permissions, symlink and executable bits.
4060 With -v, print file permissions, symlink and executable bits.
4061 With --debug, print file revision hashes.
4061 With --debug, print file revision hashes.
4062
4062
4063 If option --all is specified, the list of all files from all revisions
4063 If option --all is specified, the list of all files from all revisions
4064 is printed. This includes deleted and renamed files.
4064 is printed. This includes deleted and renamed files.
4065
4065
4066 Returns 0 on success.
4066 Returns 0 on success.
4067 """
4067 """
4068
4068
4069 fm = ui.formatter('manifest', opts)
4069 fm = ui.formatter('manifest', opts)
4070
4070
4071 if opts.get('all'):
4071 if opts.get('all'):
4072 if rev or node:
4072 if rev or node:
4073 raise util.Abort(_("can't specify a revision with --all"))
4073 raise util.Abort(_("can't specify a revision with --all"))
4074
4074
4075 res = []
4075 res = []
4076 prefix = "data/"
4076 prefix = "data/"
4077 suffix = ".i"
4077 suffix = ".i"
4078 plen = len(prefix)
4078 plen = len(prefix)
4079 slen = len(suffix)
4079 slen = len(suffix)
4080 lock = repo.lock()
4080 lock = repo.lock()
4081 try:
4081 try:
4082 for fn, b, size in repo.store.datafiles():
4082 for fn, b, size in repo.store.datafiles():
4083 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4083 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4084 res.append(fn[plen:-slen])
4084 res.append(fn[plen:-slen])
4085 finally:
4085 finally:
4086 lock.release()
4086 lock.release()
4087 for f in res:
4087 for f in res:
4088 fm.startitem()
4088 fm.startitem()
4089 fm.write("path", '%s\n', f)
4089 fm.write("path", '%s\n', f)
4090 fm.end()
4090 fm.end()
4091 return
4091 return
4092
4092
4093 if rev and node:
4093 if rev and node:
4094 raise util.Abort(_("please specify just one revision"))
4094 raise util.Abort(_("please specify just one revision"))
4095
4095
4096 if not node:
4096 if not node:
4097 node = rev
4097 node = rev
4098
4098
4099 char = {'l': '@', 'x': '*', '': ''}
4099 char = {'l': '@', 'x': '*', '': ''}
4100 mode = {'l': '644', 'x': '755', '': '644'}
4100 mode = {'l': '644', 'x': '755', '': '644'}
4101 ctx = scmutil.revsingle(repo, node)
4101 ctx = scmutil.revsingle(repo, node)
4102 mf = ctx.manifest()
4102 mf = ctx.manifest()
4103 for f in ctx:
4103 for f in ctx:
4104 fm.startitem()
4104 fm.startitem()
4105 fl = ctx[f].flags()
4105 fl = ctx[f].flags()
4106 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4106 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4107 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4107 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4108 fm.write('path', '%s\n', f)
4108 fm.write('path', '%s\n', f)
4109 fm.end()
4109 fm.end()
4110
4110
4111 @command('^merge',
4111 @command('^merge',
4112 [('f', 'force', None, _('force a merge with outstanding changes')),
4112 [('f', 'force', None, _('force a merge with outstanding changes')),
4113 ('r', 'rev', '', _('revision to merge'), _('REV')),
4113 ('r', 'rev', '', _('revision to merge'), _('REV')),
4114 ('P', 'preview', None,
4114 ('P', 'preview', None,
4115 _('review revisions to merge (no merge is performed)'))
4115 _('review revisions to merge (no merge is performed)'))
4116 ] + mergetoolopts,
4116 ] + mergetoolopts,
4117 _('[-P] [-f] [[-r] REV]'))
4117 _('[-P] [-f] [[-r] REV]'))
4118 def merge(ui, repo, node=None, **opts):
4118 def merge(ui, repo, node=None, **opts):
4119 """merge working directory with another revision
4119 """merge working directory with another revision
4120
4120
4121 The current working directory is updated with all changes made in
4121 The current working directory is updated with all changes made in
4122 the requested revision since the last common predecessor revision.
4122 the requested revision since the last common predecessor revision.
4123
4123
4124 Files that changed between either parent are marked as changed for
4124 Files that changed between either parent are marked as changed for
4125 the next commit and a commit must be performed before any further
4125 the next commit and a commit must be performed before any further
4126 updates to the repository are allowed. The next commit will have
4126 updates to the repository are allowed. The next commit will have
4127 two parents.
4127 two parents.
4128
4128
4129 ``--tool`` can be used to specify the merge tool used for file
4129 ``--tool`` can be used to specify the merge tool used for file
4130 merges. It overrides the HGMERGE environment variable and your
4130 merges. It overrides the HGMERGE environment variable and your
4131 configuration files. See :hg:`help merge-tools` for options.
4131 configuration files. See :hg:`help merge-tools` for options.
4132
4132
4133 If no revision is specified, the working directory's parent is a
4133 If no revision is specified, the working directory's parent is a
4134 head revision, and the current branch contains exactly one other
4134 head revision, and the current branch contains exactly one other
4135 head, the other head is merged with by default. Otherwise, an
4135 head, the other head is merged with by default. Otherwise, an
4136 explicit revision with which to merge with must be provided.
4136 explicit revision with which to merge with must be provided.
4137
4137
4138 :hg:`resolve` must be used to resolve unresolved files.
4138 :hg:`resolve` must be used to resolve unresolved files.
4139
4139
4140 To undo an uncommitted merge, use :hg:`update --clean .` which
4140 To undo an uncommitted merge, use :hg:`update --clean .` which
4141 will check out a clean copy of the original merge parent, losing
4141 will check out a clean copy of the original merge parent, losing
4142 all changes.
4142 all changes.
4143
4143
4144 Returns 0 on success, 1 if there are unresolved files.
4144 Returns 0 on success, 1 if there are unresolved files.
4145 """
4145 """
4146
4146
4147 if opts.get('rev') and node:
4147 if opts.get('rev') and node:
4148 raise util.Abort(_("please specify just one revision"))
4148 raise util.Abort(_("please specify just one revision"))
4149 if not node:
4149 if not node:
4150 node = opts.get('rev')
4150 node = opts.get('rev')
4151
4151
4152 if node:
4152 if node:
4153 node = scmutil.revsingle(repo, node).node()
4153 node = scmutil.revsingle(repo, node).node()
4154
4154
4155 if not node and repo._bookmarkcurrent:
4155 if not node and repo._bookmarkcurrent:
4156 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4156 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4157 curhead = repo[repo._bookmarkcurrent].node()
4157 curhead = repo[repo._bookmarkcurrent].node()
4158 if len(bmheads) == 2:
4158 if len(bmheads) == 2:
4159 if curhead == bmheads[0]:
4159 if curhead == bmheads[0]:
4160 node = bmheads[1]
4160 node = bmheads[1]
4161 else:
4161 else:
4162 node = bmheads[0]
4162 node = bmheads[0]
4163 elif len(bmheads) > 2:
4163 elif len(bmheads) > 2:
4164 raise util.Abort(_("multiple matching bookmarks to merge - "
4164 raise util.Abort(_("multiple matching bookmarks to merge - "
4165 "please merge with an explicit rev or bookmark"),
4165 "please merge with an explicit rev or bookmark"),
4166 hint=_("run 'hg heads' to see all heads"))
4166 hint=_("run 'hg heads' to see all heads"))
4167 elif len(bmheads) <= 1:
4167 elif len(bmheads) <= 1:
4168 raise util.Abort(_("no matching bookmark to merge - "
4168 raise util.Abort(_("no matching bookmark to merge - "
4169 "please merge with an explicit rev or bookmark"),
4169 "please merge with an explicit rev or bookmark"),
4170 hint=_("run 'hg heads' to see all heads"))
4170 hint=_("run 'hg heads' to see all heads"))
4171
4171
4172 if not node and not repo._bookmarkcurrent:
4172 if not node and not repo._bookmarkcurrent:
4173 branch = repo[None].branch()
4173 branch = repo[None].branch()
4174 bheads = repo.branchheads(branch)
4174 bheads = repo.branchheads(branch)
4175 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4175 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4176
4176
4177 if len(nbhs) > 2:
4177 if len(nbhs) > 2:
4178 raise util.Abort(_("branch '%s' has %d heads - "
4178 raise util.Abort(_("branch '%s' has %d heads - "
4179 "please merge with an explicit rev")
4179 "please merge with an explicit rev")
4180 % (branch, len(bheads)),
4180 % (branch, len(bheads)),
4181 hint=_("run 'hg heads .' to see heads"))
4181 hint=_("run 'hg heads .' to see heads"))
4182
4182
4183 parent = repo.dirstate.p1()
4183 parent = repo.dirstate.p1()
4184 if len(nbhs) <= 1:
4184 if len(nbhs) <= 1:
4185 if len(bheads) > 1:
4185 if len(bheads) > 1:
4186 raise util.Abort(_("heads are bookmarked - "
4186 raise util.Abort(_("heads are bookmarked - "
4187 "please merge with an explicit rev"),
4187 "please merge with an explicit rev"),
4188 hint=_("run 'hg heads' to see all heads"))
4188 hint=_("run 'hg heads' to see all heads"))
4189 if len(repo.heads()) > 1:
4189 if len(repo.heads()) > 1:
4190 raise util.Abort(_("branch '%s' has one head - "
4190 raise util.Abort(_("branch '%s' has one head - "
4191 "please merge with an explicit rev")
4191 "please merge with an explicit rev")
4192 % branch,
4192 % branch,
4193 hint=_("run 'hg heads' to see all heads"))
4193 hint=_("run 'hg heads' to see all heads"))
4194 msg, hint = _('nothing to merge'), None
4194 msg, hint = _('nothing to merge'), None
4195 if parent != repo.lookup(branch):
4195 if parent != repo.lookup(branch):
4196 hint = _("use 'hg update' instead")
4196 hint = _("use 'hg update' instead")
4197 raise util.Abort(msg, hint=hint)
4197 raise util.Abort(msg, hint=hint)
4198
4198
4199 if parent not in bheads:
4199 if parent not in bheads:
4200 raise util.Abort(_('working directory not at a head revision'),
4200 raise util.Abort(_('working directory not at a head revision'),
4201 hint=_("use 'hg update' or merge with an "
4201 hint=_("use 'hg update' or merge with an "
4202 "explicit revision"))
4202 "explicit revision"))
4203 if parent == nbhs[0]:
4203 if parent == nbhs[0]:
4204 node = nbhs[-1]
4204 node = nbhs[-1]
4205 else:
4205 else:
4206 node = nbhs[0]
4206 node = nbhs[0]
4207
4207
4208 if opts.get('preview'):
4208 if opts.get('preview'):
4209 # find nodes that are ancestors of p2 but not of p1
4209 # find nodes that are ancestors of p2 but not of p1
4210 p1 = repo.lookup('.')
4210 p1 = repo.lookup('.')
4211 p2 = repo.lookup(node)
4211 p2 = repo.lookup(node)
4212 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4212 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4213
4213
4214 displayer = cmdutil.show_changeset(ui, repo, opts)
4214 displayer = cmdutil.show_changeset(ui, repo, opts)
4215 for node in nodes:
4215 for node in nodes:
4216 displayer.show(repo[node])
4216 displayer.show(repo[node])
4217 displayer.close()
4217 displayer.close()
4218 return 0
4218 return 0
4219
4219
4220 try:
4220 try:
4221 # ui.forcemerge is an internal variable, do not document
4221 # ui.forcemerge is an internal variable, do not document
4222 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4222 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4223 return hg.merge(repo, node, force=opts.get('force'))
4223 return hg.merge(repo, node, force=opts.get('force'))
4224 finally:
4224 finally:
4225 ui.setconfig('ui', 'forcemerge', '')
4225 ui.setconfig('ui', 'forcemerge', '')
4226
4226
4227 @command('outgoing|out',
4227 @command('outgoing|out',
4228 [('f', 'force', None, _('run even when the destination is unrelated')),
4228 [('f', 'force', None, _('run even when the destination is unrelated')),
4229 ('r', 'rev', [],
4229 ('r', 'rev', [],
4230 _('a changeset intended to be included in the destination'), _('REV')),
4230 _('a changeset intended to be included in the destination'), _('REV')),
4231 ('n', 'newest-first', None, _('show newest record first')),
4231 ('n', 'newest-first', None, _('show newest record first')),
4232 ('B', 'bookmarks', False, _('compare bookmarks')),
4232 ('B', 'bookmarks', False, _('compare bookmarks')),
4233 ('b', 'branch', [], _('a specific branch you would like to push'),
4233 ('b', 'branch', [], _('a specific branch you would like to push'),
4234 _('BRANCH')),
4234 _('BRANCH')),
4235 ] + logopts + remoteopts + subrepoopts,
4235 ] + logopts + remoteopts + subrepoopts,
4236 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4236 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4237 def outgoing(ui, repo, dest=None, **opts):
4237 def outgoing(ui, repo, dest=None, **opts):
4238 """show changesets not found in the destination
4238 """show changesets not found in the destination
4239
4239
4240 Show changesets not found in the specified destination repository
4240 Show changesets not found in the specified destination repository
4241 or the default push location. These are the changesets that would
4241 or the default push location. These are the changesets that would
4242 be pushed if a push was requested.
4242 be pushed if a push was requested.
4243
4243
4244 See pull for details of valid destination formats.
4244 See pull for details of valid destination formats.
4245
4245
4246 Returns 0 if there are outgoing changes, 1 otherwise.
4246 Returns 0 if there are outgoing changes, 1 otherwise.
4247 """
4247 """
4248 if opts.get('graph'):
4248 if opts.get('graph'):
4249 cmdutil.checkunsupportedgraphflags([], opts)
4249 cmdutil.checkunsupportedgraphflags([], opts)
4250 o = hg._outgoing(ui, repo, dest, opts)
4250 o = hg._outgoing(ui, repo, dest, opts)
4251 if o is None:
4251 if o is None:
4252 return
4252 return
4253
4253
4254 revdag = cmdutil.graphrevs(repo, o, opts)
4254 revdag = cmdutil.graphrevs(repo, o, opts)
4255 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4255 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4256 showparents = [ctx.node() for ctx in repo[None].parents()]
4256 showparents = [ctx.node() for ctx in repo[None].parents()]
4257 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4257 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4258 graphmod.asciiedges)
4258 graphmod.asciiedges)
4259 return 0
4259 return 0
4260
4260
4261 if opts.get('bookmarks'):
4261 if opts.get('bookmarks'):
4262 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4262 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4263 dest, branches = hg.parseurl(dest, opts.get('branch'))
4263 dest, branches = hg.parseurl(dest, opts.get('branch'))
4264 other = hg.peer(repo, opts, dest)
4264 other = hg.peer(repo, opts, dest)
4265 if 'bookmarks' not in other.listkeys('namespaces'):
4265 if 'bookmarks' not in other.listkeys('namespaces'):
4266 ui.warn(_("remote doesn't support bookmarks\n"))
4266 ui.warn(_("remote doesn't support bookmarks\n"))
4267 return 0
4267 return 0
4268 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4268 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4269 return bookmarks.diff(ui, other, repo)
4269 return bookmarks.diff(ui, other, repo)
4270
4270
4271 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4271 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4272 try:
4272 try:
4273 return hg.outgoing(ui, repo, dest, opts)
4273 return hg.outgoing(ui, repo, dest, opts)
4274 finally:
4274 finally:
4275 del repo._subtoppath
4275 del repo._subtoppath
4276
4276
4277 @command('parents',
4277 @command('parents',
4278 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4278 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4279 ] + templateopts,
4279 ] + templateopts,
4280 _('[-r REV] [FILE]'))
4280 _('[-r REV] [FILE]'))
4281 def parents(ui, repo, file_=None, **opts):
4281 def parents(ui, repo, file_=None, **opts):
4282 """show the parents of the working directory or revision
4282 """show the parents of the working directory or revision
4283
4283
4284 Print the working directory's parent revisions. If a revision is
4284 Print the working directory's parent revisions. If a revision is
4285 given via -r/--rev, the parent of that revision will be printed.
4285 given via -r/--rev, the parent of that revision will be printed.
4286 If a file argument is given, the revision in which the file was
4286 If a file argument is given, the revision in which the file was
4287 last changed (before the working directory revision or the
4287 last changed (before the working directory revision or the
4288 argument to --rev if given) is printed.
4288 argument to --rev if given) is printed.
4289
4289
4290 Returns 0 on success.
4290 Returns 0 on success.
4291 """
4291 """
4292
4292
4293 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4293 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4294
4294
4295 if file_:
4295 if file_:
4296 m = scmutil.match(ctx, (file_,), opts)
4296 m = scmutil.match(ctx, (file_,), opts)
4297 if m.anypats() or len(m.files()) != 1:
4297 if m.anypats() or len(m.files()) != 1:
4298 raise util.Abort(_('can only specify an explicit filename'))
4298 raise util.Abort(_('can only specify an explicit filename'))
4299 file_ = m.files()[0]
4299 file_ = m.files()[0]
4300 filenodes = []
4300 filenodes = []
4301 for cp in ctx.parents():
4301 for cp in ctx.parents():
4302 if not cp:
4302 if not cp:
4303 continue
4303 continue
4304 try:
4304 try:
4305 filenodes.append(cp.filenode(file_))
4305 filenodes.append(cp.filenode(file_))
4306 except error.LookupError:
4306 except error.LookupError:
4307 pass
4307 pass
4308 if not filenodes:
4308 if not filenodes:
4309 raise util.Abort(_("'%s' not found in manifest!") % file_)
4309 raise util.Abort(_("'%s' not found in manifest!") % file_)
4310 fl = repo.file(file_)
4310 fl = repo.file(file_)
4311 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4311 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4312 else:
4312 else:
4313 p = [cp.node() for cp in ctx.parents()]
4313 p = [cp.node() for cp in ctx.parents()]
4314
4314
4315 displayer = cmdutil.show_changeset(ui, repo, opts)
4315 displayer = cmdutil.show_changeset(ui, repo, opts)
4316 for n in p:
4316 for n in p:
4317 if n != nullid:
4317 if n != nullid:
4318 displayer.show(repo[n])
4318 displayer.show(repo[n])
4319 displayer.close()
4319 displayer.close()
4320
4320
4321 @command('paths', [], _('[NAME]'))
4321 @command('paths', [], _('[NAME]'))
4322 def paths(ui, repo, search=None):
4322 def paths(ui, repo, search=None):
4323 """show aliases for remote repositories
4323 """show aliases for remote repositories
4324
4324
4325 Show definition of symbolic path name NAME. If no name is given,
4325 Show definition of symbolic path name NAME. If no name is given,
4326 show definition of all available names.
4326 show definition of all available names.
4327
4327
4328 Option -q/--quiet suppresses all output when searching for NAME
4328 Option -q/--quiet suppresses all output when searching for NAME
4329 and shows only the path names when listing all definitions.
4329 and shows only the path names when listing all definitions.
4330
4330
4331 Path names are defined in the [paths] section of your
4331 Path names are defined in the [paths] section of your
4332 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4332 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4333 repository, ``.hg/hgrc`` is used, too.
4333 repository, ``.hg/hgrc`` is used, too.
4334
4334
4335 The path names ``default`` and ``default-push`` have a special
4335 The path names ``default`` and ``default-push`` have a special
4336 meaning. When performing a push or pull operation, they are used
4336 meaning. When performing a push or pull operation, they are used
4337 as fallbacks if no location is specified on the command-line.
4337 as fallbacks if no location is specified on the command-line.
4338 When ``default-push`` is set, it will be used for push and
4338 When ``default-push`` is set, it will be used for push and
4339 ``default`` will be used for pull; otherwise ``default`` is used
4339 ``default`` will be used for pull; otherwise ``default`` is used
4340 as the fallback for both. When cloning a repository, the clone
4340 as the fallback for both. When cloning a repository, the clone
4341 source is written as ``default`` in ``.hg/hgrc``. Note that
4341 source is written as ``default`` in ``.hg/hgrc``. Note that
4342 ``default`` and ``default-push`` apply to all inbound (e.g.
4342 ``default`` and ``default-push`` apply to all inbound (e.g.
4343 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4343 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4344 :hg:`bundle`) operations.
4344 :hg:`bundle`) operations.
4345
4345
4346 See :hg:`help urls` for more information.
4346 See :hg:`help urls` for more information.
4347
4347
4348 Returns 0 on success.
4348 Returns 0 on success.
4349 """
4349 """
4350 if search:
4350 if search:
4351 for name, path in ui.configitems("paths"):
4351 for name, path in ui.configitems("paths"):
4352 if name == search:
4352 if name == search:
4353 ui.status("%s\n" % util.hidepassword(path))
4353 ui.status("%s\n" % util.hidepassword(path))
4354 return
4354 return
4355 if not ui.quiet:
4355 if not ui.quiet:
4356 ui.warn(_("not found!\n"))
4356 ui.warn(_("not found!\n"))
4357 return 1
4357 return 1
4358 else:
4358 else:
4359 for name, path in ui.configitems("paths"):
4359 for name, path in ui.configitems("paths"):
4360 if ui.quiet:
4360 if ui.quiet:
4361 ui.write("%s\n" % name)
4361 ui.write("%s\n" % name)
4362 else:
4362 else:
4363 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4363 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4364
4364
4365 @command('phase',
4365 @command('phase',
4366 [('p', 'public', False, _('set changeset phase to public')),
4366 [('p', 'public', False, _('set changeset phase to public')),
4367 ('d', 'draft', False, _('set changeset phase to draft')),
4367 ('d', 'draft', False, _('set changeset phase to draft')),
4368 ('s', 'secret', False, _('set changeset phase to secret')),
4368 ('s', 'secret', False, _('set changeset phase to secret')),
4369 ('f', 'force', False, _('allow to move boundary backward')),
4369 ('f', 'force', False, _('allow to move boundary backward')),
4370 ('r', 'rev', [], _('target revision'), _('REV')),
4370 ('r', 'rev', [], _('target revision'), _('REV')),
4371 ],
4371 ],
4372 _('[-p|-d|-s] [-f] [-r] REV...'))
4372 _('[-p|-d|-s] [-f] [-r] REV...'))
4373 def phase(ui, repo, *revs, **opts):
4373 def phase(ui, repo, *revs, **opts):
4374 """set or show the current phase name
4374 """set or show the current phase name
4375
4375
4376 With no argument, show the phase name of specified revisions.
4376 With no argument, show the phase name of specified revisions.
4377
4377
4378 With one of -p/--public, -d/--draft or -s/--secret, change the
4378 With one of -p/--public, -d/--draft or -s/--secret, change the
4379 phase value of the specified revisions.
4379 phase value of the specified revisions.
4380
4380
4381 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4381 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4382 lower phase to an higher phase. Phases are ordered as follows::
4382 lower phase to an higher phase. Phases are ordered as follows::
4383
4383
4384 public < draft < secret
4384 public < draft < secret
4385
4385
4386 Return 0 on success, 1 if no phases were changed or some could not
4386 Return 0 on success, 1 if no phases were changed or some could not
4387 be changed.
4387 be changed.
4388 """
4388 """
4389 # search for a unique phase argument
4389 # search for a unique phase argument
4390 targetphase = None
4390 targetphase = None
4391 for idx, name in enumerate(phases.phasenames):
4391 for idx, name in enumerate(phases.phasenames):
4392 if opts[name]:
4392 if opts[name]:
4393 if targetphase is not None:
4393 if targetphase is not None:
4394 raise util.Abort(_('only one phase can be specified'))
4394 raise util.Abort(_('only one phase can be specified'))
4395 targetphase = idx
4395 targetphase = idx
4396
4396
4397 # look for specified revision
4397 # look for specified revision
4398 revs = list(revs)
4398 revs = list(revs)
4399 revs.extend(opts['rev'])
4399 revs.extend(opts['rev'])
4400 if not revs:
4400 if not revs:
4401 raise util.Abort(_('no revisions specified'))
4401 raise util.Abort(_('no revisions specified'))
4402
4402
4403 revs = scmutil.revrange(repo, revs)
4403 revs = scmutil.revrange(repo, revs)
4404
4404
4405 lock = None
4405 lock = None
4406 ret = 0
4406 ret = 0
4407 if targetphase is None:
4407 if targetphase is None:
4408 # display
4408 # display
4409 for r in revs:
4409 for r in revs:
4410 ctx = repo[r]
4410 ctx = repo[r]
4411 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4411 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4412 else:
4412 else:
4413 lock = repo.lock()
4413 lock = repo.lock()
4414 try:
4414 try:
4415 # set phase
4415 # set phase
4416 if not revs:
4416 if not revs:
4417 raise util.Abort(_('empty revision set'))
4417 raise util.Abort(_('empty revision set'))
4418 nodes = [repo[r].node() for r in revs]
4418 nodes = [repo[r].node() for r in revs]
4419 olddata = repo._phasecache.getphaserevs(repo)[:]
4419 olddata = repo._phasecache.getphaserevs(repo)[:]
4420 phases.advanceboundary(repo, targetphase, nodes)
4420 phases.advanceboundary(repo, targetphase, nodes)
4421 if opts['force']:
4421 if opts['force']:
4422 phases.retractboundary(repo, targetphase, nodes)
4422 phases.retractboundary(repo, targetphase, nodes)
4423 finally:
4423 finally:
4424 lock.release()
4424 lock.release()
4425 # moving revision from public to draft may hide them
4425 # moving revision from public to draft may hide them
4426 # We have to check result on an unfiltered repository
4426 # We have to check result on an unfiltered repository
4427 unfi = repo.unfiltered()
4427 unfi = repo.unfiltered()
4428 newdata = repo._phasecache.getphaserevs(unfi)
4428 newdata = repo._phasecache.getphaserevs(unfi)
4429 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4429 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4430 cl = unfi.changelog
4430 cl = unfi.changelog
4431 rejected = [n for n in nodes
4431 rejected = [n for n in nodes
4432 if newdata[cl.rev(n)] < targetphase]
4432 if newdata[cl.rev(n)] < targetphase]
4433 if rejected:
4433 if rejected:
4434 ui.warn(_('cannot move %i changesets to a more permissive '
4434 ui.warn(_('cannot move %i changesets to a more permissive '
4435 'phase, use --force\n') % len(rejected))
4435 'phase, use --force\n') % len(rejected))
4436 ret = 1
4436 ret = 1
4437 if changes:
4437 if changes:
4438 msg = _('phase changed for %i changesets\n') % changes
4438 msg = _('phase changed for %i changesets\n') % changes
4439 if ret:
4439 if ret:
4440 ui.status(msg)
4440 ui.status(msg)
4441 else:
4441 else:
4442 ui.note(msg)
4442 ui.note(msg)
4443 else:
4443 else:
4444 ui.warn(_('no phases changed\n'))
4444 ui.warn(_('no phases changed\n'))
4445 ret = 1
4445 ret = 1
4446 return ret
4446 return ret
4447
4447
4448 def postincoming(ui, repo, modheads, optupdate, checkout):
4448 def postincoming(ui, repo, modheads, optupdate, checkout):
4449 if modheads == 0:
4449 if modheads == 0:
4450 return
4450 return
4451 if optupdate:
4451 if optupdate:
4452 movemarkfrom = repo['.'].node()
4452 movemarkfrom = repo['.'].node()
4453 try:
4453 try:
4454 ret = hg.update(repo, checkout)
4454 ret = hg.update(repo, checkout)
4455 except util.Abort, inst:
4455 except util.Abort, inst:
4456 ui.warn(_("not updating: %s\n") % str(inst))
4456 ui.warn(_("not updating: %s\n") % str(inst))
4457 return 0
4457 return 0
4458 if not ret and not checkout:
4458 if not ret and not checkout:
4459 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4459 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4460 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4460 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4461 return ret
4461 return ret
4462 if modheads > 1:
4462 if modheads > 1:
4463 currentbranchheads = len(repo.branchheads())
4463 currentbranchheads = len(repo.branchheads())
4464 if currentbranchheads == modheads:
4464 if currentbranchheads == modheads:
4465 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4465 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4466 elif currentbranchheads > 1:
4466 elif currentbranchheads > 1:
4467 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4467 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4468 "merge)\n"))
4468 "merge)\n"))
4469 else:
4469 else:
4470 ui.status(_("(run 'hg heads' to see heads)\n"))
4470 ui.status(_("(run 'hg heads' to see heads)\n"))
4471 else:
4471 else:
4472 ui.status(_("(run 'hg update' to get a working copy)\n"))
4472 ui.status(_("(run 'hg update' to get a working copy)\n"))
4473
4473
4474 @command('^pull',
4474 @command('^pull',
4475 [('u', 'update', None,
4475 [('u', 'update', None,
4476 _('update to new branch head if changesets were pulled')),
4476 _('update to new branch head if changesets were pulled')),
4477 ('f', 'force', None, _('run even when remote repository is unrelated')),
4477 ('f', 'force', None, _('run even when remote repository is unrelated')),
4478 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4478 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4479 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4479 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4480 ('b', 'branch', [], _('a specific branch you would like to pull'),
4480 ('b', 'branch', [], _('a specific branch you would like to pull'),
4481 _('BRANCH')),
4481 _('BRANCH')),
4482 ] + remoteopts,
4482 ] + remoteopts,
4483 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4483 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4484 def pull(ui, repo, source="default", **opts):
4484 def pull(ui, repo, source="default", **opts):
4485 """pull changes from the specified source
4485 """pull changes from the specified source
4486
4486
4487 Pull changes from a remote repository to a local one.
4487 Pull changes from a remote repository to a local one.
4488
4488
4489 This finds all changes from the repository at the specified path
4489 This finds all changes from the repository at the specified path
4490 or URL and adds them to a local repository (the current one unless
4490 or URL and adds them to a local repository (the current one unless
4491 -R is specified). By default, this does not update the copy of the
4491 -R is specified). By default, this does not update the copy of the
4492 project in the working directory.
4492 project in the working directory.
4493
4493
4494 Use :hg:`incoming` if you want to see what would have been added
4494 Use :hg:`incoming` if you want to see what would have been added
4495 by a pull at the time you issued this command. If you then decide
4495 by a pull at the time you issued this command. If you then decide
4496 to add those changes to the repository, you should use :hg:`pull
4496 to add those changes to the repository, you should use :hg:`pull
4497 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4497 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4498
4498
4499 If SOURCE is omitted, the 'default' path will be used.
4499 If SOURCE is omitted, the 'default' path will be used.
4500 See :hg:`help urls` for more information.
4500 See :hg:`help urls` for more information.
4501
4501
4502 Returns 0 on success, 1 if an update had unresolved files.
4502 Returns 0 on success, 1 if an update had unresolved files.
4503 """
4503 """
4504 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4504 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4505 other = hg.peer(repo, opts, source)
4505 other = hg.peer(repo, opts, source)
4506 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4506 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4507 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4507 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4508
4508
4509 remotebookmarks = other.listkeys('bookmarks')
4509 remotebookmarks = other.listkeys('bookmarks')
4510
4510
4511 if opts.get('bookmark'):
4511 if opts.get('bookmark'):
4512 if not revs:
4512 if not revs:
4513 revs = []
4513 revs = []
4514 for b in opts['bookmark']:
4514 for b in opts['bookmark']:
4515 if b not in remotebookmarks:
4515 if b not in remotebookmarks:
4516 raise util.Abort(_('remote bookmark %s not found!') % b)
4516 raise util.Abort(_('remote bookmark %s not found!') % b)
4517 revs.append(remotebookmarks[b])
4517 revs.append(remotebookmarks[b])
4518
4518
4519 if revs:
4519 if revs:
4520 try:
4520 try:
4521 revs = [other.lookup(rev) for rev in revs]
4521 revs = [other.lookup(rev) for rev in revs]
4522 except error.CapabilityError:
4522 except error.CapabilityError:
4523 err = _("other repository doesn't support revision lookup, "
4523 err = _("other repository doesn't support revision lookup, "
4524 "so a rev cannot be specified.")
4524 "so a rev cannot be specified.")
4525 raise util.Abort(err)
4525 raise util.Abort(err)
4526
4526
4527 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4527 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4528 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4528 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4529 if checkout:
4529 if checkout:
4530 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4530 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4531 repo._subtoppath = source
4531 repo._subtoppath = source
4532 try:
4532 try:
4533 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4533 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4534
4534
4535 finally:
4535 finally:
4536 del repo._subtoppath
4536 del repo._subtoppath
4537
4537
4538 # update specified bookmarks
4538 # update specified bookmarks
4539 if opts.get('bookmark'):
4539 if opts.get('bookmark'):
4540 marks = repo._bookmarks
4540 marks = repo._bookmarks
4541 for b in opts['bookmark']:
4541 for b in opts['bookmark']:
4542 # explicit pull overrides local bookmark if any
4542 # explicit pull overrides local bookmark if any
4543 ui.status(_("importing bookmark %s\n") % b)
4543 ui.status(_("importing bookmark %s\n") % b)
4544 marks[b] = repo[remotebookmarks[b]].node()
4544 marks[b] = repo[remotebookmarks[b]].node()
4545 marks.write()
4545 marks.write()
4546
4546
4547 return ret
4547 return ret
4548
4548
4549 @command('^push',
4549 @command('^push',
4550 [('f', 'force', None, _('force push')),
4550 [('f', 'force', None, _('force push')),
4551 ('r', 'rev', [],
4551 ('r', 'rev', [],
4552 _('a changeset intended to be included in the destination'),
4552 _('a changeset intended to be included in the destination'),
4553 _('REV')),
4553 _('REV')),
4554 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4554 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4555 ('b', 'branch', [],
4555 ('b', 'branch', [],
4556 _('a specific branch you would like to push'), _('BRANCH')),
4556 _('a specific branch you would like to push'), _('BRANCH')),
4557 ('', 'new-branch', False, _('allow pushing a new branch')),
4557 ('', 'new-branch', False, _('allow pushing a new branch')),
4558 ] + remoteopts,
4558 ] + remoteopts,
4559 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4559 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4560 def push(ui, repo, dest=None, **opts):
4560 def push(ui, repo, dest=None, **opts):
4561 """push changes to the specified destination
4561 """push changes to the specified destination
4562
4562
4563 Push changesets from the local repository to the specified
4563 Push changesets from the local repository to the specified
4564 destination.
4564 destination.
4565
4565
4566 This operation is symmetrical to pull: it is identical to a pull
4566 This operation is symmetrical to pull: it is identical to a pull
4567 in the destination repository from the current one.
4567 in the destination repository from the current one.
4568
4568
4569 By default, push will not allow creation of new heads at the
4569 By default, push will not allow creation of new heads at the
4570 destination, since multiple heads would make it unclear which head
4570 destination, since multiple heads would make it unclear which head
4571 to use. In this situation, it is recommended to pull and merge
4571 to use. In this situation, it is recommended to pull and merge
4572 before pushing.
4572 before pushing.
4573
4573
4574 Use --new-branch if you want to allow push to create a new named
4574 Use --new-branch if you want to allow push to create a new named
4575 branch that is not present at the destination. This allows you to
4575 branch that is not present at the destination. This allows you to
4576 only create a new branch without forcing other changes.
4576 only create a new branch without forcing other changes.
4577
4577
4578 Use -f/--force to override the default behavior and push all
4578 Use -f/--force to override the default behavior and push all
4579 changesets on all branches.
4579 changesets on all branches.
4580
4580
4581 If -r/--rev is used, the specified revision and all its ancestors
4581 If -r/--rev is used, the specified revision and all its ancestors
4582 will be pushed to the remote repository.
4582 will be pushed to the remote repository.
4583
4583
4584 If -B/--bookmark is used, the specified bookmarked revision, its
4584 If -B/--bookmark is used, the specified bookmarked revision, its
4585 ancestors, and the bookmark will be pushed to the remote
4585 ancestors, and the bookmark will be pushed to the remote
4586 repository.
4586 repository.
4587
4587
4588 Please see :hg:`help urls` for important details about ``ssh://``
4588 Please see :hg:`help urls` for important details about ``ssh://``
4589 URLs. If DESTINATION is omitted, a default path will be used.
4589 URLs. If DESTINATION is omitted, a default path will be used.
4590
4590
4591 Returns 0 if push was successful, 1 if nothing to push.
4591 Returns 0 if push was successful, 1 if nothing to push.
4592 """
4592 """
4593
4593
4594 if opts.get('bookmark'):
4594 if opts.get('bookmark'):
4595 for b in opts['bookmark']:
4595 for b in opts['bookmark']:
4596 # translate -B options to -r so changesets get pushed
4596 # translate -B options to -r so changesets get pushed
4597 if b in repo._bookmarks:
4597 if b in repo._bookmarks:
4598 opts.setdefault('rev', []).append(b)
4598 opts.setdefault('rev', []).append(b)
4599 else:
4599 else:
4600 # if we try to push a deleted bookmark, translate it to null
4600 # if we try to push a deleted bookmark, translate it to null
4601 # this lets simultaneous -r, -b options continue working
4601 # this lets simultaneous -r, -b options continue working
4602 opts.setdefault('rev', []).append("null")
4602 opts.setdefault('rev', []).append("null")
4603
4603
4604 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4604 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4605 dest, branches = hg.parseurl(dest, opts.get('branch'))
4605 dest, branches = hg.parseurl(dest, opts.get('branch'))
4606 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4606 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4607 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4607 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4608 other = hg.peer(repo, opts, dest)
4608 other = hg.peer(repo, opts, dest)
4609 if revs:
4609 if revs:
4610 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4610 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4611
4611
4612 repo._subtoppath = dest
4612 repo._subtoppath = dest
4613 try:
4613 try:
4614 # push subrepos depth-first for coherent ordering
4614 # push subrepos depth-first for coherent ordering
4615 c = repo['']
4615 c = repo['']
4616 subs = c.substate # only repos that are committed
4616 subs = c.substate # only repos that are committed
4617 for s in sorted(subs):
4617 for s in sorted(subs):
4618 if c.sub(s).push(opts) == 0:
4618 if c.sub(s).push(opts) == 0:
4619 return False
4619 return False
4620 finally:
4620 finally:
4621 del repo._subtoppath
4621 del repo._subtoppath
4622 result = repo.push(other, opts.get('force'), revs=revs,
4622 result = repo.push(other, opts.get('force'), revs=revs,
4623 newbranch=opts.get('new_branch'))
4623 newbranch=opts.get('new_branch'))
4624
4624
4625 result = not result
4625 result = not result
4626
4626
4627 if opts.get('bookmark'):
4627 if opts.get('bookmark'):
4628 rb = other.listkeys('bookmarks')
4628 rb = other.listkeys('bookmarks')
4629 for b in opts['bookmark']:
4629 for b in opts['bookmark']:
4630 # explicit push overrides remote bookmark if any
4630 # explicit push overrides remote bookmark if any
4631 if b in repo._bookmarks:
4631 if b in repo._bookmarks:
4632 ui.status(_("exporting bookmark %s\n") % b)
4632 ui.status(_("exporting bookmark %s\n") % b)
4633 new = repo[b].hex()
4633 new = repo[b].hex()
4634 elif b in rb:
4634 elif b in rb:
4635 ui.status(_("deleting remote bookmark %s\n") % b)
4635 ui.status(_("deleting remote bookmark %s\n") % b)
4636 new = '' # delete
4636 new = '' # delete
4637 else:
4637 else:
4638 ui.warn(_('bookmark %s does not exist on the local '
4638 ui.warn(_('bookmark %s does not exist on the local '
4639 'or remote repository!\n') % b)
4639 'or remote repository!\n') % b)
4640 return 2
4640 return 2
4641 old = rb.get(b, '')
4641 old = rb.get(b, '')
4642 r = other.pushkey('bookmarks', b, old, new)
4642 r = other.pushkey('bookmarks', b, old, new)
4643 if not r:
4643 if not r:
4644 ui.warn(_('updating bookmark %s failed!\n') % b)
4644 ui.warn(_('updating bookmark %s failed!\n') % b)
4645 if not result:
4645 if not result:
4646 result = 2
4646 result = 2
4647
4647
4648 return result
4648 return result
4649
4649
4650 @command('recover', [])
4650 @command('recover', [])
4651 def recover(ui, repo):
4651 def recover(ui, repo):
4652 """roll back an interrupted transaction
4652 """roll back an interrupted transaction
4653
4653
4654 Recover from an interrupted commit or pull.
4654 Recover from an interrupted commit or pull.
4655
4655
4656 This command tries to fix the repository status after an
4656 This command tries to fix the repository status after an
4657 interrupted operation. It should only be necessary when Mercurial
4657 interrupted operation. It should only be necessary when Mercurial
4658 suggests it.
4658 suggests it.
4659
4659
4660 Returns 0 if successful, 1 if nothing to recover or verify fails.
4660 Returns 0 if successful, 1 if nothing to recover or verify fails.
4661 """
4661 """
4662 if repo.recover():
4662 if repo.recover():
4663 return hg.verify(repo)
4663 return hg.verify(repo)
4664 return 1
4664 return 1
4665
4665
4666 @command('^remove|rm',
4666 @command('^remove|rm',
4667 [('A', 'after', None, _('record delete for missing files')),
4667 [('A', 'after', None, _('record delete for missing files')),
4668 ('f', 'force', None,
4668 ('f', 'force', None,
4669 _('remove (and delete) file even if added or modified')),
4669 _('remove (and delete) file even if added or modified')),
4670 ] + walkopts,
4670 ] + walkopts,
4671 _('[OPTION]... FILE...'))
4671 _('[OPTION]... FILE...'))
4672 def remove(ui, repo, *pats, **opts):
4672 def remove(ui, repo, *pats, **opts):
4673 """remove the specified files on the next commit
4673 """remove the specified files on the next commit
4674
4674
4675 Schedule the indicated files for removal from the current branch.
4675 Schedule the indicated files for removal from the current branch.
4676
4676
4677 This command schedules the files to be removed at the next commit.
4677 This command schedules the files to be removed at the next commit.
4678 To undo a remove before that, see :hg:`revert`. To undo added
4678 To undo a remove before that, see :hg:`revert`. To undo added
4679 files, see :hg:`forget`.
4679 files, see :hg:`forget`.
4680
4680
4681 .. container:: verbose
4681 .. container:: verbose
4682
4682
4683 -A/--after can be used to remove only files that have already
4683 -A/--after can be used to remove only files that have already
4684 been deleted, -f/--force can be used to force deletion, and -Af
4684 been deleted, -f/--force can be used to force deletion, and -Af
4685 can be used to remove files from the next revision without
4685 can be used to remove files from the next revision without
4686 deleting them from the working directory.
4686 deleting them from the working directory.
4687
4687
4688 The following table details the behavior of remove for different
4688 The following table details the behavior of remove for different
4689 file states (columns) and option combinations (rows). The file
4689 file states (columns) and option combinations (rows). The file
4690 states are Added [A], Clean [C], Modified [M] and Missing [!]
4690 states are Added [A], Clean [C], Modified [M] and Missing [!]
4691 (as reported by :hg:`status`). The actions are Warn, Remove
4691 (as reported by :hg:`status`). The actions are Warn, Remove
4692 (from branch) and Delete (from disk):
4692 (from branch) and Delete (from disk):
4693
4693
4694 ======= == == == ==
4694 ======= == == == ==
4695 A C M !
4695 A C M !
4696 ======= == == == ==
4696 ======= == == == ==
4697 none W RD W R
4697 none W RD W R
4698 -f R RD RD R
4698 -f R RD RD R
4699 -A W W W R
4699 -A W W W R
4700 -Af R R R R
4700 -Af R R R R
4701 ======= == == == ==
4701 ======= == == == ==
4702
4702
4703 Note that remove never deletes files in Added [A] state from the
4703 Note that remove never deletes files in Added [A] state from the
4704 working directory, not even if option --force is specified.
4704 working directory, not even if option --force is specified.
4705
4705
4706 Returns 0 on success, 1 if any warnings encountered.
4706 Returns 0 on success, 1 if any warnings encountered.
4707 """
4707 """
4708
4708
4709 ret = 0
4709 ret = 0
4710 after, force = opts.get('after'), opts.get('force')
4710 after, force = opts.get('after'), opts.get('force')
4711 if not pats and not after:
4711 if not pats and not after:
4712 raise util.Abort(_('no files specified'))
4712 raise util.Abort(_('no files specified'))
4713
4713
4714 m = scmutil.match(repo[None], pats, opts)
4714 m = scmutil.match(repo[None], pats, opts)
4715 s = repo.status(match=m, clean=True)
4715 s = repo.status(match=m, clean=True)
4716 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4716 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4717
4717
4718 # warn about failure to delete explicit files/dirs
4718 # warn about failure to delete explicit files/dirs
4719 wctx = repo[None]
4719 wctx = repo[None]
4720 for f in m.files():
4720 for f in m.files():
4721 if f in repo.dirstate or f in wctx.dirs():
4721 if f in repo.dirstate or f in wctx.dirs():
4722 continue
4722 continue
4723 if os.path.exists(m.rel(f)):
4723 if os.path.exists(m.rel(f)):
4724 if os.path.isdir(m.rel(f)):
4724 if os.path.isdir(m.rel(f)):
4725 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4725 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4726 else:
4726 else:
4727 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4727 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4728 # missing files will generate a warning elsewhere
4728 # missing files will generate a warning elsewhere
4729 ret = 1
4729 ret = 1
4730
4730
4731 if force:
4731 if force:
4732 list = modified + deleted + clean + added
4732 list = modified + deleted + clean + added
4733 elif after:
4733 elif after:
4734 list = deleted
4734 list = deleted
4735 for f in modified + added + clean:
4735 for f in modified + added + clean:
4736 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4736 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4737 ret = 1
4737 ret = 1
4738 else:
4738 else:
4739 list = deleted + clean
4739 list = deleted + clean
4740 for f in modified:
4740 for f in modified:
4741 ui.warn(_('not removing %s: file is modified (use -f'
4741 ui.warn(_('not removing %s: file is modified (use -f'
4742 ' to force removal)\n') % m.rel(f))
4742 ' to force removal)\n') % m.rel(f))
4743 ret = 1
4743 ret = 1
4744 for f in added:
4744 for f in added:
4745 ui.warn(_('not removing %s: file has been marked for add'
4745 ui.warn(_('not removing %s: file has been marked for add'
4746 ' (use forget to undo)\n') % m.rel(f))
4746 ' (use forget to undo)\n') % m.rel(f))
4747 ret = 1
4747 ret = 1
4748
4748
4749 for f in sorted(list):
4749 for f in sorted(list):
4750 if ui.verbose or not m.exact(f):
4750 if ui.verbose or not m.exact(f):
4751 ui.status(_('removing %s\n') % m.rel(f))
4751 ui.status(_('removing %s\n') % m.rel(f))
4752
4752
4753 wlock = repo.wlock()
4753 wlock = repo.wlock()
4754 try:
4754 try:
4755 if not after:
4755 if not after:
4756 for f in list:
4756 for f in list:
4757 if f in added:
4757 if f in added:
4758 continue # we never unlink added files on remove
4758 continue # we never unlink added files on remove
4759 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4759 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4760 repo[None].forget(list)
4760 repo[None].forget(list)
4761 finally:
4761 finally:
4762 wlock.release()
4762 wlock.release()
4763
4763
4764 return ret
4764 return ret
4765
4765
4766 @command('rename|move|mv',
4766 @command('rename|move|mv',
4767 [('A', 'after', None, _('record a rename that has already occurred')),
4767 [('A', 'after', None, _('record a rename that has already occurred')),
4768 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4768 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4769 ] + walkopts + dryrunopts,
4769 ] + walkopts + dryrunopts,
4770 _('[OPTION]... SOURCE... DEST'))
4770 _('[OPTION]... SOURCE... DEST'))
4771 def rename(ui, repo, *pats, **opts):
4771 def rename(ui, repo, *pats, **opts):
4772 """rename files; equivalent of copy + remove
4772 """rename files; equivalent of copy + remove
4773
4773
4774 Mark dest as copies of sources; mark sources for deletion. If dest
4774 Mark dest as copies of sources; mark sources for deletion. If dest
4775 is a directory, copies are put in that directory. If dest is a
4775 is a directory, copies are put in that directory. If dest is a
4776 file, there can only be one source.
4776 file, there can only be one source.
4777
4777
4778 By default, this command copies the contents of files as they
4778 By default, this command copies the contents of files as they
4779 exist in the working directory. If invoked with -A/--after, the
4779 exist in the working directory. If invoked with -A/--after, the
4780 operation is recorded, but no copying is performed.
4780 operation is recorded, but no copying is performed.
4781
4781
4782 This command takes effect at the next commit. To undo a rename
4782 This command takes effect at the next commit. To undo a rename
4783 before that, see :hg:`revert`.
4783 before that, see :hg:`revert`.
4784
4784
4785 Returns 0 on success, 1 if errors are encountered.
4785 Returns 0 on success, 1 if errors are encountered.
4786 """
4786 """
4787 wlock = repo.wlock(False)
4787 wlock = repo.wlock(False)
4788 try:
4788 try:
4789 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4789 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4790 finally:
4790 finally:
4791 wlock.release()
4791 wlock.release()
4792
4792
4793 @command('resolve',
4793 @command('resolve',
4794 [('a', 'all', None, _('select all unresolved files')),
4794 [('a', 'all', None, _('select all unresolved files')),
4795 ('l', 'list', None, _('list state of files needing merge')),
4795 ('l', 'list', None, _('list state of files needing merge')),
4796 ('m', 'mark', None, _('mark files as resolved')),
4796 ('m', 'mark', None, _('mark files as resolved')),
4797 ('u', 'unmark', None, _('mark files as unresolved')),
4797 ('u', 'unmark', None, _('mark files as unresolved')),
4798 ('n', 'no-status', None, _('hide status prefix'))]
4798 ('n', 'no-status', None, _('hide status prefix'))]
4799 + mergetoolopts + walkopts,
4799 + mergetoolopts + walkopts,
4800 _('[OPTION]... [FILE]...'))
4800 _('[OPTION]... [FILE]...'))
4801 def resolve(ui, repo, *pats, **opts):
4801 def resolve(ui, repo, *pats, **opts):
4802 """redo merges or set/view the merge status of files
4802 """redo merges or set/view the merge status of files
4803
4803
4804 Merges with unresolved conflicts are often the result of
4804 Merges with unresolved conflicts are often the result of
4805 non-interactive merging using the ``internal:merge`` configuration
4805 non-interactive merging using the ``internal:merge`` configuration
4806 setting, or a command-line merge tool like ``diff3``. The resolve
4806 setting, or a command-line merge tool like ``diff3``. The resolve
4807 command is used to manage the files involved in a merge, after
4807 command is used to manage the files involved in a merge, after
4808 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4808 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4809 working directory must have two parents). See :hg:`help
4809 working directory must have two parents). See :hg:`help
4810 merge-tools` for information on configuring merge tools.
4810 merge-tools` for information on configuring merge tools.
4811
4811
4812 The resolve command can be used in the following ways:
4812 The resolve command can be used in the following ways:
4813
4813
4814 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4814 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4815 files, discarding any previous merge attempts. Re-merging is not
4815 files, discarding any previous merge attempts. Re-merging is not
4816 performed for files already marked as resolved. Use ``--all/-a``
4816 performed for files already marked as resolved. Use ``--all/-a``
4817 to select all unresolved files. ``--tool`` can be used to specify
4817 to select all unresolved files. ``--tool`` can be used to specify
4818 the merge tool used for the given files. It overrides the HGMERGE
4818 the merge tool used for the given files. It overrides the HGMERGE
4819 environment variable and your configuration files. Previous file
4819 environment variable and your configuration files. Previous file
4820 contents are saved with a ``.orig`` suffix.
4820 contents are saved with a ``.orig`` suffix.
4821
4821
4822 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4822 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4823 (e.g. after having manually fixed-up the files). The default is
4823 (e.g. after having manually fixed-up the files). The default is
4824 to mark all unresolved files.
4824 to mark all unresolved files.
4825
4825
4826 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4826 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4827 default is to mark all resolved files.
4827 default is to mark all resolved files.
4828
4828
4829 - :hg:`resolve -l`: list files which had or still have conflicts.
4829 - :hg:`resolve -l`: list files which had or still have conflicts.
4830 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4830 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4831
4831
4832 Note that Mercurial will not let you commit files with unresolved
4832 Note that Mercurial will not let you commit files with unresolved
4833 merge conflicts. You must use :hg:`resolve -m ...` before you can
4833 merge conflicts. You must use :hg:`resolve -m ...` before you can
4834 commit after a conflicting merge.
4834 commit after a conflicting merge.
4835
4835
4836 Returns 0 on success, 1 if any files fail a resolve attempt.
4836 Returns 0 on success, 1 if any files fail a resolve attempt.
4837 """
4837 """
4838
4838
4839 all, mark, unmark, show, nostatus = \
4839 all, mark, unmark, show, nostatus = \
4840 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4840 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4841
4841
4842 if (show and (mark or unmark)) or (mark and unmark):
4842 if (show and (mark or unmark)) or (mark and unmark):
4843 raise util.Abort(_("too many options specified"))
4843 raise util.Abort(_("too many options specified"))
4844 if pats and all:
4844 if pats and all:
4845 raise util.Abort(_("can't specify --all and patterns"))
4845 raise util.Abort(_("can't specify --all and patterns"))
4846 if not (all or pats or show or mark or unmark):
4846 if not (all or pats or show or mark or unmark):
4847 raise util.Abort(_('no files or directories specified; '
4847 raise util.Abort(_('no files or directories specified; '
4848 'use --all to remerge all files'))
4848 'use --all to remerge all files'))
4849
4849
4850 ms = mergemod.mergestate(repo)
4850 ms = mergemod.mergestate(repo)
4851 m = scmutil.match(repo[None], pats, opts)
4851 m = scmutil.match(repo[None], pats, opts)
4852 ret = 0
4852 ret = 0
4853
4853
4854 for f in ms:
4854 for f in ms:
4855 if m(f):
4855 if m(f):
4856 if show:
4856 if show:
4857 if nostatus:
4857 if nostatus:
4858 ui.write("%s\n" % f)
4858 ui.write("%s\n" % f)
4859 else:
4859 else:
4860 ui.write("%s %s\n" % (ms[f].upper(), f),
4860 ui.write("%s %s\n" % (ms[f].upper(), f),
4861 label='resolve.' +
4861 label='resolve.' +
4862 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4862 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4863 elif mark:
4863 elif mark:
4864 ms.mark(f, "r")
4864 ms.mark(f, "r")
4865 elif unmark:
4865 elif unmark:
4866 ms.mark(f, "u")
4866 ms.mark(f, "u")
4867 else:
4867 else:
4868 wctx = repo[None]
4868 wctx = repo[None]
4869 mctx = wctx.parents()[-1]
4869 mctx = wctx.parents()[-1]
4870
4870
4871 # backup pre-resolve (merge uses .orig for its own purposes)
4871 # backup pre-resolve (merge uses .orig for its own purposes)
4872 a = repo.wjoin(f)
4872 a = repo.wjoin(f)
4873 util.copyfile(a, a + ".resolve")
4873 util.copyfile(a, a + ".resolve")
4874
4874
4875 try:
4875 try:
4876 # resolve file
4876 # resolve file
4877 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4877 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4878 if ms.resolve(f, wctx, mctx):
4878 if ms.resolve(f, wctx, mctx):
4879 ret = 1
4879 ret = 1
4880 finally:
4880 finally:
4881 ui.setconfig('ui', 'forcemerge', '')
4881 ui.setconfig('ui', 'forcemerge', '')
4882 ms.commit()
4882 ms.commit()
4883
4883
4884 # replace filemerge's .orig file with our resolve file
4884 # replace filemerge's .orig file with our resolve file
4885 util.rename(a + ".resolve", a + ".orig")
4885 util.rename(a + ".resolve", a + ".orig")
4886
4886
4887 ms.commit()
4887 ms.commit()
4888 return ret
4888 return ret
4889
4889
4890 @command('revert',
4890 @command('revert',
4891 [('a', 'all', None, _('revert all changes when no arguments given')),
4891 [('a', 'all', None, _('revert all changes when no arguments given')),
4892 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4892 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4893 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4893 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4894 ('C', 'no-backup', None, _('do not save backup copies of files')),
4894 ('C', 'no-backup', None, _('do not save backup copies of files')),
4895 ] + walkopts + dryrunopts,
4895 ] + walkopts + dryrunopts,
4896 _('[OPTION]... [-r REV] [NAME]...'))
4896 _('[OPTION]... [-r REV] [NAME]...'))
4897 def revert(ui, repo, *pats, **opts):
4897 def revert(ui, repo, *pats, **opts):
4898 """restore files to their checkout state
4898 """restore files to their checkout state
4899
4899
4900 .. note::
4900 .. note::
4901
4901
4902 To check out earlier revisions, you should use :hg:`update REV`.
4902 To check out earlier revisions, you should use :hg:`update REV`.
4903 To cancel an uncommitted merge (and lose your changes), use
4903 To cancel an uncommitted merge (and lose your changes), use
4904 :hg:`update --clean .`.
4904 :hg:`update --clean .`.
4905
4905
4906 With no revision specified, revert the specified files or directories
4906 With no revision specified, revert the specified files or directories
4907 to the contents they had in the parent of the working directory.
4907 to the contents they had in the parent of the working directory.
4908 This restores the contents of files to an unmodified
4908 This restores the contents of files to an unmodified
4909 state and unschedules adds, removes, copies, and renames. If the
4909 state and unschedules adds, removes, copies, and renames. If the
4910 working directory has two parents, you must explicitly specify a
4910 working directory has two parents, you must explicitly specify a
4911 revision.
4911 revision.
4912
4912
4913 Using the -r/--rev or -d/--date options, revert the given files or
4913 Using the -r/--rev or -d/--date options, revert the given files or
4914 directories to their states as of a specific revision. Because
4914 directories to their states as of a specific revision. Because
4915 revert does not change the working directory parents, this will
4915 revert does not change the working directory parents, this will
4916 cause these files to appear modified. This can be helpful to "back
4916 cause these files to appear modified. This can be helpful to "back
4917 out" some or all of an earlier change. See :hg:`backout` for a
4917 out" some or all of an earlier change. See :hg:`backout` for a
4918 related method.
4918 related method.
4919
4919
4920 Modified files are saved with a .orig suffix before reverting.
4920 Modified files are saved with a .orig suffix before reverting.
4921 To disable these backups, use --no-backup.
4921 To disable these backups, use --no-backup.
4922
4922
4923 See :hg:`help dates` for a list of formats valid for -d/--date.
4923 See :hg:`help dates` for a list of formats valid for -d/--date.
4924
4924
4925 Returns 0 on success.
4925 Returns 0 on success.
4926 """
4926 """
4927
4927
4928 if opts.get("date"):
4928 if opts.get("date"):
4929 if opts.get("rev"):
4929 if opts.get("rev"):
4930 raise util.Abort(_("you can't specify a revision and a date"))
4930 raise util.Abort(_("you can't specify a revision and a date"))
4931 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4931 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4932
4932
4933 parent, p2 = repo.dirstate.parents()
4933 parent, p2 = repo.dirstate.parents()
4934 if not opts.get('rev') and p2 != nullid:
4934 if not opts.get('rev') and p2 != nullid:
4935 # revert after merge is a trap for new users (issue2915)
4935 # revert after merge is a trap for new users (issue2915)
4936 raise util.Abort(_('uncommitted merge with no revision specified'),
4936 raise util.Abort(_('uncommitted merge with no revision specified'),
4937 hint=_('use "hg update" or see "hg help revert"'))
4937 hint=_('use "hg update" or see "hg help revert"'))
4938
4938
4939 ctx = scmutil.revsingle(repo, opts.get('rev'))
4939 ctx = scmutil.revsingle(repo, opts.get('rev'))
4940
4940
4941 if not pats and not opts.get('all'):
4941 if not pats and not opts.get('all'):
4942 msg = _("no files or directories specified")
4942 msg = _("no files or directories specified")
4943 if p2 != nullid:
4943 if p2 != nullid:
4944 hint = _("uncommitted merge, use --all to discard all changes,"
4944 hint = _("uncommitted merge, use --all to discard all changes,"
4945 " or 'hg update -C .' to abort the merge")
4945 " or 'hg update -C .' to abort the merge")
4946 raise util.Abort(msg, hint=hint)
4946 raise util.Abort(msg, hint=hint)
4947 dirty = util.any(repo.status())
4947 dirty = util.any(repo.status())
4948 node = ctx.node()
4948 node = ctx.node()
4949 if node != parent:
4949 if node != parent:
4950 if dirty:
4950 if dirty:
4951 hint = _("uncommitted changes, use --all to discard all"
4951 hint = _("uncommitted changes, use --all to discard all"
4952 " changes, or 'hg update %s' to update") % ctx.rev()
4952 " changes, or 'hg update %s' to update") % ctx.rev()
4953 else:
4953 else:
4954 hint = _("use --all to revert all files,"
4954 hint = _("use --all to revert all files,"
4955 " or 'hg update %s' to update") % ctx.rev()
4955 " or 'hg update %s' to update") % ctx.rev()
4956 elif dirty:
4956 elif dirty:
4957 hint = _("uncommitted changes, use --all to discard all changes")
4957 hint = _("uncommitted changes, use --all to discard all changes")
4958 else:
4958 else:
4959 hint = _("use --all to revert all files")
4959 hint = _("use --all to revert all files")
4960 raise util.Abort(msg, hint=hint)
4960 raise util.Abort(msg, hint=hint)
4961
4961
4962 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4962 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4963
4963
4964 @command('rollback', dryrunopts +
4964 @command('rollback', dryrunopts +
4965 [('f', 'force', False, _('ignore safety measures'))])
4965 [('f', 'force', False, _('ignore safety measures'))])
4966 def rollback(ui, repo, **opts):
4966 def rollback(ui, repo, **opts):
4967 """roll back the last transaction (dangerous)
4967 """roll back the last transaction (dangerous)
4968
4968
4969 This command should be used with care. There is only one level of
4969 This command should be used with care. There is only one level of
4970 rollback, and there is no way to undo a rollback. It will also
4970 rollback, and there is no way to undo a rollback. It will also
4971 restore the dirstate at the time of the last transaction, losing
4971 restore the dirstate at the time of the last transaction, losing
4972 any dirstate changes since that time. This command does not alter
4972 any dirstate changes since that time. This command does not alter
4973 the working directory.
4973 the working directory.
4974
4974
4975 Transactions are used to encapsulate the effects of all commands
4975 Transactions are used to encapsulate the effects of all commands
4976 that create new changesets or propagate existing changesets into a
4976 that create new changesets or propagate existing changesets into a
4977 repository.
4977 repository.
4978
4978
4979 .. container:: verbose
4979 .. container:: verbose
4980
4980
4981 For example, the following commands are transactional, and their
4981 For example, the following commands are transactional, and their
4982 effects can be rolled back:
4982 effects can be rolled back:
4983
4983
4984 - commit
4984 - commit
4985 - import
4985 - import
4986 - pull
4986 - pull
4987 - push (with this repository as the destination)
4987 - push (with this repository as the destination)
4988 - unbundle
4988 - unbundle
4989
4989
4990 To avoid permanent data loss, rollback will refuse to rollback a
4990 To avoid permanent data loss, rollback will refuse to rollback a
4991 commit transaction if it isn't checked out. Use --force to
4991 commit transaction if it isn't checked out. Use --force to
4992 override this protection.
4992 override this protection.
4993
4993
4994 This command is not intended for use on public repositories. Once
4994 This command is not intended for use on public repositories. Once
4995 changes are visible for pull by other users, rolling a transaction
4995 changes are visible for pull by other users, rolling a transaction
4996 back locally is ineffective (someone else may already have pulled
4996 back locally is ineffective (someone else may already have pulled
4997 the changes). Furthermore, a race is possible with readers of the
4997 the changes). Furthermore, a race is possible with readers of the
4998 repository; for example an in-progress pull from the repository
4998 repository; for example an in-progress pull from the repository
4999 may fail if a rollback is performed.
4999 may fail if a rollback is performed.
5000
5000
5001 Returns 0 on success, 1 if no rollback data is available.
5001 Returns 0 on success, 1 if no rollback data is available.
5002 """
5002 """
5003 return repo.rollback(dryrun=opts.get('dry_run'),
5003 return repo.rollback(dryrun=opts.get('dry_run'),
5004 force=opts.get('force'))
5004 force=opts.get('force'))
5005
5005
5006 @command('root', [])
5006 @command('root', [])
5007 def root(ui, repo):
5007 def root(ui, repo):
5008 """print the root (top) of the current working directory
5008 """print the root (top) of the current working directory
5009
5009
5010 Print the root directory of the current repository.
5010 Print the root directory of the current repository.
5011
5011
5012 Returns 0 on success.
5012 Returns 0 on success.
5013 """
5013 """
5014 ui.write(repo.root + "\n")
5014 ui.write(repo.root + "\n")
5015
5015
5016 @command('^serve',
5016 @command('^serve',
5017 [('A', 'accesslog', '', _('name of access log file to write to'),
5017 [('A', 'accesslog', '', _('name of access log file to write to'),
5018 _('FILE')),
5018 _('FILE')),
5019 ('d', 'daemon', None, _('run server in background')),
5019 ('d', 'daemon', None, _('run server in background')),
5020 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5020 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5021 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5021 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5022 # use string type, then we can check if something was passed
5022 # use string type, then we can check if something was passed
5023 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5023 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5024 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5024 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5025 _('ADDR')),
5025 _('ADDR')),
5026 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5026 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5027 _('PREFIX')),
5027 _('PREFIX')),
5028 ('n', 'name', '',
5028 ('n', 'name', '',
5029 _('name to show in web pages (default: working directory)'), _('NAME')),
5029 _('name to show in web pages (default: working directory)'), _('NAME')),
5030 ('', 'web-conf', '',
5030 ('', 'web-conf', '',
5031 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5031 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5032 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5032 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5033 _('FILE')),
5033 _('FILE')),
5034 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5034 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5035 ('', 'stdio', None, _('for remote clients')),
5035 ('', 'stdio', None, _('for remote clients')),
5036 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5036 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5037 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5037 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5038 ('', 'style', '', _('template style to use'), _('STYLE')),
5038 ('', 'style', '', _('template style to use'), _('STYLE')),
5039 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5039 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5040 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5040 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5041 _('[OPTION]...'))
5041 _('[OPTION]...'))
5042 def serve(ui, repo, **opts):
5042 def serve(ui, repo, **opts):
5043 """start stand-alone webserver
5043 """start stand-alone webserver
5044
5044
5045 Start a local HTTP repository browser and pull server. You can use
5045 Start a local HTTP repository browser and pull server. You can use
5046 this for ad-hoc sharing and browsing of repositories. It is
5046 this for ad-hoc sharing and browsing of repositories. It is
5047 recommended to use a real web server to serve a repository for
5047 recommended to use a real web server to serve a repository for
5048 longer periods of time.
5048 longer periods of time.
5049
5049
5050 Please note that the server does not implement access control.
5050 Please note that the server does not implement access control.
5051 This means that, by default, anybody can read from the server and
5051 This means that, by default, anybody can read from the server and
5052 nobody can write to it by default. Set the ``web.allow_push``
5052 nobody can write to it by default. Set the ``web.allow_push``
5053 option to ``*`` to allow everybody to push to the server. You
5053 option to ``*`` to allow everybody to push to the server. You
5054 should use a real web server if you need to authenticate users.
5054 should use a real web server if you need to authenticate users.
5055
5055
5056 By default, the server logs accesses to stdout and errors to
5056 By default, the server logs accesses to stdout and errors to
5057 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5057 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5058 files.
5058 files.
5059
5059
5060 To have the server choose a free port number to listen on, specify
5060 To have the server choose a free port number to listen on, specify
5061 a port number of 0; in this case, the server will print the port
5061 a port number of 0; in this case, the server will print the port
5062 number it uses.
5062 number it uses.
5063
5063
5064 Returns 0 on success.
5064 Returns 0 on success.
5065 """
5065 """
5066
5066
5067 if opts["stdio"] and opts["cmdserver"]:
5067 if opts["stdio"] and opts["cmdserver"]:
5068 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5068 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5069
5069
5070 def checkrepo():
5070 def checkrepo():
5071 if repo is None:
5071 if repo is None:
5072 raise error.RepoError(_("there is no Mercurial repository here"
5072 raise error.RepoError(_("there is no Mercurial repository here"
5073 " (.hg not found)"))
5073 " (.hg not found)"))
5074
5074
5075 if opts["stdio"]:
5075 if opts["stdio"]:
5076 checkrepo()
5076 checkrepo()
5077 s = sshserver.sshserver(ui, repo)
5077 s = sshserver.sshserver(ui, repo)
5078 s.serve_forever()
5078 s.serve_forever()
5079
5079
5080 if opts["cmdserver"]:
5080 if opts["cmdserver"]:
5081 checkrepo()
5081 checkrepo()
5082 s = commandserver.server(ui, repo, opts["cmdserver"])
5082 s = commandserver.server(ui, repo, opts["cmdserver"])
5083 return s.serve()
5083 return s.serve()
5084
5084
5085 # this way we can check if something was given in the command-line
5085 # this way we can check if something was given in the command-line
5086 if opts.get('port'):
5086 if opts.get('port'):
5087 opts['port'] = util.getport(opts.get('port'))
5087 opts['port'] = util.getport(opts.get('port'))
5088
5088
5089 baseui = repo and repo.baseui or ui
5089 baseui = repo and repo.baseui or ui
5090 optlist = ("name templates style address port prefix ipv6"
5090 optlist = ("name templates style address port prefix ipv6"
5091 " accesslog errorlog certificate encoding")
5091 " accesslog errorlog certificate encoding")
5092 for o in optlist.split():
5092 for o in optlist.split():
5093 val = opts.get(o, '')
5093 val = opts.get(o, '')
5094 if val in (None, ''): # should check against default options instead
5094 if val in (None, ''): # should check against default options instead
5095 continue
5095 continue
5096 baseui.setconfig("web", o, val)
5096 baseui.setconfig("web", o, val)
5097 if repo and repo.ui != baseui:
5097 if repo and repo.ui != baseui:
5098 repo.ui.setconfig("web", o, val)
5098 repo.ui.setconfig("web", o, val)
5099
5099
5100 o = opts.get('web_conf') or opts.get('webdir_conf')
5100 o = opts.get('web_conf') or opts.get('webdir_conf')
5101 if not o:
5101 if not o:
5102 if not repo:
5102 if not repo:
5103 raise error.RepoError(_("there is no Mercurial repository"
5103 raise error.RepoError(_("there is no Mercurial repository"
5104 " here (.hg not found)"))
5104 " here (.hg not found)"))
5105 o = repo
5105 o = repo
5106
5106
5107 app = hgweb.hgweb(o, baseui=baseui)
5107 app = hgweb.hgweb(o, baseui=baseui)
5108
5108
5109 class service(object):
5109 class service(object):
5110 def init(self):
5110 def init(self):
5111 util.setsignalhandler()
5111 util.setsignalhandler()
5112 self.httpd = hgweb.server.create_server(ui, app)
5112 self.httpd = hgweb.server.create_server(ui, app)
5113
5113
5114 if opts['port'] and not ui.verbose:
5114 if opts['port'] and not ui.verbose:
5115 return
5115 return
5116
5116
5117 if self.httpd.prefix:
5117 if self.httpd.prefix:
5118 prefix = self.httpd.prefix.strip('/') + '/'
5118 prefix = self.httpd.prefix.strip('/') + '/'
5119 else:
5119 else:
5120 prefix = ''
5120 prefix = ''
5121
5121
5122 port = ':%d' % self.httpd.port
5122 port = ':%d' % self.httpd.port
5123 if port == ':80':
5123 if port == ':80':
5124 port = ''
5124 port = ''
5125
5125
5126 bindaddr = self.httpd.addr
5126 bindaddr = self.httpd.addr
5127 if bindaddr == '0.0.0.0':
5127 if bindaddr == '0.0.0.0':
5128 bindaddr = '*'
5128 bindaddr = '*'
5129 elif ':' in bindaddr: # IPv6
5129 elif ':' in bindaddr: # IPv6
5130 bindaddr = '[%s]' % bindaddr
5130 bindaddr = '[%s]' % bindaddr
5131
5131
5132 fqaddr = self.httpd.fqaddr
5132 fqaddr = self.httpd.fqaddr
5133 if ':' in fqaddr:
5133 if ':' in fqaddr:
5134 fqaddr = '[%s]' % fqaddr
5134 fqaddr = '[%s]' % fqaddr
5135 if opts['port']:
5135 if opts['port']:
5136 write = ui.status
5136 write = ui.status
5137 else:
5137 else:
5138 write = ui.write
5138 write = ui.write
5139 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5139 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5140 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5140 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5141
5141
5142 def run(self):
5142 def run(self):
5143 self.httpd.serve_forever()
5143 self.httpd.serve_forever()
5144
5144
5145 service = service()
5145 service = service()
5146
5146
5147 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5147 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5148
5148
5149 @command('showconfig|debugconfig',
5149 @command('showconfig|debugconfig',
5150 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5150 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5151 _('[-u] [NAME]...'))
5151 _('[-u] [NAME]...'))
5152 def showconfig(ui, repo, *values, **opts):
5152 def showconfig(ui, repo, *values, **opts):
5153 """show combined config settings from all hgrc files
5153 """show combined config settings from all hgrc files
5154
5154
5155 With no arguments, print names and values of all config items.
5155 With no arguments, print names and values of all config items.
5156
5156
5157 With one argument of the form section.name, print just the value
5157 With one argument of the form section.name, print just the value
5158 of that config item.
5158 of that config item.
5159
5159
5160 With multiple arguments, print names and values of all config
5160 With multiple arguments, print names and values of all config
5161 items with matching section names.
5161 items with matching section names.
5162
5162
5163 With --debug, the source (filename and line number) is printed
5163 With --debug, the source (filename and line number) is printed
5164 for each config item.
5164 for each config item.
5165
5165
5166 Returns 0 on success.
5166 Returns 0 on success.
5167 """
5167 """
5168
5168
5169 for f in scmutil.rcpath():
5169 for f in scmutil.rcpath():
5170 ui.debug('read config from: %s\n' % f)
5170 ui.debug('read config from: %s\n' % f)
5171 untrusted = bool(opts.get('untrusted'))
5171 untrusted = bool(opts.get('untrusted'))
5172 if values:
5172 if values:
5173 sections = [v for v in values if '.' not in v]
5173 sections = [v for v in values if '.' not in v]
5174 items = [v for v in values if '.' in v]
5174 items = [v for v in values if '.' in v]
5175 if len(items) > 1 or items and sections:
5175 if len(items) > 1 or items and sections:
5176 raise util.Abort(_('only one config item permitted'))
5176 raise util.Abort(_('only one config item permitted'))
5177 for section, name, value in ui.walkconfig(untrusted=untrusted):
5177 for section, name, value in ui.walkconfig(untrusted=untrusted):
5178 value = str(value).replace('\n', '\\n')
5178 value = str(value).replace('\n', '\\n')
5179 sectname = section + '.' + name
5179 sectname = section + '.' + name
5180 if values:
5180 if values:
5181 for v in values:
5181 for v in values:
5182 if v == section:
5182 if v == section:
5183 ui.debug('%s: ' %
5183 ui.debug('%s: ' %
5184 ui.configsource(section, name, untrusted))
5184 ui.configsource(section, name, untrusted))
5185 ui.write('%s=%s\n' % (sectname, value))
5185 ui.write('%s=%s\n' % (sectname, value))
5186 elif v == sectname:
5186 elif v == sectname:
5187 ui.debug('%s: ' %
5187 ui.debug('%s: ' %
5188 ui.configsource(section, name, untrusted))
5188 ui.configsource(section, name, untrusted))
5189 ui.write(value, '\n')
5189 ui.write(value, '\n')
5190 else:
5190 else:
5191 ui.debug('%s: ' %
5191 ui.debug('%s: ' %
5192 ui.configsource(section, name, untrusted))
5192 ui.configsource(section, name, untrusted))
5193 ui.write('%s=%s\n' % (sectname, value))
5193 ui.write('%s=%s\n' % (sectname, value))
5194
5194
5195 @command('^status|st',
5195 @command('^status|st',
5196 [('A', 'all', None, _('show status of all files')),
5196 [('A', 'all', None, _('show status of all files')),
5197 ('m', 'modified', None, _('show only modified files')),
5197 ('m', 'modified', None, _('show only modified files')),
5198 ('a', 'added', None, _('show only added files')),
5198 ('a', 'added', None, _('show only added files')),
5199 ('r', 'removed', None, _('show only removed files')),
5199 ('r', 'removed', None, _('show only removed files')),
5200 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5200 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5201 ('c', 'clean', None, _('show only files without changes')),
5201 ('c', 'clean', None, _('show only files without changes')),
5202 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5202 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5203 ('i', 'ignored', None, _('show only ignored files')),
5203 ('i', 'ignored', None, _('show only ignored files')),
5204 ('n', 'no-status', None, _('hide status prefix')),
5204 ('n', 'no-status', None, _('hide status prefix')),
5205 ('C', 'copies', None, _('show source of copied files')),
5205 ('C', 'copies', None, _('show source of copied files')),
5206 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5206 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5207 ('', 'rev', [], _('show difference from revision'), _('REV')),
5207 ('', 'rev', [], _('show difference from revision'), _('REV')),
5208 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5208 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5209 ] + walkopts + subrepoopts,
5209 ] + walkopts + subrepoopts,
5210 _('[OPTION]... [FILE]...'))
5210 _('[OPTION]... [FILE]...'))
5211 def status(ui, repo, *pats, **opts):
5211 def status(ui, repo, *pats, **opts):
5212 """show changed files in the working directory
5212 """show changed files in the working directory
5213
5213
5214 Show status of files in the repository. If names are given, only
5214 Show status of files in the repository. If names are given, only
5215 files that match are shown. Files that are clean or ignored or
5215 files that match are shown. Files that are clean or ignored or
5216 the source of a copy/move operation, are not listed unless
5216 the source of a copy/move operation, are not listed unless
5217 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5217 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5218 Unless options described with "show only ..." are given, the
5218 Unless options described with "show only ..." are given, the
5219 options -mardu are used.
5219 options -mardu are used.
5220
5220
5221 Option -q/--quiet hides untracked (unknown and ignored) files
5221 Option -q/--quiet hides untracked (unknown and ignored) files
5222 unless explicitly requested with -u/--unknown or -i/--ignored.
5222 unless explicitly requested with -u/--unknown or -i/--ignored.
5223
5223
5224 .. note::
5224 .. note::
5225 status may appear to disagree with diff if permissions have
5225 status may appear to disagree with diff if permissions have
5226 changed or a merge has occurred. The standard diff format does
5226 changed or a merge has occurred. The standard diff format does
5227 not report permission changes and diff only reports changes
5227 not report permission changes and diff only reports changes
5228 relative to one merge parent.
5228 relative to one merge parent.
5229
5229
5230 If one revision is given, it is used as the base revision.
5230 If one revision is given, it is used as the base revision.
5231 If two revisions are given, the differences between them are
5231 If two revisions are given, the differences between them are
5232 shown. The --change option can also be used as a shortcut to list
5232 shown. The --change option can also be used as a shortcut to list
5233 the changed files of a revision from its first parent.
5233 the changed files of a revision from its first parent.
5234
5234
5235 The codes used to show the status of files are::
5235 The codes used to show the status of files are::
5236
5236
5237 M = modified
5237 M = modified
5238 A = added
5238 A = added
5239 R = removed
5239 R = removed
5240 C = clean
5240 C = clean
5241 ! = missing (deleted by non-hg command, but still tracked)
5241 ! = missing (deleted by non-hg command, but still tracked)
5242 ? = not tracked
5242 ? = not tracked
5243 I = ignored
5243 I = ignored
5244 = origin of the previous file listed as A (added)
5244 = origin of the previous file listed as A (added)
5245
5245
5246 .. container:: verbose
5246 .. container:: verbose
5247
5247
5248 Examples:
5248 Examples:
5249
5249
5250 - show changes in the working directory relative to a
5250 - show changes in the working directory relative to a
5251 changeset::
5251 changeset::
5252
5252
5253 hg status --rev 9353
5253 hg status --rev 9353
5254
5254
5255 - show all changes including copies in an existing changeset::
5255 - show all changes including copies in an existing changeset::
5256
5256
5257 hg status --copies --change 9353
5257 hg status --copies --change 9353
5258
5258
5259 - get a NUL separated list of added files, suitable for xargs::
5259 - get a NUL separated list of added files, suitable for xargs::
5260
5260
5261 hg status -an0
5261 hg status -an0
5262
5262
5263 Returns 0 on success.
5263 Returns 0 on success.
5264 """
5264 """
5265
5265
5266 revs = opts.get('rev')
5266 revs = opts.get('rev')
5267 change = opts.get('change')
5267 change = opts.get('change')
5268
5268
5269 if revs and change:
5269 if revs and change:
5270 msg = _('cannot specify --rev and --change at the same time')
5270 msg = _('cannot specify --rev and --change at the same time')
5271 raise util.Abort(msg)
5271 raise util.Abort(msg)
5272 elif change:
5272 elif change:
5273 node2 = scmutil.revsingle(repo, change, None).node()
5273 node2 = scmutil.revsingle(repo, change, None).node()
5274 node1 = repo[node2].p1().node()
5274 node1 = repo[node2].p1().node()
5275 else:
5275 else:
5276 node1, node2 = scmutil.revpair(repo, revs)
5276 node1, node2 = scmutil.revpair(repo, revs)
5277
5277
5278 cwd = (pats and repo.getcwd()) or ''
5278 cwd = (pats and repo.getcwd()) or ''
5279 end = opts.get('print0') and '\0' or '\n'
5279 end = opts.get('print0') and '\0' or '\n'
5280 copy = {}
5280 copy = {}
5281 states = 'modified added removed deleted unknown ignored clean'.split()
5281 states = 'modified added removed deleted unknown ignored clean'.split()
5282 show = [k for k in states if opts.get(k)]
5282 show = [k for k in states if opts.get(k)]
5283 if opts.get('all'):
5283 if opts.get('all'):
5284 show += ui.quiet and (states[:4] + ['clean']) or states
5284 show += ui.quiet and (states[:4] + ['clean']) or states
5285 if not show:
5285 if not show:
5286 show = ui.quiet and states[:4] or states[:5]
5286 show = ui.quiet and states[:4] or states[:5]
5287
5287
5288 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5288 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5289 'ignored' in show, 'clean' in show, 'unknown' in show,
5289 'ignored' in show, 'clean' in show, 'unknown' in show,
5290 opts.get('subrepos'))
5290 opts.get('subrepos'))
5291 changestates = zip(states, 'MAR!?IC', stat)
5291 changestates = zip(states, 'MAR!?IC', stat)
5292
5292
5293 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5293 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5294 copy = copies.pathcopies(repo[node1], repo[node2])
5294 copy = copies.pathcopies(repo[node1], repo[node2])
5295
5295
5296 fm = ui.formatter('status', opts)
5296 fm = ui.formatter('status', opts)
5297 fmt = '%s' + end
5297 fmt = '%s' + end
5298 showchar = not opts.get('no_status')
5298 showchar = not opts.get('no_status')
5299
5299
5300 for state, char, files in changestates:
5300 for state, char, files in changestates:
5301 if state in show:
5301 if state in show:
5302 label = 'status.' + state
5302 label = 'status.' + state
5303 for f in files:
5303 for f in files:
5304 fm.startitem()
5304 fm.startitem()
5305 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5305 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5306 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5306 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5307 if f in copy:
5307 if f in copy:
5308 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5308 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5309 label='status.copied')
5309 label='status.copied')
5310 fm.end()
5310 fm.end()
5311
5311
5312 @command('^summary|sum',
5312 @command('^summary|sum',
5313 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5313 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5314 def summary(ui, repo, **opts):
5314 def summary(ui, repo, **opts):
5315 """summarize working directory state
5315 """summarize working directory state
5316
5316
5317 This generates a brief summary of the working directory state,
5317 This generates a brief summary of the working directory state,
5318 including parents, branch, commit status, and available updates.
5318 including parents, branch, commit status, and available updates.
5319
5319
5320 With the --remote option, this will check the default paths for
5320 With the --remote option, this will check the default paths for
5321 incoming and outgoing changes. This can be time-consuming.
5321 incoming and outgoing changes. This can be time-consuming.
5322
5322
5323 Returns 0 on success.
5323 Returns 0 on success.
5324 """
5324 """
5325
5325
5326 ctx = repo[None]
5326 ctx = repo[None]
5327 parents = ctx.parents()
5327 parents = ctx.parents()
5328 pnode = parents[0].node()
5328 pnode = parents[0].node()
5329 marks = []
5329 marks = []
5330
5330
5331 for p in parents:
5331 for p in parents:
5332 # label with log.changeset (instead of log.parent) since this
5332 # label with log.changeset (instead of log.parent) since this
5333 # shows a working directory parent *changeset*:
5333 # shows a working directory parent *changeset*:
5334 # i18n: column positioning for "hg summary"
5334 # i18n: column positioning for "hg summary"
5335 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5335 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5336 label='log.changeset changeset.%s' % p.phasestr())
5336 label='log.changeset changeset.%s' % p.phasestr())
5337 ui.write(' '.join(p.tags()), label='log.tag')
5337 ui.write(' '.join(p.tags()), label='log.tag')
5338 if p.bookmarks():
5338 if p.bookmarks():
5339 marks.extend(p.bookmarks())
5339 marks.extend(p.bookmarks())
5340 if p.rev() == -1:
5340 if p.rev() == -1:
5341 if not len(repo):
5341 if not len(repo):
5342 ui.write(_(' (empty repository)'))
5342 ui.write(_(' (empty repository)'))
5343 else:
5343 else:
5344 ui.write(_(' (no revision checked out)'))
5344 ui.write(_(' (no revision checked out)'))
5345 ui.write('\n')
5345 ui.write('\n')
5346 if p.description():
5346 if p.description():
5347 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5347 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5348 label='log.summary')
5348 label='log.summary')
5349
5349
5350 branch = ctx.branch()
5350 branch = ctx.branch()
5351 bheads = repo.branchheads(branch)
5351 bheads = repo.branchheads(branch)
5352 # i18n: column positioning for "hg summary"
5352 # i18n: column positioning for "hg summary"
5353 m = _('branch: %s\n') % branch
5353 m = _('branch: %s\n') % branch
5354 if branch != 'default':
5354 if branch != 'default':
5355 ui.write(m, label='log.branch')
5355 ui.write(m, label='log.branch')
5356 else:
5356 else:
5357 ui.status(m, label='log.branch')
5357 ui.status(m, label='log.branch')
5358
5358
5359 if marks:
5359 if marks:
5360 current = repo._bookmarkcurrent
5360 current = repo._bookmarkcurrent
5361 # i18n: column positioning for "hg summary"
5361 # i18n: column positioning for "hg summary"
5362 ui.write(_('bookmarks:'), label='log.bookmark')
5362 ui.write(_('bookmarks:'), label='log.bookmark')
5363 if current is not None:
5363 if current is not None:
5364 if current in marks:
5364 if current in marks:
5365 ui.write(' *' + current, label='bookmarks.current')
5365 ui.write(' *' + current, label='bookmarks.current')
5366 marks.remove(current)
5366 marks.remove(current)
5367 else:
5367 else:
5368 ui.write(' [%s]' % current, label='bookmarks.current')
5368 ui.write(' [%s]' % current, label='bookmarks.current')
5369 for m in marks:
5369 for m in marks:
5370 ui.write(' ' + m, label='log.bookmark')
5370 ui.write(' ' + m, label='log.bookmark')
5371 ui.write('\n', label='log.bookmark')
5371 ui.write('\n', label='log.bookmark')
5372
5372
5373 st = list(repo.status(unknown=True))[:6]
5373 st = list(repo.status(unknown=True))[:6]
5374
5374
5375 c = repo.dirstate.copies()
5375 c = repo.dirstate.copies()
5376 copied, renamed = [], []
5376 copied, renamed = [], []
5377 for d, s in c.iteritems():
5377 for d, s in c.iteritems():
5378 if s in st[2]:
5378 if s in st[2]:
5379 st[2].remove(s)
5379 st[2].remove(s)
5380 renamed.append(d)
5380 renamed.append(d)
5381 else:
5381 else:
5382 copied.append(d)
5382 copied.append(d)
5383 if d in st[1]:
5383 if d in st[1]:
5384 st[1].remove(d)
5384 st[1].remove(d)
5385 st.insert(3, renamed)
5385 st.insert(3, renamed)
5386 st.insert(4, copied)
5386 st.insert(4, copied)
5387
5387
5388 ms = mergemod.mergestate(repo)
5388 ms = mergemod.mergestate(repo)
5389 st.append([f for f in ms if ms[f] == 'u'])
5389 st.append([f for f in ms if ms[f] == 'u'])
5390
5390
5391 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5391 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5392 st.append(subs)
5392 st.append(subs)
5393
5393
5394 labels = [ui.label(_('%d modified'), 'status.modified'),
5394 labels = [ui.label(_('%d modified'), 'status.modified'),
5395 ui.label(_('%d added'), 'status.added'),
5395 ui.label(_('%d added'), 'status.added'),
5396 ui.label(_('%d removed'), 'status.removed'),
5396 ui.label(_('%d removed'), 'status.removed'),
5397 ui.label(_('%d renamed'), 'status.copied'),
5397 ui.label(_('%d renamed'), 'status.copied'),
5398 ui.label(_('%d copied'), 'status.copied'),
5398 ui.label(_('%d copied'), 'status.copied'),
5399 ui.label(_('%d deleted'), 'status.deleted'),
5399 ui.label(_('%d deleted'), 'status.deleted'),
5400 ui.label(_('%d unknown'), 'status.unknown'),
5400 ui.label(_('%d unknown'), 'status.unknown'),
5401 ui.label(_('%d ignored'), 'status.ignored'),
5401 ui.label(_('%d ignored'), 'status.ignored'),
5402 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5402 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5403 ui.label(_('%d subrepos'), 'status.modified')]
5403 ui.label(_('%d subrepos'), 'status.modified')]
5404 t = []
5404 t = []
5405 for s, l in zip(st, labels):
5405 for s, l in zip(st, labels):
5406 if s:
5406 if s:
5407 t.append(l % len(s))
5407 t.append(l % len(s))
5408
5408
5409 t = ', '.join(t)
5409 t = ', '.join(t)
5410 cleanworkdir = False
5410 cleanworkdir = False
5411
5411
5412 if len(parents) > 1:
5412 if len(parents) > 1:
5413 t += _(' (merge)')
5413 t += _(' (merge)')
5414 elif branch != parents[0].branch():
5414 elif branch != parents[0].branch():
5415 t += _(' (new branch)')
5415 t += _(' (new branch)')
5416 elif (parents[0].closesbranch() and
5416 elif (parents[0].closesbranch() and
5417 pnode in repo.branchheads(branch, closed=True)):
5417 pnode in repo.branchheads(branch, closed=True)):
5418 t += _(' (head closed)')
5418 t += _(' (head closed)')
5419 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5419 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5420 t += _(' (clean)')
5420 t += _(' (clean)')
5421 cleanworkdir = True
5421 cleanworkdir = True
5422 elif pnode not in bheads:
5422 elif pnode not in bheads:
5423 t += _(' (new branch head)')
5423 t += _(' (new branch head)')
5424
5424
5425 if cleanworkdir:
5425 if cleanworkdir:
5426 # i18n: column positioning for "hg summary"
5426 # i18n: column positioning for "hg summary"
5427 ui.status(_('commit: %s\n') % t.strip())
5427 ui.status(_('commit: %s\n') % t.strip())
5428 else:
5428 else:
5429 # i18n: column positioning for "hg summary"
5429 # i18n: column positioning for "hg summary"
5430 ui.write(_('commit: %s\n') % t.strip())
5430 ui.write(_('commit: %s\n') % t.strip())
5431
5431
5432 # all ancestors of branch heads - all ancestors of parent = new csets
5432 # all ancestors of branch heads - all ancestors of parent = new csets
5433 new = [0] * len(repo)
5433 new = [0] * len(repo)
5434 cl = repo.changelog
5434 cl = repo.changelog
5435 for a in [cl.rev(n) for n in bheads]:
5435 for a in [cl.rev(n) for n in bheads]:
5436 new[a] = 1
5436 new[a] = 1
5437 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5437 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5438 new[a] = 1
5438 new[a] = 1
5439 for a in [p.rev() for p in parents]:
5439 for a in [p.rev() for p in parents]:
5440 if a >= 0:
5440 if a >= 0:
5441 new[a] = 0
5441 new[a] = 0
5442 for a in cl.ancestors([p.rev() for p in parents]):
5442 for a in cl.ancestors([p.rev() for p in parents]):
5443 new[a] = 0
5443 new[a] = 0
5444 new = sum(new)
5444 new = sum(new)
5445
5445
5446 if new == 0:
5446 if new == 0:
5447 # i18n: column positioning for "hg summary"
5447 # i18n: column positioning for "hg summary"
5448 ui.status(_('update: (current)\n'))
5448 ui.status(_('update: (current)\n'))
5449 elif pnode not in bheads:
5449 elif pnode not in bheads:
5450 # i18n: column positioning for "hg summary"
5450 # i18n: column positioning for "hg summary"
5451 ui.write(_('update: %d new changesets (update)\n') % new)
5451 ui.write(_('update: %d new changesets (update)\n') % new)
5452 else:
5452 else:
5453 # i18n: column positioning for "hg summary"
5453 # i18n: column positioning for "hg summary"
5454 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5454 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5455 (new, len(bheads)))
5455 (new, len(bheads)))
5456
5456
5457 if opts.get('remote'):
5457 if opts.get('remote'):
5458 t = []
5458 t = []
5459 source, branches = hg.parseurl(ui.expandpath('default'))
5459 source, branches = hg.parseurl(ui.expandpath('default'))
5460 other = hg.peer(repo, {}, source)
5460 other = hg.peer(repo, {}, source)
5461 revs, checkout = hg.addbranchrevs(repo, other, branches,
5461 revs, checkout = hg.addbranchrevs(repo, other, branches,
5462 opts.get('rev'))
5462 opts.get('rev'))
5463 ui.debug('comparing with %s\n' % util.hidepassword(source))
5463 ui.debug('comparing with %s\n' % util.hidepassword(source))
5464 repo.ui.pushbuffer()
5464 repo.ui.pushbuffer()
5465 commoninc = discovery.findcommonincoming(repo, other)
5465 commoninc = discovery.findcommonincoming(repo, other)
5466 _common, incoming, _rheads = commoninc
5466 _common, incoming, _rheads = commoninc
5467 repo.ui.popbuffer()
5467 repo.ui.popbuffer()
5468 if incoming:
5468 if incoming:
5469 t.append(_('1 or more incoming'))
5469 t.append(_('1 or more incoming'))
5470
5470
5471 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5471 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5472 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5472 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5473 if source != dest:
5473 if source != dest:
5474 other = hg.peer(repo, {}, dest)
5474 other = hg.peer(repo, {}, dest)
5475 commoninc = None
5475 commoninc = None
5476 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5476 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5477 repo.ui.pushbuffer()
5477 repo.ui.pushbuffer()
5478 outgoing = discovery.findcommonoutgoing(repo, other,
5478 outgoing = discovery.findcommonoutgoing(repo, other,
5479 commoninc=commoninc)
5479 commoninc=commoninc)
5480 repo.ui.popbuffer()
5480 repo.ui.popbuffer()
5481 o = outgoing.missing
5481 o = outgoing.missing
5482 if o:
5482 if o:
5483 t.append(_('%d outgoing') % len(o))
5483 t.append(_('%d outgoing') % len(o))
5484 if 'bookmarks' in other.listkeys('namespaces'):
5484 if 'bookmarks' in other.listkeys('namespaces'):
5485 lmarks = repo.listkeys('bookmarks')
5485 lmarks = repo.listkeys('bookmarks')
5486 rmarks = other.listkeys('bookmarks')
5486 rmarks = other.listkeys('bookmarks')
5487 diff = set(rmarks) - set(lmarks)
5487 diff = set(rmarks) - set(lmarks)
5488 if len(diff) > 0:
5488 if len(diff) > 0:
5489 t.append(_('%d incoming bookmarks') % len(diff))
5489 t.append(_('%d incoming bookmarks') % len(diff))
5490 diff = set(lmarks) - set(rmarks)
5490 diff = set(lmarks) - set(rmarks)
5491 if len(diff) > 0:
5491 if len(diff) > 0:
5492 t.append(_('%d outgoing bookmarks') % len(diff))
5492 t.append(_('%d outgoing bookmarks') % len(diff))
5493
5493
5494 if t:
5494 if t:
5495 # i18n: column positioning for "hg summary"
5495 # i18n: column positioning for "hg summary"
5496 ui.write(_('remote: %s\n') % (', '.join(t)))
5496 ui.write(_('remote: %s\n') % (', '.join(t)))
5497 else:
5497 else:
5498 # i18n: column positioning for "hg summary"
5498 # i18n: column positioning for "hg summary"
5499 ui.status(_('remote: (synced)\n'))
5499 ui.status(_('remote: (synced)\n'))
5500
5500
5501 @command('tag',
5501 @command('tag',
5502 [('f', 'force', None, _('force tag')),
5502 [('f', 'force', None, _('force tag')),
5503 ('l', 'local', None, _('make the tag local')),
5503 ('l', 'local', None, _('make the tag local')),
5504 ('r', 'rev', '', _('revision to tag'), _('REV')),
5504 ('r', 'rev', '', _('revision to tag'), _('REV')),
5505 ('', 'remove', None, _('remove a tag')),
5505 ('', 'remove', None, _('remove a tag')),
5506 # -l/--local is already there, commitopts cannot be used
5506 # -l/--local is already there, commitopts cannot be used
5507 ('e', 'edit', None, _('edit commit message')),
5507 ('e', 'edit', None, _('edit commit message')),
5508 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5508 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5509 ] + commitopts2,
5509 ] + commitopts2,
5510 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5510 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5511 def tag(ui, repo, name1, *names, **opts):
5511 def tag(ui, repo, name1, *names, **opts):
5512 """add one or more tags for the current or given revision
5512 """add one or more tags for the current or given revision
5513
5513
5514 Name a particular revision using <name>.
5514 Name a particular revision using <name>.
5515
5515
5516 Tags are used to name particular revisions of the repository and are
5516 Tags are used to name particular revisions of the repository and are
5517 very useful to compare different revisions, to go back to significant
5517 very useful to compare different revisions, to go back to significant
5518 earlier versions or to mark branch points as releases, etc. Changing
5518 earlier versions or to mark branch points as releases, etc. Changing
5519 an existing tag is normally disallowed; use -f/--force to override.
5519 an existing tag is normally disallowed; use -f/--force to override.
5520
5520
5521 If no revision is given, the parent of the working directory is
5521 If no revision is given, the parent of the working directory is
5522 used, or tip if no revision is checked out.
5522 used, or tip if no revision is checked out.
5523
5523
5524 To facilitate version control, distribution, and merging of tags,
5524 To facilitate version control, distribution, and merging of tags,
5525 they are stored as a file named ".hgtags" which is managed similarly
5525 they are stored as a file named ".hgtags" which is managed similarly
5526 to other project files and can be hand-edited if necessary. This
5526 to other project files and can be hand-edited if necessary. This
5527 also means that tagging creates a new commit. The file
5527 also means that tagging creates a new commit. The file
5528 ".hg/localtags" is used for local tags (not shared among
5528 ".hg/localtags" is used for local tags (not shared among
5529 repositories).
5529 repositories).
5530
5530
5531 Tag commits are usually made at the head of a branch. If the parent
5531 Tag commits are usually made at the head of a branch. If the parent
5532 of the working directory is not a branch head, :hg:`tag` aborts; use
5532 of the working directory is not a branch head, :hg:`tag` aborts; use
5533 -f/--force to force the tag commit to be based on a non-head
5533 -f/--force to force the tag commit to be based on a non-head
5534 changeset.
5534 changeset.
5535
5535
5536 See :hg:`help dates` for a list of formats valid for -d/--date.
5536 See :hg:`help dates` for a list of formats valid for -d/--date.
5537
5537
5538 Since tag names have priority over branch names during revision
5538 Since tag names have priority over branch names during revision
5539 lookup, using an existing branch name as a tag name is discouraged.
5539 lookup, using an existing branch name as a tag name is discouraged.
5540
5540
5541 Returns 0 on success.
5541 Returns 0 on success.
5542 """
5542 """
5543 wlock = lock = None
5543 wlock = lock = None
5544 try:
5544 try:
5545 wlock = repo.wlock()
5545 wlock = repo.wlock()
5546 lock = repo.lock()
5546 lock = repo.lock()
5547 rev_ = "."
5547 rev_ = "."
5548 names = [t.strip() for t in (name1,) + names]
5548 names = [t.strip() for t in (name1,) + names]
5549 if len(names) != len(set(names)):
5549 if len(names) != len(set(names)):
5550 raise util.Abort(_('tag names must be unique'))
5550 raise util.Abort(_('tag names must be unique'))
5551 for n in names:
5551 for n in names:
5552 scmutil.checknewlabel(repo, n, 'tag')
5552 scmutil.checknewlabel(repo, n, 'tag')
5553 if not n:
5553 if not n:
5554 raise util.Abort(_('tag names cannot consist entirely of '
5554 raise util.Abort(_('tag names cannot consist entirely of '
5555 'whitespace'))
5555 'whitespace'))
5556 if opts.get('rev') and opts.get('remove'):
5556 if opts.get('rev') and opts.get('remove'):
5557 raise util.Abort(_("--rev and --remove are incompatible"))
5557 raise util.Abort(_("--rev and --remove are incompatible"))
5558 if opts.get('rev'):
5558 if opts.get('rev'):
5559 rev_ = opts['rev']
5559 rev_ = opts['rev']
5560 message = opts.get('message')
5560 message = opts.get('message')
5561 if opts.get('remove'):
5561 if opts.get('remove'):
5562 expectedtype = opts.get('local') and 'local' or 'global'
5562 expectedtype = opts.get('local') and 'local' or 'global'
5563 for n in names:
5563 for n in names:
5564 if not repo.tagtype(n):
5564 if not repo.tagtype(n):
5565 raise util.Abort(_("tag '%s' does not exist") % n)
5565 raise util.Abort(_("tag '%s' does not exist") % n)
5566 if repo.tagtype(n) != expectedtype:
5566 if repo.tagtype(n) != expectedtype:
5567 if expectedtype == 'global':
5567 if expectedtype == 'global':
5568 raise util.Abort(_("tag '%s' is not a global tag") % n)
5568 raise util.Abort(_("tag '%s' is not a global tag") % n)
5569 else:
5569 else:
5570 raise util.Abort(_("tag '%s' is not a local tag") % n)
5570 raise util.Abort(_("tag '%s' is not a local tag") % n)
5571 rev_ = nullid
5571 rev_ = nullid
5572 if not message:
5572 if not message:
5573 # we don't translate commit messages
5573 # we don't translate commit messages
5574 message = 'Removed tag %s' % ', '.join(names)
5574 message = 'Removed tag %s' % ', '.join(names)
5575 elif not opts.get('force'):
5575 elif not opts.get('force'):
5576 for n in names:
5576 for n in names:
5577 if n in repo.tags():
5577 if n in repo.tags():
5578 raise util.Abort(_("tag '%s' already exists "
5578 raise util.Abort(_("tag '%s' already exists "
5579 "(use -f to force)") % n)
5579 "(use -f to force)") % n)
5580 if not opts.get('local'):
5580 if not opts.get('local'):
5581 p1, p2 = repo.dirstate.parents()
5581 p1, p2 = repo.dirstate.parents()
5582 if p2 != nullid:
5582 if p2 != nullid:
5583 raise util.Abort(_('uncommitted merge'))
5583 raise util.Abort(_('uncommitted merge'))
5584 bheads = repo.branchheads()
5584 bheads = repo.branchheads()
5585 if not opts.get('force') and bheads and p1 not in bheads:
5585 if not opts.get('force') and bheads and p1 not in bheads:
5586 raise util.Abort(_('not at a branch head (use -f to force)'))
5586 raise util.Abort(_('not at a branch head (use -f to force)'))
5587 r = scmutil.revsingle(repo, rev_).node()
5587 r = scmutil.revsingle(repo, rev_).node()
5588
5588
5589 if not message:
5589 if not message:
5590 # we don't translate commit messages
5590 # we don't translate commit messages
5591 message = ('Added tag %s for changeset %s' %
5591 message = ('Added tag %s for changeset %s' %
5592 (', '.join(names), short(r)))
5592 (', '.join(names), short(r)))
5593
5593
5594 date = opts.get('date')
5594 date = opts.get('date')
5595 if date:
5595 if date:
5596 date = util.parsedate(date)
5596 date = util.parsedate(date)
5597
5597
5598 if opts.get('edit'):
5598 if opts.get('edit'):
5599 message = ui.edit(message, ui.username())
5599 message = ui.edit(message, ui.username())
5600
5600
5601 # don't allow tagging the null rev
5601 # don't allow tagging the null rev
5602 if (not opts.get('remove') and
5602 if (not opts.get('remove') and
5603 scmutil.revsingle(repo, rev_).rev() == nullrev):
5603 scmutil.revsingle(repo, rev_).rev() == nullrev):
5604 raise util.Abort(_("null revision specified"))
5604 raise util.Abort(_("cannot tag null revision"))
5605
5605
5606 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5606 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5607 finally:
5607 finally:
5608 release(lock, wlock)
5608 release(lock, wlock)
5609
5609
5610 @command('tags', [], '')
5610 @command('tags', [], '')
5611 def tags(ui, repo, **opts):
5611 def tags(ui, repo, **opts):
5612 """list repository tags
5612 """list repository tags
5613
5613
5614 This lists both regular and local tags. When the -v/--verbose
5614 This lists both regular and local tags. When the -v/--verbose
5615 switch is used, a third column "local" is printed for local tags.
5615 switch is used, a third column "local" is printed for local tags.
5616
5616
5617 Returns 0 on success.
5617 Returns 0 on success.
5618 """
5618 """
5619
5619
5620 fm = ui.formatter('tags', opts)
5620 fm = ui.formatter('tags', opts)
5621 hexfunc = ui.debugflag and hex or short
5621 hexfunc = ui.debugflag and hex or short
5622 tagtype = ""
5622 tagtype = ""
5623
5623
5624 for t, n in reversed(repo.tagslist()):
5624 for t, n in reversed(repo.tagslist()):
5625 hn = hexfunc(n)
5625 hn = hexfunc(n)
5626 label = 'tags.normal'
5626 label = 'tags.normal'
5627 tagtype = ''
5627 tagtype = ''
5628 if repo.tagtype(t) == 'local':
5628 if repo.tagtype(t) == 'local':
5629 label = 'tags.local'
5629 label = 'tags.local'
5630 tagtype = 'local'
5630 tagtype = 'local'
5631
5631
5632 fm.startitem()
5632 fm.startitem()
5633 fm.write('tag', '%s', t, label=label)
5633 fm.write('tag', '%s', t, label=label)
5634 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5634 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5635 fm.condwrite(not ui.quiet, 'rev id', fmt,
5635 fm.condwrite(not ui.quiet, 'rev id', fmt,
5636 repo.changelog.rev(n), hn, label=label)
5636 repo.changelog.rev(n), hn, label=label)
5637 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5637 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5638 tagtype, label=label)
5638 tagtype, label=label)
5639 fm.plain('\n')
5639 fm.plain('\n')
5640 fm.end()
5640 fm.end()
5641
5641
5642 @command('tip',
5642 @command('tip',
5643 [('p', 'patch', None, _('show patch')),
5643 [('p', 'patch', None, _('show patch')),
5644 ('g', 'git', None, _('use git extended diff format')),
5644 ('g', 'git', None, _('use git extended diff format')),
5645 ] + templateopts,
5645 ] + templateopts,
5646 _('[-p] [-g]'))
5646 _('[-p] [-g]'))
5647 def tip(ui, repo, **opts):
5647 def tip(ui, repo, **opts):
5648 """show the tip revision
5648 """show the tip revision
5649
5649
5650 The tip revision (usually just called the tip) is the changeset
5650 The tip revision (usually just called the tip) is the changeset
5651 most recently added to the repository (and therefore the most
5651 most recently added to the repository (and therefore the most
5652 recently changed head).
5652 recently changed head).
5653
5653
5654 If you have just made a commit, that commit will be the tip. If
5654 If you have just made a commit, that commit will be the tip. If
5655 you have just pulled changes from another repository, the tip of
5655 you have just pulled changes from another repository, the tip of
5656 that repository becomes the current tip. The "tip" tag is special
5656 that repository becomes the current tip. The "tip" tag is special
5657 and cannot be renamed or assigned to a different changeset.
5657 and cannot be renamed or assigned to a different changeset.
5658
5658
5659 Returns 0 on success.
5659 Returns 0 on success.
5660 """
5660 """
5661 displayer = cmdutil.show_changeset(ui, repo, opts)
5661 displayer = cmdutil.show_changeset(ui, repo, opts)
5662 displayer.show(repo['tip'])
5662 displayer.show(repo['tip'])
5663 displayer.close()
5663 displayer.close()
5664
5664
5665 @command('unbundle',
5665 @command('unbundle',
5666 [('u', 'update', None,
5666 [('u', 'update', None,
5667 _('update to new branch head if changesets were unbundled'))],
5667 _('update to new branch head if changesets were unbundled'))],
5668 _('[-u] FILE...'))
5668 _('[-u] FILE...'))
5669 def unbundle(ui, repo, fname1, *fnames, **opts):
5669 def unbundle(ui, repo, fname1, *fnames, **opts):
5670 """apply one or more changegroup files
5670 """apply one or more changegroup files
5671
5671
5672 Apply one or more compressed changegroup files generated by the
5672 Apply one or more compressed changegroup files generated by the
5673 bundle command.
5673 bundle command.
5674
5674
5675 Returns 0 on success, 1 if an update has unresolved files.
5675 Returns 0 on success, 1 if an update has unresolved files.
5676 """
5676 """
5677 fnames = (fname1,) + fnames
5677 fnames = (fname1,) + fnames
5678
5678
5679 lock = repo.lock()
5679 lock = repo.lock()
5680 wc = repo['.']
5680 wc = repo['.']
5681 try:
5681 try:
5682 for fname in fnames:
5682 for fname in fnames:
5683 f = hg.openpath(ui, fname)
5683 f = hg.openpath(ui, fname)
5684 gen = changegroup.readbundle(f, fname)
5684 gen = changegroup.readbundle(f, fname)
5685 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5685 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5686 finally:
5686 finally:
5687 lock.release()
5687 lock.release()
5688 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5688 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5689 return postincoming(ui, repo, modheads, opts.get('update'), None)
5689 return postincoming(ui, repo, modheads, opts.get('update'), None)
5690
5690
5691 @command('^update|up|checkout|co',
5691 @command('^update|up|checkout|co',
5692 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5692 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5693 ('c', 'check', None,
5693 ('c', 'check', None,
5694 _('update across branches if no uncommitted changes')),
5694 _('update across branches if no uncommitted changes')),
5695 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5695 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5696 ('r', 'rev', '', _('revision'), _('REV'))],
5696 ('r', 'rev', '', _('revision'), _('REV'))],
5697 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5697 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5698 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5698 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5699 """update working directory (or switch revisions)
5699 """update working directory (or switch revisions)
5700
5700
5701 Update the repository's working directory to the specified
5701 Update the repository's working directory to the specified
5702 changeset. If no changeset is specified, update to the tip of the
5702 changeset. If no changeset is specified, update to the tip of the
5703 current named branch and move the current bookmark (see :hg:`help
5703 current named branch and move the current bookmark (see :hg:`help
5704 bookmarks`).
5704 bookmarks`).
5705
5705
5706 Update sets the working directory's parent revision to the specified
5706 Update sets the working directory's parent revision to the specified
5707 changeset (see :hg:`help parents`).
5707 changeset (see :hg:`help parents`).
5708
5708
5709 If the changeset is not a descendant or ancestor of the working
5709 If the changeset is not a descendant or ancestor of the working
5710 directory's parent, the update is aborted. With the -c/--check
5710 directory's parent, the update is aborted. With the -c/--check
5711 option, the working directory is checked for uncommitted changes; if
5711 option, the working directory is checked for uncommitted changes; if
5712 none are found, the working directory is updated to the specified
5712 none are found, the working directory is updated to the specified
5713 changeset.
5713 changeset.
5714
5714
5715 .. container:: verbose
5715 .. container:: verbose
5716
5716
5717 The following rules apply when the working directory contains
5717 The following rules apply when the working directory contains
5718 uncommitted changes:
5718 uncommitted changes:
5719
5719
5720 1. If neither -c/--check nor -C/--clean is specified, and if
5720 1. If neither -c/--check nor -C/--clean is specified, and if
5721 the requested changeset is an ancestor or descendant of
5721 the requested changeset is an ancestor or descendant of
5722 the working directory's parent, the uncommitted changes
5722 the working directory's parent, the uncommitted changes
5723 are merged into the requested changeset and the merged
5723 are merged into the requested changeset and the merged
5724 result is left uncommitted. If the requested changeset is
5724 result is left uncommitted. If the requested changeset is
5725 not an ancestor or descendant (that is, it is on another
5725 not an ancestor or descendant (that is, it is on another
5726 branch), the update is aborted and the uncommitted changes
5726 branch), the update is aborted and the uncommitted changes
5727 are preserved.
5727 are preserved.
5728
5728
5729 2. With the -c/--check option, the update is aborted and the
5729 2. With the -c/--check option, the update is aborted and the
5730 uncommitted changes are preserved.
5730 uncommitted changes are preserved.
5731
5731
5732 3. With the -C/--clean option, uncommitted changes are discarded and
5732 3. With the -C/--clean option, uncommitted changes are discarded and
5733 the working directory is updated to the requested changeset.
5733 the working directory is updated to the requested changeset.
5734
5734
5735 To cancel an uncommitted merge (and lose your changes), use
5735 To cancel an uncommitted merge (and lose your changes), use
5736 :hg:`update --clean .`.
5736 :hg:`update --clean .`.
5737
5737
5738 Use null as the changeset to remove the working directory (like
5738 Use null as the changeset to remove the working directory (like
5739 :hg:`clone -U`).
5739 :hg:`clone -U`).
5740
5740
5741 If you want to revert just one file to an older revision, use
5741 If you want to revert just one file to an older revision, use
5742 :hg:`revert [-r REV] NAME`.
5742 :hg:`revert [-r REV] NAME`.
5743
5743
5744 See :hg:`help dates` for a list of formats valid for -d/--date.
5744 See :hg:`help dates` for a list of formats valid for -d/--date.
5745
5745
5746 Returns 0 on success, 1 if there are unresolved files.
5746 Returns 0 on success, 1 if there are unresolved files.
5747 """
5747 """
5748 if rev and node:
5748 if rev and node:
5749 raise util.Abort(_("please specify just one revision"))
5749 raise util.Abort(_("please specify just one revision"))
5750
5750
5751 if rev is None or rev == '':
5751 if rev is None or rev == '':
5752 rev = node
5752 rev = node
5753
5753
5754 # with no argument, we also move the current bookmark, if any
5754 # with no argument, we also move the current bookmark, if any
5755 movemarkfrom = None
5755 movemarkfrom = None
5756 if rev is None:
5756 if rev is None:
5757 curmark = repo._bookmarkcurrent
5757 curmark = repo._bookmarkcurrent
5758 if bookmarks.iscurrent(repo):
5758 if bookmarks.iscurrent(repo):
5759 movemarkfrom = repo['.'].node()
5759 movemarkfrom = repo['.'].node()
5760 elif curmark:
5760 elif curmark:
5761 ui.status(_("updating to active bookmark %s\n") % curmark)
5761 ui.status(_("updating to active bookmark %s\n") % curmark)
5762 rev = curmark
5762 rev = curmark
5763
5763
5764 # if we defined a bookmark, we have to remember the original bookmark name
5764 # if we defined a bookmark, we have to remember the original bookmark name
5765 brev = rev
5765 brev = rev
5766 rev = scmutil.revsingle(repo, rev, rev).rev()
5766 rev = scmutil.revsingle(repo, rev, rev).rev()
5767
5767
5768 if check and clean:
5768 if check and clean:
5769 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5769 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5770
5770
5771 if date:
5771 if date:
5772 if rev is not None:
5772 if rev is not None:
5773 raise util.Abort(_("you can't specify a revision and a date"))
5773 raise util.Abort(_("you can't specify a revision and a date"))
5774 rev = cmdutil.finddate(ui, repo, date)
5774 rev = cmdutil.finddate(ui, repo, date)
5775
5775
5776 if check:
5776 if check:
5777 c = repo[None]
5777 c = repo[None]
5778 if c.dirty(merge=False, branch=False, missing=True):
5778 if c.dirty(merge=False, branch=False, missing=True):
5779 raise util.Abort(_("uncommitted local changes"))
5779 raise util.Abort(_("uncommitted local changes"))
5780 if rev is None:
5780 if rev is None:
5781 rev = repo[repo[None].branch()].rev()
5781 rev = repo[repo[None].branch()].rev()
5782 mergemod._checkunknown(repo, repo[None], repo[rev])
5782 mergemod._checkunknown(repo, repo[None], repo[rev])
5783
5783
5784 if clean:
5784 if clean:
5785 ret = hg.clean(repo, rev)
5785 ret = hg.clean(repo, rev)
5786 else:
5786 else:
5787 ret = hg.update(repo, rev)
5787 ret = hg.update(repo, rev)
5788
5788
5789 if not ret and movemarkfrom:
5789 if not ret and movemarkfrom:
5790 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5790 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5791 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5791 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5792 elif brev in repo._bookmarks:
5792 elif brev in repo._bookmarks:
5793 bookmarks.setcurrent(repo, brev)
5793 bookmarks.setcurrent(repo, brev)
5794 elif brev:
5794 elif brev:
5795 bookmarks.unsetcurrent(repo)
5795 bookmarks.unsetcurrent(repo)
5796
5796
5797 return ret
5797 return ret
5798
5798
5799 @command('verify', [])
5799 @command('verify', [])
5800 def verify(ui, repo):
5800 def verify(ui, repo):
5801 """verify the integrity of the repository
5801 """verify the integrity of the repository
5802
5802
5803 Verify the integrity of the current repository.
5803 Verify the integrity of the current repository.
5804
5804
5805 This will perform an extensive check of the repository's
5805 This will perform an extensive check of the repository's
5806 integrity, validating the hashes and checksums of each entry in
5806 integrity, validating the hashes and checksums of each entry in
5807 the changelog, manifest, and tracked files, as well as the
5807 the changelog, manifest, and tracked files, as well as the
5808 integrity of their crosslinks and indices.
5808 integrity of their crosslinks and indices.
5809
5809
5810 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5810 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5811 for more information about recovery from corruption of the
5811 for more information about recovery from corruption of the
5812 repository.
5812 repository.
5813
5813
5814 Returns 0 on success, 1 if errors are encountered.
5814 Returns 0 on success, 1 if errors are encountered.
5815 """
5815 """
5816 return hg.verify(repo)
5816 return hg.verify(repo)
5817
5817
5818 @command('version', [])
5818 @command('version', [])
5819 def version_(ui):
5819 def version_(ui):
5820 """output version and copyright information"""
5820 """output version and copyright information"""
5821 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5821 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5822 % util.version())
5822 % util.version())
5823 ui.status(_(
5823 ui.status(_(
5824 "(see http://mercurial.selenic.com for more information)\n"
5824 "(see http://mercurial.selenic.com for more information)\n"
5825 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5825 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5826 "This is free software; see the source for copying conditions. "
5826 "This is free software; see the source for copying conditions. "
5827 "There is NO\nwarranty; "
5827 "There is NO\nwarranty; "
5828 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5828 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5829 ))
5829 ))
5830
5830
5831 norepo = ("clone init version help debugcommands debugcomplete"
5831 norepo = ("clone init version help debugcommands debugcomplete"
5832 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5832 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5833 " debugknown debuggetbundle debugbundle")
5833 " debugknown debuggetbundle debugbundle")
5834 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5834 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5835 " debugdata debugindex debugindexdot debugrevlog")
5835 " debugdata debugindex debugindexdot debugrevlog")
5836 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5836 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5837 " remove resolve status debugwalk")
5837 " remove resolve status debugwalk")
@@ -1,325 +1,325 b''
1 $ hg init test
1 $ hg init test
2 $ cd test
2 $ cd test
3
3
4 $ echo a > a
4 $ echo a > a
5 $ hg add a
5 $ hg add a
6 $ hg commit -m "test"
6 $ hg commit -m "test"
7 $ hg history
7 $ hg history
8 changeset: 0:acb14030fe0a
8 changeset: 0:acb14030fe0a
9 tag: tip
9 tag: tip
10 user: test
10 user: test
11 date: Thu Jan 01 00:00:00 1970 +0000
11 date: Thu Jan 01 00:00:00 1970 +0000
12 summary: test
12 summary: test
13
13
14
14
15 $ hg tag ' '
15 $ hg tag ' '
16 abort: tag names cannot consist entirely of whitespace
16 abort: tag names cannot consist entirely of whitespace
17 [255]
17 [255]
18
18
19 $ hg tag "bleah"
19 $ hg tag "bleah"
20 $ hg history
20 $ hg history
21 changeset: 1:d4f0d2909abc
21 changeset: 1:d4f0d2909abc
22 tag: tip
22 tag: tip
23 user: test
23 user: test
24 date: Thu Jan 01 00:00:00 1970 +0000
24 date: Thu Jan 01 00:00:00 1970 +0000
25 summary: Added tag bleah for changeset acb14030fe0a
25 summary: Added tag bleah for changeset acb14030fe0a
26
26
27 changeset: 0:acb14030fe0a
27 changeset: 0:acb14030fe0a
28 tag: bleah
28 tag: bleah
29 user: test
29 user: test
30 date: Thu Jan 01 00:00:00 1970 +0000
30 date: Thu Jan 01 00:00:00 1970 +0000
31 summary: test
31 summary: test
32
32
33
33
34 $ echo foo >> .hgtags
34 $ echo foo >> .hgtags
35 $ hg tag "bleah2"
35 $ hg tag "bleah2"
36 abort: working copy of .hgtags is changed (please commit .hgtags manually)
36 abort: working copy of .hgtags is changed (please commit .hgtags manually)
37 [255]
37 [255]
38
38
39 $ hg revert .hgtags
39 $ hg revert .hgtags
40 $ hg tag -r 0 x y z y y z
40 $ hg tag -r 0 x y z y y z
41 abort: tag names must be unique
41 abort: tag names must be unique
42 [255]
42 [255]
43 $ hg tag tap nada dot tip
43 $ hg tag tap nada dot tip
44 abort: the name 'tip' is reserved
44 abort: the name 'tip' is reserved
45 [255]
45 [255]
46 $ hg tag .
46 $ hg tag .
47 abort: the name '.' is reserved
47 abort: the name '.' is reserved
48 [255]
48 [255]
49 $ hg tag null
49 $ hg tag null
50 abort: the name 'null' is reserved
50 abort: the name 'null' is reserved
51 [255]
51 [255]
52 $ hg tag "bleah"
52 $ hg tag "bleah"
53 abort: tag 'bleah' already exists (use -f to force)
53 abort: tag 'bleah' already exists (use -f to force)
54 [255]
54 [255]
55 $ hg tag "blecch" "bleah"
55 $ hg tag "blecch" "bleah"
56 abort: tag 'bleah' already exists (use -f to force)
56 abort: tag 'bleah' already exists (use -f to force)
57 [255]
57 [255]
58
58
59 $ hg tag --remove "blecch"
59 $ hg tag --remove "blecch"
60 abort: tag 'blecch' does not exist
60 abort: tag 'blecch' does not exist
61 [255]
61 [255]
62 $ hg tag --remove "bleah" "blecch" "blough"
62 $ hg tag --remove "bleah" "blecch" "blough"
63 abort: tag 'blecch' does not exist
63 abort: tag 'blecch' does not exist
64 [255]
64 [255]
65
65
66 $ hg tag -r 0 "bleah0"
66 $ hg tag -r 0 "bleah0"
67 $ hg tag -l -r 1 "bleah1"
67 $ hg tag -l -r 1 "bleah1"
68 $ hg tag gack gawk gorp
68 $ hg tag gack gawk gorp
69 $ hg tag -f gack
69 $ hg tag -f gack
70 $ hg tag --remove gack gorp
70 $ hg tag --remove gack gorp
71
71
72 $ hg tag "bleah "
72 $ hg tag "bleah "
73 abort: tag 'bleah' already exists (use -f to force)
73 abort: tag 'bleah' already exists (use -f to force)
74 [255]
74 [255]
75 $ hg tag " bleah"
75 $ hg tag " bleah"
76 abort: tag 'bleah' already exists (use -f to force)
76 abort: tag 'bleah' already exists (use -f to force)
77 [255]
77 [255]
78 $ hg tag " bleah"
78 $ hg tag " bleah"
79 abort: tag 'bleah' already exists (use -f to force)
79 abort: tag 'bleah' already exists (use -f to force)
80 [255]
80 [255]
81 $ hg tag -r 0 " bleahbleah "
81 $ hg tag -r 0 " bleahbleah "
82 $ hg tag -r 0 " bleah bleah "
82 $ hg tag -r 0 " bleah bleah "
83
83
84 $ cat .hgtags
84 $ cat .hgtags
85 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
85 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
86 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
86 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
87 336fccc858a4eb69609a291105009e484a6b6b8d gack
87 336fccc858a4eb69609a291105009e484a6b6b8d gack
88 336fccc858a4eb69609a291105009e484a6b6b8d gawk
88 336fccc858a4eb69609a291105009e484a6b6b8d gawk
89 336fccc858a4eb69609a291105009e484a6b6b8d gorp
89 336fccc858a4eb69609a291105009e484a6b6b8d gorp
90 336fccc858a4eb69609a291105009e484a6b6b8d gack
90 336fccc858a4eb69609a291105009e484a6b6b8d gack
91 799667b6f2d9b957f73fa644a918c2df22bab58f gack
91 799667b6f2d9b957f73fa644a918c2df22bab58f gack
92 799667b6f2d9b957f73fa644a918c2df22bab58f gack
92 799667b6f2d9b957f73fa644a918c2df22bab58f gack
93 0000000000000000000000000000000000000000 gack
93 0000000000000000000000000000000000000000 gack
94 336fccc858a4eb69609a291105009e484a6b6b8d gorp
94 336fccc858a4eb69609a291105009e484a6b6b8d gorp
95 0000000000000000000000000000000000000000 gorp
95 0000000000000000000000000000000000000000 gorp
96 acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
96 acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
97 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
97 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
98
98
99 $ cat .hg/localtags
99 $ cat .hg/localtags
100 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
100 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
101
101
102 tagging on a non-head revision
102 tagging on a non-head revision
103
103
104 $ hg update 0
104 $ hg update 0
105 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
105 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
106 $ hg tag -l localblah
106 $ hg tag -l localblah
107 $ hg tag "foobar"
107 $ hg tag "foobar"
108 abort: not at a branch head (use -f to force)
108 abort: not at a branch head (use -f to force)
109 [255]
109 [255]
110 $ hg tag -f "foobar"
110 $ hg tag -f "foobar"
111 $ cat .hgtags
111 $ cat .hgtags
112 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
112 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
113 $ cat .hg/localtags
113 $ cat .hg/localtags
114 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
114 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
115 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
115 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
116
116
117 $ hg tag -l 'xx
117 $ hg tag -l 'xx
118 > newline'
118 > newline'
119 abort: '\n' cannot be used in a name
119 abort: '\n' cannot be used in a name
120 [255]
120 [255]
121 $ hg tag -l 'xx:xx'
121 $ hg tag -l 'xx:xx'
122 abort: ':' cannot be used in a name
122 abort: ':' cannot be used in a name
123 [255]
123 [255]
124
124
125 cloning local tags
125 cloning local tags
126
126
127 $ cd ..
127 $ cd ..
128 $ hg -R test log -r0:5
128 $ hg -R test log -r0:5
129 changeset: 0:acb14030fe0a
129 changeset: 0:acb14030fe0a
130 tag: bleah
130 tag: bleah
131 tag: bleah bleah
131 tag: bleah bleah
132 tag: bleah0
132 tag: bleah0
133 tag: bleahbleah
133 tag: bleahbleah
134 tag: foobar
134 tag: foobar
135 tag: localblah
135 tag: localblah
136 user: test
136 user: test
137 date: Thu Jan 01 00:00:00 1970 +0000
137 date: Thu Jan 01 00:00:00 1970 +0000
138 summary: test
138 summary: test
139
139
140 changeset: 1:d4f0d2909abc
140 changeset: 1:d4f0d2909abc
141 tag: bleah1
141 tag: bleah1
142 user: test
142 user: test
143 date: Thu Jan 01 00:00:00 1970 +0000
143 date: Thu Jan 01 00:00:00 1970 +0000
144 summary: Added tag bleah for changeset acb14030fe0a
144 summary: Added tag bleah for changeset acb14030fe0a
145
145
146 changeset: 2:336fccc858a4
146 changeset: 2:336fccc858a4
147 tag: gawk
147 tag: gawk
148 user: test
148 user: test
149 date: Thu Jan 01 00:00:00 1970 +0000
149 date: Thu Jan 01 00:00:00 1970 +0000
150 summary: Added tag bleah0 for changeset acb14030fe0a
150 summary: Added tag bleah0 for changeset acb14030fe0a
151
151
152 changeset: 3:799667b6f2d9
152 changeset: 3:799667b6f2d9
153 user: test
153 user: test
154 date: Thu Jan 01 00:00:00 1970 +0000
154 date: Thu Jan 01 00:00:00 1970 +0000
155 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
155 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
156
156
157 changeset: 4:154eeb7c0138
157 changeset: 4:154eeb7c0138
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:00 1970 +0000
159 date: Thu Jan 01 00:00:00 1970 +0000
160 summary: Added tag gack for changeset 799667b6f2d9
160 summary: Added tag gack for changeset 799667b6f2d9
161
161
162 changeset: 5:b4bb47aaff09
162 changeset: 5:b4bb47aaff09
163 user: test
163 user: test
164 date: Thu Jan 01 00:00:00 1970 +0000
164 date: Thu Jan 01 00:00:00 1970 +0000
165 summary: Removed tag gack, gorp
165 summary: Removed tag gack, gorp
166
166
167 $ hg clone -q -rbleah1 test test1
167 $ hg clone -q -rbleah1 test test1
168 $ hg -R test1 parents --style=compact
168 $ hg -R test1 parents --style=compact
169 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
169 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
170 Added tag bleah for changeset acb14030fe0a
170 Added tag bleah for changeset acb14030fe0a
171
171
172 $ hg clone -q -r5 test#bleah1 test2
172 $ hg clone -q -r5 test#bleah1 test2
173 $ hg -R test2 parents --style=compact
173 $ hg -R test2 parents --style=compact
174 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
174 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
175 Removed tag gack, gorp
175 Removed tag gack, gorp
176
176
177 $ hg clone -q -U test#bleah1 test3
177 $ hg clone -q -U test#bleah1 test3
178 $ hg -R test3 parents --style=compact
178 $ hg -R test3 parents --style=compact
179
179
180 $ cd test
180 $ cd test
181
181
182 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
182 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
183 doesn't end with EOL
183 doesn't end with EOL
184
184
185 $ python << EOF
185 $ python << EOF
186 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
186 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
187 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
187 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
188 > EOF
188 > EOF
189 $ cat .hg/localtags; echo
189 $ cat .hg/localtags; echo
190 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
190 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
191 $ hg tag -l localnewline
191 $ hg tag -l localnewline
192 $ cat .hg/localtags; echo
192 $ cat .hg/localtags; echo
193 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
193 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
194 c2899151f4e76890c602a2597a650a72666681bf localnewline
194 c2899151f4e76890c602a2597a650a72666681bf localnewline
195
195
196
196
197 $ python << EOF
197 $ python << EOF
198 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
198 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
199 > f = file('.hgtags', 'w'); f.write(last); f.close()
199 > f = file('.hgtags', 'w'); f.write(last); f.close()
200 > EOF
200 > EOF
201 $ hg ci -m'broken manual edit of .hgtags'
201 $ hg ci -m'broken manual edit of .hgtags'
202 $ cat .hgtags; echo
202 $ cat .hgtags; echo
203 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
203 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
204 $ hg tag newline
204 $ hg tag newline
205 $ cat .hgtags; echo
205 $ cat .hgtags; echo
206 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
206 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
207 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
207 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
208
208
209
209
210 tag and branch using same name
210 tag and branch using same name
211
211
212 $ hg branch tag-and-branch-same-name
212 $ hg branch tag-and-branch-same-name
213 marked working directory as branch tag-and-branch-same-name
213 marked working directory as branch tag-and-branch-same-name
214 (branches are permanent and global, did you want a bookmark?)
214 (branches are permanent and global, did you want a bookmark?)
215 $ hg ci -m"discouraged"
215 $ hg ci -m"discouraged"
216 $ hg tag tag-and-branch-same-name
216 $ hg tag tag-and-branch-same-name
217 warning: tag tag-and-branch-same-name conflicts with existing branch name
217 warning: tag tag-and-branch-same-name conflicts with existing branch name
218
218
219 test custom commit messages
219 test custom commit messages
220
220
221 $ cat > editor.sh << '__EOF__'
221 $ cat > editor.sh << '__EOF__'
222 > echo "custom tag message" > "$1"
222 > echo "custom tag message" > "$1"
223 > echo "second line" >> "$1"
223 > echo "second line" >> "$1"
224 > __EOF__
224 > __EOF__
225 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
225 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
226 $ hg log -l1 --template "{desc}\n"
226 $ hg log -l1 --template "{desc}\n"
227 custom tag message
227 custom tag message
228 second line
228 second line
229
229
230
230
231 local tag with .hgtags modified
231 local tag with .hgtags modified
232
232
233 $ hg tag hgtags-modified
233 $ hg tag hgtags-modified
234 $ hg rollback
234 $ hg rollback
235 repository tip rolled back to revision 13 (undo commit)
235 repository tip rolled back to revision 13 (undo commit)
236 working directory now based on revision 13
236 working directory now based on revision 13
237 $ hg st
237 $ hg st
238 M .hgtags
238 M .hgtags
239 ? .hgtags.orig
239 ? .hgtags.orig
240 ? editor.sh
240 ? editor.sh
241 $ hg tag --local baz
241 $ hg tag --local baz
242 $ hg revert --no-backup .hgtags
242 $ hg revert --no-backup .hgtags
243
243
244
244
245 tagging when at named-branch-head that's not a topo-head
245 tagging when at named-branch-head that's not a topo-head
246
246
247 $ hg up default
247 $ hg up default
248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 $ hg merge -t internal:local
249 $ hg merge -t internal:local
250 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
250 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
251 (branch merge, don't forget to commit)
251 (branch merge, don't forget to commit)
252 $ hg ci -m 'merge named branch'
252 $ hg ci -m 'merge named branch'
253 $ hg up 13
253 $ hg up 13
254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 $ hg tag new-topo-head
255 $ hg tag new-topo-head
256
256
257 tagging on null rev
257 tagging on null rev
258
258
259 $ hg up null
259 $ hg up null
260 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
260 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
261 $ hg tag nullrev
261 $ hg tag nullrev
262 abort: not at a branch head (use -f to force)
262 abort: not at a branch head (use -f to force)
263 [255]
263 [255]
264
264
265 $ hg init empty
265 $ hg init empty
266 $ hg tag -R empty nullrev
266 $ hg tag -R empty nullrev
267 abort: null revision specified
267 abort: cannot tag null revision
268 [255]
268 [255]
269
269
270 $ hg tag -R empty -r 00000000000 -f nulltag
270 $ hg tag -R empty -r 00000000000 -f nulltag
271 abort: null revision specified
271 abort: cannot tag null revision
272 [255]
272 [255]
273
273
274 $ cd ..
274 $ cd ..
275
275
276 tagging on an uncommitted merge (issue2542)
276 tagging on an uncommitted merge (issue2542)
277
277
278 $ hg init repo-tag-uncommitted-merge
278 $ hg init repo-tag-uncommitted-merge
279 $ cd repo-tag-uncommitted-merge
279 $ cd repo-tag-uncommitted-merge
280 $ echo c1 > f1
280 $ echo c1 > f1
281 $ hg ci -Am0
281 $ hg ci -Am0
282 adding f1
282 adding f1
283 $ echo c2 > f2
283 $ echo c2 > f2
284 $ hg ci -Am1
284 $ hg ci -Am1
285 adding f2
285 adding f2
286 $ hg co -q 0
286 $ hg co -q 0
287 $ hg branch b1
287 $ hg branch b1
288 marked working directory as branch b1
288 marked working directory as branch b1
289 (branches are permanent and global, did you want a bookmark?)
289 (branches are permanent and global, did you want a bookmark?)
290 $ hg ci -m2
290 $ hg ci -m2
291 $ hg up default
291 $ hg up default
292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
293 $ hg merge b1
293 $ hg merge b1
294 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
294 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
295 (branch merge, don't forget to commit)
295 (branch merge, don't forget to commit)
296
296
297 $ hg tag t1
297 $ hg tag t1
298 abort: uncommitted merge
298 abort: uncommitted merge
299 [255]
299 [255]
300 $ hg status
300 $ hg status
301 $ hg tag --rev 1 t2
301 $ hg tag --rev 1 t2
302 abort: uncommitted merge
302 abort: uncommitted merge
303 [255]
303 [255]
304 $ hg tag --rev 1 --local t3
304 $ hg tag --rev 1 --local t3
305 $ hg tags -v
305 $ hg tags -v
306 tip 2:2a156e8887cc
306 tip 2:2a156e8887cc
307 t3 1:c3adabd1a5f4 local
307 t3 1:c3adabd1a5f4 local
308
308
309 $ cd ..
309 $ cd ..
310
310
311 commit hook on tag used to be run without write lock - issue3344
311 commit hook on tag used to be run without write lock - issue3344
312
312
313 $ hg init repo-tag
313 $ hg init repo-tag
314 $ touch repo-tag/test
314 $ touch repo-tag/test
315 $ hg -R repo-tag commit -A -m "test"
315 $ hg -R repo-tag commit -A -m "test"
316 adding test
316 adding test
317 $ hg init repo-tag-target
317 $ hg init repo-tag-target
318 $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag
318 $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag
319 pushing to $TESTTMP/repo-tag-target
319 pushing to $TESTTMP/repo-tag-target
320 searching for changes
320 searching for changes
321 adding changesets
321 adding changesets
322 adding manifests
322 adding manifests
323 adding file changes
323 adding file changes
324 added 2 changesets with 2 changes to 2 files
324 added 2 changesets with 2 changes to 2 files
325
325
General Comments 0
You need to be logged in to leave comments. Login now