##// END OF EJS Templates
commands: use bookmarks.validdest instead of duplicating logic...
Sean Farley -
r20282:2cfb7205 default
parent child Browse files
Show More
@@ -1,5922 +1,5920
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'), _('STYLE')),
93 ('', 'template', '',
93 ('', '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 # consider successor changesets as well
851 foreground = obsolete.foreground(repo, [marks[mark]])
852 deletefrom = [b for b in divs
850 deletefrom = [b for b in divs
853 if repo[b].rev() in anc or b == target]
851 if repo[b].rev() in anc or b == target]
854 bookmarks.deletedivergent(repo, deletefrom, mark)
852 bookmarks.deletedivergent(repo, deletefrom, mark)
855 if bmctx.rev() in anc or target in foreground:
853 if bookmarks.validdest(repo, bmctx, repo[target]):
856 ui.status(_("moving bookmark '%s' forward from %s\n") %
854 ui.status(_("moving bookmark '%s' forward from %s\n") %
857 (mark, short(bmctx.node())))
855 (mark, short(bmctx.node())))
858 return
856 return
859 raise util.Abort(_("bookmark '%s' already exists "
857 raise util.Abort(_("bookmark '%s' already exists "
860 "(use -f to force)") % mark)
858 "(use -f to force)") % mark)
861 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
859 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
862 and not force):
860 and not force):
863 raise util.Abort(
861 raise util.Abort(
864 _("a bookmark cannot have the name of an existing branch"))
862 _("a bookmark cannot have the name of an existing branch"))
865
863
866 if delete and rename:
864 if delete and rename:
867 raise util.Abort(_("--delete and --rename are incompatible"))
865 raise util.Abort(_("--delete and --rename are incompatible"))
868 if delete and rev:
866 if delete and rev:
869 raise util.Abort(_("--rev is incompatible with --delete"))
867 raise util.Abort(_("--rev is incompatible with --delete"))
870 if rename and rev:
868 if rename and rev:
871 raise util.Abort(_("--rev is incompatible with --rename"))
869 raise util.Abort(_("--rev is incompatible with --rename"))
872 if not names and (delete or rev):
870 if not names and (delete or rev):
873 raise util.Abort(_("bookmark name required"))
871 raise util.Abort(_("bookmark name required"))
874
872
875 if delete or rename or names or inactive:
873 if delete or rename or names or inactive:
876 wlock = repo.wlock()
874 wlock = repo.wlock()
877 try:
875 try:
878 cur = repo.changectx('.').node()
876 cur = repo.changectx('.').node()
879 marks = repo._bookmarks
877 marks = repo._bookmarks
880 if delete:
878 if delete:
881 for mark in names:
879 for mark in names:
882 if mark not in marks:
880 if mark not in marks:
883 raise util.Abort(_("bookmark '%s' does not exist") %
881 raise util.Abort(_("bookmark '%s' does not exist") %
884 mark)
882 mark)
885 if mark == repo._bookmarkcurrent:
883 if mark == repo._bookmarkcurrent:
886 bookmarks.unsetcurrent(repo)
884 bookmarks.unsetcurrent(repo)
887 del marks[mark]
885 del marks[mark]
888 marks.write()
886 marks.write()
889
887
890 elif rename:
888 elif rename:
891 if not names:
889 if not names:
892 raise util.Abort(_("new bookmark name required"))
890 raise util.Abort(_("new bookmark name required"))
893 elif len(names) > 1:
891 elif len(names) > 1:
894 raise util.Abort(_("only one new bookmark name allowed"))
892 raise util.Abort(_("only one new bookmark name allowed"))
895 mark = checkformat(names[0])
893 mark = checkformat(names[0])
896 if rename not in marks:
894 if rename not in marks:
897 raise util.Abort(_("bookmark '%s' does not exist") % rename)
895 raise util.Abort(_("bookmark '%s' does not exist") % rename)
898 checkconflict(repo, mark, cur, force)
896 checkconflict(repo, mark, cur, force)
899 marks[mark] = marks[rename]
897 marks[mark] = marks[rename]
900 if repo._bookmarkcurrent == rename and not inactive:
898 if repo._bookmarkcurrent == rename and not inactive:
901 bookmarks.setcurrent(repo, mark)
899 bookmarks.setcurrent(repo, mark)
902 del marks[rename]
900 del marks[rename]
903 marks.write()
901 marks.write()
904
902
905 elif names:
903 elif names:
906 newact = None
904 newact = None
907 for mark in names:
905 for mark in names:
908 mark = checkformat(mark)
906 mark = checkformat(mark)
909 if newact is None:
907 if newact is None:
910 newact = mark
908 newact = mark
911 if inactive and mark == repo._bookmarkcurrent:
909 if inactive and mark == repo._bookmarkcurrent:
912 bookmarks.unsetcurrent(repo)
910 bookmarks.unsetcurrent(repo)
913 return
911 return
914 tgt = cur
912 tgt = cur
915 if rev:
913 if rev:
916 tgt = scmutil.revsingle(repo, rev).node()
914 tgt = scmutil.revsingle(repo, rev).node()
917 checkconflict(repo, mark, cur, force, tgt)
915 checkconflict(repo, mark, cur, force, tgt)
918 marks[mark] = tgt
916 marks[mark] = tgt
919 if not inactive and cur == marks[newact] and not rev:
917 if not inactive and cur == marks[newact] and not rev:
920 bookmarks.setcurrent(repo, newact)
918 bookmarks.setcurrent(repo, newact)
921 elif cur != tgt and newact == repo._bookmarkcurrent:
919 elif cur != tgt and newact == repo._bookmarkcurrent:
922 bookmarks.unsetcurrent(repo)
920 bookmarks.unsetcurrent(repo)
923 marks.write()
921 marks.write()
924
922
925 elif inactive:
923 elif inactive:
926 if len(marks) == 0:
924 if len(marks) == 0:
927 ui.status(_("no bookmarks set\n"))
925 ui.status(_("no bookmarks set\n"))
928 elif not repo._bookmarkcurrent:
926 elif not repo._bookmarkcurrent:
929 ui.status(_("no active bookmark\n"))
927 ui.status(_("no active bookmark\n"))
930 else:
928 else:
931 bookmarks.unsetcurrent(repo)
929 bookmarks.unsetcurrent(repo)
932 finally:
930 finally:
933 wlock.release()
931 wlock.release()
934 else: # show bookmarks
932 else: # show bookmarks
935 hexfn = ui.debugflag and hex or short
933 hexfn = ui.debugflag and hex or short
936 marks = repo._bookmarks
934 marks = repo._bookmarks
937 if len(marks) == 0:
935 if len(marks) == 0:
938 ui.status(_("no bookmarks set\n"))
936 ui.status(_("no bookmarks set\n"))
939 else:
937 else:
940 for bmark, n in sorted(marks.iteritems()):
938 for bmark, n in sorted(marks.iteritems()):
941 current = repo._bookmarkcurrent
939 current = repo._bookmarkcurrent
942 if bmark == current:
940 if bmark == current:
943 prefix, label = '*', 'bookmarks.current'
941 prefix, label = '*', 'bookmarks.current'
944 else:
942 else:
945 prefix, label = ' ', ''
943 prefix, label = ' ', ''
946
944
947 if ui.quiet:
945 if ui.quiet:
948 ui.write("%s\n" % bmark, label=label)
946 ui.write("%s\n" % bmark, label=label)
949 else:
947 else:
950 ui.write(" %s %-25s %d:%s\n" % (
948 ui.write(" %s %-25s %d:%s\n" % (
951 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
949 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
952 label=label)
950 label=label)
953
951
954 @command('branch',
952 @command('branch',
955 [('f', 'force', None,
953 [('f', 'force', None,
956 _('set branch name even if it shadows an existing branch')),
954 _('set branch name even if it shadows an existing branch')),
957 ('C', 'clean', None, _('reset branch name to parent branch name'))],
955 ('C', 'clean', None, _('reset branch name to parent branch name'))],
958 _('[-fC] [NAME]'))
956 _('[-fC] [NAME]'))
959 def branch(ui, repo, label=None, **opts):
957 def branch(ui, repo, label=None, **opts):
960 """set or show the current branch name
958 """set or show the current branch name
961
959
962 .. note::
960 .. note::
963
961
964 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
965 light-weight bookmark instead. See :hg:`help glossary` for more
963 light-weight bookmark instead. See :hg:`help glossary` for more
966 information about named branches and bookmarks.
964 information about named branches and bookmarks.
967
965
968 With no argument, show the current branch name. With one argument,
966 With no argument, show the current branch name. With one argument,
969 set the working directory branch name (the branch will not exist
967 set the working directory branch name (the branch will not exist
970 in the repository until the next commit). Standard practice
968 in the repository until the next commit). Standard practice
971 recommends that primary development take place on the 'default'
969 recommends that primary development take place on the 'default'
972 branch.
970 branch.
973
971
974 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
975 branch name that already exists, even if it's inactive.
973 branch name that already exists, even if it's inactive.
976
974
977 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
978 the parent of the working directory, negating a previous branch
976 the parent of the working directory, negating a previous branch
979 change.
977 change.
980
978
981 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
982 :hg:`commit --close-branch` to mark this branch as closed.
980 :hg:`commit --close-branch` to mark this branch as closed.
983
981
984 Returns 0 on success.
982 Returns 0 on success.
985 """
983 """
986 if label:
984 if label:
987 label = label.strip()
985 label = label.strip()
988
986
989 if not opts.get('clean') and not label:
987 if not opts.get('clean') and not label:
990 ui.write("%s\n" % repo.dirstate.branch())
988 ui.write("%s\n" % repo.dirstate.branch())
991 return
989 return
992
990
993 wlock = repo.wlock()
991 wlock = repo.wlock()
994 try:
992 try:
995 if opts.get('clean'):
993 if opts.get('clean'):
996 label = repo[None].p1().branch()
994 label = repo[None].p1().branch()
997 repo.dirstate.setbranch(label)
995 repo.dirstate.setbranch(label)
998 ui.status(_('reset working directory to branch %s\n') % label)
996 ui.status(_('reset working directory to branch %s\n') % label)
999 elif label:
997 elif label:
1000 if not opts.get('force') and label in repo.branchmap():
998 if not opts.get('force') and label in repo.branchmap():
1001 if label not in [p.branch() for p in repo.parents()]:
999 if label not in [p.branch() for p in repo.parents()]:
1002 raise util.Abort(_('a branch of the same name already'
1000 raise util.Abort(_('a branch of the same name already'
1003 ' exists'),
1001 ' exists'),
1004 # i18n: "it" refers to an existing branch
1002 # i18n: "it" refers to an existing branch
1005 hint=_("use 'hg update' to switch to it"))
1003 hint=_("use 'hg update' to switch to it"))
1006 scmutil.checknewlabel(repo, label, 'branch')
1004 scmutil.checknewlabel(repo, label, 'branch')
1007 repo.dirstate.setbranch(label)
1005 repo.dirstate.setbranch(label)
1008 ui.status(_('marked working directory as branch %s\n') % label)
1006 ui.status(_('marked working directory as branch %s\n') % label)
1009 ui.status(_('(branches are permanent and global, '
1007 ui.status(_('(branches are permanent and global, '
1010 'did you want a bookmark?)\n'))
1008 'did you want a bookmark?)\n'))
1011 finally:
1009 finally:
1012 wlock.release()
1010 wlock.release()
1013
1011
1014 @command('branches',
1012 @command('branches',
1015 [('a', 'active', False, _('show only branches that have unmerged heads')),
1013 [('a', 'active', False, _('show only branches that have unmerged heads')),
1016 ('c', 'closed', False, _('show normal and closed branches'))],
1014 ('c', 'closed', False, _('show normal and closed branches'))],
1017 _('[-ac]'))
1015 _('[-ac]'))
1018 def branches(ui, repo, active=False, closed=False):
1016 def branches(ui, repo, active=False, closed=False):
1019 """list repository named branches
1017 """list repository named branches
1020
1018
1021 List the repository's named branches, indicating which ones are
1019 List the repository's named branches, indicating which ones are
1022 inactive. If -c/--closed is specified, also list branches which have
1020 inactive. If -c/--closed is specified, also list branches which have
1023 been marked closed (see :hg:`commit --close-branch`).
1021 been marked closed (see :hg:`commit --close-branch`).
1024
1022
1025 If -a/--active is specified, only show active branches. A branch
1023 If -a/--active is specified, only show active branches. A branch
1026 is considered active if it contains repository heads.
1024 is considered active if it contains repository heads.
1027
1025
1028 Use the command :hg:`update` to switch to an existing branch.
1026 Use the command :hg:`update` to switch to an existing branch.
1029
1027
1030 Returns 0.
1028 Returns 0.
1031 """
1029 """
1032
1030
1033 hexfunc = ui.debugflag and hex or short
1031 hexfunc = ui.debugflag and hex or short
1034
1032
1035 allheads = set(repo.heads())
1033 allheads = set(repo.heads())
1036 branches = []
1034 branches = []
1037 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1035 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1038 isactive = not isclosed and bool(set(heads) & allheads)
1036 isactive = not isclosed and bool(set(heads) & allheads)
1039 branches.append((tag, repo[tip], isactive, not isclosed))
1037 branches.append((tag, repo[tip], isactive, not isclosed))
1040 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]),
1041 reverse=True)
1039 reverse=True)
1042
1040
1043 for tag, ctx, isactive, isopen in branches:
1041 for tag, ctx, isactive, isopen in branches:
1044 if (not active) or isactive:
1042 if (not active) or isactive:
1045 if isactive:
1043 if isactive:
1046 label = 'branches.active'
1044 label = 'branches.active'
1047 notice = ''
1045 notice = ''
1048 elif not isopen:
1046 elif not isopen:
1049 if not closed:
1047 if not closed:
1050 continue
1048 continue
1051 label = 'branches.closed'
1049 label = 'branches.closed'
1052 notice = _(' (closed)')
1050 notice = _(' (closed)')
1053 else:
1051 else:
1054 label = 'branches.inactive'
1052 label = 'branches.inactive'
1055 notice = _(' (inactive)')
1053 notice = _(' (inactive)')
1056 if tag == repo.dirstate.branch():
1054 if tag == repo.dirstate.branch():
1057 label = 'branches.current'
1055 label = 'branches.current'
1058 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1056 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1059 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1057 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1060 'log.changeset changeset.%s' % ctx.phasestr())
1058 'log.changeset changeset.%s' % ctx.phasestr())
1061 labeledtag = ui.label(tag, label)
1059 labeledtag = ui.label(tag, label)
1062 if ui.quiet:
1060 if ui.quiet:
1063 ui.write("%s\n" % labeledtag)
1061 ui.write("%s\n" % labeledtag)
1064 else:
1062 else:
1065 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1063 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1066
1064
1067 @command('bundle',
1065 @command('bundle',
1068 [('f', 'force', None, _('run even when the destination is unrelated')),
1066 [('f', 'force', None, _('run even when the destination is unrelated')),
1069 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1067 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1070 _('REV')),
1068 _('REV')),
1071 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1069 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1072 _('BRANCH')),
1070 _('BRANCH')),
1073 ('', 'base', [],
1071 ('', 'base', [],
1074 _('a base changeset assumed to be available at the destination'),
1072 _('a base changeset assumed to be available at the destination'),
1075 _('REV')),
1073 _('REV')),
1076 ('a', 'all', None, _('bundle all changesets in the repository')),
1074 ('a', 'all', None, _('bundle all changesets in the repository')),
1077 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1075 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1078 ] + remoteopts,
1076 ] + remoteopts,
1079 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1077 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1080 def bundle(ui, repo, fname, dest=None, **opts):
1078 def bundle(ui, repo, fname, dest=None, **opts):
1081 """create a changegroup file
1079 """create a changegroup file
1082
1080
1083 Generate a compressed changegroup file collecting changesets not
1081 Generate a compressed changegroup file collecting changesets not
1084 known to be in another repository.
1082 known to be in another repository.
1085
1083
1086 If you omit the destination repository, then hg assumes the
1084 If you omit the destination repository, then hg assumes the
1087 destination will have all the nodes you specify with --base
1085 destination will have all the nodes you specify with --base
1088 parameters. To create a bundle containing all changesets, use
1086 parameters. To create a bundle containing all changesets, use
1089 -a/--all (or --base null).
1087 -a/--all (or --base null).
1090
1088
1091 You can change compression method with the -t/--type option.
1089 You can change compression method with the -t/--type option.
1092 The available compression methods are: none, bzip2, and
1090 The available compression methods are: none, bzip2, and
1093 gzip (by default, bundles are compressed using bzip2).
1091 gzip (by default, bundles are compressed using bzip2).
1094
1092
1095 The bundle file can then be transferred using conventional means
1093 The bundle file can then be transferred using conventional means
1096 and applied to another repository with the unbundle or pull
1094 and applied to another repository with the unbundle or pull
1097 command. This is useful when direct push and pull are not
1095 command. This is useful when direct push and pull are not
1098 available or when exporting an entire repository is undesirable.
1096 available or when exporting an entire repository is undesirable.
1099
1097
1100 Applying bundles preserves all changeset contents including
1098 Applying bundles preserves all changeset contents including
1101 permissions, copy/rename information, and revision history.
1099 permissions, copy/rename information, and revision history.
1102
1100
1103 Returns 0 on success, 1 if no changes found.
1101 Returns 0 on success, 1 if no changes found.
1104 """
1102 """
1105 revs = None
1103 revs = None
1106 if 'rev' in opts:
1104 if 'rev' in opts:
1107 revs = scmutil.revrange(repo, opts['rev'])
1105 revs = scmutil.revrange(repo, opts['rev'])
1108
1106
1109 bundletype = opts.get('type', 'bzip2').lower()
1107 bundletype = opts.get('type', 'bzip2').lower()
1110 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1108 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1111 bundletype = btypes.get(bundletype)
1109 bundletype = btypes.get(bundletype)
1112 if bundletype not in changegroup.bundletypes:
1110 if bundletype not in changegroup.bundletypes:
1113 raise util.Abort(_('unknown bundle type specified with --type'))
1111 raise util.Abort(_('unknown bundle type specified with --type'))
1114
1112
1115 if opts.get('all'):
1113 if opts.get('all'):
1116 base = ['null']
1114 base = ['null']
1117 else:
1115 else:
1118 base = scmutil.revrange(repo, opts.get('base'))
1116 base = scmutil.revrange(repo, opts.get('base'))
1119 # TODO: get desired bundlecaps from command line.
1117 # TODO: get desired bundlecaps from command line.
1120 bundlecaps = None
1118 bundlecaps = None
1121 if base:
1119 if base:
1122 if dest:
1120 if dest:
1123 raise util.Abort(_("--base is incompatible with specifying "
1121 raise util.Abort(_("--base is incompatible with specifying "
1124 "a destination"))
1122 "a destination"))
1125 common = [repo.lookup(rev) for rev in base]
1123 common = [repo.lookup(rev) for rev in base]
1126 heads = revs and map(repo.lookup, revs) or revs
1124 heads = revs and map(repo.lookup, revs) or revs
1127 cg = repo.getbundle('bundle', heads=heads, common=common,
1125 cg = repo.getbundle('bundle', heads=heads, common=common,
1128 bundlecaps=bundlecaps)
1126 bundlecaps=bundlecaps)
1129 outgoing = None
1127 outgoing = None
1130 else:
1128 else:
1131 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1132 dest, branches = hg.parseurl(dest, opts.get('branch'))
1130 dest, branches = hg.parseurl(dest, opts.get('branch'))
1133 other = hg.peer(repo, opts, dest)
1131 other = hg.peer(repo, opts, dest)
1134 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1132 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1135 heads = revs and map(repo.lookup, revs) or revs
1133 heads = revs and map(repo.lookup, revs) or revs
1136 outgoing = discovery.findcommonoutgoing(repo, other,
1134 outgoing = discovery.findcommonoutgoing(repo, other,
1137 onlyheads=heads,
1135 onlyheads=heads,
1138 force=opts.get('force'),
1136 force=opts.get('force'),
1139 portable=True)
1137 portable=True)
1140 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1138 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1141 if not cg:
1139 if not cg:
1142 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1140 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1143 return 1
1141 return 1
1144
1142
1145 changegroup.writebundle(cg, fname, bundletype)
1143 changegroup.writebundle(cg, fname, bundletype)
1146
1144
1147 @command('cat',
1145 @command('cat',
1148 [('o', 'output', '',
1146 [('o', 'output', '',
1149 _('print output to file with formatted name'), _('FORMAT')),
1147 _('print output to file with formatted name'), _('FORMAT')),
1150 ('r', 'rev', '', _('print the given revision'), _('REV')),
1148 ('r', 'rev', '', _('print the given revision'), _('REV')),
1151 ('', 'decode', None, _('apply any matching decode filter')),
1149 ('', 'decode', None, _('apply any matching decode filter')),
1152 ] + walkopts,
1150 ] + walkopts,
1153 _('[OPTION]... FILE...'))
1151 _('[OPTION]... FILE...'))
1154 def cat(ui, repo, file1, *pats, **opts):
1152 def cat(ui, repo, file1, *pats, **opts):
1155 """output the current or given revision of files
1153 """output the current or given revision of files
1156
1154
1157 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
1158 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.
1159
1157
1160 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
1161 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
1162 for the export command, with the following additions:
1160 for the export command, with the following additions:
1163
1161
1164 :``%s``: basename of file being printed
1162 :``%s``: basename of file being printed
1165 :``%d``: dirname of file being printed, or '.' if in repository root
1163 :``%d``: dirname of file being printed, or '.' if in repository root
1166 :``%p``: root-relative path name of file being printed
1164 :``%p``: root-relative path name of file being printed
1167
1165
1168 Returns 0 on success.
1166 Returns 0 on success.
1169 """
1167 """
1170 ctx = scmutil.revsingle(repo, opts.get('rev'))
1168 ctx = scmutil.revsingle(repo, opts.get('rev'))
1171 err = 1
1169 err = 1
1172 m = scmutil.match(ctx, (file1,) + pats, opts)
1170 m = scmutil.match(ctx, (file1,) + pats, opts)
1173 for abs in ctx.walk(m):
1171 for abs in ctx.walk(m):
1174 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1172 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1175 pathname=abs)
1173 pathname=abs)
1176 data = ctx[abs].data()
1174 data = ctx[abs].data()
1177 if opts.get('decode'):
1175 if opts.get('decode'):
1178 data = repo.wwritedata(abs, data)
1176 data = repo.wwritedata(abs, data)
1179 fp.write(data)
1177 fp.write(data)
1180 fp.close()
1178 fp.close()
1181 err = 0
1179 err = 0
1182 return err
1180 return err
1183
1181
1184 @command('^clone',
1182 @command('^clone',
1185 [('U', 'noupdate', None,
1183 [('U', 'noupdate', None,
1186 _('the clone will include an empty working copy (only a repository)')),
1184 _('the clone will include an empty working copy (only a repository)')),
1187 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1185 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1188 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1186 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1189 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1187 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1190 ('', 'pull', None, _('use pull protocol to copy metadata')),
1188 ('', 'pull', None, _('use pull protocol to copy metadata')),
1191 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1189 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1192 ] + remoteopts,
1190 ] + remoteopts,
1193 _('[OPTION]... SOURCE [DEST]'))
1191 _('[OPTION]... SOURCE [DEST]'))
1194 def clone(ui, source, dest=None, **opts):
1192 def clone(ui, source, dest=None, **opts):
1195 """make a copy of an existing repository
1193 """make a copy of an existing repository
1196
1194
1197 Create a copy of an existing repository in a new directory.
1195 Create a copy of an existing repository in a new directory.
1198
1196
1199 If no destination directory name is specified, it defaults to the
1197 If no destination directory name is specified, it defaults to the
1200 basename of the source.
1198 basename of the source.
1201
1199
1202 The location of the source is added to the new repository's
1200 The location of the source is added to the new repository's
1203 ``.hg/hgrc`` file, as the default to be used for future pulls.
1201 ``.hg/hgrc`` file, as the default to be used for future pulls.
1204
1202
1205 Only local paths and ``ssh://`` URLs are supported as
1203 Only local paths and ``ssh://`` URLs are supported as
1206 destinations. For ``ssh://`` destinations, no working directory or
1204 destinations. For ``ssh://`` destinations, no working directory or
1207 ``.hg/hgrc`` will be created on the remote side.
1205 ``.hg/hgrc`` will be created on the remote side.
1208
1206
1209 To pull only a subset of changesets, specify one or more revisions
1207 To pull only a subset of changesets, specify one or more revisions
1210 identifiers with -r/--rev or branches with -b/--branch. The
1208 identifiers with -r/--rev or branches with -b/--branch. The
1211 resulting clone will contain only the specified changesets and
1209 resulting clone will contain only the specified changesets and
1212 their ancestors. These options (or 'clone src#rev dest') imply
1210 their ancestors. These options (or 'clone src#rev dest') imply
1213 --pull, even for local source repositories. Note that specifying a
1211 --pull, even for local source repositories. Note that specifying a
1214 tag will include the tagged changeset but not the changeset
1212 tag will include the tagged changeset but not the changeset
1215 containing the tag.
1213 containing the tag.
1216
1214
1217 If the source repository has a bookmark called '@' set, that
1215 If the source repository has a bookmark called '@' set, that
1218 revision will be checked out in the new repository by default.
1216 revision will be checked out in the new repository by default.
1219
1217
1220 To check out a particular version, use -u/--update, or
1218 To check out a particular version, use -u/--update, or
1221 -U/--noupdate to create a clone with no working directory.
1219 -U/--noupdate to create a clone with no working directory.
1222
1220
1223 .. container:: verbose
1221 .. container:: verbose
1224
1222
1225 For efficiency, hardlinks are used for cloning whenever the
1223 For efficiency, hardlinks are used for cloning whenever the
1226 source and destination are on the same filesystem (note this
1224 source and destination are on the same filesystem (note this
1227 applies only to the repository data, not to the working
1225 applies only to the repository data, not to the working
1228 directory). Some filesystems, such as AFS, implement hardlinking
1226 directory). Some filesystems, such as AFS, implement hardlinking
1229 incorrectly, but do not report errors. In these cases, use the
1227 incorrectly, but do not report errors. In these cases, use the
1230 --pull option to avoid hardlinking.
1228 --pull option to avoid hardlinking.
1231
1229
1232 In some cases, you can clone repositories and the working
1230 In some cases, you can clone repositories and the working
1233 directory using full hardlinks with ::
1231 directory using full hardlinks with ::
1234
1232
1235 $ cp -al REPO REPOCLONE
1233 $ cp -al REPO REPOCLONE
1236
1234
1237 This is the fastest way to clone, but it is not always safe. The
1235 This is the fastest way to clone, but it is not always safe. The
1238 operation is not atomic (making sure REPO is not modified during
1236 operation is not atomic (making sure REPO is not modified during
1239 the operation is up to you) and you have to make sure your
1237 the operation is up to you) and you have to make sure your
1240 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1238 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1241 so). Also, this is not compatible with certain extensions that
1239 so). Also, this is not compatible with certain extensions that
1242 place their metadata under the .hg directory, such as mq.
1240 place their metadata under the .hg directory, such as mq.
1243
1241
1244 Mercurial will update the working directory to the first applicable
1242 Mercurial will update the working directory to the first applicable
1245 revision from this list:
1243 revision from this list:
1246
1244
1247 a) null if -U or the source repository has no changesets
1245 a) null if -U or the source repository has no changesets
1248 b) if -u . and the source repository is local, the first parent of
1246 b) if -u . and the source repository is local, the first parent of
1249 the source repository's working directory
1247 the source repository's working directory
1250 c) the changeset specified with -u (if a branch name, this means the
1248 c) the changeset specified with -u (if a branch name, this means the
1251 latest head of that branch)
1249 latest head of that branch)
1252 d) the changeset specified with -r
1250 d) the changeset specified with -r
1253 e) the tipmost head specified with -b
1251 e) the tipmost head specified with -b
1254 f) the tipmost head specified with the url#branch source syntax
1252 f) the tipmost head specified with the url#branch source syntax
1255 g) the revision marked with the '@' bookmark, if present
1253 g) the revision marked with the '@' bookmark, if present
1256 h) the tipmost head of the default branch
1254 h) the tipmost head of the default branch
1257 i) tip
1255 i) tip
1258
1256
1259 Examples:
1257 Examples:
1260
1258
1261 - clone a remote repository to a new directory named hg/::
1259 - clone a remote repository to a new directory named hg/::
1262
1260
1263 hg clone http://selenic.com/hg
1261 hg clone http://selenic.com/hg
1264
1262
1265 - create a lightweight local clone::
1263 - create a lightweight local clone::
1266
1264
1267 hg clone project/ project-feature/
1265 hg clone project/ project-feature/
1268
1266
1269 - clone from an absolute path on an ssh server (note double-slash)::
1267 - clone from an absolute path on an ssh server (note double-slash)::
1270
1268
1271 hg clone ssh://user@server//home/projects/alpha/
1269 hg clone ssh://user@server//home/projects/alpha/
1272
1270
1273 - do a high-speed clone over a LAN while checking out a
1271 - do a high-speed clone over a LAN while checking out a
1274 specified version::
1272 specified version::
1275
1273
1276 hg clone --uncompressed http://server/repo -u 1.5
1274 hg clone --uncompressed http://server/repo -u 1.5
1277
1275
1278 - create a repository without changesets after a particular revision::
1276 - create a repository without changesets after a particular revision::
1279
1277
1280 hg clone -r 04e544 experimental/ good/
1278 hg clone -r 04e544 experimental/ good/
1281
1279
1282 - clone (and track) a particular named branch::
1280 - clone (and track) a particular named branch::
1283
1281
1284 hg clone http://selenic.com/hg#stable
1282 hg clone http://selenic.com/hg#stable
1285
1283
1286 See :hg:`help urls` for details on specifying URLs.
1284 See :hg:`help urls` for details on specifying URLs.
1287
1285
1288 Returns 0 on success.
1286 Returns 0 on success.
1289 """
1287 """
1290 if opts.get('noupdate') and opts.get('updaterev'):
1288 if opts.get('noupdate') and opts.get('updaterev'):
1291 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1289 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1292
1290
1293 r = hg.clone(ui, opts, source, dest,
1291 r = hg.clone(ui, opts, source, dest,
1294 pull=opts.get('pull'),
1292 pull=opts.get('pull'),
1295 stream=opts.get('uncompressed'),
1293 stream=opts.get('uncompressed'),
1296 rev=opts.get('rev'),
1294 rev=opts.get('rev'),
1297 update=opts.get('updaterev') or not opts.get('noupdate'),
1295 update=opts.get('updaterev') or not opts.get('noupdate'),
1298 branch=opts.get('branch'))
1296 branch=opts.get('branch'))
1299
1297
1300 return r is None
1298 return r is None
1301
1299
1302 @command('^commit|ci',
1300 @command('^commit|ci',
1303 [('A', 'addremove', None,
1301 [('A', 'addremove', None,
1304 _('mark new/missing files as added/removed before committing')),
1302 _('mark new/missing files as added/removed before committing')),
1305 ('', 'close-branch', None,
1303 ('', 'close-branch', None,
1306 _('mark a branch as closed, hiding it from the branch list')),
1304 _('mark a branch as closed, hiding it from the branch list')),
1307 ('', 'amend', None, _('amend the parent of the working dir')),
1305 ('', 'amend', None, _('amend the parent of the working dir')),
1308 ('s', 'secret', None, _('use the secret phase for committing')),
1306 ('s', 'secret', None, _('use the secret phase for committing')),
1309 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1307 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1310 _('[OPTION]... [FILE]...'))
1308 _('[OPTION]... [FILE]...'))
1311 def commit(ui, repo, *pats, **opts):
1309 def commit(ui, repo, *pats, **opts):
1312 """commit the specified files or all outstanding changes
1310 """commit the specified files or all outstanding changes
1313
1311
1314 Commit changes to the given files into the repository. Unlike a
1312 Commit changes to the given files into the repository. Unlike a
1315 centralized SCM, this operation is a local operation. See
1313 centralized SCM, this operation is a local operation. See
1316 :hg:`push` for a way to actively distribute your changes.
1314 :hg:`push` for a way to actively distribute your changes.
1317
1315
1318 If a list of files is omitted, all changes reported by :hg:`status`
1316 If a list of files is omitted, all changes reported by :hg:`status`
1319 will be committed.
1317 will be committed.
1320
1318
1321 If you are committing the result of a merge, do not provide any
1319 If you are committing the result of a merge, do not provide any
1322 filenames or -I/-X filters.
1320 filenames or -I/-X filters.
1323
1321
1324 If no commit message is specified, Mercurial starts your
1322 If no commit message is specified, Mercurial starts your
1325 configured editor where you can enter a message. In case your
1323 configured editor where you can enter a message. In case your
1326 commit fails, you will find a backup of your message in
1324 commit fails, you will find a backup of your message in
1327 ``.hg/last-message.txt``.
1325 ``.hg/last-message.txt``.
1328
1326
1329 The --amend flag can be used to amend the parent of the
1327 The --amend flag can be used to amend the parent of the
1330 working directory with a new commit that contains the changes
1328 working directory with a new commit that contains the changes
1331 in the parent in addition to those currently reported by :hg:`status`,
1329 in the parent in addition to those currently reported by :hg:`status`,
1332 if there are any. The old commit is stored in a backup bundle in
1330 if there are any. The old commit is stored in a backup bundle in
1333 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1331 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1334 on how to restore it).
1332 on how to restore it).
1335
1333
1336 Message, user and date are taken from the amended commit unless
1334 Message, user and date are taken from the amended commit unless
1337 specified. When a message isn't specified on the command line,
1335 specified. When a message isn't specified on the command line,
1338 the editor will open with the message of the amended commit.
1336 the editor will open with the message of the amended commit.
1339
1337
1340 It is not possible to amend public changesets (see :hg:`help phases`)
1338 It is not possible to amend public changesets (see :hg:`help phases`)
1341 or changesets that have children.
1339 or changesets that have children.
1342
1340
1343 See :hg:`help dates` for a list of formats valid for -d/--date.
1341 See :hg:`help dates` for a list of formats valid for -d/--date.
1344
1342
1345 Returns 0 on success, 1 if nothing changed.
1343 Returns 0 on success, 1 if nothing changed.
1346 """
1344 """
1347 if opts.get('subrepos'):
1345 if opts.get('subrepos'):
1348 if opts.get('amend'):
1346 if opts.get('amend'):
1349 raise util.Abort(_('cannot amend with --subrepos'))
1347 raise util.Abort(_('cannot amend with --subrepos'))
1350 # Let --subrepos on the command line override config setting.
1348 # Let --subrepos on the command line override config setting.
1351 ui.setconfig('ui', 'commitsubrepos', True)
1349 ui.setconfig('ui', 'commitsubrepos', True)
1352
1350
1353 # Save this for restoring it later
1351 # Save this for restoring it later
1354 oldcommitphase = ui.config('phases', 'new-commit')
1352 oldcommitphase = ui.config('phases', 'new-commit')
1355
1353
1356 cmdutil.checkunfinished(repo, commit=True)
1354 cmdutil.checkunfinished(repo, commit=True)
1357
1355
1358 branch = repo[None].branch()
1356 branch = repo[None].branch()
1359 bheads = repo.branchheads(branch)
1357 bheads = repo.branchheads(branch)
1360
1358
1361 extra = {}
1359 extra = {}
1362 if opts.get('close_branch'):
1360 if opts.get('close_branch'):
1363 extra['close'] = 1
1361 extra['close'] = 1
1364
1362
1365 if not bheads:
1363 if not bheads:
1366 raise util.Abort(_('can only close branch heads'))
1364 raise util.Abort(_('can only close branch heads'))
1367 elif opts.get('amend'):
1365 elif opts.get('amend'):
1368 if repo.parents()[0].p1().branch() != branch and \
1366 if repo.parents()[0].p1().branch() != branch and \
1369 repo.parents()[0].p2().branch() != branch:
1367 repo.parents()[0].p2().branch() != branch:
1370 raise util.Abort(_('can only close branch heads'))
1368 raise util.Abort(_('can only close branch heads'))
1371
1369
1372 if opts.get('amend'):
1370 if opts.get('amend'):
1373 if ui.configbool('ui', 'commitsubrepos'):
1371 if ui.configbool('ui', 'commitsubrepos'):
1374 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1372 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1375
1373
1376 old = repo['.']
1374 old = repo['.']
1377 if old.phase() == phases.public:
1375 if old.phase() == phases.public:
1378 raise util.Abort(_('cannot amend public changesets'))
1376 raise util.Abort(_('cannot amend public changesets'))
1379 if len(repo[None].parents()) > 1:
1377 if len(repo[None].parents()) > 1:
1380 raise util.Abort(_('cannot amend while merging'))
1378 raise util.Abort(_('cannot amend while merging'))
1381 if (not obsolete._enabled) and old.children():
1379 if (not obsolete._enabled) and old.children():
1382 raise util.Abort(_('cannot amend changeset with children'))
1380 raise util.Abort(_('cannot amend changeset with children'))
1383
1381
1384 e = cmdutil.commiteditor
1382 e = cmdutil.commiteditor
1385 if opts.get('force_editor'):
1383 if opts.get('force_editor'):
1386 e = cmdutil.commitforceeditor
1384 e = cmdutil.commitforceeditor
1387
1385
1388 def commitfunc(ui, repo, message, match, opts):
1386 def commitfunc(ui, repo, message, match, opts):
1389 editor = e
1387 editor = e
1390 # message contains text from -m or -l, if it's empty,
1388 # message contains text from -m or -l, if it's empty,
1391 # open the editor with the old message
1389 # open the editor with the old message
1392 if not message:
1390 if not message:
1393 message = old.description()
1391 message = old.description()
1394 editor = cmdutil.commitforceeditor
1392 editor = cmdutil.commitforceeditor
1395 try:
1393 try:
1396 if opts.get('secret'):
1394 if opts.get('secret'):
1397 ui.setconfig('phases', 'new-commit', 'secret')
1395 ui.setconfig('phases', 'new-commit', 'secret')
1398
1396
1399 return repo.commit(message,
1397 return repo.commit(message,
1400 opts.get('user') or old.user(),
1398 opts.get('user') or old.user(),
1401 opts.get('date') or old.date(),
1399 opts.get('date') or old.date(),
1402 match,
1400 match,
1403 editor=editor,
1401 editor=editor,
1404 extra=extra)
1402 extra=extra)
1405 finally:
1403 finally:
1406 ui.setconfig('phases', 'new-commit', oldcommitphase)
1404 ui.setconfig('phases', 'new-commit', oldcommitphase)
1407
1405
1408 current = repo._bookmarkcurrent
1406 current = repo._bookmarkcurrent
1409 marks = old.bookmarks()
1407 marks = old.bookmarks()
1410 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1408 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1411 if node == old.node():
1409 if node == old.node():
1412 ui.status(_("nothing changed\n"))
1410 ui.status(_("nothing changed\n"))
1413 return 1
1411 return 1
1414 elif marks:
1412 elif marks:
1415 ui.debug('moving bookmarks %r from %s to %s\n' %
1413 ui.debug('moving bookmarks %r from %s to %s\n' %
1416 (marks, old.hex(), hex(node)))
1414 (marks, old.hex(), hex(node)))
1417 newmarks = repo._bookmarks
1415 newmarks = repo._bookmarks
1418 for bm in marks:
1416 for bm in marks:
1419 newmarks[bm] = node
1417 newmarks[bm] = node
1420 if bm == current:
1418 if bm == current:
1421 bookmarks.setcurrent(repo, bm)
1419 bookmarks.setcurrent(repo, bm)
1422 newmarks.write()
1420 newmarks.write()
1423 else:
1421 else:
1424 e = cmdutil.commiteditor
1422 e = cmdutil.commiteditor
1425 if opts.get('force_editor'):
1423 if opts.get('force_editor'):
1426 e = cmdutil.commitforceeditor
1424 e = cmdutil.commitforceeditor
1427
1425
1428 def commitfunc(ui, repo, message, match, opts):
1426 def commitfunc(ui, repo, message, match, opts):
1429 try:
1427 try:
1430 if opts.get('secret'):
1428 if opts.get('secret'):
1431 ui.setconfig('phases', 'new-commit', 'secret')
1429 ui.setconfig('phases', 'new-commit', 'secret')
1432
1430
1433 return repo.commit(message, opts.get('user'), opts.get('date'),
1431 return repo.commit(message, opts.get('user'), opts.get('date'),
1434 match, editor=e, extra=extra)
1432 match, editor=e, extra=extra)
1435 finally:
1433 finally:
1436 ui.setconfig('phases', 'new-commit', oldcommitphase)
1434 ui.setconfig('phases', 'new-commit', oldcommitphase)
1437
1435
1438
1436
1439 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1437 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1440
1438
1441 if not node:
1439 if not node:
1442 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1440 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1443 if stat[3]:
1441 if stat[3]:
1444 ui.status(_("nothing changed (%d missing files, see "
1442 ui.status(_("nothing changed (%d missing files, see "
1445 "'hg status')\n") % len(stat[3]))
1443 "'hg status')\n") % len(stat[3]))
1446 else:
1444 else:
1447 ui.status(_("nothing changed\n"))
1445 ui.status(_("nothing changed\n"))
1448 return 1
1446 return 1
1449
1447
1450 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1448 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1451
1449
1452 @command('copy|cp',
1450 @command('copy|cp',
1453 [('A', 'after', None, _('record a copy that has already occurred')),
1451 [('A', 'after', None, _('record a copy that has already occurred')),
1454 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1452 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1455 ] + walkopts + dryrunopts,
1453 ] + walkopts + dryrunopts,
1456 _('[OPTION]... [SOURCE]... DEST'))
1454 _('[OPTION]... [SOURCE]... DEST'))
1457 def copy(ui, repo, *pats, **opts):
1455 def copy(ui, repo, *pats, **opts):
1458 """mark files as copied for the next commit
1456 """mark files as copied for the next commit
1459
1457
1460 Mark dest as having copies of source files. If dest is a
1458 Mark dest as having copies of source files. If dest is a
1461 directory, copies are put in that directory. If dest is a file,
1459 directory, copies are put in that directory. If dest is a file,
1462 the source must be a single file.
1460 the source must be a single file.
1463
1461
1464 By default, this command copies the contents of files as they
1462 By default, this command copies the contents of files as they
1465 exist in the working directory. If invoked with -A/--after, the
1463 exist in the working directory. If invoked with -A/--after, the
1466 operation is recorded, but no copying is performed.
1464 operation is recorded, but no copying is performed.
1467
1465
1468 This command takes effect with the next commit. To undo a copy
1466 This command takes effect with the next commit. To undo a copy
1469 before that, see :hg:`revert`.
1467 before that, see :hg:`revert`.
1470
1468
1471 Returns 0 on success, 1 if errors are encountered.
1469 Returns 0 on success, 1 if errors are encountered.
1472 """
1470 """
1473 wlock = repo.wlock(False)
1471 wlock = repo.wlock(False)
1474 try:
1472 try:
1475 return cmdutil.copy(ui, repo, pats, opts)
1473 return cmdutil.copy(ui, repo, pats, opts)
1476 finally:
1474 finally:
1477 wlock.release()
1475 wlock.release()
1478
1476
1479 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1477 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1480 def debugancestor(ui, repo, *args):
1478 def debugancestor(ui, repo, *args):
1481 """find the ancestor revision of two revisions in a given index"""
1479 """find the ancestor revision of two revisions in a given index"""
1482 if len(args) == 3:
1480 if len(args) == 3:
1483 index, rev1, rev2 = args
1481 index, rev1, rev2 = args
1484 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1482 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1485 lookup = r.lookup
1483 lookup = r.lookup
1486 elif len(args) == 2:
1484 elif len(args) == 2:
1487 if not repo:
1485 if not repo:
1488 raise util.Abort(_("there is no Mercurial repository here "
1486 raise util.Abort(_("there is no Mercurial repository here "
1489 "(.hg not found)"))
1487 "(.hg not found)"))
1490 rev1, rev2 = args
1488 rev1, rev2 = args
1491 r = repo.changelog
1489 r = repo.changelog
1492 lookup = repo.lookup
1490 lookup = repo.lookup
1493 else:
1491 else:
1494 raise util.Abort(_('either two or three arguments required'))
1492 raise util.Abort(_('either two or three arguments required'))
1495 a = r.ancestor(lookup(rev1), lookup(rev2))
1493 a = r.ancestor(lookup(rev1), lookup(rev2))
1496 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1494 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1497
1495
1498 @command('debugbuilddag',
1496 @command('debugbuilddag',
1499 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1497 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1500 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1498 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1501 ('n', 'new-file', None, _('add new file at each rev'))],
1499 ('n', 'new-file', None, _('add new file at each rev'))],
1502 _('[OPTION]... [TEXT]'))
1500 _('[OPTION]... [TEXT]'))
1503 def debugbuilddag(ui, repo, text=None,
1501 def debugbuilddag(ui, repo, text=None,
1504 mergeable_file=False,
1502 mergeable_file=False,
1505 overwritten_file=False,
1503 overwritten_file=False,
1506 new_file=False):
1504 new_file=False):
1507 """builds a repo with a given DAG from scratch in the current empty repo
1505 """builds a repo with a given DAG from scratch in the current empty repo
1508
1506
1509 The description of the DAG is read from stdin if not given on the
1507 The description of the DAG is read from stdin if not given on the
1510 command line.
1508 command line.
1511
1509
1512 Elements:
1510 Elements:
1513
1511
1514 - "+n" is a linear run of n nodes based on the current default parent
1512 - "+n" is a linear run of n nodes based on the current default parent
1515 - "." is a single node based on the current default parent
1513 - "." is a single node based on the current default parent
1516 - "$" resets the default parent to null (implied at the start);
1514 - "$" resets the default parent to null (implied at the start);
1517 otherwise the default parent is always the last node created
1515 otherwise the default parent is always the last node created
1518 - "<p" sets the default parent to the backref p
1516 - "<p" sets the default parent to the backref p
1519 - "*p" is a fork at parent p, which is a backref
1517 - "*p" is a fork at parent p, which is a backref
1520 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1518 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1521 - "/p2" is a merge of the preceding node and p2
1519 - "/p2" is a merge of the preceding node and p2
1522 - ":tag" defines a local tag for the preceding node
1520 - ":tag" defines a local tag for the preceding node
1523 - "@branch" sets the named branch for subsequent nodes
1521 - "@branch" sets the named branch for subsequent nodes
1524 - "#...\\n" is a comment up to the end of the line
1522 - "#...\\n" is a comment up to the end of the line
1525
1523
1526 Whitespace between the above elements is ignored.
1524 Whitespace between the above elements is ignored.
1527
1525
1528 A backref is either
1526 A backref is either
1529
1527
1530 - a number n, which references the node curr-n, where curr is the current
1528 - a number n, which references the node curr-n, where curr is the current
1531 node, or
1529 node, or
1532 - the name of a local tag you placed earlier using ":tag", or
1530 - the name of a local tag you placed earlier using ":tag", or
1533 - empty to denote the default parent.
1531 - empty to denote the default parent.
1534
1532
1535 All string valued-elements are either strictly alphanumeric, or must
1533 All string valued-elements are either strictly alphanumeric, or must
1536 be enclosed in double quotes ("..."), with "\\" as escape character.
1534 be enclosed in double quotes ("..."), with "\\" as escape character.
1537 """
1535 """
1538
1536
1539 if text is None:
1537 if text is None:
1540 ui.status(_("reading DAG from stdin\n"))
1538 ui.status(_("reading DAG from stdin\n"))
1541 text = ui.fin.read()
1539 text = ui.fin.read()
1542
1540
1543 cl = repo.changelog
1541 cl = repo.changelog
1544 if len(cl) > 0:
1542 if len(cl) > 0:
1545 raise util.Abort(_('repository is not empty'))
1543 raise util.Abort(_('repository is not empty'))
1546
1544
1547 # determine number of revs in DAG
1545 # determine number of revs in DAG
1548 total = 0
1546 total = 0
1549 for type, data in dagparser.parsedag(text):
1547 for type, data in dagparser.parsedag(text):
1550 if type == 'n':
1548 if type == 'n':
1551 total += 1
1549 total += 1
1552
1550
1553 if mergeable_file:
1551 if mergeable_file:
1554 linesperrev = 2
1552 linesperrev = 2
1555 # make a file with k lines per rev
1553 # make a file with k lines per rev
1556 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1554 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1557 initialmergedlines.append("")
1555 initialmergedlines.append("")
1558
1556
1559 tags = []
1557 tags = []
1560
1558
1561 lock = tr = None
1559 lock = tr = None
1562 try:
1560 try:
1563 lock = repo.lock()
1561 lock = repo.lock()
1564 tr = repo.transaction("builddag")
1562 tr = repo.transaction("builddag")
1565
1563
1566 at = -1
1564 at = -1
1567 atbranch = 'default'
1565 atbranch = 'default'
1568 nodeids = []
1566 nodeids = []
1569 id = 0
1567 id = 0
1570 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1568 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1571 for type, data in dagparser.parsedag(text):
1569 for type, data in dagparser.parsedag(text):
1572 if type == 'n':
1570 if type == 'n':
1573 ui.note(('node %s\n' % str(data)))
1571 ui.note(('node %s\n' % str(data)))
1574 id, ps = data
1572 id, ps = data
1575
1573
1576 files = []
1574 files = []
1577 fctxs = {}
1575 fctxs = {}
1578
1576
1579 p2 = None
1577 p2 = None
1580 if mergeable_file:
1578 if mergeable_file:
1581 fn = "mf"
1579 fn = "mf"
1582 p1 = repo[ps[0]]
1580 p1 = repo[ps[0]]
1583 if len(ps) > 1:
1581 if len(ps) > 1:
1584 p2 = repo[ps[1]]
1582 p2 = repo[ps[1]]
1585 pa = p1.ancestor(p2)
1583 pa = p1.ancestor(p2)
1586 base, local, other = [x[fn].data() for x in (pa, p1,
1584 base, local, other = [x[fn].data() for x in (pa, p1,
1587 p2)]
1585 p2)]
1588 m3 = simplemerge.Merge3Text(base, local, other)
1586 m3 = simplemerge.Merge3Text(base, local, other)
1589 ml = [l.strip() for l in m3.merge_lines()]
1587 ml = [l.strip() for l in m3.merge_lines()]
1590 ml.append("")
1588 ml.append("")
1591 elif at > 0:
1589 elif at > 0:
1592 ml = p1[fn].data().split("\n")
1590 ml = p1[fn].data().split("\n")
1593 else:
1591 else:
1594 ml = initialmergedlines
1592 ml = initialmergedlines
1595 ml[id * linesperrev] += " r%i" % id
1593 ml[id * linesperrev] += " r%i" % id
1596 mergedtext = "\n".join(ml)
1594 mergedtext = "\n".join(ml)
1597 files.append(fn)
1595 files.append(fn)
1598 fctxs[fn] = context.memfilectx(fn, mergedtext)
1596 fctxs[fn] = context.memfilectx(fn, mergedtext)
1599
1597
1600 if overwritten_file:
1598 if overwritten_file:
1601 fn = "of"
1599 fn = "of"
1602 files.append(fn)
1600 files.append(fn)
1603 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1601 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1604
1602
1605 if new_file:
1603 if new_file:
1606 fn = "nf%i" % id
1604 fn = "nf%i" % id
1607 files.append(fn)
1605 files.append(fn)
1608 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1606 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1609 if len(ps) > 1:
1607 if len(ps) > 1:
1610 if not p2:
1608 if not p2:
1611 p2 = repo[ps[1]]
1609 p2 = repo[ps[1]]
1612 for fn in p2:
1610 for fn in p2:
1613 if fn.startswith("nf"):
1611 if fn.startswith("nf"):
1614 files.append(fn)
1612 files.append(fn)
1615 fctxs[fn] = p2[fn]
1613 fctxs[fn] = p2[fn]
1616
1614
1617 def fctxfn(repo, cx, path):
1615 def fctxfn(repo, cx, path):
1618 return fctxs.get(path)
1616 return fctxs.get(path)
1619
1617
1620 if len(ps) == 0 or ps[0] < 0:
1618 if len(ps) == 0 or ps[0] < 0:
1621 pars = [None, None]
1619 pars = [None, None]
1622 elif len(ps) == 1:
1620 elif len(ps) == 1:
1623 pars = [nodeids[ps[0]], None]
1621 pars = [nodeids[ps[0]], None]
1624 else:
1622 else:
1625 pars = [nodeids[p] for p in ps]
1623 pars = [nodeids[p] for p in ps]
1626 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1624 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1627 date=(id, 0),
1625 date=(id, 0),
1628 user="debugbuilddag",
1626 user="debugbuilddag",
1629 extra={'branch': atbranch})
1627 extra={'branch': atbranch})
1630 nodeid = repo.commitctx(cx)
1628 nodeid = repo.commitctx(cx)
1631 nodeids.append(nodeid)
1629 nodeids.append(nodeid)
1632 at = id
1630 at = id
1633 elif type == 'l':
1631 elif type == 'l':
1634 id, name = data
1632 id, name = data
1635 ui.note(('tag %s\n' % name))
1633 ui.note(('tag %s\n' % name))
1636 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1634 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1637 elif type == 'a':
1635 elif type == 'a':
1638 ui.note(('branch %s\n' % data))
1636 ui.note(('branch %s\n' % data))
1639 atbranch = data
1637 atbranch = data
1640 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1638 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1641 tr.close()
1639 tr.close()
1642
1640
1643 if tags:
1641 if tags:
1644 repo.opener.write("localtags", "".join(tags))
1642 repo.opener.write("localtags", "".join(tags))
1645 finally:
1643 finally:
1646 ui.progress(_('building'), None)
1644 ui.progress(_('building'), None)
1647 release(tr, lock)
1645 release(tr, lock)
1648
1646
1649 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1647 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1650 def debugbundle(ui, bundlepath, all=None, **opts):
1648 def debugbundle(ui, bundlepath, all=None, **opts):
1651 """lists the contents of a bundle"""
1649 """lists the contents of a bundle"""
1652 f = hg.openpath(ui, bundlepath)
1650 f = hg.openpath(ui, bundlepath)
1653 try:
1651 try:
1654 gen = changegroup.readbundle(f, bundlepath)
1652 gen = changegroup.readbundle(f, bundlepath)
1655 if all:
1653 if all:
1656 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1654 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1657
1655
1658 def showchunks(named):
1656 def showchunks(named):
1659 ui.write("\n%s\n" % named)
1657 ui.write("\n%s\n" % named)
1660 chain = None
1658 chain = None
1661 while True:
1659 while True:
1662 chunkdata = gen.deltachunk(chain)
1660 chunkdata = gen.deltachunk(chain)
1663 if not chunkdata:
1661 if not chunkdata:
1664 break
1662 break
1665 node = chunkdata['node']
1663 node = chunkdata['node']
1666 p1 = chunkdata['p1']
1664 p1 = chunkdata['p1']
1667 p2 = chunkdata['p2']
1665 p2 = chunkdata['p2']
1668 cs = chunkdata['cs']
1666 cs = chunkdata['cs']
1669 deltabase = chunkdata['deltabase']
1667 deltabase = chunkdata['deltabase']
1670 delta = chunkdata['delta']
1668 delta = chunkdata['delta']
1671 ui.write("%s %s %s %s %s %s\n" %
1669 ui.write("%s %s %s %s %s %s\n" %
1672 (hex(node), hex(p1), hex(p2),
1670 (hex(node), hex(p1), hex(p2),
1673 hex(cs), hex(deltabase), len(delta)))
1671 hex(cs), hex(deltabase), len(delta)))
1674 chain = node
1672 chain = node
1675
1673
1676 chunkdata = gen.changelogheader()
1674 chunkdata = gen.changelogheader()
1677 showchunks("changelog")
1675 showchunks("changelog")
1678 chunkdata = gen.manifestheader()
1676 chunkdata = gen.manifestheader()
1679 showchunks("manifest")
1677 showchunks("manifest")
1680 while True:
1678 while True:
1681 chunkdata = gen.filelogheader()
1679 chunkdata = gen.filelogheader()
1682 if not chunkdata:
1680 if not chunkdata:
1683 break
1681 break
1684 fname = chunkdata['filename']
1682 fname = chunkdata['filename']
1685 showchunks(fname)
1683 showchunks(fname)
1686 else:
1684 else:
1687 chunkdata = gen.changelogheader()
1685 chunkdata = gen.changelogheader()
1688 chain = None
1686 chain = None
1689 while True:
1687 while True:
1690 chunkdata = gen.deltachunk(chain)
1688 chunkdata = gen.deltachunk(chain)
1691 if not chunkdata:
1689 if not chunkdata:
1692 break
1690 break
1693 node = chunkdata['node']
1691 node = chunkdata['node']
1694 ui.write("%s\n" % hex(node))
1692 ui.write("%s\n" % hex(node))
1695 chain = node
1693 chain = node
1696 finally:
1694 finally:
1697 f.close()
1695 f.close()
1698
1696
1699 @command('debugcheckstate', [], '')
1697 @command('debugcheckstate', [], '')
1700 def debugcheckstate(ui, repo):
1698 def debugcheckstate(ui, repo):
1701 """validate the correctness of the current dirstate"""
1699 """validate the correctness of the current dirstate"""
1702 parent1, parent2 = repo.dirstate.parents()
1700 parent1, parent2 = repo.dirstate.parents()
1703 m1 = repo[parent1].manifest()
1701 m1 = repo[parent1].manifest()
1704 m2 = repo[parent2].manifest()
1702 m2 = repo[parent2].manifest()
1705 errors = 0
1703 errors = 0
1706 for f in repo.dirstate:
1704 for f in repo.dirstate:
1707 state = repo.dirstate[f]
1705 state = repo.dirstate[f]
1708 if state in "nr" and f not in m1:
1706 if state in "nr" and f not in m1:
1709 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1707 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1710 errors += 1
1708 errors += 1
1711 if state in "a" and f in m1:
1709 if state in "a" and f in m1:
1712 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1710 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1713 errors += 1
1711 errors += 1
1714 if state in "m" and f not in m1 and f not in m2:
1712 if state in "m" and f not in m1 and f not in m2:
1715 ui.warn(_("%s in state %s, but not in either manifest\n") %
1713 ui.warn(_("%s in state %s, but not in either manifest\n") %
1716 (f, state))
1714 (f, state))
1717 errors += 1
1715 errors += 1
1718 for f in m1:
1716 for f in m1:
1719 state = repo.dirstate[f]
1717 state = repo.dirstate[f]
1720 if state not in "nrm":
1718 if state not in "nrm":
1721 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1719 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1722 errors += 1
1720 errors += 1
1723 if errors:
1721 if errors:
1724 error = _(".hg/dirstate inconsistent with current parent's manifest")
1722 error = _(".hg/dirstate inconsistent with current parent's manifest")
1725 raise util.Abort(error)
1723 raise util.Abort(error)
1726
1724
1727 @command('debugcommands', [], _('[COMMAND]'))
1725 @command('debugcommands', [], _('[COMMAND]'))
1728 def debugcommands(ui, cmd='', *args):
1726 def debugcommands(ui, cmd='', *args):
1729 """list all available commands and options"""
1727 """list all available commands and options"""
1730 for cmd, vals in sorted(table.iteritems()):
1728 for cmd, vals in sorted(table.iteritems()):
1731 cmd = cmd.split('|')[0].strip('^')
1729 cmd = cmd.split('|')[0].strip('^')
1732 opts = ', '.join([i[1] for i in vals[1]])
1730 opts = ', '.join([i[1] for i in vals[1]])
1733 ui.write('%s: %s\n' % (cmd, opts))
1731 ui.write('%s: %s\n' % (cmd, opts))
1734
1732
1735 @command('debugcomplete',
1733 @command('debugcomplete',
1736 [('o', 'options', None, _('show the command options'))],
1734 [('o', 'options', None, _('show the command options'))],
1737 _('[-o] CMD'))
1735 _('[-o] CMD'))
1738 def debugcomplete(ui, cmd='', **opts):
1736 def debugcomplete(ui, cmd='', **opts):
1739 """returns the completion list associated with the given command"""
1737 """returns the completion list associated with the given command"""
1740
1738
1741 if opts.get('options'):
1739 if opts.get('options'):
1742 options = []
1740 options = []
1743 otables = [globalopts]
1741 otables = [globalopts]
1744 if cmd:
1742 if cmd:
1745 aliases, entry = cmdutil.findcmd(cmd, table, False)
1743 aliases, entry = cmdutil.findcmd(cmd, table, False)
1746 otables.append(entry[1])
1744 otables.append(entry[1])
1747 for t in otables:
1745 for t in otables:
1748 for o in t:
1746 for o in t:
1749 if "(DEPRECATED)" in o[3]:
1747 if "(DEPRECATED)" in o[3]:
1750 continue
1748 continue
1751 if o[0]:
1749 if o[0]:
1752 options.append('-%s' % o[0])
1750 options.append('-%s' % o[0])
1753 options.append('--%s' % o[1])
1751 options.append('--%s' % o[1])
1754 ui.write("%s\n" % "\n".join(options))
1752 ui.write("%s\n" % "\n".join(options))
1755 return
1753 return
1756
1754
1757 cmdlist = cmdutil.findpossible(cmd, table)
1755 cmdlist = cmdutil.findpossible(cmd, table)
1758 if ui.verbose:
1756 if ui.verbose:
1759 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1757 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1760 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1758 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1761
1759
1762 @command('debugdag',
1760 @command('debugdag',
1763 [('t', 'tags', None, _('use tags as labels')),
1761 [('t', 'tags', None, _('use tags as labels')),
1764 ('b', 'branches', None, _('annotate with branch names')),
1762 ('b', 'branches', None, _('annotate with branch names')),
1765 ('', 'dots', None, _('use dots for runs')),
1763 ('', 'dots', None, _('use dots for runs')),
1766 ('s', 'spaces', None, _('separate elements by spaces'))],
1764 ('s', 'spaces', None, _('separate elements by spaces'))],
1767 _('[OPTION]... [FILE [REV]...]'))
1765 _('[OPTION]... [FILE [REV]...]'))
1768 def debugdag(ui, repo, file_=None, *revs, **opts):
1766 def debugdag(ui, repo, file_=None, *revs, **opts):
1769 """format the changelog or an index DAG as a concise textual description
1767 """format the changelog or an index DAG as a concise textual description
1770
1768
1771 If you pass a revlog index, the revlog's DAG is emitted. If you list
1769 If you pass a revlog index, the revlog's DAG is emitted. If you list
1772 revision numbers, they get labeled in the output as rN.
1770 revision numbers, they get labeled in the output as rN.
1773
1771
1774 Otherwise, the changelog DAG of the current repo is emitted.
1772 Otherwise, the changelog DAG of the current repo is emitted.
1775 """
1773 """
1776 spaces = opts.get('spaces')
1774 spaces = opts.get('spaces')
1777 dots = opts.get('dots')
1775 dots = opts.get('dots')
1778 if file_:
1776 if file_:
1779 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1777 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1780 revs = set((int(r) for r in revs))
1778 revs = set((int(r) for r in revs))
1781 def events():
1779 def events():
1782 for r in rlog:
1780 for r in rlog:
1783 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1781 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1784 if p != -1)))
1782 if p != -1)))
1785 if r in revs:
1783 if r in revs:
1786 yield 'l', (r, "r%i" % r)
1784 yield 'l', (r, "r%i" % r)
1787 elif repo:
1785 elif repo:
1788 cl = repo.changelog
1786 cl = repo.changelog
1789 tags = opts.get('tags')
1787 tags = opts.get('tags')
1790 branches = opts.get('branches')
1788 branches = opts.get('branches')
1791 if tags:
1789 if tags:
1792 labels = {}
1790 labels = {}
1793 for l, n in repo.tags().items():
1791 for l, n in repo.tags().items():
1794 labels.setdefault(cl.rev(n), []).append(l)
1792 labels.setdefault(cl.rev(n), []).append(l)
1795 def events():
1793 def events():
1796 b = "default"
1794 b = "default"
1797 for r in cl:
1795 for r in cl:
1798 if branches:
1796 if branches:
1799 newb = cl.read(cl.node(r))[5]['branch']
1797 newb = cl.read(cl.node(r))[5]['branch']
1800 if newb != b:
1798 if newb != b:
1801 yield 'a', newb
1799 yield 'a', newb
1802 b = newb
1800 b = newb
1803 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1801 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1804 if p != -1)))
1802 if p != -1)))
1805 if tags:
1803 if tags:
1806 ls = labels.get(r)
1804 ls = labels.get(r)
1807 if ls:
1805 if ls:
1808 for l in ls:
1806 for l in ls:
1809 yield 'l', (r, l)
1807 yield 'l', (r, l)
1810 else:
1808 else:
1811 raise util.Abort(_('need repo for changelog dag'))
1809 raise util.Abort(_('need repo for changelog dag'))
1812
1810
1813 for line in dagparser.dagtextlines(events(),
1811 for line in dagparser.dagtextlines(events(),
1814 addspaces=spaces,
1812 addspaces=spaces,
1815 wraplabels=True,
1813 wraplabels=True,
1816 wrapannotations=True,
1814 wrapannotations=True,
1817 wrapnonlinear=dots,
1815 wrapnonlinear=dots,
1818 usedots=dots,
1816 usedots=dots,
1819 maxlinewidth=70):
1817 maxlinewidth=70):
1820 ui.write(line)
1818 ui.write(line)
1821 ui.write("\n")
1819 ui.write("\n")
1822
1820
1823 @command('debugdata',
1821 @command('debugdata',
1824 [('c', 'changelog', False, _('open changelog')),
1822 [('c', 'changelog', False, _('open changelog')),
1825 ('m', 'manifest', False, _('open manifest'))],
1823 ('m', 'manifest', False, _('open manifest'))],
1826 _('-c|-m|FILE REV'))
1824 _('-c|-m|FILE REV'))
1827 def debugdata(ui, repo, file_, rev=None, **opts):
1825 def debugdata(ui, repo, file_, rev=None, **opts):
1828 """dump the contents of a data file revision"""
1826 """dump the contents of a data file revision"""
1829 if opts.get('changelog') or opts.get('manifest'):
1827 if opts.get('changelog') or opts.get('manifest'):
1830 file_, rev = None, file_
1828 file_, rev = None, file_
1831 elif rev is None:
1829 elif rev is None:
1832 raise error.CommandError('debugdata', _('invalid arguments'))
1830 raise error.CommandError('debugdata', _('invalid arguments'))
1833 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1831 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1834 try:
1832 try:
1835 ui.write(r.revision(r.lookup(rev)))
1833 ui.write(r.revision(r.lookup(rev)))
1836 except KeyError:
1834 except KeyError:
1837 raise util.Abort(_('invalid revision identifier %s') % rev)
1835 raise util.Abort(_('invalid revision identifier %s') % rev)
1838
1836
1839 @command('debugdate',
1837 @command('debugdate',
1840 [('e', 'extended', None, _('try extended date formats'))],
1838 [('e', 'extended', None, _('try extended date formats'))],
1841 _('[-e] DATE [RANGE]'))
1839 _('[-e] DATE [RANGE]'))
1842 def debugdate(ui, date, range=None, **opts):
1840 def debugdate(ui, date, range=None, **opts):
1843 """parse and display a date"""
1841 """parse and display a date"""
1844 if opts["extended"]:
1842 if opts["extended"]:
1845 d = util.parsedate(date, util.extendeddateformats)
1843 d = util.parsedate(date, util.extendeddateformats)
1846 else:
1844 else:
1847 d = util.parsedate(date)
1845 d = util.parsedate(date)
1848 ui.write(("internal: %s %s\n") % d)
1846 ui.write(("internal: %s %s\n") % d)
1849 ui.write(("standard: %s\n") % util.datestr(d))
1847 ui.write(("standard: %s\n") % util.datestr(d))
1850 if range:
1848 if range:
1851 m = util.matchdate(range)
1849 m = util.matchdate(range)
1852 ui.write(("match: %s\n") % m(d[0]))
1850 ui.write(("match: %s\n") % m(d[0]))
1853
1851
1854 @command('debugdiscovery',
1852 @command('debugdiscovery',
1855 [('', 'old', None, _('use old-style discovery')),
1853 [('', 'old', None, _('use old-style discovery')),
1856 ('', 'nonheads', None,
1854 ('', 'nonheads', None,
1857 _('use old-style discovery with non-heads included')),
1855 _('use old-style discovery with non-heads included')),
1858 ] + remoteopts,
1856 ] + remoteopts,
1859 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1857 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1860 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1858 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1861 """runs the changeset discovery protocol in isolation"""
1859 """runs the changeset discovery protocol in isolation"""
1862 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1860 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1863 opts.get('branch'))
1861 opts.get('branch'))
1864 remote = hg.peer(repo, opts, remoteurl)
1862 remote = hg.peer(repo, opts, remoteurl)
1865 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1863 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1866
1864
1867 # make sure tests are repeatable
1865 # make sure tests are repeatable
1868 random.seed(12323)
1866 random.seed(12323)
1869
1867
1870 def doit(localheads, remoteheads, remote=remote):
1868 def doit(localheads, remoteheads, remote=remote):
1871 if opts.get('old'):
1869 if opts.get('old'):
1872 if localheads:
1870 if localheads:
1873 raise util.Abort('cannot use localheads with old style '
1871 raise util.Abort('cannot use localheads with old style '
1874 'discovery')
1872 'discovery')
1875 if not util.safehasattr(remote, 'branches'):
1873 if not util.safehasattr(remote, 'branches'):
1876 # enable in-client legacy support
1874 # enable in-client legacy support
1877 remote = localrepo.locallegacypeer(remote.local())
1875 remote = localrepo.locallegacypeer(remote.local())
1878 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1876 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1879 force=True)
1877 force=True)
1880 common = set(common)
1878 common = set(common)
1881 if not opts.get('nonheads'):
1879 if not opts.get('nonheads'):
1882 ui.write(("unpruned common: %s\n") %
1880 ui.write(("unpruned common: %s\n") %
1883 " ".join(sorted(short(n) for n in common)))
1881 " ".join(sorted(short(n) for n in common)))
1884 dag = dagutil.revlogdag(repo.changelog)
1882 dag = dagutil.revlogdag(repo.changelog)
1885 all = dag.ancestorset(dag.internalizeall(common))
1883 all = dag.ancestorset(dag.internalizeall(common))
1886 common = dag.externalizeall(dag.headsetofconnecteds(all))
1884 common = dag.externalizeall(dag.headsetofconnecteds(all))
1887 else:
1885 else:
1888 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1886 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1889 common = set(common)
1887 common = set(common)
1890 rheads = set(hds)
1888 rheads = set(hds)
1891 lheads = set(repo.heads())
1889 lheads = set(repo.heads())
1892 ui.write(("common heads: %s\n") %
1890 ui.write(("common heads: %s\n") %
1893 " ".join(sorted(short(n) for n in common)))
1891 " ".join(sorted(short(n) for n in common)))
1894 if lheads <= common:
1892 if lheads <= common:
1895 ui.write(("local is subset\n"))
1893 ui.write(("local is subset\n"))
1896 elif rheads <= common:
1894 elif rheads <= common:
1897 ui.write(("remote is subset\n"))
1895 ui.write(("remote is subset\n"))
1898
1896
1899 serverlogs = opts.get('serverlog')
1897 serverlogs = opts.get('serverlog')
1900 if serverlogs:
1898 if serverlogs:
1901 for filename in serverlogs:
1899 for filename in serverlogs:
1902 logfile = open(filename, 'r')
1900 logfile = open(filename, 'r')
1903 try:
1901 try:
1904 line = logfile.readline()
1902 line = logfile.readline()
1905 while line:
1903 while line:
1906 parts = line.strip().split(';')
1904 parts = line.strip().split(';')
1907 op = parts[1]
1905 op = parts[1]
1908 if op == 'cg':
1906 if op == 'cg':
1909 pass
1907 pass
1910 elif op == 'cgss':
1908 elif op == 'cgss':
1911 doit(parts[2].split(' '), parts[3].split(' '))
1909 doit(parts[2].split(' '), parts[3].split(' '))
1912 elif op == 'unb':
1910 elif op == 'unb':
1913 doit(parts[3].split(' '), parts[2].split(' '))
1911 doit(parts[3].split(' '), parts[2].split(' '))
1914 line = logfile.readline()
1912 line = logfile.readline()
1915 finally:
1913 finally:
1916 logfile.close()
1914 logfile.close()
1917
1915
1918 else:
1916 else:
1919 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1917 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1920 opts.get('remote_head'))
1918 opts.get('remote_head'))
1921 localrevs = opts.get('local_head')
1919 localrevs = opts.get('local_head')
1922 doit(localrevs, remoterevs)
1920 doit(localrevs, remoterevs)
1923
1921
1924 @command('debugfileset',
1922 @command('debugfileset',
1925 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1923 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1926 _('[-r REV] FILESPEC'))
1924 _('[-r REV] FILESPEC'))
1927 def debugfileset(ui, repo, expr, **opts):
1925 def debugfileset(ui, repo, expr, **opts):
1928 '''parse and apply a fileset specification'''
1926 '''parse and apply a fileset specification'''
1929 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1927 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1930 if ui.verbose:
1928 if ui.verbose:
1931 tree = fileset.parse(expr)[0]
1929 tree = fileset.parse(expr)[0]
1932 ui.note(tree, "\n")
1930 ui.note(tree, "\n")
1933
1931
1934 for f in fileset.getfileset(ctx, expr):
1932 for f in fileset.getfileset(ctx, expr):
1935 ui.write("%s\n" % f)
1933 ui.write("%s\n" % f)
1936
1934
1937 @command('debugfsinfo', [], _('[PATH]'))
1935 @command('debugfsinfo', [], _('[PATH]'))
1938 def debugfsinfo(ui, path="."):
1936 def debugfsinfo(ui, path="."):
1939 """show information detected about current filesystem"""
1937 """show information detected about current filesystem"""
1940 util.writefile('.debugfsinfo', '')
1938 util.writefile('.debugfsinfo', '')
1941 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1939 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1942 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1940 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1943 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1941 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1944 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1942 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1945 and 'yes' or 'no'))
1943 and 'yes' or 'no'))
1946 os.unlink('.debugfsinfo')
1944 os.unlink('.debugfsinfo')
1947
1945
1948 @command('debuggetbundle',
1946 @command('debuggetbundle',
1949 [('H', 'head', [], _('id of head node'), _('ID')),
1947 [('H', 'head', [], _('id of head node'), _('ID')),
1950 ('C', 'common', [], _('id of common node'), _('ID')),
1948 ('C', 'common', [], _('id of common node'), _('ID')),
1951 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1949 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1952 _('REPO FILE [-H|-C ID]...'))
1950 _('REPO FILE [-H|-C ID]...'))
1953 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1951 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1954 """retrieves a bundle from a repo
1952 """retrieves a bundle from a repo
1955
1953
1956 Every ID must be a full-length hex node id string. Saves the bundle to the
1954 Every ID must be a full-length hex node id string. Saves the bundle to the
1957 given file.
1955 given file.
1958 """
1956 """
1959 repo = hg.peer(ui, opts, repopath)
1957 repo = hg.peer(ui, opts, repopath)
1960 if not repo.capable('getbundle'):
1958 if not repo.capable('getbundle'):
1961 raise util.Abort("getbundle() not supported by target repository")
1959 raise util.Abort("getbundle() not supported by target repository")
1962 args = {}
1960 args = {}
1963 if common:
1961 if common:
1964 args['common'] = [bin(s) for s in common]
1962 args['common'] = [bin(s) for s in common]
1965 if head:
1963 if head:
1966 args['heads'] = [bin(s) for s in head]
1964 args['heads'] = [bin(s) for s in head]
1967 # TODO: get desired bundlecaps from command line.
1965 # TODO: get desired bundlecaps from command line.
1968 args['bundlecaps'] = None
1966 args['bundlecaps'] = None
1969 bundle = repo.getbundle('debug', **args)
1967 bundle = repo.getbundle('debug', **args)
1970
1968
1971 bundletype = opts.get('type', 'bzip2').lower()
1969 bundletype = opts.get('type', 'bzip2').lower()
1972 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1970 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1973 bundletype = btypes.get(bundletype)
1971 bundletype = btypes.get(bundletype)
1974 if bundletype not in changegroup.bundletypes:
1972 if bundletype not in changegroup.bundletypes:
1975 raise util.Abort(_('unknown bundle type specified with --type'))
1973 raise util.Abort(_('unknown bundle type specified with --type'))
1976 changegroup.writebundle(bundle, bundlepath, bundletype)
1974 changegroup.writebundle(bundle, bundlepath, bundletype)
1977
1975
1978 @command('debugignore', [], '')
1976 @command('debugignore', [], '')
1979 def debugignore(ui, repo, *values, **opts):
1977 def debugignore(ui, repo, *values, **opts):
1980 """display the combined ignore pattern"""
1978 """display the combined ignore pattern"""
1981 ignore = repo.dirstate._ignore
1979 ignore = repo.dirstate._ignore
1982 includepat = getattr(ignore, 'includepat', None)
1980 includepat = getattr(ignore, 'includepat', None)
1983 if includepat is not None:
1981 if includepat is not None:
1984 ui.write("%s\n" % includepat)
1982 ui.write("%s\n" % includepat)
1985 else:
1983 else:
1986 raise util.Abort(_("no ignore patterns found"))
1984 raise util.Abort(_("no ignore patterns found"))
1987
1985
1988 @command('debugindex',
1986 @command('debugindex',
1989 [('c', 'changelog', False, _('open changelog')),
1987 [('c', 'changelog', False, _('open changelog')),
1990 ('m', 'manifest', False, _('open manifest')),
1988 ('m', 'manifest', False, _('open manifest')),
1991 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1989 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1992 _('[-f FORMAT] -c|-m|FILE'))
1990 _('[-f FORMAT] -c|-m|FILE'))
1993 def debugindex(ui, repo, file_=None, **opts):
1991 def debugindex(ui, repo, file_=None, **opts):
1994 """dump the contents of an index file"""
1992 """dump the contents of an index file"""
1995 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1993 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1996 format = opts.get('format', 0)
1994 format = opts.get('format', 0)
1997 if format not in (0, 1):
1995 if format not in (0, 1):
1998 raise util.Abort(_("unknown format %d") % format)
1996 raise util.Abort(_("unknown format %d") % format)
1999
1997
2000 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1998 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2001 if generaldelta:
1999 if generaldelta:
2002 basehdr = ' delta'
2000 basehdr = ' delta'
2003 else:
2001 else:
2004 basehdr = ' base'
2002 basehdr = ' base'
2005
2003
2006 if format == 0:
2004 if format == 0:
2007 ui.write(" rev offset length " + basehdr + " linkrev"
2005 ui.write(" rev offset length " + basehdr + " linkrev"
2008 " nodeid p1 p2\n")
2006 " nodeid p1 p2\n")
2009 elif format == 1:
2007 elif format == 1:
2010 ui.write(" rev flag offset length"
2008 ui.write(" rev flag offset length"
2011 " size " + basehdr + " link p1 p2"
2009 " size " + basehdr + " link p1 p2"
2012 " nodeid\n")
2010 " nodeid\n")
2013
2011
2014 for i in r:
2012 for i in r:
2015 node = r.node(i)
2013 node = r.node(i)
2016 if generaldelta:
2014 if generaldelta:
2017 base = r.deltaparent(i)
2015 base = r.deltaparent(i)
2018 else:
2016 else:
2019 base = r.chainbase(i)
2017 base = r.chainbase(i)
2020 if format == 0:
2018 if format == 0:
2021 try:
2019 try:
2022 pp = r.parents(node)
2020 pp = r.parents(node)
2023 except Exception:
2021 except Exception:
2024 pp = [nullid, nullid]
2022 pp = [nullid, nullid]
2025 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2023 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2026 i, r.start(i), r.length(i), base, r.linkrev(i),
2024 i, r.start(i), r.length(i), base, r.linkrev(i),
2027 short(node), short(pp[0]), short(pp[1])))
2025 short(node), short(pp[0]), short(pp[1])))
2028 elif format == 1:
2026 elif format == 1:
2029 pr = r.parentrevs(i)
2027 pr = r.parentrevs(i)
2030 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2028 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2031 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2029 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2032 base, r.linkrev(i), pr[0], pr[1], short(node)))
2030 base, r.linkrev(i), pr[0], pr[1], short(node)))
2033
2031
2034 @command('debugindexdot', [], _('FILE'))
2032 @command('debugindexdot', [], _('FILE'))
2035 def debugindexdot(ui, repo, file_):
2033 def debugindexdot(ui, repo, file_):
2036 """dump an index DAG as a graphviz dot file"""
2034 """dump an index DAG as a graphviz dot file"""
2037 r = None
2035 r = None
2038 if repo:
2036 if repo:
2039 filelog = repo.file(file_)
2037 filelog = repo.file(file_)
2040 if len(filelog):
2038 if len(filelog):
2041 r = filelog
2039 r = filelog
2042 if not r:
2040 if not r:
2043 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2041 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2044 ui.write(("digraph G {\n"))
2042 ui.write(("digraph G {\n"))
2045 for i in r:
2043 for i in r:
2046 node = r.node(i)
2044 node = r.node(i)
2047 pp = r.parents(node)
2045 pp = r.parents(node)
2048 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2046 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2049 if pp[1] != nullid:
2047 if pp[1] != nullid:
2050 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2048 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2051 ui.write("}\n")
2049 ui.write("}\n")
2052
2050
2053 @command('debuginstall', [], '')
2051 @command('debuginstall', [], '')
2054 def debuginstall(ui):
2052 def debuginstall(ui):
2055 '''test Mercurial installation
2053 '''test Mercurial installation
2056
2054
2057 Returns 0 on success.
2055 Returns 0 on success.
2058 '''
2056 '''
2059
2057
2060 def writetemp(contents):
2058 def writetemp(contents):
2061 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2059 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2062 f = os.fdopen(fd, "wb")
2060 f = os.fdopen(fd, "wb")
2063 f.write(contents)
2061 f.write(contents)
2064 f.close()
2062 f.close()
2065 return name
2063 return name
2066
2064
2067 problems = 0
2065 problems = 0
2068
2066
2069 # encoding
2067 # encoding
2070 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2068 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2071 try:
2069 try:
2072 encoding.fromlocal("test")
2070 encoding.fromlocal("test")
2073 except util.Abort, inst:
2071 except util.Abort, inst:
2074 ui.write(" %s\n" % inst)
2072 ui.write(" %s\n" % inst)
2075 ui.write(_(" (check that your locale is properly set)\n"))
2073 ui.write(_(" (check that your locale is properly set)\n"))
2076 problems += 1
2074 problems += 1
2077
2075
2078 # Python lib
2076 # Python lib
2079 ui.status(_("checking Python lib (%s)...\n")
2077 ui.status(_("checking Python lib (%s)...\n")
2080 % os.path.dirname(os.__file__))
2078 % os.path.dirname(os.__file__))
2081
2079
2082 # compiled modules
2080 # compiled modules
2083 ui.status(_("checking installed modules (%s)...\n")
2081 ui.status(_("checking installed modules (%s)...\n")
2084 % os.path.dirname(__file__))
2082 % os.path.dirname(__file__))
2085 try:
2083 try:
2086 import bdiff, mpatch, base85, osutil
2084 import bdiff, mpatch, base85, osutil
2087 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2085 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2088 except Exception, inst:
2086 except Exception, inst:
2089 ui.write(" %s\n" % inst)
2087 ui.write(" %s\n" % inst)
2090 ui.write(_(" One or more extensions could not be found"))
2088 ui.write(_(" One or more extensions could not be found"))
2091 ui.write(_(" (check that you compiled the extensions)\n"))
2089 ui.write(_(" (check that you compiled the extensions)\n"))
2092 problems += 1
2090 problems += 1
2093
2091
2094 # templates
2092 # templates
2095 import templater
2093 import templater
2096 p = templater.templatepath()
2094 p = templater.templatepath()
2097 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2095 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2098 try:
2096 try:
2099 templater.templater(templater.templatepath("map-cmdline.default"))
2097 templater.templater(templater.templatepath("map-cmdline.default"))
2100 except Exception, inst:
2098 except Exception, inst:
2101 ui.write(" %s\n" % inst)
2099 ui.write(" %s\n" % inst)
2102 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2100 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2103 problems += 1
2101 problems += 1
2104
2102
2105 # editor
2103 # editor
2106 ui.status(_("checking commit editor...\n"))
2104 ui.status(_("checking commit editor...\n"))
2107 editor = ui.geteditor()
2105 editor = ui.geteditor()
2108 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2106 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2109 if not cmdpath:
2107 if not cmdpath:
2110 if editor == 'vi':
2108 if editor == 'vi':
2111 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2109 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2112 ui.write(_(" (specify a commit editor in your configuration"
2110 ui.write(_(" (specify a commit editor in your configuration"
2113 " file)\n"))
2111 " file)\n"))
2114 else:
2112 else:
2115 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2113 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2116 ui.write(_(" (specify a commit editor in your configuration"
2114 ui.write(_(" (specify a commit editor in your configuration"
2117 " file)\n"))
2115 " file)\n"))
2118 problems += 1
2116 problems += 1
2119
2117
2120 # check username
2118 # check username
2121 ui.status(_("checking username...\n"))
2119 ui.status(_("checking username...\n"))
2122 try:
2120 try:
2123 ui.username()
2121 ui.username()
2124 except util.Abort, e:
2122 except util.Abort, e:
2125 ui.write(" %s\n" % e)
2123 ui.write(" %s\n" % e)
2126 ui.write(_(" (specify a username in your configuration file)\n"))
2124 ui.write(_(" (specify a username in your configuration file)\n"))
2127 problems += 1
2125 problems += 1
2128
2126
2129 if not problems:
2127 if not problems:
2130 ui.status(_("no problems detected\n"))
2128 ui.status(_("no problems detected\n"))
2131 else:
2129 else:
2132 ui.write(_("%s problems detected,"
2130 ui.write(_("%s problems detected,"
2133 " please check your install!\n") % problems)
2131 " please check your install!\n") % problems)
2134
2132
2135 return problems
2133 return problems
2136
2134
2137 @command('debugknown', [], _('REPO ID...'))
2135 @command('debugknown', [], _('REPO ID...'))
2138 def debugknown(ui, repopath, *ids, **opts):
2136 def debugknown(ui, repopath, *ids, **opts):
2139 """test whether node ids are known to a repo
2137 """test whether node ids are known to a repo
2140
2138
2141 Every ID must be a full-length hex node id string. Returns a list of 0s
2139 Every ID must be a full-length hex node id string. Returns a list of 0s
2142 and 1s indicating unknown/known.
2140 and 1s indicating unknown/known.
2143 """
2141 """
2144 repo = hg.peer(ui, opts, repopath)
2142 repo = hg.peer(ui, opts, repopath)
2145 if not repo.capable('known'):
2143 if not repo.capable('known'):
2146 raise util.Abort("known() not supported by target repository")
2144 raise util.Abort("known() not supported by target repository")
2147 flags = repo.known([bin(s) for s in ids])
2145 flags = repo.known([bin(s) for s in ids])
2148 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2146 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2149
2147
2150 @command('debuglabelcomplete', [], _('LABEL...'))
2148 @command('debuglabelcomplete', [], _('LABEL...'))
2151 def debuglabelcomplete(ui, repo, *args):
2149 def debuglabelcomplete(ui, repo, *args):
2152 '''complete "labels" - tags, open branch names, bookmark names'''
2150 '''complete "labels" - tags, open branch names, bookmark names'''
2153
2151
2154 labels = set()
2152 labels = set()
2155 labels.update(t[0] for t in repo.tagslist())
2153 labels.update(t[0] for t in repo.tagslist())
2156 labels.update(repo._bookmarks.keys())
2154 labels.update(repo._bookmarks.keys())
2157 labels.update(tag for (tag, heads, tip, closed)
2155 labels.update(tag for (tag, heads, tip, closed)
2158 in repo.branchmap().iterbranches() if not closed)
2156 in repo.branchmap().iterbranches() if not closed)
2159 completions = set()
2157 completions = set()
2160 if not args:
2158 if not args:
2161 args = ['']
2159 args = ['']
2162 for a in args:
2160 for a in args:
2163 completions.update(l for l in labels if l.startswith(a))
2161 completions.update(l for l in labels if l.startswith(a))
2164 ui.write('\n'.join(sorted(completions)))
2162 ui.write('\n'.join(sorted(completions)))
2165 ui.write('\n')
2163 ui.write('\n')
2166
2164
2167 @command('debugobsolete',
2165 @command('debugobsolete',
2168 [('', 'flags', 0, _('markers flag')),
2166 [('', 'flags', 0, _('markers flag')),
2169 ] + commitopts2,
2167 ] + commitopts2,
2170 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2168 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2171 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2169 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2172 """create arbitrary obsolete marker
2170 """create arbitrary obsolete marker
2173
2171
2174 With no arguments, displays the list of obsolescence markers."""
2172 With no arguments, displays the list of obsolescence markers."""
2175 def parsenodeid(s):
2173 def parsenodeid(s):
2176 try:
2174 try:
2177 # We do not use revsingle/revrange functions here to accept
2175 # We do not use revsingle/revrange functions here to accept
2178 # arbitrary node identifiers, possibly not present in the
2176 # arbitrary node identifiers, possibly not present in the
2179 # local repository.
2177 # local repository.
2180 n = bin(s)
2178 n = bin(s)
2181 if len(n) != len(nullid):
2179 if len(n) != len(nullid):
2182 raise TypeError()
2180 raise TypeError()
2183 return n
2181 return n
2184 except TypeError:
2182 except TypeError:
2185 raise util.Abort('changeset references must be full hexadecimal '
2183 raise util.Abort('changeset references must be full hexadecimal '
2186 'node identifiers')
2184 'node identifiers')
2187
2185
2188 if precursor is not None:
2186 if precursor is not None:
2189 metadata = {}
2187 metadata = {}
2190 if 'date' in opts:
2188 if 'date' in opts:
2191 metadata['date'] = opts['date']
2189 metadata['date'] = opts['date']
2192 metadata['user'] = opts['user'] or ui.username()
2190 metadata['user'] = opts['user'] or ui.username()
2193 succs = tuple(parsenodeid(succ) for succ in successors)
2191 succs = tuple(parsenodeid(succ) for succ in successors)
2194 l = repo.lock()
2192 l = repo.lock()
2195 try:
2193 try:
2196 tr = repo.transaction('debugobsolete')
2194 tr = repo.transaction('debugobsolete')
2197 try:
2195 try:
2198 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2196 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2199 opts['flags'], metadata)
2197 opts['flags'], metadata)
2200 tr.close()
2198 tr.close()
2201 finally:
2199 finally:
2202 tr.release()
2200 tr.release()
2203 finally:
2201 finally:
2204 l.release()
2202 l.release()
2205 else:
2203 else:
2206 for m in obsolete.allmarkers(repo):
2204 for m in obsolete.allmarkers(repo):
2207 ui.write(hex(m.precnode()))
2205 ui.write(hex(m.precnode()))
2208 for repl in m.succnodes():
2206 for repl in m.succnodes():
2209 ui.write(' ')
2207 ui.write(' ')
2210 ui.write(hex(repl))
2208 ui.write(hex(repl))
2211 ui.write(' %X ' % m._data[2])
2209 ui.write(' %X ' % m._data[2])
2212 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2210 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2213 sorted(m.metadata().items()))))
2211 sorted(m.metadata().items()))))
2214 ui.write('\n')
2212 ui.write('\n')
2215
2213
2216 @command('debugpathcomplete',
2214 @command('debugpathcomplete',
2217 [('f', 'full', None, _('complete an entire path')),
2215 [('f', 'full', None, _('complete an entire path')),
2218 ('n', 'normal', None, _('show only normal files')),
2216 ('n', 'normal', None, _('show only normal files')),
2219 ('a', 'added', None, _('show only added files')),
2217 ('a', 'added', None, _('show only added files')),
2220 ('r', 'removed', None, _('show only removed files'))],
2218 ('r', 'removed', None, _('show only removed files'))],
2221 _('FILESPEC...'))
2219 _('FILESPEC...'))
2222 def debugpathcomplete(ui, repo, *specs, **opts):
2220 def debugpathcomplete(ui, repo, *specs, **opts):
2223 '''complete part or all of a tracked path
2221 '''complete part or all of a tracked path
2224
2222
2225 This command supports shells that offer path name completion. It
2223 This command supports shells that offer path name completion. It
2226 currently completes only files already known to the dirstate.
2224 currently completes only files already known to the dirstate.
2227
2225
2228 Completion extends only to the next path segment unless
2226 Completion extends only to the next path segment unless
2229 --full is specified, in which case entire paths are used.'''
2227 --full is specified, in which case entire paths are used.'''
2230
2228
2231 def complete(path, acceptable):
2229 def complete(path, acceptable):
2232 dirstate = repo.dirstate
2230 dirstate = repo.dirstate
2233 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2231 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2234 rootdir = repo.root + os.sep
2232 rootdir = repo.root + os.sep
2235 if spec != repo.root and not spec.startswith(rootdir):
2233 if spec != repo.root and not spec.startswith(rootdir):
2236 return [], []
2234 return [], []
2237 if os.path.isdir(spec):
2235 if os.path.isdir(spec):
2238 spec += '/'
2236 spec += '/'
2239 spec = spec[len(rootdir):]
2237 spec = spec[len(rootdir):]
2240 fixpaths = os.sep != '/'
2238 fixpaths = os.sep != '/'
2241 if fixpaths:
2239 if fixpaths:
2242 spec = spec.replace(os.sep, '/')
2240 spec = spec.replace(os.sep, '/')
2243 speclen = len(spec)
2241 speclen = len(spec)
2244 fullpaths = opts['full']
2242 fullpaths = opts['full']
2245 files, dirs = set(), set()
2243 files, dirs = set(), set()
2246 adddir, addfile = dirs.add, files.add
2244 adddir, addfile = dirs.add, files.add
2247 for f, st in dirstate.iteritems():
2245 for f, st in dirstate.iteritems():
2248 if f.startswith(spec) and st[0] in acceptable:
2246 if f.startswith(spec) and st[0] in acceptable:
2249 if fixpaths:
2247 if fixpaths:
2250 f = f.replace('/', os.sep)
2248 f = f.replace('/', os.sep)
2251 if fullpaths:
2249 if fullpaths:
2252 addfile(f)
2250 addfile(f)
2253 continue
2251 continue
2254 s = f.find(os.sep, speclen)
2252 s = f.find(os.sep, speclen)
2255 if s >= 0:
2253 if s >= 0:
2256 adddir(f[:s])
2254 adddir(f[:s])
2257 else:
2255 else:
2258 addfile(f)
2256 addfile(f)
2259 return files, dirs
2257 return files, dirs
2260
2258
2261 acceptable = ''
2259 acceptable = ''
2262 if opts['normal']:
2260 if opts['normal']:
2263 acceptable += 'nm'
2261 acceptable += 'nm'
2264 if opts['added']:
2262 if opts['added']:
2265 acceptable += 'a'
2263 acceptable += 'a'
2266 if opts['removed']:
2264 if opts['removed']:
2267 acceptable += 'r'
2265 acceptable += 'r'
2268 cwd = repo.getcwd()
2266 cwd = repo.getcwd()
2269 if not specs:
2267 if not specs:
2270 specs = ['.']
2268 specs = ['.']
2271
2269
2272 files, dirs = set(), set()
2270 files, dirs = set(), set()
2273 for spec in specs:
2271 for spec in specs:
2274 f, d = complete(spec, acceptable or 'nmar')
2272 f, d = complete(spec, acceptable or 'nmar')
2275 files.update(f)
2273 files.update(f)
2276 dirs.update(d)
2274 dirs.update(d)
2277 files.update(dirs)
2275 files.update(dirs)
2278 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2276 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2279 ui.write('\n')
2277 ui.write('\n')
2280
2278
2281 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2279 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2282 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2280 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2283 '''access the pushkey key/value protocol
2281 '''access the pushkey key/value protocol
2284
2282
2285 With two args, list the keys in the given namespace.
2283 With two args, list the keys in the given namespace.
2286
2284
2287 With five args, set a key to new if it currently is set to old.
2285 With five args, set a key to new if it currently is set to old.
2288 Reports success or failure.
2286 Reports success or failure.
2289 '''
2287 '''
2290
2288
2291 target = hg.peer(ui, {}, repopath)
2289 target = hg.peer(ui, {}, repopath)
2292 if keyinfo:
2290 if keyinfo:
2293 key, old, new = keyinfo
2291 key, old, new = keyinfo
2294 r = target.pushkey(namespace, key, old, new)
2292 r = target.pushkey(namespace, key, old, new)
2295 ui.status(str(r) + '\n')
2293 ui.status(str(r) + '\n')
2296 return not r
2294 return not r
2297 else:
2295 else:
2298 for k, v in sorted(target.listkeys(namespace).iteritems()):
2296 for k, v in sorted(target.listkeys(namespace).iteritems()):
2299 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2297 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2300 v.encode('string-escape')))
2298 v.encode('string-escape')))
2301
2299
2302 @command('debugpvec', [], _('A B'))
2300 @command('debugpvec', [], _('A B'))
2303 def debugpvec(ui, repo, a, b=None):
2301 def debugpvec(ui, repo, a, b=None):
2304 ca = scmutil.revsingle(repo, a)
2302 ca = scmutil.revsingle(repo, a)
2305 cb = scmutil.revsingle(repo, b)
2303 cb = scmutil.revsingle(repo, b)
2306 pa = pvec.ctxpvec(ca)
2304 pa = pvec.ctxpvec(ca)
2307 pb = pvec.ctxpvec(cb)
2305 pb = pvec.ctxpvec(cb)
2308 if pa == pb:
2306 if pa == pb:
2309 rel = "="
2307 rel = "="
2310 elif pa > pb:
2308 elif pa > pb:
2311 rel = ">"
2309 rel = ">"
2312 elif pa < pb:
2310 elif pa < pb:
2313 rel = "<"
2311 rel = "<"
2314 elif pa | pb:
2312 elif pa | pb:
2315 rel = "|"
2313 rel = "|"
2316 ui.write(_("a: %s\n") % pa)
2314 ui.write(_("a: %s\n") % pa)
2317 ui.write(_("b: %s\n") % pb)
2315 ui.write(_("b: %s\n") % pb)
2318 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2316 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2319 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2317 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2320 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2318 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2321 pa.distance(pb), rel))
2319 pa.distance(pb), rel))
2322
2320
2323 @command('debugrebuilddirstate|debugrebuildstate',
2321 @command('debugrebuilddirstate|debugrebuildstate',
2324 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2322 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2325 _('[-r REV]'))
2323 _('[-r REV]'))
2326 def debugrebuilddirstate(ui, repo, rev):
2324 def debugrebuilddirstate(ui, repo, rev):
2327 """rebuild the dirstate as it would look like for the given revision
2325 """rebuild the dirstate as it would look like for the given revision
2328
2326
2329 If no revision is specified the first current parent will be used.
2327 If no revision is specified the first current parent will be used.
2330
2328
2331 The dirstate will be set to the files of the given revision.
2329 The dirstate will be set to the files of the given revision.
2332 The actual working directory content or existing dirstate
2330 The actual working directory content or existing dirstate
2333 information such as adds or removes is not considered.
2331 information such as adds or removes is not considered.
2334
2332
2335 One use of this command is to make the next :hg:`status` invocation
2333 One use of this command is to make the next :hg:`status` invocation
2336 check the actual file content.
2334 check the actual file content.
2337 """
2335 """
2338 ctx = scmutil.revsingle(repo, rev)
2336 ctx = scmutil.revsingle(repo, rev)
2339 wlock = repo.wlock()
2337 wlock = repo.wlock()
2340 try:
2338 try:
2341 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2339 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2342 finally:
2340 finally:
2343 wlock.release()
2341 wlock.release()
2344
2342
2345 @command('debugrename',
2343 @command('debugrename',
2346 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2344 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2347 _('[-r REV] FILE'))
2345 _('[-r REV] FILE'))
2348 def debugrename(ui, repo, file1, *pats, **opts):
2346 def debugrename(ui, repo, file1, *pats, **opts):
2349 """dump rename information"""
2347 """dump rename information"""
2350
2348
2351 ctx = scmutil.revsingle(repo, opts.get('rev'))
2349 ctx = scmutil.revsingle(repo, opts.get('rev'))
2352 m = scmutil.match(ctx, (file1,) + pats, opts)
2350 m = scmutil.match(ctx, (file1,) + pats, opts)
2353 for abs in ctx.walk(m):
2351 for abs in ctx.walk(m):
2354 fctx = ctx[abs]
2352 fctx = ctx[abs]
2355 o = fctx.filelog().renamed(fctx.filenode())
2353 o = fctx.filelog().renamed(fctx.filenode())
2356 rel = m.rel(abs)
2354 rel = m.rel(abs)
2357 if o:
2355 if o:
2358 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2356 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2359 else:
2357 else:
2360 ui.write(_("%s not renamed\n") % rel)
2358 ui.write(_("%s not renamed\n") % rel)
2361
2359
2362 @command('debugrevlog',
2360 @command('debugrevlog',
2363 [('c', 'changelog', False, _('open changelog')),
2361 [('c', 'changelog', False, _('open changelog')),
2364 ('m', 'manifest', False, _('open manifest')),
2362 ('m', 'manifest', False, _('open manifest')),
2365 ('d', 'dump', False, _('dump index data'))],
2363 ('d', 'dump', False, _('dump index data'))],
2366 _('-c|-m|FILE'))
2364 _('-c|-m|FILE'))
2367 def debugrevlog(ui, repo, file_=None, **opts):
2365 def debugrevlog(ui, repo, file_=None, **opts):
2368 """show data and statistics about a revlog"""
2366 """show data and statistics about a revlog"""
2369 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2367 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2370
2368
2371 if opts.get("dump"):
2369 if opts.get("dump"):
2372 numrevs = len(r)
2370 numrevs = len(r)
2373 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2371 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2374 " rawsize totalsize compression heads\n")
2372 " rawsize totalsize compression heads\n")
2375 ts = 0
2373 ts = 0
2376 heads = set()
2374 heads = set()
2377 for rev in xrange(numrevs):
2375 for rev in xrange(numrevs):
2378 dbase = r.deltaparent(rev)
2376 dbase = r.deltaparent(rev)
2379 if dbase == -1:
2377 if dbase == -1:
2380 dbase = rev
2378 dbase = rev
2381 cbase = r.chainbase(rev)
2379 cbase = r.chainbase(rev)
2382 p1, p2 = r.parentrevs(rev)
2380 p1, p2 = r.parentrevs(rev)
2383 rs = r.rawsize(rev)
2381 rs = r.rawsize(rev)
2384 ts = ts + rs
2382 ts = ts + rs
2385 heads -= set(r.parentrevs(rev))
2383 heads -= set(r.parentrevs(rev))
2386 heads.add(rev)
2384 heads.add(rev)
2387 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2385 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2388 (rev, p1, p2, r.start(rev), r.end(rev),
2386 (rev, p1, p2, r.start(rev), r.end(rev),
2389 r.start(dbase), r.start(cbase),
2387 r.start(dbase), r.start(cbase),
2390 r.start(p1), r.start(p2),
2388 r.start(p1), r.start(p2),
2391 rs, ts, ts / r.end(rev), len(heads)))
2389 rs, ts, ts / r.end(rev), len(heads)))
2392 return 0
2390 return 0
2393
2391
2394 v = r.version
2392 v = r.version
2395 format = v & 0xFFFF
2393 format = v & 0xFFFF
2396 flags = []
2394 flags = []
2397 gdelta = False
2395 gdelta = False
2398 if v & revlog.REVLOGNGINLINEDATA:
2396 if v & revlog.REVLOGNGINLINEDATA:
2399 flags.append('inline')
2397 flags.append('inline')
2400 if v & revlog.REVLOGGENERALDELTA:
2398 if v & revlog.REVLOGGENERALDELTA:
2401 gdelta = True
2399 gdelta = True
2402 flags.append('generaldelta')
2400 flags.append('generaldelta')
2403 if not flags:
2401 if not flags:
2404 flags = ['(none)']
2402 flags = ['(none)']
2405
2403
2406 nummerges = 0
2404 nummerges = 0
2407 numfull = 0
2405 numfull = 0
2408 numprev = 0
2406 numprev = 0
2409 nump1 = 0
2407 nump1 = 0
2410 nump2 = 0
2408 nump2 = 0
2411 numother = 0
2409 numother = 0
2412 nump1prev = 0
2410 nump1prev = 0
2413 nump2prev = 0
2411 nump2prev = 0
2414 chainlengths = []
2412 chainlengths = []
2415
2413
2416 datasize = [None, 0, 0L]
2414 datasize = [None, 0, 0L]
2417 fullsize = [None, 0, 0L]
2415 fullsize = [None, 0, 0L]
2418 deltasize = [None, 0, 0L]
2416 deltasize = [None, 0, 0L]
2419
2417
2420 def addsize(size, l):
2418 def addsize(size, l):
2421 if l[0] is None or size < l[0]:
2419 if l[0] is None or size < l[0]:
2422 l[0] = size
2420 l[0] = size
2423 if size > l[1]:
2421 if size > l[1]:
2424 l[1] = size
2422 l[1] = size
2425 l[2] += size
2423 l[2] += size
2426
2424
2427 numrevs = len(r)
2425 numrevs = len(r)
2428 for rev in xrange(numrevs):
2426 for rev in xrange(numrevs):
2429 p1, p2 = r.parentrevs(rev)
2427 p1, p2 = r.parentrevs(rev)
2430 delta = r.deltaparent(rev)
2428 delta = r.deltaparent(rev)
2431 if format > 0:
2429 if format > 0:
2432 addsize(r.rawsize(rev), datasize)
2430 addsize(r.rawsize(rev), datasize)
2433 if p2 != nullrev:
2431 if p2 != nullrev:
2434 nummerges += 1
2432 nummerges += 1
2435 size = r.length(rev)
2433 size = r.length(rev)
2436 if delta == nullrev:
2434 if delta == nullrev:
2437 chainlengths.append(0)
2435 chainlengths.append(0)
2438 numfull += 1
2436 numfull += 1
2439 addsize(size, fullsize)
2437 addsize(size, fullsize)
2440 else:
2438 else:
2441 chainlengths.append(chainlengths[delta] + 1)
2439 chainlengths.append(chainlengths[delta] + 1)
2442 addsize(size, deltasize)
2440 addsize(size, deltasize)
2443 if delta == rev - 1:
2441 if delta == rev - 1:
2444 numprev += 1
2442 numprev += 1
2445 if delta == p1:
2443 if delta == p1:
2446 nump1prev += 1
2444 nump1prev += 1
2447 elif delta == p2:
2445 elif delta == p2:
2448 nump2prev += 1
2446 nump2prev += 1
2449 elif delta == p1:
2447 elif delta == p1:
2450 nump1 += 1
2448 nump1 += 1
2451 elif delta == p2:
2449 elif delta == p2:
2452 nump2 += 1
2450 nump2 += 1
2453 elif delta != nullrev:
2451 elif delta != nullrev:
2454 numother += 1
2452 numother += 1
2455
2453
2456 # Adjust size min value for empty cases
2454 # Adjust size min value for empty cases
2457 for size in (datasize, fullsize, deltasize):
2455 for size in (datasize, fullsize, deltasize):
2458 if size[0] is None:
2456 if size[0] is None:
2459 size[0] = 0
2457 size[0] = 0
2460
2458
2461 numdeltas = numrevs - numfull
2459 numdeltas = numrevs - numfull
2462 numoprev = numprev - nump1prev - nump2prev
2460 numoprev = numprev - nump1prev - nump2prev
2463 totalrawsize = datasize[2]
2461 totalrawsize = datasize[2]
2464 datasize[2] /= numrevs
2462 datasize[2] /= numrevs
2465 fulltotal = fullsize[2]
2463 fulltotal = fullsize[2]
2466 fullsize[2] /= numfull
2464 fullsize[2] /= numfull
2467 deltatotal = deltasize[2]
2465 deltatotal = deltasize[2]
2468 if numrevs - numfull > 0:
2466 if numrevs - numfull > 0:
2469 deltasize[2] /= numrevs - numfull
2467 deltasize[2] /= numrevs - numfull
2470 totalsize = fulltotal + deltatotal
2468 totalsize = fulltotal + deltatotal
2471 avgchainlen = sum(chainlengths) / numrevs
2469 avgchainlen = sum(chainlengths) / numrevs
2472 compratio = totalrawsize / totalsize
2470 compratio = totalrawsize / totalsize
2473
2471
2474 basedfmtstr = '%%%dd\n'
2472 basedfmtstr = '%%%dd\n'
2475 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2473 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2476
2474
2477 def dfmtstr(max):
2475 def dfmtstr(max):
2478 return basedfmtstr % len(str(max))
2476 return basedfmtstr % len(str(max))
2479 def pcfmtstr(max, padding=0):
2477 def pcfmtstr(max, padding=0):
2480 return basepcfmtstr % (len(str(max)), ' ' * padding)
2478 return basepcfmtstr % (len(str(max)), ' ' * padding)
2481
2479
2482 def pcfmt(value, total):
2480 def pcfmt(value, total):
2483 return (value, 100 * float(value) / total)
2481 return (value, 100 * float(value) / total)
2484
2482
2485 ui.write(('format : %d\n') % format)
2483 ui.write(('format : %d\n') % format)
2486 ui.write(('flags : %s\n') % ', '.join(flags))
2484 ui.write(('flags : %s\n') % ', '.join(flags))
2487
2485
2488 ui.write('\n')
2486 ui.write('\n')
2489 fmt = pcfmtstr(totalsize)
2487 fmt = pcfmtstr(totalsize)
2490 fmt2 = dfmtstr(totalsize)
2488 fmt2 = dfmtstr(totalsize)
2491 ui.write(('revisions : ') + fmt2 % numrevs)
2489 ui.write(('revisions : ') + fmt2 % numrevs)
2492 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2490 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2493 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2491 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2494 ui.write(('revisions : ') + fmt2 % numrevs)
2492 ui.write(('revisions : ') + fmt2 % numrevs)
2495 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2493 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2496 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2494 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2497 ui.write(('revision size : ') + fmt2 % totalsize)
2495 ui.write(('revision size : ') + fmt2 % totalsize)
2498 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2496 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2499 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2497 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2500
2498
2501 ui.write('\n')
2499 ui.write('\n')
2502 fmt = dfmtstr(max(avgchainlen, compratio))
2500 fmt = dfmtstr(max(avgchainlen, compratio))
2503 ui.write(('avg chain length : ') + fmt % avgchainlen)
2501 ui.write(('avg chain length : ') + fmt % avgchainlen)
2504 ui.write(('compression ratio : ') + fmt % compratio)
2502 ui.write(('compression ratio : ') + fmt % compratio)
2505
2503
2506 if format > 0:
2504 if format > 0:
2507 ui.write('\n')
2505 ui.write('\n')
2508 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2506 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2509 % tuple(datasize))
2507 % tuple(datasize))
2510 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2508 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2511 % tuple(fullsize))
2509 % tuple(fullsize))
2512 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2510 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2513 % tuple(deltasize))
2511 % tuple(deltasize))
2514
2512
2515 if numdeltas > 0:
2513 if numdeltas > 0:
2516 ui.write('\n')
2514 ui.write('\n')
2517 fmt = pcfmtstr(numdeltas)
2515 fmt = pcfmtstr(numdeltas)
2518 fmt2 = pcfmtstr(numdeltas, 4)
2516 fmt2 = pcfmtstr(numdeltas, 4)
2519 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2517 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2520 if numprev > 0:
2518 if numprev > 0:
2521 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2519 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2522 numprev))
2520 numprev))
2523 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2521 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2524 numprev))
2522 numprev))
2525 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2523 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2526 numprev))
2524 numprev))
2527 if gdelta:
2525 if gdelta:
2528 ui.write(('deltas against p1 : ')
2526 ui.write(('deltas against p1 : ')
2529 + fmt % pcfmt(nump1, numdeltas))
2527 + fmt % pcfmt(nump1, numdeltas))
2530 ui.write(('deltas against p2 : ')
2528 ui.write(('deltas against p2 : ')
2531 + fmt % pcfmt(nump2, numdeltas))
2529 + fmt % pcfmt(nump2, numdeltas))
2532 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2530 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2533 numdeltas))
2531 numdeltas))
2534
2532
2535 @command('debugrevspec', [], ('REVSPEC'))
2533 @command('debugrevspec', [], ('REVSPEC'))
2536 def debugrevspec(ui, repo, expr):
2534 def debugrevspec(ui, repo, expr):
2537 """parse and apply a revision specification
2535 """parse and apply a revision specification
2538
2536
2539 Use --verbose to print the parsed tree before and after aliases
2537 Use --verbose to print the parsed tree before and after aliases
2540 expansion.
2538 expansion.
2541 """
2539 """
2542 if ui.verbose:
2540 if ui.verbose:
2543 tree = revset.parse(expr)[0]
2541 tree = revset.parse(expr)[0]
2544 ui.note(revset.prettyformat(tree), "\n")
2542 ui.note(revset.prettyformat(tree), "\n")
2545 newtree = revset.findaliases(ui, tree)
2543 newtree = revset.findaliases(ui, tree)
2546 if newtree != tree:
2544 if newtree != tree:
2547 ui.note(revset.prettyformat(newtree), "\n")
2545 ui.note(revset.prettyformat(newtree), "\n")
2548 func = revset.match(ui, expr)
2546 func = revset.match(ui, expr)
2549 for c in func(repo, range(len(repo))):
2547 for c in func(repo, range(len(repo))):
2550 ui.write("%s\n" % c)
2548 ui.write("%s\n" % c)
2551
2549
2552 @command('debugsetparents', [], _('REV1 [REV2]'))
2550 @command('debugsetparents', [], _('REV1 [REV2]'))
2553 def debugsetparents(ui, repo, rev1, rev2=None):
2551 def debugsetparents(ui, repo, rev1, rev2=None):
2554 """manually set the parents of the current working directory
2552 """manually set the parents of the current working directory
2555
2553
2556 This is useful for writing repository conversion tools, but should
2554 This is useful for writing repository conversion tools, but should
2557 be used with care.
2555 be used with care.
2558
2556
2559 Returns 0 on success.
2557 Returns 0 on success.
2560 """
2558 """
2561
2559
2562 r1 = scmutil.revsingle(repo, rev1).node()
2560 r1 = scmutil.revsingle(repo, rev1).node()
2563 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2561 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2564
2562
2565 wlock = repo.wlock()
2563 wlock = repo.wlock()
2566 try:
2564 try:
2567 repo.setparents(r1, r2)
2565 repo.setparents(r1, r2)
2568 finally:
2566 finally:
2569 wlock.release()
2567 wlock.release()
2570
2568
2571 @command('debugdirstate|debugstate',
2569 @command('debugdirstate|debugstate',
2572 [('', 'nodates', None, _('do not display the saved mtime')),
2570 [('', 'nodates', None, _('do not display the saved mtime')),
2573 ('', 'datesort', None, _('sort by saved mtime'))],
2571 ('', 'datesort', None, _('sort by saved mtime'))],
2574 _('[OPTION]...'))
2572 _('[OPTION]...'))
2575 def debugstate(ui, repo, nodates=None, datesort=None):
2573 def debugstate(ui, repo, nodates=None, datesort=None):
2576 """show the contents of the current dirstate"""
2574 """show the contents of the current dirstate"""
2577 timestr = ""
2575 timestr = ""
2578 showdate = not nodates
2576 showdate = not nodates
2579 if datesort:
2577 if datesort:
2580 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2578 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2581 else:
2579 else:
2582 keyfunc = None # sort by filename
2580 keyfunc = None # sort by filename
2583 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2581 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2584 if showdate:
2582 if showdate:
2585 if ent[3] == -1:
2583 if ent[3] == -1:
2586 # Pad or slice to locale representation
2584 # Pad or slice to locale representation
2587 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2585 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2588 time.localtime(0)))
2586 time.localtime(0)))
2589 timestr = 'unset'
2587 timestr = 'unset'
2590 timestr = (timestr[:locale_len] +
2588 timestr = (timestr[:locale_len] +
2591 ' ' * (locale_len - len(timestr)))
2589 ' ' * (locale_len - len(timestr)))
2592 else:
2590 else:
2593 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2591 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2594 time.localtime(ent[3]))
2592 time.localtime(ent[3]))
2595 if ent[1] & 020000:
2593 if ent[1] & 020000:
2596 mode = 'lnk'
2594 mode = 'lnk'
2597 else:
2595 else:
2598 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2596 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2599 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2597 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2600 for f in repo.dirstate.copies():
2598 for f in repo.dirstate.copies():
2601 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2599 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2602
2600
2603 @command('debugsub',
2601 @command('debugsub',
2604 [('r', 'rev', '',
2602 [('r', 'rev', '',
2605 _('revision to check'), _('REV'))],
2603 _('revision to check'), _('REV'))],
2606 _('[-r REV] [REV]'))
2604 _('[-r REV] [REV]'))
2607 def debugsub(ui, repo, rev=None):
2605 def debugsub(ui, repo, rev=None):
2608 ctx = scmutil.revsingle(repo, rev, None)
2606 ctx = scmutil.revsingle(repo, rev, None)
2609 for k, v in sorted(ctx.substate.items()):
2607 for k, v in sorted(ctx.substate.items()):
2610 ui.write(('path %s\n') % k)
2608 ui.write(('path %s\n') % k)
2611 ui.write((' source %s\n') % v[0])
2609 ui.write((' source %s\n') % v[0])
2612 ui.write((' revision %s\n') % v[1])
2610 ui.write((' revision %s\n') % v[1])
2613
2611
2614 @command('debugsuccessorssets',
2612 @command('debugsuccessorssets',
2615 [],
2613 [],
2616 _('[REV]'))
2614 _('[REV]'))
2617 def debugsuccessorssets(ui, repo, *revs):
2615 def debugsuccessorssets(ui, repo, *revs):
2618 """show set of successors for revision
2616 """show set of successors for revision
2619
2617
2620 A successors set of changeset A is a consistent group of revisions that
2618 A successors set of changeset A is a consistent group of revisions that
2621 succeed A. It contains non-obsolete changesets only.
2619 succeed A. It contains non-obsolete changesets only.
2622
2620
2623 In most cases a changeset A has a single successors set containing a single
2621 In most cases a changeset A has a single successors set containing a single
2624 successor (changeset A replaced by A').
2622 successor (changeset A replaced by A').
2625
2623
2626 A changeset that is made obsolete with no successors are called "pruned".
2624 A changeset that is made obsolete with no successors are called "pruned".
2627 Such changesets have no successors sets at all.
2625 Such changesets have no successors sets at all.
2628
2626
2629 A changeset that has been "split" will have a successors set containing
2627 A changeset that has been "split" will have a successors set containing
2630 more than one successor.
2628 more than one successor.
2631
2629
2632 A changeset that has been rewritten in multiple different ways is called
2630 A changeset that has been rewritten in multiple different ways is called
2633 "divergent". Such changesets have multiple successor sets (each of which
2631 "divergent". Such changesets have multiple successor sets (each of which
2634 may also be split, i.e. have multiple successors).
2632 may also be split, i.e. have multiple successors).
2635
2633
2636 Results are displayed as follows::
2634 Results are displayed as follows::
2637
2635
2638 <rev1>
2636 <rev1>
2639 <successors-1A>
2637 <successors-1A>
2640 <rev2>
2638 <rev2>
2641 <successors-2A>
2639 <successors-2A>
2642 <successors-2B1> <successors-2B2> <successors-2B3>
2640 <successors-2B1> <successors-2B2> <successors-2B3>
2643
2641
2644 Here rev2 has two possible (i.e. divergent) successors sets. The first
2642 Here rev2 has two possible (i.e. divergent) successors sets. The first
2645 holds one element, whereas the second holds three (i.e. the changeset has
2643 holds one element, whereas the second holds three (i.e. the changeset has
2646 been split).
2644 been split).
2647 """
2645 """
2648 # passed to successorssets caching computation from one call to another
2646 # passed to successorssets caching computation from one call to another
2649 cache = {}
2647 cache = {}
2650 ctx2str = str
2648 ctx2str = str
2651 node2str = short
2649 node2str = short
2652 if ui.debug():
2650 if ui.debug():
2653 def ctx2str(ctx):
2651 def ctx2str(ctx):
2654 return ctx.hex()
2652 return ctx.hex()
2655 node2str = hex
2653 node2str = hex
2656 for rev in scmutil.revrange(repo, revs):
2654 for rev in scmutil.revrange(repo, revs):
2657 ctx = repo[rev]
2655 ctx = repo[rev]
2658 ui.write('%s\n'% ctx2str(ctx))
2656 ui.write('%s\n'% ctx2str(ctx))
2659 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2657 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2660 if succsset:
2658 if succsset:
2661 ui.write(' ')
2659 ui.write(' ')
2662 ui.write(node2str(succsset[0]))
2660 ui.write(node2str(succsset[0]))
2663 for node in succsset[1:]:
2661 for node in succsset[1:]:
2664 ui.write(' ')
2662 ui.write(' ')
2665 ui.write(node2str(node))
2663 ui.write(node2str(node))
2666 ui.write('\n')
2664 ui.write('\n')
2667
2665
2668 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2666 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2669 def debugwalk(ui, repo, *pats, **opts):
2667 def debugwalk(ui, repo, *pats, **opts):
2670 """show how files match on given patterns"""
2668 """show how files match on given patterns"""
2671 m = scmutil.match(repo[None], pats, opts)
2669 m = scmutil.match(repo[None], pats, opts)
2672 items = list(repo.walk(m))
2670 items = list(repo.walk(m))
2673 if not items:
2671 if not items:
2674 return
2672 return
2675 f = lambda fn: fn
2673 f = lambda fn: fn
2676 if ui.configbool('ui', 'slash') and os.sep != '/':
2674 if ui.configbool('ui', 'slash') and os.sep != '/':
2677 f = lambda fn: util.normpath(fn)
2675 f = lambda fn: util.normpath(fn)
2678 fmt = 'f %%-%ds %%-%ds %%s' % (
2676 fmt = 'f %%-%ds %%-%ds %%s' % (
2679 max([len(abs) for abs in items]),
2677 max([len(abs) for abs in items]),
2680 max([len(m.rel(abs)) for abs in items]))
2678 max([len(m.rel(abs)) for abs in items]))
2681 for abs in items:
2679 for abs in items:
2682 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2680 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2683 ui.write("%s\n" % line.rstrip())
2681 ui.write("%s\n" % line.rstrip())
2684
2682
2685 @command('debugwireargs',
2683 @command('debugwireargs',
2686 [('', 'three', '', 'three'),
2684 [('', 'three', '', 'three'),
2687 ('', 'four', '', 'four'),
2685 ('', 'four', '', 'four'),
2688 ('', 'five', '', 'five'),
2686 ('', 'five', '', 'five'),
2689 ] + remoteopts,
2687 ] + remoteopts,
2690 _('REPO [OPTIONS]... [ONE [TWO]]'))
2688 _('REPO [OPTIONS]... [ONE [TWO]]'))
2691 def debugwireargs(ui, repopath, *vals, **opts):
2689 def debugwireargs(ui, repopath, *vals, **opts):
2692 repo = hg.peer(ui, opts, repopath)
2690 repo = hg.peer(ui, opts, repopath)
2693 for opt in remoteopts:
2691 for opt in remoteopts:
2694 del opts[opt[1]]
2692 del opts[opt[1]]
2695 args = {}
2693 args = {}
2696 for k, v in opts.iteritems():
2694 for k, v in opts.iteritems():
2697 if v:
2695 if v:
2698 args[k] = v
2696 args[k] = v
2699 # run twice to check that we don't mess up the stream for the next command
2697 # run twice to check that we don't mess up the stream for the next command
2700 res1 = repo.debugwireargs(*vals, **args)
2698 res1 = repo.debugwireargs(*vals, **args)
2701 res2 = repo.debugwireargs(*vals, **args)
2699 res2 = repo.debugwireargs(*vals, **args)
2702 ui.write("%s\n" % res1)
2700 ui.write("%s\n" % res1)
2703 if res1 != res2:
2701 if res1 != res2:
2704 ui.warn("%s\n" % res2)
2702 ui.warn("%s\n" % res2)
2705
2703
2706 @command('^diff',
2704 @command('^diff',
2707 [('r', 'rev', [], _('revision'), _('REV')),
2705 [('r', 'rev', [], _('revision'), _('REV')),
2708 ('c', 'change', '', _('change made by revision'), _('REV'))
2706 ('c', 'change', '', _('change made by revision'), _('REV'))
2709 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2707 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2710 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2708 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2711 def diff(ui, repo, *pats, **opts):
2709 def diff(ui, repo, *pats, **opts):
2712 """diff repository (or selected files)
2710 """diff repository (or selected files)
2713
2711
2714 Show differences between revisions for the specified files.
2712 Show differences between revisions for the specified files.
2715
2713
2716 Differences between files are shown using the unified diff format.
2714 Differences between files are shown using the unified diff format.
2717
2715
2718 .. note::
2716 .. note::
2719
2717
2720 diff may generate unexpected results for merges, as it will
2718 diff may generate unexpected results for merges, as it will
2721 default to comparing against the working directory's first
2719 default to comparing against the working directory's first
2722 parent changeset if no revisions are specified.
2720 parent changeset if no revisions are specified.
2723
2721
2724 When two revision arguments are given, then changes are shown
2722 When two revision arguments are given, then changes are shown
2725 between those revisions. If only one revision is specified then
2723 between those revisions. If only one revision is specified then
2726 that revision is compared to the working directory, and, when no
2724 that revision is compared to the working directory, and, when no
2727 revisions are specified, the working directory files are compared
2725 revisions are specified, the working directory files are compared
2728 to its parent.
2726 to its parent.
2729
2727
2730 Alternatively you can specify -c/--change with a revision to see
2728 Alternatively you can specify -c/--change with a revision to see
2731 the changes in that changeset relative to its first parent.
2729 the changes in that changeset relative to its first parent.
2732
2730
2733 Without the -a/--text option, diff will avoid generating diffs of
2731 Without the -a/--text option, diff will avoid generating diffs of
2734 files it detects as binary. With -a, diff will generate a diff
2732 files it detects as binary. With -a, diff will generate a diff
2735 anyway, probably with undesirable results.
2733 anyway, probably with undesirable results.
2736
2734
2737 Use the -g/--git option to generate diffs in the git extended diff
2735 Use the -g/--git option to generate diffs in the git extended diff
2738 format. For more information, read :hg:`help diffs`.
2736 format. For more information, read :hg:`help diffs`.
2739
2737
2740 .. container:: verbose
2738 .. container:: verbose
2741
2739
2742 Examples:
2740 Examples:
2743
2741
2744 - compare a file in the current working directory to its parent::
2742 - compare a file in the current working directory to its parent::
2745
2743
2746 hg diff foo.c
2744 hg diff foo.c
2747
2745
2748 - compare two historical versions of a directory, with rename info::
2746 - compare two historical versions of a directory, with rename info::
2749
2747
2750 hg diff --git -r 1.0:1.2 lib/
2748 hg diff --git -r 1.0:1.2 lib/
2751
2749
2752 - get change stats relative to the last change on some date::
2750 - get change stats relative to the last change on some date::
2753
2751
2754 hg diff --stat -r "date('may 2')"
2752 hg diff --stat -r "date('may 2')"
2755
2753
2756 - diff all newly-added files that contain a keyword::
2754 - diff all newly-added files that contain a keyword::
2757
2755
2758 hg diff "set:added() and grep(GNU)"
2756 hg diff "set:added() and grep(GNU)"
2759
2757
2760 - compare a revision and its parents::
2758 - compare a revision and its parents::
2761
2759
2762 hg diff -c 9353 # compare against first parent
2760 hg diff -c 9353 # compare against first parent
2763 hg diff -r 9353^:9353 # same using revset syntax
2761 hg diff -r 9353^:9353 # same using revset syntax
2764 hg diff -r 9353^2:9353 # compare against the second parent
2762 hg diff -r 9353^2:9353 # compare against the second parent
2765
2763
2766 Returns 0 on success.
2764 Returns 0 on success.
2767 """
2765 """
2768
2766
2769 revs = opts.get('rev')
2767 revs = opts.get('rev')
2770 change = opts.get('change')
2768 change = opts.get('change')
2771 stat = opts.get('stat')
2769 stat = opts.get('stat')
2772 reverse = opts.get('reverse')
2770 reverse = opts.get('reverse')
2773
2771
2774 if revs and change:
2772 if revs and change:
2775 msg = _('cannot specify --rev and --change at the same time')
2773 msg = _('cannot specify --rev and --change at the same time')
2776 raise util.Abort(msg)
2774 raise util.Abort(msg)
2777 elif change:
2775 elif change:
2778 node2 = scmutil.revsingle(repo, change, None).node()
2776 node2 = scmutil.revsingle(repo, change, None).node()
2779 node1 = repo[node2].p1().node()
2777 node1 = repo[node2].p1().node()
2780 else:
2778 else:
2781 node1, node2 = scmutil.revpair(repo, revs)
2779 node1, node2 = scmutil.revpair(repo, revs)
2782
2780
2783 if reverse:
2781 if reverse:
2784 node1, node2 = node2, node1
2782 node1, node2 = node2, node1
2785
2783
2786 diffopts = patch.diffopts(ui, opts)
2784 diffopts = patch.diffopts(ui, opts)
2787 m = scmutil.match(repo[node2], pats, opts)
2785 m = scmutil.match(repo[node2], pats, opts)
2788 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2786 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2789 listsubrepos=opts.get('subrepos'))
2787 listsubrepos=opts.get('subrepos'))
2790
2788
2791 @command('^export',
2789 @command('^export',
2792 [('o', 'output', '',
2790 [('o', 'output', '',
2793 _('print output to file with formatted name'), _('FORMAT')),
2791 _('print output to file with formatted name'), _('FORMAT')),
2794 ('', 'switch-parent', None, _('diff against the second parent')),
2792 ('', 'switch-parent', None, _('diff against the second parent')),
2795 ('r', 'rev', [], _('revisions to export'), _('REV')),
2793 ('r', 'rev', [], _('revisions to export'), _('REV')),
2796 ] + diffopts,
2794 ] + diffopts,
2797 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2795 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2798 def export(ui, repo, *changesets, **opts):
2796 def export(ui, repo, *changesets, **opts):
2799 """dump the header and diffs for one or more changesets
2797 """dump the header and diffs for one or more changesets
2800
2798
2801 Print the changeset header and diffs for one or more revisions.
2799 Print the changeset header and diffs for one or more revisions.
2802 If no revision is given, the parent of the working directory is used.
2800 If no revision is given, the parent of the working directory is used.
2803
2801
2804 The information shown in the changeset header is: author, date,
2802 The information shown in the changeset header is: author, date,
2805 branch name (if non-default), changeset hash, parent(s) and commit
2803 branch name (if non-default), changeset hash, parent(s) and commit
2806 comment.
2804 comment.
2807
2805
2808 .. note::
2806 .. note::
2809
2807
2810 export may generate unexpected diff output for merge
2808 export may generate unexpected diff output for merge
2811 changesets, as it will compare the merge changeset against its
2809 changesets, as it will compare the merge changeset against its
2812 first parent only.
2810 first parent only.
2813
2811
2814 Output may be to a file, in which case the name of the file is
2812 Output may be to a file, in which case the name of the file is
2815 given using a format string. The formatting rules are as follows:
2813 given using a format string. The formatting rules are as follows:
2816
2814
2817 :``%%``: literal "%" character
2815 :``%%``: literal "%" character
2818 :``%H``: changeset hash (40 hexadecimal digits)
2816 :``%H``: changeset hash (40 hexadecimal digits)
2819 :``%N``: number of patches being generated
2817 :``%N``: number of patches being generated
2820 :``%R``: changeset revision number
2818 :``%R``: changeset revision number
2821 :``%b``: basename of the exporting repository
2819 :``%b``: basename of the exporting repository
2822 :``%h``: short-form changeset hash (12 hexadecimal digits)
2820 :``%h``: short-form changeset hash (12 hexadecimal digits)
2823 :``%m``: first line of the commit message (only alphanumeric characters)
2821 :``%m``: first line of the commit message (only alphanumeric characters)
2824 :``%n``: zero-padded sequence number, starting at 1
2822 :``%n``: zero-padded sequence number, starting at 1
2825 :``%r``: zero-padded changeset revision number
2823 :``%r``: zero-padded changeset revision number
2826
2824
2827 Without the -a/--text option, export will avoid generating diffs
2825 Without the -a/--text option, export will avoid generating diffs
2828 of files it detects as binary. With -a, export will generate a
2826 of files it detects as binary. With -a, export will generate a
2829 diff anyway, probably with undesirable results.
2827 diff anyway, probably with undesirable results.
2830
2828
2831 Use the -g/--git option to generate diffs in the git extended diff
2829 Use the -g/--git option to generate diffs in the git extended diff
2832 format. See :hg:`help diffs` for more information.
2830 format. See :hg:`help diffs` for more information.
2833
2831
2834 With the --switch-parent option, the diff will be against the
2832 With the --switch-parent option, the diff will be against the
2835 second parent. It can be useful to review a merge.
2833 second parent. It can be useful to review a merge.
2836
2834
2837 .. container:: verbose
2835 .. container:: verbose
2838
2836
2839 Examples:
2837 Examples:
2840
2838
2841 - use export and import to transplant a bugfix to the current
2839 - use export and import to transplant a bugfix to the current
2842 branch::
2840 branch::
2843
2841
2844 hg export -r 9353 | hg import -
2842 hg export -r 9353 | hg import -
2845
2843
2846 - export all the changesets between two revisions to a file with
2844 - export all the changesets between two revisions to a file with
2847 rename information::
2845 rename information::
2848
2846
2849 hg export --git -r 123:150 > changes.txt
2847 hg export --git -r 123:150 > changes.txt
2850
2848
2851 - split outgoing changes into a series of patches with
2849 - split outgoing changes into a series of patches with
2852 descriptive names::
2850 descriptive names::
2853
2851
2854 hg export -r "outgoing()" -o "%n-%m.patch"
2852 hg export -r "outgoing()" -o "%n-%m.patch"
2855
2853
2856 Returns 0 on success.
2854 Returns 0 on success.
2857 """
2855 """
2858 changesets += tuple(opts.get('rev', []))
2856 changesets += tuple(opts.get('rev', []))
2859 if not changesets:
2857 if not changesets:
2860 changesets = ['.']
2858 changesets = ['.']
2861 revs = scmutil.revrange(repo, changesets)
2859 revs = scmutil.revrange(repo, changesets)
2862 if not revs:
2860 if not revs:
2863 raise util.Abort(_("export requires at least one changeset"))
2861 raise util.Abort(_("export requires at least one changeset"))
2864 if len(revs) > 1:
2862 if len(revs) > 1:
2865 ui.note(_('exporting patches:\n'))
2863 ui.note(_('exporting patches:\n'))
2866 else:
2864 else:
2867 ui.note(_('exporting patch:\n'))
2865 ui.note(_('exporting patch:\n'))
2868 cmdutil.export(repo, revs, template=opts.get('output'),
2866 cmdutil.export(repo, revs, template=opts.get('output'),
2869 switch_parent=opts.get('switch_parent'),
2867 switch_parent=opts.get('switch_parent'),
2870 opts=patch.diffopts(ui, opts))
2868 opts=patch.diffopts(ui, opts))
2871
2869
2872 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2870 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2873 def forget(ui, repo, *pats, **opts):
2871 def forget(ui, repo, *pats, **opts):
2874 """forget the specified files on the next commit
2872 """forget the specified files on the next commit
2875
2873
2876 Mark the specified files so they will no longer be tracked
2874 Mark the specified files so they will no longer be tracked
2877 after the next commit.
2875 after the next commit.
2878
2876
2879 This only removes files from the current branch, not from the
2877 This only removes files from the current branch, not from the
2880 entire project history, and it does not delete them from the
2878 entire project history, and it does not delete them from the
2881 working directory.
2879 working directory.
2882
2880
2883 To undo a forget before the next commit, see :hg:`add`.
2881 To undo a forget before the next commit, see :hg:`add`.
2884
2882
2885 .. container:: verbose
2883 .. container:: verbose
2886
2884
2887 Examples:
2885 Examples:
2888
2886
2889 - forget newly-added binary files::
2887 - forget newly-added binary files::
2890
2888
2891 hg forget "set:added() and binary()"
2889 hg forget "set:added() and binary()"
2892
2890
2893 - forget files that would be excluded by .hgignore::
2891 - forget files that would be excluded by .hgignore::
2894
2892
2895 hg forget "set:hgignore()"
2893 hg forget "set:hgignore()"
2896
2894
2897 Returns 0 on success.
2895 Returns 0 on success.
2898 """
2896 """
2899
2897
2900 if not pats:
2898 if not pats:
2901 raise util.Abort(_('no files specified'))
2899 raise util.Abort(_('no files specified'))
2902
2900
2903 m = scmutil.match(repo[None], pats, opts)
2901 m = scmutil.match(repo[None], pats, opts)
2904 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2902 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2905 return rejected and 1 or 0
2903 return rejected and 1 or 0
2906
2904
2907 @command(
2905 @command(
2908 'graft',
2906 'graft',
2909 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2907 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2910 ('c', 'continue', False, _('resume interrupted graft')),
2908 ('c', 'continue', False, _('resume interrupted graft')),
2911 ('e', 'edit', False, _('invoke editor on commit messages')),
2909 ('e', 'edit', False, _('invoke editor on commit messages')),
2912 ('', 'log', None, _('append graft info to log message')),
2910 ('', 'log', None, _('append graft info to log message')),
2913 ('D', 'currentdate', False,
2911 ('D', 'currentdate', False,
2914 _('record the current date as commit date')),
2912 _('record the current date as commit date')),
2915 ('U', 'currentuser', False,
2913 ('U', 'currentuser', False,
2916 _('record the current user as committer'), _('DATE'))]
2914 _('record the current user as committer'), _('DATE'))]
2917 + commitopts2 + mergetoolopts + dryrunopts,
2915 + commitopts2 + mergetoolopts + dryrunopts,
2918 _('[OPTION]... [-r] REV...'))
2916 _('[OPTION]... [-r] REV...'))
2919 def graft(ui, repo, *revs, **opts):
2917 def graft(ui, repo, *revs, **opts):
2920 '''copy changes from other branches onto the current branch
2918 '''copy changes from other branches onto the current branch
2921
2919
2922 This command uses Mercurial's merge logic to copy individual
2920 This command uses Mercurial's merge logic to copy individual
2923 changes from other branches without merging branches in the
2921 changes from other branches without merging branches in the
2924 history graph. This is sometimes known as 'backporting' or
2922 history graph. This is sometimes known as 'backporting' or
2925 'cherry-picking'. By default, graft will copy user, date, and
2923 'cherry-picking'. By default, graft will copy user, date, and
2926 description from the source changesets.
2924 description from the source changesets.
2927
2925
2928 Changesets that are ancestors of the current revision, that have
2926 Changesets that are ancestors of the current revision, that have
2929 already been grafted, or that are merges will be skipped.
2927 already been grafted, or that are merges will be skipped.
2930
2928
2931 If --log is specified, log messages will have a comment appended
2929 If --log is specified, log messages will have a comment appended
2932 of the form::
2930 of the form::
2933
2931
2934 (grafted from CHANGESETHASH)
2932 (grafted from CHANGESETHASH)
2935
2933
2936 If a graft merge results in conflicts, the graft process is
2934 If a graft merge results in conflicts, the graft process is
2937 interrupted so that the current merge can be manually resolved.
2935 interrupted so that the current merge can be manually resolved.
2938 Once all conflicts are addressed, the graft process can be
2936 Once all conflicts are addressed, the graft process can be
2939 continued with the -c/--continue option.
2937 continued with the -c/--continue option.
2940
2938
2941 .. note::
2939 .. note::
2942
2940
2943 The -c/--continue option does not reapply earlier options.
2941 The -c/--continue option does not reapply earlier options.
2944
2942
2945 .. container:: verbose
2943 .. container:: verbose
2946
2944
2947 Examples:
2945 Examples:
2948
2946
2949 - copy a single change to the stable branch and edit its description::
2947 - copy a single change to the stable branch and edit its description::
2950
2948
2951 hg update stable
2949 hg update stable
2952 hg graft --edit 9393
2950 hg graft --edit 9393
2953
2951
2954 - graft a range of changesets with one exception, updating dates::
2952 - graft a range of changesets with one exception, updating dates::
2955
2953
2956 hg graft -D "2085::2093 and not 2091"
2954 hg graft -D "2085::2093 and not 2091"
2957
2955
2958 - continue a graft after resolving conflicts::
2956 - continue a graft after resolving conflicts::
2959
2957
2960 hg graft -c
2958 hg graft -c
2961
2959
2962 - show the source of a grafted changeset::
2960 - show the source of a grafted changeset::
2963
2961
2964 hg log --debug -r .
2962 hg log --debug -r .
2965
2963
2966 Returns 0 on successful completion.
2964 Returns 0 on successful completion.
2967 '''
2965 '''
2968
2966
2969 revs = list(revs)
2967 revs = list(revs)
2970 revs.extend(opts['rev'])
2968 revs.extend(opts['rev'])
2971
2969
2972 if not opts.get('user') and opts.get('currentuser'):
2970 if not opts.get('user') and opts.get('currentuser'):
2973 opts['user'] = ui.username()
2971 opts['user'] = ui.username()
2974 if not opts.get('date') and opts.get('currentdate'):
2972 if not opts.get('date') and opts.get('currentdate'):
2975 opts['date'] = "%d %d" % util.makedate()
2973 opts['date'] = "%d %d" % util.makedate()
2976
2974
2977 editor = None
2975 editor = None
2978 if opts.get('edit'):
2976 if opts.get('edit'):
2979 editor = cmdutil.commitforceeditor
2977 editor = cmdutil.commitforceeditor
2980
2978
2981 cont = False
2979 cont = False
2982 if opts['continue']:
2980 if opts['continue']:
2983 cont = True
2981 cont = True
2984 if revs:
2982 if revs:
2985 raise util.Abort(_("can't specify --continue and revisions"))
2983 raise util.Abort(_("can't specify --continue and revisions"))
2986 # read in unfinished revisions
2984 # read in unfinished revisions
2987 try:
2985 try:
2988 nodes = repo.opener.read('graftstate').splitlines()
2986 nodes = repo.opener.read('graftstate').splitlines()
2989 revs = [repo[node].rev() for node in nodes]
2987 revs = [repo[node].rev() for node in nodes]
2990 except IOError, inst:
2988 except IOError, inst:
2991 if inst.errno != errno.ENOENT:
2989 if inst.errno != errno.ENOENT:
2992 raise
2990 raise
2993 raise util.Abort(_("no graft state found, can't continue"))
2991 raise util.Abort(_("no graft state found, can't continue"))
2994 else:
2992 else:
2995 cmdutil.checkunfinished(repo)
2993 cmdutil.checkunfinished(repo)
2996 cmdutil.bailifchanged(repo)
2994 cmdutil.bailifchanged(repo)
2997 if not revs:
2995 if not revs:
2998 raise util.Abort(_('no revisions specified'))
2996 raise util.Abort(_('no revisions specified'))
2999 revs = scmutil.revrange(repo, revs)
2997 revs = scmutil.revrange(repo, revs)
3000
2998
3001 # check for merges
2999 # check for merges
3002 for rev in repo.revs('%ld and merge()', revs):
3000 for rev in repo.revs('%ld and merge()', revs):
3003 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3001 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3004 revs.remove(rev)
3002 revs.remove(rev)
3005 if not revs:
3003 if not revs:
3006 return -1
3004 return -1
3007
3005
3008 # check for ancestors of dest branch
3006 # check for ancestors of dest branch
3009 crev = repo['.'].rev()
3007 crev = repo['.'].rev()
3010 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3008 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3011 # don't mutate while iterating, create a copy
3009 # don't mutate while iterating, create a copy
3012 for rev in list(revs):
3010 for rev in list(revs):
3013 if rev in ancestors:
3011 if rev in ancestors:
3014 ui.warn(_('skipping ancestor revision %s\n') % rev)
3012 ui.warn(_('skipping ancestor revision %s\n') % rev)
3015 revs.remove(rev)
3013 revs.remove(rev)
3016 if not revs:
3014 if not revs:
3017 return -1
3015 return -1
3018
3016
3019 # analyze revs for earlier grafts
3017 # analyze revs for earlier grafts
3020 ids = {}
3018 ids = {}
3021 for ctx in repo.set("%ld", revs):
3019 for ctx in repo.set("%ld", revs):
3022 ids[ctx.hex()] = ctx.rev()
3020 ids[ctx.hex()] = ctx.rev()
3023 n = ctx.extra().get('source')
3021 n = ctx.extra().get('source')
3024 if n:
3022 if n:
3025 ids[n] = ctx.rev()
3023 ids[n] = ctx.rev()
3026
3024
3027 # check ancestors for earlier grafts
3025 # check ancestors for earlier grafts
3028 ui.debug('scanning for duplicate grafts\n')
3026 ui.debug('scanning for duplicate grafts\n')
3029
3027
3030 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3028 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3031 ctx = repo[rev]
3029 ctx = repo[rev]
3032 n = ctx.extra().get('source')
3030 n = ctx.extra().get('source')
3033 if n in ids:
3031 if n in ids:
3034 r = repo[n].rev()
3032 r = repo[n].rev()
3035 if r in revs:
3033 if r in revs:
3036 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3034 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3037 % (r, rev))
3035 % (r, rev))
3038 revs.remove(r)
3036 revs.remove(r)
3039 elif ids[n] in revs:
3037 elif ids[n] in revs:
3040 ui.warn(_('skipping already grafted revision %s '
3038 ui.warn(_('skipping already grafted revision %s '
3041 '(%s also has origin %d)\n') % (ids[n], rev, r))
3039 '(%s also has origin %d)\n') % (ids[n], rev, r))
3042 revs.remove(ids[n])
3040 revs.remove(ids[n])
3043 elif ctx.hex() in ids:
3041 elif ctx.hex() in ids:
3044 r = ids[ctx.hex()]
3042 r = ids[ctx.hex()]
3045 ui.warn(_('skipping already grafted revision %s '
3043 ui.warn(_('skipping already grafted revision %s '
3046 '(was grafted from %d)\n') % (r, rev))
3044 '(was grafted from %d)\n') % (r, rev))
3047 revs.remove(r)
3045 revs.remove(r)
3048 if not revs:
3046 if not revs:
3049 return -1
3047 return -1
3050
3048
3051 wlock = repo.wlock()
3049 wlock = repo.wlock()
3052 try:
3050 try:
3053 current = repo['.']
3051 current = repo['.']
3054 for pos, ctx in enumerate(repo.set("%ld", revs)):
3052 for pos, ctx in enumerate(repo.set("%ld", revs)):
3055
3053
3056 ui.status(_('grafting revision %s\n') % ctx.rev())
3054 ui.status(_('grafting revision %s\n') % ctx.rev())
3057 if opts.get('dry_run'):
3055 if opts.get('dry_run'):
3058 continue
3056 continue
3059
3057
3060 source = ctx.extra().get('source')
3058 source = ctx.extra().get('source')
3061 if not source:
3059 if not source:
3062 source = ctx.hex()
3060 source = ctx.hex()
3063 extra = {'source': source}
3061 extra = {'source': source}
3064 user = ctx.user()
3062 user = ctx.user()
3065 if opts.get('user'):
3063 if opts.get('user'):
3066 user = opts['user']
3064 user = opts['user']
3067 date = ctx.date()
3065 date = ctx.date()
3068 if opts.get('date'):
3066 if opts.get('date'):
3069 date = opts['date']
3067 date = opts['date']
3070 message = ctx.description()
3068 message = ctx.description()
3071 if opts.get('log'):
3069 if opts.get('log'):
3072 message += '\n(grafted from %s)' % ctx.hex()
3070 message += '\n(grafted from %s)' % ctx.hex()
3073
3071
3074 # we don't merge the first commit when continuing
3072 # we don't merge the first commit when continuing
3075 if not cont:
3073 if not cont:
3076 # perform the graft merge with p1(rev) as 'ancestor'
3074 # perform the graft merge with p1(rev) as 'ancestor'
3077 try:
3075 try:
3078 # ui.forcemerge is an internal variable, do not document
3076 # ui.forcemerge is an internal variable, do not document
3079 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3077 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3080 stats = mergemod.update(repo, ctx.node(), True, True, False,
3078 stats = mergemod.update(repo, ctx.node(), True, True, False,
3081 ctx.p1().node())
3079 ctx.p1().node())
3082 finally:
3080 finally:
3083 repo.ui.setconfig('ui', 'forcemerge', '')
3081 repo.ui.setconfig('ui', 'forcemerge', '')
3084 # report any conflicts
3082 # report any conflicts
3085 if stats and stats[3] > 0:
3083 if stats and stats[3] > 0:
3086 # write out state for --continue
3084 # write out state for --continue
3087 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3085 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3088 repo.opener.write('graftstate', ''.join(nodelines))
3086 repo.opener.write('graftstate', ''.join(nodelines))
3089 raise util.Abort(
3087 raise util.Abort(
3090 _("unresolved conflicts, can't continue"),
3088 _("unresolved conflicts, can't continue"),
3091 hint=_('use hg resolve and hg graft --continue'))
3089 hint=_('use hg resolve and hg graft --continue'))
3092 else:
3090 else:
3093 cont = False
3091 cont = False
3094
3092
3095 # drop the second merge parent
3093 # drop the second merge parent
3096 repo.setparents(current.node(), nullid)
3094 repo.setparents(current.node(), nullid)
3097 repo.dirstate.write()
3095 repo.dirstate.write()
3098 # fix up dirstate for copies and renames
3096 # fix up dirstate for copies and renames
3099 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3097 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3100
3098
3101 # commit
3099 # commit
3102 node = repo.commit(text=message, user=user,
3100 node = repo.commit(text=message, user=user,
3103 date=date, extra=extra, editor=editor)
3101 date=date, extra=extra, editor=editor)
3104 if node is None:
3102 if node is None:
3105 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3103 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3106 else:
3104 else:
3107 current = repo[node]
3105 current = repo[node]
3108 finally:
3106 finally:
3109 wlock.release()
3107 wlock.release()
3110
3108
3111 # remove state when we complete successfully
3109 # remove state when we complete successfully
3112 if not opts.get('dry_run'):
3110 if not opts.get('dry_run'):
3113 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3111 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3114
3112
3115 return 0
3113 return 0
3116
3114
3117 @command('grep',
3115 @command('grep',
3118 [('0', 'print0', None, _('end fields with NUL')),
3116 [('0', 'print0', None, _('end fields with NUL')),
3119 ('', 'all', None, _('print all revisions that match')),
3117 ('', 'all', None, _('print all revisions that match')),
3120 ('a', 'text', None, _('treat all files as text')),
3118 ('a', 'text', None, _('treat all files as text')),
3121 ('f', 'follow', None,
3119 ('f', 'follow', None,
3122 _('follow changeset history,'
3120 _('follow changeset history,'
3123 ' or file history across copies and renames')),
3121 ' or file history across copies and renames')),
3124 ('i', 'ignore-case', None, _('ignore case when matching')),
3122 ('i', 'ignore-case', None, _('ignore case when matching')),
3125 ('l', 'files-with-matches', None,
3123 ('l', 'files-with-matches', None,
3126 _('print only filenames and revisions that match')),
3124 _('print only filenames and revisions that match')),
3127 ('n', 'line-number', None, _('print matching line numbers')),
3125 ('n', 'line-number', None, _('print matching line numbers')),
3128 ('r', 'rev', [],
3126 ('r', 'rev', [],
3129 _('only search files changed within revision range'), _('REV')),
3127 _('only search files changed within revision range'), _('REV')),
3130 ('u', 'user', None, _('list the author (long with -v)')),
3128 ('u', 'user', None, _('list the author (long with -v)')),
3131 ('d', 'date', None, _('list the date (short with -q)')),
3129 ('d', 'date', None, _('list the date (short with -q)')),
3132 ] + walkopts,
3130 ] + walkopts,
3133 _('[OPTION]... PATTERN [FILE]...'))
3131 _('[OPTION]... PATTERN [FILE]...'))
3134 def grep(ui, repo, pattern, *pats, **opts):
3132 def grep(ui, repo, pattern, *pats, **opts):
3135 """search for a pattern in specified files and revisions
3133 """search for a pattern in specified files and revisions
3136
3134
3137 Search revisions of files for a regular expression.
3135 Search revisions of files for a regular expression.
3138
3136
3139 This command behaves differently than Unix grep. It only accepts
3137 This command behaves differently than Unix grep. It only accepts
3140 Python/Perl regexps. It searches repository history, not the
3138 Python/Perl regexps. It searches repository history, not the
3141 working directory. It always prints the revision number in which a
3139 working directory. It always prints the revision number in which a
3142 match appears.
3140 match appears.
3143
3141
3144 By default, grep only prints output for the first revision of a
3142 By default, grep only prints output for the first revision of a
3145 file in which it finds a match. To get it to print every revision
3143 file in which it finds a match. To get it to print every revision
3146 that contains a change in match status ("-" for a match that
3144 that contains a change in match status ("-" for a match that
3147 becomes a non-match, or "+" for a non-match that becomes a match),
3145 becomes a non-match, or "+" for a non-match that becomes a match),
3148 use the --all flag.
3146 use the --all flag.
3149
3147
3150 Returns 0 if a match is found, 1 otherwise.
3148 Returns 0 if a match is found, 1 otherwise.
3151 """
3149 """
3152 reflags = re.M
3150 reflags = re.M
3153 if opts.get('ignore_case'):
3151 if opts.get('ignore_case'):
3154 reflags |= re.I
3152 reflags |= re.I
3155 try:
3153 try:
3156 regexp = util.compilere(pattern, reflags)
3154 regexp = util.compilere(pattern, reflags)
3157 except re.error, inst:
3155 except re.error, inst:
3158 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3156 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3159 return 1
3157 return 1
3160 sep, eol = ':', '\n'
3158 sep, eol = ':', '\n'
3161 if opts.get('print0'):
3159 if opts.get('print0'):
3162 sep = eol = '\0'
3160 sep = eol = '\0'
3163
3161
3164 getfile = util.lrucachefunc(repo.file)
3162 getfile = util.lrucachefunc(repo.file)
3165
3163
3166 def matchlines(body):
3164 def matchlines(body):
3167 begin = 0
3165 begin = 0
3168 linenum = 0
3166 linenum = 0
3169 while begin < len(body):
3167 while begin < len(body):
3170 match = regexp.search(body, begin)
3168 match = regexp.search(body, begin)
3171 if not match:
3169 if not match:
3172 break
3170 break
3173 mstart, mend = match.span()
3171 mstart, mend = match.span()
3174 linenum += body.count('\n', begin, mstart) + 1
3172 linenum += body.count('\n', begin, mstart) + 1
3175 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3173 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3176 begin = body.find('\n', mend) + 1 or len(body) + 1
3174 begin = body.find('\n', mend) + 1 or len(body) + 1
3177 lend = begin - 1
3175 lend = begin - 1
3178 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3176 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3179
3177
3180 class linestate(object):
3178 class linestate(object):
3181 def __init__(self, line, linenum, colstart, colend):
3179 def __init__(self, line, linenum, colstart, colend):
3182 self.line = line
3180 self.line = line
3183 self.linenum = linenum
3181 self.linenum = linenum
3184 self.colstart = colstart
3182 self.colstart = colstart
3185 self.colend = colend
3183 self.colend = colend
3186
3184
3187 def __hash__(self):
3185 def __hash__(self):
3188 return hash((self.linenum, self.line))
3186 return hash((self.linenum, self.line))
3189
3187
3190 def __eq__(self, other):
3188 def __eq__(self, other):
3191 return self.line == other.line
3189 return self.line == other.line
3192
3190
3193 matches = {}
3191 matches = {}
3194 copies = {}
3192 copies = {}
3195 def grepbody(fn, rev, body):
3193 def grepbody(fn, rev, body):
3196 matches[rev].setdefault(fn, [])
3194 matches[rev].setdefault(fn, [])
3197 m = matches[rev][fn]
3195 m = matches[rev][fn]
3198 for lnum, cstart, cend, line in matchlines(body):
3196 for lnum, cstart, cend, line in matchlines(body):
3199 s = linestate(line, lnum, cstart, cend)
3197 s = linestate(line, lnum, cstart, cend)
3200 m.append(s)
3198 m.append(s)
3201
3199
3202 def difflinestates(a, b):
3200 def difflinestates(a, b):
3203 sm = difflib.SequenceMatcher(None, a, b)
3201 sm = difflib.SequenceMatcher(None, a, b)
3204 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3202 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3205 if tag == 'insert':
3203 if tag == 'insert':
3206 for i in xrange(blo, bhi):
3204 for i in xrange(blo, bhi):
3207 yield ('+', b[i])
3205 yield ('+', b[i])
3208 elif tag == 'delete':
3206 elif tag == 'delete':
3209 for i in xrange(alo, ahi):
3207 for i in xrange(alo, ahi):
3210 yield ('-', a[i])
3208 yield ('-', a[i])
3211 elif tag == 'replace':
3209 elif tag == 'replace':
3212 for i in xrange(alo, ahi):
3210 for i in xrange(alo, ahi):
3213 yield ('-', a[i])
3211 yield ('-', a[i])
3214 for i in xrange(blo, bhi):
3212 for i in xrange(blo, bhi):
3215 yield ('+', b[i])
3213 yield ('+', b[i])
3216
3214
3217 def display(fn, ctx, pstates, states):
3215 def display(fn, ctx, pstates, states):
3218 rev = ctx.rev()
3216 rev = ctx.rev()
3219 datefunc = ui.quiet and util.shortdate or util.datestr
3217 datefunc = ui.quiet and util.shortdate or util.datestr
3220 found = False
3218 found = False
3221 filerevmatches = {}
3219 filerevmatches = {}
3222 def binary():
3220 def binary():
3223 flog = getfile(fn)
3221 flog = getfile(fn)
3224 return util.binary(flog.read(ctx.filenode(fn)))
3222 return util.binary(flog.read(ctx.filenode(fn)))
3225
3223
3226 if opts.get('all'):
3224 if opts.get('all'):
3227 iter = difflinestates(pstates, states)
3225 iter = difflinestates(pstates, states)
3228 else:
3226 else:
3229 iter = [('', l) for l in states]
3227 iter = [('', l) for l in states]
3230 for change, l in iter:
3228 for change, l in iter:
3231 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3229 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3232 before, match, after = None, None, None
3230 before, match, after = None, None, None
3233
3231
3234 if opts.get('line_number'):
3232 if opts.get('line_number'):
3235 cols.append((str(l.linenum), 'grep.linenumber'))
3233 cols.append((str(l.linenum), 'grep.linenumber'))
3236 if opts.get('all'):
3234 if opts.get('all'):
3237 cols.append((change, 'grep.change'))
3235 cols.append((change, 'grep.change'))
3238 if opts.get('user'):
3236 if opts.get('user'):
3239 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3237 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3240 if opts.get('date'):
3238 if opts.get('date'):
3241 cols.append((datefunc(ctx.date()), 'grep.date'))
3239 cols.append((datefunc(ctx.date()), 'grep.date'))
3242 if opts.get('files_with_matches'):
3240 if opts.get('files_with_matches'):
3243 c = (fn, rev)
3241 c = (fn, rev)
3244 if c in filerevmatches:
3242 if c in filerevmatches:
3245 continue
3243 continue
3246 filerevmatches[c] = 1
3244 filerevmatches[c] = 1
3247 else:
3245 else:
3248 before = l.line[:l.colstart]
3246 before = l.line[:l.colstart]
3249 match = l.line[l.colstart:l.colend]
3247 match = l.line[l.colstart:l.colend]
3250 after = l.line[l.colend:]
3248 after = l.line[l.colend:]
3251 for col, label in cols[:-1]:
3249 for col, label in cols[:-1]:
3252 ui.write(col, label=label)
3250 ui.write(col, label=label)
3253 ui.write(sep, label='grep.sep')
3251 ui.write(sep, label='grep.sep')
3254 ui.write(cols[-1][0], label=cols[-1][1])
3252 ui.write(cols[-1][0], label=cols[-1][1])
3255 if before is not None:
3253 if before is not None:
3256 ui.write(sep, label='grep.sep')
3254 ui.write(sep, label='grep.sep')
3257 if not opts.get('text') and binary():
3255 if not opts.get('text') and binary():
3258 ui.write(" Binary file matches")
3256 ui.write(" Binary file matches")
3259 else:
3257 else:
3260 ui.write(before)
3258 ui.write(before)
3261 ui.write(match, label='grep.match')
3259 ui.write(match, label='grep.match')
3262 ui.write(after)
3260 ui.write(after)
3263 ui.write(eol)
3261 ui.write(eol)
3264 found = True
3262 found = True
3265 return found
3263 return found
3266
3264
3267 skip = {}
3265 skip = {}
3268 revfiles = {}
3266 revfiles = {}
3269 matchfn = scmutil.match(repo[None], pats, opts)
3267 matchfn = scmutil.match(repo[None], pats, opts)
3270 found = False
3268 found = False
3271 follow = opts.get('follow')
3269 follow = opts.get('follow')
3272
3270
3273 def prep(ctx, fns):
3271 def prep(ctx, fns):
3274 rev = ctx.rev()
3272 rev = ctx.rev()
3275 pctx = ctx.p1()
3273 pctx = ctx.p1()
3276 parent = pctx.rev()
3274 parent = pctx.rev()
3277 matches.setdefault(rev, {})
3275 matches.setdefault(rev, {})
3278 matches.setdefault(parent, {})
3276 matches.setdefault(parent, {})
3279 files = revfiles.setdefault(rev, [])
3277 files = revfiles.setdefault(rev, [])
3280 for fn in fns:
3278 for fn in fns:
3281 flog = getfile(fn)
3279 flog = getfile(fn)
3282 try:
3280 try:
3283 fnode = ctx.filenode(fn)
3281 fnode = ctx.filenode(fn)
3284 except error.LookupError:
3282 except error.LookupError:
3285 continue
3283 continue
3286
3284
3287 copied = flog.renamed(fnode)
3285 copied = flog.renamed(fnode)
3288 copy = follow and copied and copied[0]
3286 copy = follow and copied and copied[0]
3289 if copy:
3287 if copy:
3290 copies.setdefault(rev, {})[fn] = copy
3288 copies.setdefault(rev, {})[fn] = copy
3291 if fn in skip:
3289 if fn in skip:
3292 if copy:
3290 if copy:
3293 skip[copy] = True
3291 skip[copy] = True
3294 continue
3292 continue
3295 files.append(fn)
3293 files.append(fn)
3296
3294
3297 if fn not in matches[rev]:
3295 if fn not in matches[rev]:
3298 grepbody(fn, rev, flog.read(fnode))
3296 grepbody(fn, rev, flog.read(fnode))
3299
3297
3300 pfn = copy or fn
3298 pfn = copy or fn
3301 if pfn not in matches[parent]:
3299 if pfn not in matches[parent]:
3302 try:
3300 try:
3303 fnode = pctx.filenode(pfn)
3301 fnode = pctx.filenode(pfn)
3304 grepbody(pfn, parent, flog.read(fnode))
3302 grepbody(pfn, parent, flog.read(fnode))
3305 except error.LookupError:
3303 except error.LookupError:
3306 pass
3304 pass
3307
3305
3308 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3306 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3309 rev = ctx.rev()
3307 rev = ctx.rev()
3310 parent = ctx.p1().rev()
3308 parent = ctx.p1().rev()
3311 for fn in sorted(revfiles.get(rev, [])):
3309 for fn in sorted(revfiles.get(rev, [])):
3312 states = matches[rev][fn]
3310 states = matches[rev][fn]
3313 copy = copies.get(rev, {}).get(fn)
3311 copy = copies.get(rev, {}).get(fn)
3314 if fn in skip:
3312 if fn in skip:
3315 if copy:
3313 if copy:
3316 skip[copy] = True
3314 skip[copy] = True
3317 continue
3315 continue
3318 pstates = matches.get(parent, {}).get(copy or fn, [])
3316 pstates = matches.get(parent, {}).get(copy or fn, [])
3319 if pstates or states:
3317 if pstates or states:
3320 r = display(fn, ctx, pstates, states)
3318 r = display(fn, ctx, pstates, states)
3321 found = found or r
3319 found = found or r
3322 if r and not opts.get('all'):
3320 if r and not opts.get('all'):
3323 skip[fn] = True
3321 skip[fn] = True
3324 if copy:
3322 if copy:
3325 skip[copy] = True
3323 skip[copy] = True
3326 del matches[rev]
3324 del matches[rev]
3327 del revfiles[rev]
3325 del revfiles[rev]
3328
3326
3329 return not found
3327 return not found
3330
3328
3331 @command('heads',
3329 @command('heads',
3332 [('r', 'rev', '',
3330 [('r', 'rev', '',
3333 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3331 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3334 ('t', 'topo', False, _('show topological heads only')),
3332 ('t', 'topo', False, _('show topological heads only')),
3335 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3333 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3336 ('c', 'closed', False, _('show normal and closed branch heads')),
3334 ('c', 'closed', False, _('show normal and closed branch heads')),
3337 ] + templateopts,
3335 ] + templateopts,
3338 _('[-ct] [-r STARTREV] [REV]...'))
3336 _('[-ct] [-r STARTREV] [REV]...'))
3339 def heads(ui, repo, *branchrevs, **opts):
3337 def heads(ui, repo, *branchrevs, **opts):
3340 """show branch heads
3338 """show branch heads
3341
3339
3342 With no arguments, show all open branch heads in the repository.
3340 With no arguments, show all open branch heads in the repository.
3343 Branch heads are changesets that have no descendants on the
3341 Branch heads are changesets that have no descendants on the
3344 same branch. They are where development generally takes place and
3342 same branch. They are where development generally takes place and
3345 are the usual targets for update and merge operations.
3343 are the usual targets for update and merge operations.
3346
3344
3347 If one or more REVs are given, only open branch heads on the
3345 If one or more REVs are given, only open branch heads on the
3348 branches associated with the specified changesets are shown. This
3346 branches associated with the specified changesets are shown. This
3349 means that you can use :hg:`heads .` to see the heads on the
3347 means that you can use :hg:`heads .` to see the heads on the
3350 currently checked-out branch.
3348 currently checked-out branch.
3351
3349
3352 If -c/--closed is specified, also show branch heads marked closed
3350 If -c/--closed is specified, also show branch heads marked closed
3353 (see :hg:`commit --close-branch`).
3351 (see :hg:`commit --close-branch`).
3354
3352
3355 If STARTREV is specified, only those heads that are descendants of
3353 If STARTREV is specified, only those heads that are descendants of
3356 STARTREV will be displayed.
3354 STARTREV will be displayed.
3357
3355
3358 If -t/--topo is specified, named branch mechanics will be ignored and only
3356 If -t/--topo is specified, named branch mechanics will be ignored and only
3359 topological heads (changesets with no children) will be shown.
3357 topological heads (changesets with no children) will be shown.
3360
3358
3361 Returns 0 if matching heads are found, 1 if not.
3359 Returns 0 if matching heads are found, 1 if not.
3362 """
3360 """
3363
3361
3364 start = None
3362 start = None
3365 if 'rev' in opts:
3363 if 'rev' in opts:
3366 start = scmutil.revsingle(repo, opts['rev'], None).node()
3364 start = scmutil.revsingle(repo, opts['rev'], None).node()
3367
3365
3368 if opts.get('topo'):
3366 if opts.get('topo'):
3369 heads = [repo[h] for h in repo.heads(start)]
3367 heads = [repo[h] for h in repo.heads(start)]
3370 else:
3368 else:
3371 heads = []
3369 heads = []
3372 for branch in repo.branchmap():
3370 for branch in repo.branchmap():
3373 heads += repo.branchheads(branch, start, opts.get('closed'))
3371 heads += repo.branchheads(branch, start, opts.get('closed'))
3374 heads = [repo[h] for h in heads]
3372 heads = [repo[h] for h in heads]
3375
3373
3376 if branchrevs:
3374 if branchrevs:
3377 branches = set(repo[br].branch() for br in branchrevs)
3375 branches = set(repo[br].branch() for br in branchrevs)
3378 heads = [h for h in heads if h.branch() in branches]
3376 heads = [h for h in heads if h.branch() in branches]
3379
3377
3380 if opts.get('active') and branchrevs:
3378 if opts.get('active') and branchrevs:
3381 dagheads = repo.heads(start)
3379 dagheads = repo.heads(start)
3382 heads = [h for h in heads if h.node() in dagheads]
3380 heads = [h for h in heads if h.node() in dagheads]
3383
3381
3384 if branchrevs:
3382 if branchrevs:
3385 haveheads = set(h.branch() for h in heads)
3383 haveheads = set(h.branch() for h in heads)
3386 if branches - haveheads:
3384 if branches - haveheads:
3387 headless = ', '.join(b for b in branches - haveheads)
3385 headless = ', '.join(b for b in branches - haveheads)
3388 msg = _('no open branch heads found on branches %s')
3386 msg = _('no open branch heads found on branches %s')
3389 if opts.get('rev'):
3387 if opts.get('rev'):
3390 msg += _(' (started at %s)') % opts['rev']
3388 msg += _(' (started at %s)') % opts['rev']
3391 ui.warn((msg + '\n') % headless)
3389 ui.warn((msg + '\n') % headless)
3392
3390
3393 if not heads:
3391 if not heads:
3394 return 1
3392 return 1
3395
3393
3396 heads = sorted(heads, key=lambda x: -x.rev())
3394 heads = sorted(heads, key=lambda x: -x.rev())
3397 displayer = cmdutil.show_changeset(ui, repo, opts)
3395 displayer = cmdutil.show_changeset(ui, repo, opts)
3398 for ctx in heads:
3396 for ctx in heads:
3399 displayer.show(ctx)
3397 displayer.show(ctx)
3400 displayer.close()
3398 displayer.close()
3401
3399
3402 @command('help',
3400 @command('help',
3403 [('e', 'extension', None, _('show only help for extensions')),
3401 [('e', 'extension', None, _('show only help for extensions')),
3404 ('c', 'command', None, _('show only help for commands')),
3402 ('c', 'command', None, _('show only help for commands')),
3405 ('k', 'keyword', '', _('show topics matching keyword')),
3403 ('k', 'keyword', '', _('show topics matching keyword')),
3406 ],
3404 ],
3407 _('[-ec] [TOPIC]'))
3405 _('[-ec] [TOPIC]'))
3408 def help_(ui, name=None, **opts):
3406 def help_(ui, name=None, **opts):
3409 """show help for a given topic or a help overview
3407 """show help for a given topic or a help overview
3410
3408
3411 With no arguments, print a list of commands with short help messages.
3409 With no arguments, print a list of commands with short help messages.
3412
3410
3413 Given a topic, extension, or command name, print help for that
3411 Given a topic, extension, or command name, print help for that
3414 topic.
3412 topic.
3415
3413
3416 Returns 0 if successful.
3414 Returns 0 if successful.
3417 """
3415 """
3418
3416
3419 textwidth = min(ui.termwidth(), 80) - 2
3417 textwidth = min(ui.termwidth(), 80) - 2
3420
3418
3421 keep = ui.verbose and ['verbose'] or []
3419 keep = ui.verbose and ['verbose'] or []
3422 text = help.help_(ui, name, **opts)
3420 text = help.help_(ui, name, **opts)
3423
3421
3424 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3422 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3425 if 'verbose' in pruned:
3423 if 'verbose' in pruned:
3426 keep.append('omitted')
3424 keep.append('omitted')
3427 else:
3425 else:
3428 keep.append('notomitted')
3426 keep.append('notomitted')
3429 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3427 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3430 ui.write(formatted)
3428 ui.write(formatted)
3431
3429
3432
3430
3433 @command('identify|id',
3431 @command('identify|id',
3434 [('r', 'rev', '',
3432 [('r', 'rev', '',
3435 _('identify the specified revision'), _('REV')),
3433 _('identify the specified revision'), _('REV')),
3436 ('n', 'num', None, _('show local revision number')),
3434 ('n', 'num', None, _('show local revision number')),
3437 ('i', 'id', None, _('show global revision id')),
3435 ('i', 'id', None, _('show global revision id')),
3438 ('b', 'branch', None, _('show branch')),
3436 ('b', 'branch', None, _('show branch')),
3439 ('t', 'tags', None, _('show tags')),
3437 ('t', 'tags', None, _('show tags')),
3440 ('B', 'bookmarks', None, _('show bookmarks')),
3438 ('B', 'bookmarks', None, _('show bookmarks')),
3441 ] + remoteopts,
3439 ] + remoteopts,
3442 _('[-nibtB] [-r REV] [SOURCE]'))
3440 _('[-nibtB] [-r REV] [SOURCE]'))
3443 def identify(ui, repo, source=None, rev=None,
3441 def identify(ui, repo, source=None, rev=None,
3444 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3442 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3445 """identify the working copy or specified revision
3443 """identify the working copy or specified revision
3446
3444
3447 Print a summary identifying the repository state at REV using one or
3445 Print a summary identifying the repository state at REV using one or
3448 two parent hash identifiers, followed by a "+" if the working
3446 two parent hash identifiers, followed by a "+" if the working
3449 directory has uncommitted changes, the branch name (if not default),
3447 directory has uncommitted changes, the branch name (if not default),
3450 a list of tags, and a list of bookmarks.
3448 a list of tags, and a list of bookmarks.
3451
3449
3452 When REV is not given, print a summary of the current state of the
3450 When REV is not given, print a summary of the current state of the
3453 repository.
3451 repository.
3454
3452
3455 Specifying a path to a repository root or Mercurial bundle will
3453 Specifying a path to a repository root or Mercurial bundle will
3456 cause lookup to operate on that repository/bundle.
3454 cause lookup to operate on that repository/bundle.
3457
3455
3458 .. container:: verbose
3456 .. container:: verbose
3459
3457
3460 Examples:
3458 Examples:
3461
3459
3462 - generate a build identifier for the working directory::
3460 - generate a build identifier for the working directory::
3463
3461
3464 hg id --id > build-id.dat
3462 hg id --id > build-id.dat
3465
3463
3466 - find the revision corresponding to a tag::
3464 - find the revision corresponding to a tag::
3467
3465
3468 hg id -n -r 1.3
3466 hg id -n -r 1.3
3469
3467
3470 - check the most recent revision of a remote repository::
3468 - check the most recent revision of a remote repository::
3471
3469
3472 hg id -r tip http://selenic.com/hg/
3470 hg id -r tip http://selenic.com/hg/
3473
3471
3474 Returns 0 if successful.
3472 Returns 0 if successful.
3475 """
3473 """
3476
3474
3477 if not repo and not source:
3475 if not repo and not source:
3478 raise util.Abort(_("there is no Mercurial repository here "
3476 raise util.Abort(_("there is no Mercurial repository here "
3479 "(.hg not found)"))
3477 "(.hg not found)"))
3480
3478
3481 hexfunc = ui.debugflag and hex or short
3479 hexfunc = ui.debugflag and hex or short
3482 default = not (num or id or branch or tags or bookmarks)
3480 default = not (num or id or branch or tags or bookmarks)
3483 output = []
3481 output = []
3484 revs = []
3482 revs = []
3485
3483
3486 if source:
3484 if source:
3487 source, branches = hg.parseurl(ui.expandpath(source))
3485 source, branches = hg.parseurl(ui.expandpath(source))
3488 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3486 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3489 repo = peer.local()
3487 repo = peer.local()
3490 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3488 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3491
3489
3492 if not repo:
3490 if not repo:
3493 if num or branch or tags:
3491 if num or branch or tags:
3494 raise util.Abort(
3492 raise util.Abort(
3495 _("can't query remote revision number, branch, or tags"))
3493 _("can't query remote revision number, branch, or tags"))
3496 if not rev and revs:
3494 if not rev and revs:
3497 rev = revs[0]
3495 rev = revs[0]
3498 if not rev:
3496 if not rev:
3499 rev = "tip"
3497 rev = "tip"
3500
3498
3501 remoterev = peer.lookup(rev)
3499 remoterev = peer.lookup(rev)
3502 if default or id:
3500 if default or id:
3503 output = [hexfunc(remoterev)]
3501 output = [hexfunc(remoterev)]
3504
3502
3505 def getbms():
3503 def getbms():
3506 bms = []
3504 bms = []
3507
3505
3508 if 'bookmarks' in peer.listkeys('namespaces'):
3506 if 'bookmarks' in peer.listkeys('namespaces'):
3509 hexremoterev = hex(remoterev)
3507 hexremoterev = hex(remoterev)
3510 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3508 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3511 if bmr == hexremoterev]
3509 if bmr == hexremoterev]
3512
3510
3513 return sorted(bms)
3511 return sorted(bms)
3514
3512
3515 if bookmarks:
3513 if bookmarks:
3516 output.extend(getbms())
3514 output.extend(getbms())
3517 elif default and not ui.quiet:
3515 elif default and not ui.quiet:
3518 # multiple bookmarks for a single parent separated by '/'
3516 # multiple bookmarks for a single parent separated by '/'
3519 bm = '/'.join(getbms())
3517 bm = '/'.join(getbms())
3520 if bm:
3518 if bm:
3521 output.append(bm)
3519 output.append(bm)
3522 else:
3520 else:
3523 if not rev:
3521 if not rev:
3524 ctx = repo[None]
3522 ctx = repo[None]
3525 parents = ctx.parents()
3523 parents = ctx.parents()
3526 changed = ""
3524 changed = ""
3527 if default or id or num:
3525 if default or id or num:
3528 if (util.any(repo.status())
3526 if (util.any(repo.status())
3529 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3527 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3530 changed = '+'
3528 changed = '+'
3531 if default or id:
3529 if default or id:
3532 output = ["%s%s" %
3530 output = ["%s%s" %
3533 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3531 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3534 if num:
3532 if num:
3535 output.append("%s%s" %
3533 output.append("%s%s" %
3536 ('+'.join([str(p.rev()) for p in parents]), changed))
3534 ('+'.join([str(p.rev()) for p in parents]), changed))
3537 else:
3535 else:
3538 ctx = scmutil.revsingle(repo, rev)
3536 ctx = scmutil.revsingle(repo, rev)
3539 if default or id:
3537 if default or id:
3540 output = [hexfunc(ctx.node())]
3538 output = [hexfunc(ctx.node())]
3541 if num:
3539 if num:
3542 output.append(str(ctx.rev()))
3540 output.append(str(ctx.rev()))
3543
3541
3544 if default and not ui.quiet:
3542 if default and not ui.quiet:
3545 b = ctx.branch()
3543 b = ctx.branch()
3546 if b != 'default':
3544 if b != 'default':
3547 output.append("(%s)" % b)
3545 output.append("(%s)" % b)
3548
3546
3549 # multiple tags for a single parent separated by '/'
3547 # multiple tags for a single parent separated by '/'
3550 t = '/'.join(ctx.tags())
3548 t = '/'.join(ctx.tags())
3551 if t:
3549 if t:
3552 output.append(t)
3550 output.append(t)
3553
3551
3554 # multiple bookmarks for a single parent separated by '/'
3552 # multiple bookmarks for a single parent separated by '/'
3555 bm = '/'.join(ctx.bookmarks())
3553 bm = '/'.join(ctx.bookmarks())
3556 if bm:
3554 if bm:
3557 output.append(bm)
3555 output.append(bm)
3558 else:
3556 else:
3559 if branch:
3557 if branch:
3560 output.append(ctx.branch())
3558 output.append(ctx.branch())
3561
3559
3562 if tags:
3560 if tags:
3563 output.extend(ctx.tags())
3561 output.extend(ctx.tags())
3564
3562
3565 if bookmarks:
3563 if bookmarks:
3566 output.extend(ctx.bookmarks())
3564 output.extend(ctx.bookmarks())
3567
3565
3568 ui.write("%s\n" % ' '.join(output))
3566 ui.write("%s\n" % ' '.join(output))
3569
3567
3570 @command('import|patch',
3568 @command('import|patch',
3571 [('p', 'strip', 1,
3569 [('p', 'strip', 1,
3572 _('directory strip option for patch. This has the same '
3570 _('directory strip option for patch. This has the same '
3573 'meaning as the corresponding patch option'), _('NUM')),
3571 'meaning as the corresponding patch option'), _('NUM')),
3574 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3572 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3575 ('e', 'edit', False, _('invoke editor on commit messages')),
3573 ('e', 'edit', False, _('invoke editor on commit messages')),
3576 ('f', 'force', None,
3574 ('f', 'force', None,
3577 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3575 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3578 ('', 'no-commit', None,
3576 ('', 'no-commit', None,
3579 _("don't commit, just update the working directory")),
3577 _("don't commit, just update the working directory")),
3580 ('', 'bypass', None,
3578 ('', 'bypass', None,
3581 _("apply patch without touching the working directory")),
3579 _("apply patch without touching the working directory")),
3582 ('', 'exact', None,
3580 ('', 'exact', None,
3583 _('apply patch to the nodes from which it was generated')),
3581 _('apply patch to the nodes from which it was generated')),
3584 ('', 'import-branch', None,
3582 ('', 'import-branch', None,
3585 _('use any branch information in patch (implied by --exact)'))] +
3583 _('use any branch information in patch (implied by --exact)'))] +
3586 commitopts + commitopts2 + similarityopts,
3584 commitopts + commitopts2 + similarityopts,
3587 _('[OPTION]... PATCH...'))
3585 _('[OPTION]... PATCH...'))
3588 def import_(ui, repo, patch1=None, *patches, **opts):
3586 def import_(ui, repo, patch1=None, *patches, **opts):
3589 """import an ordered set of patches
3587 """import an ordered set of patches
3590
3588
3591 Import a list of patches and commit them individually (unless
3589 Import a list of patches and commit them individually (unless
3592 --no-commit is specified).
3590 --no-commit is specified).
3593
3591
3594 Because import first applies changes to the working directory,
3592 Because import first applies changes to the working directory,
3595 import will abort if there are outstanding changes.
3593 import will abort if there are outstanding changes.
3596
3594
3597 You can import a patch straight from a mail message. Even patches
3595 You can import a patch straight from a mail message. Even patches
3598 as attachments work (to use the body part, it must have type
3596 as attachments work (to use the body part, it must have type
3599 text/plain or text/x-patch). From and Subject headers of email
3597 text/plain or text/x-patch). From and Subject headers of email
3600 message are used as default committer and commit message. All
3598 message are used as default committer and commit message. All
3601 text/plain body parts before first diff are added to commit
3599 text/plain body parts before first diff are added to commit
3602 message.
3600 message.
3603
3601
3604 If the imported patch was generated by :hg:`export`, user and
3602 If the imported patch was generated by :hg:`export`, user and
3605 description from patch override values from message headers and
3603 description from patch override values from message headers and
3606 body. Values given on command line with -m/--message and -u/--user
3604 body. Values given on command line with -m/--message and -u/--user
3607 override these.
3605 override these.
3608
3606
3609 If --exact is specified, import will set the working directory to
3607 If --exact is specified, import will set the working directory to
3610 the parent of each patch before applying it, and will abort if the
3608 the parent of each patch before applying it, and will abort if the
3611 resulting changeset has a different ID than the one recorded in
3609 resulting changeset has a different ID than the one recorded in
3612 the patch. This may happen due to character set problems or other
3610 the patch. This may happen due to character set problems or other
3613 deficiencies in the text patch format.
3611 deficiencies in the text patch format.
3614
3612
3615 Use --bypass to apply and commit patches directly to the
3613 Use --bypass to apply and commit patches directly to the
3616 repository, not touching the working directory. Without --exact,
3614 repository, not touching the working directory. Without --exact,
3617 patches will be applied on top of the working directory parent
3615 patches will be applied on top of the working directory parent
3618 revision.
3616 revision.
3619
3617
3620 With -s/--similarity, hg will attempt to discover renames and
3618 With -s/--similarity, hg will attempt to discover renames and
3621 copies in the patch in the same way as :hg:`addremove`.
3619 copies in the patch in the same way as :hg:`addremove`.
3622
3620
3623 To read a patch from standard input, use "-" as the patch name. If
3621 To read a patch from standard input, use "-" as the patch name. If
3624 a URL is specified, the patch will be downloaded from it.
3622 a URL is specified, the patch will be downloaded from it.
3625 See :hg:`help dates` for a list of formats valid for -d/--date.
3623 See :hg:`help dates` for a list of formats valid for -d/--date.
3626
3624
3627 .. container:: verbose
3625 .. container:: verbose
3628
3626
3629 Examples:
3627 Examples:
3630
3628
3631 - import a traditional patch from a website and detect renames::
3629 - import a traditional patch from a website and detect renames::
3632
3630
3633 hg import -s 80 http://example.com/bugfix.patch
3631 hg import -s 80 http://example.com/bugfix.patch
3634
3632
3635 - import a changeset from an hgweb server::
3633 - import a changeset from an hgweb server::
3636
3634
3637 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3635 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3638
3636
3639 - import all the patches in an Unix-style mbox::
3637 - import all the patches in an Unix-style mbox::
3640
3638
3641 hg import incoming-patches.mbox
3639 hg import incoming-patches.mbox
3642
3640
3643 - attempt to exactly restore an exported changeset (not always
3641 - attempt to exactly restore an exported changeset (not always
3644 possible)::
3642 possible)::
3645
3643
3646 hg import --exact proposed-fix.patch
3644 hg import --exact proposed-fix.patch
3647
3645
3648 Returns 0 on success.
3646 Returns 0 on success.
3649 """
3647 """
3650
3648
3651 if not patch1:
3649 if not patch1:
3652 raise util.Abort(_('need at least one patch to import'))
3650 raise util.Abort(_('need at least one patch to import'))
3653
3651
3654 patches = (patch1,) + patches
3652 patches = (patch1,) + patches
3655
3653
3656 date = opts.get('date')
3654 date = opts.get('date')
3657 if date:
3655 if date:
3658 opts['date'] = util.parsedate(date)
3656 opts['date'] = util.parsedate(date)
3659
3657
3660 editor = cmdutil.commiteditor
3658 editor = cmdutil.commiteditor
3661 if opts.get('edit'):
3659 if opts.get('edit'):
3662 editor = cmdutil.commitforceeditor
3660 editor = cmdutil.commitforceeditor
3663
3661
3664 update = not opts.get('bypass')
3662 update = not opts.get('bypass')
3665 if not update and opts.get('no_commit'):
3663 if not update and opts.get('no_commit'):
3666 raise util.Abort(_('cannot use --no-commit with --bypass'))
3664 raise util.Abort(_('cannot use --no-commit with --bypass'))
3667 try:
3665 try:
3668 sim = float(opts.get('similarity') or 0)
3666 sim = float(opts.get('similarity') or 0)
3669 except ValueError:
3667 except ValueError:
3670 raise util.Abort(_('similarity must be a number'))
3668 raise util.Abort(_('similarity must be a number'))
3671 if sim < 0 or sim > 100:
3669 if sim < 0 or sim > 100:
3672 raise util.Abort(_('similarity must be between 0 and 100'))
3670 raise util.Abort(_('similarity must be between 0 and 100'))
3673 if sim and not update:
3671 if sim and not update:
3674 raise util.Abort(_('cannot use --similarity with --bypass'))
3672 raise util.Abort(_('cannot use --similarity with --bypass'))
3675
3673
3676 if update:
3674 if update:
3677 cmdutil.checkunfinished(repo)
3675 cmdutil.checkunfinished(repo)
3678 if (opts.get('exact') or not opts.get('force')) and update:
3676 if (opts.get('exact') or not opts.get('force')) and update:
3679 cmdutil.bailifchanged(repo)
3677 cmdutil.bailifchanged(repo)
3680
3678
3681 base = opts["base"]
3679 base = opts["base"]
3682 strip = opts["strip"]
3680 strip = opts["strip"]
3683 wlock = lock = tr = None
3681 wlock = lock = tr = None
3684 msgs = []
3682 msgs = []
3685
3683
3686 def tryone(ui, hunk, parents):
3684 def tryone(ui, hunk, parents):
3687 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3685 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3688 patch.extract(ui, hunk)
3686 patch.extract(ui, hunk)
3689
3687
3690 if not tmpname:
3688 if not tmpname:
3691 return (None, None)
3689 return (None, None)
3692 msg = _('applied to working directory')
3690 msg = _('applied to working directory')
3693
3691
3694 try:
3692 try:
3695 cmdline_message = cmdutil.logmessage(ui, opts)
3693 cmdline_message = cmdutil.logmessage(ui, opts)
3696 if cmdline_message:
3694 if cmdline_message:
3697 # pickup the cmdline msg
3695 # pickup the cmdline msg
3698 message = cmdline_message
3696 message = cmdline_message
3699 elif message:
3697 elif message:
3700 # pickup the patch msg
3698 # pickup the patch msg
3701 message = message.strip()
3699 message = message.strip()
3702 else:
3700 else:
3703 # launch the editor
3701 # launch the editor
3704 message = None
3702 message = None
3705 ui.debug('message:\n%s\n' % message)
3703 ui.debug('message:\n%s\n' % message)
3706
3704
3707 if len(parents) == 1:
3705 if len(parents) == 1:
3708 parents.append(repo[nullid])
3706 parents.append(repo[nullid])
3709 if opts.get('exact'):
3707 if opts.get('exact'):
3710 if not nodeid or not p1:
3708 if not nodeid or not p1:
3711 raise util.Abort(_('not a Mercurial patch'))
3709 raise util.Abort(_('not a Mercurial patch'))
3712 p1 = repo[p1]
3710 p1 = repo[p1]
3713 p2 = repo[p2 or nullid]
3711 p2 = repo[p2 or nullid]
3714 elif p2:
3712 elif p2:
3715 try:
3713 try:
3716 p1 = repo[p1]
3714 p1 = repo[p1]
3717 p2 = repo[p2]
3715 p2 = repo[p2]
3718 # Without any options, consider p2 only if the
3716 # Without any options, consider p2 only if the
3719 # patch is being applied on top of the recorded
3717 # patch is being applied on top of the recorded
3720 # first parent.
3718 # first parent.
3721 if p1 != parents[0]:
3719 if p1 != parents[0]:
3722 p1 = parents[0]
3720 p1 = parents[0]
3723 p2 = repo[nullid]
3721 p2 = repo[nullid]
3724 except error.RepoError:
3722 except error.RepoError:
3725 p1, p2 = parents
3723 p1, p2 = parents
3726 else:
3724 else:
3727 p1, p2 = parents
3725 p1, p2 = parents
3728
3726
3729 n = None
3727 n = None
3730 if update:
3728 if update:
3731 if p1 != parents[0]:
3729 if p1 != parents[0]:
3732 hg.clean(repo, p1.node())
3730 hg.clean(repo, p1.node())
3733 if p2 != parents[1]:
3731 if p2 != parents[1]:
3734 repo.setparents(p1.node(), p2.node())
3732 repo.setparents(p1.node(), p2.node())
3735
3733
3736 if opts.get('exact') or opts.get('import_branch'):
3734 if opts.get('exact') or opts.get('import_branch'):
3737 repo.dirstate.setbranch(branch or 'default')
3735 repo.dirstate.setbranch(branch or 'default')
3738
3736
3739 files = set()
3737 files = set()
3740 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3738 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3741 eolmode=None, similarity=sim / 100.0)
3739 eolmode=None, similarity=sim / 100.0)
3742 files = list(files)
3740 files = list(files)
3743 if opts.get('no_commit'):
3741 if opts.get('no_commit'):
3744 if message:
3742 if message:
3745 msgs.append(message)
3743 msgs.append(message)
3746 else:
3744 else:
3747 if opts.get('exact') or p2:
3745 if opts.get('exact') or p2:
3748 # If you got here, you either use --force and know what
3746 # If you got here, you either use --force and know what
3749 # you are doing or used --exact or a merge patch while
3747 # you are doing or used --exact or a merge patch while
3750 # being updated to its first parent.
3748 # being updated to its first parent.
3751 m = None
3749 m = None
3752 else:
3750 else:
3753 m = scmutil.matchfiles(repo, files or [])
3751 m = scmutil.matchfiles(repo, files or [])
3754 n = repo.commit(message, opts.get('user') or user,
3752 n = repo.commit(message, opts.get('user') or user,
3755 opts.get('date') or date, match=m,
3753 opts.get('date') or date, match=m,
3756 editor=editor)
3754 editor=editor)
3757 else:
3755 else:
3758 if opts.get('exact') or opts.get('import_branch'):
3756 if opts.get('exact') or opts.get('import_branch'):
3759 branch = branch or 'default'
3757 branch = branch or 'default'
3760 else:
3758 else:
3761 branch = p1.branch()
3759 branch = p1.branch()
3762 store = patch.filestore()
3760 store = patch.filestore()
3763 try:
3761 try:
3764 files = set()
3762 files = set()
3765 try:
3763 try:
3766 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3764 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3767 files, eolmode=None)
3765 files, eolmode=None)
3768 except patch.PatchError, e:
3766 except patch.PatchError, e:
3769 raise util.Abort(str(e))
3767 raise util.Abort(str(e))
3770 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3768 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3771 message,
3769 message,
3772 opts.get('user') or user,
3770 opts.get('user') or user,
3773 opts.get('date') or date,
3771 opts.get('date') or date,
3774 branch, files, store,
3772 branch, files, store,
3775 editor=cmdutil.commiteditor)
3773 editor=cmdutil.commiteditor)
3776 repo.savecommitmessage(memctx.description())
3774 repo.savecommitmessage(memctx.description())
3777 n = memctx.commit()
3775 n = memctx.commit()
3778 finally:
3776 finally:
3779 store.close()
3777 store.close()
3780 if opts.get('exact') and hex(n) != nodeid:
3778 if opts.get('exact') and hex(n) != nodeid:
3781 raise util.Abort(_('patch is damaged or loses information'))
3779 raise util.Abort(_('patch is damaged or loses information'))
3782 if n:
3780 if n:
3783 # i18n: refers to a short changeset id
3781 # i18n: refers to a short changeset id
3784 msg = _('created %s') % short(n)
3782 msg = _('created %s') % short(n)
3785 return (msg, n)
3783 return (msg, n)
3786 finally:
3784 finally:
3787 os.unlink(tmpname)
3785 os.unlink(tmpname)
3788
3786
3789 try:
3787 try:
3790 try:
3788 try:
3791 wlock = repo.wlock()
3789 wlock = repo.wlock()
3792 if not opts.get('no_commit'):
3790 if not opts.get('no_commit'):
3793 lock = repo.lock()
3791 lock = repo.lock()
3794 tr = repo.transaction('import')
3792 tr = repo.transaction('import')
3795 parents = repo.parents()
3793 parents = repo.parents()
3796 for patchurl in patches:
3794 for patchurl in patches:
3797 if patchurl == '-':
3795 if patchurl == '-':
3798 ui.status(_('applying patch from stdin\n'))
3796 ui.status(_('applying patch from stdin\n'))
3799 patchfile = ui.fin
3797 patchfile = ui.fin
3800 patchurl = 'stdin' # for error message
3798 patchurl = 'stdin' # for error message
3801 else:
3799 else:
3802 patchurl = os.path.join(base, patchurl)
3800 patchurl = os.path.join(base, patchurl)
3803 ui.status(_('applying %s\n') % patchurl)
3801 ui.status(_('applying %s\n') % patchurl)
3804 patchfile = hg.openpath(ui, patchurl)
3802 patchfile = hg.openpath(ui, patchurl)
3805
3803
3806 haspatch = False
3804 haspatch = False
3807 for hunk in patch.split(patchfile):
3805 for hunk in patch.split(patchfile):
3808 (msg, node) = tryone(ui, hunk, parents)
3806 (msg, node) = tryone(ui, hunk, parents)
3809 if msg:
3807 if msg:
3810 haspatch = True
3808 haspatch = True
3811 ui.note(msg + '\n')
3809 ui.note(msg + '\n')
3812 if update or opts.get('exact'):
3810 if update or opts.get('exact'):
3813 parents = repo.parents()
3811 parents = repo.parents()
3814 else:
3812 else:
3815 parents = [repo[node]]
3813 parents = [repo[node]]
3816
3814
3817 if not haspatch:
3815 if not haspatch:
3818 raise util.Abort(_('%s: no diffs found') % patchurl)
3816 raise util.Abort(_('%s: no diffs found') % patchurl)
3819
3817
3820 if tr:
3818 if tr:
3821 tr.close()
3819 tr.close()
3822 if msgs:
3820 if msgs:
3823 repo.savecommitmessage('\n* * *\n'.join(msgs))
3821 repo.savecommitmessage('\n* * *\n'.join(msgs))
3824 except: # re-raises
3822 except: # re-raises
3825 # wlock.release() indirectly calls dirstate.write(): since
3823 # wlock.release() indirectly calls dirstate.write(): since
3826 # we're crashing, we do not want to change the working dir
3824 # we're crashing, we do not want to change the working dir
3827 # parent after all, so make sure it writes nothing
3825 # parent after all, so make sure it writes nothing
3828 repo.dirstate.invalidate()
3826 repo.dirstate.invalidate()
3829 raise
3827 raise
3830 finally:
3828 finally:
3831 if tr:
3829 if tr:
3832 tr.release()
3830 tr.release()
3833 release(lock, wlock)
3831 release(lock, wlock)
3834
3832
3835 @command('incoming|in',
3833 @command('incoming|in',
3836 [('f', 'force', None,
3834 [('f', 'force', None,
3837 _('run even if remote repository is unrelated')),
3835 _('run even if remote repository is unrelated')),
3838 ('n', 'newest-first', None, _('show newest record first')),
3836 ('n', 'newest-first', None, _('show newest record first')),
3839 ('', 'bundle', '',
3837 ('', 'bundle', '',
3840 _('file to store the bundles into'), _('FILE')),
3838 _('file to store the bundles into'), _('FILE')),
3841 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3839 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3842 ('B', 'bookmarks', False, _("compare bookmarks")),
3840 ('B', 'bookmarks', False, _("compare bookmarks")),
3843 ('b', 'branch', [],
3841 ('b', 'branch', [],
3844 _('a specific branch you would like to pull'), _('BRANCH')),
3842 _('a specific branch you would like to pull'), _('BRANCH')),
3845 ] + logopts + remoteopts + subrepoopts,
3843 ] + logopts + remoteopts + subrepoopts,
3846 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3844 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3847 def incoming(ui, repo, source="default", **opts):
3845 def incoming(ui, repo, source="default", **opts):
3848 """show new changesets found in source
3846 """show new changesets found in source
3849
3847
3850 Show new changesets found in the specified path/URL or the default
3848 Show new changesets found in the specified path/URL or the default
3851 pull location. These are the changesets that would have been pulled
3849 pull location. These are the changesets that would have been pulled
3852 if a pull at the time you issued this command.
3850 if a pull at the time you issued this command.
3853
3851
3854 For remote repository, using --bundle avoids downloading the
3852 For remote repository, using --bundle avoids downloading the
3855 changesets twice if the incoming is followed by a pull.
3853 changesets twice if the incoming is followed by a pull.
3856
3854
3857 See pull for valid source format details.
3855 See pull for valid source format details.
3858
3856
3859 Returns 0 if there are incoming changes, 1 otherwise.
3857 Returns 0 if there are incoming changes, 1 otherwise.
3860 """
3858 """
3861 if opts.get('graph'):
3859 if opts.get('graph'):
3862 cmdutil.checkunsupportedgraphflags([], opts)
3860 cmdutil.checkunsupportedgraphflags([], opts)
3863 def display(other, chlist, displayer):
3861 def display(other, chlist, displayer):
3864 revdag = cmdutil.graphrevs(other, chlist, opts)
3862 revdag = cmdutil.graphrevs(other, chlist, opts)
3865 showparents = [ctx.node() for ctx in repo[None].parents()]
3863 showparents = [ctx.node() for ctx in repo[None].parents()]
3866 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3864 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3867 graphmod.asciiedges)
3865 graphmod.asciiedges)
3868
3866
3869 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3867 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3870 return 0
3868 return 0
3871
3869
3872 if opts.get('bundle') and opts.get('subrepos'):
3870 if opts.get('bundle') and opts.get('subrepos'):
3873 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3871 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3874
3872
3875 if opts.get('bookmarks'):
3873 if opts.get('bookmarks'):
3876 source, branches = hg.parseurl(ui.expandpath(source),
3874 source, branches = hg.parseurl(ui.expandpath(source),
3877 opts.get('branch'))
3875 opts.get('branch'))
3878 other = hg.peer(repo, opts, source)
3876 other = hg.peer(repo, opts, source)
3879 if 'bookmarks' not in other.listkeys('namespaces'):
3877 if 'bookmarks' not in other.listkeys('namespaces'):
3880 ui.warn(_("remote doesn't support bookmarks\n"))
3878 ui.warn(_("remote doesn't support bookmarks\n"))
3881 return 0
3879 return 0
3882 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3880 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3883 return bookmarks.diff(ui, repo, other)
3881 return bookmarks.diff(ui, repo, other)
3884
3882
3885 repo._subtoppath = ui.expandpath(source)
3883 repo._subtoppath = ui.expandpath(source)
3886 try:
3884 try:
3887 return hg.incoming(ui, repo, source, opts)
3885 return hg.incoming(ui, repo, source, opts)
3888 finally:
3886 finally:
3889 del repo._subtoppath
3887 del repo._subtoppath
3890
3888
3891
3889
3892 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3890 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3893 def init(ui, dest=".", **opts):
3891 def init(ui, dest=".", **opts):
3894 """create a new repository in the given directory
3892 """create a new repository in the given directory
3895
3893
3896 Initialize a new repository in the given directory. If the given
3894 Initialize a new repository in the given directory. If the given
3897 directory does not exist, it will be created.
3895 directory does not exist, it will be created.
3898
3896
3899 If no directory is given, the current directory is used.
3897 If no directory is given, the current directory is used.
3900
3898
3901 It is possible to specify an ``ssh://`` URL as the destination.
3899 It is possible to specify an ``ssh://`` URL as the destination.
3902 See :hg:`help urls` for more information.
3900 See :hg:`help urls` for more information.
3903
3901
3904 Returns 0 on success.
3902 Returns 0 on success.
3905 """
3903 """
3906 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3904 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3907
3905
3908 @command('locate',
3906 @command('locate',
3909 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3907 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3910 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3908 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3911 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3909 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3912 ] + walkopts,
3910 ] + walkopts,
3913 _('[OPTION]... [PATTERN]...'))
3911 _('[OPTION]... [PATTERN]...'))
3914 def locate(ui, repo, *pats, **opts):
3912 def locate(ui, repo, *pats, **opts):
3915 """locate files matching specific patterns
3913 """locate files matching specific patterns
3916
3914
3917 Print files under Mercurial control in the working directory whose
3915 Print files under Mercurial control in the working directory whose
3918 names match the given patterns.
3916 names match the given patterns.
3919
3917
3920 By default, this command searches all directories in the working
3918 By default, this command searches all directories in the working
3921 directory. To search just the current directory and its
3919 directory. To search just the current directory and its
3922 subdirectories, use "--include .".
3920 subdirectories, use "--include .".
3923
3921
3924 If no patterns are given to match, this command prints the names
3922 If no patterns are given to match, this command prints the names
3925 of all files under Mercurial control in the working directory.
3923 of all files under Mercurial control in the working directory.
3926
3924
3927 If you want to feed the output of this command into the "xargs"
3925 If you want to feed the output of this command into the "xargs"
3928 command, use the -0 option to both this command and "xargs". This
3926 command, use the -0 option to both this command and "xargs". This
3929 will avoid the problem of "xargs" treating single filenames that
3927 will avoid the problem of "xargs" treating single filenames that
3930 contain whitespace as multiple filenames.
3928 contain whitespace as multiple filenames.
3931
3929
3932 Returns 0 if a match is found, 1 otherwise.
3930 Returns 0 if a match is found, 1 otherwise.
3933 """
3931 """
3934 end = opts.get('print0') and '\0' or '\n'
3932 end = opts.get('print0') and '\0' or '\n'
3935 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3933 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3936
3934
3937 ret = 1
3935 ret = 1
3938 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3936 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3939 m.bad = lambda x, y: False
3937 m.bad = lambda x, y: False
3940 for abs in repo[rev].walk(m):
3938 for abs in repo[rev].walk(m):
3941 if not rev and abs not in repo.dirstate:
3939 if not rev and abs not in repo.dirstate:
3942 continue
3940 continue
3943 if opts.get('fullpath'):
3941 if opts.get('fullpath'):
3944 ui.write(repo.wjoin(abs), end)
3942 ui.write(repo.wjoin(abs), end)
3945 else:
3943 else:
3946 ui.write(((pats and m.rel(abs)) or abs), end)
3944 ui.write(((pats and m.rel(abs)) or abs), end)
3947 ret = 0
3945 ret = 0
3948
3946
3949 return ret
3947 return ret
3950
3948
3951 @command('^log|history',
3949 @command('^log|history',
3952 [('f', 'follow', None,
3950 [('f', 'follow', None,
3953 _('follow changeset history, or file history across copies and renames')),
3951 _('follow changeset history, or file history across copies and renames')),
3954 ('', 'follow-first', None,
3952 ('', 'follow-first', None,
3955 _('only follow the first parent of merge changesets (DEPRECATED)')),
3953 _('only follow the first parent of merge changesets (DEPRECATED)')),
3956 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3954 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3957 ('C', 'copies', None, _('show copied files')),
3955 ('C', 'copies', None, _('show copied files')),
3958 ('k', 'keyword', [],
3956 ('k', 'keyword', [],
3959 _('do case-insensitive search for a given text'), _('TEXT')),
3957 _('do case-insensitive search for a given text'), _('TEXT')),
3960 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3958 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3961 ('', 'removed', None, _('include revisions where files were removed')),
3959 ('', 'removed', None, _('include revisions where files were removed')),
3962 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3960 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3963 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3961 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3964 ('', 'only-branch', [],
3962 ('', 'only-branch', [],
3965 _('show only changesets within the given named branch (DEPRECATED)'),
3963 _('show only changesets within the given named branch (DEPRECATED)'),
3966 _('BRANCH')),
3964 _('BRANCH')),
3967 ('b', 'branch', [],
3965 ('b', 'branch', [],
3968 _('show changesets within the given named branch'), _('BRANCH')),
3966 _('show changesets within the given named branch'), _('BRANCH')),
3969 ('P', 'prune', [],
3967 ('P', 'prune', [],
3970 _('do not display revision or any of its ancestors'), _('REV')),
3968 _('do not display revision or any of its ancestors'), _('REV')),
3971 ] + logopts + walkopts,
3969 ] + logopts + walkopts,
3972 _('[OPTION]... [FILE]'))
3970 _('[OPTION]... [FILE]'))
3973 def log(ui, repo, *pats, **opts):
3971 def log(ui, repo, *pats, **opts):
3974 """show revision history of entire repository or files
3972 """show revision history of entire repository or files
3975
3973
3976 Print the revision history of the specified files or the entire
3974 Print the revision history of the specified files or the entire
3977 project.
3975 project.
3978
3976
3979 If no revision range is specified, the default is ``tip:0`` unless
3977 If no revision range is specified, the default is ``tip:0`` unless
3980 --follow is set, in which case the working directory parent is
3978 --follow is set, in which case the working directory parent is
3981 used as the starting revision.
3979 used as the starting revision.
3982
3980
3983 File history is shown without following rename or copy history of
3981 File history is shown without following rename or copy history of
3984 files. Use -f/--follow with a filename to follow history across
3982 files. Use -f/--follow with a filename to follow history across
3985 renames and copies. --follow without a filename will only show
3983 renames and copies. --follow without a filename will only show
3986 ancestors or descendants of the starting revision.
3984 ancestors or descendants of the starting revision.
3987
3985
3988 By default this command prints revision number and changeset id,
3986 By default this command prints revision number and changeset id,
3989 tags, non-trivial parents, user, date and time, and a summary for
3987 tags, non-trivial parents, user, date and time, and a summary for
3990 each commit. When the -v/--verbose switch is used, the list of
3988 each commit. When the -v/--verbose switch is used, the list of
3991 changed files and full commit message are shown.
3989 changed files and full commit message are shown.
3992
3990
3993 .. note::
3991 .. note::
3994
3992
3995 log -p/--patch may generate unexpected diff output for merge
3993 log -p/--patch may generate unexpected diff output for merge
3996 changesets, as it will only compare the merge changeset against
3994 changesets, as it will only compare the merge changeset against
3997 its first parent. Also, only files different from BOTH parents
3995 its first parent. Also, only files different from BOTH parents
3998 will appear in files:.
3996 will appear in files:.
3999
3997
4000 .. note::
3998 .. note::
4001
3999
4002 for performance reasons, log FILE may omit duplicate changes
4000 for performance reasons, log FILE may omit duplicate changes
4003 made on branches and will not show deletions. To see all
4001 made on branches and will not show deletions. To see all
4004 changes including duplicates and deletions, use the --removed
4002 changes including duplicates and deletions, use the --removed
4005 switch.
4003 switch.
4006
4004
4007 .. container:: verbose
4005 .. container:: verbose
4008
4006
4009 Some examples:
4007 Some examples:
4010
4008
4011 - changesets with full descriptions and file lists::
4009 - changesets with full descriptions and file lists::
4012
4010
4013 hg log -v
4011 hg log -v
4014
4012
4015 - changesets ancestral to the working directory::
4013 - changesets ancestral to the working directory::
4016
4014
4017 hg log -f
4015 hg log -f
4018
4016
4019 - last 10 commits on the current branch::
4017 - last 10 commits on the current branch::
4020
4018
4021 hg log -l 10 -b .
4019 hg log -l 10 -b .
4022
4020
4023 - changesets showing all modifications of a file, including removals::
4021 - changesets showing all modifications of a file, including removals::
4024
4022
4025 hg log --removed file.c
4023 hg log --removed file.c
4026
4024
4027 - all changesets that touch a directory, with diffs, excluding merges::
4025 - all changesets that touch a directory, with diffs, excluding merges::
4028
4026
4029 hg log -Mp lib/
4027 hg log -Mp lib/
4030
4028
4031 - all revision numbers that match a keyword::
4029 - all revision numbers that match a keyword::
4032
4030
4033 hg log -k bug --template "{rev}\\n"
4031 hg log -k bug --template "{rev}\\n"
4034
4032
4035 - check if a given changeset is included is a tagged release::
4033 - check if a given changeset is included is a tagged release::
4036
4034
4037 hg log -r "a21ccf and ancestor(1.9)"
4035 hg log -r "a21ccf and ancestor(1.9)"
4038
4036
4039 - find all changesets by some user in a date range::
4037 - find all changesets by some user in a date range::
4040
4038
4041 hg log -k alice -d "may 2008 to jul 2008"
4039 hg log -k alice -d "may 2008 to jul 2008"
4042
4040
4043 - summary of all changesets after the last tag::
4041 - summary of all changesets after the last tag::
4044
4042
4045 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4043 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4046
4044
4047 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.
4048
4046
4049 See :hg:`help revisions` and :hg:`help revsets` for more about
4047 See :hg:`help revisions` and :hg:`help revsets` for more about
4050 specifying revisions.
4048 specifying revisions.
4051
4049
4052 See :hg:`help templates` for more about pre-packaged styles and
4050 See :hg:`help templates` for more about pre-packaged styles and
4053 specifying custom templates.
4051 specifying custom templates.
4054
4052
4055 Returns 0 on success.
4053 Returns 0 on success.
4056 """
4054 """
4057 if opts.get('graph'):
4055 if opts.get('graph'):
4058 return cmdutil.graphlog(ui, repo, *pats, **opts)
4056 return cmdutil.graphlog(ui, repo, *pats, **opts)
4059
4057
4060 matchfn = scmutil.match(repo[None], pats, opts)
4058 matchfn = scmutil.match(repo[None], pats, opts)
4061 limit = cmdutil.loglimit(opts)
4059 limit = cmdutil.loglimit(opts)
4062 count = 0
4060 count = 0
4063
4061
4064 getrenamed, endrev = None, None
4062 getrenamed, endrev = None, None
4065 if opts.get('copies'):
4063 if opts.get('copies'):
4066 if opts.get('rev'):
4064 if opts.get('rev'):
4067 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4065 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4068 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4066 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4069
4067
4070 df = False
4068 df = False
4071 if opts.get("date"):
4069 if opts.get("date"):
4072 df = util.matchdate(opts["date"])
4070 df = util.matchdate(opts["date"])
4073
4071
4074 branches = opts.get('branch', []) + opts.get('only_branch', [])
4072 branches = opts.get('branch', []) + opts.get('only_branch', [])
4075 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4073 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4076
4074
4077 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4075 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4078 def prep(ctx, fns):
4076 def prep(ctx, fns):
4079 rev = ctx.rev()
4077 rev = ctx.rev()
4080 parents = [p for p in repo.changelog.parentrevs(rev)
4078 parents = [p for p in repo.changelog.parentrevs(rev)
4081 if p != nullrev]
4079 if p != nullrev]
4082 if opts.get('no_merges') and len(parents) == 2:
4080 if opts.get('no_merges') and len(parents) == 2:
4083 return
4081 return
4084 if opts.get('only_merges') and len(parents) != 2:
4082 if opts.get('only_merges') and len(parents) != 2:
4085 return
4083 return
4086 if opts.get('branch') and ctx.branch() not in opts['branch']:
4084 if opts.get('branch') and ctx.branch() not in opts['branch']:
4087 return
4085 return
4088 if df and not df(ctx.date()[0]):
4086 if df and not df(ctx.date()[0]):
4089 return
4087 return
4090
4088
4091 lower = encoding.lower
4089 lower = encoding.lower
4092 if opts.get('user'):
4090 if opts.get('user'):
4093 luser = lower(ctx.user())
4091 luser = lower(ctx.user())
4094 for k in [lower(x) for x in opts['user']]:
4092 for k in [lower(x) for x in opts['user']]:
4095 if (k in luser):
4093 if (k in luser):
4096 break
4094 break
4097 else:
4095 else:
4098 return
4096 return
4099 if opts.get('keyword'):
4097 if opts.get('keyword'):
4100 luser = lower(ctx.user())
4098 luser = lower(ctx.user())
4101 ldesc = lower(ctx.description())
4099 ldesc = lower(ctx.description())
4102 lfiles = lower(" ".join(ctx.files()))
4100 lfiles = lower(" ".join(ctx.files()))
4103 for k in [lower(x) for x in opts['keyword']]:
4101 for k in [lower(x) for x in opts['keyword']]:
4104 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):
4105 break
4103 break
4106 else:
4104 else:
4107 return
4105 return
4108
4106
4109 copies = None
4107 copies = None
4110 if getrenamed is not None and rev:
4108 if getrenamed is not None and rev:
4111 copies = []
4109 copies = []
4112 for fn in ctx.files():
4110 for fn in ctx.files():
4113 rename = getrenamed(fn, rev)
4111 rename = getrenamed(fn, rev)
4114 if rename:
4112 if rename:
4115 copies.append((fn, rename[0]))
4113 copies.append((fn, rename[0]))
4116
4114
4117 revmatchfn = None
4115 revmatchfn = None
4118 if opts.get('patch') or opts.get('stat'):
4116 if opts.get('patch') or opts.get('stat'):
4119 if opts.get('follow') or opts.get('follow_first'):
4117 if opts.get('follow') or opts.get('follow_first'):
4120 # note: this might be wrong when following through merges
4118 # note: this might be wrong when following through merges
4121 revmatchfn = scmutil.match(repo[None], fns, default='path')
4119 revmatchfn = scmutil.match(repo[None], fns, default='path')
4122 else:
4120 else:
4123 revmatchfn = matchfn
4121 revmatchfn = matchfn
4124
4122
4125 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4123 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4126
4124
4127 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4125 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4128 if displayer.flush(ctx.rev()):
4126 if displayer.flush(ctx.rev()):
4129 count += 1
4127 count += 1
4130 if count == limit:
4128 if count == limit:
4131 break
4129 break
4132 displayer.close()
4130 displayer.close()
4133
4131
4134 @command('manifest',
4132 @command('manifest',
4135 [('r', 'rev', '', _('revision to display'), _('REV')),
4133 [('r', 'rev', '', _('revision to display'), _('REV')),
4136 ('', 'all', False, _("list files from all revisions"))],
4134 ('', 'all', False, _("list files from all revisions"))],
4137 _('[-r REV]'))
4135 _('[-r REV]'))
4138 def manifest(ui, repo, node=None, rev=None, **opts):
4136 def manifest(ui, repo, node=None, rev=None, **opts):
4139 """output the current or given revision of the project manifest
4137 """output the current or given revision of the project manifest
4140
4138
4141 Print a list of version controlled files for the given revision.
4139 Print a list of version controlled files for the given revision.
4142 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
4143 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.
4144
4142
4145 With -v, print file permissions, symlink and executable bits.
4143 With -v, print file permissions, symlink and executable bits.
4146 With --debug, print file revision hashes.
4144 With --debug, print file revision hashes.
4147
4145
4148 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
4149 is printed. This includes deleted and renamed files.
4147 is printed. This includes deleted and renamed files.
4150
4148
4151 Returns 0 on success.
4149 Returns 0 on success.
4152 """
4150 """
4153
4151
4154 fm = ui.formatter('manifest', opts)
4152 fm = ui.formatter('manifest', opts)
4155
4153
4156 if opts.get('all'):
4154 if opts.get('all'):
4157 if rev or node:
4155 if rev or node:
4158 raise util.Abort(_("can't specify a revision with --all"))
4156 raise util.Abort(_("can't specify a revision with --all"))
4159
4157
4160 res = []
4158 res = []
4161 prefix = "data/"
4159 prefix = "data/"
4162 suffix = ".i"
4160 suffix = ".i"
4163 plen = len(prefix)
4161 plen = len(prefix)
4164 slen = len(suffix)
4162 slen = len(suffix)
4165 lock = repo.lock()
4163 lock = repo.lock()
4166 try:
4164 try:
4167 for fn, b, size in repo.store.datafiles():
4165 for fn, b, size in repo.store.datafiles():
4168 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4166 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4169 res.append(fn[plen:-slen])
4167 res.append(fn[plen:-slen])
4170 finally:
4168 finally:
4171 lock.release()
4169 lock.release()
4172 for f in res:
4170 for f in res:
4173 fm.startitem()
4171 fm.startitem()
4174 fm.write("path", '%s\n', f)
4172 fm.write("path", '%s\n', f)
4175 fm.end()
4173 fm.end()
4176 return
4174 return
4177
4175
4178 if rev and node:
4176 if rev and node:
4179 raise util.Abort(_("please specify just one revision"))
4177 raise util.Abort(_("please specify just one revision"))
4180
4178
4181 if not node:
4179 if not node:
4182 node = rev
4180 node = rev
4183
4181
4184 char = {'l': '@', 'x': '*', '': ''}
4182 char = {'l': '@', 'x': '*', '': ''}
4185 mode = {'l': '644', 'x': '755', '': '644'}
4183 mode = {'l': '644', 'x': '755', '': '644'}
4186 ctx = scmutil.revsingle(repo, node)
4184 ctx = scmutil.revsingle(repo, node)
4187 mf = ctx.manifest()
4185 mf = ctx.manifest()
4188 for f in ctx:
4186 for f in ctx:
4189 fm.startitem()
4187 fm.startitem()
4190 fl = ctx[f].flags()
4188 fl = ctx[f].flags()
4191 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4189 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4192 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])
4193 fm.write('path', '%s\n', f)
4191 fm.write('path', '%s\n', f)
4194 fm.end()
4192 fm.end()
4195
4193
4196 @command('^merge',
4194 @command('^merge',
4197 [('f', 'force', None,
4195 [('f', 'force', None,
4198 _('force a merge including outstanding changes (DEPRECATED)')),
4196 _('force a merge including outstanding changes (DEPRECATED)')),
4199 ('r', 'rev', '', _('revision to merge'), _('REV')),
4197 ('r', 'rev', '', _('revision to merge'), _('REV')),
4200 ('P', 'preview', None,
4198 ('P', 'preview', None,
4201 _('review revisions to merge (no merge is performed)'))
4199 _('review revisions to merge (no merge is performed)'))
4202 ] + mergetoolopts,
4200 ] + mergetoolopts,
4203 _('[-P] [-f] [[-r] REV]'))
4201 _('[-P] [-f] [[-r] REV]'))
4204 def merge(ui, repo, node=None, **opts):
4202 def merge(ui, repo, node=None, **opts):
4205 """merge working directory with another revision
4203 """merge working directory with another revision
4206
4204
4207 The current working directory is updated with all changes made in
4205 The current working directory is updated with all changes made in
4208 the requested revision since the last common predecessor revision.
4206 the requested revision since the last common predecessor revision.
4209
4207
4210 Files that changed between either parent are marked as changed for
4208 Files that changed between either parent are marked as changed for
4211 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
4212 updates to the repository are allowed. The next commit will have
4210 updates to the repository are allowed. The next commit will have
4213 two parents.
4211 two parents.
4214
4212
4215 ``--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
4216 merges. It overrides the HGMERGE environment variable and your
4214 merges. It overrides the HGMERGE environment variable and your
4217 configuration files. See :hg:`help merge-tools` for options.
4215 configuration files. See :hg:`help merge-tools` for options.
4218
4216
4219 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
4220 head revision, and the current branch contains exactly one other
4218 head revision, and the current branch contains exactly one other
4221 head, the other head is merged with by default. Otherwise, an
4219 head, the other head is merged with by default. Otherwise, an
4222 explicit revision with which to merge with must be provided.
4220 explicit revision with which to merge with must be provided.
4223
4221
4224 :hg:`resolve` must be used to resolve unresolved files.
4222 :hg:`resolve` must be used to resolve unresolved files.
4225
4223
4226 To undo an uncommitted merge, use :hg:`update --clean .` which
4224 To undo an uncommitted merge, use :hg:`update --clean .` which
4227 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
4228 all changes.
4226 all changes.
4229
4227
4230 Returns 0 on success, 1 if there are unresolved files.
4228 Returns 0 on success, 1 if there are unresolved files.
4231 """
4229 """
4232
4230
4233 if opts.get('rev') and node:
4231 if opts.get('rev') and node:
4234 raise util.Abort(_("please specify just one revision"))
4232 raise util.Abort(_("please specify just one revision"))
4235 if not node:
4233 if not node:
4236 node = opts.get('rev')
4234 node = opts.get('rev')
4237
4235
4238 if node:
4236 if node:
4239 node = scmutil.revsingle(repo, node).node()
4237 node = scmutil.revsingle(repo, node).node()
4240
4238
4241 if not node and repo._bookmarkcurrent:
4239 if not node and repo._bookmarkcurrent:
4242 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4240 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4243 curhead = repo[repo._bookmarkcurrent].node()
4241 curhead = repo[repo._bookmarkcurrent].node()
4244 if len(bmheads) == 2:
4242 if len(bmheads) == 2:
4245 if curhead == bmheads[0]:
4243 if curhead == bmheads[0]:
4246 node = bmheads[1]
4244 node = bmheads[1]
4247 else:
4245 else:
4248 node = bmheads[0]
4246 node = bmheads[0]
4249 elif len(bmheads) > 2:
4247 elif len(bmheads) > 2:
4250 raise util.Abort(_("multiple matching bookmarks to merge - "
4248 raise util.Abort(_("multiple matching bookmarks to merge - "
4251 "please merge with an explicit rev or bookmark"),
4249 "please merge with an explicit rev or bookmark"),
4252 hint=_("run 'hg heads' to see all heads"))
4250 hint=_("run 'hg heads' to see all heads"))
4253 elif len(bmheads) <= 1:
4251 elif len(bmheads) <= 1:
4254 raise util.Abort(_("no matching bookmark to merge - "
4252 raise util.Abort(_("no matching bookmark to merge - "
4255 "please merge with an explicit rev or bookmark"),
4253 "please merge with an explicit rev or bookmark"),
4256 hint=_("run 'hg heads' to see all heads"))
4254 hint=_("run 'hg heads' to see all heads"))
4257
4255
4258 if not node and not repo._bookmarkcurrent:
4256 if not node and not repo._bookmarkcurrent:
4259 branch = repo[None].branch()
4257 branch = repo[None].branch()
4260 bheads = repo.branchheads(branch)
4258 bheads = repo.branchheads(branch)
4261 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4259 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4262
4260
4263 if len(nbhs) > 2:
4261 if len(nbhs) > 2:
4264 raise util.Abort(_("branch '%s' has %d heads - "
4262 raise util.Abort(_("branch '%s' has %d heads - "
4265 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4266 % (branch, len(bheads)),
4264 % (branch, len(bheads)),
4267 hint=_("run 'hg heads .' to see heads"))
4265 hint=_("run 'hg heads .' to see heads"))
4268
4266
4269 parent = repo.dirstate.p1()
4267 parent = repo.dirstate.p1()
4270 if len(nbhs) <= 1:
4268 if len(nbhs) <= 1:
4271 if len(bheads) > 1:
4269 if len(bheads) > 1:
4272 raise util.Abort(_("heads are bookmarked - "
4270 raise util.Abort(_("heads are bookmarked - "
4273 "please merge with an explicit rev"),
4271 "please merge with an explicit rev"),
4274 hint=_("run 'hg heads' to see all heads"))
4272 hint=_("run 'hg heads' to see all heads"))
4275 if len(repo.heads()) > 1:
4273 if len(repo.heads()) > 1:
4276 raise util.Abort(_("branch '%s' has one head - "
4274 raise util.Abort(_("branch '%s' has one head - "
4277 "please merge with an explicit rev")
4275 "please merge with an explicit rev")
4278 % branch,
4276 % branch,
4279 hint=_("run 'hg heads' to see all heads"))
4277 hint=_("run 'hg heads' to see all heads"))
4280 msg, hint = _('nothing to merge'), None
4278 msg, hint = _('nothing to merge'), None
4281 if parent != repo.lookup(branch):
4279 if parent != repo.lookup(branch):
4282 hint = _("use 'hg update' instead")
4280 hint = _("use 'hg update' instead")
4283 raise util.Abort(msg, hint=hint)
4281 raise util.Abort(msg, hint=hint)
4284
4282
4285 if parent not in bheads:
4283 if parent not in bheads:
4286 raise util.Abort(_('working directory not at a head revision'),
4284 raise util.Abort(_('working directory not at a head revision'),
4287 hint=_("use 'hg update' or merge with an "
4285 hint=_("use 'hg update' or merge with an "
4288 "explicit revision"))
4286 "explicit revision"))
4289 if parent == nbhs[0]:
4287 if parent == nbhs[0]:
4290 node = nbhs[-1]
4288 node = nbhs[-1]
4291 else:
4289 else:
4292 node = nbhs[0]
4290 node = nbhs[0]
4293
4291
4294 if opts.get('preview'):
4292 if opts.get('preview'):
4295 # find nodes that are ancestors of p2 but not of p1
4293 # find nodes that are ancestors of p2 but not of p1
4296 p1 = repo.lookup('.')
4294 p1 = repo.lookup('.')
4297 p2 = repo.lookup(node)
4295 p2 = repo.lookup(node)
4298 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4296 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4299
4297
4300 displayer = cmdutil.show_changeset(ui, repo, opts)
4298 displayer = cmdutil.show_changeset(ui, repo, opts)
4301 for node in nodes:
4299 for node in nodes:
4302 displayer.show(repo[node])
4300 displayer.show(repo[node])
4303 displayer.close()
4301 displayer.close()
4304 return 0
4302 return 0
4305
4303
4306 try:
4304 try:
4307 # ui.forcemerge is an internal variable, do not document
4305 # ui.forcemerge is an internal variable, do not document
4308 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4306 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4309 return hg.merge(repo, node, force=opts.get('force'))
4307 return hg.merge(repo, node, force=opts.get('force'))
4310 finally:
4308 finally:
4311 ui.setconfig('ui', 'forcemerge', '')
4309 ui.setconfig('ui', 'forcemerge', '')
4312
4310
4313 @command('outgoing|out',
4311 @command('outgoing|out',
4314 [('f', 'force', None, _('run even when the destination is unrelated')),
4312 [('f', 'force', None, _('run even when the destination is unrelated')),
4315 ('r', 'rev', [],
4313 ('r', 'rev', [],
4316 _('a changeset intended to be included in the destination'), _('REV')),
4314 _('a changeset intended to be included in the destination'), _('REV')),
4317 ('n', 'newest-first', None, _('show newest record first')),
4315 ('n', 'newest-first', None, _('show newest record first')),
4318 ('B', 'bookmarks', False, _('compare bookmarks')),
4316 ('B', 'bookmarks', False, _('compare bookmarks')),
4319 ('b', 'branch', [], _('a specific branch you would like to push'),
4317 ('b', 'branch', [], _('a specific branch you would like to push'),
4320 _('BRANCH')),
4318 _('BRANCH')),
4321 ] + logopts + remoteopts + subrepoopts,
4319 ] + logopts + remoteopts + subrepoopts,
4322 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4320 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4323 def outgoing(ui, repo, dest=None, **opts):
4321 def outgoing(ui, repo, dest=None, **opts):
4324 """show changesets not found in the destination
4322 """show changesets not found in the destination
4325
4323
4326 Show changesets not found in the specified destination repository
4324 Show changesets not found in the specified destination repository
4327 or the default push location. These are the changesets that would
4325 or the default push location. These are the changesets that would
4328 be pushed if a push was requested.
4326 be pushed if a push was requested.
4329
4327
4330 See pull for details of valid destination formats.
4328 See pull for details of valid destination formats.
4331
4329
4332 Returns 0 if there are outgoing changes, 1 otherwise.
4330 Returns 0 if there are outgoing changes, 1 otherwise.
4333 """
4331 """
4334 if opts.get('graph'):
4332 if opts.get('graph'):
4335 cmdutil.checkunsupportedgraphflags([], opts)
4333 cmdutil.checkunsupportedgraphflags([], opts)
4336 o = hg._outgoing(ui, repo, dest, opts)
4334 o = hg._outgoing(ui, repo, dest, opts)
4337 if o is None:
4335 if o is None:
4338 return
4336 return
4339
4337
4340 revdag = cmdutil.graphrevs(repo, o, opts)
4338 revdag = cmdutil.graphrevs(repo, o, opts)
4341 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4339 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4342 showparents = [ctx.node() for ctx in repo[None].parents()]
4340 showparents = [ctx.node() for ctx in repo[None].parents()]
4343 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4341 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4344 graphmod.asciiedges)
4342 graphmod.asciiedges)
4345 return 0
4343 return 0
4346
4344
4347 if opts.get('bookmarks'):
4345 if opts.get('bookmarks'):
4348 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4346 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4349 dest, branches = hg.parseurl(dest, opts.get('branch'))
4347 dest, branches = hg.parseurl(dest, opts.get('branch'))
4350 other = hg.peer(repo, opts, dest)
4348 other = hg.peer(repo, opts, dest)
4351 if 'bookmarks' not in other.listkeys('namespaces'):
4349 if 'bookmarks' not in other.listkeys('namespaces'):
4352 ui.warn(_("remote doesn't support bookmarks\n"))
4350 ui.warn(_("remote doesn't support bookmarks\n"))
4353 return 0
4351 return 0
4354 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4352 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4355 return bookmarks.diff(ui, other, repo)
4353 return bookmarks.diff(ui, other, repo)
4356
4354
4357 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4355 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4358 try:
4356 try:
4359 return hg.outgoing(ui, repo, dest, opts)
4357 return hg.outgoing(ui, repo, dest, opts)
4360 finally:
4358 finally:
4361 del repo._subtoppath
4359 del repo._subtoppath
4362
4360
4363 @command('parents',
4361 @command('parents',
4364 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4362 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4365 ] + templateopts,
4363 ] + templateopts,
4366 _('[-r REV] [FILE]'))
4364 _('[-r REV] [FILE]'))
4367 def parents(ui, repo, file_=None, **opts):
4365 def parents(ui, repo, file_=None, **opts):
4368 """show the parents of the working directory or revision
4366 """show the parents of the working directory or revision
4369
4367
4370 Print the working directory's parent revisions. If a revision is
4368 Print the working directory's parent revisions. If a revision is
4371 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.
4372 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
4373 last changed (before the working directory revision or the
4371 last changed (before the working directory revision or the
4374 argument to --rev if given) is printed.
4372 argument to --rev if given) is printed.
4375
4373
4376 Returns 0 on success.
4374 Returns 0 on success.
4377 """
4375 """
4378
4376
4379 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4377 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4380
4378
4381 if file_:
4379 if file_:
4382 m = scmutil.match(ctx, (file_,), opts)
4380 m = scmutil.match(ctx, (file_,), opts)
4383 if m.anypats() or len(m.files()) != 1:
4381 if m.anypats() or len(m.files()) != 1:
4384 raise util.Abort(_('can only specify an explicit filename'))
4382 raise util.Abort(_('can only specify an explicit filename'))
4385 file_ = m.files()[0]
4383 file_ = m.files()[0]
4386 filenodes = []
4384 filenodes = []
4387 for cp in ctx.parents():
4385 for cp in ctx.parents():
4388 if not cp:
4386 if not cp:
4389 continue
4387 continue
4390 try:
4388 try:
4391 filenodes.append(cp.filenode(file_))
4389 filenodes.append(cp.filenode(file_))
4392 except error.LookupError:
4390 except error.LookupError:
4393 pass
4391 pass
4394 if not filenodes:
4392 if not filenodes:
4395 raise util.Abort(_("'%s' not found in manifest!") % file_)
4393 raise util.Abort(_("'%s' not found in manifest!") % file_)
4396 p = []
4394 p = []
4397 for fn in filenodes:
4395 for fn in filenodes:
4398 fctx = repo.filectx(file_, fileid=fn)
4396 fctx = repo.filectx(file_, fileid=fn)
4399 p.append(fctx.node())
4397 p.append(fctx.node())
4400 else:
4398 else:
4401 p = [cp.node() for cp in ctx.parents()]
4399 p = [cp.node() for cp in ctx.parents()]
4402
4400
4403 displayer = cmdutil.show_changeset(ui, repo, opts)
4401 displayer = cmdutil.show_changeset(ui, repo, opts)
4404 for n in p:
4402 for n in p:
4405 if n != nullid:
4403 if n != nullid:
4406 displayer.show(repo[n])
4404 displayer.show(repo[n])
4407 displayer.close()
4405 displayer.close()
4408
4406
4409 @command('paths', [], _('[NAME]'))
4407 @command('paths', [], _('[NAME]'))
4410 def paths(ui, repo, search=None):
4408 def paths(ui, repo, search=None):
4411 """show aliases for remote repositories
4409 """show aliases for remote repositories
4412
4410
4413 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,
4414 show definition of all available names.
4412 show definition of all available names.
4415
4413
4416 Option -q/--quiet suppresses all output when searching for NAME
4414 Option -q/--quiet suppresses all output when searching for NAME
4417 and shows only the path names when listing all definitions.
4415 and shows only the path names when listing all definitions.
4418
4416
4419 Path names are defined in the [paths] section of your
4417 Path names are defined in the [paths] section of your
4420 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4418 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4421 repository, ``.hg/hgrc`` is used, too.
4419 repository, ``.hg/hgrc`` is used, too.
4422
4420
4423 The path names ``default`` and ``default-push`` have a special
4421 The path names ``default`` and ``default-push`` have a special
4424 meaning. When performing a push or pull operation, they are used
4422 meaning. When performing a push or pull operation, they are used
4425 as fallbacks if no location is specified on the command-line.
4423 as fallbacks if no location is specified on the command-line.
4426 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
4427 ``default`` will be used for pull; otherwise ``default`` is used
4425 ``default`` will be used for pull; otherwise ``default`` is used
4428 as the fallback for both. When cloning a repository, the clone
4426 as the fallback for both. When cloning a repository, the clone
4429 source is written as ``default`` in ``.hg/hgrc``. Note that
4427 source is written as ``default`` in ``.hg/hgrc``. Note that
4430 ``default`` and ``default-push`` apply to all inbound (e.g.
4428 ``default`` and ``default-push`` apply to all inbound (e.g.
4431 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4429 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4432 :hg:`bundle`) operations.
4430 :hg:`bundle`) operations.
4433
4431
4434 See :hg:`help urls` for more information.
4432 See :hg:`help urls` for more information.
4435
4433
4436 Returns 0 on success.
4434 Returns 0 on success.
4437 """
4435 """
4438 if search:
4436 if search:
4439 for name, path in ui.configitems("paths"):
4437 for name, path in ui.configitems("paths"):
4440 if name == search:
4438 if name == search:
4441 ui.status("%s\n" % util.hidepassword(path))
4439 ui.status("%s\n" % util.hidepassword(path))
4442 return
4440 return
4443 if not ui.quiet:
4441 if not ui.quiet:
4444 ui.warn(_("not found!\n"))
4442 ui.warn(_("not found!\n"))
4445 return 1
4443 return 1
4446 else:
4444 else:
4447 for name, path in ui.configitems("paths"):
4445 for name, path in ui.configitems("paths"):
4448 if ui.quiet:
4446 if ui.quiet:
4449 ui.write("%s\n" % name)
4447 ui.write("%s\n" % name)
4450 else:
4448 else:
4451 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4449 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4452
4450
4453 @command('phase',
4451 @command('phase',
4454 [('p', 'public', False, _('set changeset phase to public')),
4452 [('p', 'public', False, _('set changeset phase to public')),
4455 ('d', 'draft', False, _('set changeset phase to draft')),
4453 ('d', 'draft', False, _('set changeset phase to draft')),
4456 ('s', 'secret', False, _('set changeset phase to secret')),
4454 ('s', 'secret', False, _('set changeset phase to secret')),
4457 ('f', 'force', False, _('allow to move boundary backward')),
4455 ('f', 'force', False, _('allow to move boundary backward')),
4458 ('r', 'rev', [], _('target revision'), _('REV')),
4456 ('r', 'rev', [], _('target revision'), _('REV')),
4459 ],
4457 ],
4460 _('[-p|-d|-s] [-f] [-r] REV...'))
4458 _('[-p|-d|-s] [-f] [-r] REV...'))
4461 def phase(ui, repo, *revs, **opts):
4459 def phase(ui, repo, *revs, **opts):
4462 """set or show the current phase name
4460 """set or show the current phase name
4463
4461
4464 With no argument, show the phase name of specified revisions.
4462 With no argument, show the phase name of specified revisions.
4465
4463
4466 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
4467 phase value of the specified revisions.
4465 phase value of the specified revisions.
4468
4466
4469 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
4470 lower phase to an higher phase. Phases are ordered as follows::
4468 lower phase to an higher phase. Phases are ordered as follows::
4471
4469
4472 public < draft < secret
4470 public < draft < secret
4473
4471
4474 Return 0 on success, 1 if no phases were changed or some could not
4472 Return 0 on success, 1 if no phases were changed or some could not
4475 be changed.
4473 be changed.
4476 """
4474 """
4477 # search for a unique phase argument
4475 # search for a unique phase argument
4478 targetphase = None
4476 targetphase = None
4479 for idx, name in enumerate(phases.phasenames):
4477 for idx, name in enumerate(phases.phasenames):
4480 if opts[name]:
4478 if opts[name]:
4481 if targetphase is not None:
4479 if targetphase is not None:
4482 raise util.Abort(_('only one phase can be specified'))
4480 raise util.Abort(_('only one phase can be specified'))
4483 targetphase = idx
4481 targetphase = idx
4484
4482
4485 # look for specified revision
4483 # look for specified revision
4486 revs = list(revs)
4484 revs = list(revs)
4487 revs.extend(opts['rev'])
4485 revs.extend(opts['rev'])
4488 if not revs:
4486 if not revs:
4489 raise util.Abort(_('no revisions specified'))
4487 raise util.Abort(_('no revisions specified'))
4490
4488
4491 revs = scmutil.revrange(repo, revs)
4489 revs = scmutil.revrange(repo, revs)
4492
4490
4493 lock = None
4491 lock = None
4494 ret = 0
4492 ret = 0
4495 if targetphase is None:
4493 if targetphase is None:
4496 # display
4494 # display
4497 for r in revs:
4495 for r in revs:
4498 ctx = repo[r]
4496 ctx = repo[r]
4499 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4497 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4500 else:
4498 else:
4501 lock = repo.lock()
4499 lock = repo.lock()
4502 try:
4500 try:
4503 # set phase
4501 # set phase
4504 if not revs:
4502 if not revs:
4505 raise util.Abort(_('empty revision set'))
4503 raise util.Abort(_('empty revision set'))
4506 nodes = [repo[r].node() for r in revs]
4504 nodes = [repo[r].node() for r in revs]
4507 olddata = repo._phasecache.getphaserevs(repo)[:]
4505 olddata = repo._phasecache.getphaserevs(repo)[:]
4508 phases.advanceboundary(repo, targetphase, nodes)
4506 phases.advanceboundary(repo, targetphase, nodes)
4509 if opts['force']:
4507 if opts['force']:
4510 phases.retractboundary(repo, targetphase, nodes)
4508 phases.retractboundary(repo, targetphase, nodes)
4511 finally:
4509 finally:
4512 lock.release()
4510 lock.release()
4513 # moving revision from public to draft may hide them
4511 # moving revision from public to draft may hide them
4514 # We have to check result on an unfiltered repository
4512 # We have to check result on an unfiltered repository
4515 unfi = repo.unfiltered()
4513 unfi = repo.unfiltered()
4516 newdata = repo._phasecache.getphaserevs(unfi)
4514 newdata = repo._phasecache.getphaserevs(unfi)
4517 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4515 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4518 cl = unfi.changelog
4516 cl = unfi.changelog
4519 rejected = [n for n in nodes
4517 rejected = [n for n in nodes
4520 if newdata[cl.rev(n)] < targetphase]
4518 if newdata[cl.rev(n)] < targetphase]
4521 if rejected:
4519 if rejected:
4522 ui.warn(_('cannot move %i changesets to a higher '
4520 ui.warn(_('cannot move %i changesets to a higher '
4523 'phase, use --force\n') % len(rejected))
4521 'phase, use --force\n') % len(rejected))
4524 ret = 1
4522 ret = 1
4525 if changes:
4523 if changes:
4526 msg = _('phase changed for %i changesets\n') % changes
4524 msg = _('phase changed for %i changesets\n') % changes
4527 if ret:
4525 if ret:
4528 ui.status(msg)
4526 ui.status(msg)
4529 else:
4527 else:
4530 ui.note(msg)
4528 ui.note(msg)
4531 else:
4529 else:
4532 ui.warn(_('no phases changed\n'))
4530 ui.warn(_('no phases changed\n'))
4533 ret = 1
4531 ret = 1
4534 return ret
4532 return ret
4535
4533
4536 def postincoming(ui, repo, modheads, optupdate, checkout):
4534 def postincoming(ui, repo, modheads, optupdate, checkout):
4537 if modheads == 0:
4535 if modheads == 0:
4538 return
4536 return
4539 if optupdate:
4537 if optupdate:
4540 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4538 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4541 try:
4539 try:
4542 ret = hg.update(repo, checkout)
4540 ret = hg.update(repo, checkout)
4543 except util.Abort, inst:
4541 except util.Abort, inst:
4544 ui.warn(_("not updating: %s\n") % str(inst))
4542 ui.warn(_("not updating: %s\n") % str(inst))
4545 if inst.hint:
4543 if inst.hint:
4546 ui.warn(_("(%s)\n") % inst.hint)
4544 ui.warn(_("(%s)\n") % inst.hint)
4547 return 0
4545 return 0
4548 if not ret and not checkout:
4546 if not ret and not checkout:
4549 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4547 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4550 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4548 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4551 return ret
4549 return ret
4552 if modheads > 1:
4550 if modheads > 1:
4553 currentbranchheads = len(repo.branchheads())
4551 currentbranchheads = len(repo.branchheads())
4554 if currentbranchheads == modheads:
4552 if currentbranchheads == modheads:
4555 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"))
4556 elif currentbranchheads > 1:
4554 elif currentbranchheads > 1:
4557 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4555 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4558 "merge)\n"))
4556 "merge)\n"))
4559 else:
4557 else:
4560 ui.status(_("(run 'hg heads' to see heads)\n"))
4558 ui.status(_("(run 'hg heads' to see heads)\n"))
4561 else:
4559 else:
4562 ui.status(_("(run 'hg update' to get a working copy)\n"))
4560 ui.status(_("(run 'hg update' to get a working copy)\n"))
4563
4561
4564 @command('^pull',
4562 @command('^pull',
4565 [('u', 'update', None,
4563 [('u', 'update', None,
4566 _('update to new branch head if changesets were pulled')),
4564 _('update to new branch head if changesets were pulled')),
4567 ('f', 'force', None, _('run even when remote repository is unrelated')),
4565 ('f', 'force', None, _('run even when remote repository is unrelated')),
4568 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4566 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4569 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4567 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4570 ('b', 'branch', [], _('a specific branch you would like to pull'),
4568 ('b', 'branch', [], _('a specific branch you would like to pull'),
4571 _('BRANCH')),
4569 _('BRANCH')),
4572 ] + remoteopts,
4570 ] + remoteopts,
4573 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4571 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4574 def pull(ui, repo, source="default", **opts):
4572 def pull(ui, repo, source="default", **opts):
4575 """pull changes from the specified source
4573 """pull changes from the specified source
4576
4574
4577 Pull changes from a remote repository to a local one.
4575 Pull changes from a remote repository to a local one.
4578
4576
4579 This finds all changes from the repository at the specified path
4577 This finds all changes from the repository at the specified path
4580 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
4581 -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
4582 project in the working directory.
4580 project in the working directory.
4583
4581
4584 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
4585 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
4586 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
4587 -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`.
4588
4586
4589 If SOURCE is omitted, the 'default' path will be used.
4587 If SOURCE is omitted, the 'default' path will be used.
4590 See :hg:`help urls` for more information.
4588 See :hg:`help urls` for more information.
4591
4589
4592 Returns 0 on success, 1 if an update had unresolved files.
4590 Returns 0 on success, 1 if an update had unresolved files.
4593 """
4591 """
4594 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4592 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4595 other = hg.peer(repo, opts, source)
4593 other = hg.peer(repo, opts, source)
4596 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4594 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4597 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4595 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4598
4596
4599 remotebookmarks = other.listkeys('bookmarks')
4597 remotebookmarks = other.listkeys('bookmarks')
4600
4598
4601 if opts.get('bookmark'):
4599 if opts.get('bookmark'):
4602 if not revs:
4600 if not revs:
4603 revs = []
4601 revs = []
4604 for b in opts['bookmark']:
4602 for b in opts['bookmark']:
4605 if b not in remotebookmarks:
4603 if b not in remotebookmarks:
4606 raise util.Abort(_('remote bookmark %s not found!') % b)
4604 raise util.Abort(_('remote bookmark %s not found!') % b)
4607 revs.append(remotebookmarks[b])
4605 revs.append(remotebookmarks[b])
4608
4606
4609 if revs:
4607 if revs:
4610 try:
4608 try:
4611 revs = [other.lookup(rev) for rev in revs]
4609 revs = [other.lookup(rev) for rev in revs]
4612 except error.CapabilityError:
4610 except error.CapabilityError:
4613 err = _("other repository doesn't support revision lookup, "
4611 err = _("other repository doesn't support revision lookup, "
4614 "so a rev cannot be specified.")
4612 "so a rev cannot be specified.")
4615 raise util.Abort(err)
4613 raise util.Abort(err)
4616
4614
4617 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4615 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4618 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4616 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4619 if checkout:
4617 if checkout:
4620 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4618 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4621 repo._subtoppath = source
4619 repo._subtoppath = source
4622 try:
4620 try:
4623 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4621 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4624
4622
4625 finally:
4623 finally:
4626 del repo._subtoppath
4624 del repo._subtoppath
4627
4625
4628 # update specified bookmarks
4626 # update specified bookmarks
4629 if opts.get('bookmark'):
4627 if opts.get('bookmark'):
4630 marks = repo._bookmarks
4628 marks = repo._bookmarks
4631 for b in opts['bookmark']:
4629 for b in opts['bookmark']:
4632 # explicit pull overrides local bookmark if any
4630 # explicit pull overrides local bookmark if any
4633 ui.status(_("importing bookmark %s\n") % b)
4631 ui.status(_("importing bookmark %s\n") % b)
4634 marks[b] = repo[remotebookmarks[b]].node()
4632 marks[b] = repo[remotebookmarks[b]].node()
4635 marks.write()
4633 marks.write()
4636
4634
4637 return ret
4635 return ret
4638
4636
4639 @command('^push',
4637 @command('^push',
4640 [('f', 'force', None, _('force push')),
4638 [('f', 'force', None, _('force push')),
4641 ('r', 'rev', [],
4639 ('r', 'rev', [],
4642 _('a changeset intended to be included in the destination'),
4640 _('a changeset intended to be included in the destination'),
4643 _('REV')),
4641 _('REV')),
4644 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4642 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4645 ('b', 'branch', [],
4643 ('b', 'branch', [],
4646 _('a specific branch you would like to push'), _('BRANCH')),
4644 _('a specific branch you would like to push'), _('BRANCH')),
4647 ('', 'new-branch', False, _('allow pushing a new branch')),
4645 ('', 'new-branch', False, _('allow pushing a new branch')),
4648 ] + remoteopts,
4646 ] + remoteopts,
4649 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4647 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4650 def push(ui, repo, dest=None, **opts):
4648 def push(ui, repo, dest=None, **opts):
4651 """push changes to the specified destination
4649 """push changes to the specified destination
4652
4650
4653 Push changesets from the local repository to the specified
4651 Push changesets from the local repository to the specified
4654 destination.
4652 destination.
4655
4653
4656 This operation is symmetrical to pull: it is identical to a pull
4654 This operation is symmetrical to pull: it is identical to a pull
4657 in the destination repository from the current one.
4655 in the destination repository from the current one.
4658
4656
4659 By default, push will not allow creation of new heads at the
4657 By default, push will not allow creation of new heads at the
4660 destination, since multiple heads would make it unclear which head
4658 destination, since multiple heads would make it unclear which head
4661 to use. In this situation, it is recommended to pull and merge
4659 to use. In this situation, it is recommended to pull and merge
4662 before pushing.
4660 before pushing.
4663
4661
4664 Use --new-branch if you want to allow push to create a new named
4662 Use --new-branch if you want to allow push to create a new named
4665 branch that is not present at the destination. This allows you to
4663 branch that is not present at the destination. This allows you to
4666 only create a new branch without forcing other changes.
4664 only create a new branch without forcing other changes.
4667
4665
4668 .. note::
4666 .. note::
4669
4667
4670 Extra care should be taken with the -f/--force option,
4668 Extra care should be taken with the -f/--force option,
4671 which will push all new heads on all branches, an action which will
4669 which will push all new heads on all branches, an action which will
4672 almost always cause confusion for collaborators.
4670 almost always cause confusion for collaborators.
4673
4671
4674 If -r/--rev is used, the specified revision and all its ancestors
4672 If -r/--rev is used, the specified revision and all its ancestors
4675 will be pushed to the remote repository.
4673 will be pushed to the remote repository.
4676
4674
4677 If -B/--bookmark is used, the specified bookmarked revision, its
4675 If -B/--bookmark is used, the specified bookmarked revision, its
4678 ancestors, and the bookmark will be pushed to the remote
4676 ancestors, and the bookmark will be pushed to the remote
4679 repository.
4677 repository.
4680
4678
4681 Please see :hg:`help urls` for important details about ``ssh://``
4679 Please see :hg:`help urls` for important details about ``ssh://``
4682 URLs. If DESTINATION is omitted, a default path will be used.
4680 URLs. If DESTINATION is omitted, a default path will be used.
4683
4681
4684 Returns 0 if push was successful, 1 if nothing to push.
4682 Returns 0 if push was successful, 1 if nothing to push.
4685 """
4683 """
4686
4684
4687 if opts.get('bookmark'):
4685 if opts.get('bookmark'):
4688 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4686 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4689 for b in opts['bookmark']:
4687 for b in opts['bookmark']:
4690 # translate -B options to -r so changesets get pushed
4688 # translate -B options to -r so changesets get pushed
4691 if b in repo._bookmarks:
4689 if b in repo._bookmarks:
4692 opts.setdefault('rev', []).append(b)
4690 opts.setdefault('rev', []).append(b)
4693 else:
4691 else:
4694 # if we try to push a deleted bookmark, translate it to null
4692 # if we try to push a deleted bookmark, translate it to null
4695 # this lets simultaneous -r, -b options continue working
4693 # this lets simultaneous -r, -b options continue working
4696 opts.setdefault('rev', []).append("null")
4694 opts.setdefault('rev', []).append("null")
4697
4695
4698 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4696 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4699 dest, branches = hg.parseurl(dest, opts.get('branch'))
4697 dest, branches = hg.parseurl(dest, opts.get('branch'))
4700 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4698 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4701 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4699 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4702 other = hg.peer(repo, opts, dest)
4700 other = hg.peer(repo, opts, dest)
4703 if revs:
4701 if revs:
4704 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4702 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4705
4703
4706 repo._subtoppath = dest
4704 repo._subtoppath = dest
4707 try:
4705 try:
4708 # push subrepos depth-first for coherent ordering
4706 # push subrepos depth-first for coherent ordering
4709 c = repo['']
4707 c = repo['']
4710 subs = c.substate # only repos that are committed
4708 subs = c.substate # only repos that are committed
4711 for s in sorted(subs):
4709 for s in sorted(subs):
4712 if c.sub(s).push(opts) == 0:
4710 if c.sub(s).push(opts) == 0:
4713 return False
4711 return False
4714 finally:
4712 finally:
4715 del repo._subtoppath
4713 del repo._subtoppath
4716 result = repo.push(other, opts.get('force'), revs=revs,
4714 result = repo.push(other, opts.get('force'), revs=revs,
4717 newbranch=opts.get('new_branch'))
4715 newbranch=opts.get('new_branch'))
4718
4716
4719 result = not result
4717 result = not result
4720
4718
4721 if opts.get('bookmark'):
4719 if opts.get('bookmark'):
4722 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4720 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4723 if bresult == 2:
4721 if bresult == 2:
4724 return 2
4722 return 2
4725 if not result and bresult:
4723 if not result and bresult:
4726 result = 2
4724 result = 2
4727
4725
4728 return result
4726 return result
4729
4727
4730 @command('recover', [])
4728 @command('recover', [])
4731 def recover(ui, repo):
4729 def recover(ui, repo):
4732 """roll back an interrupted transaction
4730 """roll back an interrupted transaction
4733
4731
4734 Recover from an interrupted commit or pull.
4732 Recover from an interrupted commit or pull.
4735
4733
4736 This command tries to fix the repository status after an
4734 This command tries to fix the repository status after an
4737 interrupted operation. It should only be necessary when Mercurial
4735 interrupted operation. It should only be necessary when Mercurial
4738 suggests it.
4736 suggests it.
4739
4737
4740 Returns 0 if successful, 1 if nothing to recover or verify fails.
4738 Returns 0 if successful, 1 if nothing to recover or verify fails.
4741 """
4739 """
4742 if repo.recover():
4740 if repo.recover():
4743 return hg.verify(repo)
4741 return hg.verify(repo)
4744 return 1
4742 return 1
4745
4743
4746 @command('^remove|rm',
4744 @command('^remove|rm',
4747 [('A', 'after', None, _('record delete for missing files')),
4745 [('A', 'after', None, _('record delete for missing files')),
4748 ('f', 'force', None,
4746 ('f', 'force', None,
4749 _('remove (and delete) file even if added or modified')),
4747 _('remove (and delete) file even if added or modified')),
4750 ] + walkopts,
4748 ] + walkopts,
4751 _('[OPTION]... FILE...'))
4749 _('[OPTION]... FILE...'))
4752 def remove(ui, repo, *pats, **opts):
4750 def remove(ui, repo, *pats, **opts):
4753 """remove the specified files on the next commit
4751 """remove the specified files on the next commit
4754
4752
4755 Schedule the indicated files for removal from the current branch.
4753 Schedule the indicated files for removal from the current branch.
4756
4754
4757 This command schedules the files to be removed at the next commit.
4755 This command schedules the files to be removed at the next commit.
4758 To undo a remove before that, see :hg:`revert`. To undo added
4756 To undo a remove before that, see :hg:`revert`. To undo added
4759 files, see :hg:`forget`.
4757 files, see :hg:`forget`.
4760
4758
4761 .. container:: verbose
4759 .. container:: verbose
4762
4760
4763 -A/--after can be used to remove only files that have already
4761 -A/--after can be used to remove only files that have already
4764 been deleted, -f/--force can be used to force deletion, and -Af
4762 been deleted, -f/--force can be used to force deletion, and -Af
4765 can be used to remove files from the next revision without
4763 can be used to remove files from the next revision without
4766 deleting them from the working directory.
4764 deleting them from the working directory.
4767
4765
4768 The following table details the behavior of remove for different
4766 The following table details the behavior of remove for different
4769 file states (columns) and option combinations (rows). The file
4767 file states (columns) and option combinations (rows). The file
4770 states are Added [A], Clean [C], Modified [M] and Missing [!]
4768 states are Added [A], Clean [C], Modified [M] and Missing [!]
4771 (as reported by :hg:`status`). The actions are Warn, Remove
4769 (as reported by :hg:`status`). The actions are Warn, Remove
4772 (from branch) and Delete (from disk):
4770 (from branch) and Delete (from disk):
4773
4771
4774 ========= == == == ==
4772 ========= == == == ==
4775 opt/state A C M !
4773 opt/state A C M !
4776 ========= == == == ==
4774 ========= == == == ==
4777 none W RD W R
4775 none W RD W R
4778 -f R RD RD R
4776 -f R RD RD R
4779 -A W W W R
4777 -A W W W R
4780 -Af R R R R
4778 -Af R R R R
4781 ========= == == == ==
4779 ========= == == == ==
4782
4780
4783 Note that remove never deletes files in Added [A] state from the
4781 Note that remove never deletes files in Added [A] state from the
4784 working directory, not even if option --force is specified.
4782 working directory, not even if option --force is specified.
4785
4783
4786 Returns 0 on success, 1 if any warnings encountered.
4784 Returns 0 on success, 1 if any warnings encountered.
4787 """
4785 """
4788
4786
4789 ret = 0
4787 ret = 0
4790 after, force = opts.get('after'), opts.get('force')
4788 after, force = opts.get('after'), opts.get('force')
4791 if not pats and not after:
4789 if not pats and not after:
4792 raise util.Abort(_('no files specified'))
4790 raise util.Abort(_('no files specified'))
4793
4791
4794 m = scmutil.match(repo[None], pats, opts)
4792 m = scmutil.match(repo[None], pats, opts)
4795 s = repo.status(match=m, clean=True)
4793 s = repo.status(match=m, clean=True)
4796 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4794 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4797
4795
4798 # warn about failure to delete explicit files/dirs
4796 # warn about failure to delete explicit files/dirs
4799 wctx = repo[None]
4797 wctx = repo[None]
4800 for f in m.files():
4798 for f in m.files():
4801 if f in repo.dirstate or f in wctx.dirs():
4799 if f in repo.dirstate or f in wctx.dirs():
4802 continue
4800 continue
4803 if os.path.exists(m.rel(f)):
4801 if os.path.exists(m.rel(f)):
4804 if os.path.isdir(m.rel(f)):
4802 if os.path.isdir(m.rel(f)):
4805 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4803 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4806 else:
4804 else:
4807 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4805 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4808 # missing files will generate a warning elsewhere
4806 # missing files will generate a warning elsewhere
4809 ret = 1
4807 ret = 1
4810
4808
4811 if force:
4809 if force:
4812 list = modified + deleted + clean + added
4810 list = modified + deleted + clean + added
4813 elif after:
4811 elif after:
4814 list = deleted
4812 list = deleted
4815 for f in modified + added + clean:
4813 for f in modified + added + clean:
4816 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4814 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4817 ret = 1
4815 ret = 1
4818 else:
4816 else:
4819 list = deleted + clean
4817 list = deleted + clean
4820 for f in modified:
4818 for f in modified:
4821 ui.warn(_('not removing %s: file is modified (use -f'
4819 ui.warn(_('not removing %s: file is modified (use -f'
4822 ' to force removal)\n') % m.rel(f))
4820 ' to force removal)\n') % m.rel(f))
4823 ret = 1
4821 ret = 1
4824 for f in added:
4822 for f in added:
4825 ui.warn(_('not removing %s: file has been marked for add'
4823 ui.warn(_('not removing %s: file has been marked for add'
4826 ' (use forget to undo)\n') % m.rel(f))
4824 ' (use forget to undo)\n') % m.rel(f))
4827 ret = 1
4825 ret = 1
4828
4826
4829 for f in sorted(list):
4827 for f in sorted(list):
4830 if ui.verbose or not m.exact(f):
4828 if ui.verbose or not m.exact(f):
4831 ui.status(_('removing %s\n') % m.rel(f))
4829 ui.status(_('removing %s\n') % m.rel(f))
4832
4830
4833 wlock = repo.wlock()
4831 wlock = repo.wlock()
4834 try:
4832 try:
4835 if not after:
4833 if not after:
4836 for f in list:
4834 for f in list:
4837 if f in added:
4835 if f in added:
4838 continue # we never unlink added files on remove
4836 continue # we never unlink added files on remove
4839 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4837 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4840 repo[None].forget(list)
4838 repo[None].forget(list)
4841 finally:
4839 finally:
4842 wlock.release()
4840 wlock.release()
4843
4841
4844 return ret
4842 return ret
4845
4843
4846 @command('rename|move|mv',
4844 @command('rename|move|mv',
4847 [('A', 'after', None, _('record a rename that has already occurred')),
4845 [('A', 'after', None, _('record a rename that has already occurred')),
4848 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4849 ] + walkopts + dryrunopts,
4847 ] + walkopts + dryrunopts,
4850 _('[OPTION]... SOURCE... DEST'))
4848 _('[OPTION]... SOURCE... DEST'))
4851 def rename(ui, repo, *pats, **opts):
4849 def rename(ui, repo, *pats, **opts):
4852 """rename files; equivalent of copy + remove
4850 """rename files; equivalent of copy + remove
4853
4851
4854 Mark dest as copies of sources; mark sources for deletion. If dest
4852 Mark dest as copies of sources; mark sources for deletion. If dest
4855 is a directory, copies are put in that directory. If dest is a
4853 is a directory, copies are put in that directory. If dest is a
4856 file, there can only be one source.
4854 file, there can only be one source.
4857
4855
4858 By default, this command copies the contents of files as they
4856 By default, this command copies the contents of files as they
4859 exist in the working directory. If invoked with -A/--after, the
4857 exist in the working directory. If invoked with -A/--after, the
4860 operation is recorded, but no copying is performed.
4858 operation is recorded, but no copying is performed.
4861
4859
4862 This command takes effect at the next commit. To undo a rename
4860 This command takes effect at the next commit. To undo a rename
4863 before that, see :hg:`revert`.
4861 before that, see :hg:`revert`.
4864
4862
4865 Returns 0 on success, 1 if errors are encountered.
4863 Returns 0 on success, 1 if errors are encountered.
4866 """
4864 """
4867 wlock = repo.wlock(False)
4865 wlock = repo.wlock(False)
4868 try:
4866 try:
4869 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4867 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4870 finally:
4868 finally:
4871 wlock.release()
4869 wlock.release()
4872
4870
4873 @command('resolve',
4871 @command('resolve',
4874 [('a', 'all', None, _('select all unresolved files')),
4872 [('a', 'all', None, _('select all unresolved files')),
4875 ('l', 'list', None, _('list state of files needing merge')),
4873 ('l', 'list', None, _('list state of files needing merge')),
4876 ('m', 'mark', None, _('mark files as resolved')),
4874 ('m', 'mark', None, _('mark files as resolved')),
4877 ('u', 'unmark', None, _('mark files as unresolved')),
4875 ('u', 'unmark', None, _('mark files as unresolved')),
4878 ('n', 'no-status', None, _('hide status prefix'))]
4876 ('n', 'no-status', None, _('hide status prefix'))]
4879 + mergetoolopts + walkopts,
4877 + mergetoolopts + walkopts,
4880 _('[OPTION]... [FILE]...'))
4878 _('[OPTION]... [FILE]...'))
4881 def resolve(ui, repo, *pats, **opts):
4879 def resolve(ui, repo, *pats, **opts):
4882 """redo merges or set/view the merge status of files
4880 """redo merges or set/view the merge status of files
4883
4881
4884 Merges with unresolved conflicts are often the result of
4882 Merges with unresolved conflicts are often the result of
4885 non-interactive merging using the ``internal:merge`` configuration
4883 non-interactive merging using the ``internal:merge`` configuration
4886 setting, or a command-line merge tool like ``diff3``. The resolve
4884 setting, or a command-line merge tool like ``diff3``. The resolve
4887 command is used to manage the files involved in a merge, after
4885 command is used to manage the files involved in a merge, after
4888 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4886 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4889 working directory must have two parents). See :hg:`help
4887 working directory must have two parents). See :hg:`help
4890 merge-tools` for information on configuring merge tools.
4888 merge-tools` for information on configuring merge tools.
4891
4889
4892 The resolve command can be used in the following ways:
4890 The resolve command can be used in the following ways:
4893
4891
4894 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4892 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4895 files, discarding any previous merge attempts. Re-merging is not
4893 files, discarding any previous merge attempts. Re-merging is not
4896 performed for files already marked as resolved. Use ``--all/-a``
4894 performed for files already marked as resolved. Use ``--all/-a``
4897 to select all unresolved files. ``--tool`` can be used to specify
4895 to select all unresolved files. ``--tool`` can be used to specify
4898 the merge tool used for the given files. It overrides the HGMERGE
4896 the merge tool used for the given files. It overrides the HGMERGE
4899 environment variable and your configuration files. Previous file
4897 environment variable and your configuration files. Previous file
4900 contents are saved with a ``.orig`` suffix.
4898 contents are saved with a ``.orig`` suffix.
4901
4899
4902 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4900 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4903 (e.g. after having manually fixed-up the files). The default is
4901 (e.g. after having manually fixed-up the files). The default is
4904 to mark all unresolved files.
4902 to mark all unresolved files.
4905
4903
4906 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4904 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4907 default is to mark all resolved files.
4905 default is to mark all resolved files.
4908
4906
4909 - :hg:`resolve -l`: list files which had or still have conflicts.
4907 - :hg:`resolve -l`: list files which had or still have conflicts.
4910 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4908 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4911
4909
4912 Note that Mercurial will not let you commit files with unresolved
4910 Note that Mercurial will not let you commit files with unresolved
4913 merge conflicts. You must use :hg:`resolve -m ...` before you can
4911 merge conflicts. You must use :hg:`resolve -m ...` before you can
4914 commit after a conflicting merge.
4912 commit after a conflicting merge.
4915
4913
4916 Returns 0 on success, 1 if any files fail a resolve attempt.
4914 Returns 0 on success, 1 if any files fail a resolve attempt.
4917 """
4915 """
4918
4916
4919 all, mark, unmark, show, nostatus = \
4917 all, mark, unmark, show, nostatus = \
4920 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4918 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4921
4919
4922 if (show and (mark or unmark)) or (mark and unmark):
4920 if (show and (mark or unmark)) or (mark and unmark):
4923 raise util.Abort(_("too many options specified"))
4921 raise util.Abort(_("too many options specified"))
4924 if pats and all:
4922 if pats and all:
4925 raise util.Abort(_("can't specify --all and patterns"))
4923 raise util.Abort(_("can't specify --all and patterns"))
4926 if not (all or pats or show or mark or unmark):
4924 if not (all or pats or show or mark or unmark):
4927 raise util.Abort(_('no files or directories specified; '
4925 raise util.Abort(_('no files or directories specified; '
4928 'use --all to remerge all files'))
4926 'use --all to remerge all files'))
4929
4927
4930 ms = mergemod.mergestate(repo)
4928 ms = mergemod.mergestate(repo)
4931 m = scmutil.match(repo[None], pats, opts)
4929 m = scmutil.match(repo[None], pats, opts)
4932 ret = 0
4930 ret = 0
4933
4931
4934 for f in ms:
4932 for f in ms:
4935 if m(f):
4933 if m(f):
4936 if show:
4934 if show:
4937 if nostatus:
4935 if nostatus:
4938 ui.write("%s\n" % f)
4936 ui.write("%s\n" % f)
4939 else:
4937 else:
4940 ui.write("%s %s\n" % (ms[f].upper(), f),
4938 ui.write("%s %s\n" % (ms[f].upper(), f),
4941 label='resolve.' +
4939 label='resolve.' +
4942 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4940 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4943 elif mark:
4941 elif mark:
4944 ms.mark(f, "r")
4942 ms.mark(f, "r")
4945 elif unmark:
4943 elif unmark:
4946 ms.mark(f, "u")
4944 ms.mark(f, "u")
4947 else:
4945 else:
4948 wctx = repo[None]
4946 wctx = repo[None]
4949 mctx = wctx.parents()[-1]
4947 mctx = wctx.parents()[-1]
4950
4948
4951 # backup pre-resolve (merge uses .orig for its own purposes)
4949 # backup pre-resolve (merge uses .orig for its own purposes)
4952 a = repo.wjoin(f)
4950 a = repo.wjoin(f)
4953 util.copyfile(a, a + ".resolve")
4951 util.copyfile(a, a + ".resolve")
4954
4952
4955 try:
4953 try:
4956 # resolve file
4954 # resolve file
4957 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4955 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4958 if ms.resolve(f, wctx, mctx):
4956 if ms.resolve(f, wctx, mctx):
4959 ret = 1
4957 ret = 1
4960 finally:
4958 finally:
4961 ui.setconfig('ui', 'forcemerge', '')
4959 ui.setconfig('ui', 'forcemerge', '')
4962 ms.commit()
4960 ms.commit()
4963
4961
4964 # replace filemerge's .orig file with our resolve file
4962 # replace filemerge's .orig file with our resolve file
4965 util.rename(a + ".resolve", a + ".orig")
4963 util.rename(a + ".resolve", a + ".orig")
4966
4964
4967 ms.commit()
4965 ms.commit()
4968 return ret
4966 return ret
4969
4967
4970 @command('revert',
4968 @command('revert',
4971 [('a', 'all', None, _('revert all changes when no arguments given')),
4969 [('a', 'all', None, _('revert all changes when no arguments given')),
4972 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4970 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4973 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4971 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4974 ('C', 'no-backup', None, _('do not save backup copies of files')),
4972 ('C', 'no-backup', None, _('do not save backup copies of files')),
4975 ] + walkopts + dryrunopts,
4973 ] + walkopts + dryrunopts,
4976 _('[OPTION]... [-r REV] [NAME]...'))
4974 _('[OPTION]... [-r REV] [NAME]...'))
4977 def revert(ui, repo, *pats, **opts):
4975 def revert(ui, repo, *pats, **opts):
4978 """restore files to their checkout state
4976 """restore files to their checkout state
4979
4977
4980 .. note::
4978 .. note::
4981
4979
4982 To check out earlier revisions, you should use :hg:`update REV`.
4980 To check out earlier revisions, you should use :hg:`update REV`.
4983 To cancel an uncommitted merge (and lose your changes),
4981 To cancel an uncommitted merge (and lose your changes),
4984 use :hg:`update --clean .`.
4982 use :hg:`update --clean .`.
4985
4983
4986 With no revision specified, revert the specified files or directories
4984 With no revision specified, revert the specified files or directories
4987 to the contents they had in the parent of the working directory.
4985 to the contents they had in the parent of the working directory.
4988 This restores the contents of files to an unmodified
4986 This restores the contents of files to an unmodified
4989 state and unschedules adds, removes, copies, and renames. If the
4987 state and unschedules adds, removes, copies, and renames. If the
4990 working directory has two parents, you must explicitly specify a
4988 working directory has two parents, you must explicitly specify a
4991 revision.
4989 revision.
4992
4990
4993 Using the -r/--rev or -d/--date options, revert the given files or
4991 Using the -r/--rev or -d/--date options, revert the given files or
4994 directories to their states as of a specific revision. Because
4992 directories to their states as of a specific revision. Because
4995 revert does not change the working directory parents, this will
4993 revert does not change the working directory parents, this will
4996 cause these files to appear modified. This can be helpful to "back
4994 cause these files to appear modified. This can be helpful to "back
4997 out" some or all of an earlier change. See :hg:`backout` for a
4995 out" some or all of an earlier change. See :hg:`backout` for a
4998 related method.
4996 related method.
4999
4997
5000 Modified files are saved with a .orig suffix before reverting.
4998 Modified files are saved with a .orig suffix before reverting.
5001 To disable these backups, use --no-backup.
4999 To disable these backups, use --no-backup.
5002
5000
5003 See :hg:`help dates` for a list of formats valid for -d/--date.
5001 See :hg:`help dates` for a list of formats valid for -d/--date.
5004
5002
5005 Returns 0 on success.
5003 Returns 0 on success.
5006 """
5004 """
5007
5005
5008 if opts.get("date"):
5006 if opts.get("date"):
5009 if opts.get("rev"):
5007 if opts.get("rev"):
5010 raise util.Abort(_("you can't specify a revision and a date"))
5008 raise util.Abort(_("you can't specify a revision and a date"))
5011 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5009 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5012
5010
5013 parent, p2 = repo.dirstate.parents()
5011 parent, p2 = repo.dirstate.parents()
5014 if not opts.get('rev') and p2 != nullid:
5012 if not opts.get('rev') and p2 != nullid:
5015 # revert after merge is a trap for new users (issue2915)
5013 # revert after merge is a trap for new users (issue2915)
5016 raise util.Abort(_('uncommitted merge with no revision specified'),
5014 raise util.Abort(_('uncommitted merge with no revision specified'),
5017 hint=_('use "hg update" or see "hg help revert"'))
5015 hint=_('use "hg update" or see "hg help revert"'))
5018
5016
5019 ctx = scmutil.revsingle(repo, opts.get('rev'))
5017 ctx = scmutil.revsingle(repo, opts.get('rev'))
5020
5018
5021 if not pats and not opts.get('all'):
5019 if not pats and not opts.get('all'):
5022 msg = _("no files or directories specified")
5020 msg = _("no files or directories specified")
5023 if p2 != nullid:
5021 if p2 != nullid:
5024 hint = _("uncommitted merge, use --all to discard all changes,"
5022 hint = _("uncommitted merge, use --all to discard all changes,"
5025 " or 'hg update -C .' to abort the merge")
5023 " or 'hg update -C .' to abort the merge")
5026 raise util.Abort(msg, hint=hint)
5024 raise util.Abort(msg, hint=hint)
5027 dirty = util.any(repo.status())
5025 dirty = util.any(repo.status())
5028 node = ctx.node()
5026 node = ctx.node()
5029 if node != parent:
5027 if node != parent:
5030 if dirty:
5028 if dirty:
5031 hint = _("uncommitted changes, use --all to discard all"
5029 hint = _("uncommitted changes, use --all to discard all"
5032 " changes, or 'hg update %s' to update") % ctx.rev()
5030 " changes, or 'hg update %s' to update") % ctx.rev()
5033 else:
5031 else:
5034 hint = _("use --all to revert all files,"
5032 hint = _("use --all to revert all files,"
5035 " or 'hg update %s' to update") % ctx.rev()
5033 " or 'hg update %s' to update") % ctx.rev()
5036 elif dirty:
5034 elif dirty:
5037 hint = _("uncommitted changes, use --all to discard all changes")
5035 hint = _("uncommitted changes, use --all to discard all changes")
5038 else:
5036 else:
5039 hint = _("use --all to revert all files")
5037 hint = _("use --all to revert all files")
5040 raise util.Abort(msg, hint=hint)
5038 raise util.Abort(msg, hint=hint)
5041
5039
5042 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5040 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5043
5041
5044 @command('rollback', dryrunopts +
5042 @command('rollback', dryrunopts +
5045 [('f', 'force', False, _('ignore safety measures'))])
5043 [('f', 'force', False, _('ignore safety measures'))])
5046 def rollback(ui, repo, **opts):
5044 def rollback(ui, repo, **opts):
5047 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5045 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5048
5046
5049 Please use :hg:`commit --amend` instead of rollback to correct
5047 Please use :hg:`commit --amend` instead of rollback to correct
5050 mistakes in the last commit.
5048 mistakes in the last commit.
5051
5049
5052 This command should be used with care. There is only one level of
5050 This command should be used with care. There is only one level of
5053 rollback, and there is no way to undo a rollback. It will also
5051 rollback, and there is no way to undo a rollback. It will also
5054 restore the dirstate at the time of the last transaction, losing
5052 restore the dirstate at the time of the last transaction, losing
5055 any dirstate changes since that time. This command does not alter
5053 any dirstate changes since that time. This command does not alter
5056 the working directory.
5054 the working directory.
5057
5055
5058 Transactions are used to encapsulate the effects of all commands
5056 Transactions are used to encapsulate the effects of all commands
5059 that create new changesets or propagate existing changesets into a
5057 that create new changesets or propagate existing changesets into a
5060 repository.
5058 repository.
5061
5059
5062 .. container:: verbose
5060 .. container:: verbose
5063
5061
5064 For example, the following commands are transactional, and their
5062 For example, the following commands are transactional, and their
5065 effects can be rolled back:
5063 effects can be rolled back:
5066
5064
5067 - commit
5065 - commit
5068 - import
5066 - import
5069 - pull
5067 - pull
5070 - push (with this repository as the destination)
5068 - push (with this repository as the destination)
5071 - unbundle
5069 - unbundle
5072
5070
5073 To avoid permanent data loss, rollback will refuse to rollback a
5071 To avoid permanent data loss, rollback will refuse to rollback a
5074 commit transaction if it isn't checked out. Use --force to
5072 commit transaction if it isn't checked out. Use --force to
5075 override this protection.
5073 override this protection.
5076
5074
5077 This command is not intended for use on public repositories. Once
5075 This command is not intended for use on public repositories. Once
5078 changes are visible for pull by other users, rolling a transaction
5076 changes are visible for pull by other users, rolling a transaction
5079 back locally is ineffective (someone else may already have pulled
5077 back locally is ineffective (someone else may already have pulled
5080 the changes). Furthermore, a race is possible with readers of the
5078 the changes). Furthermore, a race is possible with readers of the
5081 repository; for example an in-progress pull from the repository
5079 repository; for example an in-progress pull from the repository
5082 may fail if a rollback is performed.
5080 may fail if a rollback is performed.
5083
5081
5084 Returns 0 on success, 1 if no rollback data is available.
5082 Returns 0 on success, 1 if no rollback data is available.
5085 """
5083 """
5086 return repo.rollback(dryrun=opts.get('dry_run'),
5084 return repo.rollback(dryrun=opts.get('dry_run'),
5087 force=opts.get('force'))
5085 force=opts.get('force'))
5088
5086
5089 @command('root', [])
5087 @command('root', [])
5090 def root(ui, repo):
5088 def root(ui, repo):
5091 """print the root (top) of the current working directory
5089 """print the root (top) of the current working directory
5092
5090
5093 Print the root directory of the current repository.
5091 Print the root directory of the current repository.
5094
5092
5095 Returns 0 on success.
5093 Returns 0 on success.
5096 """
5094 """
5097 ui.write(repo.root + "\n")
5095 ui.write(repo.root + "\n")
5098
5096
5099 @command('^serve',
5097 @command('^serve',
5100 [('A', 'accesslog', '', _('name of access log file to write to'),
5098 [('A', 'accesslog', '', _('name of access log file to write to'),
5101 _('FILE')),
5099 _('FILE')),
5102 ('d', 'daemon', None, _('run server in background')),
5100 ('d', 'daemon', None, _('run server in background')),
5103 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5101 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5104 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5102 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5105 # use string type, then we can check if something was passed
5103 # use string type, then we can check if something was passed
5106 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5104 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5107 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5105 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5108 _('ADDR')),
5106 _('ADDR')),
5109 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5107 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5110 _('PREFIX')),
5108 _('PREFIX')),
5111 ('n', 'name', '',
5109 ('n', 'name', '',
5112 _('name to show in web pages (default: working directory)'), _('NAME')),
5110 _('name to show in web pages (default: working directory)'), _('NAME')),
5113 ('', 'web-conf', '',
5111 ('', 'web-conf', '',
5114 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5112 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5115 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5113 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5116 _('FILE')),
5114 _('FILE')),
5117 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5115 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5118 ('', 'stdio', None, _('for remote clients')),
5116 ('', 'stdio', None, _('for remote clients')),
5119 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5117 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5120 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5118 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5121 ('', 'style', '', _('template style to use'), _('STYLE')),
5119 ('', 'style', '', _('template style to use'), _('STYLE')),
5122 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5120 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5123 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5121 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5124 _('[OPTION]...'))
5122 _('[OPTION]...'))
5125 def serve(ui, repo, **opts):
5123 def serve(ui, repo, **opts):
5126 """start stand-alone webserver
5124 """start stand-alone webserver
5127
5125
5128 Start a local HTTP repository browser and pull server. You can use
5126 Start a local HTTP repository browser and pull server. You can use
5129 this for ad-hoc sharing and browsing of repositories. It is
5127 this for ad-hoc sharing and browsing of repositories. It is
5130 recommended to use a real web server to serve a repository for
5128 recommended to use a real web server to serve a repository for
5131 longer periods of time.
5129 longer periods of time.
5132
5130
5133 Please note that the server does not implement access control.
5131 Please note that the server does not implement access control.
5134 This means that, by default, anybody can read from the server and
5132 This means that, by default, anybody can read from the server and
5135 nobody can write to it by default. Set the ``web.allow_push``
5133 nobody can write to it by default. Set the ``web.allow_push``
5136 option to ``*`` to allow everybody to push to the server. You
5134 option to ``*`` to allow everybody to push to the server. You
5137 should use a real web server if you need to authenticate users.
5135 should use a real web server if you need to authenticate users.
5138
5136
5139 By default, the server logs accesses to stdout and errors to
5137 By default, the server logs accesses to stdout and errors to
5140 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5138 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5141 files.
5139 files.
5142
5140
5143 To have the server choose a free port number to listen on, specify
5141 To have the server choose a free port number to listen on, specify
5144 a port number of 0; in this case, the server will print the port
5142 a port number of 0; in this case, the server will print the port
5145 number it uses.
5143 number it uses.
5146
5144
5147 Returns 0 on success.
5145 Returns 0 on success.
5148 """
5146 """
5149
5147
5150 if opts["stdio"] and opts["cmdserver"]:
5148 if opts["stdio"] and opts["cmdserver"]:
5151 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5149 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5152
5150
5153 def checkrepo():
5151 def checkrepo():
5154 if repo is None:
5152 if repo is None:
5155 raise error.RepoError(_("there is no Mercurial repository here"
5153 raise error.RepoError(_("there is no Mercurial repository here"
5156 " (.hg not found)"))
5154 " (.hg not found)"))
5157
5155
5158 if opts["stdio"]:
5156 if opts["stdio"]:
5159 checkrepo()
5157 checkrepo()
5160 s = sshserver.sshserver(ui, repo)
5158 s = sshserver.sshserver(ui, repo)
5161 s.serve_forever()
5159 s.serve_forever()
5162
5160
5163 if opts["cmdserver"]:
5161 if opts["cmdserver"]:
5164 checkrepo()
5162 checkrepo()
5165 s = commandserver.server(ui, repo, opts["cmdserver"])
5163 s = commandserver.server(ui, repo, opts["cmdserver"])
5166 return s.serve()
5164 return s.serve()
5167
5165
5168 # this way we can check if something was given in the command-line
5166 # this way we can check if something was given in the command-line
5169 if opts.get('port'):
5167 if opts.get('port'):
5170 opts['port'] = util.getport(opts.get('port'))
5168 opts['port'] = util.getport(opts.get('port'))
5171
5169
5172 baseui = repo and repo.baseui or ui
5170 baseui = repo and repo.baseui or ui
5173 optlist = ("name templates style address port prefix ipv6"
5171 optlist = ("name templates style address port prefix ipv6"
5174 " accesslog errorlog certificate encoding")
5172 " accesslog errorlog certificate encoding")
5175 for o in optlist.split():
5173 for o in optlist.split():
5176 val = opts.get(o, '')
5174 val = opts.get(o, '')
5177 if val in (None, ''): # should check against default options instead
5175 if val in (None, ''): # should check against default options instead
5178 continue
5176 continue
5179 baseui.setconfig("web", o, val)
5177 baseui.setconfig("web", o, val)
5180 if repo and repo.ui != baseui:
5178 if repo and repo.ui != baseui:
5181 repo.ui.setconfig("web", o, val)
5179 repo.ui.setconfig("web", o, val)
5182
5180
5183 o = opts.get('web_conf') or opts.get('webdir_conf')
5181 o = opts.get('web_conf') or opts.get('webdir_conf')
5184 if not o:
5182 if not o:
5185 if not repo:
5183 if not repo:
5186 raise error.RepoError(_("there is no Mercurial repository"
5184 raise error.RepoError(_("there is no Mercurial repository"
5187 " here (.hg not found)"))
5185 " here (.hg not found)"))
5188 o = repo
5186 o = repo
5189
5187
5190 app = hgweb.hgweb(o, baseui=baseui)
5188 app = hgweb.hgweb(o, baseui=baseui)
5191 service = httpservice(ui, app, opts)
5189 service = httpservice(ui, app, opts)
5192 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5190 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5193
5191
5194 class httpservice(object):
5192 class httpservice(object):
5195 def __init__(self, ui, app, opts):
5193 def __init__(self, ui, app, opts):
5196 self.ui = ui
5194 self.ui = ui
5197 self.app = app
5195 self.app = app
5198 self.opts = opts
5196 self.opts = opts
5199
5197
5200 def init(self):
5198 def init(self):
5201 util.setsignalhandler()
5199 util.setsignalhandler()
5202 self.httpd = hgweb_server.create_server(self.ui, self.app)
5200 self.httpd = hgweb_server.create_server(self.ui, self.app)
5203
5201
5204 if self.opts['port'] and not self.ui.verbose:
5202 if self.opts['port'] and not self.ui.verbose:
5205 return
5203 return
5206
5204
5207 if self.httpd.prefix:
5205 if self.httpd.prefix:
5208 prefix = self.httpd.prefix.strip('/') + '/'
5206 prefix = self.httpd.prefix.strip('/') + '/'
5209 else:
5207 else:
5210 prefix = ''
5208 prefix = ''
5211
5209
5212 port = ':%d' % self.httpd.port
5210 port = ':%d' % self.httpd.port
5213 if port == ':80':
5211 if port == ':80':
5214 port = ''
5212 port = ''
5215
5213
5216 bindaddr = self.httpd.addr
5214 bindaddr = self.httpd.addr
5217 if bindaddr == '0.0.0.0':
5215 if bindaddr == '0.0.0.0':
5218 bindaddr = '*'
5216 bindaddr = '*'
5219 elif ':' in bindaddr: # IPv6
5217 elif ':' in bindaddr: # IPv6
5220 bindaddr = '[%s]' % bindaddr
5218 bindaddr = '[%s]' % bindaddr
5221
5219
5222 fqaddr = self.httpd.fqaddr
5220 fqaddr = self.httpd.fqaddr
5223 if ':' in fqaddr:
5221 if ':' in fqaddr:
5224 fqaddr = '[%s]' % fqaddr
5222 fqaddr = '[%s]' % fqaddr
5225 if self.opts['port']:
5223 if self.opts['port']:
5226 write = self.ui.status
5224 write = self.ui.status
5227 else:
5225 else:
5228 write = self.ui.write
5226 write = self.ui.write
5229 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5227 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5230 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5228 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5231
5229
5232 def run(self):
5230 def run(self):
5233 self.httpd.serve_forever()
5231 self.httpd.serve_forever()
5234
5232
5235
5233
5236 @command('showconfig|debugconfig',
5234 @command('showconfig|debugconfig',
5237 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5235 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5238 _('[-u] [NAME]...'))
5236 _('[-u] [NAME]...'))
5239 def showconfig(ui, repo, *values, **opts):
5237 def showconfig(ui, repo, *values, **opts):
5240 """show combined config settings from all hgrc files
5238 """show combined config settings from all hgrc files
5241
5239
5242 With no arguments, print names and values of all config items.
5240 With no arguments, print names and values of all config items.
5243
5241
5244 With one argument of the form section.name, print just the value
5242 With one argument of the form section.name, print just the value
5245 of that config item.
5243 of that config item.
5246
5244
5247 With multiple arguments, print names and values of all config
5245 With multiple arguments, print names and values of all config
5248 items with matching section names.
5246 items with matching section names.
5249
5247
5250 With --debug, the source (filename and line number) is printed
5248 With --debug, the source (filename and line number) is printed
5251 for each config item.
5249 for each config item.
5252
5250
5253 Returns 0 on success.
5251 Returns 0 on success.
5254 """
5252 """
5255
5253
5256 for f in scmutil.rcpath():
5254 for f in scmutil.rcpath():
5257 ui.debug('read config from: %s\n' % f)
5255 ui.debug('read config from: %s\n' % f)
5258 untrusted = bool(opts.get('untrusted'))
5256 untrusted = bool(opts.get('untrusted'))
5259 if values:
5257 if values:
5260 sections = [v for v in values if '.' not in v]
5258 sections = [v for v in values if '.' not in v]
5261 items = [v for v in values if '.' in v]
5259 items = [v for v in values if '.' in v]
5262 if len(items) > 1 or items and sections:
5260 if len(items) > 1 or items and sections:
5263 raise util.Abort(_('only one config item permitted'))
5261 raise util.Abort(_('only one config item permitted'))
5264 for section, name, value in ui.walkconfig(untrusted=untrusted):
5262 for section, name, value in ui.walkconfig(untrusted=untrusted):
5265 value = str(value).replace('\n', '\\n')
5263 value = str(value).replace('\n', '\\n')
5266 sectname = section + '.' + name
5264 sectname = section + '.' + name
5267 if values:
5265 if values:
5268 for v in values:
5266 for v in values:
5269 if v == section:
5267 if v == section:
5270 ui.debug('%s: ' %
5268 ui.debug('%s: ' %
5271 ui.configsource(section, name, untrusted))
5269 ui.configsource(section, name, untrusted))
5272 ui.write('%s=%s\n' % (sectname, value))
5270 ui.write('%s=%s\n' % (sectname, value))
5273 elif v == sectname:
5271 elif v == sectname:
5274 ui.debug('%s: ' %
5272 ui.debug('%s: ' %
5275 ui.configsource(section, name, untrusted))
5273 ui.configsource(section, name, untrusted))
5276 ui.write(value, '\n')
5274 ui.write(value, '\n')
5277 else:
5275 else:
5278 ui.debug('%s: ' %
5276 ui.debug('%s: ' %
5279 ui.configsource(section, name, untrusted))
5277 ui.configsource(section, name, untrusted))
5280 ui.write('%s=%s\n' % (sectname, value))
5278 ui.write('%s=%s\n' % (sectname, value))
5281
5279
5282 @command('^status|st',
5280 @command('^status|st',
5283 [('A', 'all', None, _('show status of all files')),
5281 [('A', 'all', None, _('show status of all files')),
5284 ('m', 'modified', None, _('show only modified files')),
5282 ('m', 'modified', None, _('show only modified files')),
5285 ('a', 'added', None, _('show only added files')),
5283 ('a', 'added', None, _('show only added files')),
5286 ('r', 'removed', None, _('show only removed files')),
5284 ('r', 'removed', None, _('show only removed files')),
5287 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5285 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5288 ('c', 'clean', None, _('show only files without changes')),
5286 ('c', 'clean', None, _('show only files without changes')),
5289 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5287 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5290 ('i', 'ignored', None, _('show only ignored files')),
5288 ('i', 'ignored', None, _('show only ignored files')),
5291 ('n', 'no-status', None, _('hide status prefix')),
5289 ('n', 'no-status', None, _('hide status prefix')),
5292 ('C', 'copies', None, _('show source of copied files')),
5290 ('C', 'copies', None, _('show source of copied files')),
5293 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5291 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5294 ('', 'rev', [], _('show difference from revision'), _('REV')),
5292 ('', 'rev', [], _('show difference from revision'), _('REV')),
5295 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5293 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5296 ] + walkopts + subrepoopts,
5294 ] + walkopts + subrepoopts,
5297 _('[OPTION]... [FILE]...'))
5295 _('[OPTION]... [FILE]...'))
5298 def status(ui, repo, *pats, **opts):
5296 def status(ui, repo, *pats, **opts):
5299 """show changed files in the working directory
5297 """show changed files in the working directory
5300
5298
5301 Show status of files in the repository. If names are given, only
5299 Show status of files in the repository. If names are given, only
5302 files that match are shown. Files that are clean or ignored or
5300 files that match are shown. Files that are clean or ignored or
5303 the source of a copy/move operation, are not listed unless
5301 the source of a copy/move operation, are not listed unless
5304 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5302 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5305 Unless options described with "show only ..." are given, the
5303 Unless options described with "show only ..." are given, the
5306 options -mardu are used.
5304 options -mardu are used.
5307
5305
5308 Option -q/--quiet hides untracked (unknown and ignored) files
5306 Option -q/--quiet hides untracked (unknown and ignored) files
5309 unless explicitly requested with -u/--unknown or -i/--ignored.
5307 unless explicitly requested with -u/--unknown or -i/--ignored.
5310
5308
5311 .. note::
5309 .. note::
5312
5310
5313 status may appear to disagree with diff if permissions have
5311 status may appear to disagree with diff if permissions have
5314 changed or a merge has occurred. The standard diff format does
5312 changed or a merge has occurred. The standard diff format does
5315 not report permission changes and diff only reports changes
5313 not report permission changes and diff only reports changes
5316 relative to one merge parent.
5314 relative to one merge parent.
5317
5315
5318 If one revision is given, it is used as the base revision.
5316 If one revision is given, it is used as the base revision.
5319 If two revisions are given, the differences between them are
5317 If two revisions are given, the differences between them are
5320 shown. The --change option can also be used as a shortcut to list
5318 shown. The --change option can also be used as a shortcut to list
5321 the changed files of a revision from its first parent.
5319 the changed files of a revision from its first parent.
5322
5320
5323 The codes used to show the status of files are::
5321 The codes used to show the status of files are::
5324
5322
5325 M = modified
5323 M = modified
5326 A = added
5324 A = added
5327 R = removed
5325 R = removed
5328 C = clean
5326 C = clean
5329 ! = missing (deleted by non-hg command, but still tracked)
5327 ! = missing (deleted by non-hg command, but still tracked)
5330 ? = not tracked
5328 ? = not tracked
5331 I = ignored
5329 I = ignored
5332 = origin of the previous file listed as A (added)
5330 = origin of the previous file listed as A (added)
5333
5331
5334 .. container:: verbose
5332 .. container:: verbose
5335
5333
5336 Examples:
5334 Examples:
5337
5335
5338 - show changes in the working directory relative to a
5336 - show changes in the working directory relative to a
5339 changeset::
5337 changeset::
5340
5338
5341 hg status --rev 9353
5339 hg status --rev 9353
5342
5340
5343 - show all changes including copies in an existing changeset::
5341 - show all changes including copies in an existing changeset::
5344
5342
5345 hg status --copies --change 9353
5343 hg status --copies --change 9353
5346
5344
5347 - get a NUL separated list of added files, suitable for xargs::
5345 - get a NUL separated list of added files, suitable for xargs::
5348
5346
5349 hg status -an0
5347 hg status -an0
5350
5348
5351 Returns 0 on success.
5349 Returns 0 on success.
5352 """
5350 """
5353
5351
5354 revs = opts.get('rev')
5352 revs = opts.get('rev')
5355 change = opts.get('change')
5353 change = opts.get('change')
5356
5354
5357 if revs and change:
5355 if revs and change:
5358 msg = _('cannot specify --rev and --change at the same time')
5356 msg = _('cannot specify --rev and --change at the same time')
5359 raise util.Abort(msg)
5357 raise util.Abort(msg)
5360 elif change:
5358 elif change:
5361 node2 = scmutil.revsingle(repo, change, None).node()
5359 node2 = scmutil.revsingle(repo, change, None).node()
5362 node1 = repo[node2].p1().node()
5360 node1 = repo[node2].p1().node()
5363 else:
5361 else:
5364 node1, node2 = scmutil.revpair(repo, revs)
5362 node1, node2 = scmutil.revpair(repo, revs)
5365
5363
5366 cwd = (pats and repo.getcwd()) or ''
5364 cwd = (pats and repo.getcwd()) or ''
5367 end = opts.get('print0') and '\0' or '\n'
5365 end = opts.get('print0') and '\0' or '\n'
5368 copy = {}
5366 copy = {}
5369 states = 'modified added removed deleted unknown ignored clean'.split()
5367 states = 'modified added removed deleted unknown ignored clean'.split()
5370 show = [k for k in states if opts.get(k)]
5368 show = [k for k in states if opts.get(k)]
5371 if opts.get('all'):
5369 if opts.get('all'):
5372 show += ui.quiet and (states[:4] + ['clean']) or states
5370 show += ui.quiet and (states[:4] + ['clean']) or states
5373 if not show:
5371 if not show:
5374 show = ui.quiet and states[:4] or states[:5]
5372 show = ui.quiet and states[:4] or states[:5]
5375
5373
5376 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5374 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5377 'ignored' in show, 'clean' in show, 'unknown' in show,
5375 'ignored' in show, 'clean' in show, 'unknown' in show,
5378 opts.get('subrepos'))
5376 opts.get('subrepos'))
5379 changestates = zip(states, 'MAR!?IC', stat)
5377 changestates = zip(states, 'MAR!?IC', stat)
5380
5378
5381 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5379 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5382 copy = copies.pathcopies(repo[node1], repo[node2])
5380 copy = copies.pathcopies(repo[node1], repo[node2])
5383
5381
5384 fm = ui.formatter('status', opts)
5382 fm = ui.formatter('status', opts)
5385 fmt = '%s' + end
5383 fmt = '%s' + end
5386 showchar = not opts.get('no_status')
5384 showchar = not opts.get('no_status')
5387
5385
5388 for state, char, files in changestates:
5386 for state, char, files in changestates:
5389 if state in show:
5387 if state in show:
5390 label = 'status.' + state
5388 label = 'status.' + state
5391 for f in files:
5389 for f in files:
5392 fm.startitem()
5390 fm.startitem()
5393 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5391 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5394 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5392 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5395 if f in copy:
5393 if f in copy:
5396 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5394 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5397 label='status.copied')
5395 label='status.copied')
5398 fm.end()
5396 fm.end()
5399
5397
5400 @command('^summary|sum',
5398 @command('^summary|sum',
5401 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5399 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5402 def summary(ui, repo, **opts):
5400 def summary(ui, repo, **opts):
5403 """summarize working directory state
5401 """summarize working directory state
5404
5402
5405 This generates a brief summary of the working directory state,
5403 This generates a brief summary of the working directory state,
5406 including parents, branch, commit status, and available updates.
5404 including parents, branch, commit status, and available updates.
5407
5405
5408 With the --remote option, this will check the default paths for
5406 With the --remote option, this will check the default paths for
5409 incoming and outgoing changes. This can be time-consuming.
5407 incoming and outgoing changes. This can be time-consuming.
5410
5408
5411 Returns 0 on success.
5409 Returns 0 on success.
5412 """
5410 """
5413
5411
5414 ctx = repo[None]
5412 ctx = repo[None]
5415 parents = ctx.parents()
5413 parents = ctx.parents()
5416 pnode = parents[0].node()
5414 pnode = parents[0].node()
5417 marks = []
5415 marks = []
5418
5416
5419 for p in parents:
5417 for p in parents:
5420 # label with log.changeset (instead of log.parent) since this
5418 # label with log.changeset (instead of log.parent) since this
5421 # shows a working directory parent *changeset*:
5419 # shows a working directory parent *changeset*:
5422 # i18n: column positioning for "hg summary"
5420 # i18n: column positioning for "hg summary"
5423 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5421 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5424 label='log.changeset changeset.%s' % p.phasestr())
5422 label='log.changeset changeset.%s' % p.phasestr())
5425 ui.write(' '.join(p.tags()), label='log.tag')
5423 ui.write(' '.join(p.tags()), label='log.tag')
5426 if p.bookmarks():
5424 if p.bookmarks():
5427 marks.extend(p.bookmarks())
5425 marks.extend(p.bookmarks())
5428 if p.rev() == -1:
5426 if p.rev() == -1:
5429 if not len(repo):
5427 if not len(repo):
5430 ui.write(_(' (empty repository)'))
5428 ui.write(_(' (empty repository)'))
5431 else:
5429 else:
5432 ui.write(_(' (no revision checked out)'))
5430 ui.write(_(' (no revision checked out)'))
5433 ui.write('\n')
5431 ui.write('\n')
5434 if p.description():
5432 if p.description():
5435 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5433 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5436 label='log.summary')
5434 label='log.summary')
5437
5435
5438 branch = ctx.branch()
5436 branch = ctx.branch()
5439 bheads = repo.branchheads(branch)
5437 bheads = repo.branchheads(branch)
5440 # i18n: column positioning for "hg summary"
5438 # i18n: column positioning for "hg summary"
5441 m = _('branch: %s\n') % branch
5439 m = _('branch: %s\n') % branch
5442 if branch != 'default':
5440 if branch != 'default':
5443 ui.write(m, label='log.branch')
5441 ui.write(m, label='log.branch')
5444 else:
5442 else:
5445 ui.status(m, label='log.branch')
5443 ui.status(m, label='log.branch')
5446
5444
5447 if marks:
5445 if marks:
5448 current = repo._bookmarkcurrent
5446 current = repo._bookmarkcurrent
5449 # i18n: column positioning for "hg summary"
5447 # i18n: column positioning for "hg summary"
5450 ui.write(_('bookmarks:'), label='log.bookmark')
5448 ui.write(_('bookmarks:'), label='log.bookmark')
5451 if current is not None:
5449 if current is not None:
5452 if current in marks:
5450 if current in marks:
5453 ui.write(' *' + current, label='bookmarks.current')
5451 ui.write(' *' + current, label='bookmarks.current')
5454 marks.remove(current)
5452 marks.remove(current)
5455 else:
5453 else:
5456 ui.write(' [%s]' % current, label='bookmarks.current')
5454 ui.write(' [%s]' % current, label='bookmarks.current')
5457 for m in marks:
5455 for m in marks:
5458 ui.write(' ' + m, label='log.bookmark')
5456 ui.write(' ' + m, label='log.bookmark')
5459 ui.write('\n', label='log.bookmark')
5457 ui.write('\n', label='log.bookmark')
5460
5458
5461 st = list(repo.status(unknown=True))[:6]
5459 st = list(repo.status(unknown=True))[:6]
5462
5460
5463 c = repo.dirstate.copies()
5461 c = repo.dirstate.copies()
5464 copied, renamed = [], []
5462 copied, renamed = [], []
5465 for d, s in c.iteritems():
5463 for d, s in c.iteritems():
5466 if s in st[2]:
5464 if s in st[2]:
5467 st[2].remove(s)
5465 st[2].remove(s)
5468 renamed.append(d)
5466 renamed.append(d)
5469 else:
5467 else:
5470 copied.append(d)
5468 copied.append(d)
5471 if d in st[1]:
5469 if d in st[1]:
5472 st[1].remove(d)
5470 st[1].remove(d)
5473 st.insert(3, renamed)
5471 st.insert(3, renamed)
5474 st.insert(4, copied)
5472 st.insert(4, copied)
5475
5473
5476 ms = mergemod.mergestate(repo)
5474 ms = mergemod.mergestate(repo)
5477 st.append([f for f in ms if ms[f] == 'u'])
5475 st.append([f for f in ms if ms[f] == 'u'])
5478
5476
5479 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5477 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5480 st.append(subs)
5478 st.append(subs)
5481
5479
5482 labels = [ui.label(_('%d modified'), 'status.modified'),
5480 labels = [ui.label(_('%d modified'), 'status.modified'),
5483 ui.label(_('%d added'), 'status.added'),
5481 ui.label(_('%d added'), 'status.added'),
5484 ui.label(_('%d removed'), 'status.removed'),
5482 ui.label(_('%d removed'), 'status.removed'),
5485 ui.label(_('%d renamed'), 'status.copied'),
5483 ui.label(_('%d renamed'), 'status.copied'),
5486 ui.label(_('%d copied'), 'status.copied'),
5484 ui.label(_('%d copied'), 'status.copied'),
5487 ui.label(_('%d deleted'), 'status.deleted'),
5485 ui.label(_('%d deleted'), 'status.deleted'),
5488 ui.label(_('%d unknown'), 'status.unknown'),
5486 ui.label(_('%d unknown'), 'status.unknown'),
5489 ui.label(_('%d ignored'), 'status.ignored'),
5487 ui.label(_('%d ignored'), 'status.ignored'),
5490 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5488 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5491 ui.label(_('%d subrepos'), 'status.modified')]
5489 ui.label(_('%d subrepos'), 'status.modified')]
5492 t = []
5490 t = []
5493 for s, l in zip(st, labels):
5491 for s, l in zip(st, labels):
5494 if s:
5492 if s:
5495 t.append(l % len(s))
5493 t.append(l % len(s))
5496
5494
5497 t = ', '.join(t)
5495 t = ', '.join(t)
5498 cleanworkdir = False
5496 cleanworkdir = False
5499
5497
5500 if repo.vfs.exists('updatestate'):
5498 if repo.vfs.exists('updatestate'):
5501 t += _(' (interrupted update)')
5499 t += _(' (interrupted update)')
5502 elif len(parents) > 1:
5500 elif len(parents) > 1:
5503 t += _(' (merge)')
5501 t += _(' (merge)')
5504 elif branch != parents[0].branch():
5502 elif branch != parents[0].branch():
5505 t += _(' (new branch)')
5503 t += _(' (new branch)')
5506 elif (parents[0].closesbranch() and
5504 elif (parents[0].closesbranch() and
5507 pnode in repo.branchheads(branch, closed=True)):
5505 pnode in repo.branchheads(branch, closed=True)):
5508 t += _(' (head closed)')
5506 t += _(' (head closed)')
5509 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5507 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5510 t += _(' (clean)')
5508 t += _(' (clean)')
5511 cleanworkdir = True
5509 cleanworkdir = True
5512 elif pnode not in bheads:
5510 elif pnode not in bheads:
5513 t += _(' (new branch head)')
5511 t += _(' (new branch head)')
5514
5512
5515 if cleanworkdir:
5513 if cleanworkdir:
5516 # i18n: column positioning for "hg summary"
5514 # i18n: column positioning for "hg summary"
5517 ui.status(_('commit: %s\n') % t.strip())
5515 ui.status(_('commit: %s\n') % t.strip())
5518 else:
5516 else:
5519 # i18n: column positioning for "hg summary"
5517 # i18n: column positioning for "hg summary"
5520 ui.write(_('commit: %s\n') % t.strip())
5518 ui.write(_('commit: %s\n') % t.strip())
5521
5519
5522 # all ancestors of branch heads - all ancestors of parent = new csets
5520 # all ancestors of branch heads - all ancestors of parent = new csets
5523 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5521 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5524 bheads))
5522 bheads))
5525
5523
5526 if new == 0:
5524 if new == 0:
5527 # i18n: column positioning for "hg summary"
5525 # i18n: column positioning for "hg summary"
5528 ui.status(_('update: (current)\n'))
5526 ui.status(_('update: (current)\n'))
5529 elif pnode not in bheads:
5527 elif pnode not in bheads:
5530 # i18n: column positioning for "hg summary"
5528 # i18n: column positioning for "hg summary"
5531 ui.write(_('update: %d new changesets (update)\n') % new)
5529 ui.write(_('update: %d new changesets (update)\n') % new)
5532 else:
5530 else:
5533 # i18n: column positioning for "hg summary"
5531 # i18n: column positioning for "hg summary"
5534 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5532 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5535 (new, len(bheads)))
5533 (new, len(bheads)))
5536
5534
5537 cmdutil.summaryhooks(ui, repo)
5535 cmdutil.summaryhooks(ui, repo)
5538
5536
5539 if opts.get('remote'):
5537 if opts.get('remote'):
5540 t = []
5538 t = []
5541 source, branches = hg.parseurl(ui.expandpath('default'))
5539 source, branches = hg.parseurl(ui.expandpath('default'))
5542 sbranch = branches[0]
5540 sbranch = branches[0]
5543 other = hg.peer(repo, {}, source)
5541 other = hg.peer(repo, {}, source)
5544 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5542 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5545 if revs:
5543 if revs:
5546 revs = [other.lookup(rev) for rev in revs]
5544 revs = [other.lookup(rev) for rev in revs]
5547 ui.debug('comparing with %s\n' % util.hidepassword(source))
5545 ui.debug('comparing with %s\n' % util.hidepassword(source))
5548 repo.ui.pushbuffer()
5546 repo.ui.pushbuffer()
5549 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5547 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5550 _common, incoming, _rheads = commoninc
5548 _common, incoming, _rheads = commoninc
5551 repo.ui.popbuffer()
5549 repo.ui.popbuffer()
5552 if incoming:
5550 if incoming:
5553 t.append(_('1 or more incoming'))
5551 t.append(_('1 or more incoming'))
5554
5552
5555 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5553 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5556 dbranch = branches[0]
5554 dbranch = branches[0]
5557 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5555 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5558 if source != dest:
5556 if source != dest:
5559 other = hg.peer(repo, {}, dest)
5557 other = hg.peer(repo, {}, dest)
5560 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5558 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5561 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5559 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5562 commoninc = None
5560 commoninc = None
5563 if revs:
5561 if revs:
5564 revs = [repo.lookup(rev) for rev in revs]
5562 revs = [repo.lookup(rev) for rev in revs]
5565 repo.ui.pushbuffer()
5563 repo.ui.pushbuffer()
5566 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5564 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5567 commoninc=commoninc)
5565 commoninc=commoninc)
5568 repo.ui.popbuffer()
5566 repo.ui.popbuffer()
5569 o = outgoing.missing
5567 o = outgoing.missing
5570 if o:
5568 if o:
5571 t.append(_('%d outgoing') % len(o))
5569 t.append(_('%d outgoing') % len(o))
5572 if 'bookmarks' in other.listkeys('namespaces'):
5570 if 'bookmarks' in other.listkeys('namespaces'):
5573 lmarks = repo.listkeys('bookmarks')
5571 lmarks = repo.listkeys('bookmarks')
5574 rmarks = other.listkeys('bookmarks')
5572 rmarks = other.listkeys('bookmarks')
5575 diff = set(rmarks) - set(lmarks)
5573 diff = set(rmarks) - set(lmarks)
5576 if len(diff) > 0:
5574 if len(diff) > 0:
5577 t.append(_('%d incoming bookmarks') % len(diff))
5575 t.append(_('%d incoming bookmarks') % len(diff))
5578 diff = set(lmarks) - set(rmarks)
5576 diff = set(lmarks) - set(rmarks)
5579 if len(diff) > 0:
5577 if len(diff) > 0:
5580 t.append(_('%d outgoing bookmarks') % len(diff))
5578 t.append(_('%d outgoing bookmarks') % len(diff))
5581
5579
5582 if t:
5580 if t:
5583 # i18n: column positioning for "hg summary"
5581 # i18n: column positioning for "hg summary"
5584 ui.write(_('remote: %s\n') % (', '.join(t)))
5582 ui.write(_('remote: %s\n') % (', '.join(t)))
5585 else:
5583 else:
5586 # i18n: column positioning for "hg summary"
5584 # i18n: column positioning for "hg summary"
5587 ui.status(_('remote: (synced)\n'))
5585 ui.status(_('remote: (synced)\n'))
5588
5586
5589 @command('tag',
5587 @command('tag',
5590 [('f', 'force', None, _('force tag')),
5588 [('f', 'force', None, _('force tag')),
5591 ('l', 'local', None, _('make the tag local')),
5589 ('l', 'local', None, _('make the tag local')),
5592 ('r', 'rev', '', _('revision to tag'), _('REV')),
5590 ('r', 'rev', '', _('revision to tag'), _('REV')),
5593 ('', 'remove', None, _('remove a tag')),
5591 ('', 'remove', None, _('remove a tag')),
5594 # -l/--local is already there, commitopts cannot be used
5592 # -l/--local is already there, commitopts cannot be used
5595 ('e', 'edit', None, _('edit commit message')),
5593 ('e', 'edit', None, _('edit commit message')),
5596 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5594 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5597 ] + commitopts2,
5595 ] + commitopts2,
5598 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5596 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5599 def tag(ui, repo, name1, *names, **opts):
5597 def tag(ui, repo, name1, *names, **opts):
5600 """add one or more tags for the current or given revision
5598 """add one or more tags for the current or given revision
5601
5599
5602 Name a particular revision using <name>.
5600 Name a particular revision using <name>.
5603
5601
5604 Tags are used to name particular revisions of the repository and are
5602 Tags are used to name particular revisions of the repository and are
5605 very useful to compare different revisions, to go back to significant
5603 very useful to compare different revisions, to go back to significant
5606 earlier versions or to mark branch points as releases, etc. Changing
5604 earlier versions or to mark branch points as releases, etc. Changing
5607 an existing tag is normally disallowed; use -f/--force to override.
5605 an existing tag is normally disallowed; use -f/--force to override.
5608
5606
5609 If no revision is given, the parent of the working directory is
5607 If no revision is given, the parent of the working directory is
5610 used.
5608 used.
5611
5609
5612 To facilitate version control, distribution, and merging of tags,
5610 To facilitate version control, distribution, and merging of tags,
5613 they are stored as a file named ".hgtags" which is managed similarly
5611 they are stored as a file named ".hgtags" which is managed similarly
5614 to other project files and can be hand-edited if necessary. This
5612 to other project files and can be hand-edited if necessary. This
5615 also means that tagging creates a new commit. The file
5613 also means that tagging creates a new commit. The file
5616 ".hg/localtags" is used for local tags (not shared among
5614 ".hg/localtags" is used for local tags (not shared among
5617 repositories).
5615 repositories).
5618
5616
5619 Tag commits are usually made at the head of a branch. If the parent
5617 Tag commits are usually made at the head of a branch. If the parent
5620 of the working directory is not a branch head, :hg:`tag` aborts; use
5618 of the working directory is not a branch head, :hg:`tag` aborts; use
5621 -f/--force to force the tag commit to be based on a non-head
5619 -f/--force to force the tag commit to be based on a non-head
5622 changeset.
5620 changeset.
5623
5621
5624 See :hg:`help dates` for a list of formats valid for -d/--date.
5622 See :hg:`help dates` for a list of formats valid for -d/--date.
5625
5623
5626 Since tag names have priority over branch names during revision
5624 Since tag names have priority over branch names during revision
5627 lookup, using an existing branch name as a tag name is discouraged.
5625 lookup, using an existing branch name as a tag name is discouraged.
5628
5626
5629 Returns 0 on success.
5627 Returns 0 on success.
5630 """
5628 """
5631 wlock = lock = None
5629 wlock = lock = None
5632 try:
5630 try:
5633 wlock = repo.wlock()
5631 wlock = repo.wlock()
5634 lock = repo.lock()
5632 lock = repo.lock()
5635 rev_ = "."
5633 rev_ = "."
5636 names = [t.strip() for t in (name1,) + names]
5634 names = [t.strip() for t in (name1,) + names]
5637 if len(names) != len(set(names)):
5635 if len(names) != len(set(names)):
5638 raise util.Abort(_('tag names must be unique'))
5636 raise util.Abort(_('tag names must be unique'))
5639 for n in names:
5637 for n in names:
5640 scmutil.checknewlabel(repo, n, 'tag')
5638 scmutil.checknewlabel(repo, n, 'tag')
5641 if not n:
5639 if not n:
5642 raise util.Abort(_('tag names cannot consist entirely of '
5640 raise util.Abort(_('tag names cannot consist entirely of '
5643 'whitespace'))
5641 'whitespace'))
5644 if opts.get('rev') and opts.get('remove'):
5642 if opts.get('rev') and opts.get('remove'):
5645 raise util.Abort(_("--rev and --remove are incompatible"))
5643 raise util.Abort(_("--rev and --remove are incompatible"))
5646 if opts.get('rev'):
5644 if opts.get('rev'):
5647 rev_ = opts['rev']
5645 rev_ = opts['rev']
5648 message = opts.get('message')
5646 message = opts.get('message')
5649 if opts.get('remove'):
5647 if opts.get('remove'):
5650 expectedtype = opts.get('local') and 'local' or 'global'
5648 expectedtype = opts.get('local') and 'local' or 'global'
5651 for n in names:
5649 for n in names:
5652 if not repo.tagtype(n):
5650 if not repo.tagtype(n):
5653 raise util.Abort(_("tag '%s' does not exist") % n)
5651 raise util.Abort(_("tag '%s' does not exist") % n)
5654 if repo.tagtype(n) != expectedtype:
5652 if repo.tagtype(n) != expectedtype:
5655 if expectedtype == 'global':
5653 if expectedtype == 'global':
5656 raise util.Abort(_("tag '%s' is not a global tag") % n)
5654 raise util.Abort(_("tag '%s' is not a global tag") % n)
5657 else:
5655 else:
5658 raise util.Abort(_("tag '%s' is not a local tag") % n)
5656 raise util.Abort(_("tag '%s' is not a local tag") % n)
5659 rev_ = nullid
5657 rev_ = nullid
5660 if not message:
5658 if not message:
5661 # we don't translate commit messages
5659 # we don't translate commit messages
5662 message = 'Removed tag %s' % ', '.join(names)
5660 message = 'Removed tag %s' % ', '.join(names)
5663 elif not opts.get('force'):
5661 elif not opts.get('force'):
5664 for n in names:
5662 for n in names:
5665 if n in repo.tags():
5663 if n in repo.tags():
5666 raise util.Abort(_("tag '%s' already exists "
5664 raise util.Abort(_("tag '%s' already exists "
5667 "(use -f to force)") % n)
5665 "(use -f to force)") % n)
5668 if not opts.get('local'):
5666 if not opts.get('local'):
5669 p1, p2 = repo.dirstate.parents()
5667 p1, p2 = repo.dirstate.parents()
5670 if p2 != nullid:
5668 if p2 != nullid:
5671 raise util.Abort(_('uncommitted merge'))
5669 raise util.Abort(_('uncommitted merge'))
5672 bheads = repo.branchheads()
5670 bheads = repo.branchheads()
5673 if not opts.get('force') and bheads and p1 not in bheads:
5671 if not opts.get('force') and bheads and p1 not in bheads:
5674 raise util.Abort(_('not at a branch head (use -f to force)'))
5672 raise util.Abort(_('not at a branch head (use -f to force)'))
5675 r = scmutil.revsingle(repo, rev_).node()
5673 r = scmutil.revsingle(repo, rev_).node()
5676
5674
5677 if not message:
5675 if not message:
5678 # we don't translate commit messages
5676 # we don't translate commit messages
5679 message = ('Added tag %s for changeset %s' %
5677 message = ('Added tag %s for changeset %s' %
5680 (', '.join(names), short(r)))
5678 (', '.join(names), short(r)))
5681
5679
5682 date = opts.get('date')
5680 date = opts.get('date')
5683 if date:
5681 if date:
5684 date = util.parsedate(date)
5682 date = util.parsedate(date)
5685
5683
5686 if opts.get('edit'):
5684 if opts.get('edit'):
5687 message = ui.edit(message, ui.username())
5685 message = ui.edit(message, ui.username())
5688
5686
5689 # don't allow tagging the null rev
5687 # don't allow tagging the null rev
5690 if (not opts.get('remove') and
5688 if (not opts.get('remove') and
5691 scmutil.revsingle(repo, rev_).rev() == nullrev):
5689 scmutil.revsingle(repo, rev_).rev() == nullrev):
5692 raise util.Abort(_("cannot tag null revision"))
5690 raise util.Abort(_("cannot tag null revision"))
5693
5691
5694 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5692 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5695 finally:
5693 finally:
5696 release(lock, wlock)
5694 release(lock, wlock)
5697
5695
5698 @command('tags', [], '')
5696 @command('tags', [], '')
5699 def tags(ui, repo, **opts):
5697 def tags(ui, repo, **opts):
5700 """list repository tags
5698 """list repository tags
5701
5699
5702 This lists both regular and local tags. When the -v/--verbose
5700 This lists both regular and local tags. When the -v/--verbose
5703 switch is used, a third column "local" is printed for local tags.
5701 switch is used, a third column "local" is printed for local tags.
5704
5702
5705 Returns 0 on success.
5703 Returns 0 on success.
5706 """
5704 """
5707
5705
5708 fm = ui.formatter('tags', opts)
5706 fm = ui.formatter('tags', opts)
5709 hexfunc = ui.debugflag and hex or short
5707 hexfunc = ui.debugflag and hex or short
5710 tagtype = ""
5708 tagtype = ""
5711
5709
5712 for t, n in reversed(repo.tagslist()):
5710 for t, n in reversed(repo.tagslist()):
5713 hn = hexfunc(n)
5711 hn = hexfunc(n)
5714 label = 'tags.normal'
5712 label = 'tags.normal'
5715 tagtype = ''
5713 tagtype = ''
5716 if repo.tagtype(t) == 'local':
5714 if repo.tagtype(t) == 'local':
5717 label = 'tags.local'
5715 label = 'tags.local'
5718 tagtype = 'local'
5716 tagtype = 'local'
5719
5717
5720 fm.startitem()
5718 fm.startitem()
5721 fm.write('tag', '%s', t, label=label)
5719 fm.write('tag', '%s', t, label=label)
5722 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5720 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5723 fm.condwrite(not ui.quiet, 'rev id', fmt,
5721 fm.condwrite(not ui.quiet, 'rev id', fmt,
5724 repo.changelog.rev(n), hn, label=label)
5722 repo.changelog.rev(n), hn, label=label)
5725 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5723 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5726 tagtype, label=label)
5724 tagtype, label=label)
5727 fm.plain('\n')
5725 fm.plain('\n')
5728 fm.end()
5726 fm.end()
5729
5727
5730 @command('tip',
5728 @command('tip',
5731 [('p', 'patch', None, _('show patch')),
5729 [('p', 'patch', None, _('show patch')),
5732 ('g', 'git', None, _('use git extended diff format')),
5730 ('g', 'git', None, _('use git extended diff format')),
5733 ] + templateopts,
5731 ] + templateopts,
5734 _('[-p] [-g]'))
5732 _('[-p] [-g]'))
5735 def tip(ui, repo, **opts):
5733 def tip(ui, repo, **opts):
5736 """show the tip revision (DEPRECATED)
5734 """show the tip revision (DEPRECATED)
5737
5735
5738 The tip revision (usually just called the tip) is the changeset
5736 The tip revision (usually just called the tip) is the changeset
5739 most recently added to the repository (and therefore the most
5737 most recently added to the repository (and therefore the most
5740 recently changed head).
5738 recently changed head).
5741
5739
5742 If you have just made a commit, that commit will be the tip. If
5740 If you have just made a commit, that commit will be the tip. If
5743 you have just pulled changes from another repository, the tip of
5741 you have just pulled changes from another repository, the tip of
5744 that repository becomes the current tip. The "tip" tag is special
5742 that repository becomes the current tip. The "tip" tag is special
5745 and cannot be renamed or assigned to a different changeset.
5743 and cannot be renamed or assigned to a different changeset.
5746
5744
5747 This command is deprecated, please use :hg:`heads` instead.
5745 This command is deprecated, please use :hg:`heads` instead.
5748
5746
5749 Returns 0 on success.
5747 Returns 0 on success.
5750 """
5748 """
5751 displayer = cmdutil.show_changeset(ui, repo, opts)
5749 displayer = cmdutil.show_changeset(ui, repo, opts)
5752 displayer.show(repo['tip'])
5750 displayer.show(repo['tip'])
5753 displayer.close()
5751 displayer.close()
5754
5752
5755 @command('unbundle',
5753 @command('unbundle',
5756 [('u', 'update', None,
5754 [('u', 'update', None,
5757 _('update to new branch head if changesets were unbundled'))],
5755 _('update to new branch head if changesets were unbundled'))],
5758 _('[-u] FILE...'))
5756 _('[-u] FILE...'))
5759 def unbundle(ui, repo, fname1, *fnames, **opts):
5757 def unbundle(ui, repo, fname1, *fnames, **opts):
5760 """apply one or more changegroup files
5758 """apply one or more changegroup files
5761
5759
5762 Apply one or more compressed changegroup files generated by the
5760 Apply one or more compressed changegroup files generated by the
5763 bundle command.
5761 bundle command.
5764
5762
5765 Returns 0 on success, 1 if an update has unresolved files.
5763 Returns 0 on success, 1 if an update has unresolved files.
5766 """
5764 """
5767 fnames = (fname1,) + fnames
5765 fnames = (fname1,) + fnames
5768
5766
5769 lock = repo.lock()
5767 lock = repo.lock()
5770 wc = repo['.']
5768 wc = repo['.']
5771 try:
5769 try:
5772 for fname in fnames:
5770 for fname in fnames:
5773 f = hg.openpath(ui, fname)
5771 f = hg.openpath(ui, fname)
5774 gen = changegroup.readbundle(f, fname)
5772 gen = changegroup.readbundle(f, fname)
5775 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5773 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5776 finally:
5774 finally:
5777 lock.release()
5775 lock.release()
5778 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5776 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5779 return postincoming(ui, repo, modheads, opts.get('update'), None)
5777 return postincoming(ui, repo, modheads, opts.get('update'), None)
5780
5778
5781 @command('^update|up|checkout|co',
5779 @command('^update|up|checkout|co',
5782 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5780 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5783 ('c', 'check', None,
5781 ('c', 'check', None,
5784 _('update across branches if no uncommitted changes')),
5782 _('update across branches if no uncommitted changes')),
5785 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5783 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5786 ('r', 'rev', '', _('revision'), _('REV'))],
5784 ('r', 'rev', '', _('revision'), _('REV'))],
5787 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5785 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5788 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5786 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5789 """update working directory (or switch revisions)
5787 """update working directory (or switch revisions)
5790
5788
5791 Update the repository's working directory to the specified
5789 Update the repository's working directory to the specified
5792 changeset. If no changeset is specified, update to the tip of the
5790 changeset. If no changeset is specified, update to the tip of the
5793 current named branch and move the current bookmark (see :hg:`help
5791 current named branch and move the current bookmark (see :hg:`help
5794 bookmarks`).
5792 bookmarks`).
5795
5793
5796 Update sets the working directory's parent revision to the specified
5794 Update sets the working directory's parent revision to the specified
5797 changeset (see :hg:`help parents`).
5795 changeset (see :hg:`help parents`).
5798
5796
5799 If the changeset is not a descendant or ancestor of the working
5797 If the changeset is not a descendant or ancestor of the working
5800 directory's parent, the update is aborted. With the -c/--check
5798 directory's parent, the update is aborted. With the -c/--check
5801 option, the working directory is checked for uncommitted changes; if
5799 option, the working directory is checked for uncommitted changes; if
5802 none are found, the working directory is updated to the specified
5800 none are found, the working directory is updated to the specified
5803 changeset.
5801 changeset.
5804
5802
5805 .. container:: verbose
5803 .. container:: verbose
5806
5804
5807 The following rules apply when the working directory contains
5805 The following rules apply when the working directory contains
5808 uncommitted changes:
5806 uncommitted changes:
5809
5807
5810 1. If neither -c/--check nor -C/--clean is specified, and if
5808 1. If neither -c/--check nor -C/--clean is specified, and if
5811 the requested changeset is an ancestor or descendant of
5809 the requested changeset is an ancestor or descendant of
5812 the working directory's parent, the uncommitted changes
5810 the working directory's parent, the uncommitted changes
5813 are merged into the requested changeset and the merged
5811 are merged into the requested changeset and the merged
5814 result is left uncommitted. If the requested changeset is
5812 result is left uncommitted. If the requested changeset is
5815 not an ancestor or descendant (that is, it is on another
5813 not an ancestor or descendant (that is, it is on another
5816 branch), the update is aborted and the uncommitted changes
5814 branch), the update is aborted and the uncommitted changes
5817 are preserved.
5815 are preserved.
5818
5816
5819 2. With the -c/--check option, the update is aborted and the
5817 2. With the -c/--check option, the update is aborted and the
5820 uncommitted changes are preserved.
5818 uncommitted changes are preserved.
5821
5819
5822 3. With the -C/--clean option, uncommitted changes are discarded and
5820 3. With the -C/--clean option, uncommitted changes are discarded and
5823 the working directory is updated to the requested changeset.
5821 the working directory is updated to the requested changeset.
5824
5822
5825 To cancel an uncommitted merge (and lose your changes), use
5823 To cancel an uncommitted merge (and lose your changes), use
5826 :hg:`update --clean .`.
5824 :hg:`update --clean .`.
5827
5825
5828 Use null as the changeset to remove the working directory (like
5826 Use null as the changeset to remove the working directory (like
5829 :hg:`clone -U`).
5827 :hg:`clone -U`).
5830
5828
5831 If you want to revert just one file to an older revision, use
5829 If you want to revert just one file to an older revision, use
5832 :hg:`revert [-r REV] NAME`.
5830 :hg:`revert [-r REV] NAME`.
5833
5831
5834 See :hg:`help dates` for a list of formats valid for -d/--date.
5832 See :hg:`help dates` for a list of formats valid for -d/--date.
5835
5833
5836 Returns 0 on success, 1 if there are unresolved files.
5834 Returns 0 on success, 1 if there are unresolved files.
5837 """
5835 """
5838 if rev and node:
5836 if rev and node:
5839 raise util.Abort(_("please specify just one revision"))
5837 raise util.Abort(_("please specify just one revision"))
5840
5838
5841 if rev is None or rev == '':
5839 if rev is None or rev == '':
5842 rev = node
5840 rev = node
5843
5841
5844 cmdutil.clearunfinished(repo)
5842 cmdutil.clearunfinished(repo)
5845
5843
5846 # with no argument, we also move the current bookmark, if any
5844 # with no argument, we also move the current bookmark, if any
5847 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5845 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5848
5846
5849 # if we defined a bookmark, we have to remember the original bookmark name
5847 # if we defined a bookmark, we have to remember the original bookmark name
5850 brev = rev
5848 brev = rev
5851 rev = scmutil.revsingle(repo, rev, rev).rev()
5849 rev = scmutil.revsingle(repo, rev, rev).rev()
5852
5850
5853 if check and clean:
5851 if check and clean:
5854 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5852 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5855
5853
5856 if date:
5854 if date:
5857 if rev is not None:
5855 if rev is not None:
5858 raise util.Abort(_("you can't specify a revision and a date"))
5856 raise util.Abort(_("you can't specify a revision and a date"))
5859 rev = cmdutil.finddate(ui, repo, date)
5857 rev = cmdutil.finddate(ui, repo, date)
5860
5858
5861 if check:
5859 if check:
5862 c = repo[None]
5860 c = repo[None]
5863 if c.dirty(merge=False, branch=False, missing=True):
5861 if c.dirty(merge=False, branch=False, missing=True):
5864 raise util.Abort(_("uncommitted changes"))
5862 raise util.Abort(_("uncommitted changes"))
5865 if rev is None:
5863 if rev is None:
5866 rev = repo[repo[None].branch()].rev()
5864 rev = repo[repo[None].branch()].rev()
5867 mergemod._checkunknown(repo, repo[None], repo[rev])
5865 mergemod._checkunknown(repo, repo[None], repo[rev])
5868
5866
5869 if clean:
5867 if clean:
5870 ret = hg.clean(repo, rev)
5868 ret = hg.clean(repo, rev)
5871 else:
5869 else:
5872 ret = hg.update(repo, rev)
5870 ret = hg.update(repo, rev)
5873
5871
5874 if not ret and movemarkfrom:
5872 if not ret and movemarkfrom:
5875 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5873 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5876 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5874 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5877 elif brev in repo._bookmarks:
5875 elif brev in repo._bookmarks:
5878 bookmarks.setcurrent(repo, brev)
5876 bookmarks.setcurrent(repo, brev)
5879 elif brev:
5877 elif brev:
5880 bookmarks.unsetcurrent(repo)
5878 bookmarks.unsetcurrent(repo)
5881
5879
5882 return ret
5880 return ret
5883
5881
5884 @command('verify', [])
5882 @command('verify', [])
5885 def verify(ui, repo):
5883 def verify(ui, repo):
5886 """verify the integrity of the repository
5884 """verify the integrity of the repository
5887
5885
5888 Verify the integrity of the current repository.
5886 Verify the integrity of the current repository.
5889
5887
5890 This will perform an extensive check of the repository's
5888 This will perform an extensive check of the repository's
5891 integrity, validating the hashes and checksums of each entry in
5889 integrity, validating the hashes and checksums of each entry in
5892 the changelog, manifest, and tracked files, as well as the
5890 the changelog, manifest, and tracked files, as well as the
5893 integrity of their crosslinks and indices.
5891 integrity of their crosslinks and indices.
5894
5892
5895 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5893 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5896 for more information about recovery from corruption of the
5894 for more information about recovery from corruption of the
5897 repository.
5895 repository.
5898
5896
5899 Returns 0 on success, 1 if errors are encountered.
5897 Returns 0 on success, 1 if errors are encountered.
5900 """
5898 """
5901 return hg.verify(repo)
5899 return hg.verify(repo)
5902
5900
5903 @command('version', [])
5901 @command('version', [])
5904 def version_(ui):
5902 def version_(ui):
5905 """output version and copyright information"""
5903 """output version and copyright information"""
5906 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5904 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5907 % util.version())
5905 % util.version())
5908 ui.status(_(
5906 ui.status(_(
5909 "(see http://mercurial.selenic.com for more information)\n"
5907 "(see http://mercurial.selenic.com for more information)\n"
5910 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5908 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5911 "This is free software; see the source for copying conditions. "
5909 "This is free software; see the source for copying conditions. "
5912 "There is NO\nwarranty; "
5910 "There is NO\nwarranty; "
5913 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5911 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5914 ))
5912 ))
5915
5913
5916 norepo = ("clone init version help debugcommands debugcomplete"
5914 norepo = ("clone init version help debugcommands debugcomplete"
5917 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5915 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5918 " debugknown debuggetbundle debugbundle")
5916 " debugknown debuggetbundle debugbundle")
5919 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5917 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5920 " debugdata debugindex debugindexdot debugrevlog")
5918 " debugdata debugindex debugindexdot debugrevlog")
5921 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5919 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5922 " remove resolve status debugwalk")
5920 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now