##// END OF EJS Templates
pull: for pull --update with failed update, print hint if any...
Siddharth Agarwal -
r19797:a9abdb16 default
parent child Browse files
Show More
@@ -1,5909 +1,5911 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, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import phases, obsolete
21 import phases, obsolete
22
22
23 table = {}
23 table = {}
24
24
25 command = cmdutil.command(table)
25 command = cmdutil.command(table)
26
26
27 # common command options
27 # common command options
28
28
29 globalopts = [
29 globalopts = [
30 ('R', 'repository', '',
30 ('R', 'repository', '',
31 _('repository root directory or name of overlay bundle file'),
31 _('repository root directory or name of overlay bundle file'),
32 _('REPO')),
32 _('REPO')),
33 ('', 'cwd', '',
33 ('', 'cwd', '',
34 _('change working directory'), _('DIR')),
34 _('change working directory'), _('DIR')),
35 ('y', 'noninteractive', None,
35 ('y', 'noninteractive', None,
36 _('do not prompt, automatically pick the first choice for all prompts')),
36 _('do not prompt, automatically pick the first choice for all prompts')),
37 ('q', 'quiet', None, _('suppress output')),
37 ('q', 'quiet', None, _('suppress output')),
38 ('v', 'verbose', None, _('enable additional output')),
38 ('v', 'verbose', None, _('enable additional output')),
39 ('', 'config', [],
39 ('', 'config', [],
40 _('set/override config option (use \'section.name=value\')'),
40 _('set/override config option (use \'section.name=value\')'),
41 _('CONFIG')),
41 _('CONFIG')),
42 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debugger', None, _('start debugger')),
43 ('', 'debugger', None, _('start debugger')),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 _('ENCODE')),
45 _('ENCODE')),
46 ('', 'encodingmode', encoding.encodingmode,
46 ('', 'encodingmode', encoding.encodingmode,
47 _('set the charset encoding mode'), _('MODE')),
47 _('set the charset encoding mode'), _('MODE')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'time', None, _('time how long the command takes')),
49 ('', 'time', None, _('time how long the command takes')),
50 ('', 'profile', None, _('print command execution profile')),
50 ('', 'profile', None, _('print command execution profile')),
51 ('', 'version', None, _('output version information and exit')),
51 ('', 'version', None, _('output version information and exit')),
52 ('h', 'help', None, _('display help and exit')),
52 ('h', 'help', None, _('display help and exit')),
53 ('', 'hidden', False, _('consider hidden changesets')),
53 ('', 'hidden', False, _('consider hidden changesets')),
54 ]
54 ]
55
55
56 dryrunopts = [('n', 'dry-run', None,
56 dryrunopts = [('n', 'dry-run', None,
57 _('do not perform actions, just print output'))]
57 _('do not perform actions, just print output'))]
58
58
59 remoteopts = [
59 remoteopts = [
60 ('e', 'ssh', '',
60 ('e', 'ssh', '',
61 _('specify ssh command to use'), _('CMD')),
61 _('specify ssh command to use'), _('CMD')),
62 ('', 'remotecmd', '',
62 ('', 'remotecmd', '',
63 _('specify hg command to run on the remote side'), _('CMD')),
63 _('specify hg command to run on the remote side'), _('CMD')),
64 ('', 'insecure', None,
64 ('', 'insecure', None,
65 _('do not verify server certificate (ignoring web.cacerts config)')),
65 _('do not verify server certificate (ignoring web.cacerts config)')),
66 ]
66 ]
67
67
68 walkopts = [
68 walkopts = [
69 ('I', 'include', [],
69 ('I', 'include', [],
70 _('include names matching the given patterns'), _('PATTERN')),
70 _('include names matching the given patterns'), _('PATTERN')),
71 ('X', 'exclude', [],
71 ('X', 'exclude', [],
72 _('exclude names matching the given patterns'), _('PATTERN')),
72 _('exclude names matching the given patterns'), _('PATTERN')),
73 ]
73 ]
74
74
75 commitopts = [
75 commitopts = [
76 ('m', 'message', '',
76 ('m', 'message', '',
77 _('use text as commit message'), _('TEXT')),
77 _('use text as commit message'), _('TEXT')),
78 ('l', 'logfile', '',
78 ('l', 'logfile', '',
79 _('read commit message from file'), _('FILE')),
79 _('read commit message from file'), _('FILE')),
80 ]
80 ]
81
81
82 commitopts2 = [
82 commitopts2 = [
83 ('d', 'date', '',
83 ('d', 'date', '',
84 _('record the specified date as commit date'), _('DATE')),
84 _('record the specified date as commit date'), _('DATE')),
85 ('u', 'user', '',
85 ('u', 'user', '',
86 _('record the specified user as committer'), _('USER')),
86 _('record the specified user as committer'), _('USER')),
87 ]
87 ]
88
88
89 templateopts = [
89 templateopts = [
90 ('', 'style', '',
90 ('', 'style', '',
91 _('display using template map file'), _('STYLE')),
91 _('display using template map file'), _('STYLE')),
92 ('', 'template', '',
92 ('', 'template', '',
93 _('display with template'), _('TEMPLATE')),
93 _('display with template'), _('TEMPLATE')),
94 ]
94 ]
95
95
96 logopts = [
96 logopts = [
97 ('p', 'patch', None, _('show patch')),
97 ('p', 'patch', None, _('show patch')),
98 ('g', 'git', None, _('use git extended diff format')),
98 ('g', 'git', None, _('use git extended diff format')),
99 ('l', 'limit', '',
99 ('l', 'limit', '',
100 _('limit number of changes displayed'), _('NUM')),
100 _('limit number of changes displayed'), _('NUM')),
101 ('M', 'no-merges', None, _('do not show merges')),
101 ('M', 'no-merges', None, _('do not show merges')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('G', 'graph', None, _("show the revision DAG")),
103 ('G', 'graph', None, _("show the revision DAG")),
104 ] + templateopts
104 ] + templateopts
105
105
106 diffopts = [
106 diffopts = [
107 ('a', 'text', None, _('treat all files as text')),
107 ('a', 'text', None, _('treat all files as text')),
108 ('g', 'git', None, _('use git extended diff format')),
108 ('g', 'git', None, _('use git extended diff format')),
109 ('', 'nodates', None, _('omit dates from diff headers'))
109 ('', 'nodates', None, _('omit dates from diff headers'))
110 ]
110 ]
111
111
112 diffwsopts = [
112 diffwsopts = [
113 ('w', 'ignore-all-space', None,
113 ('w', 'ignore-all-space', None,
114 _('ignore white space when comparing lines')),
114 _('ignore white space when comparing lines')),
115 ('b', 'ignore-space-change', None,
115 ('b', 'ignore-space-change', None,
116 _('ignore changes in the amount of white space')),
116 _('ignore changes in the amount of white space')),
117 ('B', 'ignore-blank-lines', None,
117 ('B', 'ignore-blank-lines', None,
118 _('ignore changes whose lines are all blank')),
118 _('ignore changes whose lines are all blank')),
119 ]
119 ]
120
120
121 diffopts2 = [
121 diffopts2 = [
122 ('p', 'show-function', None, _('show which function each change is in')),
122 ('p', 'show-function', None, _('show which function each change is in')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ] + diffwsopts + [
124 ] + diffwsopts + [
125 ('U', 'unified', '',
125 ('U', 'unified', '',
126 _('number of lines of context to show'), _('NUM')),
126 _('number of lines of context to show'), _('NUM')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ]
128 ]
129
129
130 mergetoolopts = [
130 mergetoolopts = [
131 ('t', 'tool', '', _('specify merge tool')),
131 ('t', 'tool', '', _('specify merge tool')),
132 ]
132 ]
133
133
134 similarityopts = [
134 similarityopts = [
135 ('s', 'similarity', '',
135 ('s', 'similarity', '',
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 ]
137 ]
138
138
139 subrepoopts = [
139 subrepoopts = [
140 ('S', 'subrepos', None,
140 ('S', 'subrepos', None,
141 _('recurse into subrepositories'))
141 _('recurse into subrepositories'))
142 ]
142 ]
143
143
144 # Commands start here, listed alphabetically
144 # Commands start here, listed alphabetically
145
145
146 @command('^add',
146 @command('^add',
147 walkopts + subrepoopts + dryrunopts,
147 walkopts + subrepoopts + dryrunopts,
148 _('[OPTION]... [FILE]...'))
148 _('[OPTION]... [FILE]...'))
149 def add(ui, repo, *pats, **opts):
149 def add(ui, repo, *pats, **opts):
150 """add the specified files on the next commit
150 """add the specified files on the next commit
151
151
152 Schedule files to be version controlled and added to the
152 Schedule files to be version controlled and added to the
153 repository.
153 repository.
154
154
155 The files will be added to the repository at the next commit. To
155 The files will be added to the repository at the next commit. To
156 undo an add before that, see :hg:`forget`.
156 undo an add before that, see :hg:`forget`.
157
157
158 If no names are given, add all files to the repository.
158 If no names are given, add all files to the repository.
159
159
160 .. container:: verbose
160 .. container:: verbose
161
161
162 An example showing how new (unknown) files are added
162 An example showing how new (unknown) files are added
163 automatically by :hg:`add`::
163 automatically by :hg:`add`::
164
164
165 $ ls
165 $ ls
166 foo.c
166 foo.c
167 $ hg status
167 $ hg status
168 ? foo.c
168 ? foo.c
169 $ hg add
169 $ hg add
170 adding foo.c
170 adding foo.c
171 $ hg status
171 $ hg status
172 A foo.c
172 A foo.c
173
173
174 Returns 0 if all files are successfully added.
174 Returns 0 if all files are successfully added.
175 """
175 """
176
176
177 m = scmutil.match(repo[None], pats, opts)
177 m = scmutil.match(repo[None], pats, opts)
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 opts.get('subrepos'), prefix="", explicitonly=False)
179 opts.get('subrepos'), prefix="", explicitonly=False)
180 return rejected and 1 or 0
180 return rejected and 1 or 0
181
181
182 @command('addremove',
182 @command('addremove',
183 similarityopts + walkopts + dryrunopts,
183 similarityopts + walkopts + dryrunopts,
184 _('[OPTION]... [FILE]...'))
184 _('[OPTION]... [FILE]...'))
185 def addremove(ui, repo, *pats, **opts):
185 def addremove(ui, repo, *pats, **opts):
186 """add all new files, delete all missing files
186 """add all new files, delete all missing files
187
187
188 Add all new files and remove all missing files from the
188 Add all new files and remove all missing files from the
189 repository.
189 repository.
190
190
191 New files are ignored if they match any of the patterns in
191 New files are ignored if they match any of the patterns in
192 ``.hgignore``. As with add, these changes take effect at the next
192 ``.hgignore``. As with add, these changes take effect at the next
193 commit.
193 commit.
194
194
195 Use the -s/--similarity option to detect renamed files. This
195 Use the -s/--similarity option to detect renamed files. This
196 option takes a percentage between 0 (disabled) and 100 (files must
196 option takes a percentage between 0 (disabled) and 100 (files must
197 be identical) as its parameter. With a parameter greater than 0,
197 be identical) as its parameter. With a parameter greater than 0,
198 this compares every removed file with every added file and records
198 this compares every removed file with every added file and records
199 those similar enough as renames. Detecting renamed files this way
199 those similar enough as renames. Detecting renamed files this way
200 can be expensive. After using this option, :hg:`status -C` can be
200 can be expensive. After using this option, :hg:`status -C` can be
201 used to check which files were identified as moved or renamed. If
201 used to check which files were identified as moved or renamed. If
202 not specified, -s/--similarity defaults to 100 and only renames of
202 not specified, -s/--similarity defaults to 100 and only renames of
203 identical files are detected.
203 identical files are detected.
204
204
205 Returns 0 if all files are successfully added.
205 Returns 0 if all files are successfully added.
206 """
206 """
207 try:
207 try:
208 sim = float(opts.get('similarity') or 100)
208 sim = float(opts.get('similarity') or 100)
209 except ValueError:
209 except ValueError:
210 raise util.Abort(_('similarity must be a number'))
210 raise util.Abort(_('similarity must be a number'))
211 if sim < 0 or sim > 100:
211 if sim < 0 or sim > 100:
212 raise util.Abort(_('similarity must be between 0 and 100'))
212 raise util.Abort(_('similarity must be between 0 and 100'))
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214
214
215 @command('^annotate|blame',
215 @command('^annotate|blame',
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 ('', 'follow', None,
217 ('', 'follow', None,
218 _('follow copies/renames and list the filename (DEPRECATED)')),
218 _('follow copies/renames and list the filename (DEPRECATED)')),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('a', 'text', None, _('treat all files as text')),
220 ('a', 'text', None, _('treat all files as text')),
221 ('u', 'user', None, _('list the author (long with -v)')),
221 ('u', 'user', None, _('list the author (long with -v)')),
222 ('f', 'file', None, _('list the filename')),
222 ('f', 'file', None, _('list the filename')),
223 ('d', 'date', None, _('list the date (short with -q)')),
223 ('d', 'date', None, _('list the date (short with -q)')),
224 ('n', 'number', None, _('list the revision number (default)')),
224 ('n', 'number', None, _('list the revision number (default)')),
225 ('c', 'changeset', None, _('list the changeset')),
225 ('c', 'changeset', None, _('list the changeset')),
226 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ] + diffwsopts + walkopts,
227 ] + diffwsopts + walkopts,
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 def annotate(ui, repo, *pats, **opts):
229 def annotate(ui, repo, *pats, **opts):
230 """show changeset information by line for each file
230 """show changeset information by line for each file
231
231
232 List changes in files, showing the revision id responsible for
232 List changes in files, showing the revision id responsible for
233 each line
233 each line
234
234
235 This command is useful for discovering when a change was made and
235 This command is useful for discovering when a change was made and
236 by whom.
236 by whom.
237
237
238 Without the -a/--text option, annotate will avoid processing files
238 Without the -a/--text option, annotate will avoid processing files
239 it detects as binary. With -a, annotate will annotate the file
239 it detects as binary. With -a, annotate will annotate the file
240 anyway, although the results will probably be neither useful
240 anyway, although the results will probably be neither useful
241 nor desirable.
241 nor desirable.
242
242
243 Returns 0 on success.
243 Returns 0 on success.
244 """
244 """
245 if opts.get('follow'):
245 if opts.get('follow'):
246 # --follow is deprecated and now just an alias for -f/--file
246 # --follow is deprecated and now just an alias for -f/--file
247 # to mimic the behavior of Mercurial before version 1.5
247 # to mimic the behavior of Mercurial before version 1.5
248 opts['file'] = True
248 opts['file'] = True
249
249
250 datefunc = ui.quiet and util.shortdate or util.datestr
250 datefunc = ui.quiet and util.shortdate or util.datestr
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252
252
253 if not pats:
253 if not pats:
254 raise util.Abort(_('at least one filename or pattern is required'))
254 raise util.Abort(_('at least one filename or pattern is required'))
255
255
256 hexfn = ui.debugflag and hex or short
256 hexfn = ui.debugflag and hex or short
257
257
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 ('number', ' ', lambda x: str(x[0].rev())),
259 ('number', ' ', lambda x: str(x[0].rev())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('date', ' ', getdate),
261 ('date', ' ', getdate),
262 ('file', ' ', lambda x: x[0].path()),
262 ('file', ' ', lambda x: x[0].path()),
263 ('line_number', ':', lambda x: str(x[1])),
263 ('line_number', ':', lambda x: str(x[1])),
264 ]
264 ]
265
265
266 if (not opts.get('user') and not opts.get('changeset')
266 if (not opts.get('user') and not opts.get('changeset')
267 and not opts.get('date') and not opts.get('file')):
267 and not opts.get('date') and not opts.get('file')):
268 opts['number'] = True
268 opts['number'] = True
269
269
270 linenumber = opts.get('line_number') is not None
270 linenumber = opts.get('line_number') is not None
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
272 raise util.Abort(_('at least one of -n/-c is required for -l'))
273
273
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276
276
277 def bad(x, y):
277 def bad(x, y):
278 raise util.Abort("%s: %s" % (x, y))
278 raise util.Abort("%s: %s" % (x, y))
279
279
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 m = scmutil.match(ctx, pats, opts)
281 m = scmutil.match(ctx, pats, opts)
282 m.bad = bad
282 m.bad = bad
283 follow = not opts.get('no_follow')
283 follow = not opts.get('no_follow')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
284 diffopts = patch.diffopts(ui, opts, section='annotate')
285 for abs in ctx.walk(m):
285 for abs in ctx.walk(m):
286 fctx = ctx[abs]
286 fctx = ctx[abs]
287 if not opts.get('text') and util.binary(fctx.data()):
287 if not opts.get('text') and util.binary(fctx.data()):
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 continue
289 continue
290
290
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 diffopts=diffopts)
292 diffopts=diffopts)
293 pieces = []
293 pieces = []
294
294
295 for f, sep in funcmap:
295 for f, sep in funcmap:
296 l = [f(n) for n, dummy in lines]
296 l = [f(n) for n, dummy in lines]
297 if l:
297 if l:
298 sized = [(x, encoding.colwidth(x)) for x in l]
298 sized = [(x, encoding.colwidth(x)) for x in l]
299 ml = max([w for x, w in sized])
299 ml = max([w for x, w in sized])
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 for x, w in sized])
301 for x, w in sized])
302
302
303 if pieces:
303 if pieces:
304 for p, l in zip(zip(*pieces), lines):
304 for p, l in zip(zip(*pieces), lines):
305 ui.write("%s: %s" % ("".join(p), l[1]))
305 ui.write("%s: %s" % ("".join(p), l[1]))
306
306
307 if lines and not lines[-1][1].endswith('\n'):
307 if lines and not lines[-1][1].endswith('\n'):
308 ui.write('\n')
308 ui.write('\n')
309
309
310 @command('archive',
310 @command('archive',
311 [('', 'no-decode', None, _('do not pass files through decoders')),
311 [('', 'no-decode', None, _('do not pass files through decoders')),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 _('PREFIX')),
313 _('PREFIX')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ] + subrepoopts + walkopts,
316 ] + subrepoopts + walkopts,
317 _('[OPTION]... DEST'))
317 _('[OPTION]... DEST'))
318 def archive(ui, repo, dest, **opts):
318 def archive(ui, repo, dest, **opts):
319 '''create an unversioned archive of a repository revision
319 '''create an unversioned archive of a repository revision
320
320
321 By default, the revision used is the parent of the working
321 By default, the revision used is the parent of the working
322 directory; use -r/--rev to specify a different revision.
322 directory; use -r/--rev to specify a different revision.
323
323
324 The archive type is automatically detected based on file
324 The archive type is automatically detected based on file
325 extension (or override using -t/--type).
325 extension (or override using -t/--type).
326
326
327 .. container:: verbose
327 .. container:: verbose
328
328
329 Examples:
329 Examples:
330
330
331 - create a zip file containing the 1.0 release::
331 - create a zip file containing the 1.0 release::
332
332
333 hg archive -r 1.0 project-1.0.zip
333 hg archive -r 1.0 project-1.0.zip
334
334
335 - create a tarball excluding .hg files::
335 - create a tarball excluding .hg files::
336
336
337 hg archive project.tar.gz -X ".hg*"
337 hg archive project.tar.gz -X ".hg*"
338
338
339 Valid types are:
339 Valid types are:
340
340
341 :``files``: a directory full of files (default)
341 :``files``: a directory full of files (default)
342 :``tar``: tar archive, uncompressed
342 :``tar``: tar archive, uncompressed
343 :``tbz2``: tar archive, compressed using bzip2
343 :``tbz2``: tar archive, compressed using bzip2
344 :``tgz``: tar archive, compressed using gzip
344 :``tgz``: tar archive, compressed using gzip
345 :``uzip``: zip archive, uncompressed
345 :``uzip``: zip archive, uncompressed
346 :``zip``: zip archive, compressed using deflate
346 :``zip``: zip archive, compressed using deflate
347
347
348 The exact name of the destination archive or directory is given
348 The exact name of the destination archive or directory is given
349 using a format string; see :hg:`help export` for details.
349 using a format string; see :hg:`help export` for details.
350
350
351 Each member added to an archive file has a directory prefix
351 Each member added to an archive file has a directory prefix
352 prepended. Use -p/--prefix to specify a format string for the
352 prepended. Use -p/--prefix to specify a format string for the
353 prefix. The default is the basename of the archive, with suffixes
353 prefix. The default is the basename of the archive, with suffixes
354 removed.
354 removed.
355
355
356 Returns 0 on success.
356 Returns 0 on success.
357 '''
357 '''
358
358
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 if not ctx:
360 if not ctx:
361 raise util.Abort(_('no working directory: please specify a revision'))
361 raise util.Abort(_('no working directory: please specify a revision'))
362 node = ctx.node()
362 node = ctx.node()
363 dest = cmdutil.makefilename(repo, dest, node)
363 dest = cmdutil.makefilename(repo, dest, node)
364 if os.path.realpath(dest) == repo.root:
364 if os.path.realpath(dest) == repo.root:
365 raise util.Abort(_('repository root cannot be destination'))
365 raise util.Abort(_('repository root cannot be destination'))
366
366
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 prefix = opts.get('prefix')
368 prefix = opts.get('prefix')
369
369
370 if dest == '-':
370 if dest == '-':
371 if kind == 'files':
371 if kind == 'files':
372 raise util.Abort(_('cannot archive plain files to stdout'))
372 raise util.Abort(_('cannot archive plain files to stdout'))
373 dest = cmdutil.makefileobj(repo, dest)
373 dest = cmdutil.makefileobj(repo, dest)
374 if not prefix:
374 if not prefix:
375 prefix = os.path.basename(repo.root) + '-%h'
375 prefix = os.path.basename(repo.root) + '-%h'
376
376
377 prefix = cmdutil.makefilename(repo, prefix, node)
377 prefix = cmdutil.makefilename(repo, prefix, node)
378 matchfn = scmutil.match(ctx, [], opts)
378 matchfn = scmutil.match(ctx, [], opts)
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 matchfn, prefix, subrepos=opts.get('subrepos'))
380 matchfn, prefix, subrepos=opts.get('subrepos'))
381
381
382 @command('backout',
382 @command('backout',
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 ('', 'parent', '',
384 ('', 'parent', '',
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 _('[OPTION]... [-r] REV'))
388 _('[OPTION]... [-r] REV'))
389 def backout(ui, repo, node=None, rev=None, **opts):
389 def backout(ui, repo, node=None, rev=None, **opts):
390 '''reverse effect of earlier changeset
390 '''reverse effect of earlier changeset
391
391
392 Prepare a new changeset with the effect of REV undone in the
392 Prepare a new changeset with the effect of REV undone in the
393 current working directory.
393 current working directory.
394
394
395 If REV is the parent of the working directory, then this new changeset
395 If REV is the parent of the working directory, then this new changeset
396 is committed automatically. Otherwise, hg needs to merge the
396 is committed automatically. Otherwise, hg needs to merge the
397 changes and the merged result is left uncommitted.
397 changes and the merged result is left uncommitted.
398
398
399 .. note::
399 .. note::
400 backout cannot be used to fix either an unwanted or
400 backout cannot be used to fix either an unwanted or
401 incorrect merge.
401 incorrect merge.
402
402
403 .. container:: verbose
403 .. container:: verbose
404
404
405 By default, the pending changeset will have one parent,
405 By default, the pending changeset will have one parent,
406 maintaining a linear history. With --merge, the pending
406 maintaining a linear history. With --merge, the pending
407 changeset will instead have two parents: the old parent of the
407 changeset will instead have two parents: the old parent of the
408 working directory and a new child of REV that simply undoes REV.
408 working directory and a new child of REV that simply undoes REV.
409
409
410 Before version 1.7, the behavior without --merge was equivalent
410 Before version 1.7, the behavior without --merge was equivalent
411 to specifying --merge followed by :hg:`update --clean .` to
411 to specifying --merge followed by :hg:`update --clean .` to
412 cancel the merge and leave the child of REV as a head to be
412 cancel the merge and leave the child of REV as a head to be
413 merged separately.
413 merged separately.
414
414
415 See :hg:`help dates` for a list of formats valid for -d/--date.
415 See :hg:`help dates` for a list of formats valid for -d/--date.
416
416
417 Returns 0 on success.
417 Returns 0 on success.
418 '''
418 '''
419 if rev and node:
419 if rev and node:
420 raise util.Abort(_("please specify just one revision"))
420 raise util.Abort(_("please specify just one revision"))
421
421
422 if not rev:
422 if not rev:
423 rev = node
423 rev = node
424
424
425 if not rev:
425 if not rev:
426 raise util.Abort(_("please specify a revision to backout"))
426 raise util.Abort(_("please specify a revision to backout"))
427
427
428 date = opts.get('date')
428 date = opts.get('date')
429 if date:
429 if date:
430 opts['date'] = util.parsedate(date)
430 opts['date'] = util.parsedate(date)
431
431
432 cmdutil.checkunfinished(repo)
432 cmdutil.checkunfinished(repo)
433 cmdutil.bailifchanged(repo)
433 cmdutil.bailifchanged(repo)
434 node = scmutil.revsingle(repo, rev).node()
434 node = scmutil.revsingle(repo, rev).node()
435
435
436 op1, op2 = repo.dirstate.parents()
436 op1, op2 = repo.dirstate.parents()
437 a = repo.changelog.ancestor(op1, node)
437 a = repo.changelog.ancestor(op1, node)
438 if a != node:
438 if a != node:
439 raise util.Abort(_('cannot backout change on a different branch'))
439 raise util.Abort(_('cannot backout change on a different branch'))
440
440
441 p1, p2 = repo.changelog.parents(node)
441 p1, p2 = repo.changelog.parents(node)
442 if p1 == nullid:
442 if p1 == nullid:
443 raise util.Abort(_('cannot backout a change with no parents'))
443 raise util.Abort(_('cannot backout a change with no parents'))
444 if p2 != nullid:
444 if p2 != nullid:
445 if not opts.get('parent'):
445 if not opts.get('parent'):
446 raise util.Abort(_('cannot backout a merge changeset'))
446 raise util.Abort(_('cannot backout a merge changeset'))
447 p = repo.lookup(opts['parent'])
447 p = repo.lookup(opts['parent'])
448 if p not in (p1, p2):
448 if p not in (p1, p2):
449 raise util.Abort(_('%s is not a parent of %s') %
449 raise util.Abort(_('%s is not a parent of %s') %
450 (short(p), short(node)))
450 (short(p), short(node)))
451 parent = p
451 parent = p
452 else:
452 else:
453 if opts.get('parent'):
453 if opts.get('parent'):
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
454 raise util.Abort(_('cannot use --parent on non-merge changeset'))
455 parent = p1
455 parent = p1
456
456
457 # the backout should appear on the same branch
457 # the backout should appear on the same branch
458 wlock = repo.wlock()
458 wlock = repo.wlock()
459 try:
459 try:
460 branch = repo.dirstate.branch()
460 branch = repo.dirstate.branch()
461 bheads = repo.branchheads(branch)
461 bheads = repo.branchheads(branch)
462 hg.clean(repo, node, show_stats=False)
462 hg.clean(repo, node, show_stats=False)
463 repo.dirstate.setbranch(branch)
463 repo.dirstate.setbranch(branch)
464 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
465 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 return hg.update(repo, op1)
469 return hg.update(repo, op1)
470 finally:
470 finally:
471 ui.setconfig('ui', 'forcemerge', '')
471 ui.setconfig('ui', 'forcemerge', '')
472
472
473 e = cmdutil.commiteditor
473 e = cmdutil.commiteditor
474 if not opts['message'] and not opts['logfile']:
474 if not opts['message'] and not opts['logfile']:
475 # we don't translate commit messages
475 # we don't translate commit messages
476 opts['message'] = "Backed out changeset %s" % short(node)
476 opts['message'] = "Backed out changeset %s" % short(node)
477 e = cmdutil.commitforceeditor
477 e = cmdutil.commitforceeditor
478
478
479 def commitfunc(ui, repo, message, match, opts):
479 def commitfunc(ui, repo, message, match, opts):
480 return repo.commit(message, opts.get('user'), opts.get('date'),
480 return repo.commit(message, opts.get('user'), opts.get('date'),
481 match, editor=e)
481 match, editor=e)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
482 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
483 cmdutil.commitstatus(repo, newnode, branch, bheads)
484
484
485 def nice(node):
485 def nice(node):
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
486 return '%d:%s' % (repo.changelog.rev(node), short(node))
487 ui.status(_('changeset %s backs out changeset %s\n') %
487 ui.status(_('changeset %s backs out changeset %s\n') %
488 (nice(repo.changelog.tip()), nice(node)))
488 (nice(repo.changelog.tip()), nice(node)))
489 if opts.get('merge') and op1 != node:
489 if opts.get('merge') and op1 != node:
490 hg.clean(repo, op1, show_stats=False)
490 hg.clean(repo, op1, show_stats=False)
491 ui.status(_('merging with changeset %s\n')
491 ui.status(_('merging with changeset %s\n')
492 % nice(repo.changelog.tip()))
492 % nice(repo.changelog.tip()))
493 try:
493 try:
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
494 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
495 return hg.merge(repo, hex(repo.changelog.tip()))
495 return hg.merge(repo, hex(repo.changelog.tip()))
496 finally:
496 finally:
497 ui.setconfig('ui', 'forcemerge', '')
497 ui.setconfig('ui', 'forcemerge', '')
498 finally:
498 finally:
499 wlock.release()
499 wlock.release()
500 return 0
500 return 0
501
501
502 @command('bisect',
502 @command('bisect',
503 [('r', 'reset', False, _('reset bisect state')),
503 [('r', 'reset', False, _('reset bisect state')),
504 ('g', 'good', False, _('mark changeset good')),
504 ('g', 'good', False, _('mark changeset good')),
505 ('b', 'bad', False, _('mark changeset bad')),
505 ('b', 'bad', False, _('mark changeset bad')),
506 ('s', 'skip', False, _('skip testing changeset')),
506 ('s', 'skip', False, _('skip testing changeset')),
507 ('e', 'extend', False, _('extend the bisect range')),
507 ('e', 'extend', False, _('extend the bisect range')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
508 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
509 ('U', 'noupdate', False, _('do not update to target'))],
509 ('U', 'noupdate', False, _('do not update to target'))],
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
510 _("[-gbsr] [-U] [-c CMD] [REV]"))
511 def bisect(ui, repo, rev=None, extra=None, command=None,
511 def bisect(ui, repo, rev=None, extra=None, command=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
512 reset=None, good=None, bad=None, skip=None, extend=None,
513 noupdate=None):
513 noupdate=None):
514 """subdivision search of changesets
514 """subdivision search of changesets
515
515
516 This command helps to find changesets which introduce problems. To
516 This command helps to find changesets which introduce problems. To
517 use, mark the earliest changeset you know exhibits the problem as
517 use, mark the earliest changeset you know exhibits the problem as
518 bad, then mark the latest changeset which is free from the problem
518 bad, then mark the latest changeset which is free from the problem
519 as good. Bisect will update your working directory to a revision
519 as good. Bisect will update your working directory to a revision
520 for testing (unless the -U/--noupdate option is specified). Once
520 for testing (unless the -U/--noupdate option is specified). Once
521 you have performed tests, mark the working directory as good or
521 you have performed tests, mark the working directory as good or
522 bad, and bisect will either update to another candidate changeset
522 bad, and bisect will either update to another candidate changeset
523 or announce that it has found the bad revision.
523 or announce that it has found the bad revision.
524
524
525 As a shortcut, you can also use the revision argument to mark a
525 As a shortcut, you can also use the revision argument to mark a
526 revision as good or bad without checking it out first.
526 revision as good or bad without checking it out first.
527
527
528 If you supply a command, it will be used for automatic bisection.
528 If you supply a command, it will be used for automatic bisection.
529 The environment variable HG_NODE will contain the ID of the
529 The environment variable HG_NODE will contain the ID of the
530 changeset being tested. The exit status of the command will be
530 changeset being tested. The exit status of the command will be
531 used to mark revisions as good or bad: status 0 means good, 125
531 used to mark revisions as good or bad: status 0 means good, 125
532 means to skip the revision, 127 (command not found) will abort the
532 means to skip the revision, 127 (command not found) will abort the
533 bisection, and any other non-zero exit status means the revision
533 bisection, and any other non-zero exit status means the revision
534 is bad.
534 is bad.
535
535
536 .. container:: verbose
536 .. container:: verbose
537
537
538 Some examples:
538 Some examples:
539
539
540 - start a bisection with known bad revision 12, and good revision 34::
540 - start a bisection with known bad revision 12, and good revision 34::
541
541
542 hg bisect --bad 34
542 hg bisect --bad 34
543 hg bisect --good 12
543 hg bisect --good 12
544
544
545 - advance the current bisection by marking current revision as good or
545 - advance the current bisection by marking current revision as good or
546 bad::
546 bad::
547
547
548 hg bisect --good
548 hg bisect --good
549 hg bisect --bad
549 hg bisect --bad
550
550
551 - mark the current revision, or a known revision, to be skipped (e.g. if
551 - mark the current revision, or a known revision, to be skipped (e.g. if
552 that revision is not usable because of another issue)::
552 that revision is not usable because of another issue)::
553
553
554 hg bisect --skip
554 hg bisect --skip
555 hg bisect --skip 23
555 hg bisect --skip 23
556
556
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
557 - skip all revisions that do not touch directories ``foo`` or ``bar``
558
558
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
559 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
560
560
561 - forget the current bisection::
561 - forget the current bisection::
562
562
563 hg bisect --reset
563 hg bisect --reset
564
564
565 - use 'make && make tests' to automatically find the first broken
565 - use 'make && make tests' to automatically find the first broken
566 revision::
566 revision::
567
567
568 hg bisect --reset
568 hg bisect --reset
569 hg bisect --bad 34
569 hg bisect --bad 34
570 hg bisect --good 12
570 hg bisect --good 12
571 hg bisect --command 'make && make tests'
571 hg bisect --command 'make && make tests'
572
572
573 - see all changesets whose states are already known in the current
573 - see all changesets whose states are already known in the current
574 bisection::
574 bisection::
575
575
576 hg log -r "bisect(pruned)"
576 hg log -r "bisect(pruned)"
577
577
578 - see the changeset currently being bisected (especially useful
578 - see the changeset currently being bisected (especially useful
579 if running with -U/--noupdate)::
579 if running with -U/--noupdate)::
580
580
581 hg log -r "bisect(current)"
581 hg log -r "bisect(current)"
582
582
583 - see all changesets that took part in the current bisection::
583 - see all changesets that took part in the current bisection::
584
584
585 hg log -r "bisect(range)"
585 hg log -r "bisect(range)"
586
586
587 - with the graphlog extension, you can even get a nice graph::
587 - with the graphlog extension, you can even get a nice graph::
588
588
589 hg log --graph -r "bisect(range)"
589 hg log --graph -r "bisect(range)"
590
590
591 See :hg:`help revsets` for more about the `bisect()` keyword.
591 See :hg:`help revsets` for more about the `bisect()` keyword.
592
592
593 Returns 0 on success.
593 Returns 0 on success.
594 """
594 """
595 def extendbisectrange(nodes, good):
595 def extendbisectrange(nodes, good):
596 # bisect is incomplete when it ends on a merge node and
596 # bisect is incomplete when it ends on a merge node and
597 # one of the parent was not checked.
597 # one of the parent was not checked.
598 parents = repo[nodes[0]].parents()
598 parents = repo[nodes[0]].parents()
599 if len(parents) > 1:
599 if len(parents) > 1:
600 side = good and state['bad'] or state['good']
600 side = good and state['bad'] or state['good']
601 num = len(set(i.node() for i in parents) & set(side))
601 num = len(set(i.node() for i in parents) & set(side))
602 if num == 1:
602 if num == 1:
603 return parents[0].ancestor(parents[1])
603 return parents[0].ancestor(parents[1])
604 return None
604 return None
605
605
606 def print_result(nodes, good):
606 def print_result(nodes, good):
607 displayer = cmdutil.show_changeset(ui, repo, {})
607 displayer = cmdutil.show_changeset(ui, repo, {})
608 if len(nodes) == 1:
608 if len(nodes) == 1:
609 # narrowed it down to a single revision
609 # narrowed it down to a single revision
610 if good:
610 if good:
611 ui.write(_("The first good revision is:\n"))
611 ui.write(_("The first good revision is:\n"))
612 else:
612 else:
613 ui.write(_("The first bad revision is:\n"))
613 ui.write(_("The first bad revision is:\n"))
614 displayer.show(repo[nodes[0]])
614 displayer.show(repo[nodes[0]])
615 extendnode = extendbisectrange(nodes, good)
615 extendnode = extendbisectrange(nodes, good)
616 if extendnode is not None:
616 if extendnode is not None:
617 ui.write(_('Not all ancestors of this changeset have been'
617 ui.write(_('Not all ancestors of this changeset have been'
618 ' checked.\nUse bisect --extend to continue the '
618 ' checked.\nUse bisect --extend to continue the '
619 'bisection from\nthe common ancestor, %s.\n')
619 'bisection from\nthe common ancestor, %s.\n')
620 % extendnode)
620 % extendnode)
621 else:
621 else:
622 # multiple possible revisions
622 # multiple possible revisions
623 if good:
623 if good:
624 ui.write(_("Due to skipped revisions, the first "
624 ui.write(_("Due to skipped revisions, the first "
625 "good revision could be any of:\n"))
625 "good revision could be any of:\n"))
626 else:
626 else:
627 ui.write(_("Due to skipped revisions, the first "
627 ui.write(_("Due to skipped revisions, the first "
628 "bad revision could be any of:\n"))
628 "bad revision could be any of:\n"))
629 for n in nodes:
629 for n in nodes:
630 displayer.show(repo[n])
630 displayer.show(repo[n])
631 displayer.close()
631 displayer.close()
632
632
633 def check_state(state, interactive=True):
633 def check_state(state, interactive=True):
634 if not state['good'] or not state['bad']:
634 if not state['good'] or not state['bad']:
635 if (good or bad or skip or reset) and interactive:
635 if (good or bad or skip or reset) and interactive:
636 return
636 return
637 if not state['good']:
637 if not state['good']:
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
638 raise util.Abort(_('cannot bisect (no known good revisions)'))
639 else:
639 else:
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
640 raise util.Abort(_('cannot bisect (no known bad revisions)'))
641 return True
641 return True
642
642
643 # backward compatibility
643 # backward compatibility
644 if rev in "good bad reset init".split():
644 if rev in "good bad reset init".split():
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
645 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
646 cmd, rev, extra = rev, extra, None
646 cmd, rev, extra = rev, extra, None
647 if cmd == "good":
647 if cmd == "good":
648 good = True
648 good = True
649 elif cmd == "bad":
649 elif cmd == "bad":
650 bad = True
650 bad = True
651 else:
651 else:
652 reset = True
652 reset = True
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
653 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
654 raise util.Abort(_('incompatible arguments'))
654 raise util.Abort(_('incompatible arguments'))
655
655
656 cmdutil.checkunfinished(repo)
656 cmdutil.checkunfinished(repo)
657
657
658 if reset:
658 if reset:
659 p = repo.join("bisect.state")
659 p = repo.join("bisect.state")
660 if os.path.exists(p):
660 if os.path.exists(p):
661 os.unlink(p)
661 os.unlink(p)
662 return
662 return
663
663
664 state = hbisect.load_state(repo)
664 state = hbisect.load_state(repo)
665
665
666 if command:
666 if command:
667 changesets = 1
667 changesets = 1
668 try:
668 try:
669 node = state['current'][0]
669 node = state['current'][0]
670 except LookupError:
670 except LookupError:
671 if noupdate:
671 if noupdate:
672 raise util.Abort(_('current bisect revision is unknown - '
672 raise util.Abort(_('current bisect revision is unknown - '
673 'start a new bisect to fix'))
673 'start a new bisect to fix'))
674 node, p2 = repo.dirstate.parents()
674 node, p2 = repo.dirstate.parents()
675 if p2 != nullid:
675 if p2 != nullid:
676 raise util.Abort(_('current bisect revision is a merge'))
676 raise util.Abort(_('current bisect revision is a merge'))
677 try:
677 try:
678 while changesets:
678 while changesets:
679 # update state
679 # update state
680 state['current'] = [node]
680 state['current'] = [node]
681 hbisect.save_state(repo, state)
681 hbisect.save_state(repo, state)
682 status = util.system(command,
682 status = util.system(command,
683 environ={'HG_NODE': hex(node)},
683 environ={'HG_NODE': hex(node)},
684 out=ui.fout)
684 out=ui.fout)
685 if status == 125:
685 if status == 125:
686 transition = "skip"
686 transition = "skip"
687 elif status == 0:
687 elif status == 0:
688 transition = "good"
688 transition = "good"
689 # status < 0 means process was killed
689 # status < 0 means process was killed
690 elif status == 127:
690 elif status == 127:
691 raise util.Abort(_("failed to execute %s") % command)
691 raise util.Abort(_("failed to execute %s") % command)
692 elif status < 0:
692 elif status < 0:
693 raise util.Abort(_("%s killed") % command)
693 raise util.Abort(_("%s killed") % command)
694 else:
694 else:
695 transition = "bad"
695 transition = "bad"
696 ctx = scmutil.revsingle(repo, rev, node)
696 ctx = scmutil.revsingle(repo, rev, node)
697 rev = None # clear for future iterations
697 rev = None # clear for future iterations
698 state[transition].append(ctx.node())
698 state[transition].append(ctx.node())
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
699 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
700 check_state(state, interactive=False)
700 check_state(state, interactive=False)
701 # bisect
701 # bisect
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
702 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
703 # update to next check
703 # update to next check
704 node = nodes[0]
704 node = nodes[0]
705 if not noupdate:
705 if not noupdate:
706 cmdutil.bailifchanged(repo)
706 cmdutil.bailifchanged(repo)
707 hg.clean(repo, node, show_stats=False)
707 hg.clean(repo, node, show_stats=False)
708 finally:
708 finally:
709 state['current'] = [node]
709 state['current'] = [node]
710 hbisect.save_state(repo, state)
710 hbisect.save_state(repo, state)
711 print_result(nodes, good)
711 print_result(nodes, good)
712 return
712 return
713
713
714 # update state
714 # update state
715
715
716 if rev:
716 if rev:
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
717 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
718 else:
718 else:
719 nodes = [repo.lookup('.')]
719 nodes = [repo.lookup('.')]
720
720
721 if good or bad or skip:
721 if good or bad or skip:
722 if good:
722 if good:
723 state['good'] += nodes
723 state['good'] += nodes
724 elif bad:
724 elif bad:
725 state['bad'] += nodes
725 state['bad'] += nodes
726 elif skip:
726 elif skip:
727 state['skip'] += nodes
727 state['skip'] += nodes
728 hbisect.save_state(repo, state)
728 hbisect.save_state(repo, state)
729
729
730 if not check_state(state):
730 if not check_state(state):
731 return
731 return
732
732
733 # actually bisect
733 # actually bisect
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
734 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
735 if extend:
735 if extend:
736 if not changesets:
736 if not changesets:
737 extendnode = extendbisectrange(nodes, good)
737 extendnode = extendbisectrange(nodes, good)
738 if extendnode is not None:
738 if extendnode is not None:
739 ui.write(_("Extending search to changeset %d:%s\n"
739 ui.write(_("Extending search to changeset %d:%s\n"
740 % (extendnode.rev(), extendnode)))
740 % (extendnode.rev(), extendnode)))
741 state['current'] = [extendnode.node()]
741 state['current'] = [extendnode.node()]
742 hbisect.save_state(repo, state)
742 hbisect.save_state(repo, state)
743 if noupdate:
743 if noupdate:
744 return
744 return
745 cmdutil.bailifchanged(repo)
745 cmdutil.bailifchanged(repo)
746 return hg.clean(repo, extendnode.node())
746 return hg.clean(repo, extendnode.node())
747 raise util.Abort(_("nothing to extend"))
747 raise util.Abort(_("nothing to extend"))
748
748
749 if changesets == 0:
749 if changesets == 0:
750 print_result(nodes, good)
750 print_result(nodes, good)
751 else:
751 else:
752 assert len(nodes) == 1 # only a single node can be tested next
752 assert len(nodes) == 1 # only a single node can be tested next
753 node = nodes[0]
753 node = nodes[0]
754 # compute the approximate number of remaining tests
754 # compute the approximate number of remaining tests
755 tests, size = 0, 2
755 tests, size = 0, 2
756 while size <= changesets:
756 while size <= changesets:
757 tests, size = tests + 1, size * 2
757 tests, size = tests + 1, size * 2
758 rev = repo.changelog.rev(node)
758 rev = repo.changelog.rev(node)
759 ui.write(_("Testing changeset %d:%s "
759 ui.write(_("Testing changeset %d:%s "
760 "(%d changesets remaining, ~%d tests)\n")
760 "(%d changesets remaining, ~%d tests)\n")
761 % (rev, short(node), changesets, tests))
761 % (rev, short(node), changesets, tests))
762 state['current'] = [node]
762 state['current'] = [node]
763 hbisect.save_state(repo, state)
763 hbisect.save_state(repo, state)
764 if not noupdate:
764 if not noupdate:
765 cmdutil.bailifchanged(repo)
765 cmdutil.bailifchanged(repo)
766 return hg.clean(repo, node)
766 return hg.clean(repo, node)
767
767
768 @command('bookmarks|bookmark',
768 @command('bookmarks|bookmark',
769 [('f', 'force', False, _('force')),
769 [('f', 'force', False, _('force')),
770 ('r', 'rev', '', _('revision'), _('REV')),
770 ('r', 'rev', '', _('revision'), _('REV')),
771 ('d', 'delete', False, _('delete a given bookmark')),
771 ('d', 'delete', False, _('delete a given bookmark')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
772 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
773 ('i', 'inactive', False, _('mark a bookmark inactive'))],
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
774 _('hg bookmarks [OPTIONS]... [NAME]...'))
775 def bookmark(ui, repo, *names, **opts):
775 def bookmark(ui, repo, *names, **opts):
776 '''track a line of development with movable markers
776 '''track a line of development with movable markers
777
777
778 Bookmarks are pointers to certain commits that move when committing.
778 Bookmarks are pointers to certain commits that move when committing.
779 Bookmarks are local. They can be renamed, copied and deleted. It is
779 Bookmarks are local. They can be renamed, copied and deleted. It is
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
780 possible to use :hg:`merge NAME` to merge from a given bookmark, and
781 :hg:`update NAME` to update to a given bookmark.
781 :hg:`update NAME` to update to a given bookmark.
782
782
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
783 You can use :hg:`bookmark NAME` to set a bookmark on the working
784 directory's parent revision with the given name. If you specify
784 directory's parent revision with the given name. If you specify
785 a revision using -r REV (where REV may be an existing bookmark),
785 a revision using -r REV (where REV may be an existing bookmark),
786 the bookmark is assigned to that revision.
786 the bookmark is assigned to that revision.
787
787
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
788 Bookmarks can be pushed and pulled between repositories (see :hg:`help
789 push` and :hg:`help pull`). This requires both the local and remote
789 push` and :hg:`help pull`). This requires both the local and remote
790 repositories to support bookmarks. For versions prior to 1.8, this means
790 repositories to support bookmarks. For versions prior to 1.8, this means
791 the bookmarks extension must be enabled.
791 the bookmarks extension must be enabled.
792
792
793 If you set a bookmark called '@', new clones of the repository will
793 If you set a bookmark called '@', new clones of the repository will
794 have that revision checked out (and the bookmark made active) by
794 have that revision checked out (and the bookmark made active) by
795 default.
795 default.
796
796
797 With -i/--inactive, the new bookmark will not be made the active
797 With -i/--inactive, the new bookmark will not be made the active
798 bookmark. If -r/--rev is given, the new bookmark will not be made
798 bookmark. If -r/--rev is given, the new bookmark will not be made
799 active even if -i/--inactive is not given. If no NAME is given, the
799 active even if -i/--inactive is not given. If no NAME is given, the
800 current active bookmark will be marked inactive.
800 current active bookmark will be marked inactive.
801 '''
801 '''
802 force = opts.get('force')
802 force = opts.get('force')
803 rev = opts.get('rev')
803 rev = opts.get('rev')
804 delete = opts.get('delete')
804 delete = opts.get('delete')
805 rename = opts.get('rename')
805 rename = opts.get('rename')
806 inactive = opts.get('inactive')
806 inactive = opts.get('inactive')
807
807
808 hexfn = ui.debugflag and hex or short
808 hexfn = ui.debugflag and hex or short
809 marks = repo._bookmarks
809 marks = repo._bookmarks
810 cur = repo.changectx('.').node()
810 cur = repo.changectx('.').node()
811
811
812 def checkformat(mark):
812 def checkformat(mark):
813 mark = mark.strip()
813 mark = mark.strip()
814 if not mark:
814 if not mark:
815 raise util.Abort(_("bookmark names cannot consist entirely of "
815 raise util.Abort(_("bookmark names cannot consist entirely of "
816 "whitespace"))
816 "whitespace"))
817 scmutil.checknewlabel(repo, mark, 'bookmark')
817 scmutil.checknewlabel(repo, mark, 'bookmark')
818 return mark
818 return mark
819
819
820 def checkconflict(repo, mark, force=False, target=None):
820 def checkconflict(repo, mark, force=False, target=None):
821 if mark in marks and not force:
821 if mark in marks and not force:
822 if target:
822 if target:
823 if marks[mark] == target and target == cur:
823 if marks[mark] == target and target == cur:
824 # re-activating a bookmark
824 # re-activating a bookmark
825 return
825 return
826 anc = repo.changelog.ancestors([repo[target].rev()])
826 anc = repo.changelog.ancestors([repo[target].rev()])
827 bmctx = repo[marks[mark]]
827 bmctx = repo[marks[mark]]
828 divs = [repo[b].node() for b in marks
828 divs = [repo[b].node() for b in marks
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
829 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
830
830
831 # allow resolving a single divergent bookmark even if moving
831 # allow resolving a single divergent bookmark even if moving
832 # the bookmark across branches when a revision is specified
832 # the bookmark across branches when a revision is specified
833 # that contains a divergent bookmark
833 # that contains a divergent bookmark
834 if bmctx.rev() not in anc and target in divs:
834 if bmctx.rev() not in anc and target in divs:
835 bookmarks.deletedivergent(repo, [target], mark)
835 bookmarks.deletedivergent(repo, [target], mark)
836 return
836 return
837
837
838 deletefrom = [b for b in divs
838 deletefrom = [b for b in divs
839 if repo[b].rev() in anc or b == target]
839 if repo[b].rev() in anc or b == target]
840 bookmarks.deletedivergent(repo, deletefrom, mark)
840 bookmarks.deletedivergent(repo, deletefrom, mark)
841 if bmctx.rev() in anc:
841 if bmctx.rev() in anc:
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
842 ui.status(_("moving bookmark '%s' forward from %s\n") %
843 (mark, short(bmctx.node())))
843 (mark, short(bmctx.node())))
844 return
844 return
845 raise util.Abort(_("bookmark '%s' already exists "
845 raise util.Abort(_("bookmark '%s' already exists "
846 "(use -f to force)") % mark)
846 "(use -f to force)") % mark)
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
847 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
848 and not force):
848 and not force):
849 raise util.Abort(
849 raise util.Abort(
850 _("a bookmark cannot have the name of an existing branch"))
850 _("a bookmark cannot have the name of an existing branch"))
851
851
852 if delete and rename:
852 if delete and rename:
853 raise util.Abort(_("--delete and --rename are incompatible"))
853 raise util.Abort(_("--delete and --rename are incompatible"))
854 if delete and rev:
854 if delete and rev:
855 raise util.Abort(_("--rev is incompatible with --delete"))
855 raise util.Abort(_("--rev is incompatible with --delete"))
856 if rename and rev:
856 if rename and rev:
857 raise util.Abort(_("--rev is incompatible with --rename"))
857 raise util.Abort(_("--rev is incompatible with --rename"))
858 if not names and (delete or rev):
858 if not names and (delete or rev):
859 raise util.Abort(_("bookmark name required"))
859 raise util.Abort(_("bookmark name required"))
860
860
861 if delete:
861 if delete:
862 for mark in names:
862 for mark in names:
863 if mark not in marks:
863 if mark not in marks:
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
864 raise util.Abort(_("bookmark '%s' does not exist") % mark)
865 if mark == repo._bookmarkcurrent:
865 if mark == repo._bookmarkcurrent:
866 bookmarks.setcurrent(repo, None)
866 bookmarks.setcurrent(repo, None)
867 del marks[mark]
867 del marks[mark]
868 marks.write()
868 marks.write()
869
869
870 elif rename:
870 elif rename:
871 if not names:
871 if not names:
872 raise util.Abort(_("new bookmark name required"))
872 raise util.Abort(_("new bookmark name required"))
873 elif len(names) > 1:
873 elif len(names) > 1:
874 raise util.Abort(_("only one new bookmark name allowed"))
874 raise util.Abort(_("only one new bookmark name allowed"))
875 mark = checkformat(names[0])
875 mark = checkformat(names[0])
876 if rename not in marks:
876 if rename not in marks:
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
877 raise util.Abort(_("bookmark '%s' does not exist") % rename)
878 checkconflict(repo, mark, force)
878 checkconflict(repo, mark, force)
879 marks[mark] = marks[rename]
879 marks[mark] = marks[rename]
880 if repo._bookmarkcurrent == rename and not inactive:
880 if repo._bookmarkcurrent == rename and not inactive:
881 bookmarks.setcurrent(repo, mark)
881 bookmarks.setcurrent(repo, mark)
882 del marks[rename]
882 del marks[rename]
883 marks.write()
883 marks.write()
884
884
885 elif names:
885 elif names:
886 newact = None
886 newact = None
887 for mark in names:
887 for mark in names:
888 mark = checkformat(mark)
888 mark = checkformat(mark)
889 if newact is None:
889 if newact is None:
890 newact = mark
890 newact = mark
891 if inactive and mark == repo._bookmarkcurrent:
891 if inactive and mark == repo._bookmarkcurrent:
892 bookmarks.setcurrent(repo, None)
892 bookmarks.setcurrent(repo, None)
893 return
893 return
894 tgt = cur
894 tgt = cur
895 if rev:
895 if rev:
896 tgt = scmutil.revsingle(repo, rev).node()
896 tgt = scmutil.revsingle(repo, rev).node()
897 checkconflict(repo, mark, force, tgt)
897 checkconflict(repo, mark, force, tgt)
898 marks[mark] = tgt
898 marks[mark] = tgt
899 if not inactive and cur == marks[newact] and not rev:
899 if not inactive and cur == marks[newact] and not rev:
900 bookmarks.setcurrent(repo, newact)
900 bookmarks.setcurrent(repo, newact)
901 elif cur != tgt and newact == repo._bookmarkcurrent:
901 elif cur != tgt and newact == repo._bookmarkcurrent:
902 bookmarks.setcurrent(repo, None)
902 bookmarks.setcurrent(repo, None)
903 marks.write()
903 marks.write()
904
904
905 # Same message whether trying to deactivate the current bookmark (-i
905 # Same message whether trying to deactivate the current bookmark (-i
906 # with no NAME) or listing bookmarks
906 # with no NAME) or listing bookmarks
907 elif len(marks) == 0:
907 elif len(marks) == 0:
908 ui.status(_("no bookmarks set\n"))
908 ui.status(_("no bookmarks set\n"))
909
909
910 elif inactive:
910 elif inactive:
911 if not repo._bookmarkcurrent:
911 if not repo._bookmarkcurrent:
912 ui.status(_("no active bookmark\n"))
912 ui.status(_("no active bookmark\n"))
913 else:
913 else:
914 bookmarks.setcurrent(repo, None)
914 bookmarks.setcurrent(repo, None)
915
915
916 else: # show bookmarks
916 else: # show bookmarks
917 for bmark, n in sorted(marks.iteritems()):
917 for bmark, n in sorted(marks.iteritems()):
918 current = repo._bookmarkcurrent
918 current = repo._bookmarkcurrent
919 if bmark == current:
919 if bmark == current:
920 prefix, label = '*', 'bookmarks.current'
920 prefix, label = '*', 'bookmarks.current'
921 else:
921 else:
922 prefix, label = ' ', ''
922 prefix, label = ' ', ''
923
923
924 if ui.quiet:
924 if ui.quiet:
925 ui.write("%s\n" % bmark, label=label)
925 ui.write("%s\n" % bmark, label=label)
926 else:
926 else:
927 ui.write(" %s %-25s %d:%s\n" % (
927 ui.write(" %s %-25s %d:%s\n" % (
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
928 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
929 label=label)
929 label=label)
930
930
931 @command('branch',
931 @command('branch',
932 [('f', 'force', None,
932 [('f', 'force', None,
933 _('set branch name even if it shadows an existing branch')),
933 _('set branch name even if it shadows an existing branch')),
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
934 ('C', 'clean', None, _('reset branch name to parent branch name'))],
935 _('[-fC] [NAME]'))
935 _('[-fC] [NAME]'))
936 def branch(ui, repo, label=None, **opts):
936 def branch(ui, repo, label=None, **opts):
937 """set or show the current branch name
937 """set or show the current branch name
938
938
939 .. note::
939 .. note::
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
940 Branch names are permanent and global. Use :hg:`bookmark` to create a
941 light-weight bookmark instead. See :hg:`help glossary` for more
941 light-weight bookmark instead. See :hg:`help glossary` for more
942 information about named branches and bookmarks.
942 information about named branches and bookmarks.
943
943
944 With no argument, show the current branch name. With one argument,
944 With no argument, show the current branch name. With one argument,
945 set the working directory branch name (the branch will not exist
945 set the working directory branch name (the branch will not exist
946 in the repository until the next commit). Standard practice
946 in the repository until the next commit). Standard practice
947 recommends that primary development take place on the 'default'
947 recommends that primary development take place on the 'default'
948 branch.
948 branch.
949
949
950 Unless -f/--force is specified, branch will not let you set a
950 Unless -f/--force is specified, branch will not let you set a
951 branch name that already exists, even if it's inactive.
951 branch name that already exists, even if it's inactive.
952
952
953 Use -C/--clean to reset the working directory branch to that of
953 Use -C/--clean to reset the working directory branch to that of
954 the parent of the working directory, negating a previous branch
954 the parent of the working directory, negating a previous branch
955 change.
955 change.
956
956
957 Use the command :hg:`update` to switch to an existing branch. Use
957 Use the command :hg:`update` to switch to an existing branch. Use
958 :hg:`commit --close-branch` to mark this branch as closed.
958 :hg:`commit --close-branch` to mark this branch as closed.
959
959
960 Returns 0 on success.
960 Returns 0 on success.
961 """
961 """
962 if label:
962 if label:
963 label = label.strip()
963 label = label.strip()
964
964
965 if not opts.get('clean') and not label:
965 if not opts.get('clean') and not label:
966 ui.write("%s\n" % repo.dirstate.branch())
966 ui.write("%s\n" % repo.dirstate.branch())
967 return
967 return
968
968
969 wlock = repo.wlock()
969 wlock = repo.wlock()
970 try:
970 try:
971 if opts.get('clean'):
971 if opts.get('clean'):
972 label = repo[None].p1().branch()
972 label = repo[None].p1().branch()
973 repo.dirstate.setbranch(label)
973 repo.dirstate.setbranch(label)
974 ui.status(_('reset working directory to branch %s\n') % label)
974 ui.status(_('reset working directory to branch %s\n') % label)
975 elif label:
975 elif label:
976 if not opts.get('force') and label in repo.branchmap():
976 if not opts.get('force') and label in repo.branchmap():
977 if label not in [p.branch() for p in repo.parents()]:
977 if label not in [p.branch() for p in repo.parents()]:
978 raise util.Abort(_('a branch of the same name already'
978 raise util.Abort(_('a branch of the same name already'
979 ' exists'),
979 ' exists'),
980 # i18n: "it" refers to an existing branch
980 # i18n: "it" refers to an existing branch
981 hint=_("use 'hg update' to switch to it"))
981 hint=_("use 'hg update' to switch to it"))
982 scmutil.checknewlabel(repo, label, 'branch')
982 scmutil.checknewlabel(repo, label, 'branch')
983 repo.dirstate.setbranch(label)
983 repo.dirstate.setbranch(label)
984 ui.status(_('marked working directory as branch %s\n') % label)
984 ui.status(_('marked working directory as branch %s\n') % label)
985 ui.status(_('(branches are permanent and global, '
985 ui.status(_('(branches are permanent and global, '
986 'did you want a bookmark?)\n'))
986 'did you want a bookmark?)\n'))
987 finally:
987 finally:
988 wlock.release()
988 wlock.release()
989
989
990 @command('branches',
990 @command('branches',
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
991 [('a', 'active', False, _('show only branches that have unmerged heads')),
992 ('c', 'closed', False, _('show normal and closed branches'))],
992 ('c', 'closed', False, _('show normal and closed branches'))],
993 _('[-ac]'))
993 _('[-ac]'))
994 def branches(ui, repo, active=False, closed=False):
994 def branches(ui, repo, active=False, closed=False):
995 """list repository named branches
995 """list repository named branches
996
996
997 List the repository's named branches, indicating which ones are
997 List the repository's named branches, indicating which ones are
998 inactive. If -c/--closed is specified, also list branches which have
998 inactive. If -c/--closed is specified, also list branches which have
999 been marked closed (see :hg:`commit --close-branch`).
999 been marked closed (see :hg:`commit --close-branch`).
1000
1000
1001 If -a/--active is specified, only show active branches. A branch
1001 If -a/--active is specified, only show active branches. A branch
1002 is considered active if it contains repository heads.
1002 is considered active if it contains repository heads.
1003
1003
1004 Use the command :hg:`update` to switch to an existing branch.
1004 Use the command :hg:`update` to switch to an existing branch.
1005
1005
1006 Returns 0.
1006 Returns 0.
1007 """
1007 """
1008
1008
1009 hexfunc = ui.debugflag and hex or short
1009 hexfunc = ui.debugflag and hex or short
1010
1010
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1011 activebranches = set([repo[n].branch() for n in repo.heads()])
1012 branches = []
1012 branches = []
1013 for tag, heads in repo.branchmap().iteritems():
1013 for tag, heads in repo.branchmap().iteritems():
1014 for h in reversed(heads):
1014 for h in reversed(heads):
1015 ctx = repo[h]
1015 ctx = repo[h]
1016 isopen = not ctx.closesbranch()
1016 isopen = not ctx.closesbranch()
1017 if isopen:
1017 if isopen:
1018 tip = ctx
1018 tip = ctx
1019 break
1019 break
1020 else:
1020 else:
1021 tip = repo[heads[-1]]
1021 tip = repo[heads[-1]]
1022 isactive = tag in activebranches and isopen
1022 isactive = tag in activebranches and isopen
1023 branches.append((tip, isactive, isopen))
1023 branches.append((tip, isactive, isopen))
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1024 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1025 reverse=True)
1025 reverse=True)
1026
1026
1027 for ctx, isactive, isopen in branches:
1027 for ctx, isactive, isopen in branches:
1028 if (not active) or isactive:
1028 if (not active) or isactive:
1029 if isactive:
1029 if isactive:
1030 label = 'branches.active'
1030 label = 'branches.active'
1031 notice = ''
1031 notice = ''
1032 elif not isopen:
1032 elif not isopen:
1033 if not closed:
1033 if not closed:
1034 continue
1034 continue
1035 label = 'branches.closed'
1035 label = 'branches.closed'
1036 notice = _(' (closed)')
1036 notice = _(' (closed)')
1037 else:
1037 else:
1038 label = 'branches.inactive'
1038 label = 'branches.inactive'
1039 notice = _(' (inactive)')
1039 notice = _(' (inactive)')
1040 if ctx.branch() == repo.dirstate.branch():
1040 if ctx.branch() == repo.dirstate.branch():
1041 label = 'branches.current'
1041 label = 'branches.current'
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1042 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1043 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1044 'log.changeset changeset.%s' % ctx.phasestr())
1044 'log.changeset changeset.%s' % ctx.phasestr())
1045 tag = ui.label(ctx.branch(), label)
1045 tag = ui.label(ctx.branch(), label)
1046 if ui.quiet:
1046 if ui.quiet:
1047 ui.write("%s\n" % tag)
1047 ui.write("%s\n" % tag)
1048 else:
1048 else:
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1049 ui.write("%s %s%s\n" % (tag, rev, notice))
1050
1050
1051 @command('bundle',
1051 @command('bundle',
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1052 [('f', 'force', None, _('run even when the destination is unrelated')),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1053 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1054 _('REV')),
1054 _('REV')),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1055 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1056 _('BRANCH')),
1056 _('BRANCH')),
1057 ('', 'base', [],
1057 ('', 'base', [],
1058 _('a base changeset assumed to be available at the destination'),
1058 _('a base changeset assumed to be available at the destination'),
1059 _('REV')),
1059 _('REV')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1060 ('a', 'all', None, _('bundle all changesets in the repository')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1061 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1062 ] + remoteopts,
1062 ] + remoteopts,
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1063 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1064 def bundle(ui, repo, fname, dest=None, **opts):
1064 def bundle(ui, repo, fname, dest=None, **opts):
1065 """create a changegroup file
1065 """create a changegroup file
1066
1066
1067 Generate a compressed changegroup file collecting changesets not
1067 Generate a compressed changegroup file collecting changesets not
1068 known to be in another repository.
1068 known to be in another repository.
1069
1069
1070 If you omit the destination repository, then hg assumes the
1070 If you omit the destination repository, then hg assumes the
1071 destination will have all the nodes you specify with --base
1071 destination will have all the nodes you specify with --base
1072 parameters. To create a bundle containing all changesets, use
1072 parameters. To create a bundle containing all changesets, use
1073 -a/--all (or --base null).
1073 -a/--all (or --base null).
1074
1074
1075 You can change compression method with the -t/--type option.
1075 You can change compression method with the -t/--type option.
1076 The available compression methods are: none, bzip2, and
1076 The available compression methods are: none, bzip2, and
1077 gzip (by default, bundles are compressed using bzip2).
1077 gzip (by default, bundles are compressed using bzip2).
1078
1078
1079 The bundle file can then be transferred using conventional means
1079 The bundle file can then be transferred using conventional means
1080 and applied to another repository with the unbundle or pull
1080 and applied to another repository with the unbundle or pull
1081 command. This is useful when direct push and pull are not
1081 command. This is useful when direct push and pull are not
1082 available or when exporting an entire repository is undesirable.
1082 available or when exporting an entire repository is undesirable.
1083
1083
1084 Applying bundles preserves all changeset contents including
1084 Applying bundles preserves all changeset contents including
1085 permissions, copy/rename information, and revision history.
1085 permissions, copy/rename information, and revision history.
1086
1086
1087 Returns 0 on success, 1 if no changes found.
1087 Returns 0 on success, 1 if no changes found.
1088 """
1088 """
1089 revs = None
1089 revs = None
1090 if 'rev' in opts:
1090 if 'rev' in opts:
1091 revs = scmutil.revrange(repo, opts['rev'])
1091 revs = scmutil.revrange(repo, opts['rev'])
1092
1092
1093 bundletype = opts.get('type', 'bzip2').lower()
1093 bundletype = opts.get('type', 'bzip2').lower()
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1094 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1095 bundletype = btypes.get(bundletype)
1095 bundletype = btypes.get(bundletype)
1096 if bundletype not in changegroup.bundletypes:
1096 if bundletype not in changegroup.bundletypes:
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1097 raise util.Abort(_('unknown bundle type specified with --type'))
1098
1098
1099 if opts.get('all'):
1099 if opts.get('all'):
1100 base = ['null']
1100 base = ['null']
1101 else:
1101 else:
1102 base = scmutil.revrange(repo, opts.get('base'))
1102 base = scmutil.revrange(repo, opts.get('base'))
1103 # TODO: get desired bundlecaps from command line.
1103 # TODO: get desired bundlecaps from command line.
1104 bundlecaps = None
1104 bundlecaps = None
1105 if base:
1105 if base:
1106 if dest:
1106 if dest:
1107 raise util.Abort(_("--base is incompatible with specifying "
1107 raise util.Abort(_("--base is incompatible with specifying "
1108 "a destination"))
1108 "a destination"))
1109 common = [repo.lookup(rev) for rev in base]
1109 common = [repo.lookup(rev) for rev in base]
1110 heads = revs and map(repo.lookup, revs) or revs
1110 heads = revs and map(repo.lookup, revs) or revs
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1111 cg = repo.getbundle('bundle', heads=heads, common=common,
1112 bundlecaps=bundlecaps)
1112 bundlecaps=bundlecaps)
1113 outgoing = None
1113 outgoing = None
1114 else:
1114 else:
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1115 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1116 dest, branches = hg.parseurl(dest, opts.get('branch'))
1117 other = hg.peer(repo, opts, dest)
1117 other = hg.peer(repo, opts, dest)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1118 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1119 heads = revs and map(repo.lookup, revs) or revs
1119 heads = revs and map(repo.lookup, revs) or revs
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1120 outgoing = discovery.findcommonoutgoing(repo, other,
1121 onlyheads=heads,
1121 onlyheads=heads,
1122 force=opts.get('force'),
1122 force=opts.get('force'),
1123 portable=True)
1123 portable=True)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1124 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1125 if not cg:
1125 if not cg:
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1126 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1127 return 1
1127 return 1
1128
1128
1129 changegroup.writebundle(cg, fname, bundletype)
1129 changegroup.writebundle(cg, fname, bundletype)
1130
1130
1131 @command('cat',
1131 @command('cat',
1132 [('o', 'output', '',
1132 [('o', 'output', '',
1133 _('print output to file with formatted name'), _('FORMAT')),
1133 _('print output to file with formatted name'), _('FORMAT')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1134 ('r', 'rev', '', _('print the given revision'), _('REV')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1135 ('', 'decode', None, _('apply any matching decode filter')),
1136 ] + walkopts,
1136 ] + walkopts,
1137 _('[OPTION]... FILE...'))
1137 _('[OPTION]... FILE...'))
1138 def cat(ui, repo, file1, *pats, **opts):
1138 def cat(ui, repo, file1, *pats, **opts):
1139 """output the current or given revision of files
1139 """output the current or given revision of files
1140
1140
1141 Print the specified files as they were at the given revision. If
1141 Print the specified files as they were at the given revision. If
1142 no revision is given, the parent of the working directory is used.
1142 no revision is given, the parent of the working directory is used.
1143
1143
1144 Output may be to a file, in which case the name of the file is
1144 Output may be to a file, in which case the name of the file is
1145 given using a format string. The formatting rules are the same as
1145 given using a format string. The formatting rules are the same as
1146 for the export command, with the following additions:
1146 for the export command, with the following additions:
1147
1147
1148 :``%s``: basename of file being printed
1148 :``%s``: basename of file being printed
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1149 :``%d``: dirname of file being printed, or '.' if in repository root
1150 :``%p``: root-relative path name of file being printed
1150 :``%p``: root-relative path name of file being printed
1151
1151
1152 Returns 0 on success.
1152 Returns 0 on success.
1153 """
1153 """
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1154 ctx = scmutil.revsingle(repo, opts.get('rev'))
1155 err = 1
1155 err = 1
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1156 m = scmutil.match(ctx, (file1,) + pats, opts)
1157 for abs in ctx.walk(m):
1157 for abs in ctx.walk(m):
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1158 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1159 pathname=abs)
1159 pathname=abs)
1160 data = ctx[abs].data()
1160 data = ctx[abs].data()
1161 if opts.get('decode'):
1161 if opts.get('decode'):
1162 data = repo.wwritedata(abs, data)
1162 data = repo.wwritedata(abs, data)
1163 fp.write(data)
1163 fp.write(data)
1164 fp.close()
1164 fp.close()
1165 err = 0
1165 err = 0
1166 return err
1166 return err
1167
1167
1168 @command('^clone',
1168 @command('^clone',
1169 [('U', 'noupdate', None,
1169 [('U', 'noupdate', None,
1170 _('the clone will include an empty working copy (only a repository)')),
1170 _('the clone will include an empty working copy (only a repository)')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1171 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1172 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1173 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1174 ('', 'pull', None, _('use pull protocol to copy metadata')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1175 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1176 ] + remoteopts,
1176 ] + remoteopts,
1177 _('[OPTION]... SOURCE [DEST]'))
1177 _('[OPTION]... SOURCE [DEST]'))
1178 def clone(ui, source, dest=None, **opts):
1178 def clone(ui, source, dest=None, **opts):
1179 """make a copy of an existing repository
1179 """make a copy of an existing repository
1180
1180
1181 Create a copy of an existing repository in a new directory.
1181 Create a copy of an existing repository in a new directory.
1182
1182
1183 If no destination directory name is specified, it defaults to the
1183 If no destination directory name is specified, it defaults to the
1184 basename of the source.
1184 basename of the source.
1185
1185
1186 The location of the source is added to the new repository's
1186 The location of the source is added to the new repository's
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1187 ``.hg/hgrc`` file, as the default to be used for future pulls.
1188
1188
1189 Only local paths and ``ssh://`` URLs are supported as
1189 Only local paths and ``ssh://`` URLs are supported as
1190 destinations. For ``ssh://`` destinations, no working directory or
1190 destinations. For ``ssh://`` destinations, no working directory or
1191 ``.hg/hgrc`` will be created on the remote side.
1191 ``.hg/hgrc`` will be created on the remote side.
1192
1192
1193 To pull only a subset of changesets, specify one or more revisions
1193 To pull only a subset of changesets, specify one or more revisions
1194 identifiers with -r/--rev or branches with -b/--branch. The
1194 identifiers with -r/--rev or branches with -b/--branch. The
1195 resulting clone will contain only the specified changesets and
1195 resulting clone will contain only the specified changesets and
1196 their ancestors. These options (or 'clone src#rev dest') imply
1196 their ancestors. These options (or 'clone src#rev dest') imply
1197 --pull, even for local source repositories. Note that specifying a
1197 --pull, even for local source repositories. Note that specifying a
1198 tag will include the tagged changeset but not the changeset
1198 tag will include the tagged changeset but not the changeset
1199 containing the tag.
1199 containing the tag.
1200
1200
1201 If the source repository has a bookmark called '@' set, that
1201 If the source repository has a bookmark called '@' set, that
1202 revision will be checked out in the new repository by default.
1202 revision will be checked out in the new repository by default.
1203
1203
1204 To check out a particular version, use -u/--update, or
1204 To check out a particular version, use -u/--update, or
1205 -U/--noupdate to create a clone with no working directory.
1205 -U/--noupdate to create a clone with no working directory.
1206
1206
1207 .. container:: verbose
1207 .. container:: verbose
1208
1208
1209 For efficiency, hardlinks are used for cloning whenever the
1209 For efficiency, hardlinks are used for cloning whenever the
1210 source and destination are on the same filesystem (note this
1210 source and destination are on the same filesystem (note this
1211 applies only to the repository data, not to the working
1211 applies only to the repository data, not to the working
1212 directory). Some filesystems, such as AFS, implement hardlinking
1212 directory). Some filesystems, such as AFS, implement hardlinking
1213 incorrectly, but do not report errors. In these cases, use the
1213 incorrectly, but do not report errors. In these cases, use the
1214 --pull option to avoid hardlinking.
1214 --pull option to avoid hardlinking.
1215
1215
1216 In some cases, you can clone repositories and the working
1216 In some cases, you can clone repositories and the working
1217 directory using full hardlinks with ::
1217 directory using full hardlinks with ::
1218
1218
1219 $ cp -al REPO REPOCLONE
1219 $ cp -al REPO REPOCLONE
1220
1220
1221 This is the fastest way to clone, but it is not always safe. The
1221 This is the fastest way to clone, but it is not always safe. The
1222 operation is not atomic (making sure REPO is not modified during
1222 operation is not atomic (making sure REPO is not modified during
1223 the operation is up to you) and you have to make sure your
1223 the operation is up to you) and you have to make sure your
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1224 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1225 so). Also, this is not compatible with certain extensions that
1225 so). Also, this is not compatible with certain extensions that
1226 place their metadata under the .hg directory, such as mq.
1226 place their metadata under the .hg directory, such as mq.
1227
1227
1228 Mercurial will update the working directory to the first applicable
1228 Mercurial will update the working directory to the first applicable
1229 revision from this list:
1229 revision from this list:
1230
1230
1231 a) null if -U or the source repository has no changesets
1231 a) null if -U or the source repository has no changesets
1232 b) if -u . and the source repository is local, the first parent of
1232 b) if -u . and the source repository is local, the first parent of
1233 the source repository's working directory
1233 the source repository's working directory
1234 c) the changeset specified with -u (if a branch name, this means the
1234 c) the changeset specified with -u (if a branch name, this means the
1235 latest head of that branch)
1235 latest head of that branch)
1236 d) the changeset specified with -r
1236 d) the changeset specified with -r
1237 e) the tipmost head specified with -b
1237 e) the tipmost head specified with -b
1238 f) the tipmost head specified with the url#branch source syntax
1238 f) the tipmost head specified with the url#branch source syntax
1239 g) the revision marked with the '@' bookmark, if present
1239 g) the revision marked with the '@' bookmark, if present
1240 h) the tipmost head of the default branch
1240 h) the tipmost head of the default branch
1241 i) tip
1241 i) tip
1242
1242
1243 Examples:
1243 Examples:
1244
1244
1245 - clone a remote repository to a new directory named hg/::
1245 - clone a remote repository to a new directory named hg/::
1246
1246
1247 hg clone http://selenic.com/hg
1247 hg clone http://selenic.com/hg
1248
1248
1249 - create a lightweight local clone::
1249 - create a lightweight local clone::
1250
1250
1251 hg clone project/ project-feature/
1251 hg clone project/ project-feature/
1252
1252
1253 - clone from an absolute path on an ssh server (note double-slash)::
1253 - clone from an absolute path on an ssh server (note double-slash)::
1254
1254
1255 hg clone ssh://user@server//home/projects/alpha/
1255 hg clone ssh://user@server//home/projects/alpha/
1256
1256
1257 - do a high-speed clone over a LAN while checking out a
1257 - do a high-speed clone over a LAN while checking out a
1258 specified version::
1258 specified version::
1259
1259
1260 hg clone --uncompressed http://server/repo -u 1.5
1260 hg clone --uncompressed http://server/repo -u 1.5
1261
1261
1262 - create a repository without changesets after a particular revision::
1262 - create a repository without changesets after a particular revision::
1263
1263
1264 hg clone -r 04e544 experimental/ good/
1264 hg clone -r 04e544 experimental/ good/
1265
1265
1266 - clone (and track) a particular named branch::
1266 - clone (and track) a particular named branch::
1267
1267
1268 hg clone http://selenic.com/hg#stable
1268 hg clone http://selenic.com/hg#stable
1269
1269
1270 See :hg:`help urls` for details on specifying URLs.
1270 See :hg:`help urls` for details on specifying URLs.
1271
1271
1272 Returns 0 on success.
1272 Returns 0 on success.
1273 """
1273 """
1274 if opts.get('noupdate') and opts.get('updaterev'):
1274 if opts.get('noupdate') and opts.get('updaterev'):
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1275 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1276
1276
1277 r = hg.clone(ui, opts, source, dest,
1277 r = hg.clone(ui, opts, source, dest,
1278 pull=opts.get('pull'),
1278 pull=opts.get('pull'),
1279 stream=opts.get('uncompressed'),
1279 stream=opts.get('uncompressed'),
1280 rev=opts.get('rev'),
1280 rev=opts.get('rev'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1281 update=opts.get('updaterev') or not opts.get('noupdate'),
1282 branch=opts.get('branch'))
1282 branch=opts.get('branch'))
1283
1283
1284 return r is None
1284 return r is None
1285
1285
1286 @command('^commit|ci',
1286 @command('^commit|ci',
1287 [('A', 'addremove', None,
1287 [('A', 'addremove', None,
1288 _('mark new/missing files as added/removed before committing')),
1288 _('mark new/missing files as added/removed before committing')),
1289 ('', 'close-branch', None,
1289 ('', 'close-branch', None,
1290 _('mark a branch as closed, hiding it from the branch list')),
1290 _('mark a branch as closed, hiding it from the branch list')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1291 ('', 'amend', None, _('amend the parent of the working dir')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1292 ('s', 'secret', None, _('use the secret phase for committing')),
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1293 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1294 _('[OPTION]... [FILE]...'))
1294 _('[OPTION]... [FILE]...'))
1295 def commit(ui, repo, *pats, **opts):
1295 def commit(ui, repo, *pats, **opts):
1296 """commit the specified files or all outstanding changes
1296 """commit the specified files or all outstanding changes
1297
1297
1298 Commit changes to the given files into the repository. Unlike a
1298 Commit changes to the given files into the repository. Unlike a
1299 centralized SCM, this operation is a local operation. See
1299 centralized SCM, this operation is a local operation. See
1300 :hg:`push` for a way to actively distribute your changes.
1300 :hg:`push` for a way to actively distribute your changes.
1301
1301
1302 If a list of files is omitted, all changes reported by :hg:`status`
1302 If a list of files is omitted, all changes reported by :hg:`status`
1303 will be committed.
1303 will be committed.
1304
1304
1305 If you are committing the result of a merge, do not provide any
1305 If you are committing the result of a merge, do not provide any
1306 filenames or -I/-X filters.
1306 filenames or -I/-X filters.
1307
1307
1308 If no commit message is specified, Mercurial starts your
1308 If no commit message is specified, Mercurial starts your
1309 configured editor where you can enter a message. In case your
1309 configured editor where you can enter a message. In case your
1310 commit fails, you will find a backup of your message in
1310 commit fails, you will find a backup of your message in
1311 ``.hg/last-message.txt``.
1311 ``.hg/last-message.txt``.
1312
1312
1313 The --amend flag can be used to amend the parent of the
1313 The --amend flag can be used to amend the parent of the
1314 working directory with a new commit that contains the changes
1314 working directory with a new commit that contains the changes
1315 in the parent in addition to those currently reported by :hg:`status`,
1315 in the parent in addition to those currently reported by :hg:`status`,
1316 if there are any. The old commit is stored in a backup bundle in
1316 if there are any. The old commit is stored in a backup bundle in
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1317 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1318 on how to restore it).
1318 on how to restore it).
1319
1319
1320 Message, user and date are taken from the amended commit unless
1320 Message, user and date are taken from the amended commit unless
1321 specified. When a message isn't specified on the command line,
1321 specified. When a message isn't specified on the command line,
1322 the editor will open with the message of the amended commit.
1322 the editor will open with the message of the amended commit.
1323
1323
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1324 It is not possible to amend public changesets (see :hg:`help phases`)
1325 or changesets that have children.
1325 or changesets that have children.
1326
1326
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1327 See :hg:`help dates` for a list of formats valid for -d/--date.
1328
1328
1329 Returns 0 on success, 1 if nothing changed.
1329 Returns 0 on success, 1 if nothing changed.
1330 """
1330 """
1331 if opts.get('subrepos'):
1331 if opts.get('subrepos'):
1332 if opts.get('amend'):
1332 if opts.get('amend'):
1333 raise util.Abort(_('cannot amend with --subrepos'))
1333 raise util.Abort(_('cannot amend with --subrepos'))
1334 # Let --subrepos on the command line override config setting.
1334 # Let --subrepos on the command line override config setting.
1335 ui.setconfig('ui', 'commitsubrepos', True)
1335 ui.setconfig('ui', 'commitsubrepos', True)
1336
1336
1337 # Save this for restoring it later
1337 # Save this for restoring it later
1338 oldcommitphase = ui.config('phases', 'new-commit')
1338 oldcommitphase = ui.config('phases', 'new-commit')
1339
1339
1340 cmdutil.checkunfinished(repo, commit=True)
1340 cmdutil.checkunfinished(repo, commit=True)
1341
1341
1342 branch = repo[None].branch()
1342 branch = repo[None].branch()
1343 bheads = repo.branchheads(branch)
1343 bheads = repo.branchheads(branch)
1344
1344
1345 extra = {}
1345 extra = {}
1346 if opts.get('close_branch'):
1346 if opts.get('close_branch'):
1347 extra['close'] = 1
1347 extra['close'] = 1
1348
1348
1349 if not bheads:
1349 if not bheads:
1350 raise util.Abort(_('can only close branch heads'))
1350 raise util.Abort(_('can only close branch heads'))
1351 elif opts.get('amend'):
1351 elif opts.get('amend'):
1352 if repo.parents()[0].p1().branch() != branch and \
1352 if repo.parents()[0].p1().branch() != branch and \
1353 repo.parents()[0].p2().branch() != branch:
1353 repo.parents()[0].p2().branch() != branch:
1354 raise util.Abort(_('can only close branch heads'))
1354 raise util.Abort(_('can only close branch heads'))
1355
1355
1356 if opts.get('amend'):
1356 if opts.get('amend'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1357 if ui.configbool('ui', 'commitsubrepos'):
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1358 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1359
1359
1360 old = repo['.']
1360 old = repo['.']
1361 if old.phase() == phases.public:
1361 if old.phase() == phases.public:
1362 raise util.Abort(_('cannot amend public changesets'))
1362 raise util.Abort(_('cannot amend public changesets'))
1363 if len(repo[None].parents()) > 1:
1363 if len(repo[None].parents()) > 1:
1364 raise util.Abort(_('cannot amend while merging'))
1364 raise util.Abort(_('cannot amend while merging'))
1365 if (not obsolete._enabled) and old.children():
1365 if (not obsolete._enabled) and old.children():
1366 raise util.Abort(_('cannot amend changeset with children'))
1366 raise util.Abort(_('cannot amend changeset with children'))
1367
1367
1368 e = cmdutil.commiteditor
1368 e = cmdutil.commiteditor
1369 if opts.get('force_editor'):
1369 if opts.get('force_editor'):
1370 e = cmdutil.commitforceeditor
1370 e = cmdutil.commitforceeditor
1371
1371
1372 def commitfunc(ui, repo, message, match, opts):
1372 def commitfunc(ui, repo, message, match, opts):
1373 editor = e
1373 editor = e
1374 # message contains text from -m or -l, if it's empty,
1374 # message contains text from -m or -l, if it's empty,
1375 # open the editor with the old message
1375 # open the editor with the old message
1376 if not message:
1376 if not message:
1377 message = old.description()
1377 message = old.description()
1378 editor = cmdutil.commitforceeditor
1378 editor = cmdutil.commitforceeditor
1379 try:
1379 try:
1380 if opts.get('secret'):
1380 if opts.get('secret'):
1381 ui.setconfig('phases', 'new-commit', 'secret')
1381 ui.setconfig('phases', 'new-commit', 'secret')
1382
1382
1383 return repo.commit(message,
1383 return repo.commit(message,
1384 opts.get('user') or old.user(),
1384 opts.get('user') or old.user(),
1385 opts.get('date') or old.date(),
1385 opts.get('date') or old.date(),
1386 match,
1386 match,
1387 editor=editor,
1387 editor=editor,
1388 extra=extra)
1388 extra=extra)
1389 finally:
1389 finally:
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1390 ui.setconfig('phases', 'new-commit', oldcommitphase)
1391
1391
1392 current = repo._bookmarkcurrent
1392 current = repo._bookmarkcurrent
1393 marks = old.bookmarks()
1393 marks = old.bookmarks()
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1394 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1395 if node == old.node():
1395 if node == old.node():
1396 ui.status(_("nothing changed\n"))
1396 ui.status(_("nothing changed\n"))
1397 return 1
1397 return 1
1398 elif marks:
1398 elif marks:
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1399 ui.debug('moving bookmarks %r from %s to %s\n' %
1400 (marks, old.hex(), hex(node)))
1400 (marks, old.hex(), hex(node)))
1401 newmarks = repo._bookmarks
1401 newmarks = repo._bookmarks
1402 for bm in marks:
1402 for bm in marks:
1403 newmarks[bm] = node
1403 newmarks[bm] = node
1404 if bm == current:
1404 if bm == current:
1405 bookmarks.setcurrent(repo, bm)
1405 bookmarks.setcurrent(repo, bm)
1406 newmarks.write()
1406 newmarks.write()
1407 else:
1407 else:
1408 e = cmdutil.commiteditor
1408 e = cmdutil.commiteditor
1409 if opts.get('force_editor'):
1409 if opts.get('force_editor'):
1410 e = cmdutil.commitforceeditor
1410 e = cmdutil.commitforceeditor
1411
1411
1412 def commitfunc(ui, repo, message, match, opts):
1412 def commitfunc(ui, repo, message, match, opts):
1413 try:
1413 try:
1414 if opts.get('secret'):
1414 if opts.get('secret'):
1415 ui.setconfig('phases', 'new-commit', 'secret')
1415 ui.setconfig('phases', 'new-commit', 'secret')
1416
1416
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1417 return repo.commit(message, opts.get('user'), opts.get('date'),
1418 match, editor=e, extra=extra)
1418 match, editor=e, extra=extra)
1419 finally:
1419 finally:
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1420 ui.setconfig('phases', 'new-commit', oldcommitphase)
1421
1421
1422
1422
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1424
1424
1425 if not node:
1425 if not node:
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1426 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1427 if stat[3]:
1427 if stat[3]:
1428 ui.status(_("nothing changed (%d missing files, see "
1428 ui.status(_("nothing changed (%d missing files, see "
1429 "'hg status')\n") % len(stat[3]))
1429 "'hg status')\n") % len(stat[3]))
1430 else:
1430 else:
1431 ui.status(_("nothing changed\n"))
1431 ui.status(_("nothing changed\n"))
1432 return 1
1432 return 1
1433
1433
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1434 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1435
1435
1436 @command('copy|cp',
1436 @command('copy|cp',
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1437 [('A', 'after', None, _('record a copy that has already occurred')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1438 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1439 ] + walkopts + dryrunopts,
1439 ] + walkopts + dryrunopts,
1440 _('[OPTION]... [SOURCE]... DEST'))
1440 _('[OPTION]... [SOURCE]... DEST'))
1441 def copy(ui, repo, *pats, **opts):
1441 def copy(ui, repo, *pats, **opts):
1442 """mark files as copied for the next commit
1442 """mark files as copied for the next commit
1443
1443
1444 Mark dest as having copies of source files. If dest is a
1444 Mark dest as having copies of source files. If dest is a
1445 directory, copies are put in that directory. If dest is a file,
1445 directory, copies are put in that directory. If dest is a file,
1446 the source must be a single file.
1446 the source must be a single file.
1447
1447
1448 By default, this command copies the contents of files as they
1448 By default, this command copies the contents of files as they
1449 exist in the working directory. If invoked with -A/--after, the
1449 exist in the working directory. If invoked with -A/--after, the
1450 operation is recorded, but no copying is performed.
1450 operation is recorded, but no copying is performed.
1451
1451
1452 This command takes effect with the next commit. To undo a copy
1452 This command takes effect with the next commit. To undo a copy
1453 before that, see :hg:`revert`.
1453 before that, see :hg:`revert`.
1454
1454
1455 Returns 0 on success, 1 if errors are encountered.
1455 Returns 0 on success, 1 if errors are encountered.
1456 """
1456 """
1457 wlock = repo.wlock(False)
1457 wlock = repo.wlock(False)
1458 try:
1458 try:
1459 return cmdutil.copy(ui, repo, pats, opts)
1459 return cmdutil.copy(ui, repo, pats, opts)
1460 finally:
1460 finally:
1461 wlock.release()
1461 wlock.release()
1462
1462
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1463 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1464 def debugancestor(ui, repo, *args):
1464 def debugancestor(ui, repo, *args):
1465 """find the ancestor revision of two revisions in a given index"""
1465 """find the ancestor revision of two revisions in a given index"""
1466 if len(args) == 3:
1466 if len(args) == 3:
1467 index, rev1, rev2 = args
1467 index, rev1, rev2 = args
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1468 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1469 lookup = r.lookup
1469 lookup = r.lookup
1470 elif len(args) == 2:
1470 elif len(args) == 2:
1471 if not repo:
1471 if not repo:
1472 raise util.Abort(_("there is no Mercurial repository here "
1472 raise util.Abort(_("there is no Mercurial repository here "
1473 "(.hg not found)"))
1473 "(.hg not found)"))
1474 rev1, rev2 = args
1474 rev1, rev2 = args
1475 r = repo.changelog
1475 r = repo.changelog
1476 lookup = repo.lookup
1476 lookup = repo.lookup
1477 else:
1477 else:
1478 raise util.Abort(_('either two or three arguments required'))
1478 raise util.Abort(_('either two or three arguments required'))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1479 a = r.ancestor(lookup(rev1), lookup(rev2))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1480 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1481
1481
1482 @command('debugbuilddag',
1482 @command('debugbuilddag',
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1483 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1484 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1485 ('n', 'new-file', None, _('add new file at each rev'))],
1486 _('[OPTION]... [TEXT]'))
1486 _('[OPTION]... [TEXT]'))
1487 def debugbuilddag(ui, repo, text=None,
1487 def debugbuilddag(ui, repo, text=None,
1488 mergeable_file=False,
1488 mergeable_file=False,
1489 overwritten_file=False,
1489 overwritten_file=False,
1490 new_file=False):
1490 new_file=False):
1491 """builds a repo with a given DAG from scratch in the current empty repo
1491 """builds a repo with a given DAG from scratch in the current empty repo
1492
1492
1493 The description of the DAG is read from stdin if not given on the
1493 The description of the DAG is read from stdin if not given on the
1494 command line.
1494 command line.
1495
1495
1496 Elements:
1496 Elements:
1497
1497
1498 - "+n" is a linear run of n nodes based on the current default parent
1498 - "+n" is a linear run of n nodes based on the current default parent
1499 - "." is a single node based on the current default parent
1499 - "." is a single node based on the current default parent
1500 - "$" resets the default parent to null (implied at the start);
1500 - "$" resets the default parent to null (implied at the start);
1501 otherwise the default parent is always the last node created
1501 otherwise the default parent is always the last node created
1502 - "<p" sets the default parent to the backref p
1502 - "<p" sets the default parent to the backref p
1503 - "*p" is a fork at parent p, which is a backref
1503 - "*p" is a fork at parent p, which is a backref
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1504 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1505 - "/p2" is a merge of the preceding node and p2
1505 - "/p2" is a merge of the preceding node and p2
1506 - ":tag" defines a local tag for the preceding node
1506 - ":tag" defines a local tag for the preceding node
1507 - "@branch" sets the named branch for subsequent nodes
1507 - "@branch" sets the named branch for subsequent nodes
1508 - "#...\\n" is a comment up to the end of the line
1508 - "#...\\n" is a comment up to the end of the line
1509
1509
1510 Whitespace between the above elements is ignored.
1510 Whitespace between the above elements is ignored.
1511
1511
1512 A backref is either
1512 A backref is either
1513
1513
1514 - a number n, which references the node curr-n, where curr is the current
1514 - a number n, which references the node curr-n, where curr is the current
1515 node, or
1515 node, or
1516 - the name of a local tag you placed earlier using ":tag", or
1516 - the name of a local tag you placed earlier using ":tag", or
1517 - empty to denote the default parent.
1517 - empty to denote the default parent.
1518
1518
1519 All string valued-elements are either strictly alphanumeric, or must
1519 All string valued-elements are either strictly alphanumeric, or must
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1520 be enclosed in double quotes ("..."), with "\\" as escape character.
1521 """
1521 """
1522
1522
1523 if text is None:
1523 if text is None:
1524 ui.status(_("reading DAG from stdin\n"))
1524 ui.status(_("reading DAG from stdin\n"))
1525 text = ui.fin.read()
1525 text = ui.fin.read()
1526
1526
1527 cl = repo.changelog
1527 cl = repo.changelog
1528 if len(cl) > 0:
1528 if len(cl) > 0:
1529 raise util.Abort(_('repository is not empty'))
1529 raise util.Abort(_('repository is not empty'))
1530
1530
1531 # determine number of revs in DAG
1531 # determine number of revs in DAG
1532 total = 0
1532 total = 0
1533 for type, data in dagparser.parsedag(text):
1533 for type, data in dagparser.parsedag(text):
1534 if type == 'n':
1534 if type == 'n':
1535 total += 1
1535 total += 1
1536
1536
1537 if mergeable_file:
1537 if mergeable_file:
1538 linesperrev = 2
1538 linesperrev = 2
1539 # make a file with k lines per rev
1539 # make a file with k lines per rev
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1540 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1541 initialmergedlines.append("")
1541 initialmergedlines.append("")
1542
1542
1543 tags = []
1543 tags = []
1544
1544
1545 lock = tr = None
1545 lock = tr = None
1546 try:
1546 try:
1547 lock = repo.lock()
1547 lock = repo.lock()
1548 tr = repo.transaction("builddag")
1548 tr = repo.transaction("builddag")
1549
1549
1550 at = -1
1550 at = -1
1551 atbranch = 'default'
1551 atbranch = 'default'
1552 nodeids = []
1552 nodeids = []
1553 id = 0
1553 id = 0
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1554 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1555 for type, data in dagparser.parsedag(text):
1555 for type, data in dagparser.parsedag(text):
1556 if type == 'n':
1556 if type == 'n':
1557 ui.note(('node %s\n' % str(data)))
1557 ui.note(('node %s\n' % str(data)))
1558 id, ps = data
1558 id, ps = data
1559
1559
1560 files = []
1560 files = []
1561 fctxs = {}
1561 fctxs = {}
1562
1562
1563 p2 = None
1563 p2 = None
1564 if mergeable_file:
1564 if mergeable_file:
1565 fn = "mf"
1565 fn = "mf"
1566 p1 = repo[ps[0]]
1566 p1 = repo[ps[0]]
1567 if len(ps) > 1:
1567 if len(ps) > 1:
1568 p2 = repo[ps[1]]
1568 p2 = repo[ps[1]]
1569 pa = p1.ancestor(p2)
1569 pa = p1.ancestor(p2)
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1570 base, local, other = [x[fn].data() for x in (pa, p1,
1571 p2)]
1571 p2)]
1572 m3 = simplemerge.Merge3Text(base, local, other)
1572 m3 = simplemerge.Merge3Text(base, local, other)
1573 ml = [l.strip() for l in m3.merge_lines()]
1573 ml = [l.strip() for l in m3.merge_lines()]
1574 ml.append("")
1574 ml.append("")
1575 elif at > 0:
1575 elif at > 0:
1576 ml = p1[fn].data().split("\n")
1576 ml = p1[fn].data().split("\n")
1577 else:
1577 else:
1578 ml = initialmergedlines
1578 ml = initialmergedlines
1579 ml[id * linesperrev] += " r%i" % id
1579 ml[id * linesperrev] += " r%i" % id
1580 mergedtext = "\n".join(ml)
1580 mergedtext = "\n".join(ml)
1581 files.append(fn)
1581 files.append(fn)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1582 fctxs[fn] = context.memfilectx(fn, mergedtext)
1583
1583
1584 if overwritten_file:
1584 if overwritten_file:
1585 fn = "of"
1585 fn = "of"
1586 files.append(fn)
1586 files.append(fn)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1587 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1588
1588
1589 if new_file:
1589 if new_file:
1590 fn = "nf%i" % id
1590 fn = "nf%i" % id
1591 files.append(fn)
1591 files.append(fn)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1593 if len(ps) > 1:
1593 if len(ps) > 1:
1594 if not p2:
1594 if not p2:
1595 p2 = repo[ps[1]]
1595 p2 = repo[ps[1]]
1596 for fn in p2:
1596 for fn in p2:
1597 if fn.startswith("nf"):
1597 if fn.startswith("nf"):
1598 files.append(fn)
1598 files.append(fn)
1599 fctxs[fn] = p2[fn]
1599 fctxs[fn] = p2[fn]
1600
1600
1601 def fctxfn(repo, cx, path):
1601 def fctxfn(repo, cx, path):
1602 return fctxs.get(path)
1602 return fctxs.get(path)
1603
1603
1604 if len(ps) == 0 or ps[0] < 0:
1604 if len(ps) == 0 or ps[0] < 0:
1605 pars = [None, None]
1605 pars = [None, None]
1606 elif len(ps) == 1:
1606 elif len(ps) == 1:
1607 pars = [nodeids[ps[0]], None]
1607 pars = [nodeids[ps[0]], None]
1608 else:
1608 else:
1609 pars = [nodeids[p] for p in ps]
1609 pars = [nodeids[p] for p in ps]
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1610 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1611 date=(id, 0),
1611 date=(id, 0),
1612 user="debugbuilddag",
1612 user="debugbuilddag",
1613 extra={'branch': atbranch})
1613 extra={'branch': atbranch})
1614 nodeid = repo.commitctx(cx)
1614 nodeid = repo.commitctx(cx)
1615 nodeids.append(nodeid)
1615 nodeids.append(nodeid)
1616 at = id
1616 at = id
1617 elif type == 'l':
1617 elif type == 'l':
1618 id, name = data
1618 id, name = data
1619 ui.note(('tag %s\n' % name))
1619 ui.note(('tag %s\n' % name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1620 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1621 elif type == 'a':
1621 elif type == 'a':
1622 ui.note(('branch %s\n' % data))
1622 ui.note(('branch %s\n' % data))
1623 atbranch = data
1623 atbranch = data
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1624 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1625 tr.close()
1625 tr.close()
1626
1626
1627 if tags:
1627 if tags:
1628 repo.opener.write("localtags", "".join(tags))
1628 repo.opener.write("localtags", "".join(tags))
1629 finally:
1629 finally:
1630 ui.progress(_('building'), None)
1630 ui.progress(_('building'), None)
1631 release(tr, lock)
1631 release(tr, lock)
1632
1632
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1633 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1634 def debugbundle(ui, bundlepath, all=None, **opts):
1635 """lists the contents of a bundle"""
1635 """lists the contents of a bundle"""
1636 f = hg.openpath(ui, bundlepath)
1636 f = hg.openpath(ui, bundlepath)
1637 try:
1637 try:
1638 gen = changegroup.readbundle(f, bundlepath)
1638 gen = changegroup.readbundle(f, bundlepath)
1639 if all:
1639 if all:
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1640 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1641
1641
1642 def showchunks(named):
1642 def showchunks(named):
1643 ui.write("\n%s\n" % named)
1643 ui.write("\n%s\n" % named)
1644 chain = None
1644 chain = None
1645 while True:
1645 while True:
1646 chunkdata = gen.deltachunk(chain)
1646 chunkdata = gen.deltachunk(chain)
1647 if not chunkdata:
1647 if not chunkdata:
1648 break
1648 break
1649 node = chunkdata['node']
1649 node = chunkdata['node']
1650 p1 = chunkdata['p1']
1650 p1 = chunkdata['p1']
1651 p2 = chunkdata['p2']
1651 p2 = chunkdata['p2']
1652 cs = chunkdata['cs']
1652 cs = chunkdata['cs']
1653 deltabase = chunkdata['deltabase']
1653 deltabase = chunkdata['deltabase']
1654 delta = chunkdata['delta']
1654 delta = chunkdata['delta']
1655 ui.write("%s %s %s %s %s %s\n" %
1655 ui.write("%s %s %s %s %s %s\n" %
1656 (hex(node), hex(p1), hex(p2),
1656 (hex(node), hex(p1), hex(p2),
1657 hex(cs), hex(deltabase), len(delta)))
1657 hex(cs), hex(deltabase), len(delta)))
1658 chain = node
1658 chain = node
1659
1659
1660 chunkdata = gen.changelogheader()
1660 chunkdata = gen.changelogheader()
1661 showchunks("changelog")
1661 showchunks("changelog")
1662 chunkdata = gen.manifestheader()
1662 chunkdata = gen.manifestheader()
1663 showchunks("manifest")
1663 showchunks("manifest")
1664 while True:
1664 while True:
1665 chunkdata = gen.filelogheader()
1665 chunkdata = gen.filelogheader()
1666 if not chunkdata:
1666 if not chunkdata:
1667 break
1667 break
1668 fname = chunkdata['filename']
1668 fname = chunkdata['filename']
1669 showchunks(fname)
1669 showchunks(fname)
1670 else:
1670 else:
1671 chunkdata = gen.changelogheader()
1671 chunkdata = gen.changelogheader()
1672 chain = None
1672 chain = None
1673 while True:
1673 while True:
1674 chunkdata = gen.deltachunk(chain)
1674 chunkdata = gen.deltachunk(chain)
1675 if not chunkdata:
1675 if not chunkdata:
1676 break
1676 break
1677 node = chunkdata['node']
1677 node = chunkdata['node']
1678 ui.write("%s\n" % hex(node))
1678 ui.write("%s\n" % hex(node))
1679 chain = node
1679 chain = node
1680 finally:
1680 finally:
1681 f.close()
1681 f.close()
1682
1682
1683 @command('debugcheckstate', [], '')
1683 @command('debugcheckstate', [], '')
1684 def debugcheckstate(ui, repo):
1684 def debugcheckstate(ui, repo):
1685 """validate the correctness of the current dirstate"""
1685 """validate the correctness of the current dirstate"""
1686 parent1, parent2 = repo.dirstate.parents()
1686 parent1, parent2 = repo.dirstate.parents()
1687 m1 = repo[parent1].manifest()
1687 m1 = repo[parent1].manifest()
1688 m2 = repo[parent2].manifest()
1688 m2 = repo[parent2].manifest()
1689 errors = 0
1689 errors = 0
1690 for f in repo.dirstate:
1690 for f in repo.dirstate:
1691 state = repo.dirstate[f]
1691 state = repo.dirstate[f]
1692 if state in "nr" and f not in m1:
1692 if state in "nr" and f not in m1:
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1693 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1694 errors += 1
1694 errors += 1
1695 if state in "a" and f in m1:
1695 if state in "a" and f in m1:
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1696 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1697 errors += 1
1697 errors += 1
1698 if state in "m" and f not in m1 and f not in m2:
1698 if state in "m" and f not in m1 and f not in m2:
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1699 ui.warn(_("%s in state %s, but not in either manifest\n") %
1700 (f, state))
1700 (f, state))
1701 errors += 1
1701 errors += 1
1702 for f in m1:
1702 for f in m1:
1703 state = repo.dirstate[f]
1703 state = repo.dirstate[f]
1704 if state not in "nrm":
1704 if state not in "nrm":
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1705 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1706 errors += 1
1706 errors += 1
1707 if errors:
1707 if errors:
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1708 error = _(".hg/dirstate inconsistent with current parent's manifest")
1709 raise util.Abort(error)
1709 raise util.Abort(error)
1710
1710
1711 @command('debugcommands', [], _('[COMMAND]'))
1711 @command('debugcommands', [], _('[COMMAND]'))
1712 def debugcommands(ui, cmd='', *args):
1712 def debugcommands(ui, cmd='', *args):
1713 """list all available commands and options"""
1713 """list all available commands and options"""
1714 for cmd, vals in sorted(table.iteritems()):
1714 for cmd, vals in sorted(table.iteritems()):
1715 cmd = cmd.split('|')[0].strip('^')
1715 cmd = cmd.split('|')[0].strip('^')
1716 opts = ', '.join([i[1] for i in vals[1]])
1716 opts = ', '.join([i[1] for i in vals[1]])
1717 ui.write('%s: %s\n' % (cmd, opts))
1717 ui.write('%s: %s\n' % (cmd, opts))
1718
1718
1719 @command('debugcomplete',
1719 @command('debugcomplete',
1720 [('o', 'options', None, _('show the command options'))],
1720 [('o', 'options', None, _('show the command options'))],
1721 _('[-o] CMD'))
1721 _('[-o] CMD'))
1722 def debugcomplete(ui, cmd='', **opts):
1722 def debugcomplete(ui, cmd='', **opts):
1723 """returns the completion list associated with the given command"""
1723 """returns the completion list associated with the given command"""
1724
1724
1725 if opts.get('options'):
1725 if opts.get('options'):
1726 options = []
1726 options = []
1727 otables = [globalopts]
1727 otables = [globalopts]
1728 if cmd:
1728 if cmd:
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1729 aliases, entry = cmdutil.findcmd(cmd, table, False)
1730 otables.append(entry[1])
1730 otables.append(entry[1])
1731 for t in otables:
1731 for t in otables:
1732 for o in t:
1732 for o in t:
1733 if "(DEPRECATED)" in o[3]:
1733 if "(DEPRECATED)" in o[3]:
1734 continue
1734 continue
1735 if o[0]:
1735 if o[0]:
1736 options.append('-%s' % o[0])
1736 options.append('-%s' % o[0])
1737 options.append('--%s' % o[1])
1737 options.append('--%s' % o[1])
1738 ui.write("%s\n" % "\n".join(options))
1738 ui.write("%s\n" % "\n".join(options))
1739 return
1739 return
1740
1740
1741 cmdlist = cmdutil.findpossible(cmd, table)
1741 cmdlist = cmdutil.findpossible(cmd, table)
1742 if ui.verbose:
1742 if ui.verbose:
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1743 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1744 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1745
1745
1746 @command('debugdag',
1746 @command('debugdag',
1747 [('t', 'tags', None, _('use tags as labels')),
1747 [('t', 'tags', None, _('use tags as labels')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1748 ('b', 'branches', None, _('annotate with branch names')),
1749 ('', 'dots', None, _('use dots for runs')),
1749 ('', 'dots', None, _('use dots for runs')),
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1750 ('s', 'spaces', None, _('separate elements by spaces'))],
1751 _('[OPTION]... [FILE [REV]...]'))
1751 _('[OPTION]... [FILE [REV]...]'))
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1752 def debugdag(ui, repo, file_=None, *revs, **opts):
1753 """format the changelog or an index DAG as a concise textual description
1753 """format the changelog or an index DAG as a concise textual description
1754
1754
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1755 If you pass a revlog index, the revlog's DAG is emitted. If you list
1756 revision numbers, they get labeled in the output as rN.
1756 revision numbers, they get labeled in the output as rN.
1757
1757
1758 Otherwise, the changelog DAG of the current repo is emitted.
1758 Otherwise, the changelog DAG of the current repo is emitted.
1759 """
1759 """
1760 spaces = opts.get('spaces')
1760 spaces = opts.get('spaces')
1761 dots = opts.get('dots')
1761 dots = opts.get('dots')
1762 if file_:
1762 if file_:
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1763 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1764 revs = set((int(r) for r in revs))
1764 revs = set((int(r) for r in revs))
1765 def events():
1765 def events():
1766 for r in rlog:
1766 for r in rlog:
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1767 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1768 if p != -1)))
1768 if p != -1)))
1769 if r in revs:
1769 if r in revs:
1770 yield 'l', (r, "r%i" % r)
1770 yield 'l', (r, "r%i" % r)
1771 elif repo:
1771 elif repo:
1772 cl = repo.changelog
1772 cl = repo.changelog
1773 tags = opts.get('tags')
1773 tags = opts.get('tags')
1774 branches = opts.get('branches')
1774 branches = opts.get('branches')
1775 if tags:
1775 if tags:
1776 labels = {}
1776 labels = {}
1777 for l, n in repo.tags().items():
1777 for l, n in repo.tags().items():
1778 labels.setdefault(cl.rev(n), []).append(l)
1778 labels.setdefault(cl.rev(n), []).append(l)
1779 def events():
1779 def events():
1780 b = "default"
1780 b = "default"
1781 for r in cl:
1781 for r in cl:
1782 if branches:
1782 if branches:
1783 newb = cl.read(cl.node(r))[5]['branch']
1783 newb = cl.read(cl.node(r))[5]['branch']
1784 if newb != b:
1784 if newb != b:
1785 yield 'a', newb
1785 yield 'a', newb
1786 b = newb
1786 b = newb
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1787 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1788 if p != -1)))
1788 if p != -1)))
1789 if tags:
1789 if tags:
1790 ls = labels.get(r)
1790 ls = labels.get(r)
1791 if ls:
1791 if ls:
1792 for l in ls:
1792 for l in ls:
1793 yield 'l', (r, l)
1793 yield 'l', (r, l)
1794 else:
1794 else:
1795 raise util.Abort(_('need repo for changelog dag'))
1795 raise util.Abort(_('need repo for changelog dag'))
1796
1796
1797 for line in dagparser.dagtextlines(events(),
1797 for line in dagparser.dagtextlines(events(),
1798 addspaces=spaces,
1798 addspaces=spaces,
1799 wraplabels=True,
1799 wraplabels=True,
1800 wrapannotations=True,
1800 wrapannotations=True,
1801 wrapnonlinear=dots,
1801 wrapnonlinear=dots,
1802 usedots=dots,
1802 usedots=dots,
1803 maxlinewidth=70):
1803 maxlinewidth=70):
1804 ui.write(line)
1804 ui.write(line)
1805 ui.write("\n")
1805 ui.write("\n")
1806
1806
1807 @command('debugdata',
1807 @command('debugdata',
1808 [('c', 'changelog', False, _('open changelog')),
1808 [('c', 'changelog', False, _('open changelog')),
1809 ('m', 'manifest', False, _('open manifest'))],
1809 ('m', 'manifest', False, _('open manifest'))],
1810 _('-c|-m|FILE REV'))
1810 _('-c|-m|FILE REV'))
1811 def debugdata(ui, repo, file_, rev = None, **opts):
1811 def debugdata(ui, repo, file_, rev = None, **opts):
1812 """dump the contents of a data file revision"""
1812 """dump the contents of a data file revision"""
1813 if opts.get('changelog') or opts.get('manifest'):
1813 if opts.get('changelog') or opts.get('manifest'):
1814 file_, rev = None, file_
1814 file_, rev = None, file_
1815 elif rev is None:
1815 elif rev is None:
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1816 raise error.CommandError('debugdata', _('invalid arguments'))
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1817 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1818 try:
1818 try:
1819 ui.write(r.revision(r.lookup(rev)))
1819 ui.write(r.revision(r.lookup(rev)))
1820 except KeyError:
1820 except KeyError:
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1821 raise util.Abort(_('invalid revision identifier %s') % rev)
1822
1822
1823 @command('debugdate',
1823 @command('debugdate',
1824 [('e', 'extended', None, _('try extended date formats'))],
1824 [('e', 'extended', None, _('try extended date formats'))],
1825 _('[-e] DATE [RANGE]'))
1825 _('[-e] DATE [RANGE]'))
1826 def debugdate(ui, date, range=None, **opts):
1826 def debugdate(ui, date, range=None, **opts):
1827 """parse and display a date"""
1827 """parse and display a date"""
1828 if opts["extended"]:
1828 if opts["extended"]:
1829 d = util.parsedate(date, util.extendeddateformats)
1829 d = util.parsedate(date, util.extendeddateformats)
1830 else:
1830 else:
1831 d = util.parsedate(date)
1831 d = util.parsedate(date)
1832 ui.write(("internal: %s %s\n") % d)
1832 ui.write(("internal: %s %s\n") % d)
1833 ui.write(("standard: %s\n") % util.datestr(d))
1833 ui.write(("standard: %s\n") % util.datestr(d))
1834 if range:
1834 if range:
1835 m = util.matchdate(range)
1835 m = util.matchdate(range)
1836 ui.write(("match: %s\n") % m(d[0]))
1836 ui.write(("match: %s\n") % m(d[0]))
1837
1837
1838 @command('debugdiscovery',
1838 @command('debugdiscovery',
1839 [('', 'old', None, _('use old-style discovery')),
1839 [('', 'old', None, _('use old-style discovery')),
1840 ('', 'nonheads', None,
1840 ('', 'nonheads', None,
1841 _('use old-style discovery with non-heads included')),
1841 _('use old-style discovery with non-heads included')),
1842 ] + remoteopts,
1842 ] + remoteopts,
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1843 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1844 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1845 """runs the changeset discovery protocol in isolation"""
1845 """runs the changeset discovery protocol in isolation"""
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1846 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1847 opts.get('branch'))
1847 opts.get('branch'))
1848 remote = hg.peer(repo, opts, remoteurl)
1848 remote = hg.peer(repo, opts, remoteurl)
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1849 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1850
1850
1851 # make sure tests are repeatable
1851 # make sure tests are repeatable
1852 random.seed(12323)
1852 random.seed(12323)
1853
1853
1854 def doit(localheads, remoteheads, remote=remote):
1854 def doit(localheads, remoteheads, remote=remote):
1855 if opts.get('old'):
1855 if opts.get('old'):
1856 if localheads:
1856 if localheads:
1857 raise util.Abort('cannot use localheads with old style '
1857 raise util.Abort('cannot use localheads with old style '
1858 'discovery')
1858 'discovery')
1859 if not util.safehasattr(remote, 'branches'):
1859 if not util.safehasattr(remote, 'branches'):
1860 # enable in-client legacy support
1860 # enable in-client legacy support
1861 remote = localrepo.locallegacypeer(remote.local())
1861 remote = localrepo.locallegacypeer(remote.local())
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1862 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1863 force=True)
1863 force=True)
1864 common = set(common)
1864 common = set(common)
1865 if not opts.get('nonheads'):
1865 if not opts.get('nonheads'):
1866 ui.write(("unpruned common: %s\n") %
1866 ui.write(("unpruned common: %s\n") %
1867 " ".join(sorted(short(n) for n in common)))
1867 " ".join(sorted(short(n) for n in common)))
1868 dag = dagutil.revlogdag(repo.changelog)
1868 dag = dagutil.revlogdag(repo.changelog)
1869 all = dag.ancestorset(dag.internalizeall(common))
1869 all = dag.ancestorset(dag.internalizeall(common))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1870 common = dag.externalizeall(dag.headsetofconnecteds(all))
1871 else:
1871 else:
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1872 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1873 common = set(common)
1873 common = set(common)
1874 rheads = set(hds)
1874 rheads = set(hds)
1875 lheads = set(repo.heads())
1875 lheads = set(repo.heads())
1876 ui.write(("common heads: %s\n") %
1876 ui.write(("common heads: %s\n") %
1877 " ".join(sorted(short(n) for n in common)))
1877 " ".join(sorted(short(n) for n in common)))
1878 if lheads <= common:
1878 if lheads <= common:
1879 ui.write(("local is subset\n"))
1879 ui.write(("local is subset\n"))
1880 elif rheads <= common:
1880 elif rheads <= common:
1881 ui.write(("remote is subset\n"))
1881 ui.write(("remote is subset\n"))
1882
1882
1883 serverlogs = opts.get('serverlog')
1883 serverlogs = opts.get('serverlog')
1884 if serverlogs:
1884 if serverlogs:
1885 for filename in serverlogs:
1885 for filename in serverlogs:
1886 logfile = open(filename, 'r')
1886 logfile = open(filename, 'r')
1887 try:
1887 try:
1888 line = logfile.readline()
1888 line = logfile.readline()
1889 while line:
1889 while line:
1890 parts = line.strip().split(';')
1890 parts = line.strip().split(';')
1891 op = parts[1]
1891 op = parts[1]
1892 if op == 'cg':
1892 if op == 'cg':
1893 pass
1893 pass
1894 elif op == 'cgss':
1894 elif op == 'cgss':
1895 doit(parts[2].split(' '), parts[3].split(' '))
1895 doit(parts[2].split(' '), parts[3].split(' '))
1896 elif op == 'unb':
1896 elif op == 'unb':
1897 doit(parts[3].split(' '), parts[2].split(' '))
1897 doit(parts[3].split(' '), parts[2].split(' '))
1898 line = logfile.readline()
1898 line = logfile.readline()
1899 finally:
1899 finally:
1900 logfile.close()
1900 logfile.close()
1901
1901
1902 else:
1902 else:
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1903 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1904 opts.get('remote_head'))
1904 opts.get('remote_head'))
1905 localrevs = opts.get('local_head')
1905 localrevs = opts.get('local_head')
1906 doit(localrevs, remoterevs)
1906 doit(localrevs, remoterevs)
1907
1907
1908 @command('debugfileset',
1908 @command('debugfileset',
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1910 _('[-r REV] FILESPEC'))
1910 _('[-r REV] FILESPEC'))
1911 def debugfileset(ui, repo, expr, **opts):
1911 def debugfileset(ui, repo, expr, **opts):
1912 '''parse and apply a fileset specification'''
1912 '''parse and apply a fileset specification'''
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1914 if ui.verbose:
1914 if ui.verbose:
1915 tree = fileset.parse(expr)[0]
1915 tree = fileset.parse(expr)[0]
1916 ui.note(tree, "\n")
1916 ui.note(tree, "\n")
1917
1917
1918 for f in fileset.getfileset(ctx, expr):
1918 for f in fileset.getfileset(ctx, expr):
1919 ui.write("%s\n" % f)
1919 ui.write("%s\n" % f)
1920
1920
1921 @command('debugfsinfo', [], _('[PATH]'))
1921 @command('debugfsinfo', [], _('[PATH]'))
1922 def debugfsinfo(ui, path = "."):
1922 def debugfsinfo(ui, path = "."):
1923 """show information detected about current filesystem"""
1923 """show information detected about current filesystem"""
1924 util.writefile('.debugfsinfo', '')
1924 util.writefile('.debugfsinfo', '')
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1928 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1929 and 'yes' or 'no'))
1929 and 'yes' or 'no'))
1930 os.unlink('.debugfsinfo')
1930 os.unlink('.debugfsinfo')
1931
1931
1932 @command('debuggetbundle',
1932 @command('debuggetbundle',
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1933 [('H', 'head', [], _('id of head node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1936 _('REPO FILE [-H|-C ID]...'))
1936 _('REPO FILE [-H|-C ID]...'))
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1937 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1938 """retrieves a bundle from a repo
1938 """retrieves a bundle from a repo
1939
1939
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1940 Every ID must be a full-length hex node id string. Saves the bundle to the
1941 given file.
1941 given file.
1942 """
1942 """
1943 repo = hg.peer(ui, opts, repopath)
1943 repo = hg.peer(ui, opts, repopath)
1944 if not repo.capable('getbundle'):
1944 if not repo.capable('getbundle'):
1945 raise util.Abort("getbundle() not supported by target repository")
1945 raise util.Abort("getbundle() not supported by target repository")
1946 args = {}
1946 args = {}
1947 if common:
1947 if common:
1948 args['common'] = [bin(s) for s in common]
1948 args['common'] = [bin(s) for s in common]
1949 if head:
1949 if head:
1950 args['heads'] = [bin(s) for s in head]
1950 args['heads'] = [bin(s) for s in head]
1951 # TODO: get desired bundlecaps from command line.
1951 # TODO: get desired bundlecaps from command line.
1952 args['bundlecaps'] = None
1952 args['bundlecaps'] = None
1953 bundle = repo.getbundle('debug', **args)
1953 bundle = repo.getbundle('debug', **args)
1954
1954
1955 bundletype = opts.get('type', 'bzip2').lower()
1955 bundletype = opts.get('type', 'bzip2').lower()
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1956 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1957 bundletype = btypes.get(bundletype)
1957 bundletype = btypes.get(bundletype)
1958 if bundletype not in changegroup.bundletypes:
1958 if bundletype not in changegroup.bundletypes:
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1959 raise util.Abort(_('unknown bundle type specified with --type'))
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1960 changegroup.writebundle(bundle, bundlepath, bundletype)
1961
1961
1962 @command('debugignore', [], '')
1962 @command('debugignore', [], '')
1963 def debugignore(ui, repo, *values, **opts):
1963 def debugignore(ui, repo, *values, **opts):
1964 """display the combined ignore pattern"""
1964 """display the combined ignore pattern"""
1965 ignore = repo.dirstate._ignore
1965 ignore = repo.dirstate._ignore
1966 includepat = getattr(ignore, 'includepat', None)
1966 includepat = getattr(ignore, 'includepat', None)
1967 if includepat is not None:
1967 if includepat is not None:
1968 ui.write("%s\n" % includepat)
1968 ui.write("%s\n" % includepat)
1969 else:
1969 else:
1970 raise util.Abort(_("no ignore patterns found"))
1970 raise util.Abort(_("no ignore patterns found"))
1971
1971
1972 @command('debugindex',
1972 @command('debugindex',
1973 [('c', 'changelog', False, _('open changelog')),
1973 [('c', 'changelog', False, _('open changelog')),
1974 ('m', 'manifest', False, _('open manifest')),
1974 ('m', 'manifest', False, _('open manifest')),
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1975 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1976 _('[-f FORMAT] -c|-m|FILE'))
1976 _('[-f FORMAT] -c|-m|FILE'))
1977 def debugindex(ui, repo, file_ = None, **opts):
1977 def debugindex(ui, repo, file_ = None, **opts):
1978 """dump the contents of an index file"""
1978 """dump the contents of an index file"""
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1979 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1980 format = opts.get('format', 0)
1980 format = opts.get('format', 0)
1981 if format not in (0, 1):
1981 if format not in (0, 1):
1982 raise util.Abort(_("unknown format %d") % format)
1982 raise util.Abort(_("unknown format %d") % format)
1983
1983
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1984 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1985 if generaldelta:
1985 if generaldelta:
1986 basehdr = ' delta'
1986 basehdr = ' delta'
1987 else:
1987 else:
1988 basehdr = ' base'
1988 basehdr = ' base'
1989
1989
1990 if format == 0:
1990 if format == 0:
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1991 ui.write(" rev offset length " + basehdr + " linkrev"
1992 " nodeid p1 p2\n")
1992 " nodeid p1 p2\n")
1993 elif format == 1:
1993 elif format == 1:
1994 ui.write(" rev flag offset length"
1994 ui.write(" rev flag offset length"
1995 " size " + basehdr + " link p1 p2"
1995 " size " + basehdr + " link p1 p2"
1996 " nodeid\n")
1996 " nodeid\n")
1997
1997
1998 for i in r:
1998 for i in r:
1999 node = r.node(i)
1999 node = r.node(i)
2000 if generaldelta:
2000 if generaldelta:
2001 base = r.deltaparent(i)
2001 base = r.deltaparent(i)
2002 else:
2002 else:
2003 base = r.chainbase(i)
2003 base = r.chainbase(i)
2004 if format == 0:
2004 if format == 0:
2005 try:
2005 try:
2006 pp = r.parents(node)
2006 pp = r.parents(node)
2007 except Exception:
2007 except Exception:
2008 pp = [nullid, nullid]
2008 pp = [nullid, nullid]
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2009 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2010 i, r.start(i), r.length(i), base, r.linkrev(i),
2011 short(node), short(pp[0]), short(pp[1])))
2011 short(node), short(pp[0]), short(pp[1])))
2012 elif format == 1:
2012 elif format == 1:
2013 pr = r.parentrevs(i)
2013 pr = r.parentrevs(i)
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2014 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2015 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2016 base, r.linkrev(i), pr[0], pr[1], short(node)))
2017
2017
2018 @command('debugindexdot', [], _('FILE'))
2018 @command('debugindexdot', [], _('FILE'))
2019 def debugindexdot(ui, repo, file_):
2019 def debugindexdot(ui, repo, file_):
2020 """dump an index DAG as a graphviz dot file"""
2020 """dump an index DAG as a graphviz dot file"""
2021 r = None
2021 r = None
2022 if repo:
2022 if repo:
2023 filelog = repo.file(file_)
2023 filelog = repo.file(file_)
2024 if len(filelog):
2024 if len(filelog):
2025 r = filelog
2025 r = filelog
2026 if not r:
2026 if not r:
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2027 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2028 ui.write(("digraph G {\n"))
2028 ui.write(("digraph G {\n"))
2029 for i in r:
2029 for i in r:
2030 node = r.node(i)
2030 node = r.node(i)
2031 pp = r.parents(node)
2031 pp = r.parents(node)
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2032 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2033 if pp[1] != nullid:
2033 if pp[1] != nullid:
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2034 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2035 ui.write("}\n")
2035 ui.write("}\n")
2036
2036
2037 @command('debuginstall', [], '')
2037 @command('debuginstall', [], '')
2038 def debuginstall(ui):
2038 def debuginstall(ui):
2039 '''test Mercurial installation
2039 '''test Mercurial installation
2040
2040
2041 Returns 0 on success.
2041 Returns 0 on success.
2042 '''
2042 '''
2043
2043
2044 def writetemp(contents):
2044 def writetemp(contents):
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2045 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2046 f = os.fdopen(fd, "wb")
2046 f = os.fdopen(fd, "wb")
2047 f.write(contents)
2047 f.write(contents)
2048 f.close()
2048 f.close()
2049 return name
2049 return name
2050
2050
2051 problems = 0
2051 problems = 0
2052
2052
2053 # encoding
2053 # encoding
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2054 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2055 try:
2055 try:
2056 encoding.fromlocal("test")
2056 encoding.fromlocal("test")
2057 except util.Abort, inst:
2057 except util.Abort, inst:
2058 ui.write(" %s\n" % inst)
2058 ui.write(" %s\n" % inst)
2059 ui.write(_(" (check that your locale is properly set)\n"))
2059 ui.write(_(" (check that your locale is properly set)\n"))
2060 problems += 1
2060 problems += 1
2061
2061
2062 # Python lib
2062 # Python lib
2063 ui.status(_("checking Python lib (%s)...\n")
2063 ui.status(_("checking Python lib (%s)...\n")
2064 % os.path.dirname(os.__file__))
2064 % os.path.dirname(os.__file__))
2065
2065
2066 # compiled modules
2066 # compiled modules
2067 ui.status(_("checking installed modules (%s)...\n")
2067 ui.status(_("checking installed modules (%s)...\n")
2068 % os.path.dirname(__file__))
2068 % os.path.dirname(__file__))
2069 try:
2069 try:
2070 import bdiff, mpatch, base85, osutil
2070 import bdiff, mpatch, base85, osutil
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2071 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2072 except Exception, inst:
2072 except Exception, inst:
2073 ui.write(" %s\n" % inst)
2073 ui.write(" %s\n" % inst)
2074 ui.write(_(" One or more extensions could not be found"))
2074 ui.write(_(" One or more extensions could not be found"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2075 ui.write(_(" (check that you compiled the extensions)\n"))
2076 problems += 1
2076 problems += 1
2077
2077
2078 # templates
2078 # templates
2079 import templater
2079 import templater
2080 p = templater.templatepath()
2080 p = templater.templatepath()
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2081 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2082 try:
2082 try:
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2083 templater.templater(templater.templatepath("map-cmdline.default"))
2084 except Exception, inst:
2084 except Exception, inst:
2085 ui.write(" %s\n" % inst)
2085 ui.write(" %s\n" % inst)
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2086 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2087 problems += 1
2087 problems += 1
2088
2088
2089 # editor
2089 # editor
2090 ui.status(_("checking commit editor...\n"))
2090 ui.status(_("checking commit editor...\n"))
2091 editor = ui.geteditor()
2091 editor = ui.geteditor()
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2092 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2093 if not cmdpath:
2093 if not cmdpath:
2094 if editor == 'vi':
2094 if editor == 'vi':
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2095 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2096 ui.write(_(" (specify a commit editor in your configuration"
2096 ui.write(_(" (specify a commit editor in your configuration"
2097 " file)\n"))
2097 " file)\n"))
2098 else:
2098 else:
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2099 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2100 ui.write(_(" (specify a commit editor in your configuration"
2100 ui.write(_(" (specify a commit editor in your configuration"
2101 " file)\n"))
2101 " file)\n"))
2102 problems += 1
2102 problems += 1
2103
2103
2104 # check username
2104 # check username
2105 ui.status(_("checking username...\n"))
2105 ui.status(_("checking username...\n"))
2106 try:
2106 try:
2107 ui.username()
2107 ui.username()
2108 except util.Abort, e:
2108 except util.Abort, e:
2109 ui.write(" %s\n" % e)
2109 ui.write(" %s\n" % e)
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2110 ui.write(_(" (specify a username in your configuration file)\n"))
2111 problems += 1
2111 problems += 1
2112
2112
2113 if not problems:
2113 if not problems:
2114 ui.status(_("no problems detected\n"))
2114 ui.status(_("no problems detected\n"))
2115 else:
2115 else:
2116 ui.write(_("%s problems detected,"
2116 ui.write(_("%s problems detected,"
2117 " please check your install!\n") % problems)
2117 " please check your install!\n") % problems)
2118
2118
2119 return problems
2119 return problems
2120
2120
2121 @command('debugknown', [], _('REPO ID...'))
2121 @command('debugknown', [], _('REPO ID...'))
2122 def debugknown(ui, repopath, *ids, **opts):
2122 def debugknown(ui, repopath, *ids, **opts):
2123 """test whether node ids are known to a repo
2123 """test whether node ids are known to a repo
2124
2124
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2125 Every ID must be a full-length hex node id string. Returns a list of 0s
2126 and 1s indicating unknown/known.
2126 and 1s indicating unknown/known.
2127 """
2127 """
2128 repo = hg.peer(ui, opts, repopath)
2128 repo = hg.peer(ui, opts, repopath)
2129 if not repo.capable('known'):
2129 if not repo.capable('known'):
2130 raise util.Abort("known() not supported by target repository")
2130 raise util.Abort("known() not supported by target repository")
2131 flags = repo.known([bin(s) for s in ids])
2131 flags = repo.known([bin(s) for s in ids])
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2132 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2133
2133
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2134 @command('debuglabelcomplete', [], _('LABEL...'))
2135 def debuglabelcomplete(ui, repo, *args):
2135 def debuglabelcomplete(ui, repo, *args):
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2136 '''complete "labels" - tags, open branch names, bookmark names'''
2137
2137
2138 labels = set()
2138 labels = set()
2139 labels.update(t[0] for t in repo.tagslist())
2139 labels.update(t[0] for t in repo.tagslist())
2140 labels.update(repo._bookmarks.keys())
2140 labels.update(repo._bookmarks.keys())
2141 for heads in repo.branchmap().itervalues():
2141 for heads in repo.branchmap().itervalues():
2142 for h in heads:
2142 for h in heads:
2143 ctx = repo[h]
2143 ctx = repo[h]
2144 if not ctx.closesbranch():
2144 if not ctx.closesbranch():
2145 labels.add(ctx.branch())
2145 labels.add(ctx.branch())
2146 completions = set()
2146 completions = set()
2147 if not args:
2147 if not args:
2148 args = ['']
2148 args = ['']
2149 for a in args:
2149 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2150 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2151 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2152 ui.write('\n')
2153
2153
2154 @command('debugobsolete',
2154 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2155 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2156 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2159 """create arbitrary obsolete marker
2160
2160
2161 With no arguments, displays the list of obsolescence markers."""
2161 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2162 def parsenodeid(s):
2163 try:
2163 try:
2164 # We do not use revsingle/revrange functions here to accept
2164 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2165 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2166 # local repository.
2167 n = bin(s)
2167 n = bin(s)
2168 if len(n) != len(nullid):
2168 if len(n) != len(nullid):
2169 raise TypeError()
2169 raise TypeError()
2170 return n
2170 return n
2171 except TypeError:
2171 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2172 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2173 'node identifiers')
2174
2174
2175 if precursor is not None:
2175 if precursor is not None:
2176 metadata = {}
2176 metadata = {}
2177 if 'date' in opts:
2177 if 'date' in opts:
2178 metadata['date'] = opts['date']
2178 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2179 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2181 l = repo.lock()
2182 try:
2182 try:
2183 tr = repo.transaction('debugobsolete')
2183 tr = repo.transaction('debugobsolete')
2184 try:
2184 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2186 opts['flags'], metadata)
2187 tr.close()
2187 tr.close()
2188 finally:
2188 finally:
2189 tr.release()
2189 tr.release()
2190 finally:
2190 finally:
2191 l.release()
2191 l.release()
2192 else:
2192 else:
2193 for m in obsolete.allmarkers(repo):
2193 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2194 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2195 for repl in m.succnodes():
2196 ui.write(' ')
2196 ui.write(' ')
2197 ui.write(hex(repl))
2197 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2198 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2200 sorted(m.metadata().items()))))
2201 ui.write('\n')
2201 ui.write('\n')
2202
2202
2203 @command('debugpathcomplete',
2203 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2204 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2205 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2206 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2207 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2208 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2210 '''complete part or all of a tracked path
2211
2211
2212 This command supports shells that offer path name completion. It
2212 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2213 currently completes only files already known to the dirstate.
2214
2214
2215 Completion extends only to the next path segment unless
2215 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2216 --full is specified, in which case entire paths are used.'''
2217
2217
2218 def complete(path, acceptable):
2218 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2219 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2221 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2222 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2223 return [], []
2224 if os.path.isdir(spec):
2224 if os.path.isdir(spec):
2225 spec += '/'
2225 spec += '/'
2226 spec = spec[len(rootdir):]
2226 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2227 fixpaths = os.sep != '/'
2228 if fixpaths:
2228 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2229 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2230 speclen = len(spec)
2231 fullpaths = opts['full']
2231 fullpaths = opts['full']
2232 files, dirs = set(), set()
2232 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2233 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2234 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2235 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2236 if fixpaths:
2237 f = f.replace('/', os.sep)
2237 f = f.replace('/', os.sep)
2238 if fullpaths:
2238 if fullpaths:
2239 addfile(f)
2239 addfile(f)
2240 continue
2240 continue
2241 s = f.find(os.sep, speclen)
2241 s = f.find(os.sep, speclen)
2242 if s >= 0:
2242 if s >= 0:
2243 adddir(f[:s + 1])
2243 adddir(f[:s + 1])
2244 else:
2244 else:
2245 addfile(f)
2245 addfile(f)
2246 return files, dirs
2246 return files, dirs
2247
2247
2248 acceptable = ''
2248 acceptable = ''
2249 if opts['normal']:
2249 if opts['normal']:
2250 acceptable += 'nm'
2250 acceptable += 'nm'
2251 if opts['added']:
2251 if opts['added']:
2252 acceptable += 'a'
2252 acceptable += 'a'
2253 if opts['removed']:
2253 if opts['removed']:
2254 acceptable += 'r'
2254 acceptable += 'r'
2255 cwd = repo.getcwd()
2255 cwd = repo.getcwd()
2256 if not specs:
2256 if not specs:
2257 specs = ['.']
2257 specs = ['.']
2258
2258
2259 files, dirs = set(), set()
2259 files, dirs = set(), set()
2260 for spec in specs:
2260 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2261 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2262 files.update(f)
2263 dirs.update(d)
2263 dirs.update(d)
2264 if not files and len(dirs) == 1:
2264 if not files and len(dirs) == 1:
2265 # force the shell to consider a completion that matches one
2265 # force the shell to consider a completion that matches one
2266 # directory and zero files to be ambiguous
2266 # directory and zero files to be ambiguous
2267 dirs.add(iter(dirs).next() + '.')
2267 dirs.add(iter(dirs).next() + '.')
2268 files.update(dirs)
2268 files.update(dirs)
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2269 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2270 ui.write('\n')
2270 ui.write('\n')
2271
2271
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2272 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2273 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2274 '''access the pushkey key/value protocol
2274 '''access the pushkey key/value protocol
2275
2275
2276 With two args, list the keys in the given namespace.
2276 With two args, list the keys in the given namespace.
2277
2277
2278 With five args, set a key to new if it currently is set to old.
2278 With five args, set a key to new if it currently is set to old.
2279 Reports success or failure.
2279 Reports success or failure.
2280 '''
2280 '''
2281
2281
2282 target = hg.peer(ui, {}, repopath)
2282 target = hg.peer(ui, {}, repopath)
2283 if keyinfo:
2283 if keyinfo:
2284 key, old, new = keyinfo
2284 key, old, new = keyinfo
2285 r = target.pushkey(namespace, key, old, new)
2285 r = target.pushkey(namespace, key, old, new)
2286 ui.status(str(r) + '\n')
2286 ui.status(str(r) + '\n')
2287 return not r
2287 return not r
2288 else:
2288 else:
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2289 for k, v in sorted(target.listkeys(namespace).iteritems()):
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2290 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2291 v.encode('string-escape')))
2291 v.encode('string-escape')))
2292
2292
2293 @command('debugpvec', [], _('A B'))
2293 @command('debugpvec', [], _('A B'))
2294 def debugpvec(ui, repo, a, b=None):
2294 def debugpvec(ui, repo, a, b=None):
2295 ca = scmutil.revsingle(repo, a)
2295 ca = scmutil.revsingle(repo, a)
2296 cb = scmutil.revsingle(repo, b)
2296 cb = scmutil.revsingle(repo, b)
2297 pa = pvec.ctxpvec(ca)
2297 pa = pvec.ctxpvec(ca)
2298 pb = pvec.ctxpvec(cb)
2298 pb = pvec.ctxpvec(cb)
2299 if pa == pb:
2299 if pa == pb:
2300 rel = "="
2300 rel = "="
2301 elif pa > pb:
2301 elif pa > pb:
2302 rel = ">"
2302 rel = ">"
2303 elif pa < pb:
2303 elif pa < pb:
2304 rel = "<"
2304 rel = "<"
2305 elif pa | pb:
2305 elif pa | pb:
2306 rel = "|"
2306 rel = "|"
2307 ui.write(_("a: %s\n") % pa)
2307 ui.write(_("a: %s\n") % pa)
2308 ui.write(_("b: %s\n") % pb)
2308 ui.write(_("b: %s\n") % pb)
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2309 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2310 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2311 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2312 pa.distance(pb), rel))
2312 pa.distance(pb), rel))
2313
2313
2314 @command('debugrebuilddirstate|debugrebuildstate',
2314 @command('debugrebuilddirstate|debugrebuildstate',
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2315 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2316 _('[-r REV]'))
2316 _('[-r REV]'))
2317 def debugrebuilddirstate(ui, repo, rev):
2317 def debugrebuilddirstate(ui, repo, rev):
2318 """rebuild the dirstate as it would look like for the given revision
2318 """rebuild the dirstate as it would look like for the given revision
2319
2319
2320 If no revision is specified the first current parent will be used.
2320 If no revision is specified the first current parent will be used.
2321
2321
2322 The dirstate will be set to the files of the given revision.
2322 The dirstate will be set to the files of the given revision.
2323 The actual working directory content or existing dirstate
2323 The actual working directory content or existing dirstate
2324 information such as adds or removes is not considered.
2324 information such as adds or removes is not considered.
2325
2325
2326 One use of this command is to make the next :hg:`status` invocation
2326 One use of this command is to make the next :hg:`status` invocation
2327 check the actual file content.
2327 check the actual file content.
2328 """
2328 """
2329 ctx = scmutil.revsingle(repo, rev)
2329 ctx = scmutil.revsingle(repo, rev)
2330 wlock = repo.wlock()
2330 wlock = repo.wlock()
2331 try:
2331 try:
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2332 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2333 finally:
2333 finally:
2334 wlock.release()
2334 wlock.release()
2335
2335
2336 @command('debugrename',
2336 @command('debugrename',
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2337 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2338 _('[-r REV] FILE'))
2338 _('[-r REV] FILE'))
2339 def debugrename(ui, repo, file1, *pats, **opts):
2339 def debugrename(ui, repo, file1, *pats, **opts):
2340 """dump rename information"""
2340 """dump rename information"""
2341
2341
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2342 ctx = scmutil.revsingle(repo, opts.get('rev'))
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2343 m = scmutil.match(ctx, (file1,) + pats, opts)
2344 for abs in ctx.walk(m):
2344 for abs in ctx.walk(m):
2345 fctx = ctx[abs]
2345 fctx = ctx[abs]
2346 o = fctx.filelog().renamed(fctx.filenode())
2346 o = fctx.filelog().renamed(fctx.filenode())
2347 rel = m.rel(abs)
2347 rel = m.rel(abs)
2348 if o:
2348 if o:
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2349 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2350 else:
2350 else:
2351 ui.write(_("%s not renamed\n") % rel)
2351 ui.write(_("%s not renamed\n") % rel)
2352
2352
2353 @command('debugrevlog',
2353 @command('debugrevlog',
2354 [('c', 'changelog', False, _('open changelog')),
2354 [('c', 'changelog', False, _('open changelog')),
2355 ('m', 'manifest', False, _('open manifest')),
2355 ('m', 'manifest', False, _('open manifest')),
2356 ('d', 'dump', False, _('dump index data'))],
2356 ('d', 'dump', False, _('dump index data'))],
2357 _('-c|-m|FILE'))
2357 _('-c|-m|FILE'))
2358 def debugrevlog(ui, repo, file_ = None, **opts):
2358 def debugrevlog(ui, repo, file_ = None, **opts):
2359 """show data and statistics about a revlog"""
2359 """show data and statistics about a revlog"""
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2360 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2361
2361
2362 if opts.get("dump"):
2362 if opts.get("dump"):
2363 numrevs = len(r)
2363 numrevs = len(r)
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2364 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2365 " rawsize totalsize compression heads\n")
2365 " rawsize totalsize compression heads\n")
2366 ts = 0
2366 ts = 0
2367 heads = set()
2367 heads = set()
2368 for rev in xrange(numrevs):
2368 for rev in xrange(numrevs):
2369 dbase = r.deltaparent(rev)
2369 dbase = r.deltaparent(rev)
2370 if dbase == -1:
2370 if dbase == -1:
2371 dbase = rev
2371 dbase = rev
2372 cbase = r.chainbase(rev)
2372 cbase = r.chainbase(rev)
2373 p1, p2 = r.parentrevs(rev)
2373 p1, p2 = r.parentrevs(rev)
2374 rs = r.rawsize(rev)
2374 rs = r.rawsize(rev)
2375 ts = ts + rs
2375 ts = ts + rs
2376 heads -= set(r.parentrevs(rev))
2376 heads -= set(r.parentrevs(rev))
2377 heads.add(rev)
2377 heads.add(rev)
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2378 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2379 (rev, p1, p2, r.start(rev), r.end(rev),
2380 r.start(dbase), r.start(cbase),
2380 r.start(dbase), r.start(cbase),
2381 r.start(p1), r.start(p2),
2381 r.start(p1), r.start(p2),
2382 rs, ts, ts / r.end(rev), len(heads)))
2382 rs, ts, ts / r.end(rev), len(heads)))
2383 return 0
2383 return 0
2384
2384
2385 v = r.version
2385 v = r.version
2386 format = v & 0xFFFF
2386 format = v & 0xFFFF
2387 flags = []
2387 flags = []
2388 gdelta = False
2388 gdelta = False
2389 if v & revlog.REVLOGNGINLINEDATA:
2389 if v & revlog.REVLOGNGINLINEDATA:
2390 flags.append('inline')
2390 flags.append('inline')
2391 if v & revlog.REVLOGGENERALDELTA:
2391 if v & revlog.REVLOGGENERALDELTA:
2392 gdelta = True
2392 gdelta = True
2393 flags.append('generaldelta')
2393 flags.append('generaldelta')
2394 if not flags:
2394 if not flags:
2395 flags = ['(none)']
2395 flags = ['(none)']
2396
2396
2397 nummerges = 0
2397 nummerges = 0
2398 numfull = 0
2398 numfull = 0
2399 numprev = 0
2399 numprev = 0
2400 nump1 = 0
2400 nump1 = 0
2401 nump2 = 0
2401 nump2 = 0
2402 numother = 0
2402 numother = 0
2403 nump1prev = 0
2403 nump1prev = 0
2404 nump2prev = 0
2404 nump2prev = 0
2405 chainlengths = []
2405 chainlengths = []
2406
2406
2407 datasize = [None, 0, 0L]
2407 datasize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2408 fullsize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2409 deltasize = [None, 0, 0L]
2410
2410
2411 def addsize(size, l):
2411 def addsize(size, l):
2412 if l[0] is None or size < l[0]:
2412 if l[0] is None or size < l[0]:
2413 l[0] = size
2413 l[0] = size
2414 if size > l[1]:
2414 if size > l[1]:
2415 l[1] = size
2415 l[1] = size
2416 l[2] += size
2416 l[2] += size
2417
2417
2418 numrevs = len(r)
2418 numrevs = len(r)
2419 for rev in xrange(numrevs):
2419 for rev in xrange(numrevs):
2420 p1, p2 = r.parentrevs(rev)
2420 p1, p2 = r.parentrevs(rev)
2421 delta = r.deltaparent(rev)
2421 delta = r.deltaparent(rev)
2422 if format > 0:
2422 if format > 0:
2423 addsize(r.rawsize(rev), datasize)
2423 addsize(r.rawsize(rev), datasize)
2424 if p2 != nullrev:
2424 if p2 != nullrev:
2425 nummerges += 1
2425 nummerges += 1
2426 size = r.length(rev)
2426 size = r.length(rev)
2427 if delta == nullrev:
2427 if delta == nullrev:
2428 chainlengths.append(0)
2428 chainlengths.append(0)
2429 numfull += 1
2429 numfull += 1
2430 addsize(size, fullsize)
2430 addsize(size, fullsize)
2431 else:
2431 else:
2432 chainlengths.append(chainlengths[delta] + 1)
2432 chainlengths.append(chainlengths[delta] + 1)
2433 addsize(size, deltasize)
2433 addsize(size, deltasize)
2434 if delta == rev - 1:
2434 if delta == rev - 1:
2435 numprev += 1
2435 numprev += 1
2436 if delta == p1:
2436 if delta == p1:
2437 nump1prev += 1
2437 nump1prev += 1
2438 elif delta == p2:
2438 elif delta == p2:
2439 nump2prev += 1
2439 nump2prev += 1
2440 elif delta == p1:
2440 elif delta == p1:
2441 nump1 += 1
2441 nump1 += 1
2442 elif delta == p2:
2442 elif delta == p2:
2443 nump2 += 1
2443 nump2 += 1
2444 elif delta != nullrev:
2444 elif delta != nullrev:
2445 numother += 1
2445 numother += 1
2446
2446
2447 # Adjust size min value for empty cases
2447 # Adjust size min value for empty cases
2448 for size in (datasize, fullsize, deltasize):
2448 for size in (datasize, fullsize, deltasize):
2449 if size[0] is None:
2449 if size[0] is None:
2450 size[0] = 0
2450 size[0] = 0
2451
2451
2452 numdeltas = numrevs - numfull
2452 numdeltas = numrevs - numfull
2453 numoprev = numprev - nump1prev - nump2prev
2453 numoprev = numprev - nump1prev - nump2prev
2454 totalrawsize = datasize[2]
2454 totalrawsize = datasize[2]
2455 datasize[2] /= numrevs
2455 datasize[2] /= numrevs
2456 fulltotal = fullsize[2]
2456 fulltotal = fullsize[2]
2457 fullsize[2] /= numfull
2457 fullsize[2] /= numfull
2458 deltatotal = deltasize[2]
2458 deltatotal = deltasize[2]
2459 if numrevs - numfull > 0:
2459 if numrevs - numfull > 0:
2460 deltasize[2] /= numrevs - numfull
2460 deltasize[2] /= numrevs - numfull
2461 totalsize = fulltotal + deltatotal
2461 totalsize = fulltotal + deltatotal
2462 avgchainlen = sum(chainlengths) / numrevs
2462 avgchainlen = sum(chainlengths) / numrevs
2463 compratio = totalrawsize / totalsize
2463 compratio = totalrawsize / totalsize
2464
2464
2465 basedfmtstr = '%%%dd\n'
2465 basedfmtstr = '%%%dd\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2466 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2467
2467
2468 def dfmtstr(max):
2468 def dfmtstr(max):
2469 return basedfmtstr % len(str(max))
2469 return basedfmtstr % len(str(max))
2470 def pcfmtstr(max, padding=0):
2470 def pcfmtstr(max, padding=0):
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2471 return basepcfmtstr % (len(str(max)), ' ' * padding)
2472
2472
2473 def pcfmt(value, total):
2473 def pcfmt(value, total):
2474 return (value, 100 * float(value) / total)
2474 return (value, 100 * float(value) / total)
2475
2475
2476 ui.write(('format : %d\n') % format)
2476 ui.write(('format : %d\n') % format)
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2477 ui.write(('flags : %s\n') % ', '.join(flags))
2478
2478
2479 ui.write('\n')
2479 ui.write('\n')
2480 fmt = pcfmtstr(totalsize)
2480 fmt = pcfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2481 fmt2 = dfmtstr(totalsize)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write(('revisions : ') + fmt2 % numrevs)
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2483 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2484 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2486 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2487 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2488 ui.write(('revision size : ') + fmt2 % totalsize)
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2489 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2490 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2491
2491
2492 ui.write('\n')
2492 ui.write('\n')
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2493 fmt = dfmtstr(max(avgchainlen, compratio))
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2494 ui.write(('avg chain length : ') + fmt % avgchainlen)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2495 ui.write(('compression ratio : ') + fmt % compratio)
2496
2496
2497 if format > 0:
2497 if format > 0:
2498 ui.write('\n')
2498 ui.write('\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2499 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(datasize))
2500 % tuple(datasize))
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2501 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2502 % tuple(fullsize))
2502 % tuple(fullsize))
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2503 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2504 % tuple(deltasize))
2504 % tuple(deltasize))
2505
2505
2506 if numdeltas > 0:
2506 if numdeltas > 0:
2507 ui.write('\n')
2507 ui.write('\n')
2508 fmt = pcfmtstr(numdeltas)
2508 fmt = pcfmtstr(numdeltas)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2509 fmt2 = pcfmtstr(numdeltas, 4)
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2510 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2511 if numprev > 0:
2511 if numprev > 0:
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2512 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2513 numprev))
2513 numprev))
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2514 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2515 numprev))
2515 numprev))
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2516 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2517 numprev))
2517 numprev))
2518 if gdelta:
2518 if gdelta:
2519 ui.write(('deltas against p1 : ')
2519 ui.write(('deltas against p1 : ')
2520 + fmt % pcfmt(nump1, numdeltas))
2520 + fmt % pcfmt(nump1, numdeltas))
2521 ui.write(('deltas against p2 : ')
2521 ui.write(('deltas against p2 : ')
2522 + fmt % pcfmt(nump2, numdeltas))
2522 + fmt % pcfmt(nump2, numdeltas))
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2523 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2524 numdeltas))
2524 numdeltas))
2525
2525
2526 @command('debugrevspec', [], ('REVSPEC'))
2526 @command('debugrevspec', [], ('REVSPEC'))
2527 def debugrevspec(ui, repo, expr):
2527 def debugrevspec(ui, repo, expr):
2528 """parse and apply a revision specification
2528 """parse and apply a revision specification
2529
2529
2530 Use --verbose to print the parsed tree before and after aliases
2530 Use --verbose to print the parsed tree before and after aliases
2531 expansion.
2531 expansion.
2532 """
2532 """
2533 if ui.verbose:
2533 if ui.verbose:
2534 tree = revset.parse(expr)[0]
2534 tree = revset.parse(expr)[0]
2535 ui.note(revset.prettyformat(tree), "\n")
2535 ui.note(revset.prettyformat(tree), "\n")
2536 newtree = revset.findaliases(ui, tree)
2536 newtree = revset.findaliases(ui, tree)
2537 if newtree != tree:
2537 if newtree != tree:
2538 ui.note(revset.prettyformat(newtree), "\n")
2538 ui.note(revset.prettyformat(newtree), "\n")
2539 func = revset.match(ui, expr)
2539 func = revset.match(ui, expr)
2540 for c in func(repo, range(len(repo))):
2540 for c in func(repo, range(len(repo))):
2541 ui.write("%s\n" % c)
2541 ui.write("%s\n" % c)
2542
2542
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2543 @command('debugsetparents', [], _('REV1 [REV2]'))
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2544 def debugsetparents(ui, repo, rev1, rev2=None):
2545 """manually set the parents of the current working directory
2545 """manually set the parents of the current working directory
2546
2546
2547 This is useful for writing repository conversion tools, but should
2547 This is useful for writing repository conversion tools, but should
2548 be used with care.
2548 be used with care.
2549
2549
2550 Returns 0 on success.
2550 Returns 0 on success.
2551 """
2551 """
2552
2552
2553 r1 = scmutil.revsingle(repo, rev1).node()
2553 r1 = scmutil.revsingle(repo, rev1).node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2554 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2555
2555
2556 wlock = repo.wlock()
2556 wlock = repo.wlock()
2557 try:
2557 try:
2558 repo.setparents(r1, r2)
2558 repo.setparents(r1, r2)
2559 finally:
2559 finally:
2560 wlock.release()
2560 wlock.release()
2561
2561
2562 @command('debugdirstate|debugstate',
2562 @command('debugdirstate|debugstate',
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2563 [('', 'nodates', None, _('do not display the saved mtime')),
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2564 ('', 'datesort', None, _('sort by saved mtime'))],
2565 _('[OPTION]...'))
2565 _('[OPTION]...'))
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2566 def debugstate(ui, repo, nodates=None, datesort=None):
2567 """show the contents of the current dirstate"""
2567 """show the contents of the current dirstate"""
2568 timestr = ""
2568 timestr = ""
2569 showdate = not nodates
2569 showdate = not nodates
2570 if datesort:
2570 if datesort:
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2571 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2572 else:
2572 else:
2573 keyfunc = None # sort by filename
2573 keyfunc = None # sort by filename
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2574 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2575 if showdate:
2575 if showdate:
2576 if ent[3] == -1:
2576 if ent[3] == -1:
2577 # Pad or slice to locale representation
2577 # Pad or slice to locale representation
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2578 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2579 time.localtime(0)))
2579 time.localtime(0)))
2580 timestr = 'unset'
2580 timestr = 'unset'
2581 timestr = (timestr[:locale_len] +
2581 timestr = (timestr[:locale_len] +
2582 ' ' * (locale_len - len(timestr)))
2582 ' ' * (locale_len - len(timestr)))
2583 else:
2583 else:
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2584 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2585 time.localtime(ent[3]))
2585 time.localtime(ent[3]))
2586 if ent[1] & 020000:
2586 if ent[1] & 020000:
2587 mode = 'lnk'
2587 mode = 'lnk'
2588 else:
2588 else:
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2589 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2590 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2591 for f in repo.dirstate.copies():
2591 for f in repo.dirstate.copies():
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2592 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2593
2593
2594 @command('debugsub',
2594 @command('debugsub',
2595 [('r', 'rev', '',
2595 [('r', 'rev', '',
2596 _('revision to check'), _('REV'))],
2596 _('revision to check'), _('REV'))],
2597 _('[-r REV] [REV]'))
2597 _('[-r REV] [REV]'))
2598 def debugsub(ui, repo, rev=None):
2598 def debugsub(ui, repo, rev=None):
2599 ctx = scmutil.revsingle(repo, rev, None)
2599 ctx = scmutil.revsingle(repo, rev, None)
2600 for k, v in sorted(ctx.substate.items()):
2600 for k, v in sorted(ctx.substate.items()):
2601 ui.write(('path %s\n') % k)
2601 ui.write(('path %s\n') % k)
2602 ui.write((' source %s\n') % v[0])
2602 ui.write((' source %s\n') % v[0])
2603 ui.write((' revision %s\n') % v[1])
2603 ui.write((' revision %s\n') % v[1])
2604
2604
2605 @command('debugsuccessorssets',
2605 @command('debugsuccessorssets',
2606 [],
2606 [],
2607 _('[REV]'))
2607 _('[REV]'))
2608 def debugsuccessorssets(ui, repo, *revs):
2608 def debugsuccessorssets(ui, repo, *revs):
2609 """show set of successors for revision
2609 """show set of successors for revision
2610
2610
2611 A successors set of changeset A is a consistent group of revisions that
2611 A successors set of changeset A is a consistent group of revisions that
2612 succeed A. It contains non-obsolete changesets only.
2612 succeed A. It contains non-obsolete changesets only.
2613
2613
2614 In most cases a changeset A has a single successors set containing a single
2614 In most cases a changeset A has a single successors set containing a single
2615 successor (changeset A replaced by A').
2615 successor (changeset A replaced by A').
2616
2616
2617 A changeset that is made obsolete with no successors are called "pruned".
2617 A changeset that is made obsolete with no successors are called "pruned".
2618 Such changesets have no successors sets at all.
2618 Such changesets have no successors sets at all.
2619
2619
2620 A changeset that has been "split" will have a successors set containing
2620 A changeset that has been "split" will have a successors set containing
2621 more than one successor.
2621 more than one successor.
2622
2622
2623 A changeset that has been rewritten in multiple different ways is called
2623 A changeset that has been rewritten in multiple different ways is called
2624 "divergent". Such changesets have multiple successor sets (each of which
2624 "divergent". Such changesets have multiple successor sets (each of which
2625 may also be split, i.e. have multiple successors).
2625 may also be split, i.e. have multiple successors).
2626
2626
2627 Results are displayed as follows::
2627 Results are displayed as follows::
2628
2628
2629 <rev1>
2629 <rev1>
2630 <successors-1A>
2630 <successors-1A>
2631 <rev2>
2631 <rev2>
2632 <successors-2A>
2632 <successors-2A>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2633 <successors-2B1> <successors-2B2> <successors-2B3>
2634
2634
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2635 Here rev2 has two possible (i.e. divergent) successors sets. The first
2636 holds one element, whereas the second holds three (i.e. the changeset has
2636 holds one element, whereas the second holds three (i.e. the changeset has
2637 been split).
2637 been split).
2638 """
2638 """
2639 # passed to successorssets caching computation from one call to another
2639 # passed to successorssets caching computation from one call to another
2640 cache = {}
2640 cache = {}
2641 ctx2str = str
2641 ctx2str = str
2642 node2str = short
2642 node2str = short
2643 if ui.debug():
2643 if ui.debug():
2644 def ctx2str(ctx):
2644 def ctx2str(ctx):
2645 return ctx.hex()
2645 return ctx.hex()
2646 node2str = hex
2646 node2str = hex
2647 for rev in scmutil.revrange(repo, revs):
2647 for rev in scmutil.revrange(repo, revs):
2648 ctx = repo[rev]
2648 ctx = repo[rev]
2649 ui.write('%s\n'% ctx2str(ctx))
2649 ui.write('%s\n'% ctx2str(ctx))
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2650 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2651 if succsset:
2651 if succsset:
2652 ui.write(' ')
2652 ui.write(' ')
2653 ui.write(node2str(succsset[0]))
2653 ui.write(node2str(succsset[0]))
2654 for node in succsset[1:]:
2654 for node in succsset[1:]:
2655 ui.write(' ')
2655 ui.write(' ')
2656 ui.write(node2str(node))
2656 ui.write(node2str(node))
2657 ui.write('\n')
2657 ui.write('\n')
2658
2658
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2659 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2660 def debugwalk(ui, repo, *pats, **opts):
2660 def debugwalk(ui, repo, *pats, **opts):
2661 """show how files match on given patterns"""
2661 """show how files match on given patterns"""
2662 m = scmutil.match(repo[None], pats, opts)
2662 m = scmutil.match(repo[None], pats, opts)
2663 items = list(repo.walk(m))
2663 items = list(repo.walk(m))
2664 if not items:
2664 if not items:
2665 return
2665 return
2666 f = lambda fn: fn
2666 f = lambda fn: fn
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2667 if ui.configbool('ui', 'slash') and os.sep != '/':
2668 f = lambda fn: util.normpath(fn)
2668 f = lambda fn: util.normpath(fn)
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2669 fmt = 'f %%-%ds %%-%ds %%s' % (
2670 max([len(abs) for abs in items]),
2670 max([len(abs) for abs in items]),
2671 max([len(m.rel(abs)) for abs in items]))
2671 max([len(m.rel(abs)) for abs in items]))
2672 for abs in items:
2672 for abs in items:
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2673 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2674 ui.write("%s\n" % line.rstrip())
2674 ui.write("%s\n" % line.rstrip())
2675
2675
2676 @command('debugwireargs',
2676 @command('debugwireargs',
2677 [('', 'three', '', 'three'),
2677 [('', 'three', '', 'three'),
2678 ('', 'four', '', 'four'),
2678 ('', 'four', '', 'four'),
2679 ('', 'five', '', 'five'),
2679 ('', 'five', '', 'five'),
2680 ] + remoteopts,
2680 ] + remoteopts,
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2681 _('REPO [OPTIONS]... [ONE [TWO]]'))
2682 def debugwireargs(ui, repopath, *vals, **opts):
2682 def debugwireargs(ui, repopath, *vals, **opts):
2683 repo = hg.peer(ui, opts, repopath)
2683 repo = hg.peer(ui, opts, repopath)
2684 for opt in remoteopts:
2684 for opt in remoteopts:
2685 del opts[opt[1]]
2685 del opts[opt[1]]
2686 args = {}
2686 args = {}
2687 for k, v in opts.iteritems():
2687 for k, v in opts.iteritems():
2688 if v:
2688 if v:
2689 args[k] = v
2689 args[k] = v
2690 # run twice to check that we don't mess up the stream for the next command
2690 # run twice to check that we don't mess up the stream for the next command
2691 res1 = repo.debugwireargs(*vals, **args)
2691 res1 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2692 res2 = repo.debugwireargs(*vals, **args)
2693 ui.write("%s\n" % res1)
2693 ui.write("%s\n" % res1)
2694 if res1 != res2:
2694 if res1 != res2:
2695 ui.warn("%s\n" % res2)
2695 ui.warn("%s\n" % res2)
2696
2696
2697 @command('^diff',
2697 @command('^diff',
2698 [('r', 'rev', [], _('revision'), _('REV')),
2698 [('r', 'rev', [], _('revision'), _('REV')),
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2699 ('c', 'change', '', _('change made by revision'), _('REV'))
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2700 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2701 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2702 def diff(ui, repo, *pats, **opts):
2702 def diff(ui, repo, *pats, **opts):
2703 """diff repository (or selected files)
2703 """diff repository (or selected files)
2704
2704
2705 Show differences between revisions for the specified files.
2705 Show differences between revisions for the specified files.
2706
2706
2707 Differences between files are shown using the unified diff format.
2707 Differences between files are shown using the unified diff format.
2708
2708
2709 .. note::
2709 .. note::
2710 diff may generate unexpected results for merges, as it will
2710 diff may generate unexpected results for merges, as it will
2711 default to comparing against the working directory's first
2711 default to comparing against the working directory's first
2712 parent changeset if no revisions are specified.
2712 parent changeset if no revisions are specified.
2713
2713
2714 When two revision arguments are given, then changes are shown
2714 When two revision arguments are given, then changes are shown
2715 between those revisions. If only one revision is specified then
2715 between those revisions. If only one revision is specified then
2716 that revision is compared to the working directory, and, when no
2716 that revision is compared to the working directory, and, when no
2717 revisions are specified, the working directory files are compared
2717 revisions are specified, the working directory files are compared
2718 to its parent.
2718 to its parent.
2719
2719
2720 Alternatively you can specify -c/--change with a revision to see
2720 Alternatively you can specify -c/--change with a revision to see
2721 the changes in that changeset relative to its first parent.
2721 the changes in that changeset relative to its first parent.
2722
2722
2723 Without the -a/--text option, diff will avoid generating diffs of
2723 Without the -a/--text option, diff will avoid generating diffs of
2724 files it detects as binary. With -a, diff will generate a diff
2724 files it detects as binary. With -a, diff will generate a diff
2725 anyway, probably with undesirable results.
2725 anyway, probably with undesirable results.
2726
2726
2727 Use the -g/--git option to generate diffs in the git extended diff
2727 Use the -g/--git option to generate diffs in the git extended diff
2728 format. For more information, read :hg:`help diffs`.
2728 format. For more information, read :hg:`help diffs`.
2729
2729
2730 .. container:: verbose
2730 .. container:: verbose
2731
2731
2732 Examples:
2732 Examples:
2733
2733
2734 - compare a file in the current working directory to its parent::
2734 - compare a file in the current working directory to its parent::
2735
2735
2736 hg diff foo.c
2736 hg diff foo.c
2737
2737
2738 - compare two historical versions of a directory, with rename info::
2738 - compare two historical versions of a directory, with rename info::
2739
2739
2740 hg diff --git -r 1.0:1.2 lib/
2740 hg diff --git -r 1.0:1.2 lib/
2741
2741
2742 - get change stats relative to the last change on some date::
2742 - get change stats relative to the last change on some date::
2743
2743
2744 hg diff --stat -r "date('may 2')"
2744 hg diff --stat -r "date('may 2')"
2745
2745
2746 - diff all newly-added files that contain a keyword::
2746 - diff all newly-added files that contain a keyword::
2747
2747
2748 hg diff "set:added() and grep(GNU)"
2748 hg diff "set:added() and grep(GNU)"
2749
2749
2750 - compare a revision and its parents::
2750 - compare a revision and its parents::
2751
2751
2752 hg diff -c 9353 # compare against first parent
2752 hg diff -c 9353 # compare against first parent
2753 hg diff -r 9353^:9353 # same using revset syntax
2753 hg diff -r 9353^:9353 # same using revset syntax
2754 hg diff -r 9353^2:9353 # compare against the second parent
2754 hg diff -r 9353^2:9353 # compare against the second parent
2755
2755
2756 Returns 0 on success.
2756 Returns 0 on success.
2757 """
2757 """
2758
2758
2759 revs = opts.get('rev')
2759 revs = opts.get('rev')
2760 change = opts.get('change')
2760 change = opts.get('change')
2761 stat = opts.get('stat')
2761 stat = opts.get('stat')
2762 reverse = opts.get('reverse')
2762 reverse = opts.get('reverse')
2763
2763
2764 if revs and change:
2764 if revs and change:
2765 msg = _('cannot specify --rev and --change at the same time')
2765 msg = _('cannot specify --rev and --change at the same time')
2766 raise util.Abort(msg)
2766 raise util.Abort(msg)
2767 elif change:
2767 elif change:
2768 node2 = scmutil.revsingle(repo, change, None).node()
2768 node2 = scmutil.revsingle(repo, change, None).node()
2769 node1 = repo[node2].p1().node()
2769 node1 = repo[node2].p1().node()
2770 else:
2770 else:
2771 node1, node2 = scmutil.revpair(repo, revs)
2771 node1, node2 = scmutil.revpair(repo, revs)
2772
2772
2773 if reverse:
2773 if reverse:
2774 node1, node2 = node2, node1
2774 node1, node2 = node2, node1
2775
2775
2776 diffopts = patch.diffopts(ui, opts)
2776 diffopts = patch.diffopts(ui, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2777 m = scmutil.match(repo[node2], pats, opts)
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2778 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2779 listsubrepos=opts.get('subrepos'))
2779 listsubrepos=opts.get('subrepos'))
2780
2780
2781 @command('^export',
2781 @command('^export',
2782 [('o', 'output', '',
2782 [('o', 'output', '',
2783 _('print output to file with formatted name'), _('FORMAT')),
2783 _('print output to file with formatted name'), _('FORMAT')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2784 ('', 'switch-parent', None, _('diff against the second parent')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2785 ('r', 'rev', [], _('revisions to export'), _('REV')),
2786 ] + diffopts,
2786 ] + diffopts,
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2787 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2788 def export(ui, repo, *changesets, **opts):
2788 def export(ui, repo, *changesets, **opts):
2789 """dump the header and diffs for one or more changesets
2789 """dump the header and diffs for one or more changesets
2790
2790
2791 Print the changeset header and diffs for one or more revisions.
2791 Print the changeset header and diffs for one or more revisions.
2792 If no revision is given, the parent of the working directory is used.
2792 If no revision is given, the parent of the working directory is used.
2793
2793
2794 The information shown in the changeset header is: author, date,
2794 The information shown in the changeset header is: author, date,
2795 branch name (if non-default), changeset hash, parent(s) and commit
2795 branch name (if non-default), changeset hash, parent(s) and commit
2796 comment.
2796 comment.
2797
2797
2798 .. note::
2798 .. note::
2799 export may generate unexpected diff output for merge
2799 export may generate unexpected diff output for merge
2800 changesets, as it will compare the merge changeset against its
2800 changesets, as it will compare the merge changeset against its
2801 first parent only.
2801 first parent only.
2802
2802
2803 Output may be to a file, in which case the name of the file is
2803 Output may be to a file, in which case the name of the file is
2804 given using a format string. The formatting rules are as follows:
2804 given using a format string. The formatting rules are as follows:
2805
2805
2806 :``%%``: literal "%" character
2806 :``%%``: literal "%" character
2807 :``%H``: changeset hash (40 hexadecimal digits)
2807 :``%H``: changeset hash (40 hexadecimal digits)
2808 :``%N``: number of patches being generated
2808 :``%N``: number of patches being generated
2809 :``%R``: changeset revision number
2809 :``%R``: changeset revision number
2810 :``%b``: basename of the exporting repository
2810 :``%b``: basename of the exporting repository
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2813 :``%n``: zero-padded sequence number, starting at 1
2813 :``%n``: zero-padded sequence number, starting at 1
2814 :``%r``: zero-padded changeset revision number
2814 :``%r``: zero-padded changeset revision number
2815
2815
2816 Without the -a/--text option, export will avoid generating diffs
2816 Without the -a/--text option, export will avoid generating diffs
2817 of files it detects as binary. With -a, export will generate a
2817 of files it detects as binary. With -a, export will generate a
2818 diff anyway, probably with undesirable results.
2818 diff anyway, probably with undesirable results.
2819
2819
2820 Use the -g/--git option to generate diffs in the git extended diff
2820 Use the -g/--git option to generate diffs in the git extended diff
2821 format. See :hg:`help diffs` for more information.
2821 format. See :hg:`help diffs` for more information.
2822
2822
2823 With the --switch-parent option, the diff will be against the
2823 With the --switch-parent option, the diff will be against the
2824 second parent. It can be useful to review a merge.
2824 second parent. It can be useful to review a merge.
2825
2825
2826 .. container:: verbose
2826 .. container:: verbose
2827
2827
2828 Examples:
2828 Examples:
2829
2829
2830 - use export and import to transplant a bugfix to the current
2830 - use export and import to transplant a bugfix to the current
2831 branch::
2831 branch::
2832
2832
2833 hg export -r 9353 | hg import -
2833 hg export -r 9353 | hg import -
2834
2834
2835 - export all the changesets between two revisions to a file with
2835 - export all the changesets between two revisions to a file with
2836 rename information::
2836 rename information::
2837
2837
2838 hg export --git -r 123:150 > changes.txt
2838 hg export --git -r 123:150 > changes.txt
2839
2839
2840 - split outgoing changes into a series of patches with
2840 - split outgoing changes into a series of patches with
2841 descriptive names::
2841 descriptive names::
2842
2842
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2844
2844
2845 Returns 0 on success.
2845 Returns 0 on success.
2846 """
2846 """
2847 changesets += tuple(opts.get('rev', []))
2847 changesets += tuple(opts.get('rev', []))
2848 if not changesets:
2848 if not changesets:
2849 changesets = ['.']
2849 changesets = ['.']
2850 revs = scmutil.revrange(repo, changesets)
2850 revs = scmutil.revrange(repo, changesets)
2851 if not revs:
2851 if not revs:
2852 raise util.Abort(_("export requires at least one changeset"))
2852 raise util.Abort(_("export requires at least one changeset"))
2853 if len(revs) > 1:
2853 if len(revs) > 1:
2854 ui.note(_('exporting patches:\n'))
2854 ui.note(_('exporting patches:\n'))
2855 else:
2855 else:
2856 ui.note(_('exporting patch:\n'))
2856 ui.note(_('exporting patch:\n'))
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2858 switch_parent=opts.get('switch_parent'),
2858 switch_parent=opts.get('switch_parent'),
2859 opts=patch.diffopts(ui, opts))
2859 opts=patch.diffopts(ui, opts))
2860
2860
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2862 def forget(ui, repo, *pats, **opts):
2862 def forget(ui, repo, *pats, **opts):
2863 """forget the specified files on the next commit
2863 """forget the specified files on the next commit
2864
2864
2865 Mark the specified files so they will no longer be tracked
2865 Mark the specified files so they will no longer be tracked
2866 after the next commit.
2866 after the next commit.
2867
2867
2868 This only removes files from the current branch, not from the
2868 This only removes files from the current branch, not from the
2869 entire project history, and it does not delete them from the
2869 entire project history, and it does not delete them from the
2870 working directory.
2870 working directory.
2871
2871
2872 To undo a forget before the next commit, see :hg:`add`.
2872 To undo a forget before the next commit, see :hg:`add`.
2873
2873
2874 .. container:: verbose
2874 .. container:: verbose
2875
2875
2876 Examples:
2876 Examples:
2877
2877
2878 - forget newly-added binary files::
2878 - forget newly-added binary files::
2879
2879
2880 hg forget "set:added() and binary()"
2880 hg forget "set:added() and binary()"
2881
2881
2882 - forget files that would be excluded by .hgignore::
2882 - forget files that would be excluded by .hgignore::
2883
2883
2884 hg forget "set:hgignore()"
2884 hg forget "set:hgignore()"
2885
2885
2886 Returns 0 on success.
2886 Returns 0 on success.
2887 """
2887 """
2888
2888
2889 if not pats:
2889 if not pats:
2890 raise util.Abort(_('no files specified'))
2890 raise util.Abort(_('no files specified'))
2891
2891
2892 m = scmutil.match(repo[None], pats, opts)
2892 m = scmutil.match(repo[None], pats, opts)
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2894 return rejected and 1 or 0
2894 return rejected and 1 or 0
2895
2895
2896 @command(
2896 @command(
2897 'graft',
2897 'graft',
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2901 ('', 'log', None, _('append graft info to log message')),
2901 ('', 'log', None, _('append graft info to log message')),
2902 ('D', 'currentdate', False,
2902 ('D', 'currentdate', False,
2903 _('record the current date as commit date')),
2903 _('record the current date as commit date')),
2904 ('U', 'currentuser', False,
2904 ('U', 'currentuser', False,
2905 _('record the current user as committer'), _('DATE'))]
2905 _('record the current user as committer'), _('DATE'))]
2906 + commitopts2 + mergetoolopts + dryrunopts,
2906 + commitopts2 + mergetoolopts + dryrunopts,
2907 _('[OPTION]... [-r] REV...'))
2907 _('[OPTION]... [-r] REV...'))
2908 def graft(ui, repo, *revs, **opts):
2908 def graft(ui, repo, *revs, **opts):
2909 '''copy changes from other branches onto the current branch
2909 '''copy changes from other branches onto the current branch
2910
2910
2911 This command uses Mercurial's merge logic to copy individual
2911 This command uses Mercurial's merge logic to copy individual
2912 changes from other branches without merging branches in the
2912 changes from other branches without merging branches in the
2913 history graph. This is sometimes known as 'backporting' or
2913 history graph. This is sometimes known as 'backporting' or
2914 'cherry-picking'. By default, graft will copy user, date, and
2914 'cherry-picking'. By default, graft will copy user, date, and
2915 description from the source changesets.
2915 description from the source changesets.
2916
2916
2917 Changesets that are ancestors of the current revision, that have
2917 Changesets that are ancestors of the current revision, that have
2918 already been grafted, or that are merges will be skipped.
2918 already been grafted, or that are merges will be skipped.
2919
2919
2920 If --log is specified, log messages will have a comment appended
2920 If --log is specified, log messages will have a comment appended
2921 of the form::
2921 of the form::
2922
2922
2923 (grafted from CHANGESETHASH)
2923 (grafted from CHANGESETHASH)
2924
2924
2925 If a graft merge results in conflicts, the graft process is
2925 If a graft merge results in conflicts, the graft process is
2926 interrupted so that the current merge can be manually resolved.
2926 interrupted so that the current merge can be manually resolved.
2927 Once all conflicts are addressed, the graft process can be
2927 Once all conflicts are addressed, the graft process can be
2928 continued with the -c/--continue option.
2928 continued with the -c/--continue option.
2929
2929
2930 .. note::
2930 .. note::
2931 The -c/--continue option does not reapply earlier options.
2931 The -c/--continue option does not reapply earlier options.
2932
2932
2933 .. container:: verbose
2933 .. container:: verbose
2934
2934
2935 Examples:
2935 Examples:
2936
2936
2937 - copy a single change to the stable branch and edit its description::
2937 - copy a single change to the stable branch and edit its description::
2938
2938
2939 hg update stable
2939 hg update stable
2940 hg graft --edit 9393
2940 hg graft --edit 9393
2941
2941
2942 - graft a range of changesets with one exception, updating dates::
2942 - graft a range of changesets with one exception, updating dates::
2943
2943
2944 hg graft -D "2085::2093 and not 2091"
2944 hg graft -D "2085::2093 and not 2091"
2945
2945
2946 - continue a graft after resolving conflicts::
2946 - continue a graft after resolving conflicts::
2947
2947
2948 hg graft -c
2948 hg graft -c
2949
2949
2950 - show the source of a grafted changeset::
2950 - show the source of a grafted changeset::
2951
2951
2952 hg log --debug -r .
2952 hg log --debug -r .
2953
2953
2954 Returns 0 on successful completion.
2954 Returns 0 on successful completion.
2955 '''
2955 '''
2956
2956
2957 revs = list(revs)
2957 revs = list(revs)
2958 revs.extend(opts['rev'])
2958 revs.extend(opts['rev'])
2959
2959
2960 if not opts.get('user') and opts.get('currentuser'):
2960 if not opts.get('user') and opts.get('currentuser'):
2961 opts['user'] = ui.username()
2961 opts['user'] = ui.username()
2962 if not opts.get('date') and opts.get('currentdate'):
2962 if not opts.get('date') and opts.get('currentdate'):
2963 opts['date'] = "%d %d" % util.makedate()
2963 opts['date'] = "%d %d" % util.makedate()
2964
2964
2965 editor = None
2965 editor = None
2966 if opts.get('edit'):
2966 if opts.get('edit'):
2967 editor = cmdutil.commitforceeditor
2967 editor = cmdutil.commitforceeditor
2968
2968
2969 cont = False
2969 cont = False
2970 if opts['continue']:
2970 if opts['continue']:
2971 cont = True
2971 cont = True
2972 if revs:
2972 if revs:
2973 raise util.Abort(_("can't specify --continue and revisions"))
2973 raise util.Abort(_("can't specify --continue and revisions"))
2974 # read in unfinished revisions
2974 # read in unfinished revisions
2975 try:
2975 try:
2976 nodes = repo.opener.read('graftstate').splitlines()
2976 nodes = repo.opener.read('graftstate').splitlines()
2977 revs = [repo[node].rev() for node in nodes]
2977 revs = [repo[node].rev() for node in nodes]
2978 except IOError, inst:
2978 except IOError, inst:
2979 if inst.errno != errno.ENOENT:
2979 if inst.errno != errno.ENOENT:
2980 raise
2980 raise
2981 raise util.Abort(_("no graft state found, can't continue"))
2981 raise util.Abort(_("no graft state found, can't continue"))
2982 else:
2982 else:
2983 cmdutil.checkunfinished(repo)
2983 cmdutil.checkunfinished(repo)
2984 cmdutil.bailifchanged(repo)
2984 cmdutil.bailifchanged(repo)
2985 if not revs:
2985 if not revs:
2986 raise util.Abort(_('no revisions specified'))
2986 raise util.Abort(_('no revisions specified'))
2987 revs = scmutil.revrange(repo, revs)
2987 revs = scmutil.revrange(repo, revs)
2988
2988
2989 # check for merges
2989 # check for merges
2990 for rev in repo.revs('%ld and merge()', revs):
2990 for rev in repo.revs('%ld and merge()', revs):
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2992 revs.remove(rev)
2992 revs.remove(rev)
2993 if not revs:
2993 if not revs:
2994 return -1
2994 return -1
2995
2995
2996 # check for ancestors of dest branch
2996 # check for ancestors of dest branch
2997 crev = repo['.'].rev()
2997 crev = repo['.'].rev()
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2999 # don't mutate while iterating, create a copy
2999 # don't mutate while iterating, create a copy
3000 for rev in list(revs):
3000 for rev in list(revs):
3001 if rev in ancestors:
3001 if rev in ancestors:
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 ui.warn(_('skipping ancestor revision %s\n') % rev)
3003 revs.remove(rev)
3003 revs.remove(rev)
3004 if not revs:
3004 if not revs:
3005 return -1
3005 return -1
3006
3006
3007 # analyze revs for earlier grafts
3007 # analyze revs for earlier grafts
3008 ids = {}
3008 ids = {}
3009 for ctx in repo.set("%ld", revs):
3009 for ctx in repo.set("%ld", revs):
3010 ids[ctx.hex()] = ctx.rev()
3010 ids[ctx.hex()] = ctx.rev()
3011 n = ctx.extra().get('source')
3011 n = ctx.extra().get('source')
3012 if n:
3012 if n:
3013 ids[n] = ctx.rev()
3013 ids[n] = ctx.rev()
3014
3014
3015 # check ancestors for earlier grafts
3015 # check ancestors for earlier grafts
3016 ui.debug('scanning for duplicate grafts\n')
3016 ui.debug('scanning for duplicate grafts\n')
3017
3017
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3019 ctx = repo[rev]
3019 ctx = repo[rev]
3020 n = ctx.extra().get('source')
3020 n = ctx.extra().get('source')
3021 if n in ids:
3021 if n in ids:
3022 r = repo[n].rev()
3022 r = repo[n].rev()
3023 if r in revs:
3023 if r in revs:
3024 ui.warn(_('skipping already grafted revision %s\n') % r)
3024 ui.warn(_('skipping already grafted revision %s\n') % r)
3025 revs.remove(r)
3025 revs.remove(r)
3026 elif ids[n] in revs:
3026 elif ids[n] in revs:
3027 ui.warn(_('skipping already grafted revision %s '
3027 ui.warn(_('skipping already grafted revision %s '
3028 '(same origin %d)\n') % (ids[n], r))
3028 '(same origin %d)\n') % (ids[n], r))
3029 revs.remove(ids[n])
3029 revs.remove(ids[n])
3030 elif ctx.hex() in ids:
3030 elif ctx.hex() in ids:
3031 r = ids[ctx.hex()]
3031 r = ids[ctx.hex()]
3032 ui.warn(_('skipping already grafted revision %s '
3032 ui.warn(_('skipping already grafted revision %s '
3033 '(was grafted from %d)\n') % (r, rev))
3033 '(was grafted from %d)\n') % (r, rev))
3034 revs.remove(r)
3034 revs.remove(r)
3035 if not revs:
3035 if not revs:
3036 return -1
3036 return -1
3037
3037
3038 wlock = repo.wlock()
3038 wlock = repo.wlock()
3039 try:
3039 try:
3040 current = repo['.']
3040 current = repo['.']
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042
3042
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 if opts.get('dry_run'):
3044 if opts.get('dry_run'):
3045 continue
3045 continue
3046
3046
3047 source = ctx.extra().get('source')
3047 source = ctx.extra().get('source')
3048 if not source:
3048 if not source:
3049 source = ctx.hex()
3049 source = ctx.hex()
3050 extra = {'source': source}
3050 extra = {'source': source}
3051 user = ctx.user()
3051 user = ctx.user()
3052 if opts.get('user'):
3052 if opts.get('user'):
3053 user = opts['user']
3053 user = opts['user']
3054 date = ctx.date()
3054 date = ctx.date()
3055 if opts.get('date'):
3055 if opts.get('date'):
3056 date = opts['date']
3056 date = opts['date']
3057 message = ctx.description()
3057 message = ctx.description()
3058 if opts.get('log'):
3058 if opts.get('log'):
3059 message += '\n(grafted from %s)' % ctx.hex()
3059 message += '\n(grafted from %s)' % ctx.hex()
3060
3060
3061 # we don't merge the first commit when continuing
3061 # we don't merge the first commit when continuing
3062 if not cont:
3062 if not cont:
3063 # perform the graft merge with p1(rev) as 'ancestor'
3063 # perform the graft merge with p1(rev) as 'ancestor'
3064 try:
3064 try:
3065 # ui.forcemerge is an internal variable, do not document
3065 # ui.forcemerge is an internal variable, do not document
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 ctx.p1().node())
3068 ctx.p1().node())
3069 finally:
3069 finally:
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3071 # report any conflicts
3071 # report any conflicts
3072 if stats and stats[3] > 0:
3072 if stats and stats[3] > 0:
3073 # write out state for --continue
3073 # write out state for --continue
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 repo.opener.write('graftstate', ''.join(nodelines))
3075 repo.opener.write('graftstate', ''.join(nodelines))
3076 raise util.Abort(
3076 raise util.Abort(
3077 _("unresolved conflicts, can't continue"),
3077 _("unresolved conflicts, can't continue"),
3078 hint=_('use hg resolve and hg graft --continue'))
3078 hint=_('use hg resolve and hg graft --continue'))
3079 else:
3079 else:
3080 cont = False
3080 cont = False
3081
3081
3082 # drop the second merge parent
3082 # drop the second merge parent
3083 repo.setparents(current.node(), nullid)
3083 repo.setparents(current.node(), nullid)
3084 repo.dirstate.write()
3084 repo.dirstate.write()
3085 # fix up dirstate for copies and renames
3085 # fix up dirstate for copies and renames
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087
3087
3088 # commit
3088 # commit
3089 node = repo.commit(text=message, user=user,
3089 node = repo.commit(text=message, user=user,
3090 date=date, extra=extra, editor=editor)
3090 date=date, extra=extra, editor=editor)
3091 if node is None:
3091 if node is None:
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 else:
3093 else:
3094 current = repo[node]
3094 current = repo[node]
3095 finally:
3095 finally:
3096 wlock.release()
3096 wlock.release()
3097
3097
3098 # remove state when we complete successfully
3098 # remove state when we complete successfully
3099 if not opts.get('dry_run'):
3099 if not opts.get('dry_run'):
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101
3101
3102 return 0
3102 return 0
3103
3103
3104 @command('grep',
3104 @command('grep',
3105 [('0', 'print0', None, _('end fields with NUL')),
3105 [('0', 'print0', None, _('end fields with NUL')),
3106 ('', 'all', None, _('print all revisions that match')),
3106 ('', 'all', None, _('print all revisions that match')),
3107 ('a', 'text', None, _('treat all files as text')),
3107 ('a', 'text', None, _('treat all files as text')),
3108 ('f', 'follow', None,
3108 ('f', 'follow', None,
3109 _('follow changeset history,'
3109 _('follow changeset history,'
3110 ' or file history across copies and renames')),
3110 ' or file history across copies and renames')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('l', 'files-with-matches', None,
3112 ('l', 'files-with-matches', None,
3113 _('print only filenames and revisions that match')),
3113 _('print only filenames and revisions that match')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('r', 'rev', [],
3115 ('r', 'rev', [],
3116 _('only search files changed within revision range'), _('REV')),
3116 _('only search files changed within revision range'), _('REV')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3119 ] + walkopts,
3119 ] + walkopts,
3120 _('[OPTION]... PATTERN [FILE]...'))
3120 _('[OPTION]... PATTERN [FILE]...'))
3121 def grep(ui, repo, pattern, *pats, **opts):
3121 def grep(ui, repo, pattern, *pats, **opts):
3122 """search for a pattern in specified files and revisions
3122 """search for a pattern in specified files and revisions
3123
3123
3124 Search revisions of files for a regular expression.
3124 Search revisions of files for a regular expression.
3125
3125
3126 This command behaves differently than Unix grep. It only accepts
3126 This command behaves differently than Unix grep. It only accepts
3127 Python/Perl regexps. It searches repository history, not the
3127 Python/Perl regexps. It searches repository history, not the
3128 working directory. It always prints the revision number in which a
3128 working directory. It always prints the revision number in which a
3129 match appears.
3129 match appears.
3130
3130
3131 By default, grep only prints output for the first revision of a
3131 By default, grep only prints output for the first revision of a
3132 file in which it finds a match. To get it to print every revision
3132 file in which it finds a match. To get it to print every revision
3133 that contains a change in match status ("-" for a match that
3133 that contains a change in match status ("-" for a match that
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3135 use the --all flag.
3135 use the --all flag.
3136
3136
3137 Returns 0 if a match is found, 1 otherwise.
3137 Returns 0 if a match is found, 1 otherwise.
3138 """
3138 """
3139 reflags = re.M
3139 reflags = re.M
3140 if opts.get('ignore_case'):
3140 if opts.get('ignore_case'):
3141 reflags |= re.I
3141 reflags |= re.I
3142 try:
3142 try:
3143 regexp = util.compilere(pattern, reflags)
3143 regexp = util.compilere(pattern, reflags)
3144 except re.error, inst:
3144 except re.error, inst:
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 return 1
3146 return 1
3147 sep, eol = ':', '\n'
3147 sep, eol = ':', '\n'
3148 if opts.get('print0'):
3148 if opts.get('print0'):
3149 sep = eol = '\0'
3149 sep = eol = '\0'
3150
3150
3151 getfile = util.lrucachefunc(repo.file)
3151 getfile = util.lrucachefunc(repo.file)
3152
3152
3153 def matchlines(body):
3153 def matchlines(body):
3154 begin = 0
3154 begin = 0
3155 linenum = 0
3155 linenum = 0
3156 while begin < len(body):
3156 while begin < len(body):
3157 match = regexp.search(body, begin)
3157 match = regexp.search(body, begin)
3158 if not match:
3158 if not match:
3159 break
3159 break
3160 mstart, mend = match.span()
3160 mstart, mend = match.span()
3161 linenum += body.count('\n', begin, mstart) + 1
3161 linenum += body.count('\n', begin, mstart) + 1
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 lend = begin - 1
3164 lend = begin - 1
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166
3166
3167 class linestate(object):
3167 class linestate(object):
3168 def __init__(self, line, linenum, colstart, colend):
3168 def __init__(self, line, linenum, colstart, colend):
3169 self.line = line
3169 self.line = line
3170 self.linenum = linenum
3170 self.linenum = linenum
3171 self.colstart = colstart
3171 self.colstart = colstart
3172 self.colend = colend
3172 self.colend = colend
3173
3173
3174 def __hash__(self):
3174 def __hash__(self):
3175 return hash((self.linenum, self.line))
3175 return hash((self.linenum, self.line))
3176
3176
3177 def __eq__(self, other):
3177 def __eq__(self, other):
3178 return self.line == other.line
3178 return self.line == other.line
3179
3179
3180 matches = {}
3180 matches = {}
3181 copies = {}
3181 copies = {}
3182 def grepbody(fn, rev, body):
3182 def grepbody(fn, rev, body):
3183 matches[rev].setdefault(fn, [])
3183 matches[rev].setdefault(fn, [])
3184 m = matches[rev][fn]
3184 m = matches[rev][fn]
3185 for lnum, cstart, cend, line in matchlines(body):
3185 for lnum, cstart, cend, line in matchlines(body):
3186 s = linestate(line, lnum, cstart, cend)
3186 s = linestate(line, lnum, cstart, cend)
3187 m.append(s)
3187 m.append(s)
3188
3188
3189 def difflinestates(a, b):
3189 def difflinestates(a, b):
3190 sm = difflib.SequenceMatcher(None, a, b)
3190 sm = difflib.SequenceMatcher(None, a, b)
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 if tag == 'insert':
3192 if tag == 'insert':
3193 for i in xrange(blo, bhi):
3193 for i in xrange(blo, bhi):
3194 yield ('+', b[i])
3194 yield ('+', b[i])
3195 elif tag == 'delete':
3195 elif tag == 'delete':
3196 for i in xrange(alo, ahi):
3196 for i in xrange(alo, ahi):
3197 yield ('-', a[i])
3197 yield ('-', a[i])
3198 elif tag == 'replace':
3198 elif tag == 'replace':
3199 for i in xrange(alo, ahi):
3199 for i in xrange(alo, ahi):
3200 yield ('-', a[i])
3200 yield ('-', a[i])
3201 for i in xrange(blo, bhi):
3201 for i in xrange(blo, bhi):
3202 yield ('+', b[i])
3202 yield ('+', b[i])
3203
3203
3204 def display(fn, ctx, pstates, states):
3204 def display(fn, ctx, pstates, states):
3205 rev = ctx.rev()
3205 rev = ctx.rev()
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3207 found = False
3207 found = False
3208 filerevmatches = {}
3208 filerevmatches = {}
3209 def binary():
3209 def binary():
3210 flog = getfile(fn)
3210 flog = getfile(fn)
3211 return util.binary(flog.read(ctx.filenode(fn)))
3211 return util.binary(flog.read(ctx.filenode(fn)))
3212
3212
3213 if opts.get('all'):
3213 if opts.get('all'):
3214 iter = difflinestates(pstates, states)
3214 iter = difflinestates(pstates, states)
3215 else:
3215 else:
3216 iter = [('', l) for l in states]
3216 iter = [('', l) for l in states]
3217 for change, l in iter:
3217 for change, l in iter:
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 before, match, after = None, None, None
3219 before, match, after = None, None, None
3220
3220
3221 if opts.get('line_number'):
3221 if opts.get('line_number'):
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3223 if opts.get('all'):
3223 if opts.get('all'):
3224 cols.append((change, 'grep.change'))
3224 cols.append((change, 'grep.change'))
3225 if opts.get('user'):
3225 if opts.get('user'):
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 if opts.get('date'):
3227 if opts.get('date'):
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 if opts.get('files_with_matches'):
3229 if opts.get('files_with_matches'):
3230 c = (fn, rev)
3230 c = (fn, rev)
3231 if c in filerevmatches:
3231 if c in filerevmatches:
3232 continue
3232 continue
3233 filerevmatches[c] = 1
3233 filerevmatches[c] = 1
3234 else:
3234 else:
3235 before = l.line[:l.colstart]
3235 before = l.line[:l.colstart]
3236 match = l.line[l.colstart:l.colend]
3236 match = l.line[l.colstart:l.colend]
3237 after = l.line[l.colend:]
3237 after = l.line[l.colend:]
3238 for col, label in cols[:-1]:
3238 for col, label in cols[:-1]:
3239 ui.write(col, label=label)
3239 ui.write(col, label=label)
3240 ui.write(sep, label='grep.sep')
3240 ui.write(sep, label='grep.sep')
3241 ui.write(cols[-1][0], label=cols[-1][1])
3241 ui.write(cols[-1][0], label=cols[-1][1])
3242 if before is not None:
3242 if before is not None:
3243 ui.write(sep, label='grep.sep')
3243 ui.write(sep, label='grep.sep')
3244 if not opts.get('text') and binary():
3244 if not opts.get('text') and binary():
3245 ui.write(" Binary file matches")
3245 ui.write(" Binary file matches")
3246 else:
3246 else:
3247 ui.write(before)
3247 ui.write(before)
3248 ui.write(match, label='grep.match')
3248 ui.write(match, label='grep.match')
3249 ui.write(after)
3249 ui.write(after)
3250 ui.write(eol)
3250 ui.write(eol)
3251 found = True
3251 found = True
3252 return found
3252 return found
3253
3253
3254 skip = {}
3254 skip = {}
3255 revfiles = {}
3255 revfiles = {}
3256 matchfn = scmutil.match(repo[None], pats, opts)
3256 matchfn = scmutil.match(repo[None], pats, opts)
3257 found = False
3257 found = False
3258 follow = opts.get('follow')
3258 follow = opts.get('follow')
3259
3259
3260 def prep(ctx, fns):
3260 def prep(ctx, fns):
3261 rev = ctx.rev()
3261 rev = ctx.rev()
3262 pctx = ctx.p1()
3262 pctx = ctx.p1()
3263 parent = pctx.rev()
3263 parent = pctx.rev()
3264 matches.setdefault(rev, {})
3264 matches.setdefault(rev, {})
3265 matches.setdefault(parent, {})
3265 matches.setdefault(parent, {})
3266 files = revfiles.setdefault(rev, [])
3266 files = revfiles.setdefault(rev, [])
3267 for fn in fns:
3267 for fn in fns:
3268 flog = getfile(fn)
3268 flog = getfile(fn)
3269 try:
3269 try:
3270 fnode = ctx.filenode(fn)
3270 fnode = ctx.filenode(fn)
3271 except error.LookupError:
3271 except error.LookupError:
3272 continue
3272 continue
3273
3273
3274 copied = flog.renamed(fnode)
3274 copied = flog.renamed(fnode)
3275 copy = follow and copied and copied[0]
3275 copy = follow and copied and copied[0]
3276 if copy:
3276 if copy:
3277 copies.setdefault(rev, {})[fn] = copy
3277 copies.setdefault(rev, {})[fn] = copy
3278 if fn in skip:
3278 if fn in skip:
3279 if copy:
3279 if copy:
3280 skip[copy] = True
3280 skip[copy] = True
3281 continue
3281 continue
3282 files.append(fn)
3282 files.append(fn)
3283
3283
3284 if fn not in matches[rev]:
3284 if fn not in matches[rev]:
3285 grepbody(fn, rev, flog.read(fnode))
3285 grepbody(fn, rev, flog.read(fnode))
3286
3286
3287 pfn = copy or fn
3287 pfn = copy or fn
3288 if pfn not in matches[parent]:
3288 if pfn not in matches[parent]:
3289 try:
3289 try:
3290 fnode = pctx.filenode(pfn)
3290 fnode = pctx.filenode(pfn)
3291 grepbody(pfn, parent, flog.read(fnode))
3291 grepbody(pfn, parent, flog.read(fnode))
3292 except error.LookupError:
3292 except error.LookupError:
3293 pass
3293 pass
3294
3294
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 rev = ctx.rev()
3296 rev = ctx.rev()
3297 parent = ctx.p1().rev()
3297 parent = ctx.p1().rev()
3298 for fn in sorted(revfiles.get(rev, [])):
3298 for fn in sorted(revfiles.get(rev, [])):
3299 states = matches[rev][fn]
3299 states = matches[rev][fn]
3300 copy = copies.get(rev, {}).get(fn)
3300 copy = copies.get(rev, {}).get(fn)
3301 if fn in skip:
3301 if fn in skip:
3302 if copy:
3302 if copy:
3303 skip[copy] = True
3303 skip[copy] = True
3304 continue
3304 continue
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 if pstates or states:
3306 if pstates or states:
3307 r = display(fn, ctx, pstates, states)
3307 r = display(fn, ctx, pstates, states)
3308 found = found or r
3308 found = found or r
3309 if r and not opts.get('all'):
3309 if r and not opts.get('all'):
3310 skip[fn] = True
3310 skip[fn] = True
3311 if copy:
3311 if copy:
3312 skip[copy] = True
3312 skip[copy] = True
3313 del matches[rev]
3313 del matches[rev]
3314 del revfiles[rev]
3314 del revfiles[rev]
3315
3315
3316 return not found
3316 return not found
3317
3317
3318 @command('heads',
3318 @command('heads',
3319 [('r', 'rev', '',
3319 [('r', 'rev', '',
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 ('t', 'topo', False, _('show topological heads only')),
3321 ('t', 'topo', False, _('show topological heads only')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ] + templateopts,
3324 ] + templateopts,
3325 _('[-ct] [-r STARTREV] [REV]...'))
3325 _('[-ct] [-r STARTREV] [REV]...'))
3326 def heads(ui, repo, *branchrevs, **opts):
3326 def heads(ui, repo, *branchrevs, **opts):
3327 """show branch heads
3327 """show branch heads
3328
3328
3329 With no arguments, show all open branch heads in the repository.
3329 With no arguments, show all open branch heads in the repository.
3330 Branch heads are changesets that have no descendants on the
3330 Branch heads are changesets that have no descendants on the
3331 same branch. They are where development generally takes place and
3331 same branch. They are where development generally takes place and
3332 are the usual targets for update and merge operations.
3332 are the usual targets for update and merge operations.
3333
3333
3334 If one or more REVs are given, only open branch heads on the
3334 If one or more REVs are given, only open branch heads on the
3335 branches associated with the specified changesets are shown. This
3335 branches associated with the specified changesets are shown. This
3336 means that you can use :hg:`heads .` to see the heads on the
3336 means that you can use :hg:`heads .` to see the heads on the
3337 currently checked-out branch.
3337 currently checked-out branch.
3338
3338
3339 If -c/--closed is specified, also show branch heads marked closed
3339 If -c/--closed is specified, also show branch heads marked closed
3340 (see :hg:`commit --close-branch`).
3340 (see :hg:`commit --close-branch`).
3341
3341
3342 If STARTREV is specified, only those heads that are descendants of
3342 If STARTREV is specified, only those heads that are descendants of
3343 STARTREV will be displayed.
3343 STARTREV will be displayed.
3344
3344
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 topological heads (changesets with no children) will be shown.
3346 topological heads (changesets with no children) will be shown.
3347
3347
3348 Returns 0 if matching heads are found, 1 if not.
3348 Returns 0 if matching heads are found, 1 if not.
3349 """
3349 """
3350
3350
3351 start = None
3351 start = None
3352 if 'rev' in opts:
3352 if 'rev' in opts:
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354
3354
3355 if opts.get('topo'):
3355 if opts.get('topo'):
3356 heads = [repo[h] for h in repo.heads(start)]
3356 heads = [repo[h] for h in repo.heads(start)]
3357 else:
3357 else:
3358 heads = []
3358 heads = []
3359 for branch in repo.branchmap():
3359 for branch in repo.branchmap():
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads = [repo[h] for h in heads]
3361 heads = [repo[h] for h in heads]
3362
3362
3363 if branchrevs:
3363 if branchrevs:
3364 branches = set(repo[br].branch() for br in branchrevs)
3364 branches = set(repo[br].branch() for br in branchrevs)
3365 heads = [h for h in heads if h.branch() in branches]
3365 heads = [h for h in heads if h.branch() in branches]
3366
3366
3367 if opts.get('active') and branchrevs:
3367 if opts.get('active') and branchrevs:
3368 dagheads = repo.heads(start)
3368 dagheads = repo.heads(start)
3369 heads = [h for h in heads if h.node() in dagheads]
3369 heads = [h for h in heads if h.node() in dagheads]
3370
3370
3371 if branchrevs:
3371 if branchrevs:
3372 haveheads = set(h.branch() for h in heads)
3372 haveheads = set(h.branch() for h in heads)
3373 if branches - haveheads:
3373 if branches - haveheads:
3374 headless = ', '.join(b for b in branches - haveheads)
3374 headless = ', '.join(b for b in branches - haveheads)
3375 msg = _('no open branch heads found on branches %s')
3375 msg = _('no open branch heads found on branches %s')
3376 if opts.get('rev'):
3376 if opts.get('rev'):
3377 msg += _(' (started at %s)') % opts['rev']
3377 msg += _(' (started at %s)') % opts['rev']
3378 ui.warn((msg + '\n') % headless)
3378 ui.warn((msg + '\n') % headless)
3379
3379
3380 if not heads:
3380 if not heads:
3381 return 1
3381 return 1
3382
3382
3383 heads = sorted(heads, key=lambda x: -x.rev())
3383 heads = sorted(heads, key=lambda x: -x.rev())
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 for ctx in heads:
3385 for ctx in heads:
3386 displayer.show(ctx)
3386 displayer.show(ctx)
3387 displayer.close()
3387 displayer.close()
3388
3388
3389 @command('help',
3389 @command('help',
3390 [('e', 'extension', None, _('show only help for extensions')),
3390 [('e', 'extension', None, _('show only help for extensions')),
3391 ('c', 'command', None, _('show only help for commands')),
3391 ('c', 'command', None, _('show only help for commands')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ],
3393 ],
3394 _('[-ec] [TOPIC]'))
3394 _('[-ec] [TOPIC]'))
3395 def help_(ui, name=None, **opts):
3395 def help_(ui, name=None, **opts):
3396 """show help for a given topic or a help overview
3396 """show help for a given topic or a help overview
3397
3397
3398 With no arguments, print a list of commands with short help messages.
3398 With no arguments, print a list of commands with short help messages.
3399
3399
3400 Given a topic, extension, or command name, print help for that
3400 Given a topic, extension, or command name, print help for that
3401 topic.
3401 topic.
3402
3402
3403 Returns 0 if successful.
3403 Returns 0 if successful.
3404 """
3404 """
3405
3405
3406 textwidth = min(ui.termwidth(), 80) - 2
3406 textwidth = min(ui.termwidth(), 80) - 2
3407
3407
3408 keep = ui.verbose and ['verbose'] or []
3408 keep = ui.verbose and ['verbose'] or []
3409 text = help.help_(ui, name, **opts)
3409 text = help.help_(ui, name, **opts)
3410
3410
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 if 'verbose' in pruned:
3412 if 'verbose' in pruned:
3413 keep.append('omitted')
3413 keep.append('omitted')
3414 else:
3414 else:
3415 keep.append('notomitted')
3415 keep.append('notomitted')
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 ui.write(formatted)
3417 ui.write(formatted)
3418
3418
3419
3419
3420 @command('identify|id',
3420 @command('identify|id',
3421 [('r', 'rev', '',
3421 [('r', 'rev', '',
3422 _('identify the specified revision'), _('REV')),
3422 _('identify the specified revision'), _('REV')),
3423 ('n', 'num', None, _('show local revision number')),
3423 ('n', 'num', None, _('show local revision number')),
3424 ('i', 'id', None, _('show global revision id')),
3424 ('i', 'id', None, _('show global revision id')),
3425 ('b', 'branch', None, _('show branch')),
3425 ('b', 'branch', None, _('show branch')),
3426 ('t', 'tags', None, _('show tags')),
3426 ('t', 'tags', None, _('show tags')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ] + remoteopts,
3428 ] + remoteopts,
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3430 def identify(ui, repo, source=None, rev=None,
3430 def identify(ui, repo, source=None, rev=None,
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 """identify the working copy or specified revision
3432 """identify the working copy or specified revision
3433
3433
3434 Print a summary identifying the repository state at REV using one or
3434 Print a summary identifying the repository state at REV using one or
3435 two parent hash identifiers, followed by a "+" if the working
3435 two parent hash identifiers, followed by a "+" if the working
3436 directory has uncommitted changes, the branch name (if not default),
3436 directory has uncommitted changes, the branch name (if not default),
3437 a list of tags, and a list of bookmarks.
3437 a list of tags, and a list of bookmarks.
3438
3438
3439 When REV is not given, print a summary of the current state of the
3439 When REV is not given, print a summary of the current state of the
3440 repository.
3440 repository.
3441
3441
3442 Specifying a path to a repository root or Mercurial bundle will
3442 Specifying a path to a repository root or Mercurial bundle will
3443 cause lookup to operate on that repository/bundle.
3443 cause lookup to operate on that repository/bundle.
3444
3444
3445 .. container:: verbose
3445 .. container:: verbose
3446
3446
3447 Examples:
3447 Examples:
3448
3448
3449 - generate a build identifier for the working directory::
3449 - generate a build identifier for the working directory::
3450
3450
3451 hg id --id > build-id.dat
3451 hg id --id > build-id.dat
3452
3452
3453 - find the revision corresponding to a tag::
3453 - find the revision corresponding to a tag::
3454
3454
3455 hg id -n -r 1.3
3455 hg id -n -r 1.3
3456
3456
3457 - check the most recent revision of a remote repository::
3457 - check the most recent revision of a remote repository::
3458
3458
3459 hg id -r tip http://selenic.com/hg/
3459 hg id -r tip http://selenic.com/hg/
3460
3460
3461 Returns 0 if successful.
3461 Returns 0 if successful.
3462 """
3462 """
3463
3463
3464 if not repo and not source:
3464 if not repo and not source:
3465 raise util.Abort(_("there is no Mercurial repository here "
3465 raise util.Abort(_("there is no Mercurial repository here "
3466 "(.hg not found)"))
3466 "(.hg not found)"))
3467
3467
3468 hexfunc = ui.debugflag and hex or short
3468 hexfunc = ui.debugflag and hex or short
3469 default = not (num or id or branch or tags or bookmarks)
3469 default = not (num or id or branch or tags or bookmarks)
3470 output = []
3470 output = []
3471 revs = []
3471 revs = []
3472
3472
3473 if source:
3473 if source:
3474 source, branches = hg.parseurl(ui.expandpath(source))
3474 source, branches = hg.parseurl(ui.expandpath(source))
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 repo = peer.local()
3476 repo = peer.local()
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478
3478
3479 if not repo:
3479 if not repo:
3480 if num or branch or tags:
3480 if num or branch or tags:
3481 raise util.Abort(
3481 raise util.Abort(
3482 _("can't query remote revision number, branch, or tags"))
3482 _("can't query remote revision number, branch, or tags"))
3483 if not rev and revs:
3483 if not rev and revs:
3484 rev = revs[0]
3484 rev = revs[0]
3485 if not rev:
3485 if not rev:
3486 rev = "tip"
3486 rev = "tip"
3487
3487
3488 remoterev = peer.lookup(rev)
3488 remoterev = peer.lookup(rev)
3489 if default or id:
3489 if default or id:
3490 output = [hexfunc(remoterev)]
3490 output = [hexfunc(remoterev)]
3491
3491
3492 def getbms():
3492 def getbms():
3493 bms = []
3493 bms = []
3494
3494
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3496 hexremoterev = hex(remoterev)
3496 hexremoterev = hex(remoterev)
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 if bmr == hexremoterev]
3498 if bmr == hexremoterev]
3499
3499
3500 return sorted(bms)
3500 return sorted(bms)
3501
3501
3502 if bookmarks:
3502 if bookmarks:
3503 output.extend(getbms())
3503 output.extend(getbms())
3504 elif default and not ui.quiet:
3504 elif default and not ui.quiet:
3505 # multiple bookmarks for a single parent separated by '/'
3505 # multiple bookmarks for a single parent separated by '/'
3506 bm = '/'.join(getbms())
3506 bm = '/'.join(getbms())
3507 if bm:
3507 if bm:
3508 output.append(bm)
3508 output.append(bm)
3509 else:
3509 else:
3510 if not rev:
3510 if not rev:
3511 ctx = repo[None]
3511 ctx = repo[None]
3512 parents = ctx.parents()
3512 parents = ctx.parents()
3513 changed = ""
3513 changed = ""
3514 if default or id or num:
3514 if default or id or num:
3515 if (util.any(repo.status())
3515 if (util.any(repo.status())
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 changed = '+'
3517 changed = '+'
3518 if default or id:
3518 if default or id:
3519 output = ["%s%s" %
3519 output = ["%s%s" %
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 if num:
3521 if num:
3522 output.append("%s%s" %
3522 output.append("%s%s" %
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 else:
3524 else:
3525 ctx = scmutil.revsingle(repo, rev)
3525 ctx = scmutil.revsingle(repo, rev)
3526 if default or id:
3526 if default or id:
3527 output = [hexfunc(ctx.node())]
3527 output = [hexfunc(ctx.node())]
3528 if num:
3528 if num:
3529 output.append(str(ctx.rev()))
3529 output.append(str(ctx.rev()))
3530
3530
3531 if default and not ui.quiet:
3531 if default and not ui.quiet:
3532 b = ctx.branch()
3532 b = ctx.branch()
3533 if b != 'default':
3533 if b != 'default':
3534 output.append("(%s)" % b)
3534 output.append("(%s)" % b)
3535
3535
3536 # multiple tags for a single parent separated by '/'
3536 # multiple tags for a single parent separated by '/'
3537 t = '/'.join(ctx.tags())
3537 t = '/'.join(ctx.tags())
3538 if t:
3538 if t:
3539 output.append(t)
3539 output.append(t)
3540
3540
3541 # multiple bookmarks for a single parent separated by '/'
3541 # multiple bookmarks for a single parent separated by '/'
3542 bm = '/'.join(ctx.bookmarks())
3542 bm = '/'.join(ctx.bookmarks())
3543 if bm:
3543 if bm:
3544 output.append(bm)
3544 output.append(bm)
3545 else:
3545 else:
3546 if branch:
3546 if branch:
3547 output.append(ctx.branch())
3547 output.append(ctx.branch())
3548
3548
3549 if tags:
3549 if tags:
3550 output.extend(ctx.tags())
3550 output.extend(ctx.tags())
3551
3551
3552 if bookmarks:
3552 if bookmarks:
3553 output.extend(ctx.bookmarks())
3553 output.extend(ctx.bookmarks())
3554
3554
3555 ui.write("%s\n" % ' '.join(output))
3555 ui.write("%s\n" % ' '.join(output))
3556
3556
3557 @command('import|patch',
3557 @command('import|patch',
3558 [('p', 'strip', 1,
3558 [('p', 'strip', 1,
3559 _('directory strip option for patch. This has the same '
3559 _('directory strip option for patch. This has the same '
3560 'meaning as the corresponding patch option'), _('NUM')),
3560 'meaning as the corresponding patch option'), _('NUM')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('f', 'force', None,
3563 ('f', 'force', None,
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 ('', 'no-commit', None,
3565 ('', 'no-commit', None,
3566 _("don't commit, just update the working directory")),
3566 _("don't commit, just update the working directory")),
3567 ('', 'bypass', None,
3567 ('', 'bypass', None,
3568 _("apply patch without touching the working directory")),
3568 _("apply patch without touching the working directory")),
3569 ('', 'exact', None,
3569 ('', 'exact', None,
3570 _('apply patch to the nodes from which it was generated')),
3570 _('apply patch to the nodes from which it was generated')),
3571 ('', 'import-branch', None,
3571 ('', 'import-branch', None,
3572 _('use any branch information in patch (implied by --exact)'))] +
3572 _('use any branch information in patch (implied by --exact)'))] +
3573 commitopts + commitopts2 + similarityopts,
3573 commitopts + commitopts2 + similarityopts,
3574 _('[OPTION]... PATCH...'))
3574 _('[OPTION]... PATCH...'))
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3576 """import an ordered set of patches
3576 """import an ordered set of patches
3577
3577
3578 Import a list of patches and commit them individually (unless
3578 Import a list of patches and commit them individually (unless
3579 --no-commit is specified).
3579 --no-commit is specified).
3580
3580
3581 Because import first applies changes to the working directory,
3581 Because import first applies changes to the working directory,
3582 import will abort if there are outstanding changes.
3582 import will abort if there are outstanding changes.
3583
3583
3584 You can import a patch straight from a mail message. Even patches
3584 You can import a patch straight from a mail message. Even patches
3585 as attachments work (to use the body part, it must have type
3585 as attachments work (to use the body part, it must have type
3586 text/plain or text/x-patch). From and Subject headers of email
3586 text/plain or text/x-patch). From and Subject headers of email
3587 message are used as default committer and commit message. All
3587 message are used as default committer and commit message. All
3588 text/plain body parts before first diff are added to commit
3588 text/plain body parts before first diff are added to commit
3589 message.
3589 message.
3590
3590
3591 If the imported patch was generated by :hg:`export`, user and
3591 If the imported patch was generated by :hg:`export`, user and
3592 description from patch override values from message headers and
3592 description from patch override values from message headers and
3593 body. Values given on command line with -m/--message and -u/--user
3593 body. Values given on command line with -m/--message and -u/--user
3594 override these.
3594 override these.
3595
3595
3596 If --exact is specified, import will set the working directory to
3596 If --exact is specified, import will set the working directory to
3597 the parent of each patch before applying it, and will abort if the
3597 the parent of each patch before applying it, and will abort if the
3598 resulting changeset has a different ID than the one recorded in
3598 resulting changeset has a different ID than the one recorded in
3599 the patch. This may happen due to character set problems or other
3599 the patch. This may happen due to character set problems or other
3600 deficiencies in the text patch format.
3600 deficiencies in the text patch format.
3601
3601
3602 Use --bypass to apply and commit patches directly to the
3602 Use --bypass to apply and commit patches directly to the
3603 repository, not touching the working directory. Without --exact,
3603 repository, not touching the working directory. Without --exact,
3604 patches will be applied on top of the working directory parent
3604 patches will be applied on top of the working directory parent
3605 revision.
3605 revision.
3606
3606
3607 With -s/--similarity, hg will attempt to discover renames and
3607 With -s/--similarity, hg will attempt to discover renames and
3608 copies in the patch in the same way as :hg:`addremove`.
3608 copies in the patch in the same way as :hg:`addremove`.
3609
3609
3610 To read a patch from standard input, use "-" as the patch name. If
3610 To read a patch from standard input, use "-" as the patch name. If
3611 a URL is specified, the patch will be downloaded from it.
3611 a URL is specified, the patch will be downloaded from it.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3613
3613
3614 .. container:: verbose
3614 .. container:: verbose
3615
3615
3616 Examples:
3616 Examples:
3617
3617
3618 - import a traditional patch from a website and detect renames::
3618 - import a traditional patch from a website and detect renames::
3619
3619
3620 hg import -s 80 http://example.com/bugfix.patch
3620 hg import -s 80 http://example.com/bugfix.patch
3621
3621
3622 - import a changeset from an hgweb server::
3622 - import a changeset from an hgweb server::
3623
3623
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625
3625
3626 - import all the patches in an Unix-style mbox::
3626 - import all the patches in an Unix-style mbox::
3627
3627
3628 hg import incoming-patches.mbox
3628 hg import incoming-patches.mbox
3629
3629
3630 - attempt to exactly restore an exported changeset (not always
3630 - attempt to exactly restore an exported changeset (not always
3631 possible)::
3631 possible)::
3632
3632
3633 hg import --exact proposed-fix.patch
3633 hg import --exact proposed-fix.patch
3634
3634
3635 Returns 0 on success.
3635 Returns 0 on success.
3636 """
3636 """
3637
3637
3638 if not patch1:
3638 if not patch1:
3639 raise util.Abort(_('need at least one patch to import'))
3639 raise util.Abort(_('need at least one patch to import'))
3640
3640
3641 patches = (patch1,) + patches
3641 patches = (patch1,) + patches
3642
3642
3643 date = opts.get('date')
3643 date = opts.get('date')
3644 if date:
3644 if date:
3645 opts['date'] = util.parsedate(date)
3645 opts['date'] = util.parsedate(date)
3646
3646
3647 editor = cmdutil.commiteditor
3647 editor = cmdutil.commiteditor
3648 if opts.get('edit'):
3648 if opts.get('edit'):
3649 editor = cmdutil.commitforceeditor
3649 editor = cmdutil.commitforceeditor
3650
3650
3651 update = not opts.get('bypass')
3651 update = not opts.get('bypass')
3652 if not update and opts.get('no_commit'):
3652 if not update and opts.get('no_commit'):
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 try:
3654 try:
3655 sim = float(opts.get('similarity') or 0)
3655 sim = float(opts.get('similarity') or 0)
3656 except ValueError:
3656 except ValueError:
3657 raise util.Abort(_('similarity must be a number'))
3657 raise util.Abort(_('similarity must be a number'))
3658 if sim < 0 or sim > 100:
3658 if sim < 0 or sim > 100:
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3660 if sim and not update:
3660 if sim and not update:
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3662
3662
3663 if update:
3663 if update:
3664 cmdutil.checkunfinished(repo)
3664 cmdutil.checkunfinished(repo)
3665 if (opts.get('exact') or not opts.get('force')) and update:
3665 if (opts.get('exact') or not opts.get('force')) and update:
3666 cmdutil.bailifchanged(repo)
3666 cmdutil.bailifchanged(repo)
3667
3667
3668 base = opts["base"]
3668 base = opts["base"]
3669 strip = opts["strip"]
3669 strip = opts["strip"]
3670 wlock = lock = tr = None
3670 wlock = lock = tr = None
3671 msgs = []
3671 msgs = []
3672
3672
3673 def tryone(ui, hunk, parents):
3673 def tryone(ui, hunk, parents):
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 patch.extract(ui, hunk)
3675 patch.extract(ui, hunk)
3676
3676
3677 if not tmpname:
3677 if not tmpname:
3678 return (None, None)
3678 return (None, None)
3679 msg = _('applied to working directory')
3679 msg = _('applied to working directory')
3680
3680
3681 try:
3681 try:
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3683 if cmdline_message:
3683 if cmdline_message:
3684 # pickup the cmdline msg
3684 # pickup the cmdline msg
3685 message = cmdline_message
3685 message = cmdline_message
3686 elif message:
3686 elif message:
3687 # pickup the patch msg
3687 # pickup the patch msg
3688 message = message.strip()
3688 message = message.strip()
3689 else:
3689 else:
3690 # launch the editor
3690 # launch the editor
3691 message = None
3691 message = None
3692 ui.debug('message:\n%s\n' % message)
3692 ui.debug('message:\n%s\n' % message)
3693
3693
3694 if len(parents) == 1:
3694 if len(parents) == 1:
3695 parents.append(repo[nullid])
3695 parents.append(repo[nullid])
3696 if opts.get('exact'):
3696 if opts.get('exact'):
3697 if not nodeid or not p1:
3697 if not nodeid or not p1:
3698 raise util.Abort(_('not a Mercurial patch'))
3698 raise util.Abort(_('not a Mercurial patch'))
3699 p1 = repo[p1]
3699 p1 = repo[p1]
3700 p2 = repo[p2 or nullid]
3700 p2 = repo[p2 or nullid]
3701 elif p2:
3701 elif p2:
3702 try:
3702 try:
3703 p1 = repo[p1]
3703 p1 = repo[p1]
3704 p2 = repo[p2]
3704 p2 = repo[p2]
3705 # Without any options, consider p2 only if the
3705 # Without any options, consider p2 only if the
3706 # patch is being applied on top of the recorded
3706 # patch is being applied on top of the recorded
3707 # first parent.
3707 # first parent.
3708 if p1 != parents[0]:
3708 if p1 != parents[0]:
3709 p1 = parents[0]
3709 p1 = parents[0]
3710 p2 = repo[nullid]
3710 p2 = repo[nullid]
3711 except error.RepoError:
3711 except error.RepoError:
3712 p1, p2 = parents
3712 p1, p2 = parents
3713 else:
3713 else:
3714 p1, p2 = parents
3714 p1, p2 = parents
3715
3715
3716 n = None
3716 n = None
3717 if update:
3717 if update:
3718 if p1 != parents[0]:
3718 if p1 != parents[0]:
3719 hg.clean(repo, p1.node())
3719 hg.clean(repo, p1.node())
3720 if p2 != parents[1]:
3720 if p2 != parents[1]:
3721 repo.setparents(p1.node(), p2.node())
3721 repo.setparents(p1.node(), p2.node())
3722
3722
3723 if opts.get('exact') or opts.get('import_branch'):
3723 if opts.get('exact') or opts.get('import_branch'):
3724 repo.dirstate.setbranch(branch or 'default')
3724 repo.dirstate.setbranch(branch or 'default')
3725
3725
3726 files = set()
3726 files = set()
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 eolmode=None, similarity=sim / 100.0)
3728 eolmode=None, similarity=sim / 100.0)
3729 files = list(files)
3729 files = list(files)
3730 if opts.get('no_commit'):
3730 if opts.get('no_commit'):
3731 if message:
3731 if message:
3732 msgs.append(message)
3732 msgs.append(message)
3733 else:
3733 else:
3734 if opts.get('exact') or p2:
3734 if opts.get('exact') or p2:
3735 # If you got here, you either use --force and know what
3735 # If you got here, you either use --force and know what
3736 # you are doing or used --exact or a merge patch while
3736 # you are doing or used --exact or a merge patch while
3737 # being updated to its first parent.
3737 # being updated to its first parent.
3738 m = None
3738 m = None
3739 else:
3739 else:
3740 m = scmutil.matchfiles(repo, files or [])
3740 m = scmutil.matchfiles(repo, files or [])
3741 n = repo.commit(message, opts.get('user') or user,
3741 n = repo.commit(message, opts.get('user') or user,
3742 opts.get('date') or date, match=m,
3742 opts.get('date') or date, match=m,
3743 editor=editor)
3743 editor=editor)
3744 else:
3744 else:
3745 if opts.get('exact') or opts.get('import_branch'):
3745 if opts.get('exact') or opts.get('import_branch'):
3746 branch = branch or 'default'
3746 branch = branch or 'default'
3747 else:
3747 else:
3748 branch = p1.branch()
3748 branch = p1.branch()
3749 store = patch.filestore()
3749 store = patch.filestore()
3750 try:
3750 try:
3751 files = set()
3751 files = set()
3752 try:
3752 try:
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 files, eolmode=None)
3754 files, eolmode=None)
3755 except patch.PatchError, e:
3755 except patch.PatchError, e:
3756 raise util.Abort(str(e))
3756 raise util.Abort(str(e))
3757 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3757 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3758 message,
3758 message,
3759 opts.get('user') or user,
3759 opts.get('user') or user,
3760 opts.get('date') or date,
3760 opts.get('date') or date,
3761 branch, files, store,
3761 branch, files, store,
3762 editor=cmdutil.commiteditor)
3762 editor=cmdutil.commiteditor)
3763 repo.savecommitmessage(memctx.description())
3763 repo.savecommitmessage(memctx.description())
3764 n = memctx.commit()
3764 n = memctx.commit()
3765 finally:
3765 finally:
3766 store.close()
3766 store.close()
3767 if opts.get('exact') and hex(n) != nodeid:
3767 if opts.get('exact') and hex(n) != nodeid:
3768 raise util.Abort(_('patch is damaged or loses information'))
3768 raise util.Abort(_('patch is damaged or loses information'))
3769 if n:
3769 if n:
3770 # i18n: refers to a short changeset id
3770 # i18n: refers to a short changeset id
3771 msg = _('created %s') % short(n)
3771 msg = _('created %s') % short(n)
3772 return (msg, n)
3772 return (msg, n)
3773 finally:
3773 finally:
3774 os.unlink(tmpname)
3774 os.unlink(tmpname)
3775
3775
3776 try:
3776 try:
3777 try:
3777 try:
3778 wlock = repo.wlock()
3778 wlock = repo.wlock()
3779 if not opts.get('no_commit'):
3779 if not opts.get('no_commit'):
3780 lock = repo.lock()
3780 lock = repo.lock()
3781 tr = repo.transaction('import')
3781 tr = repo.transaction('import')
3782 parents = repo.parents()
3782 parents = repo.parents()
3783 for patchurl in patches:
3783 for patchurl in patches:
3784 if patchurl == '-':
3784 if patchurl == '-':
3785 ui.status(_('applying patch from stdin\n'))
3785 ui.status(_('applying patch from stdin\n'))
3786 patchfile = ui.fin
3786 patchfile = ui.fin
3787 patchurl = 'stdin' # for error message
3787 patchurl = 'stdin' # for error message
3788 else:
3788 else:
3789 patchurl = os.path.join(base, patchurl)
3789 patchurl = os.path.join(base, patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3792
3792
3793 haspatch = False
3793 haspatch = False
3794 for hunk in patch.split(patchfile):
3794 for hunk in patch.split(patchfile):
3795 (msg, node) = tryone(ui, hunk, parents)
3795 (msg, node) = tryone(ui, hunk, parents)
3796 if msg:
3796 if msg:
3797 haspatch = True
3797 haspatch = True
3798 ui.note(msg + '\n')
3798 ui.note(msg + '\n')
3799 if update or opts.get('exact'):
3799 if update or opts.get('exact'):
3800 parents = repo.parents()
3800 parents = repo.parents()
3801 else:
3801 else:
3802 parents = [repo[node]]
3802 parents = [repo[node]]
3803
3803
3804 if not haspatch:
3804 if not haspatch:
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3806
3806
3807 if tr:
3807 if tr:
3808 tr.close()
3808 tr.close()
3809 if msgs:
3809 if msgs:
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 except: # re-raises
3811 except: # re-raises
3812 # wlock.release() indirectly calls dirstate.write(): since
3812 # wlock.release() indirectly calls dirstate.write(): since
3813 # we're crashing, we do not want to change the working dir
3813 # we're crashing, we do not want to change the working dir
3814 # parent after all, so make sure it writes nothing
3814 # parent after all, so make sure it writes nothing
3815 repo.dirstate.invalidate()
3815 repo.dirstate.invalidate()
3816 raise
3816 raise
3817 finally:
3817 finally:
3818 if tr:
3818 if tr:
3819 tr.release()
3819 tr.release()
3820 release(lock, wlock)
3820 release(lock, wlock)
3821
3821
3822 @command('incoming|in',
3822 @command('incoming|in',
3823 [('f', 'force', None,
3823 [('f', 'force', None,
3824 _('run even if remote repository is unrelated')),
3824 _('run even if remote repository is unrelated')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3826 ('', 'bundle', '',
3826 ('', 'bundle', '',
3827 _('file to store the bundles into'), _('FILE')),
3827 _('file to store the bundles into'), _('FILE')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('b', 'branch', [],
3830 ('b', 'branch', [],
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3832 ] + logopts + remoteopts + subrepoopts,
3832 ] + logopts + remoteopts + subrepoopts,
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 def incoming(ui, repo, source="default", **opts):
3834 def incoming(ui, repo, source="default", **opts):
3835 """show new changesets found in source
3835 """show new changesets found in source
3836
3836
3837 Show new changesets found in the specified path/URL or the default
3837 Show new changesets found in the specified path/URL or the default
3838 pull location. These are the changesets that would have been pulled
3838 pull location. These are the changesets that would have been pulled
3839 if a pull at the time you issued this command.
3839 if a pull at the time you issued this command.
3840
3840
3841 For remote repository, using --bundle avoids downloading the
3841 For remote repository, using --bundle avoids downloading the
3842 changesets twice if the incoming is followed by a pull.
3842 changesets twice if the incoming is followed by a pull.
3843
3843
3844 See pull for valid source format details.
3844 See pull for valid source format details.
3845
3845
3846 Returns 0 if there are incoming changes, 1 otherwise.
3846 Returns 0 if there are incoming changes, 1 otherwise.
3847 """
3847 """
3848 if opts.get('graph'):
3848 if opts.get('graph'):
3849 cmdutil.checkunsupportedgraphflags([], opts)
3849 cmdutil.checkunsupportedgraphflags([], opts)
3850 def display(other, chlist, displayer):
3850 def display(other, chlist, displayer):
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 graphmod.asciiedges)
3854 graphmod.asciiedges)
3855
3855
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 return 0
3857 return 0
3858
3858
3859 if opts.get('bundle') and opts.get('subrepos'):
3859 if opts.get('bundle') and opts.get('subrepos'):
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861
3861
3862 if opts.get('bookmarks'):
3862 if opts.get('bookmarks'):
3863 source, branches = hg.parseurl(ui.expandpath(source),
3863 source, branches = hg.parseurl(ui.expandpath(source),
3864 opts.get('branch'))
3864 opts.get('branch'))
3865 other = hg.peer(repo, opts, source)
3865 other = hg.peer(repo, opts, source)
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3868 return 0
3868 return 0
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 return bookmarks.diff(ui, repo, other)
3870 return bookmarks.diff(ui, repo, other)
3871
3871
3872 repo._subtoppath = ui.expandpath(source)
3872 repo._subtoppath = ui.expandpath(source)
3873 try:
3873 try:
3874 return hg.incoming(ui, repo, source, opts)
3874 return hg.incoming(ui, repo, source, opts)
3875 finally:
3875 finally:
3876 del repo._subtoppath
3876 del repo._subtoppath
3877
3877
3878
3878
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 def init(ui, dest=".", **opts):
3880 def init(ui, dest=".", **opts):
3881 """create a new repository in the given directory
3881 """create a new repository in the given directory
3882
3882
3883 Initialize a new repository in the given directory. If the given
3883 Initialize a new repository in the given directory. If the given
3884 directory does not exist, it will be created.
3884 directory does not exist, it will be created.
3885
3885
3886 If no directory is given, the current directory is used.
3886 If no directory is given, the current directory is used.
3887
3887
3888 It is possible to specify an ``ssh://`` URL as the destination.
3888 It is possible to specify an ``ssh://`` URL as the destination.
3889 See :hg:`help urls` for more information.
3889 See :hg:`help urls` for more information.
3890
3890
3891 Returns 0 on success.
3891 Returns 0 on success.
3892 """
3892 """
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894
3894
3895 @command('locate',
3895 @command('locate',
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ] + walkopts,
3899 ] + walkopts,
3900 _('[OPTION]... [PATTERN]...'))
3900 _('[OPTION]... [PATTERN]...'))
3901 def locate(ui, repo, *pats, **opts):
3901 def locate(ui, repo, *pats, **opts):
3902 """locate files matching specific patterns
3902 """locate files matching specific patterns
3903
3903
3904 Print files under Mercurial control in the working directory whose
3904 Print files under Mercurial control in the working directory whose
3905 names match the given patterns.
3905 names match the given patterns.
3906
3906
3907 By default, this command searches all directories in the working
3907 By default, this command searches all directories in the working
3908 directory. To search just the current directory and its
3908 directory. To search just the current directory and its
3909 subdirectories, use "--include .".
3909 subdirectories, use "--include .".
3910
3910
3911 If no patterns are given to match, this command prints the names
3911 If no patterns are given to match, this command prints the names
3912 of all files under Mercurial control in the working directory.
3912 of all files under Mercurial control in the working directory.
3913
3913
3914 If you want to feed the output of this command into the "xargs"
3914 If you want to feed the output of this command into the "xargs"
3915 command, use the -0 option to both this command and "xargs". This
3915 command, use the -0 option to both this command and "xargs". This
3916 will avoid the problem of "xargs" treating single filenames that
3916 will avoid the problem of "xargs" treating single filenames that
3917 contain whitespace as multiple filenames.
3917 contain whitespace as multiple filenames.
3918
3918
3919 Returns 0 if a match is found, 1 otherwise.
3919 Returns 0 if a match is found, 1 otherwise.
3920 """
3920 """
3921 end = opts.get('print0') and '\0' or '\n'
3921 end = opts.get('print0') and '\0' or '\n'
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923
3923
3924 ret = 1
3924 ret = 1
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m.bad = lambda x, y: False
3926 m.bad = lambda x, y: False
3927 for abs in repo[rev].walk(m):
3927 for abs in repo[rev].walk(m):
3928 if not rev and abs not in repo.dirstate:
3928 if not rev and abs not in repo.dirstate:
3929 continue
3929 continue
3930 if opts.get('fullpath'):
3930 if opts.get('fullpath'):
3931 ui.write(repo.wjoin(abs), end)
3931 ui.write(repo.wjoin(abs), end)
3932 else:
3932 else:
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ret = 0
3934 ret = 0
3935
3935
3936 return ret
3936 return ret
3937
3937
3938 @command('^log|history',
3938 @command('^log|history',
3939 [('f', 'follow', None,
3939 [('f', 'follow', None,
3940 _('follow changeset history, or file history across copies and renames')),
3940 _('follow changeset history, or file history across copies and renames')),
3941 ('', 'follow-first', None,
3941 ('', 'follow-first', None,
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('C', 'copies', None, _('show copied files')),
3944 ('C', 'copies', None, _('show copied files')),
3945 ('k', 'keyword', [],
3945 ('k', 'keyword', [],
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('', 'only-branch', [],
3951 ('', 'only-branch', [],
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('BRANCH')),
3953 _('BRANCH')),
3954 ('b', 'branch', [],
3954 ('b', 'branch', [],
3955 _('show changesets within the given named branch'), _('BRANCH')),
3955 _('show changesets within the given named branch'), _('BRANCH')),
3956 ('P', 'prune', [],
3956 ('P', 'prune', [],
3957 _('do not display revision or any of its ancestors'), _('REV')),
3957 _('do not display revision or any of its ancestors'), _('REV')),
3958 ] + logopts + walkopts,
3958 ] + logopts + walkopts,
3959 _('[OPTION]... [FILE]'))
3959 _('[OPTION]... [FILE]'))
3960 def log(ui, repo, *pats, **opts):
3960 def log(ui, repo, *pats, **opts):
3961 """show revision history of entire repository or files
3961 """show revision history of entire repository or files
3962
3962
3963 Print the revision history of the specified files or the entire
3963 Print the revision history of the specified files or the entire
3964 project.
3964 project.
3965
3965
3966 If no revision range is specified, the default is ``tip:0`` unless
3966 If no revision range is specified, the default is ``tip:0`` unless
3967 --follow is set, in which case the working directory parent is
3967 --follow is set, in which case the working directory parent is
3968 used as the starting revision.
3968 used as the starting revision.
3969
3969
3970 File history is shown without following rename or copy history of
3970 File history is shown without following rename or copy history of
3971 files. Use -f/--follow with a filename to follow history across
3971 files. Use -f/--follow with a filename to follow history across
3972 renames and copies. --follow without a filename will only show
3972 renames and copies. --follow without a filename will only show
3973 ancestors or descendants of the starting revision.
3973 ancestors or descendants of the starting revision.
3974
3974
3975 By default this command prints revision number and changeset id,
3975 By default this command prints revision number and changeset id,
3976 tags, non-trivial parents, user, date and time, and a summary for
3976 tags, non-trivial parents, user, date and time, and a summary for
3977 each commit. When the -v/--verbose switch is used, the list of
3977 each commit. When the -v/--verbose switch is used, the list of
3978 changed files and full commit message are shown.
3978 changed files and full commit message are shown.
3979
3979
3980 .. note::
3980 .. note::
3981 log -p/--patch may generate unexpected diff output for merge
3981 log -p/--patch may generate unexpected diff output for merge
3982 changesets, as it will only compare the merge changeset against
3982 changesets, as it will only compare the merge changeset against
3983 its first parent. Also, only files different from BOTH parents
3983 its first parent. Also, only files different from BOTH parents
3984 will appear in files:.
3984 will appear in files:.
3985
3985
3986 .. note::
3986 .. note::
3987 for performance reasons, log FILE may omit duplicate changes
3987 for performance reasons, log FILE may omit duplicate changes
3988 made on branches and will not show deletions. To see all
3988 made on branches and will not show deletions. To see all
3989 changes including duplicates and deletions, use the --removed
3989 changes including duplicates and deletions, use the --removed
3990 switch.
3990 switch.
3991
3991
3992 .. container:: verbose
3992 .. container:: verbose
3993
3993
3994 Some examples:
3994 Some examples:
3995
3995
3996 - changesets with full descriptions and file lists::
3996 - changesets with full descriptions and file lists::
3997
3997
3998 hg log -v
3998 hg log -v
3999
3999
4000 - changesets ancestral to the working directory::
4000 - changesets ancestral to the working directory::
4001
4001
4002 hg log -f
4002 hg log -f
4003
4003
4004 - last 10 commits on the current branch::
4004 - last 10 commits on the current branch::
4005
4005
4006 hg log -l 10 -b .
4006 hg log -l 10 -b .
4007
4007
4008 - changesets showing all modifications of a file, including removals::
4008 - changesets showing all modifications of a file, including removals::
4009
4009
4010 hg log --removed file.c
4010 hg log --removed file.c
4011
4011
4012 - all changesets that touch a directory, with diffs, excluding merges::
4012 - all changesets that touch a directory, with diffs, excluding merges::
4013
4013
4014 hg log -Mp lib/
4014 hg log -Mp lib/
4015
4015
4016 - all revision numbers that match a keyword::
4016 - all revision numbers that match a keyword::
4017
4017
4018 hg log -k bug --template "{rev}\\n"
4018 hg log -k bug --template "{rev}\\n"
4019
4019
4020 - check if a given changeset is included is a tagged release::
4020 - check if a given changeset is included is a tagged release::
4021
4021
4022 hg log -r "a21ccf and ancestor(1.9)"
4022 hg log -r "a21ccf and ancestor(1.9)"
4023
4023
4024 - find all changesets by some user in a date range::
4024 - find all changesets by some user in a date range::
4025
4025
4026 hg log -k alice -d "may 2008 to jul 2008"
4026 hg log -k alice -d "may 2008 to jul 2008"
4027
4027
4028 - summary of all changesets after the last tag::
4028 - summary of all changesets after the last tag::
4029
4029
4030 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4030 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4031
4031
4032 See :hg:`help dates` for a list of formats valid for -d/--date.
4032 See :hg:`help dates` for a list of formats valid for -d/--date.
4033
4033
4034 See :hg:`help revisions` and :hg:`help revsets` for more about
4034 See :hg:`help revisions` and :hg:`help revsets` for more about
4035 specifying revisions.
4035 specifying revisions.
4036
4036
4037 See :hg:`help templates` for more about pre-packaged styles and
4037 See :hg:`help templates` for more about pre-packaged styles and
4038 specifying custom templates.
4038 specifying custom templates.
4039
4039
4040 Returns 0 on success.
4040 Returns 0 on success.
4041 """
4041 """
4042 if opts.get('graph'):
4042 if opts.get('graph'):
4043 return cmdutil.graphlog(ui, repo, *pats, **opts)
4043 return cmdutil.graphlog(ui, repo, *pats, **opts)
4044
4044
4045 matchfn = scmutil.match(repo[None], pats, opts)
4045 matchfn = scmutil.match(repo[None], pats, opts)
4046 limit = cmdutil.loglimit(opts)
4046 limit = cmdutil.loglimit(opts)
4047 count = 0
4047 count = 0
4048
4048
4049 getrenamed, endrev = None, None
4049 getrenamed, endrev = None, None
4050 if opts.get('copies'):
4050 if opts.get('copies'):
4051 if opts.get('rev'):
4051 if opts.get('rev'):
4052 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4052 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4053 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4053 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4054
4054
4055 df = False
4055 df = False
4056 if opts.get("date"):
4056 if opts.get("date"):
4057 df = util.matchdate(opts["date"])
4057 df = util.matchdate(opts["date"])
4058
4058
4059 branches = opts.get('branch', []) + opts.get('only_branch', [])
4059 branches = opts.get('branch', []) + opts.get('only_branch', [])
4060 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4060 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4061
4061
4062 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4062 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4063 def prep(ctx, fns):
4063 def prep(ctx, fns):
4064 rev = ctx.rev()
4064 rev = ctx.rev()
4065 parents = [p for p in repo.changelog.parentrevs(rev)
4065 parents = [p for p in repo.changelog.parentrevs(rev)
4066 if p != nullrev]
4066 if p != nullrev]
4067 if opts.get('no_merges') and len(parents) == 2:
4067 if opts.get('no_merges') and len(parents) == 2:
4068 return
4068 return
4069 if opts.get('only_merges') and len(parents) != 2:
4069 if opts.get('only_merges') and len(parents) != 2:
4070 return
4070 return
4071 if opts.get('branch') and ctx.branch() not in opts['branch']:
4071 if opts.get('branch') and ctx.branch() not in opts['branch']:
4072 return
4072 return
4073 if df and not df(ctx.date()[0]):
4073 if df and not df(ctx.date()[0]):
4074 return
4074 return
4075
4075
4076 lower = encoding.lower
4076 lower = encoding.lower
4077 if opts.get('user'):
4077 if opts.get('user'):
4078 luser = lower(ctx.user())
4078 luser = lower(ctx.user())
4079 for k in [lower(x) for x in opts['user']]:
4079 for k in [lower(x) for x in opts['user']]:
4080 if (k in luser):
4080 if (k in luser):
4081 break
4081 break
4082 else:
4082 else:
4083 return
4083 return
4084 if opts.get('keyword'):
4084 if opts.get('keyword'):
4085 luser = lower(ctx.user())
4085 luser = lower(ctx.user())
4086 ldesc = lower(ctx.description())
4086 ldesc = lower(ctx.description())
4087 lfiles = lower(" ".join(ctx.files()))
4087 lfiles = lower(" ".join(ctx.files()))
4088 for k in [lower(x) for x in opts['keyword']]:
4088 for k in [lower(x) for x in opts['keyword']]:
4089 if (k in luser or k in ldesc or k in lfiles):
4089 if (k in luser or k in ldesc or k in lfiles):
4090 break
4090 break
4091 else:
4091 else:
4092 return
4092 return
4093
4093
4094 copies = None
4094 copies = None
4095 if getrenamed is not None and rev:
4095 if getrenamed is not None and rev:
4096 copies = []
4096 copies = []
4097 for fn in ctx.files():
4097 for fn in ctx.files():
4098 rename = getrenamed(fn, rev)
4098 rename = getrenamed(fn, rev)
4099 if rename:
4099 if rename:
4100 copies.append((fn, rename[0]))
4100 copies.append((fn, rename[0]))
4101
4101
4102 revmatchfn = None
4102 revmatchfn = None
4103 if opts.get('patch') or opts.get('stat'):
4103 if opts.get('patch') or opts.get('stat'):
4104 if opts.get('follow') or opts.get('follow_first'):
4104 if opts.get('follow') or opts.get('follow_first'):
4105 # note: this might be wrong when following through merges
4105 # note: this might be wrong when following through merges
4106 revmatchfn = scmutil.match(repo[None], fns, default='path')
4106 revmatchfn = scmutil.match(repo[None], fns, default='path')
4107 else:
4107 else:
4108 revmatchfn = matchfn
4108 revmatchfn = matchfn
4109
4109
4110 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4110 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4111
4111
4112 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4112 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4113 if displayer.flush(ctx.rev()):
4113 if displayer.flush(ctx.rev()):
4114 count += 1
4114 count += 1
4115 if count == limit:
4115 if count == limit:
4116 break
4116 break
4117 displayer.close()
4117 displayer.close()
4118
4118
4119 @command('manifest',
4119 @command('manifest',
4120 [('r', 'rev', '', _('revision to display'), _('REV')),
4120 [('r', 'rev', '', _('revision to display'), _('REV')),
4121 ('', 'all', False, _("list files from all revisions"))],
4121 ('', 'all', False, _("list files from all revisions"))],
4122 _('[-r REV]'))
4122 _('[-r REV]'))
4123 def manifest(ui, repo, node=None, rev=None, **opts):
4123 def manifest(ui, repo, node=None, rev=None, **opts):
4124 """output the current or given revision of the project manifest
4124 """output the current or given revision of the project manifest
4125
4125
4126 Print a list of version controlled files for the given revision.
4126 Print a list of version controlled files for the given revision.
4127 If no revision is given, the first parent of the working directory
4127 If no revision is given, the first parent of the working directory
4128 is used, or the null revision if no revision is checked out.
4128 is used, or the null revision if no revision is checked out.
4129
4129
4130 With -v, print file permissions, symlink and executable bits.
4130 With -v, print file permissions, symlink and executable bits.
4131 With --debug, print file revision hashes.
4131 With --debug, print file revision hashes.
4132
4132
4133 If option --all is specified, the list of all files from all revisions
4133 If option --all is specified, the list of all files from all revisions
4134 is printed. This includes deleted and renamed files.
4134 is printed. This includes deleted and renamed files.
4135
4135
4136 Returns 0 on success.
4136 Returns 0 on success.
4137 """
4137 """
4138
4138
4139 fm = ui.formatter('manifest', opts)
4139 fm = ui.formatter('manifest', opts)
4140
4140
4141 if opts.get('all'):
4141 if opts.get('all'):
4142 if rev or node:
4142 if rev or node:
4143 raise util.Abort(_("can't specify a revision with --all"))
4143 raise util.Abort(_("can't specify a revision with --all"))
4144
4144
4145 res = []
4145 res = []
4146 prefix = "data/"
4146 prefix = "data/"
4147 suffix = ".i"
4147 suffix = ".i"
4148 plen = len(prefix)
4148 plen = len(prefix)
4149 slen = len(suffix)
4149 slen = len(suffix)
4150 lock = repo.lock()
4150 lock = repo.lock()
4151 try:
4151 try:
4152 for fn, b, size in repo.store.datafiles():
4152 for fn, b, size in repo.store.datafiles():
4153 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4153 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4154 res.append(fn[plen:-slen])
4154 res.append(fn[plen:-slen])
4155 finally:
4155 finally:
4156 lock.release()
4156 lock.release()
4157 for f in res:
4157 for f in res:
4158 fm.startitem()
4158 fm.startitem()
4159 fm.write("path", '%s\n', f)
4159 fm.write("path", '%s\n', f)
4160 fm.end()
4160 fm.end()
4161 return
4161 return
4162
4162
4163 if rev and node:
4163 if rev and node:
4164 raise util.Abort(_("please specify just one revision"))
4164 raise util.Abort(_("please specify just one revision"))
4165
4165
4166 if not node:
4166 if not node:
4167 node = rev
4167 node = rev
4168
4168
4169 char = {'l': '@', 'x': '*', '': ''}
4169 char = {'l': '@', 'x': '*', '': ''}
4170 mode = {'l': '644', 'x': '755', '': '644'}
4170 mode = {'l': '644', 'x': '755', '': '644'}
4171 ctx = scmutil.revsingle(repo, node)
4171 ctx = scmutil.revsingle(repo, node)
4172 mf = ctx.manifest()
4172 mf = ctx.manifest()
4173 for f in ctx:
4173 for f in ctx:
4174 fm.startitem()
4174 fm.startitem()
4175 fl = ctx[f].flags()
4175 fl = ctx[f].flags()
4176 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4176 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4177 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4177 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4178 fm.write('path', '%s\n', f)
4178 fm.write('path', '%s\n', f)
4179 fm.end()
4179 fm.end()
4180
4180
4181 @command('^merge',
4181 @command('^merge',
4182 [('f', 'force', None,
4182 [('f', 'force', None,
4183 _('force a merge including outstanding changes (DEPRECATED)')),
4183 _('force a merge including outstanding changes (DEPRECATED)')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4184 ('r', 'rev', '', _('revision to merge'), _('REV')),
4185 ('P', 'preview', None,
4185 ('P', 'preview', None,
4186 _('review revisions to merge (no merge is performed)'))
4186 _('review revisions to merge (no merge is performed)'))
4187 ] + mergetoolopts,
4187 ] + mergetoolopts,
4188 _('[-P] [-f] [[-r] REV]'))
4188 _('[-P] [-f] [[-r] REV]'))
4189 def merge(ui, repo, node=None, **opts):
4189 def merge(ui, repo, node=None, **opts):
4190 """merge working directory with another revision
4190 """merge working directory with another revision
4191
4191
4192 The current working directory is updated with all changes made in
4192 The current working directory is updated with all changes made in
4193 the requested revision since the last common predecessor revision.
4193 the requested revision since the last common predecessor revision.
4194
4194
4195 Files that changed between either parent are marked as changed for
4195 Files that changed between either parent are marked as changed for
4196 the next commit and a commit must be performed before any further
4196 the next commit and a commit must be performed before any further
4197 updates to the repository are allowed. The next commit will have
4197 updates to the repository are allowed. The next commit will have
4198 two parents.
4198 two parents.
4199
4199
4200 ``--tool`` can be used to specify the merge tool used for file
4200 ``--tool`` can be used to specify the merge tool used for file
4201 merges. It overrides the HGMERGE environment variable and your
4201 merges. It overrides the HGMERGE environment variable and your
4202 configuration files. See :hg:`help merge-tools` for options.
4202 configuration files. See :hg:`help merge-tools` for options.
4203
4203
4204 If no revision is specified, the working directory's parent is a
4204 If no revision is specified, the working directory's parent is a
4205 head revision, and the current branch contains exactly one other
4205 head revision, and the current branch contains exactly one other
4206 head, the other head is merged with by default. Otherwise, an
4206 head, the other head is merged with by default. Otherwise, an
4207 explicit revision with which to merge with must be provided.
4207 explicit revision with which to merge with must be provided.
4208
4208
4209 :hg:`resolve` must be used to resolve unresolved files.
4209 :hg:`resolve` must be used to resolve unresolved files.
4210
4210
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4211 To undo an uncommitted merge, use :hg:`update --clean .` which
4212 will check out a clean copy of the original merge parent, losing
4212 will check out a clean copy of the original merge parent, losing
4213 all changes.
4213 all changes.
4214
4214
4215 Returns 0 on success, 1 if there are unresolved files.
4215 Returns 0 on success, 1 if there are unresolved files.
4216 """
4216 """
4217
4217
4218 if opts.get('rev') and node:
4218 if opts.get('rev') and node:
4219 raise util.Abort(_("please specify just one revision"))
4219 raise util.Abort(_("please specify just one revision"))
4220 if not node:
4220 if not node:
4221 node = opts.get('rev')
4221 node = opts.get('rev')
4222
4222
4223 if node:
4223 if node:
4224 node = scmutil.revsingle(repo, node).node()
4224 node = scmutil.revsingle(repo, node).node()
4225
4225
4226 if not node and repo._bookmarkcurrent:
4226 if not node and repo._bookmarkcurrent:
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4227 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4228 curhead = repo[repo._bookmarkcurrent].node()
4228 curhead = repo[repo._bookmarkcurrent].node()
4229 if len(bmheads) == 2:
4229 if len(bmheads) == 2:
4230 if curhead == bmheads[0]:
4230 if curhead == bmheads[0]:
4231 node = bmheads[1]
4231 node = bmheads[1]
4232 else:
4232 else:
4233 node = bmheads[0]
4233 node = bmheads[0]
4234 elif len(bmheads) > 2:
4234 elif len(bmheads) > 2:
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4235 raise util.Abort(_("multiple matching bookmarks to merge - "
4236 "please merge with an explicit rev or bookmark"),
4236 "please merge with an explicit rev or bookmark"),
4237 hint=_("run 'hg heads' to see all heads"))
4237 hint=_("run 'hg heads' to see all heads"))
4238 elif len(bmheads) <= 1:
4238 elif len(bmheads) <= 1:
4239 raise util.Abort(_("no matching bookmark to merge - "
4239 raise util.Abort(_("no matching bookmark to merge - "
4240 "please merge with an explicit rev or bookmark"),
4240 "please merge with an explicit rev or bookmark"),
4241 hint=_("run 'hg heads' to see all heads"))
4241 hint=_("run 'hg heads' to see all heads"))
4242
4242
4243 if not node and not repo._bookmarkcurrent:
4243 if not node and not repo._bookmarkcurrent:
4244 branch = repo[None].branch()
4244 branch = repo[None].branch()
4245 bheads = repo.branchheads(branch)
4245 bheads = repo.branchheads(branch)
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4246 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4247
4247
4248 if len(nbhs) > 2:
4248 if len(nbhs) > 2:
4249 raise util.Abort(_("branch '%s' has %d heads - "
4249 raise util.Abort(_("branch '%s' has %d heads - "
4250 "please merge with an explicit rev")
4250 "please merge with an explicit rev")
4251 % (branch, len(bheads)),
4251 % (branch, len(bheads)),
4252 hint=_("run 'hg heads .' to see heads"))
4252 hint=_("run 'hg heads .' to see heads"))
4253
4253
4254 parent = repo.dirstate.p1()
4254 parent = repo.dirstate.p1()
4255 if len(nbhs) <= 1:
4255 if len(nbhs) <= 1:
4256 if len(bheads) > 1:
4256 if len(bheads) > 1:
4257 raise util.Abort(_("heads are bookmarked - "
4257 raise util.Abort(_("heads are bookmarked - "
4258 "please merge with an explicit rev"),
4258 "please merge with an explicit rev"),
4259 hint=_("run 'hg heads' to see all heads"))
4259 hint=_("run 'hg heads' to see all heads"))
4260 if len(repo.heads()) > 1:
4260 if len(repo.heads()) > 1:
4261 raise util.Abort(_("branch '%s' has one head - "
4261 raise util.Abort(_("branch '%s' has one head - "
4262 "please merge with an explicit rev")
4262 "please merge with an explicit rev")
4263 % branch,
4263 % branch,
4264 hint=_("run 'hg heads' to see all heads"))
4264 hint=_("run 'hg heads' to see all heads"))
4265 msg, hint = _('nothing to merge'), None
4265 msg, hint = _('nothing to merge'), None
4266 if parent != repo.lookup(branch):
4266 if parent != repo.lookup(branch):
4267 hint = _("use 'hg update' instead")
4267 hint = _("use 'hg update' instead")
4268 raise util.Abort(msg, hint=hint)
4268 raise util.Abort(msg, hint=hint)
4269
4269
4270 if parent not in bheads:
4270 if parent not in bheads:
4271 raise util.Abort(_('working directory not at a head revision'),
4271 raise util.Abort(_('working directory not at a head revision'),
4272 hint=_("use 'hg update' or merge with an "
4272 hint=_("use 'hg update' or merge with an "
4273 "explicit revision"))
4273 "explicit revision"))
4274 if parent == nbhs[0]:
4274 if parent == nbhs[0]:
4275 node = nbhs[-1]
4275 node = nbhs[-1]
4276 else:
4276 else:
4277 node = nbhs[0]
4277 node = nbhs[0]
4278
4278
4279 if opts.get('preview'):
4279 if opts.get('preview'):
4280 # find nodes that are ancestors of p2 but not of p1
4280 # find nodes that are ancestors of p2 but not of p1
4281 p1 = repo.lookup('.')
4281 p1 = repo.lookup('.')
4282 p2 = repo.lookup(node)
4282 p2 = repo.lookup(node)
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4283 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4284
4284
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4285 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 for node in nodes:
4286 for node in nodes:
4287 displayer.show(repo[node])
4287 displayer.show(repo[node])
4288 displayer.close()
4288 displayer.close()
4289 return 0
4289 return 0
4290
4290
4291 try:
4291 try:
4292 # ui.forcemerge is an internal variable, do not document
4292 # ui.forcemerge is an internal variable, do not document
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4293 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4294 return hg.merge(repo, node, force=opts.get('force'))
4294 return hg.merge(repo, node, force=opts.get('force'))
4295 finally:
4295 finally:
4296 ui.setconfig('ui', 'forcemerge', '')
4296 ui.setconfig('ui', 'forcemerge', '')
4297
4297
4298 @command('outgoing|out',
4298 @command('outgoing|out',
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4299 [('f', 'force', None, _('run even when the destination is unrelated')),
4300 ('r', 'rev', [],
4300 ('r', 'rev', [],
4301 _('a changeset intended to be included in the destination'), _('REV')),
4301 _('a changeset intended to be included in the destination'), _('REV')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4302 ('n', 'newest-first', None, _('show newest record first')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4303 ('B', 'bookmarks', False, _('compare bookmarks')),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4304 ('b', 'branch', [], _('a specific branch you would like to push'),
4305 _('BRANCH')),
4305 _('BRANCH')),
4306 ] + logopts + remoteopts + subrepoopts,
4306 ] + logopts + remoteopts + subrepoopts,
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4307 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4308 def outgoing(ui, repo, dest=None, **opts):
4308 def outgoing(ui, repo, dest=None, **opts):
4309 """show changesets not found in the destination
4309 """show changesets not found in the destination
4310
4310
4311 Show changesets not found in the specified destination repository
4311 Show changesets not found in the specified destination repository
4312 or the default push location. These are the changesets that would
4312 or the default push location. These are the changesets that would
4313 be pushed if a push was requested.
4313 be pushed if a push was requested.
4314
4314
4315 See pull for details of valid destination formats.
4315 See pull for details of valid destination formats.
4316
4316
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4317 Returns 0 if there are outgoing changes, 1 otherwise.
4318 """
4318 """
4319 if opts.get('graph'):
4319 if opts.get('graph'):
4320 cmdutil.checkunsupportedgraphflags([], opts)
4320 cmdutil.checkunsupportedgraphflags([], opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4321 o = hg._outgoing(ui, repo, dest, opts)
4322 if o is None:
4322 if o is None:
4323 return
4323 return
4324
4324
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 graphmod.asciiedges)
4329 graphmod.asciiedges)
4330 return 0
4330 return 0
4331
4331
4332 if opts.get('bookmarks'):
4332 if opts.get('bookmarks'):
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4333 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4334 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 other = hg.peer(repo, opts, dest)
4335 other = hg.peer(repo, opts, dest)
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4336 if 'bookmarks' not in other.listkeys('namespaces'):
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4337 ui.warn(_("remote doesn't support bookmarks\n"))
4338 return 0
4338 return 0
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4339 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 return bookmarks.diff(ui, other, repo)
4340 return bookmarks.diff(ui, other, repo)
4341
4341
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4342 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 try:
4343 try:
4344 return hg.outgoing(ui, repo, dest, opts)
4344 return hg.outgoing(ui, repo, dest, opts)
4345 finally:
4345 finally:
4346 del repo._subtoppath
4346 del repo._subtoppath
4347
4347
4348 @command('parents',
4348 @command('parents',
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4349 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 ] + templateopts,
4350 ] + templateopts,
4351 _('[-r REV] [FILE]'))
4351 _('[-r REV] [FILE]'))
4352 def parents(ui, repo, file_=None, **opts):
4352 def parents(ui, repo, file_=None, **opts):
4353 """show the parents of the working directory or revision
4353 """show the parents of the working directory or revision
4354
4354
4355 Print the working directory's parent revisions. If a revision is
4355 Print the working directory's parent revisions. If a revision is
4356 given via -r/--rev, the parent of that revision will be printed.
4356 given via -r/--rev, the parent of that revision will be printed.
4357 If a file argument is given, the revision in which the file was
4357 If a file argument is given, the revision in which the file was
4358 last changed (before the working directory revision or the
4358 last changed (before the working directory revision or the
4359 argument to --rev if given) is printed.
4359 argument to --rev if given) is printed.
4360
4360
4361 Returns 0 on success.
4361 Returns 0 on success.
4362 """
4362 """
4363
4363
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4364 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365
4365
4366 if file_:
4366 if file_:
4367 m = scmutil.match(ctx, (file_,), opts)
4367 m = scmutil.match(ctx, (file_,), opts)
4368 if m.anypats() or len(m.files()) != 1:
4368 if m.anypats() or len(m.files()) != 1:
4369 raise util.Abort(_('can only specify an explicit filename'))
4369 raise util.Abort(_('can only specify an explicit filename'))
4370 file_ = m.files()[0]
4370 file_ = m.files()[0]
4371 filenodes = []
4371 filenodes = []
4372 for cp in ctx.parents():
4372 for cp in ctx.parents():
4373 if not cp:
4373 if not cp:
4374 continue
4374 continue
4375 try:
4375 try:
4376 filenodes.append(cp.filenode(file_))
4376 filenodes.append(cp.filenode(file_))
4377 except error.LookupError:
4377 except error.LookupError:
4378 pass
4378 pass
4379 if not filenodes:
4379 if not filenodes:
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4380 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 p = []
4381 p = []
4382 for fn in filenodes:
4382 for fn in filenodes:
4383 fctx = repo.filectx(file_, fileid=fn)
4383 fctx = repo.filectx(file_, fileid=fn)
4384 p.append(fctx.node())
4384 p.append(fctx.node())
4385 else:
4385 else:
4386 p = [cp.node() for cp in ctx.parents()]
4386 p = [cp.node() for cp in ctx.parents()]
4387
4387
4388 displayer = cmdutil.show_changeset(ui, repo, opts)
4388 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 for n in p:
4389 for n in p:
4390 if n != nullid:
4390 if n != nullid:
4391 displayer.show(repo[n])
4391 displayer.show(repo[n])
4392 displayer.close()
4392 displayer.close()
4393
4393
4394 @command('paths', [], _('[NAME]'))
4394 @command('paths', [], _('[NAME]'))
4395 def paths(ui, repo, search=None):
4395 def paths(ui, repo, search=None):
4396 """show aliases for remote repositories
4396 """show aliases for remote repositories
4397
4397
4398 Show definition of symbolic path name NAME. If no name is given,
4398 Show definition of symbolic path name NAME. If no name is given,
4399 show definition of all available names.
4399 show definition of all available names.
4400
4400
4401 Option -q/--quiet suppresses all output when searching for NAME
4401 Option -q/--quiet suppresses all output when searching for NAME
4402 and shows only the path names when listing all definitions.
4402 and shows only the path names when listing all definitions.
4403
4403
4404 Path names are defined in the [paths] section of your
4404 Path names are defined in the [paths] section of your
4405 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4405 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 repository, ``.hg/hgrc`` is used, too.
4406 repository, ``.hg/hgrc`` is used, too.
4407
4407
4408 The path names ``default`` and ``default-push`` have a special
4408 The path names ``default`` and ``default-push`` have a special
4409 meaning. When performing a push or pull operation, they are used
4409 meaning. When performing a push or pull operation, they are used
4410 as fallbacks if no location is specified on the command-line.
4410 as fallbacks if no location is specified on the command-line.
4411 When ``default-push`` is set, it will be used for push and
4411 When ``default-push`` is set, it will be used for push and
4412 ``default`` will be used for pull; otherwise ``default`` is used
4412 ``default`` will be used for pull; otherwise ``default`` is used
4413 as the fallback for both. When cloning a repository, the clone
4413 as the fallback for both. When cloning a repository, the clone
4414 source is written as ``default`` in ``.hg/hgrc``. Note that
4414 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 ``default`` and ``default-push`` apply to all inbound (e.g.
4415 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4416 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`bundle`) operations.
4417 :hg:`bundle`) operations.
4418
4418
4419 See :hg:`help urls` for more information.
4419 See :hg:`help urls` for more information.
4420
4420
4421 Returns 0 on success.
4421 Returns 0 on success.
4422 """
4422 """
4423 if search:
4423 if search:
4424 for name, path in ui.configitems("paths"):
4424 for name, path in ui.configitems("paths"):
4425 if name == search:
4425 if name == search:
4426 ui.status("%s\n" % util.hidepassword(path))
4426 ui.status("%s\n" % util.hidepassword(path))
4427 return
4427 return
4428 if not ui.quiet:
4428 if not ui.quiet:
4429 ui.warn(_("not found!\n"))
4429 ui.warn(_("not found!\n"))
4430 return 1
4430 return 1
4431 else:
4431 else:
4432 for name, path in ui.configitems("paths"):
4432 for name, path in ui.configitems("paths"):
4433 if ui.quiet:
4433 if ui.quiet:
4434 ui.write("%s\n" % name)
4434 ui.write("%s\n" % name)
4435 else:
4435 else:
4436 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4436 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437
4437
4438 @command('phase',
4438 @command('phase',
4439 [('p', 'public', False, _('set changeset phase to public')),
4439 [('p', 'public', False, _('set changeset phase to public')),
4440 ('d', 'draft', False, _('set changeset phase to draft')),
4440 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('s', 'secret', False, _('set changeset phase to secret')),
4441 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('f', 'force', False, _('allow to move boundary backward')),
4442 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('r', 'rev', [], _('target revision'), _('REV')),
4443 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ],
4444 ],
4445 _('[-p|-d|-s] [-f] [-r] REV...'))
4445 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 def phase(ui, repo, *revs, **opts):
4446 def phase(ui, repo, *revs, **opts):
4447 """set or show the current phase name
4447 """set or show the current phase name
4448
4448
4449 With no argument, show the phase name of specified revisions.
4449 With no argument, show the phase name of specified revisions.
4450
4450
4451 With one of -p/--public, -d/--draft or -s/--secret, change the
4451 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 phase value of the specified revisions.
4452 phase value of the specified revisions.
4453
4453
4454 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4454 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 lower phase to an higher phase. Phases are ordered as follows::
4455 lower phase to an higher phase. Phases are ordered as follows::
4456
4456
4457 public < draft < secret
4457 public < draft < secret
4458
4458
4459 Return 0 on success, 1 if no phases were changed or some could not
4459 Return 0 on success, 1 if no phases were changed or some could not
4460 be changed.
4460 be changed.
4461 """
4461 """
4462 # search for a unique phase argument
4462 # search for a unique phase argument
4463 targetphase = None
4463 targetphase = None
4464 for idx, name in enumerate(phases.phasenames):
4464 for idx, name in enumerate(phases.phasenames):
4465 if opts[name]:
4465 if opts[name]:
4466 if targetphase is not None:
4466 if targetphase is not None:
4467 raise util.Abort(_('only one phase can be specified'))
4467 raise util.Abort(_('only one phase can be specified'))
4468 targetphase = idx
4468 targetphase = idx
4469
4469
4470 # look for specified revision
4470 # look for specified revision
4471 revs = list(revs)
4471 revs = list(revs)
4472 revs.extend(opts['rev'])
4472 revs.extend(opts['rev'])
4473 if not revs:
4473 if not revs:
4474 raise util.Abort(_('no revisions specified'))
4474 raise util.Abort(_('no revisions specified'))
4475
4475
4476 revs = scmutil.revrange(repo, revs)
4476 revs = scmutil.revrange(repo, revs)
4477
4477
4478 lock = None
4478 lock = None
4479 ret = 0
4479 ret = 0
4480 if targetphase is None:
4480 if targetphase is None:
4481 # display
4481 # display
4482 for r in revs:
4482 for r in revs:
4483 ctx = repo[r]
4483 ctx = repo[r]
4484 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4484 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 else:
4485 else:
4486 lock = repo.lock()
4486 lock = repo.lock()
4487 try:
4487 try:
4488 # set phase
4488 # set phase
4489 if not revs:
4489 if not revs:
4490 raise util.Abort(_('empty revision set'))
4490 raise util.Abort(_('empty revision set'))
4491 nodes = [repo[r].node() for r in revs]
4491 nodes = [repo[r].node() for r in revs]
4492 olddata = repo._phasecache.getphaserevs(repo)[:]
4492 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 phases.advanceboundary(repo, targetphase, nodes)
4493 phases.advanceboundary(repo, targetphase, nodes)
4494 if opts['force']:
4494 if opts['force']:
4495 phases.retractboundary(repo, targetphase, nodes)
4495 phases.retractboundary(repo, targetphase, nodes)
4496 finally:
4496 finally:
4497 lock.release()
4497 lock.release()
4498 # moving revision from public to draft may hide them
4498 # moving revision from public to draft may hide them
4499 # We have to check result on an unfiltered repository
4499 # We have to check result on an unfiltered repository
4500 unfi = repo.unfiltered()
4500 unfi = repo.unfiltered()
4501 newdata = repo._phasecache.getphaserevs(unfi)
4501 newdata = repo._phasecache.getphaserevs(unfi)
4502 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4502 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 cl = unfi.changelog
4503 cl = unfi.changelog
4504 rejected = [n for n in nodes
4504 rejected = [n for n in nodes
4505 if newdata[cl.rev(n)] < targetphase]
4505 if newdata[cl.rev(n)] < targetphase]
4506 if rejected:
4506 if rejected:
4507 ui.warn(_('cannot move %i changesets to a more permissive '
4507 ui.warn(_('cannot move %i changesets to a more permissive '
4508 'phase, use --force\n') % len(rejected))
4508 'phase, use --force\n') % len(rejected))
4509 ret = 1
4509 ret = 1
4510 if changes:
4510 if changes:
4511 msg = _('phase changed for %i changesets\n') % changes
4511 msg = _('phase changed for %i changesets\n') % changes
4512 if ret:
4512 if ret:
4513 ui.status(msg)
4513 ui.status(msg)
4514 else:
4514 else:
4515 ui.note(msg)
4515 ui.note(msg)
4516 else:
4516 else:
4517 ui.warn(_('no phases changed\n'))
4517 ui.warn(_('no phases changed\n'))
4518 ret = 1
4518 ret = 1
4519 return ret
4519 return ret
4520
4520
4521 def postincoming(ui, repo, modheads, optupdate, checkout):
4521 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 if modheads == 0:
4522 if modheads == 0:
4523 return
4523 return
4524 if optupdate:
4524 if optupdate:
4525 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4525 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 try:
4526 try:
4527 ret = hg.update(repo, checkout)
4527 ret = hg.update(repo, checkout)
4528 except util.Abort, inst:
4528 except util.Abort, inst:
4529 ui.warn(_("not updating: %s\n") % str(inst))
4529 ui.warn(_("not updating: %s\n") % str(inst))
4530 if inst.hint:
4531 ui.warn(_("(%s)\n") % inst.hint)
4530 return 0
4532 return 0
4531 if not ret and not checkout:
4533 if not ret and not checkout:
4532 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4534 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4533 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4535 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4534 return ret
4536 return ret
4535 if modheads > 1:
4537 if modheads > 1:
4536 currentbranchheads = len(repo.branchheads())
4538 currentbranchheads = len(repo.branchheads())
4537 if currentbranchheads == modheads:
4539 if currentbranchheads == modheads:
4538 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4540 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4539 elif currentbranchheads > 1:
4541 elif currentbranchheads > 1:
4540 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4542 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4541 "merge)\n"))
4543 "merge)\n"))
4542 else:
4544 else:
4543 ui.status(_("(run 'hg heads' to see heads)\n"))
4545 ui.status(_("(run 'hg heads' to see heads)\n"))
4544 else:
4546 else:
4545 ui.status(_("(run 'hg update' to get a working copy)\n"))
4547 ui.status(_("(run 'hg update' to get a working copy)\n"))
4546
4548
4547 @command('^pull',
4549 @command('^pull',
4548 [('u', 'update', None,
4550 [('u', 'update', None,
4549 _('update to new branch head if changesets were pulled')),
4551 _('update to new branch head if changesets were pulled')),
4550 ('f', 'force', None, _('run even when remote repository is unrelated')),
4552 ('f', 'force', None, _('run even when remote repository is unrelated')),
4551 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4553 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4552 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4554 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4553 ('b', 'branch', [], _('a specific branch you would like to pull'),
4555 ('b', 'branch', [], _('a specific branch you would like to pull'),
4554 _('BRANCH')),
4556 _('BRANCH')),
4555 ] + remoteopts,
4557 ] + remoteopts,
4556 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4558 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4557 def pull(ui, repo, source="default", **opts):
4559 def pull(ui, repo, source="default", **opts):
4558 """pull changes from the specified source
4560 """pull changes from the specified source
4559
4561
4560 Pull changes from a remote repository to a local one.
4562 Pull changes from a remote repository to a local one.
4561
4563
4562 This finds all changes from the repository at the specified path
4564 This finds all changes from the repository at the specified path
4563 or URL and adds them to a local repository (the current one unless
4565 or URL and adds them to a local repository (the current one unless
4564 -R is specified). By default, this does not update the copy of the
4566 -R is specified). By default, this does not update the copy of the
4565 project in the working directory.
4567 project in the working directory.
4566
4568
4567 Use :hg:`incoming` if you want to see what would have been added
4569 Use :hg:`incoming` if you want to see what would have been added
4568 by a pull at the time you issued this command. If you then decide
4570 by a pull at the time you issued this command. If you then decide
4569 to add those changes to the repository, you should use :hg:`pull
4571 to add those changes to the repository, you should use :hg:`pull
4570 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4572 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4571
4573
4572 If SOURCE is omitted, the 'default' path will be used.
4574 If SOURCE is omitted, the 'default' path will be used.
4573 See :hg:`help urls` for more information.
4575 See :hg:`help urls` for more information.
4574
4576
4575 Returns 0 on success, 1 if an update had unresolved files.
4577 Returns 0 on success, 1 if an update had unresolved files.
4576 """
4578 """
4577 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4579 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4578 other = hg.peer(repo, opts, source)
4580 other = hg.peer(repo, opts, source)
4579 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4581 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4580 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4582 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4581
4583
4582 remotebookmarks = other.listkeys('bookmarks')
4584 remotebookmarks = other.listkeys('bookmarks')
4583
4585
4584 if opts.get('bookmark'):
4586 if opts.get('bookmark'):
4585 if not revs:
4587 if not revs:
4586 revs = []
4588 revs = []
4587 for b in opts['bookmark']:
4589 for b in opts['bookmark']:
4588 if b not in remotebookmarks:
4590 if b not in remotebookmarks:
4589 raise util.Abort(_('remote bookmark %s not found!') % b)
4591 raise util.Abort(_('remote bookmark %s not found!') % b)
4590 revs.append(remotebookmarks[b])
4592 revs.append(remotebookmarks[b])
4591
4593
4592 if revs:
4594 if revs:
4593 try:
4595 try:
4594 revs = [other.lookup(rev) for rev in revs]
4596 revs = [other.lookup(rev) for rev in revs]
4595 except error.CapabilityError:
4597 except error.CapabilityError:
4596 err = _("other repository doesn't support revision lookup, "
4598 err = _("other repository doesn't support revision lookup, "
4597 "so a rev cannot be specified.")
4599 "so a rev cannot be specified.")
4598 raise util.Abort(err)
4600 raise util.Abort(err)
4599
4601
4600 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4602 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4601 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4603 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4602 if checkout:
4604 if checkout:
4603 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4605 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4604 repo._subtoppath = source
4606 repo._subtoppath = source
4605 try:
4607 try:
4606 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4608 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4607
4609
4608 finally:
4610 finally:
4609 del repo._subtoppath
4611 del repo._subtoppath
4610
4612
4611 # update specified bookmarks
4613 # update specified bookmarks
4612 if opts.get('bookmark'):
4614 if opts.get('bookmark'):
4613 marks = repo._bookmarks
4615 marks = repo._bookmarks
4614 for b in opts['bookmark']:
4616 for b in opts['bookmark']:
4615 # explicit pull overrides local bookmark if any
4617 # explicit pull overrides local bookmark if any
4616 ui.status(_("importing bookmark %s\n") % b)
4618 ui.status(_("importing bookmark %s\n") % b)
4617 marks[b] = repo[remotebookmarks[b]].node()
4619 marks[b] = repo[remotebookmarks[b]].node()
4618 marks.write()
4620 marks.write()
4619
4621
4620 return ret
4622 return ret
4621
4623
4622 @command('^push',
4624 @command('^push',
4623 [('f', 'force', None, _('force push')),
4625 [('f', 'force', None, _('force push')),
4624 ('r', 'rev', [],
4626 ('r', 'rev', [],
4625 _('a changeset intended to be included in the destination'),
4627 _('a changeset intended to be included in the destination'),
4626 _('REV')),
4628 _('REV')),
4627 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4629 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4628 ('b', 'branch', [],
4630 ('b', 'branch', [],
4629 _('a specific branch you would like to push'), _('BRANCH')),
4631 _('a specific branch you would like to push'), _('BRANCH')),
4630 ('', 'new-branch', False, _('allow pushing a new branch')),
4632 ('', 'new-branch', False, _('allow pushing a new branch')),
4631 ] + remoteopts,
4633 ] + remoteopts,
4632 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4634 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4633 def push(ui, repo, dest=None, **opts):
4635 def push(ui, repo, dest=None, **opts):
4634 """push changes to the specified destination
4636 """push changes to the specified destination
4635
4637
4636 Push changesets from the local repository to the specified
4638 Push changesets from the local repository to the specified
4637 destination.
4639 destination.
4638
4640
4639 This operation is symmetrical to pull: it is identical to a pull
4641 This operation is symmetrical to pull: it is identical to a pull
4640 in the destination repository from the current one.
4642 in the destination repository from the current one.
4641
4643
4642 By default, push will not allow creation of new heads at the
4644 By default, push will not allow creation of new heads at the
4643 destination, since multiple heads would make it unclear which head
4645 destination, since multiple heads would make it unclear which head
4644 to use. In this situation, it is recommended to pull and merge
4646 to use. In this situation, it is recommended to pull and merge
4645 before pushing.
4647 before pushing.
4646
4648
4647 Use --new-branch if you want to allow push to create a new named
4649 Use --new-branch if you want to allow push to create a new named
4648 branch that is not present at the destination. This allows you to
4650 branch that is not present at the destination. This allows you to
4649 only create a new branch without forcing other changes.
4651 only create a new branch without forcing other changes.
4650
4652
4651 Use -f/--force to override the default behavior and push all
4653 Use -f/--force to override the default behavior and push all
4652 changesets on all branches.
4654 changesets on all branches.
4653
4655
4654 If -r/--rev is used, the specified revision and all its ancestors
4656 If -r/--rev is used, the specified revision and all its ancestors
4655 will be pushed to the remote repository.
4657 will be pushed to the remote repository.
4656
4658
4657 If -B/--bookmark is used, the specified bookmarked revision, its
4659 If -B/--bookmark is used, the specified bookmarked revision, its
4658 ancestors, and the bookmark will be pushed to the remote
4660 ancestors, and the bookmark will be pushed to the remote
4659 repository.
4661 repository.
4660
4662
4661 Please see :hg:`help urls` for important details about ``ssh://``
4663 Please see :hg:`help urls` for important details about ``ssh://``
4662 URLs. If DESTINATION is omitted, a default path will be used.
4664 URLs. If DESTINATION is omitted, a default path will be used.
4663
4665
4664 Returns 0 if push was successful, 1 if nothing to push.
4666 Returns 0 if push was successful, 1 if nothing to push.
4665 """
4667 """
4666
4668
4667 if opts.get('bookmark'):
4669 if opts.get('bookmark'):
4668 for b in opts['bookmark']:
4670 for b in opts['bookmark']:
4669 # translate -B options to -r so changesets get pushed
4671 # translate -B options to -r so changesets get pushed
4670 if b in repo._bookmarks:
4672 if b in repo._bookmarks:
4671 opts.setdefault('rev', []).append(b)
4673 opts.setdefault('rev', []).append(b)
4672 else:
4674 else:
4673 # if we try to push a deleted bookmark, translate it to null
4675 # if we try to push a deleted bookmark, translate it to null
4674 # this lets simultaneous -r, -b options continue working
4676 # this lets simultaneous -r, -b options continue working
4675 opts.setdefault('rev', []).append("null")
4677 opts.setdefault('rev', []).append("null")
4676
4678
4677 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4679 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4678 dest, branches = hg.parseurl(dest, opts.get('branch'))
4680 dest, branches = hg.parseurl(dest, opts.get('branch'))
4679 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4681 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4680 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4682 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4681 other = hg.peer(repo, opts, dest)
4683 other = hg.peer(repo, opts, dest)
4682 if revs:
4684 if revs:
4683 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4685 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4684
4686
4685 repo._subtoppath = dest
4687 repo._subtoppath = dest
4686 try:
4688 try:
4687 # push subrepos depth-first for coherent ordering
4689 # push subrepos depth-first for coherent ordering
4688 c = repo['']
4690 c = repo['']
4689 subs = c.substate # only repos that are committed
4691 subs = c.substate # only repos that are committed
4690 for s in sorted(subs):
4692 for s in sorted(subs):
4691 if c.sub(s).push(opts) == 0:
4693 if c.sub(s).push(opts) == 0:
4692 return False
4694 return False
4693 finally:
4695 finally:
4694 del repo._subtoppath
4696 del repo._subtoppath
4695 result = repo.push(other, opts.get('force'), revs=revs,
4697 result = repo.push(other, opts.get('force'), revs=revs,
4696 newbranch=opts.get('new_branch'))
4698 newbranch=opts.get('new_branch'))
4697
4699
4698 result = not result
4700 result = not result
4699
4701
4700 if opts.get('bookmark'):
4702 if opts.get('bookmark'):
4701 rb = other.listkeys('bookmarks')
4703 rb = other.listkeys('bookmarks')
4702 for b in opts['bookmark']:
4704 for b in opts['bookmark']:
4703 # explicit push overrides remote bookmark if any
4705 # explicit push overrides remote bookmark if any
4704 if b in repo._bookmarks:
4706 if b in repo._bookmarks:
4705 ui.status(_("exporting bookmark %s\n") % b)
4707 ui.status(_("exporting bookmark %s\n") % b)
4706 new = repo[b].hex()
4708 new = repo[b].hex()
4707 elif b in rb:
4709 elif b in rb:
4708 ui.status(_("deleting remote bookmark %s\n") % b)
4710 ui.status(_("deleting remote bookmark %s\n") % b)
4709 new = '' # delete
4711 new = '' # delete
4710 else:
4712 else:
4711 ui.warn(_('bookmark %s does not exist on the local '
4713 ui.warn(_('bookmark %s does not exist on the local '
4712 'or remote repository!\n') % b)
4714 'or remote repository!\n') % b)
4713 return 2
4715 return 2
4714 old = rb.get(b, '')
4716 old = rb.get(b, '')
4715 r = other.pushkey('bookmarks', b, old, new)
4717 r = other.pushkey('bookmarks', b, old, new)
4716 if not r:
4718 if not r:
4717 ui.warn(_('updating bookmark %s failed!\n') % b)
4719 ui.warn(_('updating bookmark %s failed!\n') % b)
4718 if not result:
4720 if not result:
4719 result = 2
4721 result = 2
4720
4722
4721 return result
4723 return result
4722
4724
4723 @command('recover', [])
4725 @command('recover', [])
4724 def recover(ui, repo):
4726 def recover(ui, repo):
4725 """roll back an interrupted transaction
4727 """roll back an interrupted transaction
4726
4728
4727 Recover from an interrupted commit or pull.
4729 Recover from an interrupted commit or pull.
4728
4730
4729 This command tries to fix the repository status after an
4731 This command tries to fix the repository status after an
4730 interrupted operation. It should only be necessary when Mercurial
4732 interrupted operation. It should only be necessary when Mercurial
4731 suggests it.
4733 suggests it.
4732
4734
4733 Returns 0 if successful, 1 if nothing to recover or verify fails.
4735 Returns 0 if successful, 1 if nothing to recover or verify fails.
4734 """
4736 """
4735 if repo.recover():
4737 if repo.recover():
4736 return hg.verify(repo)
4738 return hg.verify(repo)
4737 return 1
4739 return 1
4738
4740
4739 @command('^remove|rm',
4741 @command('^remove|rm',
4740 [('A', 'after', None, _('record delete for missing files')),
4742 [('A', 'after', None, _('record delete for missing files')),
4741 ('f', 'force', None,
4743 ('f', 'force', None,
4742 _('remove (and delete) file even if added or modified')),
4744 _('remove (and delete) file even if added or modified')),
4743 ] + walkopts,
4745 ] + walkopts,
4744 _('[OPTION]... FILE...'))
4746 _('[OPTION]... FILE...'))
4745 def remove(ui, repo, *pats, **opts):
4747 def remove(ui, repo, *pats, **opts):
4746 """remove the specified files on the next commit
4748 """remove the specified files on the next commit
4747
4749
4748 Schedule the indicated files for removal from the current branch.
4750 Schedule the indicated files for removal from the current branch.
4749
4751
4750 This command schedules the files to be removed at the next commit.
4752 This command schedules the files to be removed at the next commit.
4751 To undo a remove before that, see :hg:`revert`. To undo added
4753 To undo a remove before that, see :hg:`revert`. To undo added
4752 files, see :hg:`forget`.
4754 files, see :hg:`forget`.
4753
4755
4754 .. container:: verbose
4756 .. container:: verbose
4755
4757
4756 -A/--after can be used to remove only files that have already
4758 -A/--after can be used to remove only files that have already
4757 been deleted, -f/--force can be used to force deletion, and -Af
4759 been deleted, -f/--force can be used to force deletion, and -Af
4758 can be used to remove files from the next revision without
4760 can be used to remove files from the next revision without
4759 deleting them from the working directory.
4761 deleting them from the working directory.
4760
4762
4761 The following table details the behavior of remove for different
4763 The following table details the behavior of remove for different
4762 file states (columns) and option combinations (rows). The file
4764 file states (columns) and option combinations (rows). The file
4763 states are Added [A], Clean [C], Modified [M] and Missing [!]
4765 states are Added [A], Clean [C], Modified [M] and Missing [!]
4764 (as reported by :hg:`status`). The actions are Warn, Remove
4766 (as reported by :hg:`status`). The actions are Warn, Remove
4765 (from branch) and Delete (from disk):
4767 (from branch) and Delete (from disk):
4766
4768
4767 ======= == == == ==
4769 ======= == == == ==
4768 A C M !
4770 A C M !
4769 ======= == == == ==
4771 ======= == == == ==
4770 none W RD W R
4772 none W RD W R
4771 -f R RD RD R
4773 -f R RD RD R
4772 -A W W W R
4774 -A W W W R
4773 -Af R R R R
4775 -Af R R R R
4774 ======= == == == ==
4776 ======= == == == ==
4775
4777
4776 Note that remove never deletes files in Added [A] state from the
4778 Note that remove never deletes files in Added [A] state from the
4777 working directory, not even if option --force is specified.
4779 working directory, not even if option --force is specified.
4778
4780
4779 Returns 0 on success, 1 if any warnings encountered.
4781 Returns 0 on success, 1 if any warnings encountered.
4780 """
4782 """
4781
4783
4782 ret = 0
4784 ret = 0
4783 after, force = opts.get('after'), opts.get('force')
4785 after, force = opts.get('after'), opts.get('force')
4784 if not pats and not after:
4786 if not pats and not after:
4785 raise util.Abort(_('no files specified'))
4787 raise util.Abort(_('no files specified'))
4786
4788
4787 m = scmutil.match(repo[None], pats, opts)
4789 m = scmutil.match(repo[None], pats, opts)
4788 s = repo.status(match=m, clean=True)
4790 s = repo.status(match=m, clean=True)
4789 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4791 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4790
4792
4791 # warn about failure to delete explicit files/dirs
4793 # warn about failure to delete explicit files/dirs
4792 wctx = repo[None]
4794 wctx = repo[None]
4793 for f in m.files():
4795 for f in m.files():
4794 if f in repo.dirstate or f in wctx.dirs():
4796 if f in repo.dirstate or f in wctx.dirs():
4795 continue
4797 continue
4796 if os.path.exists(m.rel(f)):
4798 if os.path.exists(m.rel(f)):
4797 if os.path.isdir(m.rel(f)):
4799 if os.path.isdir(m.rel(f)):
4798 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4800 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4799 else:
4801 else:
4800 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4802 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4801 # missing files will generate a warning elsewhere
4803 # missing files will generate a warning elsewhere
4802 ret = 1
4804 ret = 1
4803
4805
4804 if force:
4806 if force:
4805 list = modified + deleted + clean + added
4807 list = modified + deleted + clean + added
4806 elif after:
4808 elif after:
4807 list = deleted
4809 list = deleted
4808 for f in modified + added + clean:
4810 for f in modified + added + clean:
4809 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4811 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4810 ret = 1
4812 ret = 1
4811 else:
4813 else:
4812 list = deleted + clean
4814 list = deleted + clean
4813 for f in modified:
4815 for f in modified:
4814 ui.warn(_('not removing %s: file is modified (use -f'
4816 ui.warn(_('not removing %s: file is modified (use -f'
4815 ' to force removal)\n') % m.rel(f))
4817 ' to force removal)\n') % m.rel(f))
4816 ret = 1
4818 ret = 1
4817 for f in added:
4819 for f in added:
4818 ui.warn(_('not removing %s: file has been marked for add'
4820 ui.warn(_('not removing %s: file has been marked for add'
4819 ' (use forget to undo)\n') % m.rel(f))
4821 ' (use forget to undo)\n') % m.rel(f))
4820 ret = 1
4822 ret = 1
4821
4823
4822 for f in sorted(list):
4824 for f in sorted(list):
4823 if ui.verbose or not m.exact(f):
4825 if ui.verbose or not m.exact(f):
4824 ui.status(_('removing %s\n') % m.rel(f))
4826 ui.status(_('removing %s\n') % m.rel(f))
4825
4827
4826 wlock = repo.wlock()
4828 wlock = repo.wlock()
4827 try:
4829 try:
4828 if not after:
4830 if not after:
4829 for f in list:
4831 for f in list:
4830 if f in added:
4832 if f in added:
4831 continue # we never unlink added files on remove
4833 continue # we never unlink added files on remove
4832 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4834 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4833 repo[None].forget(list)
4835 repo[None].forget(list)
4834 finally:
4836 finally:
4835 wlock.release()
4837 wlock.release()
4836
4838
4837 return ret
4839 return ret
4838
4840
4839 @command('rename|move|mv',
4841 @command('rename|move|mv',
4840 [('A', 'after', None, _('record a rename that has already occurred')),
4842 [('A', 'after', None, _('record a rename that has already occurred')),
4841 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4843 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4842 ] + walkopts + dryrunopts,
4844 ] + walkopts + dryrunopts,
4843 _('[OPTION]... SOURCE... DEST'))
4845 _('[OPTION]... SOURCE... DEST'))
4844 def rename(ui, repo, *pats, **opts):
4846 def rename(ui, repo, *pats, **opts):
4845 """rename files; equivalent of copy + remove
4847 """rename files; equivalent of copy + remove
4846
4848
4847 Mark dest as copies of sources; mark sources for deletion. If dest
4849 Mark dest as copies of sources; mark sources for deletion. If dest
4848 is a directory, copies are put in that directory. If dest is a
4850 is a directory, copies are put in that directory. If dest is a
4849 file, there can only be one source.
4851 file, there can only be one source.
4850
4852
4851 By default, this command copies the contents of files as they
4853 By default, this command copies the contents of files as they
4852 exist in the working directory. If invoked with -A/--after, the
4854 exist in the working directory. If invoked with -A/--after, the
4853 operation is recorded, but no copying is performed.
4855 operation is recorded, but no copying is performed.
4854
4856
4855 This command takes effect at the next commit. To undo a rename
4857 This command takes effect at the next commit. To undo a rename
4856 before that, see :hg:`revert`.
4858 before that, see :hg:`revert`.
4857
4859
4858 Returns 0 on success, 1 if errors are encountered.
4860 Returns 0 on success, 1 if errors are encountered.
4859 """
4861 """
4860 wlock = repo.wlock(False)
4862 wlock = repo.wlock(False)
4861 try:
4863 try:
4862 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4864 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4863 finally:
4865 finally:
4864 wlock.release()
4866 wlock.release()
4865
4867
4866 @command('resolve',
4868 @command('resolve',
4867 [('a', 'all', None, _('select all unresolved files')),
4869 [('a', 'all', None, _('select all unresolved files')),
4868 ('l', 'list', None, _('list state of files needing merge')),
4870 ('l', 'list', None, _('list state of files needing merge')),
4869 ('m', 'mark', None, _('mark files as resolved')),
4871 ('m', 'mark', None, _('mark files as resolved')),
4870 ('u', 'unmark', None, _('mark files as unresolved')),
4872 ('u', 'unmark', None, _('mark files as unresolved')),
4871 ('n', 'no-status', None, _('hide status prefix'))]
4873 ('n', 'no-status', None, _('hide status prefix'))]
4872 + mergetoolopts + walkopts,
4874 + mergetoolopts + walkopts,
4873 _('[OPTION]... [FILE]...'))
4875 _('[OPTION]... [FILE]...'))
4874 def resolve(ui, repo, *pats, **opts):
4876 def resolve(ui, repo, *pats, **opts):
4875 """redo merges or set/view the merge status of files
4877 """redo merges or set/view the merge status of files
4876
4878
4877 Merges with unresolved conflicts are often the result of
4879 Merges with unresolved conflicts are often the result of
4878 non-interactive merging using the ``internal:merge`` configuration
4880 non-interactive merging using the ``internal:merge`` configuration
4879 setting, or a command-line merge tool like ``diff3``. The resolve
4881 setting, or a command-line merge tool like ``diff3``. The resolve
4880 command is used to manage the files involved in a merge, after
4882 command is used to manage the files involved in a merge, after
4881 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4883 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4882 working directory must have two parents). See :hg:`help
4884 working directory must have two parents). See :hg:`help
4883 merge-tools` for information on configuring merge tools.
4885 merge-tools` for information on configuring merge tools.
4884
4886
4885 The resolve command can be used in the following ways:
4887 The resolve command can be used in the following ways:
4886
4888
4887 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4889 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4888 files, discarding any previous merge attempts. Re-merging is not
4890 files, discarding any previous merge attempts. Re-merging is not
4889 performed for files already marked as resolved. Use ``--all/-a``
4891 performed for files already marked as resolved. Use ``--all/-a``
4890 to select all unresolved files. ``--tool`` can be used to specify
4892 to select all unresolved files. ``--tool`` can be used to specify
4891 the merge tool used for the given files. It overrides the HGMERGE
4893 the merge tool used for the given files. It overrides the HGMERGE
4892 environment variable and your configuration files. Previous file
4894 environment variable and your configuration files. Previous file
4893 contents are saved with a ``.orig`` suffix.
4895 contents are saved with a ``.orig`` suffix.
4894
4896
4895 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4897 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4896 (e.g. after having manually fixed-up the files). The default is
4898 (e.g. after having manually fixed-up the files). The default is
4897 to mark all unresolved files.
4899 to mark all unresolved files.
4898
4900
4899 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4901 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4900 default is to mark all resolved files.
4902 default is to mark all resolved files.
4901
4903
4902 - :hg:`resolve -l`: list files which had or still have conflicts.
4904 - :hg:`resolve -l`: list files which had or still have conflicts.
4903 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4905 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4904
4906
4905 Note that Mercurial will not let you commit files with unresolved
4907 Note that Mercurial will not let you commit files with unresolved
4906 merge conflicts. You must use :hg:`resolve -m ...` before you can
4908 merge conflicts. You must use :hg:`resolve -m ...` before you can
4907 commit after a conflicting merge.
4909 commit after a conflicting merge.
4908
4910
4909 Returns 0 on success, 1 if any files fail a resolve attempt.
4911 Returns 0 on success, 1 if any files fail a resolve attempt.
4910 """
4912 """
4911
4913
4912 all, mark, unmark, show, nostatus = \
4914 all, mark, unmark, show, nostatus = \
4913 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4915 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4914
4916
4915 if (show and (mark or unmark)) or (mark and unmark):
4917 if (show and (mark or unmark)) or (mark and unmark):
4916 raise util.Abort(_("too many options specified"))
4918 raise util.Abort(_("too many options specified"))
4917 if pats and all:
4919 if pats and all:
4918 raise util.Abort(_("can't specify --all and patterns"))
4920 raise util.Abort(_("can't specify --all and patterns"))
4919 if not (all or pats or show or mark or unmark):
4921 if not (all or pats or show or mark or unmark):
4920 raise util.Abort(_('no files or directories specified; '
4922 raise util.Abort(_('no files or directories specified; '
4921 'use --all to remerge all files'))
4923 'use --all to remerge all files'))
4922
4924
4923 ms = mergemod.mergestate(repo)
4925 ms = mergemod.mergestate(repo)
4924 m = scmutil.match(repo[None], pats, opts)
4926 m = scmutil.match(repo[None], pats, opts)
4925 ret = 0
4927 ret = 0
4926
4928
4927 for f in ms:
4929 for f in ms:
4928 if m(f):
4930 if m(f):
4929 if show:
4931 if show:
4930 if nostatus:
4932 if nostatus:
4931 ui.write("%s\n" % f)
4933 ui.write("%s\n" % f)
4932 else:
4934 else:
4933 ui.write("%s %s\n" % (ms[f].upper(), f),
4935 ui.write("%s %s\n" % (ms[f].upper(), f),
4934 label='resolve.' +
4936 label='resolve.' +
4935 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4937 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4936 elif mark:
4938 elif mark:
4937 ms.mark(f, "r")
4939 ms.mark(f, "r")
4938 elif unmark:
4940 elif unmark:
4939 ms.mark(f, "u")
4941 ms.mark(f, "u")
4940 else:
4942 else:
4941 wctx = repo[None]
4943 wctx = repo[None]
4942 mctx = wctx.parents()[-1]
4944 mctx = wctx.parents()[-1]
4943
4945
4944 # backup pre-resolve (merge uses .orig for its own purposes)
4946 # backup pre-resolve (merge uses .orig for its own purposes)
4945 a = repo.wjoin(f)
4947 a = repo.wjoin(f)
4946 util.copyfile(a, a + ".resolve")
4948 util.copyfile(a, a + ".resolve")
4947
4949
4948 try:
4950 try:
4949 # resolve file
4951 # resolve file
4950 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4952 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4951 if ms.resolve(f, wctx, mctx):
4953 if ms.resolve(f, wctx, mctx):
4952 ret = 1
4954 ret = 1
4953 finally:
4955 finally:
4954 ui.setconfig('ui', 'forcemerge', '')
4956 ui.setconfig('ui', 'forcemerge', '')
4955 ms.commit()
4957 ms.commit()
4956
4958
4957 # replace filemerge's .orig file with our resolve file
4959 # replace filemerge's .orig file with our resolve file
4958 util.rename(a + ".resolve", a + ".orig")
4960 util.rename(a + ".resolve", a + ".orig")
4959
4961
4960 ms.commit()
4962 ms.commit()
4961 return ret
4963 return ret
4962
4964
4963 @command('revert',
4965 @command('revert',
4964 [('a', 'all', None, _('revert all changes when no arguments given')),
4966 [('a', 'all', None, _('revert all changes when no arguments given')),
4965 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4967 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4966 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4968 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4967 ('C', 'no-backup', None, _('do not save backup copies of files')),
4969 ('C', 'no-backup', None, _('do not save backup copies of files')),
4968 ] + walkopts + dryrunopts,
4970 ] + walkopts + dryrunopts,
4969 _('[OPTION]... [-r REV] [NAME]...'))
4971 _('[OPTION]... [-r REV] [NAME]...'))
4970 def revert(ui, repo, *pats, **opts):
4972 def revert(ui, repo, *pats, **opts):
4971 """restore files to their checkout state
4973 """restore files to their checkout state
4972
4974
4973 .. note::
4975 .. note::
4974 To check out earlier revisions, you should use :hg:`update REV`.
4976 To check out earlier revisions, you should use :hg:`update REV`.
4975 To cancel an uncommitted merge (and lose your changes),
4977 To cancel an uncommitted merge (and lose your changes),
4976 use :hg:`update --clean .`.
4978 use :hg:`update --clean .`.
4977
4979
4978 With no revision specified, revert the specified files or directories
4980 With no revision specified, revert the specified files or directories
4979 to the contents they had in the parent of the working directory.
4981 to the contents they had in the parent of the working directory.
4980 This restores the contents of files to an unmodified
4982 This restores the contents of files to an unmodified
4981 state and unschedules adds, removes, copies, and renames. If the
4983 state and unschedules adds, removes, copies, and renames. If the
4982 working directory has two parents, you must explicitly specify a
4984 working directory has two parents, you must explicitly specify a
4983 revision.
4985 revision.
4984
4986
4985 Using the -r/--rev or -d/--date options, revert the given files or
4987 Using the -r/--rev or -d/--date options, revert the given files or
4986 directories to their states as of a specific revision. Because
4988 directories to their states as of a specific revision. Because
4987 revert does not change the working directory parents, this will
4989 revert does not change the working directory parents, this will
4988 cause these files to appear modified. This can be helpful to "back
4990 cause these files to appear modified. This can be helpful to "back
4989 out" some or all of an earlier change. See :hg:`backout` for a
4991 out" some or all of an earlier change. See :hg:`backout` for a
4990 related method.
4992 related method.
4991
4993
4992 Modified files are saved with a .orig suffix before reverting.
4994 Modified files are saved with a .orig suffix before reverting.
4993 To disable these backups, use --no-backup.
4995 To disable these backups, use --no-backup.
4994
4996
4995 See :hg:`help dates` for a list of formats valid for -d/--date.
4997 See :hg:`help dates` for a list of formats valid for -d/--date.
4996
4998
4997 Returns 0 on success.
4999 Returns 0 on success.
4998 """
5000 """
4999
5001
5000 if opts.get("date"):
5002 if opts.get("date"):
5001 if opts.get("rev"):
5003 if opts.get("rev"):
5002 raise util.Abort(_("you can't specify a revision and a date"))
5004 raise util.Abort(_("you can't specify a revision and a date"))
5003 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5005 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5004
5006
5005 parent, p2 = repo.dirstate.parents()
5007 parent, p2 = repo.dirstate.parents()
5006 if not opts.get('rev') and p2 != nullid:
5008 if not opts.get('rev') and p2 != nullid:
5007 # revert after merge is a trap for new users (issue2915)
5009 # revert after merge is a trap for new users (issue2915)
5008 raise util.Abort(_('uncommitted merge with no revision specified'),
5010 raise util.Abort(_('uncommitted merge with no revision specified'),
5009 hint=_('use "hg update" or see "hg help revert"'))
5011 hint=_('use "hg update" or see "hg help revert"'))
5010
5012
5011 ctx = scmutil.revsingle(repo, opts.get('rev'))
5013 ctx = scmutil.revsingle(repo, opts.get('rev'))
5012
5014
5013 if not pats and not opts.get('all'):
5015 if not pats and not opts.get('all'):
5014 msg = _("no files or directories specified")
5016 msg = _("no files or directories specified")
5015 if p2 != nullid:
5017 if p2 != nullid:
5016 hint = _("uncommitted merge, use --all to discard all changes,"
5018 hint = _("uncommitted merge, use --all to discard all changes,"
5017 " or 'hg update -C .' to abort the merge")
5019 " or 'hg update -C .' to abort the merge")
5018 raise util.Abort(msg, hint=hint)
5020 raise util.Abort(msg, hint=hint)
5019 dirty = util.any(repo.status())
5021 dirty = util.any(repo.status())
5020 node = ctx.node()
5022 node = ctx.node()
5021 if node != parent:
5023 if node != parent:
5022 if dirty:
5024 if dirty:
5023 hint = _("uncommitted changes, use --all to discard all"
5025 hint = _("uncommitted changes, use --all to discard all"
5024 " changes, or 'hg update %s' to update") % ctx.rev()
5026 " changes, or 'hg update %s' to update") % ctx.rev()
5025 else:
5027 else:
5026 hint = _("use --all to revert all files,"
5028 hint = _("use --all to revert all files,"
5027 " or 'hg update %s' to update") % ctx.rev()
5029 " or 'hg update %s' to update") % ctx.rev()
5028 elif dirty:
5030 elif dirty:
5029 hint = _("uncommitted changes, use --all to discard all changes")
5031 hint = _("uncommitted changes, use --all to discard all changes")
5030 else:
5032 else:
5031 hint = _("use --all to revert all files")
5033 hint = _("use --all to revert all files")
5032 raise util.Abort(msg, hint=hint)
5034 raise util.Abort(msg, hint=hint)
5033
5035
5034 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5036 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5035
5037
5036 @command('rollback', dryrunopts +
5038 @command('rollback', dryrunopts +
5037 [('f', 'force', False, _('ignore safety measures'))])
5039 [('f', 'force', False, _('ignore safety measures'))])
5038 def rollback(ui, repo, **opts):
5040 def rollback(ui, repo, **opts):
5039 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5041 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5040
5042
5041 Please use :hg:`commit --amend` instead of rollback to correct
5043 Please use :hg:`commit --amend` instead of rollback to correct
5042 mistakes in the last commit.
5044 mistakes in the last commit.
5043
5045
5044 This command should be used with care. There is only one level of
5046 This command should be used with care. There is only one level of
5045 rollback, and there is no way to undo a rollback. It will also
5047 rollback, and there is no way to undo a rollback. It will also
5046 restore the dirstate at the time of the last transaction, losing
5048 restore the dirstate at the time of the last transaction, losing
5047 any dirstate changes since that time. This command does not alter
5049 any dirstate changes since that time. This command does not alter
5048 the working directory.
5050 the working directory.
5049
5051
5050 Transactions are used to encapsulate the effects of all commands
5052 Transactions are used to encapsulate the effects of all commands
5051 that create new changesets or propagate existing changesets into a
5053 that create new changesets or propagate existing changesets into a
5052 repository.
5054 repository.
5053
5055
5054 .. container:: verbose
5056 .. container:: verbose
5055
5057
5056 For example, the following commands are transactional, and their
5058 For example, the following commands are transactional, and their
5057 effects can be rolled back:
5059 effects can be rolled back:
5058
5060
5059 - commit
5061 - commit
5060 - import
5062 - import
5061 - pull
5063 - pull
5062 - push (with this repository as the destination)
5064 - push (with this repository as the destination)
5063 - unbundle
5065 - unbundle
5064
5066
5065 To avoid permanent data loss, rollback will refuse to rollback a
5067 To avoid permanent data loss, rollback will refuse to rollback a
5066 commit transaction if it isn't checked out. Use --force to
5068 commit transaction if it isn't checked out. Use --force to
5067 override this protection.
5069 override this protection.
5068
5070
5069 This command is not intended for use on public repositories. Once
5071 This command is not intended for use on public repositories. Once
5070 changes are visible for pull by other users, rolling a transaction
5072 changes are visible for pull by other users, rolling a transaction
5071 back locally is ineffective (someone else may already have pulled
5073 back locally is ineffective (someone else may already have pulled
5072 the changes). Furthermore, a race is possible with readers of the
5074 the changes). Furthermore, a race is possible with readers of the
5073 repository; for example an in-progress pull from the repository
5075 repository; for example an in-progress pull from the repository
5074 may fail if a rollback is performed.
5076 may fail if a rollback is performed.
5075
5077
5076 Returns 0 on success, 1 if no rollback data is available.
5078 Returns 0 on success, 1 if no rollback data is available.
5077 """
5079 """
5078 return repo.rollback(dryrun=opts.get('dry_run'),
5080 return repo.rollback(dryrun=opts.get('dry_run'),
5079 force=opts.get('force'))
5081 force=opts.get('force'))
5080
5082
5081 @command('root', [])
5083 @command('root', [])
5082 def root(ui, repo):
5084 def root(ui, repo):
5083 """print the root (top) of the current working directory
5085 """print the root (top) of the current working directory
5084
5086
5085 Print the root directory of the current repository.
5087 Print the root directory of the current repository.
5086
5088
5087 Returns 0 on success.
5089 Returns 0 on success.
5088 """
5090 """
5089 ui.write(repo.root + "\n")
5091 ui.write(repo.root + "\n")
5090
5092
5091 @command('^serve',
5093 @command('^serve',
5092 [('A', 'accesslog', '', _('name of access log file to write to'),
5094 [('A', 'accesslog', '', _('name of access log file to write to'),
5093 _('FILE')),
5095 _('FILE')),
5094 ('d', 'daemon', None, _('run server in background')),
5096 ('d', 'daemon', None, _('run server in background')),
5095 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5097 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5096 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5098 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5097 # use string type, then we can check if something was passed
5099 # use string type, then we can check if something was passed
5098 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5100 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5099 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5101 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5100 _('ADDR')),
5102 _('ADDR')),
5101 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5103 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5102 _('PREFIX')),
5104 _('PREFIX')),
5103 ('n', 'name', '',
5105 ('n', 'name', '',
5104 _('name to show in web pages (default: working directory)'), _('NAME')),
5106 _('name to show in web pages (default: working directory)'), _('NAME')),
5105 ('', 'web-conf', '',
5107 ('', 'web-conf', '',
5106 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5108 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5107 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5109 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5108 _('FILE')),
5110 _('FILE')),
5109 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5111 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5110 ('', 'stdio', None, _('for remote clients')),
5112 ('', 'stdio', None, _('for remote clients')),
5111 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5113 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5112 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5114 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5113 ('', 'style', '', _('template style to use'), _('STYLE')),
5115 ('', 'style', '', _('template style to use'), _('STYLE')),
5114 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5116 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5115 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5117 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5116 _('[OPTION]...'))
5118 _('[OPTION]...'))
5117 def serve(ui, repo, **opts):
5119 def serve(ui, repo, **opts):
5118 """start stand-alone webserver
5120 """start stand-alone webserver
5119
5121
5120 Start a local HTTP repository browser and pull server. You can use
5122 Start a local HTTP repository browser and pull server. You can use
5121 this for ad-hoc sharing and browsing of repositories. It is
5123 this for ad-hoc sharing and browsing of repositories. It is
5122 recommended to use a real web server to serve a repository for
5124 recommended to use a real web server to serve a repository for
5123 longer periods of time.
5125 longer periods of time.
5124
5126
5125 Please note that the server does not implement access control.
5127 Please note that the server does not implement access control.
5126 This means that, by default, anybody can read from the server and
5128 This means that, by default, anybody can read from the server and
5127 nobody can write to it by default. Set the ``web.allow_push``
5129 nobody can write to it by default. Set the ``web.allow_push``
5128 option to ``*`` to allow everybody to push to the server. You
5130 option to ``*`` to allow everybody to push to the server. You
5129 should use a real web server if you need to authenticate users.
5131 should use a real web server if you need to authenticate users.
5130
5132
5131 By default, the server logs accesses to stdout and errors to
5133 By default, the server logs accesses to stdout and errors to
5132 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5134 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5133 files.
5135 files.
5134
5136
5135 To have the server choose a free port number to listen on, specify
5137 To have the server choose a free port number to listen on, specify
5136 a port number of 0; in this case, the server will print the port
5138 a port number of 0; in this case, the server will print the port
5137 number it uses.
5139 number it uses.
5138
5140
5139 Returns 0 on success.
5141 Returns 0 on success.
5140 """
5142 """
5141
5143
5142 if opts["stdio"] and opts["cmdserver"]:
5144 if opts["stdio"] and opts["cmdserver"]:
5143 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5145 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5144
5146
5145 def checkrepo():
5147 def checkrepo():
5146 if repo is None:
5148 if repo is None:
5147 raise error.RepoError(_("there is no Mercurial repository here"
5149 raise error.RepoError(_("there is no Mercurial repository here"
5148 " (.hg not found)"))
5150 " (.hg not found)"))
5149
5151
5150 if opts["stdio"]:
5152 if opts["stdio"]:
5151 checkrepo()
5153 checkrepo()
5152 s = sshserver.sshserver(ui, repo)
5154 s = sshserver.sshserver(ui, repo)
5153 s.serve_forever()
5155 s.serve_forever()
5154
5156
5155 if opts["cmdserver"]:
5157 if opts["cmdserver"]:
5156 checkrepo()
5158 checkrepo()
5157 s = commandserver.server(ui, repo, opts["cmdserver"])
5159 s = commandserver.server(ui, repo, opts["cmdserver"])
5158 return s.serve()
5160 return s.serve()
5159
5161
5160 # this way we can check if something was given in the command-line
5162 # this way we can check if something was given in the command-line
5161 if opts.get('port'):
5163 if opts.get('port'):
5162 opts['port'] = util.getport(opts.get('port'))
5164 opts['port'] = util.getport(opts.get('port'))
5163
5165
5164 baseui = repo and repo.baseui or ui
5166 baseui = repo and repo.baseui or ui
5165 optlist = ("name templates style address port prefix ipv6"
5167 optlist = ("name templates style address port prefix ipv6"
5166 " accesslog errorlog certificate encoding")
5168 " accesslog errorlog certificate encoding")
5167 for o in optlist.split():
5169 for o in optlist.split():
5168 val = opts.get(o, '')
5170 val = opts.get(o, '')
5169 if val in (None, ''): # should check against default options instead
5171 if val in (None, ''): # should check against default options instead
5170 continue
5172 continue
5171 baseui.setconfig("web", o, val)
5173 baseui.setconfig("web", o, val)
5172 if repo and repo.ui != baseui:
5174 if repo and repo.ui != baseui:
5173 repo.ui.setconfig("web", o, val)
5175 repo.ui.setconfig("web", o, val)
5174
5176
5175 o = opts.get('web_conf') or opts.get('webdir_conf')
5177 o = opts.get('web_conf') or opts.get('webdir_conf')
5176 if not o:
5178 if not o:
5177 if not repo:
5179 if not repo:
5178 raise error.RepoError(_("there is no Mercurial repository"
5180 raise error.RepoError(_("there is no Mercurial repository"
5179 " here (.hg not found)"))
5181 " here (.hg not found)"))
5180 o = repo
5182 o = repo
5181
5183
5182 app = hgweb.hgweb(o, baseui=baseui)
5184 app = hgweb.hgweb(o, baseui=baseui)
5183
5185
5184 class service(object):
5186 class service(object):
5185 def init(self):
5187 def init(self):
5186 util.setsignalhandler()
5188 util.setsignalhandler()
5187 self.httpd = hgweb_server.create_server(ui, app)
5189 self.httpd = hgweb_server.create_server(ui, app)
5188
5190
5189 if opts['port'] and not ui.verbose:
5191 if opts['port'] and not ui.verbose:
5190 return
5192 return
5191
5193
5192 if self.httpd.prefix:
5194 if self.httpd.prefix:
5193 prefix = self.httpd.prefix.strip('/') + '/'
5195 prefix = self.httpd.prefix.strip('/') + '/'
5194 else:
5196 else:
5195 prefix = ''
5197 prefix = ''
5196
5198
5197 port = ':%d' % self.httpd.port
5199 port = ':%d' % self.httpd.port
5198 if port == ':80':
5200 if port == ':80':
5199 port = ''
5201 port = ''
5200
5202
5201 bindaddr = self.httpd.addr
5203 bindaddr = self.httpd.addr
5202 if bindaddr == '0.0.0.0':
5204 if bindaddr == '0.0.0.0':
5203 bindaddr = '*'
5205 bindaddr = '*'
5204 elif ':' in bindaddr: # IPv6
5206 elif ':' in bindaddr: # IPv6
5205 bindaddr = '[%s]' % bindaddr
5207 bindaddr = '[%s]' % bindaddr
5206
5208
5207 fqaddr = self.httpd.fqaddr
5209 fqaddr = self.httpd.fqaddr
5208 if ':' in fqaddr:
5210 if ':' in fqaddr:
5209 fqaddr = '[%s]' % fqaddr
5211 fqaddr = '[%s]' % fqaddr
5210 if opts['port']:
5212 if opts['port']:
5211 write = ui.status
5213 write = ui.status
5212 else:
5214 else:
5213 write = ui.write
5215 write = ui.write
5214 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5215 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5216
5218
5217 def run(self):
5219 def run(self):
5218 self.httpd.serve_forever()
5220 self.httpd.serve_forever()
5219
5221
5220 service = service()
5222 service = service()
5221
5223
5222 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5224 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5223
5225
5224 @command('showconfig|debugconfig',
5226 @command('showconfig|debugconfig',
5225 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5227 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5226 _('[-u] [NAME]...'))
5228 _('[-u] [NAME]...'))
5227 def showconfig(ui, repo, *values, **opts):
5229 def showconfig(ui, repo, *values, **opts):
5228 """show combined config settings from all hgrc files
5230 """show combined config settings from all hgrc files
5229
5231
5230 With no arguments, print names and values of all config items.
5232 With no arguments, print names and values of all config items.
5231
5233
5232 With one argument of the form section.name, print just the value
5234 With one argument of the form section.name, print just the value
5233 of that config item.
5235 of that config item.
5234
5236
5235 With multiple arguments, print names and values of all config
5237 With multiple arguments, print names and values of all config
5236 items with matching section names.
5238 items with matching section names.
5237
5239
5238 With --debug, the source (filename and line number) is printed
5240 With --debug, the source (filename and line number) is printed
5239 for each config item.
5241 for each config item.
5240
5242
5241 Returns 0 on success.
5243 Returns 0 on success.
5242 """
5244 """
5243
5245
5244 for f in scmutil.rcpath():
5246 for f in scmutil.rcpath():
5245 ui.debug('read config from: %s\n' % f)
5247 ui.debug('read config from: %s\n' % f)
5246 untrusted = bool(opts.get('untrusted'))
5248 untrusted = bool(opts.get('untrusted'))
5247 if values:
5249 if values:
5248 sections = [v for v in values if '.' not in v]
5250 sections = [v for v in values if '.' not in v]
5249 items = [v for v in values if '.' in v]
5251 items = [v for v in values if '.' in v]
5250 if len(items) > 1 or items and sections:
5252 if len(items) > 1 or items and sections:
5251 raise util.Abort(_('only one config item permitted'))
5253 raise util.Abort(_('only one config item permitted'))
5252 for section, name, value in ui.walkconfig(untrusted=untrusted):
5254 for section, name, value in ui.walkconfig(untrusted=untrusted):
5253 value = str(value).replace('\n', '\\n')
5255 value = str(value).replace('\n', '\\n')
5254 sectname = section + '.' + name
5256 sectname = section + '.' + name
5255 if values:
5257 if values:
5256 for v in values:
5258 for v in values:
5257 if v == section:
5259 if v == section:
5258 ui.debug('%s: ' %
5260 ui.debug('%s: ' %
5259 ui.configsource(section, name, untrusted))
5261 ui.configsource(section, name, untrusted))
5260 ui.write('%s=%s\n' % (sectname, value))
5262 ui.write('%s=%s\n' % (sectname, value))
5261 elif v == sectname:
5263 elif v == sectname:
5262 ui.debug('%s: ' %
5264 ui.debug('%s: ' %
5263 ui.configsource(section, name, untrusted))
5265 ui.configsource(section, name, untrusted))
5264 ui.write(value, '\n')
5266 ui.write(value, '\n')
5265 else:
5267 else:
5266 ui.debug('%s: ' %
5268 ui.debug('%s: ' %
5267 ui.configsource(section, name, untrusted))
5269 ui.configsource(section, name, untrusted))
5268 ui.write('%s=%s\n' % (sectname, value))
5270 ui.write('%s=%s\n' % (sectname, value))
5269
5271
5270 @command('^status|st',
5272 @command('^status|st',
5271 [('A', 'all', None, _('show status of all files')),
5273 [('A', 'all', None, _('show status of all files')),
5272 ('m', 'modified', None, _('show only modified files')),
5274 ('m', 'modified', None, _('show only modified files')),
5273 ('a', 'added', None, _('show only added files')),
5275 ('a', 'added', None, _('show only added files')),
5274 ('r', 'removed', None, _('show only removed files')),
5276 ('r', 'removed', None, _('show only removed files')),
5275 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5277 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5276 ('c', 'clean', None, _('show only files without changes')),
5278 ('c', 'clean', None, _('show only files without changes')),
5277 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5279 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5278 ('i', 'ignored', None, _('show only ignored files')),
5280 ('i', 'ignored', None, _('show only ignored files')),
5279 ('n', 'no-status', None, _('hide status prefix')),
5281 ('n', 'no-status', None, _('hide status prefix')),
5280 ('C', 'copies', None, _('show source of copied files')),
5282 ('C', 'copies', None, _('show source of copied files')),
5281 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5283 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5282 ('', 'rev', [], _('show difference from revision'), _('REV')),
5284 ('', 'rev', [], _('show difference from revision'), _('REV')),
5283 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5285 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5284 ] + walkopts + subrepoopts,
5286 ] + walkopts + subrepoopts,
5285 _('[OPTION]... [FILE]...'))
5287 _('[OPTION]... [FILE]...'))
5286 def status(ui, repo, *pats, **opts):
5288 def status(ui, repo, *pats, **opts):
5287 """show changed files in the working directory
5289 """show changed files in the working directory
5288
5290
5289 Show status of files in the repository. If names are given, only
5291 Show status of files in the repository. If names are given, only
5290 files that match are shown. Files that are clean or ignored or
5292 files that match are shown. Files that are clean or ignored or
5291 the source of a copy/move operation, are not listed unless
5293 the source of a copy/move operation, are not listed unless
5292 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5294 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5293 Unless options described with "show only ..." are given, the
5295 Unless options described with "show only ..." are given, the
5294 options -mardu are used.
5296 options -mardu are used.
5295
5297
5296 Option -q/--quiet hides untracked (unknown and ignored) files
5298 Option -q/--quiet hides untracked (unknown and ignored) files
5297 unless explicitly requested with -u/--unknown or -i/--ignored.
5299 unless explicitly requested with -u/--unknown or -i/--ignored.
5298
5300
5299 .. note::
5301 .. note::
5300 status may appear to disagree with diff if permissions have
5302 status may appear to disagree with diff if permissions have
5301 changed or a merge has occurred. The standard diff format does
5303 changed or a merge has occurred. The standard diff format does
5302 not report permission changes and diff only reports changes
5304 not report permission changes and diff only reports changes
5303 relative to one merge parent.
5305 relative to one merge parent.
5304
5306
5305 If one revision is given, it is used as the base revision.
5307 If one revision is given, it is used as the base revision.
5306 If two revisions are given, the differences between them are
5308 If two revisions are given, the differences between them are
5307 shown. The --change option can also be used as a shortcut to list
5309 shown. The --change option can also be used as a shortcut to list
5308 the changed files of a revision from its first parent.
5310 the changed files of a revision from its first parent.
5309
5311
5310 The codes used to show the status of files are::
5312 The codes used to show the status of files are::
5311
5313
5312 M = modified
5314 M = modified
5313 A = added
5315 A = added
5314 R = removed
5316 R = removed
5315 C = clean
5317 C = clean
5316 ! = missing (deleted by non-hg command, but still tracked)
5318 ! = missing (deleted by non-hg command, but still tracked)
5317 ? = not tracked
5319 ? = not tracked
5318 I = ignored
5320 I = ignored
5319 = origin of the previous file listed as A (added)
5321 = origin of the previous file listed as A (added)
5320
5322
5321 .. container:: verbose
5323 .. container:: verbose
5322
5324
5323 Examples:
5325 Examples:
5324
5326
5325 - show changes in the working directory relative to a
5327 - show changes in the working directory relative to a
5326 changeset::
5328 changeset::
5327
5329
5328 hg status --rev 9353
5330 hg status --rev 9353
5329
5331
5330 - show all changes including copies in an existing changeset::
5332 - show all changes including copies in an existing changeset::
5331
5333
5332 hg status --copies --change 9353
5334 hg status --copies --change 9353
5333
5335
5334 - get a NUL separated list of added files, suitable for xargs::
5336 - get a NUL separated list of added files, suitable for xargs::
5335
5337
5336 hg status -an0
5338 hg status -an0
5337
5339
5338 Returns 0 on success.
5340 Returns 0 on success.
5339 """
5341 """
5340
5342
5341 revs = opts.get('rev')
5343 revs = opts.get('rev')
5342 change = opts.get('change')
5344 change = opts.get('change')
5343
5345
5344 if revs and change:
5346 if revs and change:
5345 msg = _('cannot specify --rev and --change at the same time')
5347 msg = _('cannot specify --rev and --change at the same time')
5346 raise util.Abort(msg)
5348 raise util.Abort(msg)
5347 elif change:
5349 elif change:
5348 node2 = scmutil.revsingle(repo, change, None).node()
5350 node2 = scmutil.revsingle(repo, change, None).node()
5349 node1 = repo[node2].p1().node()
5351 node1 = repo[node2].p1().node()
5350 else:
5352 else:
5351 node1, node2 = scmutil.revpair(repo, revs)
5353 node1, node2 = scmutil.revpair(repo, revs)
5352
5354
5353 cwd = (pats and repo.getcwd()) or ''
5355 cwd = (pats and repo.getcwd()) or ''
5354 end = opts.get('print0') and '\0' or '\n'
5356 end = opts.get('print0') and '\0' or '\n'
5355 copy = {}
5357 copy = {}
5356 states = 'modified added removed deleted unknown ignored clean'.split()
5358 states = 'modified added removed deleted unknown ignored clean'.split()
5357 show = [k for k in states if opts.get(k)]
5359 show = [k for k in states if opts.get(k)]
5358 if opts.get('all'):
5360 if opts.get('all'):
5359 show += ui.quiet and (states[:4] + ['clean']) or states
5361 show += ui.quiet and (states[:4] + ['clean']) or states
5360 if not show:
5362 if not show:
5361 show = ui.quiet and states[:4] or states[:5]
5363 show = ui.quiet and states[:4] or states[:5]
5362
5364
5363 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5365 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5364 'ignored' in show, 'clean' in show, 'unknown' in show,
5366 'ignored' in show, 'clean' in show, 'unknown' in show,
5365 opts.get('subrepos'))
5367 opts.get('subrepos'))
5366 changestates = zip(states, 'MAR!?IC', stat)
5368 changestates = zip(states, 'MAR!?IC', stat)
5367
5369
5368 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5370 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5369 copy = copies.pathcopies(repo[node1], repo[node2])
5371 copy = copies.pathcopies(repo[node1], repo[node2])
5370
5372
5371 fm = ui.formatter('status', opts)
5373 fm = ui.formatter('status', opts)
5372 fmt = '%s' + end
5374 fmt = '%s' + end
5373 showchar = not opts.get('no_status')
5375 showchar = not opts.get('no_status')
5374
5376
5375 for state, char, files in changestates:
5377 for state, char, files in changestates:
5376 if state in show:
5378 if state in show:
5377 label = 'status.' + state
5379 label = 'status.' + state
5378 for f in files:
5380 for f in files:
5379 fm.startitem()
5381 fm.startitem()
5380 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5382 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5381 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5383 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5382 if f in copy:
5384 if f in copy:
5383 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5385 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5384 label='status.copied')
5386 label='status.copied')
5385 fm.end()
5387 fm.end()
5386
5388
5387 @command('^summary|sum',
5389 @command('^summary|sum',
5388 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5390 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5389 def summary(ui, repo, **opts):
5391 def summary(ui, repo, **opts):
5390 """summarize working directory state
5392 """summarize working directory state
5391
5393
5392 This generates a brief summary of the working directory state,
5394 This generates a brief summary of the working directory state,
5393 including parents, branch, commit status, and available updates.
5395 including parents, branch, commit status, and available updates.
5394
5396
5395 With the --remote option, this will check the default paths for
5397 With the --remote option, this will check the default paths for
5396 incoming and outgoing changes. This can be time-consuming.
5398 incoming and outgoing changes. This can be time-consuming.
5397
5399
5398 Returns 0 on success.
5400 Returns 0 on success.
5399 """
5401 """
5400
5402
5401 ctx = repo[None]
5403 ctx = repo[None]
5402 parents = ctx.parents()
5404 parents = ctx.parents()
5403 pnode = parents[0].node()
5405 pnode = parents[0].node()
5404 marks = []
5406 marks = []
5405
5407
5406 for p in parents:
5408 for p in parents:
5407 # label with log.changeset (instead of log.parent) since this
5409 # label with log.changeset (instead of log.parent) since this
5408 # shows a working directory parent *changeset*:
5410 # shows a working directory parent *changeset*:
5409 # i18n: column positioning for "hg summary"
5411 # i18n: column positioning for "hg summary"
5410 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5412 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5411 label='log.changeset changeset.%s' % p.phasestr())
5413 label='log.changeset changeset.%s' % p.phasestr())
5412 ui.write(' '.join(p.tags()), label='log.tag')
5414 ui.write(' '.join(p.tags()), label='log.tag')
5413 if p.bookmarks():
5415 if p.bookmarks():
5414 marks.extend(p.bookmarks())
5416 marks.extend(p.bookmarks())
5415 if p.rev() == -1:
5417 if p.rev() == -1:
5416 if not len(repo):
5418 if not len(repo):
5417 ui.write(_(' (empty repository)'))
5419 ui.write(_(' (empty repository)'))
5418 else:
5420 else:
5419 ui.write(_(' (no revision checked out)'))
5421 ui.write(_(' (no revision checked out)'))
5420 ui.write('\n')
5422 ui.write('\n')
5421 if p.description():
5423 if p.description():
5422 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5424 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5423 label='log.summary')
5425 label='log.summary')
5424
5426
5425 branch = ctx.branch()
5427 branch = ctx.branch()
5426 bheads = repo.branchheads(branch)
5428 bheads = repo.branchheads(branch)
5427 # i18n: column positioning for "hg summary"
5429 # i18n: column positioning for "hg summary"
5428 m = _('branch: %s\n') % branch
5430 m = _('branch: %s\n') % branch
5429 if branch != 'default':
5431 if branch != 'default':
5430 ui.write(m, label='log.branch')
5432 ui.write(m, label='log.branch')
5431 else:
5433 else:
5432 ui.status(m, label='log.branch')
5434 ui.status(m, label='log.branch')
5433
5435
5434 if marks:
5436 if marks:
5435 current = repo._bookmarkcurrent
5437 current = repo._bookmarkcurrent
5436 # i18n: column positioning for "hg summary"
5438 # i18n: column positioning for "hg summary"
5437 ui.write(_('bookmarks:'), label='log.bookmark')
5439 ui.write(_('bookmarks:'), label='log.bookmark')
5438 if current is not None:
5440 if current is not None:
5439 if current in marks:
5441 if current in marks:
5440 ui.write(' *' + current, label='bookmarks.current')
5442 ui.write(' *' + current, label='bookmarks.current')
5441 marks.remove(current)
5443 marks.remove(current)
5442 else:
5444 else:
5443 ui.write(' [%s]' % current, label='bookmarks.current')
5445 ui.write(' [%s]' % current, label='bookmarks.current')
5444 for m in marks:
5446 for m in marks:
5445 ui.write(' ' + m, label='log.bookmark')
5447 ui.write(' ' + m, label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5448 ui.write('\n', label='log.bookmark')
5447
5449
5448 st = list(repo.status(unknown=True))[:6]
5450 st = list(repo.status(unknown=True))[:6]
5449
5451
5450 c = repo.dirstate.copies()
5452 c = repo.dirstate.copies()
5451 copied, renamed = [], []
5453 copied, renamed = [], []
5452 for d, s in c.iteritems():
5454 for d, s in c.iteritems():
5453 if s in st[2]:
5455 if s in st[2]:
5454 st[2].remove(s)
5456 st[2].remove(s)
5455 renamed.append(d)
5457 renamed.append(d)
5456 else:
5458 else:
5457 copied.append(d)
5459 copied.append(d)
5458 if d in st[1]:
5460 if d in st[1]:
5459 st[1].remove(d)
5461 st[1].remove(d)
5460 st.insert(3, renamed)
5462 st.insert(3, renamed)
5461 st.insert(4, copied)
5463 st.insert(4, copied)
5462
5464
5463 ms = mergemod.mergestate(repo)
5465 ms = mergemod.mergestate(repo)
5464 st.append([f for f in ms if ms[f] == 'u'])
5466 st.append([f for f in ms if ms[f] == 'u'])
5465
5467
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5467 st.append(subs)
5469 st.append(subs)
5468
5470
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5471 labels = [ui.label(_('%d modified'), 'status.modified'),
5470 ui.label(_('%d added'), 'status.added'),
5472 ui.label(_('%d added'), 'status.added'),
5471 ui.label(_('%d removed'), 'status.removed'),
5473 ui.label(_('%d removed'), 'status.removed'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5474 ui.label(_('%d renamed'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5475 ui.label(_('%d copied'), 'status.copied'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5476 ui.label(_('%d deleted'), 'status.deleted'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5477 ui.label(_('%d unknown'), 'status.unknown'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5478 ui.label(_('%d ignored'), 'status.ignored'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5479 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5478 ui.label(_('%d subrepos'), 'status.modified')]
5480 ui.label(_('%d subrepos'), 'status.modified')]
5479 t = []
5481 t = []
5480 for s, l in zip(st, labels):
5482 for s, l in zip(st, labels):
5481 if s:
5483 if s:
5482 t.append(l % len(s))
5484 t.append(l % len(s))
5483
5485
5484 t = ', '.join(t)
5486 t = ', '.join(t)
5485 cleanworkdir = False
5487 cleanworkdir = False
5486
5488
5487 if repo.vfs.exists('updatestate'):
5489 if repo.vfs.exists('updatestate'):
5488 t += _(' (interrupted update)')
5490 t += _(' (interrupted update)')
5489 elif len(parents) > 1:
5491 elif len(parents) > 1:
5490 t += _(' (merge)')
5492 t += _(' (merge)')
5491 elif branch != parents[0].branch():
5493 elif branch != parents[0].branch():
5492 t += _(' (new branch)')
5494 t += _(' (new branch)')
5493 elif (parents[0].closesbranch() and
5495 elif (parents[0].closesbranch() and
5494 pnode in repo.branchheads(branch, closed=True)):
5496 pnode in repo.branchheads(branch, closed=True)):
5495 t += _(' (head closed)')
5497 t += _(' (head closed)')
5496 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5498 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5497 t += _(' (clean)')
5499 t += _(' (clean)')
5498 cleanworkdir = True
5500 cleanworkdir = True
5499 elif pnode not in bheads:
5501 elif pnode not in bheads:
5500 t += _(' (new branch head)')
5502 t += _(' (new branch head)')
5501
5503
5502 if cleanworkdir:
5504 if cleanworkdir:
5503 # i18n: column positioning for "hg summary"
5505 # i18n: column positioning for "hg summary"
5504 ui.status(_('commit: %s\n') % t.strip())
5506 ui.status(_('commit: %s\n') % t.strip())
5505 else:
5507 else:
5506 # i18n: column positioning for "hg summary"
5508 # i18n: column positioning for "hg summary"
5507 ui.write(_('commit: %s\n') % t.strip())
5509 ui.write(_('commit: %s\n') % t.strip())
5508
5510
5509 # all ancestors of branch heads - all ancestors of parent = new csets
5511 # all ancestors of branch heads - all ancestors of parent = new csets
5510 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5512 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5511 bheads))
5513 bheads))
5512
5514
5513 if new == 0:
5515 if new == 0:
5514 # i18n: column positioning for "hg summary"
5516 # i18n: column positioning for "hg summary"
5515 ui.status(_('update: (current)\n'))
5517 ui.status(_('update: (current)\n'))
5516 elif pnode not in bheads:
5518 elif pnode not in bheads:
5517 # i18n: column positioning for "hg summary"
5519 # i18n: column positioning for "hg summary"
5518 ui.write(_('update: %d new changesets (update)\n') % new)
5520 ui.write(_('update: %d new changesets (update)\n') % new)
5519 else:
5521 else:
5520 # i18n: column positioning for "hg summary"
5522 # i18n: column positioning for "hg summary"
5521 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5523 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5522 (new, len(bheads)))
5524 (new, len(bheads)))
5523
5525
5524 cmdutil.summaryhooks(ui, repo)
5526 cmdutil.summaryhooks(ui, repo)
5525
5527
5526 if opts.get('remote'):
5528 if opts.get('remote'):
5527 t = []
5529 t = []
5528 source, branches = hg.parseurl(ui.expandpath('default'))
5530 source, branches = hg.parseurl(ui.expandpath('default'))
5529 sbranch = branches[0]
5531 sbranch = branches[0]
5530 other = hg.peer(repo, {}, source)
5532 other = hg.peer(repo, {}, source)
5531 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5533 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5532 if revs:
5534 if revs:
5533 revs = [other.lookup(rev) for rev in revs]
5535 revs = [other.lookup(rev) for rev in revs]
5534 ui.debug('comparing with %s\n' % util.hidepassword(source))
5536 ui.debug('comparing with %s\n' % util.hidepassword(source))
5535 repo.ui.pushbuffer()
5537 repo.ui.pushbuffer()
5536 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5538 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5537 _common, incoming, _rheads = commoninc
5539 _common, incoming, _rheads = commoninc
5538 repo.ui.popbuffer()
5540 repo.ui.popbuffer()
5539 if incoming:
5541 if incoming:
5540 t.append(_('1 or more incoming'))
5542 t.append(_('1 or more incoming'))
5541
5543
5542 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5544 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5543 dbranch = branches[0]
5545 dbranch = branches[0]
5544 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5546 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5545 if source != dest:
5547 if source != dest:
5546 other = hg.peer(repo, {}, dest)
5548 other = hg.peer(repo, {}, dest)
5547 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5549 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5548 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5550 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5549 commoninc = None
5551 commoninc = None
5550 if revs:
5552 if revs:
5551 revs = [repo.lookup(rev) for rev in revs]
5553 revs = [repo.lookup(rev) for rev in revs]
5552 repo.ui.pushbuffer()
5554 repo.ui.pushbuffer()
5553 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5555 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5554 commoninc=commoninc)
5556 commoninc=commoninc)
5555 repo.ui.popbuffer()
5557 repo.ui.popbuffer()
5556 o = outgoing.missing
5558 o = outgoing.missing
5557 if o:
5559 if o:
5558 t.append(_('%d outgoing') % len(o))
5560 t.append(_('%d outgoing') % len(o))
5559 if 'bookmarks' in other.listkeys('namespaces'):
5561 if 'bookmarks' in other.listkeys('namespaces'):
5560 lmarks = repo.listkeys('bookmarks')
5562 lmarks = repo.listkeys('bookmarks')
5561 rmarks = other.listkeys('bookmarks')
5563 rmarks = other.listkeys('bookmarks')
5562 diff = set(rmarks) - set(lmarks)
5564 diff = set(rmarks) - set(lmarks)
5563 if len(diff) > 0:
5565 if len(diff) > 0:
5564 t.append(_('%d incoming bookmarks') % len(diff))
5566 t.append(_('%d incoming bookmarks') % len(diff))
5565 diff = set(lmarks) - set(rmarks)
5567 diff = set(lmarks) - set(rmarks)
5566 if len(diff) > 0:
5568 if len(diff) > 0:
5567 t.append(_('%d outgoing bookmarks') % len(diff))
5569 t.append(_('%d outgoing bookmarks') % len(diff))
5568
5570
5569 if t:
5571 if t:
5570 # i18n: column positioning for "hg summary"
5572 # i18n: column positioning for "hg summary"
5571 ui.write(_('remote: %s\n') % (', '.join(t)))
5573 ui.write(_('remote: %s\n') % (', '.join(t)))
5572 else:
5574 else:
5573 # i18n: column positioning for "hg summary"
5575 # i18n: column positioning for "hg summary"
5574 ui.status(_('remote: (synced)\n'))
5576 ui.status(_('remote: (synced)\n'))
5575
5577
5576 @command('tag',
5578 @command('tag',
5577 [('f', 'force', None, _('force tag')),
5579 [('f', 'force', None, _('force tag')),
5578 ('l', 'local', None, _('make the tag local')),
5580 ('l', 'local', None, _('make the tag local')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5581 ('r', 'rev', '', _('revision to tag'), _('REV')),
5580 ('', 'remove', None, _('remove a tag')),
5582 ('', 'remove', None, _('remove a tag')),
5581 # -l/--local is already there, commitopts cannot be used
5583 # -l/--local is already there, commitopts cannot be used
5582 ('e', 'edit', None, _('edit commit message')),
5584 ('e', 'edit', None, _('edit commit message')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5585 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5584 ] + commitopts2,
5586 ] + commitopts2,
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5587 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5586 def tag(ui, repo, name1, *names, **opts):
5588 def tag(ui, repo, name1, *names, **opts):
5587 """add one or more tags for the current or given revision
5589 """add one or more tags for the current or given revision
5588
5590
5589 Name a particular revision using <name>.
5591 Name a particular revision using <name>.
5590
5592
5591 Tags are used to name particular revisions of the repository and are
5593 Tags are used to name particular revisions of the repository and are
5592 very useful to compare different revisions, to go back to significant
5594 very useful to compare different revisions, to go back to significant
5593 earlier versions or to mark branch points as releases, etc. Changing
5595 earlier versions or to mark branch points as releases, etc. Changing
5594 an existing tag is normally disallowed; use -f/--force to override.
5596 an existing tag is normally disallowed; use -f/--force to override.
5595
5597
5596 If no revision is given, the parent of the working directory is
5598 If no revision is given, the parent of the working directory is
5597 used.
5599 used.
5598
5600
5599 To facilitate version control, distribution, and merging of tags,
5601 To facilitate version control, distribution, and merging of tags,
5600 they are stored as a file named ".hgtags" which is managed similarly
5602 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
5603 to other project files and can be hand-edited if necessary. This
5602 also means that tagging creates a new commit. The file
5604 also means that tagging creates a new commit. The file
5603 ".hg/localtags" is used for local tags (not shared among
5605 ".hg/localtags" is used for local tags (not shared among
5604 repositories).
5606 repositories).
5605
5607
5606 Tag commits are usually made at the head of a branch. If the parent
5608 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
5609 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
5610 -f/--force to force the tag commit to be based on a non-head
5609 changeset.
5611 changeset.
5610
5612
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5613 See :hg:`help dates` for a list of formats valid for -d/--date.
5612
5614
5613 Since tag names have priority over branch names during revision
5615 Since tag names have priority over branch names during revision
5614 lookup, using an existing branch name as a tag name is discouraged.
5616 lookup, using an existing branch name as a tag name is discouraged.
5615
5617
5616 Returns 0 on success.
5618 Returns 0 on success.
5617 """
5619 """
5618 wlock = lock = None
5620 wlock = lock = None
5619 try:
5621 try:
5620 wlock = repo.wlock()
5622 wlock = repo.wlock()
5621 lock = repo.lock()
5623 lock = repo.lock()
5622 rev_ = "."
5624 rev_ = "."
5623 names = [t.strip() for t in (name1,) + names]
5625 names = [t.strip() for t in (name1,) + names]
5624 if len(names) != len(set(names)):
5626 if len(names) != len(set(names)):
5625 raise util.Abort(_('tag names must be unique'))
5627 raise util.Abort(_('tag names must be unique'))
5626 for n in names:
5628 for n in names:
5627 scmutil.checknewlabel(repo, n, 'tag')
5629 scmutil.checknewlabel(repo, n, 'tag')
5628 if not n:
5630 if not n:
5629 raise util.Abort(_('tag names cannot consist entirely of '
5631 raise util.Abort(_('tag names cannot consist entirely of '
5630 'whitespace'))
5632 'whitespace'))
5631 if opts.get('rev') and opts.get('remove'):
5633 if opts.get('rev') and opts.get('remove'):
5632 raise util.Abort(_("--rev and --remove are incompatible"))
5634 raise util.Abort(_("--rev and --remove are incompatible"))
5633 if opts.get('rev'):
5635 if opts.get('rev'):
5634 rev_ = opts['rev']
5636 rev_ = opts['rev']
5635 message = opts.get('message')
5637 message = opts.get('message')
5636 if opts.get('remove'):
5638 if opts.get('remove'):
5637 expectedtype = opts.get('local') and 'local' or 'global'
5639 expectedtype = opts.get('local') and 'local' or 'global'
5638 for n in names:
5640 for n in names:
5639 if not repo.tagtype(n):
5641 if not repo.tagtype(n):
5640 raise util.Abort(_("tag '%s' does not exist") % n)
5642 raise util.Abort(_("tag '%s' does not exist") % n)
5641 if repo.tagtype(n) != expectedtype:
5643 if repo.tagtype(n) != expectedtype:
5642 if expectedtype == 'global':
5644 if expectedtype == 'global':
5643 raise util.Abort(_("tag '%s' is not a global tag") % n)
5645 raise util.Abort(_("tag '%s' is not a global tag") % n)
5644 else:
5646 else:
5645 raise util.Abort(_("tag '%s' is not a local tag") % n)
5647 raise util.Abort(_("tag '%s' is not a local tag") % n)
5646 rev_ = nullid
5648 rev_ = nullid
5647 if not message:
5649 if not message:
5648 # we don't translate commit messages
5650 # we don't translate commit messages
5649 message = 'Removed tag %s' % ', '.join(names)
5651 message = 'Removed tag %s' % ', '.join(names)
5650 elif not opts.get('force'):
5652 elif not opts.get('force'):
5651 for n in names:
5653 for n in names:
5652 if n in repo.tags():
5654 if n in repo.tags():
5653 raise util.Abort(_("tag '%s' already exists "
5655 raise util.Abort(_("tag '%s' already exists "
5654 "(use -f to force)") % n)
5656 "(use -f to force)") % n)
5655 if not opts.get('local'):
5657 if not opts.get('local'):
5656 p1, p2 = repo.dirstate.parents()
5658 p1, p2 = repo.dirstate.parents()
5657 if p2 != nullid:
5659 if p2 != nullid:
5658 raise util.Abort(_('uncommitted merge'))
5660 raise util.Abort(_('uncommitted merge'))
5659 bheads = repo.branchheads()
5661 bheads = repo.branchheads()
5660 if not opts.get('force') and bheads and p1 not in bheads:
5662 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)'))
5663 raise util.Abort(_('not at a branch head (use -f to force)'))
5662 r = scmutil.revsingle(repo, rev_).node()
5664 r = scmutil.revsingle(repo, rev_).node()
5663
5665
5664 if not message:
5666 if not message:
5665 # we don't translate commit messages
5667 # we don't translate commit messages
5666 message = ('Added tag %s for changeset %s' %
5668 message = ('Added tag %s for changeset %s' %
5667 (', '.join(names), short(r)))
5669 (', '.join(names), short(r)))
5668
5670
5669 date = opts.get('date')
5671 date = opts.get('date')
5670 if date:
5672 if date:
5671 date = util.parsedate(date)
5673 date = util.parsedate(date)
5672
5674
5673 if opts.get('edit'):
5675 if opts.get('edit'):
5674 message = ui.edit(message, ui.username())
5676 message = ui.edit(message, ui.username())
5675
5677
5676 # don't allow tagging the null rev
5678 # don't allow tagging the null rev
5677 if (not opts.get('remove') and
5679 if (not opts.get('remove') and
5678 scmutil.revsingle(repo, rev_).rev() == nullrev):
5680 scmutil.revsingle(repo, rev_).rev() == nullrev):
5679 raise util.Abort(_("cannot tag null revision"))
5681 raise util.Abort(_("cannot tag null revision"))
5680
5682
5681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5683 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5682 finally:
5684 finally:
5683 release(lock, wlock)
5685 release(lock, wlock)
5684
5686
5685 @command('tags', [], '')
5687 @command('tags', [], '')
5686 def tags(ui, repo, **opts):
5688 def tags(ui, repo, **opts):
5687 """list repository tags
5689 """list repository tags
5688
5690
5689 This lists both regular and local tags. When the -v/--verbose
5691 This lists both regular and local tags. When the -v/--verbose
5690 switch is used, a third column "local" is printed for local tags.
5692 switch is used, a third column "local" is printed for local tags.
5691
5693
5692 Returns 0 on success.
5694 Returns 0 on success.
5693 """
5695 """
5694
5696
5695 fm = ui.formatter('tags', opts)
5697 fm = ui.formatter('tags', opts)
5696 hexfunc = ui.debugflag and hex or short
5698 hexfunc = ui.debugflag and hex or short
5697 tagtype = ""
5699 tagtype = ""
5698
5700
5699 for t, n in reversed(repo.tagslist()):
5701 for t, n in reversed(repo.tagslist()):
5700 hn = hexfunc(n)
5702 hn = hexfunc(n)
5701 label = 'tags.normal'
5703 label = 'tags.normal'
5702 tagtype = ''
5704 tagtype = ''
5703 if repo.tagtype(t) == 'local':
5705 if repo.tagtype(t) == 'local':
5704 label = 'tags.local'
5706 label = 'tags.local'
5705 tagtype = 'local'
5707 tagtype = 'local'
5706
5708
5707 fm.startitem()
5709 fm.startitem()
5708 fm.write('tag', '%s', t, label=label)
5710 fm.write('tag', '%s', t, label=label)
5709 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5711 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5710 fm.condwrite(not ui.quiet, 'rev id', fmt,
5712 fm.condwrite(not ui.quiet, 'rev id', fmt,
5711 repo.changelog.rev(n), hn, label=label)
5713 repo.changelog.rev(n), hn, label=label)
5712 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5714 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5713 tagtype, label=label)
5715 tagtype, label=label)
5714 fm.plain('\n')
5716 fm.plain('\n')
5715 fm.end()
5717 fm.end()
5716
5718
5717 @command('tip',
5719 @command('tip',
5718 [('p', 'patch', None, _('show patch')),
5720 [('p', 'patch', None, _('show patch')),
5719 ('g', 'git', None, _('use git extended diff format')),
5721 ('g', 'git', None, _('use git extended diff format')),
5720 ] + templateopts,
5722 ] + templateopts,
5721 _('[-p] [-g]'))
5723 _('[-p] [-g]'))
5722 def tip(ui, repo, **opts):
5724 def tip(ui, repo, **opts):
5723 """show the tip revision (DEPRECATED)
5725 """show the tip revision (DEPRECATED)
5724
5726
5725 The tip revision (usually just called the tip) is the changeset
5727 The tip revision (usually just called the tip) is the changeset
5726 most recently added to the repository (and therefore the most
5728 most recently added to the repository (and therefore the most
5727 recently changed head).
5729 recently changed head).
5728
5730
5729 If you have just made a commit, that commit will be the tip. If
5731 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
5732 you have just pulled changes from another repository, the tip of
5731 that repository becomes the current tip. The "tip" tag is special
5733 that repository becomes the current tip. The "tip" tag is special
5732 and cannot be renamed or assigned to a different changeset.
5734 and cannot be renamed or assigned to a different changeset.
5733
5735
5734 This command is deprecated, please use :hg:`heads` instead.
5736 This command is deprecated, please use :hg:`heads` instead.
5735
5737
5736 Returns 0 on success.
5738 Returns 0 on success.
5737 """
5739 """
5738 displayer = cmdutil.show_changeset(ui, repo, opts)
5740 displayer = cmdutil.show_changeset(ui, repo, opts)
5739 displayer.show(repo['tip'])
5741 displayer.show(repo['tip'])
5740 displayer.close()
5742 displayer.close()
5741
5743
5742 @command('unbundle',
5744 @command('unbundle',
5743 [('u', 'update', None,
5745 [('u', 'update', None,
5744 _('update to new branch head if changesets were unbundled'))],
5746 _('update to new branch head if changesets were unbundled'))],
5745 _('[-u] FILE...'))
5747 _('[-u] FILE...'))
5746 def unbundle(ui, repo, fname1, *fnames, **opts):
5748 def unbundle(ui, repo, fname1, *fnames, **opts):
5747 """apply one or more changegroup files
5749 """apply one or more changegroup files
5748
5750
5749 Apply one or more compressed changegroup files generated by the
5751 Apply one or more compressed changegroup files generated by the
5750 bundle command.
5752 bundle command.
5751
5753
5752 Returns 0 on success, 1 if an update has unresolved files.
5754 Returns 0 on success, 1 if an update has unresolved files.
5753 """
5755 """
5754 fnames = (fname1,) + fnames
5756 fnames = (fname1,) + fnames
5755
5757
5756 lock = repo.lock()
5758 lock = repo.lock()
5757 wc = repo['.']
5759 wc = repo['.']
5758 try:
5760 try:
5759 for fname in fnames:
5761 for fname in fnames:
5760 f = hg.openpath(ui, fname)
5762 f = hg.openpath(ui, fname)
5761 gen = changegroup.readbundle(f, fname)
5763 gen = changegroup.readbundle(f, fname)
5762 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5764 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5763 finally:
5765 finally:
5764 lock.release()
5766 lock.release()
5765 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5767 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5766 return postincoming(ui, repo, modheads, opts.get('update'), None)
5768 return postincoming(ui, repo, modheads, opts.get('update'), None)
5767
5769
5768 @command('^update|up|checkout|co',
5770 @command('^update|up|checkout|co',
5769 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5771 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5770 ('c', 'check', None,
5772 ('c', 'check', None,
5771 _('update across branches if no uncommitted changes')),
5773 _('update across branches if no uncommitted changes')),
5772 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5774 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5773 ('r', 'rev', '', _('revision'), _('REV'))],
5775 ('r', 'rev', '', _('revision'), _('REV'))],
5774 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5776 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5775 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5777 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5776 """update working directory (or switch revisions)
5778 """update working directory (or switch revisions)
5777
5779
5778 Update the repository's working directory to the specified
5780 Update the repository's working directory to the specified
5779 changeset. If no changeset is specified, update to the tip of the
5781 changeset. If no changeset is specified, update to the tip of the
5780 current named branch and move the current bookmark (see :hg:`help
5782 current named branch and move the current bookmark (see :hg:`help
5781 bookmarks`).
5783 bookmarks`).
5782
5784
5783 Update sets the working directory's parent revision to the specified
5785 Update sets the working directory's parent revision to the specified
5784 changeset (see :hg:`help parents`).
5786 changeset (see :hg:`help parents`).
5785
5787
5786 If the changeset is not a descendant or ancestor of the working
5788 If the changeset is not a descendant or ancestor of the working
5787 directory's parent, the update is aborted. With the -c/--check
5789 directory's parent, the update is aborted. With the -c/--check
5788 option, the working directory is checked for uncommitted changes; if
5790 option, the working directory is checked for uncommitted changes; if
5789 none are found, the working directory is updated to the specified
5791 none are found, the working directory is updated to the specified
5790 changeset.
5792 changeset.
5791
5793
5792 .. container:: verbose
5794 .. container:: verbose
5793
5795
5794 The following rules apply when the working directory contains
5796 The following rules apply when the working directory contains
5795 uncommitted changes:
5797 uncommitted changes:
5796
5798
5797 1. If neither -c/--check nor -C/--clean is specified, and if
5799 1. If neither -c/--check nor -C/--clean is specified, and if
5798 the requested changeset is an ancestor or descendant of
5800 the requested changeset is an ancestor or descendant of
5799 the working directory's parent, the uncommitted changes
5801 the working directory's parent, the uncommitted changes
5800 are merged into the requested changeset and the merged
5802 are merged into the requested changeset and the merged
5801 result is left uncommitted. If the requested changeset is
5803 result is left uncommitted. If the requested changeset is
5802 not an ancestor or descendant (that is, it is on another
5804 not an ancestor or descendant (that is, it is on another
5803 branch), the update is aborted and the uncommitted changes
5805 branch), the update is aborted and the uncommitted changes
5804 are preserved.
5806 are preserved.
5805
5807
5806 2. With the -c/--check option, the update is aborted and the
5808 2. With the -c/--check option, the update is aborted and the
5807 uncommitted changes are preserved.
5809 uncommitted changes are preserved.
5808
5810
5809 3. With the -C/--clean option, uncommitted changes are discarded and
5811 3. With the -C/--clean option, uncommitted changes are discarded and
5810 the working directory is updated to the requested changeset.
5812 the working directory is updated to the requested changeset.
5811
5813
5812 To cancel an uncommitted merge (and lose your changes), use
5814 To cancel an uncommitted merge (and lose your changes), use
5813 :hg:`update --clean .`.
5815 :hg:`update --clean .`.
5814
5816
5815 Use null as the changeset to remove the working directory (like
5817 Use null as the changeset to remove the working directory (like
5816 :hg:`clone -U`).
5818 :hg:`clone -U`).
5817
5819
5818 If you want to revert just one file to an older revision, use
5820 If you want to revert just one file to an older revision, use
5819 :hg:`revert [-r REV] NAME`.
5821 :hg:`revert [-r REV] NAME`.
5820
5822
5821 See :hg:`help dates` for a list of formats valid for -d/--date.
5823 See :hg:`help dates` for a list of formats valid for -d/--date.
5822
5824
5823 Returns 0 on success, 1 if there are unresolved files.
5825 Returns 0 on success, 1 if there are unresolved files.
5824 """
5826 """
5825 if rev and node:
5827 if rev and node:
5826 raise util.Abort(_("please specify just one revision"))
5828 raise util.Abort(_("please specify just one revision"))
5827
5829
5828 if rev is None or rev == '':
5830 if rev is None or rev == '':
5829 rev = node
5831 rev = node
5830
5832
5831 cmdutil.clearunfinished(repo)
5833 cmdutil.clearunfinished(repo)
5832
5834
5833 # with no argument, we also move the current bookmark, if any
5835 # with no argument, we also move the current bookmark, if any
5834 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5836 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5835
5837
5836 # if we defined a bookmark, we have to remember the original bookmark name
5838 # if we defined a bookmark, we have to remember the original bookmark name
5837 brev = rev
5839 brev = rev
5838 rev = scmutil.revsingle(repo, rev, rev).rev()
5840 rev = scmutil.revsingle(repo, rev, rev).rev()
5839
5841
5840 if check and clean:
5842 if check and clean:
5841 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5843 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5842
5844
5843 if date:
5845 if date:
5844 if rev is not None:
5846 if rev is not None:
5845 raise util.Abort(_("you can't specify a revision and a date"))
5847 raise util.Abort(_("you can't specify a revision and a date"))
5846 rev = cmdutil.finddate(ui, repo, date)
5848 rev = cmdutil.finddate(ui, repo, date)
5847
5849
5848 if check:
5850 if check:
5849 c = repo[None]
5851 c = repo[None]
5850 if c.dirty(merge=False, branch=False, missing=True):
5852 if c.dirty(merge=False, branch=False, missing=True):
5851 raise util.Abort(_("uncommitted local changes"))
5853 raise util.Abort(_("uncommitted local changes"))
5852 if rev is None:
5854 if rev is None:
5853 rev = repo[repo[None].branch()].rev()
5855 rev = repo[repo[None].branch()].rev()
5854 mergemod._checkunknown(repo, repo[None], repo[rev])
5856 mergemod._checkunknown(repo, repo[None], repo[rev])
5855
5857
5856 if clean:
5858 if clean:
5857 ret = hg.clean(repo, rev)
5859 ret = hg.clean(repo, rev)
5858 else:
5860 else:
5859 ret = hg.update(repo, rev)
5861 ret = hg.update(repo, rev)
5860
5862
5861 if not ret and movemarkfrom:
5863 if not ret and movemarkfrom:
5862 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5864 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5863 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5865 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5864 elif brev in repo._bookmarks:
5866 elif brev in repo._bookmarks:
5865 bookmarks.setcurrent(repo, brev)
5867 bookmarks.setcurrent(repo, brev)
5866 elif brev:
5868 elif brev:
5867 bookmarks.unsetcurrent(repo)
5869 bookmarks.unsetcurrent(repo)
5868
5870
5869 return ret
5871 return ret
5870
5872
5871 @command('verify', [])
5873 @command('verify', [])
5872 def verify(ui, repo):
5874 def verify(ui, repo):
5873 """verify the integrity of the repository
5875 """verify the integrity of the repository
5874
5876
5875 Verify the integrity of the current repository.
5877 Verify the integrity of the current repository.
5876
5878
5877 This will perform an extensive check of the repository's
5879 This will perform an extensive check of the repository's
5878 integrity, validating the hashes and checksums of each entry in
5880 integrity, validating the hashes and checksums of each entry in
5879 the changelog, manifest, and tracked files, as well as the
5881 the changelog, manifest, and tracked files, as well as the
5880 integrity of their crosslinks and indices.
5882 integrity of their crosslinks and indices.
5881
5883
5882 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5884 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5883 for more information about recovery from corruption of the
5885 for more information about recovery from corruption of the
5884 repository.
5886 repository.
5885
5887
5886 Returns 0 on success, 1 if errors are encountered.
5888 Returns 0 on success, 1 if errors are encountered.
5887 """
5889 """
5888 return hg.verify(repo)
5890 return hg.verify(repo)
5889
5891
5890 @command('version', [])
5892 @command('version', [])
5891 def version_(ui):
5893 def version_(ui):
5892 """output version and copyright information"""
5894 """output version and copyright information"""
5893 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5895 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5894 % util.version())
5896 % util.version())
5895 ui.status(_(
5897 ui.status(_(
5896 "(see http://mercurial.selenic.com for more information)\n"
5898 "(see http://mercurial.selenic.com for more information)\n"
5897 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5899 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5898 "This is free software; see the source for copying conditions. "
5900 "This is free software; see the source for copying conditions. "
5899 "There is NO\nwarranty; "
5901 "There is NO\nwarranty; "
5900 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5902 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5901 ))
5903 ))
5902
5904
5903 norepo = ("clone init version help debugcommands debugcomplete"
5905 norepo = ("clone init version help debugcommands debugcomplete"
5904 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5906 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5905 " debugknown debuggetbundle debugbundle")
5907 " debugknown debuggetbundle debugbundle")
5906 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5908 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5907 " debugdata debugindex debugindexdot debugrevlog")
5909 " debugdata debugindex debugindexdot debugrevlog")
5908 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5910 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5909 " remove resolve status debugwalk")
5911 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now