##// END OF EJS Templates
commands.bookmarks: move hexfn to inside list block...
Siddharth Agarwal -
r20235:a602d2ac default
parent child Browse files
Show More
@@ -1,5909 +1,5908 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
811
812 def checkformat(mark):
810 def checkformat(mark):
813 mark = mark.strip()
811 mark = mark.strip()
814 if not mark:
812 if not mark:
815 raise util.Abort(_("bookmark names cannot consist entirely of "
813 raise util.Abort(_("bookmark names cannot consist entirely of "
816 "whitespace"))
814 "whitespace"))
817 scmutil.checknewlabel(repo, mark, 'bookmark')
815 scmutil.checknewlabel(repo, mark, 'bookmark')
818 return mark
816 return mark
819
817
820 def checkconflict(repo, mark, cur, force=False, target=None):
818 def checkconflict(repo, mark, cur, force=False, target=None):
821 if mark in marks and not force:
819 if mark in marks and not force:
822 if target:
820 if target:
823 if marks[mark] == target and target == cur:
821 if marks[mark] == target and target == cur:
824 # re-activating a bookmark
822 # re-activating a bookmark
825 return
823 return
826 anc = repo.changelog.ancestors([repo[target].rev()])
824 anc = repo.changelog.ancestors([repo[target].rev()])
827 bmctx = repo[marks[mark]]
825 bmctx = repo[marks[mark]]
828 divs = [repo[b].node() for b in marks
826 divs = [repo[b].node() for b in marks
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
827 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
830
828
831 # allow resolving a single divergent bookmark even if moving
829 # allow resolving a single divergent bookmark even if moving
832 # the bookmark across branches when a revision is specified
830 # the bookmark across branches when a revision is specified
833 # that contains a divergent bookmark
831 # that contains a divergent bookmark
834 if bmctx.rev() not in anc and target in divs:
832 if bmctx.rev() not in anc and target in divs:
835 bookmarks.deletedivergent(repo, [target], mark)
833 bookmarks.deletedivergent(repo, [target], mark)
836 return
834 return
837
835
838 # consider successor changesets as well
836 # consider successor changesets as well
839 foreground = obsolete.foreground(repo, [marks[mark]])
837 foreground = obsolete.foreground(repo, [marks[mark]])
840 deletefrom = [b for b in divs
838 deletefrom = [b for b in divs
841 if repo[b].rev() in anc or b == target]
839 if repo[b].rev() in anc or b == target]
842 bookmarks.deletedivergent(repo, deletefrom, mark)
840 bookmarks.deletedivergent(repo, deletefrom, mark)
843 if bmctx.rev() in anc or target in foreground:
841 if bmctx.rev() in anc or target in foreground:
844 ui.status(_("moving bookmark '%s' forward from %s\n") %
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
845 (mark, short(bmctx.node())))
843 (mark, short(bmctx.node())))
846 return
844 return
847 raise util.Abort(_("bookmark '%s' already exists "
845 raise util.Abort(_("bookmark '%s' already exists "
848 "(use -f to force)") % mark)
846 "(use -f to force)") % mark)
849 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
850 and not force):
848 and not force):
851 raise util.Abort(
849 raise util.Abort(
852 _("a bookmark cannot have the name of an existing branch"))
850 _("a bookmark cannot have the name of an existing branch"))
853
851
854 if delete and rename:
852 if delete and rename:
855 raise util.Abort(_("--delete and --rename are incompatible"))
853 raise util.Abort(_("--delete and --rename are incompatible"))
856 if delete and rev:
854 if delete and rev:
857 raise util.Abort(_("--rev is incompatible with --delete"))
855 raise util.Abort(_("--rev is incompatible with --delete"))
858 if rename and rev:
856 if rename and rev:
859 raise util.Abort(_("--rev is incompatible with --rename"))
857 raise util.Abort(_("--rev is incompatible with --rename"))
860 if not names and (delete or rev):
858 if not names and (delete or rev):
861 raise util.Abort(_("bookmark name required"))
859 raise util.Abort(_("bookmark name required"))
862
860
863 if delete or rename or names or inactive:
861 if delete or rename or names or inactive:
864 wlock = repo.wlock()
862 wlock = repo.wlock()
865 try:
863 try:
866 cur = repo.changectx('.').node()
864 cur = repo.changectx('.').node()
867 marks = repo._bookmarks
865 marks = repo._bookmarks
868 if delete:
866 if delete:
869 for mark in names:
867 for mark in names:
870 if mark not in marks:
868 if mark not in marks:
871 raise util.Abort(_("bookmark '%s' does not exist") %
869 raise util.Abort(_("bookmark '%s' does not exist") %
872 mark)
870 mark)
873 if mark == repo._bookmarkcurrent:
871 if mark == repo._bookmarkcurrent:
874 bookmarks.unsetcurrent(repo)
872 bookmarks.unsetcurrent(repo)
875 del marks[mark]
873 del marks[mark]
876 marks.write()
874 marks.write()
877
875
878 elif rename:
876 elif rename:
879 if not names:
877 if not names:
880 raise util.Abort(_("new bookmark name required"))
878 raise util.Abort(_("new bookmark name required"))
881 elif len(names) > 1:
879 elif len(names) > 1:
882 raise util.Abort(_("only one new bookmark name allowed"))
880 raise util.Abort(_("only one new bookmark name allowed"))
883 mark = checkformat(names[0])
881 mark = checkformat(names[0])
884 if rename not in marks:
882 if rename not in marks:
885 raise util.Abort(_("bookmark '%s' does not exist") % rename)
883 raise util.Abort(_("bookmark '%s' does not exist") % rename)
886 checkconflict(repo, mark, cur, force)
884 checkconflict(repo, mark, cur, force)
887 marks[mark] = marks[rename]
885 marks[mark] = marks[rename]
888 if repo._bookmarkcurrent == rename and not inactive:
886 if repo._bookmarkcurrent == rename and not inactive:
889 bookmarks.setcurrent(repo, mark)
887 bookmarks.setcurrent(repo, mark)
890 del marks[rename]
888 del marks[rename]
891 marks.write()
889 marks.write()
892
890
893 elif names:
891 elif names:
894 newact = None
892 newact = None
895 for mark in names:
893 for mark in names:
896 mark = checkformat(mark)
894 mark = checkformat(mark)
897 if newact is None:
895 if newact is None:
898 newact = mark
896 newact = mark
899 if inactive and mark == repo._bookmarkcurrent:
897 if inactive and mark == repo._bookmarkcurrent:
900 bookmarks.unsetcurrent(repo)
898 bookmarks.unsetcurrent(repo)
901 return
899 return
902 tgt = cur
900 tgt = cur
903 if rev:
901 if rev:
904 tgt = scmutil.revsingle(repo, rev).node()
902 tgt = scmutil.revsingle(repo, rev).node()
905 checkconflict(repo, mark, cur, force, tgt)
903 checkconflict(repo, mark, cur, force, tgt)
906 marks[mark] = tgt
904 marks[mark] = tgt
907 if not inactive and cur == marks[newact] and not rev:
905 if not inactive and cur == marks[newact] and not rev:
908 bookmarks.setcurrent(repo, newact)
906 bookmarks.setcurrent(repo, newact)
909 elif cur != tgt and newact == repo._bookmarkcurrent:
907 elif cur != tgt and newact == repo._bookmarkcurrent:
910 bookmarks.unsetcurrent(repo)
908 bookmarks.unsetcurrent(repo)
911 marks.write()
909 marks.write()
912
910
913 elif inactive:
911 elif inactive:
914 if len(marks) == 0:
912 if len(marks) == 0:
915 ui.status(_("no bookmarks set\n"))
913 ui.status(_("no bookmarks set\n"))
916 elif not repo._bookmarkcurrent:
914 elif not repo._bookmarkcurrent:
917 ui.status(_("no active bookmark\n"))
915 ui.status(_("no active bookmark\n"))
918 else:
916 else:
919 bookmarks.unsetcurrent(repo)
917 bookmarks.unsetcurrent(repo)
920 finally:
918 finally:
921 wlock.release()
919 wlock.release()
922 else: # show bookmarks
920 else: # show bookmarks
921 hexfn = ui.debugflag and hex or short
923 marks = repo._bookmarks
922 marks = repo._bookmarks
924 if len(marks) == 0:
923 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
924 ui.status(_("no bookmarks set\n"))
926 else:
925 else:
927 for bmark, n in sorted(marks.iteritems()):
926 for bmark, n in sorted(marks.iteritems()):
928 current = repo._bookmarkcurrent
927 current = repo._bookmarkcurrent
929 if bmark == current:
928 if bmark == current:
930 prefix, label = '*', 'bookmarks.current'
929 prefix, label = '*', 'bookmarks.current'
931 else:
930 else:
932 prefix, label = ' ', ''
931 prefix, label = ' ', ''
933
932
934 if ui.quiet:
933 if ui.quiet:
935 ui.write("%s\n" % bmark, label=label)
934 ui.write("%s\n" % bmark, label=label)
936 else:
935 else:
937 ui.write(" %s %-25s %d:%s\n" % (
936 ui.write(" %s %-25s %d:%s\n" % (
938 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
937 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
939 label=label)
938 label=label)
940
939
941 @command('branch',
940 @command('branch',
942 [('f', 'force', None,
941 [('f', 'force', None,
943 _('set branch name even if it shadows an existing branch')),
942 _('set branch name even if it shadows an existing branch')),
944 ('C', 'clean', None, _('reset branch name to parent branch name'))],
943 ('C', 'clean', None, _('reset branch name to parent branch name'))],
945 _('[-fC] [NAME]'))
944 _('[-fC] [NAME]'))
946 def branch(ui, repo, label=None, **opts):
945 def branch(ui, repo, label=None, **opts):
947 """set or show the current branch name
946 """set or show the current branch name
948
947
949 .. note::
948 .. note::
950
949
951 Branch names are permanent and global. Use :hg:`bookmark` to create a
950 Branch names are permanent and global. Use :hg:`bookmark` to create a
952 light-weight bookmark instead. See :hg:`help glossary` for more
951 light-weight bookmark instead. See :hg:`help glossary` for more
953 information about named branches and bookmarks.
952 information about named branches and bookmarks.
954
953
955 With no argument, show the current branch name. With one argument,
954 With no argument, show the current branch name. With one argument,
956 set the working directory branch name (the branch will not exist
955 set the working directory branch name (the branch will not exist
957 in the repository until the next commit). Standard practice
956 in the repository until the next commit). Standard practice
958 recommends that primary development take place on the 'default'
957 recommends that primary development take place on the 'default'
959 branch.
958 branch.
960
959
961 Unless -f/--force is specified, branch will not let you set a
960 Unless -f/--force is specified, branch will not let you set a
962 branch name that already exists, even if it's inactive.
961 branch name that already exists, even if it's inactive.
963
962
964 Use -C/--clean to reset the working directory branch to that of
963 Use -C/--clean to reset the working directory branch to that of
965 the parent of the working directory, negating a previous branch
964 the parent of the working directory, negating a previous branch
966 change.
965 change.
967
966
968 Use the command :hg:`update` to switch to an existing branch. Use
967 Use the command :hg:`update` to switch to an existing branch. Use
969 :hg:`commit --close-branch` to mark this branch as closed.
968 :hg:`commit --close-branch` to mark this branch as closed.
970
969
971 Returns 0 on success.
970 Returns 0 on success.
972 """
971 """
973 if label:
972 if label:
974 label = label.strip()
973 label = label.strip()
975
974
976 if not opts.get('clean') and not label:
975 if not opts.get('clean') and not label:
977 ui.write("%s\n" % repo.dirstate.branch())
976 ui.write("%s\n" % repo.dirstate.branch())
978 return
977 return
979
978
980 wlock = repo.wlock()
979 wlock = repo.wlock()
981 try:
980 try:
982 if opts.get('clean'):
981 if opts.get('clean'):
983 label = repo[None].p1().branch()
982 label = repo[None].p1().branch()
984 repo.dirstate.setbranch(label)
983 repo.dirstate.setbranch(label)
985 ui.status(_('reset working directory to branch %s\n') % label)
984 ui.status(_('reset working directory to branch %s\n') % label)
986 elif label:
985 elif label:
987 if not opts.get('force') and label in repo.branchmap():
986 if not opts.get('force') and label in repo.branchmap():
988 if label not in [p.branch() for p in repo.parents()]:
987 if label not in [p.branch() for p in repo.parents()]:
989 raise util.Abort(_('a branch of the same name already'
988 raise util.Abort(_('a branch of the same name already'
990 ' exists'),
989 ' exists'),
991 # i18n: "it" refers to an existing branch
990 # i18n: "it" refers to an existing branch
992 hint=_("use 'hg update' to switch to it"))
991 hint=_("use 'hg update' to switch to it"))
993 scmutil.checknewlabel(repo, label, 'branch')
992 scmutil.checknewlabel(repo, label, 'branch')
994 repo.dirstate.setbranch(label)
993 repo.dirstate.setbranch(label)
995 ui.status(_('marked working directory as branch %s\n') % label)
994 ui.status(_('marked working directory as branch %s\n') % label)
996 ui.status(_('(branches are permanent and global, '
995 ui.status(_('(branches are permanent and global, '
997 'did you want a bookmark?)\n'))
996 'did you want a bookmark?)\n'))
998 finally:
997 finally:
999 wlock.release()
998 wlock.release()
1000
999
1001 @command('branches',
1000 @command('branches',
1002 [('a', 'active', False, _('show only branches that have unmerged heads')),
1001 [('a', 'active', False, _('show only branches that have unmerged heads')),
1003 ('c', 'closed', False, _('show normal and closed branches'))],
1002 ('c', 'closed', False, _('show normal and closed branches'))],
1004 _('[-ac]'))
1003 _('[-ac]'))
1005 def branches(ui, repo, active=False, closed=False):
1004 def branches(ui, repo, active=False, closed=False):
1006 """list repository named branches
1005 """list repository named branches
1007
1006
1008 List the repository's named branches, indicating which ones are
1007 List the repository's named branches, indicating which ones are
1009 inactive. If -c/--closed is specified, also list branches which have
1008 inactive. If -c/--closed is specified, also list branches which have
1010 been marked closed (see :hg:`commit --close-branch`).
1009 been marked closed (see :hg:`commit --close-branch`).
1011
1010
1012 If -a/--active is specified, only show active branches. A branch
1011 If -a/--active is specified, only show active branches. A branch
1013 is considered active if it contains repository heads.
1012 is considered active if it contains repository heads.
1014
1013
1015 Use the command :hg:`update` to switch to an existing branch.
1014 Use the command :hg:`update` to switch to an existing branch.
1016
1015
1017 Returns 0.
1016 Returns 0.
1018 """
1017 """
1019
1018
1020 hexfunc = ui.debugflag and hex or short
1019 hexfunc = ui.debugflag and hex or short
1021
1020
1022 allheads = set(repo.heads())
1021 allheads = set(repo.heads())
1023 branches = []
1022 branches = []
1024 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1023 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1025 isactive = not isclosed and bool(set(heads) & allheads)
1024 isactive = not isclosed and bool(set(heads) & allheads)
1026 branches.append((tag, repo[tip], isactive, not isclosed))
1025 branches.append((tag, repo[tip], isactive, not isclosed))
1027 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1026 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1028 reverse=True)
1027 reverse=True)
1029
1028
1030 for tag, ctx, isactive, isopen in branches:
1029 for tag, ctx, isactive, isopen in branches:
1031 if (not active) or isactive:
1030 if (not active) or isactive:
1032 if isactive:
1031 if isactive:
1033 label = 'branches.active'
1032 label = 'branches.active'
1034 notice = ''
1033 notice = ''
1035 elif not isopen:
1034 elif not isopen:
1036 if not closed:
1035 if not closed:
1037 continue
1036 continue
1038 label = 'branches.closed'
1037 label = 'branches.closed'
1039 notice = _(' (closed)')
1038 notice = _(' (closed)')
1040 else:
1039 else:
1041 label = 'branches.inactive'
1040 label = 'branches.inactive'
1042 notice = _(' (inactive)')
1041 notice = _(' (inactive)')
1043 if tag == repo.dirstate.branch():
1042 if tag == repo.dirstate.branch():
1044 label = 'branches.current'
1043 label = 'branches.current'
1045 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1044 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1046 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1045 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1047 'log.changeset changeset.%s' % ctx.phasestr())
1046 'log.changeset changeset.%s' % ctx.phasestr())
1048 labeledtag = ui.label(tag, label)
1047 labeledtag = ui.label(tag, label)
1049 if ui.quiet:
1048 if ui.quiet:
1050 ui.write("%s\n" % labeledtag)
1049 ui.write("%s\n" % labeledtag)
1051 else:
1050 else:
1052 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1051 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1053
1052
1054 @command('bundle',
1053 @command('bundle',
1055 [('f', 'force', None, _('run even when the destination is unrelated')),
1054 [('f', 'force', None, _('run even when the destination is unrelated')),
1056 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1055 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1057 _('REV')),
1056 _('REV')),
1058 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1057 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1059 _('BRANCH')),
1058 _('BRANCH')),
1060 ('', 'base', [],
1059 ('', 'base', [],
1061 _('a base changeset assumed to be available at the destination'),
1060 _('a base changeset assumed to be available at the destination'),
1062 _('REV')),
1061 _('REV')),
1063 ('a', 'all', None, _('bundle all changesets in the repository')),
1062 ('a', 'all', None, _('bundle all changesets in the repository')),
1064 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1063 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1065 ] + remoteopts,
1064 ] + remoteopts,
1066 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1065 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1067 def bundle(ui, repo, fname, dest=None, **opts):
1066 def bundle(ui, repo, fname, dest=None, **opts):
1068 """create a changegroup file
1067 """create a changegroup file
1069
1068
1070 Generate a compressed changegroup file collecting changesets not
1069 Generate a compressed changegroup file collecting changesets not
1071 known to be in another repository.
1070 known to be in another repository.
1072
1071
1073 If you omit the destination repository, then hg assumes the
1072 If you omit the destination repository, then hg assumes the
1074 destination will have all the nodes you specify with --base
1073 destination will have all the nodes you specify with --base
1075 parameters. To create a bundle containing all changesets, use
1074 parameters. To create a bundle containing all changesets, use
1076 -a/--all (or --base null).
1075 -a/--all (or --base null).
1077
1076
1078 You can change compression method with the -t/--type option.
1077 You can change compression method with the -t/--type option.
1079 The available compression methods are: none, bzip2, and
1078 The available compression methods are: none, bzip2, and
1080 gzip (by default, bundles are compressed using bzip2).
1079 gzip (by default, bundles are compressed using bzip2).
1081
1080
1082 The bundle file can then be transferred using conventional means
1081 The bundle file can then be transferred using conventional means
1083 and applied to another repository with the unbundle or pull
1082 and applied to another repository with the unbundle or pull
1084 command. This is useful when direct push and pull are not
1083 command. This is useful when direct push and pull are not
1085 available or when exporting an entire repository is undesirable.
1084 available or when exporting an entire repository is undesirable.
1086
1085
1087 Applying bundles preserves all changeset contents including
1086 Applying bundles preserves all changeset contents including
1088 permissions, copy/rename information, and revision history.
1087 permissions, copy/rename information, and revision history.
1089
1088
1090 Returns 0 on success, 1 if no changes found.
1089 Returns 0 on success, 1 if no changes found.
1091 """
1090 """
1092 revs = None
1091 revs = None
1093 if 'rev' in opts:
1092 if 'rev' in opts:
1094 revs = scmutil.revrange(repo, opts['rev'])
1093 revs = scmutil.revrange(repo, opts['rev'])
1095
1094
1096 bundletype = opts.get('type', 'bzip2').lower()
1095 bundletype = opts.get('type', 'bzip2').lower()
1097 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1096 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1098 bundletype = btypes.get(bundletype)
1097 bundletype = btypes.get(bundletype)
1099 if bundletype not in changegroup.bundletypes:
1098 if bundletype not in changegroup.bundletypes:
1100 raise util.Abort(_('unknown bundle type specified with --type'))
1099 raise util.Abort(_('unknown bundle type specified with --type'))
1101
1100
1102 if opts.get('all'):
1101 if opts.get('all'):
1103 base = ['null']
1102 base = ['null']
1104 else:
1103 else:
1105 base = scmutil.revrange(repo, opts.get('base'))
1104 base = scmutil.revrange(repo, opts.get('base'))
1106 # TODO: get desired bundlecaps from command line.
1105 # TODO: get desired bundlecaps from command line.
1107 bundlecaps = None
1106 bundlecaps = None
1108 if base:
1107 if base:
1109 if dest:
1108 if dest:
1110 raise util.Abort(_("--base is incompatible with specifying "
1109 raise util.Abort(_("--base is incompatible with specifying "
1111 "a destination"))
1110 "a destination"))
1112 common = [repo.lookup(rev) for rev in base]
1111 common = [repo.lookup(rev) for rev in base]
1113 heads = revs and map(repo.lookup, revs) or revs
1112 heads = revs and map(repo.lookup, revs) or revs
1114 cg = repo.getbundle('bundle', heads=heads, common=common,
1113 cg = repo.getbundle('bundle', heads=heads, common=common,
1115 bundlecaps=bundlecaps)
1114 bundlecaps=bundlecaps)
1116 outgoing = None
1115 outgoing = None
1117 else:
1116 else:
1118 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1117 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1119 dest, branches = hg.parseurl(dest, opts.get('branch'))
1118 dest, branches = hg.parseurl(dest, opts.get('branch'))
1120 other = hg.peer(repo, opts, dest)
1119 other = hg.peer(repo, opts, dest)
1121 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1120 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1122 heads = revs and map(repo.lookup, revs) or revs
1121 heads = revs and map(repo.lookup, revs) or revs
1123 outgoing = discovery.findcommonoutgoing(repo, other,
1122 outgoing = discovery.findcommonoutgoing(repo, other,
1124 onlyheads=heads,
1123 onlyheads=heads,
1125 force=opts.get('force'),
1124 force=opts.get('force'),
1126 portable=True)
1125 portable=True)
1127 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1126 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1128 if not cg:
1127 if not cg:
1129 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1128 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1130 return 1
1129 return 1
1131
1130
1132 changegroup.writebundle(cg, fname, bundletype)
1131 changegroup.writebundle(cg, fname, bundletype)
1133
1132
1134 @command('cat',
1133 @command('cat',
1135 [('o', 'output', '',
1134 [('o', 'output', '',
1136 _('print output to file with formatted name'), _('FORMAT')),
1135 _('print output to file with formatted name'), _('FORMAT')),
1137 ('r', 'rev', '', _('print the given revision'), _('REV')),
1136 ('r', 'rev', '', _('print the given revision'), _('REV')),
1138 ('', 'decode', None, _('apply any matching decode filter')),
1137 ('', 'decode', None, _('apply any matching decode filter')),
1139 ] + walkopts,
1138 ] + walkopts,
1140 _('[OPTION]... FILE...'))
1139 _('[OPTION]... FILE...'))
1141 def cat(ui, repo, file1, *pats, **opts):
1140 def cat(ui, repo, file1, *pats, **opts):
1142 """output the current or given revision of files
1141 """output the current or given revision of files
1143
1142
1144 Print the specified files as they were at the given revision. If
1143 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.
1144 no revision is given, the parent of the working directory is used.
1146
1145
1147 Output may be to a file, in which case the name of the file is
1146 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
1147 given using a format string. The formatting rules are the same as
1149 for the export command, with the following additions:
1148 for the export command, with the following additions:
1150
1149
1151 :``%s``: basename of file being printed
1150 :``%s``: basename of file being printed
1152 :``%d``: dirname of file being printed, or '.' if in repository root
1151 :``%d``: dirname of file being printed, or '.' if in repository root
1153 :``%p``: root-relative path name of file being printed
1152 :``%p``: root-relative path name of file being printed
1154
1153
1155 Returns 0 on success.
1154 Returns 0 on success.
1156 """
1155 """
1157 ctx = scmutil.revsingle(repo, opts.get('rev'))
1156 ctx = scmutil.revsingle(repo, opts.get('rev'))
1158 err = 1
1157 err = 1
1159 m = scmutil.match(ctx, (file1,) + pats, opts)
1158 m = scmutil.match(ctx, (file1,) + pats, opts)
1160 for abs in ctx.walk(m):
1159 for abs in ctx.walk(m):
1161 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1160 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1162 pathname=abs)
1161 pathname=abs)
1163 data = ctx[abs].data()
1162 data = ctx[abs].data()
1164 if opts.get('decode'):
1163 if opts.get('decode'):
1165 data = repo.wwritedata(abs, data)
1164 data = repo.wwritedata(abs, data)
1166 fp.write(data)
1165 fp.write(data)
1167 fp.close()
1166 fp.close()
1168 err = 0
1167 err = 0
1169 return err
1168 return err
1170
1169
1171 @command('^clone',
1170 @command('^clone',
1172 [('U', 'noupdate', None,
1171 [('U', 'noupdate', None,
1173 _('the clone will include an empty working copy (only a repository)')),
1172 _('the clone will include an empty working copy (only a repository)')),
1174 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1173 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1175 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1174 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1176 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1175 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1177 ('', 'pull', None, _('use pull protocol to copy metadata')),
1176 ('', 'pull', None, _('use pull protocol to copy metadata')),
1178 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1177 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1179 ] + remoteopts,
1178 ] + remoteopts,
1180 _('[OPTION]... SOURCE [DEST]'))
1179 _('[OPTION]... SOURCE [DEST]'))
1181 def clone(ui, source, dest=None, **opts):
1180 def clone(ui, source, dest=None, **opts):
1182 """make a copy of an existing repository
1181 """make a copy of an existing repository
1183
1182
1184 Create a copy of an existing repository in a new directory.
1183 Create a copy of an existing repository in a new directory.
1185
1184
1186 If no destination directory name is specified, it defaults to the
1185 If no destination directory name is specified, it defaults to the
1187 basename of the source.
1186 basename of the source.
1188
1187
1189 The location of the source is added to the new repository's
1188 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.
1189 ``.hg/hgrc`` file, as the default to be used for future pulls.
1191
1190
1192 Only local paths and ``ssh://`` URLs are supported as
1191 Only local paths and ``ssh://`` URLs are supported as
1193 destinations. For ``ssh://`` destinations, no working directory or
1192 destinations. For ``ssh://`` destinations, no working directory or
1194 ``.hg/hgrc`` will be created on the remote side.
1193 ``.hg/hgrc`` will be created on the remote side.
1195
1194
1196 To pull only a subset of changesets, specify one or more revisions
1195 To pull only a subset of changesets, specify one or more revisions
1197 identifiers with -r/--rev or branches with -b/--branch. The
1196 identifiers with -r/--rev or branches with -b/--branch. The
1198 resulting clone will contain only the specified changesets and
1197 resulting clone will contain only the specified changesets and
1199 their ancestors. These options (or 'clone src#rev dest') imply
1198 their ancestors. These options (or 'clone src#rev dest') imply
1200 --pull, even for local source repositories. Note that specifying a
1199 --pull, even for local source repositories. Note that specifying a
1201 tag will include the tagged changeset but not the changeset
1200 tag will include the tagged changeset but not the changeset
1202 containing the tag.
1201 containing the tag.
1203
1202
1204 If the source repository has a bookmark called '@' set, that
1203 If the source repository has a bookmark called '@' set, that
1205 revision will be checked out in the new repository by default.
1204 revision will be checked out in the new repository by default.
1206
1205
1207 To check out a particular version, use -u/--update, or
1206 To check out a particular version, use -u/--update, or
1208 -U/--noupdate to create a clone with no working directory.
1207 -U/--noupdate to create a clone with no working directory.
1209
1208
1210 .. container:: verbose
1209 .. container:: verbose
1211
1210
1212 For efficiency, hardlinks are used for cloning whenever the
1211 For efficiency, hardlinks are used for cloning whenever the
1213 source and destination are on the same filesystem (note this
1212 source and destination are on the same filesystem (note this
1214 applies only to the repository data, not to the working
1213 applies only to the repository data, not to the working
1215 directory). Some filesystems, such as AFS, implement hardlinking
1214 directory). Some filesystems, such as AFS, implement hardlinking
1216 incorrectly, but do not report errors. In these cases, use the
1215 incorrectly, but do not report errors. In these cases, use the
1217 --pull option to avoid hardlinking.
1216 --pull option to avoid hardlinking.
1218
1217
1219 In some cases, you can clone repositories and the working
1218 In some cases, you can clone repositories and the working
1220 directory using full hardlinks with ::
1219 directory using full hardlinks with ::
1221
1220
1222 $ cp -al REPO REPOCLONE
1221 $ cp -al REPO REPOCLONE
1223
1222
1224 This is the fastest way to clone, but it is not always safe. The
1223 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
1224 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
1225 the operation is up to you) and you have to make sure your
1227 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1226 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1228 so). Also, this is not compatible with certain extensions that
1227 so). Also, this is not compatible with certain extensions that
1229 place their metadata under the .hg directory, such as mq.
1228 place their metadata under the .hg directory, such as mq.
1230
1229
1231 Mercurial will update the working directory to the first applicable
1230 Mercurial will update the working directory to the first applicable
1232 revision from this list:
1231 revision from this list:
1233
1232
1234 a) null if -U or the source repository has no changesets
1233 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
1234 b) if -u . and the source repository is local, the first parent of
1236 the source repository's working directory
1235 the source repository's working directory
1237 c) the changeset specified with -u (if a branch name, this means the
1236 c) the changeset specified with -u (if a branch name, this means the
1238 latest head of that branch)
1237 latest head of that branch)
1239 d) the changeset specified with -r
1238 d) the changeset specified with -r
1240 e) the tipmost head specified with -b
1239 e) the tipmost head specified with -b
1241 f) the tipmost head specified with the url#branch source syntax
1240 f) the tipmost head specified with the url#branch source syntax
1242 g) the revision marked with the '@' bookmark, if present
1241 g) the revision marked with the '@' bookmark, if present
1243 h) the tipmost head of the default branch
1242 h) the tipmost head of the default branch
1244 i) tip
1243 i) tip
1245
1244
1246 Examples:
1245 Examples:
1247
1246
1248 - clone a remote repository to a new directory named hg/::
1247 - clone a remote repository to a new directory named hg/::
1249
1248
1250 hg clone http://selenic.com/hg
1249 hg clone http://selenic.com/hg
1251
1250
1252 - create a lightweight local clone::
1251 - create a lightweight local clone::
1253
1252
1254 hg clone project/ project-feature/
1253 hg clone project/ project-feature/
1255
1254
1256 - clone from an absolute path on an ssh server (note double-slash)::
1255 - clone from an absolute path on an ssh server (note double-slash)::
1257
1256
1258 hg clone ssh://user@server//home/projects/alpha/
1257 hg clone ssh://user@server//home/projects/alpha/
1259
1258
1260 - do a high-speed clone over a LAN while checking out a
1259 - do a high-speed clone over a LAN while checking out a
1261 specified version::
1260 specified version::
1262
1261
1263 hg clone --uncompressed http://server/repo -u 1.5
1262 hg clone --uncompressed http://server/repo -u 1.5
1264
1263
1265 - create a repository without changesets after a particular revision::
1264 - create a repository without changesets after a particular revision::
1266
1265
1267 hg clone -r 04e544 experimental/ good/
1266 hg clone -r 04e544 experimental/ good/
1268
1267
1269 - clone (and track) a particular named branch::
1268 - clone (and track) a particular named branch::
1270
1269
1271 hg clone http://selenic.com/hg#stable
1270 hg clone http://selenic.com/hg#stable
1272
1271
1273 See :hg:`help urls` for details on specifying URLs.
1272 See :hg:`help urls` for details on specifying URLs.
1274
1273
1275 Returns 0 on success.
1274 Returns 0 on success.
1276 """
1275 """
1277 if opts.get('noupdate') and opts.get('updaterev'):
1276 if opts.get('noupdate') and opts.get('updaterev'):
1278 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1277 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1279
1278
1280 r = hg.clone(ui, opts, source, dest,
1279 r = hg.clone(ui, opts, source, dest,
1281 pull=opts.get('pull'),
1280 pull=opts.get('pull'),
1282 stream=opts.get('uncompressed'),
1281 stream=opts.get('uncompressed'),
1283 rev=opts.get('rev'),
1282 rev=opts.get('rev'),
1284 update=opts.get('updaterev') or not opts.get('noupdate'),
1283 update=opts.get('updaterev') or not opts.get('noupdate'),
1285 branch=opts.get('branch'))
1284 branch=opts.get('branch'))
1286
1285
1287 return r is None
1286 return r is None
1288
1287
1289 @command('^commit|ci',
1288 @command('^commit|ci',
1290 [('A', 'addremove', None,
1289 [('A', 'addremove', None,
1291 _('mark new/missing files as added/removed before committing')),
1290 _('mark new/missing files as added/removed before committing')),
1292 ('', 'close-branch', None,
1291 ('', 'close-branch', None,
1293 _('mark a branch as closed, hiding it from the branch list')),
1292 _('mark a branch as closed, hiding it from the branch list')),
1294 ('', 'amend', None, _('amend the parent of the working dir')),
1293 ('', 'amend', None, _('amend the parent of the working dir')),
1295 ('s', 'secret', None, _('use the secret phase for committing')),
1294 ('s', 'secret', None, _('use the secret phase for committing')),
1296 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1295 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1297 _('[OPTION]... [FILE]...'))
1296 _('[OPTION]... [FILE]...'))
1298 def commit(ui, repo, *pats, **opts):
1297 def commit(ui, repo, *pats, **opts):
1299 """commit the specified files or all outstanding changes
1298 """commit the specified files or all outstanding changes
1300
1299
1301 Commit changes to the given files into the repository. Unlike a
1300 Commit changes to the given files into the repository. Unlike a
1302 centralized SCM, this operation is a local operation. See
1301 centralized SCM, this operation is a local operation. See
1303 :hg:`push` for a way to actively distribute your changes.
1302 :hg:`push` for a way to actively distribute your changes.
1304
1303
1305 If a list of files is omitted, all changes reported by :hg:`status`
1304 If a list of files is omitted, all changes reported by :hg:`status`
1306 will be committed.
1305 will be committed.
1307
1306
1308 If you are committing the result of a merge, do not provide any
1307 If you are committing the result of a merge, do not provide any
1309 filenames or -I/-X filters.
1308 filenames or -I/-X filters.
1310
1309
1311 If no commit message is specified, Mercurial starts your
1310 If no commit message is specified, Mercurial starts your
1312 configured editor where you can enter a message. In case your
1311 configured editor where you can enter a message. In case your
1313 commit fails, you will find a backup of your message in
1312 commit fails, you will find a backup of your message in
1314 ``.hg/last-message.txt``.
1313 ``.hg/last-message.txt``.
1315
1314
1316 The --amend flag can be used to amend the parent of the
1315 The --amend flag can be used to amend the parent of the
1317 working directory with a new commit that contains the changes
1316 working directory with a new commit that contains the changes
1318 in the parent in addition to those currently reported by :hg:`status`,
1317 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
1318 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`
1319 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1321 on how to restore it).
1320 on how to restore it).
1322
1321
1323 Message, user and date are taken from the amended commit unless
1322 Message, user and date are taken from the amended commit unless
1324 specified. When a message isn't specified on the command line,
1323 specified. When a message isn't specified on the command line,
1325 the editor will open with the message of the amended commit.
1324 the editor will open with the message of the amended commit.
1326
1325
1327 It is not possible to amend public changesets (see :hg:`help phases`)
1326 It is not possible to amend public changesets (see :hg:`help phases`)
1328 or changesets that have children.
1327 or changesets that have children.
1329
1328
1330 See :hg:`help dates` for a list of formats valid for -d/--date.
1329 See :hg:`help dates` for a list of formats valid for -d/--date.
1331
1330
1332 Returns 0 on success, 1 if nothing changed.
1331 Returns 0 on success, 1 if nothing changed.
1333 """
1332 """
1334 if opts.get('subrepos'):
1333 if opts.get('subrepos'):
1335 if opts.get('amend'):
1334 if opts.get('amend'):
1336 raise util.Abort(_('cannot amend with --subrepos'))
1335 raise util.Abort(_('cannot amend with --subrepos'))
1337 # Let --subrepos on the command line override config setting.
1336 # Let --subrepos on the command line override config setting.
1338 ui.setconfig('ui', 'commitsubrepos', True)
1337 ui.setconfig('ui', 'commitsubrepos', True)
1339
1338
1340 # Save this for restoring it later
1339 # Save this for restoring it later
1341 oldcommitphase = ui.config('phases', 'new-commit')
1340 oldcommitphase = ui.config('phases', 'new-commit')
1342
1341
1343 cmdutil.checkunfinished(repo, commit=True)
1342 cmdutil.checkunfinished(repo, commit=True)
1344
1343
1345 branch = repo[None].branch()
1344 branch = repo[None].branch()
1346 bheads = repo.branchheads(branch)
1345 bheads = repo.branchheads(branch)
1347
1346
1348 extra = {}
1347 extra = {}
1349 if opts.get('close_branch'):
1348 if opts.get('close_branch'):
1350 extra['close'] = 1
1349 extra['close'] = 1
1351
1350
1352 if not bheads:
1351 if not bheads:
1353 raise util.Abort(_('can only close branch heads'))
1352 raise util.Abort(_('can only close branch heads'))
1354 elif opts.get('amend'):
1353 elif opts.get('amend'):
1355 if repo.parents()[0].p1().branch() != branch and \
1354 if repo.parents()[0].p1().branch() != branch and \
1356 repo.parents()[0].p2().branch() != branch:
1355 repo.parents()[0].p2().branch() != branch:
1357 raise util.Abort(_('can only close branch heads'))
1356 raise util.Abort(_('can only close branch heads'))
1358
1357
1359 if opts.get('amend'):
1358 if opts.get('amend'):
1360 if ui.configbool('ui', 'commitsubrepos'):
1359 if ui.configbool('ui', 'commitsubrepos'):
1361 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1360 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1362
1361
1363 old = repo['.']
1362 old = repo['.']
1364 if old.phase() == phases.public:
1363 if old.phase() == phases.public:
1365 raise util.Abort(_('cannot amend public changesets'))
1364 raise util.Abort(_('cannot amend public changesets'))
1366 if len(repo[None].parents()) > 1:
1365 if len(repo[None].parents()) > 1:
1367 raise util.Abort(_('cannot amend while merging'))
1366 raise util.Abort(_('cannot amend while merging'))
1368 if (not obsolete._enabled) and old.children():
1367 if (not obsolete._enabled) and old.children():
1369 raise util.Abort(_('cannot amend changeset with children'))
1368 raise util.Abort(_('cannot amend changeset with children'))
1370
1369
1371 e = cmdutil.commiteditor
1370 e = cmdutil.commiteditor
1372 if opts.get('force_editor'):
1371 if opts.get('force_editor'):
1373 e = cmdutil.commitforceeditor
1372 e = cmdutil.commitforceeditor
1374
1373
1375 def commitfunc(ui, repo, message, match, opts):
1374 def commitfunc(ui, repo, message, match, opts):
1376 editor = e
1375 editor = e
1377 # message contains text from -m or -l, if it's empty,
1376 # message contains text from -m or -l, if it's empty,
1378 # open the editor with the old message
1377 # open the editor with the old message
1379 if not message:
1378 if not message:
1380 message = old.description()
1379 message = old.description()
1381 editor = cmdutil.commitforceeditor
1380 editor = cmdutil.commitforceeditor
1382 try:
1381 try:
1383 if opts.get('secret'):
1382 if opts.get('secret'):
1384 ui.setconfig('phases', 'new-commit', 'secret')
1383 ui.setconfig('phases', 'new-commit', 'secret')
1385
1384
1386 return repo.commit(message,
1385 return repo.commit(message,
1387 opts.get('user') or old.user(),
1386 opts.get('user') or old.user(),
1388 opts.get('date') or old.date(),
1387 opts.get('date') or old.date(),
1389 match,
1388 match,
1390 editor=editor,
1389 editor=editor,
1391 extra=extra)
1390 extra=extra)
1392 finally:
1391 finally:
1393 ui.setconfig('phases', 'new-commit', oldcommitphase)
1392 ui.setconfig('phases', 'new-commit', oldcommitphase)
1394
1393
1395 current = repo._bookmarkcurrent
1394 current = repo._bookmarkcurrent
1396 marks = old.bookmarks()
1395 marks = old.bookmarks()
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1396 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1398 if node == old.node():
1397 if node == old.node():
1399 ui.status(_("nothing changed\n"))
1398 ui.status(_("nothing changed\n"))
1400 return 1
1399 return 1
1401 elif marks:
1400 elif marks:
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1401 ui.debug('moving bookmarks %r from %s to %s\n' %
1403 (marks, old.hex(), hex(node)))
1402 (marks, old.hex(), hex(node)))
1404 newmarks = repo._bookmarks
1403 newmarks = repo._bookmarks
1405 for bm in marks:
1404 for bm in marks:
1406 newmarks[bm] = node
1405 newmarks[bm] = node
1407 if bm == current:
1406 if bm == current:
1408 bookmarks.setcurrent(repo, bm)
1407 bookmarks.setcurrent(repo, bm)
1409 newmarks.write()
1408 newmarks.write()
1410 else:
1409 else:
1411 e = cmdutil.commiteditor
1410 e = cmdutil.commiteditor
1412 if opts.get('force_editor'):
1411 if opts.get('force_editor'):
1413 e = cmdutil.commitforceeditor
1412 e = cmdutil.commitforceeditor
1414
1413
1415 def commitfunc(ui, repo, message, match, opts):
1414 def commitfunc(ui, repo, message, match, opts):
1416 try:
1415 try:
1417 if opts.get('secret'):
1416 if opts.get('secret'):
1418 ui.setconfig('phases', 'new-commit', 'secret')
1417 ui.setconfig('phases', 'new-commit', 'secret')
1419
1418
1420 return repo.commit(message, opts.get('user'), opts.get('date'),
1419 return repo.commit(message, opts.get('user'), opts.get('date'),
1421 match, editor=e, extra=extra)
1420 match, editor=e, extra=extra)
1422 finally:
1421 finally:
1423 ui.setconfig('phases', 'new-commit', oldcommitphase)
1422 ui.setconfig('phases', 'new-commit', oldcommitphase)
1424
1423
1425
1424
1426 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1425 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1427
1426
1428 if not node:
1427 if not node:
1429 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1428 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1430 if stat[3]:
1429 if stat[3]:
1431 ui.status(_("nothing changed (%d missing files, see "
1430 ui.status(_("nothing changed (%d missing files, see "
1432 "'hg status')\n") % len(stat[3]))
1431 "'hg status')\n") % len(stat[3]))
1433 else:
1432 else:
1434 ui.status(_("nothing changed\n"))
1433 ui.status(_("nothing changed\n"))
1435 return 1
1434 return 1
1436
1435
1437 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1436 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1438
1437
1439 @command('copy|cp',
1438 @command('copy|cp',
1440 [('A', 'after', None, _('record a copy that has already occurred')),
1439 [('A', 'after', None, _('record a copy that has already occurred')),
1441 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1440 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1442 ] + walkopts + dryrunopts,
1441 ] + walkopts + dryrunopts,
1443 _('[OPTION]... [SOURCE]... DEST'))
1442 _('[OPTION]... [SOURCE]... DEST'))
1444 def copy(ui, repo, *pats, **opts):
1443 def copy(ui, repo, *pats, **opts):
1445 """mark files as copied for the next commit
1444 """mark files as copied for the next commit
1446
1445
1447 Mark dest as having copies of source files. If dest is a
1446 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,
1447 directory, copies are put in that directory. If dest is a file,
1449 the source must be a single file.
1448 the source must be a single file.
1450
1449
1451 By default, this command copies the contents of files as they
1450 By default, this command copies the contents of files as they
1452 exist in the working directory. If invoked with -A/--after, the
1451 exist in the working directory. If invoked with -A/--after, the
1453 operation is recorded, but no copying is performed.
1452 operation is recorded, but no copying is performed.
1454
1453
1455 This command takes effect with the next commit. To undo a copy
1454 This command takes effect with the next commit. To undo a copy
1456 before that, see :hg:`revert`.
1455 before that, see :hg:`revert`.
1457
1456
1458 Returns 0 on success, 1 if errors are encountered.
1457 Returns 0 on success, 1 if errors are encountered.
1459 """
1458 """
1460 wlock = repo.wlock(False)
1459 wlock = repo.wlock(False)
1461 try:
1460 try:
1462 return cmdutil.copy(ui, repo, pats, opts)
1461 return cmdutil.copy(ui, repo, pats, opts)
1463 finally:
1462 finally:
1464 wlock.release()
1463 wlock.release()
1465
1464
1466 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1465 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1467 def debugancestor(ui, repo, *args):
1466 def debugancestor(ui, repo, *args):
1468 """find the ancestor revision of two revisions in a given index"""
1467 """find the ancestor revision of two revisions in a given index"""
1469 if len(args) == 3:
1468 if len(args) == 3:
1470 index, rev1, rev2 = args
1469 index, rev1, rev2 = args
1471 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1470 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1472 lookup = r.lookup
1471 lookup = r.lookup
1473 elif len(args) == 2:
1472 elif len(args) == 2:
1474 if not repo:
1473 if not repo:
1475 raise util.Abort(_("there is no Mercurial repository here "
1474 raise util.Abort(_("there is no Mercurial repository here "
1476 "(.hg not found)"))
1475 "(.hg not found)"))
1477 rev1, rev2 = args
1476 rev1, rev2 = args
1478 r = repo.changelog
1477 r = repo.changelog
1479 lookup = repo.lookup
1478 lookup = repo.lookup
1480 else:
1479 else:
1481 raise util.Abort(_('either two or three arguments required'))
1480 raise util.Abort(_('either two or three arguments required'))
1482 a = r.ancestor(lookup(rev1), lookup(rev2))
1481 a = r.ancestor(lookup(rev1), lookup(rev2))
1483 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1482 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1484
1483
1485 @command('debugbuilddag',
1484 @command('debugbuilddag',
1486 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1485 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1487 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1486 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1488 ('n', 'new-file', None, _('add new file at each rev'))],
1487 ('n', 'new-file', None, _('add new file at each rev'))],
1489 _('[OPTION]... [TEXT]'))
1488 _('[OPTION]... [TEXT]'))
1490 def debugbuilddag(ui, repo, text=None,
1489 def debugbuilddag(ui, repo, text=None,
1491 mergeable_file=False,
1490 mergeable_file=False,
1492 overwritten_file=False,
1491 overwritten_file=False,
1493 new_file=False):
1492 new_file=False):
1494 """builds a repo with a given DAG from scratch in the current empty repo
1493 """builds a repo with a given DAG from scratch in the current empty repo
1495
1494
1496 The description of the DAG is read from stdin if not given on the
1495 The description of the DAG is read from stdin if not given on the
1497 command line.
1496 command line.
1498
1497
1499 Elements:
1498 Elements:
1500
1499
1501 - "+n" is a linear run of n nodes based on the current default parent
1500 - "+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
1501 - "." is a single node based on the current default parent
1503 - "$" resets the default parent to null (implied at the start);
1502 - "$" resets the default parent to null (implied at the start);
1504 otherwise the default parent is always the last node created
1503 otherwise the default parent is always the last node created
1505 - "<p" sets the default parent to the backref p
1504 - "<p" sets the default parent to the backref p
1506 - "*p" is a fork at parent p, which is a backref
1505 - "*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
1506 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1508 - "/p2" is a merge of the preceding node and p2
1507 - "/p2" is a merge of the preceding node and p2
1509 - ":tag" defines a local tag for the preceding node
1508 - ":tag" defines a local tag for the preceding node
1510 - "@branch" sets the named branch for subsequent nodes
1509 - "@branch" sets the named branch for subsequent nodes
1511 - "#...\\n" is a comment up to the end of the line
1510 - "#...\\n" is a comment up to the end of the line
1512
1511
1513 Whitespace between the above elements is ignored.
1512 Whitespace between the above elements is ignored.
1514
1513
1515 A backref is either
1514 A backref is either
1516
1515
1517 - a number n, which references the node curr-n, where curr is the current
1516 - a number n, which references the node curr-n, where curr is the current
1518 node, or
1517 node, or
1519 - the name of a local tag you placed earlier using ":tag", or
1518 - the name of a local tag you placed earlier using ":tag", or
1520 - empty to denote the default parent.
1519 - empty to denote the default parent.
1521
1520
1522 All string valued-elements are either strictly alphanumeric, or must
1521 All string valued-elements are either strictly alphanumeric, or must
1523 be enclosed in double quotes ("..."), with "\\" as escape character.
1522 be enclosed in double quotes ("..."), with "\\" as escape character.
1524 """
1523 """
1525
1524
1526 if text is None:
1525 if text is None:
1527 ui.status(_("reading DAG from stdin\n"))
1526 ui.status(_("reading DAG from stdin\n"))
1528 text = ui.fin.read()
1527 text = ui.fin.read()
1529
1528
1530 cl = repo.changelog
1529 cl = repo.changelog
1531 if len(cl) > 0:
1530 if len(cl) > 0:
1532 raise util.Abort(_('repository is not empty'))
1531 raise util.Abort(_('repository is not empty'))
1533
1532
1534 # determine number of revs in DAG
1533 # determine number of revs in DAG
1535 total = 0
1534 total = 0
1536 for type, data in dagparser.parsedag(text):
1535 for type, data in dagparser.parsedag(text):
1537 if type == 'n':
1536 if type == 'n':
1538 total += 1
1537 total += 1
1539
1538
1540 if mergeable_file:
1539 if mergeable_file:
1541 linesperrev = 2
1540 linesperrev = 2
1542 # make a file with k lines per rev
1541 # make a file with k lines per rev
1543 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1542 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1544 initialmergedlines.append("")
1543 initialmergedlines.append("")
1545
1544
1546 tags = []
1545 tags = []
1547
1546
1548 lock = tr = None
1547 lock = tr = None
1549 try:
1548 try:
1550 lock = repo.lock()
1549 lock = repo.lock()
1551 tr = repo.transaction("builddag")
1550 tr = repo.transaction("builddag")
1552
1551
1553 at = -1
1552 at = -1
1554 atbranch = 'default'
1553 atbranch = 'default'
1555 nodeids = []
1554 nodeids = []
1556 id = 0
1555 id = 0
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1556 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1558 for type, data in dagparser.parsedag(text):
1557 for type, data in dagparser.parsedag(text):
1559 if type == 'n':
1558 if type == 'n':
1560 ui.note(('node %s\n' % str(data)))
1559 ui.note(('node %s\n' % str(data)))
1561 id, ps = data
1560 id, ps = data
1562
1561
1563 files = []
1562 files = []
1564 fctxs = {}
1563 fctxs = {}
1565
1564
1566 p2 = None
1565 p2 = None
1567 if mergeable_file:
1566 if mergeable_file:
1568 fn = "mf"
1567 fn = "mf"
1569 p1 = repo[ps[0]]
1568 p1 = repo[ps[0]]
1570 if len(ps) > 1:
1569 if len(ps) > 1:
1571 p2 = repo[ps[1]]
1570 p2 = repo[ps[1]]
1572 pa = p1.ancestor(p2)
1571 pa = p1.ancestor(p2)
1573 base, local, other = [x[fn].data() for x in (pa, p1,
1572 base, local, other = [x[fn].data() for x in (pa, p1,
1574 p2)]
1573 p2)]
1575 m3 = simplemerge.Merge3Text(base, local, other)
1574 m3 = simplemerge.Merge3Text(base, local, other)
1576 ml = [l.strip() for l in m3.merge_lines()]
1575 ml = [l.strip() for l in m3.merge_lines()]
1577 ml.append("")
1576 ml.append("")
1578 elif at > 0:
1577 elif at > 0:
1579 ml = p1[fn].data().split("\n")
1578 ml = p1[fn].data().split("\n")
1580 else:
1579 else:
1581 ml = initialmergedlines
1580 ml = initialmergedlines
1582 ml[id * linesperrev] += " r%i" % id
1581 ml[id * linesperrev] += " r%i" % id
1583 mergedtext = "\n".join(ml)
1582 mergedtext = "\n".join(ml)
1584 files.append(fn)
1583 files.append(fn)
1585 fctxs[fn] = context.memfilectx(fn, mergedtext)
1584 fctxs[fn] = context.memfilectx(fn, mergedtext)
1586
1585
1587 if overwritten_file:
1586 if overwritten_file:
1588 fn = "of"
1587 fn = "of"
1589 files.append(fn)
1588 files.append(fn)
1590 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1589 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1591
1590
1592 if new_file:
1591 if new_file:
1593 fn = "nf%i" % id
1592 fn = "nf%i" % id
1594 files.append(fn)
1593 files.append(fn)
1595 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1594 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1596 if len(ps) > 1:
1595 if len(ps) > 1:
1597 if not p2:
1596 if not p2:
1598 p2 = repo[ps[1]]
1597 p2 = repo[ps[1]]
1599 for fn in p2:
1598 for fn in p2:
1600 if fn.startswith("nf"):
1599 if fn.startswith("nf"):
1601 files.append(fn)
1600 files.append(fn)
1602 fctxs[fn] = p2[fn]
1601 fctxs[fn] = p2[fn]
1603
1602
1604 def fctxfn(repo, cx, path):
1603 def fctxfn(repo, cx, path):
1605 return fctxs.get(path)
1604 return fctxs.get(path)
1606
1605
1607 if len(ps) == 0 or ps[0] < 0:
1606 if len(ps) == 0 or ps[0] < 0:
1608 pars = [None, None]
1607 pars = [None, None]
1609 elif len(ps) == 1:
1608 elif len(ps) == 1:
1610 pars = [nodeids[ps[0]], None]
1609 pars = [nodeids[ps[0]], None]
1611 else:
1610 else:
1612 pars = [nodeids[p] for p in ps]
1611 pars = [nodeids[p] for p in ps]
1613 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1612 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1614 date=(id, 0),
1613 date=(id, 0),
1615 user="debugbuilddag",
1614 user="debugbuilddag",
1616 extra={'branch': atbranch})
1615 extra={'branch': atbranch})
1617 nodeid = repo.commitctx(cx)
1616 nodeid = repo.commitctx(cx)
1618 nodeids.append(nodeid)
1617 nodeids.append(nodeid)
1619 at = id
1618 at = id
1620 elif type == 'l':
1619 elif type == 'l':
1621 id, name = data
1620 id, name = data
1622 ui.note(('tag %s\n' % name))
1621 ui.note(('tag %s\n' % name))
1623 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1622 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1624 elif type == 'a':
1623 elif type == 'a':
1625 ui.note(('branch %s\n' % data))
1624 ui.note(('branch %s\n' % data))
1626 atbranch = data
1625 atbranch = data
1627 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1626 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1628 tr.close()
1627 tr.close()
1629
1628
1630 if tags:
1629 if tags:
1631 repo.opener.write("localtags", "".join(tags))
1630 repo.opener.write("localtags", "".join(tags))
1632 finally:
1631 finally:
1633 ui.progress(_('building'), None)
1632 ui.progress(_('building'), None)
1634 release(tr, lock)
1633 release(tr, lock)
1635
1634
1636 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1635 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1637 def debugbundle(ui, bundlepath, all=None, **opts):
1636 def debugbundle(ui, bundlepath, all=None, **opts):
1638 """lists the contents of a bundle"""
1637 """lists the contents of a bundle"""
1639 f = hg.openpath(ui, bundlepath)
1638 f = hg.openpath(ui, bundlepath)
1640 try:
1639 try:
1641 gen = changegroup.readbundle(f, bundlepath)
1640 gen = changegroup.readbundle(f, bundlepath)
1642 if all:
1641 if all:
1643 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1642 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1644
1643
1645 def showchunks(named):
1644 def showchunks(named):
1646 ui.write("\n%s\n" % named)
1645 ui.write("\n%s\n" % named)
1647 chain = None
1646 chain = None
1648 while True:
1647 while True:
1649 chunkdata = gen.deltachunk(chain)
1648 chunkdata = gen.deltachunk(chain)
1650 if not chunkdata:
1649 if not chunkdata:
1651 break
1650 break
1652 node = chunkdata['node']
1651 node = chunkdata['node']
1653 p1 = chunkdata['p1']
1652 p1 = chunkdata['p1']
1654 p2 = chunkdata['p2']
1653 p2 = chunkdata['p2']
1655 cs = chunkdata['cs']
1654 cs = chunkdata['cs']
1656 deltabase = chunkdata['deltabase']
1655 deltabase = chunkdata['deltabase']
1657 delta = chunkdata['delta']
1656 delta = chunkdata['delta']
1658 ui.write("%s %s %s %s %s %s\n" %
1657 ui.write("%s %s %s %s %s %s\n" %
1659 (hex(node), hex(p1), hex(p2),
1658 (hex(node), hex(p1), hex(p2),
1660 hex(cs), hex(deltabase), len(delta)))
1659 hex(cs), hex(deltabase), len(delta)))
1661 chain = node
1660 chain = node
1662
1661
1663 chunkdata = gen.changelogheader()
1662 chunkdata = gen.changelogheader()
1664 showchunks("changelog")
1663 showchunks("changelog")
1665 chunkdata = gen.manifestheader()
1664 chunkdata = gen.manifestheader()
1666 showchunks("manifest")
1665 showchunks("manifest")
1667 while True:
1666 while True:
1668 chunkdata = gen.filelogheader()
1667 chunkdata = gen.filelogheader()
1669 if not chunkdata:
1668 if not chunkdata:
1670 break
1669 break
1671 fname = chunkdata['filename']
1670 fname = chunkdata['filename']
1672 showchunks(fname)
1671 showchunks(fname)
1673 else:
1672 else:
1674 chunkdata = gen.changelogheader()
1673 chunkdata = gen.changelogheader()
1675 chain = None
1674 chain = None
1676 while True:
1675 while True:
1677 chunkdata = gen.deltachunk(chain)
1676 chunkdata = gen.deltachunk(chain)
1678 if not chunkdata:
1677 if not chunkdata:
1679 break
1678 break
1680 node = chunkdata['node']
1679 node = chunkdata['node']
1681 ui.write("%s\n" % hex(node))
1680 ui.write("%s\n" % hex(node))
1682 chain = node
1681 chain = node
1683 finally:
1682 finally:
1684 f.close()
1683 f.close()
1685
1684
1686 @command('debugcheckstate', [], '')
1685 @command('debugcheckstate', [], '')
1687 def debugcheckstate(ui, repo):
1686 def debugcheckstate(ui, repo):
1688 """validate the correctness of the current dirstate"""
1687 """validate the correctness of the current dirstate"""
1689 parent1, parent2 = repo.dirstate.parents()
1688 parent1, parent2 = repo.dirstate.parents()
1690 m1 = repo[parent1].manifest()
1689 m1 = repo[parent1].manifest()
1691 m2 = repo[parent2].manifest()
1690 m2 = repo[parent2].manifest()
1692 errors = 0
1691 errors = 0
1693 for f in repo.dirstate:
1692 for f in repo.dirstate:
1694 state = repo.dirstate[f]
1693 state = repo.dirstate[f]
1695 if state in "nr" and f not in m1:
1694 if state in "nr" and f not in m1:
1696 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1695 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1697 errors += 1
1696 errors += 1
1698 if state in "a" and f in m1:
1697 if state in "a" and f in m1:
1699 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1698 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1700 errors += 1
1699 errors += 1
1701 if state in "m" and f not in m1 and f not in m2:
1700 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") %
1701 ui.warn(_("%s in state %s, but not in either manifest\n") %
1703 (f, state))
1702 (f, state))
1704 errors += 1
1703 errors += 1
1705 for f in m1:
1704 for f in m1:
1706 state = repo.dirstate[f]
1705 state = repo.dirstate[f]
1707 if state not in "nrm":
1706 if state not in "nrm":
1708 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1707 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1709 errors += 1
1708 errors += 1
1710 if errors:
1709 if errors:
1711 error = _(".hg/dirstate inconsistent with current parent's manifest")
1710 error = _(".hg/dirstate inconsistent with current parent's manifest")
1712 raise util.Abort(error)
1711 raise util.Abort(error)
1713
1712
1714 @command('debugcommands', [], _('[COMMAND]'))
1713 @command('debugcommands', [], _('[COMMAND]'))
1715 def debugcommands(ui, cmd='', *args):
1714 def debugcommands(ui, cmd='', *args):
1716 """list all available commands and options"""
1715 """list all available commands and options"""
1717 for cmd, vals in sorted(table.iteritems()):
1716 for cmd, vals in sorted(table.iteritems()):
1718 cmd = cmd.split('|')[0].strip('^')
1717 cmd = cmd.split('|')[0].strip('^')
1719 opts = ', '.join([i[1] for i in vals[1]])
1718 opts = ', '.join([i[1] for i in vals[1]])
1720 ui.write('%s: %s\n' % (cmd, opts))
1719 ui.write('%s: %s\n' % (cmd, opts))
1721
1720
1722 @command('debugcomplete',
1721 @command('debugcomplete',
1723 [('o', 'options', None, _('show the command options'))],
1722 [('o', 'options', None, _('show the command options'))],
1724 _('[-o] CMD'))
1723 _('[-o] CMD'))
1725 def debugcomplete(ui, cmd='', **opts):
1724 def debugcomplete(ui, cmd='', **opts):
1726 """returns the completion list associated with the given command"""
1725 """returns the completion list associated with the given command"""
1727
1726
1728 if opts.get('options'):
1727 if opts.get('options'):
1729 options = []
1728 options = []
1730 otables = [globalopts]
1729 otables = [globalopts]
1731 if cmd:
1730 if cmd:
1732 aliases, entry = cmdutil.findcmd(cmd, table, False)
1731 aliases, entry = cmdutil.findcmd(cmd, table, False)
1733 otables.append(entry[1])
1732 otables.append(entry[1])
1734 for t in otables:
1733 for t in otables:
1735 for o in t:
1734 for o in t:
1736 if "(DEPRECATED)" in o[3]:
1735 if "(DEPRECATED)" in o[3]:
1737 continue
1736 continue
1738 if o[0]:
1737 if o[0]:
1739 options.append('-%s' % o[0])
1738 options.append('-%s' % o[0])
1740 options.append('--%s' % o[1])
1739 options.append('--%s' % o[1])
1741 ui.write("%s\n" % "\n".join(options))
1740 ui.write("%s\n" % "\n".join(options))
1742 return
1741 return
1743
1742
1744 cmdlist = cmdutil.findpossible(cmd, table)
1743 cmdlist = cmdutil.findpossible(cmd, table)
1745 if ui.verbose:
1744 if ui.verbose:
1746 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1745 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1747 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1746 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1748
1747
1749 @command('debugdag',
1748 @command('debugdag',
1750 [('t', 'tags', None, _('use tags as labels')),
1749 [('t', 'tags', None, _('use tags as labels')),
1751 ('b', 'branches', None, _('annotate with branch names')),
1750 ('b', 'branches', None, _('annotate with branch names')),
1752 ('', 'dots', None, _('use dots for runs')),
1751 ('', 'dots', None, _('use dots for runs')),
1753 ('s', 'spaces', None, _('separate elements by spaces'))],
1752 ('s', 'spaces', None, _('separate elements by spaces'))],
1754 _('[OPTION]... [FILE [REV]...]'))
1753 _('[OPTION]... [FILE [REV]...]'))
1755 def debugdag(ui, repo, file_=None, *revs, **opts):
1754 def debugdag(ui, repo, file_=None, *revs, **opts):
1756 """format the changelog or an index DAG as a concise textual description
1755 """format the changelog or an index DAG as a concise textual description
1757
1756
1758 If you pass a revlog index, the revlog's DAG is emitted. If you list
1757 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.
1758 revision numbers, they get labeled in the output as rN.
1760
1759
1761 Otherwise, the changelog DAG of the current repo is emitted.
1760 Otherwise, the changelog DAG of the current repo is emitted.
1762 """
1761 """
1763 spaces = opts.get('spaces')
1762 spaces = opts.get('spaces')
1764 dots = opts.get('dots')
1763 dots = opts.get('dots')
1765 if file_:
1764 if file_:
1766 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1765 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1767 revs = set((int(r) for r in revs))
1766 revs = set((int(r) for r in revs))
1768 def events():
1767 def events():
1769 for r in rlog:
1768 for r in rlog:
1770 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1769 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1771 if p != -1)))
1770 if p != -1)))
1772 if r in revs:
1771 if r in revs:
1773 yield 'l', (r, "r%i" % r)
1772 yield 'l', (r, "r%i" % r)
1774 elif repo:
1773 elif repo:
1775 cl = repo.changelog
1774 cl = repo.changelog
1776 tags = opts.get('tags')
1775 tags = opts.get('tags')
1777 branches = opts.get('branches')
1776 branches = opts.get('branches')
1778 if tags:
1777 if tags:
1779 labels = {}
1778 labels = {}
1780 for l, n in repo.tags().items():
1779 for l, n in repo.tags().items():
1781 labels.setdefault(cl.rev(n), []).append(l)
1780 labels.setdefault(cl.rev(n), []).append(l)
1782 def events():
1781 def events():
1783 b = "default"
1782 b = "default"
1784 for r in cl:
1783 for r in cl:
1785 if branches:
1784 if branches:
1786 newb = cl.read(cl.node(r))[5]['branch']
1785 newb = cl.read(cl.node(r))[5]['branch']
1787 if newb != b:
1786 if newb != b:
1788 yield 'a', newb
1787 yield 'a', newb
1789 b = newb
1788 b = newb
1790 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1789 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1791 if p != -1)))
1790 if p != -1)))
1792 if tags:
1791 if tags:
1793 ls = labels.get(r)
1792 ls = labels.get(r)
1794 if ls:
1793 if ls:
1795 for l in ls:
1794 for l in ls:
1796 yield 'l', (r, l)
1795 yield 'l', (r, l)
1797 else:
1796 else:
1798 raise util.Abort(_('need repo for changelog dag'))
1797 raise util.Abort(_('need repo for changelog dag'))
1799
1798
1800 for line in dagparser.dagtextlines(events(),
1799 for line in dagparser.dagtextlines(events(),
1801 addspaces=spaces,
1800 addspaces=spaces,
1802 wraplabels=True,
1801 wraplabels=True,
1803 wrapannotations=True,
1802 wrapannotations=True,
1804 wrapnonlinear=dots,
1803 wrapnonlinear=dots,
1805 usedots=dots,
1804 usedots=dots,
1806 maxlinewidth=70):
1805 maxlinewidth=70):
1807 ui.write(line)
1806 ui.write(line)
1808 ui.write("\n")
1807 ui.write("\n")
1809
1808
1810 @command('debugdata',
1809 @command('debugdata',
1811 [('c', 'changelog', False, _('open changelog')),
1810 [('c', 'changelog', False, _('open changelog')),
1812 ('m', 'manifest', False, _('open manifest'))],
1811 ('m', 'manifest', False, _('open manifest'))],
1813 _('-c|-m|FILE REV'))
1812 _('-c|-m|FILE REV'))
1814 def debugdata(ui, repo, file_, rev=None, **opts):
1813 def debugdata(ui, repo, file_, rev=None, **opts):
1815 """dump the contents of a data file revision"""
1814 """dump the contents of a data file revision"""
1816 if opts.get('changelog') or opts.get('manifest'):
1815 if opts.get('changelog') or opts.get('manifest'):
1817 file_, rev = None, file_
1816 file_, rev = None, file_
1818 elif rev is None:
1817 elif rev is None:
1819 raise error.CommandError('debugdata', _('invalid arguments'))
1818 raise error.CommandError('debugdata', _('invalid arguments'))
1820 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1819 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1821 try:
1820 try:
1822 ui.write(r.revision(r.lookup(rev)))
1821 ui.write(r.revision(r.lookup(rev)))
1823 except KeyError:
1822 except KeyError:
1824 raise util.Abort(_('invalid revision identifier %s') % rev)
1823 raise util.Abort(_('invalid revision identifier %s') % rev)
1825
1824
1826 @command('debugdate',
1825 @command('debugdate',
1827 [('e', 'extended', None, _('try extended date formats'))],
1826 [('e', 'extended', None, _('try extended date formats'))],
1828 _('[-e] DATE [RANGE]'))
1827 _('[-e] DATE [RANGE]'))
1829 def debugdate(ui, date, range=None, **opts):
1828 def debugdate(ui, date, range=None, **opts):
1830 """parse and display a date"""
1829 """parse and display a date"""
1831 if opts["extended"]:
1830 if opts["extended"]:
1832 d = util.parsedate(date, util.extendeddateformats)
1831 d = util.parsedate(date, util.extendeddateformats)
1833 else:
1832 else:
1834 d = util.parsedate(date)
1833 d = util.parsedate(date)
1835 ui.write(("internal: %s %s\n") % d)
1834 ui.write(("internal: %s %s\n") % d)
1836 ui.write(("standard: %s\n") % util.datestr(d))
1835 ui.write(("standard: %s\n") % util.datestr(d))
1837 if range:
1836 if range:
1838 m = util.matchdate(range)
1837 m = util.matchdate(range)
1839 ui.write(("match: %s\n") % m(d[0]))
1838 ui.write(("match: %s\n") % m(d[0]))
1840
1839
1841 @command('debugdiscovery',
1840 @command('debugdiscovery',
1842 [('', 'old', None, _('use old-style discovery')),
1841 [('', 'old', None, _('use old-style discovery')),
1843 ('', 'nonheads', None,
1842 ('', 'nonheads', None,
1844 _('use old-style discovery with non-heads included')),
1843 _('use old-style discovery with non-heads included')),
1845 ] + remoteopts,
1844 ] + remoteopts,
1846 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1845 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1847 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1846 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1848 """runs the changeset discovery protocol in isolation"""
1847 """runs the changeset discovery protocol in isolation"""
1849 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1848 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1850 opts.get('branch'))
1849 opts.get('branch'))
1851 remote = hg.peer(repo, opts, remoteurl)
1850 remote = hg.peer(repo, opts, remoteurl)
1852 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1851 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1853
1852
1854 # make sure tests are repeatable
1853 # make sure tests are repeatable
1855 random.seed(12323)
1854 random.seed(12323)
1856
1855
1857 def doit(localheads, remoteheads, remote=remote):
1856 def doit(localheads, remoteheads, remote=remote):
1858 if opts.get('old'):
1857 if opts.get('old'):
1859 if localheads:
1858 if localheads:
1860 raise util.Abort('cannot use localheads with old style '
1859 raise util.Abort('cannot use localheads with old style '
1861 'discovery')
1860 'discovery')
1862 if not util.safehasattr(remote, 'branches'):
1861 if not util.safehasattr(remote, 'branches'):
1863 # enable in-client legacy support
1862 # enable in-client legacy support
1864 remote = localrepo.locallegacypeer(remote.local())
1863 remote = localrepo.locallegacypeer(remote.local())
1865 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1864 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1866 force=True)
1865 force=True)
1867 common = set(common)
1866 common = set(common)
1868 if not opts.get('nonheads'):
1867 if not opts.get('nonheads'):
1869 ui.write(("unpruned common: %s\n") %
1868 ui.write(("unpruned common: %s\n") %
1870 " ".join(sorted(short(n) for n in common)))
1869 " ".join(sorted(short(n) for n in common)))
1871 dag = dagutil.revlogdag(repo.changelog)
1870 dag = dagutil.revlogdag(repo.changelog)
1872 all = dag.ancestorset(dag.internalizeall(common))
1871 all = dag.ancestorset(dag.internalizeall(common))
1873 common = dag.externalizeall(dag.headsetofconnecteds(all))
1872 common = dag.externalizeall(dag.headsetofconnecteds(all))
1874 else:
1873 else:
1875 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1874 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1876 common = set(common)
1875 common = set(common)
1877 rheads = set(hds)
1876 rheads = set(hds)
1878 lheads = set(repo.heads())
1877 lheads = set(repo.heads())
1879 ui.write(("common heads: %s\n") %
1878 ui.write(("common heads: %s\n") %
1880 " ".join(sorted(short(n) for n in common)))
1879 " ".join(sorted(short(n) for n in common)))
1881 if lheads <= common:
1880 if lheads <= common:
1882 ui.write(("local is subset\n"))
1881 ui.write(("local is subset\n"))
1883 elif rheads <= common:
1882 elif rheads <= common:
1884 ui.write(("remote is subset\n"))
1883 ui.write(("remote is subset\n"))
1885
1884
1886 serverlogs = opts.get('serverlog')
1885 serverlogs = opts.get('serverlog')
1887 if serverlogs:
1886 if serverlogs:
1888 for filename in serverlogs:
1887 for filename in serverlogs:
1889 logfile = open(filename, 'r')
1888 logfile = open(filename, 'r')
1890 try:
1889 try:
1891 line = logfile.readline()
1890 line = logfile.readline()
1892 while line:
1891 while line:
1893 parts = line.strip().split(';')
1892 parts = line.strip().split(';')
1894 op = parts[1]
1893 op = parts[1]
1895 if op == 'cg':
1894 if op == 'cg':
1896 pass
1895 pass
1897 elif op == 'cgss':
1896 elif op == 'cgss':
1898 doit(parts[2].split(' '), parts[3].split(' '))
1897 doit(parts[2].split(' '), parts[3].split(' '))
1899 elif op == 'unb':
1898 elif op == 'unb':
1900 doit(parts[3].split(' '), parts[2].split(' '))
1899 doit(parts[3].split(' '), parts[2].split(' '))
1901 line = logfile.readline()
1900 line = logfile.readline()
1902 finally:
1901 finally:
1903 logfile.close()
1902 logfile.close()
1904
1903
1905 else:
1904 else:
1906 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1905 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1907 opts.get('remote_head'))
1906 opts.get('remote_head'))
1908 localrevs = opts.get('local_head')
1907 localrevs = opts.get('local_head')
1909 doit(localrevs, remoterevs)
1908 doit(localrevs, remoterevs)
1910
1909
1911 @command('debugfileset',
1910 @command('debugfileset',
1912 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1911 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1913 _('[-r REV] FILESPEC'))
1912 _('[-r REV] FILESPEC'))
1914 def debugfileset(ui, repo, expr, **opts):
1913 def debugfileset(ui, repo, expr, **opts):
1915 '''parse and apply a fileset specification'''
1914 '''parse and apply a fileset specification'''
1916 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1915 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1917 if ui.verbose:
1916 if ui.verbose:
1918 tree = fileset.parse(expr)[0]
1917 tree = fileset.parse(expr)[0]
1919 ui.note(tree, "\n")
1918 ui.note(tree, "\n")
1920
1919
1921 for f in fileset.getfileset(ctx, expr):
1920 for f in fileset.getfileset(ctx, expr):
1922 ui.write("%s\n" % f)
1921 ui.write("%s\n" % f)
1923
1922
1924 @command('debugfsinfo', [], _('[PATH]'))
1923 @command('debugfsinfo', [], _('[PATH]'))
1925 def debugfsinfo(ui, path="."):
1924 def debugfsinfo(ui, path="."):
1926 """show information detected about current filesystem"""
1925 """show information detected about current filesystem"""
1927 util.writefile('.debugfsinfo', '')
1926 util.writefile('.debugfsinfo', '')
1928 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1927 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'))
1928 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'))
1929 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1931 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1930 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1932 and 'yes' or 'no'))
1931 and 'yes' or 'no'))
1933 os.unlink('.debugfsinfo')
1932 os.unlink('.debugfsinfo')
1934
1933
1935 @command('debuggetbundle',
1934 @command('debuggetbundle',
1936 [('H', 'head', [], _('id of head node'), _('ID')),
1935 [('H', 'head', [], _('id of head node'), _('ID')),
1937 ('C', 'common', [], _('id of common node'), _('ID')),
1936 ('C', 'common', [], _('id of common node'), _('ID')),
1938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1937 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1939 _('REPO FILE [-H|-C ID]...'))
1938 _('REPO FILE [-H|-C ID]...'))
1940 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1939 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1941 """retrieves a bundle from a repo
1940 """retrieves a bundle from a repo
1942
1941
1943 Every ID must be a full-length hex node id string. Saves the bundle to the
1942 Every ID must be a full-length hex node id string. Saves the bundle to the
1944 given file.
1943 given file.
1945 """
1944 """
1946 repo = hg.peer(ui, opts, repopath)
1945 repo = hg.peer(ui, opts, repopath)
1947 if not repo.capable('getbundle'):
1946 if not repo.capable('getbundle'):
1948 raise util.Abort("getbundle() not supported by target repository")
1947 raise util.Abort("getbundle() not supported by target repository")
1949 args = {}
1948 args = {}
1950 if common:
1949 if common:
1951 args['common'] = [bin(s) for s in common]
1950 args['common'] = [bin(s) for s in common]
1952 if head:
1951 if head:
1953 args['heads'] = [bin(s) for s in head]
1952 args['heads'] = [bin(s) for s in head]
1954 # TODO: get desired bundlecaps from command line.
1953 # TODO: get desired bundlecaps from command line.
1955 args['bundlecaps'] = None
1954 args['bundlecaps'] = None
1956 bundle = repo.getbundle('debug', **args)
1955 bundle = repo.getbundle('debug', **args)
1957
1956
1958 bundletype = opts.get('type', 'bzip2').lower()
1957 bundletype = opts.get('type', 'bzip2').lower()
1959 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1958 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1960 bundletype = btypes.get(bundletype)
1959 bundletype = btypes.get(bundletype)
1961 if bundletype not in changegroup.bundletypes:
1960 if bundletype not in changegroup.bundletypes:
1962 raise util.Abort(_('unknown bundle type specified with --type'))
1961 raise util.Abort(_('unknown bundle type specified with --type'))
1963 changegroup.writebundle(bundle, bundlepath, bundletype)
1962 changegroup.writebundle(bundle, bundlepath, bundletype)
1964
1963
1965 @command('debugignore', [], '')
1964 @command('debugignore', [], '')
1966 def debugignore(ui, repo, *values, **opts):
1965 def debugignore(ui, repo, *values, **opts):
1967 """display the combined ignore pattern"""
1966 """display the combined ignore pattern"""
1968 ignore = repo.dirstate._ignore
1967 ignore = repo.dirstate._ignore
1969 includepat = getattr(ignore, 'includepat', None)
1968 includepat = getattr(ignore, 'includepat', None)
1970 if includepat is not None:
1969 if includepat is not None:
1971 ui.write("%s\n" % includepat)
1970 ui.write("%s\n" % includepat)
1972 else:
1971 else:
1973 raise util.Abort(_("no ignore patterns found"))
1972 raise util.Abort(_("no ignore patterns found"))
1974
1973
1975 @command('debugindex',
1974 @command('debugindex',
1976 [('c', 'changelog', False, _('open changelog')),
1975 [('c', 'changelog', False, _('open changelog')),
1977 ('m', 'manifest', False, _('open manifest')),
1976 ('m', 'manifest', False, _('open manifest')),
1978 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1977 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1979 _('[-f FORMAT] -c|-m|FILE'))
1978 _('[-f FORMAT] -c|-m|FILE'))
1980 def debugindex(ui, repo, file_=None, **opts):
1979 def debugindex(ui, repo, file_=None, **opts):
1981 """dump the contents of an index file"""
1980 """dump the contents of an index file"""
1982 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1981 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1983 format = opts.get('format', 0)
1982 format = opts.get('format', 0)
1984 if format not in (0, 1):
1983 if format not in (0, 1):
1985 raise util.Abort(_("unknown format %d") % format)
1984 raise util.Abort(_("unknown format %d") % format)
1986
1985
1987 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1986 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1988 if generaldelta:
1987 if generaldelta:
1989 basehdr = ' delta'
1988 basehdr = ' delta'
1990 else:
1989 else:
1991 basehdr = ' base'
1990 basehdr = ' base'
1992
1991
1993 if format == 0:
1992 if format == 0:
1994 ui.write(" rev offset length " + basehdr + " linkrev"
1993 ui.write(" rev offset length " + basehdr + " linkrev"
1995 " nodeid p1 p2\n")
1994 " nodeid p1 p2\n")
1996 elif format == 1:
1995 elif format == 1:
1997 ui.write(" rev flag offset length"
1996 ui.write(" rev flag offset length"
1998 " size " + basehdr + " link p1 p2"
1997 " size " + basehdr + " link p1 p2"
1999 " nodeid\n")
1998 " nodeid\n")
2000
1999
2001 for i in r:
2000 for i in r:
2002 node = r.node(i)
2001 node = r.node(i)
2003 if generaldelta:
2002 if generaldelta:
2004 base = r.deltaparent(i)
2003 base = r.deltaparent(i)
2005 else:
2004 else:
2006 base = r.chainbase(i)
2005 base = r.chainbase(i)
2007 if format == 0:
2006 if format == 0:
2008 try:
2007 try:
2009 pp = r.parents(node)
2008 pp = r.parents(node)
2010 except Exception:
2009 except Exception:
2011 pp = [nullid, nullid]
2010 pp = [nullid, nullid]
2012 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2011 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2013 i, r.start(i), r.length(i), base, r.linkrev(i),
2012 i, r.start(i), r.length(i), base, r.linkrev(i),
2014 short(node), short(pp[0]), short(pp[1])))
2013 short(node), short(pp[0]), short(pp[1])))
2015 elif format == 1:
2014 elif format == 1:
2016 pr = r.parentrevs(i)
2015 pr = r.parentrevs(i)
2017 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2016 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),
2017 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2019 base, r.linkrev(i), pr[0], pr[1], short(node)))
2018 base, r.linkrev(i), pr[0], pr[1], short(node)))
2020
2019
2021 @command('debugindexdot', [], _('FILE'))
2020 @command('debugindexdot', [], _('FILE'))
2022 def debugindexdot(ui, repo, file_):
2021 def debugindexdot(ui, repo, file_):
2023 """dump an index DAG as a graphviz dot file"""
2022 """dump an index DAG as a graphviz dot file"""
2024 r = None
2023 r = None
2025 if repo:
2024 if repo:
2026 filelog = repo.file(file_)
2025 filelog = repo.file(file_)
2027 if len(filelog):
2026 if len(filelog):
2028 r = filelog
2027 r = filelog
2029 if not r:
2028 if not r:
2030 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2029 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2031 ui.write(("digraph G {\n"))
2030 ui.write(("digraph G {\n"))
2032 for i in r:
2031 for i in r:
2033 node = r.node(i)
2032 node = r.node(i)
2034 pp = r.parents(node)
2033 pp = r.parents(node)
2035 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2036 if pp[1] != nullid:
2035 if pp[1] != nullid:
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2036 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2038 ui.write("}\n")
2037 ui.write("}\n")
2039
2038
2040 @command('debuginstall', [], '')
2039 @command('debuginstall', [], '')
2041 def debuginstall(ui):
2040 def debuginstall(ui):
2042 '''test Mercurial installation
2041 '''test Mercurial installation
2043
2042
2044 Returns 0 on success.
2043 Returns 0 on success.
2045 '''
2044 '''
2046
2045
2047 def writetemp(contents):
2046 def writetemp(contents):
2048 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2047 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2049 f = os.fdopen(fd, "wb")
2048 f = os.fdopen(fd, "wb")
2050 f.write(contents)
2049 f.write(contents)
2051 f.close()
2050 f.close()
2052 return name
2051 return name
2053
2052
2054 problems = 0
2053 problems = 0
2055
2054
2056 # encoding
2055 # encoding
2057 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2056 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2058 try:
2057 try:
2059 encoding.fromlocal("test")
2058 encoding.fromlocal("test")
2060 except util.Abort, inst:
2059 except util.Abort, inst:
2061 ui.write(" %s\n" % inst)
2060 ui.write(" %s\n" % inst)
2062 ui.write(_(" (check that your locale is properly set)\n"))
2061 ui.write(_(" (check that your locale is properly set)\n"))
2063 problems += 1
2062 problems += 1
2064
2063
2065 # Python lib
2064 # Python lib
2066 ui.status(_("checking Python lib (%s)...\n")
2065 ui.status(_("checking Python lib (%s)...\n")
2067 % os.path.dirname(os.__file__))
2066 % os.path.dirname(os.__file__))
2068
2067
2069 # compiled modules
2068 # compiled modules
2070 ui.status(_("checking installed modules (%s)...\n")
2069 ui.status(_("checking installed modules (%s)...\n")
2071 % os.path.dirname(__file__))
2070 % os.path.dirname(__file__))
2072 try:
2071 try:
2073 import bdiff, mpatch, base85, osutil
2072 import bdiff, mpatch, base85, osutil
2074 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2073 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2075 except Exception, inst:
2074 except Exception, inst:
2076 ui.write(" %s\n" % inst)
2075 ui.write(" %s\n" % inst)
2077 ui.write(_(" One or more extensions could not be found"))
2076 ui.write(_(" One or more extensions could not be found"))
2078 ui.write(_(" (check that you compiled the extensions)\n"))
2077 ui.write(_(" (check that you compiled the extensions)\n"))
2079 problems += 1
2078 problems += 1
2080
2079
2081 # templates
2080 # templates
2082 import templater
2081 import templater
2083 p = templater.templatepath()
2082 p = templater.templatepath()
2084 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2083 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2085 try:
2084 try:
2086 templater.templater(templater.templatepath("map-cmdline.default"))
2085 templater.templater(templater.templatepath("map-cmdline.default"))
2087 except Exception, inst:
2086 except Exception, inst:
2088 ui.write(" %s\n" % inst)
2087 ui.write(" %s\n" % inst)
2089 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2088 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2090 problems += 1
2089 problems += 1
2091
2090
2092 # editor
2091 # editor
2093 ui.status(_("checking commit editor...\n"))
2092 ui.status(_("checking commit editor...\n"))
2094 editor = ui.geteditor()
2093 editor = ui.geteditor()
2095 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2094 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2096 if not cmdpath:
2095 if not cmdpath:
2097 if editor == 'vi':
2096 if editor == 'vi':
2098 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2097 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2099 ui.write(_(" (specify a commit editor in your configuration"
2098 ui.write(_(" (specify a commit editor in your configuration"
2100 " file)\n"))
2099 " file)\n"))
2101 else:
2100 else:
2102 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2101 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2103 ui.write(_(" (specify a commit editor in your configuration"
2102 ui.write(_(" (specify a commit editor in your configuration"
2104 " file)\n"))
2103 " file)\n"))
2105 problems += 1
2104 problems += 1
2106
2105
2107 # check username
2106 # check username
2108 ui.status(_("checking username...\n"))
2107 ui.status(_("checking username...\n"))
2109 try:
2108 try:
2110 ui.username()
2109 ui.username()
2111 except util.Abort, e:
2110 except util.Abort, e:
2112 ui.write(" %s\n" % e)
2111 ui.write(" %s\n" % e)
2113 ui.write(_(" (specify a username in your configuration file)\n"))
2112 ui.write(_(" (specify a username in your configuration file)\n"))
2114 problems += 1
2113 problems += 1
2115
2114
2116 if not problems:
2115 if not problems:
2117 ui.status(_("no problems detected\n"))
2116 ui.status(_("no problems detected\n"))
2118 else:
2117 else:
2119 ui.write(_("%s problems detected,"
2118 ui.write(_("%s problems detected,"
2120 " please check your install!\n") % problems)
2119 " please check your install!\n") % problems)
2121
2120
2122 return problems
2121 return problems
2123
2122
2124 @command('debugknown', [], _('REPO ID...'))
2123 @command('debugknown', [], _('REPO ID...'))
2125 def debugknown(ui, repopath, *ids, **opts):
2124 def debugknown(ui, repopath, *ids, **opts):
2126 """test whether node ids are known to a repo
2125 """test whether node ids are known to a repo
2127
2126
2128 Every ID must be a full-length hex node id string. Returns a list of 0s
2127 Every ID must be a full-length hex node id string. Returns a list of 0s
2129 and 1s indicating unknown/known.
2128 and 1s indicating unknown/known.
2130 """
2129 """
2131 repo = hg.peer(ui, opts, repopath)
2130 repo = hg.peer(ui, opts, repopath)
2132 if not repo.capable('known'):
2131 if not repo.capable('known'):
2133 raise util.Abort("known() not supported by target repository")
2132 raise util.Abort("known() not supported by target repository")
2134 flags = repo.known([bin(s) for s in ids])
2133 flags = repo.known([bin(s) for s in ids])
2135 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2134 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2136
2135
2137 @command('debuglabelcomplete', [], _('LABEL...'))
2136 @command('debuglabelcomplete', [], _('LABEL...'))
2138 def debuglabelcomplete(ui, repo, *args):
2137 def debuglabelcomplete(ui, repo, *args):
2139 '''complete "labels" - tags, open branch names, bookmark names'''
2138 '''complete "labels" - tags, open branch names, bookmark names'''
2140
2139
2141 labels = set()
2140 labels = set()
2142 labels.update(t[0] for t in repo.tagslist())
2141 labels.update(t[0] for t in repo.tagslist())
2143 labels.update(repo._bookmarks.keys())
2142 labels.update(repo._bookmarks.keys())
2144 labels.update(tag for (tag, heads, tip, closed)
2143 labels.update(tag for (tag, heads, tip, closed)
2145 in repo.branchmap().iterbranches() if not closed)
2144 in repo.branchmap().iterbranches() if not closed)
2146 completions = set()
2145 completions = set()
2147 if not args:
2146 if not args:
2148 args = ['']
2147 args = ['']
2149 for a in args:
2148 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2149 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2150 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2151 ui.write('\n')
2153
2152
2154 @command('debugobsolete',
2153 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2154 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2155 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2156 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2157 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2158 """create arbitrary obsolete marker
2160
2159
2161 With no arguments, displays the list of obsolescence markers."""
2160 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2161 def parsenodeid(s):
2163 try:
2162 try:
2164 # We do not use revsingle/revrange functions here to accept
2163 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2164 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2165 # local repository.
2167 n = bin(s)
2166 n = bin(s)
2168 if len(n) != len(nullid):
2167 if len(n) != len(nullid):
2169 raise TypeError()
2168 raise TypeError()
2170 return n
2169 return n
2171 except TypeError:
2170 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2171 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2172 'node identifiers')
2174
2173
2175 if precursor is not None:
2174 if precursor is not None:
2176 metadata = {}
2175 metadata = {}
2177 if 'date' in opts:
2176 if 'date' in opts:
2178 metadata['date'] = opts['date']
2177 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2178 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2179 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2180 l = repo.lock()
2182 try:
2181 try:
2183 tr = repo.transaction('debugobsolete')
2182 tr = repo.transaction('debugobsolete')
2184 try:
2183 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2184 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2185 opts['flags'], metadata)
2187 tr.close()
2186 tr.close()
2188 finally:
2187 finally:
2189 tr.release()
2188 tr.release()
2190 finally:
2189 finally:
2191 l.release()
2190 l.release()
2192 else:
2191 else:
2193 for m in obsolete.allmarkers(repo):
2192 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2193 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2194 for repl in m.succnodes():
2196 ui.write(' ')
2195 ui.write(' ')
2197 ui.write(hex(repl))
2196 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2197 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2198 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2199 sorted(m.metadata().items()))))
2201 ui.write('\n')
2200 ui.write('\n')
2202
2201
2203 @command('debugpathcomplete',
2202 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2203 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2204 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2205 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2206 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2207 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2208 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2209 '''complete part or all of a tracked path
2211
2210
2212 This command supports shells that offer path name completion. It
2211 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2212 currently completes only files already known to the dirstate.
2214
2213
2215 Completion extends only to the next path segment unless
2214 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2215 --full is specified, in which case entire paths are used.'''
2217
2216
2218 def complete(path, acceptable):
2217 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2218 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2219 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2220 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2221 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2222 return [], []
2224 if os.path.isdir(spec):
2223 if os.path.isdir(spec):
2225 spec += '/'
2224 spec += '/'
2226 spec = spec[len(rootdir):]
2225 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2226 fixpaths = os.sep != '/'
2228 if fixpaths:
2227 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2228 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2229 speclen = len(spec)
2231 fullpaths = opts['full']
2230 fullpaths = opts['full']
2232 files, dirs = set(), set()
2231 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2232 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2233 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2234 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2235 if fixpaths:
2237 f = f.replace('/', os.sep)
2236 f = f.replace('/', os.sep)
2238 if fullpaths:
2237 if fullpaths:
2239 addfile(f)
2238 addfile(f)
2240 continue
2239 continue
2241 s = f.find(os.sep, speclen)
2240 s = f.find(os.sep, speclen)
2242 if s >= 0:
2241 if s >= 0:
2243 adddir(f[:s])
2242 adddir(f[:s])
2244 else:
2243 else:
2245 addfile(f)
2244 addfile(f)
2246 return files, dirs
2245 return files, dirs
2247
2246
2248 acceptable = ''
2247 acceptable = ''
2249 if opts['normal']:
2248 if opts['normal']:
2250 acceptable += 'nm'
2249 acceptable += 'nm'
2251 if opts['added']:
2250 if opts['added']:
2252 acceptable += 'a'
2251 acceptable += 'a'
2253 if opts['removed']:
2252 if opts['removed']:
2254 acceptable += 'r'
2253 acceptable += 'r'
2255 cwd = repo.getcwd()
2254 cwd = repo.getcwd()
2256 if not specs:
2255 if not specs:
2257 specs = ['.']
2256 specs = ['.']
2258
2257
2259 files, dirs = set(), set()
2258 files, dirs = set(), set()
2260 for spec in specs:
2259 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2260 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2261 files.update(f)
2263 dirs.update(d)
2262 dirs.update(d)
2264 files.update(dirs)
2263 files.update(dirs)
2265 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2264 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2266 ui.write('\n')
2265 ui.write('\n')
2267
2266
2268 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2267 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2269 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2268 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2270 '''access the pushkey key/value protocol
2269 '''access the pushkey key/value protocol
2271
2270
2272 With two args, list the keys in the given namespace.
2271 With two args, list the keys in the given namespace.
2273
2272
2274 With five args, set a key to new if it currently is set to old.
2273 With five args, set a key to new if it currently is set to old.
2275 Reports success or failure.
2274 Reports success or failure.
2276 '''
2275 '''
2277
2276
2278 target = hg.peer(ui, {}, repopath)
2277 target = hg.peer(ui, {}, repopath)
2279 if keyinfo:
2278 if keyinfo:
2280 key, old, new = keyinfo
2279 key, old, new = keyinfo
2281 r = target.pushkey(namespace, key, old, new)
2280 r = target.pushkey(namespace, key, old, new)
2282 ui.status(str(r) + '\n')
2281 ui.status(str(r) + '\n')
2283 return not r
2282 return not r
2284 else:
2283 else:
2285 for k, v in sorted(target.listkeys(namespace).iteritems()):
2284 for k, v in sorted(target.listkeys(namespace).iteritems()):
2286 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2285 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2287 v.encode('string-escape')))
2286 v.encode('string-escape')))
2288
2287
2289 @command('debugpvec', [], _('A B'))
2288 @command('debugpvec', [], _('A B'))
2290 def debugpvec(ui, repo, a, b=None):
2289 def debugpvec(ui, repo, a, b=None):
2291 ca = scmutil.revsingle(repo, a)
2290 ca = scmutil.revsingle(repo, a)
2292 cb = scmutil.revsingle(repo, b)
2291 cb = scmutil.revsingle(repo, b)
2293 pa = pvec.ctxpvec(ca)
2292 pa = pvec.ctxpvec(ca)
2294 pb = pvec.ctxpvec(cb)
2293 pb = pvec.ctxpvec(cb)
2295 if pa == pb:
2294 if pa == pb:
2296 rel = "="
2295 rel = "="
2297 elif pa > pb:
2296 elif pa > pb:
2298 rel = ">"
2297 rel = ">"
2299 elif pa < pb:
2298 elif pa < pb:
2300 rel = "<"
2299 rel = "<"
2301 elif pa | pb:
2300 elif pa | pb:
2302 rel = "|"
2301 rel = "|"
2303 ui.write(_("a: %s\n") % pa)
2302 ui.write(_("a: %s\n") % pa)
2304 ui.write(_("b: %s\n") % pb)
2303 ui.write(_("b: %s\n") % pb)
2305 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2304 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") %
2305 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2307 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2306 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2308 pa.distance(pb), rel))
2307 pa.distance(pb), rel))
2309
2308
2310 @command('debugrebuilddirstate|debugrebuildstate',
2309 @command('debugrebuilddirstate|debugrebuildstate',
2311 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2310 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2312 _('[-r REV]'))
2311 _('[-r REV]'))
2313 def debugrebuilddirstate(ui, repo, rev):
2312 def debugrebuilddirstate(ui, repo, rev):
2314 """rebuild the dirstate as it would look like for the given revision
2313 """rebuild the dirstate as it would look like for the given revision
2315
2314
2316 If no revision is specified the first current parent will be used.
2315 If no revision is specified the first current parent will be used.
2317
2316
2318 The dirstate will be set to the files of the given revision.
2317 The dirstate will be set to the files of the given revision.
2319 The actual working directory content or existing dirstate
2318 The actual working directory content or existing dirstate
2320 information such as adds or removes is not considered.
2319 information such as adds or removes is not considered.
2321
2320
2322 One use of this command is to make the next :hg:`status` invocation
2321 One use of this command is to make the next :hg:`status` invocation
2323 check the actual file content.
2322 check the actual file content.
2324 """
2323 """
2325 ctx = scmutil.revsingle(repo, rev)
2324 ctx = scmutil.revsingle(repo, rev)
2326 wlock = repo.wlock()
2325 wlock = repo.wlock()
2327 try:
2326 try:
2328 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2327 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2329 finally:
2328 finally:
2330 wlock.release()
2329 wlock.release()
2331
2330
2332 @command('debugrename',
2331 @command('debugrename',
2333 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2332 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2334 _('[-r REV] FILE'))
2333 _('[-r REV] FILE'))
2335 def debugrename(ui, repo, file1, *pats, **opts):
2334 def debugrename(ui, repo, file1, *pats, **opts):
2336 """dump rename information"""
2335 """dump rename information"""
2337
2336
2338 ctx = scmutil.revsingle(repo, opts.get('rev'))
2337 ctx = scmutil.revsingle(repo, opts.get('rev'))
2339 m = scmutil.match(ctx, (file1,) + pats, opts)
2338 m = scmutil.match(ctx, (file1,) + pats, opts)
2340 for abs in ctx.walk(m):
2339 for abs in ctx.walk(m):
2341 fctx = ctx[abs]
2340 fctx = ctx[abs]
2342 o = fctx.filelog().renamed(fctx.filenode())
2341 o = fctx.filelog().renamed(fctx.filenode())
2343 rel = m.rel(abs)
2342 rel = m.rel(abs)
2344 if o:
2343 if o:
2345 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2344 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2346 else:
2345 else:
2347 ui.write(_("%s not renamed\n") % rel)
2346 ui.write(_("%s not renamed\n") % rel)
2348
2347
2349 @command('debugrevlog',
2348 @command('debugrevlog',
2350 [('c', 'changelog', False, _('open changelog')),
2349 [('c', 'changelog', False, _('open changelog')),
2351 ('m', 'manifest', False, _('open manifest')),
2350 ('m', 'manifest', False, _('open manifest')),
2352 ('d', 'dump', False, _('dump index data'))],
2351 ('d', 'dump', False, _('dump index data'))],
2353 _('-c|-m|FILE'))
2352 _('-c|-m|FILE'))
2354 def debugrevlog(ui, repo, file_=None, **opts):
2353 def debugrevlog(ui, repo, file_=None, **opts):
2355 """show data and statistics about a revlog"""
2354 """show data and statistics about a revlog"""
2356 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2355 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2357
2356
2358 if opts.get("dump"):
2357 if opts.get("dump"):
2359 numrevs = len(r)
2358 numrevs = len(r)
2360 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2359 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2361 " rawsize totalsize compression heads\n")
2360 " rawsize totalsize compression heads\n")
2362 ts = 0
2361 ts = 0
2363 heads = set()
2362 heads = set()
2364 for rev in xrange(numrevs):
2363 for rev in xrange(numrevs):
2365 dbase = r.deltaparent(rev)
2364 dbase = r.deltaparent(rev)
2366 if dbase == -1:
2365 if dbase == -1:
2367 dbase = rev
2366 dbase = rev
2368 cbase = r.chainbase(rev)
2367 cbase = r.chainbase(rev)
2369 p1, p2 = r.parentrevs(rev)
2368 p1, p2 = r.parentrevs(rev)
2370 rs = r.rawsize(rev)
2369 rs = r.rawsize(rev)
2371 ts = ts + rs
2370 ts = ts + rs
2372 heads -= set(r.parentrevs(rev))
2371 heads -= set(r.parentrevs(rev))
2373 heads.add(rev)
2372 heads.add(rev)
2374 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2373 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),
2374 (rev, p1, p2, r.start(rev), r.end(rev),
2376 r.start(dbase), r.start(cbase),
2375 r.start(dbase), r.start(cbase),
2377 r.start(p1), r.start(p2),
2376 r.start(p1), r.start(p2),
2378 rs, ts, ts / r.end(rev), len(heads)))
2377 rs, ts, ts / r.end(rev), len(heads)))
2379 return 0
2378 return 0
2380
2379
2381 v = r.version
2380 v = r.version
2382 format = v & 0xFFFF
2381 format = v & 0xFFFF
2383 flags = []
2382 flags = []
2384 gdelta = False
2383 gdelta = False
2385 if v & revlog.REVLOGNGINLINEDATA:
2384 if v & revlog.REVLOGNGINLINEDATA:
2386 flags.append('inline')
2385 flags.append('inline')
2387 if v & revlog.REVLOGGENERALDELTA:
2386 if v & revlog.REVLOGGENERALDELTA:
2388 gdelta = True
2387 gdelta = True
2389 flags.append('generaldelta')
2388 flags.append('generaldelta')
2390 if not flags:
2389 if not flags:
2391 flags = ['(none)']
2390 flags = ['(none)']
2392
2391
2393 nummerges = 0
2392 nummerges = 0
2394 numfull = 0
2393 numfull = 0
2395 numprev = 0
2394 numprev = 0
2396 nump1 = 0
2395 nump1 = 0
2397 nump2 = 0
2396 nump2 = 0
2398 numother = 0
2397 numother = 0
2399 nump1prev = 0
2398 nump1prev = 0
2400 nump2prev = 0
2399 nump2prev = 0
2401 chainlengths = []
2400 chainlengths = []
2402
2401
2403 datasize = [None, 0, 0L]
2402 datasize = [None, 0, 0L]
2404 fullsize = [None, 0, 0L]
2403 fullsize = [None, 0, 0L]
2405 deltasize = [None, 0, 0L]
2404 deltasize = [None, 0, 0L]
2406
2405
2407 def addsize(size, l):
2406 def addsize(size, l):
2408 if l[0] is None or size < l[0]:
2407 if l[0] is None or size < l[0]:
2409 l[0] = size
2408 l[0] = size
2410 if size > l[1]:
2409 if size > l[1]:
2411 l[1] = size
2410 l[1] = size
2412 l[2] += size
2411 l[2] += size
2413
2412
2414 numrevs = len(r)
2413 numrevs = len(r)
2415 for rev in xrange(numrevs):
2414 for rev in xrange(numrevs):
2416 p1, p2 = r.parentrevs(rev)
2415 p1, p2 = r.parentrevs(rev)
2417 delta = r.deltaparent(rev)
2416 delta = r.deltaparent(rev)
2418 if format > 0:
2417 if format > 0:
2419 addsize(r.rawsize(rev), datasize)
2418 addsize(r.rawsize(rev), datasize)
2420 if p2 != nullrev:
2419 if p2 != nullrev:
2421 nummerges += 1
2420 nummerges += 1
2422 size = r.length(rev)
2421 size = r.length(rev)
2423 if delta == nullrev:
2422 if delta == nullrev:
2424 chainlengths.append(0)
2423 chainlengths.append(0)
2425 numfull += 1
2424 numfull += 1
2426 addsize(size, fullsize)
2425 addsize(size, fullsize)
2427 else:
2426 else:
2428 chainlengths.append(chainlengths[delta] + 1)
2427 chainlengths.append(chainlengths[delta] + 1)
2429 addsize(size, deltasize)
2428 addsize(size, deltasize)
2430 if delta == rev - 1:
2429 if delta == rev - 1:
2431 numprev += 1
2430 numprev += 1
2432 if delta == p1:
2431 if delta == p1:
2433 nump1prev += 1
2432 nump1prev += 1
2434 elif delta == p2:
2433 elif delta == p2:
2435 nump2prev += 1
2434 nump2prev += 1
2436 elif delta == p1:
2435 elif delta == p1:
2437 nump1 += 1
2436 nump1 += 1
2438 elif delta == p2:
2437 elif delta == p2:
2439 nump2 += 1
2438 nump2 += 1
2440 elif delta != nullrev:
2439 elif delta != nullrev:
2441 numother += 1
2440 numother += 1
2442
2441
2443 # Adjust size min value for empty cases
2442 # Adjust size min value for empty cases
2444 for size in (datasize, fullsize, deltasize):
2443 for size in (datasize, fullsize, deltasize):
2445 if size[0] is None:
2444 if size[0] is None:
2446 size[0] = 0
2445 size[0] = 0
2447
2446
2448 numdeltas = numrevs - numfull
2447 numdeltas = numrevs - numfull
2449 numoprev = numprev - nump1prev - nump2prev
2448 numoprev = numprev - nump1prev - nump2prev
2450 totalrawsize = datasize[2]
2449 totalrawsize = datasize[2]
2451 datasize[2] /= numrevs
2450 datasize[2] /= numrevs
2452 fulltotal = fullsize[2]
2451 fulltotal = fullsize[2]
2453 fullsize[2] /= numfull
2452 fullsize[2] /= numfull
2454 deltatotal = deltasize[2]
2453 deltatotal = deltasize[2]
2455 if numrevs - numfull > 0:
2454 if numrevs - numfull > 0:
2456 deltasize[2] /= numrevs - numfull
2455 deltasize[2] /= numrevs - numfull
2457 totalsize = fulltotal + deltatotal
2456 totalsize = fulltotal + deltatotal
2458 avgchainlen = sum(chainlengths) / numrevs
2457 avgchainlen = sum(chainlengths) / numrevs
2459 compratio = totalrawsize / totalsize
2458 compratio = totalrawsize / totalsize
2460
2459
2461 basedfmtstr = '%%%dd\n'
2460 basedfmtstr = '%%%dd\n'
2462 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2461 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2463
2462
2464 def dfmtstr(max):
2463 def dfmtstr(max):
2465 return basedfmtstr % len(str(max))
2464 return basedfmtstr % len(str(max))
2466 def pcfmtstr(max, padding=0):
2465 def pcfmtstr(max, padding=0):
2467 return basepcfmtstr % (len(str(max)), ' ' * padding)
2466 return basepcfmtstr % (len(str(max)), ' ' * padding)
2468
2467
2469 def pcfmt(value, total):
2468 def pcfmt(value, total):
2470 return (value, 100 * float(value) / total)
2469 return (value, 100 * float(value) / total)
2471
2470
2472 ui.write(('format : %d\n') % format)
2471 ui.write(('format : %d\n') % format)
2473 ui.write(('flags : %s\n') % ', '.join(flags))
2472 ui.write(('flags : %s\n') % ', '.join(flags))
2474
2473
2475 ui.write('\n')
2474 ui.write('\n')
2476 fmt = pcfmtstr(totalsize)
2475 fmt = pcfmtstr(totalsize)
2477 fmt2 = dfmtstr(totalsize)
2476 fmt2 = dfmtstr(totalsize)
2478 ui.write(('revisions : ') + fmt2 % numrevs)
2477 ui.write(('revisions : ') + fmt2 % numrevs)
2479 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2478 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2480 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2479 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2481 ui.write(('revisions : ') + fmt2 % numrevs)
2480 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2481 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2483 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2482 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2484 ui.write(('revision size : ') + fmt2 % totalsize)
2483 ui.write(('revision size : ') + fmt2 % totalsize)
2485 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2484 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2486 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2485 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2487
2486
2488 ui.write('\n')
2487 ui.write('\n')
2489 fmt = dfmtstr(max(avgchainlen, compratio))
2488 fmt = dfmtstr(max(avgchainlen, compratio))
2490 ui.write(('avg chain length : ') + fmt % avgchainlen)
2489 ui.write(('avg chain length : ') + fmt % avgchainlen)
2491 ui.write(('compression ratio : ') + fmt % compratio)
2490 ui.write(('compression ratio : ') + fmt % compratio)
2492
2491
2493 if format > 0:
2492 if format > 0:
2494 ui.write('\n')
2493 ui.write('\n')
2495 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2494 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2496 % tuple(datasize))
2495 % tuple(datasize))
2497 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2496 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2498 % tuple(fullsize))
2497 % tuple(fullsize))
2499 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2498 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(deltasize))
2499 % tuple(deltasize))
2501
2500
2502 if numdeltas > 0:
2501 if numdeltas > 0:
2503 ui.write('\n')
2502 ui.write('\n')
2504 fmt = pcfmtstr(numdeltas)
2503 fmt = pcfmtstr(numdeltas)
2505 fmt2 = pcfmtstr(numdeltas, 4)
2504 fmt2 = pcfmtstr(numdeltas, 4)
2506 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2505 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2507 if numprev > 0:
2506 if numprev > 0:
2508 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2507 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2509 numprev))
2508 numprev))
2510 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2509 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2511 numprev))
2510 numprev))
2512 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2511 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2513 numprev))
2512 numprev))
2514 if gdelta:
2513 if gdelta:
2515 ui.write(('deltas against p1 : ')
2514 ui.write(('deltas against p1 : ')
2516 + fmt % pcfmt(nump1, numdeltas))
2515 + fmt % pcfmt(nump1, numdeltas))
2517 ui.write(('deltas against p2 : ')
2516 ui.write(('deltas against p2 : ')
2518 + fmt % pcfmt(nump2, numdeltas))
2517 + fmt % pcfmt(nump2, numdeltas))
2519 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2518 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2520 numdeltas))
2519 numdeltas))
2521
2520
2522 @command('debugrevspec', [], ('REVSPEC'))
2521 @command('debugrevspec', [], ('REVSPEC'))
2523 def debugrevspec(ui, repo, expr):
2522 def debugrevspec(ui, repo, expr):
2524 """parse and apply a revision specification
2523 """parse and apply a revision specification
2525
2524
2526 Use --verbose to print the parsed tree before and after aliases
2525 Use --verbose to print the parsed tree before and after aliases
2527 expansion.
2526 expansion.
2528 """
2527 """
2529 if ui.verbose:
2528 if ui.verbose:
2530 tree = revset.parse(expr)[0]
2529 tree = revset.parse(expr)[0]
2531 ui.note(revset.prettyformat(tree), "\n")
2530 ui.note(revset.prettyformat(tree), "\n")
2532 newtree = revset.findaliases(ui, tree)
2531 newtree = revset.findaliases(ui, tree)
2533 if newtree != tree:
2532 if newtree != tree:
2534 ui.note(revset.prettyformat(newtree), "\n")
2533 ui.note(revset.prettyformat(newtree), "\n")
2535 func = revset.match(ui, expr)
2534 func = revset.match(ui, expr)
2536 for c in func(repo, range(len(repo))):
2535 for c in func(repo, range(len(repo))):
2537 ui.write("%s\n" % c)
2536 ui.write("%s\n" % c)
2538
2537
2539 @command('debugsetparents', [], _('REV1 [REV2]'))
2538 @command('debugsetparents', [], _('REV1 [REV2]'))
2540 def debugsetparents(ui, repo, rev1, rev2=None):
2539 def debugsetparents(ui, repo, rev1, rev2=None):
2541 """manually set the parents of the current working directory
2540 """manually set the parents of the current working directory
2542
2541
2543 This is useful for writing repository conversion tools, but should
2542 This is useful for writing repository conversion tools, but should
2544 be used with care.
2543 be used with care.
2545
2544
2546 Returns 0 on success.
2545 Returns 0 on success.
2547 """
2546 """
2548
2547
2549 r1 = scmutil.revsingle(repo, rev1).node()
2548 r1 = scmutil.revsingle(repo, rev1).node()
2550 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2549 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2551
2550
2552 wlock = repo.wlock()
2551 wlock = repo.wlock()
2553 try:
2552 try:
2554 repo.setparents(r1, r2)
2553 repo.setparents(r1, r2)
2555 finally:
2554 finally:
2556 wlock.release()
2555 wlock.release()
2557
2556
2558 @command('debugdirstate|debugstate',
2557 @command('debugdirstate|debugstate',
2559 [('', 'nodates', None, _('do not display the saved mtime')),
2558 [('', 'nodates', None, _('do not display the saved mtime')),
2560 ('', 'datesort', None, _('sort by saved mtime'))],
2559 ('', 'datesort', None, _('sort by saved mtime'))],
2561 _('[OPTION]...'))
2560 _('[OPTION]...'))
2562 def debugstate(ui, repo, nodates=None, datesort=None):
2561 def debugstate(ui, repo, nodates=None, datesort=None):
2563 """show the contents of the current dirstate"""
2562 """show the contents of the current dirstate"""
2564 timestr = ""
2563 timestr = ""
2565 showdate = not nodates
2564 showdate = not nodates
2566 if datesort:
2565 if datesort:
2567 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2566 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2568 else:
2567 else:
2569 keyfunc = None # sort by filename
2568 keyfunc = None # sort by filename
2570 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2569 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2571 if showdate:
2570 if showdate:
2572 if ent[3] == -1:
2571 if ent[3] == -1:
2573 # Pad or slice to locale representation
2572 # Pad or slice to locale representation
2574 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2573 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2575 time.localtime(0)))
2574 time.localtime(0)))
2576 timestr = 'unset'
2575 timestr = 'unset'
2577 timestr = (timestr[:locale_len] +
2576 timestr = (timestr[:locale_len] +
2578 ' ' * (locale_len - len(timestr)))
2577 ' ' * (locale_len - len(timestr)))
2579 else:
2578 else:
2580 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2579 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2581 time.localtime(ent[3]))
2580 time.localtime(ent[3]))
2582 if ent[1] & 020000:
2581 if ent[1] & 020000:
2583 mode = 'lnk'
2582 mode = 'lnk'
2584 else:
2583 else:
2585 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2584 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2586 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2585 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2587 for f in repo.dirstate.copies():
2586 for f in repo.dirstate.copies():
2588 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2587 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2589
2588
2590 @command('debugsub',
2589 @command('debugsub',
2591 [('r', 'rev', '',
2590 [('r', 'rev', '',
2592 _('revision to check'), _('REV'))],
2591 _('revision to check'), _('REV'))],
2593 _('[-r REV] [REV]'))
2592 _('[-r REV] [REV]'))
2594 def debugsub(ui, repo, rev=None):
2593 def debugsub(ui, repo, rev=None):
2595 ctx = scmutil.revsingle(repo, rev, None)
2594 ctx = scmutil.revsingle(repo, rev, None)
2596 for k, v in sorted(ctx.substate.items()):
2595 for k, v in sorted(ctx.substate.items()):
2597 ui.write(('path %s\n') % k)
2596 ui.write(('path %s\n') % k)
2598 ui.write((' source %s\n') % v[0])
2597 ui.write((' source %s\n') % v[0])
2599 ui.write((' revision %s\n') % v[1])
2598 ui.write((' revision %s\n') % v[1])
2600
2599
2601 @command('debugsuccessorssets',
2600 @command('debugsuccessorssets',
2602 [],
2601 [],
2603 _('[REV]'))
2602 _('[REV]'))
2604 def debugsuccessorssets(ui, repo, *revs):
2603 def debugsuccessorssets(ui, repo, *revs):
2605 """show set of successors for revision
2604 """show set of successors for revision
2606
2605
2607 A successors set of changeset A is a consistent group of revisions that
2606 A successors set of changeset A is a consistent group of revisions that
2608 succeed A. It contains non-obsolete changesets only.
2607 succeed A. It contains non-obsolete changesets only.
2609
2608
2610 In most cases a changeset A has a single successors set containing a single
2609 In most cases a changeset A has a single successors set containing a single
2611 successor (changeset A replaced by A').
2610 successor (changeset A replaced by A').
2612
2611
2613 A changeset that is made obsolete with no successors are called "pruned".
2612 A changeset that is made obsolete with no successors are called "pruned".
2614 Such changesets have no successors sets at all.
2613 Such changesets have no successors sets at all.
2615
2614
2616 A changeset that has been "split" will have a successors set containing
2615 A changeset that has been "split" will have a successors set containing
2617 more than one successor.
2616 more than one successor.
2618
2617
2619 A changeset that has been rewritten in multiple different ways is called
2618 A changeset that has been rewritten in multiple different ways is called
2620 "divergent". Such changesets have multiple successor sets (each of which
2619 "divergent". Such changesets have multiple successor sets (each of which
2621 may also be split, i.e. have multiple successors).
2620 may also be split, i.e. have multiple successors).
2622
2621
2623 Results are displayed as follows::
2622 Results are displayed as follows::
2624
2623
2625 <rev1>
2624 <rev1>
2626 <successors-1A>
2625 <successors-1A>
2627 <rev2>
2626 <rev2>
2628 <successors-2A>
2627 <successors-2A>
2629 <successors-2B1> <successors-2B2> <successors-2B3>
2628 <successors-2B1> <successors-2B2> <successors-2B3>
2630
2629
2631 Here rev2 has two possible (i.e. divergent) successors sets. The first
2630 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
2631 holds one element, whereas the second holds three (i.e. the changeset has
2633 been split).
2632 been split).
2634 """
2633 """
2635 # passed to successorssets caching computation from one call to another
2634 # passed to successorssets caching computation from one call to another
2636 cache = {}
2635 cache = {}
2637 ctx2str = str
2636 ctx2str = str
2638 node2str = short
2637 node2str = short
2639 if ui.debug():
2638 if ui.debug():
2640 def ctx2str(ctx):
2639 def ctx2str(ctx):
2641 return ctx.hex()
2640 return ctx.hex()
2642 node2str = hex
2641 node2str = hex
2643 for rev in scmutil.revrange(repo, revs):
2642 for rev in scmutil.revrange(repo, revs):
2644 ctx = repo[rev]
2643 ctx = repo[rev]
2645 ui.write('%s\n'% ctx2str(ctx))
2644 ui.write('%s\n'% ctx2str(ctx))
2646 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2645 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2647 if succsset:
2646 if succsset:
2648 ui.write(' ')
2647 ui.write(' ')
2649 ui.write(node2str(succsset[0]))
2648 ui.write(node2str(succsset[0]))
2650 for node in succsset[1:]:
2649 for node in succsset[1:]:
2651 ui.write(' ')
2650 ui.write(' ')
2652 ui.write(node2str(node))
2651 ui.write(node2str(node))
2653 ui.write('\n')
2652 ui.write('\n')
2654
2653
2655 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2654 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2656 def debugwalk(ui, repo, *pats, **opts):
2655 def debugwalk(ui, repo, *pats, **opts):
2657 """show how files match on given patterns"""
2656 """show how files match on given patterns"""
2658 m = scmutil.match(repo[None], pats, opts)
2657 m = scmutil.match(repo[None], pats, opts)
2659 items = list(repo.walk(m))
2658 items = list(repo.walk(m))
2660 if not items:
2659 if not items:
2661 return
2660 return
2662 f = lambda fn: fn
2661 f = lambda fn: fn
2663 if ui.configbool('ui', 'slash') and os.sep != '/':
2662 if ui.configbool('ui', 'slash') and os.sep != '/':
2664 f = lambda fn: util.normpath(fn)
2663 f = lambda fn: util.normpath(fn)
2665 fmt = 'f %%-%ds %%-%ds %%s' % (
2664 fmt = 'f %%-%ds %%-%ds %%s' % (
2666 max([len(abs) for abs in items]),
2665 max([len(abs) for abs in items]),
2667 max([len(m.rel(abs)) for abs in items]))
2666 max([len(m.rel(abs)) for abs in items]))
2668 for abs in items:
2667 for abs in items:
2669 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2668 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2670 ui.write("%s\n" % line.rstrip())
2669 ui.write("%s\n" % line.rstrip())
2671
2670
2672 @command('debugwireargs',
2671 @command('debugwireargs',
2673 [('', 'three', '', 'three'),
2672 [('', 'three', '', 'three'),
2674 ('', 'four', '', 'four'),
2673 ('', 'four', '', 'four'),
2675 ('', 'five', '', 'five'),
2674 ('', 'five', '', 'five'),
2676 ] + remoteopts,
2675 ] + remoteopts,
2677 _('REPO [OPTIONS]... [ONE [TWO]]'))
2676 _('REPO [OPTIONS]... [ONE [TWO]]'))
2678 def debugwireargs(ui, repopath, *vals, **opts):
2677 def debugwireargs(ui, repopath, *vals, **opts):
2679 repo = hg.peer(ui, opts, repopath)
2678 repo = hg.peer(ui, opts, repopath)
2680 for opt in remoteopts:
2679 for opt in remoteopts:
2681 del opts[opt[1]]
2680 del opts[opt[1]]
2682 args = {}
2681 args = {}
2683 for k, v in opts.iteritems():
2682 for k, v in opts.iteritems():
2684 if v:
2683 if v:
2685 args[k] = v
2684 args[k] = v
2686 # run twice to check that we don't mess up the stream for the next command
2685 # run twice to check that we don't mess up the stream for the next command
2687 res1 = repo.debugwireargs(*vals, **args)
2686 res1 = repo.debugwireargs(*vals, **args)
2688 res2 = repo.debugwireargs(*vals, **args)
2687 res2 = repo.debugwireargs(*vals, **args)
2689 ui.write("%s\n" % res1)
2688 ui.write("%s\n" % res1)
2690 if res1 != res2:
2689 if res1 != res2:
2691 ui.warn("%s\n" % res2)
2690 ui.warn("%s\n" % res2)
2692
2691
2693 @command('^diff',
2692 @command('^diff',
2694 [('r', 'rev', [], _('revision'), _('REV')),
2693 [('r', 'rev', [], _('revision'), _('REV')),
2695 ('c', 'change', '', _('change made by revision'), _('REV'))
2694 ('c', 'change', '', _('change made by revision'), _('REV'))
2696 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2695 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2697 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2696 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2698 def diff(ui, repo, *pats, **opts):
2697 def diff(ui, repo, *pats, **opts):
2699 """diff repository (or selected files)
2698 """diff repository (or selected files)
2700
2699
2701 Show differences between revisions for the specified files.
2700 Show differences between revisions for the specified files.
2702
2701
2703 Differences between files are shown using the unified diff format.
2702 Differences between files are shown using the unified diff format.
2704
2703
2705 .. note::
2704 .. note::
2706
2705
2707 diff may generate unexpected results for merges, as it will
2706 diff may generate unexpected results for merges, as it will
2708 default to comparing against the working directory's first
2707 default to comparing against the working directory's first
2709 parent changeset if no revisions are specified.
2708 parent changeset if no revisions are specified.
2710
2709
2711 When two revision arguments are given, then changes are shown
2710 When two revision arguments are given, then changes are shown
2712 between those revisions. If only one revision is specified then
2711 between those revisions. If only one revision is specified then
2713 that revision is compared to the working directory, and, when no
2712 that revision is compared to the working directory, and, when no
2714 revisions are specified, the working directory files are compared
2713 revisions are specified, the working directory files are compared
2715 to its parent.
2714 to its parent.
2716
2715
2717 Alternatively you can specify -c/--change with a revision to see
2716 Alternatively you can specify -c/--change with a revision to see
2718 the changes in that changeset relative to its first parent.
2717 the changes in that changeset relative to its first parent.
2719
2718
2720 Without the -a/--text option, diff will avoid generating diffs of
2719 Without the -a/--text option, diff will avoid generating diffs of
2721 files it detects as binary. With -a, diff will generate a diff
2720 files it detects as binary. With -a, diff will generate a diff
2722 anyway, probably with undesirable results.
2721 anyway, probably with undesirable results.
2723
2722
2724 Use the -g/--git option to generate diffs in the git extended diff
2723 Use the -g/--git option to generate diffs in the git extended diff
2725 format. For more information, read :hg:`help diffs`.
2724 format. For more information, read :hg:`help diffs`.
2726
2725
2727 .. container:: verbose
2726 .. container:: verbose
2728
2727
2729 Examples:
2728 Examples:
2730
2729
2731 - compare a file in the current working directory to its parent::
2730 - compare a file in the current working directory to its parent::
2732
2731
2733 hg diff foo.c
2732 hg diff foo.c
2734
2733
2735 - compare two historical versions of a directory, with rename info::
2734 - compare two historical versions of a directory, with rename info::
2736
2735
2737 hg diff --git -r 1.0:1.2 lib/
2736 hg diff --git -r 1.0:1.2 lib/
2738
2737
2739 - get change stats relative to the last change on some date::
2738 - get change stats relative to the last change on some date::
2740
2739
2741 hg diff --stat -r "date('may 2')"
2740 hg diff --stat -r "date('may 2')"
2742
2741
2743 - diff all newly-added files that contain a keyword::
2742 - diff all newly-added files that contain a keyword::
2744
2743
2745 hg diff "set:added() and grep(GNU)"
2744 hg diff "set:added() and grep(GNU)"
2746
2745
2747 - compare a revision and its parents::
2746 - compare a revision and its parents::
2748
2747
2749 hg diff -c 9353 # compare against first parent
2748 hg diff -c 9353 # compare against first parent
2750 hg diff -r 9353^:9353 # same using revset syntax
2749 hg diff -r 9353^:9353 # same using revset syntax
2751 hg diff -r 9353^2:9353 # compare against the second parent
2750 hg diff -r 9353^2:9353 # compare against the second parent
2752
2751
2753 Returns 0 on success.
2752 Returns 0 on success.
2754 """
2753 """
2755
2754
2756 revs = opts.get('rev')
2755 revs = opts.get('rev')
2757 change = opts.get('change')
2756 change = opts.get('change')
2758 stat = opts.get('stat')
2757 stat = opts.get('stat')
2759 reverse = opts.get('reverse')
2758 reverse = opts.get('reverse')
2760
2759
2761 if revs and change:
2760 if revs and change:
2762 msg = _('cannot specify --rev and --change at the same time')
2761 msg = _('cannot specify --rev and --change at the same time')
2763 raise util.Abort(msg)
2762 raise util.Abort(msg)
2764 elif change:
2763 elif change:
2765 node2 = scmutil.revsingle(repo, change, None).node()
2764 node2 = scmutil.revsingle(repo, change, None).node()
2766 node1 = repo[node2].p1().node()
2765 node1 = repo[node2].p1().node()
2767 else:
2766 else:
2768 node1, node2 = scmutil.revpair(repo, revs)
2767 node1, node2 = scmutil.revpair(repo, revs)
2769
2768
2770 if reverse:
2769 if reverse:
2771 node1, node2 = node2, node1
2770 node1, node2 = node2, node1
2772
2771
2773 diffopts = patch.diffopts(ui, opts)
2772 diffopts = patch.diffopts(ui, opts)
2774 m = scmutil.match(repo[node2], pats, opts)
2773 m = scmutil.match(repo[node2], pats, opts)
2775 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2774 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2776 listsubrepos=opts.get('subrepos'))
2775 listsubrepos=opts.get('subrepos'))
2777
2776
2778 @command('^export',
2777 @command('^export',
2779 [('o', 'output', '',
2778 [('o', 'output', '',
2780 _('print output to file with formatted name'), _('FORMAT')),
2779 _('print output to file with formatted name'), _('FORMAT')),
2781 ('', 'switch-parent', None, _('diff against the second parent')),
2780 ('', 'switch-parent', None, _('diff against the second parent')),
2782 ('r', 'rev', [], _('revisions to export'), _('REV')),
2781 ('r', 'rev', [], _('revisions to export'), _('REV')),
2783 ] + diffopts,
2782 ] + diffopts,
2784 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2783 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2785 def export(ui, repo, *changesets, **opts):
2784 def export(ui, repo, *changesets, **opts):
2786 """dump the header and diffs for one or more changesets
2785 """dump the header and diffs for one or more changesets
2787
2786
2788 Print the changeset header and diffs for one or more revisions.
2787 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.
2788 If no revision is given, the parent of the working directory is used.
2790
2789
2791 The information shown in the changeset header is: author, date,
2790 The information shown in the changeset header is: author, date,
2792 branch name (if non-default), changeset hash, parent(s) and commit
2791 branch name (if non-default), changeset hash, parent(s) and commit
2793 comment.
2792 comment.
2794
2793
2795 .. note::
2794 .. note::
2796
2795
2797 export may generate unexpected diff output for merge
2796 export may generate unexpected diff output for merge
2798 changesets, as it will compare the merge changeset against its
2797 changesets, as it will compare the merge changeset against its
2799 first parent only.
2798 first parent only.
2800
2799
2801 Output may be to a file, in which case the name of the file is
2800 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:
2801 given using a format string. The formatting rules are as follows:
2803
2802
2804 :``%%``: literal "%" character
2803 :``%%``: literal "%" character
2805 :``%H``: changeset hash (40 hexadecimal digits)
2804 :``%H``: changeset hash (40 hexadecimal digits)
2806 :``%N``: number of patches being generated
2805 :``%N``: number of patches being generated
2807 :``%R``: changeset revision number
2806 :``%R``: changeset revision number
2808 :``%b``: basename of the exporting repository
2807 :``%b``: basename of the exporting repository
2809 :``%h``: short-form changeset hash (12 hexadecimal digits)
2808 :``%h``: short-form changeset hash (12 hexadecimal digits)
2810 :``%m``: first line of the commit message (only alphanumeric characters)
2809 :``%m``: first line of the commit message (only alphanumeric characters)
2811 :``%n``: zero-padded sequence number, starting at 1
2810 :``%n``: zero-padded sequence number, starting at 1
2812 :``%r``: zero-padded changeset revision number
2811 :``%r``: zero-padded changeset revision number
2813
2812
2814 Without the -a/--text option, export will avoid generating diffs
2813 Without the -a/--text option, export will avoid generating diffs
2815 of files it detects as binary. With -a, export will generate a
2814 of files it detects as binary. With -a, export will generate a
2816 diff anyway, probably with undesirable results.
2815 diff anyway, probably with undesirable results.
2817
2816
2818 Use the -g/--git option to generate diffs in the git extended diff
2817 Use the -g/--git option to generate diffs in the git extended diff
2819 format. See :hg:`help diffs` for more information.
2818 format. See :hg:`help diffs` for more information.
2820
2819
2821 With the --switch-parent option, the diff will be against the
2820 With the --switch-parent option, the diff will be against the
2822 second parent. It can be useful to review a merge.
2821 second parent. It can be useful to review a merge.
2823
2822
2824 .. container:: verbose
2823 .. container:: verbose
2825
2824
2826 Examples:
2825 Examples:
2827
2826
2828 - use export and import to transplant a bugfix to the current
2827 - use export and import to transplant a bugfix to the current
2829 branch::
2828 branch::
2830
2829
2831 hg export -r 9353 | hg import -
2830 hg export -r 9353 | hg import -
2832
2831
2833 - export all the changesets between two revisions to a file with
2832 - export all the changesets between two revisions to a file with
2834 rename information::
2833 rename information::
2835
2834
2836 hg export --git -r 123:150 > changes.txt
2835 hg export --git -r 123:150 > changes.txt
2837
2836
2838 - split outgoing changes into a series of patches with
2837 - split outgoing changes into a series of patches with
2839 descriptive names::
2838 descriptive names::
2840
2839
2841 hg export -r "outgoing()" -o "%n-%m.patch"
2840 hg export -r "outgoing()" -o "%n-%m.patch"
2842
2841
2843 Returns 0 on success.
2842 Returns 0 on success.
2844 """
2843 """
2845 changesets += tuple(opts.get('rev', []))
2844 changesets += tuple(opts.get('rev', []))
2846 if not changesets:
2845 if not changesets:
2847 changesets = ['.']
2846 changesets = ['.']
2848 revs = scmutil.revrange(repo, changesets)
2847 revs = scmutil.revrange(repo, changesets)
2849 if not revs:
2848 if not revs:
2850 raise util.Abort(_("export requires at least one changeset"))
2849 raise util.Abort(_("export requires at least one changeset"))
2851 if len(revs) > 1:
2850 if len(revs) > 1:
2852 ui.note(_('exporting patches:\n'))
2851 ui.note(_('exporting patches:\n'))
2853 else:
2852 else:
2854 ui.note(_('exporting patch:\n'))
2853 ui.note(_('exporting patch:\n'))
2855 cmdutil.export(repo, revs, template=opts.get('output'),
2854 cmdutil.export(repo, revs, template=opts.get('output'),
2856 switch_parent=opts.get('switch_parent'),
2855 switch_parent=opts.get('switch_parent'),
2857 opts=patch.diffopts(ui, opts))
2856 opts=patch.diffopts(ui, opts))
2858
2857
2859 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2858 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2860 def forget(ui, repo, *pats, **opts):
2859 def forget(ui, repo, *pats, **opts):
2861 """forget the specified files on the next commit
2860 """forget the specified files on the next commit
2862
2861
2863 Mark the specified files so they will no longer be tracked
2862 Mark the specified files so they will no longer be tracked
2864 after the next commit.
2863 after the next commit.
2865
2864
2866 This only removes files from the current branch, not from the
2865 This only removes files from the current branch, not from the
2867 entire project history, and it does not delete them from the
2866 entire project history, and it does not delete them from the
2868 working directory.
2867 working directory.
2869
2868
2870 To undo a forget before the next commit, see :hg:`add`.
2869 To undo a forget before the next commit, see :hg:`add`.
2871
2870
2872 .. container:: verbose
2871 .. container:: verbose
2873
2872
2874 Examples:
2873 Examples:
2875
2874
2876 - forget newly-added binary files::
2875 - forget newly-added binary files::
2877
2876
2878 hg forget "set:added() and binary()"
2877 hg forget "set:added() and binary()"
2879
2878
2880 - forget files that would be excluded by .hgignore::
2879 - forget files that would be excluded by .hgignore::
2881
2880
2882 hg forget "set:hgignore()"
2881 hg forget "set:hgignore()"
2883
2882
2884 Returns 0 on success.
2883 Returns 0 on success.
2885 """
2884 """
2886
2885
2887 if not pats:
2886 if not pats:
2888 raise util.Abort(_('no files specified'))
2887 raise util.Abort(_('no files specified'))
2889
2888
2890 m = scmutil.match(repo[None], pats, opts)
2889 m = scmutil.match(repo[None], pats, opts)
2891 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2890 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2892 return rejected and 1 or 0
2891 return rejected and 1 or 0
2893
2892
2894 @command(
2893 @command(
2895 'graft',
2894 'graft',
2896 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2895 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2897 ('c', 'continue', False, _('resume interrupted graft')),
2896 ('c', 'continue', False, _('resume interrupted graft')),
2898 ('e', 'edit', False, _('invoke editor on commit messages')),
2897 ('e', 'edit', False, _('invoke editor on commit messages')),
2899 ('', 'log', None, _('append graft info to log message')),
2898 ('', 'log', None, _('append graft info to log message')),
2900 ('D', 'currentdate', False,
2899 ('D', 'currentdate', False,
2901 _('record the current date as commit date')),
2900 _('record the current date as commit date')),
2902 ('U', 'currentuser', False,
2901 ('U', 'currentuser', False,
2903 _('record the current user as committer'), _('DATE'))]
2902 _('record the current user as committer'), _('DATE'))]
2904 + commitopts2 + mergetoolopts + dryrunopts,
2903 + commitopts2 + mergetoolopts + dryrunopts,
2905 _('[OPTION]... [-r] REV...'))
2904 _('[OPTION]... [-r] REV...'))
2906 def graft(ui, repo, *revs, **opts):
2905 def graft(ui, repo, *revs, **opts):
2907 '''copy changes from other branches onto the current branch
2906 '''copy changes from other branches onto the current branch
2908
2907
2909 This command uses Mercurial's merge logic to copy individual
2908 This command uses Mercurial's merge logic to copy individual
2910 changes from other branches without merging branches in the
2909 changes from other branches without merging branches in the
2911 history graph. This is sometimes known as 'backporting' or
2910 history graph. This is sometimes known as 'backporting' or
2912 'cherry-picking'. By default, graft will copy user, date, and
2911 'cherry-picking'. By default, graft will copy user, date, and
2913 description from the source changesets.
2912 description from the source changesets.
2914
2913
2915 Changesets that are ancestors of the current revision, that have
2914 Changesets that are ancestors of the current revision, that have
2916 already been grafted, or that are merges will be skipped.
2915 already been grafted, or that are merges will be skipped.
2917
2916
2918 If --log is specified, log messages will have a comment appended
2917 If --log is specified, log messages will have a comment appended
2919 of the form::
2918 of the form::
2920
2919
2921 (grafted from CHANGESETHASH)
2920 (grafted from CHANGESETHASH)
2922
2921
2923 If a graft merge results in conflicts, the graft process is
2922 If a graft merge results in conflicts, the graft process is
2924 interrupted so that the current merge can be manually resolved.
2923 interrupted so that the current merge can be manually resolved.
2925 Once all conflicts are addressed, the graft process can be
2924 Once all conflicts are addressed, the graft process can be
2926 continued with the -c/--continue option.
2925 continued with the -c/--continue option.
2927
2926
2928 .. note::
2927 .. note::
2929
2928
2930 The -c/--continue option does not reapply earlier options.
2929 The -c/--continue option does not reapply earlier options.
2931
2930
2932 .. container:: verbose
2931 .. container:: verbose
2933
2932
2934 Examples:
2933 Examples:
2935
2934
2936 - copy a single change to the stable branch and edit its description::
2935 - copy a single change to the stable branch and edit its description::
2937
2936
2938 hg update stable
2937 hg update stable
2939 hg graft --edit 9393
2938 hg graft --edit 9393
2940
2939
2941 - graft a range of changesets with one exception, updating dates::
2940 - graft a range of changesets with one exception, updating dates::
2942
2941
2943 hg graft -D "2085::2093 and not 2091"
2942 hg graft -D "2085::2093 and not 2091"
2944
2943
2945 - continue a graft after resolving conflicts::
2944 - continue a graft after resolving conflicts::
2946
2945
2947 hg graft -c
2946 hg graft -c
2948
2947
2949 - show the source of a grafted changeset::
2948 - show the source of a grafted changeset::
2950
2949
2951 hg log --debug -r .
2950 hg log --debug -r .
2952
2951
2953 Returns 0 on successful completion.
2952 Returns 0 on successful completion.
2954 '''
2953 '''
2955
2954
2956 revs = list(revs)
2955 revs = list(revs)
2957 revs.extend(opts['rev'])
2956 revs.extend(opts['rev'])
2958
2957
2959 if not opts.get('user') and opts.get('currentuser'):
2958 if not opts.get('user') and opts.get('currentuser'):
2960 opts['user'] = ui.username()
2959 opts['user'] = ui.username()
2961 if not opts.get('date') and opts.get('currentdate'):
2960 if not opts.get('date') and opts.get('currentdate'):
2962 opts['date'] = "%d %d" % util.makedate()
2961 opts['date'] = "%d %d" % util.makedate()
2963
2962
2964 editor = None
2963 editor = None
2965 if opts.get('edit'):
2964 if opts.get('edit'):
2966 editor = cmdutil.commitforceeditor
2965 editor = cmdutil.commitforceeditor
2967
2966
2968 cont = False
2967 cont = False
2969 if opts['continue']:
2968 if opts['continue']:
2970 cont = True
2969 cont = True
2971 if revs:
2970 if revs:
2972 raise util.Abort(_("can't specify --continue and revisions"))
2971 raise util.Abort(_("can't specify --continue and revisions"))
2973 # read in unfinished revisions
2972 # read in unfinished revisions
2974 try:
2973 try:
2975 nodes = repo.opener.read('graftstate').splitlines()
2974 nodes = repo.opener.read('graftstate').splitlines()
2976 revs = [repo[node].rev() for node in nodes]
2975 revs = [repo[node].rev() for node in nodes]
2977 except IOError, inst:
2976 except IOError, inst:
2978 if inst.errno != errno.ENOENT:
2977 if inst.errno != errno.ENOENT:
2979 raise
2978 raise
2980 raise util.Abort(_("no graft state found, can't continue"))
2979 raise util.Abort(_("no graft state found, can't continue"))
2981 else:
2980 else:
2982 cmdutil.checkunfinished(repo)
2981 cmdutil.checkunfinished(repo)
2983 cmdutil.bailifchanged(repo)
2982 cmdutil.bailifchanged(repo)
2984 if not revs:
2983 if not revs:
2985 raise util.Abort(_('no revisions specified'))
2984 raise util.Abort(_('no revisions specified'))
2986 revs = scmutil.revrange(repo, revs)
2985 revs = scmutil.revrange(repo, revs)
2987
2986
2988 # check for merges
2987 # check for merges
2989 for rev in repo.revs('%ld and merge()', revs):
2988 for rev in repo.revs('%ld and merge()', revs):
2990 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2989 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 revs.remove(rev)
2990 revs.remove(rev)
2992 if not revs:
2991 if not revs:
2993 return -1
2992 return -1
2994
2993
2995 # check for ancestors of dest branch
2994 # check for ancestors of dest branch
2996 crev = repo['.'].rev()
2995 crev = repo['.'].rev()
2997 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2996 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 # don't mutate while iterating, create a copy
2997 # don't mutate while iterating, create a copy
2999 for rev in list(revs):
2998 for rev in list(revs):
3000 if rev in ancestors:
2999 if rev in ancestors:
3001 ui.warn(_('skipping ancestor revision %s\n') % rev)
3000 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 revs.remove(rev)
3001 revs.remove(rev)
3003 if not revs:
3002 if not revs:
3004 return -1
3003 return -1
3005
3004
3006 # analyze revs for earlier grafts
3005 # analyze revs for earlier grafts
3007 ids = {}
3006 ids = {}
3008 for ctx in repo.set("%ld", revs):
3007 for ctx in repo.set("%ld", revs):
3009 ids[ctx.hex()] = ctx.rev()
3008 ids[ctx.hex()] = ctx.rev()
3010 n = ctx.extra().get('source')
3009 n = ctx.extra().get('source')
3011 if n:
3010 if n:
3012 ids[n] = ctx.rev()
3011 ids[n] = ctx.rev()
3013
3012
3014 # check ancestors for earlier grafts
3013 # check ancestors for earlier grafts
3015 ui.debug('scanning for duplicate grafts\n')
3014 ui.debug('scanning for duplicate grafts\n')
3016
3015
3017 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3016 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 ctx = repo[rev]
3017 ctx = repo[rev]
3019 n = ctx.extra().get('source')
3018 n = ctx.extra().get('source')
3020 if n in ids:
3019 if n in ids:
3021 r = repo[n].rev()
3020 r = repo[n].rev()
3022 if r in revs:
3021 if r in revs:
3023 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3022 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3024 % (r, rev))
3023 % (r, rev))
3025 revs.remove(r)
3024 revs.remove(r)
3026 elif ids[n] in revs:
3025 elif ids[n] in revs:
3027 ui.warn(_('skipping already grafted revision %s '
3026 ui.warn(_('skipping already grafted revision %s '
3028 '(%s also has origin %d)\n') % (ids[n], rev, r))
3027 '(%s also has origin %d)\n') % (ids[n], rev, r))
3029 revs.remove(ids[n])
3028 revs.remove(ids[n])
3030 elif ctx.hex() in ids:
3029 elif ctx.hex() in ids:
3031 r = ids[ctx.hex()]
3030 r = ids[ctx.hex()]
3032 ui.warn(_('skipping already grafted revision %s '
3031 ui.warn(_('skipping already grafted revision %s '
3033 '(was grafted from %d)\n') % (r, rev))
3032 '(was grafted from %d)\n') % (r, rev))
3034 revs.remove(r)
3033 revs.remove(r)
3035 if not revs:
3034 if not revs:
3036 return -1
3035 return -1
3037
3036
3038 wlock = repo.wlock()
3037 wlock = repo.wlock()
3039 try:
3038 try:
3040 current = repo['.']
3039 current = repo['.']
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3040 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042
3041
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3042 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 if opts.get('dry_run'):
3043 if opts.get('dry_run'):
3045 continue
3044 continue
3046
3045
3047 source = ctx.extra().get('source')
3046 source = ctx.extra().get('source')
3048 if not source:
3047 if not source:
3049 source = ctx.hex()
3048 source = ctx.hex()
3050 extra = {'source': source}
3049 extra = {'source': source}
3051 user = ctx.user()
3050 user = ctx.user()
3052 if opts.get('user'):
3051 if opts.get('user'):
3053 user = opts['user']
3052 user = opts['user']
3054 date = ctx.date()
3053 date = ctx.date()
3055 if opts.get('date'):
3054 if opts.get('date'):
3056 date = opts['date']
3055 date = opts['date']
3057 message = ctx.description()
3056 message = ctx.description()
3058 if opts.get('log'):
3057 if opts.get('log'):
3059 message += '\n(grafted from %s)' % ctx.hex()
3058 message += '\n(grafted from %s)' % ctx.hex()
3060
3059
3061 # we don't merge the first commit when continuing
3060 # we don't merge the first commit when continuing
3062 if not cont:
3061 if not cont:
3063 # perform the graft merge with p1(rev) as 'ancestor'
3062 # perform the graft merge with p1(rev) as 'ancestor'
3064 try:
3063 try:
3065 # ui.forcemerge is an internal variable, do not document
3064 # ui.forcemerge is an internal variable, do not document
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3065 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3066 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 ctx.p1().node())
3067 ctx.p1().node())
3069 finally:
3068 finally:
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3069 repo.ui.setconfig('ui', 'forcemerge', '')
3071 # report any conflicts
3070 # report any conflicts
3072 if stats and stats[3] > 0:
3071 if stats and stats[3] > 0:
3073 # write out state for --continue
3072 # write out state for --continue
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3073 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 repo.opener.write('graftstate', ''.join(nodelines))
3074 repo.opener.write('graftstate', ''.join(nodelines))
3076 raise util.Abort(
3075 raise util.Abort(
3077 _("unresolved conflicts, can't continue"),
3076 _("unresolved conflicts, can't continue"),
3078 hint=_('use hg resolve and hg graft --continue'))
3077 hint=_('use hg resolve and hg graft --continue'))
3079 else:
3078 else:
3080 cont = False
3079 cont = False
3081
3080
3082 # drop the second merge parent
3081 # drop the second merge parent
3083 repo.setparents(current.node(), nullid)
3082 repo.setparents(current.node(), nullid)
3084 repo.dirstate.write()
3083 repo.dirstate.write()
3085 # fix up dirstate for copies and renames
3084 # fix up dirstate for copies and renames
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3085 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087
3086
3088 # commit
3087 # commit
3089 node = repo.commit(text=message, user=user,
3088 node = repo.commit(text=message, user=user,
3090 date=date, extra=extra, editor=editor)
3089 date=date, extra=extra, editor=editor)
3091 if node is None:
3090 if node is None:
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3091 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 else:
3092 else:
3094 current = repo[node]
3093 current = repo[node]
3095 finally:
3094 finally:
3096 wlock.release()
3095 wlock.release()
3097
3096
3098 # remove state when we complete successfully
3097 # remove state when we complete successfully
3099 if not opts.get('dry_run'):
3098 if not opts.get('dry_run'):
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3099 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101
3100
3102 return 0
3101 return 0
3103
3102
3104 @command('grep',
3103 @command('grep',
3105 [('0', 'print0', None, _('end fields with NUL')),
3104 [('0', 'print0', None, _('end fields with NUL')),
3106 ('', 'all', None, _('print all revisions that match')),
3105 ('', 'all', None, _('print all revisions that match')),
3107 ('a', 'text', None, _('treat all files as text')),
3106 ('a', 'text', None, _('treat all files as text')),
3108 ('f', 'follow', None,
3107 ('f', 'follow', None,
3109 _('follow changeset history,'
3108 _('follow changeset history,'
3110 ' or file history across copies and renames')),
3109 ' or file history across copies and renames')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3110 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('l', 'files-with-matches', None,
3111 ('l', 'files-with-matches', None,
3113 _('print only filenames and revisions that match')),
3112 _('print only filenames and revisions that match')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3113 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('r', 'rev', [],
3114 ('r', 'rev', [],
3116 _('only search files changed within revision range'), _('REV')),
3115 _('only search files changed within revision range'), _('REV')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3116 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3117 ('d', 'date', None, _('list the date (short with -q)')),
3119 ] + walkopts,
3118 ] + walkopts,
3120 _('[OPTION]... PATTERN [FILE]...'))
3119 _('[OPTION]... PATTERN [FILE]...'))
3121 def grep(ui, repo, pattern, *pats, **opts):
3120 def grep(ui, repo, pattern, *pats, **opts):
3122 """search for a pattern in specified files and revisions
3121 """search for a pattern in specified files and revisions
3123
3122
3124 Search revisions of files for a regular expression.
3123 Search revisions of files for a regular expression.
3125
3124
3126 This command behaves differently than Unix grep. It only accepts
3125 This command behaves differently than Unix grep. It only accepts
3127 Python/Perl regexps. It searches repository history, not the
3126 Python/Perl regexps. It searches repository history, not the
3128 working directory. It always prints the revision number in which a
3127 working directory. It always prints the revision number in which a
3129 match appears.
3128 match appears.
3130
3129
3131 By default, grep only prints output for the first revision of a
3130 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
3131 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
3132 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),
3133 becomes a non-match, or "+" for a non-match that becomes a match),
3135 use the --all flag.
3134 use the --all flag.
3136
3135
3137 Returns 0 if a match is found, 1 otherwise.
3136 Returns 0 if a match is found, 1 otherwise.
3138 """
3137 """
3139 reflags = re.M
3138 reflags = re.M
3140 if opts.get('ignore_case'):
3139 if opts.get('ignore_case'):
3141 reflags |= re.I
3140 reflags |= re.I
3142 try:
3141 try:
3143 regexp = util.compilere(pattern, reflags)
3142 regexp = util.compilere(pattern, reflags)
3144 except re.error, inst:
3143 except re.error, inst:
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3144 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 return 1
3145 return 1
3147 sep, eol = ':', '\n'
3146 sep, eol = ':', '\n'
3148 if opts.get('print0'):
3147 if opts.get('print0'):
3149 sep = eol = '\0'
3148 sep = eol = '\0'
3150
3149
3151 getfile = util.lrucachefunc(repo.file)
3150 getfile = util.lrucachefunc(repo.file)
3152
3151
3153 def matchlines(body):
3152 def matchlines(body):
3154 begin = 0
3153 begin = 0
3155 linenum = 0
3154 linenum = 0
3156 while begin < len(body):
3155 while begin < len(body):
3157 match = regexp.search(body, begin)
3156 match = regexp.search(body, begin)
3158 if not match:
3157 if not match:
3159 break
3158 break
3160 mstart, mend = match.span()
3159 mstart, mend = match.span()
3161 linenum += body.count('\n', begin, mstart) + 1
3160 linenum += body.count('\n', begin, mstart) + 1
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3161 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3162 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 lend = begin - 1
3163 lend = begin - 1
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3164 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166
3165
3167 class linestate(object):
3166 class linestate(object):
3168 def __init__(self, line, linenum, colstart, colend):
3167 def __init__(self, line, linenum, colstart, colend):
3169 self.line = line
3168 self.line = line
3170 self.linenum = linenum
3169 self.linenum = linenum
3171 self.colstart = colstart
3170 self.colstart = colstart
3172 self.colend = colend
3171 self.colend = colend
3173
3172
3174 def __hash__(self):
3173 def __hash__(self):
3175 return hash((self.linenum, self.line))
3174 return hash((self.linenum, self.line))
3176
3175
3177 def __eq__(self, other):
3176 def __eq__(self, other):
3178 return self.line == other.line
3177 return self.line == other.line
3179
3178
3180 matches = {}
3179 matches = {}
3181 copies = {}
3180 copies = {}
3182 def grepbody(fn, rev, body):
3181 def grepbody(fn, rev, body):
3183 matches[rev].setdefault(fn, [])
3182 matches[rev].setdefault(fn, [])
3184 m = matches[rev][fn]
3183 m = matches[rev][fn]
3185 for lnum, cstart, cend, line in matchlines(body):
3184 for lnum, cstart, cend, line in matchlines(body):
3186 s = linestate(line, lnum, cstart, cend)
3185 s = linestate(line, lnum, cstart, cend)
3187 m.append(s)
3186 m.append(s)
3188
3187
3189 def difflinestates(a, b):
3188 def difflinestates(a, b):
3190 sm = difflib.SequenceMatcher(None, a, b)
3189 sm = difflib.SequenceMatcher(None, a, b)
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3190 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 if tag == 'insert':
3191 if tag == 'insert':
3193 for i in xrange(blo, bhi):
3192 for i in xrange(blo, bhi):
3194 yield ('+', b[i])
3193 yield ('+', b[i])
3195 elif tag == 'delete':
3194 elif tag == 'delete':
3196 for i in xrange(alo, ahi):
3195 for i in xrange(alo, ahi):
3197 yield ('-', a[i])
3196 yield ('-', a[i])
3198 elif tag == 'replace':
3197 elif tag == 'replace':
3199 for i in xrange(alo, ahi):
3198 for i in xrange(alo, ahi):
3200 yield ('-', a[i])
3199 yield ('-', a[i])
3201 for i in xrange(blo, bhi):
3200 for i in xrange(blo, bhi):
3202 yield ('+', b[i])
3201 yield ('+', b[i])
3203
3202
3204 def display(fn, ctx, pstates, states):
3203 def display(fn, ctx, pstates, states):
3205 rev = ctx.rev()
3204 rev = ctx.rev()
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3205 datefunc = ui.quiet and util.shortdate or util.datestr
3207 found = False
3206 found = False
3208 filerevmatches = {}
3207 filerevmatches = {}
3209 def binary():
3208 def binary():
3210 flog = getfile(fn)
3209 flog = getfile(fn)
3211 return util.binary(flog.read(ctx.filenode(fn)))
3210 return util.binary(flog.read(ctx.filenode(fn)))
3212
3211
3213 if opts.get('all'):
3212 if opts.get('all'):
3214 iter = difflinestates(pstates, states)
3213 iter = difflinestates(pstates, states)
3215 else:
3214 else:
3216 iter = [('', l) for l in states]
3215 iter = [('', l) for l in states]
3217 for change, l in iter:
3216 for change, l in iter:
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3217 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 before, match, after = None, None, None
3218 before, match, after = None, None, None
3220
3219
3221 if opts.get('line_number'):
3220 if opts.get('line_number'):
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3221 cols.append((str(l.linenum), 'grep.linenumber'))
3223 if opts.get('all'):
3222 if opts.get('all'):
3224 cols.append((change, 'grep.change'))
3223 cols.append((change, 'grep.change'))
3225 if opts.get('user'):
3224 if opts.get('user'):
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3225 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 if opts.get('date'):
3226 if opts.get('date'):
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3227 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 if opts.get('files_with_matches'):
3228 if opts.get('files_with_matches'):
3230 c = (fn, rev)
3229 c = (fn, rev)
3231 if c in filerevmatches:
3230 if c in filerevmatches:
3232 continue
3231 continue
3233 filerevmatches[c] = 1
3232 filerevmatches[c] = 1
3234 else:
3233 else:
3235 before = l.line[:l.colstart]
3234 before = l.line[:l.colstart]
3236 match = l.line[l.colstart:l.colend]
3235 match = l.line[l.colstart:l.colend]
3237 after = l.line[l.colend:]
3236 after = l.line[l.colend:]
3238 for col, label in cols[:-1]:
3237 for col, label in cols[:-1]:
3239 ui.write(col, label=label)
3238 ui.write(col, label=label)
3240 ui.write(sep, label='grep.sep')
3239 ui.write(sep, label='grep.sep')
3241 ui.write(cols[-1][0], label=cols[-1][1])
3240 ui.write(cols[-1][0], label=cols[-1][1])
3242 if before is not None:
3241 if before is not None:
3243 ui.write(sep, label='grep.sep')
3242 ui.write(sep, label='grep.sep')
3244 if not opts.get('text') and binary():
3243 if not opts.get('text') and binary():
3245 ui.write(" Binary file matches")
3244 ui.write(" Binary file matches")
3246 else:
3245 else:
3247 ui.write(before)
3246 ui.write(before)
3248 ui.write(match, label='grep.match')
3247 ui.write(match, label='grep.match')
3249 ui.write(after)
3248 ui.write(after)
3250 ui.write(eol)
3249 ui.write(eol)
3251 found = True
3250 found = True
3252 return found
3251 return found
3253
3252
3254 skip = {}
3253 skip = {}
3255 revfiles = {}
3254 revfiles = {}
3256 matchfn = scmutil.match(repo[None], pats, opts)
3255 matchfn = scmutil.match(repo[None], pats, opts)
3257 found = False
3256 found = False
3258 follow = opts.get('follow')
3257 follow = opts.get('follow')
3259
3258
3260 def prep(ctx, fns):
3259 def prep(ctx, fns):
3261 rev = ctx.rev()
3260 rev = ctx.rev()
3262 pctx = ctx.p1()
3261 pctx = ctx.p1()
3263 parent = pctx.rev()
3262 parent = pctx.rev()
3264 matches.setdefault(rev, {})
3263 matches.setdefault(rev, {})
3265 matches.setdefault(parent, {})
3264 matches.setdefault(parent, {})
3266 files = revfiles.setdefault(rev, [])
3265 files = revfiles.setdefault(rev, [])
3267 for fn in fns:
3266 for fn in fns:
3268 flog = getfile(fn)
3267 flog = getfile(fn)
3269 try:
3268 try:
3270 fnode = ctx.filenode(fn)
3269 fnode = ctx.filenode(fn)
3271 except error.LookupError:
3270 except error.LookupError:
3272 continue
3271 continue
3273
3272
3274 copied = flog.renamed(fnode)
3273 copied = flog.renamed(fnode)
3275 copy = follow and copied and copied[0]
3274 copy = follow and copied and copied[0]
3276 if copy:
3275 if copy:
3277 copies.setdefault(rev, {})[fn] = copy
3276 copies.setdefault(rev, {})[fn] = copy
3278 if fn in skip:
3277 if fn in skip:
3279 if copy:
3278 if copy:
3280 skip[copy] = True
3279 skip[copy] = True
3281 continue
3280 continue
3282 files.append(fn)
3281 files.append(fn)
3283
3282
3284 if fn not in matches[rev]:
3283 if fn not in matches[rev]:
3285 grepbody(fn, rev, flog.read(fnode))
3284 grepbody(fn, rev, flog.read(fnode))
3286
3285
3287 pfn = copy or fn
3286 pfn = copy or fn
3288 if pfn not in matches[parent]:
3287 if pfn not in matches[parent]:
3289 try:
3288 try:
3290 fnode = pctx.filenode(pfn)
3289 fnode = pctx.filenode(pfn)
3291 grepbody(pfn, parent, flog.read(fnode))
3290 grepbody(pfn, parent, flog.read(fnode))
3292 except error.LookupError:
3291 except error.LookupError:
3293 pass
3292 pass
3294
3293
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3294 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 rev = ctx.rev()
3295 rev = ctx.rev()
3297 parent = ctx.p1().rev()
3296 parent = ctx.p1().rev()
3298 for fn in sorted(revfiles.get(rev, [])):
3297 for fn in sorted(revfiles.get(rev, [])):
3299 states = matches[rev][fn]
3298 states = matches[rev][fn]
3300 copy = copies.get(rev, {}).get(fn)
3299 copy = copies.get(rev, {}).get(fn)
3301 if fn in skip:
3300 if fn in skip:
3302 if copy:
3301 if copy:
3303 skip[copy] = True
3302 skip[copy] = True
3304 continue
3303 continue
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3304 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 if pstates or states:
3305 if pstates or states:
3307 r = display(fn, ctx, pstates, states)
3306 r = display(fn, ctx, pstates, states)
3308 found = found or r
3307 found = found or r
3309 if r and not opts.get('all'):
3308 if r and not opts.get('all'):
3310 skip[fn] = True
3309 skip[fn] = True
3311 if copy:
3310 if copy:
3312 skip[copy] = True
3311 skip[copy] = True
3313 del matches[rev]
3312 del matches[rev]
3314 del revfiles[rev]
3313 del revfiles[rev]
3315
3314
3316 return not found
3315 return not found
3317
3316
3318 @command('heads',
3317 @command('heads',
3319 [('r', 'rev', '',
3318 [('r', 'rev', '',
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3319 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 ('t', 'topo', False, _('show topological heads only')),
3320 ('t', 'topo', False, _('show topological heads only')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3321 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3322 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ] + templateopts,
3323 ] + templateopts,
3325 _('[-ct] [-r STARTREV] [REV]...'))
3324 _('[-ct] [-r STARTREV] [REV]...'))
3326 def heads(ui, repo, *branchrevs, **opts):
3325 def heads(ui, repo, *branchrevs, **opts):
3327 """show branch heads
3326 """show branch heads
3328
3327
3329 With no arguments, show all open branch heads in the repository.
3328 With no arguments, show all open branch heads in the repository.
3330 Branch heads are changesets that have no descendants on the
3329 Branch heads are changesets that have no descendants on the
3331 same branch. They are where development generally takes place and
3330 same branch. They are where development generally takes place and
3332 are the usual targets for update and merge operations.
3331 are the usual targets for update and merge operations.
3333
3332
3334 If one or more REVs are given, only open branch heads on the
3333 If one or more REVs are given, only open branch heads on the
3335 branches associated with the specified changesets are shown. This
3334 branches associated with the specified changesets are shown. This
3336 means that you can use :hg:`heads .` to see the heads on the
3335 means that you can use :hg:`heads .` to see the heads on the
3337 currently checked-out branch.
3336 currently checked-out branch.
3338
3337
3339 If -c/--closed is specified, also show branch heads marked closed
3338 If -c/--closed is specified, also show branch heads marked closed
3340 (see :hg:`commit --close-branch`).
3339 (see :hg:`commit --close-branch`).
3341
3340
3342 If STARTREV is specified, only those heads that are descendants of
3341 If STARTREV is specified, only those heads that are descendants of
3343 STARTREV will be displayed.
3342 STARTREV will be displayed.
3344
3343
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3344 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 topological heads (changesets with no children) will be shown.
3345 topological heads (changesets with no children) will be shown.
3347
3346
3348 Returns 0 if matching heads are found, 1 if not.
3347 Returns 0 if matching heads are found, 1 if not.
3349 """
3348 """
3350
3349
3351 start = None
3350 start = None
3352 if 'rev' in opts:
3351 if 'rev' in opts:
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3352 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354
3353
3355 if opts.get('topo'):
3354 if opts.get('topo'):
3356 heads = [repo[h] for h in repo.heads(start)]
3355 heads = [repo[h] for h in repo.heads(start)]
3357 else:
3356 else:
3358 heads = []
3357 heads = []
3359 for branch in repo.branchmap():
3358 for branch in repo.branchmap():
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3359 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads = [repo[h] for h in heads]
3360 heads = [repo[h] for h in heads]
3362
3361
3363 if branchrevs:
3362 if branchrevs:
3364 branches = set(repo[br].branch() for br in branchrevs)
3363 branches = set(repo[br].branch() for br in branchrevs)
3365 heads = [h for h in heads if h.branch() in branches]
3364 heads = [h for h in heads if h.branch() in branches]
3366
3365
3367 if opts.get('active') and branchrevs:
3366 if opts.get('active') and branchrevs:
3368 dagheads = repo.heads(start)
3367 dagheads = repo.heads(start)
3369 heads = [h for h in heads if h.node() in dagheads]
3368 heads = [h for h in heads if h.node() in dagheads]
3370
3369
3371 if branchrevs:
3370 if branchrevs:
3372 haveheads = set(h.branch() for h in heads)
3371 haveheads = set(h.branch() for h in heads)
3373 if branches - haveheads:
3372 if branches - haveheads:
3374 headless = ', '.join(b for b in branches - haveheads)
3373 headless = ', '.join(b for b in branches - haveheads)
3375 msg = _('no open branch heads found on branches %s')
3374 msg = _('no open branch heads found on branches %s')
3376 if opts.get('rev'):
3375 if opts.get('rev'):
3377 msg += _(' (started at %s)') % opts['rev']
3376 msg += _(' (started at %s)') % opts['rev']
3378 ui.warn((msg + '\n') % headless)
3377 ui.warn((msg + '\n') % headless)
3379
3378
3380 if not heads:
3379 if not heads:
3381 return 1
3380 return 1
3382
3381
3383 heads = sorted(heads, key=lambda x: -x.rev())
3382 heads = sorted(heads, key=lambda x: -x.rev())
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3383 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 for ctx in heads:
3384 for ctx in heads:
3386 displayer.show(ctx)
3385 displayer.show(ctx)
3387 displayer.close()
3386 displayer.close()
3388
3387
3389 @command('help',
3388 @command('help',
3390 [('e', 'extension', None, _('show only help for extensions')),
3389 [('e', 'extension', None, _('show only help for extensions')),
3391 ('c', 'command', None, _('show only help for commands')),
3390 ('c', 'command', None, _('show only help for commands')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3391 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ],
3392 ],
3394 _('[-ec] [TOPIC]'))
3393 _('[-ec] [TOPIC]'))
3395 def help_(ui, name=None, **opts):
3394 def help_(ui, name=None, **opts):
3396 """show help for a given topic or a help overview
3395 """show help for a given topic or a help overview
3397
3396
3398 With no arguments, print a list of commands with short help messages.
3397 With no arguments, print a list of commands with short help messages.
3399
3398
3400 Given a topic, extension, or command name, print help for that
3399 Given a topic, extension, or command name, print help for that
3401 topic.
3400 topic.
3402
3401
3403 Returns 0 if successful.
3402 Returns 0 if successful.
3404 """
3403 """
3405
3404
3406 textwidth = min(ui.termwidth(), 80) - 2
3405 textwidth = min(ui.termwidth(), 80) - 2
3407
3406
3408 keep = ui.verbose and ['verbose'] or []
3407 keep = ui.verbose and ['verbose'] or []
3409 text = help.help_(ui, name, **opts)
3408 text = help.help_(ui, name, **opts)
3410
3409
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3410 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 if 'verbose' in pruned:
3411 if 'verbose' in pruned:
3413 keep.append('omitted')
3412 keep.append('omitted')
3414 else:
3413 else:
3415 keep.append('notomitted')
3414 keep.append('notomitted')
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3415 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 ui.write(formatted)
3416 ui.write(formatted)
3418
3417
3419
3418
3420 @command('identify|id',
3419 @command('identify|id',
3421 [('r', 'rev', '',
3420 [('r', 'rev', '',
3422 _('identify the specified revision'), _('REV')),
3421 _('identify the specified revision'), _('REV')),
3423 ('n', 'num', None, _('show local revision number')),
3422 ('n', 'num', None, _('show local revision number')),
3424 ('i', 'id', None, _('show global revision id')),
3423 ('i', 'id', None, _('show global revision id')),
3425 ('b', 'branch', None, _('show branch')),
3424 ('b', 'branch', None, _('show branch')),
3426 ('t', 'tags', None, _('show tags')),
3425 ('t', 'tags', None, _('show tags')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3426 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ] + remoteopts,
3427 ] + remoteopts,
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3428 _('[-nibtB] [-r REV] [SOURCE]'))
3430 def identify(ui, repo, source=None, rev=None,
3429 def identify(ui, repo, source=None, rev=None,
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3430 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 """identify the working copy or specified revision
3431 """identify the working copy or specified revision
3433
3432
3434 Print a summary identifying the repository state at REV using one or
3433 Print a summary identifying the repository state at REV using one or
3435 two parent hash identifiers, followed by a "+" if the working
3434 two parent hash identifiers, followed by a "+" if the working
3436 directory has uncommitted changes, the branch name (if not default),
3435 directory has uncommitted changes, the branch name (if not default),
3437 a list of tags, and a list of bookmarks.
3436 a list of tags, and a list of bookmarks.
3438
3437
3439 When REV is not given, print a summary of the current state of the
3438 When REV is not given, print a summary of the current state of the
3440 repository.
3439 repository.
3441
3440
3442 Specifying a path to a repository root or Mercurial bundle will
3441 Specifying a path to a repository root or Mercurial bundle will
3443 cause lookup to operate on that repository/bundle.
3442 cause lookup to operate on that repository/bundle.
3444
3443
3445 .. container:: verbose
3444 .. container:: verbose
3446
3445
3447 Examples:
3446 Examples:
3448
3447
3449 - generate a build identifier for the working directory::
3448 - generate a build identifier for the working directory::
3450
3449
3451 hg id --id > build-id.dat
3450 hg id --id > build-id.dat
3452
3451
3453 - find the revision corresponding to a tag::
3452 - find the revision corresponding to a tag::
3454
3453
3455 hg id -n -r 1.3
3454 hg id -n -r 1.3
3456
3455
3457 - check the most recent revision of a remote repository::
3456 - check the most recent revision of a remote repository::
3458
3457
3459 hg id -r tip http://selenic.com/hg/
3458 hg id -r tip http://selenic.com/hg/
3460
3459
3461 Returns 0 if successful.
3460 Returns 0 if successful.
3462 """
3461 """
3463
3462
3464 if not repo and not source:
3463 if not repo and not source:
3465 raise util.Abort(_("there is no Mercurial repository here "
3464 raise util.Abort(_("there is no Mercurial repository here "
3466 "(.hg not found)"))
3465 "(.hg not found)"))
3467
3466
3468 hexfunc = ui.debugflag and hex or short
3467 hexfunc = ui.debugflag and hex or short
3469 default = not (num or id or branch or tags or bookmarks)
3468 default = not (num or id or branch or tags or bookmarks)
3470 output = []
3469 output = []
3471 revs = []
3470 revs = []
3472
3471
3473 if source:
3472 if source:
3474 source, branches = hg.parseurl(ui.expandpath(source))
3473 source, branches = hg.parseurl(ui.expandpath(source))
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3474 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 repo = peer.local()
3475 repo = peer.local()
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3476 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478
3477
3479 if not repo:
3478 if not repo:
3480 if num or branch or tags:
3479 if num or branch or tags:
3481 raise util.Abort(
3480 raise util.Abort(
3482 _("can't query remote revision number, branch, or tags"))
3481 _("can't query remote revision number, branch, or tags"))
3483 if not rev and revs:
3482 if not rev and revs:
3484 rev = revs[0]
3483 rev = revs[0]
3485 if not rev:
3484 if not rev:
3486 rev = "tip"
3485 rev = "tip"
3487
3486
3488 remoterev = peer.lookup(rev)
3487 remoterev = peer.lookup(rev)
3489 if default or id:
3488 if default or id:
3490 output = [hexfunc(remoterev)]
3489 output = [hexfunc(remoterev)]
3491
3490
3492 def getbms():
3491 def getbms():
3493 bms = []
3492 bms = []
3494
3493
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3494 if 'bookmarks' in peer.listkeys('namespaces'):
3496 hexremoterev = hex(remoterev)
3495 hexremoterev = hex(remoterev)
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3496 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 if bmr == hexremoterev]
3497 if bmr == hexremoterev]
3499
3498
3500 return sorted(bms)
3499 return sorted(bms)
3501
3500
3502 if bookmarks:
3501 if bookmarks:
3503 output.extend(getbms())
3502 output.extend(getbms())
3504 elif default and not ui.quiet:
3503 elif default and not ui.quiet:
3505 # multiple bookmarks for a single parent separated by '/'
3504 # multiple bookmarks for a single parent separated by '/'
3506 bm = '/'.join(getbms())
3505 bm = '/'.join(getbms())
3507 if bm:
3506 if bm:
3508 output.append(bm)
3507 output.append(bm)
3509 else:
3508 else:
3510 if not rev:
3509 if not rev:
3511 ctx = repo[None]
3510 ctx = repo[None]
3512 parents = ctx.parents()
3511 parents = ctx.parents()
3513 changed = ""
3512 changed = ""
3514 if default or id or num:
3513 if default or id or num:
3515 if (util.any(repo.status())
3514 if (util.any(repo.status())
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3515 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 changed = '+'
3516 changed = '+'
3518 if default or id:
3517 if default or id:
3519 output = ["%s%s" %
3518 output = ["%s%s" %
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3519 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 if num:
3520 if num:
3522 output.append("%s%s" %
3521 output.append("%s%s" %
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3522 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 else:
3523 else:
3525 ctx = scmutil.revsingle(repo, rev)
3524 ctx = scmutil.revsingle(repo, rev)
3526 if default or id:
3525 if default or id:
3527 output = [hexfunc(ctx.node())]
3526 output = [hexfunc(ctx.node())]
3528 if num:
3527 if num:
3529 output.append(str(ctx.rev()))
3528 output.append(str(ctx.rev()))
3530
3529
3531 if default and not ui.quiet:
3530 if default and not ui.quiet:
3532 b = ctx.branch()
3531 b = ctx.branch()
3533 if b != 'default':
3532 if b != 'default':
3534 output.append("(%s)" % b)
3533 output.append("(%s)" % b)
3535
3534
3536 # multiple tags for a single parent separated by '/'
3535 # multiple tags for a single parent separated by '/'
3537 t = '/'.join(ctx.tags())
3536 t = '/'.join(ctx.tags())
3538 if t:
3537 if t:
3539 output.append(t)
3538 output.append(t)
3540
3539
3541 # multiple bookmarks for a single parent separated by '/'
3540 # multiple bookmarks for a single parent separated by '/'
3542 bm = '/'.join(ctx.bookmarks())
3541 bm = '/'.join(ctx.bookmarks())
3543 if bm:
3542 if bm:
3544 output.append(bm)
3543 output.append(bm)
3545 else:
3544 else:
3546 if branch:
3545 if branch:
3547 output.append(ctx.branch())
3546 output.append(ctx.branch())
3548
3547
3549 if tags:
3548 if tags:
3550 output.extend(ctx.tags())
3549 output.extend(ctx.tags())
3551
3550
3552 if bookmarks:
3551 if bookmarks:
3553 output.extend(ctx.bookmarks())
3552 output.extend(ctx.bookmarks())
3554
3553
3555 ui.write("%s\n" % ' '.join(output))
3554 ui.write("%s\n" % ' '.join(output))
3556
3555
3557 @command('import|patch',
3556 @command('import|patch',
3558 [('p', 'strip', 1,
3557 [('p', 'strip', 1,
3559 _('directory strip option for patch. This has the same '
3558 _('directory strip option for patch. This has the same '
3560 'meaning as the corresponding patch option'), _('NUM')),
3559 'meaning as the corresponding patch option'), _('NUM')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3560 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3561 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('f', 'force', None,
3562 ('f', 'force', None,
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3563 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 ('', 'no-commit', None,
3564 ('', 'no-commit', None,
3566 _("don't commit, just update the working directory")),
3565 _("don't commit, just update the working directory")),
3567 ('', 'bypass', None,
3566 ('', 'bypass', None,
3568 _("apply patch without touching the working directory")),
3567 _("apply patch without touching the working directory")),
3569 ('', 'exact', None,
3568 ('', 'exact', None,
3570 _('apply patch to the nodes from which it was generated')),
3569 _('apply patch to the nodes from which it was generated')),
3571 ('', 'import-branch', None,
3570 ('', 'import-branch', None,
3572 _('use any branch information in patch (implied by --exact)'))] +
3571 _('use any branch information in patch (implied by --exact)'))] +
3573 commitopts + commitopts2 + similarityopts,
3572 commitopts + commitopts2 + similarityopts,
3574 _('[OPTION]... PATCH...'))
3573 _('[OPTION]... PATCH...'))
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3574 def import_(ui, repo, patch1=None, *patches, **opts):
3576 """import an ordered set of patches
3575 """import an ordered set of patches
3577
3576
3578 Import a list of patches and commit them individually (unless
3577 Import a list of patches and commit them individually (unless
3579 --no-commit is specified).
3578 --no-commit is specified).
3580
3579
3581 Because import first applies changes to the working directory,
3580 Because import first applies changes to the working directory,
3582 import will abort if there are outstanding changes.
3581 import will abort if there are outstanding changes.
3583
3582
3584 You can import a patch straight from a mail message. Even patches
3583 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
3584 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
3585 text/plain or text/x-patch). From and Subject headers of email
3587 message are used as default committer and commit message. All
3586 message are used as default committer and commit message. All
3588 text/plain body parts before first diff are added to commit
3587 text/plain body parts before first diff are added to commit
3589 message.
3588 message.
3590
3589
3591 If the imported patch was generated by :hg:`export`, user and
3590 If the imported patch was generated by :hg:`export`, user and
3592 description from patch override values from message headers and
3591 description from patch override values from message headers and
3593 body. Values given on command line with -m/--message and -u/--user
3592 body. Values given on command line with -m/--message and -u/--user
3594 override these.
3593 override these.
3595
3594
3596 If --exact is specified, import will set the working directory to
3595 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
3596 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
3597 resulting changeset has a different ID than the one recorded in
3599 the patch. This may happen due to character set problems or other
3598 the patch. This may happen due to character set problems or other
3600 deficiencies in the text patch format.
3599 deficiencies in the text patch format.
3601
3600
3602 Use --bypass to apply and commit patches directly to the
3601 Use --bypass to apply and commit patches directly to the
3603 repository, not touching the working directory. Without --exact,
3602 repository, not touching the working directory. Without --exact,
3604 patches will be applied on top of the working directory parent
3603 patches will be applied on top of the working directory parent
3605 revision.
3604 revision.
3606
3605
3607 With -s/--similarity, hg will attempt to discover renames and
3606 With -s/--similarity, hg will attempt to discover renames and
3608 copies in the patch in the same way as :hg:`addremove`.
3607 copies in the patch in the same way as :hg:`addremove`.
3609
3608
3610 To read a patch from standard input, use "-" as the patch name. If
3609 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.
3610 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.
3611 See :hg:`help dates` for a list of formats valid for -d/--date.
3613
3612
3614 .. container:: verbose
3613 .. container:: verbose
3615
3614
3616 Examples:
3615 Examples:
3617
3616
3618 - import a traditional patch from a website and detect renames::
3617 - import a traditional patch from a website and detect renames::
3619
3618
3620 hg import -s 80 http://example.com/bugfix.patch
3619 hg import -s 80 http://example.com/bugfix.patch
3621
3620
3622 - import a changeset from an hgweb server::
3621 - import a changeset from an hgweb server::
3623
3622
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3623 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625
3624
3626 - import all the patches in an Unix-style mbox::
3625 - import all the patches in an Unix-style mbox::
3627
3626
3628 hg import incoming-patches.mbox
3627 hg import incoming-patches.mbox
3629
3628
3630 - attempt to exactly restore an exported changeset (not always
3629 - attempt to exactly restore an exported changeset (not always
3631 possible)::
3630 possible)::
3632
3631
3633 hg import --exact proposed-fix.patch
3632 hg import --exact proposed-fix.patch
3634
3633
3635 Returns 0 on success.
3634 Returns 0 on success.
3636 """
3635 """
3637
3636
3638 if not patch1:
3637 if not patch1:
3639 raise util.Abort(_('need at least one patch to import'))
3638 raise util.Abort(_('need at least one patch to import'))
3640
3639
3641 patches = (patch1,) + patches
3640 patches = (patch1,) + patches
3642
3641
3643 date = opts.get('date')
3642 date = opts.get('date')
3644 if date:
3643 if date:
3645 opts['date'] = util.parsedate(date)
3644 opts['date'] = util.parsedate(date)
3646
3645
3647 editor = cmdutil.commiteditor
3646 editor = cmdutil.commiteditor
3648 if opts.get('edit'):
3647 if opts.get('edit'):
3649 editor = cmdutil.commitforceeditor
3648 editor = cmdutil.commitforceeditor
3650
3649
3651 update = not opts.get('bypass')
3650 update = not opts.get('bypass')
3652 if not update and opts.get('no_commit'):
3651 if not update and opts.get('no_commit'):
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3652 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 try:
3653 try:
3655 sim = float(opts.get('similarity') or 0)
3654 sim = float(opts.get('similarity') or 0)
3656 except ValueError:
3655 except ValueError:
3657 raise util.Abort(_('similarity must be a number'))
3656 raise util.Abort(_('similarity must be a number'))
3658 if sim < 0 or sim > 100:
3657 if sim < 0 or sim > 100:
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3658 raise util.Abort(_('similarity must be between 0 and 100'))
3660 if sim and not update:
3659 if sim and not update:
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3660 raise util.Abort(_('cannot use --similarity with --bypass'))
3662
3661
3663 if update:
3662 if update:
3664 cmdutil.checkunfinished(repo)
3663 cmdutil.checkunfinished(repo)
3665 if (opts.get('exact') or not opts.get('force')) and update:
3664 if (opts.get('exact') or not opts.get('force')) and update:
3666 cmdutil.bailifchanged(repo)
3665 cmdutil.bailifchanged(repo)
3667
3666
3668 base = opts["base"]
3667 base = opts["base"]
3669 strip = opts["strip"]
3668 strip = opts["strip"]
3670 wlock = lock = tr = None
3669 wlock = lock = tr = None
3671 msgs = []
3670 msgs = []
3672
3671
3673 def tryone(ui, hunk, parents):
3672 def tryone(ui, hunk, parents):
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3673 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 patch.extract(ui, hunk)
3674 patch.extract(ui, hunk)
3676
3675
3677 if not tmpname:
3676 if not tmpname:
3678 return (None, None)
3677 return (None, None)
3679 msg = _('applied to working directory')
3678 msg = _('applied to working directory')
3680
3679
3681 try:
3680 try:
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3681 cmdline_message = cmdutil.logmessage(ui, opts)
3683 if cmdline_message:
3682 if cmdline_message:
3684 # pickup the cmdline msg
3683 # pickup the cmdline msg
3685 message = cmdline_message
3684 message = cmdline_message
3686 elif message:
3685 elif message:
3687 # pickup the patch msg
3686 # pickup the patch msg
3688 message = message.strip()
3687 message = message.strip()
3689 else:
3688 else:
3690 # launch the editor
3689 # launch the editor
3691 message = None
3690 message = None
3692 ui.debug('message:\n%s\n' % message)
3691 ui.debug('message:\n%s\n' % message)
3693
3692
3694 if len(parents) == 1:
3693 if len(parents) == 1:
3695 parents.append(repo[nullid])
3694 parents.append(repo[nullid])
3696 if opts.get('exact'):
3695 if opts.get('exact'):
3697 if not nodeid or not p1:
3696 if not nodeid or not p1:
3698 raise util.Abort(_('not a Mercurial patch'))
3697 raise util.Abort(_('not a Mercurial patch'))
3699 p1 = repo[p1]
3698 p1 = repo[p1]
3700 p2 = repo[p2 or nullid]
3699 p2 = repo[p2 or nullid]
3701 elif p2:
3700 elif p2:
3702 try:
3701 try:
3703 p1 = repo[p1]
3702 p1 = repo[p1]
3704 p2 = repo[p2]
3703 p2 = repo[p2]
3705 # Without any options, consider p2 only if the
3704 # Without any options, consider p2 only if the
3706 # patch is being applied on top of the recorded
3705 # patch is being applied on top of the recorded
3707 # first parent.
3706 # first parent.
3708 if p1 != parents[0]:
3707 if p1 != parents[0]:
3709 p1 = parents[0]
3708 p1 = parents[0]
3710 p2 = repo[nullid]
3709 p2 = repo[nullid]
3711 except error.RepoError:
3710 except error.RepoError:
3712 p1, p2 = parents
3711 p1, p2 = parents
3713 else:
3712 else:
3714 p1, p2 = parents
3713 p1, p2 = parents
3715
3714
3716 n = None
3715 n = None
3717 if update:
3716 if update:
3718 if p1 != parents[0]:
3717 if p1 != parents[0]:
3719 hg.clean(repo, p1.node())
3718 hg.clean(repo, p1.node())
3720 if p2 != parents[1]:
3719 if p2 != parents[1]:
3721 repo.setparents(p1.node(), p2.node())
3720 repo.setparents(p1.node(), p2.node())
3722
3721
3723 if opts.get('exact') or opts.get('import_branch'):
3722 if opts.get('exact') or opts.get('import_branch'):
3724 repo.dirstate.setbranch(branch or 'default')
3723 repo.dirstate.setbranch(branch or 'default')
3725
3724
3726 files = set()
3725 files = set()
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3726 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 eolmode=None, similarity=sim / 100.0)
3727 eolmode=None, similarity=sim / 100.0)
3729 files = list(files)
3728 files = list(files)
3730 if opts.get('no_commit'):
3729 if opts.get('no_commit'):
3731 if message:
3730 if message:
3732 msgs.append(message)
3731 msgs.append(message)
3733 else:
3732 else:
3734 if opts.get('exact') or p2:
3733 if opts.get('exact') or p2:
3735 # If you got here, you either use --force and know what
3734 # If you got here, you either use --force and know what
3736 # you are doing or used --exact or a merge patch while
3735 # you are doing or used --exact or a merge patch while
3737 # being updated to its first parent.
3736 # being updated to its first parent.
3738 m = None
3737 m = None
3739 else:
3738 else:
3740 m = scmutil.matchfiles(repo, files or [])
3739 m = scmutil.matchfiles(repo, files or [])
3741 n = repo.commit(message, opts.get('user') or user,
3740 n = repo.commit(message, opts.get('user') or user,
3742 opts.get('date') or date, match=m,
3741 opts.get('date') or date, match=m,
3743 editor=editor)
3742 editor=editor)
3744 else:
3743 else:
3745 if opts.get('exact') or opts.get('import_branch'):
3744 if opts.get('exact') or opts.get('import_branch'):
3746 branch = branch or 'default'
3745 branch = branch or 'default'
3747 else:
3746 else:
3748 branch = p1.branch()
3747 branch = p1.branch()
3749 store = patch.filestore()
3748 store = patch.filestore()
3750 try:
3749 try:
3751 files = set()
3750 files = set()
3752 try:
3751 try:
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3752 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 files, eolmode=None)
3753 files, eolmode=None)
3755 except patch.PatchError, e:
3754 except patch.PatchError, e:
3756 raise util.Abort(str(e))
3755 raise util.Abort(str(e))
3757 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3756 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3758 message,
3757 message,
3759 opts.get('user') or user,
3758 opts.get('user') or user,
3760 opts.get('date') or date,
3759 opts.get('date') or date,
3761 branch, files, store,
3760 branch, files, store,
3762 editor=cmdutil.commiteditor)
3761 editor=cmdutil.commiteditor)
3763 repo.savecommitmessage(memctx.description())
3762 repo.savecommitmessage(memctx.description())
3764 n = memctx.commit()
3763 n = memctx.commit()
3765 finally:
3764 finally:
3766 store.close()
3765 store.close()
3767 if opts.get('exact') and hex(n) != nodeid:
3766 if opts.get('exact') and hex(n) != nodeid:
3768 raise util.Abort(_('patch is damaged or loses information'))
3767 raise util.Abort(_('patch is damaged or loses information'))
3769 if n:
3768 if n:
3770 # i18n: refers to a short changeset id
3769 # i18n: refers to a short changeset id
3771 msg = _('created %s') % short(n)
3770 msg = _('created %s') % short(n)
3772 return (msg, n)
3771 return (msg, n)
3773 finally:
3772 finally:
3774 os.unlink(tmpname)
3773 os.unlink(tmpname)
3775
3774
3776 try:
3775 try:
3777 try:
3776 try:
3778 wlock = repo.wlock()
3777 wlock = repo.wlock()
3779 if not opts.get('no_commit'):
3778 if not opts.get('no_commit'):
3780 lock = repo.lock()
3779 lock = repo.lock()
3781 tr = repo.transaction('import')
3780 tr = repo.transaction('import')
3782 parents = repo.parents()
3781 parents = repo.parents()
3783 for patchurl in patches:
3782 for patchurl in patches:
3784 if patchurl == '-':
3783 if patchurl == '-':
3785 ui.status(_('applying patch from stdin\n'))
3784 ui.status(_('applying patch from stdin\n'))
3786 patchfile = ui.fin
3785 patchfile = ui.fin
3787 patchurl = 'stdin' # for error message
3786 patchurl = 'stdin' # for error message
3788 else:
3787 else:
3789 patchurl = os.path.join(base, patchurl)
3788 patchurl = os.path.join(base, patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3789 ui.status(_('applying %s\n') % patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3790 patchfile = hg.openpath(ui, patchurl)
3792
3791
3793 haspatch = False
3792 haspatch = False
3794 for hunk in patch.split(patchfile):
3793 for hunk in patch.split(patchfile):
3795 (msg, node) = tryone(ui, hunk, parents)
3794 (msg, node) = tryone(ui, hunk, parents)
3796 if msg:
3795 if msg:
3797 haspatch = True
3796 haspatch = True
3798 ui.note(msg + '\n')
3797 ui.note(msg + '\n')
3799 if update or opts.get('exact'):
3798 if update or opts.get('exact'):
3800 parents = repo.parents()
3799 parents = repo.parents()
3801 else:
3800 else:
3802 parents = [repo[node]]
3801 parents = [repo[node]]
3803
3802
3804 if not haspatch:
3803 if not haspatch:
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3804 raise util.Abort(_('%s: no diffs found') % patchurl)
3806
3805
3807 if tr:
3806 if tr:
3808 tr.close()
3807 tr.close()
3809 if msgs:
3808 if msgs:
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3809 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 except: # re-raises
3810 except: # re-raises
3812 # wlock.release() indirectly calls dirstate.write(): since
3811 # wlock.release() indirectly calls dirstate.write(): since
3813 # we're crashing, we do not want to change the working dir
3812 # we're crashing, we do not want to change the working dir
3814 # parent after all, so make sure it writes nothing
3813 # parent after all, so make sure it writes nothing
3815 repo.dirstate.invalidate()
3814 repo.dirstate.invalidate()
3816 raise
3815 raise
3817 finally:
3816 finally:
3818 if tr:
3817 if tr:
3819 tr.release()
3818 tr.release()
3820 release(lock, wlock)
3819 release(lock, wlock)
3821
3820
3822 @command('incoming|in',
3821 @command('incoming|in',
3823 [('f', 'force', None,
3822 [('f', 'force', None,
3824 _('run even if remote repository is unrelated')),
3823 _('run even if remote repository is unrelated')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3824 ('n', 'newest-first', None, _('show newest record first')),
3826 ('', 'bundle', '',
3825 ('', 'bundle', '',
3827 _('file to store the bundles into'), _('FILE')),
3826 _('file to store the bundles into'), _('FILE')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3827 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3828 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('b', 'branch', [],
3829 ('b', 'branch', [],
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3830 _('a specific branch you would like to pull'), _('BRANCH')),
3832 ] + logopts + remoteopts + subrepoopts,
3831 ] + logopts + remoteopts + subrepoopts,
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3832 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 def incoming(ui, repo, source="default", **opts):
3833 def incoming(ui, repo, source="default", **opts):
3835 """show new changesets found in source
3834 """show new changesets found in source
3836
3835
3837 Show new changesets found in the specified path/URL or the default
3836 Show new changesets found in the specified path/URL or the default
3838 pull location. These are the changesets that would have been pulled
3837 pull location. These are the changesets that would have been pulled
3839 if a pull at the time you issued this command.
3838 if a pull at the time you issued this command.
3840
3839
3841 For remote repository, using --bundle avoids downloading the
3840 For remote repository, using --bundle avoids downloading the
3842 changesets twice if the incoming is followed by a pull.
3841 changesets twice if the incoming is followed by a pull.
3843
3842
3844 See pull for valid source format details.
3843 See pull for valid source format details.
3845
3844
3846 Returns 0 if there are incoming changes, 1 otherwise.
3845 Returns 0 if there are incoming changes, 1 otherwise.
3847 """
3846 """
3848 if opts.get('graph'):
3847 if opts.get('graph'):
3849 cmdutil.checkunsupportedgraphflags([], opts)
3848 cmdutil.checkunsupportedgraphflags([], opts)
3850 def display(other, chlist, displayer):
3849 def display(other, chlist, displayer):
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3850 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3851 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3852 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 graphmod.asciiedges)
3853 graphmod.asciiedges)
3855
3854
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3855 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 return 0
3856 return 0
3858
3857
3859 if opts.get('bundle') and opts.get('subrepos'):
3858 if opts.get('bundle') and opts.get('subrepos'):
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3859 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861
3860
3862 if opts.get('bookmarks'):
3861 if opts.get('bookmarks'):
3863 source, branches = hg.parseurl(ui.expandpath(source),
3862 source, branches = hg.parseurl(ui.expandpath(source),
3864 opts.get('branch'))
3863 opts.get('branch'))
3865 other = hg.peer(repo, opts, source)
3864 other = hg.peer(repo, opts, source)
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3865 if 'bookmarks' not in other.listkeys('namespaces'):
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3866 ui.warn(_("remote doesn't support bookmarks\n"))
3868 return 0
3867 return 0
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3868 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 return bookmarks.diff(ui, repo, other)
3869 return bookmarks.diff(ui, repo, other)
3871
3870
3872 repo._subtoppath = ui.expandpath(source)
3871 repo._subtoppath = ui.expandpath(source)
3873 try:
3872 try:
3874 return hg.incoming(ui, repo, source, opts)
3873 return hg.incoming(ui, repo, source, opts)
3875 finally:
3874 finally:
3876 del repo._subtoppath
3875 del repo._subtoppath
3877
3876
3878
3877
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3878 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 def init(ui, dest=".", **opts):
3879 def init(ui, dest=".", **opts):
3881 """create a new repository in the given directory
3880 """create a new repository in the given directory
3882
3881
3883 Initialize a new repository in the given directory. If the given
3882 Initialize a new repository in the given directory. If the given
3884 directory does not exist, it will be created.
3883 directory does not exist, it will be created.
3885
3884
3886 If no directory is given, the current directory is used.
3885 If no directory is given, the current directory is used.
3887
3886
3888 It is possible to specify an ``ssh://`` URL as the destination.
3887 It is possible to specify an ``ssh://`` URL as the destination.
3889 See :hg:`help urls` for more information.
3888 See :hg:`help urls` for more information.
3890
3889
3891 Returns 0 on success.
3890 Returns 0 on success.
3892 """
3891 """
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3892 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894
3893
3895 @command('locate',
3894 @command('locate',
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3895 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3896 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3897 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ] + walkopts,
3898 ] + walkopts,
3900 _('[OPTION]... [PATTERN]...'))
3899 _('[OPTION]... [PATTERN]...'))
3901 def locate(ui, repo, *pats, **opts):
3900 def locate(ui, repo, *pats, **opts):
3902 """locate files matching specific patterns
3901 """locate files matching specific patterns
3903
3902
3904 Print files under Mercurial control in the working directory whose
3903 Print files under Mercurial control in the working directory whose
3905 names match the given patterns.
3904 names match the given patterns.
3906
3905
3907 By default, this command searches all directories in the working
3906 By default, this command searches all directories in the working
3908 directory. To search just the current directory and its
3907 directory. To search just the current directory and its
3909 subdirectories, use "--include .".
3908 subdirectories, use "--include .".
3910
3909
3911 If no patterns are given to match, this command prints the names
3910 If no patterns are given to match, this command prints the names
3912 of all files under Mercurial control in the working directory.
3911 of all files under Mercurial control in the working directory.
3913
3912
3914 If you want to feed the output of this command into the "xargs"
3913 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
3914 command, use the -0 option to both this command and "xargs". This
3916 will avoid the problem of "xargs" treating single filenames that
3915 will avoid the problem of "xargs" treating single filenames that
3917 contain whitespace as multiple filenames.
3916 contain whitespace as multiple filenames.
3918
3917
3919 Returns 0 if a match is found, 1 otherwise.
3918 Returns 0 if a match is found, 1 otherwise.
3920 """
3919 """
3921 end = opts.get('print0') and '\0' or '\n'
3920 end = opts.get('print0') and '\0' or '\n'
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3921 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923
3922
3924 ret = 1
3923 ret = 1
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3924 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m.bad = lambda x, y: False
3925 m.bad = lambda x, y: False
3927 for abs in repo[rev].walk(m):
3926 for abs in repo[rev].walk(m):
3928 if not rev and abs not in repo.dirstate:
3927 if not rev and abs not in repo.dirstate:
3929 continue
3928 continue
3930 if opts.get('fullpath'):
3929 if opts.get('fullpath'):
3931 ui.write(repo.wjoin(abs), end)
3930 ui.write(repo.wjoin(abs), end)
3932 else:
3931 else:
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3932 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ret = 0
3933 ret = 0
3935
3934
3936 return ret
3935 return ret
3937
3936
3938 @command('^log|history',
3937 @command('^log|history',
3939 [('f', 'follow', None,
3938 [('f', 'follow', None,
3940 _('follow changeset history, or file history across copies and renames')),
3939 _('follow changeset history, or file history across copies and renames')),
3941 ('', 'follow-first', None,
3940 ('', 'follow-first', None,
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3941 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3942 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('C', 'copies', None, _('show copied files')),
3943 ('C', 'copies', None, _('show copied files')),
3945 ('k', 'keyword', [],
3944 ('k', 'keyword', [],
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3945 _('do case-insensitive search for a given text'), _('TEXT')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3946 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3947 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3948 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3949 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('', 'only-branch', [],
3950 ('', 'only-branch', [],
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3951 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('BRANCH')),
3952 _('BRANCH')),
3954 ('b', 'branch', [],
3953 ('b', 'branch', [],
3955 _('show changesets within the given named branch'), _('BRANCH')),
3954 _('show changesets within the given named branch'), _('BRANCH')),
3956 ('P', 'prune', [],
3955 ('P', 'prune', [],
3957 _('do not display revision or any of its ancestors'), _('REV')),
3956 _('do not display revision or any of its ancestors'), _('REV')),
3958 ] + logopts + walkopts,
3957 ] + logopts + walkopts,
3959 _('[OPTION]... [FILE]'))
3958 _('[OPTION]... [FILE]'))
3960 def log(ui, repo, *pats, **opts):
3959 def log(ui, repo, *pats, **opts):
3961 """show revision history of entire repository or files
3960 """show revision history of entire repository or files
3962
3961
3963 Print the revision history of the specified files or the entire
3962 Print the revision history of the specified files or the entire
3964 project.
3963 project.
3965
3964
3966 If no revision range is specified, the default is ``tip:0`` unless
3965 If no revision range is specified, the default is ``tip:0`` unless
3967 --follow is set, in which case the working directory parent is
3966 --follow is set, in which case the working directory parent is
3968 used as the starting revision.
3967 used as the starting revision.
3969
3968
3970 File history is shown without following rename or copy history of
3969 File history is shown without following rename or copy history of
3971 files. Use -f/--follow with a filename to follow history across
3970 files. Use -f/--follow with a filename to follow history across
3972 renames and copies. --follow without a filename will only show
3971 renames and copies. --follow without a filename will only show
3973 ancestors or descendants of the starting revision.
3972 ancestors or descendants of the starting revision.
3974
3973
3975 By default this command prints revision number and changeset id,
3974 By default this command prints revision number and changeset id,
3976 tags, non-trivial parents, user, date and time, and a summary for
3975 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
3976 each commit. When the -v/--verbose switch is used, the list of
3978 changed files and full commit message are shown.
3977 changed files and full commit message are shown.
3979
3978
3980 .. note::
3979 .. note::
3981
3980
3982 log -p/--patch may generate unexpected diff output for merge
3981 log -p/--patch may generate unexpected diff output for merge
3983 changesets, as it will only compare the merge changeset against
3982 changesets, as it will only compare the merge changeset against
3984 its first parent. Also, only files different from BOTH parents
3983 its first parent. Also, only files different from BOTH parents
3985 will appear in files:.
3984 will appear in files:.
3986
3985
3987 .. note::
3986 .. note::
3988
3987
3989 for performance reasons, log FILE may omit duplicate changes
3988 for performance reasons, log FILE may omit duplicate changes
3990 made on branches and will not show deletions. To see all
3989 made on branches and will not show deletions. To see all
3991 changes including duplicates and deletions, use the --removed
3990 changes including duplicates and deletions, use the --removed
3992 switch.
3991 switch.
3993
3992
3994 .. container:: verbose
3993 .. container:: verbose
3995
3994
3996 Some examples:
3995 Some examples:
3997
3996
3998 - changesets with full descriptions and file lists::
3997 - changesets with full descriptions and file lists::
3999
3998
4000 hg log -v
3999 hg log -v
4001
4000
4002 - changesets ancestral to the working directory::
4001 - changesets ancestral to the working directory::
4003
4002
4004 hg log -f
4003 hg log -f
4005
4004
4006 - last 10 commits on the current branch::
4005 - last 10 commits on the current branch::
4007
4006
4008 hg log -l 10 -b .
4007 hg log -l 10 -b .
4009
4008
4010 - changesets showing all modifications of a file, including removals::
4009 - changesets showing all modifications of a file, including removals::
4011
4010
4012 hg log --removed file.c
4011 hg log --removed file.c
4013
4012
4014 - all changesets that touch a directory, with diffs, excluding merges::
4013 - all changesets that touch a directory, with diffs, excluding merges::
4015
4014
4016 hg log -Mp lib/
4015 hg log -Mp lib/
4017
4016
4018 - all revision numbers that match a keyword::
4017 - all revision numbers that match a keyword::
4019
4018
4020 hg log -k bug --template "{rev}\\n"
4019 hg log -k bug --template "{rev}\\n"
4021
4020
4022 - check if a given changeset is included is a tagged release::
4021 - check if a given changeset is included is a tagged release::
4023
4022
4024 hg log -r "a21ccf and ancestor(1.9)"
4023 hg log -r "a21ccf and ancestor(1.9)"
4025
4024
4026 - find all changesets by some user in a date range::
4025 - find all changesets by some user in a date range::
4027
4026
4028 hg log -k alice -d "may 2008 to jul 2008"
4027 hg log -k alice -d "may 2008 to jul 2008"
4029
4028
4030 - summary of all changesets after the last tag::
4029 - summary of all changesets after the last tag::
4031
4030
4032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4031 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4033
4032
4034 See :hg:`help dates` for a list of formats valid for -d/--date.
4033 See :hg:`help dates` for a list of formats valid for -d/--date.
4035
4034
4036 See :hg:`help revisions` and :hg:`help revsets` for more about
4035 See :hg:`help revisions` and :hg:`help revsets` for more about
4037 specifying revisions.
4036 specifying revisions.
4038
4037
4039 See :hg:`help templates` for more about pre-packaged styles and
4038 See :hg:`help templates` for more about pre-packaged styles and
4040 specifying custom templates.
4039 specifying custom templates.
4041
4040
4042 Returns 0 on success.
4041 Returns 0 on success.
4043 """
4042 """
4044 if opts.get('graph'):
4043 if opts.get('graph'):
4045 return cmdutil.graphlog(ui, repo, *pats, **opts)
4044 return cmdutil.graphlog(ui, repo, *pats, **opts)
4046
4045
4047 matchfn = scmutil.match(repo[None], pats, opts)
4046 matchfn = scmutil.match(repo[None], pats, opts)
4048 limit = cmdutil.loglimit(opts)
4047 limit = cmdutil.loglimit(opts)
4049 count = 0
4048 count = 0
4050
4049
4051 getrenamed, endrev = None, None
4050 getrenamed, endrev = None, None
4052 if opts.get('copies'):
4051 if opts.get('copies'):
4053 if opts.get('rev'):
4052 if opts.get('rev'):
4054 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4053 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4055 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4054 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4056
4055
4057 df = False
4056 df = False
4058 if opts.get("date"):
4057 if opts.get("date"):
4059 df = util.matchdate(opts["date"])
4058 df = util.matchdate(opts["date"])
4060
4059
4061 branches = opts.get('branch', []) + opts.get('only_branch', [])
4060 branches = opts.get('branch', []) + opts.get('only_branch', [])
4062 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4061 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4063
4062
4064 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4063 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4065 def prep(ctx, fns):
4064 def prep(ctx, fns):
4066 rev = ctx.rev()
4065 rev = ctx.rev()
4067 parents = [p for p in repo.changelog.parentrevs(rev)
4066 parents = [p for p in repo.changelog.parentrevs(rev)
4068 if p != nullrev]
4067 if p != nullrev]
4069 if opts.get('no_merges') and len(parents) == 2:
4068 if opts.get('no_merges') and len(parents) == 2:
4070 return
4069 return
4071 if opts.get('only_merges') and len(parents) != 2:
4070 if opts.get('only_merges') and len(parents) != 2:
4072 return
4071 return
4073 if opts.get('branch') and ctx.branch() not in opts['branch']:
4072 if opts.get('branch') and ctx.branch() not in opts['branch']:
4074 return
4073 return
4075 if df and not df(ctx.date()[0]):
4074 if df and not df(ctx.date()[0]):
4076 return
4075 return
4077
4076
4078 lower = encoding.lower
4077 lower = encoding.lower
4079 if opts.get('user'):
4078 if opts.get('user'):
4080 luser = lower(ctx.user())
4079 luser = lower(ctx.user())
4081 for k in [lower(x) for x in opts['user']]:
4080 for k in [lower(x) for x in opts['user']]:
4082 if (k in luser):
4081 if (k in luser):
4083 break
4082 break
4084 else:
4083 else:
4085 return
4084 return
4086 if opts.get('keyword'):
4085 if opts.get('keyword'):
4087 luser = lower(ctx.user())
4086 luser = lower(ctx.user())
4088 ldesc = lower(ctx.description())
4087 ldesc = lower(ctx.description())
4089 lfiles = lower(" ".join(ctx.files()))
4088 lfiles = lower(" ".join(ctx.files()))
4090 for k in [lower(x) for x in opts['keyword']]:
4089 for k in [lower(x) for x in opts['keyword']]:
4091 if (k in luser or k in ldesc or k in lfiles):
4090 if (k in luser or k in ldesc or k in lfiles):
4092 break
4091 break
4093 else:
4092 else:
4094 return
4093 return
4095
4094
4096 copies = None
4095 copies = None
4097 if getrenamed is not None and rev:
4096 if getrenamed is not None and rev:
4098 copies = []
4097 copies = []
4099 for fn in ctx.files():
4098 for fn in ctx.files():
4100 rename = getrenamed(fn, rev)
4099 rename = getrenamed(fn, rev)
4101 if rename:
4100 if rename:
4102 copies.append((fn, rename[0]))
4101 copies.append((fn, rename[0]))
4103
4102
4104 revmatchfn = None
4103 revmatchfn = None
4105 if opts.get('patch') or opts.get('stat'):
4104 if opts.get('patch') or opts.get('stat'):
4106 if opts.get('follow') or opts.get('follow_first'):
4105 if opts.get('follow') or opts.get('follow_first'):
4107 # note: this might be wrong when following through merges
4106 # note: this might be wrong when following through merges
4108 revmatchfn = scmutil.match(repo[None], fns, default='path')
4107 revmatchfn = scmutil.match(repo[None], fns, default='path')
4109 else:
4108 else:
4110 revmatchfn = matchfn
4109 revmatchfn = matchfn
4111
4110
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4111 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4113
4112
4114 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4113 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4115 if displayer.flush(ctx.rev()):
4114 if displayer.flush(ctx.rev()):
4116 count += 1
4115 count += 1
4117 if count == limit:
4116 if count == limit:
4118 break
4117 break
4119 displayer.close()
4118 displayer.close()
4120
4119
4121 @command('manifest',
4120 @command('manifest',
4122 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 [('r', 'rev', '', _('revision to display'), _('REV')),
4123 ('', 'all', False, _("list files from all revisions"))],
4122 ('', 'all', False, _("list files from all revisions"))],
4124 _('[-r REV]'))
4123 _('[-r REV]'))
4125 def manifest(ui, repo, node=None, rev=None, **opts):
4124 def manifest(ui, repo, node=None, rev=None, **opts):
4126 """output the current or given revision of the project manifest
4125 """output the current or given revision of the project manifest
4127
4126
4128 Print a list of version controlled files for the given revision.
4127 Print a list of version controlled files for the given revision.
4129 If no revision is given, the first parent of the working directory
4128 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.
4129 is used, or the null revision if no revision is checked out.
4131
4130
4132 With -v, print file permissions, symlink and executable bits.
4131 With -v, print file permissions, symlink and executable bits.
4133 With --debug, print file revision hashes.
4132 With --debug, print file revision hashes.
4134
4133
4135 If option --all is specified, the list of all files from all revisions
4134 If option --all is specified, the list of all files from all revisions
4136 is printed. This includes deleted and renamed files.
4135 is printed. This includes deleted and renamed files.
4137
4136
4138 Returns 0 on success.
4137 Returns 0 on success.
4139 """
4138 """
4140
4139
4141 fm = ui.formatter('manifest', opts)
4140 fm = ui.formatter('manifest', opts)
4142
4141
4143 if opts.get('all'):
4142 if opts.get('all'):
4144 if rev or node:
4143 if rev or node:
4145 raise util.Abort(_("can't specify a revision with --all"))
4144 raise util.Abort(_("can't specify a revision with --all"))
4146
4145
4147 res = []
4146 res = []
4148 prefix = "data/"
4147 prefix = "data/"
4149 suffix = ".i"
4148 suffix = ".i"
4150 plen = len(prefix)
4149 plen = len(prefix)
4151 slen = len(suffix)
4150 slen = len(suffix)
4152 lock = repo.lock()
4151 lock = repo.lock()
4153 try:
4152 try:
4154 for fn, b, size in repo.store.datafiles():
4153 for fn, b, size in repo.store.datafiles():
4155 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4156 res.append(fn[plen:-slen])
4155 res.append(fn[plen:-slen])
4157 finally:
4156 finally:
4158 lock.release()
4157 lock.release()
4159 for f in res:
4158 for f in res:
4160 fm.startitem()
4159 fm.startitem()
4161 fm.write("path", '%s\n', f)
4160 fm.write("path", '%s\n', f)
4162 fm.end()
4161 fm.end()
4163 return
4162 return
4164
4163
4165 if rev and node:
4164 if rev and node:
4166 raise util.Abort(_("please specify just one revision"))
4165 raise util.Abort(_("please specify just one revision"))
4167
4166
4168 if not node:
4167 if not node:
4169 node = rev
4168 node = rev
4170
4169
4171 char = {'l': '@', 'x': '*', '': ''}
4170 char = {'l': '@', 'x': '*', '': ''}
4172 mode = {'l': '644', 'x': '755', '': '644'}
4171 mode = {'l': '644', 'x': '755', '': '644'}
4173 ctx = scmutil.revsingle(repo, node)
4172 ctx = scmutil.revsingle(repo, node)
4174 mf = ctx.manifest()
4173 mf = ctx.manifest()
4175 for f in ctx:
4174 for f in ctx:
4176 fm.startitem()
4175 fm.startitem()
4177 fl = ctx[f].flags()
4176 fl = ctx[f].flags()
4178 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4179 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4180 fm.write('path', '%s\n', f)
4179 fm.write('path', '%s\n', f)
4181 fm.end()
4180 fm.end()
4182
4181
4183 @command('^merge',
4182 @command('^merge',
4184 [('f', 'force', None,
4183 [('f', 'force', None,
4185 _('force a merge including outstanding changes (DEPRECATED)')),
4184 _('force a merge including outstanding changes (DEPRECATED)')),
4186 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('r', 'rev', '', _('revision to merge'), _('REV')),
4187 ('P', 'preview', None,
4186 ('P', 'preview', None,
4188 _('review revisions to merge (no merge is performed)'))
4187 _('review revisions to merge (no merge is performed)'))
4189 ] + mergetoolopts,
4188 ] + mergetoolopts,
4190 _('[-P] [-f] [[-r] REV]'))
4189 _('[-P] [-f] [[-r] REV]'))
4191 def merge(ui, repo, node=None, **opts):
4190 def merge(ui, repo, node=None, **opts):
4192 """merge working directory with another revision
4191 """merge working directory with another revision
4193
4192
4194 The current working directory is updated with all changes made in
4193 The current working directory is updated with all changes made in
4195 the requested revision since the last common predecessor revision.
4194 the requested revision since the last common predecessor revision.
4196
4195
4197 Files that changed between either parent are marked as changed for
4196 Files that changed between either parent are marked as changed for
4198 the next commit and a commit must be performed before any further
4197 the next commit and a commit must be performed before any further
4199 updates to the repository are allowed. The next commit will have
4198 updates to the repository are allowed. The next commit will have
4200 two parents.
4199 two parents.
4201
4200
4202 ``--tool`` can be used to specify the merge tool used for file
4201 ``--tool`` can be used to specify the merge tool used for file
4203 merges. It overrides the HGMERGE environment variable and your
4202 merges. It overrides the HGMERGE environment variable and your
4204 configuration files. See :hg:`help merge-tools` for options.
4203 configuration files. See :hg:`help merge-tools` for options.
4205
4204
4206 If no revision is specified, the working directory's parent is a
4205 If no revision is specified, the working directory's parent is a
4207 head revision, and the current branch contains exactly one other
4206 head revision, and the current branch contains exactly one other
4208 head, the other head is merged with by default. Otherwise, an
4207 head, the other head is merged with by default. Otherwise, an
4209 explicit revision with which to merge with must be provided.
4208 explicit revision with which to merge with must be provided.
4210
4209
4211 :hg:`resolve` must be used to resolve unresolved files.
4210 :hg:`resolve` must be used to resolve unresolved files.
4212
4211
4213 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 To undo an uncommitted merge, use :hg:`update --clean .` which
4214 will check out a clean copy of the original merge parent, losing
4213 will check out a clean copy of the original merge parent, losing
4215 all changes.
4214 all changes.
4216
4215
4217 Returns 0 on success, 1 if there are unresolved files.
4216 Returns 0 on success, 1 if there are unresolved files.
4218 """
4217 """
4219
4218
4220 if opts.get('rev') and node:
4219 if opts.get('rev') and node:
4221 raise util.Abort(_("please specify just one revision"))
4220 raise util.Abort(_("please specify just one revision"))
4222 if not node:
4221 if not node:
4223 node = opts.get('rev')
4222 node = opts.get('rev')
4224
4223
4225 if node:
4224 if node:
4226 node = scmutil.revsingle(repo, node).node()
4225 node = scmutil.revsingle(repo, node).node()
4227
4226
4228 if not node and repo._bookmarkcurrent:
4227 if not node and repo._bookmarkcurrent:
4229 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4230 curhead = repo[repo._bookmarkcurrent].node()
4229 curhead = repo[repo._bookmarkcurrent].node()
4231 if len(bmheads) == 2:
4230 if len(bmheads) == 2:
4232 if curhead == bmheads[0]:
4231 if curhead == bmheads[0]:
4233 node = bmheads[1]
4232 node = bmheads[1]
4234 else:
4233 else:
4235 node = bmheads[0]
4234 node = bmheads[0]
4236 elif len(bmheads) > 2:
4235 elif len(bmheads) > 2:
4237 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 raise util.Abort(_("multiple matching bookmarks to merge - "
4238 "please merge with an explicit rev or bookmark"),
4237 "please merge with an explicit rev or bookmark"),
4239 hint=_("run 'hg heads' to see all heads"))
4238 hint=_("run 'hg heads' to see all heads"))
4240 elif len(bmheads) <= 1:
4239 elif len(bmheads) <= 1:
4241 raise util.Abort(_("no matching bookmark to merge - "
4240 raise util.Abort(_("no matching bookmark to merge - "
4242 "please merge with an explicit rev or bookmark"),
4241 "please merge with an explicit rev or bookmark"),
4243 hint=_("run 'hg heads' to see all heads"))
4242 hint=_("run 'hg heads' to see all heads"))
4244
4243
4245 if not node and not repo._bookmarkcurrent:
4244 if not node and not repo._bookmarkcurrent:
4246 branch = repo[None].branch()
4245 branch = repo[None].branch()
4247 bheads = repo.branchheads(branch)
4246 bheads = repo.branchheads(branch)
4248 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4249
4248
4250 if len(nbhs) > 2:
4249 if len(nbhs) > 2:
4251 raise util.Abort(_("branch '%s' has %d heads - "
4250 raise util.Abort(_("branch '%s' has %d heads - "
4252 "please merge with an explicit rev")
4251 "please merge with an explicit rev")
4253 % (branch, len(bheads)),
4252 % (branch, len(bheads)),
4254 hint=_("run 'hg heads .' to see heads"))
4253 hint=_("run 'hg heads .' to see heads"))
4255
4254
4256 parent = repo.dirstate.p1()
4255 parent = repo.dirstate.p1()
4257 if len(nbhs) <= 1:
4256 if len(nbhs) <= 1:
4258 if len(bheads) > 1:
4257 if len(bheads) > 1:
4259 raise util.Abort(_("heads are bookmarked - "
4258 raise util.Abort(_("heads are bookmarked - "
4260 "please merge with an explicit rev"),
4259 "please merge with an explicit rev"),
4261 hint=_("run 'hg heads' to see all heads"))
4260 hint=_("run 'hg heads' to see all heads"))
4262 if len(repo.heads()) > 1:
4261 if len(repo.heads()) > 1:
4263 raise util.Abort(_("branch '%s' has one head - "
4262 raise util.Abort(_("branch '%s' has one head - "
4264 "please merge with an explicit rev")
4263 "please merge with an explicit rev")
4265 % branch,
4264 % branch,
4266 hint=_("run 'hg heads' to see all heads"))
4265 hint=_("run 'hg heads' to see all heads"))
4267 msg, hint = _('nothing to merge'), None
4266 msg, hint = _('nothing to merge'), None
4268 if parent != repo.lookup(branch):
4267 if parent != repo.lookup(branch):
4269 hint = _("use 'hg update' instead")
4268 hint = _("use 'hg update' instead")
4270 raise util.Abort(msg, hint=hint)
4269 raise util.Abort(msg, hint=hint)
4271
4270
4272 if parent not in bheads:
4271 if parent not in bheads:
4273 raise util.Abort(_('working directory not at a head revision'),
4272 raise util.Abort(_('working directory not at a head revision'),
4274 hint=_("use 'hg update' or merge with an "
4273 hint=_("use 'hg update' or merge with an "
4275 "explicit revision"))
4274 "explicit revision"))
4276 if parent == nbhs[0]:
4275 if parent == nbhs[0]:
4277 node = nbhs[-1]
4276 node = nbhs[-1]
4278 else:
4277 else:
4279 node = nbhs[0]
4278 node = nbhs[0]
4280
4279
4281 if opts.get('preview'):
4280 if opts.get('preview'):
4282 # find nodes that are ancestors of p2 but not of p1
4281 # find nodes that are ancestors of p2 but not of p1
4283 p1 = repo.lookup('.')
4282 p1 = repo.lookup('.')
4284 p2 = repo.lookup(node)
4283 p2 = repo.lookup(node)
4285 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4286
4285
4287 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4288 for node in nodes:
4287 for node in nodes:
4289 displayer.show(repo[node])
4288 displayer.show(repo[node])
4290 displayer.close()
4289 displayer.close()
4291 return 0
4290 return 0
4292
4291
4293 try:
4292 try:
4294 # ui.forcemerge is an internal variable, do not document
4293 # ui.forcemerge is an internal variable, do not document
4295 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4296 return hg.merge(repo, node, force=opts.get('force'))
4295 return hg.merge(repo, node, force=opts.get('force'))
4297 finally:
4296 finally:
4298 ui.setconfig('ui', 'forcemerge', '')
4297 ui.setconfig('ui', 'forcemerge', '')
4299
4298
4300 @command('outgoing|out',
4299 @command('outgoing|out',
4301 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 [('f', 'force', None, _('run even when the destination is unrelated')),
4302 ('r', 'rev', [],
4301 ('r', 'rev', [],
4303 _('a changeset intended to be included in the destination'), _('REV')),
4302 _('a changeset intended to be included in the destination'), _('REV')),
4304 ('n', 'newest-first', None, _('show newest record first')),
4303 ('n', 'newest-first', None, _('show newest record first')),
4305 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('B', 'bookmarks', False, _('compare bookmarks')),
4306 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 ('b', 'branch', [], _('a specific branch you would like to push'),
4307 _('BRANCH')),
4306 _('BRANCH')),
4308 ] + logopts + remoteopts + subrepoopts,
4307 ] + logopts + remoteopts + subrepoopts,
4309 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4310 def outgoing(ui, repo, dest=None, **opts):
4309 def outgoing(ui, repo, dest=None, **opts):
4311 """show changesets not found in the destination
4310 """show changesets not found in the destination
4312
4311
4313 Show changesets not found in the specified destination repository
4312 Show changesets not found in the specified destination repository
4314 or the default push location. These are the changesets that would
4313 or the default push location. These are the changesets that would
4315 be pushed if a push was requested.
4314 be pushed if a push was requested.
4316
4315
4317 See pull for details of valid destination formats.
4316 See pull for details of valid destination formats.
4318
4317
4319 Returns 0 if there are outgoing changes, 1 otherwise.
4318 Returns 0 if there are outgoing changes, 1 otherwise.
4320 """
4319 """
4321 if opts.get('graph'):
4320 if opts.get('graph'):
4322 cmdutil.checkunsupportedgraphflags([], opts)
4321 cmdutil.checkunsupportedgraphflags([], opts)
4323 o = hg._outgoing(ui, repo, dest, opts)
4322 o = hg._outgoing(ui, repo, dest, opts)
4324 if o is None:
4323 if o is None:
4325 return
4324 return
4326
4325
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4326 revdag = cmdutil.graphrevs(repo, o, opts)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 showparents = [ctx.node() for ctx in repo[None].parents()]
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4331 graphmod.asciiedges)
4330 graphmod.asciiedges)
4332 return 0
4331 return 0
4333
4332
4334 if opts.get('bookmarks'):
4333 if opts.get('bookmarks'):
4335 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4336 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4337 other = hg.peer(repo, opts, dest)
4336 other = hg.peer(repo, opts, dest)
4338 if 'bookmarks' not in other.listkeys('namespaces'):
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4339 ui.warn(_("remote doesn't support bookmarks\n"))
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4340 return 0
4339 return 0
4341 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4342 return bookmarks.diff(ui, other, repo)
4341 return bookmarks.diff(ui, other, repo)
4343
4342
4344 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4345 try:
4344 try:
4346 return hg.outgoing(ui, repo, dest, opts)
4345 return hg.outgoing(ui, repo, dest, opts)
4347 finally:
4346 finally:
4348 del repo._subtoppath
4347 del repo._subtoppath
4349
4348
4350 @command('parents',
4349 @command('parents',
4351 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4352 ] + templateopts,
4351 ] + templateopts,
4353 _('[-r REV] [FILE]'))
4352 _('[-r REV] [FILE]'))
4354 def parents(ui, repo, file_=None, **opts):
4353 def parents(ui, repo, file_=None, **opts):
4355 """show the parents of the working directory or revision
4354 """show the parents of the working directory or revision
4356
4355
4357 Print the working directory's parent revisions. If a revision is
4356 Print the working directory's parent revisions. If a revision is
4358 given via -r/--rev, the parent of that revision will be printed.
4357 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
4358 If a file argument is given, the revision in which the file was
4360 last changed (before the working directory revision or the
4359 last changed (before the working directory revision or the
4361 argument to --rev if given) is printed.
4360 argument to --rev if given) is printed.
4362
4361
4363 Returns 0 on success.
4362 Returns 0 on success.
4364 """
4363 """
4365
4364
4366 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4367
4366
4368 if file_:
4367 if file_:
4369 m = scmutil.match(ctx, (file_,), opts)
4368 m = scmutil.match(ctx, (file_,), opts)
4370 if m.anypats() or len(m.files()) != 1:
4369 if m.anypats() or len(m.files()) != 1:
4371 raise util.Abort(_('can only specify an explicit filename'))
4370 raise util.Abort(_('can only specify an explicit filename'))
4372 file_ = m.files()[0]
4371 file_ = m.files()[0]
4373 filenodes = []
4372 filenodes = []
4374 for cp in ctx.parents():
4373 for cp in ctx.parents():
4375 if not cp:
4374 if not cp:
4376 continue
4375 continue
4377 try:
4376 try:
4378 filenodes.append(cp.filenode(file_))
4377 filenodes.append(cp.filenode(file_))
4379 except error.LookupError:
4378 except error.LookupError:
4380 pass
4379 pass
4381 if not filenodes:
4380 if not filenodes:
4382 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4383 p = []
4382 p = []
4384 for fn in filenodes:
4383 for fn in filenodes:
4385 fctx = repo.filectx(file_, fileid=fn)
4384 fctx = repo.filectx(file_, fileid=fn)
4386 p.append(fctx.node())
4385 p.append(fctx.node())
4387 else:
4386 else:
4388 p = [cp.node() for cp in ctx.parents()]
4387 p = [cp.node() for cp in ctx.parents()]
4389
4388
4390 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4391 for n in p:
4390 for n in p:
4392 if n != nullid:
4391 if n != nullid:
4393 displayer.show(repo[n])
4392 displayer.show(repo[n])
4394 displayer.close()
4393 displayer.close()
4395
4394
4396 @command('paths', [], _('[NAME]'))
4395 @command('paths', [], _('[NAME]'))
4397 def paths(ui, repo, search=None):
4396 def paths(ui, repo, search=None):
4398 """show aliases for remote repositories
4397 """show aliases for remote repositories
4399
4398
4400 Show definition of symbolic path name NAME. If no name is given,
4399 Show definition of symbolic path name NAME. If no name is given,
4401 show definition of all available names.
4400 show definition of all available names.
4402
4401
4403 Option -q/--quiet suppresses all output when searching for NAME
4402 Option -q/--quiet suppresses all output when searching for NAME
4404 and shows only the path names when listing all definitions.
4403 and shows only the path names when listing all definitions.
4405
4404
4406 Path names are defined in the [paths] section of your
4405 Path names are defined in the [paths] section of your
4407 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4408 repository, ``.hg/hgrc`` is used, too.
4407 repository, ``.hg/hgrc`` is used, too.
4409
4408
4410 The path names ``default`` and ``default-push`` have a special
4409 The path names ``default`` and ``default-push`` have a special
4411 meaning. When performing a push or pull operation, they are used
4410 meaning. When performing a push or pull operation, they are used
4412 as fallbacks if no location is specified on the command-line.
4411 as fallbacks if no location is specified on the command-line.
4413 When ``default-push`` is set, it will be used for push and
4412 When ``default-push`` is set, it will be used for push and
4414 ``default`` will be used for pull; otherwise ``default`` is used
4413 ``default`` will be used for pull; otherwise ``default`` is used
4415 as the fallback for both. When cloning a repository, the clone
4414 as the fallback for both. When cloning a repository, the clone
4416 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4417 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4418 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4419 :hg:`bundle`) operations.
4418 :hg:`bundle`) operations.
4420
4419
4421 See :hg:`help urls` for more information.
4420 See :hg:`help urls` for more information.
4422
4421
4423 Returns 0 on success.
4422 Returns 0 on success.
4424 """
4423 """
4425 if search:
4424 if search:
4426 for name, path in ui.configitems("paths"):
4425 for name, path in ui.configitems("paths"):
4427 if name == search:
4426 if name == search:
4428 ui.status("%s\n" % util.hidepassword(path))
4427 ui.status("%s\n" % util.hidepassword(path))
4429 return
4428 return
4430 if not ui.quiet:
4429 if not ui.quiet:
4431 ui.warn(_("not found!\n"))
4430 ui.warn(_("not found!\n"))
4432 return 1
4431 return 1
4433 else:
4432 else:
4434 for name, path in ui.configitems("paths"):
4433 for name, path in ui.configitems("paths"):
4435 if ui.quiet:
4434 if ui.quiet:
4436 ui.write("%s\n" % name)
4435 ui.write("%s\n" % name)
4437 else:
4436 else:
4438 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4439
4438
4440 @command('phase',
4439 @command('phase',
4441 [('p', 'public', False, _('set changeset phase to public')),
4440 [('p', 'public', False, _('set changeset phase to public')),
4442 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4443 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4444 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4445 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4446 ],
4445 ],
4447 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4448 def phase(ui, repo, *revs, **opts):
4447 def phase(ui, repo, *revs, **opts):
4449 """set or show the current phase name
4448 """set or show the current phase name
4450
4449
4451 With no argument, show the phase name of specified revisions.
4450 With no argument, show the phase name of specified revisions.
4452
4451
4453 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4454 phase value of the specified revisions.
4453 phase value of the specified revisions.
4455
4454
4456 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 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::
4456 lower phase to an higher phase. Phases are ordered as follows::
4458
4457
4459 public < draft < secret
4458 public < draft < secret
4460
4459
4461 Return 0 on success, 1 if no phases were changed or some could not
4460 Return 0 on success, 1 if no phases were changed or some could not
4462 be changed.
4461 be changed.
4463 """
4462 """
4464 # search for a unique phase argument
4463 # search for a unique phase argument
4465 targetphase = None
4464 targetphase = None
4466 for idx, name in enumerate(phases.phasenames):
4465 for idx, name in enumerate(phases.phasenames):
4467 if opts[name]:
4466 if opts[name]:
4468 if targetphase is not None:
4467 if targetphase is not None:
4469 raise util.Abort(_('only one phase can be specified'))
4468 raise util.Abort(_('only one phase can be specified'))
4470 targetphase = idx
4469 targetphase = idx
4471
4470
4472 # look for specified revision
4471 # look for specified revision
4473 revs = list(revs)
4472 revs = list(revs)
4474 revs.extend(opts['rev'])
4473 revs.extend(opts['rev'])
4475 if not revs:
4474 if not revs:
4476 raise util.Abort(_('no revisions specified'))
4475 raise util.Abort(_('no revisions specified'))
4477
4476
4478 revs = scmutil.revrange(repo, revs)
4477 revs = scmutil.revrange(repo, revs)
4479
4478
4480 lock = None
4479 lock = None
4481 ret = 0
4480 ret = 0
4482 if targetphase is None:
4481 if targetphase is None:
4483 # display
4482 # display
4484 for r in revs:
4483 for r in revs:
4485 ctx = repo[r]
4484 ctx = repo[r]
4486 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4487 else:
4486 else:
4488 lock = repo.lock()
4487 lock = repo.lock()
4489 try:
4488 try:
4490 # set phase
4489 # set phase
4491 if not revs:
4490 if not revs:
4492 raise util.Abort(_('empty revision set'))
4491 raise util.Abort(_('empty revision set'))
4493 nodes = [repo[r].node() for r in revs]
4492 nodes = [repo[r].node() for r in revs]
4494 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4495 phases.advanceboundary(repo, targetphase, nodes)
4494 phases.advanceboundary(repo, targetphase, nodes)
4496 if opts['force']:
4495 if opts['force']:
4497 phases.retractboundary(repo, targetphase, nodes)
4496 phases.retractboundary(repo, targetphase, nodes)
4498 finally:
4497 finally:
4499 lock.release()
4498 lock.release()
4500 # moving revision from public to draft may hide them
4499 # moving revision from public to draft may hide them
4501 # We have to check result on an unfiltered repository
4500 # We have to check result on an unfiltered repository
4502 unfi = repo.unfiltered()
4501 unfi = repo.unfiltered()
4503 newdata = repo._phasecache.getphaserevs(unfi)
4502 newdata = repo._phasecache.getphaserevs(unfi)
4504 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4505 cl = unfi.changelog
4504 cl = unfi.changelog
4506 rejected = [n for n in nodes
4505 rejected = [n for n in nodes
4507 if newdata[cl.rev(n)] < targetphase]
4506 if newdata[cl.rev(n)] < targetphase]
4508 if rejected:
4507 if rejected:
4509 ui.warn(_('cannot move %i changesets to a higher '
4508 ui.warn(_('cannot move %i changesets to a higher '
4510 'phase, use --force\n') % len(rejected))
4509 'phase, use --force\n') % len(rejected))
4511 ret = 1
4510 ret = 1
4512 if changes:
4511 if changes:
4513 msg = _('phase changed for %i changesets\n') % changes
4512 msg = _('phase changed for %i changesets\n') % changes
4514 if ret:
4513 if ret:
4515 ui.status(msg)
4514 ui.status(msg)
4516 else:
4515 else:
4517 ui.note(msg)
4516 ui.note(msg)
4518 else:
4517 else:
4519 ui.warn(_('no phases changed\n'))
4518 ui.warn(_('no phases changed\n'))
4520 ret = 1
4519 ret = 1
4521 return ret
4520 return ret
4522
4521
4523 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4524 if modheads == 0:
4523 if modheads == 0:
4525 return
4524 return
4526 if optupdate:
4525 if optupdate:
4527 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4528 try:
4527 try:
4529 ret = hg.update(repo, checkout)
4528 ret = hg.update(repo, checkout)
4530 except util.Abort, inst:
4529 except util.Abort, inst:
4531 ui.warn(_("not updating: %s\n") % str(inst))
4530 ui.warn(_("not updating: %s\n") % str(inst))
4532 if inst.hint:
4531 if inst.hint:
4533 ui.warn(_("(%s)\n") % inst.hint)
4532 ui.warn(_("(%s)\n") % inst.hint)
4534 return 0
4533 return 0
4535 if not ret and not checkout:
4534 if not ret and not checkout:
4536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4537 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4538 return ret
4537 return ret
4539 if modheads > 1:
4538 if modheads > 1:
4540 currentbranchheads = len(repo.branchheads())
4539 currentbranchheads = len(repo.branchheads())
4541 if currentbranchheads == modheads:
4540 if currentbranchheads == modheads:
4542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4543 elif currentbranchheads > 1:
4542 elif currentbranchheads > 1:
4544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4545 "merge)\n"))
4544 "merge)\n"))
4546 else:
4545 else:
4547 ui.status(_("(run 'hg heads' to see heads)\n"))
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4548 else:
4547 else:
4549 ui.status(_("(run 'hg update' to get a working copy)\n"))
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4550
4549
4551 @command('^pull',
4550 @command('^pull',
4552 [('u', 'update', None,
4551 [('u', 'update', None,
4553 _('update to new branch head if changesets were pulled')),
4552 _('update to new branch head if changesets were pulled')),
4554 ('f', 'force', None, _('run even when remote repository is unrelated')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4557 ('b', 'branch', [], _('a specific branch you would like to pull'),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4558 _('BRANCH')),
4557 _('BRANCH')),
4559 ] + remoteopts,
4558 ] + remoteopts,
4560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4561 def pull(ui, repo, source="default", **opts):
4560 def pull(ui, repo, source="default", **opts):
4562 """pull changes from the specified source
4561 """pull changes from the specified source
4563
4562
4564 Pull changes from a remote repository to a local one.
4563 Pull changes from a remote repository to a local one.
4565
4564
4566 This finds all changes from the repository at the specified path
4565 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
4566 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
4567 -R is specified). By default, this does not update the copy of the
4569 project in the working directory.
4568 project in the working directory.
4570
4569
4571 Use :hg:`incoming` if you want to see what would have been added
4570 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
4571 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
4572 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`.
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4575
4574
4576 If SOURCE is omitted, the 'default' path will be used.
4575 If SOURCE is omitted, the 'default' path will be used.
4577 See :hg:`help urls` for more information.
4576 See :hg:`help urls` for more information.
4578
4577
4579 Returns 0 on success, 1 if an update had unresolved files.
4578 Returns 0 on success, 1 if an update had unresolved files.
4580 """
4579 """
4581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4582 other = hg.peer(repo, opts, source)
4581 other = hg.peer(repo, opts, source)
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4584 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4583 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4585
4584
4586 remotebookmarks = other.listkeys('bookmarks')
4585 remotebookmarks = other.listkeys('bookmarks')
4587
4586
4588 if opts.get('bookmark'):
4587 if opts.get('bookmark'):
4589 if not revs:
4588 if not revs:
4590 revs = []
4589 revs = []
4591 for b in opts['bookmark']:
4590 for b in opts['bookmark']:
4592 if b not in remotebookmarks:
4591 if b not in remotebookmarks:
4593 raise util.Abort(_('remote bookmark %s not found!') % b)
4592 raise util.Abort(_('remote bookmark %s not found!') % b)
4594 revs.append(remotebookmarks[b])
4593 revs.append(remotebookmarks[b])
4595
4594
4596 if revs:
4595 if revs:
4597 try:
4596 try:
4598 revs = [other.lookup(rev) for rev in revs]
4597 revs = [other.lookup(rev) for rev in revs]
4599 except error.CapabilityError:
4598 except error.CapabilityError:
4600 err = _("other repository doesn't support revision lookup, "
4599 err = _("other repository doesn't support revision lookup, "
4601 "so a rev cannot be specified.")
4600 "so a rev cannot be specified.")
4602 raise util.Abort(err)
4601 raise util.Abort(err)
4603
4602
4604 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4603 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4605 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4604 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4606 if checkout:
4605 if checkout:
4607 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4606 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4608 repo._subtoppath = source
4607 repo._subtoppath = source
4609 try:
4608 try:
4610 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4609 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4611
4610
4612 finally:
4611 finally:
4613 del repo._subtoppath
4612 del repo._subtoppath
4614
4613
4615 # update specified bookmarks
4614 # update specified bookmarks
4616 if opts.get('bookmark'):
4615 if opts.get('bookmark'):
4617 marks = repo._bookmarks
4616 marks = repo._bookmarks
4618 for b in opts['bookmark']:
4617 for b in opts['bookmark']:
4619 # explicit pull overrides local bookmark if any
4618 # explicit pull overrides local bookmark if any
4620 ui.status(_("importing bookmark %s\n") % b)
4619 ui.status(_("importing bookmark %s\n") % b)
4621 marks[b] = repo[remotebookmarks[b]].node()
4620 marks[b] = repo[remotebookmarks[b]].node()
4622 marks.write()
4621 marks.write()
4623
4622
4624 return ret
4623 return ret
4625
4624
4626 @command('^push',
4625 @command('^push',
4627 [('f', 'force', None, _('force push')),
4626 [('f', 'force', None, _('force push')),
4628 ('r', 'rev', [],
4627 ('r', 'rev', [],
4629 _('a changeset intended to be included in the destination'),
4628 _('a changeset intended to be included in the destination'),
4630 _('REV')),
4629 _('REV')),
4631 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4630 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4632 ('b', 'branch', [],
4631 ('b', 'branch', [],
4633 _('a specific branch you would like to push'), _('BRANCH')),
4632 _('a specific branch you would like to push'), _('BRANCH')),
4634 ('', 'new-branch', False, _('allow pushing a new branch')),
4633 ('', 'new-branch', False, _('allow pushing a new branch')),
4635 ] + remoteopts,
4634 ] + remoteopts,
4636 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4635 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4637 def push(ui, repo, dest=None, **opts):
4636 def push(ui, repo, dest=None, **opts):
4638 """push changes to the specified destination
4637 """push changes to the specified destination
4639
4638
4640 Push changesets from the local repository to the specified
4639 Push changesets from the local repository to the specified
4641 destination.
4640 destination.
4642
4641
4643 This operation is symmetrical to pull: it is identical to a pull
4642 This operation is symmetrical to pull: it is identical to a pull
4644 in the destination repository from the current one.
4643 in the destination repository from the current one.
4645
4644
4646 By default, push will not allow creation of new heads at the
4645 By default, push will not allow creation of new heads at the
4647 destination, since multiple heads would make it unclear which head
4646 destination, since multiple heads would make it unclear which head
4648 to use. In this situation, it is recommended to pull and merge
4647 to use. In this situation, it is recommended to pull and merge
4649 before pushing.
4648 before pushing.
4650
4649
4651 Use --new-branch if you want to allow push to create a new named
4650 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
4651 branch that is not present at the destination. This allows you to
4653 only create a new branch without forcing other changes.
4652 only create a new branch without forcing other changes.
4654
4653
4655 .. note::
4654 .. note::
4656
4655
4657 Extra care should be taken with the -f/--force option,
4656 Extra care should be taken with the -f/--force option,
4658 which will push all new heads on all branches, an action which will
4657 which will push all new heads on all branches, an action which will
4659 almost always cause confusion for collaborators.
4658 almost always cause confusion for collaborators.
4660
4659
4661 If -r/--rev is used, the specified revision and all its ancestors
4660 If -r/--rev is used, the specified revision and all its ancestors
4662 will be pushed to the remote repository.
4661 will be pushed to the remote repository.
4663
4662
4664 If -B/--bookmark is used, the specified bookmarked revision, its
4663 If -B/--bookmark is used, the specified bookmarked revision, its
4665 ancestors, and the bookmark will be pushed to the remote
4664 ancestors, and the bookmark will be pushed to the remote
4666 repository.
4665 repository.
4667
4666
4668 Please see :hg:`help urls` for important details about ``ssh://``
4667 Please see :hg:`help urls` for important details about ``ssh://``
4669 URLs. If DESTINATION is omitted, a default path will be used.
4668 URLs. If DESTINATION is omitted, a default path will be used.
4670
4669
4671 Returns 0 if push was successful, 1 if nothing to push.
4670 Returns 0 if push was successful, 1 if nothing to push.
4672 """
4671 """
4673
4672
4674 if opts.get('bookmark'):
4673 if opts.get('bookmark'):
4675 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4674 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4676 for b in opts['bookmark']:
4675 for b in opts['bookmark']:
4677 # translate -B options to -r so changesets get pushed
4676 # translate -B options to -r so changesets get pushed
4678 if b in repo._bookmarks:
4677 if b in repo._bookmarks:
4679 opts.setdefault('rev', []).append(b)
4678 opts.setdefault('rev', []).append(b)
4680 else:
4679 else:
4681 # if we try to push a deleted bookmark, translate it to null
4680 # if we try to push a deleted bookmark, translate it to null
4682 # this lets simultaneous -r, -b options continue working
4681 # this lets simultaneous -r, -b options continue working
4683 opts.setdefault('rev', []).append("null")
4682 opts.setdefault('rev', []).append("null")
4684
4683
4685 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4684 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4686 dest, branches = hg.parseurl(dest, opts.get('branch'))
4685 dest, branches = hg.parseurl(dest, opts.get('branch'))
4687 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4686 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4688 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4687 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4689 other = hg.peer(repo, opts, dest)
4688 other = hg.peer(repo, opts, dest)
4690 if revs:
4689 if revs:
4691 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4690 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4692
4691
4693 repo._subtoppath = dest
4692 repo._subtoppath = dest
4694 try:
4693 try:
4695 # push subrepos depth-first for coherent ordering
4694 # push subrepos depth-first for coherent ordering
4696 c = repo['']
4695 c = repo['']
4697 subs = c.substate # only repos that are committed
4696 subs = c.substate # only repos that are committed
4698 for s in sorted(subs):
4697 for s in sorted(subs):
4699 if c.sub(s).push(opts) == 0:
4698 if c.sub(s).push(opts) == 0:
4700 return False
4699 return False
4701 finally:
4700 finally:
4702 del repo._subtoppath
4701 del repo._subtoppath
4703 result = repo.push(other, opts.get('force'), revs=revs,
4702 result = repo.push(other, opts.get('force'), revs=revs,
4704 newbranch=opts.get('new_branch'))
4703 newbranch=opts.get('new_branch'))
4705
4704
4706 result = not result
4705 result = not result
4707
4706
4708 if opts.get('bookmark'):
4707 if opts.get('bookmark'):
4709 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4708 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4710 if bresult == 2:
4709 if bresult == 2:
4711 return 2
4710 return 2
4712 if not result and bresult:
4711 if not result and bresult:
4713 result = 2
4712 result = 2
4714
4713
4715 return result
4714 return result
4716
4715
4717 @command('recover', [])
4716 @command('recover', [])
4718 def recover(ui, repo):
4717 def recover(ui, repo):
4719 """roll back an interrupted transaction
4718 """roll back an interrupted transaction
4720
4719
4721 Recover from an interrupted commit or pull.
4720 Recover from an interrupted commit or pull.
4722
4721
4723 This command tries to fix the repository status after an
4722 This command tries to fix the repository status after an
4724 interrupted operation. It should only be necessary when Mercurial
4723 interrupted operation. It should only be necessary when Mercurial
4725 suggests it.
4724 suggests it.
4726
4725
4727 Returns 0 if successful, 1 if nothing to recover or verify fails.
4726 Returns 0 if successful, 1 if nothing to recover or verify fails.
4728 """
4727 """
4729 if repo.recover():
4728 if repo.recover():
4730 return hg.verify(repo)
4729 return hg.verify(repo)
4731 return 1
4730 return 1
4732
4731
4733 @command('^remove|rm',
4732 @command('^remove|rm',
4734 [('A', 'after', None, _('record delete for missing files')),
4733 [('A', 'after', None, _('record delete for missing files')),
4735 ('f', 'force', None,
4734 ('f', 'force', None,
4736 _('remove (and delete) file even if added or modified')),
4735 _('remove (and delete) file even if added or modified')),
4737 ] + walkopts,
4736 ] + walkopts,
4738 _('[OPTION]... FILE...'))
4737 _('[OPTION]... FILE...'))
4739 def remove(ui, repo, *pats, **opts):
4738 def remove(ui, repo, *pats, **opts):
4740 """remove the specified files on the next commit
4739 """remove the specified files on the next commit
4741
4740
4742 Schedule the indicated files for removal from the current branch.
4741 Schedule the indicated files for removal from the current branch.
4743
4742
4744 This command schedules the files to be removed at the next commit.
4743 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
4744 To undo a remove before that, see :hg:`revert`. To undo added
4746 files, see :hg:`forget`.
4745 files, see :hg:`forget`.
4747
4746
4748 .. container:: verbose
4747 .. container:: verbose
4749
4748
4750 -A/--after can be used to remove only files that have already
4749 -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
4750 been deleted, -f/--force can be used to force deletion, and -Af
4752 can be used to remove files from the next revision without
4751 can be used to remove files from the next revision without
4753 deleting them from the working directory.
4752 deleting them from the working directory.
4754
4753
4755 The following table details the behavior of remove for different
4754 The following table details the behavior of remove for different
4756 file states (columns) and option combinations (rows). The file
4755 file states (columns) and option combinations (rows). The file
4757 states are Added [A], Clean [C], Modified [M] and Missing [!]
4756 states are Added [A], Clean [C], Modified [M] and Missing [!]
4758 (as reported by :hg:`status`). The actions are Warn, Remove
4757 (as reported by :hg:`status`). The actions are Warn, Remove
4759 (from branch) and Delete (from disk):
4758 (from branch) and Delete (from disk):
4760
4759
4761 ========= == == == ==
4760 ========= == == == ==
4762 opt/state A C M !
4761 opt/state A C M !
4763 ========= == == == ==
4762 ========= == == == ==
4764 none W RD W R
4763 none W RD W R
4765 -f R RD RD R
4764 -f R RD RD R
4766 -A W W W R
4765 -A W W W R
4767 -Af R R R R
4766 -Af R R R R
4768 ========= == == == ==
4767 ========= == == == ==
4769
4768
4770 Note that remove never deletes files in Added [A] state from the
4769 Note that remove never deletes files in Added [A] state from the
4771 working directory, not even if option --force is specified.
4770 working directory, not even if option --force is specified.
4772
4771
4773 Returns 0 on success, 1 if any warnings encountered.
4772 Returns 0 on success, 1 if any warnings encountered.
4774 """
4773 """
4775
4774
4776 ret = 0
4775 ret = 0
4777 after, force = opts.get('after'), opts.get('force')
4776 after, force = opts.get('after'), opts.get('force')
4778 if not pats and not after:
4777 if not pats and not after:
4779 raise util.Abort(_('no files specified'))
4778 raise util.Abort(_('no files specified'))
4780
4779
4781 m = scmutil.match(repo[None], pats, opts)
4780 m = scmutil.match(repo[None], pats, opts)
4782 s = repo.status(match=m, clean=True)
4781 s = repo.status(match=m, clean=True)
4783 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4782 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4784
4783
4785 # warn about failure to delete explicit files/dirs
4784 # warn about failure to delete explicit files/dirs
4786 wctx = repo[None]
4785 wctx = repo[None]
4787 for f in m.files():
4786 for f in m.files():
4788 if f in repo.dirstate or f in wctx.dirs():
4787 if f in repo.dirstate or f in wctx.dirs():
4789 continue
4788 continue
4790 if os.path.exists(m.rel(f)):
4789 if os.path.exists(m.rel(f)):
4791 if os.path.isdir(m.rel(f)):
4790 if os.path.isdir(m.rel(f)):
4792 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4791 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4793 else:
4792 else:
4794 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4793 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4795 # missing files will generate a warning elsewhere
4794 # missing files will generate a warning elsewhere
4796 ret = 1
4795 ret = 1
4797
4796
4798 if force:
4797 if force:
4799 list = modified + deleted + clean + added
4798 list = modified + deleted + clean + added
4800 elif after:
4799 elif after:
4801 list = deleted
4800 list = deleted
4802 for f in modified + added + clean:
4801 for f in modified + added + clean:
4803 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4802 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4804 ret = 1
4803 ret = 1
4805 else:
4804 else:
4806 list = deleted + clean
4805 list = deleted + clean
4807 for f in modified:
4806 for f in modified:
4808 ui.warn(_('not removing %s: file is modified (use -f'
4807 ui.warn(_('not removing %s: file is modified (use -f'
4809 ' to force removal)\n') % m.rel(f))
4808 ' to force removal)\n') % m.rel(f))
4810 ret = 1
4809 ret = 1
4811 for f in added:
4810 for f in added:
4812 ui.warn(_('not removing %s: file has been marked for add'
4811 ui.warn(_('not removing %s: file has been marked for add'
4813 ' (use forget to undo)\n') % m.rel(f))
4812 ' (use forget to undo)\n') % m.rel(f))
4814 ret = 1
4813 ret = 1
4815
4814
4816 for f in sorted(list):
4815 for f in sorted(list):
4817 if ui.verbose or not m.exact(f):
4816 if ui.verbose or not m.exact(f):
4818 ui.status(_('removing %s\n') % m.rel(f))
4817 ui.status(_('removing %s\n') % m.rel(f))
4819
4818
4820 wlock = repo.wlock()
4819 wlock = repo.wlock()
4821 try:
4820 try:
4822 if not after:
4821 if not after:
4823 for f in list:
4822 for f in list:
4824 if f in added:
4823 if f in added:
4825 continue # we never unlink added files on remove
4824 continue # we never unlink added files on remove
4826 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4825 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4827 repo[None].forget(list)
4826 repo[None].forget(list)
4828 finally:
4827 finally:
4829 wlock.release()
4828 wlock.release()
4830
4829
4831 return ret
4830 return ret
4832
4831
4833 @command('rename|move|mv',
4832 @command('rename|move|mv',
4834 [('A', 'after', None, _('record a rename that has already occurred')),
4833 [('A', 'after', None, _('record a rename that has already occurred')),
4835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4834 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4836 ] + walkopts + dryrunopts,
4835 ] + walkopts + dryrunopts,
4837 _('[OPTION]... SOURCE... DEST'))
4836 _('[OPTION]... SOURCE... DEST'))
4838 def rename(ui, repo, *pats, **opts):
4837 def rename(ui, repo, *pats, **opts):
4839 """rename files; equivalent of copy + remove
4838 """rename files; equivalent of copy + remove
4840
4839
4841 Mark dest as copies of sources; mark sources for deletion. If dest
4840 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
4841 is a directory, copies are put in that directory. If dest is a
4843 file, there can only be one source.
4842 file, there can only be one source.
4844
4843
4845 By default, this command copies the contents of files as they
4844 By default, this command copies the contents of files as they
4846 exist in the working directory. If invoked with -A/--after, the
4845 exist in the working directory. If invoked with -A/--after, the
4847 operation is recorded, but no copying is performed.
4846 operation is recorded, but no copying is performed.
4848
4847
4849 This command takes effect at the next commit. To undo a rename
4848 This command takes effect at the next commit. To undo a rename
4850 before that, see :hg:`revert`.
4849 before that, see :hg:`revert`.
4851
4850
4852 Returns 0 on success, 1 if errors are encountered.
4851 Returns 0 on success, 1 if errors are encountered.
4853 """
4852 """
4854 wlock = repo.wlock(False)
4853 wlock = repo.wlock(False)
4855 try:
4854 try:
4856 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4855 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4857 finally:
4856 finally:
4858 wlock.release()
4857 wlock.release()
4859
4858
4860 @command('resolve',
4859 @command('resolve',
4861 [('a', 'all', None, _('select all unresolved files')),
4860 [('a', 'all', None, _('select all unresolved files')),
4862 ('l', 'list', None, _('list state of files needing merge')),
4861 ('l', 'list', None, _('list state of files needing merge')),
4863 ('m', 'mark', None, _('mark files as resolved')),
4862 ('m', 'mark', None, _('mark files as resolved')),
4864 ('u', 'unmark', None, _('mark files as unresolved')),
4863 ('u', 'unmark', None, _('mark files as unresolved')),
4865 ('n', 'no-status', None, _('hide status prefix'))]
4864 ('n', 'no-status', None, _('hide status prefix'))]
4866 + mergetoolopts + walkopts,
4865 + mergetoolopts + walkopts,
4867 _('[OPTION]... [FILE]...'))
4866 _('[OPTION]... [FILE]...'))
4868 def resolve(ui, repo, *pats, **opts):
4867 def resolve(ui, repo, *pats, **opts):
4869 """redo merges or set/view the merge status of files
4868 """redo merges or set/view the merge status of files
4870
4869
4871 Merges with unresolved conflicts are often the result of
4870 Merges with unresolved conflicts are often the result of
4872 non-interactive merging using the ``internal:merge`` configuration
4871 non-interactive merging using the ``internal:merge`` configuration
4873 setting, or a command-line merge tool like ``diff3``. The resolve
4872 setting, or a command-line merge tool like ``diff3``. The resolve
4874 command is used to manage the files involved in a merge, after
4873 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
4874 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4876 working directory must have two parents). See :hg:`help
4875 working directory must have two parents). See :hg:`help
4877 merge-tools` for information on configuring merge tools.
4876 merge-tools` for information on configuring merge tools.
4878
4877
4879 The resolve command can be used in the following ways:
4878 The resolve command can be used in the following ways:
4880
4879
4881 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4880 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4882 files, discarding any previous merge attempts. Re-merging is not
4881 files, discarding any previous merge attempts. Re-merging is not
4883 performed for files already marked as resolved. Use ``--all/-a``
4882 performed for files already marked as resolved. Use ``--all/-a``
4884 to select all unresolved files. ``--tool`` can be used to specify
4883 to select all unresolved files. ``--tool`` can be used to specify
4885 the merge tool used for the given files. It overrides the HGMERGE
4884 the merge tool used for the given files. It overrides the HGMERGE
4886 environment variable and your configuration files. Previous file
4885 environment variable and your configuration files. Previous file
4887 contents are saved with a ``.orig`` suffix.
4886 contents are saved with a ``.orig`` suffix.
4888
4887
4889 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4888 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4890 (e.g. after having manually fixed-up the files). The default is
4889 (e.g. after having manually fixed-up the files). The default is
4891 to mark all unresolved files.
4890 to mark all unresolved files.
4892
4891
4893 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4892 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4894 default is to mark all resolved files.
4893 default is to mark all resolved files.
4895
4894
4896 - :hg:`resolve -l`: list files which had or still have conflicts.
4895 - :hg:`resolve -l`: list files which had or still have conflicts.
4897 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4896 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4898
4897
4899 Note that Mercurial will not let you commit files with unresolved
4898 Note that Mercurial will not let you commit files with unresolved
4900 merge conflicts. You must use :hg:`resolve -m ...` before you can
4899 merge conflicts. You must use :hg:`resolve -m ...` before you can
4901 commit after a conflicting merge.
4900 commit after a conflicting merge.
4902
4901
4903 Returns 0 on success, 1 if any files fail a resolve attempt.
4902 Returns 0 on success, 1 if any files fail a resolve attempt.
4904 """
4903 """
4905
4904
4906 all, mark, unmark, show, nostatus = \
4905 all, mark, unmark, show, nostatus = \
4907 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4906 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4908
4907
4909 if (show and (mark or unmark)) or (mark and unmark):
4908 if (show and (mark or unmark)) or (mark and unmark):
4910 raise util.Abort(_("too many options specified"))
4909 raise util.Abort(_("too many options specified"))
4911 if pats and all:
4910 if pats and all:
4912 raise util.Abort(_("can't specify --all and patterns"))
4911 raise util.Abort(_("can't specify --all and patterns"))
4913 if not (all or pats or show or mark or unmark):
4912 if not (all or pats or show or mark or unmark):
4914 raise util.Abort(_('no files or directories specified; '
4913 raise util.Abort(_('no files or directories specified; '
4915 'use --all to remerge all files'))
4914 'use --all to remerge all files'))
4916
4915
4917 ms = mergemod.mergestate(repo)
4916 ms = mergemod.mergestate(repo)
4918 m = scmutil.match(repo[None], pats, opts)
4917 m = scmutil.match(repo[None], pats, opts)
4919 ret = 0
4918 ret = 0
4920
4919
4921 for f in ms:
4920 for f in ms:
4922 if m(f):
4921 if m(f):
4923 if show:
4922 if show:
4924 if nostatus:
4923 if nostatus:
4925 ui.write("%s\n" % f)
4924 ui.write("%s\n" % f)
4926 else:
4925 else:
4927 ui.write("%s %s\n" % (ms[f].upper(), f),
4926 ui.write("%s %s\n" % (ms[f].upper(), f),
4928 label='resolve.' +
4927 label='resolve.' +
4929 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4928 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4930 elif mark:
4929 elif mark:
4931 ms.mark(f, "r")
4930 ms.mark(f, "r")
4932 elif unmark:
4931 elif unmark:
4933 ms.mark(f, "u")
4932 ms.mark(f, "u")
4934 else:
4933 else:
4935 wctx = repo[None]
4934 wctx = repo[None]
4936 mctx = wctx.parents()[-1]
4935 mctx = wctx.parents()[-1]
4937
4936
4938 # backup pre-resolve (merge uses .orig for its own purposes)
4937 # backup pre-resolve (merge uses .orig for its own purposes)
4939 a = repo.wjoin(f)
4938 a = repo.wjoin(f)
4940 util.copyfile(a, a + ".resolve")
4939 util.copyfile(a, a + ".resolve")
4941
4940
4942 try:
4941 try:
4943 # resolve file
4942 # resolve file
4944 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4943 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4945 if ms.resolve(f, wctx, mctx):
4944 if ms.resolve(f, wctx, mctx):
4946 ret = 1
4945 ret = 1
4947 finally:
4946 finally:
4948 ui.setconfig('ui', 'forcemerge', '')
4947 ui.setconfig('ui', 'forcemerge', '')
4949 ms.commit()
4948 ms.commit()
4950
4949
4951 # replace filemerge's .orig file with our resolve file
4950 # replace filemerge's .orig file with our resolve file
4952 util.rename(a + ".resolve", a + ".orig")
4951 util.rename(a + ".resolve", a + ".orig")
4953
4952
4954 ms.commit()
4953 ms.commit()
4955 return ret
4954 return ret
4956
4955
4957 @command('revert',
4956 @command('revert',
4958 [('a', 'all', None, _('revert all changes when no arguments given')),
4957 [('a', 'all', None, _('revert all changes when no arguments given')),
4959 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4958 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4960 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4959 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4961 ('C', 'no-backup', None, _('do not save backup copies of files')),
4960 ('C', 'no-backup', None, _('do not save backup copies of files')),
4962 ] + walkopts + dryrunopts,
4961 ] + walkopts + dryrunopts,
4963 _('[OPTION]... [-r REV] [NAME]...'))
4962 _('[OPTION]... [-r REV] [NAME]...'))
4964 def revert(ui, repo, *pats, **opts):
4963 def revert(ui, repo, *pats, **opts):
4965 """restore files to their checkout state
4964 """restore files to their checkout state
4966
4965
4967 .. note::
4966 .. note::
4968
4967
4969 To check out earlier revisions, you should use :hg:`update REV`.
4968 To check out earlier revisions, you should use :hg:`update REV`.
4970 To cancel an uncommitted merge (and lose your changes),
4969 To cancel an uncommitted merge (and lose your changes),
4971 use :hg:`update --clean .`.
4970 use :hg:`update --clean .`.
4972
4971
4973 With no revision specified, revert the specified files or directories
4972 With no revision specified, revert the specified files or directories
4974 to the contents they had in the parent of the working directory.
4973 to the contents they had in the parent of the working directory.
4975 This restores the contents of files to an unmodified
4974 This restores the contents of files to an unmodified
4976 state and unschedules adds, removes, copies, and renames. If the
4975 state and unschedules adds, removes, copies, and renames. If the
4977 working directory has two parents, you must explicitly specify a
4976 working directory has two parents, you must explicitly specify a
4978 revision.
4977 revision.
4979
4978
4980 Using the -r/--rev or -d/--date options, revert the given files or
4979 Using the -r/--rev or -d/--date options, revert the given files or
4981 directories to their states as of a specific revision. Because
4980 directories to their states as of a specific revision. Because
4982 revert does not change the working directory parents, this will
4981 revert does not change the working directory parents, this will
4983 cause these files to appear modified. This can be helpful to "back
4982 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
4983 out" some or all of an earlier change. See :hg:`backout` for a
4985 related method.
4984 related method.
4986
4985
4987 Modified files are saved with a .orig suffix before reverting.
4986 Modified files are saved with a .orig suffix before reverting.
4988 To disable these backups, use --no-backup.
4987 To disable these backups, use --no-backup.
4989
4988
4990 See :hg:`help dates` for a list of formats valid for -d/--date.
4989 See :hg:`help dates` for a list of formats valid for -d/--date.
4991
4990
4992 Returns 0 on success.
4991 Returns 0 on success.
4993 """
4992 """
4994
4993
4995 if opts.get("date"):
4994 if opts.get("date"):
4996 if opts.get("rev"):
4995 if opts.get("rev"):
4997 raise util.Abort(_("you can't specify a revision and a date"))
4996 raise util.Abort(_("you can't specify a revision and a date"))
4998 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4997 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4999
4998
5000 parent, p2 = repo.dirstate.parents()
4999 parent, p2 = repo.dirstate.parents()
5001 if not opts.get('rev') and p2 != nullid:
5000 if not opts.get('rev') and p2 != nullid:
5002 # revert after merge is a trap for new users (issue2915)
5001 # revert after merge is a trap for new users (issue2915)
5003 raise util.Abort(_('uncommitted merge with no revision specified'),
5002 raise util.Abort(_('uncommitted merge with no revision specified'),
5004 hint=_('use "hg update" or see "hg help revert"'))
5003 hint=_('use "hg update" or see "hg help revert"'))
5005
5004
5006 ctx = scmutil.revsingle(repo, opts.get('rev'))
5005 ctx = scmutil.revsingle(repo, opts.get('rev'))
5007
5006
5008 if not pats and not opts.get('all'):
5007 if not pats and not opts.get('all'):
5009 msg = _("no files or directories specified")
5008 msg = _("no files or directories specified")
5010 if p2 != nullid:
5009 if p2 != nullid:
5011 hint = _("uncommitted merge, use --all to discard all changes,"
5010 hint = _("uncommitted merge, use --all to discard all changes,"
5012 " or 'hg update -C .' to abort the merge")
5011 " or 'hg update -C .' to abort the merge")
5013 raise util.Abort(msg, hint=hint)
5012 raise util.Abort(msg, hint=hint)
5014 dirty = util.any(repo.status())
5013 dirty = util.any(repo.status())
5015 node = ctx.node()
5014 node = ctx.node()
5016 if node != parent:
5015 if node != parent:
5017 if dirty:
5016 if dirty:
5018 hint = _("uncommitted changes, use --all to discard all"
5017 hint = _("uncommitted changes, use --all to discard all"
5019 " changes, or 'hg update %s' to update") % ctx.rev()
5018 " changes, or 'hg update %s' to update") % ctx.rev()
5020 else:
5019 else:
5021 hint = _("use --all to revert all files,"
5020 hint = _("use --all to revert all files,"
5022 " or 'hg update %s' to update") % ctx.rev()
5021 " or 'hg update %s' to update") % ctx.rev()
5023 elif dirty:
5022 elif dirty:
5024 hint = _("uncommitted changes, use --all to discard all changes")
5023 hint = _("uncommitted changes, use --all to discard all changes")
5025 else:
5024 else:
5026 hint = _("use --all to revert all files")
5025 hint = _("use --all to revert all files")
5027 raise util.Abort(msg, hint=hint)
5026 raise util.Abort(msg, hint=hint)
5028
5027
5029 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5028 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5030
5029
5031 @command('rollback', dryrunopts +
5030 @command('rollback', dryrunopts +
5032 [('f', 'force', False, _('ignore safety measures'))])
5031 [('f', 'force', False, _('ignore safety measures'))])
5033 def rollback(ui, repo, **opts):
5032 def rollback(ui, repo, **opts):
5034 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5033 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5035
5034
5036 Please use :hg:`commit --amend` instead of rollback to correct
5035 Please use :hg:`commit --amend` instead of rollback to correct
5037 mistakes in the last commit.
5036 mistakes in the last commit.
5038
5037
5039 This command should be used with care. There is only one level of
5038 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
5039 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
5040 restore the dirstate at the time of the last transaction, losing
5042 any dirstate changes since that time. This command does not alter
5041 any dirstate changes since that time. This command does not alter
5043 the working directory.
5042 the working directory.
5044
5043
5045 Transactions are used to encapsulate the effects of all commands
5044 Transactions are used to encapsulate the effects of all commands
5046 that create new changesets or propagate existing changesets into a
5045 that create new changesets or propagate existing changesets into a
5047 repository.
5046 repository.
5048
5047
5049 .. container:: verbose
5048 .. container:: verbose
5050
5049
5051 For example, the following commands are transactional, and their
5050 For example, the following commands are transactional, and their
5052 effects can be rolled back:
5051 effects can be rolled back:
5053
5052
5054 - commit
5053 - commit
5055 - import
5054 - import
5056 - pull
5055 - pull
5057 - push (with this repository as the destination)
5056 - push (with this repository as the destination)
5058 - unbundle
5057 - unbundle
5059
5058
5060 To avoid permanent data loss, rollback will refuse to rollback a
5059 To avoid permanent data loss, rollback will refuse to rollback a
5061 commit transaction if it isn't checked out. Use --force to
5060 commit transaction if it isn't checked out. Use --force to
5062 override this protection.
5061 override this protection.
5063
5062
5064 This command is not intended for use on public repositories. Once
5063 This command is not intended for use on public repositories. Once
5065 changes are visible for pull by other users, rolling a transaction
5064 changes are visible for pull by other users, rolling a transaction
5066 back locally is ineffective (someone else may already have pulled
5065 back locally is ineffective (someone else may already have pulled
5067 the changes). Furthermore, a race is possible with readers of the
5066 the changes). Furthermore, a race is possible with readers of the
5068 repository; for example an in-progress pull from the repository
5067 repository; for example an in-progress pull from the repository
5069 may fail if a rollback is performed.
5068 may fail if a rollback is performed.
5070
5069
5071 Returns 0 on success, 1 if no rollback data is available.
5070 Returns 0 on success, 1 if no rollback data is available.
5072 """
5071 """
5073 return repo.rollback(dryrun=opts.get('dry_run'),
5072 return repo.rollback(dryrun=opts.get('dry_run'),
5074 force=opts.get('force'))
5073 force=opts.get('force'))
5075
5074
5076 @command('root', [])
5075 @command('root', [])
5077 def root(ui, repo):
5076 def root(ui, repo):
5078 """print the root (top) of the current working directory
5077 """print the root (top) of the current working directory
5079
5078
5080 Print the root directory of the current repository.
5079 Print the root directory of the current repository.
5081
5080
5082 Returns 0 on success.
5081 Returns 0 on success.
5083 """
5082 """
5084 ui.write(repo.root + "\n")
5083 ui.write(repo.root + "\n")
5085
5084
5086 @command('^serve',
5085 @command('^serve',
5087 [('A', 'accesslog', '', _('name of access log file to write to'),
5086 [('A', 'accesslog', '', _('name of access log file to write to'),
5088 _('FILE')),
5087 _('FILE')),
5089 ('d', 'daemon', None, _('run server in background')),
5088 ('d', 'daemon', None, _('run server in background')),
5090 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5089 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5091 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5090 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5092 # use string type, then we can check if something was passed
5091 # use string type, then we can check if something was passed
5093 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5092 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5094 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5093 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5095 _('ADDR')),
5094 _('ADDR')),
5096 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5095 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5097 _('PREFIX')),
5096 _('PREFIX')),
5098 ('n', 'name', '',
5097 ('n', 'name', '',
5099 _('name to show in web pages (default: working directory)'), _('NAME')),
5098 _('name to show in web pages (default: working directory)'), _('NAME')),
5100 ('', 'web-conf', '',
5099 ('', 'web-conf', '',
5101 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5100 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5102 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5101 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5103 _('FILE')),
5102 _('FILE')),
5104 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5103 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5105 ('', 'stdio', None, _('for remote clients')),
5104 ('', 'stdio', None, _('for remote clients')),
5106 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5105 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5107 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5106 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5108 ('', 'style', '', _('template style to use'), _('STYLE')),
5107 ('', 'style', '', _('template style to use'), _('STYLE')),
5109 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5108 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5110 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5109 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5111 _('[OPTION]...'))
5110 _('[OPTION]...'))
5112 def serve(ui, repo, **opts):
5111 def serve(ui, repo, **opts):
5113 """start stand-alone webserver
5112 """start stand-alone webserver
5114
5113
5115 Start a local HTTP repository browser and pull server. You can use
5114 Start a local HTTP repository browser and pull server. You can use
5116 this for ad-hoc sharing and browsing of repositories. It is
5115 this for ad-hoc sharing and browsing of repositories. It is
5117 recommended to use a real web server to serve a repository for
5116 recommended to use a real web server to serve a repository for
5118 longer periods of time.
5117 longer periods of time.
5119
5118
5120 Please note that the server does not implement access control.
5119 Please note that the server does not implement access control.
5121 This means that, by default, anybody can read from the server and
5120 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``
5121 nobody can write to it by default. Set the ``web.allow_push``
5123 option to ``*`` to allow everybody to push to the server. You
5122 option to ``*`` to allow everybody to push to the server. You
5124 should use a real web server if you need to authenticate users.
5123 should use a real web server if you need to authenticate users.
5125
5124
5126 By default, the server logs accesses to stdout and errors to
5125 By default, the server logs accesses to stdout and errors to
5127 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5126 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5128 files.
5127 files.
5129
5128
5130 To have the server choose a free port number to listen on, specify
5129 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
5130 a port number of 0; in this case, the server will print the port
5132 number it uses.
5131 number it uses.
5133
5132
5134 Returns 0 on success.
5133 Returns 0 on success.
5135 """
5134 """
5136
5135
5137 if opts["stdio"] and opts["cmdserver"]:
5136 if opts["stdio"] and opts["cmdserver"]:
5138 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5137 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5139
5138
5140 def checkrepo():
5139 def checkrepo():
5141 if repo is None:
5140 if repo is None:
5142 raise error.RepoError(_("there is no Mercurial repository here"
5141 raise error.RepoError(_("there is no Mercurial repository here"
5143 " (.hg not found)"))
5142 " (.hg not found)"))
5144
5143
5145 if opts["stdio"]:
5144 if opts["stdio"]:
5146 checkrepo()
5145 checkrepo()
5147 s = sshserver.sshserver(ui, repo)
5146 s = sshserver.sshserver(ui, repo)
5148 s.serve_forever()
5147 s.serve_forever()
5149
5148
5150 if opts["cmdserver"]:
5149 if opts["cmdserver"]:
5151 checkrepo()
5150 checkrepo()
5152 s = commandserver.server(ui, repo, opts["cmdserver"])
5151 s = commandserver.server(ui, repo, opts["cmdserver"])
5153 return s.serve()
5152 return s.serve()
5154
5153
5155 # this way we can check if something was given in the command-line
5154 # this way we can check if something was given in the command-line
5156 if opts.get('port'):
5155 if opts.get('port'):
5157 opts['port'] = util.getport(opts.get('port'))
5156 opts['port'] = util.getport(opts.get('port'))
5158
5157
5159 baseui = repo and repo.baseui or ui
5158 baseui = repo and repo.baseui or ui
5160 optlist = ("name templates style address port prefix ipv6"
5159 optlist = ("name templates style address port prefix ipv6"
5161 " accesslog errorlog certificate encoding")
5160 " accesslog errorlog certificate encoding")
5162 for o in optlist.split():
5161 for o in optlist.split():
5163 val = opts.get(o, '')
5162 val = opts.get(o, '')
5164 if val in (None, ''): # should check against default options instead
5163 if val in (None, ''): # should check against default options instead
5165 continue
5164 continue
5166 baseui.setconfig("web", o, val)
5165 baseui.setconfig("web", o, val)
5167 if repo and repo.ui != baseui:
5166 if repo and repo.ui != baseui:
5168 repo.ui.setconfig("web", o, val)
5167 repo.ui.setconfig("web", o, val)
5169
5168
5170 o = opts.get('web_conf') or opts.get('webdir_conf')
5169 o = opts.get('web_conf') or opts.get('webdir_conf')
5171 if not o:
5170 if not o:
5172 if not repo:
5171 if not repo:
5173 raise error.RepoError(_("there is no Mercurial repository"
5172 raise error.RepoError(_("there is no Mercurial repository"
5174 " here (.hg not found)"))
5173 " here (.hg not found)"))
5175 o = repo
5174 o = repo
5176
5175
5177 app = hgweb.hgweb(o, baseui=baseui)
5176 app = hgweb.hgweb(o, baseui=baseui)
5178 service = httpservice(ui, app, opts)
5177 service = httpservice(ui, app, opts)
5179 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5178 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5180
5179
5181 class httpservice(object):
5180 class httpservice(object):
5182 def __init__(self, ui, app, opts):
5181 def __init__(self, ui, app, opts):
5183 self.ui = ui
5182 self.ui = ui
5184 self.app = app
5183 self.app = app
5185 self.opts = opts
5184 self.opts = opts
5186
5185
5187 def init(self):
5186 def init(self):
5188 util.setsignalhandler()
5187 util.setsignalhandler()
5189 self.httpd = hgweb_server.create_server(self.ui, self.app)
5188 self.httpd = hgweb_server.create_server(self.ui, self.app)
5190
5189
5191 if self.opts['port'] and not self.ui.verbose:
5190 if self.opts['port'] and not self.ui.verbose:
5192 return
5191 return
5193
5192
5194 if self.httpd.prefix:
5193 if self.httpd.prefix:
5195 prefix = self.httpd.prefix.strip('/') + '/'
5194 prefix = self.httpd.prefix.strip('/') + '/'
5196 else:
5195 else:
5197 prefix = ''
5196 prefix = ''
5198
5197
5199 port = ':%d' % self.httpd.port
5198 port = ':%d' % self.httpd.port
5200 if port == ':80':
5199 if port == ':80':
5201 port = ''
5200 port = ''
5202
5201
5203 bindaddr = self.httpd.addr
5202 bindaddr = self.httpd.addr
5204 if bindaddr == '0.0.0.0':
5203 if bindaddr == '0.0.0.0':
5205 bindaddr = '*'
5204 bindaddr = '*'
5206 elif ':' in bindaddr: # IPv6
5205 elif ':' in bindaddr: # IPv6
5207 bindaddr = '[%s]' % bindaddr
5206 bindaddr = '[%s]' % bindaddr
5208
5207
5209 fqaddr = self.httpd.fqaddr
5208 fqaddr = self.httpd.fqaddr
5210 if ':' in fqaddr:
5209 if ':' in fqaddr:
5211 fqaddr = '[%s]' % fqaddr
5210 fqaddr = '[%s]' % fqaddr
5212 if self.opts['port']:
5211 if self.opts['port']:
5213 write = self.ui.status
5212 write = self.ui.status
5214 else:
5213 else:
5215 write = self.ui.write
5214 write = self.ui.write
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5215 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5216 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5218
5217
5219 def run(self):
5218 def run(self):
5220 self.httpd.serve_forever()
5219 self.httpd.serve_forever()
5221
5220
5222
5221
5223 @command('showconfig|debugconfig',
5222 @command('showconfig|debugconfig',
5224 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5223 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5225 _('[-u] [NAME]...'))
5224 _('[-u] [NAME]...'))
5226 def showconfig(ui, repo, *values, **opts):
5225 def showconfig(ui, repo, *values, **opts):
5227 """show combined config settings from all hgrc files
5226 """show combined config settings from all hgrc files
5228
5227
5229 With no arguments, print names and values of all config items.
5228 With no arguments, print names and values of all config items.
5230
5229
5231 With one argument of the form section.name, print just the value
5230 With one argument of the form section.name, print just the value
5232 of that config item.
5231 of that config item.
5233
5232
5234 With multiple arguments, print names and values of all config
5233 With multiple arguments, print names and values of all config
5235 items with matching section names.
5234 items with matching section names.
5236
5235
5237 With --debug, the source (filename and line number) is printed
5236 With --debug, the source (filename and line number) is printed
5238 for each config item.
5237 for each config item.
5239
5238
5240 Returns 0 on success.
5239 Returns 0 on success.
5241 """
5240 """
5242
5241
5243 for f in scmutil.rcpath():
5242 for f in scmutil.rcpath():
5244 ui.debug('read config from: %s\n' % f)
5243 ui.debug('read config from: %s\n' % f)
5245 untrusted = bool(opts.get('untrusted'))
5244 untrusted = bool(opts.get('untrusted'))
5246 if values:
5245 if values:
5247 sections = [v for v in values if '.' not in v]
5246 sections = [v for v in values if '.' not in v]
5248 items = [v for v in values if '.' in v]
5247 items = [v for v in values if '.' in v]
5249 if len(items) > 1 or items and sections:
5248 if len(items) > 1 or items and sections:
5250 raise util.Abort(_('only one config item permitted'))
5249 raise util.Abort(_('only one config item permitted'))
5251 for section, name, value in ui.walkconfig(untrusted=untrusted):
5250 for section, name, value in ui.walkconfig(untrusted=untrusted):
5252 value = str(value).replace('\n', '\\n')
5251 value = str(value).replace('\n', '\\n')
5253 sectname = section + '.' + name
5252 sectname = section + '.' + name
5254 if values:
5253 if values:
5255 for v in values:
5254 for v in values:
5256 if v == section:
5255 if v == section:
5257 ui.debug('%s: ' %
5256 ui.debug('%s: ' %
5258 ui.configsource(section, name, untrusted))
5257 ui.configsource(section, name, untrusted))
5259 ui.write('%s=%s\n' % (sectname, value))
5258 ui.write('%s=%s\n' % (sectname, value))
5260 elif v == sectname:
5259 elif v == sectname:
5261 ui.debug('%s: ' %
5260 ui.debug('%s: ' %
5262 ui.configsource(section, name, untrusted))
5261 ui.configsource(section, name, untrusted))
5263 ui.write(value, '\n')
5262 ui.write(value, '\n')
5264 else:
5263 else:
5265 ui.debug('%s: ' %
5264 ui.debug('%s: ' %
5266 ui.configsource(section, name, untrusted))
5265 ui.configsource(section, name, untrusted))
5267 ui.write('%s=%s\n' % (sectname, value))
5266 ui.write('%s=%s\n' % (sectname, value))
5268
5267
5269 @command('^status|st',
5268 @command('^status|st',
5270 [('A', 'all', None, _('show status of all files')),
5269 [('A', 'all', None, _('show status of all files')),
5271 ('m', 'modified', None, _('show only modified files')),
5270 ('m', 'modified', None, _('show only modified files')),
5272 ('a', 'added', None, _('show only added files')),
5271 ('a', 'added', None, _('show only added files')),
5273 ('r', 'removed', None, _('show only removed files')),
5272 ('r', 'removed', None, _('show only removed files')),
5274 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5273 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5275 ('c', 'clean', None, _('show only files without changes')),
5274 ('c', 'clean', None, _('show only files without changes')),
5276 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5275 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5277 ('i', 'ignored', None, _('show only ignored files')),
5276 ('i', 'ignored', None, _('show only ignored files')),
5278 ('n', 'no-status', None, _('hide status prefix')),
5277 ('n', 'no-status', None, _('hide status prefix')),
5279 ('C', 'copies', None, _('show source of copied files')),
5278 ('C', 'copies', None, _('show source of copied files')),
5280 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5279 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5281 ('', 'rev', [], _('show difference from revision'), _('REV')),
5280 ('', 'rev', [], _('show difference from revision'), _('REV')),
5282 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5281 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5283 ] + walkopts + subrepoopts,
5282 ] + walkopts + subrepoopts,
5284 _('[OPTION]... [FILE]...'))
5283 _('[OPTION]... [FILE]...'))
5285 def status(ui, repo, *pats, **opts):
5284 def status(ui, repo, *pats, **opts):
5286 """show changed files in the working directory
5285 """show changed files in the working directory
5287
5286
5288 Show status of files in the repository. If names are given, only
5287 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
5288 files that match are shown. Files that are clean or ignored or
5290 the source of a copy/move operation, are not listed unless
5289 the source of a copy/move operation, are not listed unless
5291 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5290 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5292 Unless options described with "show only ..." are given, the
5291 Unless options described with "show only ..." are given, the
5293 options -mardu are used.
5292 options -mardu are used.
5294
5293
5295 Option -q/--quiet hides untracked (unknown and ignored) files
5294 Option -q/--quiet hides untracked (unknown and ignored) files
5296 unless explicitly requested with -u/--unknown or -i/--ignored.
5295 unless explicitly requested with -u/--unknown or -i/--ignored.
5297
5296
5298 .. note::
5297 .. note::
5299
5298
5300 status may appear to disagree with diff if permissions have
5299 status may appear to disagree with diff if permissions have
5301 changed or a merge has occurred. The standard diff format does
5300 changed or a merge has occurred. The standard diff format does
5302 not report permission changes and diff only reports changes
5301 not report permission changes and diff only reports changes
5303 relative to one merge parent.
5302 relative to one merge parent.
5304
5303
5305 If one revision is given, it is used as the base revision.
5304 If one revision is given, it is used as the base revision.
5306 If two revisions are given, the differences between them are
5305 If two revisions are given, the differences between them are
5307 shown. The --change option can also be used as a shortcut to list
5306 shown. The --change option can also be used as a shortcut to list
5308 the changed files of a revision from its first parent.
5307 the changed files of a revision from its first parent.
5309
5308
5310 The codes used to show the status of files are::
5309 The codes used to show the status of files are::
5311
5310
5312 M = modified
5311 M = modified
5313 A = added
5312 A = added
5314 R = removed
5313 R = removed
5315 C = clean
5314 C = clean
5316 ! = missing (deleted by non-hg command, but still tracked)
5315 ! = missing (deleted by non-hg command, but still tracked)
5317 ? = not tracked
5316 ? = not tracked
5318 I = ignored
5317 I = ignored
5319 = origin of the previous file listed as A (added)
5318 = origin of the previous file listed as A (added)
5320
5319
5321 .. container:: verbose
5320 .. container:: verbose
5322
5321
5323 Examples:
5322 Examples:
5324
5323
5325 - show changes in the working directory relative to a
5324 - show changes in the working directory relative to a
5326 changeset::
5325 changeset::
5327
5326
5328 hg status --rev 9353
5327 hg status --rev 9353
5329
5328
5330 - show all changes including copies in an existing changeset::
5329 - show all changes including copies in an existing changeset::
5331
5330
5332 hg status --copies --change 9353
5331 hg status --copies --change 9353
5333
5332
5334 - get a NUL separated list of added files, suitable for xargs::
5333 - get a NUL separated list of added files, suitable for xargs::
5335
5334
5336 hg status -an0
5335 hg status -an0
5337
5336
5338 Returns 0 on success.
5337 Returns 0 on success.
5339 """
5338 """
5340
5339
5341 revs = opts.get('rev')
5340 revs = opts.get('rev')
5342 change = opts.get('change')
5341 change = opts.get('change')
5343
5342
5344 if revs and change:
5343 if revs and change:
5345 msg = _('cannot specify --rev and --change at the same time')
5344 msg = _('cannot specify --rev and --change at the same time')
5346 raise util.Abort(msg)
5345 raise util.Abort(msg)
5347 elif change:
5346 elif change:
5348 node2 = scmutil.revsingle(repo, change, None).node()
5347 node2 = scmutil.revsingle(repo, change, None).node()
5349 node1 = repo[node2].p1().node()
5348 node1 = repo[node2].p1().node()
5350 else:
5349 else:
5351 node1, node2 = scmutil.revpair(repo, revs)
5350 node1, node2 = scmutil.revpair(repo, revs)
5352
5351
5353 cwd = (pats and repo.getcwd()) or ''
5352 cwd = (pats and repo.getcwd()) or ''
5354 end = opts.get('print0') and '\0' or '\n'
5353 end = opts.get('print0') and '\0' or '\n'
5355 copy = {}
5354 copy = {}
5356 states = 'modified added removed deleted unknown ignored clean'.split()
5355 states = 'modified added removed deleted unknown ignored clean'.split()
5357 show = [k for k in states if opts.get(k)]
5356 show = [k for k in states if opts.get(k)]
5358 if opts.get('all'):
5357 if opts.get('all'):
5359 show += ui.quiet and (states[:4] + ['clean']) or states
5358 show += ui.quiet and (states[:4] + ['clean']) or states
5360 if not show:
5359 if not show:
5361 show = ui.quiet and states[:4] or states[:5]
5360 show = ui.quiet and states[:4] or states[:5]
5362
5361
5363 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5362 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5364 'ignored' in show, 'clean' in show, 'unknown' in show,
5363 'ignored' in show, 'clean' in show, 'unknown' in show,
5365 opts.get('subrepos'))
5364 opts.get('subrepos'))
5366 changestates = zip(states, 'MAR!?IC', stat)
5365 changestates = zip(states, 'MAR!?IC', stat)
5367
5366
5368 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5367 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5369 copy = copies.pathcopies(repo[node1], repo[node2])
5368 copy = copies.pathcopies(repo[node1], repo[node2])
5370
5369
5371 fm = ui.formatter('status', opts)
5370 fm = ui.formatter('status', opts)
5372 fmt = '%s' + end
5371 fmt = '%s' + end
5373 showchar = not opts.get('no_status')
5372 showchar = not opts.get('no_status')
5374
5373
5375 for state, char, files in changestates:
5374 for state, char, files in changestates:
5376 if state in show:
5375 if state in show:
5377 label = 'status.' + state
5376 label = 'status.' + state
5378 for f in files:
5377 for f in files:
5379 fm.startitem()
5378 fm.startitem()
5380 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5379 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5381 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5380 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5382 if f in copy:
5381 if f in copy:
5383 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5382 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5384 label='status.copied')
5383 label='status.copied')
5385 fm.end()
5384 fm.end()
5386
5385
5387 @command('^summary|sum',
5386 @command('^summary|sum',
5388 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5387 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5389 def summary(ui, repo, **opts):
5388 def summary(ui, repo, **opts):
5390 """summarize working directory state
5389 """summarize working directory state
5391
5390
5392 This generates a brief summary of the working directory state,
5391 This generates a brief summary of the working directory state,
5393 including parents, branch, commit status, and available updates.
5392 including parents, branch, commit status, and available updates.
5394
5393
5395 With the --remote option, this will check the default paths for
5394 With the --remote option, this will check the default paths for
5396 incoming and outgoing changes. This can be time-consuming.
5395 incoming and outgoing changes. This can be time-consuming.
5397
5396
5398 Returns 0 on success.
5397 Returns 0 on success.
5399 """
5398 """
5400
5399
5401 ctx = repo[None]
5400 ctx = repo[None]
5402 parents = ctx.parents()
5401 parents = ctx.parents()
5403 pnode = parents[0].node()
5402 pnode = parents[0].node()
5404 marks = []
5403 marks = []
5405
5404
5406 for p in parents:
5405 for p in parents:
5407 # label with log.changeset (instead of log.parent) since this
5406 # label with log.changeset (instead of log.parent) since this
5408 # shows a working directory parent *changeset*:
5407 # shows a working directory parent *changeset*:
5409 # i18n: column positioning for "hg summary"
5408 # i18n: column positioning for "hg summary"
5410 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5409 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5411 label='log.changeset changeset.%s' % p.phasestr())
5410 label='log.changeset changeset.%s' % p.phasestr())
5412 ui.write(' '.join(p.tags()), label='log.tag')
5411 ui.write(' '.join(p.tags()), label='log.tag')
5413 if p.bookmarks():
5412 if p.bookmarks():
5414 marks.extend(p.bookmarks())
5413 marks.extend(p.bookmarks())
5415 if p.rev() == -1:
5414 if p.rev() == -1:
5416 if not len(repo):
5415 if not len(repo):
5417 ui.write(_(' (empty repository)'))
5416 ui.write(_(' (empty repository)'))
5418 else:
5417 else:
5419 ui.write(_(' (no revision checked out)'))
5418 ui.write(_(' (no revision checked out)'))
5420 ui.write('\n')
5419 ui.write('\n')
5421 if p.description():
5420 if p.description():
5422 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5421 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5423 label='log.summary')
5422 label='log.summary')
5424
5423
5425 branch = ctx.branch()
5424 branch = ctx.branch()
5426 bheads = repo.branchheads(branch)
5425 bheads = repo.branchheads(branch)
5427 # i18n: column positioning for "hg summary"
5426 # i18n: column positioning for "hg summary"
5428 m = _('branch: %s\n') % branch
5427 m = _('branch: %s\n') % branch
5429 if branch != 'default':
5428 if branch != 'default':
5430 ui.write(m, label='log.branch')
5429 ui.write(m, label='log.branch')
5431 else:
5430 else:
5432 ui.status(m, label='log.branch')
5431 ui.status(m, label='log.branch')
5433
5432
5434 if marks:
5433 if marks:
5435 current = repo._bookmarkcurrent
5434 current = repo._bookmarkcurrent
5436 # i18n: column positioning for "hg summary"
5435 # i18n: column positioning for "hg summary"
5437 ui.write(_('bookmarks:'), label='log.bookmark')
5436 ui.write(_('bookmarks:'), label='log.bookmark')
5438 if current is not None:
5437 if current is not None:
5439 if current in marks:
5438 if current in marks:
5440 ui.write(' *' + current, label='bookmarks.current')
5439 ui.write(' *' + current, label='bookmarks.current')
5441 marks.remove(current)
5440 marks.remove(current)
5442 else:
5441 else:
5443 ui.write(' [%s]' % current, label='bookmarks.current')
5442 ui.write(' [%s]' % current, label='bookmarks.current')
5444 for m in marks:
5443 for m in marks:
5445 ui.write(' ' + m, label='log.bookmark')
5444 ui.write(' ' + m, label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5445 ui.write('\n', label='log.bookmark')
5447
5446
5448 st = list(repo.status(unknown=True))[:6]
5447 st = list(repo.status(unknown=True))[:6]
5449
5448
5450 c = repo.dirstate.copies()
5449 c = repo.dirstate.copies()
5451 copied, renamed = [], []
5450 copied, renamed = [], []
5452 for d, s in c.iteritems():
5451 for d, s in c.iteritems():
5453 if s in st[2]:
5452 if s in st[2]:
5454 st[2].remove(s)
5453 st[2].remove(s)
5455 renamed.append(d)
5454 renamed.append(d)
5456 else:
5455 else:
5457 copied.append(d)
5456 copied.append(d)
5458 if d in st[1]:
5457 if d in st[1]:
5459 st[1].remove(d)
5458 st[1].remove(d)
5460 st.insert(3, renamed)
5459 st.insert(3, renamed)
5461 st.insert(4, copied)
5460 st.insert(4, copied)
5462
5461
5463 ms = mergemod.mergestate(repo)
5462 ms = mergemod.mergestate(repo)
5464 st.append([f for f in ms if ms[f] == 'u'])
5463 st.append([f for f in ms if ms[f] == 'u'])
5465
5464
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5465 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5467 st.append(subs)
5466 st.append(subs)
5468
5467
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5468 labels = [ui.label(_('%d modified'), 'status.modified'),
5470 ui.label(_('%d added'), 'status.added'),
5469 ui.label(_('%d added'), 'status.added'),
5471 ui.label(_('%d removed'), 'status.removed'),
5470 ui.label(_('%d removed'), 'status.removed'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5471 ui.label(_('%d renamed'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5472 ui.label(_('%d copied'), 'status.copied'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5473 ui.label(_('%d deleted'), 'status.deleted'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5474 ui.label(_('%d unknown'), 'status.unknown'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5475 ui.label(_('%d ignored'), 'status.ignored'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5476 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5478 ui.label(_('%d subrepos'), 'status.modified')]
5477 ui.label(_('%d subrepos'), 'status.modified')]
5479 t = []
5478 t = []
5480 for s, l in zip(st, labels):
5479 for s, l in zip(st, labels):
5481 if s:
5480 if s:
5482 t.append(l % len(s))
5481 t.append(l % len(s))
5483
5482
5484 t = ', '.join(t)
5483 t = ', '.join(t)
5485 cleanworkdir = False
5484 cleanworkdir = False
5486
5485
5487 if repo.vfs.exists('updatestate'):
5486 if repo.vfs.exists('updatestate'):
5488 t += _(' (interrupted update)')
5487 t += _(' (interrupted update)')
5489 elif len(parents) > 1:
5488 elif len(parents) > 1:
5490 t += _(' (merge)')
5489 t += _(' (merge)')
5491 elif branch != parents[0].branch():
5490 elif branch != parents[0].branch():
5492 t += _(' (new branch)')
5491 t += _(' (new branch)')
5493 elif (parents[0].closesbranch() and
5492 elif (parents[0].closesbranch() and
5494 pnode in repo.branchheads(branch, closed=True)):
5493 pnode in repo.branchheads(branch, closed=True)):
5495 t += _(' (head closed)')
5494 t += _(' (head closed)')
5496 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5495 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5497 t += _(' (clean)')
5496 t += _(' (clean)')
5498 cleanworkdir = True
5497 cleanworkdir = True
5499 elif pnode not in bheads:
5498 elif pnode not in bheads:
5500 t += _(' (new branch head)')
5499 t += _(' (new branch head)')
5501
5500
5502 if cleanworkdir:
5501 if cleanworkdir:
5503 # i18n: column positioning for "hg summary"
5502 # i18n: column positioning for "hg summary"
5504 ui.status(_('commit: %s\n') % t.strip())
5503 ui.status(_('commit: %s\n') % t.strip())
5505 else:
5504 else:
5506 # i18n: column positioning for "hg summary"
5505 # i18n: column positioning for "hg summary"
5507 ui.write(_('commit: %s\n') % t.strip())
5506 ui.write(_('commit: %s\n') % t.strip())
5508
5507
5509 # all ancestors of branch heads - all ancestors of parent = new csets
5508 # all ancestors of branch heads - all ancestors of parent = new csets
5510 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5509 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5511 bheads))
5510 bheads))
5512
5511
5513 if new == 0:
5512 if new == 0:
5514 # i18n: column positioning for "hg summary"
5513 # i18n: column positioning for "hg summary"
5515 ui.status(_('update: (current)\n'))
5514 ui.status(_('update: (current)\n'))
5516 elif pnode not in bheads:
5515 elif pnode not in bheads:
5517 # i18n: column positioning for "hg summary"
5516 # i18n: column positioning for "hg summary"
5518 ui.write(_('update: %d new changesets (update)\n') % new)
5517 ui.write(_('update: %d new changesets (update)\n') % new)
5519 else:
5518 else:
5520 # i18n: column positioning for "hg summary"
5519 # i18n: column positioning for "hg summary"
5521 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5520 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5522 (new, len(bheads)))
5521 (new, len(bheads)))
5523
5522
5524 cmdutil.summaryhooks(ui, repo)
5523 cmdutil.summaryhooks(ui, repo)
5525
5524
5526 if opts.get('remote'):
5525 if opts.get('remote'):
5527 t = []
5526 t = []
5528 source, branches = hg.parseurl(ui.expandpath('default'))
5527 source, branches = hg.parseurl(ui.expandpath('default'))
5529 sbranch = branches[0]
5528 sbranch = branches[0]
5530 other = hg.peer(repo, {}, source)
5529 other = hg.peer(repo, {}, source)
5531 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5530 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5532 if revs:
5531 if revs:
5533 revs = [other.lookup(rev) for rev in revs]
5532 revs = [other.lookup(rev) for rev in revs]
5534 ui.debug('comparing with %s\n' % util.hidepassword(source))
5533 ui.debug('comparing with %s\n' % util.hidepassword(source))
5535 repo.ui.pushbuffer()
5534 repo.ui.pushbuffer()
5536 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5535 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5537 _common, incoming, _rheads = commoninc
5536 _common, incoming, _rheads = commoninc
5538 repo.ui.popbuffer()
5537 repo.ui.popbuffer()
5539 if incoming:
5538 if incoming:
5540 t.append(_('1 or more incoming'))
5539 t.append(_('1 or more incoming'))
5541
5540
5542 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5541 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5543 dbranch = branches[0]
5542 dbranch = branches[0]
5544 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5543 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5545 if source != dest:
5544 if source != dest:
5546 other = hg.peer(repo, {}, dest)
5545 other = hg.peer(repo, {}, dest)
5547 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5546 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5548 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5547 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5549 commoninc = None
5548 commoninc = None
5550 if revs:
5549 if revs:
5551 revs = [repo.lookup(rev) for rev in revs]
5550 revs = [repo.lookup(rev) for rev in revs]
5552 repo.ui.pushbuffer()
5551 repo.ui.pushbuffer()
5553 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5552 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5554 commoninc=commoninc)
5553 commoninc=commoninc)
5555 repo.ui.popbuffer()
5554 repo.ui.popbuffer()
5556 o = outgoing.missing
5555 o = outgoing.missing
5557 if o:
5556 if o:
5558 t.append(_('%d outgoing') % len(o))
5557 t.append(_('%d outgoing') % len(o))
5559 if 'bookmarks' in other.listkeys('namespaces'):
5558 if 'bookmarks' in other.listkeys('namespaces'):
5560 lmarks = repo.listkeys('bookmarks')
5559 lmarks = repo.listkeys('bookmarks')
5561 rmarks = other.listkeys('bookmarks')
5560 rmarks = other.listkeys('bookmarks')
5562 diff = set(rmarks) - set(lmarks)
5561 diff = set(rmarks) - set(lmarks)
5563 if len(diff) > 0:
5562 if len(diff) > 0:
5564 t.append(_('%d incoming bookmarks') % len(diff))
5563 t.append(_('%d incoming bookmarks') % len(diff))
5565 diff = set(lmarks) - set(rmarks)
5564 diff = set(lmarks) - set(rmarks)
5566 if len(diff) > 0:
5565 if len(diff) > 0:
5567 t.append(_('%d outgoing bookmarks') % len(diff))
5566 t.append(_('%d outgoing bookmarks') % len(diff))
5568
5567
5569 if t:
5568 if t:
5570 # i18n: column positioning for "hg summary"
5569 # i18n: column positioning for "hg summary"
5571 ui.write(_('remote: %s\n') % (', '.join(t)))
5570 ui.write(_('remote: %s\n') % (', '.join(t)))
5572 else:
5571 else:
5573 # i18n: column positioning for "hg summary"
5572 # i18n: column positioning for "hg summary"
5574 ui.status(_('remote: (synced)\n'))
5573 ui.status(_('remote: (synced)\n'))
5575
5574
5576 @command('tag',
5575 @command('tag',
5577 [('f', 'force', None, _('force tag')),
5576 [('f', 'force', None, _('force tag')),
5578 ('l', 'local', None, _('make the tag local')),
5577 ('l', 'local', None, _('make the tag local')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5578 ('r', 'rev', '', _('revision to tag'), _('REV')),
5580 ('', 'remove', None, _('remove a tag')),
5579 ('', 'remove', None, _('remove a tag')),
5581 # -l/--local is already there, commitopts cannot be used
5580 # -l/--local is already there, commitopts cannot be used
5582 ('e', 'edit', None, _('edit commit message')),
5581 ('e', 'edit', None, _('edit commit message')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5582 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5584 ] + commitopts2,
5583 ] + commitopts2,
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5584 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5586 def tag(ui, repo, name1, *names, **opts):
5585 def tag(ui, repo, name1, *names, **opts):
5587 """add one or more tags for the current or given revision
5586 """add one or more tags for the current or given revision
5588
5587
5589 Name a particular revision using <name>.
5588 Name a particular revision using <name>.
5590
5589
5591 Tags are used to name particular revisions of the repository and are
5590 Tags are used to name particular revisions of the repository and are
5592 very useful to compare different revisions, to go back to significant
5591 very useful to compare different revisions, to go back to significant
5593 earlier versions or to mark branch points as releases, etc. Changing
5592 earlier versions or to mark branch points as releases, etc. Changing
5594 an existing tag is normally disallowed; use -f/--force to override.
5593 an existing tag is normally disallowed; use -f/--force to override.
5595
5594
5596 If no revision is given, the parent of the working directory is
5595 If no revision is given, the parent of the working directory is
5597 used.
5596 used.
5598
5597
5599 To facilitate version control, distribution, and merging of tags,
5598 To facilitate version control, distribution, and merging of tags,
5600 they are stored as a file named ".hgtags" which is managed similarly
5599 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
5600 to other project files and can be hand-edited if necessary. This
5602 also means that tagging creates a new commit. The file
5601 also means that tagging creates a new commit. The file
5603 ".hg/localtags" is used for local tags (not shared among
5602 ".hg/localtags" is used for local tags (not shared among
5604 repositories).
5603 repositories).
5605
5604
5606 Tag commits are usually made at the head of a branch. If the parent
5605 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
5606 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
5607 -f/--force to force the tag commit to be based on a non-head
5609 changeset.
5608 changeset.
5610
5609
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5610 See :hg:`help dates` for a list of formats valid for -d/--date.
5612
5611
5613 Since tag names have priority over branch names during revision
5612 Since tag names have priority over branch names during revision
5614 lookup, using an existing branch name as a tag name is discouraged.
5613 lookup, using an existing branch name as a tag name is discouraged.
5615
5614
5616 Returns 0 on success.
5615 Returns 0 on success.
5617 """
5616 """
5618 wlock = lock = None
5617 wlock = lock = None
5619 try:
5618 try:
5620 wlock = repo.wlock()
5619 wlock = repo.wlock()
5621 lock = repo.lock()
5620 lock = repo.lock()
5622 rev_ = "."
5621 rev_ = "."
5623 names = [t.strip() for t in (name1,) + names]
5622 names = [t.strip() for t in (name1,) + names]
5624 if len(names) != len(set(names)):
5623 if len(names) != len(set(names)):
5625 raise util.Abort(_('tag names must be unique'))
5624 raise util.Abort(_('tag names must be unique'))
5626 for n in names:
5625 for n in names:
5627 scmutil.checknewlabel(repo, n, 'tag')
5626 scmutil.checknewlabel(repo, n, 'tag')
5628 if not n:
5627 if not n:
5629 raise util.Abort(_('tag names cannot consist entirely of '
5628 raise util.Abort(_('tag names cannot consist entirely of '
5630 'whitespace'))
5629 'whitespace'))
5631 if opts.get('rev') and opts.get('remove'):
5630 if opts.get('rev') and opts.get('remove'):
5632 raise util.Abort(_("--rev and --remove are incompatible"))
5631 raise util.Abort(_("--rev and --remove are incompatible"))
5633 if opts.get('rev'):
5632 if opts.get('rev'):
5634 rev_ = opts['rev']
5633 rev_ = opts['rev']
5635 message = opts.get('message')
5634 message = opts.get('message')
5636 if opts.get('remove'):
5635 if opts.get('remove'):
5637 expectedtype = opts.get('local') and 'local' or 'global'
5636 expectedtype = opts.get('local') and 'local' or 'global'
5638 for n in names:
5637 for n in names:
5639 if not repo.tagtype(n):
5638 if not repo.tagtype(n):
5640 raise util.Abort(_("tag '%s' does not exist") % n)
5639 raise util.Abort(_("tag '%s' does not exist") % n)
5641 if repo.tagtype(n) != expectedtype:
5640 if repo.tagtype(n) != expectedtype:
5642 if expectedtype == 'global':
5641 if expectedtype == 'global':
5643 raise util.Abort(_("tag '%s' is not a global tag") % n)
5642 raise util.Abort(_("tag '%s' is not a global tag") % n)
5644 else:
5643 else:
5645 raise util.Abort(_("tag '%s' is not a local tag") % n)
5644 raise util.Abort(_("tag '%s' is not a local tag") % n)
5646 rev_ = nullid
5645 rev_ = nullid
5647 if not message:
5646 if not message:
5648 # we don't translate commit messages
5647 # we don't translate commit messages
5649 message = 'Removed tag %s' % ', '.join(names)
5648 message = 'Removed tag %s' % ', '.join(names)
5650 elif not opts.get('force'):
5649 elif not opts.get('force'):
5651 for n in names:
5650 for n in names:
5652 if n in repo.tags():
5651 if n in repo.tags():
5653 raise util.Abort(_("tag '%s' already exists "
5652 raise util.Abort(_("tag '%s' already exists "
5654 "(use -f to force)") % n)
5653 "(use -f to force)") % n)
5655 if not opts.get('local'):
5654 if not opts.get('local'):
5656 p1, p2 = repo.dirstate.parents()
5655 p1, p2 = repo.dirstate.parents()
5657 if p2 != nullid:
5656 if p2 != nullid:
5658 raise util.Abort(_('uncommitted merge'))
5657 raise util.Abort(_('uncommitted merge'))
5659 bheads = repo.branchheads()
5658 bheads = repo.branchheads()
5660 if not opts.get('force') and bheads and p1 not in bheads:
5659 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)'))
5660 raise util.Abort(_('not at a branch head (use -f to force)'))
5662 r = scmutil.revsingle(repo, rev_).node()
5661 r = scmutil.revsingle(repo, rev_).node()
5663
5662
5664 if not message:
5663 if not message:
5665 # we don't translate commit messages
5664 # we don't translate commit messages
5666 message = ('Added tag %s for changeset %s' %
5665 message = ('Added tag %s for changeset %s' %
5667 (', '.join(names), short(r)))
5666 (', '.join(names), short(r)))
5668
5667
5669 date = opts.get('date')
5668 date = opts.get('date')
5670 if date:
5669 if date:
5671 date = util.parsedate(date)
5670 date = util.parsedate(date)
5672
5671
5673 if opts.get('edit'):
5672 if opts.get('edit'):
5674 message = ui.edit(message, ui.username())
5673 message = ui.edit(message, ui.username())
5675
5674
5676 # don't allow tagging the null rev
5675 # don't allow tagging the null rev
5677 if (not opts.get('remove') and
5676 if (not opts.get('remove') and
5678 scmutil.revsingle(repo, rev_).rev() == nullrev):
5677 scmutil.revsingle(repo, rev_).rev() == nullrev):
5679 raise util.Abort(_("cannot tag null revision"))
5678 raise util.Abort(_("cannot tag null revision"))
5680
5679
5681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5680 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5682 finally:
5681 finally:
5683 release(lock, wlock)
5682 release(lock, wlock)
5684
5683
5685 @command('tags', [], '')
5684 @command('tags', [], '')
5686 def tags(ui, repo, **opts):
5685 def tags(ui, repo, **opts):
5687 """list repository tags
5686 """list repository tags
5688
5687
5689 This lists both regular and local tags. When the -v/--verbose
5688 This lists both regular and local tags. When the -v/--verbose
5690 switch is used, a third column "local" is printed for local tags.
5689 switch is used, a third column "local" is printed for local tags.
5691
5690
5692 Returns 0 on success.
5691 Returns 0 on success.
5693 """
5692 """
5694
5693
5695 fm = ui.formatter('tags', opts)
5694 fm = ui.formatter('tags', opts)
5696 hexfunc = ui.debugflag and hex or short
5695 hexfunc = ui.debugflag and hex or short
5697 tagtype = ""
5696 tagtype = ""
5698
5697
5699 for t, n in reversed(repo.tagslist()):
5698 for t, n in reversed(repo.tagslist()):
5700 hn = hexfunc(n)
5699 hn = hexfunc(n)
5701 label = 'tags.normal'
5700 label = 'tags.normal'
5702 tagtype = ''
5701 tagtype = ''
5703 if repo.tagtype(t) == 'local':
5702 if repo.tagtype(t) == 'local':
5704 label = 'tags.local'
5703 label = 'tags.local'
5705 tagtype = 'local'
5704 tagtype = 'local'
5706
5705
5707 fm.startitem()
5706 fm.startitem()
5708 fm.write('tag', '%s', t, label=label)
5707 fm.write('tag', '%s', t, label=label)
5709 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5708 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5710 fm.condwrite(not ui.quiet, 'rev id', fmt,
5709 fm.condwrite(not ui.quiet, 'rev id', fmt,
5711 repo.changelog.rev(n), hn, label=label)
5710 repo.changelog.rev(n), hn, label=label)
5712 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5711 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5713 tagtype, label=label)
5712 tagtype, label=label)
5714 fm.plain('\n')
5713 fm.plain('\n')
5715 fm.end()
5714 fm.end()
5716
5715
5717 @command('tip',
5716 @command('tip',
5718 [('p', 'patch', None, _('show patch')),
5717 [('p', 'patch', None, _('show patch')),
5719 ('g', 'git', None, _('use git extended diff format')),
5718 ('g', 'git', None, _('use git extended diff format')),
5720 ] + templateopts,
5719 ] + templateopts,
5721 _('[-p] [-g]'))
5720 _('[-p] [-g]'))
5722 def tip(ui, repo, **opts):
5721 def tip(ui, repo, **opts):
5723 """show the tip revision (DEPRECATED)
5722 """show the tip revision (DEPRECATED)
5724
5723
5725 The tip revision (usually just called the tip) is the changeset
5724 The tip revision (usually just called the tip) is the changeset
5726 most recently added to the repository (and therefore the most
5725 most recently added to the repository (and therefore the most
5727 recently changed head).
5726 recently changed head).
5728
5727
5729 If you have just made a commit, that commit will be the tip. If
5728 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
5729 you have just pulled changes from another repository, the tip of
5731 that repository becomes the current tip. The "tip" tag is special
5730 that repository becomes the current tip. The "tip" tag is special
5732 and cannot be renamed or assigned to a different changeset.
5731 and cannot be renamed or assigned to a different changeset.
5733
5732
5734 This command is deprecated, please use :hg:`heads` instead.
5733 This command is deprecated, please use :hg:`heads` instead.
5735
5734
5736 Returns 0 on success.
5735 Returns 0 on success.
5737 """
5736 """
5738 displayer = cmdutil.show_changeset(ui, repo, opts)
5737 displayer = cmdutil.show_changeset(ui, repo, opts)
5739 displayer.show(repo['tip'])
5738 displayer.show(repo['tip'])
5740 displayer.close()
5739 displayer.close()
5741
5740
5742 @command('unbundle',
5741 @command('unbundle',
5743 [('u', 'update', None,
5742 [('u', 'update', None,
5744 _('update to new branch head if changesets were unbundled'))],
5743 _('update to new branch head if changesets were unbundled'))],
5745 _('[-u] FILE...'))
5744 _('[-u] FILE...'))
5746 def unbundle(ui, repo, fname1, *fnames, **opts):
5745 def unbundle(ui, repo, fname1, *fnames, **opts):
5747 """apply one or more changegroup files
5746 """apply one or more changegroup files
5748
5747
5749 Apply one or more compressed changegroup files generated by the
5748 Apply one or more compressed changegroup files generated by the
5750 bundle command.
5749 bundle command.
5751
5750
5752 Returns 0 on success, 1 if an update has unresolved files.
5751 Returns 0 on success, 1 if an update has unresolved files.
5753 """
5752 """
5754 fnames = (fname1,) + fnames
5753 fnames = (fname1,) + fnames
5755
5754
5756 lock = repo.lock()
5755 lock = repo.lock()
5757 wc = repo['.']
5756 wc = repo['.']
5758 try:
5757 try:
5759 for fname in fnames:
5758 for fname in fnames:
5760 f = hg.openpath(ui, fname)
5759 f = hg.openpath(ui, fname)
5761 gen = changegroup.readbundle(f, fname)
5760 gen = changegroup.readbundle(f, fname)
5762 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5761 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5763 finally:
5762 finally:
5764 lock.release()
5763 lock.release()
5765 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5764 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5766 return postincoming(ui, repo, modheads, opts.get('update'), None)
5765 return postincoming(ui, repo, modheads, opts.get('update'), None)
5767
5766
5768 @command('^update|up|checkout|co',
5767 @command('^update|up|checkout|co',
5769 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5768 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5770 ('c', 'check', None,
5769 ('c', 'check', None,
5771 _('update across branches if no uncommitted changes')),
5770 _('update across branches if no uncommitted changes')),
5772 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5771 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5773 ('r', 'rev', '', _('revision'), _('REV'))],
5772 ('r', 'rev', '', _('revision'), _('REV'))],
5774 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5773 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5775 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5774 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5776 """update working directory (or switch revisions)
5775 """update working directory (or switch revisions)
5777
5776
5778 Update the repository's working directory to the specified
5777 Update the repository's working directory to the specified
5779 changeset. If no changeset is specified, update to the tip of the
5778 changeset. If no changeset is specified, update to the tip of the
5780 current named branch and move the current bookmark (see :hg:`help
5779 current named branch and move the current bookmark (see :hg:`help
5781 bookmarks`).
5780 bookmarks`).
5782
5781
5783 Update sets the working directory's parent revision to the specified
5782 Update sets the working directory's parent revision to the specified
5784 changeset (see :hg:`help parents`).
5783 changeset (see :hg:`help parents`).
5785
5784
5786 If the changeset is not a descendant or ancestor of the working
5785 If the changeset is not a descendant or ancestor of the working
5787 directory's parent, the update is aborted. With the -c/--check
5786 directory's parent, the update is aborted. With the -c/--check
5788 option, the working directory is checked for uncommitted changes; if
5787 option, the working directory is checked for uncommitted changes; if
5789 none are found, the working directory is updated to the specified
5788 none are found, the working directory is updated to the specified
5790 changeset.
5789 changeset.
5791
5790
5792 .. container:: verbose
5791 .. container:: verbose
5793
5792
5794 The following rules apply when the working directory contains
5793 The following rules apply when the working directory contains
5795 uncommitted changes:
5794 uncommitted changes:
5796
5795
5797 1. If neither -c/--check nor -C/--clean is specified, and if
5796 1. If neither -c/--check nor -C/--clean is specified, and if
5798 the requested changeset is an ancestor or descendant of
5797 the requested changeset is an ancestor or descendant of
5799 the working directory's parent, the uncommitted changes
5798 the working directory's parent, the uncommitted changes
5800 are merged into the requested changeset and the merged
5799 are merged into the requested changeset and the merged
5801 result is left uncommitted. If the requested changeset is
5800 result is left uncommitted. If the requested changeset is
5802 not an ancestor or descendant (that is, it is on another
5801 not an ancestor or descendant (that is, it is on another
5803 branch), the update is aborted and the uncommitted changes
5802 branch), the update is aborted and the uncommitted changes
5804 are preserved.
5803 are preserved.
5805
5804
5806 2. With the -c/--check option, the update is aborted and the
5805 2. With the -c/--check option, the update is aborted and the
5807 uncommitted changes are preserved.
5806 uncommitted changes are preserved.
5808
5807
5809 3. With the -C/--clean option, uncommitted changes are discarded and
5808 3. With the -C/--clean option, uncommitted changes are discarded and
5810 the working directory is updated to the requested changeset.
5809 the working directory is updated to the requested changeset.
5811
5810
5812 To cancel an uncommitted merge (and lose your changes), use
5811 To cancel an uncommitted merge (and lose your changes), use
5813 :hg:`update --clean .`.
5812 :hg:`update --clean .`.
5814
5813
5815 Use null as the changeset to remove the working directory (like
5814 Use null as the changeset to remove the working directory (like
5816 :hg:`clone -U`).
5815 :hg:`clone -U`).
5817
5816
5818 If you want to revert just one file to an older revision, use
5817 If you want to revert just one file to an older revision, use
5819 :hg:`revert [-r REV] NAME`.
5818 :hg:`revert [-r REV] NAME`.
5820
5819
5821 See :hg:`help dates` for a list of formats valid for -d/--date.
5820 See :hg:`help dates` for a list of formats valid for -d/--date.
5822
5821
5823 Returns 0 on success, 1 if there are unresolved files.
5822 Returns 0 on success, 1 if there are unresolved files.
5824 """
5823 """
5825 if rev and node:
5824 if rev and node:
5826 raise util.Abort(_("please specify just one revision"))
5825 raise util.Abort(_("please specify just one revision"))
5827
5826
5828 if rev is None or rev == '':
5827 if rev is None or rev == '':
5829 rev = node
5828 rev = node
5830
5829
5831 cmdutil.clearunfinished(repo)
5830 cmdutil.clearunfinished(repo)
5832
5831
5833 # with no argument, we also move the current bookmark, if any
5832 # with no argument, we also move the current bookmark, if any
5834 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5833 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5835
5834
5836 # if we defined a bookmark, we have to remember the original bookmark name
5835 # if we defined a bookmark, we have to remember the original bookmark name
5837 brev = rev
5836 brev = rev
5838 rev = scmutil.revsingle(repo, rev, rev).rev()
5837 rev = scmutil.revsingle(repo, rev, rev).rev()
5839
5838
5840 if check and clean:
5839 if check and clean:
5841 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5840 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5842
5841
5843 if date:
5842 if date:
5844 if rev is not None:
5843 if rev is not None:
5845 raise util.Abort(_("you can't specify a revision and a date"))
5844 raise util.Abort(_("you can't specify a revision and a date"))
5846 rev = cmdutil.finddate(ui, repo, date)
5845 rev = cmdutil.finddate(ui, repo, date)
5847
5846
5848 if check:
5847 if check:
5849 c = repo[None]
5848 c = repo[None]
5850 if c.dirty(merge=False, branch=False, missing=True):
5849 if c.dirty(merge=False, branch=False, missing=True):
5851 raise util.Abort(_("uncommitted changes"))
5850 raise util.Abort(_("uncommitted changes"))
5852 if rev is None:
5851 if rev is None:
5853 rev = repo[repo[None].branch()].rev()
5852 rev = repo[repo[None].branch()].rev()
5854 mergemod._checkunknown(repo, repo[None], repo[rev])
5853 mergemod._checkunknown(repo, repo[None], repo[rev])
5855
5854
5856 if clean:
5855 if clean:
5857 ret = hg.clean(repo, rev)
5856 ret = hg.clean(repo, rev)
5858 else:
5857 else:
5859 ret = hg.update(repo, rev)
5858 ret = hg.update(repo, rev)
5860
5859
5861 if not ret and movemarkfrom:
5860 if not ret and movemarkfrom:
5862 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5861 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5863 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5862 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5864 elif brev in repo._bookmarks:
5863 elif brev in repo._bookmarks:
5865 bookmarks.setcurrent(repo, brev)
5864 bookmarks.setcurrent(repo, brev)
5866 elif brev:
5865 elif brev:
5867 bookmarks.unsetcurrent(repo)
5866 bookmarks.unsetcurrent(repo)
5868
5867
5869 return ret
5868 return ret
5870
5869
5871 @command('verify', [])
5870 @command('verify', [])
5872 def verify(ui, repo):
5871 def verify(ui, repo):
5873 """verify the integrity of the repository
5872 """verify the integrity of the repository
5874
5873
5875 Verify the integrity of the current repository.
5874 Verify the integrity of the current repository.
5876
5875
5877 This will perform an extensive check of the repository's
5876 This will perform an extensive check of the repository's
5878 integrity, validating the hashes and checksums of each entry in
5877 integrity, validating the hashes and checksums of each entry in
5879 the changelog, manifest, and tracked files, as well as the
5878 the changelog, manifest, and tracked files, as well as the
5880 integrity of their crosslinks and indices.
5879 integrity of their crosslinks and indices.
5881
5880
5882 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5881 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5883 for more information about recovery from corruption of the
5882 for more information about recovery from corruption of the
5884 repository.
5883 repository.
5885
5884
5886 Returns 0 on success, 1 if errors are encountered.
5885 Returns 0 on success, 1 if errors are encountered.
5887 """
5886 """
5888 return hg.verify(repo)
5887 return hg.verify(repo)
5889
5888
5890 @command('version', [])
5889 @command('version', [])
5891 def version_(ui):
5890 def version_(ui):
5892 """output version and copyright information"""
5891 """output version and copyright information"""
5893 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5892 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5894 % util.version())
5893 % util.version())
5895 ui.status(_(
5894 ui.status(_(
5896 "(see http://mercurial.selenic.com for more information)\n"
5895 "(see http://mercurial.selenic.com for more information)\n"
5897 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5896 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5898 "This is free software; see the source for copying conditions. "
5897 "This is free software; see the source for copying conditions. "
5899 "There is NO\nwarranty; "
5898 "There is NO\nwarranty; "
5900 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5899 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5901 ))
5900 ))
5902
5901
5903 norepo = ("clone init version help debugcommands debugcomplete"
5902 norepo = ("clone init version help debugcommands debugcomplete"
5904 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5903 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5905 " debugknown debuggetbundle debugbundle")
5904 " debugknown debuggetbundle debugbundle")
5906 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5905 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5907 " debugdata debugindex debugindexdot debugrevlog")
5906 " debugdata debugindex debugindexdot debugrevlog")
5908 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5907 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5909 " remove resolve status debugwalk")
5908 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now