##// END OF EJS Templates
templater: deprecate --style now that -T exists
Matt Mackall -
r20669:870d6029 default
parent child Browse files
Show More
@@ -1,5883 +1,5883 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, commandserver
15 import sshserver, hgweb, commandserver
16 from hgweb import server as hgweb_server
16 from hgweb import server as hgweb_server
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge, graphmod
19 import dagparser, context, simplemerge, graphmod
20 import random
20 import random
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import phases, obsolete
22 import phases, obsolete
23
23
24 table = {}
24 table = {}
25
25
26 command = cmdutil.command(table)
26 command = cmdutil.command(table)
27
27
28 # common command options
28 # common command options
29
29
30 globalopts = [
30 globalopts = [
31 ('R', 'repository', '',
31 ('R', 'repository', '',
32 _('repository root directory or name of overlay bundle file'),
32 _('repository root directory or name of overlay bundle file'),
33 _('REPO')),
33 _('REPO')),
34 ('', 'cwd', '',
34 ('', 'cwd', '',
35 _('change working directory'), _('DIR')),
35 _('change working directory'), _('DIR')),
36 ('y', 'noninteractive', None,
36 ('y', 'noninteractive', None,
37 _('do not prompt, automatically pick the first choice for all prompts')),
37 _('do not prompt, automatically pick the first choice for all prompts')),
38 ('q', 'quiet', None, _('suppress output')),
38 ('q', 'quiet', None, _('suppress output')),
39 ('v', 'verbose', None, _('enable additional output')),
39 ('v', 'verbose', None, _('enable additional output')),
40 ('', 'config', [],
40 ('', 'config', [],
41 _('set/override config option (use \'section.name=value\')'),
41 _('set/override config option (use \'section.name=value\')'),
42 _('CONFIG')),
42 _('CONFIG')),
43 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debugger', None, _('start debugger')),
44 ('', 'debugger', None, _('start debugger')),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 _('ENCODE')),
46 _('ENCODE')),
47 ('', 'encodingmode', encoding.encodingmode,
47 ('', 'encodingmode', encoding.encodingmode,
48 _('set the charset encoding mode'), _('MODE')),
48 _('set the charset encoding mode'), _('MODE')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'time', None, _('time how long the command takes')),
50 ('', 'time', None, _('time how long the command takes')),
51 ('', 'profile', None, _('print command execution profile')),
51 ('', 'profile', None, _('print command execution profile')),
52 ('', 'version', None, _('output version information and exit')),
52 ('', 'version', None, _('output version information and exit')),
53 ('h', 'help', None, _('display help and exit')),
53 ('h', 'help', None, _('display help and exit')),
54 ('', 'hidden', False, _('consider hidden changesets')),
54 ('', 'hidden', False, _('consider hidden changesets')),
55 ]
55 ]
56
56
57 dryrunopts = [('n', 'dry-run', None,
57 dryrunopts = [('n', 'dry-run', None,
58 _('do not perform actions, just print output'))]
58 _('do not perform actions, just print output'))]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 templateopts = [
90 templateopts = [
91 ('', 'style', '',
91 ('', 'style', '',
92 _('display using template map file'), _('STYLE')),
92 _('display using template map file (DEPRECATED)'), _('STYLE')),
93 ('T', 'template', '',
93 ('T', 'template', '',
94 _('display with template'), _('TEMPLATE')),
94 _('display with template'), _('TEMPLATE')),
95 ]
95 ]
96
96
97 logopts = [
97 logopts = [
98 ('p', 'patch', None, _('show patch')),
98 ('p', 'patch', None, _('show patch')),
99 ('g', 'git', None, _('use git extended diff format')),
99 ('g', 'git', None, _('use git extended diff format')),
100 ('l', 'limit', '',
100 ('l', 'limit', '',
101 _('limit number of changes displayed'), _('NUM')),
101 _('limit number of changes displayed'), _('NUM')),
102 ('M', 'no-merges', None, _('do not show merges')),
102 ('M', 'no-merges', None, _('do not show merges')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('G', 'graph', None, _("show the revision DAG")),
104 ('G', 'graph', None, _("show the revision DAG")),
105 ] + templateopts
105 ] + templateopts
106
106
107 diffopts = [
107 diffopts = [
108 ('a', 'text', None, _('treat all files as text')),
108 ('a', 'text', None, _('treat all files as text')),
109 ('g', 'git', None, _('use git extended diff format')),
109 ('g', 'git', None, _('use git extended diff format')),
110 ('', 'nodates', None, _('omit dates from diff headers'))
110 ('', 'nodates', None, _('omit dates from diff headers'))
111 ]
111 ]
112
112
113 diffwsopts = [
113 diffwsopts = [
114 ('w', 'ignore-all-space', None,
114 ('w', 'ignore-all-space', None,
115 _('ignore white space when comparing lines')),
115 _('ignore white space when comparing lines')),
116 ('b', 'ignore-space-change', None,
116 ('b', 'ignore-space-change', None,
117 _('ignore changes in the amount of white space')),
117 _('ignore changes in the amount of white space')),
118 ('B', 'ignore-blank-lines', None,
118 ('B', 'ignore-blank-lines', None,
119 _('ignore changes whose lines are all blank')),
119 _('ignore changes whose lines are all blank')),
120 ]
120 ]
121
121
122 diffopts2 = [
122 diffopts2 = [
123 ('p', 'show-function', None, _('show which function each change is in')),
123 ('p', 'show-function', None, _('show which function each change is in')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ] + diffwsopts + [
125 ] + diffwsopts + [
126 ('U', 'unified', '',
126 ('U', 'unified', '',
127 _('number of lines of context to show'), _('NUM')),
127 _('number of lines of context to show'), _('NUM')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ]
129 ]
130
130
131 mergetoolopts = [
131 mergetoolopts = [
132 ('t', 'tool', '', _('specify merge tool')),
132 ('t', 'tool', '', _('specify merge tool')),
133 ]
133 ]
134
134
135 similarityopts = [
135 similarityopts = [
136 ('s', 'similarity', '',
136 ('s', 'similarity', '',
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 ]
138 ]
139
139
140 subrepoopts = [
140 subrepoopts = [
141 ('S', 'subrepos', None,
141 ('S', 'subrepos', None,
142 _('recurse into subrepositories'))
142 _('recurse into subrepositories'))
143 ]
143 ]
144
144
145 # Commands start here, listed alphabetically
145 # Commands start here, listed alphabetically
146
146
147 @command('^add',
147 @command('^add',
148 walkopts + subrepoopts + dryrunopts,
148 walkopts + subrepoopts + dryrunopts,
149 _('[OPTION]... [FILE]...'))
149 _('[OPTION]... [FILE]...'))
150 def add(ui, repo, *pats, **opts):
150 def add(ui, repo, *pats, **opts):
151 """add the specified files on the next commit
151 """add the specified files on the next commit
152
152
153 Schedule files to be version controlled and added to the
153 Schedule files to be version controlled and added to the
154 repository.
154 repository.
155
155
156 The files will be added to the repository at the next commit. To
156 The files will be added to the repository at the next commit. To
157 undo an add before that, see :hg:`forget`.
157 undo an add before that, see :hg:`forget`.
158
158
159 If no names are given, add all files to the repository.
159 If no names are given, add all files to the repository.
160
160
161 .. container:: verbose
161 .. container:: verbose
162
162
163 An example showing how new (unknown) files are added
163 An example showing how new (unknown) files are added
164 automatically by :hg:`add`::
164 automatically by :hg:`add`::
165
165
166 $ ls
166 $ ls
167 foo.c
167 foo.c
168 $ hg status
168 $ hg status
169 ? foo.c
169 ? foo.c
170 $ hg add
170 $ hg add
171 adding foo.c
171 adding foo.c
172 $ hg status
172 $ hg status
173 A foo.c
173 A foo.c
174
174
175 Returns 0 if all files are successfully added.
175 Returns 0 if all files are successfully added.
176 """
176 """
177
177
178 m = scmutil.match(repo[None], pats, opts)
178 m = scmutil.match(repo[None], pats, opts)
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 opts.get('subrepos'), prefix="", explicitonly=False)
180 opts.get('subrepos'), prefix="", explicitonly=False)
181 return rejected and 1 or 0
181 return rejected and 1 or 0
182
182
183 @command('addremove',
183 @command('addremove',
184 similarityopts + walkopts + dryrunopts,
184 similarityopts + walkopts + dryrunopts,
185 _('[OPTION]... [FILE]...'))
185 _('[OPTION]... [FILE]...'))
186 def addremove(ui, repo, *pats, **opts):
186 def addremove(ui, repo, *pats, **opts):
187 """add all new files, delete all missing files
187 """add all new files, delete all missing files
188
188
189 Add all new files and remove all missing files from the
189 Add all new files and remove all missing files from the
190 repository.
190 repository.
191
191
192 New files are ignored if they match any of the patterns in
192 New files are ignored if they match any of the patterns in
193 ``.hgignore``. As with add, these changes take effect at the next
193 ``.hgignore``. As with add, these changes take effect at the next
194 commit.
194 commit.
195
195
196 Use the -s/--similarity option to detect renamed files. This
196 Use the -s/--similarity option to detect renamed files. This
197 option takes a percentage between 0 (disabled) and 100 (files must
197 option takes a percentage between 0 (disabled) and 100 (files must
198 be identical) as its parameter. With a parameter greater than 0,
198 be identical) as its parameter. With a parameter greater than 0,
199 this compares every removed file with every added file and records
199 this compares every removed file with every added file and records
200 those similar enough as renames. Detecting renamed files this way
200 those similar enough as renames. Detecting renamed files this way
201 can be expensive. After using this option, :hg:`status -C` can be
201 can be expensive. After using this option, :hg:`status -C` can be
202 used to check which files were identified as moved or renamed. If
202 used to check which files were identified as moved or renamed. If
203 not specified, -s/--similarity defaults to 100 and only renames of
203 not specified, -s/--similarity defaults to 100 and only renames of
204 identical files are detected.
204 identical files are detected.
205
205
206 Returns 0 if all files are successfully added.
206 Returns 0 if all files are successfully added.
207 """
207 """
208 try:
208 try:
209 sim = float(opts.get('similarity') or 100)
209 sim = float(opts.get('similarity') or 100)
210 except ValueError:
210 except ValueError:
211 raise util.Abort(_('similarity must be a number'))
211 raise util.Abort(_('similarity must be a number'))
212 if sim < 0 or sim > 100:
212 if sim < 0 or sim > 100:
213 raise util.Abort(_('similarity must be between 0 and 100'))
213 raise util.Abort(_('similarity must be between 0 and 100'))
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215
215
216 @command('^annotate|blame',
216 @command('^annotate|blame',
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 ('', 'follow', None,
218 ('', 'follow', None,
219 _('follow copies/renames and list the filename (DEPRECATED)')),
219 _('follow copies/renames and list the filename (DEPRECATED)')),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('a', 'text', None, _('treat all files as text')),
221 ('a', 'text', None, _('treat all files as text')),
222 ('u', 'user', None, _('list the author (long with -v)')),
222 ('u', 'user', None, _('list the author (long with -v)')),
223 ('f', 'file', None, _('list the filename')),
223 ('f', 'file', None, _('list the filename')),
224 ('d', 'date', None, _('list the date (short with -q)')),
224 ('d', 'date', None, _('list the date (short with -q)')),
225 ('n', 'number', None, _('list the revision number (default)')),
225 ('n', 'number', None, _('list the revision number (default)')),
226 ('c', 'changeset', None, _('list the changeset')),
226 ('c', 'changeset', None, _('list the changeset')),
227 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ] + diffwsopts + walkopts,
228 ] + diffwsopts + walkopts,
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 def annotate(ui, repo, *pats, **opts):
230 def annotate(ui, repo, *pats, **opts):
231 """show changeset information by line for each file
231 """show changeset information by line for each file
232
232
233 List changes in files, showing the revision id responsible for
233 List changes in files, showing the revision id responsible for
234 each line
234 each line
235
235
236 This command is useful for discovering when a change was made and
236 This command is useful for discovering when a change was made and
237 by whom.
237 by whom.
238
238
239 Without the -a/--text option, annotate will avoid processing files
239 Without the -a/--text option, annotate will avoid processing files
240 it detects as binary. With -a, annotate will annotate the file
240 it detects as binary. With -a, annotate will annotate the file
241 anyway, although the results will probably be neither useful
241 anyway, although the results will probably be neither useful
242 nor desirable.
242 nor desirable.
243
243
244 Returns 0 on success.
244 Returns 0 on success.
245 """
245 """
246 if opts.get('follow'):
246 if opts.get('follow'):
247 # --follow is deprecated and now just an alias for -f/--file
247 # --follow is deprecated and now just an alias for -f/--file
248 # to mimic the behavior of Mercurial before version 1.5
248 # to mimic the behavior of Mercurial before version 1.5
249 opts['file'] = True
249 opts['file'] = True
250
250
251 datefunc = ui.quiet and util.shortdate or util.datestr
251 datefunc = ui.quiet and util.shortdate or util.datestr
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253
253
254 if not pats:
254 if not pats:
255 raise util.Abort(_('at least one filename or pattern is required'))
255 raise util.Abort(_('at least one filename or pattern is required'))
256
256
257 hexfn = ui.debugflag and hex or short
257 hexfn = ui.debugflag and hex or short
258
258
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 ('number', ' ', lambda x: str(x[0].rev())),
260 ('number', ' ', lambda x: str(x[0].rev())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('date', ' ', getdate),
262 ('date', ' ', getdate),
263 ('file', ' ', lambda x: x[0].path()),
263 ('file', ' ', lambda x: x[0].path()),
264 ('line_number', ':', lambda x: str(x[1])),
264 ('line_number', ':', lambda x: str(x[1])),
265 ]
265 ]
266
266
267 if (not opts.get('user') and not opts.get('changeset')
267 if (not opts.get('user') and not opts.get('changeset')
268 and not opts.get('date') and not opts.get('file')):
268 and not opts.get('date') and not opts.get('file')):
269 opts['number'] = True
269 opts['number'] = True
270
270
271 linenumber = opts.get('line_number') is not None
271 linenumber = opts.get('line_number') is not None
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
274
274
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277
277
278 def bad(x, y):
278 def bad(x, y):
279 raise util.Abort("%s: %s" % (x, y))
279 raise util.Abort("%s: %s" % (x, y))
280
280
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 m = scmutil.match(ctx, pats, opts)
282 m = scmutil.match(ctx, pats, opts)
283 m.bad = bad
283 m.bad = bad
284 follow = not opts.get('no_follow')
284 follow = not opts.get('no_follow')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
286 for abs in ctx.walk(m):
286 for abs in ctx.walk(m):
287 fctx = ctx[abs]
287 fctx = ctx[abs]
288 if not opts.get('text') and util.binary(fctx.data()):
288 if not opts.get('text') and util.binary(fctx.data()):
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 continue
290 continue
291
291
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 diffopts=diffopts)
293 diffopts=diffopts)
294 pieces = []
294 pieces = []
295
295
296 for f, sep in funcmap:
296 for f, sep in funcmap:
297 l = [f(n) for n, dummy in lines]
297 l = [f(n) for n, dummy in lines]
298 if l:
298 if l:
299 sized = [(x, encoding.colwidth(x)) for x in l]
299 sized = [(x, encoding.colwidth(x)) for x in l]
300 ml = max([w for x, w in sized])
300 ml = max([w for x, w in sized])
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 for x, w in sized])
302 for x, w in sized])
303
303
304 if pieces:
304 if pieces:
305 for p, l in zip(zip(*pieces), lines):
305 for p, l in zip(zip(*pieces), lines):
306 ui.write("%s: %s" % ("".join(p), l[1]))
306 ui.write("%s: %s" % ("".join(p), l[1]))
307
307
308 if lines and not lines[-1][1].endswith('\n'):
308 if lines and not lines[-1][1].endswith('\n'):
309 ui.write('\n')
309 ui.write('\n')
310
310
311 @command('archive',
311 @command('archive',
312 [('', 'no-decode', None, _('do not pass files through decoders')),
312 [('', 'no-decode', None, _('do not pass files through decoders')),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 _('PREFIX')),
314 _('PREFIX')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ] + subrepoopts + walkopts,
317 ] + subrepoopts + walkopts,
318 _('[OPTION]... DEST'))
318 _('[OPTION]... DEST'))
319 def archive(ui, repo, dest, **opts):
319 def archive(ui, repo, dest, **opts):
320 '''create an unversioned archive of a repository revision
320 '''create an unversioned archive of a repository revision
321
321
322 By default, the revision used is the parent of the working
322 By default, the revision used is the parent of the working
323 directory; use -r/--rev to specify a different revision.
323 directory; use -r/--rev to specify a different revision.
324
324
325 The archive type is automatically detected based on file
325 The archive type is automatically detected based on file
326 extension (or override using -t/--type).
326 extension (or override using -t/--type).
327
327
328 .. container:: verbose
328 .. container:: verbose
329
329
330 Examples:
330 Examples:
331
331
332 - create a zip file containing the 1.0 release::
332 - create a zip file containing the 1.0 release::
333
333
334 hg archive -r 1.0 project-1.0.zip
334 hg archive -r 1.0 project-1.0.zip
335
335
336 - create a tarball excluding .hg files::
336 - create a tarball excluding .hg files::
337
337
338 hg archive project.tar.gz -X ".hg*"
338 hg archive project.tar.gz -X ".hg*"
339
339
340 Valid types are:
340 Valid types are:
341
341
342 :``files``: a directory full of files (default)
342 :``files``: a directory full of files (default)
343 :``tar``: tar archive, uncompressed
343 :``tar``: tar archive, uncompressed
344 :``tbz2``: tar archive, compressed using bzip2
344 :``tbz2``: tar archive, compressed using bzip2
345 :``tgz``: tar archive, compressed using gzip
345 :``tgz``: tar archive, compressed using gzip
346 :``uzip``: zip archive, uncompressed
346 :``uzip``: zip archive, uncompressed
347 :``zip``: zip archive, compressed using deflate
347 :``zip``: zip archive, compressed using deflate
348
348
349 The exact name of the destination archive or directory is given
349 The exact name of the destination archive or directory is given
350 using a format string; see :hg:`help export` for details.
350 using a format string; see :hg:`help export` for details.
351
351
352 Each member added to an archive file has a directory prefix
352 Each member added to an archive file has a directory prefix
353 prepended. Use -p/--prefix to specify a format string for the
353 prepended. Use -p/--prefix to specify a format string for the
354 prefix. The default is the basename of the archive, with suffixes
354 prefix. The default is the basename of the archive, with suffixes
355 removed.
355 removed.
356
356
357 Returns 0 on success.
357 Returns 0 on success.
358 '''
358 '''
359
359
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 if not ctx:
361 if not ctx:
362 raise util.Abort(_('no working directory: please specify a revision'))
362 raise util.Abort(_('no working directory: please specify a revision'))
363 node = ctx.node()
363 node = ctx.node()
364 dest = cmdutil.makefilename(repo, dest, node)
364 dest = cmdutil.makefilename(repo, dest, node)
365 if os.path.realpath(dest) == repo.root:
365 if os.path.realpath(dest) == repo.root:
366 raise util.Abort(_('repository root cannot be destination'))
366 raise util.Abort(_('repository root cannot be destination'))
367
367
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 prefix = opts.get('prefix')
369 prefix = opts.get('prefix')
370
370
371 if dest == '-':
371 if dest == '-':
372 if kind == 'files':
372 if kind == 'files':
373 raise util.Abort(_('cannot archive plain files to stdout'))
373 raise util.Abort(_('cannot archive plain files to stdout'))
374 dest = cmdutil.makefileobj(repo, dest)
374 dest = cmdutil.makefileobj(repo, dest)
375 if not prefix:
375 if not prefix:
376 prefix = os.path.basename(repo.root) + '-%h'
376 prefix = os.path.basename(repo.root) + '-%h'
377
377
378 prefix = cmdutil.makefilename(repo, prefix, node)
378 prefix = cmdutil.makefilename(repo, prefix, node)
379 matchfn = scmutil.match(ctx, [], opts)
379 matchfn = scmutil.match(ctx, [], opts)
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 matchfn, prefix, subrepos=opts.get('subrepos'))
381 matchfn, prefix, subrepos=opts.get('subrepos'))
382
382
383 @command('backout',
383 @command('backout',
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 ('', 'parent', '',
385 ('', 'parent', '',
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 _('[OPTION]... [-r] REV'))
389 _('[OPTION]... [-r] REV'))
390 def backout(ui, repo, node=None, rev=None, **opts):
390 def backout(ui, repo, node=None, rev=None, **opts):
391 '''reverse effect of earlier changeset
391 '''reverse effect of earlier changeset
392
392
393 Prepare a new changeset with the effect of REV undone in the
393 Prepare a new changeset with the effect of REV undone in the
394 current working directory.
394 current working directory.
395
395
396 If REV is the parent of the working directory, then this new changeset
396 If REV is the parent of the working directory, then this new changeset
397 is committed automatically. Otherwise, hg needs to merge the
397 is committed automatically. Otherwise, hg needs to merge the
398 changes and the merged result is left uncommitted.
398 changes and the merged result is left uncommitted.
399
399
400 .. note::
400 .. note::
401
401
402 backout cannot be used to fix either an unwanted or
402 backout cannot be used to fix either an unwanted or
403 incorrect merge.
403 incorrect merge.
404
404
405 .. container:: verbose
405 .. container:: verbose
406
406
407 By default, the pending changeset will have one parent,
407 By default, the pending changeset will have one parent,
408 maintaining a linear history. With --merge, the pending
408 maintaining a linear history. With --merge, the pending
409 changeset will instead have two parents: the old parent of the
409 changeset will instead have two parents: the old parent of the
410 working directory and a new child of REV that simply undoes REV.
410 working directory and a new child of REV that simply undoes REV.
411
411
412 Before version 1.7, the behavior without --merge was equivalent
412 Before version 1.7, the behavior without --merge was equivalent
413 to specifying --merge followed by :hg:`update --clean .` to
413 to specifying --merge followed by :hg:`update --clean .` to
414 cancel the merge and leave the child of REV as a head to be
414 cancel the merge and leave the child of REV as a head to be
415 merged separately.
415 merged separately.
416
416
417 See :hg:`help dates` for a list of formats valid for -d/--date.
417 See :hg:`help dates` for a list of formats valid for -d/--date.
418
418
419 Returns 0 on success.
419 Returns 0 on success.
420 '''
420 '''
421 if rev and node:
421 if rev and node:
422 raise util.Abort(_("please specify just one revision"))
422 raise util.Abort(_("please specify just one revision"))
423
423
424 if not rev:
424 if not rev:
425 rev = node
425 rev = node
426
426
427 if not rev:
427 if not rev:
428 raise util.Abort(_("please specify a revision to backout"))
428 raise util.Abort(_("please specify a revision to backout"))
429
429
430 date = opts.get('date')
430 date = opts.get('date')
431 if date:
431 if date:
432 opts['date'] = util.parsedate(date)
432 opts['date'] = util.parsedate(date)
433
433
434 cmdutil.checkunfinished(repo)
434 cmdutil.checkunfinished(repo)
435 cmdutil.bailifchanged(repo)
435 cmdutil.bailifchanged(repo)
436 node = scmutil.revsingle(repo, rev).node()
436 node = scmutil.revsingle(repo, rev).node()
437
437
438 op1, op2 = repo.dirstate.parents()
438 op1, op2 = repo.dirstate.parents()
439 a = repo.changelog.ancestor(op1, node)
439 a = repo.changelog.ancestor(op1, node)
440 if a != node:
440 if a != node:
441 raise util.Abort(_('cannot backout change on a different branch'))
441 raise util.Abort(_('cannot backout change on a different branch'))
442
442
443 p1, p2 = repo.changelog.parents(node)
443 p1, p2 = repo.changelog.parents(node)
444 if p1 == nullid:
444 if p1 == nullid:
445 raise util.Abort(_('cannot backout a change with no parents'))
445 raise util.Abort(_('cannot backout a change with no parents'))
446 if p2 != nullid:
446 if p2 != nullid:
447 if not opts.get('parent'):
447 if not opts.get('parent'):
448 raise util.Abort(_('cannot backout a merge changeset'))
448 raise util.Abort(_('cannot backout a merge changeset'))
449 p = repo.lookup(opts['parent'])
449 p = repo.lookup(opts['parent'])
450 if p not in (p1, p2):
450 if p not in (p1, p2):
451 raise util.Abort(_('%s is not a parent of %s') %
451 raise util.Abort(_('%s is not a parent of %s') %
452 (short(p), short(node)))
452 (short(p), short(node)))
453 parent = p
453 parent = p
454 else:
454 else:
455 if opts.get('parent'):
455 if opts.get('parent'):
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 parent = p1
457 parent = p1
458
458
459 # the backout should appear on the same branch
459 # the backout should appear on the same branch
460 wlock = repo.wlock()
460 wlock = repo.wlock()
461 try:
461 try:
462 branch = repo.dirstate.branch()
462 branch = repo.dirstate.branch()
463 bheads = repo.branchheads(branch)
463 bheads = repo.branchheads(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
465 if not opts.get('merge') and op1 != node:
465 if not opts.get('merge') and op1 != node:
466 try:
466 try:
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 stats = mergemod.update(repo, parent, True, True, False,
468 stats = mergemod.update(repo, parent, True, True, False,
469 node, False)
469 node, False)
470 repo.setparents(op1, op2)
470 repo.setparents(op1, op2)
471 hg._showstats(repo, stats)
471 hg._showstats(repo, stats)
472 if stats[3]:
472 if stats[3]:
473 repo.ui.status(_("use 'hg resolve' to retry unresolved "
473 repo.ui.status(_("use 'hg resolve' to retry unresolved "
474 "file merges\n"))
474 "file merges\n"))
475 else:
475 else:
476 msg = _("changeset %s backed out, "
476 msg = _("changeset %s backed out, "
477 "don't forget to commit.\n")
477 "don't forget to commit.\n")
478 ui.status(msg % short(node))
478 ui.status(msg % short(node))
479 return stats[3] > 0
479 return stats[3] > 0
480 finally:
480 finally:
481 ui.setconfig('ui', 'forcemerge', '')
481 ui.setconfig('ui', 'forcemerge', '')
482 else:
482 else:
483 hg.clean(repo, node, show_stats=False)
483 hg.clean(repo, node, show_stats=False)
484 repo.dirstate.setbranch(branch)
484 repo.dirstate.setbranch(branch)
485 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
485 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
486
486
487
487
488 e = cmdutil.commiteditor
488 e = cmdutil.commiteditor
489 if not opts['message'] and not opts['logfile']:
489 if not opts['message'] and not opts['logfile']:
490 # we don't translate commit messages
490 # we don't translate commit messages
491 opts['message'] = "Backed out changeset %s" % short(node)
491 opts['message'] = "Backed out changeset %s" % short(node)
492 e = cmdutil.commitforceeditor
492 e = cmdutil.commitforceeditor
493
493
494 def commitfunc(ui, repo, message, match, opts):
494 def commitfunc(ui, repo, message, match, opts):
495 return repo.commit(message, opts.get('user'), opts.get('date'),
495 return repo.commit(message, opts.get('user'), opts.get('date'),
496 match, editor=e)
496 match, editor=e)
497 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
497 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
498 cmdutil.commitstatus(repo, newnode, branch, bheads)
498 cmdutil.commitstatus(repo, newnode, branch, bheads)
499
499
500 def nice(node):
500 def nice(node):
501 return '%d:%s' % (repo.changelog.rev(node), short(node))
501 return '%d:%s' % (repo.changelog.rev(node), short(node))
502 ui.status(_('changeset %s backs out changeset %s\n') %
502 ui.status(_('changeset %s backs out changeset %s\n') %
503 (nice(repo.changelog.tip()), nice(node)))
503 (nice(repo.changelog.tip()), nice(node)))
504 if opts.get('merge') and op1 != node:
504 if opts.get('merge') and op1 != node:
505 hg.clean(repo, op1, show_stats=False)
505 hg.clean(repo, op1, show_stats=False)
506 ui.status(_('merging with changeset %s\n')
506 ui.status(_('merging with changeset %s\n')
507 % nice(repo.changelog.tip()))
507 % nice(repo.changelog.tip()))
508 try:
508 try:
509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
509 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
510 return hg.merge(repo, hex(repo.changelog.tip()))
510 return hg.merge(repo, hex(repo.changelog.tip()))
511 finally:
511 finally:
512 ui.setconfig('ui', 'forcemerge', '')
512 ui.setconfig('ui', 'forcemerge', '')
513 finally:
513 finally:
514 wlock.release()
514 wlock.release()
515 return 0
515 return 0
516
516
517 @command('bisect',
517 @command('bisect',
518 [('r', 'reset', False, _('reset bisect state')),
518 [('r', 'reset', False, _('reset bisect state')),
519 ('g', 'good', False, _('mark changeset good')),
519 ('g', 'good', False, _('mark changeset good')),
520 ('b', 'bad', False, _('mark changeset bad')),
520 ('b', 'bad', False, _('mark changeset bad')),
521 ('s', 'skip', False, _('skip testing changeset')),
521 ('s', 'skip', False, _('skip testing changeset')),
522 ('e', 'extend', False, _('extend the bisect range')),
522 ('e', 'extend', False, _('extend the bisect range')),
523 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
523 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
524 ('U', 'noupdate', False, _('do not update to target'))],
524 ('U', 'noupdate', False, _('do not update to target'))],
525 _("[-gbsr] [-U] [-c CMD] [REV]"))
525 _("[-gbsr] [-U] [-c CMD] [REV]"))
526 def bisect(ui, repo, rev=None, extra=None, command=None,
526 def bisect(ui, repo, rev=None, extra=None, command=None,
527 reset=None, good=None, bad=None, skip=None, extend=None,
527 reset=None, good=None, bad=None, skip=None, extend=None,
528 noupdate=None):
528 noupdate=None):
529 """subdivision search of changesets
529 """subdivision search of changesets
530
530
531 This command helps to find changesets which introduce problems. To
531 This command helps to find changesets which introduce problems. To
532 use, mark the earliest changeset you know exhibits the problem as
532 use, mark the earliest changeset you know exhibits the problem as
533 bad, then mark the latest changeset which is free from the problem
533 bad, then mark the latest changeset which is free from the problem
534 as good. Bisect will update your working directory to a revision
534 as good. Bisect will update your working directory to a revision
535 for testing (unless the -U/--noupdate option is specified). Once
535 for testing (unless the -U/--noupdate option is specified). Once
536 you have performed tests, mark the working directory as good or
536 you have performed tests, mark the working directory as good or
537 bad, and bisect will either update to another candidate changeset
537 bad, and bisect will either update to another candidate changeset
538 or announce that it has found the bad revision.
538 or announce that it has found the bad revision.
539
539
540 As a shortcut, you can also use the revision argument to mark a
540 As a shortcut, you can also use the revision argument to mark a
541 revision as good or bad without checking it out first.
541 revision as good or bad without checking it out first.
542
542
543 If you supply a command, it will be used for automatic bisection.
543 If you supply a command, it will be used for automatic bisection.
544 The environment variable HG_NODE will contain the ID of the
544 The environment variable HG_NODE will contain the ID of the
545 changeset being tested. The exit status of the command will be
545 changeset being tested. The exit status of the command will be
546 used to mark revisions as good or bad: status 0 means good, 125
546 used to mark revisions as good or bad: status 0 means good, 125
547 means to skip the revision, 127 (command not found) will abort the
547 means to skip the revision, 127 (command not found) will abort the
548 bisection, and any other non-zero exit status means the revision
548 bisection, and any other non-zero exit status means the revision
549 is bad.
549 is bad.
550
550
551 .. container:: verbose
551 .. container:: verbose
552
552
553 Some examples:
553 Some examples:
554
554
555 - start a bisection with known bad revision 34, and good revision 12::
555 - start a bisection with known bad revision 34, and good revision 12::
556
556
557 hg bisect --bad 34
557 hg bisect --bad 34
558 hg bisect --good 12
558 hg bisect --good 12
559
559
560 - advance the current bisection by marking current revision as good or
560 - advance the current bisection by marking current revision as good or
561 bad::
561 bad::
562
562
563 hg bisect --good
563 hg bisect --good
564 hg bisect --bad
564 hg bisect --bad
565
565
566 - mark the current revision, or a known revision, to be skipped (e.g. if
566 - mark the current revision, or a known revision, to be skipped (e.g. if
567 that revision is not usable because of another issue)::
567 that revision is not usable because of another issue)::
568
568
569 hg bisect --skip
569 hg bisect --skip
570 hg bisect --skip 23
570 hg bisect --skip 23
571
571
572 - skip all revisions that do not touch directories ``foo`` or ``bar``::
572 - skip all revisions that do not touch directories ``foo`` or ``bar``::
573
573
574 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
574 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
575
575
576 - forget the current bisection::
576 - forget the current bisection::
577
577
578 hg bisect --reset
578 hg bisect --reset
579
579
580 - use 'make && make tests' to automatically find the first broken
580 - use 'make && make tests' to automatically find the first broken
581 revision::
581 revision::
582
582
583 hg bisect --reset
583 hg bisect --reset
584 hg bisect --bad 34
584 hg bisect --bad 34
585 hg bisect --good 12
585 hg bisect --good 12
586 hg bisect --command "make && make tests"
586 hg bisect --command "make && make tests"
587
587
588 - see all changesets whose states are already known in the current
588 - see all changesets whose states are already known in the current
589 bisection::
589 bisection::
590
590
591 hg log -r "bisect(pruned)"
591 hg log -r "bisect(pruned)"
592
592
593 - see the changeset currently being bisected (especially useful
593 - see the changeset currently being bisected (especially useful
594 if running with -U/--noupdate)::
594 if running with -U/--noupdate)::
595
595
596 hg log -r "bisect(current)"
596 hg log -r "bisect(current)"
597
597
598 - see all changesets that took part in the current bisection::
598 - see all changesets that took part in the current bisection::
599
599
600 hg log -r "bisect(range)"
600 hg log -r "bisect(range)"
601
601
602 - you can even get a nice graph::
602 - you can even get a nice graph::
603
603
604 hg log --graph -r "bisect(range)"
604 hg log --graph -r "bisect(range)"
605
605
606 See :hg:`help revsets` for more about the `bisect()` keyword.
606 See :hg:`help revsets` for more about the `bisect()` keyword.
607
607
608 Returns 0 on success.
608 Returns 0 on success.
609 """
609 """
610 def extendbisectrange(nodes, good):
610 def extendbisectrange(nodes, good):
611 # bisect is incomplete when it ends on a merge node and
611 # bisect is incomplete when it ends on a merge node and
612 # one of the parent was not checked.
612 # one of the parent was not checked.
613 parents = repo[nodes[0]].parents()
613 parents = repo[nodes[0]].parents()
614 if len(parents) > 1:
614 if len(parents) > 1:
615 side = good and state['bad'] or state['good']
615 side = good and state['bad'] or state['good']
616 num = len(set(i.node() for i in parents) & set(side))
616 num = len(set(i.node() for i in parents) & set(side))
617 if num == 1:
617 if num == 1:
618 return parents[0].ancestor(parents[1])
618 return parents[0].ancestor(parents[1])
619 return None
619 return None
620
620
621 def print_result(nodes, good):
621 def print_result(nodes, good):
622 displayer = cmdutil.show_changeset(ui, repo, {})
622 displayer = cmdutil.show_changeset(ui, repo, {})
623 if len(nodes) == 1:
623 if len(nodes) == 1:
624 # narrowed it down to a single revision
624 # narrowed it down to a single revision
625 if good:
625 if good:
626 ui.write(_("The first good revision is:\n"))
626 ui.write(_("The first good revision is:\n"))
627 else:
627 else:
628 ui.write(_("The first bad revision is:\n"))
628 ui.write(_("The first bad revision is:\n"))
629 displayer.show(repo[nodes[0]])
629 displayer.show(repo[nodes[0]])
630 extendnode = extendbisectrange(nodes, good)
630 extendnode = extendbisectrange(nodes, good)
631 if extendnode is not None:
631 if extendnode is not None:
632 ui.write(_('Not all ancestors of this changeset have been'
632 ui.write(_('Not all ancestors of this changeset have been'
633 ' checked.\nUse bisect --extend to continue the '
633 ' checked.\nUse bisect --extend to continue the '
634 'bisection from\nthe common ancestor, %s.\n')
634 'bisection from\nthe common ancestor, %s.\n')
635 % extendnode)
635 % extendnode)
636 else:
636 else:
637 # multiple possible revisions
637 # multiple possible revisions
638 if good:
638 if good:
639 ui.write(_("Due to skipped revisions, the first "
639 ui.write(_("Due to skipped revisions, the first "
640 "good revision could be any of:\n"))
640 "good revision could be any of:\n"))
641 else:
641 else:
642 ui.write(_("Due to skipped revisions, the first "
642 ui.write(_("Due to skipped revisions, the first "
643 "bad revision could be any of:\n"))
643 "bad revision could be any of:\n"))
644 for n in nodes:
644 for n in nodes:
645 displayer.show(repo[n])
645 displayer.show(repo[n])
646 displayer.close()
646 displayer.close()
647
647
648 def check_state(state, interactive=True):
648 def check_state(state, interactive=True):
649 if not state['good'] or not state['bad']:
649 if not state['good'] or not state['bad']:
650 if (good or bad or skip or reset) and interactive:
650 if (good or bad or skip or reset) and interactive:
651 return
651 return
652 if not state['good']:
652 if not state['good']:
653 raise util.Abort(_('cannot bisect (no known good revisions)'))
653 raise util.Abort(_('cannot bisect (no known good revisions)'))
654 else:
654 else:
655 raise util.Abort(_('cannot bisect (no known bad revisions)'))
655 raise util.Abort(_('cannot bisect (no known bad revisions)'))
656 return True
656 return True
657
657
658 # backward compatibility
658 # backward compatibility
659 if rev in "good bad reset init".split():
659 if rev in "good bad reset init".split():
660 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
660 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
661 cmd, rev, extra = rev, extra, None
661 cmd, rev, extra = rev, extra, None
662 if cmd == "good":
662 if cmd == "good":
663 good = True
663 good = True
664 elif cmd == "bad":
664 elif cmd == "bad":
665 bad = True
665 bad = True
666 else:
666 else:
667 reset = True
667 reset = True
668 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
668 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
669 raise util.Abort(_('incompatible arguments'))
669 raise util.Abort(_('incompatible arguments'))
670
670
671 cmdutil.checkunfinished(repo)
671 cmdutil.checkunfinished(repo)
672
672
673 if reset:
673 if reset:
674 p = repo.join("bisect.state")
674 p = repo.join("bisect.state")
675 if os.path.exists(p):
675 if os.path.exists(p):
676 os.unlink(p)
676 os.unlink(p)
677 return
677 return
678
678
679 state = hbisect.load_state(repo)
679 state = hbisect.load_state(repo)
680
680
681 if command:
681 if command:
682 changesets = 1
682 changesets = 1
683 if noupdate:
683 if noupdate:
684 try:
684 try:
685 node = state['current'][0]
685 node = state['current'][0]
686 except LookupError:
686 except LookupError:
687 raise util.Abort(_('current bisect revision is unknown - '
687 raise util.Abort(_('current bisect revision is unknown - '
688 'start a new bisect to fix'))
688 'start a new bisect to fix'))
689 else:
689 else:
690 node, p2 = repo.dirstate.parents()
690 node, p2 = repo.dirstate.parents()
691 if p2 != nullid:
691 if p2 != nullid:
692 raise util.Abort(_('current bisect revision is a merge'))
692 raise util.Abort(_('current bisect revision is a merge'))
693 try:
693 try:
694 while changesets:
694 while changesets:
695 # update state
695 # update state
696 state['current'] = [node]
696 state['current'] = [node]
697 hbisect.save_state(repo, state)
697 hbisect.save_state(repo, state)
698 status = util.system(command,
698 status = util.system(command,
699 environ={'HG_NODE': hex(node)},
699 environ={'HG_NODE': hex(node)},
700 out=ui.fout)
700 out=ui.fout)
701 if status == 125:
701 if status == 125:
702 transition = "skip"
702 transition = "skip"
703 elif status == 0:
703 elif status == 0:
704 transition = "good"
704 transition = "good"
705 # status < 0 means process was killed
705 # status < 0 means process was killed
706 elif status == 127:
706 elif status == 127:
707 raise util.Abort(_("failed to execute %s") % command)
707 raise util.Abort(_("failed to execute %s") % command)
708 elif status < 0:
708 elif status < 0:
709 raise util.Abort(_("%s killed") % command)
709 raise util.Abort(_("%s killed") % command)
710 else:
710 else:
711 transition = "bad"
711 transition = "bad"
712 ctx = scmutil.revsingle(repo, rev, node)
712 ctx = scmutil.revsingle(repo, rev, node)
713 rev = None # clear for future iterations
713 rev = None # clear for future iterations
714 state[transition].append(ctx.node())
714 state[transition].append(ctx.node())
715 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
715 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
716 check_state(state, interactive=False)
716 check_state(state, interactive=False)
717 # bisect
717 # bisect
718 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
718 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
719 # update to next check
719 # update to next check
720 node = nodes[0]
720 node = nodes[0]
721 if not noupdate:
721 if not noupdate:
722 cmdutil.bailifchanged(repo)
722 cmdutil.bailifchanged(repo)
723 hg.clean(repo, node, show_stats=False)
723 hg.clean(repo, node, show_stats=False)
724 finally:
724 finally:
725 state['current'] = [node]
725 state['current'] = [node]
726 hbisect.save_state(repo, state)
726 hbisect.save_state(repo, state)
727 print_result(nodes, bgood)
727 print_result(nodes, bgood)
728 return
728 return
729
729
730 # update state
730 # update state
731
731
732 if rev:
732 if rev:
733 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
733 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
734 else:
734 else:
735 nodes = [repo.lookup('.')]
735 nodes = [repo.lookup('.')]
736
736
737 if good or bad or skip:
737 if good or bad or skip:
738 if good:
738 if good:
739 state['good'] += nodes
739 state['good'] += nodes
740 elif bad:
740 elif bad:
741 state['bad'] += nodes
741 state['bad'] += nodes
742 elif skip:
742 elif skip:
743 state['skip'] += nodes
743 state['skip'] += nodes
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745
745
746 if not check_state(state):
746 if not check_state(state):
747 return
747 return
748
748
749 # actually bisect
749 # actually bisect
750 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
750 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
751 if extend:
751 if extend:
752 if not changesets:
752 if not changesets:
753 extendnode = extendbisectrange(nodes, good)
753 extendnode = extendbisectrange(nodes, good)
754 if extendnode is not None:
754 if extendnode is not None:
755 ui.write(_("Extending search to changeset %d:%s\n"
755 ui.write(_("Extending search to changeset %d:%s\n"
756 % (extendnode.rev(), extendnode)))
756 % (extendnode.rev(), extendnode)))
757 state['current'] = [extendnode.node()]
757 state['current'] = [extendnode.node()]
758 hbisect.save_state(repo, state)
758 hbisect.save_state(repo, state)
759 if noupdate:
759 if noupdate:
760 return
760 return
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, extendnode.node())
762 return hg.clean(repo, extendnode.node())
763 raise util.Abort(_("nothing to extend"))
763 raise util.Abort(_("nothing to extend"))
764
764
765 if changesets == 0:
765 if changesets == 0:
766 print_result(nodes, good)
766 print_result(nodes, good)
767 else:
767 else:
768 assert len(nodes) == 1 # only a single node can be tested next
768 assert len(nodes) == 1 # only a single node can be tested next
769 node = nodes[0]
769 node = nodes[0]
770 # compute the approximate number of remaining tests
770 # compute the approximate number of remaining tests
771 tests, size = 0, 2
771 tests, size = 0, 2
772 while size <= changesets:
772 while size <= changesets:
773 tests, size = tests + 1, size * 2
773 tests, size = tests + 1, size * 2
774 rev = repo.changelog.rev(node)
774 rev = repo.changelog.rev(node)
775 ui.write(_("Testing changeset %d:%s "
775 ui.write(_("Testing changeset %d:%s "
776 "(%d changesets remaining, ~%d tests)\n")
776 "(%d changesets remaining, ~%d tests)\n")
777 % (rev, short(node), changesets, tests))
777 % (rev, short(node), changesets, tests))
778 state['current'] = [node]
778 state['current'] = [node]
779 hbisect.save_state(repo, state)
779 hbisect.save_state(repo, state)
780 if not noupdate:
780 if not noupdate:
781 cmdutil.bailifchanged(repo)
781 cmdutil.bailifchanged(repo)
782 return hg.clean(repo, node)
782 return hg.clean(repo, node)
783
783
784 @command('bookmarks|bookmark',
784 @command('bookmarks|bookmark',
785 [('f', 'force', False, _('force')),
785 [('f', 'force', False, _('force')),
786 ('r', 'rev', '', _('revision'), _('REV')),
786 ('r', 'rev', '', _('revision'), _('REV')),
787 ('d', 'delete', False, _('delete a given bookmark')),
787 ('d', 'delete', False, _('delete a given bookmark')),
788 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
788 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
789 ('i', 'inactive', False, _('mark a bookmark inactive'))],
789 ('i', 'inactive', False, _('mark a bookmark inactive'))],
790 _('hg bookmarks [OPTIONS]... [NAME]...'))
790 _('hg bookmarks [OPTIONS]... [NAME]...'))
791 def bookmark(ui, repo, *names, **opts):
791 def bookmark(ui, repo, *names, **opts):
792 '''track a line of development with movable markers
792 '''track a line of development with movable markers
793
793
794 Bookmarks are pointers to certain commits that move when committing.
794 Bookmarks are pointers to certain commits that move when committing.
795 Bookmarks are local. They can be renamed, copied and deleted. It is
795 Bookmarks are local. They can be renamed, copied and deleted. It is
796 possible to use :hg:`merge NAME` to merge from a given bookmark, and
796 possible to use :hg:`merge NAME` to merge from a given bookmark, and
797 :hg:`update NAME` to update to a given bookmark.
797 :hg:`update NAME` to update to a given bookmark.
798
798
799 You can use :hg:`bookmark NAME` to set a bookmark on the working
799 You can use :hg:`bookmark NAME` to set a bookmark on the working
800 directory's parent revision with the given name. If you specify
800 directory's parent revision with the given name. If you specify
801 a revision using -r REV (where REV may be an existing bookmark),
801 a revision using -r REV (where REV may be an existing bookmark),
802 the bookmark is assigned to that revision.
802 the bookmark is assigned to that revision.
803
803
804 Bookmarks can be pushed and pulled between repositories (see :hg:`help
804 Bookmarks can be pushed and pulled between repositories (see :hg:`help
805 push` and :hg:`help pull`). This requires both the local and remote
805 push` and :hg:`help pull`). This requires both the local and remote
806 repositories to support bookmarks. For versions prior to 1.8, this means
806 repositories to support bookmarks. For versions prior to 1.8, this means
807 the bookmarks extension must be enabled.
807 the bookmarks extension must be enabled.
808
808
809 If you set a bookmark called '@', new clones of the repository will
809 If you set a bookmark called '@', new clones of the repository will
810 have that revision checked out (and the bookmark made active) by
810 have that revision checked out (and the bookmark made active) by
811 default.
811 default.
812
812
813 With -i/--inactive, the new bookmark will not be made the active
813 With -i/--inactive, the new bookmark will not be made the active
814 bookmark. If -r/--rev is given, the new bookmark will not be made
814 bookmark. If -r/--rev is given, the new bookmark will not be made
815 active even if -i/--inactive is not given. If no NAME is given, the
815 active even if -i/--inactive is not given. If no NAME is given, the
816 current active bookmark will be marked inactive.
816 current active bookmark will be marked inactive.
817 '''
817 '''
818 force = opts.get('force')
818 force = opts.get('force')
819 rev = opts.get('rev')
819 rev = opts.get('rev')
820 delete = opts.get('delete')
820 delete = opts.get('delete')
821 rename = opts.get('rename')
821 rename = opts.get('rename')
822 inactive = opts.get('inactive')
822 inactive = opts.get('inactive')
823
823
824 def checkformat(mark):
824 def checkformat(mark):
825 mark = mark.strip()
825 mark = mark.strip()
826 if not mark:
826 if not mark:
827 raise util.Abort(_("bookmark names cannot consist entirely of "
827 raise util.Abort(_("bookmark names cannot consist entirely of "
828 "whitespace"))
828 "whitespace"))
829 scmutil.checknewlabel(repo, mark, 'bookmark')
829 scmutil.checknewlabel(repo, mark, 'bookmark')
830 return mark
830 return mark
831
831
832 def checkconflict(repo, mark, cur, force=False, target=None):
832 def checkconflict(repo, mark, cur, force=False, target=None):
833 if mark in marks and not force:
833 if mark in marks and not force:
834 if target:
834 if target:
835 if marks[mark] == target and target == cur:
835 if marks[mark] == target and target == cur:
836 # re-activating a bookmark
836 # re-activating a bookmark
837 return
837 return
838 anc = repo.changelog.ancestors([repo[target].rev()])
838 anc = repo.changelog.ancestors([repo[target].rev()])
839 bmctx = repo[marks[mark]]
839 bmctx = repo[marks[mark]]
840 divs = [repo[b].node() for b in marks
840 divs = [repo[b].node() for b in marks
841 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
841 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
842
842
843 # allow resolving a single divergent bookmark even if moving
843 # allow resolving a single divergent bookmark even if moving
844 # the bookmark across branches when a revision is specified
844 # the bookmark across branches when a revision is specified
845 # that contains a divergent bookmark
845 # that contains a divergent bookmark
846 if bmctx.rev() not in anc and target in divs:
846 if bmctx.rev() not in anc and target in divs:
847 bookmarks.deletedivergent(repo, [target], mark)
847 bookmarks.deletedivergent(repo, [target], mark)
848 return
848 return
849
849
850 deletefrom = [b for b in divs
850 deletefrom = [b for b in divs
851 if repo[b].rev() in anc or b == target]
851 if repo[b].rev() in anc or b == target]
852 bookmarks.deletedivergent(repo, deletefrom, mark)
852 bookmarks.deletedivergent(repo, deletefrom, mark)
853 if bookmarks.validdest(repo, bmctx, repo[target]):
853 if bookmarks.validdest(repo, bmctx, repo[target]):
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
855 (mark, short(bmctx.node())))
855 (mark, short(bmctx.node())))
856 return
856 return
857 raise util.Abort(_("bookmark '%s' already exists "
857 raise util.Abort(_("bookmark '%s' already exists "
858 "(use -f to force)") % mark)
858 "(use -f to force)") % mark)
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
860 and not force):
860 and not force):
861 raise util.Abort(
861 raise util.Abort(
862 _("a bookmark cannot have the name of an existing branch"))
862 _("a bookmark cannot have the name of an existing branch"))
863
863
864 if delete and rename:
864 if delete and rename:
865 raise util.Abort(_("--delete and --rename are incompatible"))
865 raise util.Abort(_("--delete and --rename are incompatible"))
866 if delete and rev:
866 if delete and rev:
867 raise util.Abort(_("--rev is incompatible with --delete"))
867 raise util.Abort(_("--rev is incompatible with --delete"))
868 if rename and rev:
868 if rename and rev:
869 raise util.Abort(_("--rev is incompatible with --rename"))
869 raise util.Abort(_("--rev is incompatible with --rename"))
870 if not names and (delete or rev):
870 if not names and (delete or rev):
871 raise util.Abort(_("bookmark name required"))
871 raise util.Abort(_("bookmark name required"))
872
872
873 if delete or rename or names or inactive:
873 if delete or rename or names or inactive:
874 wlock = repo.wlock()
874 wlock = repo.wlock()
875 try:
875 try:
876 cur = repo.changectx('.').node()
876 cur = repo.changectx('.').node()
877 marks = repo._bookmarks
877 marks = repo._bookmarks
878 if delete:
878 if delete:
879 for mark in names:
879 for mark in names:
880 if mark not in marks:
880 if mark not in marks:
881 raise util.Abort(_("bookmark '%s' does not exist") %
881 raise util.Abort(_("bookmark '%s' does not exist") %
882 mark)
882 mark)
883 if mark == repo._bookmarkcurrent:
883 if mark == repo._bookmarkcurrent:
884 bookmarks.unsetcurrent(repo)
884 bookmarks.unsetcurrent(repo)
885 del marks[mark]
885 del marks[mark]
886 marks.write()
886 marks.write()
887
887
888 elif rename:
888 elif rename:
889 if not names:
889 if not names:
890 raise util.Abort(_("new bookmark name required"))
890 raise util.Abort(_("new bookmark name required"))
891 elif len(names) > 1:
891 elif len(names) > 1:
892 raise util.Abort(_("only one new bookmark name allowed"))
892 raise util.Abort(_("only one new bookmark name allowed"))
893 mark = checkformat(names[0])
893 mark = checkformat(names[0])
894 if rename not in marks:
894 if rename not in marks:
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
896 checkconflict(repo, mark, cur, force)
896 checkconflict(repo, mark, cur, force)
897 marks[mark] = marks[rename]
897 marks[mark] = marks[rename]
898 if repo._bookmarkcurrent == rename and not inactive:
898 if repo._bookmarkcurrent == rename and not inactive:
899 bookmarks.setcurrent(repo, mark)
899 bookmarks.setcurrent(repo, mark)
900 del marks[rename]
900 del marks[rename]
901 marks.write()
901 marks.write()
902
902
903 elif names:
903 elif names:
904 newact = None
904 newact = None
905 for mark in names:
905 for mark in names:
906 mark = checkformat(mark)
906 mark = checkformat(mark)
907 if newact is None:
907 if newact is None:
908 newact = mark
908 newact = mark
909 if inactive and mark == repo._bookmarkcurrent:
909 if inactive and mark == repo._bookmarkcurrent:
910 bookmarks.unsetcurrent(repo)
910 bookmarks.unsetcurrent(repo)
911 return
911 return
912 tgt = cur
912 tgt = cur
913 if rev:
913 if rev:
914 tgt = scmutil.revsingle(repo, rev).node()
914 tgt = scmutil.revsingle(repo, rev).node()
915 checkconflict(repo, mark, cur, force, tgt)
915 checkconflict(repo, mark, cur, force, tgt)
916 marks[mark] = tgt
916 marks[mark] = tgt
917 if not inactive and cur == marks[newact] and not rev:
917 if not inactive and cur == marks[newact] and not rev:
918 bookmarks.setcurrent(repo, newact)
918 bookmarks.setcurrent(repo, newact)
919 elif cur != tgt and newact == repo._bookmarkcurrent:
919 elif cur != tgt and newact == repo._bookmarkcurrent:
920 bookmarks.unsetcurrent(repo)
920 bookmarks.unsetcurrent(repo)
921 marks.write()
921 marks.write()
922
922
923 elif inactive:
923 elif inactive:
924 if len(marks) == 0:
924 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
925 ui.status(_("no bookmarks set\n"))
926 elif not repo._bookmarkcurrent:
926 elif not repo._bookmarkcurrent:
927 ui.status(_("no active bookmark\n"))
927 ui.status(_("no active bookmark\n"))
928 else:
928 else:
929 bookmarks.unsetcurrent(repo)
929 bookmarks.unsetcurrent(repo)
930 finally:
930 finally:
931 wlock.release()
931 wlock.release()
932 else: # show bookmarks
932 else: # show bookmarks
933 hexfn = ui.debugflag and hex or short
933 hexfn = ui.debugflag and hex or short
934 marks = repo._bookmarks
934 marks = repo._bookmarks
935 if len(marks) == 0:
935 if len(marks) == 0:
936 ui.status(_("no bookmarks set\n"))
936 ui.status(_("no bookmarks set\n"))
937 else:
937 else:
938 for bmark, n in sorted(marks.iteritems()):
938 for bmark, n in sorted(marks.iteritems()):
939 current = repo._bookmarkcurrent
939 current = repo._bookmarkcurrent
940 if bmark == current:
940 if bmark == current:
941 prefix, label = '*', 'bookmarks.current'
941 prefix, label = '*', 'bookmarks.current'
942 else:
942 else:
943 prefix, label = ' ', ''
943 prefix, label = ' ', ''
944
944
945 if ui.quiet:
945 if ui.quiet:
946 ui.write("%s\n" % bmark, label=label)
946 ui.write("%s\n" % bmark, label=label)
947 else:
947 else:
948 ui.write(" %s %-25s %d:%s\n" % (
948 ui.write(" %s %-25s %d:%s\n" % (
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
950 label=label)
950 label=label)
951
951
952 @command('branch',
952 @command('branch',
953 [('f', 'force', None,
953 [('f', 'force', None,
954 _('set branch name even if it shadows an existing branch')),
954 _('set branch name even if it shadows an existing branch')),
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
956 _('[-fC] [NAME]'))
956 _('[-fC] [NAME]'))
957 def branch(ui, repo, label=None, **opts):
957 def branch(ui, repo, label=None, **opts):
958 """set or show the current branch name
958 """set or show the current branch name
959
959
960 .. note::
960 .. note::
961
961
962 Branch names are permanent and global. Use :hg:`bookmark` to create a
962 Branch names are permanent and global. Use :hg:`bookmark` to create a
963 light-weight bookmark instead. See :hg:`help glossary` for more
963 light-weight bookmark instead. See :hg:`help glossary` for more
964 information about named branches and bookmarks.
964 information about named branches and bookmarks.
965
965
966 With no argument, show the current branch name. With one argument,
966 With no argument, show the current branch name. With one argument,
967 set the working directory branch name (the branch will not exist
967 set the working directory branch name (the branch will not exist
968 in the repository until the next commit). Standard practice
968 in the repository until the next commit). Standard practice
969 recommends that primary development take place on the 'default'
969 recommends that primary development take place on the 'default'
970 branch.
970 branch.
971
971
972 Unless -f/--force is specified, branch will not let you set a
972 Unless -f/--force is specified, branch will not let you set a
973 branch name that already exists, even if it's inactive.
973 branch name that already exists, even if it's inactive.
974
974
975 Use -C/--clean to reset the working directory branch to that of
975 Use -C/--clean to reset the working directory branch to that of
976 the parent of the working directory, negating a previous branch
976 the parent of the working directory, negating a previous branch
977 change.
977 change.
978
978
979 Use the command :hg:`update` to switch to an existing branch. Use
979 Use the command :hg:`update` to switch to an existing branch. Use
980 :hg:`commit --close-branch` to mark this branch as closed.
980 :hg:`commit --close-branch` to mark this branch as closed.
981
981
982 Returns 0 on success.
982 Returns 0 on success.
983 """
983 """
984 if label:
984 if label:
985 label = label.strip()
985 label = label.strip()
986
986
987 if not opts.get('clean') and not label:
987 if not opts.get('clean') and not label:
988 ui.write("%s\n" % repo.dirstate.branch())
988 ui.write("%s\n" % repo.dirstate.branch())
989 return
989 return
990
990
991 wlock = repo.wlock()
991 wlock = repo.wlock()
992 try:
992 try:
993 if opts.get('clean'):
993 if opts.get('clean'):
994 label = repo[None].p1().branch()
994 label = repo[None].p1().branch()
995 repo.dirstate.setbranch(label)
995 repo.dirstate.setbranch(label)
996 ui.status(_('reset working directory to branch %s\n') % label)
996 ui.status(_('reset working directory to branch %s\n') % label)
997 elif label:
997 elif label:
998 if not opts.get('force') and label in repo.branchmap():
998 if not opts.get('force') and label in repo.branchmap():
999 if label not in [p.branch() for p in repo.parents()]:
999 if label not in [p.branch() for p in repo.parents()]:
1000 raise util.Abort(_('a branch of the same name already'
1000 raise util.Abort(_('a branch of the same name already'
1001 ' exists'),
1001 ' exists'),
1002 # i18n: "it" refers to an existing branch
1002 # i18n: "it" refers to an existing branch
1003 hint=_("use 'hg update' to switch to it"))
1003 hint=_("use 'hg update' to switch to it"))
1004 scmutil.checknewlabel(repo, label, 'branch')
1004 scmutil.checknewlabel(repo, label, 'branch')
1005 repo.dirstate.setbranch(label)
1005 repo.dirstate.setbranch(label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1007 ui.status(_('(branches are permanent and global, '
1007 ui.status(_('(branches are permanent and global, '
1008 'did you want a bookmark?)\n'))
1008 'did you want a bookmark?)\n'))
1009 finally:
1009 finally:
1010 wlock.release()
1010 wlock.release()
1011
1011
1012 @command('branches',
1012 @command('branches',
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1015 _('[-ac]'))
1015 _('[-ac]'))
1016 def branches(ui, repo, active=False, closed=False):
1016 def branches(ui, repo, active=False, closed=False):
1017 """list repository named branches
1017 """list repository named branches
1018
1018
1019 List the repository's named branches, indicating which ones are
1019 List the repository's named branches, indicating which ones are
1020 inactive. If -c/--closed is specified, also list branches which have
1020 inactive. If -c/--closed is specified, also list branches which have
1021 been marked closed (see :hg:`commit --close-branch`).
1021 been marked closed (see :hg:`commit --close-branch`).
1022
1022
1023 If -a/--active is specified, only show active branches. A branch
1023 If -a/--active is specified, only show active branches. A branch
1024 is considered active if it contains repository heads.
1024 is considered active if it contains repository heads.
1025
1025
1026 Use the command :hg:`update` to switch to an existing branch.
1026 Use the command :hg:`update` to switch to an existing branch.
1027
1027
1028 Returns 0.
1028 Returns 0.
1029 """
1029 """
1030
1030
1031 hexfunc = ui.debugflag and hex or short
1031 hexfunc = ui.debugflag and hex or short
1032
1032
1033 allheads = set(repo.heads())
1033 allheads = set(repo.heads())
1034 branches = []
1034 branches = []
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1036 isactive = not isclosed and bool(set(heads) & allheads)
1036 isactive = not isclosed and bool(set(heads) & allheads)
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1038 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1038 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1039 reverse=True)
1039 reverse=True)
1040
1040
1041 for tag, ctx, isactive, isopen in branches:
1041 for tag, ctx, isactive, isopen in branches:
1042 if (not active) or isactive:
1042 if (not active) or isactive:
1043 if isactive:
1043 if isactive:
1044 label = 'branches.active'
1044 label = 'branches.active'
1045 notice = ''
1045 notice = ''
1046 elif not isopen:
1046 elif not isopen:
1047 if not closed:
1047 if not closed:
1048 continue
1048 continue
1049 label = 'branches.closed'
1049 label = 'branches.closed'
1050 notice = _(' (closed)')
1050 notice = _(' (closed)')
1051 else:
1051 else:
1052 label = 'branches.inactive'
1052 label = 'branches.inactive'
1053 notice = _(' (inactive)')
1053 notice = _(' (inactive)')
1054 if tag == repo.dirstate.branch():
1054 if tag == repo.dirstate.branch():
1055 label = 'branches.current'
1055 label = 'branches.current'
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1058 'log.changeset changeset.%s' % ctx.phasestr())
1058 'log.changeset changeset.%s' % ctx.phasestr())
1059 labeledtag = ui.label(tag, label)
1059 labeledtag = ui.label(tag, label)
1060 if ui.quiet:
1060 if ui.quiet:
1061 ui.write("%s\n" % labeledtag)
1061 ui.write("%s\n" % labeledtag)
1062 else:
1062 else:
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1064
1064
1065 @command('bundle',
1065 @command('bundle',
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1068 _('REV')),
1068 _('REV')),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1070 _('BRANCH')),
1070 _('BRANCH')),
1071 ('', 'base', [],
1071 ('', 'base', [],
1072 _('a base changeset assumed to be available at the destination'),
1072 _('a base changeset assumed to be available at the destination'),
1073 _('REV')),
1073 _('REV')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1076 ] + remoteopts,
1076 ] + remoteopts,
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1078 def bundle(ui, repo, fname, dest=None, **opts):
1078 def bundle(ui, repo, fname, dest=None, **opts):
1079 """create a changegroup file
1079 """create a changegroup file
1080
1080
1081 Generate a compressed changegroup file collecting changesets not
1081 Generate a compressed changegroup file collecting changesets not
1082 known to be in another repository.
1082 known to be in another repository.
1083
1083
1084 If you omit the destination repository, then hg assumes the
1084 If you omit the destination repository, then hg assumes the
1085 destination will have all the nodes you specify with --base
1085 destination will have all the nodes you specify with --base
1086 parameters. To create a bundle containing all changesets, use
1086 parameters. To create a bundle containing all changesets, use
1087 -a/--all (or --base null).
1087 -a/--all (or --base null).
1088
1088
1089 You can change compression method with the -t/--type option.
1089 You can change compression method with the -t/--type option.
1090 The available compression methods are: none, bzip2, and
1090 The available compression methods are: none, bzip2, and
1091 gzip (by default, bundles are compressed using bzip2).
1091 gzip (by default, bundles are compressed using bzip2).
1092
1092
1093 The bundle file can then be transferred using conventional means
1093 The bundle file can then be transferred using conventional means
1094 and applied to another repository with the unbundle or pull
1094 and applied to another repository with the unbundle or pull
1095 command. This is useful when direct push and pull are not
1095 command. This is useful when direct push and pull are not
1096 available or when exporting an entire repository is undesirable.
1096 available or when exporting an entire repository is undesirable.
1097
1097
1098 Applying bundles preserves all changeset contents including
1098 Applying bundles preserves all changeset contents including
1099 permissions, copy/rename information, and revision history.
1099 permissions, copy/rename information, and revision history.
1100
1100
1101 Returns 0 on success, 1 if no changes found.
1101 Returns 0 on success, 1 if no changes found.
1102 """
1102 """
1103 revs = None
1103 revs = None
1104 if 'rev' in opts:
1104 if 'rev' in opts:
1105 revs = scmutil.revrange(repo, opts['rev'])
1105 revs = scmutil.revrange(repo, opts['rev'])
1106
1106
1107 bundletype = opts.get('type', 'bzip2').lower()
1107 bundletype = opts.get('type', 'bzip2').lower()
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1109 bundletype = btypes.get(bundletype)
1109 bundletype = btypes.get(bundletype)
1110 if bundletype not in changegroup.bundletypes:
1110 if bundletype not in changegroup.bundletypes:
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1112
1112
1113 if opts.get('all'):
1113 if opts.get('all'):
1114 base = ['null']
1114 base = ['null']
1115 else:
1115 else:
1116 base = scmutil.revrange(repo, opts.get('base'))
1116 base = scmutil.revrange(repo, opts.get('base'))
1117 # TODO: get desired bundlecaps from command line.
1117 # TODO: get desired bundlecaps from command line.
1118 bundlecaps = None
1118 bundlecaps = None
1119 if base:
1119 if base:
1120 if dest:
1120 if dest:
1121 raise util.Abort(_("--base is incompatible with specifying "
1121 raise util.Abort(_("--base is incompatible with specifying "
1122 "a destination"))
1122 "a destination"))
1123 common = [repo.lookup(rev) for rev in base]
1123 common = [repo.lookup(rev) for rev in base]
1124 heads = revs and map(repo.lookup, revs) or revs
1124 heads = revs and map(repo.lookup, revs) or revs
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1126 bundlecaps=bundlecaps)
1126 bundlecaps=bundlecaps)
1127 outgoing = None
1127 outgoing = None
1128 else:
1128 else:
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1131 other = hg.peer(repo, opts, dest)
1131 other = hg.peer(repo, opts, dest)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1133 heads = revs and map(repo.lookup, revs) or revs
1133 heads = revs and map(repo.lookup, revs) or revs
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1135 onlyheads=heads,
1135 onlyheads=heads,
1136 force=opts.get('force'),
1136 force=opts.get('force'),
1137 portable=True)
1137 portable=True)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1139 if not cg:
1139 if not cg:
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1141 return 1
1141 return 1
1142
1142
1143 changegroup.writebundle(cg, fname, bundletype)
1143 changegroup.writebundle(cg, fname, bundletype)
1144
1144
1145 @command('cat',
1145 @command('cat',
1146 [('o', 'output', '',
1146 [('o', 'output', '',
1147 _('print output to file with formatted name'), _('FORMAT')),
1147 _('print output to file with formatted name'), _('FORMAT')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1150 ] + walkopts,
1150 ] + walkopts,
1151 _('[OPTION]... FILE...'))
1151 _('[OPTION]... FILE...'))
1152 def cat(ui, repo, file1, *pats, **opts):
1152 def cat(ui, repo, file1, *pats, **opts):
1153 """output the current or given revision of files
1153 """output the current or given revision of files
1154
1154
1155 Print the specified files as they were at the given revision. If
1155 Print the specified files as they were at the given revision. If
1156 no revision is given, the parent of the working directory is used.
1156 no revision is given, the parent of the working directory is used.
1157
1157
1158 Output may be to a file, in which case the name of the file is
1158 Output may be to a file, in which case the name of the file is
1159 given using a format string. The formatting rules are the same as
1159 given using a format string. The formatting rules are the same as
1160 for the export command, with the following additions:
1160 for the export command, with the following additions:
1161
1161
1162 :``%s``: basename of file being printed
1162 :``%s``: basename of file being printed
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1164 :``%p``: root-relative path name of file being printed
1164 :``%p``: root-relative path name of file being printed
1165
1165
1166 Returns 0 on success.
1166 Returns 0 on success.
1167 """
1167 """
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1169 err = 1
1169 err = 1
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1171
1171
1172 def write(path):
1172 def write(path):
1173 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1173 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1174 pathname=path)
1174 pathname=path)
1175 data = ctx[path].data()
1175 data = ctx[path].data()
1176 if opts.get('decode'):
1176 if opts.get('decode'):
1177 data = repo.wwritedata(path, data)
1177 data = repo.wwritedata(path, data)
1178 fp.write(data)
1178 fp.write(data)
1179 fp.close()
1179 fp.close()
1180
1180
1181 # Automation often uses hg cat on single files, so special case it
1181 # Automation often uses hg cat on single files, so special case it
1182 # for performance to avoid the cost of parsing the manifest.
1182 # for performance to avoid the cost of parsing the manifest.
1183 if len(m.files()) == 1 and not m.anypats():
1183 if len(m.files()) == 1 and not m.anypats():
1184 file = m.files()[0]
1184 file = m.files()[0]
1185 mf = repo.manifest
1185 mf = repo.manifest
1186 mfnode = ctx._changeset[0]
1186 mfnode = ctx._changeset[0]
1187 if mf.find(mfnode, file)[0]:
1187 if mf.find(mfnode, file)[0]:
1188 write(file)
1188 write(file)
1189 return 0
1189 return 0
1190
1190
1191 for abs in ctx.walk(m):
1191 for abs in ctx.walk(m):
1192 write(abs)
1192 write(abs)
1193 err = 0
1193 err = 0
1194 return err
1194 return err
1195
1195
1196 @command('^clone',
1196 @command('^clone',
1197 [('U', 'noupdate', None,
1197 [('U', 'noupdate', None,
1198 _('the clone will include an empty working copy (only a repository)')),
1198 _('the clone will include an empty working copy (only a repository)')),
1199 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1199 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1200 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1200 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1201 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1201 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1202 ('', 'pull', None, _('use pull protocol to copy metadata')),
1202 ('', 'pull', None, _('use pull protocol to copy metadata')),
1203 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1203 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1204 ] + remoteopts,
1204 ] + remoteopts,
1205 _('[OPTION]... SOURCE [DEST]'))
1205 _('[OPTION]... SOURCE [DEST]'))
1206 def clone(ui, source, dest=None, **opts):
1206 def clone(ui, source, dest=None, **opts):
1207 """make a copy of an existing repository
1207 """make a copy of an existing repository
1208
1208
1209 Create a copy of an existing repository in a new directory.
1209 Create a copy of an existing repository in a new directory.
1210
1210
1211 If no destination directory name is specified, it defaults to the
1211 If no destination directory name is specified, it defaults to the
1212 basename of the source.
1212 basename of the source.
1213
1213
1214 The location of the source is added to the new repository's
1214 The location of the source is added to the new repository's
1215 ``.hg/hgrc`` file, as the default to be used for future pulls.
1215 ``.hg/hgrc`` file, as the default to be used for future pulls.
1216
1216
1217 Only local paths and ``ssh://`` URLs are supported as
1217 Only local paths and ``ssh://`` URLs are supported as
1218 destinations. For ``ssh://`` destinations, no working directory or
1218 destinations. For ``ssh://`` destinations, no working directory or
1219 ``.hg/hgrc`` will be created on the remote side.
1219 ``.hg/hgrc`` will be created on the remote side.
1220
1220
1221 To pull only a subset of changesets, specify one or more revisions
1221 To pull only a subset of changesets, specify one or more revisions
1222 identifiers with -r/--rev or branches with -b/--branch. The
1222 identifiers with -r/--rev or branches with -b/--branch. The
1223 resulting clone will contain only the specified changesets and
1223 resulting clone will contain only the specified changesets and
1224 their ancestors. These options (or 'clone src#rev dest') imply
1224 their ancestors. These options (or 'clone src#rev dest') imply
1225 --pull, even for local source repositories. Note that specifying a
1225 --pull, even for local source repositories. Note that specifying a
1226 tag will include the tagged changeset but not the changeset
1226 tag will include the tagged changeset but not the changeset
1227 containing the tag.
1227 containing the tag.
1228
1228
1229 If the source repository has a bookmark called '@' set, that
1229 If the source repository has a bookmark called '@' set, that
1230 revision will be checked out in the new repository by default.
1230 revision will be checked out in the new repository by default.
1231
1231
1232 To check out a particular version, use -u/--update, or
1232 To check out a particular version, use -u/--update, or
1233 -U/--noupdate to create a clone with no working directory.
1233 -U/--noupdate to create a clone with no working directory.
1234
1234
1235 .. container:: verbose
1235 .. container:: verbose
1236
1236
1237 For efficiency, hardlinks are used for cloning whenever the
1237 For efficiency, hardlinks are used for cloning whenever the
1238 source and destination are on the same filesystem (note this
1238 source and destination are on the same filesystem (note this
1239 applies only to the repository data, not to the working
1239 applies only to the repository data, not to the working
1240 directory). Some filesystems, such as AFS, implement hardlinking
1240 directory). Some filesystems, such as AFS, implement hardlinking
1241 incorrectly, but do not report errors. In these cases, use the
1241 incorrectly, but do not report errors. In these cases, use the
1242 --pull option to avoid hardlinking.
1242 --pull option to avoid hardlinking.
1243
1243
1244 In some cases, you can clone repositories and the working
1244 In some cases, you can clone repositories and the working
1245 directory using full hardlinks with ::
1245 directory using full hardlinks with ::
1246
1246
1247 $ cp -al REPO REPOCLONE
1247 $ cp -al REPO REPOCLONE
1248
1248
1249 This is the fastest way to clone, but it is not always safe. The
1249 This is the fastest way to clone, but it is not always safe. The
1250 operation is not atomic (making sure REPO is not modified during
1250 operation is not atomic (making sure REPO is not modified during
1251 the operation is up to you) and you have to make sure your
1251 the operation is up to you) and you have to make sure your
1252 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1252 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1253 so). Also, this is not compatible with certain extensions that
1253 so). Also, this is not compatible with certain extensions that
1254 place their metadata under the .hg directory, such as mq.
1254 place their metadata under the .hg directory, such as mq.
1255
1255
1256 Mercurial will update the working directory to the first applicable
1256 Mercurial will update the working directory to the first applicable
1257 revision from this list:
1257 revision from this list:
1258
1258
1259 a) null if -U or the source repository has no changesets
1259 a) null if -U or the source repository has no changesets
1260 b) if -u . and the source repository is local, the first parent of
1260 b) if -u . and the source repository is local, the first parent of
1261 the source repository's working directory
1261 the source repository's working directory
1262 c) the changeset specified with -u (if a branch name, this means the
1262 c) the changeset specified with -u (if a branch name, this means the
1263 latest head of that branch)
1263 latest head of that branch)
1264 d) the changeset specified with -r
1264 d) the changeset specified with -r
1265 e) the tipmost head specified with -b
1265 e) the tipmost head specified with -b
1266 f) the tipmost head specified with the url#branch source syntax
1266 f) the tipmost head specified with the url#branch source syntax
1267 g) the revision marked with the '@' bookmark, if present
1267 g) the revision marked with the '@' bookmark, if present
1268 h) the tipmost head of the default branch
1268 h) the tipmost head of the default branch
1269 i) tip
1269 i) tip
1270
1270
1271 Examples:
1271 Examples:
1272
1272
1273 - clone a remote repository to a new directory named hg/::
1273 - clone a remote repository to a new directory named hg/::
1274
1274
1275 hg clone http://selenic.com/hg
1275 hg clone http://selenic.com/hg
1276
1276
1277 - create a lightweight local clone::
1277 - create a lightweight local clone::
1278
1278
1279 hg clone project/ project-feature/
1279 hg clone project/ project-feature/
1280
1280
1281 - clone from an absolute path on an ssh server (note double-slash)::
1281 - clone from an absolute path on an ssh server (note double-slash)::
1282
1282
1283 hg clone ssh://user@server//home/projects/alpha/
1283 hg clone ssh://user@server//home/projects/alpha/
1284
1284
1285 - do a high-speed clone over a LAN while checking out a
1285 - do a high-speed clone over a LAN while checking out a
1286 specified version::
1286 specified version::
1287
1287
1288 hg clone --uncompressed http://server/repo -u 1.5
1288 hg clone --uncompressed http://server/repo -u 1.5
1289
1289
1290 - create a repository without changesets after a particular revision::
1290 - create a repository without changesets after a particular revision::
1291
1291
1292 hg clone -r 04e544 experimental/ good/
1292 hg clone -r 04e544 experimental/ good/
1293
1293
1294 - clone (and track) a particular named branch::
1294 - clone (and track) a particular named branch::
1295
1295
1296 hg clone http://selenic.com/hg#stable
1296 hg clone http://selenic.com/hg#stable
1297
1297
1298 See :hg:`help urls` for details on specifying URLs.
1298 See :hg:`help urls` for details on specifying URLs.
1299
1299
1300 Returns 0 on success.
1300 Returns 0 on success.
1301 """
1301 """
1302 if opts.get('noupdate') and opts.get('updaterev'):
1302 if opts.get('noupdate') and opts.get('updaterev'):
1303 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1303 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1304
1304
1305 r = hg.clone(ui, opts, source, dest,
1305 r = hg.clone(ui, opts, source, dest,
1306 pull=opts.get('pull'),
1306 pull=opts.get('pull'),
1307 stream=opts.get('uncompressed'),
1307 stream=opts.get('uncompressed'),
1308 rev=opts.get('rev'),
1308 rev=opts.get('rev'),
1309 update=opts.get('updaterev') or not opts.get('noupdate'),
1309 update=opts.get('updaterev') or not opts.get('noupdate'),
1310 branch=opts.get('branch'))
1310 branch=opts.get('branch'))
1311
1311
1312 return r is None
1312 return r is None
1313
1313
1314 @command('^commit|ci',
1314 @command('^commit|ci',
1315 [('A', 'addremove', None,
1315 [('A', 'addremove', None,
1316 _('mark new/missing files as added/removed before committing')),
1316 _('mark new/missing files as added/removed before committing')),
1317 ('', 'close-branch', None,
1317 ('', 'close-branch', None,
1318 _('mark a branch as closed, hiding it from the branch list')),
1318 _('mark a branch as closed, hiding it from the branch list')),
1319 ('', 'amend', None, _('amend the parent of the working dir')),
1319 ('', 'amend', None, _('amend the parent of the working dir')),
1320 ('s', 'secret', None, _('use the secret phase for committing')),
1320 ('s', 'secret', None, _('use the secret phase for committing')),
1321 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1321 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1322 _('[OPTION]... [FILE]...'))
1322 _('[OPTION]... [FILE]...'))
1323 def commit(ui, repo, *pats, **opts):
1323 def commit(ui, repo, *pats, **opts):
1324 """commit the specified files or all outstanding changes
1324 """commit the specified files or all outstanding changes
1325
1325
1326 Commit changes to the given files into the repository. Unlike a
1326 Commit changes to the given files into the repository. Unlike a
1327 centralized SCM, this operation is a local operation. See
1327 centralized SCM, this operation is a local operation. See
1328 :hg:`push` for a way to actively distribute your changes.
1328 :hg:`push` for a way to actively distribute your changes.
1329
1329
1330 If a list of files is omitted, all changes reported by :hg:`status`
1330 If a list of files is omitted, all changes reported by :hg:`status`
1331 will be committed.
1331 will be committed.
1332
1332
1333 If you are committing the result of a merge, do not provide any
1333 If you are committing the result of a merge, do not provide any
1334 filenames or -I/-X filters.
1334 filenames or -I/-X filters.
1335
1335
1336 If no commit message is specified, Mercurial starts your
1336 If no commit message is specified, Mercurial starts your
1337 configured editor where you can enter a message. In case your
1337 configured editor where you can enter a message. In case your
1338 commit fails, you will find a backup of your message in
1338 commit fails, you will find a backup of your message in
1339 ``.hg/last-message.txt``.
1339 ``.hg/last-message.txt``.
1340
1340
1341 The --amend flag can be used to amend the parent of the
1341 The --amend flag can be used to amend the parent of the
1342 working directory with a new commit that contains the changes
1342 working directory with a new commit that contains the changes
1343 in the parent in addition to those currently reported by :hg:`status`,
1343 in the parent in addition to those currently reported by :hg:`status`,
1344 if there are any. The old commit is stored in a backup bundle in
1344 if there are any. The old commit is stored in a backup bundle in
1345 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1345 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1346 on how to restore it).
1346 on how to restore it).
1347
1347
1348 Message, user and date are taken from the amended commit unless
1348 Message, user and date are taken from the amended commit unless
1349 specified. When a message isn't specified on the command line,
1349 specified. When a message isn't specified on the command line,
1350 the editor will open with the message of the amended commit.
1350 the editor will open with the message of the amended commit.
1351
1351
1352 It is not possible to amend public changesets (see :hg:`help phases`)
1352 It is not possible to amend public changesets (see :hg:`help phases`)
1353 or changesets that have children.
1353 or changesets that have children.
1354
1354
1355 See :hg:`help dates` for a list of formats valid for -d/--date.
1355 See :hg:`help dates` for a list of formats valid for -d/--date.
1356
1356
1357 Returns 0 on success, 1 if nothing changed.
1357 Returns 0 on success, 1 if nothing changed.
1358 """
1358 """
1359 if opts.get('subrepos'):
1359 if opts.get('subrepos'):
1360 if opts.get('amend'):
1360 if opts.get('amend'):
1361 raise util.Abort(_('cannot amend with --subrepos'))
1361 raise util.Abort(_('cannot amend with --subrepos'))
1362 # Let --subrepos on the command line override config setting.
1362 # Let --subrepos on the command line override config setting.
1363 ui.setconfig('ui', 'commitsubrepos', True)
1363 ui.setconfig('ui', 'commitsubrepos', True)
1364
1364
1365 # Save this for restoring it later
1365 # Save this for restoring it later
1366 oldcommitphase = ui.config('phases', 'new-commit')
1366 oldcommitphase = ui.config('phases', 'new-commit')
1367
1367
1368 cmdutil.checkunfinished(repo, commit=True)
1368 cmdutil.checkunfinished(repo, commit=True)
1369
1369
1370 branch = repo[None].branch()
1370 branch = repo[None].branch()
1371 bheads = repo.branchheads(branch)
1371 bheads = repo.branchheads(branch)
1372
1372
1373 extra = {}
1373 extra = {}
1374 if opts.get('close_branch'):
1374 if opts.get('close_branch'):
1375 extra['close'] = 1
1375 extra['close'] = 1
1376
1376
1377 if not bheads:
1377 if not bheads:
1378 raise util.Abort(_('can only close branch heads'))
1378 raise util.Abort(_('can only close branch heads'))
1379 elif opts.get('amend'):
1379 elif opts.get('amend'):
1380 if repo.parents()[0].p1().branch() != branch and \
1380 if repo.parents()[0].p1().branch() != branch and \
1381 repo.parents()[0].p2().branch() != branch:
1381 repo.parents()[0].p2().branch() != branch:
1382 raise util.Abort(_('can only close branch heads'))
1382 raise util.Abort(_('can only close branch heads'))
1383
1383
1384 if opts.get('amend'):
1384 if opts.get('amend'):
1385 if ui.configbool('ui', 'commitsubrepos'):
1385 if ui.configbool('ui', 'commitsubrepos'):
1386 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1386 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1387
1387
1388 old = repo['.']
1388 old = repo['.']
1389 if old.phase() == phases.public:
1389 if old.phase() == phases.public:
1390 raise util.Abort(_('cannot amend public changesets'))
1390 raise util.Abort(_('cannot amend public changesets'))
1391 if len(repo[None].parents()) > 1:
1391 if len(repo[None].parents()) > 1:
1392 raise util.Abort(_('cannot amend while merging'))
1392 raise util.Abort(_('cannot amend while merging'))
1393 if (not obsolete._enabled) and old.children():
1393 if (not obsolete._enabled) and old.children():
1394 raise util.Abort(_('cannot amend changeset with children'))
1394 raise util.Abort(_('cannot amend changeset with children'))
1395
1395
1396 e = cmdutil.commiteditor
1396 e = cmdutil.commiteditor
1397 if opts.get('force_editor'):
1397 if opts.get('force_editor'):
1398 e = cmdutil.commitforceeditor
1398 e = cmdutil.commitforceeditor
1399
1399
1400 def commitfunc(ui, repo, message, match, opts):
1400 def commitfunc(ui, repo, message, match, opts):
1401 editor = e
1401 editor = e
1402 # message contains text from -m or -l, if it's empty,
1402 # message contains text from -m or -l, if it's empty,
1403 # open the editor with the old message
1403 # open the editor with the old message
1404 if not message:
1404 if not message:
1405 message = old.description()
1405 message = old.description()
1406 editor = cmdutil.commitforceeditor
1406 editor = cmdutil.commitforceeditor
1407 try:
1407 try:
1408 if opts.get('secret'):
1408 if opts.get('secret'):
1409 ui.setconfig('phases', 'new-commit', 'secret')
1409 ui.setconfig('phases', 'new-commit', 'secret')
1410
1410
1411 return repo.commit(message,
1411 return repo.commit(message,
1412 opts.get('user') or old.user(),
1412 opts.get('user') or old.user(),
1413 opts.get('date') or old.date(),
1413 opts.get('date') or old.date(),
1414 match,
1414 match,
1415 editor=editor,
1415 editor=editor,
1416 extra=extra)
1416 extra=extra)
1417 finally:
1417 finally:
1418 ui.setconfig('phases', 'new-commit', oldcommitphase)
1418 ui.setconfig('phases', 'new-commit', oldcommitphase)
1419
1419
1420 current = repo._bookmarkcurrent
1420 current = repo._bookmarkcurrent
1421 marks = old.bookmarks()
1421 marks = old.bookmarks()
1422 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1422 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1423 if node == old.node():
1423 if node == old.node():
1424 ui.status(_("nothing changed\n"))
1424 ui.status(_("nothing changed\n"))
1425 return 1
1425 return 1
1426 elif marks:
1426 elif marks:
1427 ui.debug('moving bookmarks %r from %s to %s\n' %
1427 ui.debug('moving bookmarks %r from %s to %s\n' %
1428 (marks, old.hex(), hex(node)))
1428 (marks, old.hex(), hex(node)))
1429 newmarks = repo._bookmarks
1429 newmarks = repo._bookmarks
1430 for bm in marks:
1430 for bm in marks:
1431 newmarks[bm] = node
1431 newmarks[bm] = node
1432 if bm == current:
1432 if bm == current:
1433 bookmarks.setcurrent(repo, bm)
1433 bookmarks.setcurrent(repo, bm)
1434 newmarks.write()
1434 newmarks.write()
1435 else:
1435 else:
1436 e = cmdutil.commiteditor
1436 e = cmdutil.commiteditor
1437 if opts.get('force_editor'):
1437 if opts.get('force_editor'):
1438 e = cmdutil.commitforceeditor
1438 e = cmdutil.commitforceeditor
1439
1439
1440 def commitfunc(ui, repo, message, match, opts):
1440 def commitfunc(ui, repo, message, match, opts):
1441 try:
1441 try:
1442 if opts.get('secret'):
1442 if opts.get('secret'):
1443 ui.setconfig('phases', 'new-commit', 'secret')
1443 ui.setconfig('phases', 'new-commit', 'secret')
1444
1444
1445 return repo.commit(message, opts.get('user'), opts.get('date'),
1445 return repo.commit(message, opts.get('user'), opts.get('date'),
1446 match, editor=e, extra=extra)
1446 match, editor=e, extra=extra)
1447 finally:
1447 finally:
1448 ui.setconfig('phases', 'new-commit', oldcommitphase)
1448 ui.setconfig('phases', 'new-commit', oldcommitphase)
1449
1449
1450
1450
1451 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1451 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1452
1452
1453 if not node:
1453 if not node:
1454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1455 if stat[3]:
1455 if stat[3]:
1456 ui.status(_("nothing changed (%d missing files, see "
1456 ui.status(_("nothing changed (%d missing files, see "
1457 "'hg status')\n") % len(stat[3]))
1457 "'hg status')\n") % len(stat[3]))
1458 else:
1458 else:
1459 ui.status(_("nothing changed\n"))
1459 ui.status(_("nothing changed\n"))
1460 return 1
1460 return 1
1461
1461
1462 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1462 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1463
1463
1464 @command('config|showconfig|debugconfig',
1464 @command('config|showconfig|debugconfig',
1465 [('u', 'untrusted', None, _('show untrusted configuration options')),
1465 [('u', 'untrusted', None, _('show untrusted configuration options')),
1466 ('e', 'edit', None, _('start editor'))],
1466 ('e', 'edit', None, _('start editor'))],
1467 _('[-u] [NAME]...'))
1467 _('[-u] [NAME]...'))
1468 def config(ui, repo, *values, **opts):
1468 def config(ui, repo, *values, **opts):
1469 """show combined config settings from all hgrc files
1469 """show combined config settings from all hgrc files
1470
1470
1471 With no arguments, print names and values of all config items.
1471 With no arguments, print names and values of all config items.
1472
1472
1473 With one argument of the form section.name, print just the value
1473 With one argument of the form section.name, print just the value
1474 of that config item.
1474 of that config item.
1475
1475
1476 With multiple arguments, print names and values of all config
1476 With multiple arguments, print names and values of all config
1477 items with matching section names.
1477 items with matching section names.
1478
1478
1479 With --debug, the source (filename and line number) is printed
1479 With --debug, the source (filename and line number) is printed
1480 for each config item.
1480 for each config item.
1481
1481
1482 Returns 0 on success.
1482 Returns 0 on success.
1483 """
1483 """
1484
1484
1485 if opts.get('edit'):
1485 if opts.get('edit'):
1486 paths = scmutil.userrcpath()
1486 paths = scmutil.userrcpath()
1487 for f in paths:
1487 for f in paths:
1488 if os.path.exists(f):
1488 if os.path.exists(f):
1489 break
1489 break
1490 else:
1490 else:
1491 f = paths[0]
1491 f = paths[0]
1492 fp = open(f, "w")
1492 fp = open(f, "w")
1493 fp.write(
1493 fp.write(
1494 '# example config (see "hg help config" for more info)\n'
1494 '# example config (see "hg help config" for more info)\n'
1495 '\n'
1495 '\n'
1496 '[ui]\n'
1496 '[ui]\n'
1497 '# name and email, e.g.\n'
1497 '# name and email, e.g.\n'
1498 '# username = Jane Doe <jdoe@example.com>\n'
1498 '# username = Jane Doe <jdoe@example.com>\n'
1499 'username =\n'
1499 'username =\n'
1500 '\n'
1500 '\n'
1501 '[extensions]\n'
1501 '[extensions]\n'
1502 '# uncomment these lines to enable some popular extensions\n'
1502 '# uncomment these lines to enable some popular extensions\n'
1503 '# (see "hg help extensions" for more info)\n'
1503 '# (see "hg help extensions" for more info)\n'
1504 '# pager =\n'
1504 '# pager =\n'
1505 '# progress =\n'
1505 '# progress =\n'
1506 '# color =\n')
1506 '# color =\n')
1507 fp.close()
1507 fp.close()
1508
1508
1509 editor = ui.geteditor()
1509 editor = ui.geteditor()
1510 util.system("%s \"%s\"" % (editor, f),
1510 util.system("%s \"%s\"" % (editor, f),
1511 onerr=util.Abort, errprefix=_("edit failed"),
1511 onerr=util.Abort, errprefix=_("edit failed"),
1512 out=ui.fout)
1512 out=ui.fout)
1513 return
1513 return
1514
1514
1515 for f in scmutil.rcpath():
1515 for f in scmutil.rcpath():
1516 ui.debug('read config from: %s\n' % f)
1516 ui.debug('read config from: %s\n' % f)
1517 untrusted = bool(opts.get('untrusted'))
1517 untrusted = bool(opts.get('untrusted'))
1518 if values:
1518 if values:
1519 sections = [v for v in values if '.' not in v]
1519 sections = [v for v in values if '.' not in v]
1520 items = [v for v in values if '.' in v]
1520 items = [v for v in values if '.' in v]
1521 if len(items) > 1 or items and sections:
1521 if len(items) > 1 or items and sections:
1522 raise util.Abort(_('only one config item permitted'))
1522 raise util.Abort(_('only one config item permitted'))
1523 for section, name, value in ui.walkconfig(untrusted=untrusted):
1523 for section, name, value in ui.walkconfig(untrusted=untrusted):
1524 value = str(value).replace('\n', '\\n')
1524 value = str(value).replace('\n', '\\n')
1525 sectname = section + '.' + name
1525 sectname = section + '.' + name
1526 if values:
1526 if values:
1527 for v in values:
1527 for v in values:
1528 if v == section:
1528 if v == section:
1529 ui.debug('%s: ' %
1529 ui.debug('%s: ' %
1530 ui.configsource(section, name, untrusted))
1530 ui.configsource(section, name, untrusted))
1531 ui.write('%s=%s\n' % (sectname, value))
1531 ui.write('%s=%s\n' % (sectname, value))
1532 elif v == sectname:
1532 elif v == sectname:
1533 ui.debug('%s: ' %
1533 ui.debug('%s: ' %
1534 ui.configsource(section, name, untrusted))
1534 ui.configsource(section, name, untrusted))
1535 ui.write(value, '\n')
1535 ui.write(value, '\n')
1536 else:
1536 else:
1537 ui.debug('%s: ' %
1537 ui.debug('%s: ' %
1538 ui.configsource(section, name, untrusted))
1538 ui.configsource(section, name, untrusted))
1539 ui.write('%s=%s\n' % (sectname, value))
1539 ui.write('%s=%s\n' % (sectname, value))
1540
1540
1541 @command('copy|cp',
1541 @command('copy|cp',
1542 [('A', 'after', None, _('record a copy that has already occurred')),
1542 [('A', 'after', None, _('record a copy that has already occurred')),
1543 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1543 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1544 ] + walkopts + dryrunopts,
1544 ] + walkopts + dryrunopts,
1545 _('[OPTION]... [SOURCE]... DEST'))
1545 _('[OPTION]... [SOURCE]... DEST'))
1546 def copy(ui, repo, *pats, **opts):
1546 def copy(ui, repo, *pats, **opts):
1547 """mark files as copied for the next commit
1547 """mark files as copied for the next commit
1548
1548
1549 Mark dest as having copies of source files. If dest is a
1549 Mark dest as having copies of source files. If dest is a
1550 directory, copies are put in that directory. If dest is a file,
1550 directory, copies are put in that directory. If dest is a file,
1551 the source must be a single file.
1551 the source must be a single file.
1552
1552
1553 By default, this command copies the contents of files as they
1553 By default, this command copies the contents of files as they
1554 exist in the working directory. If invoked with -A/--after, the
1554 exist in the working directory. If invoked with -A/--after, the
1555 operation is recorded, but no copying is performed.
1555 operation is recorded, but no copying is performed.
1556
1556
1557 This command takes effect with the next commit. To undo a copy
1557 This command takes effect with the next commit. To undo a copy
1558 before that, see :hg:`revert`.
1558 before that, see :hg:`revert`.
1559
1559
1560 Returns 0 on success, 1 if errors are encountered.
1560 Returns 0 on success, 1 if errors are encountered.
1561 """
1561 """
1562 wlock = repo.wlock(False)
1562 wlock = repo.wlock(False)
1563 try:
1563 try:
1564 return cmdutil.copy(ui, repo, pats, opts)
1564 return cmdutil.copy(ui, repo, pats, opts)
1565 finally:
1565 finally:
1566 wlock.release()
1566 wlock.release()
1567
1567
1568 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1568 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1569 def debugancestor(ui, repo, *args):
1569 def debugancestor(ui, repo, *args):
1570 """find the ancestor revision of two revisions in a given index"""
1570 """find the ancestor revision of two revisions in a given index"""
1571 if len(args) == 3:
1571 if len(args) == 3:
1572 index, rev1, rev2 = args
1572 index, rev1, rev2 = args
1573 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1573 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1574 lookup = r.lookup
1574 lookup = r.lookup
1575 elif len(args) == 2:
1575 elif len(args) == 2:
1576 if not repo:
1576 if not repo:
1577 raise util.Abort(_("there is no Mercurial repository here "
1577 raise util.Abort(_("there is no Mercurial repository here "
1578 "(.hg not found)"))
1578 "(.hg not found)"))
1579 rev1, rev2 = args
1579 rev1, rev2 = args
1580 r = repo.changelog
1580 r = repo.changelog
1581 lookup = repo.lookup
1581 lookup = repo.lookup
1582 else:
1582 else:
1583 raise util.Abort(_('either two or three arguments required'))
1583 raise util.Abort(_('either two or three arguments required'))
1584 a = r.ancestor(lookup(rev1), lookup(rev2))
1584 a = r.ancestor(lookup(rev1), lookup(rev2))
1585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1586
1586
1587 @command('debugbuilddag',
1587 @command('debugbuilddag',
1588 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1588 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1589 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1589 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1590 ('n', 'new-file', None, _('add new file at each rev'))],
1590 ('n', 'new-file', None, _('add new file at each rev'))],
1591 _('[OPTION]... [TEXT]'))
1591 _('[OPTION]... [TEXT]'))
1592 def debugbuilddag(ui, repo, text=None,
1592 def debugbuilddag(ui, repo, text=None,
1593 mergeable_file=False,
1593 mergeable_file=False,
1594 overwritten_file=False,
1594 overwritten_file=False,
1595 new_file=False):
1595 new_file=False):
1596 """builds a repo with a given DAG from scratch in the current empty repo
1596 """builds a repo with a given DAG from scratch in the current empty repo
1597
1597
1598 The description of the DAG is read from stdin if not given on the
1598 The description of the DAG is read from stdin if not given on the
1599 command line.
1599 command line.
1600
1600
1601 Elements:
1601 Elements:
1602
1602
1603 - "+n" is a linear run of n nodes based on the current default parent
1603 - "+n" is a linear run of n nodes based on the current default parent
1604 - "." is a single node based on the current default parent
1604 - "." is a single node based on the current default parent
1605 - "$" resets the default parent to null (implied at the start);
1605 - "$" resets the default parent to null (implied at the start);
1606 otherwise the default parent is always the last node created
1606 otherwise the default parent is always the last node created
1607 - "<p" sets the default parent to the backref p
1607 - "<p" sets the default parent to the backref p
1608 - "*p" is a fork at parent p, which is a backref
1608 - "*p" is a fork at parent p, which is a backref
1609 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1609 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1610 - "/p2" is a merge of the preceding node and p2
1610 - "/p2" is a merge of the preceding node and p2
1611 - ":tag" defines a local tag for the preceding node
1611 - ":tag" defines a local tag for the preceding node
1612 - "@branch" sets the named branch for subsequent nodes
1612 - "@branch" sets the named branch for subsequent nodes
1613 - "#...\\n" is a comment up to the end of the line
1613 - "#...\\n" is a comment up to the end of the line
1614
1614
1615 Whitespace between the above elements is ignored.
1615 Whitespace between the above elements is ignored.
1616
1616
1617 A backref is either
1617 A backref is either
1618
1618
1619 - a number n, which references the node curr-n, where curr is the current
1619 - a number n, which references the node curr-n, where curr is the current
1620 node, or
1620 node, or
1621 - the name of a local tag you placed earlier using ":tag", or
1621 - the name of a local tag you placed earlier using ":tag", or
1622 - empty to denote the default parent.
1622 - empty to denote the default parent.
1623
1623
1624 All string valued-elements are either strictly alphanumeric, or must
1624 All string valued-elements are either strictly alphanumeric, or must
1625 be enclosed in double quotes ("..."), with "\\" as escape character.
1625 be enclosed in double quotes ("..."), with "\\" as escape character.
1626 """
1626 """
1627
1627
1628 if text is None:
1628 if text is None:
1629 ui.status(_("reading DAG from stdin\n"))
1629 ui.status(_("reading DAG from stdin\n"))
1630 text = ui.fin.read()
1630 text = ui.fin.read()
1631
1631
1632 cl = repo.changelog
1632 cl = repo.changelog
1633 if len(cl) > 0:
1633 if len(cl) > 0:
1634 raise util.Abort(_('repository is not empty'))
1634 raise util.Abort(_('repository is not empty'))
1635
1635
1636 # determine number of revs in DAG
1636 # determine number of revs in DAG
1637 total = 0
1637 total = 0
1638 for type, data in dagparser.parsedag(text):
1638 for type, data in dagparser.parsedag(text):
1639 if type == 'n':
1639 if type == 'n':
1640 total += 1
1640 total += 1
1641
1641
1642 if mergeable_file:
1642 if mergeable_file:
1643 linesperrev = 2
1643 linesperrev = 2
1644 # make a file with k lines per rev
1644 # make a file with k lines per rev
1645 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1645 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1646 initialmergedlines.append("")
1646 initialmergedlines.append("")
1647
1647
1648 tags = []
1648 tags = []
1649
1649
1650 lock = tr = None
1650 lock = tr = None
1651 try:
1651 try:
1652 lock = repo.lock()
1652 lock = repo.lock()
1653 tr = repo.transaction("builddag")
1653 tr = repo.transaction("builddag")
1654
1654
1655 at = -1
1655 at = -1
1656 atbranch = 'default'
1656 atbranch = 'default'
1657 nodeids = []
1657 nodeids = []
1658 id = 0
1658 id = 0
1659 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1659 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1660 for type, data in dagparser.parsedag(text):
1660 for type, data in dagparser.parsedag(text):
1661 if type == 'n':
1661 if type == 'n':
1662 ui.note(('node %s\n' % str(data)))
1662 ui.note(('node %s\n' % str(data)))
1663 id, ps = data
1663 id, ps = data
1664
1664
1665 files = []
1665 files = []
1666 fctxs = {}
1666 fctxs = {}
1667
1667
1668 p2 = None
1668 p2 = None
1669 if mergeable_file:
1669 if mergeable_file:
1670 fn = "mf"
1670 fn = "mf"
1671 p1 = repo[ps[0]]
1671 p1 = repo[ps[0]]
1672 if len(ps) > 1:
1672 if len(ps) > 1:
1673 p2 = repo[ps[1]]
1673 p2 = repo[ps[1]]
1674 pa = p1.ancestor(p2)
1674 pa = p1.ancestor(p2)
1675 base, local, other = [x[fn].data() for x in (pa, p1,
1675 base, local, other = [x[fn].data() for x in (pa, p1,
1676 p2)]
1676 p2)]
1677 m3 = simplemerge.Merge3Text(base, local, other)
1677 m3 = simplemerge.Merge3Text(base, local, other)
1678 ml = [l.strip() for l in m3.merge_lines()]
1678 ml = [l.strip() for l in m3.merge_lines()]
1679 ml.append("")
1679 ml.append("")
1680 elif at > 0:
1680 elif at > 0:
1681 ml = p1[fn].data().split("\n")
1681 ml = p1[fn].data().split("\n")
1682 else:
1682 else:
1683 ml = initialmergedlines
1683 ml = initialmergedlines
1684 ml[id * linesperrev] += " r%i" % id
1684 ml[id * linesperrev] += " r%i" % id
1685 mergedtext = "\n".join(ml)
1685 mergedtext = "\n".join(ml)
1686 files.append(fn)
1686 files.append(fn)
1687 fctxs[fn] = context.memfilectx(fn, mergedtext)
1687 fctxs[fn] = context.memfilectx(fn, mergedtext)
1688
1688
1689 if overwritten_file:
1689 if overwritten_file:
1690 fn = "of"
1690 fn = "of"
1691 files.append(fn)
1691 files.append(fn)
1692 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1692 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1693
1693
1694 if new_file:
1694 if new_file:
1695 fn = "nf%i" % id
1695 fn = "nf%i" % id
1696 files.append(fn)
1696 files.append(fn)
1697 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1697 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1698 if len(ps) > 1:
1698 if len(ps) > 1:
1699 if not p2:
1699 if not p2:
1700 p2 = repo[ps[1]]
1700 p2 = repo[ps[1]]
1701 for fn in p2:
1701 for fn in p2:
1702 if fn.startswith("nf"):
1702 if fn.startswith("nf"):
1703 files.append(fn)
1703 files.append(fn)
1704 fctxs[fn] = p2[fn]
1704 fctxs[fn] = p2[fn]
1705
1705
1706 def fctxfn(repo, cx, path):
1706 def fctxfn(repo, cx, path):
1707 return fctxs.get(path)
1707 return fctxs.get(path)
1708
1708
1709 if len(ps) == 0 or ps[0] < 0:
1709 if len(ps) == 0 or ps[0] < 0:
1710 pars = [None, None]
1710 pars = [None, None]
1711 elif len(ps) == 1:
1711 elif len(ps) == 1:
1712 pars = [nodeids[ps[0]], None]
1712 pars = [nodeids[ps[0]], None]
1713 else:
1713 else:
1714 pars = [nodeids[p] for p in ps]
1714 pars = [nodeids[p] for p in ps]
1715 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1715 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1716 date=(id, 0),
1716 date=(id, 0),
1717 user="debugbuilddag",
1717 user="debugbuilddag",
1718 extra={'branch': atbranch})
1718 extra={'branch': atbranch})
1719 nodeid = repo.commitctx(cx)
1719 nodeid = repo.commitctx(cx)
1720 nodeids.append(nodeid)
1720 nodeids.append(nodeid)
1721 at = id
1721 at = id
1722 elif type == 'l':
1722 elif type == 'l':
1723 id, name = data
1723 id, name = data
1724 ui.note(('tag %s\n' % name))
1724 ui.note(('tag %s\n' % name))
1725 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1725 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1726 elif type == 'a':
1726 elif type == 'a':
1727 ui.note(('branch %s\n' % data))
1727 ui.note(('branch %s\n' % data))
1728 atbranch = data
1728 atbranch = data
1729 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1729 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1730 tr.close()
1730 tr.close()
1731
1731
1732 if tags:
1732 if tags:
1733 repo.opener.write("localtags", "".join(tags))
1733 repo.opener.write("localtags", "".join(tags))
1734 finally:
1734 finally:
1735 ui.progress(_('building'), None)
1735 ui.progress(_('building'), None)
1736 release(tr, lock)
1736 release(tr, lock)
1737
1737
1738 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1738 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1739 def debugbundle(ui, bundlepath, all=None, **opts):
1739 def debugbundle(ui, bundlepath, all=None, **opts):
1740 """lists the contents of a bundle"""
1740 """lists the contents of a bundle"""
1741 f = hg.openpath(ui, bundlepath)
1741 f = hg.openpath(ui, bundlepath)
1742 try:
1742 try:
1743 gen = changegroup.readbundle(f, bundlepath)
1743 gen = changegroup.readbundle(f, bundlepath)
1744 if all:
1744 if all:
1745 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1745 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1746
1746
1747 def showchunks(named):
1747 def showchunks(named):
1748 ui.write("\n%s\n" % named)
1748 ui.write("\n%s\n" % named)
1749 chain = None
1749 chain = None
1750 while True:
1750 while True:
1751 chunkdata = gen.deltachunk(chain)
1751 chunkdata = gen.deltachunk(chain)
1752 if not chunkdata:
1752 if not chunkdata:
1753 break
1753 break
1754 node = chunkdata['node']
1754 node = chunkdata['node']
1755 p1 = chunkdata['p1']
1755 p1 = chunkdata['p1']
1756 p2 = chunkdata['p2']
1756 p2 = chunkdata['p2']
1757 cs = chunkdata['cs']
1757 cs = chunkdata['cs']
1758 deltabase = chunkdata['deltabase']
1758 deltabase = chunkdata['deltabase']
1759 delta = chunkdata['delta']
1759 delta = chunkdata['delta']
1760 ui.write("%s %s %s %s %s %s\n" %
1760 ui.write("%s %s %s %s %s %s\n" %
1761 (hex(node), hex(p1), hex(p2),
1761 (hex(node), hex(p1), hex(p2),
1762 hex(cs), hex(deltabase), len(delta)))
1762 hex(cs), hex(deltabase), len(delta)))
1763 chain = node
1763 chain = node
1764
1764
1765 chunkdata = gen.changelogheader()
1765 chunkdata = gen.changelogheader()
1766 showchunks("changelog")
1766 showchunks("changelog")
1767 chunkdata = gen.manifestheader()
1767 chunkdata = gen.manifestheader()
1768 showchunks("manifest")
1768 showchunks("manifest")
1769 while True:
1769 while True:
1770 chunkdata = gen.filelogheader()
1770 chunkdata = gen.filelogheader()
1771 if not chunkdata:
1771 if not chunkdata:
1772 break
1772 break
1773 fname = chunkdata['filename']
1773 fname = chunkdata['filename']
1774 showchunks(fname)
1774 showchunks(fname)
1775 else:
1775 else:
1776 chunkdata = gen.changelogheader()
1776 chunkdata = gen.changelogheader()
1777 chain = None
1777 chain = None
1778 while True:
1778 while True:
1779 chunkdata = gen.deltachunk(chain)
1779 chunkdata = gen.deltachunk(chain)
1780 if not chunkdata:
1780 if not chunkdata:
1781 break
1781 break
1782 node = chunkdata['node']
1782 node = chunkdata['node']
1783 ui.write("%s\n" % hex(node))
1783 ui.write("%s\n" % hex(node))
1784 chain = node
1784 chain = node
1785 finally:
1785 finally:
1786 f.close()
1786 f.close()
1787
1787
1788 @command('debugcheckstate', [], '')
1788 @command('debugcheckstate', [], '')
1789 def debugcheckstate(ui, repo):
1789 def debugcheckstate(ui, repo):
1790 """validate the correctness of the current dirstate"""
1790 """validate the correctness of the current dirstate"""
1791 parent1, parent2 = repo.dirstate.parents()
1791 parent1, parent2 = repo.dirstate.parents()
1792 m1 = repo[parent1].manifest()
1792 m1 = repo[parent1].manifest()
1793 m2 = repo[parent2].manifest()
1793 m2 = repo[parent2].manifest()
1794 errors = 0
1794 errors = 0
1795 for f in repo.dirstate:
1795 for f in repo.dirstate:
1796 state = repo.dirstate[f]
1796 state = repo.dirstate[f]
1797 if state in "nr" and f not in m1:
1797 if state in "nr" and f not in m1:
1798 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1798 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1799 errors += 1
1799 errors += 1
1800 if state in "a" and f in m1:
1800 if state in "a" and f in m1:
1801 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1801 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1802 errors += 1
1802 errors += 1
1803 if state in "m" and f not in m1 and f not in m2:
1803 if state in "m" and f not in m1 and f not in m2:
1804 ui.warn(_("%s in state %s, but not in either manifest\n") %
1804 ui.warn(_("%s in state %s, but not in either manifest\n") %
1805 (f, state))
1805 (f, state))
1806 errors += 1
1806 errors += 1
1807 for f in m1:
1807 for f in m1:
1808 state = repo.dirstate[f]
1808 state = repo.dirstate[f]
1809 if state not in "nrm":
1809 if state not in "nrm":
1810 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1810 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1811 errors += 1
1811 errors += 1
1812 if errors:
1812 if errors:
1813 error = _(".hg/dirstate inconsistent with current parent's manifest")
1813 error = _(".hg/dirstate inconsistent with current parent's manifest")
1814 raise util.Abort(error)
1814 raise util.Abort(error)
1815
1815
1816 @command('debugcommands', [], _('[COMMAND]'))
1816 @command('debugcommands', [], _('[COMMAND]'))
1817 def debugcommands(ui, cmd='', *args):
1817 def debugcommands(ui, cmd='', *args):
1818 """list all available commands and options"""
1818 """list all available commands and options"""
1819 for cmd, vals in sorted(table.iteritems()):
1819 for cmd, vals in sorted(table.iteritems()):
1820 cmd = cmd.split('|')[0].strip('^')
1820 cmd = cmd.split('|')[0].strip('^')
1821 opts = ', '.join([i[1] for i in vals[1]])
1821 opts = ', '.join([i[1] for i in vals[1]])
1822 ui.write('%s: %s\n' % (cmd, opts))
1822 ui.write('%s: %s\n' % (cmd, opts))
1823
1823
1824 @command('debugcomplete',
1824 @command('debugcomplete',
1825 [('o', 'options', None, _('show the command options'))],
1825 [('o', 'options', None, _('show the command options'))],
1826 _('[-o] CMD'))
1826 _('[-o] CMD'))
1827 def debugcomplete(ui, cmd='', **opts):
1827 def debugcomplete(ui, cmd='', **opts):
1828 """returns the completion list associated with the given command"""
1828 """returns the completion list associated with the given command"""
1829
1829
1830 if opts.get('options'):
1830 if opts.get('options'):
1831 options = []
1831 options = []
1832 otables = [globalopts]
1832 otables = [globalopts]
1833 if cmd:
1833 if cmd:
1834 aliases, entry = cmdutil.findcmd(cmd, table, False)
1834 aliases, entry = cmdutil.findcmd(cmd, table, False)
1835 otables.append(entry[1])
1835 otables.append(entry[1])
1836 for t in otables:
1836 for t in otables:
1837 for o in t:
1837 for o in t:
1838 if "(DEPRECATED)" in o[3]:
1838 if "(DEPRECATED)" in o[3]:
1839 continue
1839 continue
1840 if o[0]:
1840 if o[0]:
1841 options.append('-%s' % o[0])
1841 options.append('-%s' % o[0])
1842 options.append('--%s' % o[1])
1842 options.append('--%s' % o[1])
1843 ui.write("%s\n" % "\n".join(options))
1843 ui.write("%s\n" % "\n".join(options))
1844 return
1844 return
1845
1845
1846 cmdlist = cmdutil.findpossible(cmd, table)
1846 cmdlist = cmdutil.findpossible(cmd, table)
1847 if ui.verbose:
1847 if ui.verbose:
1848 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1848 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1849 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1849 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1850
1850
1851 @command('debugdag',
1851 @command('debugdag',
1852 [('t', 'tags', None, _('use tags as labels')),
1852 [('t', 'tags', None, _('use tags as labels')),
1853 ('b', 'branches', None, _('annotate with branch names')),
1853 ('b', 'branches', None, _('annotate with branch names')),
1854 ('', 'dots', None, _('use dots for runs')),
1854 ('', 'dots', None, _('use dots for runs')),
1855 ('s', 'spaces', None, _('separate elements by spaces'))],
1855 ('s', 'spaces', None, _('separate elements by spaces'))],
1856 _('[OPTION]... [FILE [REV]...]'))
1856 _('[OPTION]... [FILE [REV]...]'))
1857 def debugdag(ui, repo, file_=None, *revs, **opts):
1857 def debugdag(ui, repo, file_=None, *revs, **opts):
1858 """format the changelog or an index DAG as a concise textual description
1858 """format the changelog or an index DAG as a concise textual description
1859
1859
1860 If you pass a revlog index, the revlog's DAG is emitted. If you list
1860 If you pass a revlog index, the revlog's DAG is emitted. If you list
1861 revision numbers, they get labeled in the output as rN.
1861 revision numbers, they get labeled in the output as rN.
1862
1862
1863 Otherwise, the changelog DAG of the current repo is emitted.
1863 Otherwise, the changelog DAG of the current repo is emitted.
1864 """
1864 """
1865 spaces = opts.get('spaces')
1865 spaces = opts.get('spaces')
1866 dots = opts.get('dots')
1866 dots = opts.get('dots')
1867 if file_:
1867 if file_:
1868 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1868 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1869 revs = set((int(r) for r in revs))
1869 revs = set((int(r) for r in revs))
1870 def events():
1870 def events():
1871 for r in rlog:
1871 for r in rlog:
1872 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1872 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1873 if p != -1)))
1873 if p != -1)))
1874 if r in revs:
1874 if r in revs:
1875 yield 'l', (r, "r%i" % r)
1875 yield 'l', (r, "r%i" % r)
1876 elif repo:
1876 elif repo:
1877 cl = repo.changelog
1877 cl = repo.changelog
1878 tags = opts.get('tags')
1878 tags = opts.get('tags')
1879 branches = opts.get('branches')
1879 branches = opts.get('branches')
1880 if tags:
1880 if tags:
1881 labels = {}
1881 labels = {}
1882 for l, n in repo.tags().items():
1882 for l, n in repo.tags().items():
1883 labels.setdefault(cl.rev(n), []).append(l)
1883 labels.setdefault(cl.rev(n), []).append(l)
1884 def events():
1884 def events():
1885 b = "default"
1885 b = "default"
1886 for r in cl:
1886 for r in cl:
1887 if branches:
1887 if branches:
1888 newb = cl.read(cl.node(r))[5]['branch']
1888 newb = cl.read(cl.node(r))[5]['branch']
1889 if newb != b:
1889 if newb != b:
1890 yield 'a', newb
1890 yield 'a', newb
1891 b = newb
1891 b = newb
1892 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1892 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1893 if p != -1)))
1893 if p != -1)))
1894 if tags:
1894 if tags:
1895 ls = labels.get(r)
1895 ls = labels.get(r)
1896 if ls:
1896 if ls:
1897 for l in ls:
1897 for l in ls:
1898 yield 'l', (r, l)
1898 yield 'l', (r, l)
1899 else:
1899 else:
1900 raise util.Abort(_('need repo for changelog dag'))
1900 raise util.Abort(_('need repo for changelog dag'))
1901
1901
1902 for line in dagparser.dagtextlines(events(),
1902 for line in dagparser.dagtextlines(events(),
1903 addspaces=spaces,
1903 addspaces=spaces,
1904 wraplabels=True,
1904 wraplabels=True,
1905 wrapannotations=True,
1905 wrapannotations=True,
1906 wrapnonlinear=dots,
1906 wrapnonlinear=dots,
1907 usedots=dots,
1907 usedots=dots,
1908 maxlinewidth=70):
1908 maxlinewidth=70):
1909 ui.write(line)
1909 ui.write(line)
1910 ui.write("\n")
1910 ui.write("\n")
1911
1911
1912 @command('debugdata',
1912 @command('debugdata',
1913 [('c', 'changelog', False, _('open changelog')),
1913 [('c', 'changelog', False, _('open changelog')),
1914 ('m', 'manifest', False, _('open manifest'))],
1914 ('m', 'manifest', False, _('open manifest'))],
1915 _('-c|-m|FILE REV'))
1915 _('-c|-m|FILE REV'))
1916 def debugdata(ui, repo, file_, rev=None, **opts):
1916 def debugdata(ui, repo, file_, rev=None, **opts):
1917 """dump the contents of a data file revision"""
1917 """dump the contents of a data file revision"""
1918 if opts.get('changelog') or opts.get('manifest'):
1918 if opts.get('changelog') or opts.get('manifest'):
1919 file_, rev = None, file_
1919 file_, rev = None, file_
1920 elif rev is None:
1920 elif rev is None:
1921 raise error.CommandError('debugdata', _('invalid arguments'))
1921 raise error.CommandError('debugdata', _('invalid arguments'))
1922 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1922 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1923 try:
1923 try:
1924 ui.write(r.revision(r.lookup(rev)))
1924 ui.write(r.revision(r.lookup(rev)))
1925 except KeyError:
1925 except KeyError:
1926 raise util.Abort(_('invalid revision identifier %s') % rev)
1926 raise util.Abort(_('invalid revision identifier %s') % rev)
1927
1927
1928 @command('debugdate',
1928 @command('debugdate',
1929 [('e', 'extended', None, _('try extended date formats'))],
1929 [('e', 'extended', None, _('try extended date formats'))],
1930 _('[-e] DATE [RANGE]'))
1930 _('[-e] DATE [RANGE]'))
1931 def debugdate(ui, date, range=None, **opts):
1931 def debugdate(ui, date, range=None, **opts):
1932 """parse and display a date"""
1932 """parse and display a date"""
1933 if opts["extended"]:
1933 if opts["extended"]:
1934 d = util.parsedate(date, util.extendeddateformats)
1934 d = util.parsedate(date, util.extendeddateformats)
1935 else:
1935 else:
1936 d = util.parsedate(date)
1936 d = util.parsedate(date)
1937 ui.write(("internal: %s %s\n") % d)
1937 ui.write(("internal: %s %s\n") % d)
1938 ui.write(("standard: %s\n") % util.datestr(d))
1938 ui.write(("standard: %s\n") % util.datestr(d))
1939 if range:
1939 if range:
1940 m = util.matchdate(range)
1940 m = util.matchdate(range)
1941 ui.write(("match: %s\n") % m(d[0]))
1941 ui.write(("match: %s\n") % m(d[0]))
1942
1942
1943 @command('debugdiscovery',
1943 @command('debugdiscovery',
1944 [('', 'old', None, _('use old-style discovery')),
1944 [('', 'old', None, _('use old-style discovery')),
1945 ('', 'nonheads', None,
1945 ('', 'nonheads', None,
1946 _('use old-style discovery with non-heads included')),
1946 _('use old-style discovery with non-heads included')),
1947 ] + remoteopts,
1947 ] + remoteopts,
1948 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1948 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1949 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1949 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1950 """runs the changeset discovery protocol in isolation"""
1950 """runs the changeset discovery protocol in isolation"""
1951 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1951 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1952 opts.get('branch'))
1952 opts.get('branch'))
1953 remote = hg.peer(repo, opts, remoteurl)
1953 remote = hg.peer(repo, opts, remoteurl)
1954 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1954 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1955
1955
1956 # make sure tests are repeatable
1956 # make sure tests are repeatable
1957 random.seed(12323)
1957 random.seed(12323)
1958
1958
1959 def doit(localheads, remoteheads, remote=remote):
1959 def doit(localheads, remoteheads, remote=remote):
1960 if opts.get('old'):
1960 if opts.get('old'):
1961 if localheads:
1961 if localheads:
1962 raise util.Abort('cannot use localheads with old style '
1962 raise util.Abort('cannot use localheads with old style '
1963 'discovery')
1963 'discovery')
1964 if not util.safehasattr(remote, 'branches'):
1964 if not util.safehasattr(remote, 'branches'):
1965 # enable in-client legacy support
1965 # enable in-client legacy support
1966 remote = localrepo.locallegacypeer(remote.local())
1966 remote = localrepo.locallegacypeer(remote.local())
1967 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1967 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1968 force=True)
1968 force=True)
1969 common = set(common)
1969 common = set(common)
1970 if not opts.get('nonheads'):
1970 if not opts.get('nonheads'):
1971 ui.write(("unpruned common: %s\n") %
1971 ui.write(("unpruned common: %s\n") %
1972 " ".join(sorted(short(n) for n in common)))
1972 " ".join(sorted(short(n) for n in common)))
1973 dag = dagutil.revlogdag(repo.changelog)
1973 dag = dagutil.revlogdag(repo.changelog)
1974 all = dag.ancestorset(dag.internalizeall(common))
1974 all = dag.ancestorset(dag.internalizeall(common))
1975 common = dag.externalizeall(dag.headsetofconnecteds(all))
1975 common = dag.externalizeall(dag.headsetofconnecteds(all))
1976 else:
1976 else:
1977 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1977 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1978 common = set(common)
1978 common = set(common)
1979 rheads = set(hds)
1979 rheads = set(hds)
1980 lheads = set(repo.heads())
1980 lheads = set(repo.heads())
1981 ui.write(("common heads: %s\n") %
1981 ui.write(("common heads: %s\n") %
1982 " ".join(sorted(short(n) for n in common)))
1982 " ".join(sorted(short(n) for n in common)))
1983 if lheads <= common:
1983 if lheads <= common:
1984 ui.write(("local is subset\n"))
1984 ui.write(("local is subset\n"))
1985 elif rheads <= common:
1985 elif rheads <= common:
1986 ui.write(("remote is subset\n"))
1986 ui.write(("remote is subset\n"))
1987
1987
1988 serverlogs = opts.get('serverlog')
1988 serverlogs = opts.get('serverlog')
1989 if serverlogs:
1989 if serverlogs:
1990 for filename in serverlogs:
1990 for filename in serverlogs:
1991 logfile = open(filename, 'r')
1991 logfile = open(filename, 'r')
1992 try:
1992 try:
1993 line = logfile.readline()
1993 line = logfile.readline()
1994 while line:
1994 while line:
1995 parts = line.strip().split(';')
1995 parts = line.strip().split(';')
1996 op = parts[1]
1996 op = parts[1]
1997 if op == 'cg':
1997 if op == 'cg':
1998 pass
1998 pass
1999 elif op == 'cgss':
1999 elif op == 'cgss':
2000 doit(parts[2].split(' '), parts[3].split(' '))
2000 doit(parts[2].split(' '), parts[3].split(' '))
2001 elif op == 'unb':
2001 elif op == 'unb':
2002 doit(parts[3].split(' '), parts[2].split(' '))
2002 doit(parts[3].split(' '), parts[2].split(' '))
2003 line = logfile.readline()
2003 line = logfile.readline()
2004 finally:
2004 finally:
2005 logfile.close()
2005 logfile.close()
2006
2006
2007 else:
2007 else:
2008 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2008 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2009 opts.get('remote_head'))
2009 opts.get('remote_head'))
2010 localrevs = opts.get('local_head')
2010 localrevs = opts.get('local_head')
2011 doit(localrevs, remoterevs)
2011 doit(localrevs, remoterevs)
2012
2012
2013 @command('debugfileset',
2013 @command('debugfileset',
2014 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2014 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2015 _('[-r REV] FILESPEC'))
2015 _('[-r REV] FILESPEC'))
2016 def debugfileset(ui, repo, expr, **opts):
2016 def debugfileset(ui, repo, expr, **opts):
2017 '''parse and apply a fileset specification'''
2017 '''parse and apply a fileset specification'''
2018 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2018 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2019 if ui.verbose:
2019 if ui.verbose:
2020 tree = fileset.parse(expr)[0]
2020 tree = fileset.parse(expr)[0]
2021 ui.note(tree, "\n")
2021 ui.note(tree, "\n")
2022
2022
2023 for f in ctx.getfileset(expr):
2023 for f in ctx.getfileset(expr):
2024 ui.write("%s\n" % f)
2024 ui.write("%s\n" % f)
2025
2025
2026 @command('debugfsinfo', [], _('[PATH]'))
2026 @command('debugfsinfo', [], _('[PATH]'))
2027 def debugfsinfo(ui, path="."):
2027 def debugfsinfo(ui, path="."):
2028 """show information detected about current filesystem"""
2028 """show information detected about current filesystem"""
2029 util.writefile('.debugfsinfo', '')
2029 util.writefile('.debugfsinfo', '')
2030 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2030 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2031 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2031 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2032 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2032 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2033 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2033 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2034 and 'yes' or 'no'))
2034 and 'yes' or 'no'))
2035 os.unlink('.debugfsinfo')
2035 os.unlink('.debugfsinfo')
2036
2036
2037 @command('debuggetbundle',
2037 @command('debuggetbundle',
2038 [('H', 'head', [], _('id of head node'), _('ID')),
2038 [('H', 'head', [], _('id of head node'), _('ID')),
2039 ('C', 'common', [], _('id of common node'), _('ID')),
2039 ('C', 'common', [], _('id of common node'), _('ID')),
2040 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2040 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2041 _('REPO FILE [-H|-C ID]...'))
2041 _('REPO FILE [-H|-C ID]...'))
2042 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2042 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2043 """retrieves a bundle from a repo
2043 """retrieves a bundle from a repo
2044
2044
2045 Every ID must be a full-length hex node id string. Saves the bundle to the
2045 Every ID must be a full-length hex node id string. Saves the bundle to the
2046 given file.
2046 given file.
2047 """
2047 """
2048 repo = hg.peer(ui, opts, repopath)
2048 repo = hg.peer(ui, opts, repopath)
2049 if not repo.capable('getbundle'):
2049 if not repo.capable('getbundle'):
2050 raise util.Abort("getbundle() not supported by target repository")
2050 raise util.Abort("getbundle() not supported by target repository")
2051 args = {}
2051 args = {}
2052 if common:
2052 if common:
2053 args['common'] = [bin(s) for s in common]
2053 args['common'] = [bin(s) for s in common]
2054 if head:
2054 if head:
2055 args['heads'] = [bin(s) for s in head]
2055 args['heads'] = [bin(s) for s in head]
2056 # TODO: get desired bundlecaps from command line.
2056 # TODO: get desired bundlecaps from command line.
2057 args['bundlecaps'] = None
2057 args['bundlecaps'] = None
2058 bundle = repo.getbundle('debug', **args)
2058 bundle = repo.getbundle('debug', **args)
2059
2059
2060 bundletype = opts.get('type', 'bzip2').lower()
2060 bundletype = opts.get('type', 'bzip2').lower()
2061 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2061 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2062 bundletype = btypes.get(bundletype)
2062 bundletype = btypes.get(bundletype)
2063 if bundletype not in changegroup.bundletypes:
2063 if bundletype not in changegroup.bundletypes:
2064 raise util.Abort(_('unknown bundle type specified with --type'))
2064 raise util.Abort(_('unknown bundle type specified with --type'))
2065 changegroup.writebundle(bundle, bundlepath, bundletype)
2065 changegroup.writebundle(bundle, bundlepath, bundletype)
2066
2066
2067 @command('debugignore', [], '')
2067 @command('debugignore', [], '')
2068 def debugignore(ui, repo, *values, **opts):
2068 def debugignore(ui, repo, *values, **opts):
2069 """display the combined ignore pattern"""
2069 """display the combined ignore pattern"""
2070 ignore = repo.dirstate._ignore
2070 ignore = repo.dirstate._ignore
2071 includepat = getattr(ignore, 'includepat', None)
2071 includepat = getattr(ignore, 'includepat', None)
2072 if includepat is not None:
2072 if includepat is not None:
2073 ui.write("%s\n" % includepat)
2073 ui.write("%s\n" % includepat)
2074 else:
2074 else:
2075 raise util.Abort(_("no ignore patterns found"))
2075 raise util.Abort(_("no ignore patterns found"))
2076
2076
2077 @command('debugindex',
2077 @command('debugindex',
2078 [('c', 'changelog', False, _('open changelog')),
2078 [('c', 'changelog', False, _('open changelog')),
2079 ('m', 'manifest', False, _('open manifest')),
2079 ('m', 'manifest', False, _('open manifest')),
2080 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2080 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2081 _('[-f FORMAT] -c|-m|FILE'))
2081 _('[-f FORMAT] -c|-m|FILE'))
2082 def debugindex(ui, repo, file_=None, **opts):
2082 def debugindex(ui, repo, file_=None, **opts):
2083 """dump the contents of an index file"""
2083 """dump the contents of an index file"""
2084 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2084 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2085 format = opts.get('format', 0)
2085 format = opts.get('format', 0)
2086 if format not in (0, 1):
2086 if format not in (0, 1):
2087 raise util.Abort(_("unknown format %d") % format)
2087 raise util.Abort(_("unknown format %d") % format)
2088
2088
2089 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2089 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2090 if generaldelta:
2090 if generaldelta:
2091 basehdr = ' delta'
2091 basehdr = ' delta'
2092 else:
2092 else:
2093 basehdr = ' base'
2093 basehdr = ' base'
2094
2094
2095 if format == 0:
2095 if format == 0:
2096 ui.write(" rev offset length " + basehdr + " linkrev"
2096 ui.write(" rev offset length " + basehdr + " linkrev"
2097 " nodeid p1 p2\n")
2097 " nodeid p1 p2\n")
2098 elif format == 1:
2098 elif format == 1:
2099 ui.write(" rev flag offset length"
2099 ui.write(" rev flag offset length"
2100 " size " + basehdr + " link p1 p2"
2100 " size " + basehdr + " link p1 p2"
2101 " nodeid\n")
2101 " nodeid\n")
2102
2102
2103 for i in r:
2103 for i in r:
2104 node = r.node(i)
2104 node = r.node(i)
2105 if generaldelta:
2105 if generaldelta:
2106 base = r.deltaparent(i)
2106 base = r.deltaparent(i)
2107 else:
2107 else:
2108 base = r.chainbase(i)
2108 base = r.chainbase(i)
2109 if format == 0:
2109 if format == 0:
2110 try:
2110 try:
2111 pp = r.parents(node)
2111 pp = r.parents(node)
2112 except Exception:
2112 except Exception:
2113 pp = [nullid, nullid]
2113 pp = [nullid, nullid]
2114 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2114 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2115 i, r.start(i), r.length(i), base, r.linkrev(i),
2115 i, r.start(i), r.length(i), base, r.linkrev(i),
2116 short(node), short(pp[0]), short(pp[1])))
2116 short(node), short(pp[0]), short(pp[1])))
2117 elif format == 1:
2117 elif format == 1:
2118 pr = r.parentrevs(i)
2118 pr = r.parentrevs(i)
2119 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2119 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2120 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2120 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2121 base, r.linkrev(i), pr[0], pr[1], short(node)))
2121 base, r.linkrev(i), pr[0], pr[1], short(node)))
2122
2122
2123 @command('debugindexdot', [], _('FILE'))
2123 @command('debugindexdot', [], _('FILE'))
2124 def debugindexdot(ui, repo, file_):
2124 def debugindexdot(ui, repo, file_):
2125 """dump an index DAG as a graphviz dot file"""
2125 """dump an index DAG as a graphviz dot file"""
2126 r = None
2126 r = None
2127 if repo:
2127 if repo:
2128 filelog = repo.file(file_)
2128 filelog = repo.file(file_)
2129 if len(filelog):
2129 if len(filelog):
2130 r = filelog
2130 r = filelog
2131 if not r:
2131 if not r:
2132 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2132 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2133 ui.write(("digraph G {\n"))
2133 ui.write(("digraph G {\n"))
2134 for i in r:
2134 for i in r:
2135 node = r.node(i)
2135 node = r.node(i)
2136 pp = r.parents(node)
2136 pp = r.parents(node)
2137 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2137 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2138 if pp[1] != nullid:
2138 if pp[1] != nullid:
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2140 ui.write("}\n")
2140 ui.write("}\n")
2141
2141
2142 @command('debuginstall', [], '')
2142 @command('debuginstall', [], '')
2143 def debuginstall(ui):
2143 def debuginstall(ui):
2144 '''test Mercurial installation
2144 '''test Mercurial installation
2145
2145
2146 Returns 0 on success.
2146 Returns 0 on success.
2147 '''
2147 '''
2148
2148
2149 def writetemp(contents):
2149 def writetemp(contents):
2150 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2150 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2151 f = os.fdopen(fd, "wb")
2151 f = os.fdopen(fd, "wb")
2152 f.write(contents)
2152 f.write(contents)
2153 f.close()
2153 f.close()
2154 return name
2154 return name
2155
2155
2156 problems = 0
2156 problems = 0
2157
2157
2158 # encoding
2158 # encoding
2159 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2159 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2160 try:
2160 try:
2161 encoding.fromlocal("test")
2161 encoding.fromlocal("test")
2162 except util.Abort, inst:
2162 except util.Abort, inst:
2163 ui.write(" %s\n" % inst)
2163 ui.write(" %s\n" % inst)
2164 ui.write(_(" (check that your locale is properly set)\n"))
2164 ui.write(_(" (check that your locale is properly set)\n"))
2165 problems += 1
2165 problems += 1
2166
2166
2167 # Python lib
2167 # Python lib
2168 ui.status(_("checking Python lib (%s)...\n")
2168 ui.status(_("checking Python lib (%s)...\n")
2169 % os.path.dirname(os.__file__))
2169 % os.path.dirname(os.__file__))
2170
2170
2171 # compiled modules
2171 # compiled modules
2172 ui.status(_("checking installed modules (%s)...\n")
2172 ui.status(_("checking installed modules (%s)...\n")
2173 % os.path.dirname(__file__))
2173 % os.path.dirname(__file__))
2174 try:
2174 try:
2175 import bdiff, mpatch, base85, osutil
2175 import bdiff, mpatch, base85, osutil
2176 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2176 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2177 except Exception, inst:
2177 except Exception, inst:
2178 ui.write(" %s\n" % inst)
2178 ui.write(" %s\n" % inst)
2179 ui.write(_(" One or more extensions could not be found"))
2179 ui.write(_(" One or more extensions could not be found"))
2180 ui.write(_(" (check that you compiled the extensions)\n"))
2180 ui.write(_(" (check that you compiled the extensions)\n"))
2181 problems += 1
2181 problems += 1
2182
2182
2183 # templates
2183 # templates
2184 import templater
2184 import templater
2185 p = templater.templatepath()
2185 p = templater.templatepath()
2186 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2186 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2187 if p:
2187 if p:
2188 m = templater.templatepath("map-cmdline.default")
2188 m = templater.templatepath("map-cmdline.default")
2189 if m:
2189 if m:
2190 # template found, check if it is working
2190 # template found, check if it is working
2191 try:
2191 try:
2192 templater.templater(m)
2192 templater.templater(m)
2193 except Exception, inst:
2193 except Exception, inst:
2194 ui.write(" %s\n" % inst)
2194 ui.write(" %s\n" % inst)
2195 p = None
2195 p = None
2196 else:
2196 else:
2197 ui.write(_(" template 'default' not found\n"))
2197 ui.write(_(" template 'default' not found\n"))
2198 p = None
2198 p = None
2199 else:
2199 else:
2200 ui.write(_(" no template directories found\n"))
2200 ui.write(_(" no template directories found\n"))
2201 if not p:
2201 if not p:
2202 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2202 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2203 problems += 1
2203 problems += 1
2204
2204
2205 # editor
2205 # editor
2206 ui.status(_("checking commit editor...\n"))
2206 ui.status(_("checking commit editor...\n"))
2207 editor = ui.geteditor()
2207 editor = ui.geteditor()
2208 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2208 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2209 if not cmdpath:
2209 if not cmdpath:
2210 if editor == 'vi':
2210 if editor == 'vi':
2211 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2211 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2212 ui.write(_(" (specify a commit editor in your configuration"
2212 ui.write(_(" (specify a commit editor in your configuration"
2213 " file)\n"))
2213 " file)\n"))
2214 else:
2214 else:
2215 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2215 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2216 ui.write(_(" (specify a commit editor in your configuration"
2216 ui.write(_(" (specify a commit editor in your configuration"
2217 " file)\n"))
2217 " file)\n"))
2218 problems += 1
2218 problems += 1
2219
2219
2220 # check username
2220 # check username
2221 ui.status(_("checking username...\n"))
2221 ui.status(_("checking username...\n"))
2222 try:
2222 try:
2223 ui.username()
2223 ui.username()
2224 except util.Abort, e:
2224 except util.Abort, e:
2225 ui.write(" %s\n" % e)
2225 ui.write(" %s\n" % e)
2226 ui.write(_(" (specify a username in your configuration file)\n"))
2226 ui.write(_(" (specify a username in your configuration file)\n"))
2227 problems += 1
2227 problems += 1
2228
2228
2229 if not problems:
2229 if not problems:
2230 ui.status(_("no problems detected\n"))
2230 ui.status(_("no problems detected\n"))
2231 else:
2231 else:
2232 ui.write(_("%s problems detected,"
2232 ui.write(_("%s problems detected,"
2233 " please check your install!\n") % problems)
2233 " please check your install!\n") % problems)
2234
2234
2235 return problems
2235 return problems
2236
2236
2237 @command('debugknown', [], _('REPO ID...'))
2237 @command('debugknown', [], _('REPO ID...'))
2238 def debugknown(ui, repopath, *ids, **opts):
2238 def debugknown(ui, repopath, *ids, **opts):
2239 """test whether node ids are known to a repo
2239 """test whether node ids are known to a repo
2240
2240
2241 Every ID must be a full-length hex node id string. Returns a list of 0s
2241 Every ID must be a full-length hex node id string. Returns a list of 0s
2242 and 1s indicating unknown/known.
2242 and 1s indicating unknown/known.
2243 """
2243 """
2244 repo = hg.peer(ui, opts, repopath)
2244 repo = hg.peer(ui, opts, repopath)
2245 if not repo.capable('known'):
2245 if not repo.capable('known'):
2246 raise util.Abort("known() not supported by target repository")
2246 raise util.Abort("known() not supported by target repository")
2247 flags = repo.known([bin(s) for s in ids])
2247 flags = repo.known([bin(s) for s in ids])
2248 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2248 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2249
2249
2250 @command('debuglabelcomplete', [], _('LABEL...'))
2250 @command('debuglabelcomplete', [], _('LABEL...'))
2251 def debuglabelcomplete(ui, repo, *args):
2251 def debuglabelcomplete(ui, repo, *args):
2252 '''complete "labels" - tags, open branch names, bookmark names'''
2252 '''complete "labels" - tags, open branch names, bookmark names'''
2253
2253
2254 labels = set()
2254 labels = set()
2255 labels.update(t[0] for t in repo.tagslist())
2255 labels.update(t[0] for t in repo.tagslist())
2256 labels.update(repo._bookmarks.keys())
2256 labels.update(repo._bookmarks.keys())
2257 labels.update(tag for (tag, heads, tip, closed)
2257 labels.update(tag for (tag, heads, tip, closed)
2258 in repo.branchmap().iterbranches() if not closed)
2258 in repo.branchmap().iterbranches() if not closed)
2259 completions = set()
2259 completions = set()
2260 if not args:
2260 if not args:
2261 args = ['']
2261 args = ['']
2262 for a in args:
2262 for a in args:
2263 completions.update(l for l in labels if l.startswith(a))
2263 completions.update(l for l in labels if l.startswith(a))
2264 ui.write('\n'.join(sorted(completions)))
2264 ui.write('\n'.join(sorted(completions)))
2265 ui.write('\n')
2265 ui.write('\n')
2266
2266
2267 @command('debugobsolete',
2267 @command('debugobsolete',
2268 [('', 'flags', 0, _('markers flag')),
2268 [('', 'flags', 0, _('markers flag')),
2269 ] + commitopts2,
2269 ] + commitopts2,
2270 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2270 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2271 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2271 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2272 """create arbitrary obsolete marker
2272 """create arbitrary obsolete marker
2273
2273
2274 With no arguments, displays the list of obsolescence markers."""
2274 With no arguments, displays the list of obsolescence markers."""
2275 def parsenodeid(s):
2275 def parsenodeid(s):
2276 try:
2276 try:
2277 # We do not use revsingle/revrange functions here to accept
2277 # We do not use revsingle/revrange functions here to accept
2278 # arbitrary node identifiers, possibly not present in the
2278 # arbitrary node identifiers, possibly not present in the
2279 # local repository.
2279 # local repository.
2280 n = bin(s)
2280 n = bin(s)
2281 if len(n) != len(nullid):
2281 if len(n) != len(nullid):
2282 raise TypeError()
2282 raise TypeError()
2283 return n
2283 return n
2284 except TypeError:
2284 except TypeError:
2285 raise util.Abort('changeset references must be full hexadecimal '
2285 raise util.Abort('changeset references must be full hexadecimal '
2286 'node identifiers')
2286 'node identifiers')
2287
2287
2288 if precursor is not None:
2288 if precursor is not None:
2289 metadata = {}
2289 metadata = {}
2290 if 'date' in opts:
2290 if 'date' in opts:
2291 metadata['date'] = opts['date']
2291 metadata['date'] = opts['date']
2292 metadata['user'] = opts['user'] or ui.username()
2292 metadata['user'] = opts['user'] or ui.username()
2293 succs = tuple(parsenodeid(succ) for succ in successors)
2293 succs = tuple(parsenodeid(succ) for succ in successors)
2294 l = repo.lock()
2294 l = repo.lock()
2295 try:
2295 try:
2296 tr = repo.transaction('debugobsolete')
2296 tr = repo.transaction('debugobsolete')
2297 try:
2297 try:
2298 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2298 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2299 opts['flags'], metadata)
2299 opts['flags'], metadata)
2300 tr.close()
2300 tr.close()
2301 finally:
2301 finally:
2302 tr.release()
2302 tr.release()
2303 finally:
2303 finally:
2304 l.release()
2304 l.release()
2305 else:
2305 else:
2306 for m in obsolete.allmarkers(repo):
2306 for m in obsolete.allmarkers(repo):
2307 cmdutil.showmarker(ui, m)
2307 cmdutil.showmarker(ui, m)
2308
2308
2309 @command('debugpathcomplete',
2309 @command('debugpathcomplete',
2310 [('f', 'full', None, _('complete an entire path')),
2310 [('f', 'full', None, _('complete an entire path')),
2311 ('n', 'normal', None, _('show only normal files')),
2311 ('n', 'normal', None, _('show only normal files')),
2312 ('a', 'added', None, _('show only added files')),
2312 ('a', 'added', None, _('show only added files')),
2313 ('r', 'removed', None, _('show only removed files'))],
2313 ('r', 'removed', None, _('show only removed files'))],
2314 _('FILESPEC...'))
2314 _('FILESPEC...'))
2315 def debugpathcomplete(ui, repo, *specs, **opts):
2315 def debugpathcomplete(ui, repo, *specs, **opts):
2316 '''complete part or all of a tracked path
2316 '''complete part or all of a tracked path
2317
2317
2318 This command supports shells that offer path name completion. It
2318 This command supports shells that offer path name completion. It
2319 currently completes only files already known to the dirstate.
2319 currently completes only files already known to the dirstate.
2320
2320
2321 Completion extends only to the next path segment unless
2321 Completion extends only to the next path segment unless
2322 --full is specified, in which case entire paths are used.'''
2322 --full is specified, in which case entire paths are used.'''
2323
2323
2324 def complete(path, acceptable):
2324 def complete(path, acceptable):
2325 dirstate = repo.dirstate
2325 dirstate = repo.dirstate
2326 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2326 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2327 rootdir = repo.root + os.sep
2327 rootdir = repo.root + os.sep
2328 if spec != repo.root and not spec.startswith(rootdir):
2328 if spec != repo.root and not spec.startswith(rootdir):
2329 return [], []
2329 return [], []
2330 if os.path.isdir(spec):
2330 if os.path.isdir(spec):
2331 spec += '/'
2331 spec += '/'
2332 spec = spec[len(rootdir):]
2332 spec = spec[len(rootdir):]
2333 fixpaths = os.sep != '/'
2333 fixpaths = os.sep != '/'
2334 if fixpaths:
2334 if fixpaths:
2335 spec = spec.replace(os.sep, '/')
2335 spec = spec.replace(os.sep, '/')
2336 speclen = len(spec)
2336 speclen = len(spec)
2337 fullpaths = opts['full']
2337 fullpaths = opts['full']
2338 files, dirs = set(), set()
2338 files, dirs = set(), set()
2339 adddir, addfile = dirs.add, files.add
2339 adddir, addfile = dirs.add, files.add
2340 for f, st in dirstate.iteritems():
2340 for f, st in dirstate.iteritems():
2341 if f.startswith(spec) and st[0] in acceptable:
2341 if f.startswith(spec) and st[0] in acceptable:
2342 if fixpaths:
2342 if fixpaths:
2343 f = f.replace('/', os.sep)
2343 f = f.replace('/', os.sep)
2344 if fullpaths:
2344 if fullpaths:
2345 addfile(f)
2345 addfile(f)
2346 continue
2346 continue
2347 s = f.find(os.sep, speclen)
2347 s = f.find(os.sep, speclen)
2348 if s >= 0:
2348 if s >= 0:
2349 adddir(f[:s])
2349 adddir(f[:s])
2350 else:
2350 else:
2351 addfile(f)
2351 addfile(f)
2352 return files, dirs
2352 return files, dirs
2353
2353
2354 acceptable = ''
2354 acceptable = ''
2355 if opts['normal']:
2355 if opts['normal']:
2356 acceptable += 'nm'
2356 acceptable += 'nm'
2357 if opts['added']:
2357 if opts['added']:
2358 acceptable += 'a'
2358 acceptable += 'a'
2359 if opts['removed']:
2359 if opts['removed']:
2360 acceptable += 'r'
2360 acceptable += 'r'
2361 cwd = repo.getcwd()
2361 cwd = repo.getcwd()
2362 if not specs:
2362 if not specs:
2363 specs = ['.']
2363 specs = ['.']
2364
2364
2365 files, dirs = set(), set()
2365 files, dirs = set(), set()
2366 for spec in specs:
2366 for spec in specs:
2367 f, d = complete(spec, acceptable or 'nmar')
2367 f, d = complete(spec, acceptable or 'nmar')
2368 files.update(f)
2368 files.update(f)
2369 dirs.update(d)
2369 dirs.update(d)
2370 files.update(dirs)
2370 files.update(dirs)
2371 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2371 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2372 ui.write('\n')
2372 ui.write('\n')
2373
2373
2374 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2374 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2375 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2375 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2376 '''access the pushkey key/value protocol
2376 '''access the pushkey key/value protocol
2377
2377
2378 With two args, list the keys in the given namespace.
2378 With two args, list the keys in the given namespace.
2379
2379
2380 With five args, set a key to new if it currently is set to old.
2380 With five args, set a key to new if it currently is set to old.
2381 Reports success or failure.
2381 Reports success or failure.
2382 '''
2382 '''
2383
2383
2384 target = hg.peer(ui, {}, repopath)
2384 target = hg.peer(ui, {}, repopath)
2385 if keyinfo:
2385 if keyinfo:
2386 key, old, new = keyinfo
2386 key, old, new = keyinfo
2387 r = target.pushkey(namespace, key, old, new)
2387 r = target.pushkey(namespace, key, old, new)
2388 ui.status(str(r) + '\n')
2388 ui.status(str(r) + '\n')
2389 return not r
2389 return not r
2390 else:
2390 else:
2391 for k, v in sorted(target.listkeys(namespace).iteritems()):
2391 for k, v in sorted(target.listkeys(namespace).iteritems()):
2392 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2392 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2393 v.encode('string-escape')))
2393 v.encode('string-escape')))
2394
2394
2395 @command('debugpvec', [], _('A B'))
2395 @command('debugpvec', [], _('A B'))
2396 def debugpvec(ui, repo, a, b=None):
2396 def debugpvec(ui, repo, a, b=None):
2397 ca = scmutil.revsingle(repo, a)
2397 ca = scmutil.revsingle(repo, a)
2398 cb = scmutil.revsingle(repo, b)
2398 cb = scmutil.revsingle(repo, b)
2399 pa = pvec.ctxpvec(ca)
2399 pa = pvec.ctxpvec(ca)
2400 pb = pvec.ctxpvec(cb)
2400 pb = pvec.ctxpvec(cb)
2401 if pa == pb:
2401 if pa == pb:
2402 rel = "="
2402 rel = "="
2403 elif pa > pb:
2403 elif pa > pb:
2404 rel = ">"
2404 rel = ">"
2405 elif pa < pb:
2405 elif pa < pb:
2406 rel = "<"
2406 rel = "<"
2407 elif pa | pb:
2407 elif pa | pb:
2408 rel = "|"
2408 rel = "|"
2409 ui.write(_("a: %s\n") % pa)
2409 ui.write(_("a: %s\n") % pa)
2410 ui.write(_("b: %s\n") % pb)
2410 ui.write(_("b: %s\n") % pb)
2411 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2411 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2412 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2412 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2413 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2413 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2414 pa.distance(pb), rel))
2414 pa.distance(pb), rel))
2415
2415
2416 @command('debugrebuilddirstate|debugrebuildstate',
2416 @command('debugrebuilddirstate|debugrebuildstate',
2417 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2417 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2418 _('[-r REV]'))
2418 _('[-r REV]'))
2419 def debugrebuilddirstate(ui, repo, rev):
2419 def debugrebuilddirstate(ui, repo, rev):
2420 """rebuild the dirstate as it would look like for the given revision
2420 """rebuild the dirstate as it would look like for the given revision
2421
2421
2422 If no revision is specified the first current parent will be used.
2422 If no revision is specified the first current parent will be used.
2423
2423
2424 The dirstate will be set to the files of the given revision.
2424 The dirstate will be set to the files of the given revision.
2425 The actual working directory content or existing dirstate
2425 The actual working directory content or existing dirstate
2426 information such as adds or removes is not considered.
2426 information such as adds or removes is not considered.
2427
2427
2428 One use of this command is to make the next :hg:`status` invocation
2428 One use of this command is to make the next :hg:`status` invocation
2429 check the actual file content.
2429 check the actual file content.
2430 """
2430 """
2431 ctx = scmutil.revsingle(repo, rev)
2431 ctx = scmutil.revsingle(repo, rev)
2432 wlock = repo.wlock()
2432 wlock = repo.wlock()
2433 try:
2433 try:
2434 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2434 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2435 finally:
2435 finally:
2436 wlock.release()
2436 wlock.release()
2437
2437
2438 @command('debugrename',
2438 @command('debugrename',
2439 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2439 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2440 _('[-r REV] FILE'))
2440 _('[-r REV] FILE'))
2441 def debugrename(ui, repo, file1, *pats, **opts):
2441 def debugrename(ui, repo, file1, *pats, **opts):
2442 """dump rename information"""
2442 """dump rename information"""
2443
2443
2444 ctx = scmutil.revsingle(repo, opts.get('rev'))
2444 ctx = scmutil.revsingle(repo, opts.get('rev'))
2445 m = scmutil.match(ctx, (file1,) + pats, opts)
2445 m = scmutil.match(ctx, (file1,) + pats, opts)
2446 for abs in ctx.walk(m):
2446 for abs in ctx.walk(m):
2447 fctx = ctx[abs]
2447 fctx = ctx[abs]
2448 o = fctx.filelog().renamed(fctx.filenode())
2448 o = fctx.filelog().renamed(fctx.filenode())
2449 rel = m.rel(abs)
2449 rel = m.rel(abs)
2450 if o:
2450 if o:
2451 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2451 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2452 else:
2452 else:
2453 ui.write(_("%s not renamed\n") % rel)
2453 ui.write(_("%s not renamed\n") % rel)
2454
2454
2455 @command('debugrevlog',
2455 @command('debugrevlog',
2456 [('c', 'changelog', False, _('open changelog')),
2456 [('c', 'changelog', False, _('open changelog')),
2457 ('m', 'manifest', False, _('open manifest')),
2457 ('m', 'manifest', False, _('open manifest')),
2458 ('d', 'dump', False, _('dump index data'))],
2458 ('d', 'dump', False, _('dump index data'))],
2459 _('-c|-m|FILE'))
2459 _('-c|-m|FILE'))
2460 def debugrevlog(ui, repo, file_=None, **opts):
2460 def debugrevlog(ui, repo, file_=None, **opts):
2461 """show data and statistics about a revlog"""
2461 """show data and statistics about a revlog"""
2462 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2462 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2463
2463
2464 if opts.get("dump"):
2464 if opts.get("dump"):
2465 numrevs = len(r)
2465 numrevs = len(r)
2466 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2466 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2467 " rawsize totalsize compression heads\n")
2467 " rawsize totalsize compression heads\n")
2468 ts = 0
2468 ts = 0
2469 heads = set()
2469 heads = set()
2470 for rev in xrange(numrevs):
2470 for rev in xrange(numrevs):
2471 dbase = r.deltaparent(rev)
2471 dbase = r.deltaparent(rev)
2472 if dbase == -1:
2472 if dbase == -1:
2473 dbase = rev
2473 dbase = rev
2474 cbase = r.chainbase(rev)
2474 cbase = r.chainbase(rev)
2475 p1, p2 = r.parentrevs(rev)
2475 p1, p2 = r.parentrevs(rev)
2476 rs = r.rawsize(rev)
2476 rs = r.rawsize(rev)
2477 ts = ts + rs
2477 ts = ts + rs
2478 heads -= set(r.parentrevs(rev))
2478 heads -= set(r.parentrevs(rev))
2479 heads.add(rev)
2479 heads.add(rev)
2480 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2480 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2481 (rev, p1, p2, r.start(rev), r.end(rev),
2481 (rev, p1, p2, r.start(rev), r.end(rev),
2482 r.start(dbase), r.start(cbase),
2482 r.start(dbase), r.start(cbase),
2483 r.start(p1), r.start(p2),
2483 r.start(p1), r.start(p2),
2484 rs, ts, ts / r.end(rev), len(heads)))
2484 rs, ts, ts / r.end(rev), len(heads)))
2485 return 0
2485 return 0
2486
2486
2487 v = r.version
2487 v = r.version
2488 format = v & 0xFFFF
2488 format = v & 0xFFFF
2489 flags = []
2489 flags = []
2490 gdelta = False
2490 gdelta = False
2491 if v & revlog.REVLOGNGINLINEDATA:
2491 if v & revlog.REVLOGNGINLINEDATA:
2492 flags.append('inline')
2492 flags.append('inline')
2493 if v & revlog.REVLOGGENERALDELTA:
2493 if v & revlog.REVLOGGENERALDELTA:
2494 gdelta = True
2494 gdelta = True
2495 flags.append('generaldelta')
2495 flags.append('generaldelta')
2496 if not flags:
2496 if not flags:
2497 flags = ['(none)']
2497 flags = ['(none)']
2498
2498
2499 nummerges = 0
2499 nummerges = 0
2500 numfull = 0
2500 numfull = 0
2501 numprev = 0
2501 numprev = 0
2502 nump1 = 0
2502 nump1 = 0
2503 nump2 = 0
2503 nump2 = 0
2504 numother = 0
2504 numother = 0
2505 nump1prev = 0
2505 nump1prev = 0
2506 nump2prev = 0
2506 nump2prev = 0
2507 chainlengths = []
2507 chainlengths = []
2508
2508
2509 datasize = [None, 0, 0L]
2509 datasize = [None, 0, 0L]
2510 fullsize = [None, 0, 0L]
2510 fullsize = [None, 0, 0L]
2511 deltasize = [None, 0, 0L]
2511 deltasize = [None, 0, 0L]
2512
2512
2513 def addsize(size, l):
2513 def addsize(size, l):
2514 if l[0] is None or size < l[0]:
2514 if l[0] is None or size < l[0]:
2515 l[0] = size
2515 l[0] = size
2516 if size > l[1]:
2516 if size > l[1]:
2517 l[1] = size
2517 l[1] = size
2518 l[2] += size
2518 l[2] += size
2519
2519
2520 numrevs = len(r)
2520 numrevs = len(r)
2521 for rev in xrange(numrevs):
2521 for rev in xrange(numrevs):
2522 p1, p2 = r.parentrevs(rev)
2522 p1, p2 = r.parentrevs(rev)
2523 delta = r.deltaparent(rev)
2523 delta = r.deltaparent(rev)
2524 if format > 0:
2524 if format > 0:
2525 addsize(r.rawsize(rev), datasize)
2525 addsize(r.rawsize(rev), datasize)
2526 if p2 != nullrev:
2526 if p2 != nullrev:
2527 nummerges += 1
2527 nummerges += 1
2528 size = r.length(rev)
2528 size = r.length(rev)
2529 if delta == nullrev:
2529 if delta == nullrev:
2530 chainlengths.append(0)
2530 chainlengths.append(0)
2531 numfull += 1
2531 numfull += 1
2532 addsize(size, fullsize)
2532 addsize(size, fullsize)
2533 else:
2533 else:
2534 chainlengths.append(chainlengths[delta] + 1)
2534 chainlengths.append(chainlengths[delta] + 1)
2535 addsize(size, deltasize)
2535 addsize(size, deltasize)
2536 if delta == rev - 1:
2536 if delta == rev - 1:
2537 numprev += 1
2537 numprev += 1
2538 if delta == p1:
2538 if delta == p1:
2539 nump1prev += 1
2539 nump1prev += 1
2540 elif delta == p2:
2540 elif delta == p2:
2541 nump2prev += 1
2541 nump2prev += 1
2542 elif delta == p1:
2542 elif delta == p1:
2543 nump1 += 1
2543 nump1 += 1
2544 elif delta == p2:
2544 elif delta == p2:
2545 nump2 += 1
2545 nump2 += 1
2546 elif delta != nullrev:
2546 elif delta != nullrev:
2547 numother += 1
2547 numother += 1
2548
2548
2549 # Adjust size min value for empty cases
2549 # Adjust size min value for empty cases
2550 for size in (datasize, fullsize, deltasize):
2550 for size in (datasize, fullsize, deltasize):
2551 if size[0] is None:
2551 if size[0] is None:
2552 size[0] = 0
2552 size[0] = 0
2553
2553
2554 numdeltas = numrevs - numfull
2554 numdeltas = numrevs - numfull
2555 numoprev = numprev - nump1prev - nump2prev
2555 numoprev = numprev - nump1prev - nump2prev
2556 totalrawsize = datasize[2]
2556 totalrawsize = datasize[2]
2557 datasize[2] /= numrevs
2557 datasize[2] /= numrevs
2558 fulltotal = fullsize[2]
2558 fulltotal = fullsize[2]
2559 fullsize[2] /= numfull
2559 fullsize[2] /= numfull
2560 deltatotal = deltasize[2]
2560 deltatotal = deltasize[2]
2561 if numrevs - numfull > 0:
2561 if numrevs - numfull > 0:
2562 deltasize[2] /= numrevs - numfull
2562 deltasize[2] /= numrevs - numfull
2563 totalsize = fulltotal + deltatotal
2563 totalsize = fulltotal + deltatotal
2564 avgchainlen = sum(chainlengths) / numrevs
2564 avgchainlen = sum(chainlengths) / numrevs
2565 compratio = totalrawsize / totalsize
2565 compratio = totalrawsize / totalsize
2566
2566
2567 basedfmtstr = '%%%dd\n'
2567 basedfmtstr = '%%%dd\n'
2568 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2568 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2569
2569
2570 def dfmtstr(max):
2570 def dfmtstr(max):
2571 return basedfmtstr % len(str(max))
2571 return basedfmtstr % len(str(max))
2572 def pcfmtstr(max, padding=0):
2572 def pcfmtstr(max, padding=0):
2573 return basepcfmtstr % (len(str(max)), ' ' * padding)
2573 return basepcfmtstr % (len(str(max)), ' ' * padding)
2574
2574
2575 def pcfmt(value, total):
2575 def pcfmt(value, total):
2576 return (value, 100 * float(value) / total)
2576 return (value, 100 * float(value) / total)
2577
2577
2578 ui.write(('format : %d\n') % format)
2578 ui.write(('format : %d\n') % format)
2579 ui.write(('flags : %s\n') % ', '.join(flags))
2579 ui.write(('flags : %s\n') % ', '.join(flags))
2580
2580
2581 ui.write('\n')
2581 ui.write('\n')
2582 fmt = pcfmtstr(totalsize)
2582 fmt = pcfmtstr(totalsize)
2583 fmt2 = dfmtstr(totalsize)
2583 fmt2 = dfmtstr(totalsize)
2584 ui.write(('revisions : ') + fmt2 % numrevs)
2584 ui.write(('revisions : ') + fmt2 % numrevs)
2585 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2585 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2586 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2586 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2587 ui.write(('revisions : ') + fmt2 % numrevs)
2587 ui.write(('revisions : ') + fmt2 % numrevs)
2588 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2588 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2589 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2589 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2590 ui.write(('revision size : ') + fmt2 % totalsize)
2590 ui.write(('revision size : ') + fmt2 % totalsize)
2591 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2591 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2592 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2592 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2593
2593
2594 ui.write('\n')
2594 ui.write('\n')
2595 fmt = dfmtstr(max(avgchainlen, compratio))
2595 fmt = dfmtstr(max(avgchainlen, compratio))
2596 ui.write(('avg chain length : ') + fmt % avgchainlen)
2596 ui.write(('avg chain length : ') + fmt % avgchainlen)
2597 ui.write(('compression ratio : ') + fmt % compratio)
2597 ui.write(('compression ratio : ') + fmt % compratio)
2598
2598
2599 if format > 0:
2599 if format > 0:
2600 ui.write('\n')
2600 ui.write('\n')
2601 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2601 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2602 % tuple(datasize))
2602 % tuple(datasize))
2603 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2603 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2604 % tuple(fullsize))
2604 % tuple(fullsize))
2605 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2605 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2606 % tuple(deltasize))
2606 % tuple(deltasize))
2607
2607
2608 if numdeltas > 0:
2608 if numdeltas > 0:
2609 ui.write('\n')
2609 ui.write('\n')
2610 fmt = pcfmtstr(numdeltas)
2610 fmt = pcfmtstr(numdeltas)
2611 fmt2 = pcfmtstr(numdeltas, 4)
2611 fmt2 = pcfmtstr(numdeltas, 4)
2612 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2612 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2613 if numprev > 0:
2613 if numprev > 0:
2614 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2614 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2615 numprev))
2615 numprev))
2616 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2616 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2617 numprev))
2617 numprev))
2618 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2618 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2619 numprev))
2619 numprev))
2620 if gdelta:
2620 if gdelta:
2621 ui.write(('deltas against p1 : ')
2621 ui.write(('deltas against p1 : ')
2622 + fmt % pcfmt(nump1, numdeltas))
2622 + fmt % pcfmt(nump1, numdeltas))
2623 ui.write(('deltas against p2 : ')
2623 ui.write(('deltas against p2 : ')
2624 + fmt % pcfmt(nump2, numdeltas))
2624 + fmt % pcfmt(nump2, numdeltas))
2625 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2625 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2626 numdeltas))
2626 numdeltas))
2627
2627
2628 @command('debugrevspec',
2628 @command('debugrevspec',
2629 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2629 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2630 ('REVSPEC'))
2630 ('REVSPEC'))
2631 def debugrevspec(ui, repo, expr, **opts):
2631 def debugrevspec(ui, repo, expr, **opts):
2632 """parse and apply a revision specification
2632 """parse and apply a revision specification
2633
2633
2634 Use --verbose to print the parsed tree before and after aliases
2634 Use --verbose to print the parsed tree before and after aliases
2635 expansion.
2635 expansion.
2636 """
2636 """
2637 if ui.verbose:
2637 if ui.verbose:
2638 tree = revset.parse(expr)[0]
2638 tree = revset.parse(expr)[0]
2639 ui.note(revset.prettyformat(tree), "\n")
2639 ui.note(revset.prettyformat(tree), "\n")
2640 newtree = revset.findaliases(ui, tree)
2640 newtree = revset.findaliases(ui, tree)
2641 if newtree != tree:
2641 if newtree != tree:
2642 ui.note(revset.prettyformat(newtree), "\n")
2642 ui.note(revset.prettyformat(newtree), "\n")
2643 if opts["optimize"]:
2643 if opts["optimize"]:
2644 weight, optimizedtree = revset.optimize(newtree, True)
2644 weight, optimizedtree = revset.optimize(newtree, True)
2645 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2645 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2646 func = revset.match(ui, expr)
2646 func = revset.match(ui, expr)
2647 for c in func(repo, revset.spanset(repo)):
2647 for c in func(repo, revset.spanset(repo)):
2648 ui.write("%s\n" % c)
2648 ui.write("%s\n" % c)
2649
2649
2650 @command('debugsetparents', [], _('REV1 [REV2]'))
2650 @command('debugsetparents', [], _('REV1 [REV2]'))
2651 def debugsetparents(ui, repo, rev1, rev2=None):
2651 def debugsetparents(ui, repo, rev1, rev2=None):
2652 """manually set the parents of the current working directory
2652 """manually set the parents of the current working directory
2653
2653
2654 This is useful for writing repository conversion tools, but should
2654 This is useful for writing repository conversion tools, but should
2655 be used with care.
2655 be used with care.
2656
2656
2657 Returns 0 on success.
2657 Returns 0 on success.
2658 """
2658 """
2659
2659
2660 r1 = scmutil.revsingle(repo, rev1).node()
2660 r1 = scmutil.revsingle(repo, rev1).node()
2661 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2661 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2662
2662
2663 wlock = repo.wlock()
2663 wlock = repo.wlock()
2664 try:
2664 try:
2665 repo.setparents(r1, r2)
2665 repo.setparents(r1, r2)
2666 finally:
2666 finally:
2667 wlock.release()
2667 wlock.release()
2668
2668
2669 @command('debugdirstate|debugstate',
2669 @command('debugdirstate|debugstate',
2670 [('', 'nodates', None, _('do not display the saved mtime')),
2670 [('', 'nodates', None, _('do not display the saved mtime')),
2671 ('', 'datesort', None, _('sort by saved mtime'))],
2671 ('', 'datesort', None, _('sort by saved mtime'))],
2672 _('[OPTION]...'))
2672 _('[OPTION]...'))
2673 def debugstate(ui, repo, nodates=None, datesort=None):
2673 def debugstate(ui, repo, nodates=None, datesort=None):
2674 """show the contents of the current dirstate"""
2674 """show the contents of the current dirstate"""
2675 timestr = ""
2675 timestr = ""
2676 showdate = not nodates
2676 showdate = not nodates
2677 if datesort:
2677 if datesort:
2678 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2678 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2679 else:
2679 else:
2680 keyfunc = None # sort by filename
2680 keyfunc = None # sort by filename
2681 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2681 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2682 if showdate:
2682 if showdate:
2683 if ent[3] == -1:
2683 if ent[3] == -1:
2684 # Pad or slice to locale representation
2684 # Pad or slice to locale representation
2685 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2685 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2686 time.localtime(0)))
2686 time.localtime(0)))
2687 timestr = 'unset'
2687 timestr = 'unset'
2688 timestr = (timestr[:locale_len] +
2688 timestr = (timestr[:locale_len] +
2689 ' ' * (locale_len - len(timestr)))
2689 ' ' * (locale_len - len(timestr)))
2690 else:
2690 else:
2691 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2691 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2692 time.localtime(ent[3]))
2692 time.localtime(ent[3]))
2693 if ent[1] & 020000:
2693 if ent[1] & 020000:
2694 mode = 'lnk'
2694 mode = 'lnk'
2695 else:
2695 else:
2696 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2696 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2697 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2697 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2698 for f in repo.dirstate.copies():
2698 for f in repo.dirstate.copies():
2699 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2699 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2700
2700
2701 @command('debugsub',
2701 @command('debugsub',
2702 [('r', 'rev', '',
2702 [('r', 'rev', '',
2703 _('revision to check'), _('REV'))],
2703 _('revision to check'), _('REV'))],
2704 _('[-r REV] [REV]'))
2704 _('[-r REV] [REV]'))
2705 def debugsub(ui, repo, rev=None):
2705 def debugsub(ui, repo, rev=None):
2706 ctx = scmutil.revsingle(repo, rev, None)
2706 ctx = scmutil.revsingle(repo, rev, None)
2707 for k, v in sorted(ctx.substate.items()):
2707 for k, v in sorted(ctx.substate.items()):
2708 ui.write(('path %s\n') % k)
2708 ui.write(('path %s\n') % k)
2709 ui.write((' source %s\n') % v[0])
2709 ui.write((' source %s\n') % v[0])
2710 ui.write((' revision %s\n') % v[1])
2710 ui.write((' revision %s\n') % v[1])
2711
2711
2712 @command('debugsuccessorssets',
2712 @command('debugsuccessorssets',
2713 [],
2713 [],
2714 _('[REV]'))
2714 _('[REV]'))
2715 def debugsuccessorssets(ui, repo, *revs):
2715 def debugsuccessorssets(ui, repo, *revs):
2716 """show set of successors for revision
2716 """show set of successors for revision
2717
2717
2718 A successors set of changeset A is a consistent group of revisions that
2718 A successors set of changeset A is a consistent group of revisions that
2719 succeed A. It contains non-obsolete changesets only.
2719 succeed A. It contains non-obsolete changesets only.
2720
2720
2721 In most cases a changeset A has a single successors set containing a single
2721 In most cases a changeset A has a single successors set containing a single
2722 successor (changeset A replaced by A').
2722 successor (changeset A replaced by A').
2723
2723
2724 A changeset that is made obsolete with no successors are called "pruned".
2724 A changeset that is made obsolete with no successors are called "pruned".
2725 Such changesets have no successors sets at all.
2725 Such changesets have no successors sets at all.
2726
2726
2727 A changeset that has been "split" will have a successors set containing
2727 A changeset that has been "split" will have a successors set containing
2728 more than one successor.
2728 more than one successor.
2729
2729
2730 A changeset that has been rewritten in multiple different ways is called
2730 A changeset that has been rewritten in multiple different ways is called
2731 "divergent". Such changesets have multiple successor sets (each of which
2731 "divergent". Such changesets have multiple successor sets (each of which
2732 may also be split, i.e. have multiple successors).
2732 may also be split, i.e. have multiple successors).
2733
2733
2734 Results are displayed as follows::
2734 Results are displayed as follows::
2735
2735
2736 <rev1>
2736 <rev1>
2737 <successors-1A>
2737 <successors-1A>
2738 <rev2>
2738 <rev2>
2739 <successors-2A>
2739 <successors-2A>
2740 <successors-2B1> <successors-2B2> <successors-2B3>
2740 <successors-2B1> <successors-2B2> <successors-2B3>
2741
2741
2742 Here rev2 has two possible (i.e. divergent) successors sets. The first
2742 Here rev2 has two possible (i.e. divergent) successors sets. The first
2743 holds one element, whereas the second holds three (i.e. the changeset has
2743 holds one element, whereas the second holds three (i.e. the changeset has
2744 been split).
2744 been split).
2745 """
2745 """
2746 # passed to successorssets caching computation from one call to another
2746 # passed to successorssets caching computation from one call to another
2747 cache = {}
2747 cache = {}
2748 ctx2str = str
2748 ctx2str = str
2749 node2str = short
2749 node2str = short
2750 if ui.debug():
2750 if ui.debug():
2751 def ctx2str(ctx):
2751 def ctx2str(ctx):
2752 return ctx.hex()
2752 return ctx.hex()
2753 node2str = hex
2753 node2str = hex
2754 for rev in scmutil.revrange(repo, revs):
2754 for rev in scmutil.revrange(repo, revs):
2755 ctx = repo[rev]
2755 ctx = repo[rev]
2756 ui.write('%s\n'% ctx2str(ctx))
2756 ui.write('%s\n'% ctx2str(ctx))
2757 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2757 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2758 if succsset:
2758 if succsset:
2759 ui.write(' ')
2759 ui.write(' ')
2760 ui.write(node2str(succsset[0]))
2760 ui.write(node2str(succsset[0]))
2761 for node in succsset[1:]:
2761 for node in succsset[1:]:
2762 ui.write(' ')
2762 ui.write(' ')
2763 ui.write(node2str(node))
2763 ui.write(node2str(node))
2764 ui.write('\n')
2764 ui.write('\n')
2765
2765
2766 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2766 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2767 def debugwalk(ui, repo, *pats, **opts):
2767 def debugwalk(ui, repo, *pats, **opts):
2768 """show how files match on given patterns"""
2768 """show how files match on given patterns"""
2769 m = scmutil.match(repo[None], pats, opts)
2769 m = scmutil.match(repo[None], pats, opts)
2770 items = list(repo.walk(m))
2770 items = list(repo.walk(m))
2771 if not items:
2771 if not items:
2772 return
2772 return
2773 f = lambda fn: fn
2773 f = lambda fn: fn
2774 if ui.configbool('ui', 'slash') and os.sep != '/':
2774 if ui.configbool('ui', 'slash') and os.sep != '/':
2775 f = lambda fn: util.normpath(fn)
2775 f = lambda fn: util.normpath(fn)
2776 fmt = 'f %%-%ds %%-%ds %%s' % (
2776 fmt = 'f %%-%ds %%-%ds %%s' % (
2777 max([len(abs) for abs in items]),
2777 max([len(abs) for abs in items]),
2778 max([len(m.rel(abs)) for abs in items]))
2778 max([len(m.rel(abs)) for abs in items]))
2779 for abs in items:
2779 for abs in items:
2780 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2780 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2781 ui.write("%s\n" % line.rstrip())
2781 ui.write("%s\n" % line.rstrip())
2782
2782
2783 @command('debugwireargs',
2783 @command('debugwireargs',
2784 [('', 'three', '', 'three'),
2784 [('', 'three', '', 'three'),
2785 ('', 'four', '', 'four'),
2785 ('', 'four', '', 'four'),
2786 ('', 'five', '', 'five'),
2786 ('', 'five', '', 'five'),
2787 ] + remoteopts,
2787 ] + remoteopts,
2788 _('REPO [OPTIONS]... [ONE [TWO]]'))
2788 _('REPO [OPTIONS]... [ONE [TWO]]'))
2789 def debugwireargs(ui, repopath, *vals, **opts):
2789 def debugwireargs(ui, repopath, *vals, **opts):
2790 repo = hg.peer(ui, opts, repopath)
2790 repo = hg.peer(ui, opts, repopath)
2791 for opt in remoteopts:
2791 for opt in remoteopts:
2792 del opts[opt[1]]
2792 del opts[opt[1]]
2793 args = {}
2793 args = {}
2794 for k, v in opts.iteritems():
2794 for k, v in opts.iteritems():
2795 if v:
2795 if v:
2796 args[k] = v
2796 args[k] = v
2797 # run twice to check that we don't mess up the stream for the next command
2797 # run twice to check that we don't mess up the stream for the next command
2798 res1 = repo.debugwireargs(*vals, **args)
2798 res1 = repo.debugwireargs(*vals, **args)
2799 res2 = repo.debugwireargs(*vals, **args)
2799 res2 = repo.debugwireargs(*vals, **args)
2800 ui.write("%s\n" % res1)
2800 ui.write("%s\n" % res1)
2801 if res1 != res2:
2801 if res1 != res2:
2802 ui.warn("%s\n" % res2)
2802 ui.warn("%s\n" % res2)
2803
2803
2804 @command('^diff',
2804 @command('^diff',
2805 [('r', 'rev', [], _('revision'), _('REV')),
2805 [('r', 'rev', [], _('revision'), _('REV')),
2806 ('c', 'change', '', _('change made by revision'), _('REV'))
2806 ('c', 'change', '', _('change made by revision'), _('REV'))
2807 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2807 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2808 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2808 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2809 def diff(ui, repo, *pats, **opts):
2809 def diff(ui, repo, *pats, **opts):
2810 """diff repository (or selected files)
2810 """diff repository (or selected files)
2811
2811
2812 Show differences between revisions for the specified files.
2812 Show differences between revisions for the specified files.
2813
2813
2814 Differences between files are shown using the unified diff format.
2814 Differences between files are shown using the unified diff format.
2815
2815
2816 .. note::
2816 .. note::
2817
2817
2818 diff may generate unexpected results for merges, as it will
2818 diff may generate unexpected results for merges, as it will
2819 default to comparing against the working directory's first
2819 default to comparing against the working directory's first
2820 parent changeset if no revisions are specified.
2820 parent changeset if no revisions are specified.
2821
2821
2822 When two revision arguments are given, then changes are shown
2822 When two revision arguments are given, then changes are shown
2823 between those revisions. If only one revision is specified then
2823 between those revisions. If only one revision is specified then
2824 that revision is compared to the working directory, and, when no
2824 that revision is compared to the working directory, and, when no
2825 revisions are specified, the working directory files are compared
2825 revisions are specified, the working directory files are compared
2826 to its parent.
2826 to its parent.
2827
2827
2828 Alternatively you can specify -c/--change with a revision to see
2828 Alternatively you can specify -c/--change with a revision to see
2829 the changes in that changeset relative to its first parent.
2829 the changes in that changeset relative to its first parent.
2830
2830
2831 Without the -a/--text option, diff will avoid generating diffs of
2831 Without the -a/--text option, diff will avoid generating diffs of
2832 files it detects as binary. With -a, diff will generate a diff
2832 files it detects as binary. With -a, diff will generate a diff
2833 anyway, probably with undesirable results.
2833 anyway, probably with undesirable results.
2834
2834
2835 Use the -g/--git option to generate diffs in the git extended diff
2835 Use the -g/--git option to generate diffs in the git extended diff
2836 format. For more information, read :hg:`help diffs`.
2836 format. For more information, read :hg:`help diffs`.
2837
2837
2838 .. container:: verbose
2838 .. container:: verbose
2839
2839
2840 Examples:
2840 Examples:
2841
2841
2842 - compare a file in the current working directory to its parent::
2842 - compare a file in the current working directory to its parent::
2843
2843
2844 hg diff foo.c
2844 hg diff foo.c
2845
2845
2846 - compare two historical versions of a directory, with rename info::
2846 - compare two historical versions of a directory, with rename info::
2847
2847
2848 hg diff --git -r 1.0:1.2 lib/
2848 hg diff --git -r 1.0:1.2 lib/
2849
2849
2850 - get change stats relative to the last change on some date::
2850 - get change stats relative to the last change on some date::
2851
2851
2852 hg diff --stat -r "date('may 2')"
2852 hg diff --stat -r "date('may 2')"
2853
2853
2854 - diff all newly-added files that contain a keyword::
2854 - diff all newly-added files that contain a keyword::
2855
2855
2856 hg diff "set:added() and grep(GNU)"
2856 hg diff "set:added() and grep(GNU)"
2857
2857
2858 - compare a revision and its parents::
2858 - compare a revision and its parents::
2859
2859
2860 hg diff -c 9353 # compare against first parent
2860 hg diff -c 9353 # compare against first parent
2861 hg diff -r 9353^:9353 # same using revset syntax
2861 hg diff -r 9353^:9353 # same using revset syntax
2862 hg diff -r 9353^2:9353 # compare against the second parent
2862 hg diff -r 9353^2:9353 # compare against the second parent
2863
2863
2864 Returns 0 on success.
2864 Returns 0 on success.
2865 """
2865 """
2866
2866
2867 revs = opts.get('rev')
2867 revs = opts.get('rev')
2868 change = opts.get('change')
2868 change = opts.get('change')
2869 stat = opts.get('stat')
2869 stat = opts.get('stat')
2870 reverse = opts.get('reverse')
2870 reverse = opts.get('reverse')
2871
2871
2872 if revs and change:
2872 if revs and change:
2873 msg = _('cannot specify --rev and --change at the same time')
2873 msg = _('cannot specify --rev and --change at the same time')
2874 raise util.Abort(msg)
2874 raise util.Abort(msg)
2875 elif change:
2875 elif change:
2876 node2 = scmutil.revsingle(repo, change, None).node()
2876 node2 = scmutil.revsingle(repo, change, None).node()
2877 node1 = repo[node2].p1().node()
2877 node1 = repo[node2].p1().node()
2878 else:
2878 else:
2879 node1, node2 = scmutil.revpair(repo, revs)
2879 node1, node2 = scmutil.revpair(repo, revs)
2880
2880
2881 if reverse:
2881 if reverse:
2882 node1, node2 = node2, node1
2882 node1, node2 = node2, node1
2883
2883
2884 diffopts = patch.diffopts(ui, opts)
2884 diffopts = patch.diffopts(ui, opts)
2885 m = scmutil.match(repo[node2], pats, opts)
2885 m = scmutil.match(repo[node2], pats, opts)
2886 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2886 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2887 listsubrepos=opts.get('subrepos'))
2887 listsubrepos=opts.get('subrepos'))
2888
2888
2889 @command('^export',
2889 @command('^export',
2890 [('o', 'output', '',
2890 [('o', 'output', '',
2891 _('print output to file with formatted name'), _('FORMAT')),
2891 _('print output to file with formatted name'), _('FORMAT')),
2892 ('', 'switch-parent', None, _('diff against the second parent')),
2892 ('', 'switch-parent', None, _('diff against the second parent')),
2893 ('r', 'rev', [], _('revisions to export'), _('REV')),
2893 ('r', 'rev', [], _('revisions to export'), _('REV')),
2894 ] + diffopts,
2894 ] + diffopts,
2895 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2895 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2896 def export(ui, repo, *changesets, **opts):
2896 def export(ui, repo, *changesets, **opts):
2897 """dump the header and diffs for one or more changesets
2897 """dump the header and diffs for one or more changesets
2898
2898
2899 Print the changeset header and diffs for one or more revisions.
2899 Print the changeset header and diffs for one or more revisions.
2900 If no revision is given, the parent of the working directory is used.
2900 If no revision is given, the parent of the working directory is used.
2901
2901
2902 The information shown in the changeset header is: author, date,
2902 The information shown in the changeset header is: author, date,
2903 branch name (if non-default), changeset hash, parent(s) and commit
2903 branch name (if non-default), changeset hash, parent(s) and commit
2904 comment.
2904 comment.
2905
2905
2906 .. note::
2906 .. note::
2907
2907
2908 export may generate unexpected diff output for merge
2908 export may generate unexpected diff output for merge
2909 changesets, as it will compare the merge changeset against its
2909 changesets, as it will compare the merge changeset against its
2910 first parent only.
2910 first parent only.
2911
2911
2912 Output may be to a file, in which case the name of the file is
2912 Output may be to a file, in which case the name of the file is
2913 given using a format string. The formatting rules are as follows:
2913 given using a format string. The formatting rules are as follows:
2914
2914
2915 :``%%``: literal "%" character
2915 :``%%``: literal "%" character
2916 :``%H``: changeset hash (40 hexadecimal digits)
2916 :``%H``: changeset hash (40 hexadecimal digits)
2917 :``%N``: number of patches being generated
2917 :``%N``: number of patches being generated
2918 :``%R``: changeset revision number
2918 :``%R``: changeset revision number
2919 :``%b``: basename of the exporting repository
2919 :``%b``: basename of the exporting repository
2920 :``%h``: short-form changeset hash (12 hexadecimal digits)
2920 :``%h``: short-form changeset hash (12 hexadecimal digits)
2921 :``%m``: first line of the commit message (only alphanumeric characters)
2921 :``%m``: first line of the commit message (only alphanumeric characters)
2922 :``%n``: zero-padded sequence number, starting at 1
2922 :``%n``: zero-padded sequence number, starting at 1
2923 :``%r``: zero-padded changeset revision number
2923 :``%r``: zero-padded changeset revision number
2924
2924
2925 Without the -a/--text option, export will avoid generating diffs
2925 Without the -a/--text option, export will avoid generating diffs
2926 of files it detects as binary. With -a, export will generate a
2926 of files it detects as binary. With -a, export will generate a
2927 diff anyway, probably with undesirable results.
2927 diff anyway, probably with undesirable results.
2928
2928
2929 Use the -g/--git option to generate diffs in the git extended diff
2929 Use the -g/--git option to generate diffs in the git extended diff
2930 format. See :hg:`help diffs` for more information.
2930 format. See :hg:`help diffs` for more information.
2931
2931
2932 With the --switch-parent option, the diff will be against the
2932 With the --switch-parent option, the diff will be against the
2933 second parent. It can be useful to review a merge.
2933 second parent. It can be useful to review a merge.
2934
2934
2935 .. container:: verbose
2935 .. container:: verbose
2936
2936
2937 Examples:
2937 Examples:
2938
2938
2939 - use export and import to transplant a bugfix to the current
2939 - use export and import to transplant a bugfix to the current
2940 branch::
2940 branch::
2941
2941
2942 hg export -r 9353 | hg import -
2942 hg export -r 9353 | hg import -
2943
2943
2944 - export all the changesets between two revisions to a file with
2944 - export all the changesets between two revisions to a file with
2945 rename information::
2945 rename information::
2946
2946
2947 hg export --git -r 123:150 > changes.txt
2947 hg export --git -r 123:150 > changes.txt
2948
2948
2949 - split outgoing changes into a series of patches with
2949 - split outgoing changes into a series of patches with
2950 descriptive names::
2950 descriptive names::
2951
2951
2952 hg export -r "outgoing()" -o "%n-%m.patch"
2952 hg export -r "outgoing()" -o "%n-%m.patch"
2953
2953
2954 Returns 0 on success.
2954 Returns 0 on success.
2955 """
2955 """
2956 changesets += tuple(opts.get('rev', []))
2956 changesets += tuple(opts.get('rev', []))
2957 if not changesets:
2957 if not changesets:
2958 changesets = ['.']
2958 changesets = ['.']
2959 revs = scmutil.revrange(repo, changesets)
2959 revs = scmutil.revrange(repo, changesets)
2960 if not revs:
2960 if not revs:
2961 raise util.Abort(_("export requires at least one changeset"))
2961 raise util.Abort(_("export requires at least one changeset"))
2962 if len(revs) > 1:
2962 if len(revs) > 1:
2963 ui.note(_('exporting patches:\n'))
2963 ui.note(_('exporting patches:\n'))
2964 else:
2964 else:
2965 ui.note(_('exporting patch:\n'))
2965 ui.note(_('exporting patch:\n'))
2966 cmdutil.export(repo, revs, template=opts.get('output'),
2966 cmdutil.export(repo, revs, template=opts.get('output'),
2967 switch_parent=opts.get('switch_parent'),
2967 switch_parent=opts.get('switch_parent'),
2968 opts=patch.diffopts(ui, opts))
2968 opts=patch.diffopts(ui, opts))
2969
2969
2970 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2970 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2971 def forget(ui, repo, *pats, **opts):
2971 def forget(ui, repo, *pats, **opts):
2972 """forget the specified files on the next commit
2972 """forget the specified files on the next commit
2973
2973
2974 Mark the specified files so they will no longer be tracked
2974 Mark the specified files so they will no longer be tracked
2975 after the next commit.
2975 after the next commit.
2976
2976
2977 This only removes files from the current branch, not from the
2977 This only removes files from the current branch, not from the
2978 entire project history, and it does not delete them from the
2978 entire project history, and it does not delete them from the
2979 working directory.
2979 working directory.
2980
2980
2981 To undo a forget before the next commit, see :hg:`add`.
2981 To undo a forget before the next commit, see :hg:`add`.
2982
2982
2983 .. container:: verbose
2983 .. container:: verbose
2984
2984
2985 Examples:
2985 Examples:
2986
2986
2987 - forget newly-added binary files::
2987 - forget newly-added binary files::
2988
2988
2989 hg forget "set:added() and binary()"
2989 hg forget "set:added() and binary()"
2990
2990
2991 - forget files that would be excluded by .hgignore::
2991 - forget files that would be excluded by .hgignore::
2992
2992
2993 hg forget "set:hgignore()"
2993 hg forget "set:hgignore()"
2994
2994
2995 Returns 0 on success.
2995 Returns 0 on success.
2996 """
2996 """
2997
2997
2998 if not pats:
2998 if not pats:
2999 raise util.Abort(_('no files specified'))
2999 raise util.Abort(_('no files specified'))
3000
3000
3001 m = scmutil.match(repo[None], pats, opts)
3001 m = scmutil.match(repo[None], pats, opts)
3002 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3002 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3003 return rejected and 1 or 0
3003 return rejected and 1 or 0
3004
3004
3005 @command(
3005 @command(
3006 'graft',
3006 'graft',
3007 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3007 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3008 ('c', 'continue', False, _('resume interrupted graft')),
3008 ('c', 'continue', False, _('resume interrupted graft')),
3009 ('e', 'edit', False, _('invoke editor on commit messages')),
3009 ('e', 'edit', False, _('invoke editor on commit messages')),
3010 ('', 'log', None, _('append graft info to log message')),
3010 ('', 'log', None, _('append graft info to log message')),
3011 ('D', 'currentdate', False,
3011 ('D', 'currentdate', False,
3012 _('record the current date as commit date')),
3012 _('record the current date as commit date')),
3013 ('U', 'currentuser', False,
3013 ('U', 'currentuser', False,
3014 _('record the current user as committer'), _('DATE'))]
3014 _('record the current user as committer'), _('DATE'))]
3015 + commitopts2 + mergetoolopts + dryrunopts,
3015 + commitopts2 + mergetoolopts + dryrunopts,
3016 _('[OPTION]... [-r] REV...'))
3016 _('[OPTION]... [-r] REV...'))
3017 def graft(ui, repo, *revs, **opts):
3017 def graft(ui, repo, *revs, **opts):
3018 '''copy changes from other branches onto the current branch
3018 '''copy changes from other branches onto the current branch
3019
3019
3020 This command uses Mercurial's merge logic to copy individual
3020 This command uses Mercurial's merge logic to copy individual
3021 changes from other branches without merging branches in the
3021 changes from other branches without merging branches in the
3022 history graph. This is sometimes known as 'backporting' or
3022 history graph. This is sometimes known as 'backporting' or
3023 'cherry-picking'. By default, graft will copy user, date, and
3023 'cherry-picking'. By default, graft will copy user, date, and
3024 description from the source changesets.
3024 description from the source changesets.
3025
3025
3026 Changesets that are ancestors of the current revision, that have
3026 Changesets that are ancestors of the current revision, that have
3027 already been grafted, or that are merges will be skipped.
3027 already been grafted, or that are merges will be skipped.
3028
3028
3029 If --log is specified, log messages will have a comment appended
3029 If --log is specified, log messages will have a comment appended
3030 of the form::
3030 of the form::
3031
3031
3032 (grafted from CHANGESETHASH)
3032 (grafted from CHANGESETHASH)
3033
3033
3034 If a graft merge results in conflicts, the graft process is
3034 If a graft merge results in conflicts, the graft process is
3035 interrupted so that the current merge can be manually resolved.
3035 interrupted so that the current merge can be manually resolved.
3036 Once all conflicts are addressed, the graft process can be
3036 Once all conflicts are addressed, the graft process can be
3037 continued with the -c/--continue option.
3037 continued with the -c/--continue option.
3038
3038
3039 .. note::
3039 .. note::
3040
3040
3041 The -c/--continue option does not reapply earlier options.
3041 The -c/--continue option does not reapply earlier options.
3042
3042
3043 .. container:: verbose
3043 .. container:: verbose
3044
3044
3045 Examples:
3045 Examples:
3046
3046
3047 - copy a single change to the stable branch and edit its description::
3047 - copy a single change to the stable branch and edit its description::
3048
3048
3049 hg update stable
3049 hg update stable
3050 hg graft --edit 9393
3050 hg graft --edit 9393
3051
3051
3052 - graft a range of changesets with one exception, updating dates::
3052 - graft a range of changesets with one exception, updating dates::
3053
3053
3054 hg graft -D "2085::2093 and not 2091"
3054 hg graft -D "2085::2093 and not 2091"
3055
3055
3056 - continue a graft after resolving conflicts::
3056 - continue a graft after resolving conflicts::
3057
3057
3058 hg graft -c
3058 hg graft -c
3059
3059
3060 - show the source of a grafted changeset::
3060 - show the source of a grafted changeset::
3061
3061
3062 hg log --debug -r .
3062 hg log --debug -r .
3063
3063
3064 Returns 0 on successful completion.
3064 Returns 0 on successful completion.
3065 '''
3065 '''
3066
3066
3067 revs = list(revs)
3067 revs = list(revs)
3068 revs.extend(opts['rev'])
3068 revs.extend(opts['rev'])
3069
3069
3070 if not opts.get('user') and opts.get('currentuser'):
3070 if not opts.get('user') and opts.get('currentuser'):
3071 opts['user'] = ui.username()
3071 opts['user'] = ui.username()
3072 if not opts.get('date') and opts.get('currentdate'):
3072 if not opts.get('date') and opts.get('currentdate'):
3073 opts['date'] = "%d %d" % util.makedate()
3073 opts['date'] = "%d %d" % util.makedate()
3074
3074
3075 editor = None
3075 editor = None
3076 if opts.get('edit'):
3076 if opts.get('edit'):
3077 editor = cmdutil.commitforceeditor
3077 editor = cmdutil.commitforceeditor
3078
3078
3079 cont = False
3079 cont = False
3080 if opts['continue']:
3080 if opts['continue']:
3081 cont = True
3081 cont = True
3082 if revs:
3082 if revs:
3083 raise util.Abort(_("can't specify --continue and revisions"))
3083 raise util.Abort(_("can't specify --continue and revisions"))
3084 # read in unfinished revisions
3084 # read in unfinished revisions
3085 try:
3085 try:
3086 nodes = repo.opener.read('graftstate').splitlines()
3086 nodes = repo.opener.read('graftstate').splitlines()
3087 revs = [repo[node].rev() for node in nodes]
3087 revs = [repo[node].rev() for node in nodes]
3088 except IOError, inst:
3088 except IOError, inst:
3089 if inst.errno != errno.ENOENT:
3089 if inst.errno != errno.ENOENT:
3090 raise
3090 raise
3091 raise util.Abort(_("no graft state found, can't continue"))
3091 raise util.Abort(_("no graft state found, can't continue"))
3092 else:
3092 else:
3093 cmdutil.checkunfinished(repo)
3093 cmdutil.checkunfinished(repo)
3094 cmdutil.bailifchanged(repo)
3094 cmdutil.bailifchanged(repo)
3095 if not revs:
3095 if not revs:
3096 raise util.Abort(_('no revisions specified'))
3096 raise util.Abort(_('no revisions specified'))
3097 revs = scmutil.revrange(repo, revs)
3097 revs = scmutil.revrange(repo, revs)
3098
3098
3099 # check for merges
3099 # check for merges
3100 for rev in repo.revs('%ld and merge()', revs):
3100 for rev in repo.revs('%ld and merge()', revs):
3101 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3101 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3102 revs.remove(rev)
3102 revs.remove(rev)
3103 if not revs:
3103 if not revs:
3104 return -1
3104 return -1
3105
3105
3106 # check for ancestors of dest branch
3106 # check for ancestors of dest branch
3107 crev = repo['.'].rev()
3107 crev = repo['.'].rev()
3108 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3108 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3109 # don't mutate while iterating, create a copy
3109 # don't mutate while iterating, create a copy
3110 for rev in list(revs):
3110 for rev in list(revs):
3111 if rev in ancestors:
3111 if rev in ancestors:
3112 ui.warn(_('skipping ancestor revision %s\n') % rev)
3112 ui.warn(_('skipping ancestor revision %s\n') % rev)
3113 revs.remove(rev)
3113 revs.remove(rev)
3114 if not revs:
3114 if not revs:
3115 return -1
3115 return -1
3116
3116
3117 # analyze revs for earlier grafts
3117 # analyze revs for earlier grafts
3118 ids = {}
3118 ids = {}
3119 for ctx in repo.set("%ld", revs):
3119 for ctx in repo.set("%ld", revs):
3120 ids[ctx.hex()] = ctx.rev()
3120 ids[ctx.hex()] = ctx.rev()
3121 n = ctx.extra().get('source')
3121 n = ctx.extra().get('source')
3122 if n:
3122 if n:
3123 ids[n] = ctx.rev()
3123 ids[n] = ctx.rev()
3124
3124
3125 # check ancestors for earlier grafts
3125 # check ancestors for earlier grafts
3126 ui.debug('scanning for duplicate grafts\n')
3126 ui.debug('scanning for duplicate grafts\n')
3127
3127
3128 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3128 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3129 ctx = repo[rev]
3129 ctx = repo[rev]
3130 n = ctx.extra().get('source')
3130 n = ctx.extra().get('source')
3131 if n in ids:
3131 if n in ids:
3132 r = repo[n].rev()
3132 r = repo[n].rev()
3133 if r in revs:
3133 if r in revs:
3134 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3134 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3135 % (r, rev))
3135 % (r, rev))
3136 revs.remove(r)
3136 revs.remove(r)
3137 elif ids[n] in revs:
3137 elif ids[n] in revs:
3138 ui.warn(_('skipping already grafted revision %s '
3138 ui.warn(_('skipping already grafted revision %s '
3139 '(%s also has origin %d)\n') % (ids[n], rev, r))
3139 '(%s also has origin %d)\n') % (ids[n], rev, r))
3140 revs.remove(ids[n])
3140 revs.remove(ids[n])
3141 elif ctx.hex() in ids:
3141 elif ctx.hex() in ids:
3142 r = ids[ctx.hex()]
3142 r = ids[ctx.hex()]
3143 ui.warn(_('skipping already grafted revision %s '
3143 ui.warn(_('skipping already grafted revision %s '
3144 '(was grafted from %d)\n') % (r, rev))
3144 '(was grafted from %d)\n') % (r, rev))
3145 revs.remove(r)
3145 revs.remove(r)
3146 if not revs:
3146 if not revs:
3147 return -1
3147 return -1
3148
3148
3149 wlock = repo.wlock()
3149 wlock = repo.wlock()
3150 try:
3150 try:
3151 current = repo['.']
3151 current = repo['.']
3152 for pos, ctx in enumerate(repo.set("%ld", revs)):
3152 for pos, ctx in enumerate(repo.set("%ld", revs)):
3153
3153
3154 ui.status(_('grafting revision %s\n') % ctx.rev())
3154 ui.status(_('grafting revision %s\n') % ctx.rev())
3155 if opts.get('dry_run'):
3155 if opts.get('dry_run'):
3156 continue
3156 continue
3157
3157
3158 source = ctx.extra().get('source')
3158 source = ctx.extra().get('source')
3159 if not source:
3159 if not source:
3160 source = ctx.hex()
3160 source = ctx.hex()
3161 extra = {'source': source}
3161 extra = {'source': source}
3162 user = ctx.user()
3162 user = ctx.user()
3163 if opts.get('user'):
3163 if opts.get('user'):
3164 user = opts['user']
3164 user = opts['user']
3165 date = ctx.date()
3165 date = ctx.date()
3166 if opts.get('date'):
3166 if opts.get('date'):
3167 date = opts['date']
3167 date = opts['date']
3168 message = ctx.description()
3168 message = ctx.description()
3169 if opts.get('log'):
3169 if opts.get('log'):
3170 message += '\n(grafted from %s)' % ctx.hex()
3170 message += '\n(grafted from %s)' % ctx.hex()
3171
3171
3172 # we don't merge the first commit when continuing
3172 # we don't merge the first commit when continuing
3173 if not cont:
3173 if not cont:
3174 # perform the graft merge with p1(rev) as 'ancestor'
3174 # perform the graft merge with p1(rev) as 'ancestor'
3175 try:
3175 try:
3176 # ui.forcemerge is an internal variable, do not document
3176 # ui.forcemerge is an internal variable, do not document
3177 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3177 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3178 stats = mergemod.update(repo, ctx.node(), True, True, False,
3178 stats = mergemod.update(repo, ctx.node(), True, True, False,
3179 ctx.p1().node())
3179 ctx.p1().node())
3180 finally:
3180 finally:
3181 repo.ui.setconfig('ui', 'forcemerge', '')
3181 repo.ui.setconfig('ui', 'forcemerge', '')
3182 # report any conflicts
3182 # report any conflicts
3183 if stats and stats[3] > 0:
3183 if stats and stats[3] > 0:
3184 # write out state for --continue
3184 # write out state for --continue
3185 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3185 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3186 repo.opener.write('graftstate', ''.join(nodelines))
3186 repo.opener.write('graftstate', ''.join(nodelines))
3187 raise util.Abort(
3187 raise util.Abort(
3188 _("unresolved conflicts, can't continue"),
3188 _("unresolved conflicts, can't continue"),
3189 hint=_('use hg resolve and hg graft --continue'))
3189 hint=_('use hg resolve and hg graft --continue'))
3190 else:
3190 else:
3191 cont = False
3191 cont = False
3192
3192
3193 # drop the second merge parent
3193 # drop the second merge parent
3194 repo.setparents(current.node(), nullid)
3194 repo.setparents(current.node(), nullid)
3195 repo.dirstate.write()
3195 repo.dirstate.write()
3196 # fix up dirstate for copies and renames
3196 # fix up dirstate for copies and renames
3197 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3197 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3198
3198
3199 # commit
3199 # commit
3200 node = repo.commit(text=message, user=user,
3200 node = repo.commit(text=message, user=user,
3201 date=date, extra=extra, editor=editor)
3201 date=date, extra=extra, editor=editor)
3202 if node is None:
3202 if node is None:
3203 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3203 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3204 else:
3204 else:
3205 current = repo[node]
3205 current = repo[node]
3206 finally:
3206 finally:
3207 wlock.release()
3207 wlock.release()
3208
3208
3209 # remove state when we complete successfully
3209 # remove state when we complete successfully
3210 if not opts.get('dry_run'):
3210 if not opts.get('dry_run'):
3211 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3211 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3212
3212
3213 return 0
3213 return 0
3214
3214
3215 @command('grep',
3215 @command('grep',
3216 [('0', 'print0', None, _('end fields with NUL')),
3216 [('0', 'print0', None, _('end fields with NUL')),
3217 ('', 'all', None, _('print all revisions that match')),
3217 ('', 'all', None, _('print all revisions that match')),
3218 ('a', 'text', None, _('treat all files as text')),
3218 ('a', 'text', None, _('treat all files as text')),
3219 ('f', 'follow', None,
3219 ('f', 'follow', None,
3220 _('follow changeset history,'
3220 _('follow changeset history,'
3221 ' or file history across copies and renames')),
3221 ' or file history across copies and renames')),
3222 ('i', 'ignore-case', None, _('ignore case when matching')),
3222 ('i', 'ignore-case', None, _('ignore case when matching')),
3223 ('l', 'files-with-matches', None,
3223 ('l', 'files-with-matches', None,
3224 _('print only filenames and revisions that match')),
3224 _('print only filenames and revisions that match')),
3225 ('n', 'line-number', None, _('print matching line numbers')),
3225 ('n', 'line-number', None, _('print matching line numbers')),
3226 ('r', 'rev', [],
3226 ('r', 'rev', [],
3227 _('only search files changed within revision range'), _('REV')),
3227 _('only search files changed within revision range'), _('REV')),
3228 ('u', 'user', None, _('list the author (long with -v)')),
3228 ('u', 'user', None, _('list the author (long with -v)')),
3229 ('d', 'date', None, _('list the date (short with -q)')),
3229 ('d', 'date', None, _('list the date (short with -q)')),
3230 ] + walkopts,
3230 ] + walkopts,
3231 _('[OPTION]... PATTERN [FILE]...'))
3231 _('[OPTION]... PATTERN [FILE]...'))
3232 def grep(ui, repo, pattern, *pats, **opts):
3232 def grep(ui, repo, pattern, *pats, **opts):
3233 """search for a pattern in specified files and revisions
3233 """search for a pattern in specified files and revisions
3234
3234
3235 Search revisions of files for a regular expression.
3235 Search revisions of files for a regular expression.
3236
3236
3237 This command behaves differently than Unix grep. It only accepts
3237 This command behaves differently than Unix grep. It only accepts
3238 Python/Perl regexps. It searches repository history, not the
3238 Python/Perl regexps. It searches repository history, not the
3239 working directory. It always prints the revision number in which a
3239 working directory. It always prints the revision number in which a
3240 match appears.
3240 match appears.
3241
3241
3242 By default, grep only prints output for the first revision of a
3242 By default, grep only prints output for the first revision of a
3243 file in which it finds a match. To get it to print every revision
3243 file in which it finds a match. To get it to print every revision
3244 that contains a change in match status ("-" for a match that
3244 that contains a change in match status ("-" for a match that
3245 becomes a non-match, or "+" for a non-match that becomes a match),
3245 becomes a non-match, or "+" for a non-match that becomes a match),
3246 use the --all flag.
3246 use the --all flag.
3247
3247
3248 Returns 0 if a match is found, 1 otherwise.
3248 Returns 0 if a match is found, 1 otherwise.
3249 """
3249 """
3250 reflags = re.M
3250 reflags = re.M
3251 if opts.get('ignore_case'):
3251 if opts.get('ignore_case'):
3252 reflags |= re.I
3252 reflags |= re.I
3253 try:
3253 try:
3254 regexp = util.compilere(pattern, reflags)
3254 regexp = util.compilere(pattern, reflags)
3255 except re.error, inst:
3255 except re.error, inst:
3256 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3256 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3257 return 1
3257 return 1
3258 sep, eol = ':', '\n'
3258 sep, eol = ':', '\n'
3259 if opts.get('print0'):
3259 if opts.get('print0'):
3260 sep = eol = '\0'
3260 sep = eol = '\0'
3261
3261
3262 getfile = util.lrucachefunc(repo.file)
3262 getfile = util.lrucachefunc(repo.file)
3263
3263
3264 def matchlines(body):
3264 def matchlines(body):
3265 begin = 0
3265 begin = 0
3266 linenum = 0
3266 linenum = 0
3267 while begin < len(body):
3267 while begin < len(body):
3268 match = regexp.search(body, begin)
3268 match = regexp.search(body, begin)
3269 if not match:
3269 if not match:
3270 break
3270 break
3271 mstart, mend = match.span()
3271 mstart, mend = match.span()
3272 linenum += body.count('\n', begin, mstart) + 1
3272 linenum += body.count('\n', begin, mstart) + 1
3273 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3273 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3274 begin = body.find('\n', mend) + 1 or len(body) + 1
3274 begin = body.find('\n', mend) + 1 or len(body) + 1
3275 lend = begin - 1
3275 lend = begin - 1
3276 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3276 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3277
3277
3278 class linestate(object):
3278 class linestate(object):
3279 def __init__(self, line, linenum, colstart, colend):
3279 def __init__(self, line, linenum, colstart, colend):
3280 self.line = line
3280 self.line = line
3281 self.linenum = linenum
3281 self.linenum = linenum
3282 self.colstart = colstart
3282 self.colstart = colstart
3283 self.colend = colend
3283 self.colend = colend
3284
3284
3285 def __hash__(self):
3285 def __hash__(self):
3286 return hash((self.linenum, self.line))
3286 return hash((self.linenum, self.line))
3287
3287
3288 def __eq__(self, other):
3288 def __eq__(self, other):
3289 return self.line == other.line
3289 return self.line == other.line
3290
3290
3291 matches = {}
3291 matches = {}
3292 copies = {}
3292 copies = {}
3293 def grepbody(fn, rev, body):
3293 def grepbody(fn, rev, body):
3294 matches[rev].setdefault(fn, [])
3294 matches[rev].setdefault(fn, [])
3295 m = matches[rev][fn]
3295 m = matches[rev][fn]
3296 for lnum, cstart, cend, line in matchlines(body):
3296 for lnum, cstart, cend, line in matchlines(body):
3297 s = linestate(line, lnum, cstart, cend)
3297 s = linestate(line, lnum, cstart, cend)
3298 m.append(s)
3298 m.append(s)
3299
3299
3300 def difflinestates(a, b):
3300 def difflinestates(a, b):
3301 sm = difflib.SequenceMatcher(None, a, b)
3301 sm = difflib.SequenceMatcher(None, a, b)
3302 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3302 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3303 if tag == 'insert':
3303 if tag == 'insert':
3304 for i in xrange(blo, bhi):
3304 for i in xrange(blo, bhi):
3305 yield ('+', b[i])
3305 yield ('+', b[i])
3306 elif tag == 'delete':
3306 elif tag == 'delete':
3307 for i in xrange(alo, ahi):
3307 for i in xrange(alo, ahi):
3308 yield ('-', a[i])
3308 yield ('-', a[i])
3309 elif tag == 'replace':
3309 elif tag == 'replace':
3310 for i in xrange(alo, ahi):
3310 for i in xrange(alo, ahi):
3311 yield ('-', a[i])
3311 yield ('-', a[i])
3312 for i in xrange(blo, bhi):
3312 for i in xrange(blo, bhi):
3313 yield ('+', b[i])
3313 yield ('+', b[i])
3314
3314
3315 def display(fn, ctx, pstates, states):
3315 def display(fn, ctx, pstates, states):
3316 rev = ctx.rev()
3316 rev = ctx.rev()
3317 datefunc = ui.quiet and util.shortdate or util.datestr
3317 datefunc = ui.quiet and util.shortdate or util.datestr
3318 found = False
3318 found = False
3319 filerevmatches = {}
3319 filerevmatches = {}
3320 def binary():
3320 def binary():
3321 flog = getfile(fn)
3321 flog = getfile(fn)
3322 return util.binary(flog.read(ctx.filenode(fn)))
3322 return util.binary(flog.read(ctx.filenode(fn)))
3323
3323
3324 if opts.get('all'):
3324 if opts.get('all'):
3325 iter = difflinestates(pstates, states)
3325 iter = difflinestates(pstates, states)
3326 else:
3326 else:
3327 iter = [('', l) for l in states]
3327 iter = [('', l) for l in states]
3328 for change, l in iter:
3328 for change, l in iter:
3329 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3329 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3330 before, match, after = None, None, None
3330 before, match, after = None, None, None
3331
3331
3332 if opts.get('line_number'):
3332 if opts.get('line_number'):
3333 cols.append((str(l.linenum), 'grep.linenumber'))
3333 cols.append((str(l.linenum), 'grep.linenumber'))
3334 if opts.get('all'):
3334 if opts.get('all'):
3335 cols.append((change, 'grep.change'))
3335 cols.append((change, 'grep.change'))
3336 if opts.get('user'):
3336 if opts.get('user'):
3337 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3337 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3338 if opts.get('date'):
3338 if opts.get('date'):
3339 cols.append((datefunc(ctx.date()), 'grep.date'))
3339 cols.append((datefunc(ctx.date()), 'grep.date'))
3340 if opts.get('files_with_matches'):
3340 if opts.get('files_with_matches'):
3341 c = (fn, rev)
3341 c = (fn, rev)
3342 if c in filerevmatches:
3342 if c in filerevmatches:
3343 continue
3343 continue
3344 filerevmatches[c] = 1
3344 filerevmatches[c] = 1
3345 else:
3345 else:
3346 before = l.line[:l.colstart]
3346 before = l.line[:l.colstart]
3347 match = l.line[l.colstart:l.colend]
3347 match = l.line[l.colstart:l.colend]
3348 after = l.line[l.colend:]
3348 after = l.line[l.colend:]
3349 for col, label in cols[:-1]:
3349 for col, label in cols[:-1]:
3350 ui.write(col, label=label)
3350 ui.write(col, label=label)
3351 ui.write(sep, label='grep.sep')
3351 ui.write(sep, label='grep.sep')
3352 ui.write(cols[-1][0], label=cols[-1][1])
3352 ui.write(cols[-1][0], label=cols[-1][1])
3353 if before is not None:
3353 if before is not None:
3354 ui.write(sep, label='grep.sep')
3354 ui.write(sep, label='grep.sep')
3355 if not opts.get('text') and binary():
3355 if not opts.get('text') and binary():
3356 ui.write(" Binary file matches")
3356 ui.write(" Binary file matches")
3357 else:
3357 else:
3358 ui.write(before)
3358 ui.write(before)
3359 ui.write(match, label='grep.match')
3359 ui.write(match, label='grep.match')
3360 ui.write(after)
3360 ui.write(after)
3361 ui.write(eol)
3361 ui.write(eol)
3362 found = True
3362 found = True
3363 return found
3363 return found
3364
3364
3365 skip = {}
3365 skip = {}
3366 revfiles = {}
3366 revfiles = {}
3367 matchfn = scmutil.match(repo[None], pats, opts)
3367 matchfn = scmutil.match(repo[None], pats, opts)
3368 found = False
3368 found = False
3369 follow = opts.get('follow')
3369 follow = opts.get('follow')
3370
3370
3371 def prep(ctx, fns):
3371 def prep(ctx, fns):
3372 rev = ctx.rev()
3372 rev = ctx.rev()
3373 pctx = ctx.p1()
3373 pctx = ctx.p1()
3374 parent = pctx.rev()
3374 parent = pctx.rev()
3375 matches.setdefault(rev, {})
3375 matches.setdefault(rev, {})
3376 matches.setdefault(parent, {})
3376 matches.setdefault(parent, {})
3377 files = revfiles.setdefault(rev, [])
3377 files = revfiles.setdefault(rev, [])
3378 for fn in fns:
3378 for fn in fns:
3379 flog = getfile(fn)
3379 flog = getfile(fn)
3380 try:
3380 try:
3381 fnode = ctx.filenode(fn)
3381 fnode = ctx.filenode(fn)
3382 except error.LookupError:
3382 except error.LookupError:
3383 continue
3383 continue
3384
3384
3385 copied = flog.renamed(fnode)
3385 copied = flog.renamed(fnode)
3386 copy = follow and copied and copied[0]
3386 copy = follow and copied and copied[0]
3387 if copy:
3387 if copy:
3388 copies.setdefault(rev, {})[fn] = copy
3388 copies.setdefault(rev, {})[fn] = copy
3389 if fn in skip:
3389 if fn in skip:
3390 if copy:
3390 if copy:
3391 skip[copy] = True
3391 skip[copy] = True
3392 continue
3392 continue
3393 files.append(fn)
3393 files.append(fn)
3394
3394
3395 if fn not in matches[rev]:
3395 if fn not in matches[rev]:
3396 grepbody(fn, rev, flog.read(fnode))
3396 grepbody(fn, rev, flog.read(fnode))
3397
3397
3398 pfn = copy or fn
3398 pfn = copy or fn
3399 if pfn not in matches[parent]:
3399 if pfn not in matches[parent]:
3400 try:
3400 try:
3401 fnode = pctx.filenode(pfn)
3401 fnode = pctx.filenode(pfn)
3402 grepbody(pfn, parent, flog.read(fnode))
3402 grepbody(pfn, parent, flog.read(fnode))
3403 except error.LookupError:
3403 except error.LookupError:
3404 pass
3404 pass
3405
3405
3406 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3406 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3407 rev = ctx.rev()
3407 rev = ctx.rev()
3408 parent = ctx.p1().rev()
3408 parent = ctx.p1().rev()
3409 for fn in sorted(revfiles.get(rev, [])):
3409 for fn in sorted(revfiles.get(rev, [])):
3410 states = matches[rev][fn]
3410 states = matches[rev][fn]
3411 copy = copies.get(rev, {}).get(fn)
3411 copy = copies.get(rev, {}).get(fn)
3412 if fn in skip:
3412 if fn in skip:
3413 if copy:
3413 if copy:
3414 skip[copy] = True
3414 skip[copy] = True
3415 continue
3415 continue
3416 pstates = matches.get(parent, {}).get(copy or fn, [])
3416 pstates = matches.get(parent, {}).get(copy or fn, [])
3417 if pstates or states:
3417 if pstates or states:
3418 r = display(fn, ctx, pstates, states)
3418 r = display(fn, ctx, pstates, states)
3419 found = found or r
3419 found = found or r
3420 if r and not opts.get('all'):
3420 if r and not opts.get('all'):
3421 skip[fn] = True
3421 skip[fn] = True
3422 if copy:
3422 if copy:
3423 skip[copy] = True
3423 skip[copy] = True
3424 del matches[rev]
3424 del matches[rev]
3425 del revfiles[rev]
3425 del revfiles[rev]
3426
3426
3427 return not found
3427 return not found
3428
3428
3429 @command('heads',
3429 @command('heads',
3430 [('r', 'rev', '',
3430 [('r', 'rev', '',
3431 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3431 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3432 ('t', 'topo', False, _('show topological heads only')),
3432 ('t', 'topo', False, _('show topological heads only')),
3433 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3433 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3434 ('c', 'closed', False, _('show normal and closed branch heads')),
3434 ('c', 'closed', False, _('show normal and closed branch heads')),
3435 ] + templateopts,
3435 ] + templateopts,
3436 _('[-ct] [-r STARTREV] [REV]...'))
3436 _('[-ct] [-r STARTREV] [REV]...'))
3437 def heads(ui, repo, *branchrevs, **opts):
3437 def heads(ui, repo, *branchrevs, **opts):
3438 """show branch heads
3438 """show branch heads
3439
3439
3440 With no arguments, show all open branch heads in the repository.
3440 With no arguments, show all open branch heads in the repository.
3441 Branch heads are changesets that have no descendants on the
3441 Branch heads are changesets that have no descendants on the
3442 same branch. They are where development generally takes place and
3442 same branch. They are where development generally takes place and
3443 are the usual targets for update and merge operations.
3443 are the usual targets for update and merge operations.
3444
3444
3445 If one or more REVs are given, only open branch heads on the
3445 If one or more REVs are given, only open branch heads on the
3446 branches associated with the specified changesets are shown. This
3446 branches associated with the specified changesets are shown. This
3447 means that you can use :hg:`heads .` to see the heads on the
3447 means that you can use :hg:`heads .` to see the heads on the
3448 currently checked-out branch.
3448 currently checked-out branch.
3449
3449
3450 If -c/--closed is specified, also show branch heads marked closed
3450 If -c/--closed is specified, also show branch heads marked closed
3451 (see :hg:`commit --close-branch`).
3451 (see :hg:`commit --close-branch`).
3452
3452
3453 If STARTREV is specified, only those heads that are descendants of
3453 If STARTREV is specified, only those heads that are descendants of
3454 STARTREV will be displayed.
3454 STARTREV will be displayed.
3455
3455
3456 If -t/--topo is specified, named branch mechanics will be ignored and only
3456 If -t/--topo is specified, named branch mechanics will be ignored and only
3457 topological heads (changesets with no children) will be shown.
3457 topological heads (changesets with no children) will be shown.
3458
3458
3459 Returns 0 if matching heads are found, 1 if not.
3459 Returns 0 if matching heads are found, 1 if not.
3460 """
3460 """
3461
3461
3462 start = None
3462 start = None
3463 if 'rev' in opts:
3463 if 'rev' in opts:
3464 start = scmutil.revsingle(repo, opts['rev'], None).node()
3464 start = scmutil.revsingle(repo, opts['rev'], None).node()
3465
3465
3466 if opts.get('topo'):
3466 if opts.get('topo'):
3467 heads = [repo[h] for h in repo.heads(start)]
3467 heads = [repo[h] for h in repo.heads(start)]
3468 else:
3468 else:
3469 heads = []
3469 heads = []
3470 for branch in repo.branchmap():
3470 for branch in repo.branchmap():
3471 heads += repo.branchheads(branch, start, opts.get('closed'))
3471 heads += repo.branchheads(branch, start, opts.get('closed'))
3472 heads = [repo[h] for h in heads]
3472 heads = [repo[h] for h in heads]
3473
3473
3474 if branchrevs:
3474 if branchrevs:
3475 branches = set(repo[br].branch() for br in branchrevs)
3475 branches = set(repo[br].branch() for br in branchrevs)
3476 heads = [h for h in heads if h.branch() in branches]
3476 heads = [h for h in heads if h.branch() in branches]
3477
3477
3478 if opts.get('active') and branchrevs:
3478 if opts.get('active') and branchrevs:
3479 dagheads = repo.heads(start)
3479 dagheads = repo.heads(start)
3480 heads = [h for h in heads if h.node() in dagheads]
3480 heads = [h for h in heads if h.node() in dagheads]
3481
3481
3482 if branchrevs:
3482 if branchrevs:
3483 haveheads = set(h.branch() for h in heads)
3483 haveheads = set(h.branch() for h in heads)
3484 if branches - haveheads:
3484 if branches - haveheads:
3485 headless = ', '.join(b for b in branches - haveheads)
3485 headless = ', '.join(b for b in branches - haveheads)
3486 msg = _('no open branch heads found on branches %s')
3486 msg = _('no open branch heads found on branches %s')
3487 if opts.get('rev'):
3487 if opts.get('rev'):
3488 msg += _(' (started at %s)') % opts['rev']
3488 msg += _(' (started at %s)') % opts['rev']
3489 ui.warn((msg + '\n') % headless)
3489 ui.warn((msg + '\n') % headless)
3490
3490
3491 if not heads:
3491 if not heads:
3492 return 1
3492 return 1
3493
3493
3494 heads = sorted(heads, key=lambda x: -x.rev())
3494 heads = sorted(heads, key=lambda x: -x.rev())
3495 displayer = cmdutil.show_changeset(ui, repo, opts)
3495 displayer = cmdutil.show_changeset(ui, repo, opts)
3496 for ctx in heads:
3496 for ctx in heads:
3497 displayer.show(ctx)
3497 displayer.show(ctx)
3498 displayer.close()
3498 displayer.close()
3499
3499
3500 @command('help',
3500 @command('help',
3501 [('e', 'extension', None, _('show only help for extensions')),
3501 [('e', 'extension', None, _('show only help for extensions')),
3502 ('c', 'command', None, _('show only help for commands')),
3502 ('c', 'command', None, _('show only help for commands')),
3503 ('k', 'keyword', '', _('show topics matching keyword')),
3503 ('k', 'keyword', '', _('show topics matching keyword')),
3504 ],
3504 ],
3505 _('[-ec] [TOPIC]'))
3505 _('[-ec] [TOPIC]'))
3506 def help_(ui, name=None, **opts):
3506 def help_(ui, name=None, **opts):
3507 """show help for a given topic or a help overview
3507 """show help for a given topic or a help overview
3508
3508
3509 With no arguments, print a list of commands with short help messages.
3509 With no arguments, print a list of commands with short help messages.
3510
3510
3511 Given a topic, extension, or command name, print help for that
3511 Given a topic, extension, or command name, print help for that
3512 topic.
3512 topic.
3513
3513
3514 Returns 0 if successful.
3514 Returns 0 if successful.
3515 """
3515 """
3516
3516
3517 textwidth = min(ui.termwidth(), 80) - 2
3517 textwidth = min(ui.termwidth(), 80) - 2
3518
3518
3519 keep = ui.verbose and ['verbose'] or []
3519 keep = ui.verbose and ['verbose'] or []
3520 text = help.help_(ui, name, **opts)
3520 text = help.help_(ui, name, **opts)
3521
3521
3522 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3522 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3523 if 'verbose' in pruned:
3523 if 'verbose' in pruned:
3524 keep.append('omitted')
3524 keep.append('omitted')
3525 else:
3525 else:
3526 keep.append('notomitted')
3526 keep.append('notomitted')
3527 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3527 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3528 ui.write(formatted)
3528 ui.write(formatted)
3529
3529
3530
3530
3531 @command('identify|id',
3531 @command('identify|id',
3532 [('r', 'rev', '',
3532 [('r', 'rev', '',
3533 _('identify the specified revision'), _('REV')),
3533 _('identify the specified revision'), _('REV')),
3534 ('n', 'num', None, _('show local revision number')),
3534 ('n', 'num', None, _('show local revision number')),
3535 ('i', 'id', None, _('show global revision id')),
3535 ('i', 'id', None, _('show global revision id')),
3536 ('b', 'branch', None, _('show branch')),
3536 ('b', 'branch', None, _('show branch')),
3537 ('t', 'tags', None, _('show tags')),
3537 ('t', 'tags', None, _('show tags')),
3538 ('B', 'bookmarks', None, _('show bookmarks')),
3538 ('B', 'bookmarks', None, _('show bookmarks')),
3539 ] + remoteopts,
3539 ] + remoteopts,
3540 _('[-nibtB] [-r REV] [SOURCE]'))
3540 _('[-nibtB] [-r REV] [SOURCE]'))
3541 def identify(ui, repo, source=None, rev=None,
3541 def identify(ui, repo, source=None, rev=None,
3542 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3542 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3543 """identify the working copy or specified revision
3543 """identify the working copy or specified revision
3544
3544
3545 Print a summary identifying the repository state at REV using one or
3545 Print a summary identifying the repository state at REV using one or
3546 two parent hash identifiers, followed by a "+" if the working
3546 two parent hash identifiers, followed by a "+" if the working
3547 directory has uncommitted changes, the branch name (if not default),
3547 directory has uncommitted changes, the branch name (if not default),
3548 a list of tags, and a list of bookmarks.
3548 a list of tags, and a list of bookmarks.
3549
3549
3550 When REV is not given, print a summary of the current state of the
3550 When REV is not given, print a summary of the current state of the
3551 repository.
3551 repository.
3552
3552
3553 Specifying a path to a repository root or Mercurial bundle will
3553 Specifying a path to a repository root or Mercurial bundle will
3554 cause lookup to operate on that repository/bundle.
3554 cause lookup to operate on that repository/bundle.
3555
3555
3556 .. container:: verbose
3556 .. container:: verbose
3557
3557
3558 Examples:
3558 Examples:
3559
3559
3560 - generate a build identifier for the working directory::
3560 - generate a build identifier for the working directory::
3561
3561
3562 hg id --id > build-id.dat
3562 hg id --id > build-id.dat
3563
3563
3564 - find the revision corresponding to a tag::
3564 - find the revision corresponding to a tag::
3565
3565
3566 hg id -n -r 1.3
3566 hg id -n -r 1.3
3567
3567
3568 - check the most recent revision of a remote repository::
3568 - check the most recent revision of a remote repository::
3569
3569
3570 hg id -r tip http://selenic.com/hg/
3570 hg id -r tip http://selenic.com/hg/
3571
3571
3572 Returns 0 if successful.
3572 Returns 0 if successful.
3573 """
3573 """
3574
3574
3575 if not repo and not source:
3575 if not repo and not source:
3576 raise util.Abort(_("there is no Mercurial repository here "
3576 raise util.Abort(_("there is no Mercurial repository here "
3577 "(.hg not found)"))
3577 "(.hg not found)"))
3578
3578
3579 hexfunc = ui.debugflag and hex or short
3579 hexfunc = ui.debugflag and hex or short
3580 default = not (num or id or branch or tags or bookmarks)
3580 default = not (num or id or branch or tags or bookmarks)
3581 output = []
3581 output = []
3582 revs = []
3582 revs = []
3583
3583
3584 if source:
3584 if source:
3585 source, branches = hg.parseurl(ui.expandpath(source))
3585 source, branches = hg.parseurl(ui.expandpath(source))
3586 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3586 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3587 repo = peer.local()
3587 repo = peer.local()
3588 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3588 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3589
3589
3590 if not repo:
3590 if not repo:
3591 if num or branch or tags:
3591 if num or branch or tags:
3592 raise util.Abort(
3592 raise util.Abort(
3593 _("can't query remote revision number, branch, or tags"))
3593 _("can't query remote revision number, branch, or tags"))
3594 if not rev and revs:
3594 if not rev and revs:
3595 rev = revs[0]
3595 rev = revs[0]
3596 if not rev:
3596 if not rev:
3597 rev = "tip"
3597 rev = "tip"
3598
3598
3599 remoterev = peer.lookup(rev)
3599 remoterev = peer.lookup(rev)
3600 if default or id:
3600 if default or id:
3601 output = [hexfunc(remoterev)]
3601 output = [hexfunc(remoterev)]
3602
3602
3603 def getbms():
3603 def getbms():
3604 bms = []
3604 bms = []
3605
3605
3606 if 'bookmarks' in peer.listkeys('namespaces'):
3606 if 'bookmarks' in peer.listkeys('namespaces'):
3607 hexremoterev = hex(remoterev)
3607 hexremoterev = hex(remoterev)
3608 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3608 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3609 if bmr == hexremoterev]
3609 if bmr == hexremoterev]
3610
3610
3611 return sorted(bms)
3611 return sorted(bms)
3612
3612
3613 if bookmarks:
3613 if bookmarks:
3614 output.extend(getbms())
3614 output.extend(getbms())
3615 elif default and not ui.quiet:
3615 elif default and not ui.quiet:
3616 # multiple bookmarks for a single parent separated by '/'
3616 # multiple bookmarks for a single parent separated by '/'
3617 bm = '/'.join(getbms())
3617 bm = '/'.join(getbms())
3618 if bm:
3618 if bm:
3619 output.append(bm)
3619 output.append(bm)
3620 else:
3620 else:
3621 if not rev:
3621 if not rev:
3622 ctx = repo[None]
3622 ctx = repo[None]
3623 parents = ctx.parents()
3623 parents = ctx.parents()
3624 changed = ""
3624 changed = ""
3625 if default or id or num:
3625 if default or id or num:
3626 if (util.any(repo.status())
3626 if (util.any(repo.status())
3627 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3627 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3628 changed = '+'
3628 changed = '+'
3629 if default or id:
3629 if default or id:
3630 output = ["%s%s" %
3630 output = ["%s%s" %
3631 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3631 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3632 if num:
3632 if num:
3633 output.append("%s%s" %
3633 output.append("%s%s" %
3634 ('+'.join([str(p.rev()) for p in parents]), changed))
3634 ('+'.join([str(p.rev()) for p in parents]), changed))
3635 else:
3635 else:
3636 ctx = scmutil.revsingle(repo, rev)
3636 ctx = scmutil.revsingle(repo, rev)
3637 if default or id:
3637 if default or id:
3638 output = [hexfunc(ctx.node())]
3638 output = [hexfunc(ctx.node())]
3639 if num:
3639 if num:
3640 output.append(str(ctx.rev()))
3640 output.append(str(ctx.rev()))
3641
3641
3642 if default and not ui.quiet:
3642 if default and not ui.quiet:
3643 b = ctx.branch()
3643 b = ctx.branch()
3644 if b != 'default':
3644 if b != 'default':
3645 output.append("(%s)" % b)
3645 output.append("(%s)" % b)
3646
3646
3647 # multiple tags for a single parent separated by '/'
3647 # multiple tags for a single parent separated by '/'
3648 t = '/'.join(ctx.tags())
3648 t = '/'.join(ctx.tags())
3649 if t:
3649 if t:
3650 output.append(t)
3650 output.append(t)
3651
3651
3652 # multiple bookmarks for a single parent separated by '/'
3652 # multiple bookmarks for a single parent separated by '/'
3653 bm = '/'.join(ctx.bookmarks())
3653 bm = '/'.join(ctx.bookmarks())
3654 if bm:
3654 if bm:
3655 output.append(bm)
3655 output.append(bm)
3656 else:
3656 else:
3657 if branch:
3657 if branch:
3658 output.append(ctx.branch())
3658 output.append(ctx.branch())
3659
3659
3660 if tags:
3660 if tags:
3661 output.extend(ctx.tags())
3661 output.extend(ctx.tags())
3662
3662
3663 if bookmarks:
3663 if bookmarks:
3664 output.extend(ctx.bookmarks())
3664 output.extend(ctx.bookmarks())
3665
3665
3666 ui.write("%s\n" % ' '.join(output))
3666 ui.write("%s\n" % ' '.join(output))
3667
3667
3668 @command('import|patch',
3668 @command('import|patch',
3669 [('p', 'strip', 1,
3669 [('p', 'strip', 1,
3670 _('directory strip option for patch. This has the same '
3670 _('directory strip option for patch. This has the same '
3671 'meaning as the corresponding patch option'), _('NUM')),
3671 'meaning as the corresponding patch option'), _('NUM')),
3672 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3672 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3673 ('e', 'edit', False, _('invoke editor on commit messages')),
3673 ('e', 'edit', False, _('invoke editor on commit messages')),
3674 ('f', 'force', None,
3674 ('f', 'force', None,
3675 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3675 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3676 ('', 'no-commit', None,
3676 ('', 'no-commit', None,
3677 _("don't commit, just update the working directory")),
3677 _("don't commit, just update the working directory")),
3678 ('', 'bypass', None,
3678 ('', 'bypass', None,
3679 _("apply patch without touching the working directory")),
3679 _("apply patch without touching the working directory")),
3680 ('', 'exact', None,
3680 ('', 'exact', None,
3681 _('apply patch to the nodes from which it was generated')),
3681 _('apply patch to the nodes from which it was generated')),
3682 ('', 'import-branch', None,
3682 ('', 'import-branch', None,
3683 _('use any branch information in patch (implied by --exact)'))] +
3683 _('use any branch information in patch (implied by --exact)'))] +
3684 commitopts + commitopts2 + similarityopts,
3684 commitopts + commitopts2 + similarityopts,
3685 _('[OPTION]... PATCH...'))
3685 _('[OPTION]... PATCH...'))
3686 def import_(ui, repo, patch1=None, *patches, **opts):
3686 def import_(ui, repo, patch1=None, *patches, **opts):
3687 """import an ordered set of patches
3687 """import an ordered set of patches
3688
3688
3689 Import a list of patches and commit them individually (unless
3689 Import a list of patches and commit them individually (unless
3690 --no-commit is specified).
3690 --no-commit is specified).
3691
3691
3692 Because import first applies changes to the working directory,
3692 Because import first applies changes to the working directory,
3693 import will abort if there are outstanding changes.
3693 import will abort if there are outstanding changes.
3694
3694
3695 You can import a patch straight from a mail message. Even patches
3695 You can import a patch straight from a mail message. Even patches
3696 as attachments work (to use the body part, it must have type
3696 as attachments work (to use the body part, it must have type
3697 text/plain or text/x-patch). From and Subject headers of email
3697 text/plain or text/x-patch). From and Subject headers of email
3698 message are used as default committer and commit message. All
3698 message are used as default committer and commit message. All
3699 text/plain body parts before first diff are added to commit
3699 text/plain body parts before first diff are added to commit
3700 message.
3700 message.
3701
3701
3702 If the imported patch was generated by :hg:`export`, user and
3702 If the imported patch was generated by :hg:`export`, user and
3703 description from patch override values from message headers and
3703 description from patch override values from message headers and
3704 body. Values given on command line with -m/--message and -u/--user
3704 body. Values given on command line with -m/--message and -u/--user
3705 override these.
3705 override these.
3706
3706
3707 If --exact is specified, import will set the working directory to
3707 If --exact is specified, import will set the working directory to
3708 the parent of each patch before applying it, and will abort if the
3708 the parent of each patch before applying it, and will abort if the
3709 resulting changeset has a different ID than the one recorded in
3709 resulting changeset has a different ID than the one recorded in
3710 the patch. This may happen due to character set problems or other
3710 the patch. This may happen due to character set problems or other
3711 deficiencies in the text patch format.
3711 deficiencies in the text patch format.
3712
3712
3713 Use --bypass to apply and commit patches directly to the
3713 Use --bypass to apply and commit patches directly to the
3714 repository, not touching the working directory. Without --exact,
3714 repository, not touching the working directory. Without --exact,
3715 patches will be applied on top of the working directory parent
3715 patches will be applied on top of the working directory parent
3716 revision.
3716 revision.
3717
3717
3718 With -s/--similarity, hg will attempt to discover renames and
3718 With -s/--similarity, hg will attempt to discover renames and
3719 copies in the patch in the same way as :hg:`addremove`.
3719 copies in the patch in the same way as :hg:`addremove`.
3720
3720
3721 To read a patch from standard input, use "-" as the patch name. If
3721 To read a patch from standard input, use "-" as the patch name. If
3722 a URL is specified, the patch will be downloaded from it.
3722 a URL is specified, the patch will be downloaded from it.
3723 See :hg:`help dates` for a list of formats valid for -d/--date.
3723 See :hg:`help dates` for a list of formats valid for -d/--date.
3724
3724
3725 .. container:: verbose
3725 .. container:: verbose
3726
3726
3727 Examples:
3727 Examples:
3728
3728
3729 - import a traditional patch from a website and detect renames::
3729 - import a traditional patch from a website and detect renames::
3730
3730
3731 hg import -s 80 http://example.com/bugfix.patch
3731 hg import -s 80 http://example.com/bugfix.patch
3732
3732
3733 - import a changeset from an hgweb server::
3733 - import a changeset from an hgweb server::
3734
3734
3735 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3735 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3736
3736
3737 - import all the patches in an Unix-style mbox::
3737 - import all the patches in an Unix-style mbox::
3738
3738
3739 hg import incoming-patches.mbox
3739 hg import incoming-patches.mbox
3740
3740
3741 - attempt to exactly restore an exported changeset (not always
3741 - attempt to exactly restore an exported changeset (not always
3742 possible)::
3742 possible)::
3743
3743
3744 hg import --exact proposed-fix.patch
3744 hg import --exact proposed-fix.patch
3745
3745
3746 Returns 0 on success.
3746 Returns 0 on success.
3747 """
3747 """
3748
3748
3749 if not patch1:
3749 if not patch1:
3750 raise util.Abort(_('need at least one patch to import'))
3750 raise util.Abort(_('need at least one patch to import'))
3751
3751
3752 patches = (patch1,) + patches
3752 patches = (patch1,) + patches
3753
3753
3754 date = opts.get('date')
3754 date = opts.get('date')
3755 if date:
3755 if date:
3756 opts['date'] = util.parsedate(date)
3756 opts['date'] = util.parsedate(date)
3757
3757
3758 update = not opts.get('bypass')
3758 update = not opts.get('bypass')
3759 if not update and opts.get('no_commit'):
3759 if not update and opts.get('no_commit'):
3760 raise util.Abort(_('cannot use --no-commit with --bypass'))
3760 raise util.Abort(_('cannot use --no-commit with --bypass'))
3761 try:
3761 try:
3762 sim = float(opts.get('similarity') or 0)
3762 sim = float(opts.get('similarity') or 0)
3763 except ValueError:
3763 except ValueError:
3764 raise util.Abort(_('similarity must be a number'))
3764 raise util.Abort(_('similarity must be a number'))
3765 if sim < 0 or sim > 100:
3765 if sim < 0 or sim > 100:
3766 raise util.Abort(_('similarity must be between 0 and 100'))
3766 raise util.Abort(_('similarity must be between 0 and 100'))
3767 if sim and not update:
3767 if sim and not update:
3768 raise util.Abort(_('cannot use --similarity with --bypass'))
3768 raise util.Abort(_('cannot use --similarity with --bypass'))
3769
3769
3770 if update:
3770 if update:
3771 cmdutil.checkunfinished(repo)
3771 cmdutil.checkunfinished(repo)
3772 if (opts.get('exact') or not opts.get('force')) and update:
3772 if (opts.get('exact') or not opts.get('force')) and update:
3773 cmdutil.bailifchanged(repo)
3773 cmdutil.bailifchanged(repo)
3774
3774
3775 base = opts["base"]
3775 base = opts["base"]
3776 wlock = lock = tr = None
3776 wlock = lock = tr = None
3777 msgs = []
3777 msgs = []
3778
3778
3779
3779
3780 try:
3780 try:
3781 try:
3781 try:
3782 wlock = repo.wlock()
3782 wlock = repo.wlock()
3783 if not opts.get('no_commit'):
3783 if not opts.get('no_commit'):
3784 lock = repo.lock()
3784 lock = repo.lock()
3785 tr = repo.transaction('import')
3785 tr = repo.transaction('import')
3786 parents = repo.parents()
3786 parents = repo.parents()
3787 for patchurl in patches:
3787 for patchurl in patches:
3788 if patchurl == '-':
3788 if patchurl == '-':
3789 ui.status(_('applying patch from stdin\n'))
3789 ui.status(_('applying patch from stdin\n'))
3790 patchfile = ui.fin
3790 patchfile = ui.fin
3791 patchurl = 'stdin' # for error message
3791 patchurl = 'stdin' # for error message
3792 else:
3792 else:
3793 patchurl = os.path.join(base, patchurl)
3793 patchurl = os.path.join(base, patchurl)
3794 ui.status(_('applying %s\n') % patchurl)
3794 ui.status(_('applying %s\n') % patchurl)
3795 patchfile = hg.openpath(ui, patchurl)
3795 patchfile = hg.openpath(ui, patchurl)
3796
3796
3797 haspatch = False
3797 haspatch = False
3798 for hunk in patch.split(patchfile):
3798 for hunk in patch.split(patchfile):
3799 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3799 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3800 opts, msgs, hg.clean)
3800 opts, msgs, hg.clean)
3801 if msg:
3801 if msg:
3802 haspatch = True
3802 haspatch = True
3803 ui.note(msg + '\n')
3803 ui.note(msg + '\n')
3804 if update or opts.get('exact'):
3804 if update or opts.get('exact'):
3805 parents = repo.parents()
3805 parents = repo.parents()
3806 else:
3806 else:
3807 parents = [repo[node]]
3807 parents = [repo[node]]
3808
3808
3809 if not haspatch:
3809 if not haspatch:
3810 raise util.Abort(_('%s: no diffs found') % patchurl)
3810 raise util.Abort(_('%s: no diffs found') % patchurl)
3811
3811
3812 if tr:
3812 if tr:
3813 tr.close()
3813 tr.close()
3814 if msgs:
3814 if msgs:
3815 repo.savecommitmessage('\n* * *\n'.join(msgs))
3815 repo.savecommitmessage('\n* * *\n'.join(msgs))
3816 except: # re-raises
3816 except: # re-raises
3817 # wlock.release() indirectly calls dirstate.write(): since
3817 # wlock.release() indirectly calls dirstate.write(): since
3818 # we're crashing, we do not want to change the working dir
3818 # we're crashing, we do not want to change the working dir
3819 # parent after all, so make sure it writes nothing
3819 # parent after all, so make sure it writes nothing
3820 repo.dirstate.invalidate()
3820 repo.dirstate.invalidate()
3821 raise
3821 raise
3822 finally:
3822 finally:
3823 if tr:
3823 if tr:
3824 tr.release()
3824 tr.release()
3825 release(lock, wlock)
3825 release(lock, wlock)
3826
3826
3827 @command('incoming|in',
3827 @command('incoming|in',
3828 [('f', 'force', None,
3828 [('f', 'force', None,
3829 _('run even if remote repository is unrelated')),
3829 _('run even if remote repository is unrelated')),
3830 ('n', 'newest-first', None, _('show newest record first')),
3830 ('n', 'newest-first', None, _('show newest record first')),
3831 ('', 'bundle', '',
3831 ('', 'bundle', '',
3832 _('file to store the bundles into'), _('FILE')),
3832 _('file to store the bundles into'), _('FILE')),
3833 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3833 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3834 ('B', 'bookmarks', False, _("compare bookmarks")),
3834 ('B', 'bookmarks', False, _("compare bookmarks")),
3835 ('b', 'branch', [],
3835 ('b', 'branch', [],
3836 _('a specific branch you would like to pull'), _('BRANCH')),
3836 _('a specific branch you would like to pull'), _('BRANCH')),
3837 ] + logopts + remoteopts + subrepoopts,
3837 ] + logopts + remoteopts + subrepoopts,
3838 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3838 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3839 def incoming(ui, repo, source="default", **opts):
3839 def incoming(ui, repo, source="default", **opts):
3840 """show new changesets found in source
3840 """show new changesets found in source
3841
3841
3842 Show new changesets found in the specified path/URL or the default
3842 Show new changesets found in the specified path/URL or the default
3843 pull location. These are the changesets that would have been pulled
3843 pull location. These are the changesets that would have been pulled
3844 if a pull at the time you issued this command.
3844 if a pull at the time you issued this command.
3845
3845
3846 For remote repository, using --bundle avoids downloading the
3846 For remote repository, using --bundle avoids downloading the
3847 changesets twice if the incoming is followed by a pull.
3847 changesets twice if the incoming is followed by a pull.
3848
3848
3849 See pull for valid source format details.
3849 See pull for valid source format details.
3850
3850
3851 Returns 0 if there are incoming changes, 1 otherwise.
3851 Returns 0 if there are incoming changes, 1 otherwise.
3852 """
3852 """
3853 if opts.get('graph'):
3853 if opts.get('graph'):
3854 cmdutil.checkunsupportedgraphflags([], opts)
3854 cmdutil.checkunsupportedgraphflags([], opts)
3855 def display(other, chlist, displayer):
3855 def display(other, chlist, displayer):
3856 revdag = cmdutil.graphrevs(other, chlist, opts)
3856 revdag = cmdutil.graphrevs(other, chlist, opts)
3857 showparents = [ctx.node() for ctx in repo[None].parents()]
3857 showparents = [ctx.node() for ctx in repo[None].parents()]
3858 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3858 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3859 graphmod.asciiedges)
3859 graphmod.asciiedges)
3860
3860
3861 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3861 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3862 return 0
3862 return 0
3863
3863
3864 if opts.get('bundle') and opts.get('subrepos'):
3864 if opts.get('bundle') and opts.get('subrepos'):
3865 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3865 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3866
3866
3867 if opts.get('bookmarks'):
3867 if opts.get('bookmarks'):
3868 source, branches = hg.parseurl(ui.expandpath(source),
3868 source, branches = hg.parseurl(ui.expandpath(source),
3869 opts.get('branch'))
3869 opts.get('branch'))
3870 other = hg.peer(repo, opts, source)
3870 other = hg.peer(repo, opts, source)
3871 if 'bookmarks' not in other.listkeys('namespaces'):
3871 if 'bookmarks' not in other.listkeys('namespaces'):
3872 ui.warn(_("remote doesn't support bookmarks\n"))
3872 ui.warn(_("remote doesn't support bookmarks\n"))
3873 return 0
3873 return 0
3874 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3874 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3875 return bookmarks.diff(ui, repo, other)
3875 return bookmarks.diff(ui, repo, other)
3876
3876
3877 repo._subtoppath = ui.expandpath(source)
3877 repo._subtoppath = ui.expandpath(source)
3878 try:
3878 try:
3879 return hg.incoming(ui, repo, source, opts)
3879 return hg.incoming(ui, repo, source, opts)
3880 finally:
3880 finally:
3881 del repo._subtoppath
3881 del repo._subtoppath
3882
3882
3883
3883
3884 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3884 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3885 def init(ui, dest=".", **opts):
3885 def init(ui, dest=".", **opts):
3886 """create a new repository in the given directory
3886 """create a new repository in the given directory
3887
3887
3888 Initialize a new repository in the given directory. If the given
3888 Initialize a new repository in the given directory. If the given
3889 directory does not exist, it will be created.
3889 directory does not exist, it will be created.
3890
3890
3891 If no directory is given, the current directory is used.
3891 If no directory is given, the current directory is used.
3892
3892
3893 It is possible to specify an ``ssh://`` URL as the destination.
3893 It is possible to specify an ``ssh://`` URL as the destination.
3894 See :hg:`help urls` for more information.
3894 See :hg:`help urls` for more information.
3895
3895
3896 Returns 0 on success.
3896 Returns 0 on success.
3897 """
3897 """
3898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3899
3899
3900 @command('locate',
3900 @command('locate',
3901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3904 ] + walkopts,
3904 ] + walkopts,
3905 _('[OPTION]... [PATTERN]...'))
3905 _('[OPTION]... [PATTERN]...'))
3906 def locate(ui, repo, *pats, **opts):
3906 def locate(ui, repo, *pats, **opts):
3907 """locate files matching specific patterns
3907 """locate files matching specific patterns
3908
3908
3909 Print files under Mercurial control in the working directory whose
3909 Print files under Mercurial control in the working directory whose
3910 names match the given patterns.
3910 names match the given patterns.
3911
3911
3912 By default, this command searches all directories in the working
3912 By default, this command searches all directories in the working
3913 directory. To search just the current directory and its
3913 directory. To search just the current directory and its
3914 subdirectories, use "--include .".
3914 subdirectories, use "--include .".
3915
3915
3916 If no patterns are given to match, this command prints the names
3916 If no patterns are given to match, this command prints the names
3917 of all files under Mercurial control in the working directory.
3917 of all files under Mercurial control in the working directory.
3918
3918
3919 If you want to feed the output of this command into the "xargs"
3919 If you want to feed the output of this command into the "xargs"
3920 command, use the -0 option to both this command and "xargs". This
3920 command, use the -0 option to both this command and "xargs". This
3921 will avoid the problem of "xargs" treating single filenames that
3921 will avoid the problem of "xargs" treating single filenames that
3922 contain whitespace as multiple filenames.
3922 contain whitespace as multiple filenames.
3923
3923
3924 Returns 0 if a match is found, 1 otherwise.
3924 Returns 0 if a match is found, 1 otherwise.
3925 """
3925 """
3926 end = opts.get('print0') and '\0' or '\n'
3926 end = opts.get('print0') and '\0' or '\n'
3927 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3927 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3928
3928
3929 ret = 1
3929 ret = 1
3930 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3930 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3931 m.bad = lambda x, y: False
3931 m.bad = lambda x, y: False
3932 for abs in repo[rev].walk(m):
3932 for abs in repo[rev].walk(m):
3933 if not rev and abs not in repo.dirstate:
3933 if not rev and abs not in repo.dirstate:
3934 continue
3934 continue
3935 if opts.get('fullpath'):
3935 if opts.get('fullpath'):
3936 ui.write(repo.wjoin(abs), end)
3936 ui.write(repo.wjoin(abs), end)
3937 else:
3937 else:
3938 ui.write(((pats and m.rel(abs)) or abs), end)
3938 ui.write(((pats and m.rel(abs)) or abs), end)
3939 ret = 0
3939 ret = 0
3940
3940
3941 return ret
3941 return ret
3942
3942
3943 @command('^log|history',
3943 @command('^log|history',
3944 [('f', 'follow', None,
3944 [('f', 'follow', None,
3945 _('follow changeset history, or file history across copies and renames')),
3945 _('follow changeset history, or file history across copies and renames')),
3946 ('', 'follow-first', None,
3946 ('', 'follow-first', None,
3947 _('only follow the first parent of merge changesets (DEPRECATED)')),
3947 _('only follow the first parent of merge changesets (DEPRECATED)')),
3948 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3948 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3949 ('C', 'copies', None, _('show copied files')),
3949 ('C', 'copies', None, _('show copied files')),
3950 ('k', 'keyword', [],
3950 ('k', 'keyword', [],
3951 _('do case-insensitive search for a given text'), _('TEXT')),
3951 _('do case-insensitive search for a given text'), _('TEXT')),
3952 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3952 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3953 ('', 'removed', None, _('include revisions where files were removed')),
3953 ('', 'removed', None, _('include revisions where files were removed')),
3954 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3954 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3955 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3955 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3956 ('', 'only-branch', [],
3956 ('', 'only-branch', [],
3957 _('show only changesets within the given named branch (DEPRECATED)'),
3957 _('show only changesets within the given named branch (DEPRECATED)'),
3958 _('BRANCH')),
3958 _('BRANCH')),
3959 ('b', 'branch', [],
3959 ('b', 'branch', [],
3960 _('show changesets within the given named branch'), _('BRANCH')),
3960 _('show changesets within the given named branch'), _('BRANCH')),
3961 ('P', 'prune', [],
3961 ('P', 'prune', [],
3962 _('do not display revision or any of its ancestors'), _('REV')),
3962 _('do not display revision or any of its ancestors'), _('REV')),
3963 ] + logopts + walkopts,
3963 ] + logopts + walkopts,
3964 _('[OPTION]... [FILE]'))
3964 _('[OPTION]... [FILE]'))
3965 def log(ui, repo, *pats, **opts):
3965 def log(ui, repo, *pats, **opts):
3966 """show revision history of entire repository or files
3966 """show revision history of entire repository or files
3967
3967
3968 Print the revision history of the specified files or the entire
3968 Print the revision history of the specified files or the entire
3969 project.
3969 project.
3970
3970
3971 If no revision range is specified, the default is ``tip:0`` unless
3971 If no revision range is specified, the default is ``tip:0`` unless
3972 --follow is set, in which case the working directory parent is
3972 --follow is set, in which case the working directory parent is
3973 used as the starting revision.
3973 used as the starting revision.
3974
3974
3975 File history is shown without following rename or copy history of
3975 File history is shown without following rename or copy history of
3976 files. Use -f/--follow with a filename to follow history across
3976 files. Use -f/--follow with a filename to follow history across
3977 renames and copies. --follow without a filename will only show
3977 renames and copies. --follow without a filename will only show
3978 ancestors or descendants of the starting revision.
3978 ancestors or descendants of the starting revision.
3979
3979
3980 By default this command prints revision number and changeset id,
3980 By default this command prints revision number and changeset id,
3981 tags, non-trivial parents, user, date and time, and a summary for
3981 tags, non-trivial parents, user, date and time, and a summary for
3982 each commit. When the -v/--verbose switch is used, the list of
3982 each commit. When the -v/--verbose switch is used, the list of
3983 changed files and full commit message are shown.
3983 changed files and full commit message are shown.
3984
3984
3985 With --graph the revisions are shown as an ASCII art DAG with the most
3985 With --graph the revisions are shown as an ASCII art DAG with the most
3986 recent changeset at the top.
3986 recent changeset at the top.
3987 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3987 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3988 and '+' represents a fork where the changeset from the lines below is a
3988 and '+' represents a fork where the changeset from the lines below is a
3989 parent of the 'o' merge on the same same line.
3989 parent of the 'o' merge on the same same line.
3990
3990
3991 .. note::
3991 .. note::
3992
3992
3993 log -p/--patch may generate unexpected diff output for merge
3993 log -p/--patch may generate unexpected diff output for merge
3994 changesets, as it will only compare the merge changeset against
3994 changesets, as it will only compare the merge changeset against
3995 its first parent. Also, only files different from BOTH parents
3995 its first parent. Also, only files different from BOTH parents
3996 will appear in files:.
3996 will appear in files:.
3997
3997
3998 .. note::
3998 .. note::
3999
3999
4000 for performance reasons, log FILE may omit duplicate changes
4000 for performance reasons, log FILE may omit duplicate changes
4001 made on branches and will not show deletions. To see all
4001 made on branches and will not show deletions. To see all
4002 changes including duplicates and deletions, use the --removed
4002 changes including duplicates and deletions, use the --removed
4003 switch.
4003 switch.
4004
4004
4005 .. container:: verbose
4005 .. container:: verbose
4006
4006
4007 Some examples:
4007 Some examples:
4008
4008
4009 - changesets with full descriptions and file lists::
4009 - changesets with full descriptions and file lists::
4010
4010
4011 hg log -v
4011 hg log -v
4012
4012
4013 - changesets ancestral to the working directory::
4013 - changesets ancestral to the working directory::
4014
4014
4015 hg log -f
4015 hg log -f
4016
4016
4017 - last 10 commits on the current branch::
4017 - last 10 commits on the current branch::
4018
4018
4019 hg log -l 10 -b .
4019 hg log -l 10 -b .
4020
4020
4021 - changesets showing all modifications of a file, including removals::
4021 - changesets showing all modifications of a file, including removals::
4022
4022
4023 hg log --removed file.c
4023 hg log --removed file.c
4024
4024
4025 - all changesets that touch a directory, with diffs, excluding merges::
4025 - all changesets that touch a directory, with diffs, excluding merges::
4026
4026
4027 hg log -Mp lib/
4027 hg log -Mp lib/
4028
4028
4029 - all revision numbers that match a keyword::
4029 - all revision numbers that match a keyword::
4030
4030
4031 hg log -k bug --template "{rev}\\n"
4031 hg log -k bug --template "{rev}\\n"
4032
4032
4033 - check if a given changeset is included is a tagged release::
4033 - check if a given changeset is included is a tagged release::
4034
4034
4035 hg log -r "a21ccf and ancestor(1.9)"
4035 hg log -r "a21ccf and ancestor(1.9)"
4036
4036
4037 - find all changesets by some user in a date range::
4037 - find all changesets by some user in a date range::
4038
4038
4039 hg log -k alice -d "may 2008 to jul 2008"
4039 hg log -k alice -d "may 2008 to jul 2008"
4040
4040
4041 - summary of all changesets after the last tag::
4041 - summary of all changesets after the last tag::
4042
4042
4043 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4043 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4044
4044
4045 See :hg:`help dates` for a list of formats valid for -d/--date.
4045 See :hg:`help dates` for a list of formats valid for -d/--date.
4046
4046
4047 See :hg:`help revisions` and :hg:`help revsets` for more about
4047 See :hg:`help revisions` and :hg:`help revsets` for more about
4048 specifying revisions.
4048 specifying revisions.
4049
4049
4050 See :hg:`help templates` for more about pre-packaged styles and
4050 See :hg:`help templates` for more about pre-packaged styles and
4051 specifying custom templates.
4051 specifying custom templates.
4052
4052
4053 Returns 0 on success.
4053 Returns 0 on success.
4054 """
4054 """
4055 if opts.get('graph'):
4055 if opts.get('graph'):
4056 return cmdutil.graphlog(ui, repo, *pats, **opts)
4056 return cmdutil.graphlog(ui, repo, *pats, **opts)
4057
4057
4058 matchfn = scmutil.match(repo[None], pats, opts)
4058 matchfn = scmutil.match(repo[None], pats, opts)
4059 limit = cmdutil.loglimit(opts)
4059 limit = cmdutil.loglimit(opts)
4060 count = 0
4060 count = 0
4061
4061
4062 getrenamed, endrev = None, None
4062 getrenamed, endrev = None, None
4063 if opts.get('copies'):
4063 if opts.get('copies'):
4064 if opts.get('rev'):
4064 if opts.get('rev'):
4065 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4065 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4066 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4066 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4067
4067
4068 df = False
4068 df = False
4069 if opts.get("date"):
4069 if opts.get("date"):
4070 df = util.matchdate(opts["date"])
4070 df = util.matchdate(opts["date"])
4071
4071
4072 branches = opts.get('branch', []) + opts.get('only_branch', [])
4072 branches = opts.get('branch', []) + opts.get('only_branch', [])
4073 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4073 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4074
4074
4075 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4075 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4076 def prep(ctx, fns):
4076 def prep(ctx, fns):
4077 rev = ctx.rev()
4077 rev = ctx.rev()
4078 parents = [p for p in repo.changelog.parentrevs(rev)
4078 parents = [p for p in repo.changelog.parentrevs(rev)
4079 if p != nullrev]
4079 if p != nullrev]
4080 if opts.get('no_merges') and len(parents) == 2:
4080 if opts.get('no_merges') and len(parents) == 2:
4081 return
4081 return
4082 if opts.get('only_merges') and len(parents) != 2:
4082 if opts.get('only_merges') and len(parents) != 2:
4083 return
4083 return
4084 if opts.get('branch') and ctx.branch() not in opts['branch']:
4084 if opts.get('branch') and ctx.branch() not in opts['branch']:
4085 return
4085 return
4086 if df and not df(ctx.date()[0]):
4086 if df and not df(ctx.date()[0]):
4087 return
4087 return
4088
4088
4089 lower = encoding.lower
4089 lower = encoding.lower
4090 if opts.get('user'):
4090 if opts.get('user'):
4091 luser = lower(ctx.user())
4091 luser = lower(ctx.user())
4092 for k in [lower(x) for x in opts['user']]:
4092 for k in [lower(x) for x in opts['user']]:
4093 if (k in luser):
4093 if (k in luser):
4094 break
4094 break
4095 else:
4095 else:
4096 return
4096 return
4097 if opts.get('keyword'):
4097 if opts.get('keyword'):
4098 luser = lower(ctx.user())
4098 luser = lower(ctx.user())
4099 ldesc = lower(ctx.description())
4099 ldesc = lower(ctx.description())
4100 lfiles = lower(" ".join(ctx.files()))
4100 lfiles = lower(" ".join(ctx.files()))
4101 for k in [lower(x) for x in opts['keyword']]:
4101 for k in [lower(x) for x in opts['keyword']]:
4102 if (k in luser or k in ldesc or k in lfiles):
4102 if (k in luser or k in ldesc or k in lfiles):
4103 break
4103 break
4104 else:
4104 else:
4105 return
4105 return
4106
4106
4107 copies = None
4107 copies = None
4108 if getrenamed is not None and rev:
4108 if getrenamed is not None and rev:
4109 copies = []
4109 copies = []
4110 for fn in ctx.files():
4110 for fn in ctx.files():
4111 rename = getrenamed(fn, rev)
4111 rename = getrenamed(fn, rev)
4112 if rename:
4112 if rename:
4113 copies.append((fn, rename[0]))
4113 copies.append((fn, rename[0]))
4114
4114
4115 revmatchfn = None
4115 revmatchfn = None
4116 if opts.get('patch') or opts.get('stat'):
4116 if opts.get('patch') or opts.get('stat'):
4117 if opts.get('follow') or opts.get('follow_first'):
4117 if opts.get('follow') or opts.get('follow_first'):
4118 # note: this might be wrong when following through merges
4118 # note: this might be wrong when following through merges
4119 revmatchfn = scmutil.match(repo[None], fns, default='path')
4119 revmatchfn = scmutil.match(repo[None], fns, default='path')
4120 else:
4120 else:
4121 revmatchfn = matchfn
4121 revmatchfn = matchfn
4122
4122
4123 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4123 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4124
4124
4125 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4125 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4126 if displayer.flush(ctx.rev()):
4126 if displayer.flush(ctx.rev()):
4127 count += 1
4127 count += 1
4128 if count == limit:
4128 if count == limit:
4129 break
4129 break
4130 displayer.close()
4130 displayer.close()
4131
4131
4132 @command('manifest',
4132 @command('manifest',
4133 [('r', 'rev', '', _('revision to display'), _('REV')),
4133 [('r', 'rev', '', _('revision to display'), _('REV')),
4134 ('', 'all', False, _("list files from all revisions"))],
4134 ('', 'all', False, _("list files from all revisions"))],
4135 _('[-r REV]'))
4135 _('[-r REV]'))
4136 def manifest(ui, repo, node=None, rev=None, **opts):
4136 def manifest(ui, repo, node=None, rev=None, **opts):
4137 """output the current or given revision of the project manifest
4137 """output the current or given revision of the project manifest
4138
4138
4139 Print a list of version controlled files for the given revision.
4139 Print a list of version controlled files for the given revision.
4140 If no revision is given, the first parent of the working directory
4140 If no revision is given, the first parent of the working directory
4141 is used, or the null revision if no revision is checked out.
4141 is used, or the null revision if no revision is checked out.
4142
4142
4143 With -v, print file permissions, symlink and executable bits.
4143 With -v, print file permissions, symlink and executable bits.
4144 With --debug, print file revision hashes.
4144 With --debug, print file revision hashes.
4145
4145
4146 If option --all is specified, the list of all files from all revisions
4146 If option --all is specified, the list of all files from all revisions
4147 is printed. This includes deleted and renamed files.
4147 is printed. This includes deleted and renamed files.
4148
4148
4149 Returns 0 on success.
4149 Returns 0 on success.
4150 """
4150 """
4151
4151
4152 fm = ui.formatter('manifest', opts)
4152 fm = ui.formatter('manifest', opts)
4153
4153
4154 if opts.get('all'):
4154 if opts.get('all'):
4155 if rev or node:
4155 if rev or node:
4156 raise util.Abort(_("can't specify a revision with --all"))
4156 raise util.Abort(_("can't specify a revision with --all"))
4157
4157
4158 res = []
4158 res = []
4159 prefix = "data/"
4159 prefix = "data/"
4160 suffix = ".i"
4160 suffix = ".i"
4161 plen = len(prefix)
4161 plen = len(prefix)
4162 slen = len(suffix)
4162 slen = len(suffix)
4163 lock = repo.lock()
4163 lock = repo.lock()
4164 try:
4164 try:
4165 for fn, b, size in repo.store.datafiles():
4165 for fn, b, size in repo.store.datafiles():
4166 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4166 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4167 res.append(fn[plen:-slen])
4167 res.append(fn[plen:-slen])
4168 finally:
4168 finally:
4169 lock.release()
4169 lock.release()
4170 for f in res:
4170 for f in res:
4171 fm.startitem()
4171 fm.startitem()
4172 fm.write("path", '%s\n', f)
4172 fm.write("path", '%s\n', f)
4173 fm.end()
4173 fm.end()
4174 return
4174 return
4175
4175
4176 if rev and node:
4176 if rev and node:
4177 raise util.Abort(_("please specify just one revision"))
4177 raise util.Abort(_("please specify just one revision"))
4178
4178
4179 if not node:
4179 if not node:
4180 node = rev
4180 node = rev
4181
4181
4182 char = {'l': '@', 'x': '*', '': ''}
4182 char = {'l': '@', 'x': '*', '': ''}
4183 mode = {'l': '644', 'x': '755', '': '644'}
4183 mode = {'l': '644', 'x': '755', '': '644'}
4184 ctx = scmutil.revsingle(repo, node)
4184 ctx = scmutil.revsingle(repo, node)
4185 mf = ctx.manifest()
4185 mf = ctx.manifest()
4186 for f in ctx:
4186 for f in ctx:
4187 fm.startitem()
4187 fm.startitem()
4188 fl = ctx[f].flags()
4188 fl = ctx[f].flags()
4189 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4189 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4190 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4190 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4191 fm.write('path', '%s\n', f)
4191 fm.write('path', '%s\n', f)
4192 fm.end()
4192 fm.end()
4193
4193
4194 @command('^merge',
4194 @command('^merge',
4195 [('f', 'force', None,
4195 [('f', 'force', None,
4196 _('force a merge including outstanding changes (DEPRECATED)')),
4196 _('force a merge including outstanding changes (DEPRECATED)')),
4197 ('r', 'rev', '', _('revision to merge'), _('REV')),
4197 ('r', 'rev', '', _('revision to merge'), _('REV')),
4198 ('P', 'preview', None,
4198 ('P', 'preview', None,
4199 _('review revisions to merge (no merge is performed)'))
4199 _('review revisions to merge (no merge is performed)'))
4200 ] + mergetoolopts,
4200 ] + mergetoolopts,
4201 _('[-P] [-f] [[-r] REV]'))
4201 _('[-P] [-f] [[-r] REV]'))
4202 def merge(ui, repo, node=None, **opts):
4202 def merge(ui, repo, node=None, **opts):
4203 """merge working directory with another revision
4203 """merge working directory with another revision
4204
4204
4205 The current working directory is updated with all changes made in
4205 The current working directory is updated with all changes made in
4206 the requested revision since the last common predecessor revision.
4206 the requested revision since the last common predecessor revision.
4207
4207
4208 Files that changed between either parent are marked as changed for
4208 Files that changed between either parent are marked as changed for
4209 the next commit and a commit must be performed before any further
4209 the next commit and a commit must be performed before any further
4210 updates to the repository are allowed. The next commit will have
4210 updates to the repository are allowed. The next commit will have
4211 two parents.
4211 two parents.
4212
4212
4213 ``--tool`` can be used to specify the merge tool used for file
4213 ``--tool`` can be used to specify the merge tool used for file
4214 merges. It overrides the HGMERGE environment variable and your
4214 merges. It overrides the HGMERGE environment variable and your
4215 configuration files. See :hg:`help merge-tools` for options.
4215 configuration files. See :hg:`help merge-tools` for options.
4216
4216
4217 If no revision is specified, the working directory's parent is a
4217 If no revision is specified, the working directory's parent is a
4218 head revision, and the current branch contains exactly one other
4218 head revision, and the current branch contains exactly one other
4219 head, the other head is merged with by default. Otherwise, an
4219 head, the other head is merged with by default. Otherwise, an
4220 explicit revision with which to merge with must be provided.
4220 explicit revision with which to merge with must be provided.
4221
4221
4222 :hg:`resolve` must be used to resolve unresolved files.
4222 :hg:`resolve` must be used to resolve unresolved files.
4223
4223
4224 To undo an uncommitted merge, use :hg:`update --clean .` which
4224 To undo an uncommitted merge, use :hg:`update --clean .` which
4225 will check out a clean copy of the original merge parent, losing
4225 will check out a clean copy of the original merge parent, losing
4226 all changes.
4226 all changes.
4227
4227
4228 Returns 0 on success, 1 if there are unresolved files.
4228 Returns 0 on success, 1 if there are unresolved files.
4229 """
4229 """
4230
4230
4231 if opts.get('rev') and node:
4231 if opts.get('rev') and node:
4232 raise util.Abort(_("please specify just one revision"))
4232 raise util.Abort(_("please specify just one revision"))
4233 if not node:
4233 if not node:
4234 node = opts.get('rev')
4234 node = opts.get('rev')
4235
4235
4236 if node:
4236 if node:
4237 node = scmutil.revsingle(repo, node).node()
4237 node = scmutil.revsingle(repo, node).node()
4238
4238
4239 if not node and repo._bookmarkcurrent:
4239 if not node and repo._bookmarkcurrent:
4240 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4240 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4241 curhead = repo[repo._bookmarkcurrent].node()
4241 curhead = repo[repo._bookmarkcurrent].node()
4242 if len(bmheads) == 2:
4242 if len(bmheads) == 2:
4243 if curhead == bmheads[0]:
4243 if curhead == bmheads[0]:
4244 node = bmheads[1]
4244 node = bmheads[1]
4245 else:
4245 else:
4246 node = bmheads[0]
4246 node = bmheads[0]
4247 elif len(bmheads) > 2:
4247 elif len(bmheads) > 2:
4248 raise util.Abort(_("multiple matching bookmarks to merge - "
4248 raise util.Abort(_("multiple matching bookmarks to merge - "
4249 "please merge with an explicit rev or bookmark"),
4249 "please merge with an explicit rev or bookmark"),
4250 hint=_("run 'hg heads' to see all heads"))
4250 hint=_("run 'hg heads' to see all heads"))
4251 elif len(bmheads) <= 1:
4251 elif len(bmheads) <= 1:
4252 raise util.Abort(_("no matching bookmark to merge - "
4252 raise util.Abort(_("no matching bookmark to merge - "
4253 "please merge with an explicit rev or bookmark"),
4253 "please merge with an explicit rev or bookmark"),
4254 hint=_("run 'hg heads' to see all heads"))
4254 hint=_("run 'hg heads' to see all heads"))
4255
4255
4256 if not node and not repo._bookmarkcurrent:
4256 if not node and not repo._bookmarkcurrent:
4257 branch = repo[None].branch()
4257 branch = repo[None].branch()
4258 bheads = repo.branchheads(branch)
4258 bheads = repo.branchheads(branch)
4259 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4259 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4260
4260
4261 if len(nbhs) > 2:
4261 if len(nbhs) > 2:
4262 raise util.Abort(_("branch '%s' has %d heads - "
4262 raise util.Abort(_("branch '%s' has %d heads - "
4263 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4264 % (branch, len(bheads)),
4264 % (branch, len(bheads)),
4265 hint=_("run 'hg heads .' to see heads"))
4265 hint=_("run 'hg heads .' to see heads"))
4266
4266
4267 parent = repo.dirstate.p1()
4267 parent = repo.dirstate.p1()
4268 if len(nbhs) <= 1:
4268 if len(nbhs) <= 1:
4269 if len(bheads) > 1:
4269 if len(bheads) > 1:
4270 raise util.Abort(_("heads are bookmarked - "
4270 raise util.Abort(_("heads are bookmarked - "
4271 "please merge with an explicit rev"),
4271 "please merge with an explicit rev"),
4272 hint=_("run 'hg heads' to see all heads"))
4272 hint=_("run 'hg heads' to see all heads"))
4273 if len(repo.heads()) > 1:
4273 if len(repo.heads()) > 1:
4274 raise util.Abort(_("branch '%s' has one head - "
4274 raise util.Abort(_("branch '%s' has one head - "
4275 "please merge with an explicit rev")
4275 "please merge with an explicit rev")
4276 % branch,
4276 % branch,
4277 hint=_("run 'hg heads' to see all heads"))
4277 hint=_("run 'hg heads' to see all heads"))
4278 msg, hint = _('nothing to merge'), None
4278 msg, hint = _('nothing to merge'), None
4279 if parent != repo.lookup(branch):
4279 if parent != repo.lookup(branch):
4280 hint = _("use 'hg update' instead")
4280 hint = _("use 'hg update' instead")
4281 raise util.Abort(msg, hint=hint)
4281 raise util.Abort(msg, hint=hint)
4282
4282
4283 if parent not in bheads:
4283 if parent not in bheads:
4284 raise util.Abort(_('working directory not at a head revision'),
4284 raise util.Abort(_('working directory not at a head revision'),
4285 hint=_("use 'hg update' or merge with an "
4285 hint=_("use 'hg update' or merge with an "
4286 "explicit revision"))
4286 "explicit revision"))
4287 if parent == nbhs[0]:
4287 if parent == nbhs[0]:
4288 node = nbhs[-1]
4288 node = nbhs[-1]
4289 else:
4289 else:
4290 node = nbhs[0]
4290 node = nbhs[0]
4291
4291
4292 if opts.get('preview'):
4292 if opts.get('preview'):
4293 # find nodes that are ancestors of p2 but not of p1
4293 # find nodes that are ancestors of p2 but not of p1
4294 p1 = repo.lookup('.')
4294 p1 = repo.lookup('.')
4295 p2 = repo.lookup(node)
4295 p2 = repo.lookup(node)
4296 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4296 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4297
4297
4298 displayer = cmdutil.show_changeset(ui, repo, opts)
4298 displayer = cmdutil.show_changeset(ui, repo, opts)
4299 for node in nodes:
4299 for node in nodes:
4300 displayer.show(repo[node])
4300 displayer.show(repo[node])
4301 displayer.close()
4301 displayer.close()
4302 return 0
4302 return 0
4303
4303
4304 try:
4304 try:
4305 # ui.forcemerge is an internal variable, do not document
4305 # ui.forcemerge is an internal variable, do not document
4306 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4306 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4307 return hg.merge(repo, node, force=opts.get('force'))
4307 return hg.merge(repo, node, force=opts.get('force'))
4308 finally:
4308 finally:
4309 ui.setconfig('ui', 'forcemerge', '')
4309 ui.setconfig('ui', 'forcemerge', '')
4310
4310
4311 @command('outgoing|out',
4311 @command('outgoing|out',
4312 [('f', 'force', None, _('run even when the destination is unrelated')),
4312 [('f', 'force', None, _('run even when the destination is unrelated')),
4313 ('r', 'rev', [],
4313 ('r', 'rev', [],
4314 _('a changeset intended to be included in the destination'), _('REV')),
4314 _('a changeset intended to be included in the destination'), _('REV')),
4315 ('n', 'newest-first', None, _('show newest record first')),
4315 ('n', 'newest-first', None, _('show newest record first')),
4316 ('B', 'bookmarks', False, _('compare bookmarks')),
4316 ('B', 'bookmarks', False, _('compare bookmarks')),
4317 ('b', 'branch', [], _('a specific branch you would like to push'),
4317 ('b', 'branch', [], _('a specific branch you would like to push'),
4318 _('BRANCH')),
4318 _('BRANCH')),
4319 ] + logopts + remoteopts + subrepoopts,
4319 ] + logopts + remoteopts + subrepoopts,
4320 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4320 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4321 def outgoing(ui, repo, dest=None, **opts):
4321 def outgoing(ui, repo, dest=None, **opts):
4322 """show changesets not found in the destination
4322 """show changesets not found in the destination
4323
4323
4324 Show changesets not found in the specified destination repository
4324 Show changesets not found in the specified destination repository
4325 or the default push location. These are the changesets that would
4325 or the default push location. These are the changesets that would
4326 be pushed if a push was requested.
4326 be pushed if a push was requested.
4327
4327
4328 See pull for details of valid destination formats.
4328 See pull for details of valid destination formats.
4329
4329
4330 Returns 0 if there are outgoing changes, 1 otherwise.
4330 Returns 0 if there are outgoing changes, 1 otherwise.
4331 """
4331 """
4332 if opts.get('graph'):
4332 if opts.get('graph'):
4333 cmdutil.checkunsupportedgraphflags([], opts)
4333 cmdutil.checkunsupportedgraphflags([], opts)
4334 o = hg._outgoing(ui, repo, dest, opts)
4334 o = hg._outgoing(ui, repo, dest, opts)
4335 if o is None:
4335 if o is None:
4336 return
4336 return
4337
4337
4338 revdag = cmdutil.graphrevs(repo, o, opts)
4338 revdag = cmdutil.graphrevs(repo, o, opts)
4339 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4339 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4340 showparents = [ctx.node() for ctx in repo[None].parents()]
4340 showparents = [ctx.node() for ctx in repo[None].parents()]
4341 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4341 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4342 graphmod.asciiedges)
4342 graphmod.asciiedges)
4343 return 0
4343 return 0
4344
4344
4345 if opts.get('bookmarks'):
4345 if opts.get('bookmarks'):
4346 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4346 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4347 dest, branches = hg.parseurl(dest, opts.get('branch'))
4347 dest, branches = hg.parseurl(dest, opts.get('branch'))
4348 other = hg.peer(repo, opts, dest)
4348 other = hg.peer(repo, opts, dest)
4349 if 'bookmarks' not in other.listkeys('namespaces'):
4349 if 'bookmarks' not in other.listkeys('namespaces'):
4350 ui.warn(_("remote doesn't support bookmarks\n"))
4350 ui.warn(_("remote doesn't support bookmarks\n"))
4351 return 0
4351 return 0
4352 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4352 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4353 return bookmarks.diff(ui, other, repo)
4353 return bookmarks.diff(ui, other, repo)
4354
4354
4355 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4355 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4356 try:
4356 try:
4357 return hg.outgoing(ui, repo, dest, opts)
4357 return hg.outgoing(ui, repo, dest, opts)
4358 finally:
4358 finally:
4359 del repo._subtoppath
4359 del repo._subtoppath
4360
4360
4361 @command('parents',
4361 @command('parents',
4362 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4362 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4363 ] + templateopts,
4363 ] + templateopts,
4364 _('[-r REV] [FILE]'))
4364 _('[-r REV] [FILE]'))
4365 def parents(ui, repo, file_=None, **opts):
4365 def parents(ui, repo, file_=None, **opts):
4366 """show the parents of the working directory or revision
4366 """show the parents of the working directory or revision
4367
4367
4368 Print the working directory's parent revisions. If a revision is
4368 Print the working directory's parent revisions. If a revision is
4369 given via -r/--rev, the parent of that revision will be printed.
4369 given via -r/--rev, the parent of that revision will be printed.
4370 If a file argument is given, the revision in which the file was
4370 If a file argument is given, the revision in which the file was
4371 last changed (before the working directory revision or the
4371 last changed (before the working directory revision or the
4372 argument to --rev if given) is printed.
4372 argument to --rev if given) is printed.
4373
4373
4374 Returns 0 on success.
4374 Returns 0 on success.
4375 """
4375 """
4376
4376
4377 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4377 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4378
4378
4379 if file_:
4379 if file_:
4380 m = scmutil.match(ctx, (file_,), opts)
4380 m = scmutil.match(ctx, (file_,), opts)
4381 if m.anypats() or len(m.files()) != 1:
4381 if m.anypats() or len(m.files()) != 1:
4382 raise util.Abort(_('can only specify an explicit filename'))
4382 raise util.Abort(_('can only specify an explicit filename'))
4383 file_ = m.files()[0]
4383 file_ = m.files()[0]
4384 filenodes = []
4384 filenodes = []
4385 for cp in ctx.parents():
4385 for cp in ctx.parents():
4386 if not cp:
4386 if not cp:
4387 continue
4387 continue
4388 try:
4388 try:
4389 filenodes.append(cp.filenode(file_))
4389 filenodes.append(cp.filenode(file_))
4390 except error.LookupError:
4390 except error.LookupError:
4391 pass
4391 pass
4392 if not filenodes:
4392 if not filenodes:
4393 raise util.Abort(_("'%s' not found in manifest!") % file_)
4393 raise util.Abort(_("'%s' not found in manifest!") % file_)
4394 p = []
4394 p = []
4395 for fn in filenodes:
4395 for fn in filenodes:
4396 fctx = repo.filectx(file_, fileid=fn)
4396 fctx = repo.filectx(file_, fileid=fn)
4397 p.append(fctx.node())
4397 p.append(fctx.node())
4398 else:
4398 else:
4399 p = [cp.node() for cp in ctx.parents()]
4399 p = [cp.node() for cp in ctx.parents()]
4400
4400
4401 displayer = cmdutil.show_changeset(ui, repo, opts)
4401 displayer = cmdutil.show_changeset(ui, repo, opts)
4402 for n in p:
4402 for n in p:
4403 if n != nullid:
4403 if n != nullid:
4404 displayer.show(repo[n])
4404 displayer.show(repo[n])
4405 displayer.close()
4405 displayer.close()
4406
4406
4407 @command('paths', [], _('[NAME]'))
4407 @command('paths', [], _('[NAME]'))
4408 def paths(ui, repo, search=None):
4408 def paths(ui, repo, search=None):
4409 """show aliases for remote repositories
4409 """show aliases for remote repositories
4410
4410
4411 Show definition of symbolic path name NAME. If no name is given,
4411 Show definition of symbolic path name NAME. If no name is given,
4412 show definition of all available names.
4412 show definition of all available names.
4413
4413
4414 Option -q/--quiet suppresses all output when searching for NAME
4414 Option -q/--quiet suppresses all output when searching for NAME
4415 and shows only the path names when listing all definitions.
4415 and shows only the path names when listing all definitions.
4416
4416
4417 Path names are defined in the [paths] section of your
4417 Path names are defined in the [paths] section of your
4418 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4418 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4419 repository, ``.hg/hgrc`` is used, too.
4419 repository, ``.hg/hgrc`` is used, too.
4420
4420
4421 The path names ``default`` and ``default-push`` have a special
4421 The path names ``default`` and ``default-push`` have a special
4422 meaning. When performing a push or pull operation, they are used
4422 meaning. When performing a push or pull operation, they are used
4423 as fallbacks if no location is specified on the command-line.
4423 as fallbacks if no location is specified on the command-line.
4424 When ``default-push`` is set, it will be used for push and
4424 When ``default-push`` is set, it will be used for push and
4425 ``default`` will be used for pull; otherwise ``default`` is used
4425 ``default`` will be used for pull; otherwise ``default`` is used
4426 as the fallback for both. When cloning a repository, the clone
4426 as the fallback for both. When cloning a repository, the clone
4427 source is written as ``default`` in ``.hg/hgrc``. Note that
4427 source is written as ``default`` in ``.hg/hgrc``. Note that
4428 ``default`` and ``default-push`` apply to all inbound (e.g.
4428 ``default`` and ``default-push`` apply to all inbound (e.g.
4429 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4429 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4430 :hg:`bundle`) operations.
4430 :hg:`bundle`) operations.
4431
4431
4432 See :hg:`help urls` for more information.
4432 See :hg:`help urls` for more information.
4433
4433
4434 Returns 0 on success.
4434 Returns 0 on success.
4435 """
4435 """
4436 if search:
4436 if search:
4437 for name, path in ui.configitems("paths"):
4437 for name, path in ui.configitems("paths"):
4438 if name == search:
4438 if name == search:
4439 ui.status("%s\n" % util.hidepassword(path))
4439 ui.status("%s\n" % util.hidepassword(path))
4440 return
4440 return
4441 if not ui.quiet:
4441 if not ui.quiet:
4442 ui.warn(_("not found!\n"))
4442 ui.warn(_("not found!\n"))
4443 return 1
4443 return 1
4444 else:
4444 else:
4445 for name, path in ui.configitems("paths"):
4445 for name, path in ui.configitems("paths"):
4446 if ui.quiet:
4446 if ui.quiet:
4447 ui.write("%s\n" % name)
4447 ui.write("%s\n" % name)
4448 else:
4448 else:
4449 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4449 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4450
4450
4451 @command('phase',
4451 @command('phase',
4452 [('p', 'public', False, _('set changeset phase to public')),
4452 [('p', 'public', False, _('set changeset phase to public')),
4453 ('d', 'draft', False, _('set changeset phase to draft')),
4453 ('d', 'draft', False, _('set changeset phase to draft')),
4454 ('s', 'secret', False, _('set changeset phase to secret')),
4454 ('s', 'secret', False, _('set changeset phase to secret')),
4455 ('f', 'force', False, _('allow to move boundary backward')),
4455 ('f', 'force', False, _('allow to move boundary backward')),
4456 ('r', 'rev', [], _('target revision'), _('REV')),
4456 ('r', 'rev', [], _('target revision'), _('REV')),
4457 ],
4457 ],
4458 _('[-p|-d|-s] [-f] [-r] REV...'))
4458 _('[-p|-d|-s] [-f] [-r] REV...'))
4459 def phase(ui, repo, *revs, **opts):
4459 def phase(ui, repo, *revs, **opts):
4460 """set or show the current phase name
4460 """set or show the current phase name
4461
4461
4462 With no argument, show the phase name of specified revisions.
4462 With no argument, show the phase name of specified revisions.
4463
4463
4464 With one of -p/--public, -d/--draft or -s/--secret, change the
4464 With one of -p/--public, -d/--draft or -s/--secret, change the
4465 phase value of the specified revisions.
4465 phase value of the specified revisions.
4466
4466
4467 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4467 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4468 lower phase to an higher phase. Phases are ordered as follows::
4468 lower phase to an higher phase. Phases are ordered as follows::
4469
4469
4470 public < draft < secret
4470 public < draft < secret
4471
4471
4472 Returns 0 on success, 1 if no phases were changed or some could not
4472 Returns 0 on success, 1 if no phases were changed or some could not
4473 be changed.
4473 be changed.
4474 """
4474 """
4475 # search for a unique phase argument
4475 # search for a unique phase argument
4476 targetphase = None
4476 targetphase = None
4477 for idx, name in enumerate(phases.phasenames):
4477 for idx, name in enumerate(phases.phasenames):
4478 if opts[name]:
4478 if opts[name]:
4479 if targetphase is not None:
4479 if targetphase is not None:
4480 raise util.Abort(_('only one phase can be specified'))
4480 raise util.Abort(_('only one phase can be specified'))
4481 targetphase = idx
4481 targetphase = idx
4482
4482
4483 # look for specified revision
4483 # look for specified revision
4484 revs = list(revs)
4484 revs = list(revs)
4485 revs.extend(opts['rev'])
4485 revs.extend(opts['rev'])
4486 if not revs:
4486 if not revs:
4487 raise util.Abort(_('no revisions specified'))
4487 raise util.Abort(_('no revisions specified'))
4488
4488
4489 revs = scmutil.revrange(repo, revs)
4489 revs = scmutil.revrange(repo, revs)
4490
4490
4491 lock = None
4491 lock = None
4492 ret = 0
4492 ret = 0
4493 if targetphase is None:
4493 if targetphase is None:
4494 # display
4494 # display
4495 for r in revs:
4495 for r in revs:
4496 ctx = repo[r]
4496 ctx = repo[r]
4497 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4497 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4498 else:
4498 else:
4499 lock = repo.lock()
4499 lock = repo.lock()
4500 try:
4500 try:
4501 # set phase
4501 # set phase
4502 if not revs:
4502 if not revs:
4503 raise util.Abort(_('empty revision set'))
4503 raise util.Abort(_('empty revision set'))
4504 nodes = [repo[r].node() for r in revs]
4504 nodes = [repo[r].node() for r in revs]
4505 olddata = repo._phasecache.getphaserevs(repo)[:]
4505 olddata = repo._phasecache.getphaserevs(repo)[:]
4506 phases.advanceboundary(repo, targetphase, nodes)
4506 phases.advanceboundary(repo, targetphase, nodes)
4507 if opts['force']:
4507 if opts['force']:
4508 phases.retractboundary(repo, targetphase, nodes)
4508 phases.retractboundary(repo, targetphase, nodes)
4509 finally:
4509 finally:
4510 lock.release()
4510 lock.release()
4511 # moving revision from public to draft may hide them
4511 # moving revision from public to draft may hide them
4512 # We have to check result on an unfiltered repository
4512 # We have to check result on an unfiltered repository
4513 unfi = repo.unfiltered()
4513 unfi = repo.unfiltered()
4514 newdata = repo._phasecache.getphaserevs(unfi)
4514 newdata = repo._phasecache.getphaserevs(unfi)
4515 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4515 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4516 cl = unfi.changelog
4516 cl = unfi.changelog
4517 rejected = [n for n in nodes
4517 rejected = [n for n in nodes
4518 if newdata[cl.rev(n)] < targetphase]
4518 if newdata[cl.rev(n)] < targetphase]
4519 if rejected:
4519 if rejected:
4520 ui.warn(_('cannot move %i changesets to a higher '
4520 ui.warn(_('cannot move %i changesets to a higher '
4521 'phase, use --force\n') % len(rejected))
4521 'phase, use --force\n') % len(rejected))
4522 ret = 1
4522 ret = 1
4523 if changes:
4523 if changes:
4524 msg = _('phase changed for %i changesets\n') % changes
4524 msg = _('phase changed for %i changesets\n') % changes
4525 if ret:
4525 if ret:
4526 ui.status(msg)
4526 ui.status(msg)
4527 else:
4527 else:
4528 ui.note(msg)
4528 ui.note(msg)
4529 else:
4529 else:
4530 ui.warn(_('no phases changed\n'))
4530 ui.warn(_('no phases changed\n'))
4531 ret = 1
4531 ret = 1
4532 return ret
4532 return ret
4533
4533
4534 def postincoming(ui, repo, modheads, optupdate, checkout):
4534 def postincoming(ui, repo, modheads, optupdate, checkout):
4535 if modheads == 0:
4535 if modheads == 0:
4536 return
4536 return
4537 if optupdate:
4537 if optupdate:
4538 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4538 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4539 try:
4539 try:
4540 ret = hg.update(repo, checkout)
4540 ret = hg.update(repo, checkout)
4541 except util.Abort, inst:
4541 except util.Abort, inst:
4542 ui.warn(_("not updating: %s\n") % str(inst))
4542 ui.warn(_("not updating: %s\n") % str(inst))
4543 if inst.hint:
4543 if inst.hint:
4544 ui.warn(_("(%s)\n") % inst.hint)
4544 ui.warn(_("(%s)\n") % inst.hint)
4545 return 0
4545 return 0
4546 if not ret and not checkout:
4546 if not ret and not checkout:
4547 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4547 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4548 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4548 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4549 return ret
4549 return ret
4550 if modheads > 1:
4550 if modheads > 1:
4551 currentbranchheads = len(repo.branchheads())
4551 currentbranchheads = len(repo.branchheads())
4552 if currentbranchheads == modheads:
4552 if currentbranchheads == modheads:
4553 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4553 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4554 elif currentbranchheads > 1:
4554 elif currentbranchheads > 1:
4555 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4555 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4556 "merge)\n"))
4556 "merge)\n"))
4557 else:
4557 else:
4558 ui.status(_("(run 'hg heads' to see heads)\n"))
4558 ui.status(_("(run 'hg heads' to see heads)\n"))
4559 else:
4559 else:
4560 ui.status(_("(run 'hg update' to get a working copy)\n"))
4560 ui.status(_("(run 'hg update' to get a working copy)\n"))
4561
4561
4562 @command('^pull',
4562 @command('^pull',
4563 [('u', 'update', None,
4563 [('u', 'update', None,
4564 _('update to new branch head if changesets were pulled')),
4564 _('update to new branch head if changesets were pulled')),
4565 ('f', 'force', None, _('run even when remote repository is unrelated')),
4565 ('f', 'force', None, _('run even when remote repository is unrelated')),
4566 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4566 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4567 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4567 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4568 ('b', 'branch', [], _('a specific branch you would like to pull'),
4568 ('b', 'branch', [], _('a specific branch you would like to pull'),
4569 _('BRANCH')),
4569 _('BRANCH')),
4570 ] + remoteopts,
4570 ] + remoteopts,
4571 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4571 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4572 def pull(ui, repo, source="default", **opts):
4572 def pull(ui, repo, source="default", **opts):
4573 """pull changes from the specified source
4573 """pull changes from the specified source
4574
4574
4575 Pull changes from a remote repository to a local one.
4575 Pull changes from a remote repository to a local one.
4576
4576
4577 This finds all changes from the repository at the specified path
4577 This finds all changes from the repository at the specified path
4578 or URL and adds them to a local repository (the current one unless
4578 or URL and adds them to a local repository (the current one unless
4579 -R is specified). By default, this does not update the copy of the
4579 -R is specified). By default, this does not update the copy of the
4580 project in the working directory.
4580 project in the working directory.
4581
4581
4582 Use :hg:`incoming` if you want to see what would have been added
4582 Use :hg:`incoming` if you want to see what would have been added
4583 by a pull at the time you issued this command. If you then decide
4583 by a pull at the time you issued this command. If you then decide
4584 to add those changes to the repository, you should use :hg:`pull
4584 to add those changes to the repository, you should use :hg:`pull
4585 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4585 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4586
4586
4587 If SOURCE is omitted, the 'default' path will be used.
4587 If SOURCE is omitted, the 'default' path will be used.
4588 See :hg:`help urls` for more information.
4588 See :hg:`help urls` for more information.
4589
4589
4590 Returns 0 on success, 1 if an update had unresolved files.
4590 Returns 0 on success, 1 if an update had unresolved files.
4591 """
4591 """
4592 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4592 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4593 other = hg.peer(repo, opts, source)
4593 other = hg.peer(repo, opts, source)
4594 try:
4594 try:
4595 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4595 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4596 revs, checkout = hg.addbranchrevs(repo, other, branches,
4596 revs, checkout = hg.addbranchrevs(repo, other, branches,
4597 opts.get('rev'))
4597 opts.get('rev'))
4598
4598
4599 remotebookmarks = other.listkeys('bookmarks')
4599 remotebookmarks = other.listkeys('bookmarks')
4600
4600
4601 if opts.get('bookmark'):
4601 if opts.get('bookmark'):
4602 if not revs:
4602 if not revs:
4603 revs = []
4603 revs = []
4604 for b in opts['bookmark']:
4604 for b in opts['bookmark']:
4605 if b not in remotebookmarks:
4605 if b not in remotebookmarks:
4606 raise util.Abort(_('remote bookmark %s not found!') % b)
4606 raise util.Abort(_('remote bookmark %s not found!') % b)
4607 revs.append(remotebookmarks[b])
4607 revs.append(remotebookmarks[b])
4608
4608
4609 if revs:
4609 if revs:
4610 try:
4610 try:
4611 revs = [other.lookup(rev) for rev in revs]
4611 revs = [other.lookup(rev) for rev in revs]
4612 except error.CapabilityError:
4612 except error.CapabilityError:
4613 err = _("other repository doesn't support revision lookup, "
4613 err = _("other repository doesn't support revision lookup, "
4614 "so a rev cannot be specified.")
4614 "so a rev cannot be specified.")
4615 raise util.Abort(err)
4615 raise util.Abort(err)
4616
4616
4617 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4617 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4618 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4618 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4619 if checkout:
4619 if checkout:
4620 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4620 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4621 repo._subtoppath = source
4621 repo._subtoppath = source
4622 try:
4622 try:
4623 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4623 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4624
4624
4625 finally:
4625 finally:
4626 del repo._subtoppath
4626 del repo._subtoppath
4627
4627
4628 # update specified bookmarks
4628 # update specified bookmarks
4629 if opts.get('bookmark'):
4629 if opts.get('bookmark'):
4630 marks = repo._bookmarks
4630 marks = repo._bookmarks
4631 for b in opts['bookmark']:
4631 for b in opts['bookmark']:
4632 # explicit pull overrides local bookmark if any
4632 # explicit pull overrides local bookmark if any
4633 ui.status(_("importing bookmark %s\n") % b)
4633 ui.status(_("importing bookmark %s\n") % b)
4634 marks[b] = repo[remotebookmarks[b]].node()
4634 marks[b] = repo[remotebookmarks[b]].node()
4635 marks.write()
4635 marks.write()
4636 finally:
4636 finally:
4637 other.close()
4637 other.close()
4638 return ret
4638 return ret
4639
4639
4640 @command('^push',
4640 @command('^push',
4641 [('f', 'force', None, _('force push')),
4641 [('f', 'force', None, _('force push')),
4642 ('r', 'rev', [],
4642 ('r', 'rev', [],
4643 _('a changeset intended to be included in the destination'),
4643 _('a changeset intended to be included in the destination'),
4644 _('REV')),
4644 _('REV')),
4645 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4645 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4646 ('b', 'branch', [],
4646 ('b', 'branch', [],
4647 _('a specific branch you would like to push'), _('BRANCH')),
4647 _('a specific branch you would like to push'), _('BRANCH')),
4648 ('', 'new-branch', False, _('allow pushing a new branch')),
4648 ('', 'new-branch', False, _('allow pushing a new branch')),
4649 ] + remoteopts,
4649 ] + remoteopts,
4650 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4650 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4651 def push(ui, repo, dest=None, **opts):
4651 def push(ui, repo, dest=None, **opts):
4652 """push changes to the specified destination
4652 """push changes to the specified destination
4653
4653
4654 Push changesets from the local repository to the specified
4654 Push changesets from the local repository to the specified
4655 destination.
4655 destination.
4656
4656
4657 This operation is symmetrical to pull: it is identical to a pull
4657 This operation is symmetrical to pull: it is identical to a pull
4658 in the destination repository from the current one.
4658 in the destination repository from the current one.
4659
4659
4660 By default, push will not allow creation of new heads at the
4660 By default, push will not allow creation of new heads at the
4661 destination, since multiple heads would make it unclear which head
4661 destination, since multiple heads would make it unclear which head
4662 to use. In this situation, it is recommended to pull and merge
4662 to use. In this situation, it is recommended to pull and merge
4663 before pushing.
4663 before pushing.
4664
4664
4665 Use --new-branch if you want to allow push to create a new named
4665 Use --new-branch if you want to allow push to create a new named
4666 branch that is not present at the destination. This allows you to
4666 branch that is not present at the destination. This allows you to
4667 only create a new branch without forcing other changes.
4667 only create a new branch without forcing other changes.
4668
4668
4669 .. note::
4669 .. note::
4670
4670
4671 Extra care should be taken with the -f/--force option,
4671 Extra care should be taken with the -f/--force option,
4672 which will push all new heads on all branches, an action which will
4672 which will push all new heads on all branches, an action which will
4673 almost always cause confusion for collaborators.
4673 almost always cause confusion for collaborators.
4674
4674
4675 If -r/--rev is used, the specified revision and all its ancestors
4675 If -r/--rev is used, the specified revision and all its ancestors
4676 will be pushed to the remote repository.
4676 will be pushed to the remote repository.
4677
4677
4678 If -B/--bookmark is used, the specified bookmarked revision, its
4678 If -B/--bookmark is used, the specified bookmarked revision, its
4679 ancestors, and the bookmark will be pushed to the remote
4679 ancestors, and the bookmark will be pushed to the remote
4680 repository.
4680 repository.
4681
4681
4682 Please see :hg:`help urls` for important details about ``ssh://``
4682 Please see :hg:`help urls` for important details about ``ssh://``
4683 URLs. If DESTINATION is omitted, a default path will be used.
4683 URLs. If DESTINATION is omitted, a default path will be used.
4684
4684
4685 Returns 0 if push was successful, 1 if nothing to push.
4685 Returns 0 if push was successful, 1 if nothing to push.
4686 """
4686 """
4687
4687
4688 if opts.get('bookmark'):
4688 if opts.get('bookmark'):
4689 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4689 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4690 for b in opts['bookmark']:
4690 for b in opts['bookmark']:
4691 # translate -B options to -r so changesets get pushed
4691 # translate -B options to -r so changesets get pushed
4692 if b in repo._bookmarks:
4692 if b in repo._bookmarks:
4693 opts.setdefault('rev', []).append(b)
4693 opts.setdefault('rev', []).append(b)
4694 else:
4694 else:
4695 # if we try to push a deleted bookmark, translate it to null
4695 # if we try to push a deleted bookmark, translate it to null
4696 # this lets simultaneous -r, -b options continue working
4696 # this lets simultaneous -r, -b options continue working
4697 opts.setdefault('rev', []).append("null")
4697 opts.setdefault('rev', []).append("null")
4698
4698
4699 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4699 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4700 dest, branches = hg.parseurl(dest, opts.get('branch'))
4700 dest, branches = hg.parseurl(dest, opts.get('branch'))
4701 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4701 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4702 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4702 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4703 try:
4703 try:
4704 other = hg.peer(repo, opts, dest)
4704 other = hg.peer(repo, opts, dest)
4705 except error.RepoError:
4705 except error.RepoError:
4706 if dest == "default-push":
4706 if dest == "default-push":
4707 raise util.Abort(_("default repository not configured!"),
4707 raise util.Abort(_("default repository not configured!"),
4708 hint=_('see the "path" section in "hg help config"'))
4708 hint=_('see the "path" section in "hg help config"'))
4709 else:
4709 else:
4710 raise
4710 raise
4711
4711
4712 if revs:
4712 if revs:
4713 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4713 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4714
4714
4715 repo._subtoppath = dest
4715 repo._subtoppath = dest
4716 try:
4716 try:
4717 # push subrepos depth-first for coherent ordering
4717 # push subrepos depth-first for coherent ordering
4718 c = repo['']
4718 c = repo['']
4719 subs = c.substate # only repos that are committed
4719 subs = c.substate # only repos that are committed
4720 for s in sorted(subs):
4720 for s in sorted(subs):
4721 if c.sub(s).push(opts) == 0:
4721 if c.sub(s).push(opts) == 0:
4722 return False
4722 return False
4723 finally:
4723 finally:
4724 del repo._subtoppath
4724 del repo._subtoppath
4725 result = repo.push(other, opts.get('force'), revs=revs,
4725 result = repo.push(other, opts.get('force'), revs=revs,
4726 newbranch=opts.get('new_branch'))
4726 newbranch=opts.get('new_branch'))
4727
4727
4728 result = not result
4728 result = not result
4729
4729
4730 if opts.get('bookmark'):
4730 if opts.get('bookmark'):
4731 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4731 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4732 if bresult == 2:
4732 if bresult == 2:
4733 return 2
4733 return 2
4734 if not result and bresult:
4734 if not result and bresult:
4735 result = 2
4735 result = 2
4736
4736
4737 return result
4737 return result
4738
4738
4739 @command('recover', [])
4739 @command('recover', [])
4740 def recover(ui, repo):
4740 def recover(ui, repo):
4741 """roll back an interrupted transaction
4741 """roll back an interrupted transaction
4742
4742
4743 Recover from an interrupted commit or pull.
4743 Recover from an interrupted commit or pull.
4744
4744
4745 This command tries to fix the repository status after an
4745 This command tries to fix the repository status after an
4746 interrupted operation. It should only be necessary when Mercurial
4746 interrupted operation. It should only be necessary when Mercurial
4747 suggests it.
4747 suggests it.
4748
4748
4749 Returns 0 if successful, 1 if nothing to recover or verify fails.
4749 Returns 0 if successful, 1 if nothing to recover or verify fails.
4750 """
4750 """
4751 if repo.recover():
4751 if repo.recover():
4752 return hg.verify(repo)
4752 return hg.verify(repo)
4753 return 1
4753 return 1
4754
4754
4755 @command('^remove|rm',
4755 @command('^remove|rm',
4756 [('A', 'after', None, _('record delete for missing files')),
4756 [('A', 'after', None, _('record delete for missing files')),
4757 ('f', 'force', None,
4757 ('f', 'force', None,
4758 _('remove (and delete) file even if added or modified')),
4758 _('remove (and delete) file even if added or modified')),
4759 ] + walkopts,
4759 ] + walkopts,
4760 _('[OPTION]... FILE...'))
4760 _('[OPTION]... FILE...'))
4761 def remove(ui, repo, *pats, **opts):
4761 def remove(ui, repo, *pats, **opts):
4762 """remove the specified files on the next commit
4762 """remove the specified files on the next commit
4763
4763
4764 Schedule the indicated files for removal from the current branch.
4764 Schedule the indicated files for removal from the current branch.
4765
4765
4766 This command schedules the files to be removed at the next commit.
4766 This command schedules the files to be removed at the next commit.
4767 To undo a remove before that, see :hg:`revert`. To undo added
4767 To undo a remove before that, see :hg:`revert`. To undo added
4768 files, see :hg:`forget`.
4768 files, see :hg:`forget`.
4769
4769
4770 .. container:: verbose
4770 .. container:: verbose
4771
4771
4772 -A/--after can be used to remove only files that have already
4772 -A/--after can be used to remove only files that have already
4773 been deleted, -f/--force can be used to force deletion, and -Af
4773 been deleted, -f/--force can be used to force deletion, and -Af
4774 can be used to remove files from the next revision without
4774 can be used to remove files from the next revision without
4775 deleting them from the working directory.
4775 deleting them from the working directory.
4776
4776
4777 The following table details the behavior of remove for different
4777 The following table details the behavior of remove for different
4778 file states (columns) and option combinations (rows). The file
4778 file states (columns) and option combinations (rows). The file
4779 states are Added [A], Clean [C], Modified [M] and Missing [!]
4779 states are Added [A], Clean [C], Modified [M] and Missing [!]
4780 (as reported by :hg:`status`). The actions are Warn, Remove
4780 (as reported by :hg:`status`). The actions are Warn, Remove
4781 (from branch) and Delete (from disk):
4781 (from branch) and Delete (from disk):
4782
4782
4783 ========= == == == ==
4783 ========= == == == ==
4784 opt/state A C M !
4784 opt/state A C M !
4785 ========= == == == ==
4785 ========= == == == ==
4786 none W RD W R
4786 none W RD W R
4787 -f R RD RD R
4787 -f R RD RD R
4788 -A W W W R
4788 -A W W W R
4789 -Af R R R R
4789 -Af R R R R
4790 ========= == == == ==
4790 ========= == == == ==
4791
4791
4792 Note that remove never deletes files in Added [A] state from the
4792 Note that remove never deletes files in Added [A] state from the
4793 working directory, not even if option --force is specified.
4793 working directory, not even if option --force is specified.
4794
4794
4795 Returns 0 on success, 1 if any warnings encountered.
4795 Returns 0 on success, 1 if any warnings encountered.
4796 """
4796 """
4797
4797
4798 ret = 0
4798 ret = 0
4799 after, force = opts.get('after'), opts.get('force')
4799 after, force = opts.get('after'), opts.get('force')
4800 if not pats and not after:
4800 if not pats and not after:
4801 raise util.Abort(_('no files specified'))
4801 raise util.Abort(_('no files specified'))
4802
4802
4803 m = scmutil.match(repo[None], pats, opts)
4803 m = scmutil.match(repo[None], pats, opts)
4804 s = repo.status(match=m, clean=True)
4804 s = repo.status(match=m, clean=True)
4805 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4805 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4806
4806
4807 # warn about failure to delete explicit files/dirs
4807 # warn about failure to delete explicit files/dirs
4808 wctx = repo[None]
4808 wctx = repo[None]
4809 for f in m.files():
4809 for f in m.files():
4810 if f in repo.dirstate or f in wctx.dirs():
4810 if f in repo.dirstate or f in wctx.dirs():
4811 continue
4811 continue
4812 if os.path.exists(m.rel(f)):
4812 if os.path.exists(m.rel(f)):
4813 if os.path.isdir(m.rel(f)):
4813 if os.path.isdir(m.rel(f)):
4814 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4814 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4815 else:
4815 else:
4816 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4816 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4817 # missing files will generate a warning elsewhere
4817 # missing files will generate a warning elsewhere
4818 ret = 1
4818 ret = 1
4819
4819
4820 if force:
4820 if force:
4821 list = modified + deleted + clean + added
4821 list = modified + deleted + clean + added
4822 elif after:
4822 elif after:
4823 list = deleted
4823 list = deleted
4824 for f in modified + added + clean:
4824 for f in modified + added + clean:
4825 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4825 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4826 ret = 1
4826 ret = 1
4827 else:
4827 else:
4828 list = deleted + clean
4828 list = deleted + clean
4829 for f in modified:
4829 for f in modified:
4830 ui.warn(_('not removing %s: file is modified (use -f'
4830 ui.warn(_('not removing %s: file is modified (use -f'
4831 ' to force removal)\n') % m.rel(f))
4831 ' to force removal)\n') % m.rel(f))
4832 ret = 1
4832 ret = 1
4833 for f in added:
4833 for f in added:
4834 ui.warn(_('not removing %s: file has been marked for add'
4834 ui.warn(_('not removing %s: file has been marked for add'
4835 ' (use forget to undo)\n') % m.rel(f))
4835 ' (use forget to undo)\n') % m.rel(f))
4836 ret = 1
4836 ret = 1
4837
4837
4838 for f in sorted(list):
4838 for f in sorted(list):
4839 if ui.verbose or not m.exact(f):
4839 if ui.verbose or not m.exact(f):
4840 ui.status(_('removing %s\n') % m.rel(f))
4840 ui.status(_('removing %s\n') % m.rel(f))
4841
4841
4842 wlock = repo.wlock()
4842 wlock = repo.wlock()
4843 try:
4843 try:
4844 if not after:
4844 if not after:
4845 for f in list:
4845 for f in list:
4846 if f in added:
4846 if f in added:
4847 continue # we never unlink added files on remove
4847 continue # we never unlink added files on remove
4848 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4848 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4849 repo[None].forget(list)
4849 repo[None].forget(list)
4850 finally:
4850 finally:
4851 wlock.release()
4851 wlock.release()
4852
4852
4853 return ret
4853 return ret
4854
4854
4855 @command('rename|move|mv',
4855 @command('rename|move|mv',
4856 [('A', 'after', None, _('record a rename that has already occurred')),
4856 [('A', 'after', None, _('record a rename that has already occurred')),
4857 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4857 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4858 ] + walkopts + dryrunopts,
4858 ] + walkopts + dryrunopts,
4859 _('[OPTION]... SOURCE... DEST'))
4859 _('[OPTION]... SOURCE... DEST'))
4860 def rename(ui, repo, *pats, **opts):
4860 def rename(ui, repo, *pats, **opts):
4861 """rename files; equivalent of copy + remove
4861 """rename files; equivalent of copy + remove
4862
4862
4863 Mark dest as copies of sources; mark sources for deletion. If dest
4863 Mark dest as copies of sources; mark sources for deletion. If dest
4864 is a directory, copies are put in that directory. If dest is a
4864 is a directory, copies are put in that directory. If dest is a
4865 file, there can only be one source.
4865 file, there can only be one source.
4866
4866
4867 By default, this command copies the contents of files as they
4867 By default, this command copies the contents of files as they
4868 exist in the working directory. If invoked with -A/--after, the
4868 exist in the working directory. If invoked with -A/--after, the
4869 operation is recorded, but no copying is performed.
4869 operation is recorded, but no copying is performed.
4870
4870
4871 This command takes effect at the next commit. To undo a rename
4871 This command takes effect at the next commit. To undo a rename
4872 before that, see :hg:`revert`.
4872 before that, see :hg:`revert`.
4873
4873
4874 Returns 0 on success, 1 if errors are encountered.
4874 Returns 0 on success, 1 if errors are encountered.
4875 """
4875 """
4876 wlock = repo.wlock(False)
4876 wlock = repo.wlock(False)
4877 try:
4877 try:
4878 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4878 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4879 finally:
4879 finally:
4880 wlock.release()
4880 wlock.release()
4881
4881
4882 @command('resolve',
4882 @command('resolve',
4883 [('a', 'all', None, _('select all unresolved files')),
4883 [('a', 'all', None, _('select all unresolved files')),
4884 ('l', 'list', None, _('list state of files needing merge')),
4884 ('l', 'list', None, _('list state of files needing merge')),
4885 ('m', 'mark', None, _('mark files as resolved')),
4885 ('m', 'mark', None, _('mark files as resolved')),
4886 ('u', 'unmark', None, _('mark files as unresolved')),
4886 ('u', 'unmark', None, _('mark files as unresolved')),
4887 ('n', 'no-status', None, _('hide status prefix'))]
4887 ('n', 'no-status', None, _('hide status prefix'))]
4888 + mergetoolopts + walkopts,
4888 + mergetoolopts + walkopts,
4889 _('[OPTION]... [FILE]...'))
4889 _('[OPTION]... [FILE]...'))
4890 def resolve(ui, repo, *pats, **opts):
4890 def resolve(ui, repo, *pats, **opts):
4891 """redo merges or set/view the merge status of files
4891 """redo merges or set/view the merge status of files
4892
4892
4893 Merges with unresolved conflicts are often the result of
4893 Merges with unresolved conflicts are often the result of
4894 non-interactive merging using the ``internal:merge`` configuration
4894 non-interactive merging using the ``internal:merge`` configuration
4895 setting, or a command-line merge tool like ``diff3``. The resolve
4895 setting, or a command-line merge tool like ``diff3``. The resolve
4896 command is used to manage the files involved in a merge, after
4896 command is used to manage the files involved in a merge, after
4897 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4897 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4898 working directory must have two parents). See :hg:`help
4898 working directory must have two parents). See :hg:`help
4899 merge-tools` for information on configuring merge tools.
4899 merge-tools` for information on configuring merge tools.
4900
4900
4901 The resolve command can be used in the following ways:
4901 The resolve command can be used in the following ways:
4902
4902
4903 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4903 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4904 files, discarding any previous merge attempts. Re-merging is not
4904 files, discarding any previous merge attempts. Re-merging is not
4905 performed for files already marked as resolved. Use ``--all/-a``
4905 performed for files already marked as resolved. Use ``--all/-a``
4906 to select all unresolved files. ``--tool`` can be used to specify
4906 to select all unresolved files. ``--tool`` can be used to specify
4907 the merge tool used for the given files. It overrides the HGMERGE
4907 the merge tool used for the given files. It overrides the HGMERGE
4908 environment variable and your configuration files. Previous file
4908 environment variable and your configuration files. Previous file
4909 contents are saved with a ``.orig`` suffix.
4909 contents are saved with a ``.orig`` suffix.
4910
4910
4911 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4911 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4912 (e.g. after having manually fixed-up the files). The default is
4912 (e.g. after having manually fixed-up the files). The default is
4913 to mark all unresolved files.
4913 to mark all unresolved files.
4914
4914
4915 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4915 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4916 default is to mark all resolved files.
4916 default is to mark all resolved files.
4917
4917
4918 - :hg:`resolve -l`: list files which had or still have conflicts.
4918 - :hg:`resolve -l`: list files which had or still have conflicts.
4919 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4919 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4920
4920
4921 Note that Mercurial will not let you commit files with unresolved
4921 Note that Mercurial will not let you commit files with unresolved
4922 merge conflicts. You must use :hg:`resolve -m ...` before you can
4922 merge conflicts. You must use :hg:`resolve -m ...` before you can
4923 commit after a conflicting merge.
4923 commit after a conflicting merge.
4924
4924
4925 Returns 0 on success, 1 if any files fail a resolve attempt.
4925 Returns 0 on success, 1 if any files fail a resolve attempt.
4926 """
4926 """
4927
4927
4928 all, mark, unmark, show, nostatus = \
4928 all, mark, unmark, show, nostatus = \
4929 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4929 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4930
4930
4931 if (show and (mark or unmark)) or (mark and unmark):
4931 if (show and (mark or unmark)) or (mark and unmark):
4932 raise util.Abort(_("too many options specified"))
4932 raise util.Abort(_("too many options specified"))
4933 if pats and all:
4933 if pats and all:
4934 raise util.Abort(_("can't specify --all and patterns"))
4934 raise util.Abort(_("can't specify --all and patterns"))
4935 if not (all or pats or show or mark or unmark):
4935 if not (all or pats or show or mark or unmark):
4936 raise util.Abort(_('no files or directories specified; '
4936 raise util.Abort(_('no files or directories specified; '
4937 'use --all to remerge all files'))
4937 'use --all to remerge all files'))
4938
4938
4939 ms = mergemod.mergestate(repo)
4939 ms = mergemod.mergestate(repo)
4940 m = scmutil.match(repo[None], pats, opts)
4940 m = scmutil.match(repo[None], pats, opts)
4941 ret = 0
4941 ret = 0
4942
4942
4943 for f in ms:
4943 for f in ms:
4944 if m(f):
4944 if m(f):
4945 if show:
4945 if show:
4946 if nostatus:
4946 if nostatus:
4947 ui.write("%s\n" % f)
4947 ui.write("%s\n" % f)
4948 else:
4948 else:
4949 ui.write("%s %s\n" % (ms[f].upper(), f),
4949 ui.write("%s %s\n" % (ms[f].upper(), f),
4950 label='resolve.' +
4950 label='resolve.' +
4951 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4951 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4952 elif mark:
4952 elif mark:
4953 ms.mark(f, "r")
4953 ms.mark(f, "r")
4954 elif unmark:
4954 elif unmark:
4955 ms.mark(f, "u")
4955 ms.mark(f, "u")
4956 else:
4956 else:
4957 wctx = repo[None]
4957 wctx = repo[None]
4958
4958
4959 # backup pre-resolve (merge uses .orig for its own purposes)
4959 # backup pre-resolve (merge uses .orig for its own purposes)
4960 a = repo.wjoin(f)
4960 a = repo.wjoin(f)
4961 util.copyfile(a, a + ".resolve")
4961 util.copyfile(a, a + ".resolve")
4962
4962
4963 try:
4963 try:
4964 # resolve file
4964 # resolve file
4965 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4965 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4966 if ms.resolve(f, wctx):
4966 if ms.resolve(f, wctx):
4967 ret = 1
4967 ret = 1
4968 finally:
4968 finally:
4969 ui.setconfig('ui', 'forcemerge', '')
4969 ui.setconfig('ui', 'forcemerge', '')
4970 ms.commit()
4970 ms.commit()
4971
4971
4972 # replace filemerge's .orig file with our resolve file
4972 # replace filemerge's .orig file with our resolve file
4973 util.rename(a + ".resolve", a + ".orig")
4973 util.rename(a + ".resolve", a + ".orig")
4974
4974
4975 ms.commit()
4975 ms.commit()
4976 return ret
4976 return ret
4977
4977
4978 @command('revert',
4978 @command('revert',
4979 [('a', 'all', None, _('revert all changes when no arguments given')),
4979 [('a', 'all', None, _('revert all changes when no arguments given')),
4980 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4980 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4981 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4981 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4982 ('C', 'no-backup', None, _('do not save backup copies of files')),
4982 ('C', 'no-backup', None, _('do not save backup copies of files')),
4983 ] + walkopts + dryrunopts,
4983 ] + walkopts + dryrunopts,
4984 _('[OPTION]... [-r REV] [NAME]...'))
4984 _('[OPTION]... [-r REV] [NAME]...'))
4985 def revert(ui, repo, *pats, **opts):
4985 def revert(ui, repo, *pats, **opts):
4986 """restore files to their checkout state
4986 """restore files to their checkout state
4987
4987
4988 .. note::
4988 .. note::
4989
4989
4990 To check out earlier revisions, you should use :hg:`update REV`.
4990 To check out earlier revisions, you should use :hg:`update REV`.
4991 To cancel an uncommitted merge (and lose your changes),
4991 To cancel an uncommitted merge (and lose your changes),
4992 use :hg:`update --clean .`.
4992 use :hg:`update --clean .`.
4993
4993
4994 With no revision specified, revert the specified files or directories
4994 With no revision specified, revert the specified files or directories
4995 to the contents they had in the parent of the working directory.
4995 to the contents they had in the parent of the working directory.
4996 This restores the contents of files to an unmodified
4996 This restores the contents of files to an unmodified
4997 state and unschedules adds, removes, copies, and renames. If the
4997 state and unschedules adds, removes, copies, and renames. If the
4998 working directory has two parents, you must explicitly specify a
4998 working directory has two parents, you must explicitly specify a
4999 revision.
4999 revision.
5000
5000
5001 Using the -r/--rev or -d/--date options, revert the given files or
5001 Using the -r/--rev or -d/--date options, revert the given files or
5002 directories to their states as of a specific revision. Because
5002 directories to their states as of a specific revision. Because
5003 revert does not change the working directory parents, this will
5003 revert does not change the working directory parents, this will
5004 cause these files to appear modified. This can be helpful to "back
5004 cause these files to appear modified. This can be helpful to "back
5005 out" some or all of an earlier change. See :hg:`backout` for a
5005 out" some or all of an earlier change. See :hg:`backout` for a
5006 related method.
5006 related method.
5007
5007
5008 Modified files are saved with a .orig suffix before reverting.
5008 Modified files are saved with a .orig suffix before reverting.
5009 To disable these backups, use --no-backup.
5009 To disable these backups, use --no-backup.
5010
5010
5011 See :hg:`help dates` for a list of formats valid for -d/--date.
5011 See :hg:`help dates` for a list of formats valid for -d/--date.
5012
5012
5013 Returns 0 on success.
5013 Returns 0 on success.
5014 """
5014 """
5015
5015
5016 if opts.get("date"):
5016 if opts.get("date"):
5017 if opts.get("rev"):
5017 if opts.get("rev"):
5018 raise util.Abort(_("you can't specify a revision and a date"))
5018 raise util.Abort(_("you can't specify a revision and a date"))
5019 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5019 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5020
5020
5021 parent, p2 = repo.dirstate.parents()
5021 parent, p2 = repo.dirstate.parents()
5022 if not opts.get('rev') and p2 != nullid:
5022 if not opts.get('rev') and p2 != nullid:
5023 # revert after merge is a trap for new users (issue2915)
5023 # revert after merge is a trap for new users (issue2915)
5024 raise util.Abort(_('uncommitted merge with no revision specified'),
5024 raise util.Abort(_('uncommitted merge with no revision specified'),
5025 hint=_('use "hg update" or see "hg help revert"'))
5025 hint=_('use "hg update" or see "hg help revert"'))
5026
5026
5027 ctx = scmutil.revsingle(repo, opts.get('rev'))
5027 ctx = scmutil.revsingle(repo, opts.get('rev'))
5028
5028
5029 if not pats and not opts.get('all'):
5029 if not pats and not opts.get('all'):
5030 msg = _("no files or directories specified")
5030 msg = _("no files or directories specified")
5031 if p2 != nullid:
5031 if p2 != nullid:
5032 hint = _("uncommitted merge, use --all to discard all changes,"
5032 hint = _("uncommitted merge, use --all to discard all changes,"
5033 " or 'hg update -C .' to abort the merge")
5033 " or 'hg update -C .' to abort the merge")
5034 raise util.Abort(msg, hint=hint)
5034 raise util.Abort(msg, hint=hint)
5035 dirty = util.any(repo.status())
5035 dirty = util.any(repo.status())
5036 node = ctx.node()
5036 node = ctx.node()
5037 if node != parent:
5037 if node != parent:
5038 if dirty:
5038 if dirty:
5039 hint = _("uncommitted changes, use --all to discard all"
5039 hint = _("uncommitted changes, use --all to discard all"
5040 " changes, or 'hg update %s' to update") % ctx.rev()
5040 " changes, or 'hg update %s' to update") % ctx.rev()
5041 else:
5041 else:
5042 hint = _("use --all to revert all files,"
5042 hint = _("use --all to revert all files,"
5043 " or 'hg update %s' to update") % ctx.rev()
5043 " or 'hg update %s' to update") % ctx.rev()
5044 elif dirty:
5044 elif dirty:
5045 hint = _("uncommitted changes, use --all to discard all changes")
5045 hint = _("uncommitted changes, use --all to discard all changes")
5046 else:
5046 else:
5047 hint = _("use --all to revert all files")
5047 hint = _("use --all to revert all files")
5048 raise util.Abort(msg, hint=hint)
5048 raise util.Abort(msg, hint=hint)
5049
5049
5050 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5050 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5051
5051
5052 @command('rollback', dryrunopts +
5052 @command('rollback', dryrunopts +
5053 [('f', 'force', False, _('ignore safety measures'))])
5053 [('f', 'force', False, _('ignore safety measures'))])
5054 def rollback(ui, repo, **opts):
5054 def rollback(ui, repo, **opts):
5055 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5055 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5056
5056
5057 Please use :hg:`commit --amend` instead of rollback to correct
5057 Please use :hg:`commit --amend` instead of rollback to correct
5058 mistakes in the last commit.
5058 mistakes in the last commit.
5059
5059
5060 This command should be used with care. There is only one level of
5060 This command should be used with care. There is only one level of
5061 rollback, and there is no way to undo a rollback. It will also
5061 rollback, and there is no way to undo a rollback. It will also
5062 restore the dirstate at the time of the last transaction, losing
5062 restore the dirstate at the time of the last transaction, losing
5063 any dirstate changes since that time. This command does not alter
5063 any dirstate changes since that time. This command does not alter
5064 the working directory.
5064 the working directory.
5065
5065
5066 Transactions are used to encapsulate the effects of all commands
5066 Transactions are used to encapsulate the effects of all commands
5067 that create new changesets or propagate existing changesets into a
5067 that create new changesets or propagate existing changesets into a
5068 repository.
5068 repository.
5069
5069
5070 .. container:: verbose
5070 .. container:: verbose
5071
5071
5072 For example, the following commands are transactional, and their
5072 For example, the following commands are transactional, and their
5073 effects can be rolled back:
5073 effects can be rolled back:
5074
5074
5075 - commit
5075 - commit
5076 - import
5076 - import
5077 - pull
5077 - pull
5078 - push (with this repository as the destination)
5078 - push (with this repository as the destination)
5079 - unbundle
5079 - unbundle
5080
5080
5081 To avoid permanent data loss, rollback will refuse to rollback a
5081 To avoid permanent data loss, rollback will refuse to rollback a
5082 commit transaction if it isn't checked out. Use --force to
5082 commit transaction if it isn't checked out. Use --force to
5083 override this protection.
5083 override this protection.
5084
5084
5085 This command is not intended for use on public repositories. Once
5085 This command is not intended for use on public repositories. Once
5086 changes are visible for pull by other users, rolling a transaction
5086 changes are visible for pull by other users, rolling a transaction
5087 back locally is ineffective (someone else may already have pulled
5087 back locally is ineffective (someone else may already have pulled
5088 the changes). Furthermore, a race is possible with readers of the
5088 the changes). Furthermore, a race is possible with readers of the
5089 repository; for example an in-progress pull from the repository
5089 repository; for example an in-progress pull from the repository
5090 may fail if a rollback is performed.
5090 may fail if a rollback is performed.
5091
5091
5092 Returns 0 on success, 1 if no rollback data is available.
5092 Returns 0 on success, 1 if no rollback data is available.
5093 """
5093 """
5094 return repo.rollback(dryrun=opts.get('dry_run'),
5094 return repo.rollback(dryrun=opts.get('dry_run'),
5095 force=opts.get('force'))
5095 force=opts.get('force'))
5096
5096
5097 @command('root', [])
5097 @command('root', [])
5098 def root(ui, repo):
5098 def root(ui, repo):
5099 """print the root (top) of the current working directory
5099 """print the root (top) of the current working directory
5100
5100
5101 Print the root directory of the current repository.
5101 Print the root directory of the current repository.
5102
5102
5103 Returns 0 on success.
5103 Returns 0 on success.
5104 """
5104 """
5105 ui.write(repo.root + "\n")
5105 ui.write(repo.root + "\n")
5106
5106
5107 @command('^serve',
5107 @command('^serve',
5108 [('A', 'accesslog', '', _('name of access log file to write to'),
5108 [('A', 'accesslog', '', _('name of access log file to write to'),
5109 _('FILE')),
5109 _('FILE')),
5110 ('d', 'daemon', None, _('run server in background')),
5110 ('d', 'daemon', None, _('run server in background')),
5111 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5111 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5112 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5112 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5113 # use string type, then we can check if something was passed
5113 # use string type, then we can check if something was passed
5114 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5114 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5115 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5115 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5116 _('ADDR')),
5116 _('ADDR')),
5117 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5117 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5118 _('PREFIX')),
5118 _('PREFIX')),
5119 ('n', 'name', '',
5119 ('n', 'name', '',
5120 _('name to show in web pages (default: working directory)'), _('NAME')),
5120 _('name to show in web pages (default: working directory)'), _('NAME')),
5121 ('', 'web-conf', '',
5121 ('', 'web-conf', '',
5122 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5122 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5123 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5123 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5124 _('FILE')),
5124 _('FILE')),
5125 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5125 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5126 ('', 'stdio', None, _('for remote clients')),
5126 ('', 'stdio', None, _('for remote clients')),
5127 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5127 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5128 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5128 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5129 ('', 'style', '', _('template style to use'), _('STYLE')),
5129 ('', 'style', '', _('template style to use'), _('STYLE')),
5130 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5130 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5131 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5131 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5132 _('[OPTION]...'))
5132 _('[OPTION]...'))
5133 def serve(ui, repo, **opts):
5133 def serve(ui, repo, **opts):
5134 """start stand-alone webserver
5134 """start stand-alone webserver
5135
5135
5136 Start a local HTTP repository browser and pull server. You can use
5136 Start a local HTTP repository browser and pull server. You can use
5137 this for ad-hoc sharing and browsing of repositories. It is
5137 this for ad-hoc sharing and browsing of repositories. It is
5138 recommended to use a real web server to serve a repository for
5138 recommended to use a real web server to serve a repository for
5139 longer periods of time.
5139 longer periods of time.
5140
5140
5141 Please note that the server does not implement access control.
5141 Please note that the server does not implement access control.
5142 This means that, by default, anybody can read from the server and
5142 This means that, by default, anybody can read from the server and
5143 nobody can write to it by default. Set the ``web.allow_push``
5143 nobody can write to it by default. Set the ``web.allow_push``
5144 option to ``*`` to allow everybody to push to the server. You
5144 option to ``*`` to allow everybody to push to the server. You
5145 should use a real web server if you need to authenticate users.
5145 should use a real web server if you need to authenticate users.
5146
5146
5147 By default, the server logs accesses to stdout and errors to
5147 By default, the server logs accesses to stdout and errors to
5148 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5148 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5149 files.
5149 files.
5150
5150
5151 To have the server choose a free port number to listen on, specify
5151 To have the server choose a free port number to listen on, specify
5152 a port number of 0; in this case, the server will print the port
5152 a port number of 0; in this case, the server will print the port
5153 number it uses.
5153 number it uses.
5154
5154
5155 Returns 0 on success.
5155 Returns 0 on success.
5156 """
5156 """
5157
5157
5158 if opts["stdio"] and opts["cmdserver"]:
5158 if opts["stdio"] and opts["cmdserver"]:
5159 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5159 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5160
5160
5161 def checkrepo():
5161 def checkrepo():
5162 if repo is None:
5162 if repo is None:
5163 raise error.RepoError(_("there is no Mercurial repository here"
5163 raise error.RepoError(_("there is no Mercurial repository here"
5164 " (.hg not found)"))
5164 " (.hg not found)"))
5165
5165
5166 if opts["stdio"]:
5166 if opts["stdio"]:
5167 checkrepo()
5167 checkrepo()
5168 s = sshserver.sshserver(ui, repo)
5168 s = sshserver.sshserver(ui, repo)
5169 s.serve_forever()
5169 s.serve_forever()
5170
5170
5171 if opts["cmdserver"]:
5171 if opts["cmdserver"]:
5172 s = commandserver.server(ui, repo, opts["cmdserver"])
5172 s = commandserver.server(ui, repo, opts["cmdserver"])
5173 return s.serve()
5173 return s.serve()
5174
5174
5175 # this way we can check if something was given in the command-line
5175 # this way we can check if something was given in the command-line
5176 if opts.get('port'):
5176 if opts.get('port'):
5177 opts['port'] = util.getport(opts.get('port'))
5177 opts['port'] = util.getport(opts.get('port'))
5178
5178
5179 baseui = repo and repo.baseui or ui
5179 baseui = repo and repo.baseui or ui
5180 optlist = ("name templates style address port prefix ipv6"
5180 optlist = ("name templates style address port prefix ipv6"
5181 " accesslog errorlog certificate encoding")
5181 " accesslog errorlog certificate encoding")
5182 for o in optlist.split():
5182 for o in optlist.split():
5183 val = opts.get(o, '')
5183 val = opts.get(o, '')
5184 if val in (None, ''): # should check against default options instead
5184 if val in (None, ''): # should check against default options instead
5185 continue
5185 continue
5186 baseui.setconfig("web", o, val)
5186 baseui.setconfig("web", o, val)
5187 if repo and repo.ui != baseui:
5187 if repo and repo.ui != baseui:
5188 repo.ui.setconfig("web", o, val)
5188 repo.ui.setconfig("web", o, val)
5189
5189
5190 o = opts.get('web_conf') or opts.get('webdir_conf')
5190 o = opts.get('web_conf') or opts.get('webdir_conf')
5191 if not o:
5191 if not o:
5192 if not repo:
5192 if not repo:
5193 raise error.RepoError(_("there is no Mercurial repository"
5193 raise error.RepoError(_("there is no Mercurial repository"
5194 " here (.hg not found)"))
5194 " here (.hg not found)"))
5195 o = repo
5195 o = repo
5196
5196
5197 app = hgweb.hgweb(o, baseui=baseui)
5197 app = hgweb.hgweb(o, baseui=baseui)
5198 service = httpservice(ui, app, opts)
5198 service = httpservice(ui, app, opts)
5199 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5199 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5200
5200
5201 class httpservice(object):
5201 class httpservice(object):
5202 def __init__(self, ui, app, opts):
5202 def __init__(self, ui, app, opts):
5203 self.ui = ui
5203 self.ui = ui
5204 self.app = app
5204 self.app = app
5205 self.opts = opts
5205 self.opts = opts
5206
5206
5207 def init(self):
5207 def init(self):
5208 util.setsignalhandler()
5208 util.setsignalhandler()
5209 self.httpd = hgweb_server.create_server(self.ui, self.app)
5209 self.httpd = hgweb_server.create_server(self.ui, self.app)
5210
5210
5211 if self.opts['port'] and not self.ui.verbose:
5211 if self.opts['port'] and not self.ui.verbose:
5212 return
5212 return
5213
5213
5214 if self.httpd.prefix:
5214 if self.httpd.prefix:
5215 prefix = self.httpd.prefix.strip('/') + '/'
5215 prefix = self.httpd.prefix.strip('/') + '/'
5216 else:
5216 else:
5217 prefix = ''
5217 prefix = ''
5218
5218
5219 port = ':%d' % self.httpd.port
5219 port = ':%d' % self.httpd.port
5220 if port == ':80':
5220 if port == ':80':
5221 port = ''
5221 port = ''
5222
5222
5223 bindaddr = self.httpd.addr
5223 bindaddr = self.httpd.addr
5224 if bindaddr == '0.0.0.0':
5224 if bindaddr == '0.0.0.0':
5225 bindaddr = '*'
5225 bindaddr = '*'
5226 elif ':' in bindaddr: # IPv6
5226 elif ':' in bindaddr: # IPv6
5227 bindaddr = '[%s]' % bindaddr
5227 bindaddr = '[%s]' % bindaddr
5228
5228
5229 fqaddr = self.httpd.fqaddr
5229 fqaddr = self.httpd.fqaddr
5230 if ':' in fqaddr:
5230 if ':' in fqaddr:
5231 fqaddr = '[%s]' % fqaddr
5231 fqaddr = '[%s]' % fqaddr
5232 if self.opts['port']:
5232 if self.opts['port']:
5233 write = self.ui.status
5233 write = self.ui.status
5234 else:
5234 else:
5235 write = self.ui.write
5235 write = self.ui.write
5236 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5236 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5237 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5237 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5238
5238
5239 def run(self):
5239 def run(self):
5240 self.httpd.serve_forever()
5240 self.httpd.serve_forever()
5241
5241
5242
5242
5243 @command('^status|st',
5243 @command('^status|st',
5244 [('A', 'all', None, _('show status of all files')),
5244 [('A', 'all', None, _('show status of all files')),
5245 ('m', 'modified', None, _('show only modified files')),
5245 ('m', 'modified', None, _('show only modified files')),
5246 ('a', 'added', None, _('show only added files')),
5246 ('a', 'added', None, _('show only added files')),
5247 ('r', 'removed', None, _('show only removed files')),
5247 ('r', 'removed', None, _('show only removed files')),
5248 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5248 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5249 ('c', 'clean', None, _('show only files without changes')),
5249 ('c', 'clean', None, _('show only files without changes')),
5250 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5250 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5251 ('i', 'ignored', None, _('show only ignored files')),
5251 ('i', 'ignored', None, _('show only ignored files')),
5252 ('n', 'no-status', None, _('hide status prefix')),
5252 ('n', 'no-status', None, _('hide status prefix')),
5253 ('C', 'copies', None, _('show source of copied files')),
5253 ('C', 'copies', None, _('show source of copied files')),
5254 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5254 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5255 ('', 'rev', [], _('show difference from revision'), _('REV')),
5255 ('', 'rev', [], _('show difference from revision'), _('REV')),
5256 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5256 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5257 ] + walkopts + subrepoopts,
5257 ] + walkopts + subrepoopts,
5258 _('[OPTION]... [FILE]...'))
5258 _('[OPTION]... [FILE]...'))
5259 def status(ui, repo, *pats, **opts):
5259 def status(ui, repo, *pats, **opts):
5260 """show changed files in the working directory
5260 """show changed files in the working directory
5261
5261
5262 Show status of files in the repository. If names are given, only
5262 Show status of files in the repository. If names are given, only
5263 files that match are shown. Files that are clean or ignored or
5263 files that match are shown. Files that are clean or ignored or
5264 the source of a copy/move operation, are not listed unless
5264 the source of a copy/move operation, are not listed unless
5265 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5265 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5266 Unless options described with "show only ..." are given, the
5266 Unless options described with "show only ..." are given, the
5267 options -mardu are used.
5267 options -mardu are used.
5268
5268
5269 Option -q/--quiet hides untracked (unknown and ignored) files
5269 Option -q/--quiet hides untracked (unknown and ignored) files
5270 unless explicitly requested with -u/--unknown or -i/--ignored.
5270 unless explicitly requested with -u/--unknown or -i/--ignored.
5271
5271
5272 .. note::
5272 .. note::
5273
5273
5274 status may appear to disagree with diff if permissions have
5274 status may appear to disagree with diff if permissions have
5275 changed or a merge has occurred. The standard diff format does
5275 changed or a merge has occurred. The standard diff format does
5276 not report permission changes and diff only reports changes
5276 not report permission changes and diff only reports changes
5277 relative to one merge parent.
5277 relative to one merge parent.
5278
5278
5279 If one revision is given, it is used as the base revision.
5279 If one revision is given, it is used as the base revision.
5280 If two revisions are given, the differences between them are
5280 If two revisions are given, the differences between them are
5281 shown. The --change option can also be used as a shortcut to list
5281 shown. The --change option can also be used as a shortcut to list
5282 the changed files of a revision from its first parent.
5282 the changed files of a revision from its first parent.
5283
5283
5284 The codes used to show the status of files are::
5284 The codes used to show the status of files are::
5285
5285
5286 M = modified
5286 M = modified
5287 A = added
5287 A = added
5288 R = removed
5288 R = removed
5289 C = clean
5289 C = clean
5290 ! = missing (deleted by non-hg command, but still tracked)
5290 ! = missing (deleted by non-hg command, but still tracked)
5291 ? = not tracked
5291 ? = not tracked
5292 I = ignored
5292 I = ignored
5293 = origin of the previous file (with --copies)
5293 = origin of the previous file (with --copies)
5294
5294
5295 .. container:: verbose
5295 .. container:: verbose
5296
5296
5297 Examples:
5297 Examples:
5298
5298
5299 - show changes in the working directory relative to a
5299 - show changes in the working directory relative to a
5300 changeset::
5300 changeset::
5301
5301
5302 hg status --rev 9353
5302 hg status --rev 9353
5303
5303
5304 - show all changes including copies in an existing changeset::
5304 - show all changes including copies in an existing changeset::
5305
5305
5306 hg status --copies --change 9353
5306 hg status --copies --change 9353
5307
5307
5308 - get a NUL separated list of added files, suitable for xargs::
5308 - get a NUL separated list of added files, suitable for xargs::
5309
5309
5310 hg status -an0
5310 hg status -an0
5311
5311
5312 Returns 0 on success.
5312 Returns 0 on success.
5313 """
5313 """
5314
5314
5315 revs = opts.get('rev')
5315 revs = opts.get('rev')
5316 change = opts.get('change')
5316 change = opts.get('change')
5317
5317
5318 if revs and change:
5318 if revs and change:
5319 msg = _('cannot specify --rev and --change at the same time')
5319 msg = _('cannot specify --rev and --change at the same time')
5320 raise util.Abort(msg)
5320 raise util.Abort(msg)
5321 elif change:
5321 elif change:
5322 node2 = scmutil.revsingle(repo, change, None).node()
5322 node2 = scmutil.revsingle(repo, change, None).node()
5323 node1 = repo[node2].p1().node()
5323 node1 = repo[node2].p1().node()
5324 else:
5324 else:
5325 node1, node2 = scmutil.revpair(repo, revs)
5325 node1, node2 = scmutil.revpair(repo, revs)
5326
5326
5327 cwd = (pats and repo.getcwd()) or ''
5327 cwd = (pats and repo.getcwd()) or ''
5328 end = opts.get('print0') and '\0' or '\n'
5328 end = opts.get('print0') and '\0' or '\n'
5329 copy = {}
5329 copy = {}
5330 states = 'modified added removed deleted unknown ignored clean'.split()
5330 states = 'modified added removed deleted unknown ignored clean'.split()
5331 show = [k for k in states if opts.get(k)]
5331 show = [k for k in states if opts.get(k)]
5332 if opts.get('all'):
5332 if opts.get('all'):
5333 show += ui.quiet and (states[:4] + ['clean']) or states
5333 show += ui.quiet and (states[:4] + ['clean']) or states
5334 if not show:
5334 if not show:
5335 show = ui.quiet and states[:4] or states[:5]
5335 show = ui.quiet and states[:4] or states[:5]
5336
5336
5337 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5337 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5338 'ignored' in show, 'clean' in show, 'unknown' in show,
5338 'ignored' in show, 'clean' in show, 'unknown' in show,
5339 opts.get('subrepos'))
5339 opts.get('subrepos'))
5340 changestates = zip(states, 'MAR!?IC', stat)
5340 changestates = zip(states, 'MAR!?IC', stat)
5341
5341
5342 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5342 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5343 copy = copies.pathcopies(repo[node1], repo[node2])
5343 copy = copies.pathcopies(repo[node1], repo[node2])
5344
5344
5345 fm = ui.formatter('status', opts)
5345 fm = ui.formatter('status', opts)
5346 fmt = '%s' + end
5346 fmt = '%s' + end
5347 showchar = not opts.get('no_status')
5347 showchar = not opts.get('no_status')
5348
5348
5349 for state, char, files in changestates:
5349 for state, char, files in changestates:
5350 if state in show:
5350 if state in show:
5351 label = 'status.' + state
5351 label = 'status.' + state
5352 for f in files:
5352 for f in files:
5353 fm.startitem()
5353 fm.startitem()
5354 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5354 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5355 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5355 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5356 if f in copy:
5356 if f in copy:
5357 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5357 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5358 label='status.copied')
5358 label='status.copied')
5359 fm.end()
5359 fm.end()
5360
5360
5361 @command('^summary|sum',
5361 @command('^summary|sum',
5362 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5362 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5363 def summary(ui, repo, **opts):
5363 def summary(ui, repo, **opts):
5364 """summarize working directory state
5364 """summarize working directory state
5365
5365
5366 This generates a brief summary of the working directory state,
5366 This generates a brief summary of the working directory state,
5367 including parents, branch, commit status, and available updates.
5367 including parents, branch, commit status, and available updates.
5368
5368
5369 With the --remote option, this will check the default paths for
5369 With the --remote option, this will check the default paths for
5370 incoming and outgoing changes. This can be time-consuming.
5370 incoming and outgoing changes. This can be time-consuming.
5371
5371
5372 Returns 0 on success.
5372 Returns 0 on success.
5373 """
5373 """
5374
5374
5375 ctx = repo[None]
5375 ctx = repo[None]
5376 parents = ctx.parents()
5376 parents = ctx.parents()
5377 pnode = parents[0].node()
5377 pnode = parents[0].node()
5378 marks = []
5378 marks = []
5379
5379
5380 for p in parents:
5380 for p in parents:
5381 # label with log.changeset (instead of log.parent) since this
5381 # label with log.changeset (instead of log.parent) since this
5382 # shows a working directory parent *changeset*:
5382 # shows a working directory parent *changeset*:
5383 # i18n: column positioning for "hg summary"
5383 # i18n: column positioning for "hg summary"
5384 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5384 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5385 label='log.changeset changeset.%s' % p.phasestr())
5385 label='log.changeset changeset.%s' % p.phasestr())
5386 ui.write(' '.join(p.tags()), label='log.tag')
5386 ui.write(' '.join(p.tags()), label='log.tag')
5387 if p.bookmarks():
5387 if p.bookmarks():
5388 marks.extend(p.bookmarks())
5388 marks.extend(p.bookmarks())
5389 if p.rev() == -1:
5389 if p.rev() == -1:
5390 if not len(repo):
5390 if not len(repo):
5391 ui.write(_(' (empty repository)'))
5391 ui.write(_(' (empty repository)'))
5392 else:
5392 else:
5393 ui.write(_(' (no revision checked out)'))
5393 ui.write(_(' (no revision checked out)'))
5394 ui.write('\n')
5394 ui.write('\n')
5395 if p.description():
5395 if p.description():
5396 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5396 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5397 label='log.summary')
5397 label='log.summary')
5398
5398
5399 branch = ctx.branch()
5399 branch = ctx.branch()
5400 bheads = repo.branchheads(branch)
5400 bheads = repo.branchheads(branch)
5401 # i18n: column positioning for "hg summary"
5401 # i18n: column positioning for "hg summary"
5402 m = _('branch: %s\n') % branch
5402 m = _('branch: %s\n') % branch
5403 if branch != 'default':
5403 if branch != 'default':
5404 ui.write(m, label='log.branch')
5404 ui.write(m, label='log.branch')
5405 else:
5405 else:
5406 ui.status(m, label='log.branch')
5406 ui.status(m, label='log.branch')
5407
5407
5408 if marks:
5408 if marks:
5409 current = repo._bookmarkcurrent
5409 current = repo._bookmarkcurrent
5410 # i18n: column positioning for "hg summary"
5410 # i18n: column positioning for "hg summary"
5411 ui.write(_('bookmarks:'), label='log.bookmark')
5411 ui.write(_('bookmarks:'), label='log.bookmark')
5412 if current is not None:
5412 if current is not None:
5413 if current in marks:
5413 if current in marks:
5414 ui.write(' *' + current, label='bookmarks.current')
5414 ui.write(' *' + current, label='bookmarks.current')
5415 marks.remove(current)
5415 marks.remove(current)
5416 else:
5416 else:
5417 ui.write(' [%s]' % current, label='bookmarks.current')
5417 ui.write(' [%s]' % current, label='bookmarks.current')
5418 for m in marks:
5418 for m in marks:
5419 ui.write(' ' + m, label='log.bookmark')
5419 ui.write(' ' + m, label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5420 ui.write('\n', label='log.bookmark')
5421
5421
5422 st = list(repo.status(unknown=True))[:6]
5422 st = list(repo.status(unknown=True))[:6]
5423
5423
5424 c = repo.dirstate.copies()
5424 c = repo.dirstate.copies()
5425 copied, renamed = [], []
5425 copied, renamed = [], []
5426 for d, s in c.iteritems():
5426 for d, s in c.iteritems():
5427 if s in st[2]:
5427 if s in st[2]:
5428 st[2].remove(s)
5428 st[2].remove(s)
5429 renamed.append(d)
5429 renamed.append(d)
5430 else:
5430 else:
5431 copied.append(d)
5431 copied.append(d)
5432 if d in st[1]:
5432 if d in st[1]:
5433 st[1].remove(d)
5433 st[1].remove(d)
5434 st.insert(3, renamed)
5434 st.insert(3, renamed)
5435 st.insert(4, copied)
5435 st.insert(4, copied)
5436
5436
5437 ms = mergemod.mergestate(repo)
5437 ms = mergemod.mergestate(repo)
5438 st.append([f for f in ms if ms[f] == 'u'])
5438 st.append([f for f in ms if ms[f] == 'u'])
5439
5439
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5440 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5441 st.append(subs)
5441 st.append(subs)
5442
5442
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5443 labels = [ui.label(_('%d modified'), 'status.modified'),
5444 ui.label(_('%d added'), 'status.added'),
5444 ui.label(_('%d added'), 'status.added'),
5445 ui.label(_('%d removed'), 'status.removed'),
5445 ui.label(_('%d removed'), 'status.removed'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5446 ui.label(_('%d renamed'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5447 ui.label(_('%d copied'), 'status.copied'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5448 ui.label(_('%d deleted'), 'status.deleted'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5449 ui.label(_('%d unknown'), 'status.unknown'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5450 ui.label(_('%d ignored'), 'status.ignored'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5451 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5452 ui.label(_('%d subrepos'), 'status.modified')]
5452 ui.label(_('%d subrepos'), 'status.modified')]
5453 t = []
5453 t = []
5454 for s, l in zip(st, labels):
5454 for s, l in zip(st, labels):
5455 if s:
5455 if s:
5456 t.append(l % len(s))
5456 t.append(l % len(s))
5457
5457
5458 t = ', '.join(t)
5458 t = ', '.join(t)
5459 cleanworkdir = False
5459 cleanworkdir = False
5460
5460
5461 if repo.vfs.exists('updatestate'):
5461 if repo.vfs.exists('updatestate'):
5462 t += _(' (interrupted update)')
5462 t += _(' (interrupted update)')
5463 elif len(parents) > 1:
5463 elif len(parents) > 1:
5464 t += _(' (merge)')
5464 t += _(' (merge)')
5465 elif branch != parents[0].branch():
5465 elif branch != parents[0].branch():
5466 t += _(' (new branch)')
5466 t += _(' (new branch)')
5467 elif (parents[0].closesbranch() and
5467 elif (parents[0].closesbranch() and
5468 pnode in repo.branchheads(branch, closed=True)):
5468 pnode in repo.branchheads(branch, closed=True)):
5469 t += _(' (head closed)')
5469 t += _(' (head closed)')
5470 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5470 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5471 t += _(' (clean)')
5471 t += _(' (clean)')
5472 cleanworkdir = True
5472 cleanworkdir = True
5473 elif pnode not in bheads:
5473 elif pnode not in bheads:
5474 t += _(' (new branch head)')
5474 t += _(' (new branch head)')
5475
5475
5476 if cleanworkdir:
5476 if cleanworkdir:
5477 # i18n: column positioning for "hg summary"
5477 # i18n: column positioning for "hg summary"
5478 ui.status(_('commit: %s\n') % t.strip())
5478 ui.status(_('commit: %s\n') % t.strip())
5479 else:
5479 else:
5480 # i18n: column positioning for "hg summary"
5480 # i18n: column positioning for "hg summary"
5481 ui.write(_('commit: %s\n') % t.strip())
5481 ui.write(_('commit: %s\n') % t.strip())
5482
5482
5483 # all ancestors of branch heads - all ancestors of parent = new csets
5483 # all ancestors of branch heads - all ancestors of parent = new csets
5484 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5484 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5485 bheads))
5485 bheads))
5486
5486
5487 if new == 0:
5487 if new == 0:
5488 # i18n: column positioning for "hg summary"
5488 # i18n: column positioning for "hg summary"
5489 ui.status(_('update: (current)\n'))
5489 ui.status(_('update: (current)\n'))
5490 elif pnode not in bheads:
5490 elif pnode not in bheads:
5491 # i18n: column positioning for "hg summary"
5491 # i18n: column positioning for "hg summary"
5492 ui.write(_('update: %d new changesets (update)\n') % new)
5492 ui.write(_('update: %d new changesets (update)\n') % new)
5493 else:
5493 else:
5494 # i18n: column positioning for "hg summary"
5494 # i18n: column positioning for "hg summary"
5495 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5495 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5496 (new, len(bheads)))
5496 (new, len(bheads)))
5497
5497
5498 cmdutil.summaryhooks(ui, repo)
5498 cmdutil.summaryhooks(ui, repo)
5499
5499
5500 if opts.get('remote'):
5500 if opts.get('remote'):
5501 t = []
5501 t = []
5502 source, branches = hg.parseurl(ui.expandpath('default'))
5502 source, branches = hg.parseurl(ui.expandpath('default'))
5503 sbranch = branches[0]
5503 sbranch = branches[0]
5504 other = hg.peer(repo, {}, source)
5504 other = hg.peer(repo, {}, source)
5505 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5505 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5506 if revs:
5506 if revs:
5507 revs = [other.lookup(rev) for rev in revs]
5507 revs = [other.lookup(rev) for rev in revs]
5508 ui.debug('comparing with %s\n' % util.hidepassword(source))
5508 ui.debug('comparing with %s\n' % util.hidepassword(source))
5509 repo.ui.pushbuffer()
5509 repo.ui.pushbuffer()
5510 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5510 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5511 _common, incoming, _rheads = commoninc
5511 _common, incoming, _rheads = commoninc
5512 repo.ui.popbuffer()
5512 repo.ui.popbuffer()
5513 if incoming:
5513 if incoming:
5514 t.append(_('1 or more incoming'))
5514 t.append(_('1 or more incoming'))
5515
5515
5516 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5516 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5517 dbranch = branches[0]
5517 dbranch = branches[0]
5518 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5518 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5519 if source != dest:
5519 if source != dest:
5520 other = hg.peer(repo, {}, dest)
5520 other = hg.peer(repo, {}, dest)
5521 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5521 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5522 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5522 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5523 commoninc = None
5523 commoninc = None
5524 if revs:
5524 if revs:
5525 revs = [repo.lookup(rev) for rev in revs]
5525 revs = [repo.lookup(rev) for rev in revs]
5526 repo.ui.pushbuffer()
5526 repo.ui.pushbuffer()
5527 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5527 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5528 commoninc=commoninc)
5528 commoninc=commoninc)
5529 repo.ui.popbuffer()
5529 repo.ui.popbuffer()
5530 o = outgoing.missing
5530 o = outgoing.missing
5531 if o:
5531 if o:
5532 t.append(_('%d outgoing') % len(o))
5532 t.append(_('%d outgoing') % len(o))
5533 if 'bookmarks' in other.listkeys('namespaces'):
5533 if 'bookmarks' in other.listkeys('namespaces'):
5534 lmarks = repo.listkeys('bookmarks')
5534 lmarks = repo.listkeys('bookmarks')
5535 rmarks = other.listkeys('bookmarks')
5535 rmarks = other.listkeys('bookmarks')
5536 diff = set(rmarks) - set(lmarks)
5536 diff = set(rmarks) - set(lmarks)
5537 if len(diff) > 0:
5537 if len(diff) > 0:
5538 t.append(_('%d incoming bookmarks') % len(diff))
5538 t.append(_('%d incoming bookmarks') % len(diff))
5539 diff = set(lmarks) - set(rmarks)
5539 diff = set(lmarks) - set(rmarks)
5540 if len(diff) > 0:
5540 if len(diff) > 0:
5541 t.append(_('%d outgoing bookmarks') % len(diff))
5541 t.append(_('%d outgoing bookmarks') % len(diff))
5542
5542
5543 if t:
5543 if t:
5544 # i18n: column positioning for "hg summary"
5544 # i18n: column positioning for "hg summary"
5545 ui.write(_('remote: %s\n') % (', '.join(t)))
5545 ui.write(_('remote: %s\n') % (', '.join(t)))
5546 else:
5546 else:
5547 # i18n: column positioning for "hg summary"
5547 # i18n: column positioning for "hg summary"
5548 ui.status(_('remote: (synced)\n'))
5548 ui.status(_('remote: (synced)\n'))
5549
5549
5550 @command('tag',
5550 @command('tag',
5551 [('f', 'force', None, _('force tag')),
5551 [('f', 'force', None, _('force tag')),
5552 ('l', 'local', None, _('make the tag local')),
5552 ('l', 'local', None, _('make the tag local')),
5553 ('r', 'rev', '', _('revision to tag'), _('REV')),
5553 ('r', 'rev', '', _('revision to tag'), _('REV')),
5554 ('', 'remove', None, _('remove a tag')),
5554 ('', 'remove', None, _('remove a tag')),
5555 # -l/--local is already there, commitopts cannot be used
5555 # -l/--local is already there, commitopts cannot be used
5556 ('e', 'edit', None, _('edit commit message')),
5556 ('e', 'edit', None, _('edit commit message')),
5557 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5557 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5558 ] + commitopts2,
5558 ] + commitopts2,
5559 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5559 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5560 def tag(ui, repo, name1, *names, **opts):
5560 def tag(ui, repo, name1, *names, **opts):
5561 """add one or more tags for the current or given revision
5561 """add one or more tags for the current or given revision
5562
5562
5563 Name a particular revision using <name>.
5563 Name a particular revision using <name>.
5564
5564
5565 Tags are used to name particular revisions of the repository and are
5565 Tags are used to name particular revisions of the repository and are
5566 very useful to compare different revisions, to go back to significant
5566 very useful to compare different revisions, to go back to significant
5567 earlier versions or to mark branch points as releases, etc. Changing
5567 earlier versions or to mark branch points as releases, etc. Changing
5568 an existing tag is normally disallowed; use -f/--force to override.
5568 an existing tag is normally disallowed; use -f/--force to override.
5569
5569
5570 If no revision is given, the parent of the working directory is
5570 If no revision is given, the parent of the working directory is
5571 used.
5571 used.
5572
5572
5573 To facilitate version control, distribution, and merging of tags,
5573 To facilitate version control, distribution, and merging of tags,
5574 they are stored as a file named ".hgtags" which is managed similarly
5574 they are stored as a file named ".hgtags" which is managed similarly
5575 to other project files and can be hand-edited if necessary. This
5575 to other project files and can be hand-edited if necessary. This
5576 also means that tagging creates a new commit. The file
5576 also means that tagging creates a new commit. The file
5577 ".hg/localtags" is used for local tags (not shared among
5577 ".hg/localtags" is used for local tags (not shared among
5578 repositories).
5578 repositories).
5579
5579
5580 Tag commits are usually made at the head of a branch. If the parent
5580 Tag commits are usually made at the head of a branch. If the parent
5581 of the working directory is not a branch head, :hg:`tag` aborts; use
5581 of the working directory is not a branch head, :hg:`tag` aborts; use
5582 -f/--force to force the tag commit to be based on a non-head
5582 -f/--force to force the tag commit to be based on a non-head
5583 changeset.
5583 changeset.
5584
5584
5585 See :hg:`help dates` for a list of formats valid for -d/--date.
5585 See :hg:`help dates` for a list of formats valid for -d/--date.
5586
5586
5587 Since tag names have priority over branch names during revision
5587 Since tag names have priority over branch names during revision
5588 lookup, using an existing branch name as a tag name is discouraged.
5588 lookup, using an existing branch name as a tag name is discouraged.
5589
5589
5590 Returns 0 on success.
5590 Returns 0 on success.
5591 """
5591 """
5592 wlock = lock = None
5592 wlock = lock = None
5593 try:
5593 try:
5594 wlock = repo.wlock()
5594 wlock = repo.wlock()
5595 lock = repo.lock()
5595 lock = repo.lock()
5596 rev_ = "."
5596 rev_ = "."
5597 names = [t.strip() for t in (name1,) + names]
5597 names = [t.strip() for t in (name1,) + names]
5598 if len(names) != len(set(names)):
5598 if len(names) != len(set(names)):
5599 raise util.Abort(_('tag names must be unique'))
5599 raise util.Abort(_('tag names must be unique'))
5600 for n in names:
5600 for n in names:
5601 scmutil.checknewlabel(repo, n, 'tag')
5601 scmutil.checknewlabel(repo, n, 'tag')
5602 if not n:
5602 if not n:
5603 raise util.Abort(_('tag names cannot consist entirely of '
5603 raise util.Abort(_('tag names cannot consist entirely of '
5604 'whitespace'))
5604 'whitespace'))
5605 if opts.get('rev') and opts.get('remove'):
5605 if opts.get('rev') and opts.get('remove'):
5606 raise util.Abort(_("--rev and --remove are incompatible"))
5606 raise util.Abort(_("--rev and --remove are incompatible"))
5607 if opts.get('rev'):
5607 if opts.get('rev'):
5608 rev_ = opts['rev']
5608 rev_ = opts['rev']
5609 message = opts.get('message')
5609 message = opts.get('message')
5610 if opts.get('remove'):
5610 if opts.get('remove'):
5611 expectedtype = opts.get('local') and 'local' or 'global'
5611 expectedtype = opts.get('local') and 'local' or 'global'
5612 for n in names:
5612 for n in names:
5613 if not repo.tagtype(n):
5613 if not repo.tagtype(n):
5614 raise util.Abort(_("tag '%s' does not exist") % n)
5614 raise util.Abort(_("tag '%s' does not exist") % n)
5615 if repo.tagtype(n) != expectedtype:
5615 if repo.tagtype(n) != expectedtype:
5616 if expectedtype == 'global':
5616 if expectedtype == 'global':
5617 raise util.Abort(_("tag '%s' is not a global tag") % n)
5617 raise util.Abort(_("tag '%s' is not a global tag") % n)
5618 else:
5618 else:
5619 raise util.Abort(_("tag '%s' is not a local tag") % n)
5619 raise util.Abort(_("tag '%s' is not a local tag") % n)
5620 rev_ = nullid
5620 rev_ = nullid
5621 if not message:
5621 if not message:
5622 # we don't translate commit messages
5622 # we don't translate commit messages
5623 message = 'Removed tag %s' % ', '.join(names)
5623 message = 'Removed tag %s' % ', '.join(names)
5624 elif not opts.get('force'):
5624 elif not opts.get('force'):
5625 for n in names:
5625 for n in names:
5626 if n in repo.tags():
5626 if n in repo.tags():
5627 raise util.Abort(_("tag '%s' already exists "
5627 raise util.Abort(_("tag '%s' already exists "
5628 "(use -f to force)") % n)
5628 "(use -f to force)") % n)
5629 if not opts.get('local'):
5629 if not opts.get('local'):
5630 p1, p2 = repo.dirstate.parents()
5630 p1, p2 = repo.dirstate.parents()
5631 if p2 != nullid:
5631 if p2 != nullid:
5632 raise util.Abort(_('uncommitted merge'))
5632 raise util.Abort(_('uncommitted merge'))
5633 bheads = repo.branchheads()
5633 bheads = repo.branchheads()
5634 if not opts.get('force') and bheads and p1 not in bheads:
5634 if not opts.get('force') and bheads and p1 not in bheads:
5635 raise util.Abort(_('not at a branch head (use -f to force)'))
5635 raise util.Abort(_('not at a branch head (use -f to force)'))
5636 r = scmutil.revsingle(repo, rev_).node()
5636 r = scmutil.revsingle(repo, rev_).node()
5637
5637
5638 if not message:
5638 if not message:
5639 # we don't translate commit messages
5639 # we don't translate commit messages
5640 message = ('Added tag %s for changeset %s' %
5640 message = ('Added tag %s for changeset %s' %
5641 (', '.join(names), short(r)))
5641 (', '.join(names), short(r)))
5642
5642
5643 date = opts.get('date')
5643 date = opts.get('date')
5644 if date:
5644 if date:
5645 date = util.parsedate(date)
5645 date = util.parsedate(date)
5646
5646
5647 if opts.get('edit'):
5647 if opts.get('edit'):
5648 message = ui.edit(message, ui.username())
5648 message = ui.edit(message, ui.username())
5649
5649
5650 # don't allow tagging the null rev
5650 # don't allow tagging the null rev
5651 if (not opts.get('remove') and
5651 if (not opts.get('remove') and
5652 scmutil.revsingle(repo, rev_).rev() == nullrev):
5652 scmutil.revsingle(repo, rev_).rev() == nullrev):
5653 raise util.Abort(_("cannot tag null revision"))
5653 raise util.Abort(_("cannot tag null revision"))
5654
5654
5655 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5655 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5656 finally:
5656 finally:
5657 release(lock, wlock)
5657 release(lock, wlock)
5658
5658
5659 @command('tags', [], '')
5659 @command('tags', [], '')
5660 def tags(ui, repo, **opts):
5660 def tags(ui, repo, **opts):
5661 """list repository tags
5661 """list repository tags
5662
5662
5663 This lists both regular and local tags. When the -v/--verbose
5663 This lists both regular and local tags. When the -v/--verbose
5664 switch is used, a third column "local" is printed for local tags.
5664 switch is used, a third column "local" is printed for local tags.
5665
5665
5666 Returns 0 on success.
5666 Returns 0 on success.
5667 """
5667 """
5668
5668
5669 fm = ui.formatter('tags', opts)
5669 fm = ui.formatter('tags', opts)
5670 hexfunc = ui.debugflag and hex or short
5670 hexfunc = ui.debugflag and hex or short
5671 tagtype = ""
5671 tagtype = ""
5672
5672
5673 for t, n in reversed(repo.tagslist()):
5673 for t, n in reversed(repo.tagslist()):
5674 hn = hexfunc(n)
5674 hn = hexfunc(n)
5675 label = 'tags.normal'
5675 label = 'tags.normal'
5676 tagtype = ''
5676 tagtype = ''
5677 if repo.tagtype(t) == 'local':
5677 if repo.tagtype(t) == 'local':
5678 label = 'tags.local'
5678 label = 'tags.local'
5679 tagtype = 'local'
5679 tagtype = 'local'
5680
5680
5681 fm.startitem()
5681 fm.startitem()
5682 fm.write('tag', '%s', t, label=label)
5682 fm.write('tag', '%s', t, label=label)
5683 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5683 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5684 fm.condwrite(not ui.quiet, 'rev id', fmt,
5684 fm.condwrite(not ui.quiet, 'rev id', fmt,
5685 repo.changelog.rev(n), hn, label=label)
5685 repo.changelog.rev(n), hn, label=label)
5686 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5686 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5687 tagtype, label=label)
5687 tagtype, label=label)
5688 fm.plain('\n')
5688 fm.plain('\n')
5689 fm.end()
5689 fm.end()
5690
5690
5691 @command('tip',
5691 @command('tip',
5692 [('p', 'patch', None, _('show patch')),
5692 [('p', 'patch', None, _('show patch')),
5693 ('g', 'git', None, _('use git extended diff format')),
5693 ('g', 'git', None, _('use git extended diff format')),
5694 ] + templateopts,
5694 ] + templateopts,
5695 _('[-p] [-g]'))
5695 _('[-p] [-g]'))
5696 def tip(ui, repo, **opts):
5696 def tip(ui, repo, **opts):
5697 """show the tip revision (DEPRECATED)
5697 """show the tip revision (DEPRECATED)
5698
5698
5699 The tip revision (usually just called the tip) is the changeset
5699 The tip revision (usually just called the tip) is the changeset
5700 most recently added to the repository (and therefore the most
5700 most recently added to the repository (and therefore the most
5701 recently changed head).
5701 recently changed head).
5702
5702
5703 If you have just made a commit, that commit will be the tip. If
5703 If you have just made a commit, that commit will be the tip. If
5704 you have just pulled changes from another repository, the tip of
5704 you have just pulled changes from another repository, the tip of
5705 that repository becomes the current tip. The "tip" tag is special
5705 that repository becomes the current tip. The "tip" tag is special
5706 and cannot be renamed or assigned to a different changeset.
5706 and cannot be renamed or assigned to a different changeset.
5707
5707
5708 This command is deprecated, please use :hg:`heads` instead.
5708 This command is deprecated, please use :hg:`heads` instead.
5709
5709
5710 Returns 0 on success.
5710 Returns 0 on success.
5711 """
5711 """
5712 displayer = cmdutil.show_changeset(ui, repo, opts)
5712 displayer = cmdutil.show_changeset(ui, repo, opts)
5713 displayer.show(repo['tip'])
5713 displayer.show(repo['tip'])
5714 displayer.close()
5714 displayer.close()
5715
5715
5716 @command('unbundle',
5716 @command('unbundle',
5717 [('u', 'update', None,
5717 [('u', 'update', None,
5718 _('update to new branch head if changesets were unbundled'))],
5718 _('update to new branch head if changesets were unbundled'))],
5719 _('[-u] FILE...'))
5719 _('[-u] FILE...'))
5720 def unbundle(ui, repo, fname1, *fnames, **opts):
5720 def unbundle(ui, repo, fname1, *fnames, **opts):
5721 """apply one or more changegroup files
5721 """apply one or more changegroup files
5722
5722
5723 Apply one or more compressed changegroup files generated by the
5723 Apply one or more compressed changegroup files generated by the
5724 bundle command.
5724 bundle command.
5725
5725
5726 Returns 0 on success, 1 if an update has unresolved files.
5726 Returns 0 on success, 1 if an update has unresolved files.
5727 """
5727 """
5728 fnames = (fname1,) + fnames
5728 fnames = (fname1,) + fnames
5729
5729
5730 lock = repo.lock()
5730 lock = repo.lock()
5731 wc = repo['.']
5731 wc = repo['.']
5732 try:
5732 try:
5733 for fname in fnames:
5733 for fname in fnames:
5734 f = hg.openpath(ui, fname)
5734 f = hg.openpath(ui, fname)
5735 gen = changegroup.readbundle(f, fname)
5735 gen = changegroup.readbundle(f, fname)
5736 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5736 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5737 finally:
5737 finally:
5738 lock.release()
5738 lock.release()
5739 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5739 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5740 return postincoming(ui, repo, modheads, opts.get('update'), None)
5740 return postincoming(ui, repo, modheads, opts.get('update'), None)
5741
5741
5742 @command('^update|up|checkout|co',
5742 @command('^update|up|checkout|co',
5743 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5743 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5744 ('c', 'check', None,
5744 ('c', 'check', None,
5745 _('update across branches if no uncommitted changes')),
5745 _('update across branches if no uncommitted changes')),
5746 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5746 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5747 ('r', 'rev', '', _('revision'), _('REV'))],
5747 ('r', 'rev', '', _('revision'), _('REV'))],
5748 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5748 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5749 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5749 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5750 """update working directory (or switch revisions)
5750 """update working directory (or switch revisions)
5751
5751
5752 Update the repository's working directory to the specified
5752 Update the repository's working directory to the specified
5753 changeset. If no changeset is specified, update to the tip of the
5753 changeset. If no changeset is specified, update to the tip of the
5754 current named branch and move the current bookmark (see :hg:`help
5754 current named branch and move the current bookmark (see :hg:`help
5755 bookmarks`).
5755 bookmarks`).
5756
5756
5757 Update sets the working directory's parent revision to the specified
5757 Update sets the working directory's parent revision to the specified
5758 changeset (see :hg:`help parents`).
5758 changeset (see :hg:`help parents`).
5759
5759
5760 If the changeset is not a descendant or ancestor of the working
5760 If the changeset is not a descendant or ancestor of the working
5761 directory's parent, the update is aborted. With the -c/--check
5761 directory's parent, the update is aborted. With the -c/--check
5762 option, the working directory is checked for uncommitted changes; if
5762 option, the working directory is checked for uncommitted changes; if
5763 none are found, the working directory is updated to the specified
5763 none are found, the working directory is updated to the specified
5764 changeset.
5764 changeset.
5765
5765
5766 .. container:: verbose
5766 .. container:: verbose
5767
5767
5768 The following rules apply when the working directory contains
5768 The following rules apply when the working directory contains
5769 uncommitted changes:
5769 uncommitted changes:
5770
5770
5771 1. If neither -c/--check nor -C/--clean is specified, and if
5771 1. If neither -c/--check nor -C/--clean is specified, and if
5772 the requested changeset is an ancestor or descendant of
5772 the requested changeset is an ancestor or descendant of
5773 the working directory's parent, the uncommitted changes
5773 the working directory's parent, the uncommitted changes
5774 are merged into the requested changeset and the merged
5774 are merged into the requested changeset and the merged
5775 result is left uncommitted. If the requested changeset is
5775 result is left uncommitted. If the requested changeset is
5776 not an ancestor or descendant (that is, it is on another
5776 not an ancestor or descendant (that is, it is on another
5777 branch), the update is aborted and the uncommitted changes
5777 branch), the update is aborted and the uncommitted changes
5778 are preserved.
5778 are preserved.
5779
5779
5780 2. With the -c/--check option, the update is aborted and the
5780 2. With the -c/--check option, the update is aborted and the
5781 uncommitted changes are preserved.
5781 uncommitted changes are preserved.
5782
5782
5783 3. With the -C/--clean option, uncommitted changes are discarded and
5783 3. With the -C/--clean option, uncommitted changes are discarded and
5784 the working directory is updated to the requested changeset.
5784 the working directory is updated to the requested changeset.
5785
5785
5786 To cancel an uncommitted merge (and lose your changes), use
5786 To cancel an uncommitted merge (and lose your changes), use
5787 :hg:`update --clean .`.
5787 :hg:`update --clean .`.
5788
5788
5789 Use null as the changeset to remove the working directory (like
5789 Use null as the changeset to remove the working directory (like
5790 :hg:`clone -U`).
5790 :hg:`clone -U`).
5791
5791
5792 If you want to revert just one file to an older revision, use
5792 If you want to revert just one file to an older revision, use
5793 :hg:`revert [-r REV] NAME`.
5793 :hg:`revert [-r REV] NAME`.
5794
5794
5795 See :hg:`help dates` for a list of formats valid for -d/--date.
5795 See :hg:`help dates` for a list of formats valid for -d/--date.
5796
5796
5797 Returns 0 on success, 1 if there are unresolved files.
5797 Returns 0 on success, 1 if there are unresolved files.
5798 """
5798 """
5799 if rev and node:
5799 if rev and node:
5800 raise util.Abort(_("please specify just one revision"))
5800 raise util.Abort(_("please specify just one revision"))
5801
5801
5802 if rev is None or rev == '':
5802 if rev is None or rev == '':
5803 rev = node
5803 rev = node
5804
5804
5805 cmdutil.clearunfinished(repo)
5805 cmdutil.clearunfinished(repo)
5806
5806
5807 # with no argument, we also move the current bookmark, if any
5807 # with no argument, we also move the current bookmark, if any
5808 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5808 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5809
5809
5810 # if we defined a bookmark, we have to remember the original bookmark name
5810 # if we defined a bookmark, we have to remember the original bookmark name
5811 brev = rev
5811 brev = rev
5812 rev = scmutil.revsingle(repo, rev, rev).rev()
5812 rev = scmutil.revsingle(repo, rev, rev).rev()
5813
5813
5814 if check and clean:
5814 if check and clean:
5815 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5815 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5816
5816
5817 if date:
5817 if date:
5818 if rev is not None:
5818 if rev is not None:
5819 raise util.Abort(_("you can't specify a revision and a date"))
5819 raise util.Abort(_("you can't specify a revision and a date"))
5820 rev = cmdutil.finddate(ui, repo, date)
5820 rev = cmdutil.finddate(ui, repo, date)
5821
5821
5822 if check:
5822 if check:
5823 c = repo[None]
5823 c = repo[None]
5824 if c.dirty(merge=False, branch=False, missing=True):
5824 if c.dirty(merge=False, branch=False, missing=True):
5825 raise util.Abort(_("uncommitted changes"))
5825 raise util.Abort(_("uncommitted changes"))
5826 if rev is None:
5826 if rev is None:
5827 rev = repo[repo[None].branch()].rev()
5827 rev = repo[repo[None].branch()].rev()
5828 mergemod._checkunknown(repo, repo[None], repo[rev])
5828 mergemod._checkunknown(repo, repo[None], repo[rev])
5829
5829
5830 if clean:
5830 if clean:
5831 ret = hg.clean(repo, rev)
5831 ret = hg.clean(repo, rev)
5832 else:
5832 else:
5833 ret = hg.update(repo, rev)
5833 ret = hg.update(repo, rev)
5834
5834
5835 if not ret and movemarkfrom:
5835 if not ret and movemarkfrom:
5836 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5836 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5837 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5837 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5838 elif brev in repo._bookmarks:
5838 elif brev in repo._bookmarks:
5839 bookmarks.setcurrent(repo, brev)
5839 bookmarks.setcurrent(repo, brev)
5840 elif brev:
5840 elif brev:
5841 bookmarks.unsetcurrent(repo)
5841 bookmarks.unsetcurrent(repo)
5842
5842
5843 return ret
5843 return ret
5844
5844
5845 @command('verify', [])
5845 @command('verify', [])
5846 def verify(ui, repo):
5846 def verify(ui, repo):
5847 """verify the integrity of the repository
5847 """verify the integrity of the repository
5848
5848
5849 Verify the integrity of the current repository.
5849 Verify the integrity of the current repository.
5850
5850
5851 This will perform an extensive check of the repository's
5851 This will perform an extensive check of the repository's
5852 integrity, validating the hashes and checksums of each entry in
5852 integrity, validating the hashes and checksums of each entry in
5853 the changelog, manifest, and tracked files, as well as the
5853 the changelog, manifest, and tracked files, as well as the
5854 integrity of their crosslinks and indices.
5854 integrity of their crosslinks and indices.
5855
5855
5856 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5856 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5857 for more information about recovery from corruption of the
5857 for more information about recovery from corruption of the
5858 repository.
5858 repository.
5859
5859
5860 Returns 0 on success, 1 if errors are encountered.
5860 Returns 0 on success, 1 if errors are encountered.
5861 """
5861 """
5862 return hg.verify(repo)
5862 return hg.verify(repo)
5863
5863
5864 @command('version', [])
5864 @command('version', [])
5865 def version_(ui):
5865 def version_(ui):
5866 """output version and copyright information"""
5866 """output version and copyright information"""
5867 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5867 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5868 % util.version())
5868 % util.version())
5869 ui.status(_(
5869 ui.status(_(
5870 "(see http://mercurial.selenic.com for more information)\n"
5870 "(see http://mercurial.selenic.com for more information)\n"
5871 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5871 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5872 "This is free software; see the source for copying conditions. "
5872 "This is free software; see the source for copying conditions. "
5873 "There is NO\nwarranty; "
5873 "There is NO\nwarranty; "
5874 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5874 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5875 ))
5875 ))
5876
5876
5877 norepo = ("clone init version help debugcommands debugcomplete"
5877 norepo = ("clone init version help debugcommands debugcomplete"
5878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5879 " debugknown debuggetbundle debugbundle")
5879 " debugknown debuggetbundle debugbundle")
5880 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5880 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5881 " debugdata debugindex debugindexdot debugrevlog")
5881 " debugdata debugindex debugindexdot debugrevlog")
5882 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5882 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5883 " remove resolve status debugwalk")
5883 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now