##// END OF EJS Templates
commands.bookmarks: move cur initialization to inside wlock...
Siddharth Agarwal -
r20234:8a133190 default
parent child Browse files
Show More
@@ -1,5909 +1,5909 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, commandserver
15 import sshserver, hgweb, commandserver
16 from hgweb import server as hgweb_server
16 from hgweb import server as hgweb_server
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge, graphmod
19 import dagparser, context, simplemerge, graphmod
20 import random
20 import random
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import phases, obsolete
22 import phases, obsolete
23
23
24 table = {}
24 table = {}
25
25
26 command = cmdutil.command(table)
26 command = cmdutil.command(table)
27
27
28 # common command options
28 # common command options
29
29
30 globalopts = [
30 globalopts = [
31 ('R', 'repository', '',
31 ('R', 'repository', '',
32 _('repository root directory or name of overlay bundle file'),
32 _('repository root directory or name of overlay bundle file'),
33 _('REPO')),
33 _('REPO')),
34 ('', 'cwd', '',
34 ('', 'cwd', '',
35 _('change working directory'), _('DIR')),
35 _('change working directory'), _('DIR')),
36 ('y', 'noninteractive', None,
36 ('y', 'noninteractive', None,
37 _('do not prompt, automatically pick the first choice for all prompts')),
37 _('do not prompt, automatically pick the first choice for all prompts')),
38 ('q', 'quiet', None, _('suppress output')),
38 ('q', 'quiet', None, _('suppress output')),
39 ('v', 'verbose', None, _('enable additional output')),
39 ('v', 'verbose', None, _('enable additional output')),
40 ('', 'config', [],
40 ('', 'config', [],
41 _('set/override config option (use \'section.name=value\')'),
41 _('set/override config option (use \'section.name=value\')'),
42 _('CONFIG')),
42 _('CONFIG')),
43 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debugger', None, _('start debugger')),
44 ('', 'debugger', None, _('start debugger')),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 _('ENCODE')),
46 _('ENCODE')),
47 ('', 'encodingmode', encoding.encodingmode,
47 ('', 'encodingmode', encoding.encodingmode,
48 _('set the charset encoding mode'), _('MODE')),
48 _('set the charset encoding mode'), _('MODE')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'time', None, _('time how long the command takes')),
50 ('', 'time', None, _('time how long the command takes')),
51 ('', 'profile', None, _('print command execution profile')),
51 ('', 'profile', None, _('print command execution profile')),
52 ('', 'version', None, _('output version information and exit')),
52 ('', 'version', None, _('output version information and exit')),
53 ('h', 'help', None, _('display help and exit')),
53 ('h', 'help', None, _('display help and exit')),
54 ('', 'hidden', False, _('consider hidden changesets')),
54 ('', 'hidden', False, _('consider hidden changesets')),
55 ]
55 ]
56
56
57 dryrunopts = [('n', 'dry-run', None,
57 dryrunopts = [('n', 'dry-run', None,
58 _('do not perform actions, just print output'))]
58 _('do not perform actions, just print output'))]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 templateopts = [
90 templateopts = [
91 ('', 'style', '',
91 ('', 'style', '',
92 _('display using template map file'), _('STYLE')),
92 _('display using template map file'), _('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 hg.clean(repo, node, show_stats=False)
464 hg.clean(repo, node, show_stats=False)
465 repo.dirstate.setbranch(branch)
465 repo.dirstate.setbranch(branch)
466 rctx = scmutil.revsingle(repo, hex(parent))
466 rctx = scmutil.revsingle(repo, hex(parent))
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
468 if not opts.get('merge') and op1 != node:
468 if not opts.get('merge') and op1 != node:
469 try:
469 try:
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
471 return hg.update(repo, op1)
471 return hg.update(repo, op1)
472 finally:
472 finally:
473 ui.setconfig('ui', 'forcemerge', '')
473 ui.setconfig('ui', 'forcemerge', '')
474
474
475 e = cmdutil.commiteditor
475 e = cmdutil.commiteditor
476 if not opts['message'] and not opts['logfile']:
476 if not opts['message'] and not opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 opts['message'] = "Backed out changeset %s" % short(node)
478 opts['message'] = "Backed out changeset %s" % short(node)
479 e = cmdutil.commitforceeditor
479 e = cmdutil.commitforceeditor
480
480
481 def commitfunc(ui, repo, message, match, opts):
481 def commitfunc(ui, repo, message, match, opts):
482 return repo.commit(message, opts.get('user'), opts.get('date'),
482 return repo.commit(message, opts.get('user'), opts.get('date'),
483 match, editor=e)
483 match, editor=e)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
486
486
487 def nice(node):
487 def nice(node):
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
489 ui.status(_('changeset %s backs out changeset %s\n') %
489 ui.status(_('changeset %s backs out changeset %s\n') %
490 (nice(repo.changelog.tip()), nice(node)))
490 (nice(repo.changelog.tip()), nice(node)))
491 if opts.get('merge') and op1 != node:
491 if opts.get('merge') and op1 != node:
492 hg.clean(repo, op1, show_stats=False)
492 hg.clean(repo, op1, show_stats=False)
493 ui.status(_('merging with changeset %s\n')
493 ui.status(_('merging with changeset %s\n')
494 % nice(repo.changelog.tip()))
494 % nice(repo.changelog.tip()))
495 try:
495 try:
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
497 return hg.merge(repo, hex(repo.changelog.tip()))
497 return hg.merge(repo, hex(repo.changelog.tip()))
498 finally:
498 finally:
499 ui.setconfig('ui', 'forcemerge', '')
499 ui.setconfig('ui', 'forcemerge', '')
500 finally:
500 finally:
501 wlock.release()
501 wlock.release()
502 return 0
502 return 0
503
503
504 @command('bisect',
504 @command('bisect',
505 [('r', 'reset', False, _('reset bisect state')),
505 [('r', 'reset', False, _('reset bisect state')),
506 ('g', 'good', False, _('mark changeset good')),
506 ('g', 'good', False, _('mark changeset good')),
507 ('b', 'bad', False, _('mark changeset bad')),
507 ('b', 'bad', False, _('mark changeset bad')),
508 ('s', 'skip', False, _('skip testing changeset')),
508 ('s', 'skip', False, _('skip testing changeset')),
509 ('e', 'extend', False, _('extend the bisect range')),
509 ('e', 'extend', False, _('extend the bisect range')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
511 ('U', 'noupdate', False, _('do not update to target'))],
511 ('U', 'noupdate', False, _('do not update to target'))],
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
513 def bisect(ui, repo, rev=None, extra=None, command=None,
513 def bisect(ui, repo, rev=None, extra=None, command=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
515 noupdate=None):
515 noupdate=None):
516 """subdivision search of changesets
516 """subdivision search of changesets
517
517
518 This command helps to find changesets which introduce problems. To
518 This command helps to find changesets which introduce problems. To
519 use, mark the earliest changeset you know exhibits the problem as
519 use, mark the earliest changeset you know exhibits the problem as
520 bad, then mark the latest changeset which is free from the problem
520 bad, then mark the latest changeset which is free from the problem
521 as good. Bisect will update your working directory to a revision
521 as good. Bisect will update your working directory to a revision
522 for testing (unless the -U/--noupdate option is specified). Once
522 for testing (unless the -U/--noupdate option is specified). Once
523 you have performed tests, mark the working directory as good or
523 you have performed tests, mark the working directory as good or
524 bad, and bisect will either update to another candidate changeset
524 bad, and bisect will either update to another candidate changeset
525 or announce that it has found the bad revision.
525 or announce that it has found the bad revision.
526
526
527 As a shortcut, you can also use the revision argument to mark a
527 As a shortcut, you can also use the revision argument to mark a
528 revision as good or bad without checking it out first.
528 revision as good or bad without checking it out first.
529
529
530 If you supply a command, it will be used for automatic bisection.
530 If you supply a command, it will be used for automatic bisection.
531 The environment variable HG_NODE will contain the ID of the
531 The environment variable HG_NODE will contain the ID of the
532 changeset being tested. The exit status of the command will be
532 changeset being tested. The exit status of the command will be
533 used to mark revisions as good or bad: status 0 means good, 125
533 used to mark revisions as good or bad: status 0 means good, 125
534 means to skip the revision, 127 (command not found) will abort the
534 means to skip the revision, 127 (command not found) will abort the
535 bisection, and any other non-zero exit status means the revision
535 bisection, and any other non-zero exit status means the revision
536 is bad.
536 is bad.
537
537
538 .. container:: verbose
538 .. container:: verbose
539
539
540 Some examples:
540 Some examples:
541
541
542 - start a bisection with known bad revision 34, and good revision 12::
542 - start a bisection with known bad revision 34, and good revision 12::
543
543
544 hg bisect --bad 34
544 hg bisect --bad 34
545 hg bisect --good 12
545 hg bisect --good 12
546
546
547 - advance the current bisection by marking current revision as good or
547 - advance the current bisection by marking current revision as good or
548 bad::
548 bad::
549
549
550 hg bisect --good
550 hg bisect --good
551 hg bisect --bad
551 hg bisect --bad
552
552
553 - mark the current revision, or a known revision, to be skipped (e.g. if
553 - mark the current revision, or a known revision, to be skipped (e.g. if
554 that revision is not usable because of another issue)::
554 that revision is not usable because of another issue)::
555
555
556 hg bisect --skip
556 hg bisect --skip
557 hg bisect --skip 23
557 hg bisect --skip 23
558
558
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
560
560
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
562
562
563 - forget the current bisection::
563 - forget the current bisection::
564
564
565 hg bisect --reset
565 hg bisect --reset
566
566
567 - use 'make && make tests' to automatically find the first broken
567 - use 'make && make tests' to automatically find the first broken
568 revision::
568 revision::
569
569
570 hg bisect --reset
570 hg bisect --reset
571 hg bisect --bad 34
571 hg bisect --bad 34
572 hg bisect --good 12
572 hg bisect --good 12
573 hg bisect --command "make && make tests"
573 hg bisect --command "make && make tests"
574
574
575 - see all changesets whose states are already known in the current
575 - see all changesets whose states are already known in the current
576 bisection::
576 bisection::
577
577
578 hg log -r "bisect(pruned)"
578 hg log -r "bisect(pruned)"
579
579
580 - see the changeset currently being bisected (especially useful
580 - see the changeset currently being bisected (especially useful
581 if running with -U/--noupdate)::
581 if running with -U/--noupdate)::
582
582
583 hg log -r "bisect(current)"
583 hg log -r "bisect(current)"
584
584
585 - see all changesets that took part in the current bisection::
585 - see all changesets that took part in the current bisection::
586
586
587 hg log -r "bisect(range)"
587 hg log -r "bisect(range)"
588
588
589 - you can even get a nice graph::
589 - you can even get a nice graph::
590
590
591 hg log --graph -r "bisect(range)"
591 hg log --graph -r "bisect(range)"
592
592
593 See :hg:`help revsets` for more about the `bisect()` keyword.
593 See :hg:`help revsets` for more about the `bisect()` keyword.
594
594
595 Returns 0 on success.
595 Returns 0 on success.
596 """
596 """
597 def extendbisectrange(nodes, good):
597 def extendbisectrange(nodes, good):
598 # bisect is incomplete when it ends on a merge node and
598 # bisect is incomplete when it ends on a merge node and
599 # one of the parent was not checked.
599 # one of the parent was not checked.
600 parents = repo[nodes[0]].parents()
600 parents = repo[nodes[0]].parents()
601 if len(parents) > 1:
601 if len(parents) > 1:
602 side = good and state['bad'] or state['good']
602 side = good and state['bad'] or state['good']
603 num = len(set(i.node() for i in parents) & set(side))
603 num = len(set(i.node() for i in parents) & set(side))
604 if num == 1:
604 if num == 1:
605 return parents[0].ancestor(parents[1])
605 return parents[0].ancestor(parents[1])
606 return None
606 return None
607
607
608 def print_result(nodes, good):
608 def print_result(nodes, good):
609 displayer = cmdutil.show_changeset(ui, repo, {})
609 displayer = cmdutil.show_changeset(ui, repo, {})
610 if len(nodes) == 1:
610 if len(nodes) == 1:
611 # narrowed it down to a single revision
611 # narrowed it down to a single revision
612 if good:
612 if good:
613 ui.write(_("The first good revision is:\n"))
613 ui.write(_("The first good revision is:\n"))
614 else:
614 else:
615 ui.write(_("The first bad revision is:\n"))
615 ui.write(_("The first bad revision is:\n"))
616 displayer.show(repo[nodes[0]])
616 displayer.show(repo[nodes[0]])
617 extendnode = extendbisectrange(nodes, good)
617 extendnode = extendbisectrange(nodes, good)
618 if extendnode is not None:
618 if extendnode is not None:
619 ui.write(_('Not all ancestors of this changeset have been'
619 ui.write(_('Not all ancestors of this changeset have been'
620 ' checked.\nUse bisect --extend to continue the '
620 ' checked.\nUse bisect --extend to continue the '
621 'bisection from\nthe common ancestor, %s.\n')
621 'bisection from\nthe common ancestor, %s.\n')
622 % extendnode)
622 % extendnode)
623 else:
623 else:
624 # multiple possible revisions
624 # multiple possible revisions
625 if good:
625 if good:
626 ui.write(_("Due to skipped revisions, the first "
626 ui.write(_("Due to skipped revisions, the first "
627 "good revision could be any of:\n"))
627 "good revision could be any of:\n"))
628 else:
628 else:
629 ui.write(_("Due to skipped revisions, the first "
629 ui.write(_("Due to skipped revisions, the first "
630 "bad revision could be any of:\n"))
630 "bad revision could be any of:\n"))
631 for n in nodes:
631 for n in nodes:
632 displayer.show(repo[n])
632 displayer.show(repo[n])
633 displayer.close()
633 displayer.close()
634
634
635 def check_state(state, interactive=True):
635 def check_state(state, interactive=True):
636 if not state['good'] or not state['bad']:
636 if not state['good'] or not state['bad']:
637 if (good or bad or skip or reset) and interactive:
637 if (good or bad or skip or reset) and interactive:
638 return
638 return
639 if not state['good']:
639 if not state['good']:
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
641 else:
641 else:
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
643 return True
643 return True
644
644
645 # backward compatibility
645 # backward compatibility
646 if rev in "good bad reset init".split():
646 if rev in "good bad reset init".split():
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
648 cmd, rev, extra = rev, extra, None
648 cmd, rev, extra = rev, extra, None
649 if cmd == "good":
649 if cmd == "good":
650 good = True
650 good = True
651 elif cmd == "bad":
651 elif cmd == "bad":
652 bad = True
652 bad = True
653 else:
653 else:
654 reset = True
654 reset = True
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
656 raise util.Abort(_('incompatible arguments'))
656 raise util.Abort(_('incompatible arguments'))
657
657
658 cmdutil.checkunfinished(repo)
658 cmdutil.checkunfinished(repo)
659
659
660 if reset:
660 if reset:
661 p = repo.join("bisect.state")
661 p = repo.join("bisect.state")
662 if os.path.exists(p):
662 if os.path.exists(p):
663 os.unlink(p)
663 os.unlink(p)
664 return
664 return
665
665
666 state = hbisect.load_state(repo)
666 state = hbisect.load_state(repo)
667
667
668 if command:
668 if command:
669 changesets = 1
669 changesets = 1
670 try:
670 try:
671 node = state['current'][0]
671 node = state['current'][0]
672 except LookupError:
672 except LookupError:
673 if noupdate:
673 if noupdate:
674 raise util.Abort(_('current bisect revision is unknown - '
674 raise util.Abort(_('current bisect revision is unknown - '
675 'start a new bisect to fix'))
675 'start a new bisect to fix'))
676 node, p2 = repo.dirstate.parents()
676 node, p2 = repo.dirstate.parents()
677 if p2 != nullid:
677 if p2 != nullid:
678 raise util.Abort(_('current bisect revision is a merge'))
678 raise util.Abort(_('current bisect revision is a merge'))
679 try:
679 try:
680 while changesets:
680 while changesets:
681 # update state
681 # update state
682 state['current'] = [node]
682 state['current'] = [node]
683 hbisect.save_state(repo, state)
683 hbisect.save_state(repo, state)
684 status = util.system(command,
684 status = util.system(command,
685 environ={'HG_NODE': hex(node)},
685 environ={'HG_NODE': hex(node)},
686 out=ui.fout)
686 out=ui.fout)
687 if status == 125:
687 if status == 125:
688 transition = "skip"
688 transition = "skip"
689 elif status == 0:
689 elif status == 0:
690 transition = "good"
690 transition = "good"
691 # status < 0 means process was killed
691 # status < 0 means process was killed
692 elif status == 127:
692 elif status == 127:
693 raise util.Abort(_("failed to execute %s") % command)
693 raise util.Abort(_("failed to execute %s") % command)
694 elif status < 0:
694 elif status < 0:
695 raise util.Abort(_("%s killed") % command)
695 raise util.Abort(_("%s killed") % command)
696 else:
696 else:
697 transition = "bad"
697 transition = "bad"
698 ctx = scmutil.revsingle(repo, rev, node)
698 ctx = scmutil.revsingle(repo, rev, node)
699 rev = None # clear for future iterations
699 rev = None # clear for future iterations
700 state[transition].append(ctx.node())
700 state[transition].append(ctx.node())
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
702 check_state(state, interactive=False)
702 check_state(state, interactive=False)
703 # bisect
703 # bisect
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
705 # update to next check
705 # update to next check
706 node = nodes[0]
706 node = nodes[0]
707 if not noupdate:
707 if not noupdate:
708 cmdutil.bailifchanged(repo)
708 cmdutil.bailifchanged(repo)
709 hg.clean(repo, node, show_stats=False)
709 hg.clean(repo, node, show_stats=False)
710 finally:
710 finally:
711 state['current'] = [node]
711 state['current'] = [node]
712 hbisect.save_state(repo, state)
712 hbisect.save_state(repo, state)
713 print_result(nodes, bgood)
713 print_result(nodes, bgood)
714 return
714 return
715
715
716 # update state
716 # update state
717
717
718 if rev:
718 if rev:
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
720 else:
720 else:
721 nodes = [repo.lookup('.')]
721 nodes = [repo.lookup('.')]
722
722
723 if good or bad or skip:
723 if good or bad or skip:
724 if good:
724 if good:
725 state['good'] += nodes
725 state['good'] += nodes
726 elif bad:
726 elif bad:
727 state['bad'] += nodes
727 state['bad'] += nodes
728 elif skip:
728 elif skip:
729 state['skip'] += nodes
729 state['skip'] += nodes
730 hbisect.save_state(repo, state)
730 hbisect.save_state(repo, state)
731
731
732 if not check_state(state):
732 if not check_state(state):
733 return
733 return
734
734
735 # actually bisect
735 # actually bisect
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
737 if extend:
737 if extend:
738 if not changesets:
738 if not changesets:
739 extendnode = extendbisectrange(nodes, good)
739 extendnode = extendbisectrange(nodes, good)
740 if extendnode is not None:
740 if extendnode is not None:
741 ui.write(_("Extending search to changeset %d:%s\n"
741 ui.write(_("Extending search to changeset %d:%s\n"
742 % (extendnode.rev(), extendnode)))
742 % (extendnode.rev(), extendnode)))
743 state['current'] = [extendnode.node()]
743 state['current'] = [extendnode.node()]
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745 if noupdate:
745 if noupdate:
746 return
746 return
747 cmdutil.bailifchanged(repo)
747 cmdutil.bailifchanged(repo)
748 return hg.clean(repo, extendnode.node())
748 return hg.clean(repo, extendnode.node())
749 raise util.Abort(_("nothing to extend"))
749 raise util.Abort(_("nothing to extend"))
750
750
751 if changesets == 0:
751 if changesets == 0:
752 print_result(nodes, good)
752 print_result(nodes, good)
753 else:
753 else:
754 assert len(nodes) == 1 # only a single node can be tested next
754 assert len(nodes) == 1 # only a single node can be tested next
755 node = nodes[0]
755 node = nodes[0]
756 # compute the approximate number of remaining tests
756 # compute the approximate number of remaining tests
757 tests, size = 0, 2
757 tests, size = 0, 2
758 while size <= changesets:
758 while size <= changesets:
759 tests, size = tests + 1, size * 2
759 tests, size = tests + 1, size * 2
760 rev = repo.changelog.rev(node)
760 rev = repo.changelog.rev(node)
761 ui.write(_("Testing changeset %d:%s "
761 ui.write(_("Testing changeset %d:%s "
762 "(%d changesets remaining, ~%d tests)\n")
762 "(%d changesets remaining, ~%d tests)\n")
763 % (rev, short(node), changesets, tests))
763 % (rev, short(node), changesets, tests))
764 state['current'] = [node]
764 state['current'] = [node]
765 hbisect.save_state(repo, state)
765 hbisect.save_state(repo, state)
766 if not noupdate:
766 if not noupdate:
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, node)
768 return hg.clean(repo, node)
769
769
770 @command('bookmarks|bookmark',
770 @command('bookmarks|bookmark',
771 [('f', 'force', False, _('force')),
771 [('f', 'force', False, _('force')),
772 ('r', 'rev', '', _('revision'), _('REV')),
772 ('r', 'rev', '', _('revision'), _('REV')),
773 ('d', 'delete', False, _('delete a given bookmark')),
773 ('d', 'delete', False, _('delete a given bookmark')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
777 def bookmark(ui, repo, *names, **opts):
777 def bookmark(ui, repo, *names, **opts):
778 '''track a line of development with movable markers
778 '''track a line of development with movable markers
779
779
780 Bookmarks are pointers to certain commits that move when committing.
780 Bookmarks are pointers to certain commits that move when committing.
781 Bookmarks are local. They can be renamed, copied and deleted. It is
781 Bookmarks are local. They can be renamed, copied and deleted. It is
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
783 :hg:`update NAME` to update to a given bookmark.
783 :hg:`update NAME` to update to a given bookmark.
784
784
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
786 directory's parent revision with the given name. If you specify
786 directory's parent revision with the given name. If you specify
787 a revision using -r REV (where REV may be an existing bookmark),
787 a revision using -r REV (where REV may be an existing bookmark),
788 the bookmark is assigned to that revision.
788 the bookmark is assigned to that revision.
789
789
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
791 push` and :hg:`help pull`). This requires both the local and remote
791 push` and :hg:`help pull`). This requires both the local and remote
792 repositories to support bookmarks. For versions prior to 1.8, this means
792 repositories to support bookmarks. For versions prior to 1.8, this means
793 the bookmarks extension must be enabled.
793 the bookmarks extension must be enabled.
794
794
795 If you set a bookmark called '@', new clones of the repository will
795 If you set a bookmark called '@', new clones of the repository will
796 have that revision checked out (and the bookmark made active) by
796 have that revision checked out (and the bookmark made active) by
797 default.
797 default.
798
798
799 With -i/--inactive, the new bookmark will not be made the active
799 With -i/--inactive, the new bookmark will not be made the active
800 bookmark. If -r/--rev is given, the new bookmark will not be made
800 bookmark. If -r/--rev is given, the new bookmark will not be made
801 active even if -i/--inactive is not given. If no NAME is given, the
801 active even if -i/--inactive is not given. If no NAME is given, the
802 current active bookmark will be marked inactive.
802 current active bookmark will be marked inactive.
803 '''
803 '''
804 force = opts.get('force')
804 force = opts.get('force')
805 rev = opts.get('rev')
805 rev = opts.get('rev')
806 delete = opts.get('delete')
806 delete = opts.get('delete')
807 rename = opts.get('rename')
807 rename = opts.get('rename')
808 inactive = opts.get('inactive')
808 inactive = opts.get('inactive')
809
809
810 hexfn = ui.debugflag and hex or short
810 hexfn = ui.debugflag and hex or short
811 cur = repo.changectx('.').node()
812
811
813 def checkformat(mark):
812 def checkformat(mark):
814 mark = mark.strip()
813 mark = mark.strip()
815 if not mark:
814 if not mark:
816 raise util.Abort(_("bookmark names cannot consist entirely of "
815 raise util.Abort(_("bookmark names cannot consist entirely of "
817 "whitespace"))
816 "whitespace"))
818 scmutil.checknewlabel(repo, mark, 'bookmark')
817 scmutil.checknewlabel(repo, mark, 'bookmark')
819 return mark
818 return mark
820
819
821 def checkconflict(repo, mark, cur, force=False, target=None):
820 def checkconflict(repo, mark, cur, force=False, target=None):
822 if mark in marks and not force:
821 if mark in marks and not force:
823 if target:
822 if target:
824 if marks[mark] == target and target == cur:
823 if marks[mark] == target and target == cur:
825 # re-activating a bookmark
824 # re-activating a bookmark
826 return
825 return
827 anc = repo.changelog.ancestors([repo[target].rev()])
826 anc = repo.changelog.ancestors([repo[target].rev()])
828 bmctx = repo[marks[mark]]
827 bmctx = repo[marks[mark]]
829 divs = [repo[b].node() for b in marks
828 divs = [repo[b].node() for b in marks
830 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
831
830
832 # allow resolving a single divergent bookmark even if moving
831 # allow resolving a single divergent bookmark even if moving
833 # the bookmark across branches when a revision is specified
832 # the bookmark across branches when a revision is specified
834 # that contains a divergent bookmark
833 # that contains a divergent bookmark
835 if bmctx.rev() not in anc and target in divs:
834 if bmctx.rev() not in anc and target in divs:
836 bookmarks.deletedivergent(repo, [target], mark)
835 bookmarks.deletedivergent(repo, [target], mark)
837 return
836 return
838
837
839 # consider successor changesets as well
838 # consider successor changesets as well
840 foreground = obsolete.foreground(repo, [marks[mark]])
839 foreground = obsolete.foreground(repo, [marks[mark]])
841 deletefrom = [b for b in divs
840 deletefrom = [b for b in divs
842 if repo[b].rev() in anc or b == target]
841 if repo[b].rev() in anc or b == target]
843 bookmarks.deletedivergent(repo, deletefrom, mark)
842 bookmarks.deletedivergent(repo, deletefrom, mark)
844 if bmctx.rev() in anc or target in foreground:
843 if bmctx.rev() in anc or target in foreground:
845 ui.status(_("moving bookmark '%s' forward from %s\n") %
844 ui.status(_("moving bookmark '%s' forward from %s\n") %
846 (mark, short(bmctx.node())))
845 (mark, short(bmctx.node())))
847 return
846 return
848 raise util.Abort(_("bookmark '%s' already exists "
847 raise util.Abort(_("bookmark '%s' already exists "
849 "(use -f to force)") % mark)
848 "(use -f to force)") % mark)
850 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
849 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
851 and not force):
850 and not force):
852 raise util.Abort(
851 raise util.Abort(
853 _("a bookmark cannot have the name of an existing branch"))
852 _("a bookmark cannot have the name of an existing branch"))
854
853
855 if delete and rename:
854 if delete and rename:
856 raise util.Abort(_("--delete and --rename are incompatible"))
855 raise util.Abort(_("--delete and --rename are incompatible"))
857 if delete and rev:
856 if delete and rev:
858 raise util.Abort(_("--rev is incompatible with --delete"))
857 raise util.Abort(_("--rev is incompatible with --delete"))
859 if rename and rev:
858 if rename and rev:
860 raise util.Abort(_("--rev is incompatible with --rename"))
859 raise util.Abort(_("--rev is incompatible with --rename"))
861 if not names and (delete or rev):
860 if not names and (delete or rev):
862 raise util.Abort(_("bookmark name required"))
861 raise util.Abort(_("bookmark name required"))
863
862
864 if delete or rename or names or inactive:
863 if delete or rename or names or inactive:
865 wlock = repo.wlock()
864 wlock = repo.wlock()
866 try:
865 try:
866 cur = repo.changectx('.').node()
867 marks = repo._bookmarks
867 marks = repo._bookmarks
868 if delete:
868 if delete:
869 for mark in names:
869 for mark in names:
870 if mark not in marks:
870 if mark not in marks:
871 raise util.Abort(_("bookmark '%s' does not exist") %
871 raise util.Abort(_("bookmark '%s' does not exist") %
872 mark)
872 mark)
873 if mark == repo._bookmarkcurrent:
873 if mark == repo._bookmarkcurrent:
874 bookmarks.unsetcurrent(repo)
874 bookmarks.unsetcurrent(repo)
875 del marks[mark]
875 del marks[mark]
876 marks.write()
876 marks.write()
877
877
878 elif rename:
878 elif rename:
879 if not names:
879 if not names:
880 raise util.Abort(_("new bookmark name required"))
880 raise util.Abort(_("new bookmark name required"))
881 elif len(names) > 1:
881 elif len(names) > 1:
882 raise util.Abort(_("only one new bookmark name allowed"))
882 raise util.Abort(_("only one new bookmark name allowed"))
883 mark = checkformat(names[0])
883 mark = checkformat(names[0])
884 if rename not in marks:
884 if rename not in marks:
885 raise util.Abort(_("bookmark '%s' does not exist") % rename)
885 raise util.Abort(_("bookmark '%s' does not exist") % rename)
886 checkconflict(repo, mark, cur, force)
886 checkconflict(repo, mark, cur, force)
887 marks[mark] = marks[rename]
887 marks[mark] = marks[rename]
888 if repo._bookmarkcurrent == rename and not inactive:
888 if repo._bookmarkcurrent == rename and not inactive:
889 bookmarks.setcurrent(repo, mark)
889 bookmarks.setcurrent(repo, mark)
890 del marks[rename]
890 del marks[rename]
891 marks.write()
891 marks.write()
892
892
893 elif names:
893 elif names:
894 newact = None
894 newact = None
895 for mark in names:
895 for mark in names:
896 mark = checkformat(mark)
896 mark = checkformat(mark)
897 if newact is None:
897 if newact is None:
898 newact = mark
898 newact = mark
899 if inactive and mark == repo._bookmarkcurrent:
899 if inactive and mark == repo._bookmarkcurrent:
900 bookmarks.unsetcurrent(repo)
900 bookmarks.unsetcurrent(repo)
901 return
901 return
902 tgt = cur
902 tgt = cur
903 if rev:
903 if rev:
904 tgt = scmutil.revsingle(repo, rev).node()
904 tgt = scmutil.revsingle(repo, rev).node()
905 checkconflict(repo, mark, cur, force, tgt)
905 checkconflict(repo, mark, cur, force, tgt)
906 marks[mark] = tgt
906 marks[mark] = tgt
907 if not inactive and cur == marks[newact] and not rev:
907 if not inactive and cur == marks[newact] and not rev:
908 bookmarks.setcurrent(repo, newact)
908 bookmarks.setcurrent(repo, newact)
909 elif cur != tgt and newact == repo._bookmarkcurrent:
909 elif cur != tgt and newact == repo._bookmarkcurrent:
910 bookmarks.unsetcurrent(repo)
910 bookmarks.unsetcurrent(repo)
911 marks.write()
911 marks.write()
912
912
913 elif inactive:
913 elif inactive:
914 if len(marks) == 0:
914 if len(marks) == 0:
915 ui.status(_("no bookmarks set\n"))
915 ui.status(_("no bookmarks set\n"))
916 elif not repo._bookmarkcurrent:
916 elif not repo._bookmarkcurrent:
917 ui.status(_("no active bookmark\n"))
917 ui.status(_("no active bookmark\n"))
918 else:
918 else:
919 bookmarks.unsetcurrent(repo)
919 bookmarks.unsetcurrent(repo)
920 finally:
920 finally:
921 wlock.release()
921 wlock.release()
922 else: # show bookmarks
922 else: # show bookmarks
923 marks = repo._bookmarks
923 marks = repo._bookmarks
924 if len(marks) == 0:
924 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
925 ui.status(_("no bookmarks set\n"))
926 else:
926 else:
927 for bmark, n in sorted(marks.iteritems()):
927 for bmark, n in sorted(marks.iteritems()):
928 current = repo._bookmarkcurrent
928 current = repo._bookmarkcurrent
929 if bmark == current:
929 if bmark == current:
930 prefix, label = '*', 'bookmarks.current'
930 prefix, label = '*', 'bookmarks.current'
931 else:
931 else:
932 prefix, label = ' ', ''
932 prefix, label = ' ', ''
933
933
934 if ui.quiet:
934 if ui.quiet:
935 ui.write("%s\n" % bmark, label=label)
935 ui.write("%s\n" % bmark, label=label)
936 else:
936 else:
937 ui.write(" %s %-25s %d:%s\n" % (
937 ui.write(" %s %-25s %d:%s\n" % (
938 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
938 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
939 label=label)
939 label=label)
940
940
941 @command('branch',
941 @command('branch',
942 [('f', 'force', None,
942 [('f', 'force', None,
943 _('set branch name even if it shadows an existing branch')),
943 _('set branch name even if it shadows an existing branch')),
944 ('C', 'clean', None, _('reset branch name to parent branch name'))],
944 ('C', 'clean', None, _('reset branch name to parent branch name'))],
945 _('[-fC] [NAME]'))
945 _('[-fC] [NAME]'))
946 def branch(ui, repo, label=None, **opts):
946 def branch(ui, repo, label=None, **opts):
947 """set or show the current branch name
947 """set or show the current branch name
948
948
949 .. note::
949 .. note::
950
950
951 Branch names are permanent and global. Use :hg:`bookmark` to create a
951 Branch names are permanent and global. Use :hg:`bookmark` to create a
952 light-weight bookmark instead. See :hg:`help glossary` for more
952 light-weight bookmark instead. See :hg:`help glossary` for more
953 information about named branches and bookmarks.
953 information about named branches and bookmarks.
954
954
955 With no argument, show the current branch name. With one argument,
955 With no argument, show the current branch name. With one argument,
956 set the working directory branch name (the branch will not exist
956 set the working directory branch name (the branch will not exist
957 in the repository until the next commit). Standard practice
957 in the repository until the next commit). Standard practice
958 recommends that primary development take place on the 'default'
958 recommends that primary development take place on the 'default'
959 branch.
959 branch.
960
960
961 Unless -f/--force is specified, branch will not let you set a
961 Unless -f/--force is specified, branch will not let you set a
962 branch name that already exists, even if it's inactive.
962 branch name that already exists, even if it's inactive.
963
963
964 Use -C/--clean to reset the working directory branch to that of
964 Use -C/--clean to reset the working directory branch to that of
965 the parent of the working directory, negating a previous branch
965 the parent of the working directory, negating a previous branch
966 change.
966 change.
967
967
968 Use the command :hg:`update` to switch to an existing branch. Use
968 Use the command :hg:`update` to switch to an existing branch. Use
969 :hg:`commit --close-branch` to mark this branch as closed.
969 :hg:`commit --close-branch` to mark this branch as closed.
970
970
971 Returns 0 on success.
971 Returns 0 on success.
972 """
972 """
973 if label:
973 if label:
974 label = label.strip()
974 label = label.strip()
975
975
976 if not opts.get('clean') and not label:
976 if not opts.get('clean') and not label:
977 ui.write("%s\n" % repo.dirstate.branch())
977 ui.write("%s\n" % repo.dirstate.branch())
978 return
978 return
979
979
980 wlock = repo.wlock()
980 wlock = repo.wlock()
981 try:
981 try:
982 if opts.get('clean'):
982 if opts.get('clean'):
983 label = repo[None].p1().branch()
983 label = repo[None].p1().branch()
984 repo.dirstate.setbranch(label)
984 repo.dirstate.setbranch(label)
985 ui.status(_('reset working directory to branch %s\n') % label)
985 ui.status(_('reset working directory to branch %s\n') % label)
986 elif label:
986 elif label:
987 if not opts.get('force') and label in repo.branchmap():
987 if not opts.get('force') and label in repo.branchmap():
988 if label not in [p.branch() for p in repo.parents()]:
988 if label not in [p.branch() for p in repo.parents()]:
989 raise util.Abort(_('a branch of the same name already'
989 raise util.Abort(_('a branch of the same name already'
990 ' exists'),
990 ' exists'),
991 # i18n: "it" refers to an existing branch
991 # i18n: "it" refers to an existing branch
992 hint=_("use 'hg update' to switch to it"))
992 hint=_("use 'hg update' to switch to it"))
993 scmutil.checknewlabel(repo, label, 'branch')
993 scmutil.checknewlabel(repo, label, 'branch')
994 repo.dirstate.setbranch(label)
994 repo.dirstate.setbranch(label)
995 ui.status(_('marked working directory as branch %s\n') % label)
995 ui.status(_('marked working directory as branch %s\n') % label)
996 ui.status(_('(branches are permanent and global, '
996 ui.status(_('(branches are permanent and global, '
997 'did you want a bookmark?)\n'))
997 'did you want a bookmark?)\n'))
998 finally:
998 finally:
999 wlock.release()
999 wlock.release()
1000
1000
1001 @command('branches',
1001 @command('branches',
1002 [('a', 'active', False, _('show only branches that have unmerged heads')),
1002 [('a', 'active', False, _('show only branches that have unmerged heads')),
1003 ('c', 'closed', False, _('show normal and closed branches'))],
1003 ('c', 'closed', False, _('show normal and closed branches'))],
1004 _('[-ac]'))
1004 _('[-ac]'))
1005 def branches(ui, repo, active=False, closed=False):
1005 def branches(ui, repo, active=False, closed=False):
1006 """list repository named branches
1006 """list repository named branches
1007
1007
1008 List the repository's named branches, indicating which ones are
1008 List the repository's named branches, indicating which ones are
1009 inactive. If -c/--closed is specified, also list branches which have
1009 inactive. If -c/--closed is specified, also list branches which have
1010 been marked closed (see :hg:`commit --close-branch`).
1010 been marked closed (see :hg:`commit --close-branch`).
1011
1011
1012 If -a/--active is specified, only show active branches. A branch
1012 If -a/--active is specified, only show active branches. A branch
1013 is considered active if it contains repository heads.
1013 is considered active if it contains repository heads.
1014
1014
1015 Use the command :hg:`update` to switch to an existing branch.
1015 Use the command :hg:`update` to switch to an existing branch.
1016
1016
1017 Returns 0.
1017 Returns 0.
1018 """
1018 """
1019
1019
1020 hexfunc = ui.debugflag and hex or short
1020 hexfunc = ui.debugflag and hex or short
1021
1021
1022 allheads = set(repo.heads())
1022 allheads = set(repo.heads())
1023 branches = []
1023 branches = []
1024 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1024 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1025 isactive = not isclosed and bool(set(heads) & allheads)
1025 isactive = not isclosed and bool(set(heads) & allheads)
1026 branches.append((tag, repo[tip], isactive, not isclosed))
1026 branches.append((tag, repo[tip], isactive, not isclosed))
1027 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1027 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1028 reverse=True)
1028 reverse=True)
1029
1029
1030 for tag, ctx, isactive, isopen in branches:
1030 for tag, ctx, isactive, isopen in branches:
1031 if (not active) or isactive:
1031 if (not active) or isactive:
1032 if isactive:
1032 if isactive:
1033 label = 'branches.active'
1033 label = 'branches.active'
1034 notice = ''
1034 notice = ''
1035 elif not isopen:
1035 elif not isopen:
1036 if not closed:
1036 if not closed:
1037 continue
1037 continue
1038 label = 'branches.closed'
1038 label = 'branches.closed'
1039 notice = _(' (closed)')
1039 notice = _(' (closed)')
1040 else:
1040 else:
1041 label = 'branches.inactive'
1041 label = 'branches.inactive'
1042 notice = _(' (inactive)')
1042 notice = _(' (inactive)')
1043 if tag == repo.dirstate.branch():
1043 if tag == repo.dirstate.branch():
1044 label = 'branches.current'
1044 label = 'branches.current'
1045 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1045 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1046 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1046 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1047 'log.changeset changeset.%s' % ctx.phasestr())
1047 'log.changeset changeset.%s' % ctx.phasestr())
1048 labeledtag = ui.label(tag, label)
1048 labeledtag = ui.label(tag, label)
1049 if ui.quiet:
1049 if ui.quiet:
1050 ui.write("%s\n" % labeledtag)
1050 ui.write("%s\n" % labeledtag)
1051 else:
1051 else:
1052 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1052 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1053
1053
1054 @command('bundle',
1054 @command('bundle',
1055 [('f', 'force', None, _('run even when the destination is unrelated')),
1055 [('f', 'force', None, _('run even when the destination is unrelated')),
1056 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1056 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1057 _('REV')),
1057 _('REV')),
1058 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1058 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1059 _('BRANCH')),
1059 _('BRANCH')),
1060 ('', 'base', [],
1060 ('', 'base', [],
1061 _('a base changeset assumed to be available at the destination'),
1061 _('a base changeset assumed to be available at the destination'),
1062 _('REV')),
1062 _('REV')),
1063 ('a', 'all', None, _('bundle all changesets in the repository')),
1063 ('a', 'all', None, _('bundle all changesets in the repository')),
1064 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1064 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1065 ] + remoteopts,
1065 ] + remoteopts,
1066 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1066 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1067 def bundle(ui, repo, fname, dest=None, **opts):
1067 def bundle(ui, repo, fname, dest=None, **opts):
1068 """create a changegroup file
1068 """create a changegroup file
1069
1069
1070 Generate a compressed changegroup file collecting changesets not
1070 Generate a compressed changegroup file collecting changesets not
1071 known to be in another repository.
1071 known to be in another repository.
1072
1072
1073 If you omit the destination repository, then hg assumes the
1073 If you omit the destination repository, then hg assumes the
1074 destination will have all the nodes you specify with --base
1074 destination will have all the nodes you specify with --base
1075 parameters. To create a bundle containing all changesets, use
1075 parameters. To create a bundle containing all changesets, use
1076 -a/--all (or --base null).
1076 -a/--all (or --base null).
1077
1077
1078 You can change compression method with the -t/--type option.
1078 You can change compression method with the -t/--type option.
1079 The available compression methods are: none, bzip2, and
1079 The available compression methods are: none, bzip2, and
1080 gzip (by default, bundles are compressed using bzip2).
1080 gzip (by default, bundles are compressed using bzip2).
1081
1081
1082 The bundle file can then be transferred using conventional means
1082 The bundle file can then be transferred using conventional means
1083 and applied to another repository with the unbundle or pull
1083 and applied to another repository with the unbundle or pull
1084 command. This is useful when direct push and pull are not
1084 command. This is useful when direct push and pull are not
1085 available or when exporting an entire repository is undesirable.
1085 available or when exporting an entire repository is undesirable.
1086
1086
1087 Applying bundles preserves all changeset contents including
1087 Applying bundles preserves all changeset contents including
1088 permissions, copy/rename information, and revision history.
1088 permissions, copy/rename information, and revision history.
1089
1089
1090 Returns 0 on success, 1 if no changes found.
1090 Returns 0 on success, 1 if no changes found.
1091 """
1091 """
1092 revs = None
1092 revs = None
1093 if 'rev' in opts:
1093 if 'rev' in opts:
1094 revs = scmutil.revrange(repo, opts['rev'])
1094 revs = scmutil.revrange(repo, opts['rev'])
1095
1095
1096 bundletype = opts.get('type', 'bzip2').lower()
1096 bundletype = opts.get('type', 'bzip2').lower()
1097 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1097 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1098 bundletype = btypes.get(bundletype)
1098 bundletype = btypes.get(bundletype)
1099 if bundletype not in changegroup.bundletypes:
1099 if bundletype not in changegroup.bundletypes:
1100 raise util.Abort(_('unknown bundle type specified with --type'))
1100 raise util.Abort(_('unknown bundle type specified with --type'))
1101
1101
1102 if opts.get('all'):
1102 if opts.get('all'):
1103 base = ['null']
1103 base = ['null']
1104 else:
1104 else:
1105 base = scmutil.revrange(repo, opts.get('base'))
1105 base = scmutil.revrange(repo, opts.get('base'))
1106 # TODO: get desired bundlecaps from command line.
1106 # TODO: get desired bundlecaps from command line.
1107 bundlecaps = None
1107 bundlecaps = None
1108 if base:
1108 if base:
1109 if dest:
1109 if dest:
1110 raise util.Abort(_("--base is incompatible with specifying "
1110 raise util.Abort(_("--base is incompatible with specifying "
1111 "a destination"))
1111 "a destination"))
1112 common = [repo.lookup(rev) for rev in base]
1112 common = [repo.lookup(rev) for rev in base]
1113 heads = revs and map(repo.lookup, revs) or revs
1113 heads = revs and map(repo.lookup, revs) or revs
1114 cg = repo.getbundle('bundle', heads=heads, common=common,
1114 cg = repo.getbundle('bundle', heads=heads, common=common,
1115 bundlecaps=bundlecaps)
1115 bundlecaps=bundlecaps)
1116 outgoing = None
1116 outgoing = None
1117 else:
1117 else:
1118 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1118 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1119 dest, branches = hg.parseurl(dest, opts.get('branch'))
1119 dest, branches = hg.parseurl(dest, opts.get('branch'))
1120 other = hg.peer(repo, opts, dest)
1120 other = hg.peer(repo, opts, dest)
1121 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1121 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1122 heads = revs and map(repo.lookup, revs) or revs
1122 heads = revs and map(repo.lookup, revs) or revs
1123 outgoing = discovery.findcommonoutgoing(repo, other,
1123 outgoing = discovery.findcommonoutgoing(repo, other,
1124 onlyheads=heads,
1124 onlyheads=heads,
1125 force=opts.get('force'),
1125 force=opts.get('force'),
1126 portable=True)
1126 portable=True)
1127 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1127 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1128 if not cg:
1128 if not cg:
1129 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1129 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1130 return 1
1130 return 1
1131
1131
1132 changegroup.writebundle(cg, fname, bundletype)
1132 changegroup.writebundle(cg, fname, bundletype)
1133
1133
1134 @command('cat',
1134 @command('cat',
1135 [('o', 'output', '',
1135 [('o', 'output', '',
1136 _('print output to file with formatted name'), _('FORMAT')),
1136 _('print output to file with formatted name'), _('FORMAT')),
1137 ('r', 'rev', '', _('print the given revision'), _('REV')),
1137 ('r', 'rev', '', _('print the given revision'), _('REV')),
1138 ('', 'decode', None, _('apply any matching decode filter')),
1138 ('', 'decode', None, _('apply any matching decode filter')),
1139 ] + walkopts,
1139 ] + walkopts,
1140 _('[OPTION]... FILE...'))
1140 _('[OPTION]... FILE...'))
1141 def cat(ui, repo, file1, *pats, **opts):
1141 def cat(ui, repo, file1, *pats, **opts):
1142 """output the current or given revision of files
1142 """output the current or given revision of files
1143
1143
1144 Print the specified files as they were at the given revision. If
1144 Print the specified files as they were at the given revision. If
1145 no revision is given, the parent of the working directory is used.
1145 no revision is given, the parent of the working directory is used.
1146
1146
1147 Output may be to a file, in which case the name of the file is
1147 Output may be to a file, in which case the name of the file is
1148 given using a format string. The formatting rules are the same as
1148 given using a format string. The formatting rules are the same as
1149 for the export command, with the following additions:
1149 for the export command, with the following additions:
1150
1150
1151 :``%s``: basename of file being printed
1151 :``%s``: basename of file being printed
1152 :``%d``: dirname of file being printed, or '.' if in repository root
1152 :``%d``: dirname of file being printed, or '.' if in repository root
1153 :``%p``: root-relative path name of file being printed
1153 :``%p``: root-relative path name of file being printed
1154
1154
1155 Returns 0 on success.
1155 Returns 0 on success.
1156 """
1156 """
1157 ctx = scmutil.revsingle(repo, opts.get('rev'))
1157 ctx = scmutil.revsingle(repo, opts.get('rev'))
1158 err = 1
1158 err = 1
1159 m = scmutil.match(ctx, (file1,) + pats, opts)
1159 m = scmutil.match(ctx, (file1,) + pats, opts)
1160 for abs in ctx.walk(m):
1160 for abs in ctx.walk(m):
1161 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1161 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1162 pathname=abs)
1162 pathname=abs)
1163 data = ctx[abs].data()
1163 data = ctx[abs].data()
1164 if opts.get('decode'):
1164 if opts.get('decode'):
1165 data = repo.wwritedata(abs, data)
1165 data = repo.wwritedata(abs, data)
1166 fp.write(data)
1166 fp.write(data)
1167 fp.close()
1167 fp.close()
1168 err = 0
1168 err = 0
1169 return err
1169 return err
1170
1170
1171 @command('^clone',
1171 @command('^clone',
1172 [('U', 'noupdate', None,
1172 [('U', 'noupdate', None,
1173 _('the clone will include an empty working copy (only a repository)')),
1173 _('the clone will include an empty working copy (only a repository)')),
1174 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1174 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1175 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1175 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1176 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1176 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1177 ('', 'pull', None, _('use pull protocol to copy metadata')),
1177 ('', 'pull', None, _('use pull protocol to copy metadata')),
1178 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1178 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1179 ] + remoteopts,
1179 ] + remoteopts,
1180 _('[OPTION]... SOURCE [DEST]'))
1180 _('[OPTION]... SOURCE [DEST]'))
1181 def clone(ui, source, dest=None, **opts):
1181 def clone(ui, source, dest=None, **opts):
1182 """make a copy of an existing repository
1182 """make a copy of an existing repository
1183
1183
1184 Create a copy of an existing repository in a new directory.
1184 Create a copy of an existing repository in a new directory.
1185
1185
1186 If no destination directory name is specified, it defaults to the
1186 If no destination directory name is specified, it defaults to the
1187 basename of the source.
1187 basename of the source.
1188
1188
1189 The location of the source is added to the new repository's
1189 The location of the source is added to the new repository's
1190 ``.hg/hgrc`` file, as the default to be used for future pulls.
1190 ``.hg/hgrc`` file, as the default to be used for future pulls.
1191
1191
1192 Only local paths and ``ssh://`` URLs are supported as
1192 Only local paths and ``ssh://`` URLs are supported as
1193 destinations. For ``ssh://`` destinations, no working directory or
1193 destinations. For ``ssh://`` destinations, no working directory or
1194 ``.hg/hgrc`` will be created on the remote side.
1194 ``.hg/hgrc`` will be created on the remote side.
1195
1195
1196 To pull only a subset of changesets, specify one or more revisions
1196 To pull only a subset of changesets, specify one or more revisions
1197 identifiers with -r/--rev or branches with -b/--branch. The
1197 identifiers with -r/--rev or branches with -b/--branch. The
1198 resulting clone will contain only the specified changesets and
1198 resulting clone will contain only the specified changesets and
1199 their ancestors. These options (or 'clone src#rev dest') imply
1199 their ancestors. These options (or 'clone src#rev dest') imply
1200 --pull, even for local source repositories. Note that specifying a
1200 --pull, even for local source repositories. Note that specifying a
1201 tag will include the tagged changeset but not the changeset
1201 tag will include the tagged changeset but not the changeset
1202 containing the tag.
1202 containing the tag.
1203
1203
1204 If the source repository has a bookmark called '@' set, that
1204 If the source repository has a bookmark called '@' set, that
1205 revision will be checked out in the new repository by default.
1205 revision will be checked out in the new repository by default.
1206
1206
1207 To check out a particular version, use -u/--update, or
1207 To check out a particular version, use -u/--update, or
1208 -U/--noupdate to create a clone with no working directory.
1208 -U/--noupdate to create a clone with no working directory.
1209
1209
1210 .. container:: verbose
1210 .. container:: verbose
1211
1211
1212 For efficiency, hardlinks are used for cloning whenever the
1212 For efficiency, hardlinks are used for cloning whenever the
1213 source and destination are on the same filesystem (note this
1213 source and destination are on the same filesystem (note this
1214 applies only to the repository data, not to the working
1214 applies only to the repository data, not to the working
1215 directory). Some filesystems, such as AFS, implement hardlinking
1215 directory). Some filesystems, such as AFS, implement hardlinking
1216 incorrectly, but do not report errors. In these cases, use the
1216 incorrectly, but do not report errors. In these cases, use the
1217 --pull option to avoid hardlinking.
1217 --pull option to avoid hardlinking.
1218
1218
1219 In some cases, you can clone repositories and the working
1219 In some cases, you can clone repositories and the working
1220 directory using full hardlinks with ::
1220 directory using full hardlinks with ::
1221
1221
1222 $ cp -al REPO REPOCLONE
1222 $ cp -al REPO REPOCLONE
1223
1223
1224 This is the fastest way to clone, but it is not always safe. The
1224 This is the fastest way to clone, but it is not always safe. The
1225 operation is not atomic (making sure REPO is not modified during
1225 operation is not atomic (making sure REPO is not modified during
1226 the operation is up to you) and you have to make sure your
1226 the operation is up to you) and you have to make sure your
1227 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1227 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1228 so). Also, this is not compatible with certain extensions that
1228 so). Also, this is not compatible with certain extensions that
1229 place their metadata under the .hg directory, such as mq.
1229 place their metadata under the .hg directory, such as mq.
1230
1230
1231 Mercurial will update the working directory to the first applicable
1231 Mercurial will update the working directory to the first applicable
1232 revision from this list:
1232 revision from this list:
1233
1233
1234 a) null if -U or the source repository has no changesets
1234 a) null if -U or the source repository has no changesets
1235 b) if -u . and the source repository is local, the first parent of
1235 b) if -u . and the source repository is local, the first parent of
1236 the source repository's working directory
1236 the source repository's working directory
1237 c) the changeset specified with -u (if a branch name, this means the
1237 c) the changeset specified with -u (if a branch name, this means the
1238 latest head of that branch)
1238 latest head of that branch)
1239 d) the changeset specified with -r
1239 d) the changeset specified with -r
1240 e) the tipmost head specified with -b
1240 e) the tipmost head specified with -b
1241 f) the tipmost head specified with the url#branch source syntax
1241 f) the tipmost head specified with the url#branch source syntax
1242 g) the revision marked with the '@' bookmark, if present
1242 g) the revision marked with the '@' bookmark, if present
1243 h) the tipmost head of the default branch
1243 h) the tipmost head of the default branch
1244 i) tip
1244 i) tip
1245
1245
1246 Examples:
1246 Examples:
1247
1247
1248 - clone a remote repository to a new directory named hg/::
1248 - clone a remote repository to a new directory named hg/::
1249
1249
1250 hg clone http://selenic.com/hg
1250 hg clone http://selenic.com/hg
1251
1251
1252 - create a lightweight local clone::
1252 - create a lightweight local clone::
1253
1253
1254 hg clone project/ project-feature/
1254 hg clone project/ project-feature/
1255
1255
1256 - clone from an absolute path on an ssh server (note double-slash)::
1256 - clone from an absolute path on an ssh server (note double-slash)::
1257
1257
1258 hg clone ssh://user@server//home/projects/alpha/
1258 hg clone ssh://user@server//home/projects/alpha/
1259
1259
1260 - do a high-speed clone over a LAN while checking out a
1260 - do a high-speed clone over a LAN while checking out a
1261 specified version::
1261 specified version::
1262
1262
1263 hg clone --uncompressed http://server/repo -u 1.5
1263 hg clone --uncompressed http://server/repo -u 1.5
1264
1264
1265 - create a repository without changesets after a particular revision::
1265 - create a repository without changesets after a particular revision::
1266
1266
1267 hg clone -r 04e544 experimental/ good/
1267 hg clone -r 04e544 experimental/ good/
1268
1268
1269 - clone (and track) a particular named branch::
1269 - clone (and track) a particular named branch::
1270
1270
1271 hg clone http://selenic.com/hg#stable
1271 hg clone http://selenic.com/hg#stable
1272
1272
1273 See :hg:`help urls` for details on specifying URLs.
1273 See :hg:`help urls` for details on specifying URLs.
1274
1274
1275 Returns 0 on success.
1275 Returns 0 on success.
1276 """
1276 """
1277 if opts.get('noupdate') and opts.get('updaterev'):
1277 if opts.get('noupdate') and opts.get('updaterev'):
1278 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1278 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1279
1279
1280 r = hg.clone(ui, opts, source, dest,
1280 r = hg.clone(ui, opts, source, dest,
1281 pull=opts.get('pull'),
1281 pull=opts.get('pull'),
1282 stream=opts.get('uncompressed'),
1282 stream=opts.get('uncompressed'),
1283 rev=opts.get('rev'),
1283 rev=opts.get('rev'),
1284 update=opts.get('updaterev') or not opts.get('noupdate'),
1284 update=opts.get('updaterev') or not opts.get('noupdate'),
1285 branch=opts.get('branch'))
1285 branch=opts.get('branch'))
1286
1286
1287 return r is None
1287 return r is None
1288
1288
1289 @command('^commit|ci',
1289 @command('^commit|ci',
1290 [('A', 'addremove', None,
1290 [('A', 'addremove', None,
1291 _('mark new/missing files as added/removed before committing')),
1291 _('mark new/missing files as added/removed before committing')),
1292 ('', 'close-branch', None,
1292 ('', 'close-branch', None,
1293 _('mark a branch as closed, hiding it from the branch list')),
1293 _('mark a branch as closed, hiding it from the branch list')),
1294 ('', 'amend', None, _('amend the parent of the working dir')),
1294 ('', 'amend', None, _('amend the parent of the working dir')),
1295 ('s', 'secret', None, _('use the secret phase for committing')),
1295 ('s', 'secret', None, _('use the secret phase for committing')),
1296 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1296 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1297 _('[OPTION]... [FILE]...'))
1297 _('[OPTION]... [FILE]...'))
1298 def commit(ui, repo, *pats, **opts):
1298 def commit(ui, repo, *pats, **opts):
1299 """commit the specified files or all outstanding changes
1299 """commit the specified files or all outstanding changes
1300
1300
1301 Commit changes to the given files into the repository. Unlike a
1301 Commit changes to the given files into the repository. Unlike a
1302 centralized SCM, this operation is a local operation. See
1302 centralized SCM, this operation is a local operation. See
1303 :hg:`push` for a way to actively distribute your changes.
1303 :hg:`push` for a way to actively distribute your changes.
1304
1304
1305 If a list of files is omitted, all changes reported by :hg:`status`
1305 If a list of files is omitted, all changes reported by :hg:`status`
1306 will be committed.
1306 will be committed.
1307
1307
1308 If you are committing the result of a merge, do not provide any
1308 If you are committing the result of a merge, do not provide any
1309 filenames or -I/-X filters.
1309 filenames or -I/-X filters.
1310
1310
1311 If no commit message is specified, Mercurial starts your
1311 If no commit message is specified, Mercurial starts your
1312 configured editor where you can enter a message. In case your
1312 configured editor where you can enter a message. In case your
1313 commit fails, you will find a backup of your message in
1313 commit fails, you will find a backup of your message in
1314 ``.hg/last-message.txt``.
1314 ``.hg/last-message.txt``.
1315
1315
1316 The --amend flag can be used to amend the parent of the
1316 The --amend flag can be used to amend the parent of the
1317 working directory with a new commit that contains the changes
1317 working directory with a new commit that contains the changes
1318 in the parent in addition to those currently reported by :hg:`status`,
1318 in the parent in addition to those currently reported by :hg:`status`,
1319 if there are any. The old commit is stored in a backup bundle in
1319 if there are any. The old commit is stored in a backup bundle in
1320 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1320 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1321 on how to restore it).
1321 on how to restore it).
1322
1322
1323 Message, user and date are taken from the amended commit unless
1323 Message, user and date are taken from the amended commit unless
1324 specified. When a message isn't specified on the command line,
1324 specified. When a message isn't specified on the command line,
1325 the editor will open with the message of the amended commit.
1325 the editor will open with the message of the amended commit.
1326
1326
1327 It is not possible to amend public changesets (see :hg:`help phases`)
1327 It is not possible to amend public changesets (see :hg:`help phases`)
1328 or changesets that have children.
1328 or changesets that have children.
1329
1329
1330 See :hg:`help dates` for a list of formats valid for -d/--date.
1330 See :hg:`help dates` for a list of formats valid for -d/--date.
1331
1331
1332 Returns 0 on success, 1 if nothing changed.
1332 Returns 0 on success, 1 if nothing changed.
1333 """
1333 """
1334 if opts.get('subrepos'):
1334 if opts.get('subrepos'):
1335 if opts.get('amend'):
1335 if opts.get('amend'):
1336 raise util.Abort(_('cannot amend with --subrepos'))
1336 raise util.Abort(_('cannot amend with --subrepos'))
1337 # Let --subrepos on the command line override config setting.
1337 # Let --subrepos on the command line override config setting.
1338 ui.setconfig('ui', 'commitsubrepos', True)
1338 ui.setconfig('ui', 'commitsubrepos', True)
1339
1339
1340 # Save this for restoring it later
1340 # Save this for restoring it later
1341 oldcommitphase = ui.config('phases', 'new-commit')
1341 oldcommitphase = ui.config('phases', 'new-commit')
1342
1342
1343 cmdutil.checkunfinished(repo, commit=True)
1343 cmdutil.checkunfinished(repo, commit=True)
1344
1344
1345 branch = repo[None].branch()
1345 branch = repo[None].branch()
1346 bheads = repo.branchheads(branch)
1346 bheads = repo.branchheads(branch)
1347
1347
1348 extra = {}
1348 extra = {}
1349 if opts.get('close_branch'):
1349 if opts.get('close_branch'):
1350 extra['close'] = 1
1350 extra['close'] = 1
1351
1351
1352 if not bheads:
1352 if not bheads:
1353 raise util.Abort(_('can only close branch heads'))
1353 raise util.Abort(_('can only close branch heads'))
1354 elif opts.get('amend'):
1354 elif opts.get('amend'):
1355 if repo.parents()[0].p1().branch() != branch and \
1355 if repo.parents()[0].p1().branch() != branch and \
1356 repo.parents()[0].p2().branch() != branch:
1356 repo.parents()[0].p2().branch() != branch:
1357 raise util.Abort(_('can only close branch heads'))
1357 raise util.Abort(_('can only close branch heads'))
1358
1358
1359 if opts.get('amend'):
1359 if opts.get('amend'):
1360 if ui.configbool('ui', 'commitsubrepos'):
1360 if ui.configbool('ui', 'commitsubrepos'):
1361 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1361 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1362
1362
1363 old = repo['.']
1363 old = repo['.']
1364 if old.phase() == phases.public:
1364 if old.phase() == phases.public:
1365 raise util.Abort(_('cannot amend public changesets'))
1365 raise util.Abort(_('cannot amend public changesets'))
1366 if len(repo[None].parents()) > 1:
1366 if len(repo[None].parents()) > 1:
1367 raise util.Abort(_('cannot amend while merging'))
1367 raise util.Abort(_('cannot amend while merging'))
1368 if (not obsolete._enabled) and old.children():
1368 if (not obsolete._enabled) and old.children():
1369 raise util.Abort(_('cannot amend changeset with children'))
1369 raise util.Abort(_('cannot amend changeset with children'))
1370
1370
1371 e = cmdutil.commiteditor
1371 e = cmdutil.commiteditor
1372 if opts.get('force_editor'):
1372 if opts.get('force_editor'):
1373 e = cmdutil.commitforceeditor
1373 e = cmdutil.commitforceeditor
1374
1374
1375 def commitfunc(ui, repo, message, match, opts):
1375 def commitfunc(ui, repo, message, match, opts):
1376 editor = e
1376 editor = e
1377 # message contains text from -m or -l, if it's empty,
1377 # message contains text from -m or -l, if it's empty,
1378 # open the editor with the old message
1378 # open the editor with the old message
1379 if not message:
1379 if not message:
1380 message = old.description()
1380 message = old.description()
1381 editor = cmdutil.commitforceeditor
1381 editor = cmdutil.commitforceeditor
1382 try:
1382 try:
1383 if opts.get('secret'):
1383 if opts.get('secret'):
1384 ui.setconfig('phases', 'new-commit', 'secret')
1384 ui.setconfig('phases', 'new-commit', 'secret')
1385
1385
1386 return repo.commit(message,
1386 return repo.commit(message,
1387 opts.get('user') or old.user(),
1387 opts.get('user') or old.user(),
1388 opts.get('date') or old.date(),
1388 opts.get('date') or old.date(),
1389 match,
1389 match,
1390 editor=editor,
1390 editor=editor,
1391 extra=extra)
1391 extra=extra)
1392 finally:
1392 finally:
1393 ui.setconfig('phases', 'new-commit', oldcommitphase)
1393 ui.setconfig('phases', 'new-commit', oldcommitphase)
1394
1394
1395 current = repo._bookmarkcurrent
1395 current = repo._bookmarkcurrent
1396 marks = old.bookmarks()
1396 marks = old.bookmarks()
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1398 if node == old.node():
1398 if node == old.node():
1399 ui.status(_("nothing changed\n"))
1399 ui.status(_("nothing changed\n"))
1400 return 1
1400 return 1
1401 elif marks:
1401 elif marks:
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1403 (marks, old.hex(), hex(node)))
1403 (marks, old.hex(), hex(node)))
1404 newmarks = repo._bookmarks
1404 newmarks = repo._bookmarks
1405 for bm in marks:
1405 for bm in marks:
1406 newmarks[bm] = node
1406 newmarks[bm] = node
1407 if bm == current:
1407 if bm == current:
1408 bookmarks.setcurrent(repo, bm)
1408 bookmarks.setcurrent(repo, bm)
1409 newmarks.write()
1409 newmarks.write()
1410 else:
1410 else:
1411 e = cmdutil.commiteditor
1411 e = cmdutil.commiteditor
1412 if opts.get('force_editor'):
1412 if opts.get('force_editor'):
1413 e = cmdutil.commitforceeditor
1413 e = cmdutil.commitforceeditor
1414
1414
1415 def commitfunc(ui, repo, message, match, opts):
1415 def commitfunc(ui, repo, message, match, opts):
1416 try:
1416 try:
1417 if opts.get('secret'):
1417 if opts.get('secret'):
1418 ui.setconfig('phases', 'new-commit', 'secret')
1418 ui.setconfig('phases', 'new-commit', 'secret')
1419
1419
1420 return repo.commit(message, opts.get('user'), opts.get('date'),
1420 return repo.commit(message, opts.get('user'), opts.get('date'),
1421 match, editor=e, extra=extra)
1421 match, editor=e, extra=extra)
1422 finally:
1422 finally:
1423 ui.setconfig('phases', 'new-commit', oldcommitphase)
1423 ui.setconfig('phases', 'new-commit', oldcommitphase)
1424
1424
1425
1425
1426 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1426 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1427
1427
1428 if not node:
1428 if not node:
1429 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1429 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1430 if stat[3]:
1430 if stat[3]:
1431 ui.status(_("nothing changed (%d missing files, see "
1431 ui.status(_("nothing changed (%d missing files, see "
1432 "'hg status')\n") % len(stat[3]))
1432 "'hg status')\n") % len(stat[3]))
1433 else:
1433 else:
1434 ui.status(_("nothing changed\n"))
1434 ui.status(_("nothing changed\n"))
1435 return 1
1435 return 1
1436
1436
1437 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1437 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1438
1438
1439 @command('copy|cp',
1439 @command('copy|cp',
1440 [('A', 'after', None, _('record a copy that has already occurred')),
1440 [('A', 'after', None, _('record a copy that has already occurred')),
1441 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1441 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1442 ] + walkopts + dryrunopts,
1442 ] + walkopts + dryrunopts,
1443 _('[OPTION]... [SOURCE]... DEST'))
1443 _('[OPTION]... [SOURCE]... DEST'))
1444 def copy(ui, repo, *pats, **opts):
1444 def copy(ui, repo, *pats, **opts):
1445 """mark files as copied for the next commit
1445 """mark files as copied for the next commit
1446
1446
1447 Mark dest as having copies of source files. If dest is a
1447 Mark dest as having copies of source files. If dest is a
1448 directory, copies are put in that directory. If dest is a file,
1448 directory, copies are put in that directory. If dest is a file,
1449 the source must be a single file.
1449 the source must be a single file.
1450
1450
1451 By default, this command copies the contents of files as they
1451 By default, this command copies the contents of files as they
1452 exist in the working directory. If invoked with -A/--after, the
1452 exist in the working directory. If invoked with -A/--after, the
1453 operation is recorded, but no copying is performed.
1453 operation is recorded, but no copying is performed.
1454
1454
1455 This command takes effect with the next commit. To undo a copy
1455 This command takes effect with the next commit. To undo a copy
1456 before that, see :hg:`revert`.
1456 before that, see :hg:`revert`.
1457
1457
1458 Returns 0 on success, 1 if errors are encountered.
1458 Returns 0 on success, 1 if errors are encountered.
1459 """
1459 """
1460 wlock = repo.wlock(False)
1460 wlock = repo.wlock(False)
1461 try:
1461 try:
1462 return cmdutil.copy(ui, repo, pats, opts)
1462 return cmdutil.copy(ui, repo, pats, opts)
1463 finally:
1463 finally:
1464 wlock.release()
1464 wlock.release()
1465
1465
1466 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1466 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1467 def debugancestor(ui, repo, *args):
1467 def debugancestor(ui, repo, *args):
1468 """find the ancestor revision of two revisions in a given index"""
1468 """find the ancestor revision of two revisions in a given index"""
1469 if len(args) == 3:
1469 if len(args) == 3:
1470 index, rev1, rev2 = args
1470 index, rev1, rev2 = args
1471 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1471 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1472 lookup = r.lookup
1472 lookup = r.lookup
1473 elif len(args) == 2:
1473 elif len(args) == 2:
1474 if not repo:
1474 if not repo:
1475 raise util.Abort(_("there is no Mercurial repository here "
1475 raise util.Abort(_("there is no Mercurial repository here "
1476 "(.hg not found)"))
1476 "(.hg not found)"))
1477 rev1, rev2 = args
1477 rev1, rev2 = args
1478 r = repo.changelog
1478 r = repo.changelog
1479 lookup = repo.lookup
1479 lookup = repo.lookup
1480 else:
1480 else:
1481 raise util.Abort(_('either two or three arguments required'))
1481 raise util.Abort(_('either two or three arguments required'))
1482 a = r.ancestor(lookup(rev1), lookup(rev2))
1482 a = r.ancestor(lookup(rev1), lookup(rev2))
1483 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1483 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1484
1484
1485 @command('debugbuilddag',
1485 @command('debugbuilddag',
1486 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1486 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1487 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1487 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1488 ('n', 'new-file', None, _('add new file at each rev'))],
1488 ('n', 'new-file', None, _('add new file at each rev'))],
1489 _('[OPTION]... [TEXT]'))
1489 _('[OPTION]... [TEXT]'))
1490 def debugbuilddag(ui, repo, text=None,
1490 def debugbuilddag(ui, repo, text=None,
1491 mergeable_file=False,
1491 mergeable_file=False,
1492 overwritten_file=False,
1492 overwritten_file=False,
1493 new_file=False):
1493 new_file=False):
1494 """builds a repo with a given DAG from scratch in the current empty repo
1494 """builds a repo with a given DAG from scratch in the current empty repo
1495
1495
1496 The description of the DAG is read from stdin if not given on the
1496 The description of the DAG is read from stdin if not given on the
1497 command line.
1497 command line.
1498
1498
1499 Elements:
1499 Elements:
1500
1500
1501 - "+n" is a linear run of n nodes based on the current default parent
1501 - "+n" is a linear run of n nodes based on the current default parent
1502 - "." is a single node based on the current default parent
1502 - "." is a single node based on the current default parent
1503 - "$" resets the default parent to null (implied at the start);
1503 - "$" resets the default parent to null (implied at the start);
1504 otherwise the default parent is always the last node created
1504 otherwise the default parent is always the last node created
1505 - "<p" sets the default parent to the backref p
1505 - "<p" sets the default parent to the backref p
1506 - "*p" is a fork at parent p, which is a backref
1506 - "*p" is a fork at parent p, which is a backref
1507 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1507 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1508 - "/p2" is a merge of the preceding node and p2
1508 - "/p2" is a merge of the preceding node and p2
1509 - ":tag" defines a local tag for the preceding node
1509 - ":tag" defines a local tag for the preceding node
1510 - "@branch" sets the named branch for subsequent nodes
1510 - "@branch" sets the named branch for subsequent nodes
1511 - "#...\\n" is a comment up to the end of the line
1511 - "#...\\n" is a comment up to the end of the line
1512
1512
1513 Whitespace between the above elements is ignored.
1513 Whitespace between the above elements is ignored.
1514
1514
1515 A backref is either
1515 A backref is either
1516
1516
1517 - a number n, which references the node curr-n, where curr is the current
1517 - a number n, which references the node curr-n, where curr is the current
1518 node, or
1518 node, or
1519 - the name of a local tag you placed earlier using ":tag", or
1519 - the name of a local tag you placed earlier using ":tag", or
1520 - empty to denote the default parent.
1520 - empty to denote the default parent.
1521
1521
1522 All string valued-elements are either strictly alphanumeric, or must
1522 All string valued-elements are either strictly alphanumeric, or must
1523 be enclosed in double quotes ("..."), with "\\" as escape character.
1523 be enclosed in double quotes ("..."), with "\\" as escape character.
1524 """
1524 """
1525
1525
1526 if text is None:
1526 if text is None:
1527 ui.status(_("reading DAG from stdin\n"))
1527 ui.status(_("reading DAG from stdin\n"))
1528 text = ui.fin.read()
1528 text = ui.fin.read()
1529
1529
1530 cl = repo.changelog
1530 cl = repo.changelog
1531 if len(cl) > 0:
1531 if len(cl) > 0:
1532 raise util.Abort(_('repository is not empty'))
1532 raise util.Abort(_('repository is not empty'))
1533
1533
1534 # determine number of revs in DAG
1534 # determine number of revs in DAG
1535 total = 0
1535 total = 0
1536 for type, data in dagparser.parsedag(text):
1536 for type, data in dagparser.parsedag(text):
1537 if type == 'n':
1537 if type == 'n':
1538 total += 1
1538 total += 1
1539
1539
1540 if mergeable_file:
1540 if mergeable_file:
1541 linesperrev = 2
1541 linesperrev = 2
1542 # make a file with k lines per rev
1542 # make a file with k lines per rev
1543 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1543 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1544 initialmergedlines.append("")
1544 initialmergedlines.append("")
1545
1545
1546 tags = []
1546 tags = []
1547
1547
1548 lock = tr = None
1548 lock = tr = None
1549 try:
1549 try:
1550 lock = repo.lock()
1550 lock = repo.lock()
1551 tr = repo.transaction("builddag")
1551 tr = repo.transaction("builddag")
1552
1552
1553 at = -1
1553 at = -1
1554 atbranch = 'default'
1554 atbranch = 'default'
1555 nodeids = []
1555 nodeids = []
1556 id = 0
1556 id = 0
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1558 for type, data in dagparser.parsedag(text):
1558 for type, data in dagparser.parsedag(text):
1559 if type == 'n':
1559 if type == 'n':
1560 ui.note(('node %s\n' % str(data)))
1560 ui.note(('node %s\n' % str(data)))
1561 id, ps = data
1561 id, ps = data
1562
1562
1563 files = []
1563 files = []
1564 fctxs = {}
1564 fctxs = {}
1565
1565
1566 p2 = None
1566 p2 = None
1567 if mergeable_file:
1567 if mergeable_file:
1568 fn = "mf"
1568 fn = "mf"
1569 p1 = repo[ps[0]]
1569 p1 = repo[ps[0]]
1570 if len(ps) > 1:
1570 if len(ps) > 1:
1571 p2 = repo[ps[1]]
1571 p2 = repo[ps[1]]
1572 pa = p1.ancestor(p2)
1572 pa = p1.ancestor(p2)
1573 base, local, other = [x[fn].data() for x in (pa, p1,
1573 base, local, other = [x[fn].data() for x in (pa, p1,
1574 p2)]
1574 p2)]
1575 m3 = simplemerge.Merge3Text(base, local, other)
1575 m3 = simplemerge.Merge3Text(base, local, other)
1576 ml = [l.strip() for l in m3.merge_lines()]
1576 ml = [l.strip() for l in m3.merge_lines()]
1577 ml.append("")
1577 ml.append("")
1578 elif at > 0:
1578 elif at > 0:
1579 ml = p1[fn].data().split("\n")
1579 ml = p1[fn].data().split("\n")
1580 else:
1580 else:
1581 ml = initialmergedlines
1581 ml = initialmergedlines
1582 ml[id * linesperrev] += " r%i" % id
1582 ml[id * linesperrev] += " r%i" % id
1583 mergedtext = "\n".join(ml)
1583 mergedtext = "\n".join(ml)
1584 files.append(fn)
1584 files.append(fn)
1585 fctxs[fn] = context.memfilectx(fn, mergedtext)
1585 fctxs[fn] = context.memfilectx(fn, mergedtext)
1586
1586
1587 if overwritten_file:
1587 if overwritten_file:
1588 fn = "of"
1588 fn = "of"
1589 files.append(fn)
1589 files.append(fn)
1590 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1590 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1591
1591
1592 if new_file:
1592 if new_file:
1593 fn = "nf%i" % id
1593 fn = "nf%i" % id
1594 files.append(fn)
1594 files.append(fn)
1595 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1595 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1596 if len(ps) > 1:
1596 if len(ps) > 1:
1597 if not p2:
1597 if not p2:
1598 p2 = repo[ps[1]]
1598 p2 = repo[ps[1]]
1599 for fn in p2:
1599 for fn in p2:
1600 if fn.startswith("nf"):
1600 if fn.startswith("nf"):
1601 files.append(fn)
1601 files.append(fn)
1602 fctxs[fn] = p2[fn]
1602 fctxs[fn] = p2[fn]
1603
1603
1604 def fctxfn(repo, cx, path):
1604 def fctxfn(repo, cx, path):
1605 return fctxs.get(path)
1605 return fctxs.get(path)
1606
1606
1607 if len(ps) == 0 or ps[0] < 0:
1607 if len(ps) == 0 or ps[0] < 0:
1608 pars = [None, None]
1608 pars = [None, None]
1609 elif len(ps) == 1:
1609 elif len(ps) == 1:
1610 pars = [nodeids[ps[0]], None]
1610 pars = [nodeids[ps[0]], None]
1611 else:
1611 else:
1612 pars = [nodeids[p] for p in ps]
1612 pars = [nodeids[p] for p in ps]
1613 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1613 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1614 date=(id, 0),
1614 date=(id, 0),
1615 user="debugbuilddag",
1615 user="debugbuilddag",
1616 extra={'branch': atbranch})
1616 extra={'branch': atbranch})
1617 nodeid = repo.commitctx(cx)
1617 nodeid = repo.commitctx(cx)
1618 nodeids.append(nodeid)
1618 nodeids.append(nodeid)
1619 at = id
1619 at = id
1620 elif type == 'l':
1620 elif type == 'l':
1621 id, name = data
1621 id, name = data
1622 ui.note(('tag %s\n' % name))
1622 ui.note(('tag %s\n' % name))
1623 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1623 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1624 elif type == 'a':
1624 elif type == 'a':
1625 ui.note(('branch %s\n' % data))
1625 ui.note(('branch %s\n' % data))
1626 atbranch = data
1626 atbranch = data
1627 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1627 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1628 tr.close()
1628 tr.close()
1629
1629
1630 if tags:
1630 if tags:
1631 repo.opener.write("localtags", "".join(tags))
1631 repo.opener.write("localtags", "".join(tags))
1632 finally:
1632 finally:
1633 ui.progress(_('building'), None)
1633 ui.progress(_('building'), None)
1634 release(tr, lock)
1634 release(tr, lock)
1635
1635
1636 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1636 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1637 def debugbundle(ui, bundlepath, all=None, **opts):
1637 def debugbundle(ui, bundlepath, all=None, **opts):
1638 """lists the contents of a bundle"""
1638 """lists the contents of a bundle"""
1639 f = hg.openpath(ui, bundlepath)
1639 f = hg.openpath(ui, bundlepath)
1640 try:
1640 try:
1641 gen = changegroup.readbundle(f, bundlepath)
1641 gen = changegroup.readbundle(f, bundlepath)
1642 if all:
1642 if all:
1643 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1643 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1644
1644
1645 def showchunks(named):
1645 def showchunks(named):
1646 ui.write("\n%s\n" % named)
1646 ui.write("\n%s\n" % named)
1647 chain = None
1647 chain = None
1648 while True:
1648 while True:
1649 chunkdata = gen.deltachunk(chain)
1649 chunkdata = gen.deltachunk(chain)
1650 if not chunkdata:
1650 if not chunkdata:
1651 break
1651 break
1652 node = chunkdata['node']
1652 node = chunkdata['node']
1653 p1 = chunkdata['p1']
1653 p1 = chunkdata['p1']
1654 p2 = chunkdata['p2']
1654 p2 = chunkdata['p2']
1655 cs = chunkdata['cs']
1655 cs = chunkdata['cs']
1656 deltabase = chunkdata['deltabase']
1656 deltabase = chunkdata['deltabase']
1657 delta = chunkdata['delta']
1657 delta = chunkdata['delta']
1658 ui.write("%s %s %s %s %s %s\n" %
1658 ui.write("%s %s %s %s %s %s\n" %
1659 (hex(node), hex(p1), hex(p2),
1659 (hex(node), hex(p1), hex(p2),
1660 hex(cs), hex(deltabase), len(delta)))
1660 hex(cs), hex(deltabase), len(delta)))
1661 chain = node
1661 chain = node
1662
1662
1663 chunkdata = gen.changelogheader()
1663 chunkdata = gen.changelogheader()
1664 showchunks("changelog")
1664 showchunks("changelog")
1665 chunkdata = gen.manifestheader()
1665 chunkdata = gen.manifestheader()
1666 showchunks("manifest")
1666 showchunks("manifest")
1667 while True:
1667 while True:
1668 chunkdata = gen.filelogheader()
1668 chunkdata = gen.filelogheader()
1669 if not chunkdata:
1669 if not chunkdata:
1670 break
1670 break
1671 fname = chunkdata['filename']
1671 fname = chunkdata['filename']
1672 showchunks(fname)
1672 showchunks(fname)
1673 else:
1673 else:
1674 chunkdata = gen.changelogheader()
1674 chunkdata = gen.changelogheader()
1675 chain = None
1675 chain = None
1676 while True:
1676 while True:
1677 chunkdata = gen.deltachunk(chain)
1677 chunkdata = gen.deltachunk(chain)
1678 if not chunkdata:
1678 if not chunkdata:
1679 break
1679 break
1680 node = chunkdata['node']
1680 node = chunkdata['node']
1681 ui.write("%s\n" % hex(node))
1681 ui.write("%s\n" % hex(node))
1682 chain = node
1682 chain = node
1683 finally:
1683 finally:
1684 f.close()
1684 f.close()
1685
1685
1686 @command('debugcheckstate', [], '')
1686 @command('debugcheckstate', [], '')
1687 def debugcheckstate(ui, repo):
1687 def debugcheckstate(ui, repo):
1688 """validate the correctness of the current dirstate"""
1688 """validate the correctness of the current dirstate"""
1689 parent1, parent2 = repo.dirstate.parents()
1689 parent1, parent2 = repo.dirstate.parents()
1690 m1 = repo[parent1].manifest()
1690 m1 = repo[parent1].manifest()
1691 m2 = repo[parent2].manifest()
1691 m2 = repo[parent2].manifest()
1692 errors = 0
1692 errors = 0
1693 for f in repo.dirstate:
1693 for f in repo.dirstate:
1694 state = repo.dirstate[f]
1694 state = repo.dirstate[f]
1695 if state in "nr" and f not in m1:
1695 if state in "nr" and f not in m1:
1696 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1696 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1697 errors += 1
1697 errors += 1
1698 if state in "a" and f in m1:
1698 if state in "a" and f in m1:
1699 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1699 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1700 errors += 1
1700 errors += 1
1701 if state in "m" and f not in m1 and f not in m2:
1701 if state in "m" and f not in m1 and f not in m2:
1702 ui.warn(_("%s in state %s, but not in either manifest\n") %
1702 ui.warn(_("%s in state %s, but not in either manifest\n") %
1703 (f, state))
1703 (f, state))
1704 errors += 1
1704 errors += 1
1705 for f in m1:
1705 for f in m1:
1706 state = repo.dirstate[f]
1706 state = repo.dirstate[f]
1707 if state not in "nrm":
1707 if state not in "nrm":
1708 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1708 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1709 errors += 1
1709 errors += 1
1710 if errors:
1710 if errors:
1711 error = _(".hg/dirstate inconsistent with current parent's manifest")
1711 error = _(".hg/dirstate inconsistent with current parent's manifest")
1712 raise util.Abort(error)
1712 raise util.Abort(error)
1713
1713
1714 @command('debugcommands', [], _('[COMMAND]'))
1714 @command('debugcommands', [], _('[COMMAND]'))
1715 def debugcommands(ui, cmd='', *args):
1715 def debugcommands(ui, cmd='', *args):
1716 """list all available commands and options"""
1716 """list all available commands and options"""
1717 for cmd, vals in sorted(table.iteritems()):
1717 for cmd, vals in sorted(table.iteritems()):
1718 cmd = cmd.split('|')[0].strip('^')
1718 cmd = cmd.split('|')[0].strip('^')
1719 opts = ', '.join([i[1] for i in vals[1]])
1719 opts = ', '.join([i[1] for i in vals[1]])
1720 ui.write('%s: %s\n' % (cmd, opts))
1720 ui.write('%s: %s\n' % (cmd, opts))
1721
1721
1722 @command('debugcomplete',
1722 @command('debugcomplete',
1723 [('o', 'options', None, _('show the command options'))],
1723 [('o', 'options', None, _('show the command options'))],
1724 _('[-o] CMD'))
1724 _('[-o] CMD'))
1725 def debugcomplete(ui, cmd='', **opts):
1725 def debugcomplete(ui, cmd='', **opts):
1726 """returns the completion list associated with the given command"""
1726 """returns the completion list associated with the given command"""
1727
1727
1728 if opts.get('options'):
1728 if opts.get('options'):
1729 options = []
1729 options = []
1730 otables = [globalopts]
1730 otables = [globalopts]
1731 if cmd:
1731 if cmd:
1732 aliases, entry = cmdutil.findcmd(cmd, table, False)
1732 aliases, entry = cmdutil.findcmd(cmd, table, False)
1733 otables.append(entry[1])
1733 otables.append(entry[1])
1734 for t in otables:
1734 for t in otables:
1735 for o in t:
1735 for o in t:
1736 if "(DEPRECATED)" in o[3]:
1736 if "(DEPRECATED)" in o[3]:
1737 continue
1737 continue
1738 if o[0]:
1738 if o[0]:
1739 options.append('-%s' % o[0])
1739 options.append('-%s' % o[0])
1740 options.append('--%s' % o[1])
1740 options.append('--%s' % o[1])
1741 ui.write("%s\n" % "\n".join(options))
1741 ui.write("%s\n" % "\n".join(options))
1742 return
1742 return
1743
1743
1744 cmdlist = cmdutil.findpossible(cmd, table)
1744 cmdlist = cmdutil.findpossible(cmd, table)
1745 if ui.verbose:
1745 if ui.verbose:
1746 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1746 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1747 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1747 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1748
1748
1749 @command('debugdag',
1749 @command('debugdag',
1750 [('t', 'tags', None, _('use tags as labels')),
1750 [('t', 'tags', None, _('use tags as labels')),
1751 ('b', 'branches', None, _('annotate with branch names')),
1751 ('b', 'branches', None, _('annotate with branch names')),
1752 ('', 'dots', None, _('use dots for runs')),
1752 ('', 'dots', None, _('use dots for runs')),
1753 ('s', 'spaces', None, _('separate elements by spaces'))],
1753 ('s', 'spaces', None, _('separate elements by spaces'))],
1754 _('[OPTION]... [FILE [REV]...]'))
1754 _('[OPTION]... [FILE [REV]...]'))
1755 def debugdag(ui, repo, file_=None, *revs, **opts):
1755 def debugdag(ui, repo, file_=None, *revs, **opts):
1756 """format the changelog or an index DAG as a concise textual description
1756 """format the changelog or an index DAG as a concise textual description
1757
1757
1758 If you pass a revlog index, the revlog's DAG is emitted. If you list
1758 If you pass a revlog index, the revlog's DAG is emitted. If you list
1759 revision numbers, they get labeled in the output as rN.
1759 revision numbers, they get labeled in the output as rN.
1760
1760
1761 Otherwise, the changelog DAG of the current repo is emitted.
1761 Otherwise, the changelog DAG of the current repo is emitted.
1762 """
1762 """
1763 spaces = opts.get('spaces')
1763 spaces = opts.get('spaces')
1764 dots = opts.get('dots')
1764 dots = opts.get('dots')
1765 if file_:
1765 if file_:
1766 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1766 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1767 revs = set((int(r) for r in revs))
1767 revs = set((int(r) for r in revs))
1768 def events():
1768 def events():
1769 for r in rlog:
1769 for r in rlog:
1770 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1770 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1771 if p != -1)))
1771 if p != -1)))
1772 if r in revs:
1772 if r in revs:
1773 yield 'l', (r, "r%i" % r)
1773 yield 'l', (r, "r%i" % r)
1774 elif repo:
1774 elif repo:
1775 cl = repo.changelog
1775 cl = repo.changelog
1776 tags = opts.get('tags')
1776 tags = opts.get('tags')
1777 branches = opts.get('branches')
1777 branches = opts.get('branches')
1778 if tags:
1778 if tags:
1779 labels = {}
1779 labels = {}
1780 for l, n in repo.tags().items():
1780 for l, n in repo.tags().items():
1781 labels.setdefault(cl.rev(n), []).append(l)
1781 labels.setdefault(cl.rev(n), []).append(l)
1782 def events():
1782 def events():
1783 b = "default"
1783 b = "default"
1784 for r in cl:
1784 for r in cl:
1785 if branches:
1785 if branches:
1786 newb = cl.read(cl.node(r))[5]['branch']
1786 newb = cl.read(cl.node(r))[5]['branch']
1787 if newb != b:
1787 if newb != b:
1788 yield 'a', newb
1788 yield 'a', newb
1789 b = newb
1789 b = newb
1790 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1790 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1791 if p != -1)))
1791 if p != -1)))
1792 if tags:
1792 if tags:
1793 ls = labels.get(r)
1793 ls = labels.get(r)
1794 if ls:
1794 if ls:
1795 for l in ls:
1795 for l in ls:
1796 yield 'l', (r, l)
1796 yield 'l', (r, l)
1797 else:
1797 else:
1798 raise util.Abort(_('need repo for changelog dag'))
1798 raise util.Abort(_('need repo for changelog dag'))
1799
1799
1800 for line in dagparser.dagtextlines(events(),
1800 for line in dagparser.dagtextlines(events(),
1801 addspaces=spaces,
1801 addspaces=spaces,
1802 wraplabels=True,
1802 wraplabels=True,
1803 wrapannotations=True,
1803 wrapannotations=True,
1804 wrapnonlinear=dots,
1804 wrapnonlinear=dots,
1805 usedots=dots,
1805 usedots=dots,
1806 maxlinewidth=70):
1806 maxlinewidth=70):
1807 ui.write(line)
1807 ui.write(line)
1808 ui.write("\n")
1808 ui.write("\n")
1809
1809
1810 @command('debugdata',
1810 @command('debugdata',
1811 [('c', 'changelog', False, _('open changelog')),
1811 [('c', 'changelog', False, _('open changelog')),
1812 ('m', 'manifest', False, _('open manifest'))],
1812 ('m', 'manifest', False, _('open manifest'))],
1813 _('-c|-m|FILE REV'))
1813 _('-c|-m|FILE REV'))
1814 def debugdata(ui, repo, file_, rev=None, **opts):
1814 def debugdata(ui, repo, file_, rev=None, **opts):
1815 """dump the contents of a data file revision"""
1815 """dump the contents of a data file revision"""
1816 if opts.get('changelog') or opts.get('manifest'):
1816 if opts.get('changelog') or opts.get('manifest'):
1817 file_, rev = None, file_
1817 file_, rev = None, file_
1818 elif rev is None:
1818 elif rev is None:
1819 raise error.CommandError('debugdata', _('invalid arguments'))
1819 raise error.CommandError('debugdata', _('invalid arguments'))
1820 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1820 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1821 try:
1821 try:
1822 ui.write(r.revision(r.lookup(rev)))
1822 ui.write(r.revision(r.lookup(rev)))
1823 except KeyError:
1823 except KeyError:
1824 raise util.Abort(_('invalid revision identifier %s') % rev)
1824 raise util.Abort(_('invalid revision identifier %s') % rev)
1825
1825
1826 @command('debugdate',
1826 @command('debugdate',
1827 [('e', 'extended', None, _('try extended date formats'))],
1827 [('e', 'extended', None, _('try extended date formats'))],
1828 _('[-e] DATE [RANGE]'))
1828 _('[-e] DATE [RANGE]'))
1829 def debugdate(ui, date, range=None, **opts):
1829 def debugdate(ui, date, range=None, **opts):
1830 """parse and display a date"""
1830 """parse and display a date"""
1831 if opts["extended"]:
1831 if opts["extended"]:
1832 d = util.parsedate(date, util.extendeddateformats)
1832 d = util.parsedate(date, util.extendeddateformats)
1833 else:
1833 else:
1834 d = util.parsedate(date)
1834 d = util.parsedate(date)
1835 ui.write(("internal: %s %s\n") % d)
1835 ui.write(("internal: %s %s\n") % d)
1836 ui.write(("standard: %s\n") % util.datestr(d))
1836 ui.write(("standard: %s\n") % util.datestr(d))
1837 if range:
1837 if range:
1838 m = util.matchdate(range)
1838 m = util.matchdate(range)
1839 ui.write(("match: %s\n") % m(d[0]))
1839 ui.write(("match: %s\n") % m(d[0]))
1840
1840
1841 @command('debugdiscovery',
1841 @command('debugdiscovery',
1842 [('', 'old', None, _('use old-style discovery')),
1842 [('', 'old', None, _('use old-style discovery')),
1843 ('', 'nonheads', None,
1843 ('', 'nonheads', None,
1844 _('use old-style discovery with non-heads included')),
1844 _('use old-style discovery with non-heads included')),
1845 ] + remoteopts,
1845 ] + remoteopts,
1846 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1846 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1847 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1847 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1848 """runs the changeset discovery protocol in isolation"""
1848 """runs the changeset discovery protocol in isolation"""
1849 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1849 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1850 opts.get('branch'))
1850 opts.get('branch'))
1851 remote = hg.peer(repo, opts, remoteurl)
1851 remote = hg.peer(repo, opts, remoteurl)
1852 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1852 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1853
1853
1854 # make sure tests are repeatable
1854 # make sure tests are repeatable
1855 random.seed(12323)
1855 random.seed(12323)
1856
1856
1857 def doit(localheads, remoteheads, remote=remote):
1857 def doit(localheads, remoteheads, remote=remote):
1858 if opts.get('old'):
1858 if opts.get('old'):
1859 if localheads:
1859 if localheads:
1860 raise util.Abort('cannot use localheads with old style '
1860 raise util.Abort('cannot use localheads with old style '
1861 'discovery')
1861 'discovery')
1862 if not util.safehasattr(remote, 'branches'):
1862 if not util.safehasattr(remote, 'branches'):
1863 # enable in-client legacy support
1863 # enable in-client legacy support
1864 remote = localrepo.locallegacypeer(remote.local())
1864 remote = localrepo.locallegacypeer(remote.local())
1865 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1865 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1866 force=True)
1866 force=True)
1867 common = set(common)
1867 common = set(common)
1868 if not opts.get('nonheads'):
1868 if not opts.get('nonheads'):
1869 ui.write(("unpruned common: %s\n") %
1869 ui.write(("unpruned common: %s\n") %
1870 " ".join(sorted(short(n) for n in common)))
1870 " ".join(sorted(short(n) for n in common)))
1871 dag = dagutil.revlogdag(repo.changelog)
1871 dag = dagutil.revlogdag(repo.changelog)
1872 all = dag.ancestorset(dag.internalizeall(common))
1872 all = dag.ancestorset(dag.internalizeall(common))
1873 common = dag.externalizeall(dag.headsetofconnecteds(all))
1873 common = dag.externalizeall(dag.headsetofconnecteds(all))
1874 else:
1874 else:
1875 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1875 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1876 common = set(common)
1876 common = set(common)
1877 rheads = set(hds)
1877 rheads = set(hds)
1878 lheads = set(repo.heads())
1878 lheads = set(repo.heads())
1879 ui.write(("common heads: %s\n") %
1879 ui.write(("common heads: %s\n") %
1880 " ".join(sorted(short(n) for n in common)))
1880 " ".join(sorted(short(n) for n in common)))
1881 if lheads <= common:
1881 if lheads <= common:
1882 ui.write(("local is subset\n"))
1882 ui.write(("local is subset\n"))
1883 elif rheads <= common:
1883 elif rheads <= common:
1884 ui.write(("remote is subset\n"))
1884 ui.write(("remote is subset\n"))
1885
1885
1886 serverlogs = opts.get('serverlog')
1886 serverlogs = opts.get('serverlog')
1887 if serverlogs:
1887 if serverlogs:
1888 for filename in serverlogs:
1888 for filename in serverlogs:
1889 logfile = open(filename, 'r')
1889 logfile = open(filename, 'r')
1890 try:
1890 try:
1891 line = logfile.readline()
1891 line = logfile.readline()
1892 while line:
1892 while line:
1893 parts = line.strip().split(';')
1893 parts = line.strip().split(';')
1894 op = parts[1]
1894 op = parts[1]
1895 if op == 'cg':
1895 if op == 'cg':
1896 pass
1896 pass
1897 elif op == 'cgss':
1897 elif op == 'cgss':
1898 doit(parts[2].split(' '), parts[3].split(' '))
1898 doit(parts[2].split(' '), parts[3].split(' '))
1899 elif op == 'unb':
1899 elif op == 'unb':
1900 doit(parts[3].split(' '), parts[2].split(' '))
1900 doit(parts[3].split(' '), parts[2].split(' '))
1901 line = logfile.readline()
1901 line = logfile.readline()
1902 finally:
1902 finally:
1903 logfile.close()
1903 logfile.close()
1904
1904
1905 else:
1905 else:
1906 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1906 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1907 opts.get('remote_head'))
1907 opts.get('remote_head'))
1908 localrevs = opts.get('local_head')
1908 localrevs = opts.get('local_head')
1909 doit(localrevs, remoterevs)
1909 doit(localrevs, remoterevs)
1910
1910
1911 @command('debugfileset',
1911 @command('debugfileset',
1912 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1912 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1913 _('[-r REV] FILESPEC'))
1913 _('[-r REV] FILESPEC'))
1914 def debugfileset(ui, repo, expr, **opts):
1914 def debugfileset(ui, repo, expr, **opts):
1915 '''parse and apply a fileset specification'''
1915 '''parse and apply a fileset specification'''
1916 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1916 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1917 if ui.verbose:
1917 if ui.verbose:
1918 tree = fileset.parse(expr)[0]
1918 tree = fileset.parse(expr)[0]
1919 ui.note(tree, "\n")
1919 ui.note(tree, "\n")
1920
1920
1921 for f in fileset.getfileset(ctx, expr):
1921 for f in fileset.getfileset(ctx, expr):
1922 ui.write("%s\n" % f)
1922 ui.write("%s\n" % f)
1923
1923
1924 @command('debugfsinfo', [], _('[PATH]'))
1924 @command('debugfsinfo', [], _('[PATH]'))
1925 def debugfsinfo(ui, path="."):
1925 def debugfsinfo(ui, path="."):
1926 """show information detected about current filesystem"""
1926 """show information detected about current filesystem"""
1927 util.writefile('.debugfsinfo', '')
1927 util.writefile('.debugfsinfo', '')
1928 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1928 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1929 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1929 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1930 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1930 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1931 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1931 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1932 and 'yes' or 'no'))
1932 and 'yes' or 'no'))
1933 os.unlink('.debugfsinfo')
1933 os.unlink('.debugfsinfo')
1934
1934
1935 @command('debuggetbundle',
1935 @command('debuggetbundle',
1936 [('H', 'head', [], _('id of head node'), _('ID')),
1936 [('H', 'head', [], _('id of head node'), _('ID')),
1937 ('C', 'common', [], _('id of common node'), _('ID')),
1937 ('C', 'common', [], _('id of common node'), _('ID')),
1938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1939 _('REPO FILE [-H|-C ID]...'))
1939 _('REPO FILE [-H|-C ID]...'))
1940 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1940 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1941 """retrieves a bundle from a repo
1941 """retrieves a bundle from a repo
1942
1942
1943 Every ID must be a full-length hex node id string. Saves the bundle to the
1943 Every ID must be a full-length hex node id string. Saves the bundle to the
1944 given file.
1944 given file.
1945 """
1945 """
1946 repo = hg.peer(ui, opts, repopath)
1946 repo = hg.peer(ui, opts, repopath)
1947 if not repo.capable('getbundle'):
1947 if not repo.capable('getbundle'):
1948 raise util.Abort("getbundle() not supported by target repository")
1948 raise util.Abort("getbundle() not supported by target repository")
1949 args = {}
1949 args = {}
1950 if common:
1950 if common:
1951 args['common'] = [bin(s) for s in common]
1951 args['common'] = [bin(s) for s in common]
1952 if head:
1952 if head:
1953 args['heads'] = [bin(s) for s in head]
1953 args['heads'] = [bin(s) for s in head]
1954 # TODO: get desired bundlecaps from command line.
1954 # TODO: get desired bundlecaps from command line.
1955 args['bundlecaps'] = None
1955 args['bundlecaps'] = None
1956 bundle = repo.getbundle('debug', **args)
1956 bundle = repo.getbundle('debug', **args)
1957
1957
1958 bundletype = opts.get('type', 'bzip2').lower()
1958 bundletype = opts.get('type', 'bzip2').lower()
1959 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1959 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1960 bundletype = btypes.get(bundletype)
1960 bundletype = btypes.get(bundletype)
1961 if bundletype not in changegroup.bundletypes:
1961 if bundletype not in changegroup.bundletypes:
1962 raise util.Abort(_('unknown bundle type specified with --type'))
1962 raise util.Abort(_('unknown bundle type specified with --type'))
1963 changegroup.writebundle(bundle, bundlepath, bundletype)
1963 changegroup.writebundle(bundle, bundlepath, bundletype)
1964
1964
1965 @command('debugignore', [], '')
1965 @command('debugignore', [], '')
1966 def debugignore(ui, repo, *values, **opts):
1966 def debugignore(ui, repo, *values, **opts):
1967 """display the combined ignore pattern"""
1967 """display the combined ignore pattern"""
1968 ignore = repo.dirstate._ignore
1968 ignore = repo.dirstate._ignore
1969 includepat = getattr(ignore, 'includepat', None)
1969 includepat = getattr(ignore, 'includepat', None)
1970 if includepat is not None:
1970 if includepat is not None:
1971 ui.write("%s\n" % includepat)
1971 ui.write("%s\n" % includepat)
1972 else:
1972 else:
1973 raise util.Abort(_("no ignore patterns found"))
1973 raise util.Abort(_("no ignore patterns found"))
1974
1974
1975 @command('debugindex',
1975 @command('debugindex',
1976 [('c', 'changelog', False, _('open changelog')),
1976 [('c', 'changelog', False, _('open changelog')),
1977 ('m', 'manifest', False, _('open manifest')),
1977 ('m', 'manifest', False, _('open manifest')),
1978 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1978 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1979 _('[-f FORMAT] -c|-m|FILE'))
1979 _('[-f FORMAT] -c|-m|FILE'))
1980 def debugindex(ui, repo, file_=None, **opts):
1980 def debugindex(ui, repo, file_=None, **opts):
1981 """dump the contents of an index file"""
1981 """dump the contents of an index file"""
1982 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1982 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1983 format = opts.get('format', 0)
1983 format = opts.get('format', 0)
1984 if format not in (0, 1):
1984 if format not in (0, 1):
1985 raise util.Abort(_("unknown format %d") % format)
1985 raise util.Abort(_("unknown format %d") % format)
1986
1986
1987 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1987 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1988 if generaldelta:
1988 if generaldelta:
1989 basehdr = ' delta'
1989 basehdr = ' delta'
1990 else:
1990 else:
1991 basehdr = ' base'
1991 basehdr = ' base'
1992
1992
1993 if format == 0:
1993 if format == 0:
1994 ui.write(" rev offset length " + basehdr + " linkrev"
1994 ui.write(" rev offset length " + basehdr + " linkrev"
1995 " nodeid p1 p2\n")
1995 " nodeid p1 p2\n")
1996 elif format == 1:
1996 elif format == 1:
1997 ui.write(" rev flag offset length"
1997 ui.write(" rev flag offset length"
1998 " size " + basehdr + " link p1 p2"
1998 " size " + basehdr + " link p1 p2"
1999 " nodeid\n")
1999 " nodeid\n")
2000
2000
2001 for i in r:
2001 for i in r:
2002 node = r.node(i)
2002 node = r.node(i)
2003 if generaldelta:
2003 if generaldelta:
2004 base = r.deltaparent(i)
2004 base = r.deltaparent(i)
2005 else:
2005 else:
2006 base = r.chainbase(i)
2006 base = r.chainbase(i)
2007 if format == 0:
2007 if format == 0:
2008 try:
2008 try:
2009 pp = r.parents(node)
2009 pp = r.parents(node)
2010 except Exception:
2010 except Exception:
2011 pp = [nullid, nullid]
2011 pp = [nullid, nullid]
2012 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2012 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2013 i, r.start(i), r.length(i), base, r.linkrev(i),
2013 i, r.start(i), r.length(i), base, r.linkrev(i),
2014 short(node), short(pp[0]), short(pp[1])))
2014 short(node), short(pp[0]), short(pp[1])))
2015 elif format == 1:
2015 elif format == 1:
2016 pr = r.parentrevs(i)
2016 pr = r.parentrevs(i)
2017 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2017 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2018 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2018 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2019 base, r.linkrev(i), pr[0], pr[1], short(node)))
2019 base, r.linkrev(i), pr[0], pr[1], short(node)))
2020
2020
2021 @command('debugindexdot', [], _('FILE'))
2021 @command('debugindexdot', [], _('FILE'))
2022 def debugindexdot(ui, repo, file_):
2022 def debugindexdot(ui, repo, file_):
2023 """dump an index DAG as a graphviz dot file"""
2023 """dump an index DAG as a graphviz dot file"""
2024 r = None
2024 r = None
2025 if repo:
2025 if repo:
2026 filelog = repo.file(file_)
2026 filelog = repo.file(file_)
2027 if len(filelog):
2027 if len(filelog):
2028 r = filelog
2028 r = filelog
2029 if not r:
2029 if not r:
2030 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2030 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2031 ui.write(("digraph G {\n"))
2031 ui.write(("digraph G {\n"))
2032 for i in r:
2032 for i in r:
2033 node = r.node(i)
2033 node = r.node(i)
2034 pp = r.parents(node)
2034 pp = r.parents(node)
2035 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2035 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2036 if pp[1] != nullid:
2036 if pp[1] != nullid:
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2038 ui.write("}\n")
2038 ui.write("}\n")
2039
2039
2040 @command('debuginstall', [], '')
2040 @command('debuginstall', [], '')
2041 def debuginstall(ui):
2041 def debuginstall(ui):
2042 '''test Mercurial installation
2042 '''test Mercurial installation
2043
2043
2044 Returns 0 on success.
2044 Returns 0 on success.
2045 '''
2045 '''
2046
2046
2047 def writetemp(contents):
2047 def writetemp(contents):
2048 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2048 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2049 f = os.fdopen(fd, "wb")
2049 f = os.fdopen(fd, "wb")
2050 f.write(contents)
2050 f.write(contents)
2051 f.close()
2051 f.close()
2052 return name
2052 return name
2053
2053
2054 problems = 0
2054 problems = 0
2055
2055
2056 # encoding
2056 # encoding
2057 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2057 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2058 try:
2058 try:
2059 encoding.fromlocal("test")
2059 encoding.fromlocal("test")
2060 except util.Abort, inst:
2060 except util.Abort, inst:
2061 ui.write(" %s\n" % inst)
2061 ui.write(" %s\n" % inst)
2062 ui.write(_(" (check that your locale is properly set)\n"))
2062 ui.write(_(" (check that your locale is properly set)\n"))
2063 problems += 1
2063 problems += 1
2064
2064
2065 # Python lib
2065 # Python lib
2066 ui.status(_("checking Python lib (%s)...\n")
2066 ui.status(_("checking Python lib (%s)...\n")
2067 % os.path.dirname(os.__file__))
2067 % os.path.dirname(os.__file__))
2068
2068
2069 # compiled modules
2069 # compiled modules
2070 ui.status(_("checking installed modules (%s)...\n")
2070 ui.status(_("checking installed modules (%s)...\n")
2071 % os.path.dirname(__file__))
2071 % os.path.dirname(__file__))
2072 try:
2072 try:
2073 import bdiff, mpatch, base85, osutil
2073 import bdiff, mpatch, base85, osutil
2074 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2074 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2075 except Exception, inst:
2075 except Exception, inst:
2076 ui.write(" %s\n" % inst)
2076 ui.write(" %s\n" % inst)
2077 ui.write(_(" One or more extensions could not be found"))
2077 ui.write(_(" One or more extensions could not be found"))
2078 ui.write(_(" (check that you compiled the extensions)\n"))
2078 ui.write(_(" (check that you compiled the extensions)\n"))
2079 problems += 1
2079 problems += 1
2080
2080
2081 # templates
2081 # templates
2082 import templater
2082 import templater
2083 p = templater.templatepath()
2083 p = templater.templatepath()
2084 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2084 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2085 try:
2085 try:
2086 templater.templater(templater.templatepath("map-cmdline.default"))
2086 templater.templater(templater.templatepath("map-cmdline.default"))
2087 except Exception, inst:
2087 except Exception, inst:
2088 ui.write(" %s\n" % inst)
2088 ui.write(" %s\n" % inst)
2089 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2089 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2090 problems += 1
2090 problems += 1
2091
2091
2092 # editor
2092 # editor
2093 ui.status(_("checking commit editor...\n"))
2093 ui.status(_("checking commit editor...\n"))
2094 editor = ui.geteditor()
2094 editor = ui.geteditor()
2095 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2095 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2096 if not cmdpath:
2096 if not cmdpath:
2097 if editor == 'vi':
2097 if editor == 'vi':
2098 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2098 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2099 ui.write(_(" (specify a commit editor in your configuration"
2099 ui.write(_(" (specify a commit editor in your configuration"
2100 " file)\n"))
2100 " file)\n"))
2101 else:
2101 else:
2102 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2102 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2103 ui.write(_(" (specify a commit editor in your configuration"
2103 ui.write(_(" (specify a commit editor in your configuration"
2104 " file)\n"))
2104 " file)\n"))
2105 problems += 1
2105 problems += 1
2106
2106
2107 # check username
2107 # check username
2108 ui.status(_("checking username...\n"))
2108 ui.status(_("checking username...\n"))
2109 try:
2109 try:
2110 ui.username()
2110 ui.username()
2111 except util.Abort, e:
2111 except util.Abort, e:
2112 ui.write(" %s\n" % e)
2112 ui.write(" %s\n" % e)
2113 ui.write(_(" (specify a username in your configuration file)\n"))
2113 ui.write(_(" (specify a username in your configuration file)\n"))
2114 problems += 1
2114 problems += 1
2115
2115
2116 if not problems:
2116 if not problems:
2117 ui.status(_("no problems detected\n"))
2117 ui.status(_("no problems detected\n"))
2118 else:
2118 else:
2119 ui.write(_("%s problems detected,"
2119 ui.write(_("%s problems detected,"
2120 " please check your install!\n") % problems)
2120 " please check your install!\n") % problems)
2121
2121
2122 return problems
2122 return problems
2123
2123
2124 @command('debugknown', [], _('REPO ID...'))
2124 @command('debugknown', [], _('REPO ID...'))
2125 def debugknown(ui, repopath, *ids, **opts):
2125 def debugknown(ui, repopath, *ids, **opts):
2126 """test whether node ids are known to a repo
2126 """test whether node ids are known to a repo
2127
2127
2128 Every ID must be a full-length hex node id string. Returns a list of 0s
2128 Every ID must be a full-length hex node id string. Returns a list of 0s
2129 and 1s indicating unknown/known.
2129 and 1s indicating unknown/known.
2130 """
2130 """
2131 repo = hg.peer(ui, opts, repopath)
2131 repo = hg.peer(ui, opts, repopath)
2132 if not repo.capable('known'):
2132 if not repo.capable('known'):
2133 raise util.Abort("known() not supported by target repository")
2133 raise util.Abort("known() not supported by target repository")
2134 flags = repo.known([bin(s) for s in ids])
2134 flags = repo.known([bin(s) for s in ids])
2135 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2135 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2136
2136
2137 @command('debuglabelcomplete', [], _('LABEL...'))
2137 @command('debuglabelcomplete', [], _('LABEL...'))
2138 def debuglabelcomplete(ui, repo, *args):
2138 def debuglabelcomplete(ui, repo, *args):
2139 '''complete "labels" - tags, open branch names, bookmark names'''
2139 '''complete "labels" - tags, open branch names, bookmark names'''
2140
2140
2141 labels = set()
2141 labels = set()
2142 labels.update(t[0] for t in repo.tagslist())
2142 labels.update(t[0] for t in repo.tagslist())
2143 labels.update(repo._bookmarks.keys())
2143 labels.update(repo._bookmarks.keys())
2144 labels.update(tag for (tag, heads, tip, closed)
2144 labels.update(tag for (tag, heads, tip, closed)
2145 in repo.branchmap().iterbranches() if not closed)
2145 in repo.branchmap().iterbranches() if not closed)
2146 completions = set()
2146 completions = set()
2147 if not args:
2147 if not args:
2148 args = ['']
2148 args = ['']
2149 for a in args:
2149 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2150 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2151 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2152 ui.write('\n')
2153
2153
2154 @command('debugobsolete',
2154 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2155 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2156 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2159 """create arbitrary obsolete marker
2160
2160
2161 With no arguments, displays the list of obsolescence markers."""
2161 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2162 def parsenodeid(s):
2163 try:
2163 try:
2164 # We do not use revsingle/revrange functions here to accept
2164 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2165 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2166 # local repository.
2167 n = bin(s)
2167 n = bin(s)
2168 if len(n) != len(nullid):
2168 if len(n) != len(nullid):
2169 raise TypeError()
2169 raise TypeError()
2170 return n
2170 return n
2171 except TypeError:
2171 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2172 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2173 'node identifiers')
2174
2174
2175 if precursor is not None:
2175 if precursor is not None:
2176 metadata = {}
2176 metadata = {}
2177 if 'date' in opts:
2177 if 'date' in opts:
2178 metadata['date'] = opts['date']
2178 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2179 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2181 l = repo.lock()
2182 try:
2182 try:
2183 tr = repo.transaction('debugobsolete')
2183 tr = repo.transaction('debugobsolete')
2184 try:
2184 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2186 opts['flags'], metadata)
2187 tr.close()
2187 tr.close()
2188 finally:
2188 finally:
2189 tr.release()
2189 tr.release()
2190 finally:
2190 finally:
2191 l.release()
2191 l.release()
2192 else:
2192 else:
2193 for m in obsolete.allmarkers(repo):
2193 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2194 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2195 for repl in m.succnodes():
2196 ui.write(' ')
2196 ui.write(' ')
2197 ui.write(hex(repl))
2197 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2198 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2200 sorted(m.metadata().items()))))
2201 ui.write('\n')
2201 ui.write('\n')
2202
2202
2203 @command('debugpathcomplete',
2203 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2204 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2205 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2206 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2207 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2208 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2210 '''complete part or all of a tracked path
2211
2211
2212 This command supports shells that offer path name completion. It
2212 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2213 currently completes only files already known to the dirstate.
2214
2214
2215 Completion extends only to the next path segment unless
2215 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2216 --full is specified, in which case entire paths are used.'''
2217
2217
2218 def complete(path, acceptable):
2218 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2219 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2221 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2222 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2223 return [], []
2224 if os.path.isdir(spec):
2224 if os.path.isdir(spec):
2225 spec += '/'
2225 spec += '/'
2226 spec = spec[len(rootdir):]
2226 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2227 fixpaths = os.sep != '/'
2228 if fixpaths:
2228 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2229 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2230 speclen = len(spec)
2231 fullpaths = opts['full']
2231 fullpaths = opts['full']
2232 files, dirs = set(), set()
2232 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2233 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2234 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2235 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2236 if fixpaths:
2237 f = f.replace('/', os.sep)
2237 f = f.replace('/', os.sep)
2238 if fullpaths:
2238 if fullpaths:
2239 addfile(f)
2239 addfile(f)
2240 continue
2240 continue
2241 s = f.find(os.sep, speclen)
2241 s = f.find(os.sep, speclen)
2242 if s >= 0:
2242 if s >= 0:
2243 adddir(f[:s])
2243 adddir(f[:s])
2244 else:
2244 else:
2245 addfile(f)
2245 addfile(f)
2246 return files, dirs
2246 return files, dirs
2247
2247
2248 acceptable = ''
2248 acceptable = ''
2249 if opts['normal']:
2249 if opts['normal']:
2250 acceptable += 'nm'
2250 acceptable += 'nm'
2251 if opts['added']:
2251 if opts['added']:
2252 acceptable += 'a'
2252 acceptable += 'a'
2253 if opts['removed']:
2253 if opts['removed']:
2254 acceptable += 'r'
2254 acceptable += 'r'
2255 cwd = repo.getcwd()
2255 cwd = repo.getcwd()
2256 if not specs:
2256 if not specs:
2257 specs = ['.']
2257 specs = ['.']
2258
2258
2259 files, dirs = set(), set()
2259 files, dirs = set(), set()
2260 for spec in specs:
2260 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2261 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2262 files.update(f)
2263 dirs.update(d)
2263 dirs.update(d)
2264 files.update(dirs)
2264 files.update(dirs)
2265 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2265 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2266 ui.write('\n')
2266 ui.write('\n')
2267
2267
2268 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2268 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2269 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2269 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2270 '''access the pushkey key/value protocol
2270 '''access the pushkey key/value protocol
2271
2271
2272 With two args, list the keys in the given namespace.
2272 With two args, list the keys in the given namespace.
2273
2273
2274 With five args, set a key to new if it currently is set to old.
2274 With five args, set a key to new if it currently is set to old.
2275 Reports success or failure.
2275 Reports success or failure.
2276 '''
2276 '''
2277
2277
2278 target = hg.peer(ui, {}, repopath)
2278 target = hg.peer(ui, {}, repopath)
2279 if keyinfo:
2279 if keyinfo:
2280 key, old, new = keyinfo
2280 key, old, new = keyinfo
2281 r = target.pushkey(namespace, key, old, new)
2281 r = target.pushkey(namespace, key, old, new)
2282 ui.status(str(r) + '\n')
2282 ui.status(str(r) + '\n')
2283 return not r
2283 return not r
2284 else:
2284 else:
2285 for k, v in sorted(target.listkeys(namespace).iteritems()):
2285 for k, v in sorted(target.listkeys(namespace).iteritems()):
2286 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2286 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2287 v.encode('string-escape')))
2287 v.encode('string-escape')))
2288
2288
2289 @command('debugpvec', [], _('A B'))
2289 @command('debugpvec', [], _('A B'))
2290 def debugpvec(ui, repo, a, b=None):
2290 def debugpvec(ui, repo, a, b=None):
2291 ca = scmutil.revsingle(repo, a)
2291 ca = scmutil.revsingle(repo, a)
2292 cb = scmutil.revsingle(repo, b)
2292 cb = scmutil.revsingle(repo, b)
2293 pa = pvec.ctxpvec(ca)
2293 pa = pvec.ctxpvec(ca)
2294 pb = pvec.ctxpvec(cb)
2294 pb = pvec.ctxpvec(cb)
2295 if pa == pb:
2295 if pa == pb:
2296 rel = "="
2296 rel = "="
2297 elif pa > pb:
2297 elif pa > pb:
2298 rel = ">"
2298 rel = ">"
2299 elif pa < pb:
2299 elif pa < pb:
2300 rel = "<"
2300 rel = "<"
2301 elif pa | pb:
2301 elif pa | pb:
2302 rel = "|"
2302 rel = "|"
2303 ui.write(_("a: %s\n") % pa)
2303 ui.write(_("a: %s\n") % pa)
2304 ui.write(_("b: %s\n") % pb)
2304 ui.write(_("b: %s\n") % pb)
2305 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2305 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2306 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2306 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2307 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2307 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2308 pa.distance(pb), rel))
2308 pa.distance(pb), rel))
2309
2309
2310 @command('debugrebuilddirstate|debugrebuildstate',
2310 @command('debugrebuilddirstate|debugrebuildstate',
2311 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2311 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2312 _('[-r REV]'))
2312 _('[-r REV]'))
2313 def debugrebuilddirstate(ui, repo, rev):
2313 def debugrebuilddirstate(ui, repo, rev):
2314 """rebuild the dirstate as it would look like for the given revision
2314 """rebuild the dirstate as it would look like for the given revision
2315
2315
2316 If no revision is specified the first current parent will be used.
2316 If no revision is specified the first current parent will be used.
2317
2317
2318 The dirstate will be set to the files of the given revision.
2318 The dirstate will be set to the files of the given revision.
2319 The actual working directory content or existing dirstate
2319 The actual working directory content or existing dirstate
2320 information such as adds or removes is not considered.
2320 information such as adds or removes is not considered.
2321
2321
2322 One use of this command is to make the next :hg:`status` invocation
2322 One use of this command is to make the next :hg:`status` invocation
2323 check the actual file content.
2323 check the actual file content.
2324 """
2324 """
2325 ctx = scmutil.revsingle(repo, rev)
2325 ctx = scmutil.revsingle(repo, rev)
2326 wlock = repo.wlock()
2326 wlock = repo.wlock()
2327 try:
2327 try:
2328 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2328 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2329 finally:
2329 finally:
2330 wlock.release()
2330 wlock.release()
2331
2331
2332 @command('debugrename',
2332 @command('debugrename',
2333 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2333 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2334 _('[-r REV] FILE'))
2334 _('[-r REV] FILE'))
2335 def debugrename(ui, repo, file1, *pats, **opts):
2335 def debugrename(ui, repo, file1, *pats, **opts):
2336 """dump rename information"""
2336 """dump rename information"""
2337
2337
2338 ctx = scmutil.revsingle(repo, opts.get('rev'))
2338 ctx = scmutil.revsingle(repo, opts.get('rev'))
2339 m = scmutil.match(ctx, (file1,) + pats, opts)
2339 m = scmutil.match(ctx, (file1,) + pats, opts)
2340 for abs in ctx.walk(m):
2340 for abs in ctx.walk(m):
2341 fctx = ctx[abs]
2341 fctx = ctx[abs]
2342 o = fctx.filelog().renamed(fctx.filenode())
2342 o = fctx.filelog().renamed(fctx.filenode())
2343 rel = m.rel(abs)
2343 rel = m.rel(abs)
2344 if o:
2344 if o:
2345 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2345 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2346 else:
2346 else:
2347 ui.write(_("%s not renamed\n") % rel)
2347 ui.write(_("%s not renamed\n") % rel)
2348
2348
2349 @command('debugrevlog',
2349 @command('debugrevlog',
2350 [('c', 'changelog', False, _('open changelog')),
2350 [('c', 'changelog', False, _('open changelog')),
2351 ('m', 'manifest', False, _('open manifest')),
2351 ('m', 'manifest', False, _('open manifest')),
2352 ('d', 'dump', False, _('dump index data'))],
2352 ('d', 'dump', False, _('dump index data'))],
2353 _('-c|-m|FILE'))
2353 _('-c|-m|FILE'))
2354 def debugrevlog(ui, repo, file_=None, **opts):
2354 def debugrevlog(ui, repo, file_=None, **opts):
2355 """show data and statistics about a revlog"""
2355 """show data and statistics about a revlog"""
2356 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2356 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2357
2357
2358 if opts.get("dump"):
2358 if opts.get("dump"):
2359 numrevs = len(r)
2359 numrevs = len(r)
2360 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2360 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2361 " rawsize totalsize compression heads\n")
2361 " rawsize totalsize compression heads\n")
2362 ts = 0
2362 ts = 0
2363 heads = set()
2363 heads = set()
2364 for rev in xrange(numrevs):
2364 for rev in xrange(numrevs):
2365 dbase = r.deltaparent(rev)
2365 dbase = r.deltaparent(rev)
2366 if dbase == -1:
2366 if dbase == -1:
2367 dbase = rev
2367 dbase = rev
2368 cbase = r.chainbase(rev)
2368 cbase = r.chainbase(rev)
2369 p1, p2 = r.parentrevs(rev)
2369 p1, p2 = r.parentrevs(rev)
2370 rs = r.rawsize(rev)
2370 rs = r.rawsize(rev)
2371 ts = ts + rs
2371 ts = ts + rs
2372 heads -= set(r.parentrevs(rev))
2372 heads -= set(r.parentrevs(rev))
2373 heads.add(rev)
2373 heads.add(rev)
2374 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2374 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2375 (rev, p1, p2, r.start(rev), r.end(rev),
2375 (rev, p1, p2, r.start(rev), r.end(rev),
2376 r.start(dbase), r.start(cbase),
2376 r.start(dbase), r.start(cbase),
2377 r.start(p1), r.start(p2),
2377 r.start(p1), r.start(p2),
2378 rs, ts, ts / r.end(rev), len(heads)))
2378 rs, ts, ts / r.end(rev), len(heads)))
2379 return 0
2379 return 0
2380
2380
2381 v = r.version
2381 v = r.version
2382 format = v & 0xFFFF
2382 format = v & 0xFFFF
2383 flags = []
2383 flags = []
2384 gdelta = False
2384 gdelta = False
2385 if v & revlog.REVLOGNGINLINEDATA:
2385 if v & revlog.REVLOGNGINLINEDATA:
2386 flags.append('inline')
2386 flags.append('inline')
2387 if v & revlog.REVLOGGENERALDELTA:
2387 if v & revlog.REVLOGGENERALDELTA:
2388 gdelta = True
2388 gdelta = True
2389 flags.append('generaldelta')
2389 flags.append('generaldelta')
2390 if not flags:
2390 if not flags:
2391 flags = ['(none)']
2391 flags = ['(none)']
2392
2392
2393 nummerges = 0
2393 nummerges = 0
2394 numfull = 0
2394 numfull = 0
2395 numprev = 0
2395 numprev = 0
2396 nump1 = 0
2396 nump1 = 0
2397 nump2 = 0
2397 nump2 = 0
2398 numother = 0
2398 numother = 0
2399 nump1prev = 0
2399 nump1prev = 0
2400 nump2prev = 0
2400 nump2prev = 0
2401 chainlengths = []
2401 chainlengths = []
2402
2402
2403 datasize = [None, 0, 0L]
2403 datasize = [None, 0, 0L]
2404 fullsize = [None, 0, 0L]
2404 fullsize = [None, 0, 0L]
2405 deltasize = [None, 0, 0L]
2405 deltasize = [None, 0, 0L]
2406
2406
2407 def addsize(size, l):
2407 def addsize(size, l):
2408 if l[0] is None or size < l[0]:
2408 if l[0] is None or size < l[0]:
2409 l[0] = size
2409 l[0] = size
2410 if size > l[1]:
2410 if size > l[1]:
2411 l[1] = size
2411 l[1] = size
2412 l[2] += size
2412 l[2] += size
2413
2413
2414 numrevs = len(r)
2414 numrevs = len(r)
2415 for rev in xrange(numrevs):
2415 for rev in xrange(numrevs):
2416 p1, p2 = r.parentrevs(rev)
2416 p1, p2 = r.parentrevs(rev)
2417 delta = r.deltaparent(rev)
2417 delta = r.deltaparent(rev)
2418 if format > 0:
2418 if format > 0:
2419 addsize(r.rawsize(rev), datasize)
2419 addsize(r.rawsize(rev), datasize)
2420 if p2 != nullrev:
2420 if p2 != nullrev:
2421 nummerges += 1
2421 nummerges += 1
2422 size = r.length(rev)
2422 size = r.length(rev)
2423 if delta == nullrev:
2423 if delta == nullrev:
2424 chainlengths.append(0)
2424 chainlengths.append(0)
2425 numfull += 1
2425 numfull += 1
2426 addsize(size, fullsize)
2426 addsize(size, fullsize)
2427 else:
2427 else:
2428 chainlengths.append(chainlengths[delta] + 1)
2428 chainlengths.append(chainlengths[delta] + 1)
2429 addsize(size, deltasize)
2429 addsize(size, deltasize)
2430 if delta == rev - 1:
2430 if delta == rev - 1:
2431 numprev += 1
2431 numprev += 1
2432 if delta == p1:
2432 if delta == p1:
2433 nump1prev += 1
2433 nump1prev += 1
2434 elif delta == p2:
2434 elif delta == p2:
2435 nump2prev += 1
2435 nump2prev += 1
2436 elif delta == p1:
2436 elif delta == p1:
2437 nump1 += 1
2437 nump1 += 1
2438 elif delta == p2:
2438 elif delta == p2:
2439 nump2 += 1
2439 nump2 += 1
2440 elif delta != nullrev:
2440 elif delta != nullrev:
2441 numother += 1
2441 numother += 1
2442
2442
2443 # Adjust size min value for empty cases
2443 # Adjust size min value for empty cases
2444 for size in (datasize, fullsize, deltasize):
2444 for size in (datasize, fullsize, deltasize):
2445 if size[0] is None:
2445 if size[0] is None:
2446 size[0] = 0
2446 size[0] = 0
2447
2447
2448 numdeltas = numrevs - numfull
2448 numdeltas = numrevs - numfull
2449 numoprev = numprev - nump1prev - nump2prev
2449 numoprev = numprev - nump1prev - nump2prev
2450 totalrawsize = datasize[2]
2450 totalrawsize = datasize[2]
2451 datasize[2] /= numrevs
2451 datasize[2] /= numrevs
2452 fulltotal = fullsize[2]
2452 fulltotal = fullsize[2]
2453 fullsize[2] /= numfull
2453 fullsize[2] /= numfull
2454 deltatotal = deltasize[2]
2454 deltatotal = deltasize[2]
2455 if numrevs - numfull > 0:
2455 if numrevs - numfull > 0:
2456 deltasize[2] /= numrevs - numfull
2456 deltasize[2] /= numrevs - numfull
2457 totalsize = fulltotal + deltatotal
2457 totalsize = fulltotal + deltatotal
2458 avgchainlen = sum(chainlengths) / numrevs
2458 avgchainlen = sum(chainlengths) / numrevs
2459 compratio = totalrawsize / totalsize
2459 compratio = totalrawsize / totalsize
2460
2460
2461 basedfmtstr = '%%%dd\n'
2461 basedfmtstr = '%%%dd\n'
2462 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2462 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2463
2463
2464 def dfmtstr(max):
2464 def dfmtstr(max):
2465 return basedfmtstr % len(str(max))
2465 return basedfmtstr % len(str(max))
2466 def pcfmtstr(max, padding=0):
2466 def pcfmtstr(max, padding=0):
2467 return basepcfmtstr % (len(str(max)), ' ' * padding)
2467 return basepcfmtstr % (len(str(max)), ' ' * padding)
2468
2468
2469 def pcfmt(value, total):
2469 def pcfmt(value, total):
2470 return (value, 100 * float(value) / total)
2470 return (value, 100 * float(value) / total)
2471
2471
2472 ui.write(('format : %d\n') % format)
2472 ui.write(('format : %d\n') % format)
2473 ui.write(('flags : %s\n') % ', '.join(flags))
2473 ui.write(('flags : %s\n') % ', '.join(flags))
2474
2474
2475 ui.write('\n')
2475 ui.write('\n')
2476 fmt = pcfmtstr(totalsize)
2476 fmt = pcfmtstr(totalsize)
2477 fmt2 = dfmtstr(totalsize)
2477 fmt2 = dfmtstr(totalsize)
2478 ui.write(('revisions : ') + fmt2 % numrevs)
2478 ui.write(('revisions : ') + fmt2 % numrevs)
2479 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2479 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2480 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2480 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2481 ui.write(('revisions : ') + fmt2 % numrevs)
2481 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2482 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2483 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2483 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2484 ui.write(('revision size : ') + fmt2 % totalsize)
2484 ui.write(('revision size : ') + fmt2 % totalsize)
2485 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2485 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2486 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2486 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2487
2487
2488 ui.write('\n')
2488 ui.write('\n')
2489 fmt = dfmtstr(max(avgchainlen, compratio))
2489 fmt = dfmtstr(max(avgchainlen, compratio))
2490 ui.write(('avg chain length : ') + fmt % avgchainlen)
2490 ui.write(('avg chain length : ') + fmt % avgchainlen)
2491 ui.write(('compression ratio : ') + fmt % compratio)
2491 ui.write(('compression ratio : ') + fmt % compratio)
2492
2492
2493 if format > 0:
2493 if format > 0:
2494 ui.write('\n')
2494 ui.write('\n')
2495 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2495 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2496 % tuple(datasize))
2496 % tuple(datasize))
2497 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2497 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2498 % tuple(fullsize))
2498 % tuple(fullsize))
2499 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2499 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(deltasize))
2500 % tuple(deltasize))
2501
2501
2502 if numdeltas > 0:
2502 if numdeltas > 0:
2503 ui.write('\n')
2503 ui.write('\n')
2504 fmt = pcfmtstr(numdeltas)
2504 fmt = pcfmtstr(numdeltas)
2505 fmt2 = pcfmtstr(numdeltas, 4)
2505 fmt2 = pcfmtstr(numdeltas, 4)
2506 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2506 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2507 if numprev > 0:
2507 if numprev > 0:
2508 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2508 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2509 numprev))
2509 numprev))
2510 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2510 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2511 numprev))
2511 numprev))
2512 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2512 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2513 numprev))
2513 numprev))
2514 if gdelta:
2514 if gdelta:
2515 ui.write(('deltas against p1 : ')
2515 ui.write(('deltas against p1 : ')
2516 + fmt % pcfmt(nump1, numdeltas))
2516 + fmt % pcfmt(nump1, numdeltas))
2517 ui.write(('deltas against p2 : ')
2517 ui.write(('deltas against p2 : ')
2518 + fmt % pcfmt(nump2, numdeltas))
2518 + fmt % pcfmt(nump2, numdeltas))
2519 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2519 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2520 numdeltas))
2520 numdeltas))
2521
2521
2522 @command('debugrevspec', [], ('REVSPEC'))
2522 @command('debugrevspec', [], ('REVSPEC'))
2523 def debugrevspec(ui, repo, expr):
2523 def debugrevspec(ui, repo, expr):
2524 """parse and apply a revision specification
2524 """parse and apply a revision specification
2525
2525
2526 Use --verbose to print the parsed tree before and after aliases
2526 Use --verbose to print the parsed tree before and after aliases
2527 expansion.
2527 expansion.
2528 """
2528 """
2529 if ui.verbose:
2529 if ui.verbose:
2530 tree = revset.parse(expr)[0]
2530 tree = revset.parse(expr)[0]
2531 ui.note(revset.prettyformat(tree), "\n")
2531 ui.note(revset.prettyformat(tree), "\n")
2532 newtree = revset.findaliases(ui, tree)
2532 newtree = revset.findaliases(ui, tree)
2533 if newtree != tree:
2533 if newtree != tree:
2534 ui.note(revset.prettyformat(newtree), "\n")
2534 ui.note(revset.prettyformat(newtree), "\n")
2535 func = revset.match(ui, expr)
2535 func = revset.match(ui, expr)
2536 for c in func(repo, range(len(repo))):
2536 for c in func(repo, range(len(repo))):
2537 ui.write("%s\n" % c)
2537 ui.write("%s\n" % c)
2538
2538
2539 @command('debugsetparents', [], _('REV1 [REV2]'))
2539 @command('debugsetparents', [], _('REV1 [REV2]'))
2540 def debugsetparents(ui, repo, rev1, rev2=None):
2540 def debugsetparents(ui, repo, rev1, rev2=None):
2541 """manually set the parents of the current working directory
2541 """manually set the parents of the current working directory
2542
2542
2543 This is useful for writing repository conversion tools, but should
2543 This is useful for writing repository conversion tools, but should
2544 be used with care.
2544 be used with care.
2545
2545
2546 Returns 0 on success.
2546 Returns 0 on success.
2547 """
2547 """
2548
2548
2549 r1 = scmutil.revsingle(repo, rev1).node()
2549 r1 = scmutil.revsingle(repo, rev1).node()
2550 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2550 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2551
2551
2552 wlock = repo.wlock()
2552 wlock = repo.wlock()
2553 try:
2553 try:
2554 repo.setparents(r1, r2)
2554 repo.setparents(r1, r2)
2555 finally:
2555 finally:
2556 wlock.release()
2556 wlock.release()
2557
2557
2558 @command('debugdirstate|debugstate',
2558 @command('debugdirstate|debugstate',
2559 [('', 'nodates', None, _('do not display the saved mtime')),
2559 [('', 'nodates', None, _('do not display the saved mtime')),
2560 ('', 'datesort', None, _('sort by saved mtime'))],
2560 ('', 'datesort', None, _('sort by saved mtime'))],
2561 _('[OPTION]...'))
2561 _('[OPTION]...'))
2562 def debugstate(ui, repo, nodates=None, datesort=None):
2562 def debugstate(ui, repo, nodates=None, datesort=None):
2563 """show the contents of the current dirstate"""
2563 """show the contents of the current dirstate"""
2564 timestr = ""
2564 timestr = ""
2565 showdate = not nodates
2565 showdate = not nodates
2566 if datesort:
2566 if datesort:
2567 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2567 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2568 else:
2568 else:
2569 keyfunc = None # sort by filename
2569 keyfunc = None # sort by filename
2570 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2570 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2571 if showdate:
2571 if showdate:
2572 if ent[3] == -1:
2572 if ent[3] == -1:
2573 # Pad or slice to locale representation
2573 # Pad or slice to locale representation
2574 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2574 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2575 time.localtime(0)))
2575 time.localtime(0)))
2576 timestr = 'unset'
2576 timestr = 'unset'
2577 timestr = (timestr[:locale_len] +
2577 timestr = (timestr[:locale_len] +
2578 ' ' * (locale_len - len(timestr)))
2578 ' ' * (locale_len - len(timestr)))
2579 else:
2579 else:
2580 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2580 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2581 time.localtime(ent[3]))
2581 time.localtime(ent[3]))
2582 if ent[1] & 020000:
2582 if ent[1] & 020000:
2583 mode = 'lnk'
2583 mode = 'lnk'
2584 else:
2584 else:
2585 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2585 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2586 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2586 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2587 for f in repo.dirstate.copies():
2587 for f in repo.dirstate.copies():
2588 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2588 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2589
2589
2590 @command('debugsub',
2590 @command('debugsub',
2591 [('r', 'rev', '',
2591 [('r', 'rev', '',
2592 _('revision to check'), _('REV'))],
2592 _('revision to check'), _('REV'))],
2593 _('[-r REV] [REV]'))
2593 _('[-r REV] [REV]'))
2594 def debugsub(ui, repo, rev=None):
2594 def debugsub(ui, repo, rev=None):
2595 ctx = scmutil.revsingle(repo, rev, None)
2595 ctx = scmutil.revsingle(repo, rev, None)
2596 for k, v in sorted(ctx.substate.items()):
2596 for k, v in sorted(ctx.substate.items()):
2597 ui.write(('path %s\n') % k)
2597 ui.write(('path %s\n') % k)
2598 ui.write((' source %s\n') % v[0])
2598 ui.write((' source %s\n') % v[0])
2599 ui.write((' revision %s\n') % v[1])
2599 ui.write((' revision %s\n') % v[1])
2600
2600
2601 @command('debugsuccessorssets',
2601 @command('debugsuccessorssets',
2602 [],
2602 [],
2603 _('[REV]'))
2603 _('[REV]'))
2604 def debugsuccessorssets(ui, repo, *revs):
2604 def debugsuccessorssets(ui, repo, *revs):
2605 """show set of successors for revision
2605 """show set of successors for revision
2606
2606
2607 A successors set of changeset A is a consistent group of revisions that
2607 A successors set of changeset A is a consistent group of revisions that
2608 succeed A. It contains non-obsolete changesets only.
2608 succeed A. It contains non-obsolete changesets only.
2609
2609
2610 In most cases a changeset A has a single successors set containing a single
2610 In most cases a changeset A has a single successors set containing a single
2611 successor (changeset A replaced by A').
2611 successor (changeset A replaced by A').
2612
2612
2613 A changeset that is made obsolete with no successors are called "pruned".
2613 A changeset that is made obsolete with no successors are called "pruned".
2614 Such changesets have no successors sets at all.
2614 Such changesets have no successors sets at all.
2615
2615
2616 A changeset that has been "split" will have a successors set containing
2616 A changeset that has been "split" will have a successors set containing
2617 more than one successor.
2617 more than one successor.
2618
2618
2619 A changeset that has been rewritten in multiple different ways is called
2619 A changeset that has been rewritten in multiple different ways is called
2620 "divergent". Such changesets have multiple successor sets (each of which
2620 "divergent". Such changesets have multiple successor sets (each of which
2621 may also be split, i.e. have multiple successors).
2621 may also be split, i.e. have multiple successors).
2622
2622
2623 Results are displayed as follows::
2623 Results are displayed as follows::
2624
2624
2625 <rev1>
2625 <rev1>
2626 <successors-1A>
2626 <successors-1A>
2627 <rev2>
2627 <rev2>
2628 <successors-2A>
2628 <successors-2A>
2629 <successors-2B1> <successors-2B2> <successors-2B3>
2629 <successors-2B1> <successors-2B2> <successors-2B3>
2630
2630
2631 Here rev2 has two possible (i.e. divergent) successors sets. The first
2631 Here rev2 has two possible (i.e. divergent) successors sets. The first
2632 holds one element, whereas the second holds three (i.e. the changeset has
2632 holds one element, whereas the second holds three (i.e. the changeset has
2633 been split).
2633 been split).
2634 """
2634 """
2635 # passed to successorssets caching computation from one call to another
2635 # passed to successorssets caching computation from one call to another
2636 cache = {}
2636 cache = {}
2637 ctx2str = str
2637 ctx2str = str
2638 node2str = short
2638 node2str = short
2639 if ui.debug():
2639 if ui.debug():
2640 def ctx2str(ctx):
2640 def ctx2str(ctx):
2641 return ctx.hex()
2641 return ctx.hex()
2642 node2str = hex
2642 node2str = hex
2643 for rev in scmutil.revrange(repo, revs):
2643 for rev in scmutil.revrange(repo, revs):
2644 ctx = repo[rev]
2644 ctx = repo[rev]
2645 ui.write('%s\n'% ctx2str(ctx))
2645 ui.write('%s\n'% ctx2str(ctx))
2646 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2646 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2647 if succsset:
2647 if succsset:
2648 ui.write(' ')
2648 ui.write(' ')
2649 ui.write(node2str(succsset[0]))
2649 ui.write(node2str(succsset[0]))
2650 for node in succsset[1:]:
2650 for node in succsset[1:]:
2651 ui.write(' ')
2651 ui.write(' ')
2652 ui.write(node2str(node))
2652 ui.write(node2str(node))
2653 ui.write('\n')
2653 ui.write('\n')
2654
2654
2655 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2655 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2656 def debugwalk(ui, repo, *pats, **opts):
2656 def debugwalk(ui, repo, *pats, **opts):
2657 """show how files match on given patterns"""
2657 """show how files match on given patterns"""
2658 m = scmutil.match(repo[None], pats, opts)
2658 m = scmutil.match(repo[None], pats, opts)
2659 items = list(repo.walk(m))
2659 items = list(repo.walk(m))
2660 if not items:
2660 if not items:
2661 return
2661 return
2662 f = lambda fn: fn
2662 f = lambda fn: fn
2663 if ui.configbool('ui', 'slash') and os.sep != '/':
2663 if ui.configbool('ui', 'slash') and os.sep != '/':
2664 f = lambda fn: util.normpath(fn)
2664 f = lambda fn: util.normpath(fn)
2665 fmt = 'f %%-%ds %%-%ds %%s' % (
2665 fmt = 'f %%-%ds %%-%ds %%s' % (
2666 max([len(abs) for abs in items]),
2666 max([len(abs) for abs in items]),
2667 max([len(m.rel(abs)) for abs in items]))
2667 max([len(m.rel(abs)) for abs in items]))
2668 for abs in items:
2668 for abs in items:
2669 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2669 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2670 ui.write("%s\n" % line.rstrip())
2670 ui.write("%s\n" % line.rstrip())
2671
2671
2672 @command('debugwireargs',
2672 @command('debugwireargs',
2673 [('', 'three', '', 'three'),
2673 [('', 'three', '', 'three'),
2674 ('', 'four', '', 'four'),
2674 ('', 'four', '', 'four'),
2675 ('', 'five', '', 'five'),
2675 ('', 'five', '', 'five'),
2676 ] + remoteopts,
2676 ] + remoteopts,
2677 _('REPO [OPTIONS]... [ONE [TWO]]'))
2677 _('REPO [OPTIONS]... [ONE [TWO]]'))
2678 def debugwireargs(ui, repopath, *vals, **opts):
2678 def debugwireargs(ui, repopath, *vals, **opts):
2679 repo = hg.peer(ui, opts, repopath)
2679 repo = hg.peer(ui, opts, repopath)
2680 for opt in remoteopts:
2680 for opt in remoteopts:
2681 del opts[opt[1]]
2681 del opts[opt[1]]
2682 args = {}
2682 args = {}
2683 for k, v in opts.iteritems():
2683 for k, v in opts.iteritems():
2684 if v:
2684 if v:
2685 args[k] = v
2685 args[k] = v
2686 # run twice to check that we don't mess up the stream for the next command
2686 # run twice to check that we don't mess up the stream for the next command
2687 res1 = repo.debugwireargs(*vals, **args)
2687 res1 = repo.debugwireargs(*vals, **args)
2688 res2 = repo.debugwireargs(*vals, **args)
2688 res2 = repo.debugwireargs(*vals, **args)
2689 ui.write("%s\n" % res1)
2689 ui.write("%s\n" % res1)
2690 if res1 != res2:
2690 if res1 != res2:
2691 ui.warn("%s\n" % res2)
2691 ui.warn("%s\n" % res2)
2692
2692
2693 @command('^diff',
2693 @command('^diff',
2694 [('r', 'rev', [], _('revision'), _('REV')),
2694 [('r', 'rev', [], _('revision'), _('REV')),
2695 ('c', 'change', '', _('change made by revision'), _('REV'))
2695 ('c', 'change', '', _('change made by revision'), _('REV'))
2696 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2696 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2697 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2697 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2698 def diff(ui, repo, *pats, **opts):
2698 def diff(ui, repo, *pats, **opts):
2699 """diff repository (or selected files)
2699 """diff repository (or selected files)
2700
2700
2701 Show differences between revisions for the specified files.
2701 Show differences between revisions for the specified files.
2702
2702
2703 Differences between files are shown using the unified diff format.
2703 Differences between files are shown using the unified diff format.
2704
2704
2705 .. note::
2705 .. note::
2706
2706
2707 diff may generate unexpected results for merges, as it will
2707 diff may generate unexpected results for merges, as it will
2708 default to comparing against the working directory's first
2708 default to comparing against the working directory's first
2709 parent changeset if no revisions are specified.
2709 parent changeset if no revisions are specified.
2710
2710
2711 When two revision arguments are given, then changes are shown
2711 When two revision arguments are given, then changes are shown
2712 between those revisions. If only one revision is specified then
2712 between those revisions. If only one revision is specified then
2713 that revision is compared to the working directory, and, when no
2713 that revision is compared to the working directory, and, when no
2714 revisions are specified, the working directory files are compared
2714 revisions are specified, the working directory files are compared
2715 to its parent.
2715 to its parent.
2716
2716
2717 Alternatively you can specify -c/--change with a revision to see
2717 Alternatively you can specify -c/--change with a revision to see
2718 the changes in that changeset relative to its first parent.
2718 the changes in that changeset relative to its first parent.
2719
2719
2720 Without the -a/--text option, diff will avoid generating diffs of
2720 Without the -a/--text option, diff will avoid generating diffs of
2721 files it detects as binary. With -a, diff will generate a diff
2721 files it detects as binary. With -a, diff will generate a diff
2722 anyway, probably with undesirable results.
2722 anyway, probably with undesirable results.
2723
2723
2724 Use the -g/--git option to generate diffs in the git extended diff
2724 Use the -g/--git option to generate diffs in the git extended diff
2725 format. For more information, read :hg:`help diffs`.
2725 format. For more information, read :hg:`help diffs`.
2726
2726
2727 .. container:: verbose
2727 .. container:: verbose
2728
2728
2729 Examples:
2729 Examples:
2730
2730
2731 - compare a file in the current working directory to its parent::
2731 - compare a file in the current working directory to its parent::
2732
2732
2733 hg diff foo.c
2733 hg diff foo.c
2734
2734
2735 - compare two historical versions of a directory, with rename info::
2735 - compare two historical versions of a directory, with rename info::
2736
2736
2737 hg diff --git -r 1.0:1.2 lib/
2737 hg diff --git -r 1.0:1.2 lib/
2738
2738
2739 - get change stats relative to the last change on some date::
2739 - get change stats relative to the last change on some date::
2740
2740
2741 hg diff --stat -r "date('may 2')"
2741 hg diff --stat -r "date('may 2')"
2742
2742
2743 - diff all newly-added files that contain a keyword::
2743 - diff all newly-added files that contain a keyword::
2744
2744
2745 hg diff "set:added() and grep(GNU)"
2745 hg diff "set:added() and grep(GNU)"
2746
2746
2747 - compare a revision and its parents::
2747 - compare a revision and its parents::
2748
2748
2749 hg diff -c 9353 # compare against first parent
2749 hg diff -c 9353 # compare against first parent
2750 hg diff -r 9353^:9353 # same using revset syntax
2750 hg diff -r 9353^:9353 # same using revset syntax
2751 hg diff -r 9353^2:9353 # compare against the second parent
2751 hg diff -r 9353^2:9353 # compare against the second parent
2752
2752
2753 Returns 0 on success.
2753 Returns 0 on success.
2754 """
2754 """
2755
2755
2756 revs = opts.get('rev')
2756 revs = opts.get('rev')
2757 change = opts.get('change')
2757 change = opts.get('change')
2758 stat = opts.get('stat')
2758 stat = opts.get('stat')
2759 reverse = opts.get('reverse')
2759 reverse = opts.get('reverse')
2760
2760
2761 if revs and change:
2761 if revs and change:
2762 msg = _('cannot specify --rev and --change at the same time')
2762 msg = _('cannot specify --rev and --change at the same time')
2763 raise util.Abort(msg)
2763 raise util.Abort(msg)
2764 elif change:
2764 elif change:
2765 node2 = scmutil.revsingle(repo, change, None).node()
2765 node2 = scmutil.revsingle(repo, change, None).node()
2766 node1 = repo[node2].p1().node()
2766 node1 = repo[node2].p1().node()
2767 else:
2767 else:
2768 node1, node2 = scmutil.revpair(repo, revs)
2768 node1, node2 = scmutil.revpair(repo, revs)
2769
2769
2770 if reverse:
2770 if reverse:
2771 node1, node2 = node2, node1
2771 node1, node2 = node2, node1
2772
2772
2773 diffopts = patch.diffopts(ui, opts)
2773 diffopts = patch.diffopts(ui, opts)
2774 m = scmutil.match(repo[node2], pats, opts)
2774 m = scmutil.match(repo[node2], pats, opts)
2775 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2775 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2776 listsubrepos=opts.get('subrepos'))
2776 listsubrepos=opts.get('subrepos'))
2777
2777
2778 @command('^export',
2778 @command('^export',
2779 [('o', 'output', '',
2779 [('o', 'output', '',
2780 _('print output to file with formatted name'), _('FORMAT')),
2780 _('print output to file with formatted name'), _('FORMAT')),
2781 ('', 'switch-parent', None, _('diff against the second parent')),
2781 ('', 'switch-parent', None, _('diff against the second parent')),
2782 ('r', 'rev', [], _('revisions to export'), _('REV')),
2782 ('r', 'rev', [], _('revisions to export'), _('REV')),
2783 ] + diffopts,
2783 ] + diffopts,
2784 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2784 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2785 def export(ui, repo, *changesets, **opts):
2785 def export(ui, repo, *changesets, **opts):
2786 """dump the header and diffs for one or more changesets
2786 """dump the header and diffs for one or more changesets
2787
2787
2788 Print the changeset header and diffs for one or more revisions.
2788 Print the changeset header and diffs for one or more revisions.
2789 If no revision is given, the parent of the working directory is used.
2789 If no revision is given, the parent of the working directory is used.
2790
2790
2791 The information shown in the changeset header is: author, date,
2791 The information shown in the changeset header is: author, date,
2792 branch name (if non-default), changeset hash, parent(s) and commit
2792 branch name (if non-default), changeset hash, parent(s) and commit
2793 comment.
2793 comment.
2794
2794
2795 .. note::
2795 .. note::
2796
2796
2797 export may generate unexpected diff output for merge
2797 export may generate unexpected diff output for merge
2798 changesets, as it will compare the merge changeset against its
2798 changesets, as it will compare the merge changeset against its
2799 first parent only.
2799 first parent only.
2800
2800
2801 Output may be to a file, in which case the name of the file is
2801 Output may be to a file, in which case the name of the file is
2802 given using a format string. The formatting rules are as follows:
2802 given using a format string. The formatting rules are as follows:
2803
2803
2804 :``%%``: literal "%" character
2804 :``%%``: literal "%" character
2805 :``%H``: changeset hash (40 hexadecimal digits)
2805 :``%H``: changeset hash (40 hexadecimal digits)
2806 :``%N``: number of patches being generated
2806 :``%N``: number of patches being generated
2807 :``%R``: changeset revision number
2807 :``%R``: changeset revision number
2808 :``%b``: basename of the exporting repository
2808 :``%b``: basename of the exporting repository
2809 :``%h``: short-form changeset hash (12 hexadecimal digits)
2809 :``%h``: short-form changeset hash (12 hexadecimal digits)
2810 :``%m``: first line of the commit message (only alphanumeric characters)
2810 :``%m``: first line of the commit message (only alphanumeric characters)
2811 :``%n``: zero-padded sequence number, starting at 1
2811 :``%n``: zero-padded sequence number, starting at 1
2812 :``%r``: zero-padded changeset revision number
2812 :``%r``: zero-padded changeset revision number
2813
2813
2814 Without the -a/--text option, export will avoid generating diffs
2814 Without the -a/--text option, export will avoid generating diffs
2815 of files it detects as binary. With -a, export will generate a
2815 of files it detects as binary. With -a, export will generate a
2816 diff anyway, probably with undesirable results.
2816 diff anyway, probably with undesirable results.
2817
2817
2818 Use the -g/--git option to generate diffs in the git extended diff
2818 Use the -g/--git option to generate diffs in the git extended diff
2819 format. See :hg:`help diffs` for more information.
2819 format. See :hg:`help diffs` for more information.
2820
2820
2821 With the --switch-parent option, the diff will be against the
2821 With the --switch-parent option, the diff will be against the
2822 second parent. It can be useful to review a merge.
2822 second parent. It can be useful to review a merge.
2823
2823
2824 .. container:: verbose
2824 .. container:: verbose
2825
2825
2826 Examples:
2826 Examples:
2827
2827
2828 - use export and import to transplant a bugfix to the current
2828 - use export and import to transplant a bugfix to the current
2829 branch::
2829 branch::
2830
2830
2831 hg export -r 9353 | hg import -
2831 hg export -r 9353 | hg import -
2832
2832
2833 - export all the changesets between two revisions to a file with
2833 - export all the changesets between two revisions to a file with
2834 rename information::
2834 rename information::
2835
2835
2836 hg export --git -r 123:150 > changes.txt
2836 hg export --git -r 123:150 > changes.txt
2837
2837
2838 - split outgoing changes into a series of patches with
2838 - split outgoing changes into a series of patches with
2839 descriptive names::
2839 descriptive names::
2840
2840
2841 hg export -r "outgoing()" -o "%n-%m.patch"
2841 hg export -r "outgoing()" -o "%n-%m.patch"
2842
2842
2843 Returns 0 on success.
2843 Returns 0 on success.
2844 """
2844 """
2845 changesets += tuple(opts.get('rev', []))
2845 changesets += tuple(opts.get('rev', []))
2846 if not changesets:
2846 if not changesets:
2847 changesets = ['.']
2847 changesets = ['.']
2848 revs = scmutil.revrange(repo, changesets)
2848 revs = scmutil.revrange(repo, changesets)
2849 if not revs:
2849 if not revs:
2850 raise util.Abort(_("export requires at least one changeset"))
2850 raise util.Abort(_("export requires at least one changeset"))
2851 if len(revs) > 1:
2851 if len(revs) > 1:
2852 ui.note(_('exporting patches:\n'))
2852 ui.note(_('exporting patches:\n'))
2853 else:
2853 else:
2854 ui.note(_('exporting patch:\n'))
2854 ui.note(_('exporting patch:\n'))
2855 cmdutil.export(repo, revs, template=opts.get('output'),
2855 cmdutil.export(repo, revs, template=opts.get('output'),
2856 switch_parent=opts.get('switch_parent'),
2856 switch_parent=opts.get('switch_parent'),
2857 opts=patch.diffopts(ui, opts))
2857 opts=patch.diffopts(ui, opts))
2858
2858
2859 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2859 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2860 def forget(ui, repo, *pats, **opts):
2860 def forget(ui, repo, *pats, **opts):
2861 """forget the specified files on the next commit
2861 """forget the specified files on the next commit
2862
2862
2863 Mark the specified files so they will no longer be tracked
2863 Mark the specified files so they will no longer be tracked
2864 after the next commit.
2864 after the next commit.
2865
2865
2866 This only removes files from the current branch, not from the
2866 This only removes files from the current branch, not from the
2867 entire project history, and it does not delete them from the
2867 entire project history, and it does not delete them from the
2868 working directory.
2868 working directory.
2869
2869
2870 To undo a forget before the next commit, see :hg:`add`.
2870 To undo a forget before the next commit, see :hg:`add`.
2871
2871
2872 .. container:: verbose
2872 .. container:: verbose
2873
2873
2874 Examples:
2874 Examples:
2875
2875
2876 - forget newly-added binary files::
2876 - forget newly-added binary files::
2877
2877
2878 hg forget "set:added() and binary()"
2878 hg forget "set:added() and binary()"
2879
2879
2880 - forget files that would be excluded by .hgignore::
2880 - forget files that would be excluded by .hgignore::
2881
2881
2882 hg forget "set:hgignore()"
2882 hg forget "set:hgignore()"
2883
2883
2884 Returns 0 on success.
2884 Returns 0 on success.
2885 """
2885 """
2886
2886
2887 if not pats:
2887 if not pats:
2888 raise util.Abort(_('no files specified'))
2888 raise util.Abort(_('no files specified'))
2889
2889
2890 m = scmutil.match(repo[None], pats, opts)
2890 m = scmutil.match(repo[None], pats, opts)
2891 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2891 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2892 return rejected and 1 or 0
2892 return rejected and 1 or 0
2893
2893
2894 @command(
2894 @command(
2895 'graft',
2895 'graft',
2896 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2896 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2897 ('c', 'continue', False, _('resume interrupted graft')),
2897 ('c', 'continue', False, _('resume interrupted graft')),
2898 ('e', 'edit', False, _('invoke editor on commit messages')),
2898 ('e', 'edit', False, _('invoke editor on commit messages')),
2899 ('', 'log', None, _('append graft info to log message')),
2899 ('', 'log', None, _('append graft info to log message')),
2900 ('D', 'currentdate', False,
2900 ('D', 'currentdate', False,
2901 _('record the current date as commit date')),
2901 _('record the current date as commit date')),
2902 ('U', 'currentuser', False,
2902 ('U', 'currentuser', False,
2903 _('record the current user as committer'), _('DATE'))]
2903 _('record the current user as committer'), _('DATE'))]
2904 + commitopts2 + mergetoolopts + dryrunopts,
2904 + commitopts2 + mergetoolopts + dryrunopts,
2905 _('[OPTION]... [-r] REV...'))
2905 _('[OPTION]... [-r] REV...'))
2906 def graft(ui, repo, *revs, **opts):
2906 def graft(ui, repo, *revs, **opts):
2907 '''copy changes from other branches onto the current branch
2907 '''copy changes from other branches onto the current branch
2908
2908
2909 This command uses Mercurial's merge logic to copy individual
2909 This command uses Mercurial's merge logic to copy individual
2910 changes from other branches without merging branches in the
2910 changes from other branches without merging branches in the
2911 history graph. This is sometimes known as 'backporting' or
2911 history graph. This is sometimes known as 'backporting' or
2912 'cherry-picking'. By default, graft will copy user, date, and
2912 'cherry-picking'. By default, graft will copy user, date, and
2913 description from the source changesets.
2913 description from the source changesets.
2914
2914
2915 Changesets that are ancestors of the current revision, that have
2915 Changesets that are ancestors of the current revision, that have
2916 already been grafted, or that are merges will be skipped.
2916 already been grafted, or that are merges will be skipped.
2917
2917
2918 If --log is specified, log messages will have a comment appended
2918 If --log is specified, log messages will have a comment appended
2919 of the form::
2919 of the form::
2920
2920
2921 (grafted from CHANGESETHASH)
2921 (grafted from CHANGESETHASH)
2922
2922
2923 If a graft merge results in conflicts, the graft process is
2923 If a graft merge results in conflicts, the graft process is
2924 interrupted so that the current merge can be manually resolved.
2924 interrupted so that the current merge can be manually resolved.
2925 Once all conflicts are addressed, the graft process can be
2925 Once all conflicts are addressed, the graft process can be
2926 continued with the -c/--continue option.
2926 continued with the -c/--continue option.
2927
2927
2928 .. note::
2928 .. note::
2929
2929
2930 The -c/--continue option does not reapply earlier options.
2930 The -c/--continue option does not reapply earlier options.
2931
2931
2932 .. container:: verbose
2932 .. container:: verbose
2933
2933
2934 Examples:
2934 Examples:
2935
2935
2936 - copy a single change to the stable branch and edit its description::
2936 - copy a single change to the stable branch and edit its description::
2937
2937
2938 hg update stable
2938 hg update stable
2939 hg graft --edit 9393
2939 hg graft --edit 9393
2940
2940
2941 - graft a range of changesets with one exception, updating dates::
2941 - graft a range of changesets with one exception, updating dates::
2942
2942
2943 hg graft -D "2085::2093 and not 2091"
2943 hg graft -D "2085::2093 and not 2091"
2944
2944
2945 - continue a graft after resolving conflicts::
2945 - continue a graft after resolving conflicts::
2946
2946
2947 hg graft -c
2947 hg graft -c
2948
2948
2949 - show the source of a grafted changeset::
2949 - show the source of a grafted changeset::
2950
2950
2951 hg log --debug -r .
2951 hg log --debug -r .
2952
2952
2953 Returns 0 on successful completion.
2953 Returns 0 on successful completion.
2954 '''
2954 '''
2955
2955
2956 revs = list(revs)
2956 revs = list(revs)
2957 revs.extend(opts['rev'])
2957 revs.extend(opts['rev'])
2958
2958
2959 if not opts.get('user') and opts.get('currentuser'):
2959 if not opts.get('user') and opts.get('currentuser'):
2960 opts['user'] = ui.username()
2960 opts['user'] = ui.username()
2961 if not opts.get('date') and opts.get('currentdate'):
2961 if not opts.get('date') and opts.get('currentdate'):
2962 opts['date'] = "%d %d" % util.makedate()
2962 opts['date'] = "%d %d" % util.makedate()
2963
2963
2964 editor = None
2964 editor = None
2965 if opts.get('edit'):
2965 if opts.get('edit'):
2966 editor = cmdutil.commitforceeditor
2966 editor = cmdutil.commitforceeditor
2967
2967
2968 cont = False
2968 cont = False
2969 if opts['continue']:
2969 if opts['continue']:
2970 cont = True
2970 cont = True
2971 if revs:
2971 if revs:
2972 raise util.Abort(_("can't specify --continue and revisions"))
2972 raise util.Abort(_("can't specify --continue and revisions"))
2973 # read in unfinished revisions
2973 # read in unfinished revisions
2974 try:
2974 try:
2975 nodes = repo.opener.read('graftstate').splitlines()
2975 nodes = repo.opener.read('graftstate').splitlines()
2976 revs = [repo[node].rev() for node in nodes]
2976 revs = [repo[node].rev() for node in nodes]
2977 except IOError, inst:
2977 except IOError, inst:
2978 if inst.errno != errno.ENOENT:
2978 if inst.errno != errno.ENOENT:
2979 raise
2979 raise
2980 raise util.Abort(_("no graft state found, can't continue"))
2980 raise util.Abort(_("no graft state found, can't continue"))
2981 else:
2981 else:
2982 cmdutil.checkunfinished(repo)
2982 cmdutil.checkunfinished(repo)
2983 cmdutil.bailifchanged(repo)
2983 cmdutil.bailifchanged(repo)
2984 if not revs:
2984 if not revs:
2985 raise util.Abort(_('no revisions specified'))
2985 raise util.Abort(_('no revisions specified'))
2986 revs = scmutil.revrange(repo, revs)
2986 revs = scmutil.revrange(repo, revs)
2987
2987
2988 # check for merges
2988 # check for merges
2989 for rev in repo.revs('%ld and merge()', revs):
2989 for rev in repo.revs('%ld and merge()', revs):
2990 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2990 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 revs.remove(rev)
2991 revs.remove(rev)
2992 if not revs:
2992 if not revs:
2993 return -1
2993 return -1
2994
2994
2995 # check for ancestors of dest branch
2995 # check for ancestors of dest branch
2996 crev = repo['.'].rev()
2996 crev = repo['.'].rev()
2997 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2997 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 # don't mutate while iterating, create a copy
2998 # don't mutate while iterating, create a copy
2999 for rev in list(revs):
2999 for rev in list(revs):
3000 if rev in ancestors:
3000 if rev in ancestors:
3001 ui.warn(_('skipping ancestor revision %s\n') % rev)
3001 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 revs.remove(rev)
3002 revs.remove(rev)
3003 if not revs:
3003 if not revs:
3004 return -1
3004 return -1
3005
3005
3006 # analyze revs for earlier grafts
3006 # analyze revs for earlier grafts
3007 ids = {}
3007 ids = {}
3008 for ctx in repo.set("%ld", revs):
3008 for ctx in repo.set("%ld", revs):
3009 ids[ctx.hex()] = ctx.rev()
3009 ids[ctx.hex()] = ctx.rev()
3010 n = ctx.extra().get('source')
3010 n = ctx.extra().get('source')
3011 if n:
3011 if n:
3012 ids[n] = ctx.rev()
3012 ids[n] = ctx.rev()
3013
3013
3014 # check ancestors for earlier grafts
3014 # check ancestors for earlier grafts
3015 ui.debug('scanning for duplicate grafts\n')
3015 ui.debug('scanning for duplicate grafts\n')
3016
3016
3017 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3017 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 ctx = repo[rev]
3018 ctx = repo[rev]
3019 n = ctx.extra().get('source')
3019 n = ctx.extra().get('source')
3020 if n in ids:
3020 if n in ids:
3021 r = repo[n].rev()
3021 r = repo[n].rev()
3022 if r in revs:
3022 if r in revs:
3023 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3023 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3024 % (r, rev))
3024 % (r, rev))
3025 revs.remove(r)
3025 revs.remove(r)
3026 elif ids[n] in revs:
3026 elif ids[n] in revs:
3027 ui.warn(_('skipping already grafted revision %s '
3027 ui.warn(_('skipping already grafted revision %s '
3028 '(%s also has origin %d)\n') % (ids[n], rev, r))
3028 '(%s also has origin %d)\n') % (ids[n], rev, r))
3029 revs.remove(ids[n])
3029 revs.remove(ids[n])
3030 elif ctx.hex() in ids:
3030 elif ctx.hex() in ids:
3031 r = ids[ctx.hex()]
3031 r = ids[ctx.hex()]
3032 ui.warn(_('skipping already grafted revision %s '
3032 ui.warn(_('skipping already grafted revision %s '
3033 '(was grafted from %d)\n') % (r, rev))
3033 '(was grafted from %d)\n') % (r, rev))
3034 revs.remove(r)
3034 revs.remove(r)
3035 if not revs:
3035 if not revs:
3036 return -1
3036 return -1
3037
3037
3038 wlock = repo.wlock()
3038 wlock = repo.wlock()
3039 try:
3039 try:
3040 current = repo['.']
3040 current = repo['.']
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042
3042
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 if opts.get('dry_run'):
3044 if opts.get('dry_run'):
3045 continue
3045 continue
3046
3046
3047 source = ctx.extra().get('source')
3047 source = ctx.extra().get('source')
3048 if not source:
3048 if not source:
3049 source = ctx.hex()
3049 source = ctx.hex()
3050 extra = {'source': source}
3050 extra = {'source': source}
3051 user = ctx.user()
3051 user = ctx.user()
3052 if opts.get('user'):
3052 if opts.get('user'):
3053 user = opts['user']
3053 user = opts['user']
3054 date = ctx.date()
3054 date = ctx.date()
3055 if opts.get('date'):
3055 if opts.get('date'):
3056 date = opts['date']
3056 date = opts['date']
3057 message = ctx.description()
3057 message = ctx.description()
3058 if opts.get('log'):
3058 if opts.get('log'):
3059 message += '\n(grafted from %s)' % ctx.hex()
3059 message += '\n(grafted from %s)' % ctx.hex()
3060
3060
3061 # we don't merge the first commit when continuing
3061 # we don't merge the first commit when continuing
3062 if not cont:
3062 if not cont:
3063 # perform the graft merge with p1(rev) as 'ancestor'
3063 # perform the graft merge with p1(rev) as 'ancestor'
3064 try:
3064 try:
3065 # ui.forcemerge is an internal variable, do not document
3065 # ui.forcemerge is an internal variable, do not document
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 ctx.p1().node())
3068 ctx.p1().node())
3069 finally:
3069 finally:
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3071 # report any conflicts
3071 # report any conflicts
3072 if stats and stats[3] > 0:
3072 if stats and stats[3] > 0:
3073 # write out state for --continue
3073 # write out state for --continue
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 repo.opener.write('graftstate', ''.join(nodelines))
3075 repo.opener.write('graftstate', ''.join(nodelines))
3076 raise util.Abort(
3076 raise util.Abort(
3077 _("unresolved conflicts, can't continue"),
3077 _("unresolved conflicts, can't continue"),
3078 hint=_('use hg resolve and hg graft --continue'))
3078 hint=_('use hg resolve and hg graft --continue'))
3079 else:
3079 else:
3080 cont = False
3080 cont = False
3081
3081
3082 # drop the second merge parent
3082 # drop the second merge parent
3083 repo.setparents(current.node(), nullid)
3083 repo.setparents(current.node(), nullid)
3084 repo.dirstate.write()
3084 repo.dirstate.write()
3085 # fix up dirstate for copies and renames
3085 # fix up dirstate for copies and renames
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087
3087
3088 # commit
3088 # commit
3089 node = repo.commit(text=message, user=user,
3089 node = repo.commit(text=message, user=user,
3090 date=date, extra=extra, editor=editor)
3090 date=date, extra=extra, editor=editor)
3091 if node is None:
3091 if node is None:
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 else:
3093 else:
3094 current = repo[node]
3094 current = repo[node]
3095 finally:
3095 finally:
3096 wlock.release()
3096 wlock.release()
3097
3097
3098 # remove state when we complete successfully
3098 # remove state when we complete successfully
3099 if not opts.get('dry_run'):
3099 if not opts.get('dry_run'):
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101
3101
3102 return 0
3102 return 0
3103
3103
3104 @command('grep',
3104 @command('grep',
3105 [('0', 'print0', None, _('end fields with NUL')),
3105 [('0', 'print0', None, _('end fields with NUL')),
3106 ('', 'all', None, _('print all revisions that match')),
3106 ('', 'all', None, _('print all revisions that match')),
3107 ('a', 'text', None, _('treat all files as text')),
3107 ('a', 'text', None, _('treat all files as text')),
3108 ('f', 'follow', None,
3108 ('f', 'follow', None,
3109 _('follow changeset history,'
3109 _('follow changeset history,'
3110 ' or file history across copies and renames')),
3110 ' or file history across copies and renames')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('l', 'files-with-matches', None,
3112 ('l', 'files-with-matches', None,
3113 _('print only filenames and revisions that match')),
3113 _('print only filenames and revisions that match')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('r', 'rev', [],
3115 ('r', 'rev', [],
3116 _('only search files changed within revision range'), _('REV')),
3116 _('only search files changed within revision range'), _('REV')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3119 ] + walkopts,
3119 ] + walkopts,
3120 _('[OPTION]... PATTERN [FILE]...'))
3120 _('[OPTION]... PATTERN [FILE]...'))
3121 def grep(ui, repo, pattern, *pats, **opts):
3121 def grep(ui, repo, pattern, *pats, **opts):
3122 """search for a pattern in specified files and revisions
3122 """search for a pattern in specified files and revisions
3123
3123
3124 Search revisions of files for a regular expression.
3124 Search revisions of files for a regular expression.
3125
3125
3126 This command behaves differently than Unix grep. It only accepts
3126 This command behaves differently than Unix grep. It only accepts
3127 Python/Perl regexps. It searches repository history, not the
3127 Python/Perl regexps. It searches repository history, not the
3128 working directory. It always prints the revision number in which a
3128 working directory. It always prints the revision number in which a
3129 match appears.
3129 match appears.
3130
3130
3131 By default, grep only prints output for the first revision of a
3131 By default, grep only prints output for the first revision of a
3132 file in which it finds a match. To get it to print every revision
3132 file in which it finds a match. To get it to print every revision
3133 that contains a change in match status ("-" for a match that
3133 that contains a change in match status ("-" for a match that
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3135 use the --all flag.
3135 use the --all flag.
3136
3136
3137 Returns 0 if a match is found, 1 otherwise.
3137 Returns 0 if a match is found, 1 otherwise.
3138 """
3138 """
3139 reflags = re.M
3139 reflags = re.M
3140 if opts.get('ignore_case'):
3140 if opts.get('ignore_case'):
3141 reflags |= re.I
3141 reflags |= re.I
3142 try:
3142 try:
3143 regexp = util.compilere(pattern, reflags)
3143 regexp = util.compilere(pattern, reflags)
3144 except re.error, inst:
3144 except re.error, inst:
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 return 1
3146 return 1
3147 sep, eol = ':', '\n'
3147 sep, eol = ':', '\n'
3148 if opts.get('print0'):
3148 if opts.get('print0'):
3149 sep = eol = '\0'
3149 sep = eol = '\0'
3150
3150
3151 getfile = util.lrucachefunc(repo.file)
3151 getfile = util.lrucachefunc(repo.file)
3152
3152
3153 def matchlines(body):
3153 def matchlines(body):
3154 begin = 0
3154 begin = 0
3155 linenum = 0
3155 linenum = 0
3156 while begin < len(body):
3156 while begin < len(body):
3157 match = regexp.search(body, begin)
3157 match = regexp.search(body, begin)
3158 if not match:
3158 if not match:
3159 break
3159 break
3160 mstart, mend = match.span()
3160 mstart, mend = match.span()
3161 linenum += body.count('\n', begin, mstart) + 1
3161 linenum += body.count('\n', begin, mstart) + 1
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 lend = begin - 1
3164 lend = begin - 1
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166
3166
3167 class linestate(object):
3167 class linestate(object):
3168 def __init__(self, line, linenum, colstart, colend):
3168 def __init__(self, line, linenum, colstart, colend):
3169 self.line = line
3169 self.line = line
3170 self.linenum = linenum
3170 self.linenum = linenum
3171 self.colstart = colstart
3171 self.colstart = colstart
3172 self.colend = colend
3172 self.colend = colend
3173
3173
3174 def __hash__(self):
3174 def __hash__(self):
3175 return hash((self.linenum, self.line))
3175 return hash((self.linenum, self.line))
3176
3176
3177 def __eq__(self, other):
3177 def __eq__(self, other):
3178 return self.line == other.line
3178 return self.line == other.line
3179
3179
3180 matches = {}
3180 matches = {}
3181 copies = {}
3181 copies = {}
3182 def grepbody(fn, rev, body):
3182 def grepbody(fn, rev, body):
3183 matches[rev].setdefault(fn, [])
3183 matches[rev].setdefault(fn, [])
3184 m = matches[rev][fn]
3184 m = matches[rev][fn]
3185 for lnum, cstart, cend, line in matchlines(body):
3185 for lnum, cstart, cend, line in matchlines(body):
3186 s = linestate(line, lnum, cstart, cend)
3186 s = linestate(line, lnum, cstart, cend)
3187 m.append(s)
3187 m.append(s)
3188
3188
3189 def difflinestates(a, b):
3189 def difflinestates(a, b):
3190 sm = difflib.SequenceMatcher(None, a, b)
3190 sm = difflib.SequenceMatcher(None, a, b)
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 if tag == 'insert':
3192 if tag == 'insert':
3193 for i in xrange(blo, bhi):
3193 for i in xrange(blo, bhi):
3194 yield ('+', b[i])
3194 yield ('+', b[i])
3195 elif tag == 'delete':
3195 elif tag == 'delete':
3196 for i in xrange(alo, ahi):
3196 for i in xrange(alo, ahi):
3197 yield ('-', a[i])
3197 yield ('-', a[i])
3198 elif tag == 'replace':
3198 elif tag == 'replace':
3199 for i in xrange(alo, ahi):
3199 for i in xrange(alo, ahi):
3200 yield ('-', a[i])
3200 yield ('-', a[i])
3201 for i in xrange(blo, bhi):
3201 for i in xrange(blo, bhi):
3202 yield ('+', b[i])
3202 yield ('+', b[i])
3203
3203
3204 def display(fn, ctx, pstates, states):
3204 def display(fn, ctx, pstates, states):
3205 rev = ctx.rev()
3205 rev = ctx.rev()
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3207 found = False
3207 found = False
3208 filerevmatches = {}
3208 filerevmatches = {}
3209 def binary():
3209 def binary():
3210 flog = getfile(fn)
3210 flog = getfile(fn)
3211 return util.binary(flog.read(ctx.filenode(fn)))
3211 return util.binary(flog.read(ctx.filenode(fn)))
3212
3212
3213 if opts.get('all'):
3213 if opts.get('all'):
3214 iter = difflinestates(pstates, states)
3214 iter = difflinestates(pstates, states)
3215 else:
3215 else:
3216 iter = [('', l) for l in states]
3216 iter = [('', l) for l in states]
3217 for change, l in iter:
3217 for change, l in iter:
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 before, match, after = None, None, None
3219 before, match, after = None, None, None
3220
3220
3221 if opts.get('line_number'):
3221 if opts.get('line_number'):
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3223 if opts.get('all'):
3223 if opts.get('all'):
3224 cols.append((change, 'grep.change'))
3224 cols.append((change, 'grep.change'))
3225 if opts.get('user'):
3225 if opts.get('user'):
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 if opts.get('date'):
3227 if opts.get('date'):
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 if opts.get('files_with_matches'):
3229 if opts.get('files_with_matches'):
3230 c = (fn, rev)
3230 c = (fn, rev)
3231 if c in filerevmatches:
3231 if c in filerevmatches:
3232 continue
3232 continue
3233 filerevmatches[c] = 1
3233 filerevmatches[c] = 1
3234 else:
3234 else:
3235 before = l.line[:l.colstart]
3235 before = l.line[:l.colstart]
3236 match = l.line[l.colstart:l.colend]
3236 match = l.line[l.colstart:l.colend]
3237 after = l.line[l.colend:]
3237 after = l.line[l.colend:]
3238 for col, label in cols[:-1]:
3238 for col, label in cols[:-1]:
3239 ui.write(col, label=label)
3239 ui.write(col, label=label)
3240 ui.write(sep, label='grep.sep')
3240 ui.write(sep, label='grep.sep')
3241 ui.write(cols[-1][0], label=cols[-1][1])
3241 ui.write(cols[-1][0], label=cols[-1][1])
3242 if before is not None:
3242 if before is not None:
3243 ui.write(sep, label='grep.sep')
3243 ui.write(sep, label='grep.sep')
3244 if not opts.get('text') and binary():
3244 if not opts.get('text') and binary():
3245 ui.write(" Binary file matches")
3245 ui.write(" Binary file matches")
3246 else:
3246 else:
3247 ui.write(before)
3247 ui.write(before)
3248 ui.write(match, label='grep.match')
3248 ui.write(match, label='grep.match')
3249 ui.write(after)
3249 ui.write(after)
3250 ui.write(eol)
3250 ui.write(eol)
3251 found = True
3251 found = True
3252 return found
3252 return found
3253
3253
3254 skip = {}
3254 skip = {}
3255 revfiles = {}
3255 revfiles = {}
3256 matchfn = scmutil.match(repo[None], pats, opts)
3256 matchfn = scmutil.match(repo[None], pats, opts)
3257 found = False
3257 found = False
3258 follow = opts.get('follow')
3258 follow = opts.get('follow')
3259
3259
3260 def prep(ctx, fns):
3260 def prep(ctx, fns):
3261 rev = ctx.rev()
3261 rev = ctx.rev()
3262 pctx = ctx.p1()
3262 pctx = ctx.p1()
3263 parent = pctx.rev()
3263 parent = pctx.rev()
3264 matches.setdefault(rev, {})
3264 matches.setdefault(rev, {})
3265 matches.setdefault(parent, {})
3265 matches.setdefault(parent, {})
3266 files = revfiles.setdefault(rev, [])
3266 files = revfiles.setdefault(rev, [])
3267 for fn in fns:
3267 for fn in fns:
3268 flog = getfile(fn)
3268 flog = getfile(fn)
3269 try:
3269 try:
3270 fnode = ctx.filenode(fn)
3270 fnode = ctx.filenode(fn)
3271 except error.LookupError:
3271 except error.LookupError:
3272 continue
3272 continue
3273
3273
3274 copied = flog.renamed(fnode)
3274 copied = flog.renamed(fnode)
3275 copy = follow and copied and copied[0]
3275 copy = follow and copied and copied[0]
3276 if copy:
3276 if copy:
3277 copies.setdefault(rev, {})[fn] = copy
3277 copies.setdefault(rev, {})[fn] = copy
3278 if fn in skip:
3278 if fn in skip:
3279 if copy:
3279 if copy:
3280 skip[copy] = True
3280 skip[copy] = True
3281 continue
3281 continue
3282 files.append(fn)
3282 files.append(fn)
3283
3283
3284 if fn not in matches[rev]:
3284 if fn not in matches[rev]:
3285 grepbody(fn, rev, flog.read(fnode))
3285 grepbody(fn, rev, flog.read(fnode))
3286
3286
3287 pfn = copy or fn
3287 pfn = copy or fn
3288 if pfn not in matches[parent]:
3288 if pfn not in matches[parent]:
3289 try:
3289 try:
3290 fnode = pctx.filenode(pfn)
3290 fnode = pctx.filenode(pfn)
3291 grepbody(pfn, parent, flog.read(fnode))
3291 grepbody(pfn, parent, flog.read(fnode))
3292 except error.LookupError:
3292 except error.LookupError:
3293 pass
3293 pass
3294
3294
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 rev = ctx.rev()
3296 rev = ctx.rev()
3297 parent = ctx.p1().rev()
3297 parent = ctx.p1().rev()
3298 for fn in sorted(revfiles.get(rev, [])):
3298 for fn in sorted(revfiles.get(rev, [])):
3299 states = matches[rev][fn]
3299 states = matches[rev][fn]
3300 copy = copies.get(rev, {}).get(fn)
3300 copy = copies.get(rev, {}).get(fn)
3301 if fn in skip:
3301 if fn in skip:
3302 if copy:
3302 if copy:
3303 skip[copy] = True
3303 skip[copy] = True
3304 continue
3304 continue
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 if pstates or states:
3306 if pstates or states:
3307 r = display(fn, ctx, pstates, states)
3307 r = display(fn, ctx, pstates, states)
3308 found = found or r
3308 found = found or r
3309 if r and not opts.get('all'):
3309 if r and not opts.get('all'):
3310 skip[fn] = True
3310 skip[fn] = True
3311 if copy:
3311 if copy:
3312 skip[copy] = True
3312 skip[copy] = True
3313 del matches[rev]
3313 del matches[rev]
3314 del revfiles[rev]
3314 del revfiles[rev]
3315
3315
3316 return not found
3316 return not found
3317
3317
3318 @command('heads',
3318 @command('heads',
3319 [('r', 'rev', '',
3319 [('r', 'rev', '',
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 ('t', 'topo', False, _('show topological heads only')),
3321 ('t', 'topo', False, _('show topological heads only')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ] + templateopts,
3324 ] + templateopts,
3325 _('[-ct] [-r STARTREV] [REV]...'))
3325 _('[-ct] [-r STARTREV] [REV]...'))
3326 def heads(ui, repo, *branchrevs, **opts):
3326 def heads(ui, repo, *branchrevs, **opts):
3327 """show branch heads
3327 """show branch heads
3328
3328
3329 With no arguments, show all open branch heads in the repository.
3329 With no arguments, show all open branch heads in the repository.
3330 Branch heads are changesets that have no descendants on the
3330 Branch heads are changesets that have no descendants on the
3331 same branch. They are where development generally takes place and
3331 same branch. They are where development generally takes place and
3332 are the usual targets for update and merge operations.
3332 are the usual targets for update and merge operations.
3333
3333
3334 If one or more REVs are given, only open branch heads on the
3334 If one or more REVs are given, only open branch heads on the
3335 branches associated with the specified changesets are shown. This
3335 branches associated with the specified changesets are shown. This
3336 means that you can use :hg:`heads .` to see the heads on the
3336 means that you can use :hg:`heads .` to see the heads on the
3337 currently checked-out branch.
3337 currently checked-out branch.
3338
3338
3339 If -c/--closed is specified, also show branch heads marked closed
3339 If -c/--closed is specified, also show branch heads marked closed
3340 (see :hg:`commit --close-branch`).
3340 (see :hg:`commit --close-branch`).
3341
3341
3342 If STARTREV is specified, only those heads that are descendants of
3342 If STARTREV is specified, only those heads that are descendants of
3343 STARTREV will be displayed.
3343 STARTREV will be displayed.
3344
3344
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 topological heads (changesets with no children) will be shown.
3346 topological heads (changesets with no children) will be shown.
3347
3347
3348 Returns 0 if matching heads are found, 1 if not.
3348 Returns 0 if matching heads are found, 1 if not.
3349 """
3349 """
3350
3350
3351 start = None
3351 start = None
3352 if 'rev' in opts:
3352 if 'rev' in opts:
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354
3354
3355 if opts.get('topo'):
3355 if opts.get('topo'):
3356 heads = [repo[h] for h in repo.heads(start)]
3356 heads = [repo[h] for h in repo.heads(start)]
3357 else:
3357 else:
3358 heads = []
3358 heads = []
3359 for branch in repo.branchmap():
3359 for branch in repo.branchmap():
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads = [repo[h] for h in heads]
3361 heads = [repo[h] for h in heads]
3362
3362
3363 if branchrevs:
3363 if branchrevs:
3364 branches = set(repo[br].branch() for br in branchrevs)
3364 branches = set(repo[br].branch() for br in branchrevs)
3365 heads = [h for h in heads if h.branch() in branches]
3365 heads = [h for h in heads if h.branch() in branches]
3366
3366
3367 if opts.get('active') and branchrevs:
3367 if opts.get('active') and branchrevs:
3368 dagheads = repo.heads(start)
3368 dagheads = repo.heads(start)
3369 heads = [h for h in heads if h.node() in dagheads]
3369 heads = [h for h in heads if h.node() in dagheads]
3370
3370
3371 if branchrevs:
3371 if branchrevs:
3372 haveheads = set(h.branch() for h in heads)
3372 haveheads = set(h.branch() for h in heads)
3373 if branches - haveheads:
3373 if branches - haveheads:
3374 headless = ', '.join(b for b in branches - haveheads)
3374 headless = ', '.join(b for b in branches - haveheads)
3375 msg = _('no open branch heads found on branches %s')
3375 msg = _('no open branch heads found on branches %s')
3376 if opts.get('rev'):
3376 if opts.get('rev'):
3377 msg += _(' (started at %s)') % opts['rev']
3377 msg += _(' (started at %s)') % opts['rev']
3378 ui.warn((msg + '\n') % headless)
3378 ui.warn((msg + '\n') % headless)
3379
3379
3380 if not heads:
3380 if not heads:
3381 return 1
3381 return 1
3382
3382
3383 heads = sorted(heads, key=lambda x: -x.rev())
3383 heads = sorted(heads, key=lambda x: -x.rev())
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 for ctx in heads:
3385 for ctx in heads:
3386 displayer.show(ctx)
3386 displayer.show(ctx)
3387 displayer.close()
3387 displayer.close()
3388
3388
3389 @command('help',
3389 @command('help',
3390 [('e', 'extension', None, _('show only help for extensions')),
3390 [('e', 'extension', None, _('show only help for extensions')),
3391 ('c', 'command', None, _('show only help for commands')),
3391 ('c', 'command', None, _('show only help for commands')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ],
3393 ],
3394 _('[-ec] [TOPIC]'))
3394 _('[-ec] [TOPIC]'))
3395 def help_(ui, name=None, **opts):
3395 def help_(ui, name=None, **opts):
3396 """show help for a given topic or a help overview
3396 """show help for a given topic or a help overview
3397
3397
3398 With no arguments, print a list of commands with short help messages.
3398 With no arguments, print a list of commands with short help messages.
3399
3399
3400 Given a topic, extension, or command name, print help for that
3400 Given a topic, extension, or command name, print help for that
3401 topic.
3401 topic.
3402
3402
3403 Returns 0 if successful.
3403 Returns 0 if successful.
3404 """
3404 """
3405
3405
3406 textwidth = min(ui.termwidth(), 80) - 2
3406 textwidth = min(ui.termwidth(), 80) - 2
3407
3407
3408 keep = ui.verbose and ['verbose'] or []
3408 keep = ui.verbose and ['verbose'] or []
3409 text = help.help_(ui, name, **opts)
3409 text = help.help_(ui, name, **opts)
3410
3410
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 if 'verbose' in pruned:
3412 if 'verbose' in pruned:
3413 keep.append('omitted')
3413 keep.append('omitted')
3414 else:
3414 else:
3415 keep.append('notomitted')
3415 keep.append('notomitted')
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 ui.write(formatted)
3417 ui.write(formatted)
3418
3418
3419
3419
3420 @command('identify|id',
3420 @command('identify|id',
3421 [('r', 'rev', '',
3421 [('r', 'rev', '',
3422 _('identify the specified revision'), _('REV')),
3422 _('identify the specified revision'), _('REV')),
3423 ('n', 'num', None, _('show local revision number')),
3423 ('n', 'num', None, _('show local revision number')),
3424 ('i', 'id', None, _('show global revision id')),
3424 ('i', 'id', None, _('show global revision id')),
3425 ('b', 'branch', None, _('show branch')),
3425 ('b', 'branch', None, _('show branch')),
3426 ('t', 'tags', None, _('show tags')),
3426 ('t', 'tags', None, _('show tags')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ] + remoteopts,
3428 ] + remoteopts,
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3430 def identify(ui, repo, source=None, rev=None,
3430 def identify(ui, repo, source=None, rev=None,
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 """identify the working copy or specified revision
3432 """identify the working copy or specified revision
3433
3433
3434 Print a summary identifying the repository state at REV using one or
3434 Print a summary identifying the repository state at REV using one or
3435 two parent hash identifiers, followed by a "+" if the working
3435 two parent hash identifiers, followed by a "+" if the working
3436 directory has uncommitted changes, the branch name (if not default),
3436 directory has uncommitted changes, the branch name (if not default),
3437 a list of tags, and a list of bookmarks.
3437 a list of tags, and a list of bookmarks.
3438
3438
3439 When REV is not given, print a summary of the current state of the
3439 When REV is not given, print a summary of the current state of the
3440 repository.
3440 repository.
3441
3441
3442 Specifying a path to a repository root or Mercurial bundle will
3442 Specifying a path to a repository root or Mercurial bundle will
3443 cause lookup to operate on that repository/bundle.
3443 cause lookup to operate on that repository/bundle.
3444
3444
3445 .. container:: verbose
3445 .. container:: verbose
3446
3446
3447 Examples:
3447 Examples:
3448
3448
3449 - generate a build identifier for the working directory::
3449 - generate a build identifier for the working directory::
3450
3450
3451 hg id --id > build-id.dat
3451 hg id --id > build-id.dat
3452
3452
3453 - find the revision corresponding to a tag::
3453 - find the revision corresponding to a tag::
3454
3454
3455 hg id -n -r 1.3
3455 hg id -n -r 1.3
3456
3456
3457 - check the most recent revision of a remote repository::
3457 - check the most recent revision of a remote repository::
3458
3458
3459 hg id -r tip http://selenic.com/hg/
3459 hg id -r tip http://selenic.com/hg/
3460
3460
3461 Returns 0 if successful.
3461 Returns 0 if successful.
3462 """
3462 """
3463
3463
3464 if not repo and not source:
3464 if not repo and not source:
3465 raise util.Abort(_("there is no Mercurial repository here "
3465 raise util.Abort(_("there is no Mercurial repository here "
3466 "(.hg not found)"))
3466 "(.hg not found)"))
3467
3467
3468 hexfunc = ui.debugflag and hex or short
3468 hexfunc = ui.debugflag and hex or short
3469 default = not (num or id or branch or tags or bookmarks)
3469 default = not (num or id or branch or tags or bookmarks)
3470 output = []
3470 output = []
3471 revs = []
3471 revs = []
3472
3472
3473 if source:
3473 if source:
3474 source, branches = hg.parseurl(ui.expandpath(source))
3474 source, branches = hg.parseurl(ui.expandpath(source))
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 repo = peer.local()
3476 repo = peer.local()
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478
3478
3479 if not repo:
3479 if not repo:
3480 if num or branch or tags:
3480 if num or branch or tags:
3481 raise util.Abort(
3481 raise util.Abort(
3482 _("can't query remote revision number, branch, or tags"))
3482 _("can't query remote revision number, branch, or tags"))
3483 if not rev and revs:
3483 if not rev and revs:
3484 rev = revs[0]
3484 rev = revs[0]
3485 if not rev:
3485 if not rev:
3486 rev = "tip"
3486 rev = "tip"
3487
3487
3488 remoterev = peer.lookup(rev)
3488 remoterev = peer.lookup(rev)
3489 if default or id:
3489 if default or id:
3490 output = [hexfunc(remoterev)]
3490 output = [hexfunc(remoterev)]
3491
3491
3492 def getbms():
3492 def getbms():
3493 bms = []
3493 bms = []
3494
3494
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3496 hexremoterev = hex(remoterev)
3496 hexremoterev = hex(remoterev)
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 if bmr == hexremoterev]
3498 if bmr == hexremoterev]
3499
3499
3500 return sorted(bms)
3500 return sorted(bms)
3501
3501
3502 if bookmarks:
3502 if bookmarks:
3503 output.extend(getbms())
3503 output.extend(getbms())
3504 elif default and not ui.quiet:
3504 elif default and not ui.quiet:
3505 # multiple bookmarks for a single parent separated by '/'
3505 # multiple bookmarks for a single parent separated by '/'
3506 bm = '/'.join(getbms())
3506 bm = '/'.join(getbms())
3507 if bm:
3507 if bm:
3508 output.append(bm)
3508 output.append(bm)
3509 else:
3509 else:
3510 if not rev:
3510 if not rev:
3511 ctx = repo[None]
3511 ctx = repo[None]
3512 parents = ctx.parents()
3512 parents = ctx.parents()
3513 changed = ""
3513 changed = ""
3514 if default or id or num:
3514 if default or id or num:
3515 if (util.any(repo.status())
3515 if (util.any(repo.status())
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 changed = '+'
3517 changed = '+'
3518 if default or id:
3518 if default or id:
3519 output = ["%s%s" %
3519 output = ["%s%s" %
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 if num:
3521 if num:
3522 output.append("%s%s" %
3522 output.append("%s%s" %
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 else:
3524 else:
3525 ctx = scmutil.revsingle(repo, rev)
3525 ctx = scmutil.revsingle(repo, rev)
3526 if default or id:
3526 if default or id:
3527 output = [hexfunc(ctx.node())]
3527 output = [hexfunc(ctx.node())]
3528 if num:
3528 if num:
3529 output.append(str(ctx.rev()))
3529 output.append(str(ctx.rev()))
3530
3530
3531 if default and not ui.quiet:
3531 if default and not ui.quiet:
3532 b = ctx.branch()
3532 b = ctx.branch()
3533 if b != 'default':
3533 if b != 'default':
3534 output.append("(%s)" % b)
3534 output.append("(%s)" % b)
3535
3535
3536 # multiple tags for a single parent separated by '/'
3536 # multiple tags for a single parent separated by '/'
3537 t = '/'.join(ctx.tags())
3537 t = '/'.join(ctx.tags())
3538 if t:
3538 if t:
3539 output.append(t)
3539 output.append(t)
3540
3540
3541 # multiple bookmarks for a single parent separated by '/'
3541 # multiple bookmarks for a single parent separated by '/'
3542 bm = '/'.join(ctx.bookmarks())
3542 bm = '/'.join(ctx.bookmarks())
3543 if bm:
3543 if bm:
3544 output.append(bm)
3544 output.append(bm)
3545 else:
3545 else:
3546 if branch:
3546 if branch:
3547 output.append(ctx.branch())
3547 output.append(ctx.branch())
3548
3548
3549 if tags:
3549 if tags:
3550 output.extend(ctx.tags())
3550 output.extend(ctx.tags())
3551
3551
3552 if bookmarks:
3552 if bookmarks:
3553 output.extend(ctx.bookmarks())
3553 output.extend(ctx.bookmarks())
3554
3554
3555 ui.write("%s\n" % ' '.join(output))
3555 ui.write("%s\n" % ' '.join(output))
3556
3556
3557 @command('import|patch',
3557 @command('import|patch',
3558 [('p', 'strip', 1,
3558 [('p', 'strip', 1,
3559 _('directory strip option for patch. This has the same '
3559 _('directory strip option for patch. This has the same '
3560 'meaning as the corresponding patch option'), _('NUM')),
3560 'meaning as the corresponding patch option'), _('NUM')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('f', 'force', None,
3563 ('f', 'force', None,
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 ('', 'no-commit', None,
3565 ('', 'no-commit', None,
3566 _("don't commit, just update the working directory")),
3566 _("don't commit, just update the working directory")),
3567 ('', 'bypass', None,
3567 ('', 'bypass', None,
3568 _("apply patch without touching the working directory")),
3568 _("apply patch without touching the working directory")),
3569 ('', 'exact', None,
3569 ('', 'exact', None,
3570 _('apply patch to the nodes from which it was generated')),
3570 _('apply patch to the nodes from which it was generated')),
3571 ('', 'import-branch', None,
3571 ('', 'import-branch', None,
3572 _('use any branch information in patch (implied by --exact)'))] +
3572 _('use any branch information in patch (implied by --exact)'))] +
3573 commitopts + commitopts2 + similarityopts,
3573 commitopts + commitopts2 + similarityopts,
3574 _('[OPTION]... PATCH...'))
3574 _('[OPTION]... PATCH...'))
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3576 """import an ordered set of patches
3576 """import an ordered set of patches
3577
3577
3578 Import a list of patches and commit them individually (unless
3578 Import a list of patches and commit them individually (unless
3579 --no-commit is specified).
3579 --no-commit is specified).
3580
3580
3581 Because import first applies changes to the working directory,
3581 Because import first applies changes to the working directory,
3582 import will abort if there are outstanding changes.
3582 import will abort if there are outstanding changes.
3583
3583
3584 You can import a patch straight from a mail message. Even patches
3584 You can import a patch straight from a mail message. Even patches
3585 as attachments work (to use the body part, it must have type
3585 as attachments work (to use the body part, it must have type
3586 text/plain or text/x-patch). From and Subject headers of email
3586 text/plain or text/x-patch). From and Subject headers of email
3587 message are used as default committer and commit message. All
3587 message are used as default committer and commit message. All
3588 text/plain body parts before first diff are added to commit
3588 text/plain body parts before first diff are added to commit
3589 message.
3589 message.
3590
3590
3591 If the imported patch was generated by :hg:`export`, user and
3591 If the imported patch was generated by :hg:`export`, user and
3592 description from patch override values from message headers and
3592 description from patch override values from message headers and
3593 body. Values given on command line with -m/--message and -u/--user
3593 body. Values given on command line with -m/--message and -u/--user
3594 override these.
3594 override these.
3595
3595
3596 If --exact is specified, import will set the working directory to
3596 If --exact is specified, import will set the working directory to
3597 the parent of each patch before applying it, and will abort if the
3597 the parent of each patch before applying it, and will abort if the
3598 resulting changeset has a different ID than the one recorded in
3598 resulting changeset has a different ID than the one recorded in
3599 the patch. This may happen due to character set problems or other
3599 the patch. This may happen due to character set problems or other
3600 deficiencies in the text patch format.
3600 deficiencies in the text patch format.
3601
3601
3602 Use --bypass to apply and commit patches directly to the
3602 Use --bypass to apply and commit patches directly to the
3603 repository, not touching the working directory. Without --exact,
3603 repository, not touching the working directory. Without --exact,
3604 patches will be applied on top of the working directory parent
3604 patches will be applied on top of the working directory parent
3605 revision.
3605 revision.
3606
3606
3607 With -s/--similarity, hg will attempt to discover renames and
3607 With -s/--similarity, hg will attempt to discover renames and
3608 copies in the patch in the same way as :hg:`addremove`.
3608 copies in the patch in the same way as :hg:`addremove`.
3609
3609
3610 To read a patch from standard input, use "-" as the patch name. If
3610 To read a patch from standard input, use "-" as the patch name. If
3611 a URL is specified, the patch will be downloaded from it.
3611 a URL is specified, the patch will be downloaded from it.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3613
3613
3614 .. container:: verbose
3614 .. container:: verbose
3615
3615
3616 Examples:
3616 Examples:
3617
3617
3618 - import a traditional patch from a website and detect renames::
3618 - import a traditional patch from a website and detect renames::
3619
3619
3620 hg import -s 80 http://example.com/bugfix.patch
3620 hg import -s 80 http://example.com/bugfix.patch
3621
3621
3622 - import a changeset from an hgweb server::
3622 - import a changeset from an hgweb server::
3623
3623
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625
3625
3626 - import all the patches in an Unix-style mbox::
3626 - import all the patches in an Unix-style mbox::
3627
3627
3628 hg import incoming-patches.mbox
3628 hg import incoming-patches.mbox
3629
3629
3630 - attempt to exactly restore an exported changeset (not always
3630 - attempt to exactly restore an exported changeset (not always
3631 possible)::
3631 possible)::
3632
3632
3633 hg import --exact proposed-fix.patch
3633 hg import --exact proposed-fix.patch
3634
3634
3635 Returns 0 on success.
3635 Returns 0 on success.
3636 """
3636 """
3637
3637
3638 if not patch1:
3638 if not patch1:
3639 raise util.Abort(_('need at least one patch to import'))
3639 raise util.Abort(_('need at least one patch to import'))
3640
3640
3641 patches = (patch1,) + patches
3641 patches = (patch1,) + patches
3642
3642
3643 date = opts.get('date')
3643 date = opts.get('date')
3644 if date:
3644 if date:
3645 opts['date'] = util.parsedate(date)
3645 opts['date'] = util.parsedate(date)
3646
3646
3647 editor = cmdutil.commiteditor
3647 editor = cmdutil.commiteditor
3648 if opts.get('edit'):
3648 if opts.get('edit'):
3649 editor = cmdutil.commitforceeditor
3649 editor = cmdutil.commitforceeditor
3650
3650
3651 update = not opts.get('bypass')
3651 update = not opts.get('bypass')
3652 if not update and opts.get('no_commit'):
3652 if not update and opts.get('no_commit'):
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 try:
3654 try:
3655 sim = float(opts.get('similarity') or 0)
3655 sim = float(opts.get('similarity') or 0)
3656 except ValueError:
3656 except ValueError:
3657 raise util.Abort(_('similarity must be a number'))
3657 raise util.Abort(_('similarity must be a number'))
3658 if sim < 0 or sim > 100:
3658 if sim < 0 or sim > 100:
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3660 if sim and not update:
3660 if sim and not update:
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3662
3662
3663 if update:
3663 if update:
3664 cmdutil.checkunfinished(repo)
3664 cmdutil.checkunfinished(repo)
3665 if (opts.get('exact') or not opts.get('force')) and update:
3665 if (opts.get('exact') or not opts.get('force')) and update:
3666 cmdutil.bailifchanged(repo)
3666 cmdutil.bailifchanged(repo)
3667
3667
3668 base = opts["base"]
3668 base = opts["base"]
3669 strip = opts["strip"]
3669 strip = opts["strip"]
3670 wlock = lock = tr = None
3670 wlock = lock = tr = None
3671 msgs = []
3671 msgs = []
3672
3672
3673 def tryone(ui, hunk, parents):
3673 def tryone(ui, hunk, parents):
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 patch.extract(ui, hunk)
3675 patch.extract(ui, hunk)
3676
3676
3677 if not tmpname:
3677 if not tmpname:
3678 return (None, None)
3678 return (None, None)
3679 msg = _('applied to working directory')
3679 msg = _('applied to working directory')
3680
3680
3681 try:
3681 try:
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3683 if cmdline_message:
3683 if cmdline_message:
3684 # pickup the cmdline msg
3684 # pickup the cmdline msg
3685 message = cmdline_message
3685 message = cmdline_message
3686 elif message:
3686 elif message:
3687 # pickup the patch msg
3687 # pickup the patch msg
3688 message = message.strip()
3688 message = message.strip()
3689 else:
3689 else:
3690 # launch the editor
3690 # launch the editor
3691 message = None
3691 message = None
3692 ui.debug('message:\n%s\n' % message)
3692 ui.debug('message:\n%s\n' % message)
3693
3693
3694 if len(parents) == 1:
3694 if len(parents) == 1:
3695 parents.append(repo[nullid])
3695 parents.append(repo[nullid])
3696 if opts.get('exact'):
3696 if opts.get('exact'):
3697 if not nodeid or not p1:
3697 if not nodeid or not p1:
3698 raise util.Abort(_('not a Mercurial patch'))
3698 raise util.Abort(_('not a Mercurial patch'))
3699 p1 = repo[p1]
3699 p1 = repo[p1]
3700 p2 = repo[p2 or nullid]
3700 p2 = repo[p2 or nullid]
3701 elif p2:
3701 elif p2:
3702 try:
3702 try:
3703 p1 = repo[p1]
3703 p1 = repo[p1]
3704 p2 = repo[p2]
3704 p2 = repo[p2]
3705 # Without any options, consider p2 only if the
3705 # Without any options, consider p2 only if the
3706 # patch is being applied on top of the recorded
3706 # patch is being applied on top of the recorded
3707 # first parent.
3707 # first parent.
3708 if p1 != parents[0]:
3708 if p1 != parents[0]:
3709 p1 = parents[0]
3709 p1 = parents[0]
3710 p2 = repo[nullid]
3710 p2 = repo[nullid]
3711 except error.RepoError:
3711 except error.RepoError:
3712 p1, p2 = parents
3712 p1, p2 = parents
3713 else:
3713 else:
3714 p1, p2 = parents
3714 p1, p2 = parents
3715
3715
3716 n = None
3716 n = None
3717 if update:
3717 if update:
3718 if p1 != parents[0]:
3718 if p1 != parents[0]:
3719 hg.clean(repo, p1.node())
3719 hg.clean(repo, p1.node())
3720 if p2 != parents[1]:
3720 if p2 != parents[1]:
3721 repo.setparents(p1.node(), p2.node())
3721 repo.setparents(p1.node(), p2.node())
3722
3722
3723 if opts.get('exact') or opts.get('import_branch'):
3723 if opts.get('exact') or opts.get('import_branch'):
3724 repo.dirstate.setbranch(branch or 'default')
3724 repo.dirstate.setbranch(branch or 'default')
3725
3725
3726 files = set()
3726 files = set()
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 eolmode=None, similarity=sim / 100.0)
3728 eolmode=None, similarity=sim / 100.0)
3729 files = list(files)
3729 files = list(files)
3730 if opts.get('no_commit'):
3730 if opts.get('no_commit'):
3731 if message:
3731 if message:
3732 msgs.append(message)
3732 msgs.append(message)
3733 else:
3733 else:
3734 if opts.get('exact') or p2:
3734 if opts.get('exact') or p2:
3735 # If you got here, you either use --force and know what
3735 # If you got here, you either use --force and know what
3736 # you are doing or used --exact or a merge patch while
3736 # you are doing or used --exact or a merge patch while
3737 # being updated to its first parent.
3737 # being updated to its first parent.
3738 m = None
3738 m = None
3739 else:
3739 else:
3740 m = scmutil.matchfiles(repo, files or [])
3740 m = scmutil.matchfiles(repo, files or [])
3741 n = repo.commit(message, opts.get('user') or user,
3741 n = repo.commit(message, opts.get('user') or user,
3742 opts.get('date') or date, match=m,
3742 opts.get('date') or date, match=m,
3743 editor=editor)
3743 editor=editor)
3744 else:
3744 else:
3745 if opts.get('exact') or opts.get('import_branch'):
3745 if opts.get('exact') or opts.get('import_branch'):
3746 branch = branch or 'default'
3746 branch = branch or 'default'
3747 else:
3747 else:
3748 branch = p1.branch()
3748 branch = p1.branch()
3749 store = patch.filestore()
3749 store = patch.filestore()
3750 try:
3750 try:
3751 files = set()
3751 files = set()
3752 try:
3752 try:
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 files, eolmode=None)
3754 files, eolmode=None)
3755 except patch.PatchError, e:
3755 except patch.PatchError, e:
3756 raise util.Abort(str(e))
3756 raise util.Abort(str(e))
3757 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3757 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3758 message,
3758 message,
3759 opts.get('user') or user,
3759 opts.get('user') or user,
3760 opts.get('date') or date,
3760 opts.get('date') or date,
3761 branch, files, store,
3761 branch, files, store,
3762 editor=cmdutil.commiteditor)
3762 editor=cmdutil.commiteditor)
3763 repo.savecommitmessage(memctx.description())
3763 repo.savecommitmessage(memctx.description())
3764 n = memctx.commit()
3764 n = memctx.commit()
3765 finally:
3765 finally:
3766 store.close()
3766 store.close()
3767 if opts.get('exact') and hex(n) != nodeid:
3767 if opts.get('exact') and hex(n) != nodeid:
3768 raise util.Abort(_('patch is damaged or loses information'))
3768 raise util.Abort(_('patch is damaged or loses information'))
3769 if n:
3769 if n:
3770 # i18n: refers to a short changeset id
3770 # i18n: refers to a short changeset id
3771 msg = _('created %s') % short(n)
3771 msg = _('created %s') % short(n)
3772 return (msg, n)
3772 return (msg, n)
3773 finally:
3773 finally:
3774 os.unlink(tmpname)
3774 os.unlink(tmpname)
3775
3775
3776 try:
3776 try:
3777 try:
3777 try:
3778 wlock = repo.wlock()
3778 wlock = repo.wlock()
3779 if not opts.get('no_commit'):
3779 if not opts.get('no_commit'):
3780 lock = repo.lock()
3780 lock = repo.lock()
3781 tr = repo.transaction('import')
3781 tr = repo.transaction('import')
3782 parents = repo.parents()
3782 parents = repo.parents()
3783 for patchurl in patches:
3783 for patchurl in patches:
3784 if patchurl == '-':
3784 if patchurl == '-':
3785 ui.status(_('applying patch from stdin\n'))
3785 ui.status(_('applying patch from stdin\n'))
3786 patchfile = ui.fin
3786 patchfile = ui.fin
3787 patchurl = 'stdin' # for error message
3787 patchurl = 'stdin' # for error message
3788 else:
3788 else:
3789 patchurl = os.path.join(base, patchurl)
3789 patchurl = os.path.join(base, patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3792
3792
3793 haspatch = False
3793 haspatch = False
3794 for hunk in patch.split(patchfile):
3794 for hunk in patch.split(patchfile):
3795 (msg, node) = tryone(ui, hunk, parents)
3795 (msg, node) = tryone(ui, hunk, parents)
3796 if msg:
3796 if msg:
3797 haspatch = True
3797 haspatch = True
3798 ui.note(msg + '\n')
3798 ui.note(msg + '\n')
3799 if update or opts.get('exact'):
3799 if update or opts.get('exact'):
3800 parents = repo.parents()
3800 parents = repo.parents()
3801 else:
3801 else:
3802 parents = [repo[node]]
3802 parents = [repo[node]]
3803
3803
3804 if not haspatch:
3804 if not haspatch:
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3806
3806
3807 if tr:
3807 if tr:
3808 tr.close()
3808 tr.close()
3809 if msgs:
3809 if msgs:
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 except: # re-raises
3811 except: # re-raises
3812 # wlock.release() indirectly calls dirstate.write(): since
3812 # wlock.release() indirectly calls dirstate.write(): since
3813 # we're crashing, we do not want to change the working dir
3813 # we're crashing, we do not want to change the working dir
3814 # parent after all, so make sure it writes nothing
3814 # parent after all, so make sure it writes nothing
3815 repo.dirstate.invalidate()
3815 repo.dirstate.invalidate()
3816 raise
3816 raise
3817 finally:
3817 finally:
3818 if tr:
3818 if tr:
3819 tr.release()
3819 tr.release()
3820 release(lock, wlock)
3820 release(lock, wlock)
3821
3821
3822 @command('incoming|in',
3822 @command('incoming|in',
3823 [('f', 'force', None,
3823 [('f', 'force', None,
3824 _('run even if remote repository is unrelated')),
3824 _('run even if remote repository is unrelated')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3826 ('', 'bundle', '',
3826 ('', 'bundle', '',
3827 _('file to store the bundles into'), _('FILE')),
3827 _('file to store the bundles into'), _('FILE')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('b', 'branch', [],
3830 ('b', 'branch', [],
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3832 ] + logopts + remoteopts + subrepoopts,
3832 ] + logopts + remoteopts + subrepoopts,
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 def incoming(ui, repo, source="default", **opts):
3834 def incoming(ui, repo, source="default", **opts):
3835 """show new changesets found in source
3835 """show new changesets found in source
3836
3836
3837 Show new changesets found in the specified path/URL or the default
3837 Show new changesets found in the specified path/URL or the default
3838 pull location. These are the changesets that would have been pulled
3838 pull location. These are the changesets that would have been pulled
3839 if a pull at the time you issued this command.
3839 if a pull at the time you issued this command.
3840
3840
3841 For remote repository, using --bundle avoids downloading the
3841 For remote repository, using --bundle avoids downloading the
3842 changesets twice if the incoming is followed by a pull.
3842 changesets twice if the incoming is followed by a pull.
3843
3843
3844 See pull for valid source format details.
3844 See pull for valid source format details.
3845
3845
3846 Returns 0 if there are incoming changes, 1 otherwise.
3846 Returns 0 if there are incoming changes, 1 otherwise.
3847 """
3847 """
3848 if opts.get('graph'):
3848 if opts.get('graph'):
3849 cmdutil.checkunsupportedgraphflags([], opts)
3849 cmdutil.checkunsupportedgraphflags([], opts)
3850 def display(other, chlist, displayer):
3850 def display(other, chlist, displayer):
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 graphmod.asciiedges)
3854 graphmod.asciiedges)
3855
3855
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 return 0
3857 return 0
3858
3858
3859 if opts.get('bundle') and opts.get('subrepos'):
3859 if opts.get('bundle') and opts.get('subrepos'):
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861
3861
3862 if opts.get('bookmarks'):
3862 if opts.get('bookmarks'):
3863 source, branches = hg.parseurl(ui.expandpath(source),
3863 source, branches = hg.parseurl(ui.expandpath(source),
3864 opts.get('branch'))
3864 opts.get('branch'))
3865 other = hg.peer(repo, opts, source)
3865 other = hg.peer(repo, opts, source)
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3868 return 0
3868 return 0
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 return bookmarks.diff(ui, repo, other)
3870 return bookmarks.diff(ui, repo, other)
3871
3871
3872 repo._subtoppath = ui.expandpath(source)
3872 repo._subtoppath = ui.expandpath(source)
3873 try:
3873 try:
3874 return hg.incoming(ui, repo, source, opts)
3874 return hg.incoming(ui, repo, source, opts)
3875 finally:
3875 finally:
3876 del repo._subtoppath
3876 del repo._subtoppath
3877
3877
3878
3878
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 def init(ui, dest=".", **opts):
3880 def init(ui, dest=".", **opts):
3881 """create a new repository in the given directory
3881 """create a new repository in the given directory
3882
3882
3883 Initialize a new repository in the given directory. If the given
3883 Initialize a new repository in the given directory. If the given
3884 directory does not exist, it will be created.
3884 directory does not exist, it will be created.
3885
3885
3886 If no directory is given, the current directory is used.
3886 If no directory is given, the current directory is used.
3887
3887
3888 It is possible to specify an ``ssh://`` URL as the destination.
3888 It is possible to specify an ``ssh://`` URL as the destination.
3889 See :hg:`help urls` for more information.
3889 See :hg:`help urls` for more information.
3890
3890
3891 Returns 0 on success.
3891 Returns 0 on success.
3892 """
3892 """
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894
3894
3895 @command('locate',
3895 @command('locate',
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ] + walkopts,
3899 ] + walkopts,
3900 _('[OPTION]... [PATTERN]...'))
3900 _('[OPTION]... [PATTERN]...'))
3901 def locate(ui, repo, *pats, **opts):
3901 def locate(ui, repo, *pats, **opts):
3902 """locate files matching specific patterns
3902 """locate files matching specific patterns
3903
3903
3904 Print files under Mercurial control in the working directory whose
3904 Print files under Mercurial control in the working directory whose
3905 names match the given patterns.
3905 names match the given patterns.
3906
3906
3907 By default, this command searches all directories in the working
3907 By default, this command searches all directories in the working
3908 directory. To search just the current directory and its
3908 directory. To search just the current directory and its
3909 subdirectories, use "--include .".
3909 subdirectories, use "--include .".
3910
3910
3911 If no patterns are given to match, this command prints the names
3911 If no patterns are given to match, this command prints the names
3912 of all files under Mercurial control in the working directory.
3912 of all files under Mercurial control in the working directory.
3913
3913
3914 If you want to feed the output of this command into the "xargs"
3914 If you want to feed the output of this command into the "xargs"
3915 command, use the -0 option to both this command and "xargs". This
3915 command, use the -0 option to both this command and "xargs". This
3916 will avoid the problem of "xargs" treating single filenames that
3916 will avoid the problem of "xargs" treating single filenames that
3917 contain whitespace as multiple filenames.
3917 contain whitespace as multiple filenames.
3918
3918
3919 Returns 0 if a match is found, 1 otherwise.
3919 Returns 0 if a match is found, 1 otherwise.
3920 """
3920 """
3921 end = opts.get('print0') and '\0' or '\n'
3921 end = opts.get('print0') and '\0' or '\n'
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923
3923
3924 ret = 1
3924 ret = 1
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m.bad = lambda x, y: False
3926 m.bad = lambda x, y: False
3927 for abs in repo[rev].walk(m):
3927 for abs in repo[rev].walk(m):
3928 if not rev and abs not in repo.dirstate:
3928 if not rev and abs not in repo.dirstate:
3929 continue
3929 continue
3930 if opts.get('fullpath'):
3930 if opts.get('fullpath'):
3931 ui.write(repo.wjoin(abs), end)
3931 ui.write(repo.wjoin(abs), end)
3932 else:
3932 else:
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ret = 0
3934 ret = 0
3935
3935
3936 return ret
3936 return ret
3937
3937
3938 @command('^log|history',
3938 @command('^log|history',
3939 [('f', 'follow', None,
3939 [('f', 'follow', None,
3940 _('follow changeset history, or file history across copies and renames')),
3940 _('follow changeset history, or file history across copies and renames')),
3941 ('', 'follow-first', None,
3941 ('', 'follow-first', None,
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('C', 'copies', None, _('show copied files')),
3944 ('C', 'copies', None, _('show copied files')),
3945 ('k', 'keyword', [],
3945 ('k', 'keyword', [],
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('', 'only-branch', [],
3951 ('', 'only-branch', [],
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('BRANCH')),
3953 _('BRANCH')),
3954 ('b', 'branch', [],
3954 ('b', 'branch', [],
3955 _('show changesets within the given named branch'), _('BRANCH')),
3955 _('show changesets within the given named branch'), _('BRANCH')),
3956 ('P', 'prune', [],
3956 ('P', 'prune', [],
3957 _('do not display revision or any of its ancestors'), _('REV')),
3957 _('do not display revision or any of its ancestors'), _('REV')),
3958 ] + logopts + walkopts,
3958 ] + logopts + walkopts,
3959 _('[OPTION]... [FILE]'))
3959 _('[OPTION]... [FILE]'))
3960 def log(ui, repo, *pats, **opts):
3960 def log(ui, repo, *pats, **opts):
3961 """show revision history of entire repository or files
3961 """show revision history of entire repository or files
3962
3962
3963 Print the revision history of the specified files or the entire
3963 Print the revision history of the specified files or the entire
3964 project.
3964 project.
3965
3965
3966 If no revision range is specified, the default is ``tip:0`` unless
3966 If no revision range is specified, the default is ``tip:0`` unless
3967 --follow is set, in which case the working directory parent is
3967 --follow is set, in which case the working directory parent is
3968 used as the starting revision.
3968 used as the starting revision.
3969
3969
3970 File history is shown without following rename or copy history of
3970 File history is shown without following rename or copy history of
3971 files. Use -f/--follow with a filename to follow history across
3971 files. Use -f/--follow with a filename to follow history across
3972 renames and copies. --follow without a filename will only show
3972 renames and copies. --follow without a filename will only show
3973 ancestors or descendants of the starting revision.
3973 ancestors or descendants of the starting revision.
3974
3974
3975 By default this command prints revision number and changeset id,
3975 By default this command prints revision number and changeset id,
3976 tags, non-trivial parents, user, date and time, and a summary for
3976 tags, non-trivial parents, user, date and time, and a summary for
3977 each commit. When the -v/--verbose switch is used, the list of
3977 each commit. When the -v/--verbose switch is used, the list of
3978 changed files and full commit message are shown.
3978 changed files and full commit message are shown.
3979
3979
3980 .. note::
3980 .. note::
3981
3981
3982 log -p/--patch may generate unexpected diff output for merge
3982 log -p/--patch may generate unexpected diff output for merge
3983 changesets, as it will only compare the merge changeset against
3983 changesets, as it will only compare the merge changeset against
3984 its first parent. Also, only files different from BOTH parents
3984 its first parent. Also, only files different from BOTH parents
3985 will appear in files:.
3985 will appear in files:.
3986
3986
3987 .. note::
3987 .. note::
3988
3988
3989 for performance reasons, log FILE may omit duplicate changes
3989 for performance reasons, log FILE may omit duplicate changes
3990 made on branches and will not show deletions. To see all
3990 made on branches and will not show deletions. To see all
3991 changes including duplicates and deletions, use the --removed
3991 changes including duplicates and deletions, use the --removed
3992 switch.
3992 switch.
3993
3993
3994 .. container:: verbose
3994 .. container:: verbose
3995
3995
3996 Some examples:
3996 Some examples:
3997
3997
3998 - changesets with full descriptions and file lists::
3998 - changesets with full descriptions and file lists::
3999
3999
4000 hg log -v
4000 hg log -v
4001
4001
4002 - changesets ancestral to the working directory::
4002 - changesets ancestral to the working directory::
4003
4003
4004 hg log -f
4004 hg log -f
4005
4005
4006 - last 10 commits on the current branch::
4006 - last 10 commits on the current branch::
4007
4007
4008 hg log -l 10 -b .
4008 hg log -l 10 -b .
4009
4009
4010 - changesets showing all modifications of a file, including removals::
4010 - changesets showing all modifications of a file, including removals::
4011
4011
4012 hg log --removed file.c
4012 hg log --removed file.c
4013
4013
4014 - all changesets that touch a directory, with diffs, excluding merges::
4014 - all changesets that touch a directory, with diffs, excluding merges::
4015
4015
4016 hg log -Mp lib/
4016 hg log -Mp lib/
4017
4017
4018 - all revision numbers that match a keyword::
4018 - all revision numbers that match a keyword::
4019
4019
4020 hg log -k bug --template "{rev}\\n"
4020 hg log -k bug --template "{rev}\\n"
4021
4021
4022 - check if a given changeset is included is a tagged release::
4022 - check if a given changeset is included is a tagged release::
4023
4023
4024 hg log -r "a21ccf and ancestor(1.9)"
4024 hg log -r "a21ccf and ancestor(1.9)"
4025
4025
4026 - find all changesets by some user in a date range::
4026 - find all changesets by some user in a date range::
4027
4027
4028 hg log -k alice -d "may 2008 to jul 2008"
4028 hg log -k alice -d "may 2008 to jul 2008"
4029
4029
4030 - summary of all changesets after the last tag::
4030 - summary of all changesets after the last tag::
4031
4031
4032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4033
4033
4034 See :hg:`help dates` for a list of formats valid for -d/--date.
4034 See :hg:`help dates` for a list of formats valid for -d/--date.
4035
4035
4036 See :hg:`help revisions` and :hg:`help revsets` for more about
4036 See :hg:`help revisions` and :hg:`help revsets` for more about
4037 specifying revisions.
4037 specifying revisions.
4038
4038
4039 See :hg:`help templates` for more about pre-packaged styles and
4039 See :hg:`help templates` for more about pre-packaged styles and
4040 specifying custom templates.
4040 specifying custom templates.
4041
4041
4042 Returns 0 on success.
4042 Returns 0 on success.
4043 """
4043 """
4044 if opts.get('graph'):
4044 if opts.get('graph'):
4045 return cmdutil.graphlog(ui, repo, *pats, **opts)
4045 return cmdutil.graphlog(ui, repo, *pats, **opts)
4046
4046
4047 matchfn = scmutil.match(repo[None], pats, opts)
4047 matchfn = scmutil.match(repo[None], pats, opts)
4048 limit = cmdutil.loglimit(opts)
4048 limit = cmdutil.loglimit(opts)
4049 count = 0
4049 count = 0
4050
4050
4051 getrenamed, endrev = None, None
4051 getrenamed, endrev = None, None
4052 if opts.get('copies'):
4052 if opts.get('copies'):
4053 if opts.get('rev'):
4053 if opts.get('rev'):
4054 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4054 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4055 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4055 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4056
4056
4057 df = False
4057 df = False
4058 if opts.get("date"):
4058 if opts.get("date"):
4059 df = util.matchdate(opts["date"])
4059 df = util.matchdate(opts["date"])
4060
4060
4061 branches = opts.get('branch', []) + opts.get('only_branch', [])
4061 branches = opts.get('branch', []) + opts.get('only_branch', [])
4062 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4062 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4063
4063
4064 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4064 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4065 def prep(ctx, fns):
4065 def prep(ctx, fns):
4066 rev = ctx.rev()
4066 rev = ctx.rev()
4067 parents = [p for p in repo.changelog.parentrevs(rev)
4067 parents = [p for p in repo.changelog.parentrevs(rev)
4068 if p != nullrev]
4068 if p != nullrev]
4069 if opts.get('no_merges') and len(parents) == 2:
4069 if opts.get('no_merges') and len(parents) == 2:
4070 return
4070 return
4071 if opts.get('only_merges') and len(parents) != 2:
4071 if opts.get('only_merges') and len(parents) != 2:
4072 return
4072 return
4073 if opts.get('branch') and ctx.branch() not in opts['branch']:
4073 if opts.get('branch') and ctx.branch() not in opts['branch']:
4074 return
4074 return
4075 if df and not df(ctx.date()[0]):
4075 if df and not df(ctx.date()[0]):
4076 return
4076 return
4077
4077
4078 lower = encoding.lower
4078 lower = encoding.lower
4079 if opts.get('user'):
4079 if opts.get('user'):
4080 luser = lower(ctx.user())
4080 luser = lower(ctx.user())
4081 for k in [lower(x) for x in opts['user']]:
4081 for k in [lower(x) for x in opts['user']]:
4082 if (k in luser):
4082 if (k in luser):
4083 break
4083 break
4084 else:
4084 else:
4085 return
4085 return
4086 if opts.get('keyword'):
4086 if opts.get('keyword'):
4087 luser = lower(ctx.user())
4087 luser = lower(ctx.user())
4088 ldesc = lower(ctx.description())
4088 ldesc = lower(ctx.description())
4089 lfiles = lower(" ".join(ctx.files()))
4089 lfiles = lower(" ".join(ctx.files()))
4090 for k in [lower(x) for x in opts['keyword']]:
4090 for k in [lower(x) for x in opts['keyword']]:
4091 if (k in luser or k in ldesc or k in lfiles):
4091 if (k in luser or k in ldesc or k in lfiles):
4092 break
4092 break
4093 else:
4093 else:
4094 return
4094 return
4095
4095
4096 copies = None
4096 copies = None
4097 if getrenamed is not None and rev:
4097 if getrenamed is not None and rev:
4098 copies = []
4098 copies = []
4099 for fn in ctx.files():
4099 for fn in ctx.files():
4100 rename = getrenamed(fn, rev)
4100 rename = getrenamed(fn, rev)
4101 if rename:
4101 if rename:
4102 copies.append((fn, rename[0]))
4102 copies.append((fn, rename[0]))
4103
4103
4104 revmatchfn = None
4104 revmatchfn = None
4105 if opts.get('patch') or opts.get('stat'):
4105 if opts.get('patch') or opts.get('stat'):
4106 if opts.get('follow') or opts.get('follow_first'):
4106 if opts.get('follow') or opts.get('follow_first'):
4107 # note: this might be wrong when following through merges
4107 # note: this might be wrong when following through merges
4108 revmatchfn = scmutil.match(repo[None], fns, default='path')
4108 revmatchfn = scmutil.match(repo[None], fns, default='path')
4109 else:
4109 else:
4110 revmatchfn = matchfn
4110 revmatchfn = matchfn
4111
4111
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4113
4113
4114 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4114 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4115 if displayer.flush(ctx.rev()):
4115 if displayer.flush(ctx.rev()):
4116 count += 1
4116 count += 1
4117 if count == limit:
4117 if count == limit:
4118 break
4118 break
4119 displayer.close()
4119 displayer.close()
4120
4120
4121 @command('manifest',
4121 @command('manifest',
4122 [('r', 'rev', '', _('revision to display'), _('REV')),
4122 [('r', 'rev', '', _('revision to display'), _('REV')),
4123 ('', 'all', False, _("list files from all revisions"))],
4123 ('', 'all', False, _("list files from all revisions"))],
4124 _('[-r REV]'))
4124 _('[-r REV]'))
4125 def manifest(ui, repo, node=None, rev=None, **opts):
4125 def manifest(ui, repo, node=None, rev=None, **opts):
4126 """output the current or given revision of the project manifest
4126 """output the current or given revision of the project manifest
4127
4127
4128 Print a list of version controlled files for the given revision.
4128 Print a list of version controlled files for the given revision.
4129 If no revision is given, the first parent of the working directory
4129 If no revision is given, the first parent of the working directory
4130 is used, or the null revision if no revision is checked out.
4130 is used, or the null revision if no revision is checked out.
4131
4131
4132 With -v, print file permissions, symlink and executable bits.
4132 With -v, print file permissions, symlink and executable bits.
4133 With --debug, print file revision hashes.
4133 With --debug, print file revision hashes.
4134
4134
4135 If option --all is specified, the list of all files from all revisions
4135 If option --all is specified, the list of all files from all revisions
4136 is printed. This includes deleted and renamed files.
4136 is printed. This includes deleted and renamed files.
4137
4137
4138 Returns 0 on success.
4138 Returns 0 on success.
4139 """
4139 """
4140
4140
4141 fm = ui.formatter('manifest', opts)
4141 fm = ui.formatter('manifest', opts)
4142
4142
4143 if opts.get('all'):
4143 if opts.get('all'):
4144 if rev or node:
4144 if rev or node:
4145 raise util.Abort(_("can't specify a revision with --all"))
4145 raise util.Abort(_("can't specify a revision with --all"))
4146
4146
4147 res = []
4147 res = []
4148 prefix = "data/"
4148 prefix = "data/"
4149 suffix = ".i"
4149 suffix = ".i"
4150 plen = len(prefix)
4150 plen = len(prefix)
4151 slen = len(suffix)
4151 slen = len(suffix)
4152 lock = repo.lock()
4152 lock = repo.lock()
4153 try:
4153 try:
4154 for fn, b, size in repo.store.datafiles():
4154 for fn, b, size in repo.store.datafiles():
4155 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4155 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4156 res.append(fn[plen:-slen])
4156 res.append(fn[plen:-slen])
4157 finally:
4157 finally:
4158 lock.release()
4158 lock.release()
4159 for f in res:
4159 for f in res:
4160 fm.startitem()
4160 fm.startitem()
4161 fm.write("path", '%s\n', f)
4161 fm.write("path", '%s\n', f)
4162 fm.end()
4162 fm.end()
4163 return
4163 return
4164
4164
4165 if rev and node:
4165 if rev and node:
4166 raise util.Abort(_("please specify just one revision"))
4166 raise util.Abort(_("please specify just one revision"))
4167
4167
4168 if not node:
4168 if not node:
4169 node = rev
4169 node = rev
4170
4170
4171 char = {'l': '@', 'x': '*', '': ''}
4171 char = {'l': '@', 'x': '*', '': ''}
4172 mode = {'l': '644', 'x': '755', '': '644'}
4172 mode = {'l': '644', 'x': '755', '': '644'}
4173 ctx = scmutil.revsingle(repo, node)
4173 ctx = scmutil.revsingle(repo, node)
4174 mf = ctx.manifest()
4174 mf = ctx.manifest()
4175 for f in ctx:
4175 for f in ctx:
4176 fm.startitem()
4176 fm.startitem()
4177 fl = ctx[f].flags()
4177 fl = ctx[f].flags()
4178 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4178 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4179 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4179 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4180 fm.write('path', '%s\n', f)
4180 fm.write('path', '%s\n', f)
4181 fm.end()
4181 fm.end()
4182
4182
4183 @command('^merge',
4183 @command('^merge',
4184 [('f', 'force', None,
4184 [('f', 'force', None,
4185 _('force a merge including outstanding changes (DEPRECATED)')),
4185 _('force a merge including outstanding changes (DEPRECATED)')),
4186 ('r', 'rev', '', _('revision to merge'), _('REV')),
4186 ('r', 'rev', '', _('revision to merge'), _('REV')),
4187 ('P', 'preview', None,
4187 ('P', 'preview', None,
4188 _('review revisions to merge (no merge is performed)'))
4188 _('review revisions to merge (no merge is performed)'))
4189 ] + mergetoolopts,
4189 ] + mergetoolopts,
4190 _('[-P] [-f] [[-r] REV]'))
4190 _('[-P] [-f] [[-r] REV]'))
4191 def merge(ui, repo, node=None, **opts):
4191 def merge(ui, repo, node=None, **opts):
4192 """merge working directory with another revision
4192 """merge working directory with another revision
4193
4193
4194 The current working directory is updated with all changes made in
4194 The current working directory is updated with all changes made in
4195 the requested revision since the last common predecessor revision.
4195 the requested revision since the last common predecessor revision.
4196
4196
4197 Files that changed between either parent are marked as changed for
4197 Files that changed between either parent are marked as changed for
4198 the next commit and a commit must be performed before any further
4198 the next commit and a commit must be performed before any further
4199 updates to the repository are allowed. The next commit will have
4199 updates to the repository are allowed. The next commit will have
4200 two parents.
4200 two parents.
4201
4201
4202 ``--tool`` can be used to specify the merge tool used for file
4202 ``--tool`` can be used to specify the merge tool used for file
4203 merges. It overrides the HGMERGE environment variable and your
4203 merges. It overrides the HGMERGE environment variable and your
4204 configuration files. See :hg:`help merge-tools` for options.
4204 configuration files. See :hg:`help merge-tools` for options.
4205
4205
4206 If no revision is specified, the working directory's parent is a
4206 If no revision is specified, the working directory's parent is a
4207 head revision, and the current branch contains exactly one other
4207 head revision, and the current branch contains exactly one other
4208 head, the other head is merged with by default. Otherwise, an
4208 head, the other head is merged with by default. Otherwise, an
4209 explicit revision with which to merge with must be provided.
4209 explicit revision with which to merge with must be provided.
4210
4210
4211 :hg:`resolve` must be used to resolve unresolved files.
4211 :hg:`resolve` must be used to resolve unresolved files.
4212
4212
4213 To undo an uncommitted merge, use :hg:`update --clean .` which
4213 To undo an uncommitted merge, use :hg:`update --clean .` which
4214 will check out a clean copy of the original merge parent, losing
4214 will check out a clean copy of the original merge parent, losing
4215 all changes.
4215 all changes.
4216
4216
4217 Returns 0 on success, 1 if there are unresolved files.
4217 Returns 0 on success, 1 if there are unresolved files.
4218 """
4218 """
4219
4219
4220 if opts.get('rev') and node:
4220 if opts.get('rev') and node:
4221 raise util.Abort(_("please specify just one revision"))
4221 raise util.Abort(_("please specify just one revision"))
4222 if not node:
4222 if not node:
4223 node = opts.get('rev')
4223 node = opts.get('rev')
4224
4224
4225 if node:
4225 if node:
4226 node = scmutil.revsingle(repo, node).node()
4226 node = scmutil.revsingle(repo, node).node()
4227
4227
4228 if not node and repo._bookmarkcurrent:
4228 if not node and repo._bookmarkcurrent:
4229 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4229 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4230 curhead = repo[repo._bookmarkcurrent].node()
4230 curhead = repo[repo._bookmarkcurrent].node()
4231 if len(bmheads) == 2:
4231 if len(bmheads) == 2:
4232 if curhead == bmheads[0]:
4232 if curhead == bmheads[0]:
4233 node = bmheads[1]
4233 node = bmheads[1]
4234 else:
4234 else:
4235 node = bmheads[0]
4235 node = bmheads[0]
4236 elif len(bmheads) > 2:
4236 elif len(bmheads) > 2:
4237 raise util.Abort(_("multiple matching bookmarks to merge - "
4237 raise util.Abort(_("multiple matching bookmarks to merge - "
4238 "please merge with an explicit rev or bookmark"),
4238 "please merge with an explicit rev or bookmark"),
4239 hint=_("run 'hg heads' to see all heads"))
4239 hint=_("run 'hg heads' to see all heads"))
4240 elif len(bmheads) <= 1:
4240 elif len(bmheads) <= 1:
4241 raise util.Abort(_("no matching bookmark to merge - "
4241 raise util.Abort(_("no matching bookmark to merge - "
4242 "please merge with an explicit rev or bookmark"),
4242 "please merge with an explicit rev or bookmark"),
4243 hint=_("run 'hg heads' to see all heads"))
4243 hint=_("run 'hg heads' to see all heads"))
4244
4244
4245 if not node and not repo._bookmarkcurrent:
4245 if not node and not repo._bookmarkcurrent:
4246 branch = repo[None].branch()
4246 branch = repo[None].branch()
4247 bheads = repo.branchheads(branch)
4247 bheads = repo.branchheads(branch)
4248 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4248 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4249
4249
4250 if len(nbhs) > 2:
4250 if len(nbhs) > 2:
4251 raise util.Abort(_("branch '%s' has %d heads - "
4251 raise util.Abort(_("branch '%s' has %d heads - "
4252 "please merge with an explicit rev")
4252 "please merge with an explicit rev")
4253 % (branch, len(bheads)),
4253 % (branch, len(bheads)),
4254 hint=_("run 'hg heads .' to see heads"))
4254 hint=_("run 'hg heads .' to see heads"))
4255
4255
4256 parent = repo.dirstate.p1()
4256 parent = repo.dirstate.p1()
4257 if len(nbhs) <= 1:
4257 if len(nbhs) <= 1:
4258 if len(bheads) > 1:
4258 if len(bheads) > 1:
4259 raise util.Abort(_("heads are bookmarked - "
4259 raise util.Abort(_("heads are bookmarked - "
4260 "please merge with an explicit rev"),
4260 "please merge with an explicit rev"),
4261 hint=_("run 'hg heads' to see all heads"))
4261 hint=_("run 'hg heads' to see all heads"))
4262 if len(repo.heads()) > 1:
4262 if len(repo.heads()) > 1:
4263 raise util.Abort(_("branch '%s' has one head - "
4263 raise util.Abort(_("branch '%s' has one head - "
4264 "please merge with an explicit rev")
4264 "please merge with an explicit rev")
4265 % branch,
4265 % branch,
4266 hint=_("run 'hg heads' to see all heads"))
4266 hint=_("run 'hg heads' to see all heads"))
4267 msg, hint = _('nothing to merge'), None
4267 msg, hint = _('nothing to merge'), None
4268 if parent != repo.lookup(branch):
4268 if parent != repo.lookup(branch):
4269 hint = _("use 'hg update' instead")
4269 hint = _("use 'hg update' instead")
4270 raise util.Abort(msg, hint=hint)
4270 raise util.Abort(msg, hint=hint)
4271
4271
4272 if parent not in bheads:
4272 if parent not in bheads:
4273 raise util.Abort(_('working directory not at a head revision'),
4273 raise util.Abort(_('working directory not at a head revision'),
4274 hint=_("use 'hg update' or merge with an "
4274 hint=_("use 'hg update' or merge with an "
4275 "explicit revision"))
4275 "explicit revision"))
4276 if parent == nbhs[0]:
4276 if parent == nbhs[0]:
4277 node = nbhs[-1]
4277 node = nbhs[-1]
4278 else:
4278 else:
4279 node = nbhs[0]
4279 node = nbhs[0]
4280
4280
4281 if opts.get('preview'):
4281 if opts.get('preview'):
4282 # find nodes that are ancestors of p2 but not of p1
4282 # find nodes that are ancestors of p2 but not of p1
4283 p1 = repo.lookup('.')
4283 p1 = repo.lookup('.')
4284 p2 = repo.lookup(node)
4284 p2 = repo.lookup(node)
4285 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4285 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4286
4286
4287 displayer = cmdutil.show_changeset(ui, repo, opts)
4287 displayer = cmdutil.show_changeset(ui, repo, opts)
4288 for node in nodes:
4288 for node in nodes:
4289 displayer.show(repo[node])
4289 displayer.show(repo[node])
4290 displayer.close()
4290 displayer.close()
4291 return 0
4291 return 0
4292
4292
4293 try:
4293 try:
4294 # ui.forcemerge is an internal variable, do not document
4294 # ui.forcemerge is an internal variable, do not document
4295 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4295 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4296 return hg.merge(repo, node, force=opts.get('force'))
4296 return hg.merge(repo, node, force=opts.get('force'))
4297 finally:
4297 finally:
4298 ui.setconfig('ui', 'forcemerge', '')
4298 ui.setconfig('ui', 'forcemerge', '')
4299
4299
4300 @command('outgoing|out',
4300 @command('outgoing|out',
4301 [('f', 'force', None, _('run even when the destination is unrelated')),
4301 [('f', 'force', None, _('run even when the destination is unrelated')),
4302 ('r', 'rev', [],
4302 ('r', 'rev', [],
4303 _('a changeset intended to be included in the destination'), _('REV')),
4303 _('a changeset intended to be included in the destination'), _('REV')),
4304 ('n', 'newest-first', None, _('show newest record first')),
4304 ('n', 'newest-first', None, _('show newest record first')),
4305 ('B', 'bookmarks', False, _('compare bookmarks')),
4305 ('B', 'bookmarks', False, _('compare bookmarks')),
4306 ('b', 'branch', [], _('a specific branch you would like to push'),
4306 ('b', 'branch', [], _('a specific branch you would like to push'),
4307 _('BRANCH')),
4307 _('BRANCH')),
4308 ] + logopts + remoteopts + subrepoopts,
4308 ] + logopts + remoteopts + subrepoopts,
4309 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4309 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4310 def outgoing(ui, repo, dest=None, **opts):
4310 def outgoing(ui, repo, dest=None, **opts):
4311 """show changesets not found in the destination
4311 """show changesets not found in the destination
4312
4312
4313 Show changesets not found in the specified destination repository
4313 Show changesets not found in the specified destination repository
4314 or the default push location. These are the changesets that would
4314 or the default push location. These are the changesets that would
4315 be pushed if a push was requested.
4315 be pushed if a push was requested.
4316
4316
4317 See pull for details of valid destination formats.
4317 See pull for details of valid destination formats.
4318
4318
4319 Returns 0 if there are outgoing changes, 1 otherwise.
4319 Returns 0 if there are outgoing changes, 1 otherwise.
4320 """
4320 """
4321 if opts.get('graph'):
4321 if opts.get('graph'):
4322 cmdutil.checkunsupportedgraphflags([], opts)
4322 cmdutil.checkunsupportedgraphflags([], opts)
4323 o = hg._outgoing(ui, repo, dest, opts)
4323 o = hg._outgoing(ui, repo, dest, opts)
4324 if o is None:
4324 if o is None:
4325 return
4325 return
4326
4326
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4331 graphmod.asciiedges)
4331 graphmod.asciiedges)
4332 return 0
4332 return 0
4333
4333
4334 if opts.get('bookmarks'):
4334 if opts.get('bookmarks'):
4335 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4335 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4336 dest, branches = hg.parseurl(dest, opts.get('branch'))
4336 dest, branches = hg.parseurl(dest, opts.get('branch'))
4337 other = hg.peer(repo, opts, dest)
4337 other = hg.peer(repo, opts, dest)
4338 if 'bookmarks' not in other.listkeys('namespaces'):
4338 if 'bookmarks' not in other.listkeys('namespaces'):
4339 ui.warn(_("remote doesn't support bookmarks\n"))
4339 ui.warn(_("remote doesn't support bookmarks\n"))
4340 return 0
4340 return 0
4341 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4341 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4342 return bookmarks.diff(ui, other, repo)
4342 return bookmarks.diff(ui, other, repo)
4343
4343
4344 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4344 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4345 try:
4345 try:
4346 return hg.outgoing(ui, repo, dest, opts)
4346 return hg.outgoing(ui, repo, dest, opts)
4347 finally:
4347 finally:
4348 del repo._subtoppath
4348 del repo._subtoppath
4349
4349
4350 @command('parents',
4350 @command('parents',
4351 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4351 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4352 ] + templateopts,
4352 ] + templateopts,
4353 _('[-r REV] [FILE]'))
4353 _('[-r REV] [FILE]'))
4354 def parents(ui, repo, file_=None, **opts):
4354 def parents(ui, repo, file_=None, **opts):
4355 """show the parents of the working directory or revision
4355 """show the parents of the working directory or revision
4356
4356
4357 Print the working directory's parent revisions. If a revision is
4357 Print the working directory's parent revisions. If a revision is
4358 given via -r/--rev, the parent of that revision will be printed.
4358 given via -r/--rev, the parent of that revision will be printed.
4359 If a file argument is given, the revision in which the file was
4359 If a file argument is given, the revision in which the file was
4360 last changed (before the working directory revision or the
4360 last changed (before the working directory revision or the
4361 argument to --rev if given) is printed.
4361 argument to --rev if given) is printed.
4362
4362
4363 Returns 0 on success.
4363 Returns 0 on success.
4364 """
4364 """
4365
4365
4366 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4366 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4367
4367
4368 if file_:
4368 if file_:
4369 m = scmutil.match(ctx, (file_,), opts)
4369 m = scmutil.match(ctx, (file_,), opts)
4370 if m.anypats() or len(m.files()) != 1:
4370 if m.anypats() or len(m.files()) != 1:
4371 raise util.Abort(_('can only specify an explicit filename'))
4371 raise util.Abort(_('can only specify an explicit filename'))
4372 file_ = m.files()[0]
4372 file_ = m.files()[0]
4373 filenodes = []
4373 filenodes = []
4374 for cp in ctx.parents():
4374 for cp in ctx.parents():
4375 if not cp:
4375 if not cp:
4376 continue
4376 continue
4377 try:
4377 try:
4378 filenodes.append(cp.filenode(file_))
4378 filenodes.append(cp.filenode(file_))
4379 except error.LookupError:
4379 except error.LookupError:
4380 pass
4380 pass
4381 if not filenodes:
4381 if not filenodes:
4382 raise util.Abort(_("'%s' not found in manifest!") % file_)
4382 raise util.Abort(_("'%s' not found in manifest!") % file_)
4383 p = []
4383 p = []
4384 for fn in filenodes:
4384 for fn in filenodes:
4385 fctx = repo.filectx(file_, fileid=fn)
4385 fctx = repo.filectx(file_, fileid=fn)
4386 p.append(fctx.node())
4386 p.append(fctx.node())
4387 else:
4387 else:
4388 p = [cp.node() for cp in ctx.parents()]
4388 p = [cp.node() for cp in ctx.parents()]
4389
4389
4390 displayer = cmdutil.show_changeset(ui, repo, opts)
4390 displayer = cmdutil.show_changeset(ui, repo, opts)
4391 for n in p:
4391 for n in p:
4392 if n != nullid:
4392 if n != nullid:
4393 displayer.show(repo[n])
4393 displayer.show(repo[n])
4394 displayer.close()
4394 displayer.close()
4395
4395
4396 @command('paths', [], _('[NAME]'))
4396 @command('paths', [], _('[NAME]'))
4397 def paths(ui, repo, search=None):
4397 def paths(ui, repo, search=None):
4398 """show aliases for remote repositories
4398 """show aliases for remote repositories
4399
4399
4400 Show definition of symbolic path name NAME. If no name is given,
4400 Show definition of symbolic path name NAME. If no name is given,
4401 show definition of all available names.
4401 show definition of all available names.
4402
4402
4403 Option -q/--quiet suppresses all output when searching for NAME
4403 Option -q/--quiet suppresses all output when searching for NAME
4404 and shows only the path names when listing all definitions.
4404 and shows only the path names when listing all definitions.
4405
4405
4406 Path names are defined in the [paths] section of your
4406 Path names are defined in the [paths] section of your
4407 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4407 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4408 repository, ``.hg/hgrc`` is used, too.
4408 repository, ``.hg/hgrc`` is used, too.
4409
4409
4410 The path names ``default`` and ``default-push`` have a special
4410 The path names ``default`` and ``default-push`` have a special
4411 meaning. When performing a push or pull operation, they are used
4411 meaning. When performing a push or pull operation, they are used
4412 as fallbacks if no location is specified on the command-line.
4412 as fallbacks if no location is specified on the command-line.
4413 When ``default-push`` is set, it will be used for push and
4413 When ``default-push`` is set, it will be used for push and
4414 ``default`` will be used for pull; otherwise ``default`` is used
4414 ``default`` will be used for pull; otherwise ``default`` is used
4415 as the fallback for both. When cloning a repository, the clone
4415 as the fallback for both. When cloning a repository, the clone
4416 source is written as ``default`` in ``.hg/hgrc``. Note that
4416 source is written as ``default`` in ``.hg/hgrc``. Note that
4417 ``default`` and ``default-push`` apply to all inbound (e.g.
4417 ``default`` and ``default-push`` apply to all inbound (e.g.
4418 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4418 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4419 :hg:`bundle`) operations.
4419 :hg:`bundle`) operations.
4420
4420
4421 See :hg:`help urls` for more information.
4421 See :hg:`help urls` for more information.
4422
4422
4423 Returns 0 on success.
4423 Returns 0 on success.
4424 """
4424 """
4425 if search:
4425 if search:
4426 for name, path in ui.configitems("paths"):
4426 for name, path in ui.configitems("paths"):
4427 if name == search:
4427 if name == search:
4428 ui.status("%s\n" % util.hidepassword(path))
4428 ui.status("%s\n" % util.hidepassword(path))
4429 return
4429 return
4430 if not ui.quiet:
4430 if not ui.quiet:
4431 ui.warn(_("not found!\n"))
4431 ui.warn(_("not found!\n"))
4432 return 1
4432 return 1
4433 else:
4433 else:
4434 for name, path in ui.configitems("paths"):
4434 for name, path in ui.configitems("paths"):
4435 if ui.quiet:
4435 if ui.quiet:
4436 ui.write("%s\n" % name)
4436 ui.write("%s\n" % name)
4437 else:
4437 else:
4438 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4438 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4439
4439
4440 @command('phase',
4440 @command('phase',
4441 [('p', 'public', False, _('set changeset phase to public')),
4441 [('p', 'public', False, _('set changeset phase to public')),
4442 ('d', 'draft', False, _('set changeset phase to draft')),
4442 ('d', 'draft', False, _('set changeset phase to draft')),
4443 ('s', 'secret', False, _('set changeset phase to secret')),
4443 ('s', 'secret', False, _('set changeset phase to secret')),
4444 ('f', 'force', False, _('allow to move boundary backward')),
4444 ('f', 'force', False, _('allow to move boundary backward')),
4445 ('r', 'rev', [], _('target revision'), _('REV')),
4445 ('r', 'rev', [], _('target revision'), _('REV')),
4446 ],
4446 ],
4447 _('[-p|-d|-s] [-f] [-r] REV...'))
4447 _('[-p|-d|-s] [-f] [-r] REV...'))
4448 def phase(ui, repo, *revs, **opts):
4448 def phase(ui, repo, *revs, **opts):
4449 """set or show the current phase name
4449 """set or show the current phase name
4450
4450
4451 With no argument, show the phase name of specified revisions.
4451 With no argument, show the phase name of specified revisions.
4452
4452
4453 With one of -p/--public, -d/--draft or -s/--secret, change the
4453 With one of -p/--public, -d/--draft or -s/--secret, change the
4454 phase value of the specified revisions.
4454 phase value of the specified revisions.
4455
4455
4456 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4456 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4457 lower phase to an higher phase. Phases are ordered as follows::
4457 lower phase to an higher phase. Phases are ordered as follows::
4458
4458
4459 public < draft < secret
4459 public < draft < secret
4460
4460
4461 Return 0 on success, 1 if no phases were changed or some could not
4461 Return 0 on success, 1 if no phases were changed or some could not
4462 be changed.
4462 be changed.
4463 """
4463 """
4464 # search for a unique phase argument
4464 # search for a unique phase argument
4465 targetphase = None
4465 targetphase = None
4466 for idx, name in enumerate(phases.phasenames):
4466 for idx, name in enumerate(phases.phasenames):
4467 if opts[name]:
4467 if opts[name]:
4468 if targetphase is not None:
4468 if targetphase is not None:
4469 raise util.Abort(_('only one phase can be specified'))
4469 raise util.Abort(_('only one phase can be specified'))
4470 targetphase = idx
4470 targetphase = idx
4471
4471
4472 # look for specified revision
4472 # look for specified revision
4473 revs = list(revs)
4473 revs = list(revs)
4474 revs.extend(opts['rev'])
4474 revs.extend(opts['rev'])
4475 if not revs:
4475 if not revs:
4476 raise util.Abort(_('no revisions specified'))
4476 raise util.Abort(_('no revisions specified'))
4477
4477
4478 revs = scmutil.revrange(repo, revs)
4478 revs = scmutil.revrange(repo, revs)
4479
4479
4480 lock = None
4480 lock = None
4481 ret = 0
4481 ret = 0
4482 if targetphase is None:
4482 if targetphase is None:
4483 # display
4483 # display
4484 for r in revs:
4484 for r in revs:
4485 ctx = repo[r]
4485 ctx = repo[r]
4486 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4486 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4487 else:
4487 else:
4488 lock = repo.lock()
4488 lock = repo.lock()
4489 try:
4489 try:
4490 # set phase
4490 # set phase
4491 if not revs:
4491 if not revs:
4492 raise util.Abort(_('empty revision set'))
4492 raise util.Abort(_('empty revision set'))
4493 nodes = [repo[r].node() for r in revs]
4493 nodes = [repo[r].node() for r in revs]
4494 olddata = repo._phasecache.getphaserevs(repo)[:]
4494 olddata = repo._phasecache.getphaserevs(repo)[:]
4495 phases.advanceboundary(repo, targetphase, nodes)
4495 phases.advanceboundary(repo, targetphase, nodes)
4496 if opts['force']:
4496 if opts['force']:
4497 phases.retractboundary(repo, targetphase, nodes)
4497 phases.retractboundary(repo, targetphase, nodes)
4498 finally:
4498 finally:
4499 lock.release()
4499 lock.release()
4500 # moving revision from public to draft may hide them
4500 # moving revision from public to draft may hide them
4501 # We have to check result on an unfiltered repository
4501 # We have to check result on an unfiltered repository
4502 unfi = repo.unfiltered()
4502 unfi = repo.unfiltered()
4503 newdata = repo._phasecache.getphaserevs(unfi)
4503 newdata = repo._phasecache.getphaserevs(unfi)
4504 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4504 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4505 cl = unfi.changelog
4505 cl = unfi.changelog
4506 rejected = [n for n in nodes
4506 rejected = [n for n in nodes
4507 if newdata[cl.rev(n)] < targetphase]
4507 if newdata[cl.rev(n)] < targetphase]
4508 if rejected:
4508 if rejected:
4509 ui.warn(_('cannot move %i changesets to a higher '
4509 ui.warn(_('cannot move %i changesets to a higher '
4510 'phase, use --force\n') % len(rejected))
4510 'phase, use --force\n') % len(rejected))
4511 ret = 1
4511 ret = 1
4512 if changes:
4512 if changes:
4513 msg = _('phase changed for %i changesets\n') % changes
4513 msg = _('phase changed for %i changesets\n') % changes
4514 if ret:
4514 if ret:
4515 ui.status(msg)
4515 ui.status(msg)
4516 else:
4516 else:
4517 ui.note(msg)
4517 ui.note(msg)
4518 else:
4518 else:
4519 ui.warn(_('no phases changed\n'))
4519 ui.warn(_('no phases changed\n'))
4520 ret = 1
4520 ret = 1
4521 return ret
4521 return ret
4522
4522
4523 def postincoming(ui, repo, modheads, optupdate, checkout):
4523 def postincoming(ui, repo, modheads, optupdate, checkout):
4524 if modheads == 0:
4524 if modheads == 0:
4525 return
4525 return
4526 if optupdate:
4526 if optupdate:
4527 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4527 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4528 try:
4528 try:
4529 ret = hg.update(repo, checkout)
4529 ret = hg.update(repo, checkout)
4530 except util.Abort, inst:
4530 except util.Abort, inst:
4531 ui.warn(_("not updating: %s\n") % str(inst))
4531 ui.warn(_("not updating: %s\n") % str(inst))
4532 if inst.hint:
4532 if inst.hint:
4533 ui.warn(_("(%s)\n") % inst.hint)
4533 ui.warn(_("(%s)\n") % inst.hint)
4534 return 0
4534 return 0
4535 if not ret and not checkout:
4535 if not ret and not checkout:
4536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4537 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4537 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4538 return ret
4538 return ret
4539 if modheads > 1:
4539 if modheads > 1:
4540 currentbranchheads = len(repo.branchheads())
4540 currentbranchheads = len(repo.branchheads())
4541 if currentbranchheads == modheads:
4541 if currentbranchheads == modheads:
4542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4543 elif currentbranchheads > 1:
4543 elif currentbranchheads > 1:
4544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4545 "merge)\n"))
4545 "merge)\n"))
4546 else:
4546 else:
4547 ui.status(_("(run 'hg heads' to see heads)\n"))
4547 ui.status(_("(run 'hg heads' to see heads)\n"))
4548 else:
4548 else:
4549 ui.status(_("(run 'hg update' to get a working copy)\n"))
4549 ui.status(_("(run 'hg update' to get a working copy)\n"))
4550
4550
4551 @command('^pull',
4551 @command('^pull',
4552 [('u', 'update', None,
4552 [('u', 'update', None,
4553 _('update to new branch head if changesets were pulled')),
4553 _('update to new branch head if changesets were pulled')),
4554 ('f', 'force', None, _('run even when remote repository is unrelated')),
4554 ('f', 'force', None, _('run even when remote repository is unrelated')),
4555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4557 ('b', 'branch', [], _('a specific branch you would like to pull'),
4557 ('b', 'branch', [], _('a specific branch you would like to pull'),
4558 _('BRANCH')),
4558 _('BRANCH')),
4559 ] + remoteopts,
4559 ] + remoteopts,
4560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4561 def pull(ui, repo, source="default", **opts):
4561 def pull(ui, repo, source="default", **opts):
4562 """pull changes from the specified source
4562 """pull changes from the specified source
4563
4563
4564 Pull changes from a remote repository to a local one.
4564 Pull changes from a remote repository to a local one.
4565
4565
4566 This finds all changes from the repository at the specified path
4566 This finds all changes from the repository at the specified path
4567 or URL and adds them to a local repository (the current one unless
4567 or URL and adds them to a local repository (the current one unless
4568 -R is specified). By default, this does not update the copy of the
4568 -R is specified). By default, this does not update the copy of the
4569 project in the working directory.
4569 project in the working directory.
4570
4570
4571 Use :hg:`incoming` if you want to see what would have been added
4571 Use :hg:`incoming` if you want to see what would have been added
4572 by a pull at the time you issued this command. If you then decide
4572 by a pull at the time you issued this command. If you then decide
4573 to add those changes to the repository, you should use :hg:`pull
4573 to add those changes to the repository, you should use :hg:`pull
4574 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4574 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4575
4575
4576 If SOURCE is omitted, the 'default' path will be used.
4576 If SOURCE is omitted, the 'default' path will be used.
4577 See :hg:`help urls` for more information.
4577 See :hg:`help urls` for more information.
4578
4578
4579 Returns 0 on success, 1 if an update had unresolved files.
4579 Returns 0 on success, 1 if an update had unresolved files.
4580 """
4580 """
4581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4582 other = hg.peer(repo, opts, source)
4582 other = hg.peer(repo, opts, source)
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4584 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4584 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4585
4585
4586 remotebookmarks = other.listkeys('bookmarks')
4586 remotebookmarks = other.listkeys('bookmarks')
4587
4587
4588 if opts.get('bookmark'):
4588 if opts.get('bookmark'):
4589 if not revs:
4589 if not revs:
4590 revs = []
4590 revs = []
4591 for b in opts['bookmark']:
4591 for b in opts['bookmark']:
4592 if b not in remotebookmarks:
4592 if b not in remotebookmarks:
4593 raise util.Abort(_('remote bookmark %s not found!') % b)
4593 raise util.Abort(_('remote bookmark %s not found!') % b)
4594 revs.append(remotebookmarks[b])
4594 revs.append(remotebookmarks[b])
4595
4595
4596 if revs:
4596 if revs:
4597 try:
4597 try:
4598 revs = [other.lookup(rev) for rev in revs]
4598 revs = [other.lookup(rev) for rev in revs]
4599 except error.CapabilityError:
4599 except error.CapabilityError:
4600 err = _("other repository doesn't support revision lookup, "
4600 err = _("other repository doesn't support revision lookup, "
4601 "so a rev cannot be specified.")
4601 "so a rev cannot be specified.")
4602 raise util.Abort(err)
4602 raise util.Abort(err)
4603
4603
4604 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4604 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4605 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4605 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4606 if checkout:
4606 if checkout:
4607 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4607 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4608 repo._subtoppath = source
4608 repo._subtoppath = source
4609 try:
4609 try:
4610 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4610 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4611
4611
4612 finally:
4612 finally:
4613 del repo._subtoppath
4613 del repo._subtoppath
4614
4614
4615 # update specified bookmarks
4615 # update specified bookmarks
4616 if opts.get('bookmark'):
4616 if opts.get('bookmark'):
4617 marks = repo._bookmarks
4617 marks = repo._bookmarks
4618 for b in opts['bookmark']:
4618 for b in opts['bookmark']:
4619 # explicit pull overrides local bookmark if any
4619 # explicit pull overrides local bookmark if any
4620 ui.status(_("importing bookmark %s\n") % b)
4620 ui.status(_("importing bookmark %s\n") % b)
4621 marks[b] = repo[remotebookmarks[b]].node()
4621 marks[b] = repo[remotebookmarks[b]].node()
4622 marks.write()
4622 marks.write()
4623
4623
4624 return ret
4624 return ret
4625
4625
4626 @command('^push',
4626 @command('^push',
4627 [('f', 'force', None, _('force push')),
4627 [('f', 'force', None, _('force push')),
4628 ('r', 'rev', [],
4628 ('r', 'rev', [],
4629 _('a changeset intended to be included in the destination'),
4629 _('a changeset intended to be included in the destination'),
4630 _('REV')),
4630 _('REV')),
4631 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4631 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4632 ('b', 'branch', [],
4632 ('b', 'branch', [],
4633 _('a specific branch you would like to push'), _('BRANCH')),
4633 _('a specific branch you would like to push'), _('BRANCH')),
4634 ('', 'new-branch', False, _('allow pushing a new branch')),
4634 ('', 'new-branch', False, _('allow pushing a new branch')),
4635 ] + remoteopts,
4635 ] + remoteopts,
4636 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4636 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4637 def push(ui, repo, dest=None, **opts):
4637 def push(ui, repo, dest=None, **opts):
4638 """push changes to the specified destination
4638 """push changes to the specified destination
4639
4639
4640 Push changesets from the local repository to the specified
4640 Push changesets from the local repository to the specified
4641 destination.
4641 destination.
4642
4642
4643 This operation is symmetrical to pull: it is identical to a pull
4643 This operation is symmetrical to pull: it is identical to a pull
4644 in the destination repository from the current one.
4644 in the destination repository from the current one.
4645
4645
4646 By default, push will not allow creation of new heads at the
4646 By default, push will not allow creation of new heads at the
4647 destination, since multiple heads would make it unclear which head
4647 destination, since multiple heads would make it unclear which head
4648 to use. In this situation, it is recommended to pull and merge
4648 to use. In this situation, it is recommended to pull and merge
4649 before pushing.
4649 before pushing.
4650
4650
4651 Use --new-branch if you want to allow push to create a new named
4651 Use --new-branch if you want to allow push to create a new named
4652 branch that is not present at the destination. This allows you to
4652 branch that is not present at the destination. This allows you to
4653 only create a new branch without forcing other changes.
4653 only create a new branch without forcing other changes.
4654
4654
4655 .. note::
4655 .. note::
4656
4656
4657 Extra care should be taken with the -f/--force option,
4657 Extra care should be taken with the -f/--force option,
4658 which will push all new heads on all branches, an action which will
4658 which will push all new heads on all branches, an action which will
4659 almost always cause confusion for collaborators.
4659 almost always cause confusion for collaborators.
4660
4660
4661 If -r/--rev is used, the specified revision and all its ancestors
4661 If -r/--rev is used, the specified revision and all its ancestors
4662 will be pushed to the remote repository.
4662 will be pushed to the remote repository.
4663
4663
4664 If -B/--bookmark is used, the specified bookmarked revision, its
4664 If -B/--bookmark is used, the specified bookmarked revision, its
4665 ancestors, and the bookmark will be pushed to the remote
4665 ancestors, and the bookmark will be pushed to the remote
4666 repository.
4666 repository.
4667
4667
4668 Please see :hg:`help urls` for important details about ``ssh://``
4668 Please see :hg:`help urls` for important details about ``ssh://``
4669 URLs. If DESTINATION is omitted, a default path will be used.
4669 URLs. If DESTINATION is omitted, a default path will be used.
4670
4670
4671 Returns 0 if push was successful, 1 if nothing to push.
4671 Returns 0 if push was successful, 1 if nothing to push.
4672 """
4672 """
4673
4673
4674 if opts.get('bookmark'):
4674 if opts.get('bookmark'):
4675 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4675 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4676 for b in opts['bookmark']:
4676 for b in opts['bookmark']:
4677 # translate -B options to -r so changesets get pushed
4677 # translate -B options to -r so changesets get pushed
4678 if b in repo._bookmarks:
4678 if b in repo._bookmarks:
4679 opts.setdefault('rev', []).append(b)
4679 opts.setdefault('rev', []).append(b)
4680 else:
4680 else:
4681 # if we try to push a deleted bookmark, translate it to null
4681 # if we try to push a deleted bookmark, translate it to null
4682 # this lets simultaneous -r, -b options continue working
4682 # this lets simultaneous -r, -b options continue working
4683 opts.setdefault('rev', []).append("null")
4683 opts.setdefault('rev', []).append("null")
4684
4684
4685 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4685 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4686 dest, branches = hg.parseurl(dest, opts.get('branch'))
4686 dest, branches = hg.parseurl(dest, opts.get('branch'))
4687 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4687 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4688 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4688 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4689 other = hg.peer(repo, opts, dest)
4689 other = hg.peer(repo, opts, dest)
4690 if revs:
4690 if revs:
4691 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4691 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4692
4692
4693 repo._subtoppath = dest
4693 repo._subtoppath = dest
4694 try:
4694 try:
4695 # push subrepos depth-first for coherent ordering
4695 # push subrepos depth-first for coherent ordering
4696 c = repo['']
4696 c = repo['']
4697 subs = c.substate # only repos that are committed
4697 subs = c.substate # only repos that are committed
4698 for s in sorted(subs):
4698 for s in sorted(subs):
4699 if c.sub(s).push(opts) == 0:
4699 if c.sub(s).push(opts) == 0:
4700 return False
4700 return False
4701 finally:
4701 finally:
4702 del repo._subtoppath
4702 del repo._subtoppath
4703 result = repo.push(other, opts.get('force'), revs=revs,
4703 result = repo.push(other, opts.get('force'), revs=revs,
4704 newbranch=opts.get('new_branch'))
4704 newbranch=opts.get('new_branch'))
4705
4705
4706 result = not result
4706 result = not result
4707
4707
4708 if opts.get('bookmark'):
4708 if opts.get('bookmark'):
4709 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4709 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4710 if bresult == 2:
4710 if bresult == 2:
4711 return 2
4711 return 2
4712 if not result and bresult:
4712 if not result and bresult:
4713 result = 2
4713 result = 2
4714
4714
4715 return result
4715 return result
4716
4716
4717 @command('recover', [])
4717 @command('recover', [])
4718 def recover(ui, repo):
4718 def recover(ui, repo):
4719 """roll back an interrupted transaction
4719 """roll back an interrupted transaction
4720
4720
4721 Recover from an interrupted commit or pull.
4721 Recover from an interrupted commit or pull.
4722
4722
4723 This command tries to fix the repository status after an
4723 This command tries to fix the repository status after an
4724 interrupted operation. It should only be necessary when Mercurial
4724 interrupted operation. It should only be necessary when Mercurial
4725 suggests it.
4725 suggests it.
4726
4726
4727 Returns 0 if successful, 1 if nothing to recover or verify fails.
4727 Returns 0 if successful, 1 if nothing to recover or verify fails.
4728 """
4728 """
4729 if repo.recover():
4729 if repo.recover():
4730 return hg.verify(repo)
4730 return hg.verify(repo)
4731 return 1
4731 return 1
4732
4732
4733 @command('^remove|rm',
4733 @command('^remove|rm',
4734 [('A', 'after', None, _('record delete for missing files')),
4734 [('A', 'after', None, _('record delete for missing files')),
4735 ('f', 'force', None,
4735 ('f', 'force', None,
4736 _('remove (and delete) file even if added or modified')),
4736 _('remove (and delete) file even if added or modified')),
4737 ] + walkopts,
4737 ] + walkopts,
4738 _('[OPTION]... FILE...'))
4738 _('[OPTION]... FILE...'))
4739 def remove(ui, repo, *pats, **opts):
4739 def remove(ui, repo, *pats, **opts):
4740 """remove the specified files on the next commit
4740 """remove the specified files on the next commit
4741
4741
4742 Schedule the indicated files for removal from the current branch.
4742 Schedule the indicated files for removal from the current branch.
4743
4743
4744 This command schedules the files to be removed at the next commit.
4744 This command schedules the files to be removed at the next commit.
4745 To undo a remove before that, see :hg:`revert`. To undo added
4745 To undo a remove before that, see :hg:`revert`. To undo added
4746 files, see :hg:`forget`.
4746 files, see :hg:`forget`.
4747
4747
4748 .. container:: verbose
4748 .. container:: verbose
4749
4749
4750 -A/--after can be used to remove only files that have already
4750 -A/--after can be used to remove only files that have already
4751 been deleted, -f/--force can be used to force deletion, and -Af
4751 been deleted, -f/--force can be used to force deletion, and -Af
4752 can be used to remove files from the next revision without
4752 can be used to remove files from the next revision without
4753 deleting them from the working directory.
4753 deleting them from the working directory.
4754
4754
4755 The following table details the behavior of remove for different
4755 The following table details the behavior of remove for different
4756 file states (columns) and option combinations (rows). The file
4756 file states (columns) and option combinations (rows). The file
4757 states are Added [A], Clean [C], Modified [M] and Missing [!]
4757 states are Added [A], Clean [C], Modified [M] and Missing [!]
4758 (as reported by :hg:`status`). The actions are Warn, Remove
4758 (as reported by :hg:`status`). The actions are Warn, Remove
4759 (from branch) and Delete (from disk):
4759 (from branch) and Delete (from disk):
4760
4760
4761 ========= == == == ==
4761 ========= == == == ==
4762 opt/state A C M !
4762 opt/state A C M !
4763 ========= == == == ==
4763 ========= == == == ==
4764 none W RD W R
4764 none W RD W R
4765 -f R RD RD R
4765 -f R RD RD R
4766 -A W W W R
4766 -A W W W R
4767 -Af R R R R
4767 -Af R R R R
4768 ========= == == == ==
4768 ========= == == == ==
4769
4769
4770 Note that remove never deletes files in Added [A] state from the
4770 Note that remove never deletes files in Added [A] state from the
4771 working directory, not even if option --force is specified.
4771 working directory, not even if option --force is specified.
4772
4772
4773 Returns 0 on success, 1 if any warnings encountered.
4773 Returns 0 on success, 1 if any warnings encountered.
4774 """
4774 """
4775
4775
4776 ret = 0
4776 ret = 0
4777 after, force = opts.get('after'), opts.get('force')
4777 after, force = opts.get('after'), opts.get('force')
4778 if not pats and not after:
4778 if not pats and not after:
4779 raise util.Abort(_('no files specified'))
4779 raise util.Abort(_('no files specified'))
4780
4780
4781 m = scmutil.match(repo[None], pats, opts)
4781 m = scmutil.match(repo[None], pats, opts)
4782 s = repo.status(match=m, clean=True)
4782 s = repo.status(match=m, clean=True)
4783 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4783 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4784
4784
4785 # warn about failure to delete explicit files/dirs
4785 # warn about failure to delete explicit files/dirs
4786 wctx = repo[None]
4786 wctx = repo[None]
4787 for f in m.files():
4787 for f in m.files():
4788 if f in repo.dirstate or f in wctx.dirs():
4788 if f in repo.dirstate or f in wctx.dirs():
4789 continue
4789 continue
4790 if os.path.exists(m.rel(f)):
4790 if os.path.exists(m.rel(f)):
4791 if os.path.isdir(m.rel(f)):
4791 if os.path.isdir(m.rel(f)):
4792 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4792 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4793 else:
4793 else:
4794 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4794 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4795 # missing files will generate a warning elsewhere
4795 # missing files will generate a warning elsewhere
4796 ret = 1
4796 ret = 1
4797
4797
4798 if force:
4798 if force:
4799 list = modified + deleted + clean + added
4799 list = modified + deleted + clean + added
4800 elif after:
4800 elif after:
4801 list = deleted
4801 list = deleted
4802 for f in modified + added + clean:
4802 for f in modified + added + clean:
4803 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4803 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4804 ret = 1
4804 ret = 1
4805 else:
4805 else:
4806 list = deleted + clean
4806 list = deleted + clean
4807 for f in modified:
4807 for f in modified:
4808 ui.warn(_('not removing %s: file is modified (use -f'
4808 ui.warn(_('not removing %s: file is modified (use -f'
4809 ' to force removal)\n') % m.rel(f))
4809 ' to force removal)\n') % m.rel(f))
4810 ret = 1
4810 ret = 1
4811 for f in added:
4811 for f in added:
4812 ui.warn(_('not removing %s: file has been marked for add'
4812 ui.warn(_('not removing %s: file has been marked for add'
4813 ' (use forget to undo)\n') % m.rel(f))
4813 ' (use forget to undo)\n') % m.rel(f))
4814 ret = 1
4814 ret = 1
4815
4815
4816 for f in sorted(list):
4816 for f in sorted(list):
4817 if ui.verbose or not m.exact(f):
4817 if ui.verbose or not m.exact(f):
4818 ui.status(_('removing %s\n') % m.rel(f))
4818 ui.status(_('removing %s\n') % m.rel(f))
4819
4819
4820 wlock = repo.wlock()
4820 wlock = repo.wlock()
4821 try:
4821 try:
4822 if not after:
4822 if not after:
4823 for f in list:
4823 for f in list:
4824 if f in added:
4824 if f in added:
4825 continue # we never unlink added files on remove
4825 continue # we never unlink added files on remove
4826 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4826 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4827 repo[None].forget(list)
4827 repo[None].forget(list)
4828 finally:
4828 finally:
4829 wlock.release()
4829 wlock.release()
4830
4830
4831 return ret
4831 return ret
4832
4832
4833 @command('rename|move|mv',
4833 @command('rename|move|mv',
4834 [('A', 'after', None, _('record a rename that has already occurred')),
4834 [('A', 'after', None, _('record a rename that has already occurred')),
4835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4836 ] + walkopts + dryrunopts,
4836 ] + walkopts + dryrunopts,
4837 _('[OPTION]... SOURCE... DEST'))
4837 _('[OPTION]... SOURCE... DEST'))
4838 def rename(ui, repo, *pats, **opts):
4838 def rename(ui, repo, *pats, **opts):
4839 """rename files; equivalent of copy + remove
4839 """rename files; equivalent of copy + remove
4840
4840
4841 Mark dest as copies of sources; mark sources for deletion. If dest
4841 Mark dest as copies of sources; mark sources for deletion. If dest
4842 is a directory, copies are put in that directory. If dest is a
4842 is a directory, copies are put in that directory. If dest is a
4843 file, there can only be one source.
4843 file, there can only be one source.
4844
4844
4845 By default, this command copies the contents of files as they
4845 By default, this command copies the contents of files as they
4846 exist in the working directory. If invoked with -A/--after, the
4846 exist in the working directory. If invoked with -A/--after, the
4847 operation is recorded, but no copying is performed.
4847 operation is recorded, but no copying is performed.
4848
4848
4849 This command takes effect at the next commit. To undo a rename
4849 This command takes effect at the next commit. To undo a rename
4850 before that, see :hg:`revert`.
4850 before that, see :hg:`revert`.
4851
4851
4852 Returns 0 on success, 1 if errors are encountered.
4852 Returns 0 on success, 1 if errors are encountered.
4853 """
4853 """
4854 wlock = repo.wlock(False)
4854 wlock = repo.wlock(False)
4855 try:
4855 try:
4856 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4856 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4857 finally:
4857 finally:
4858 wlock.release()
4858 wlock.release()
4859
4859
4860 @command('resolve',
4860 @command('resolve',
4861 [('a', 'all', None, _('select all unresolved files')),
4861 [('a', 'all', None, _('select all unresolved files')),
4862 ('l', 'list', None, _('list state of files needing merge')),
4862 ('l', 'list', None, _('list state of files needing merge')),
4863 ('m', 'mark', None, _('mark files as resolved')),
4863 ('m', 'mark', None, _('mark files as resolved')),
4864 ('u', 'unmark', None, _('mark files as unresolved')),
4864 ('u', 'unmark', None, _('mark files as unresolved')),
4865 ('n', 'no-status', None, _('hide status prefix'))]
4865 ('n', 'no-status', None, _('hide status prefix'))]
4866 + mergetoolopts + walkopts,
4866 + mergetoolopts + walkopts,
4867 _('[OPTION]... [FILE]...'))
4867 _('[OPTION]... [FILE]...'))
4868 def resolve(ui, repo, *pats, **opts):
4868 def resolve(ui, repo, *pats, **opts):
4869 """redo merges or set/view the merge status of files
4869 """redo merges or set/view the merge status of files
4870
4870
4871 Merges with unresolved conflicts are often the result of
4871 Merges with unresolved conflicts are often the result of
4872 non-interactive merging using the ``internal:merge`` configuration
4872 non-interactive merging using the ``internal:merge`` configuration
4873 setting, or a command-line merge tool like ``diff3``. The resolve
4873 setting, or a command-line merge tool like ``diff3``. The resolve
4874 command is used to manage the files involved in a merge, after
4874 command is used to manage the files involved in a merge, after
4875 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4875 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4876 working directory must have two parents). See :hg:`help
4876 working directory must have two parents). See :hg:`help
4877 merge-tools` for information on configuring merge tools.
4877 merge-tools` for information on configuring merge tools.
4878
4878
4879 The resolve command can be used in the following ways:
4879 The resolve command can be used in the following ways:
4880
4880
4881 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4881 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4882 files, discarding any previous merge attempts. Re-merging is not
4882 files, discarding any previous merge attempts. Re-merging is not
4883 performed for files already marked as resolved. Use ``--all/-a``
4883 performed for files already marked as resolved. Use ``--all/-a``
4884 to select all unresolved files. ``--tool`` can be used to specify
4884 to select all unresolved files. ``--tool`` can be used to specify
4885 the merge tool used for the given files. It overrides the HGMERGE
4885 the merge tool used for the given files. It overrides the HGMERGE
4886 environment variable and your configuration files. Previous file
4886 environment variable and your configuration files. Previous file
4887 contents are saved with a ``.orig`` suffix.
4887 contents are saved with a ``.orig`` suffix.
4888
4888
4889 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4889 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4890 (e.g. after having manually fixed-up the files). The default is
4890 (e.g. after having manually fixed-up the files). The default is
4891 to mark all unresolved files.
4891 to mark all unresolved files.
4892
4892
4893 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4893 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4894 default is to mark all resolved files.
4894 default is to mark all resolved files.
4895
4895
4896 - :hg:`resolve -l`: list files which had or still have conflicts.
4896 - :hg:`resolve -l`: list files which had or still have conflicts.
4897 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4897 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4898
4898
4899 Note that Mercurial will not let you commit files with unresolved
4899 Note that Mercurial will not let you commit files with unresolved
4900 merge conflicts. You must use :hg:`resolve -m ...` before you can
4900 merge conflicts. You must use :hg:`resolve -m ...` before you can
4901 commit after a conflicting merge.
4901 commit after a conflicting merge.
4902
4902
4903 Returns 0 on success, 1 if any files fail a resolve attempt.
4903 Returns 0 on success, 1 if any files fail a resolve attempt.
4904 """
4904 """
4905
4905
4906 all, mark, unmark, show, nostatus = \
4906 all, mark, unmark, show, nostatus = \
4907 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4907 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4908
4908
4909 if (show and (mark or unmark)) or (mark and unmark):
4909 if (show and (mark or unmark)) or (mark and unmark):
4910 raise util.Abort(_("too many options specified"))
4910 raise util.Abort(_("too many options specified"))
4911 if pats and all:
4911 if pats and all:
4912 raise util.Abort(_("can't specify --all and patterns"))
4912 raise util.Abort(_("can't specify --all and patterns"))
4913 if not (all or pats or show or mark or unmark):
4913 if not (all or pats or show or mark or unmark):
4914 raise util.Abort(_('no files or directories specified; '
4914 raise util.Abort(_('no files or directories specified; '
4915 'use --all to remerge all files'))
4915 'use --all to remerge all files'))
4916
4916
4917 ms = mergemod.mergestate(repo)
4917 ms = mergemod.mergestate(repo)
4918 m = scmutil.match(repo[None], pats, opts)
4918 m = scmutil.match(repo[None], pats, opts)
4919 ret = 0
4919 ret = 0
4920
4920
4921 for f in ms:
4921 for f in ms:
4922 if m(f):
4922 if m(f):
4923 if show:
4923 if show:
4924 if nostatus:
4924 if nostatus:
4925 ui.write("%s\n" % f)
4925 ui.write("%s\n" % f)
4926 else:
4926 else:
4927 ui.write("%s %s\n" % (ms[f].upper(), f),
4927 ui.write("%s %s\n" % (ms[f].upper(), f),
4928 label='resolve.' +
4928 label='resolve.' +
4929 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4929 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4930 elif mark:
4930 elif mark:
4931 ms.mark(f, "r")
4931 ms.mark(f, "r")
4932 elif unmark:
4932 elif unmark:
4933 ms.mark(f, "u")
4933 ms.mark(f, "u")
4934 else:
4934 else:
4935 wctx = repo[None]
4935 wctx = repo[None]
4936 mctx = wctx.parents()[-1]
4936 mctx = wctx.parents()[-1]
4937
4937
4938 # backup pre-resolve (merge uses .orig for its own purposes)
4938 # backup pre-resolve (merge uses .orig for its own purposes)
4939 a = repo.wjoin(f)
4939 a = repo.wjoin(f)
4940 util.copyfile(a, a + ".resolve")
4940 util.copyfile(a, a + ".resolve")
4941
4941
4942 try:
4942 try:
4943 # resolve file
4943 # resolve file
4944 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4944 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4945 if ms.resolve(f, wctx, mctx):
4945 if ms.resolve(f, wctx, mctx):
4946 ret = 1
4946 ret = 1
4947 finally:
4947 finally:
4948 ui.setconfig('ui', 'forcemerge', '')
4948 ui.setconfig('ui', 'forcemerge', '')
4949 ms.commit()
4949 ms.commit()
4950
4950
4951 # replace filemerge's .orig file with our resolve file
4951 # replace filemerge's .orig file with our resolve file
4952 util.rename(a + ".resolve", a + ".orig")
4952 util.rename(a + ".resolve", a + ".orig")
4953
4953
4954 ms.commit()
4954 ms.commit()
4955 return ret
4955 return ret
4956
4956
4957 @command('revert',
4957 @command('revert',
4958 [('a', 'all', None, _('revert all changes when no arguments given')),
4958 [('a', 'all', None, _('revert all changes when no arguments given')),
4959 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4959 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4960 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4960 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4961 ('C', 'no-backup', None, _('do not save backup copies of files')),
4961 ('C', 'no-backup', None, _('do not save backup copies of files')),
4962 ] + walkopts + dryrunopts,
4962 ] + walkopts + dryrunopts,
4963 _('[OPTION]... [-r REV] [NAME]...'))
4963 _('[OPTION]... [-r REV] [NAME]...'))
4964 def revert(ui, repo, *pats, **opts):
4964 def revert(ui, repo, *pats, **opts):
4965 """restore files to their checkout state
4965 """restore files to their checkout state
4966
4966
4967 .. note::
4967 .. note::
4968
4968
4969 To check out earlier revisions, you should use :hg:`update REV`.
4969 To check out earlier revisions, you should use :hg:`update REV`.
4970 To cancel an uncommitted merge (and lose your changes),
4970 To cancel an uncommitted merge (and lose your changes),
4971 use :hg:`update --clean .`.
4971 use :hg:`update --clean .`.
4972
4972
4973 With no revision specified, revert the specified files or directories
4973 With no revision specified, revert the specified files or directories
4974 to the contents they had in the parent of the working directory.
4974 to the contents they had in the parent of the working directory.
4975 This restores the contents of files to an unmodified
4975 This restores the contents of files to an unmodified
4976 state and unschedules adds, removes, copies, and renames. If the
4976 state and unschedules adds, removes, copies, and renames. If the
4977 working directory has two parents, you must explicitly specify a
4977 working directory has two parents, you must explicitly specify a
4978 revision.
4978 revision.
4979
4979
4980 Using the -r/--rev or -d/--date options, revert the given files or
4980 Using the -r/--rev or -d/--date options, revert the given files or
4981 directories to their states as of a specific revision. Because
4981 directories to their states as of a specific revision. Because
4982 revert does not change the working directory parents, this will
4982 revert does not change the working directory parents, this will
4983 cause these files to appear modified. This can be helpful to "back
4983 cause these files to appear modified. This can be helpful to "back
4984 out" some or all of an earlier change. See :hg:`backout` for a
4984 out" some or all of an earlier change. See :hg:`backout` for a
4985 related method.
4985 related method.
4986
4986
4987 Modified files are saved with a .orig suffix before reverting.
4987 Modified files are saved with a .orig suffix before reverting.
4988 To disable these backups, use --no-backup.
4988 To disable these backups, use --no-backup.
4989
4989
4990 See :hg:`help dates` for a list of formats valid for -d/--date.
4990 See :hg:`help dates` for a list of formats valid for -d/--date.
4991
4991
4992 Returns 0 on success.
4992 Returns 0 on success.
4993 """
4993 """
4994
4994
4995 if opts.get("date"):
4995 if opts.get("date"):
4996 if opts.get("rev"):
4996 if opts.get("rev"):
4997 raise util.Abort(_("you can't specify a revision and a date"))
4997 raise util.Abort(_("you can't specify a revision and a date"))
4998 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4998 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4999
4999
5000 parent, p2 = repo.dirstate.parents()
5000 parent, p2 = repo.dirstate.parents()
5001 if not opts.get('rev') and p2 != nullid:
5001 if not opts.get('rev') and p2 != nullid:
5002 # revert after merge is a trap for new users (issue2915)
5002 # revert after merge is a trap for new users (issue2915)
5003 raise util.Abort(_('uncommitted merge with no revision specified'),
5003 raise util.Abort(_('uncommitted merge with no revision specified'),
5004 hint=_('use "hg update" or see "hg help revert"'))
5004 hint=_('use "hg update" or see "hg help revert"'))
5005
5005
5006 ctx = scmutil.revsingle(repo, opts.get('rev'))
5006 ctx = scmutil.revsingle(repo, opts.get('rev'))
5007
5007
5008 if not pats and not opts.get('all'):
5008 if not pats and not opts.get('all'):
5009 msg = _("no files or directories specified")
5009 msg = _("no files or directories specified")
5010 if p2 != nullid:
5010 if p2 != nullid:
5011 hint = _("uncommitted merge, use --all to discard all changes,"
5011 hint = _("uncommitted merge, use --all to discard all changes,"
5012 " or 'hg update -C .' to abort the merge")
5012 " or 'hg update -C .' to abort the merge")
5013 raise util.Abort(msg, hint=hint)
5013 raise util.Abort(msg, hint=hint)
5014 dirty = util.any(repo.status())
5014 dirty = util.any(repo.status())
5015 node = ctx.node()
5015 node = ctx.node()
5016 if node != parent:
5016 if node != parent:
5017 if dirty:
5017 if dirty:
5018 hint = _("uncommitted changes, use --all to discard all"
5018 hint = _("uncommitted changes, use --all to discard all"
5019 " changes, or 'hg update %s' to update") % ctx.rev()
5019 " changes, or 'hg update %s' to update") % ctx.rev()
5020 else:
5020 else:
5021 hint = _("use --all to revert all files,"
5021 hint = _("use --all to revert all files,"
5022 " or 'hg update %s' to update") % ctx.rev()
5022 " or 'hg update %s' to update") % ctx.rev()
5023 elif dirty:
5023 elif dirty:
5024 hint = _("uncommitted changes, use --all to discard all changes")
5024 hint = _("uncommitted changes, use --all to discard all changes")
5025 else:
5025 else:
5026 hint = _("use --all to revert all files")
5026 hint = _("use --all to revert all files")
5027 raise util.Abort(msg, hint=hint)
5027 raise util.Abort(msg, hint=hint)
5028
5028
5029 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5029 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5030
5030
5031 @command('rollback', dryrunopts +
5031 @command('rollback', dryrunopts +
5032 [('f', 'force', False, _('ignore safety measures'))])
5032 [('f', 'force', False, _('ignore safety measures'))])
5033 def rollback(ui, repo, **opts):
5033 def rollback(ui, repo, **opts):
5034 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5034 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5035
5035
5036 Please use :hg:`commit --amend` instead of rollback to correct
5036 Please use :hg:`commit --amend` instead of rollback to correct
5037 mistakes in the last commit.
5037 mistakes in the last commit.
5038
5038
5039 This command should be used with care. There is only one level of
5039 This command should be used with care. There is only one level of
5040 rollback, and there is no way to undo a rollback. It will also
5040 rollback, and there is no way to undo a rollback. It will also
5041 restore the dirstate at the time of the last transaction, losing
5041 restore the dirstate at the time of the last transaction, losing
5042 any dirstate changes since that time. This command does not alter
5042 any dirstate changes since that time. This command does not alter
5043 the working directory.
5043 the working directory.
5044
5044
5045 Transactions are used to encapsulate the effects of all commands
5045 Transactions are used to encapsulate the effects of all commands
5046 that create new changesets or propagate existing changesets into a
5046 that create new changesets or propagate existing changesets into a
5047 repository.
5047 repository.
5048
5048
5049 .. container:: verbose
5049 .. container:: verbose
5050
5050
5051 For example, the following commands are transactional, and their
5051 For example, the following commands are transactional, and their
5052 effects can be rolled back:
5052 effects can be rolled back:
5053
5053
5054 - commit
5054 - commit
5055 - import
5055 - import
5056 - pull
5056 - pull
5057 - push (with this repository as the destination)
5057 - push (with this repository as the destination)
5058 - unbundle
5058 - unbundle
5059
5059
5060 To avoid permanent data loss, rollback will refuse to rollback a
5060 To avoid permanent data loss, rollback will refuse to rollback a
5061 commit transaction if it isn't checked out. Use --force to
5061 commit transaction if it isn't checked out. Use --force to
5062 override this protection.
5062 override this protection.
5063
5063
5064 This command is not intended for use on public repositories. Once
5064 This command is not intended for use on public repositories. Once
5065 changes are visible for pull by other users, rolling a transaction
5065 changes are visible for pull by other users, rolling a transaction
5066 back locally is ineffective (someone else may already have pulled
5066 back locally is ineffective (someone else may already have pulled
5067 the changes). Furthermore, a race is possible with readers of the
5067 the changes). Furthermore, a race is possible with readers of the
5068 repository; for example an in-progress pull from the repository
5068 repository; for example an in-progress pull from the repository
5069 may fail if a rollback is performed.
5069 may fail if a rollback is performed.
5070
5070
5071 Returns 0 on success, 1 if no rollback data is available.
5071 Returns 0 on success, 1 if no rollback data is available.
5072 """
5072 """
5073 return repo.rollback(dryrun=opts.get('dry_run'),
5073 return repo.rollback(dryrun=opts.get('dry_run'),
5074 force=opts.get('force'))
5074 force=opts.get('force'))
5075
5075
5076 @command('root', [])
5076 @command('root', [])
5077 def root(ui, repo):
5077 def root(ui, repo):
5078 """print the root (top) of the current working directory
5078 """print the root (top) of the current working directory
5079
5079
5080 Print the root directory of the current repository.
5080 Print the root directory of the current repository.
5081
5081
5082 Returns 0 on success.
5082 Returns 0 on success.
5083 """
5083 """
5084 ui.write(repo.root + "\n")
5084 ui.write(repo.root + "\n")
5085
5085
5086 @command('^serve',
5086 @command('^serve',
5087 [('A', 'accesslog', '', _('name of access log file to write to'),
5087 [('A', 'accesslog', '', _('name of access log file to write to'),
5088 _('FILE')),
5088 _('FILE')),
5089 ('d', 'daemon', None, _('run server in background')),
5089 ('d', 'daemon', None, _('run server in background')),
5090 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5090 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5091 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5091 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5092 # use string type, then we can check if something was passed
5092 # use string type, then we can check if something was passed
5093 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5093 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5094 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5094 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5095 _('ADDR')),
5095 _('ADDR')),
5096 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5096 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5097 _('PREFIX')),
5097 _('PREFIX')),
5098 ('n', 'name', '',
5098 ('n', 'name', '',
5099 _('name to show in web pages (default: working directory)'), _('NAME')),
5099 _('name to show in web pages (default: working directory)'), _('NAME')),
5100 ('', 'web-conf', '',
5100 ('', 'web-conf', '',
5101 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5101 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5102 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5102 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5103 _('FILE')),
5103 _('FILE')),
5104 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5104 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5105 ('', 'stdio', None, _('for remote clients')),
5105 ('', 'stdio', None, _('for remote clients')),
5106 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5106 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5107 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5107 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5108 ('', 'style', '', _('template style to use'), _('STYLE')),
5108 ('', 'style', '', _('template style to use'), _('STYLE')),
5109 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5109 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5110 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5110 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5111 _('[OPTION]...'))
5111 _('[OPTION]...'))
5112 def serve(ui, repo, **opts):
5112 def serve(ui, repo, **opts):
5113 """start stand-alone webserver
5113 """start stand-alone webserver
5114
5114
5115 Start a local HTTP repository browser and pull server. You can use
5115 Start a local HTTP repository browser and pull server. You can use
5116 this for ad-hoc sharing and browsing of repositories. It is
5116 this for ad-hoc sharing and browsing of repositories. It is
5117 recommended to use a real web server to serve a repository for
5117 recommended to use a real web server to serve a repository for
5118 longer periods of time.
5118 longer periods of time.
5119
5119
5120 Please note that the server does not implement access control.
5120 Please note that the server does not implement access control.
5121 This means that, by default, anybody can read from the server and
5121 This means that, by default, anybody can read from the server and
5122 nobody can write to it by default. Set the ``web.allow_push``
5122 nobody can write to it by default. Set the ``web.allow_push``
5123 option to ``*`` to allow everybody to push to the server. You
5123 option to ``*`` to allow everybody to push to the server. You
5124 should use a real web server if you need to authenticate users.
5124 should use a real web server if you need to authenticate users.
5125
5125
5126 By default, the server logs accesses to stdout and errors to
5126 By default, the server logs accesses to stdout and errors to
5127 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5127 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5128 files.
5128 files.
5129
5129
5130 To have the server choose a free port number to listen on, specify
5130 To have the server choose a free port number to listen on, specify
5131 a port number of 0; in this case, the server will print the port
5131 a port number of 0; in this case, the server will print the port
5132 number it uses.
5132 number it uses.
5133
5133
5134 Returns 0 on success.
5134 Returns 0 on success.
5135 """
5135 """
5136
5136
5137 if opts["stdio"] and opts["cmdserver"]:
5137 if opts["stdio"] and opts["cmdserver"]:
5138 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5138 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5139
5139
5140 def checkrepo():
5140 def checkrepo():
5141 if repo is None:
5141 if repo is None:
5142 raise error.RepoError(_("there is no Mercurial repository here"
5142 raise error.RepoError(_("there is no Mercurial repository here"
5143 " (.hg not found)"))
5143 " (.hg not found)"))
5144
5144
5145 if opts["stdio"]:
5145 if opts["stdio"]:
5146 checkrepo()
5146 checkrepo()
5147 s = sshserver.sshserver(ui, repo)
5147 s = sshserver.sshserver(ui, repo)
5148 s.serve_forever()
5148 s.serve_forever()
5149
5149
5150 if opts["cmdserver"]:
5150 if opts["cmdserver"]:
5151 checkrepo()
5151 checkrepo()
5152 s = commandserver.server(ui, repo, opts["cmdserver"])
5152 s = commandserver.server(ui, repo, opts["cmdserver"])
5153 return s.serve()
5153 return s.serve()
5154
5154
5155 # this way we can check if something was given in the command-line
5155 # this way we can check if something was given in the command-line
5156 if opts.get('port'):
5156 if opts.get('port'):
5157 opts['port'] = util.getport(opts.get('port'))
5157 opts['port'] = util.getport(opts.get('port'))
5158
5158
5159 baseui = repo and repo.baseui or ui
5159 baseui = repo and repo.baseui or ui
5160 optlist = ("name templates style address port prefix ipv6"
5160 optlist = ("name templates style address port prefix ipv6"
5161 " accesslog errorlog certificate encoding")
5161 " accesslog errorlog certificate encoding")
5162 for o in optlist.split():
5162 for o in optlist.split():
5163 val = opts.get(o, '')
5163 val = opts.get(o, '')
5164 if val in (None, ''): # should check against default options instead
5164 if val in (None, ''): # should check against default options instead
5165 continue
5165 continue
5166 baseui.setconfig("web", o, val)
5166 baseui.setconfig("web", o, val)
5167 if repo and repo.ui != baseui:
5167 if repo and repo.ui != baseui:
5168 repo.ui.setconfig("web", o, val)
5168 repo.ui.setconfig("web", o, val)
5169
5169
5170 o = opts.get('web_conf') or opts.get('webdir_conf')
5170 o = opts.get('web_conf') or opts.get('webdir_conf')
5171 if not o:
5171 if not o:
5172 if not repo:
5172 if not repo:
5173 raise error.RepoError(_("there is no Mercurial repository"
5173 raise error.RepoError(_("there is no Mercurial repository"
5174 " here (.hg not found)"))
5174 " here (.hg not found)"))
5175 o = repo
5175 o = repo
5176
5176
5177 app = hgweb.hgweb(o, baseui=baseui)
5177 app = hgweb.hgweb(o, baseui=baseui)
5178 service = httpservice(ui, app, opts)
5178 service = httpservice(ui, app, opts)
5179 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5179 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5180
5180
5181 class httpservice(object):
5181 class httpservice(object):
5182 def __init__(self, ui, app, opts):
5182 def __init__(self, ui, app, opts):
5183 self.ui = ui
5183 self.ui = ui
5184 self.app = app
5184 self.app = app
5185 self.opts = opts
5185 self.opts = opts
5186
5186
5187 def init(self):
5187 def init(self):
5188 util.setsignalhandler()
5188 util.setsignalhandler()
5189 self.httpd = hgweb_server.create_server(self.ui, self.app)
5189 self.httpd = hgweb_server.create_server(self.ui, self.app)
5190
5190
5191 if self.opts['port'] and not self.ui.verbose:
5191 if self.opts['port'] and not self.ui.verbose:
5192 return
5192 return
5193
5193
5194 if self.httpd.prefix:
5194 if self.httpd.prefix:
5195 prefix = self.httpd.prefix.strip('/') + '/'
5195 prefix = self.httpd.prefix.strip('/') + '/'
5196 else:
5196 else:
5197 prefix = ''
5197 prefix = ''
5198
5198
5199 port = ':%d' % self.httpd.port
5199 port = ':%d' % self.httpd.port
5200 if port == ':80':
5200 if port == ':80':
5201 port = ''
5201 port = ''
5202
5202
5203 bindaddr = self.httpd.addr
5203 bindaddr = self.httpd.addr
5204 if bindaddr == '0.0.0.0':
5204 if bindaddr == '0.0.0.0':
5205 bindaddr = '*'
5205 bindaddr = '*'
5206 elif ':' in bindaddr: # IPv6
5206 elif ':' in bindaddr: # IPv6
5207 bindaddr = '[%s]' % bindaddr
5207 bindaddr = '[%s]' % bindaddr
5208
5208
5209 fqaddr = self.httpd.fqaddr
5209 fqaddr = self.httpd.fqaddr
5210 if ':' in fqaddr:
5210 if ':' in fqaddr:
5211 fqaddr = '[%s]' % fqaddr
5211 fqaddr = '[%s]' % fqaddr
5212 if self.opts['port']:
5212 if self.opts['port']:
5213 write = self.ui.status
5213 write = self.ui.status
5214 else:
5214 else:
5215 write = self.ui.write
5215 write = self.ui.write
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5218
5218
5219 def run(self):
5219 def run(self):
5220 self.httpd.serve_forever()
5220 self.httpd.serve_forever()
5221
5221
5222
5222
5223 @command('showconfig|debugconfig',
5223 @command('showconfig|debugconfig',
5224 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5224 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5225 _('[-u] [NAME]...'))
5225 _('[-u] [NAME]...'))
5226 def showconfig(ui, repo, *values, **opts):
5226 def showconfig(ui, repo, *values, **opts):
5227 """show combined config settings from all hgrc files
5227 """show combined config settings from all hgrc files
5228
5228
5229 With no arguments, print names and values of all config items.
5229 With no arguments, print names and values of all config items.
5230
5230
5231 With one argument of the form section.name, print just the value
5231 With one argument of the form section.name, print just the value
5232 of that config item.
5232 of that config item.
5233
5233
5234 With multiple arguments, print names and values of all config
5234 With multiple arguments, print names and values of all config
5235 items with matching section names.
5235 items with matching section names.
5236
5236
5237 With --debug, the source (filename and line number) is printed
5237 With --debug, the source (filename and line number) is printed
5238 for each config item.
5238 for each config item.
5239
5239
5240 Returns 0 on success.
5240 Returns 0 on success.
5241 """
5241 """
5242
5242
5243 for f in scmutil.rcpath():
5243 for f in scmutil.rcpath():
5244 ui.debug('read config from: %s\n' % f)
5244 ui.debug('read config from: %s\n' % f)
5245 untrusted = bool(opts.get('untrusted'))
5245 untrusted = bool(opts.get('untrusted'))
5246 if values:
5246 if values:
5247 sections = [v for v in values if '.' not in v]
5247 sections = [v for v in values if '.' not in v]
5248 items = [v for v in values if '.' in v]
5248 items = [v for v in values if '.' in v]
5249 if len(items) > 1 or items and sections:
5249 if len(items) > 1 or items and sections:
5250 raise util.Abort(_('only one config item permitted'))
5250 raise util.Abort(_('only one config item permitted'))
5251 for section, name, value in ui.walkconfig(untrusted=untrusted):
5251 for section, name, value in ui.walkconfig(untrusted=untrusted):
5252 value = str(value).replace('\n', '\\n')
5252 value = str(value).replace('\n', '\\n')
5253 sectname = section + '.' + name
5253 sectname = section + '.' + name
5254 if values:
5254 if values:
5255 for v in values:
5255 for v in values:
5256 if v == section:
5256 if v == section:
5257 ui.debug('%s: ' %
5257 ui.debug('%s: ' %
5258 ui.configsource(section, name, untrusted))
5258 ui.configsource(section, name, untrusted))
5259 ui.write('%s=%s\n' % (sectname, value))
5259 ui.write('%s=%s\n' % (sectname, value))
5260 elif v == sectname:
5260 elif v == sectname:
5261 ui.debug('%s: ' %
5261 ui.debug('%s: ' %
5262 ui.configsource(section, name, untrusted))
5262 ui.configsource(section, name, untrusted))
5263 ui.write(value, '\n')
5263 ui.write(value, '\n')
5264 else:
5264 else:
5265 ui.debug('%s: ' %
5265 ui.debug('%s: ' %
5266 ui.configsource(section, name, untrusted))
5266 ui.configsource(section, name, untrusted))
5267 ui.write('%s=%s\n' % (sectname, value))
5267 ui.write('%s=%s\n' % (sectname, value))
5268
5268
5269 @command('^status|st',
5269 @command('^status|st',
5270 [('A', 'all', None, _('show status of all files')),
5270 [('A', 'all', None, _('show status of all files')),
5271 ('m', 'modified', None, _('show only modified files')),
5271 ('m', 'modified', None, _('show only modified files')),
5272 ('a', 'added', None, _('show only added files')),
5272 ('a', 'added', None, _('show only added files')),
5273 ('r', 'removed', None, _('show only removed files')),
5273 ('r', 'removed', None, _('show only removed files')),
5274 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5274 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5275 ('c', 'clean', None, _('show only files without changes')),
5275 ('c', 'clean', None, _('show only files without changes')),
5276 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5276 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5277 ('i', 'ignored', None, _('show only ignored files')),
5277 ('i', 'ignored', None, _('show only ignored files')),
5278 ('n', 'no-status', None, _('hide status prefix')),
5278 ('n', 'no-status', None, _('hide status prefix')),
5279 ('C', 'copies', None, _('show source of copied files')),
5279 ('C', 'copies', None, _('show source of copied files')),
5280 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5280 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5281 ('', 'rev', [], _('show difference from revision'), _('REV')),
5281 ('', 'rev', [], _('show difference from revision'), _('REV')),
5282 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5282 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5283 ] + walkopts + subrepoopts,
5283 ] + walkopts + subrepoopts,
5284 _('[OPTION]... [FILE]...'))
5284 _('[OPTION]... [FILE]...'))
5285 def status(ui, repo, *pats, **opts):
5285 def status(ui, repo, *pats, **opts):
5286 """show changed files in the working directory
5286 """show changed files in the working directory
5287
5287
5288 Show status of files in the repository. If names are given, only
5288 Show status of files in the repository. If names are given, only
5289 files that match are shown. Files that are clean or ignored or
5289 files that match are shown. Files that are clean or ignored or
5290 the source of a copy/move operation, are not listed unless
5290 the source of a copy/move operation, are not listed unless
5291 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5291 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5292 Unless options described with "show only ..." are given, the
5292 Unless options described with "show only ..." are given, the
5293 options -mardu are used.
5293 options -mardu are used.
5294
5294
5295 Option -q/--quiet hides untracked (unknown and ignored) files
5295 Option -q/--quiet hides untracked (unknown and ignored) files
5296 unless explicitly requested with -u/--unknown or -i/--ignored.
5296 unless explicitly requested with -u/--unknown or -i/--ignored.
5297
5297
5298 .. note::
5298 .. note::
5299
5299
5300 status may appear to disagree with diff if permissions have
5300 status may appear to disagree with diff if permissions have
5301 changed or a merge has occurred. The standard diff format does
5301 changed or a merge has occurred. The standard diff format does
5302 not report permission changes and diff only reports changes
5302 not report permission changes and diff only reports changes
5303 relative to one merge parent.
5303 relative to one merge parent.
5304
5304
5305 If one revision is given, it is used as the base revision.
5305 If one revision is given, it is used as the base revision.
5306 If two revisions are given, the differences between them are
5306 If two revisions are given, the differences between them are
5307 shown. The --change option can also be used as a shortcut to list
5307 shown. The --change option can also be used as a shortcut to list
5308 the changed files of a revision from its first parent.
5308 the changed files of a revision from its first parent.
5309
5309
5310 The codes used to show the status of files are::
5310 The codes used to show the status of files are::
5311
5311
5312 M = modified
5312 M = modified
5313 A = added
5313 A = added
5314 R = removed
5314 R = removed
5315 C = clean
5315 C = clean
5316 ! = missing (deleted by non-hg command, but still tracked)
5316 ! = missing (deleted by non-hg command, but still tracked)
5317 ? = not tracked
5317 ? = not tracked
5318 I = ignored
5318 I = ignored
5319 = origin of the previous file listed as A (added)
5319 = origin of the previous file listed as A (added)
5320
5320
5321 .. container:: verbose
5321 .. container:: verbose
5322
5322
5323 Examples:
5323 Examples:
5324
5324
5325 - show changes in the working directory relative to a
5325 - show changes in the working directory relative to a
5326 changeset::
5326 changeset::
5327
5327
5328 hg status --rev 9353
5328 hg status --rev 9353
5329
5329
5330 - show all changes including copies in an existing changeset::
5330 - show all changes including copies in an existing changeset::
5331
5331
5332 hg status --copies --change 9353
5332 hg status --copies --change 9353
5333
5333
5334 - get a NUL separated list of added files, suitable for xargs::
5334 - get a NUL separated list of added files, suitable for xargs::
5335
5335
5336 hg status -an0
5336 hg status -an0
5337
5337
5338 Returns 0 on success.
5338 Returns 0 on success.
5339 """
5339 """
5340
5340
5341 revs = opts.get('rev')
5341 revs = opts.get('rev')
5342 change = opts.get('change')
5342 change = opts.get('change')
5343
5343
5344 if revs and change:
5344 if revs and change:
5345 msg = _('cannot specify --rev and --change at the same time')
5345 msg = _('cannot specify --rev and --change at the same time')
5346 raise util.Abort(msg)
5346 raise util.Abort(msg)
5347 elif change:
5347 elif change:
5348 node2 = scmutil.revsingle(repo, change, None).node()
5348 node2 = scmutil.revsingle(repo, change, None).node()
5349 node1 = repo[node2].p1().node()
5349 node1 = repo[node2].p1().node()
5350 else:
5350 else:
5351 node1, node2 = scmutil.revpair(repo, revs)
5351 node1, node2 = scmutil.revpair(repo, revs)
5352
5352
5353 cwd = (pats and repo.getcwd()) or ''
5353 cwd = (pats and repo.getcwd()) or ''
5354 end = opts.get('print0') and '\0' or '\n'
5354 end = opts.get('print0') and '\0' or '\n'
5355 copy = {}
5355 copy = {}
5356 states = 'modified added removed deleted unknown ignored clean'.split()
5356 states = 'modified added removed deleted unknown ignored clean'.split()
5357 show = [k for k in states if opts.get(k)]
5357 show = [k for k in states if opts.get(k)]
5358 if opts.get('all'):
5358 if opts.get('all'):
5359 show += ui.quiet and (states[:4] + ['clean']) or states
5359 show += ui.quiet and (states[:4] + ['clean']) or states
5360 if not show:
5360 if not show:
5361 show = ui.quiet and states[:4] or states[:5]
5361 show = ui.quiet and states[:4] or states[:5]
5362
5362
5363 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5363 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5364 'ignored' in show, 'clean' in show, 'unknown' in show,
5364 'ignored' in show, 'clean' in show, 'unknown' in show,
5365 opts.get('subrepos'))
5365 opts.get('subrepos'))
5366 changestates = zip(states, 'MAR!?IC', stat)
5366 changestates = zip(states, 'MAR!?IC', stat)
5367
5367
5368 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5368 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5369 copy = copies.pathcopies(repo[node1], repo[node2])
5369 copy = copies.pathcopies(repo[node1], repo[node2])
5370
5370
5371 fm = ui.formatter('status', opts)
5371 fm = ui.formatter('status', opts)
5372 fmt = '%s' + end
5372 fmt = '%s' + end
5373 showchar = not opts.get('no_status')
5373 showchar = not opts.get('no_status')
5374
5374
5375 for state, char, files in changestates:
5375 for state, char, files in changestates:
5376 if state in show:
5376 if state in show:
5377 label = 'status.' + state
5377 label = 'status.' + state
5378 for f in files:
5378 for f in files:
5379 fm.startitem()
5379 fm.startitem()
5380 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5380 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5381 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5381 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5382 if f in copy:
5382 if f in copy:
5383 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5383 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5384 label='status.copied')
5384 label='status.copied')
5385 fm.end()
5385 fm.end()
5386
5386
5387 @command('^summary|sum',
5387 @command('^summary|sum',
5388 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5388 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5389 def summary(ui, repo, **opts):
5389 def summary(ui, repo, **opts):
5390 """summarize working directory state
5390 """summarize working directory state
5391
5391
5392 This generates a brief summary of the working directory state,
5392 This generates a brief summary of the working directory state,
5393 including parents, branch, commit status, and available updates.
5393 including parents, branch, commit status, and available updates.
5394
5394
5395 With the --remote option, this will check the default paths for
5395 With the --remote option, this will check the default paths for
5396 incoming and outgoing changes. This can be time-consuming.
5396 incoming and outgoing changes. This can be time-consuming.
5397
5397
5398 Returns 0 on success.
5398 Returns 0 on success.
5399 """
5399 """
5400
5400
5401 ctx = repo[None]
5401 ctx = repo[None]
5402 parents = ctx.parents()
5402 parents = ctx.parents()
5403 pnode = parents[0].node()
5403 pnode = parents[0].node()
5404 marks = []
5404 marks = []
5405
5405
5406 for p in parents:
5406 for p in parents:
5407 # label with log.changeset (instead of log.parent) since this
5407 # label with log.changeset (instead of log.parent) since this
5408 # shows a working directory parent *changeset*:
5408 # shows a working directory parent *changeset*:
5409 # i18n: column positioning for "hg summary"
5409 # i18n: column positioning for "hg summary"
5410 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5410 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5411 label='log.changeset changeset.%s' % p.phasestr())
5411 label='log.changeset changeset.%s' % p.phasestr())
5412 ui.write(' '.join(p.tags()), label='log.tag')
5412 ui.write(' '.join(p.tags()), label='log.tag')
5413 if p.bookmarks():
5413 if p.bookmarks():
5414 marks.extend(p.bookmarks())
5414 marks.extend(p.bookmarks())
5415 if p.rev() == -1:
5415 if p.rev() == -1:
5416 if not len(repo):
5416 if not len(repo):
5417 ui.write(_(' (empty repository)'))
5417 ui.write(_(' (empty repository)'))
5418 else:
5418 else:
5419 ui.write(_(' (no revision checked out)'))
5419 ui.write(_(' (no revision checked out)'))
5420 ui.write('\n')
5420 ui.write('\n')
5421 if p.description():
5421 if p.description():
5422 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5422 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5423 label='log.summary')
5423 label='log.summary')
5424
5424
5425 branch = ctx.branch()
5425 branch = ctx.branch()
5426 bheads = repo.branchheads(branch)
5426 bheads = repo.branchheads(branch)
5427 # i18n: column positioning for "hg summary"
5427 # i18n: column positioning for "hg summary"
5428 m = _('branch: %s\n') % branch
5428 m = _('branch: %s\n') % branch
5429 if branch != 'default':
5429 if branch != 'default':
5430 ui.write(m, label='log.branch')
5430 ui.write(m, label='log.branch')
5431 else:
5431 else:
5432 ui.status(m, label='log.branch')
5432 ui.status(m, label='log.branch')
5433
5433
5434 if marks:
5434 if marks:
5435 current = repo._bookmarkcurrent
5435 current = repo._bookmarkcurrent
5436 # i18n: column positioning for "hg summary"
5436 # i18n: column positioning for "hg summary"
5437 ui.write(_('bookmarks:'), label='log.bookmark')
5437 ui.write(_('bookmarks:'), label='log.bookmark')
5438 if current is not None:
5438 if current is not None:
5439 if current in marks:
5439 if current in marks:
5440 ui.write(' *' + current, label='bookmarks.current')
5440 ui.write(' *' + current, label='bookmarks.current')
5441 marks.remove(current)
5441 marks.remove(current)
5442 else:
5442 else:
5443 ui.write(' [%s]' % current, label='bookmarks.current')
5443 ui.write(' [%s]' % current, label='bookmarks.current')
5444 for m in marks:
5444 for m in marks:
5445 ui.write(' ' + m, label='log.bookmark')
5445 ui.write(' ' + m, label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5447
5447
5448 st = list(repo.status(unknown=True))[:6]
5448 st = list(repo.status(unknown=True))[:6]
5449
5449
5450 c = repo.dirstate.copies()
5450 c = repo.dirstate.copies()
5451 copied, renamed = [], []
5451 copied, renamed = [], []
5452 for d, s in c.iteritems():
5452 for d, s in c.iteritems():
5453 if s in st[2]:
5453 if s in st[2]:
5454 st[2].remove(s)
5454 st[2].remove(s)
5455 renamed.append(d)
5455 renamed.append(d)
5456 else:
5456 else:
5457 copied.append(d)
5457 copied.append(d)
5458 if d in st[1]:
5458 if d in st[1]:
5459 st[1].remove(d)
5459 st[1].remove(d)
5460 st.insert(3, renamed)
5460 st.insert(3, renamed)
5461 st.insert(4, copied)
5461 st.insert(4, copied)
5462
5462
5463 ms = mergemod.mergestate(repo)
5463 ms = mergemod.mergestate(repo)
5464 st.append([f for f in ms if ms[f] == 'u'])
5464 st.append([f for f in ms if ms[f] == 'u'])
5465
5465
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5467 st.append(subs)
5467 st.append(subs)
5468
5468
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5470 ui.label(_('%d added'), 'status.added'),
5470 ui.label(_('%d added'), 'status.added'),
5471 ui.label(_('%d removed'), 'status.removed'),
5471 ui.label(_('%d removed'), 'status.removed'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5478 ui.label(_('%d subrepos'), 'status.modified')]
5478 ui.label(_('%d subrepos'), 'status.modified')]
5479 t = []
5479 t = []
5480 for s, l in zip(st, labels):
5480 for s, l in zip(st, labels):
5481 if s:
5481 if s:
5482 t.append(l % len(s))
5482 t.append(l % len(s))
5483
5483
5484 t = ', '.join(t)
5484 t = ', '.join(t)
5485 cleanworkdir = False
5485 cleanworkdir = False
5486
5486
5487 if repo.vfs.exists('updatestate'):
5487 if repo.vfs.exists('updatestate'):
5488 t += _(' (interrupted update)')
5488 t += _(' (interrupted update)')
5489 elif len(parents) > 1:
5489 elif len(parents) > 1:
5490 t += _(' (merge)')
5490 t += _(' (merge)')
5491 elif branch != parents[0].branch():
5491 elif branch != parents[0].branch():
5492 t += _(' (new branch)')
5492 t += _(' (new branch)')
5493 elif (parents[0].closesbranch() and
5493 elif (parents[0].closesbranch() and
5494 pnode in repo.branchheads(branch, closed=True)):
5494 pnode in repo.branchheads(branch, closed=True)):
5495 t += _(' (head closed)')
5495 t += _(' (head closed)')
5496 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5496 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5497 t += _(' (clean)')
5497 t += _(' (clean)')
5498 cleanworkdir = True
5498 cleanworkdir = True
5499 elif pnode not in bheads:
5499 elif pnode not in bheads:
5500 t += _(' (new branch head)')
5500 t += _(' (new branch head)')
5501
5501
5502 if cleanworkdir:
5502 if cleanworkdir:
5503 # i18n: column positioning for "hg summary"
5503 # i18n: column positioning for "hg summary"
5504 ui.status(_('commit: %s\n') % t.strip())
5504 ui.status(_('commit: %s\n') % t.strip())
5505 else:
5505 else:
5506 # i18n: column positioning for "hg summary"
5506 # i18n: column positioning for "hg summary"
5507 ui.write(_('commit: %s\n') % t.strip())
5507 ui.write(_('commit: %s\n') % t.strip())
5508
5508
5509 # all ancestors of branch heads - all ancestors of parent = new csets
5509 # all ancestors of branch heads - all ancestors of parent = new csets
5510 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5510 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5511 bheads))
5511 bheads))
5512
5512
5513 if new == 0:
5513 if new == 0:
5514 # i18n: column positioning for "hg summary"
5514 # i18n: column positioning for "hg summary"
5515 ui.status(_('update: (current)\n'))
5515 ui.status(_('update: (current)\n'))
5516 elif pnode not in bheads:
5516 elif pnode not in bheads:
5517 # i18n: column positioning for "hg summary"
5517 # i18n: column positioning for "hg summary"
5518 ui.write(_('update: %d new changesets (update)\n') % new)
5518 ui.write(_('update: %d new changesets (update)\n') % new)
5519 else:
5519 else:
5520 # i18n: column positioning for "hg summary"
5520 # i18n: column positioning for "hg summary"
5521 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5521 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5522 (new, len(bheads)))
5522 (new, len(bheads)))
5523
5523
5524 cmdutil.summaryhooks(ui, repo)
5524 cmdutil.summaryhooks(ui, repo)
5525
5525
5526 if opts.get('remote'):
5526 if opts.get('remote'):
5527 t = []
5527 t = []
5528 source, branches = hg.parseurl(ui.expandpath('default'))
5528 source, branches = hg.parseurl(ui.expandpath('default'))
5529 sbranch = branches[0]
5529 sbranch = branches[0]
5530 other = hg.peer(repo, {}, source)
5530 other = hg.peer(repo, {}, source)
5531 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5531 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5532 if revs:
5532 if revs:
5533 revs = [other.lookup(rev) for rev in revs]
5533 revs = [other.lookup(rev) for rev in revs]
5534 ui.debug('comparing with %s\n' % util.hidepassword(source))
5534 ui.debug('comparing with %s\n' % util.hidepassword(source))
5535 repo.ui.pushbuffer()
5535 repo.ui.pushbuffer()
5536 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5536 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5537 _common, incoming, _rheads = commoninc
5537 _common, incoming, _rheads = commoninc
5538 repo.ui.popbuffer()
5538 repo.ui.popbuffer()
5539 if incoming:
5539 if incoming:
5540 t.append(_('1 or more incoming'))
5540 t.append(_('1 or more incoming'))
5541
5541
5542 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5542 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5543 dbranch = branches[0]
5543 dbranch = branches[0]
5544 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5544 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5545 if source != dest:
5545 if source != dest:
5546 other = hg.peer(repo, {}, dest)
5546 other = hg.peer(repo, {}, dest)
5547 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5547 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5548 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5548 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5549 commoninc = None
5549 commoninc = None
5550 if revs:
5550 if revs:
5551 revs = [repo.lookup(rev) for rev in revs]
5551 revs = [repo.lookup(rev) for rev in revs]
5552 repo.ui.pushbuffer()
5552 repo.ui.pushbuffer()
5553 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5553 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5554 commoninc=commoninc)
5554 commoninc=commoninc)
5555 repo.ui.popbuffer()
5555 repo.ui.popbuffer()
5556 o = outgoing.missing
5556 o = outgoing.missing
5557 if o:
5557 if o:
5558 t.append(_('%d outgoing') % len(o))
5558 t.append(_('%d outgoing') % len(o))
5559 if 'bookmarks' in other.listkeys('namespaces'):
5559 if 'bookmarks' in other.listkeys('namespaces'):
5560 lmarks = repo.listkeys('bookmarks')
5560 lmarks = repo.listkeys('bookmarks')
5561 rmarks = other.listkeys('bookmarks')
5561 rmarks = other.listkeys('bookmarks')
5562 diff = set(rmarks) - set(lmarks)
5562 diff = set(rmarks) - set(lmarks)
5563 if len(diff) > 0:
5563 if len(diff) > 0:
5564 t.append(_('%d incoming bookmarks') % len(diff))
5564 t.append(_('%d incoming bookmarks') % len(diff))
5565 diff = set(lmarks) - set(rmarks)
5565 diff = set(lmarks) - set(rmarks)
5566 if len(diff) > 0:
5566 if len(diff) > 0:
5567 t.append(_('%d outgoing bookmarks') % len(diff))
5567 t.append(_('%d outgoing bookmarks') % len(diff))
5568
5568
5569 if t:
5569 if t:
5570 # i18n: column positioning for "hg summary"
5570 # i18n: column positioning for "hg summary"
5571 ui.write(_('remote: %s\n') % (', '.join(t)))
5571 ui.write(_('remote: %s\n') % (', '.join(t)))
5572 else:
5572 else:
5573 # i18n: column positioning for "hg summary"
5573 # i18n: column positioning for "hg summary"
5574 ui.status(_('remote: (synced)\n'))
5574 ui.status(_('remote: (synced)\n'))
5575
5575
5576 @command('tag',
5576 @command('tag',
5577 [('f', 'force', None, _('force tag')),
5577 [('f', 'force', None, _('force tag')),
5578 ('l', 'local', None, _('make the tag local')),
5578 ('l', 'local', None, _('make the tag local')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5580 ('', 'remove', None, _('remove a tag')),
5580 ('', 'remove', None, _('remove a tag')),
5581 # -l/--local is already there, commitopts cannot be used
5581 # -l/--local is already there, commitopts cannot be used
5582 ('e', 'edit', None, _('edit commit message')),
5582 ('e', 'edit', None, _('edit commit message')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5584 ] + commitopts2,
5584 ] + commitopts2,
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5586 def tag(ui, repo, name1, *names, **opts):
5586 def tag(ui, repo, name1, *names, **opts):
5587 """add one or more tags for the current or given revision
5587 """add one or more tags for the current or given revision
5588
5588
5589 Name a particular revision using <name>.
5589 Name a particular revision using <name>.
5590
5590
5591 Tags are used to name particular revisions of the repository and are
5591 Tags are used to name particular revisions of the repository and are
5592 very useful to compare different revisions, to go back to significant
5592 very useful to compare different revisions, to go back to significant
5593 earlier versions or to mark branch points as releases, etc. Changing
5593 earlier versions or to mark branch points as releases, etc. Changing
5594 an existing tag is normally disallowed; use -f/--force to override.
5594 an existing tag is normally disallowed; use -f/--force to override.
5595
5595
5596 If no revision is given, the parent of the working directory is
5596 If no revision is given, the parent of the working directory is
5597 used.
5597 used.
5598
5598
5599 To facilitate version control, distribution, and merging of tags,
5599 To facilitate version control, distribution, and merging of tags,
5600 they are stored as a file named ".hgtags" which is managed similarly
5600 they are stored as a file named ".hgtags" which is managed similarly
5601 to other project files and can be hand-edited if necessary. This
5601 to other project files and can be hand-edited if necessary. This
5602 also means that tagging creates a new commit. The file
5602 also means that tagging creates a new commit. The file
5603 ".hg/localtags" is used for local tags (not shared among
5603 ".hg/localtags" is used for local tags (not shared among
5604 repositories).
5604 repositories).
5605
5605
5606 Tag commits are usually made at the head of a branch. If the parent
5606 Tag commits are usually made at the head of a branch. If the parent
5607 of the working directory is not a branch head, :hg:`tag` aborts; use
5607 of the working directory is not a branch head, :hg:`tag` aborts; use
5608 -f/--force to force the tag commit to be based on a non-head
5608 -f/--force to force the tag commit to be based on a non-head
5609 changeset.
5609 changeset.
5610
5610
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5612
5612
5613 Since tag names have priority over branch names during revision
5613 Since tag names have priority over branch names during revision
5614 lookup, using an existing branch name as a tag name is discouraged.
5614 lookup, using an existing branch name as a tag name is discouraged.
5615
5615
5616 Returns 0 on success.
5616 Returns 0 on success.
5617 """
5617 """
5618 wlock = lock = None
5618 wlock = lock = None
5619 try:
5619 try:
5620 wlock = repo.wlock()
5620 wlock = repo.wlock()
5621 lock = repo.lock()
5621 lock = repo.lock()
5622 rev_ = "."
5622 rev_ = "."
5623 names = [t.strip() for t in (name1,) + names]
5623 names = [t.strip() for t in (name1,) + names]
5624 if len(names) != len(set(names)):
5624 if len(names) != len(set(names)):
5625 raise util.Abort(_('tag names must be unique'))
5625 raise util.Abort(_('tag names must be unique'))
5626 for n in names:
5626 for n in names:
5627 scmutil.checknewlabel(repo, n, 'tag')
5627 scmutil.checknewlabel(repo, n, 'tag')
5628 if not n:
5628 if not n:
5629 raise util.Abort(_('tag names cannot consist entirely of '
5629 raise util.Abort(_('tag names cannot consist entirely of '
5630 'whitespace'))
5630 'whitespace'))
5631 if opts.get('rev') and opts.get('remove'):
5631 if opts.get('rev') and opts.get('remove'):
5632 raise util.Abort(_("--rev and --remove are incompatible"))
5632 raise util.Abort(_("--rev and --remove are incompatible"))
5633 if opts.get('rev'):
5633 if opts.get('rev'):
5634 rev_ = opts['rev']
5634 rev_ = opts['rev']
5635 message = opts.get('message')
5635 message = opts.get('message')
5636 if opts.get('remove'):
5636 if opts.get('remove'):
5637 expectedtype = opts.get('local') and 'local' or 'global'
5637 expectedtype = opts.get('local') and 'local' or 'global'
5638 for n in names:
5638 for n in names:
5639 if not repo.tagtype(n):
5639 if not repo.tagtype(n):
5640 raise util.Abort(_("tag '%s' does not exist") % n)
5640 raise util.Abort(_("tag '%s' does not exist") % n)
5641 if repo.tagtype(n) != expectedtype:
5641 if repo.tagtype(n) != expectedtype:
5642 if expectedtype == 'global':
5642 if expectedtype == 'global':
5643 raise util.Abort(_("tag '%s' is not a global tag") % n)
5643 raise util.Abort(_("tag '%s' is not a global tag") % n)
5644 else:
5644 else:
5645 raise util.Abort(_("tag '%s' is not a local tag") % n)
5645 raise util.Abort(_("tag '%s' is not a local tag") % n)
5646 rev_ = nullid
5646 rev_ = nullid
5647 if not message:
5647 if not message:
5648 # we don't translate commit messages
5648 # we don't translate commit messages
5649 message = 'Removed tag %s' % ', '.join(names)
5649 message = 'Removed tag %s' % ', '.join(names)
5650 elif not opts.get('force'):
5650 elif not opts.get('force'):
5651 for n in names:
5651 for n in names:
5652 if n in repo.tags():
5652 if n in repo.tags():
5653 raise util.Abort(_("tag '%s' already exists "
5653 raise util.Abort(_("tag '%s' already exists "
5654 "(use -f to force)") % n)
5654 "(use -f to force)") % n)
5655 if not opts.get('local'):
5655 if not opts.get('local'):
5656 p1, p2 = repo.dirstate.parents()
5656 p1, p2 = repo.dirstate.parents()
5657 if p2 != nullid:
5657 if p2 != nullid:
5658 raise util.Abort(_('uncommitted merge'))
5658 raise util.Abort(_('uncommitted merge'))
5659 bheads = repo.branchheads()
5659 bheads = repo.branchheads()
5660 if not opts.get('force') and bheads and p1 not in bheads:
5660 if not opts.get('force') and bheads and p1 not in bheads:
5661 raise util.Abort(_('not at a branch head (use -f to force)'))
5661 raise util.Abort(_('not at a branch head (use -f to force)'))
5662 r = scmutil.revsingle(repo, rev_).node()
5662 r = scmutil.revsingle(repo, rev_).node()
5663
5663
5664 if not message:
5664 if not message:
5665 # we don't translate commit messages
5665 # we don't translate commit messages
5666 message = ('Added tag %s for changeset %s' %
5666 message = ('Added tag %s for changeset %s' %
5667 (', '.join(names), short(r)))
5667 (', '.join(names), short(r)))
5668
5668
5669 date = opts.get('date')
5669 date = opts.get('date')
5670 if date:
5670 if date:
5671 date = util.parsedate(date)
5671 date = util.parsedate(date)
5672
5672
5673 if opts.get('edit'):
5673 if opts.get('edit'):
5674 message = ui.edit(message, ui.username())
5674 message = ui.edit(message, ui.username())
5675
5675
5676 # don't allow tagging the null rev
5676 # don't allow tagging the null rev
5677 if (not opts.get('remove') and
5677 if (not opts.get('remove') and
5678 scmutil.revsingle(repo, rev_).rev() == nullrev):
5678 scmutil.revsingle(repo, rev_).rev() == nullrev):
5679 raise util.Abort(_("cannot tag null revision"))
5679 raise util.Abort(_("cannot tag null revision"))
5680
5680
5681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5682 finally:
5682 finally:
5683 release(lock, wlock)
5683 release(lock, wlock)
5684
5684
5685 @command('tags', [], '')
5685 @command('tags', [], '')
5686 def tags(ui, repo, **opts):
5686 def tags(ui, repo, **opts):
5687 """list repository tags
5687 """list repository tags
5688
5688
5689 This lists both regular and local tags. When the -v/--verbose
5689 This lists both regular and local tags. When the -v/--verbose
5690 switch is used, a third column "local" is printed for local tags.
5690 switch is used, a third column "local" is printed for local tags.
5691
5691
5692 Returns 0 on success.
5692 Returns 0 on success.
5693 """
5693 """
5694
5694
5695 fm = ui.formatter('tags', opts)
5695 fm = ui.formatter('tags', opts)
5696 hexfunc = ui.debugflag and hex or short
5696 hexfunc = ui.debugflag and hex or short
5697 tagtype = ""
5697 tagtype = ""
5698
5698
5699 for t, n in reversed(repo.tagslist()):
5699 for t, n in reversed(repo.tagslist()):
5700 hn = hexfunc(n)
5700 hn = hexfunc(n)
5701 label = 'tags.normal'
5701 label = 'tags.normal'
5702 tagtype = ''
5702 tagtype = ''
5703 if repo.tagtype(t) == 'local':
5703 if repo.tagtype(t) == 'local':
5704 label = 'tags.local'
5704 label = 'tags.local'
5705 tagtype = 'local'
5705 tagtype = 'local'
5706
5706
5707 fm.startitem()
5707 fm.startitem()
5708 fm.write('tag', '%s', t, label=label)
5708 fm.write('tag', '%s', t, label=label)
5709 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5709 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5710 fm.condwrite(not ui.quiet, 'rev id', fmt,
5710 fm.condwrite(not ui.quiet, 'rev id', fmt,
5711 repo.changelog.rev(n), hn, label=label)
5711 repo.changelog.rev(n), hn, label=label)
5712 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5712 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5713 tagtype, label=label)
5713 tagtype, label=label)
5714 fm.plain('\n')
5714 fm.plain('\n')
5715 fm.end()
5715 fm.end()
5716
5716
5717 @command('tip',
5717 @command('tip',
5718 [('p', 'patch', None, _('show patch')),
5718 [('p', 'patch', None, _('show patch')),
5719 ('g', 'git', None, _('use git extended diff format')),
5719 ('g', 'git', None, _('use git extended diff format')),
5720 ] + templateopts,
5720 ] + templateopts,
5721 _('[-p] [-g]'))
5721 _('[-p] [-g]'))
5722 def tip(ui, repo, **opts):
5722 def tip(ui, repo, **opts):
5723 """show the tip revision (DEPRECATED)
5723 """show the tip revision (DEPRECATED)
5724
5724
5725 The tip revision (usually just called the tip) is the changeset
5725 The tip revision (usually just called the tip) is the changeset
5726 most recently added to the repository (and therefore the most
5726 most recently added to the repository (and therefore the most
5727 recently changed head).
5727 recently changed head).
5728
5728
5729 If you have just made a commit, that commit will be the tip. If
5729 If you have just made a commit, that commit will be the tip. If
5730 you have just pulled changes from another repository, the tip of
5730 you have just pulled changes from another repository, the tip of
5731 that repository becomes the current tip. The "tip" tag is special
5731 that repository becomes the current tip. The "tip" tag is special
5732 and cannot be renamed or assigned to a different changeset.
5732 and cannot be renamed or assigned to a different changeset.
5733
5733
5734 This command is deprecated, please use :hg:`heads` instead.
5734 This command is deprecated, please use :hg:`heads` instead.
5735
5735
5736 Returns 0 on success.
5736 Returns 0 on success.
5737 """
5737 """
5738 displayer = cmdutil.show_changeset(ui, repo, opts)
5738 displayer = cmdutil.show_changeset(ui, repo, opts)
5739 displayer.show(repo['tip'])
5739 displayer.show(repo['tip'])
5740 displayer.close()
5740 displayer.close()
5741
5741
5742 @command('unbundle',
5742 @command('unbundle',
5743 [('u', 'update', None,
5743 [('u', 'update', None,
5744 _('update to new branch head if changesets were unbundled'))],
5744 _('update to new branch head if changesets were unbundled'))],
5745 _('[-u] FILE...'))
5745 _('[-u] FILE...'))
5746 def unbundle(ui, repo, fname1, *fnames, **opts):
5746 def unbundle(ui, repo, fname1, *fnames, **opts):
5747 """apply one or more changegroup files
5747 """apply one or more changegroup files
5748
5748
5749 Apply one or more compressed changegroup files generated by the
5749 Apply one or more compressed changegroup files generated by the
5750 bundle command.
5750 bundle command.
5751
5751
5752 Returns 0 on success, 1 if an update has unresolved files.
5752 Returns 0 on success, 1 if an update has unresolved files.
5753 """
5753 """
5754 fnames = (fname1,) + fnames
5754 fnames = (fname1,) + fnames
5755
5755
5756 lock = repo.lock()
5756 lock = repo.lock()
5757 wc = repo['.']
5757 wc = repo['.']
5758 try:
5758 try:
5759 for fname in fnames:
5759 for fname in fnames:
5760 f = hg.openpath(ui, fname)
5760 f = hg.openpath(ui, fname)
5761 gen = changegroup.readbundle(f, fname)
5761 gen = changegroup.readbundle(f, fname)
5762 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5762 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5763 finally:
5763 finally:
5764 lock.release()
5764 lock.release()
5765 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5765 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5766 return postincoming(ui, repo, modheads, opts.get('update'), None)
5766 return postincoming(ui, repo, modheads, opts.get('update'), None)
5767
5767
5768 @command('^update|up|checkout|co',
5768 @command('^update|up|checkout|co',
5769 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5769 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5770 ('c', 'check', None,
5770 ('c', 'check', None,
5771 _('update across branches if no uncommitted changes')),
5771 _('update across branches if no uncommitted changes')),
5772 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5772 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5773 ('r', 'rev', '', _('revision'), _('REV'))],
5773 ('r', 'rev', '', _('revision'), _('REV'))],
5774 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5774 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5775 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5775 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5776 """update working directory (or switch revisions)
5776 """update working directory (or switch revisions)
5777
5777
5778 Update the repository's working directory to the specified
5778 Update the repository's working directory to the specified
5779 changeset. If no changeset is specified, update to the tip of the
5779 changeset. If no changeset is specified, update to the tip of the
5780 current named branch and move the current bookmark (see :hg:`help
5780 current named branch and move the current bookmark (see :hg:`help
5781 bookmarks`).
5781 bookmarks`).
5782
5782
5783 Update sets the working directory's parent revision to the specified
5783 Update sets the working directory's parent revision to the specified
5784 changeset (see :hg:`help parents`).
5784 changeset (see :hg:`help parents`).
5785
5785
5786 If the changeset is not a descendant or ancestor of the working
5786 If the changeset is not a descendant or ancestor of the working
5787 directory's parent, the update is aborted. With the -c/--check
5787 directory's parent, the update is aborted. With the -c/--check
5788 option, the working directory is checked for uncommitted changes; if
5788 option, the working directory is checked for uncommitted changes; if
5789 none are found, the working directory is updated to the specified
5789 none are found, the working directory is updated to the specified
5790 changeset.
5790 changeset.
5791
5791
5792 .. container:: verbose
5792 .. container:: verbose
5793
5793
5794 The following rules apply when the working directory contains
5794 The following rules apply when the working directory contains
5795 uncommitted changes:
5795 uncommitted changes:
5796
5796
5797 1. If neither -c/--check nor -C/--clean is specified, and if
5797 1. If neither -c/--check nor -C/--clean is specified, and if
5798 the requested changeset is an ancestor or descendant of
5798 the requested changeset is an ancestor or descendant of
5799 the working directory's parent, the uncommitted changes
5799 the working directory's parent, the uncommitted changes
5800 are merged into the requested changeset and the merged
5800 are merged into the requested changeset and the merged
5801 result is left uncommitted. If the requested changeset is
5801 result is left uncommitted. If the requested changeset is
5802 not an ancestor or descendant (that is, it is on another
5802 not an ancestor or descendant (that is, it is on another
5803 branch), the update is aborted and the uncommitted changes
5803 branch), the update is aborted and the uncommitted changes
5804 are preserved.
5804 are preserved.
5805
5805
5806 2. With the -c/--check option, the update is aborted and the
5806 2. With the -c/--check option, the update is aborted and the
5807 uncommitted changes are preserved.
5807 uncommitted changes are preserved.
5808
5808
5809 3. With the -C/--clean option, uncommitted changes are discarded and
5809 3. With the -C/--clean option, uncommitted changes are discarded and
5810 the working directory is updated to the requested changeset.
5810 the working directory is updated to the requested changeset.
5811
5811
5812 To cancel an uncommitted merge (and lose your changes), use
5812 To cancel an uncommitted merge (and lose your changes), use
5813 :hg:`update --clean .`.
5813 :hg:`update --clean .`.
5814
5814
5815 Use null as the changeset to remove the working directory (like
5815 Use null as the changeset to remove the working directory (like
5816 :hg:`clone -U`).
5816 :hg:`clone -U`).
5817
5817
5818 If you want to revert just one file to an older revision, use
5818 If you want to revert just one file to an older revision, use
5819 :hg:`revert [-r REV] NAME`.
5819 :hg:`revert [-r REV] NAME`.
5820
5820
5821 See :hg:`help dates` for a list of formats valid for -d/--date.
5821 See :hg:`help dates` for a list of formats valid for -d/--date.
5822
5822
5823 Returns 0 on success, 1 if there are unresolved files.
5823 Returns 0 on success, 1 if there are unresolved files.
5824 """
5824 """
5825 if rev and node:
5825 if rev and node:
5826 raise util.Abort(_("please specify just one revision"))
5826 raise util.Abort(_("please specify just one revision"))
5827
5827
5828 if rev is None or rev == '':
5828 if rev is None or rev == '':
5829 rev = node
5829 rev = node
5830
5830
5831 cmdutil.clearunfinished(repo)
5831 cmdutil.clearunfinished(repo)
5832
5832
5833 # with no argument, we also move the current bookmark, if any
5833 # with no argument, we also move the current bookmark, if any
5834 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5834 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5835
5835
5836 # if we defined a bookmark, we have to remember the original bookmark name
5836 # if we defined a bookmark, we have to remember the original bookmark name
5837 brev = rev
5837 brev = rev
5838 rev = scmutil.revsingle(repo, rev, rev).rev()
5838 rev = scmutil.revsingle(repo, rev, rev).rev()
5839
5839
5840 if check and clean:
5840 if check and clean:
5841 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5841 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5842
5842
5843 if date:
5843 if date:
5844 if rev is not None:
5844 if rev is not None:
5845 raise util.Abort(_("you can't specify a revision and a date"))
5845 raise util.Abort(_("you can't specify a revision and a date"))
5846 rev = cmdutil.finddate(ui, repo, date)
5846 rev = cmdutil.finddate(ui, repo, date)
5847
5847
5848 if check:
5848 if check:
5849 c = repo[None]
5849 c = repo[None]
5850 if c.dirty(merge=False, branch=False, missing=True):
5850 if c.dirty(merge=False, branch=False, missing=True):
5851 raise util.Abort(_("uncommitted changes"))
5851 raise util.Abort(_("uncommitted changes"))
5852 if rev is None:
5852 if rev is None:
5853 rev = repo[repo[None].branch()].rev()
5853 rev = repo[repo[None].branch()].rev()
5854 mergemod._checkunknown(repo, repo[None], repo[rev])
5854 mergemod._checkunknown(repo, repo[None], repo[rev])
5855
5855
5856 if clean:
5856 if clean:
5857 ret = hg.clean(repo, rev)
5857 ret = hg.clean(repo, rev)
5858 else:
5858 else:
5859 ret = hg.update(repo, rev)
5859 ret = hg.update(repo, rev)
5860
5860
5861 if not ret and movemarkfrom:
5861 if not ret and movemarkfrom:
5862 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5862 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5863 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5863 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5864 elif brev in repo._bookmarks:
5864 elif brev in repo._bookmarks:
5865 bookmarks.setcurrent(repo, brev)
5865 bookmarks.setcurrent(repo, brev)
5866 elif brev:
5866 elif brev:
5867 bookmarks.unsetcurrent(repo)
5867 bookmarks.unsetcurrent(repo)
5868
5868
5869 return ret
5869 return ret
5870
5870
5871 @command('verify', [])
5871 @command('verify', [])
5872 def verify(ui, repo):
5872 def verify(ui, repo):
5873 """verify the integrity of the repository
5873 """verify the integrity of the repository
5874
5874
5875 Verify the integrity of the current repository.
5875 Verify the integrity of the current repository.
5876
5876
5877 This will perform an extensive check of the repository's
5877 This will perform an extensive check of the repository's
5878 integrity, validating the hashes and checksums of each entry in
5878 integrity, validating the hashes and checksums of each entry in
5879 the changelog, manifest, and tracked files, as well as the
5879 the changelog, manifest, and tracked files, as well as the
5880 integrity of their crosslinks and indices.
5880 integrity of their crosslinks and indices.
5881
5881
5882 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5882 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5883 for more information about recovery from corruption of the
5883 for more information about recovery from corruption of the
5884 repository.
5884 repository.
5885
5885
5886 Returns 0 on success, 1 if errors are encountered.
5886 Returns 0 on success, 1 if errors are encountered.
5887 """
5887 """
5888 return hg.verify(repo)
5888 return hg.verify(repo)
5889
5889
5890 @command('version', [])
5890 @command('version', [])
5891 def version_(ui):
5891 def version_(ui):
5892 """output version and copyright information"""
5892 """output version and copyright information"""
5893 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5893 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5894 % util.version())
5894 % util.version())
5895 ui.status(_(
5895 ui.status(_(
5896 "(see http://mercurial.selenic.com for more information)\n"
5896 "(see http://mercurial.selenic.com for more information)\n"
5897 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5897 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5898 "This is free software; see the source for copying conditions. "
5898 "This is free software; see the source for copying conditions. "
5899 "There is NO\nwarranty; "
5899 "There is NO\nwarranty; "
5900 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5900 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5901 ))
5901 ))
5902
5902
5903 norepo = ("clone init version help debugcommands debugcomplete"
5903 norepo = ("clone init version help debugcommands debugcomplete"
5904 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5904 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5905 " debugknown debuggetbundle debugbundle")
5905 " debugknown debuggetbundle debugbundle")
5906 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5906 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5907 " debugdata debugindex debugindexdot debugrevlog")
5907 " debugdata debugindex debugindexdot debugrevlog")
5908 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5908 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5909 " remove resolve status debugwalk")
5909 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now