##// END OF EJS Templates
Use more note admonitions in help texts
Christian Ebert -
r12390:aff4afdc default
parent child Browse files
Show More
@@ -1,578 +1,579 b''
1 # keyword.py - $Keyword$ expansion for Mercurial
1 # keyword.py - $Keyword$ expansion for Mercurial
2 #
2 #
3 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
3 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
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 # $Id$
8 # $Id$
9 #
9 #
10 # Keyword expansion hack against the grain of a DSCM
10 # Keyword expansion hack against the grain of a DSCM
11 #
11 #
12 # There are many good reasons why this is not needed in a distributed
12 # There are many good reasons why this is not needed in a distributed
13 # SCM, still it may be useful in very small projects based on single
13 # SCM, still it may be useful in very small projects based on single
14 # files (like LaTeX packages), that are mostly addressed to an
14 # files (like LaTeX packages), that are mostly addressed to an
15 # audience not running a version control system.
15 # audience not running a version control system.
16 #
16 #
17 # For in-depth discussion refer to
17 # For in-depth discussion refer to
18 # <http://mercurial.selenic.com/wiki/KeywordPlan>.
18 # <http://mercurial.selenic.com/wiki/KeywordPlan>.
19 #
19 #
20 # Keyword expansion is based on Mercurial's changeset template mappings.
20 # Keyword expansion is based on Mercurial's changeset template mappings.
21 #
21 #
22 # Binary files are not touched.
22 # Binary files are not touched.
23 #
23 #
24 # Files to act upon/ignore are specified in the [keyword] section.
24 # Files to act upon/ignore are specified in the [keyword] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
25 # Customized keyword template mappings in the [keywordmaps] section.
26 #
26 #
27 # Run "hg help keyword" and "hg kwdemo" to get info on configuration.
27 # Run "hg help keyword" and "hg kwdemo" to get info on configuration.
28
28
29 '''expand keywords in tracked files
29 '''expand keywords in tracked files
30
30
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
31 This extension expands RCS/CVS-like or self-customized $Keywords$ in
32 tracked text files selected by your configuration.
32 tracked text files selected by your configuration.
33
33
34 Keywords are only expanded in local repositories and not stored in the
34 Keywords are only expanded in local repositories and not stored in the
35 change history. The mechanism can be regarded as a convenience for the
35 change history. The mechanism can be regarded as a convenience for the
36 current user or for archive distribution.
36 current user or for archive distribution.
37
37
38 Keywords expand to the changeset data pertaining to the latest change
38 Keywords expand to the changeset data pertaining to the latest change
39 relative to the working directory parent of each file.
39 relative to the working directory parent of each file.
40
40
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
41 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
42 sections of hgrc files.
42 sections of hgrc files.
43
43
44 Example::
44 Example::
45
45
46 [keyword]
46 [keyword]
47 # expand keywords in every python file except those matching "x*"
47 # expand keywords in every python file except those matching "x*"
48 **.py =
48 **.py =
49 x* = ignore
49 x* = ignore
50
50
51 [keywordset]
51 [keywordset]
52 # prefer svn- over cvs-like default keywordmaps
52 # prefer svn- over cvs-like default keywordmaps
53 svn = True
53 svn = True
54
54
55 NOTE: the more specific you are in your filename patterns the less you
55 .. note::
56 lose speed in huge repositories.
56 The more specific you are in your filename patterns the less you
57 lose speed in huge repositories.
57
58
58 For [keywordmaps] template mapping and expansion demonstration and
59 For [keywordmaps] template mapping and expansion demonstration and
59 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
60 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
60 available templates and filters.
61 available templates and filters.
61
62
62 Three additional date template filters are provided::
63 Three additional date template filters are provided::
63
64
64 utcdate "2006/09/18 15:13:13"
65 utcdate "2006/09/18 15:13:13"
65 svnutcdate "2006-09-18 15:13:13Z"
66 svnutcdate "2006-09-18 15:13:13Z"
66 svnisodate "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
67 svnisodate "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
67
68
68 The default template mappings (view with :hg:`kwdemo -d`) can be
69 The default template mappings (view with :hg:`kwdemo -d`) can be
69 replaced with customized keywords and templates. Again, run
70 replaced with customized keywords and templates. Again, run
70 :hg:`kwdemo` to control the results of your config changes.
71 :hg:`kwdemo` to control the results of your config changes.
71
72
72 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
73 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
73 the risk of inadvertently storing expanded keywords in the change
74 the risk of inadvertently storing expanded keywords in the change
74 history.
75 history.
75
76
76 To force expansion after enabling it, or a configuration change, run
77 To force expansion after enabling it, or a configuration change, run
77 :hg:`kwexpand`.
78 :hg:`kwexpand`.
78
79
79 Expansions spanning more than one line and incremental expansions,
80 Expansions spanning more than one line and incremental expansions,
80 like CVS' $Log$, are not supported. A keyword template map "Log =
81 like CVS' $Log$, are not supported. A keyword template map "Log =
81 {desc}" expands to the first line of the changeset description.
82 {desc}" expands to the first line of the changeset description.
82 '''
83 '''
83
84
84 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
85 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
85 from mercurial import patch, localrepo, templater, templatefilters, util, match
86 from mercurial import patch, localrepo, templater, templatefilters, util, match
86 from mercurial.hgweb import webcommands
87 from mercurial.hgweb import webcommands
87 from mercurial.i18n import _
88 from mercurial.i18n import _
88 import re, shutil, tempfile
89 import re, shutil, tempfile
89
90
90 commands.optionalrepo += ' kwdemo'
91 commands.optionalrepo += ' kwdemo'
91
92
92 # hg commands that do not act on keywords
93 # hg commands that do not act on keywords
93 nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
94 nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
94 ' log outgoing push rename rollback tip verify'
95 ' log outgoing push rename rollback tip verify'
95 ' convert email glog')
96 ' convert email glog')
96
97
97 # hg commands that trigger expansion only when writing to working dir,
98 # hg commands that trigger expansion only when writing to working dir,
98 # not when reading filelog, and unexpand when reading from working dir
99 # not when reading filelog, and unexpand when reading from working dir
99 restricted = 'merge record qrecord resolve transplant'
100 restricted = 'merge record qrecord resolve transplant'
100
101
101 # commands using dorecord
102 # commands using dorecord
102 recordcommands = 'record qrecord'
103 recordcommands = 'record qrecord'
103 # names of extensions using dorecord
104 # names of extensions using dorecord
104 recordextensions = 'record'
105 recordextensions = 'record'
105
106
106 # date like in cvs' $Date
107 # date like in cvs' $Date
107 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
108 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
108 # date like in svn's $Date
109 # date like in svn's $Date
109 svnisodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
110 svnisodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
110 # date like in svn's $Id
111 # date like in svn's $Id
111 svnutcdate = lambda x: util.datestr((x[0], 0), '%Y-%m-%d %H:%M:%SZ')
112 svnutcdate = lambda x: util.datestr((x[0], 0), '%Y-%m-%d %H:%M:%SZ')
112
113
113 # make keyword tools accessible
114 # make keyword tools accessible
114 kwtools = {'templater': None, 'hgcmd': ''}
115 kwtools = {'templater': None, 'hgcmd': ''}
115
116
116
117
117 def _defaultkwmaps(ui):
118 def _defaultkwmaps(ui):
118 '''Returns default keywordmaps according to keywordset configuration.'''
119 '''Returns default keywordmaps according to keywordset configuration.'''
119 templates = {
120 templates = {
120 'Revision': '{node|short}',
121 'Revision': '{node|short}',
121 'Author': '{author|user}',
122 'Author': '{author|user}',
122 }
123 }
123 kwsets = ({
124 kwsets = ({
124 'Date': '{date|utcdate}',
125 'Date': '{date|utcdate}',
125 'RCSfile': '{file|basename},v',
126 'RCSfile': '{file|basename},v',
126 'RCSFile': '{file|basename},v', # kept for backwards compatibility
127 'RCSFile': '{file|basename},v', # kept for backwards compatibility
127 # with hg-keyword
128 # with hg-keyword
128 'Source': '{root}/{file},v',
129 'Source': '{root}/{file},v',
129 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
130 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
130 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
131 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
131 }, {
132 }, {
132 'Date': '{date|svnisodate}',
133 'Date': '{date|svnisodate}',
133 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
134 'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
134 'LastChangedRevision': '{node|short}',
135 'LastChangedRevision': '{node|short}',
135 'LastChangedBy': '{author|user}',
136 'LastChangedBy': '{author|user}',
136 'LastChangedDate': '{date|svnisodate}',
137 'LastChangedDate': '{date|svnisodate}',
137 })
138 })
138 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
139 templates.update(kwsets[ui.configbool('keywordset', 'svn')])
139 return templates
140 return templates
140
141
141 class kwtemplater(object):
142 class kwtemplater(object):
142 '''
143 '''
143 Sets up keyword templates, corresponding keyword regex, and
144 Sets up keyword templates, corresponding keyword regex, and
144 provides keyword substitution functions.
145 provides keyword substitution functions.
145 '''
146 '''
146
147
147 def __init__(self, ui, repo, inc, exc):
148 def __init__(self, ui, repo, inc, exc):
148 self.ui = ui
149 self.ui = ui
149 self.repo = repo
150 self.repo = repo
150 self.match = match.match(repo.root, '', [], inc, exc)
151 self.match = match.match(repo.root, '', [], inc, exc)
151 self.restrict = kwtools['hgcmd'] in restricted.split()
152 self.restrict = kwtools['hgcmd'] in restricted.split()
152 self.record = kwtools['hgcmd'] in recordcommands.split()
153 self.record = kwtools['hgcmd'] in recordcommands.split()
153
154
154 kwmaps = self.ui.configitems('keywordmaps')
155 kwmaps = self.ui.configitems('keywordmaps')
155 if kwmaps: # override default templates
156 if kwmaps: # override default templates
156 self.templates = dict((k, templater.parsestring(v, False))
157 self.templates = dict((k, templater.parsestring(v, False))
157 for k, v in kwmaps)
158 for k, v in kwmaps)
158 else:
159 else:
159 self.templates = _defaultkwmaps(self.ui)
160 self.templates = _defaultkwmaps(self.ui)
160 escaped = map(re.escape, self.templates.keys())
161 escaped = map(re.escape, self.templates.keys())
161 kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
162 kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
162 self.re_kw = re.compile(kwpat)
163 self.re_kw = re.compile(kwpat)
163
164
164 templatefilters.filters.update({'utcdate': utcdate,
165 templatefilters.filters.update({'utcdate': utcdate,
165 'svnisodate': svnisodate,
166 'svnisodate': svnisodate,
166 'svnutcdate': svnutcdate})
167 'svnutcdate': svnutcdate})
167
168
168 def substitute(self, data, path, ctx, subfunc):
169 def substitute(self, data, path, ctx, subfunc):
169 '''Replaces keywords in data with expanded template.'''
170 '''Replaces keywords in data with expanded template.'''
170 def kwsub(mobj):
171 def kwsub(mobj):
171 kw = mobj.group(1)
172 kw = mobj.group(1)
172 ct = cmdutil.changeset_templater(self.ui, self.repo,
173 ct = cmdutil.changeset_templater(self.ui, self.repo,
173 False, None, '', False)
174 False, None, '', False)
174 ct.use_template(self.templates[kw])
175 ct.use_template(self.templates[kw])
175 self.ui.pushbuffer()
176 self.ui.pushbuffer()
176 ct.show(ctx, root=self.repo.root, file=path)
177 ct.show(ctx, root=self.repo.root, file=path)
177 ekw = templatefilters.firstline(self.ui.popbuffer())
178 ekw = templatefilters.firstline(self.ui.popbuffer())
178 return '$%s: %s $' % (kw, ekw)
179 return '$%s: %s $' % (kw, ekw)
179 return subfunc(kwsub, data)
180 return subfunc(kwsub, data)
180
181
181 def expand(self, path, node, data):
182 def expand(self, path, node, data):
182 '''Returns data with keywords expanded.'''
183 '''Returns data with keywords expanded.'''
183 if not self.restrict and self.match(path) and not util.binary(data):
184 if not self.restrict and self.match(path) and not util.binary(data):
184 ctx = self.repo.filectx(path, fileid=node).changectx()
185 ctx = self.repo.filectx(path, fileid=node).changectx()
185 return self.substitute(data, path, ctx, self.re_kw.sub)
186 return self.substitute(data, path, ctx, self.re_kw.sub)
186 return data
187 return data
187
188
188 def iskwfile(self, path, flagfunc):
189 def iskwfile(self, path, flagfunc):
189 '''Returns true if path matches [keyword] pattern
190 '''Returns true if path matches [keyword] pattern
190 and is not a symbolic link.
191 and is not a symbolic link.
191 Caveat: localrepository._link fails on Windows.'''
192 Caveat: localrepository._link fails on Windows.'''
192 return self.match(path) and not 'l' in flagfunc(path)
193 return self.match(path) and not 'l' in flagfunc(path)
193
194
194 def overwrite(self, ctx, candidates, iswctx, expand):
195 def overwrite(self, ctx, candidates, iswctx, expand):
195 '''Overwrites selected files expanding/shrinking keywords.'''
196 '''Overwrites selected files expanding/shrinking keywords.'''
196 if self.record:
197 if self.record:
197 candidates = [f for f in ctx.files() if f in ctx]
198 candidates = [f for f in ctx.files() if f in ctx]
198 candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
199 candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
199 if candidates:
200 if candidates:
200 self.restrict = True # do not expand when reading
201 self.restrict = True # do not expand when reading
201 mf = ctx.manifest()
202 mf = ctx.manifest()
202 msg = (expand and _('overwriting %s expanding keywords\n')
203 msg = (expand and _('overwriting %s expanding keywords\n')
203 or _('overwriting %s shrinking keywords\n'))
204 or _('overwriting %s shrinking keywords\n'))
204 for f in candidates:
205 for f in candidates:
205 if not self.record:
206 if not self.record:
206 data = self.repo.file(f).read(mf[f])
207 data = self.repo.file(f).read(mf[f])
207 else:
208 else:
208 data = self.repo.wread(f)
209 data = self.repo.wread(f)
209 if util.binary(data):
210 if util.binary(data):
210 continue
211 continue
211 if expand:
212 if expand:
212 if iswctx:
213 if iswctx:
213 ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
214 ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
214 data, found = self.substitute(data, f, ctx,
215 data, found = self.substitute(data, f, ctx,
215 self.re_kw.subn)
216 self.re_kw.subn)
216 else:
217 else:
217 found = self.re_kw.search(data)
218 found = self.re_kw.search(data)
218 if found:
219 if found:
219 self.ui.note(msg % f)
220 self.ui.note(msg % f)
220 self.repo.wwrite(f, data, mf.flags(f))
221 self.repo.wwrite(f, data, mf.flags(f))
221 if iswctx:
222 if iswctx:
222 self.repo.dirstate.normal(f)
223 self.repo.dirstate.normal(f)
223 elif self.record:
224 elif self.record:
224 self.repo.dirstate.normallookup(f)
225 self.repo.dirstate.normallookup(f)
225 self.restrict = False
226 self.restrict = False
226
227
227 def shrinktext(self, text):
228 def shrinktext(self, text):
228 '''Unconditionally removes all keyword substitutions from text.'''
229 '''Unconditionally removes all keyword substitutions from text.'''
229 return self.re_kw.sub(r'$\1$', text)
230 return self.re_kw.sub(r'$\1$', text)
230
231
231 def shrink(self, fname, text):
232 def shrink(self, fname, text):
232 '''Returns text with all keyword substitutions removed.'''
233 '''Returns text with all keyword substitutions removed.'''
233 if self.match(fname) and not util.binary(text):
234 if self.match(fname) and not util.binary(text):
234 return self.shrinktext(text)
235 return self.shrinktext(text)
235 return text
236 return text
236
237
237 def shrinklines(self, fname, lines):
238 def shrinklines(self, fname, lines):
238 '''Returns lines with keyword substitutions removed.'''
239 '''Returns lines with keyword substitutions removed.'''
239 if self.match(fname):
240 if self.match(fname):
240 text = ''.join(lines)
241 text = ''.join(lines)
241 if not util.binary(text):
242 if not util.binary(text):
242 return self.shrinktext(text).splitlines(True)
243 return self.shrinktext(text).splitlines(True)
243 return lines
244 return lines
244
245
245 def wread(self, fname, data):
246 def wread(self, fname, data):
246 '''If in restricted mode returns data read from wdir with
247 '''If in restricted mode returns data read from wdir with
247 keyword substitutions removed.'''
248 keyword substitutions removed.'''
248 return self.restrict and self.shrink(fname, data) or data
249 return self.restrict and self.shrink(fname, data) or data
249
250
250 class kwfilelog(filelog.filelog):
251 class kwfilelog(filelog.filelog):
251 '''
252 '''
252 Subclass of filelog to hook into its read, add, cmp methods.
253 Subclass of filelog to hook into its read, add, cmp methods.
253 Keywords are "stored" unexpanded, and processed on reading.
254 Keywords are "stored" unexpanded, and processed on reading.
254 '''
255 '''
255 def __init__(self, opener, kwt, path):
256 def __init__(self, opener, kwt, path):
256 super(kwfilelog, self).__init__(opener, path)
257 super(kwfilelog, self).__init__(opener, path)
257 self.kwt = kwt
258 self.kwt = kwt
258 self.path = path
259 self.path = path
259
260
260 def read(self, node):
261 def read(self, node):
261 '''Expands keywords when reading filelog.'''
262 '''Expands keywords when reading filelog.'''
262 data = super(kwfilelog, self).read(node)
263 data = super(kwfilelog, self).read(node)
263 return self.kwt.expand(self.path, node, data)
264 return self.kwt.expand(self.path, node, data)
264
265
265 def add(self, text, meta, tr, link, p1=None, p2=None):
266 def add(self, text, meta, tr, link, p1=None, p2=None):
266 '''Removes keyword substitutions when adding to filelog.'''
267 '''Removes keyword substitutions when adding to filelog.'''
267 text = self.kwt.shrink(self.path, text)
268 text = self.kwt.shrink(self.path, text)
268 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
269 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
269
270
270 def cmp(self, node, text):
271 def cmp(self, node, text):
271 '''Removes keyword substitutions for comparison.'''
272 '''Removes keyword substitutions for comparison.'''
272 text = self.kwt.shrink(self.path, text)
273 text = self.kwt.shrink(self.path, text)
273 if self.renamed(node):
274 if self.renamed(node):
274 t2 = super(kwfilelog, self).read(node)
275 t2 = super(kwfilelog, self).read(node)
275 return t2 != text
276 return t2 != text
276 return revlog.revlog.cmp(self, node, text)
277 return revlog.revlog.cmp(self, node, text)
277
278
278 def _status(ui, repo, kwt, *pats, **opts):
279 def _status(ui, repo, kwt, *pats, **opts):
279 '''Bails out if [keyword] configuration is not active.
280 '''Bails out if [keyword] configuration is not active.
280 Returns status of working directory.'''
281 Returns status of working directory.'''
281 if kwt:
282 if kwt:
282 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
283 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
283 unknown=opts.get('unknown') or opts.get('all'))
284 unknown=opts.get('unknown') or opts.get('all'))
284 if ui.configitems('keyword'):
285 if ui.configitems('keyword'):
285 raise util.Abort(_('[keyword] patterns cannot match'))
286 raise util.Abort(_('[keyword] patterns cannot match'))
286 raise util.Abort(_('no [keyword] patterns configured'))
287 raise util.Abort(_('no [keyword] patterns configured'))
287
288
288 def _kwfwrite(ui, repo, expand, *pats, **opts):
289 def _kwfwrite(ui, repo, expand, *pats, **opts):
289 '''Selects files and passes them to kwtemplater.overwrite.'''
290 '''Selects files and passes them to kwtemplater.overwrite.'''
290 wctx = repo[None]
291 wctx = repo[None]
291 if len(wctx.parents()) > 1:
292 if len(wctx.parents()) > 1:
292 raise util.Abort(_('outstanding uncommitted merge'))
293 raise util.Abort(_('outstanding uncommitted merge'))
293 kwt = kwtools['templater']
294 kwt = kwtools['templater']
294 wlock = repo.wlock()
295 wlock = repo.wlock()
295 try:
296 try:
296 status = _status(ui, repo, kwt, *pats, **opts)
297 status = _status(ui, repo, kwt, *pats, **opts)
297 modified, added, removed, deleted, unknown, ignored, clean = status
298 modified, added, removed, deleted, unknown, ignored, clean = status
298 if modified or added or removed or deleted:
299 if modified or added or removed or deleted:
299 raise util.Abort(_('outstanding uncommitted changes'))
300 raise util.Abort(_('outstanding uncommitted changes'))
300 kwt.overwrite(wctx, clean, True, expand)
301 kwt.overwrite(wctx, clean, True, expand)
301 finally:
302 finally:
302 wlock.release()
303 wlock.release()
303
304
304 def demo(ui, repo, *args, **opts):
305 def demo(ui, repo, *args, **opts):
305 '''print [keywordmaps] configuration and an expansion example
306 '''print [keywordmaps] configuration and an expansion example
306
307
307 Show current, custom, or default keyword template maps and their
308 Show current, custom, or default keyword template maps and their
308 expansions.
309 expansions.
309
310
310 Extend the current configuration by specifying maps as arguments
311 Extend the current configuration by specifying maps as arguments
311 and using -f/--rcfile to source an external hgrc file.
312 and using -f/--rcfile to source an external hgrc file.
312
313
313 Use -d/--default to disable current configuration.
314 Use -d/--default to disable current configuration.
314
315
315 See :hg:`help templates` for information on templates and filters.
316 See :hg:`help templates` for information on templates and filters.
316 '''
317 '''
317 def demoitems(section, items):
318 def demoitems(section, items):
318 ui.write('[%s]\n' % section)
319 ui.write('[%s]\n' % section)
319 for k, v in sorted(items):
320 for k, v in sorted(items):
320 ui.write('%s = %s\n' % (k, v))
321 ui.write('%s = %s\n' % (k, v))
321
322
322 fn = 'demo.txt'
323 fn = 'demo.txt'
323 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
324 tmpdir = tempfile.mkdtemp('', 'kwdemo.')
324 ui.note(_('creating temporary repository at %s\n') % tmpdir)
325 ui.note(_('creating temporary repository at %s\n') % tmpdir)
325 repo = localrepo.localrepository(ui, tmpdir, True)
326 repo = localrepo.localrepository(ui, tmpdir, True)
326 ui.setconfig('keyword', fn, '')
327 ui.setconfig('keyword', fn, '')
327
328
328 uikwmaps = ui.configitems('keywordmaps')
329 uikwmaps = ui.configitems('keywordmaps')
329 if args or opts.get('rcfile'):
330 if args or opts.get('rcfile'):
330 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
331 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
331 if uikwmaps:
332 if uikwmaps:
332 ui.status(_('\textending current template maps\n'))
333 ui.status(_('\textending current template maps\n'))
333 if opts.get('default') or not uikwmaps:
334 if opts.get('default') or not uikwmaps:
334 ui.status(_('\toverriding default template maps\n'))
335 ui.status(_('\toverriding default template maps\n'))
335 if opts.get('rcfile'):
336 if opts.get('rcfile'):
336 ui.readconfig(opts.get('rcfile'))
337 ui.readconfig(opts.get('rcfile'))
337 if args:
338 if args:
338 # simulate hgrc parsing
339 # simulate hgrc parsing
339 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
340 rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
340 fp = repo.opener('hgrc', 'w')
341 fp = repo.opener('hgrc', 'w')
341 fp.writelines(rcmaps)
342 fp.writelines(rcmaps)
342 fp.close()
343 fp.close()
343 ui.readconfig(repo.join('hgrc'))
344 ui.readconfig(repo.join('hgrc'))
344 kwmaps = dict(ui.configitems('keywordmaps'))
345 kwmaps = dict(ui.configitems('keywordmaps'))
345 elif opts.get('default'):
346 elif opts.get('default'):
346 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
347 ui.status(_('\n\tconfiguration using default keyword template maps\n'))
347 kwmaps = _defaultkwmaps(ui)
348 kwmaps = _defaultkwmaps(ui)
348 if uikwmaps:
349 if uikwmaps:
349 ui.status(_('\tdisabling current template maps\n'))
350 ui.status(_('\tdisabling current template maps\n'))
350 for k, v in kwmaps.iteritems():
351 for k, v in kwmaps.iteritems():
351 ui.setconfig('keywordmaps', k, v)
352 ui.setconfig('keywordmaps', k, v)
352 else:
353 else:
353 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
354 ui.status(_('\n\tconfiguration using current keyword template maps\n'))
354 kwmaps = dict(uikwmaps) or _defaultkwmaps(ui)
355 kwmaps = dict(uikwmaps) or _defaultkwmaps(ui)
355
356
356 uisetup(ui)
357 uisetup(ui)
357 reposetup(ui, repo)
358 reposetup(ui, repo)
358 ui.write('[extensions]\nkeyword =\n')
359 ui.write('[extensions]\nkeyword =\n')
359 demoitems('keyword', ui.configitems('keyword'))
360 demoitems('keyword', ui.configitems('keyword'))
360 demoitems('keywordmaps', kwmaps.iteritems())
361 demoitems('keywordmaps', kwmaps.iteritems())
361 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
362 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
362 repo.wopener(fn, 'w').write(keywords)
363 repo.wopener(fn, 'w').write(keywords)
363 repo[None].add([fn])
364 repo[None].add([fn])
364 ui.note(_('\nkeywords written to %s:\n') % fn)
365 ui.note(_('\nkeywords written to %s:\n') % fn)
365 ui.note(keywords)
366 ui.note(keywords)
366 repo.dirstate.setbranch('demobranch')
367 repo.dirstate.setbranch('demobranch')
367 for name, cmd in ui.configitems('hooks'):
368 for name, cmd in ui.configitems('hooks'):
368 if name.split('.', 1)[0].find('commit') > -1:
369 if name.split('.', 1)[0].find('commit') > -1:
369 repo.ui.setconfig('hooks', name, '')
370 repo.ui.setconfig('hooks', name, '')
370 msg = _('hg keyword configuration and expansion example')
371 msg = _('hg keyword configuration and expansion example')
371 ui.note("hg ci -m '%s'\n" % msg)
372 ui.note("hg ci -m '%s'\n" % msg)
372 repo.commit(text=msg)
373 repo.commit(text=msg)
373 ui.status(_('\n\tkeywords expanded\n'))
374 ui.status(_('\n\tkeywords expanded\n'))
374 ui.write(repo.wread(fn))
375 ui.write(repo.wread(fn))
375 shutil.rmtree(tmpdir, ignore_errors=True)
376 shutil.rmtree(tmpdir, ignore_errors=True)
376
377
377 def expand(ui, repo, *pats, **opts):
378 def expand(ui, repo, *pats, **opts):
378 '''expand keywords in the working directory
379 '''expand keywords in the working directory
379
380
380 Run after (re)enabling keyword expansion.
381 Run after (re)enabling keyword expansion.
381
382
382 kwexpand refuses to run if given files contain local changes.
383 kwexpand refuses to run if given files contain local changes.
383 '''
384 '''
384 # 3rd argument sets expansion to True
385 # 3rd argument sets expansion to True
385 _kwfwrite(ui, repo, True, *pats, **opts)
386 _kwfwrite(ui, repo, True, *pats, **opts)
386
387
387 def files(ui, repo, *pats, **opts):
388 def files(ui, repo, *pats, **opts):
388 '''show files configured for keyword expansion
389 '''show files configured for keyword expansion
389
390
390 List which files in the working directory are matched by the
391 List which files in the working directory are matched by the
391 [keyword] configuration patterns.
392 [keyword] configuration patterns.
392
393
393 Useful to prevent inadvertent keyword expansion and to speed up
394 Useful to prevent inadvertent keyword expansion and to speed up
394 execution by including only files that are actual candidates for
395 execution by including only files that are actual candidates for
395 expansion.
396 expansion.
396
397
397 See :hg:`help keyword` on how to construct patterns both for
398 See :hg:`help keyword` on how to construct patterns both for
398 inclusion and exclusion of files.
399 inclusion and exclusion of files.
399
400
400 With -A/--all and -v/--verbose the codes used to show the status
401 With -A/--all and -v/--verbose the codes used to show the status
401 of files are::
402 of files are::
402
403
403 K = keyword expansion candidate
404 K = keyword expansion candidate
404 k = keyword expansion candidate (not tracked)
405 k = keyword expansion candidate (not tracked)
405 I = ignored
406 I = ignored
406 i = ignored (not tracked)
407 i = ignored (not tracked)
407 '''
408 '''
408 kwt = kwtools['templater']
409 kwt = kwtools['templater']
409 status = _status(ui, repo, kwt, *pats, **opts)
410 status = _status(ui, repo, kwt, *pats, **opts)
410 cwd = pats and repo.getcwd() or ''
411 cwd = pats and repo.getcwd() or ''
411 modified, added, removed, deleted, unknown, ignored, clean = status
412 modified, added, removed, deleted, unknown, ignored, clean = status
412 files = []
413 files = []
413 if not opts.get('unknown') or opts.get('all'):
414 if not opts.get('unknown') or opts.get('all'):
414 files = sorted(modified + added + clean)
415 files = sorted(modified + added + clean)
415 wctx = repo[None]
416 wctx = repo[None]
416 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
417 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
417 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
418 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
418 if not opts.get('ignore') or opts.get('all'):
419 if not opts.get('ignore') or opts.get('all'):
419 showfiles = kwfiles, kwunknown
420 showfiles = kwfiles, kwunknown
420 else:
421 else:
421 showfiles = [], []
422 showfiles = [], []
422 if opts.get('all') or opts.get('ignore'):
423 if opts.get('all') or opts.get('ignore'):
423 showfiles += ([f for f in files if f not in kwfiles],
424 showfiles += ([f for f in files if f not in kwfiles],
424 [f for f in unknown if f not in kwunknown])
425 [f for f in unknown if f not in kwunknown])
425 for char, filenames in zip('KkIi', showfiles):
426 for char, filenames in zip('KkIi', showfiles):
426 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
427 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
427 for f in filenames:
428 for f in filenames:
428 ui.write(fmt % repo.pathto(f, cwd))
429 ui.write(fmt % repo.pathto(f, cwd))
429
430
430 def shrink(ui, repo, *pats, **opts):
431 def shrink(ui, repo, *pats, **opts):
431 '''revert expanded keywords in the working directory
432 '''revert expanded keywords in the working directory
432
433
433 Run before changing/disabling active keywords or if you experience
434 Run before changing/disabling active keywords or if you experience
434 problems with :hg:`import` or :hg:`merge`.
435 problems with :hg:`import` or :hg:`merge`.
435
436
436 kwshrink refuses to run if given files contain local changes.
437 kwshrink refuses to run if given files contain local changes.
437 '''
438 '''
438 # 3rd argument sets expansion to False
439 # 3rd argument sets expansion to False
439 _kwfwrite(ui, repo, False, *pats, **opts)
440 _kwfwrite(ui, repo, False, *pats, **opts)
440
441
441
442
442 def uisetup(ui):
443 def uisetup(ui):
443 ''' Monkeypatches dispatch._parse to retrieve user command.'''
444 ''' Monkeypatches dispatch._parse to retrieve user command.'''
444
445
445 def kwdispatch_parse(orig, ui, args):
446 def kwdispatch_parse(orig, ui, args):
446 '''Monkeypatch dispatch._parse to obtain running hg command.'''
447 '''Monkeypatch dispatch._parse to obtain running hg command.'''
447 cmd, func, args, options, cmdoptions = orig(ui, args)
448 cmd, func, args, options, cmdoptions = orig(ui, args)
448 kwtools['hgcmd'] = cmd
449 kwtools['hgcmd'] = cmd
449 return cmd, func, args, options, cmdoptions
450 return cmd, func, args, options, cmdoptions
450
451
451 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
452 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
452
453
453 def reposetup(ui, repo):
454 def reposetup(ui, repo):
454 '''Sets up repo as kwrepo for keyword substitution.
455 '''Sets up repo as kwrepo for keyword substitution.
455 Overrides file method to return kwfilelog instead of filelog
456 Overrides file method to return kwfilelog instead of filelog
456 if file matches user configuration.
457 if file matches user configuration.
457 Wraps commit to overwrite configured files with updated
458 Wraps commit to overwrite configured files with updated
458 keyword substitutions.
459 keyword substitutions.
459 Monkeypatches patch and webcommands.'''
460 Monkeypatches patch and webcommands.'''
460
461
461 try:
462 try:
462 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
463 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
463 or '.hg' in util.splitpath(repo.root)
464 or '.hg' in util.splitpath(repo.root)
464 or repo._url.startswith('bundle:')):
465 or repo._url.startswith('bundle:')):
465 return
466 return
466 except AttributeError:
467 except AttributeError:
467 pass
468 pass
468
469
469 inc, exc = [], ['.hg*']
470 inc, exc = [], ['.hg*']
470 for pat, opt in ui.configitems('keyword'):
471 for pat, opt in ui.configitems('keyword'):
471 if opt != 'ignore':
472 if opt != 'ignore':
472 inc.append(pat)
473 inc.append(pat)
473 else:
474 else:
474 exc.append(pat)
475 exc.append(pat)
475 if not inc:
476 if not inc:
476 return
477 return
477
478
478 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
479 kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc)
479
480
480 class kwrepo(repo.__class__):
481 class kwrepo(repo.__class__):
481 def file(self, f):
482 def file(self, f):
482 if f[0] == '/':
483 if f[0] == '/':
483 f = f[1:]
484 f = f[1:]
484 return kwfilelog(self.sopener, kwt, f)
485 return kwfilelog(self.sopener, kwt, f)
485
486
486 def wread(self, filename):
487 def wread(self, filename):
487 data = super(kwrepo, self).wread(filename)
488 data = super(kwrepo, self).wread(filename)
488 return kwt.wread(filename, data)
489 return kwt.wread(filename, data)
489
490
490 def commit(self, *args, **opts):
491 def commit(self, *args, **opts):
491 # use custom commitctx for user commands
492 # use custom commitctx for user commands
492 # other extensions can still wrap repo.commitctx directly
493 # other extensions can still wrap repo.commitctx directly
493 self.commitctx = self.kwcommitctx
494 self.commitctx = self.kwcommitctx
494 try:
495 try:
495 return super(kwrepo, self).commit(*args, **opts)
496 return super(kwrepo, self).commit(*args, **opts)
496 finally:
497 finally:
497 del self.commitctx
498 del self.commitctx
498
499
499 def kwcommitctx(self, ctx, error=False):
500 def kwcommitctx(self, ctx, error=False):
500 n = super(kwrepo, self).commitctx(ctx, error)
501 n = super(kwrepo, self).commitctx(ctx, error)
501 # no lock needed, only called from repo.commit() which already locks
502 # no lock needed, only called from repo.commit() which already locks
502 if not kwt.record:
503 if not kwt.record:
503 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
504 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
504 False, True)
505 False, True)
505 return n
506 return n
506
507
507 # monkeypatches
508 # monkeypatches
508 def kwpatchfile_init(orig, self, ui, fname, opener,
509 def kwpatchfile_init(orig, self, ui, fname, opener,
509 missing=False, eolmode=None):
510 missing=False, eolmode=None):
510 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
511 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
511 rejects or conflicts due to expanded keywords in working dir.'''
512 rejects or conflicts due to expanded keywords in working dir.'''
512 orig(self, ui, fname, opener, missing, eolmode)
513 orig(self, ui, fname, opener, missing, eolmode)
513 # shrink keywords read from working dir
514 # shrink keywords read from working dir
514 self.lines = kwt.shrinklines(self.fname, self.lines)
515 self.lines = kwt.shrinklines(self.fname, self.lines)
515
516
516 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
517 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
517 opts=None, prefix=''):
518 opts=None, prefix=''):
518 '''Monkeypatch patch.diff to avoid expansion except when
519 '''Monkeypatch patch.diff to avoid expansion except when
519 comparing against working dir.'''
520 comparing against working dir.'''
520 if node2 is not None:
521 if node2 is not None:
521 kwt.match = util.never
522 kwt.match = util.never
522 elif node1 is not None and node1 != repo['.'].node():
523 elif node1 is not None and node1 != repo['.'].node():
523 kwt.restrict = True
524 kwt.restrict = True
524 return orig(repo, node1, node2, match, changes, opts, prefix)
525 return orig(repo, node1, node2, match, changes, opts, prefix)
525
526
526 def kwweb_skip(orig, web, req, tmpl):
527 def kwweb_skip(orig, web, req, tmpl):
527 '''Wraps webcommands.x turning off keyword expansion.'''
528 '''Wraps webcommands.x turning off keyword expansion.'''
528 kwt.match = util.never
529 kwt.match = util.never
529 return orig(web, req, tmpl)
530 return orig(web, req, tmpl)
530
531
531 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
532 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
532 '''Wraps record.dorecord expanding keywords after recording.'''
533 '''Wraps record.dorecord expanding keywords after recording.'''
533 wlock = repo.wlock()
534 wlock = repo.wlock()
534 try:
535 try:
535 # record returns 0 even when nothing has changed
536 # record returns 0 even when nothing has changed
536 # therefore compare nodes before and after
537 # therefore compare nodes before and after
537 ctx = repo['.']
538 ctx = repo['.']
538 ret = orig(ui, repo, commitfunc, *pats, **opts)
539 ret = orig(ui, repo, commitfunc, *pats, **opts)
539 recordctx = repo['.']
540 recordctx = repo['.']
540 if ctx != recordctx:
541 if ctx != recordctx:
541 kwt.overwrite(recordctx, None, False, True)
542 kwt.overwrite(recordctx, None, False, True)
542 return ret
543 return ret
543 finally:
544 finally:
544 wlock.release()
545 wlock.release()
545
546
546 repo.__class__ = kwrepo
547 repo.__class__ = kwrepo
547
548
548 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
549 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
549 if not kwt.restrict:
550 if not kwt.restrict:
550 extensions.wrapfunction(patch, 'diff', kw_diff)
551 extensions.wrapfunction(patch, 'diff', kw_diff)
551 for c in 'annotate changeset rev filediff diff'.split():
552 for c in 'annotate changeset rev filediff diff'.split():
552 extensions.wrapfunction(webcommands, c, kwweb_skip)
553 extensions.wrapfunction(webcommands, c, kwweb_skip)
553 for name in recordextensions.split():
554 for name in recordextensions.split():
554 try:
555 try:
555 record = extensions.find(name)
556 record = extensions.find(name)
556 extensions.wrapfunction(record, 'dorecord', kw_dorecord)
557 extensions.wrapfunction(record, 'dorecord', kw_dorecord)
557 except KeyError:
558 except KeyError:
558 pass
559 pass
559
560
560 cmdtable = {
561 cmdtable = {
561 'kwdemo':
562 'kwdemo':
562 (demo,
563 (demo,
563 [('d', 'default', None, _('show default keyword template maps')),
564 [('d', 'default', None, _('show default keyword template maps')),
564 ('f', 'rcfile', '',
565 ('f', 'rcfile', '',
565 _('read maps from rcfile'), _('FILE'))],
566 _('read maps from rcfile'), _('FILE'))],
566 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
567 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
567 'kwexpand': (expand, commands.walkopts,
568 'kwexpand': (expand, commands.walkopts,
568 _('hg kwexpand [OPTION]... [FILE]...')),
569 _('hg kwexpand [OPTION]... [FILE]...')),
569 'kwfiles':
570 'kwfiles':
570 (files,
571 (files,
571 [('A', 'all', None, _('show keyword status flags of all files')),
572 [('A', 'all', None, _('show keyword status flags of all files')),
572 ('i', 'ignore', None, _('show files excluded from expansion')),
573 ('i', 'ignore', None, _('show files excluded from expansion')),
573 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
574 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
574 ] + commands.walkopts,
575 ] + commands.walkopts,
575 _('hg kwfiles [OPTION]... [FILE]...')),
576 _('hg kwfiles [OPTION]... [FILE]...')),
576 'kwshrink': (shrink, commands.walkopts,
577 'kwshrink': (shrink, commands.walkopts,
577 _('hg kwshrink [OPTION]... [FILE]...')),
578 _('hg kwshrink [OPTION]... [FILE]...')),
578 }
579 }
@@ -1,4448 +1,4453 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, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error
12 import hg, util, revlog, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 .hgignore. As with add, these changes take effect at the next
61 .hgignore. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = repo[opts.get('rev')]
129 ctx = repo[opts.get('rev')]
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = repo[opts.get('rev')]
181 ctx = repo[opts.get('rev')]
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 Commit the backed out changes as a new changeset. The new
207 Commit the backed out changes as a new changeset. The new
208 changeset is a child of the backed out changeset.
208 changeset is a child of the backed out changeset.
209
209
210 If you backout a changeset other than the tip, a new head is
210 If you backout a changeset other than the tip, a new head is
211 created. This head will be the new tip and you should merge this
211 created. This head will be the new tip and you should merge this
212 backout changeset with another head.
212 backout changeset with another head.
213
213
214 The --merge option remembers the parent of the working directory
214 The --merge option remembers the parent of the working directory
215 before starting the backout, then merges the new head with that
215 before starting the backout, then merges the new head with that
216 changeset afterwards. This saves you from doing the merge by hand.
216 changeset afterwards. This saves you from doing the merge by hand.
217 The result of this merge is not committed, as with a normal merge.
217 The result of this merge is not committed, as with a normal merge.
218
218
219 See :hg:`help dates` for a list of formats valid for -d/--date.
219 See :hg:`help dates` for a list of formats valid for -d/--date.
220
220
221 Returns 0 on success.
221 Returns 0 on success.
222 '''
222 '''
223 if rev and node:
223 if rev and node:
224 raise util.Abort(_("please specify just one revision"))
224 raise util.Abort(_("please specify just one revision"))
225
225
226 if not rev:
226 if not rev:
227 rev = node
227 rev = node
228
228
229 if not rev:
229 if not rev:
230 raise util.Abort(_("please specify a revision to backout"))
230 raise util.Abort(_("please specify a revision to backout"))
231
231
232 date = opts.get('date')
232 date = opts.get('date')
233 if date:
233 if date:
234 opts['date'] = util.parsedate(date)
234 opts['date'] = util.parsedate(date)
235
235
236 cmdutil.bail_if_changed(repo)
236 cmdutil.bail_if_changed(repo)
237 node = repo.lookup(rev)
237 node = repo.lookup(rev)
238
238
239 op1, op2 = repo.dirstate.parents()
239 op1, op2 = repo.dirstate.parents()
240 a = repo.changelog.ancestor(op1, node)
240 a = repo.changelog.ancestor(op1, node)
241 if a != node:
241 if a != node:
242 raise util.Abort(_('cannot backout change on a different branch'))
242 raise util.Abort(_('cannot backout change on a different branch'))
243
243
244 p1, p2 = repo.changelog.parents(node)
244 p1, p2 = repo.changelog.parents(node)
245 if p1 == nullid:
245 if p1 == nullid:
246 raise util.Abort(_('cannot backout a change with no parents'))
246 raise util.Abort(_('cannot backout a change with no parents'))
247 if p2 != nullid:
247 if p2 != nullid:
248 if not opts.get('parent'):
248 if not opts.get('parent'):
249 raise util.Abort(_('cannot backout a merge changeset without '
249 raise util.Abort(_('cannot backout a merge changeset without '
250 '--parent'))
250 '--parent'))
251 p = repo.lookup(opts['parent'])
251 p = repo.lookup(opts['parent'])
252 if p not in (p1, p2):
252 if p not in (p1, p2):
253 raise util.Abort(_('%s is not a parent of %s') %
253 raise util.Abort(_('%s is not a parent of %s') %
254 (short(p), short(node)))
254 (short(p), short(node)))
255 parent = p
255 parent = p
256 else:
256 else:
257 if opts.get('parent'):
257 if opts.get('parent'):
258 raise util.Abort(_('cannot use --parent on non-merge changeset'))
258 raise util.Abort(_('cannot use --parent on non-merge changeset'))
259 parent = p1
259 parent = p1
260
260
261 # the backout should appear on the same branch
261 # the backout should appear on the same branch
262 branch = repo.dirstate.branch()
262 branch = repo.dirstate.branch()
263 hg.clean(repo, node, show_stats=False)
263 hg.clean(repo, node, show_stats=False)
264 repo.dirstate.setbranch(branch)
264 repo.dirstate.setbranch(branch)
265 revert_opts = opts.copy()
265 revert_opts = opts.copy()
266 revert_opts['date'] = None
266 revert_opts['date'] = None
267 revert_opts['all'] = True
267 revert_opts['all'] = True
268 revert_opts['rev'] = hex(parent)
268 revert_opts['rev'] = hex(parent)
269 revert_opts['no_backup'] = None
269 revert_opts['no_backup'] = None
270 revert(ui, repo, **revert_opts)
270 revert(ui, repo, **revert_opts)
271 commit_opts = opts.copy()
271 commit_opts = opts.copy()
272 commit_opts['addremove'] = False
272 commit_opts['addremove'] = False
273 if not commit_opts['message'] and not commit_opts['logfile']:
273 if not commit_opts['message'] and not commit_opts['logfile']:
274 # we don't translate commit messages
274 # we don't translate commit messages
275 commit_opts['message'] = "Backed out changeset %s" % short(node)
275 commit_opts['message'] = "Backed out changeset %s" % short(node)
276 commit_opts['force_editor'] = True
276 commit_opts['force_editor'] = True
277 commit(ui, repo, **commit_opts)
277 commit(ui, repo, **commit_opts)
278 def nice(node):
278 def nice(node):
279 return '%d:%s' % (repo.changelog.rev(node), short(node))
279 return '%d:%s' % (repo.changelog.rev(node), short(node))
280 ui.status(_('changeset %s backs out changeset %s\n') %
280 ui.status(_('changeset %s backs out changeset %s\n') %
281 (nice(repo.changelog.tip()), nice(node)))
281 (nice(repo.changelog.tip()), nice(node)))
282 if op1 != node:
282 if op1 != node:
283 hg.clean(repo, op1, show_stats=False)
283 hg.clean(repo, op1, show_stats=False)
284 if opts.get('merge'):
284 if opts.get('merge'):
285 ui.status(_('merging with changeset %s\n')
285 ui.status(_('merging with changeset %s\n')
286 % nice(repo.changelog.tip()))
286 % nice(repo.changelog.tip()))
287 hg.merge(repo, hex(repo.changelog.tip()))
287 hg.merge(repo, hex(repo.changelog.tip()))
288 else:
288 else:
289 ui.status(_('the backout changeset is a new head - '
289 ui.status(_('the backout changeset is a new head - '
290 'do not forget to merge\n'))
290 'do not forget to merge\n'))
291 ui.status(_('(use "backout --merge" '
291 ui.status(_('(use "backout --merge" '
292 'if you want to auto-merge)\n'))
292 'if you want to auto-merge)\n'))
293
293
294 def bisect(ui, repo, rev=None, extra=None, command=None,
294 def bisect(ui, repo, rev=None, extra=None, command=None,
295 reset=None, good=None, bad=None, skip=None, noupdate=None):
295 reset=None, good=None, bad=None, skip=None, noupdate=None):
296 """subdivision search of changesets
296 """subdivision search of changesets
297
297
298 This command helps to find changesets which introduce problems. To
298 This command helps to find changesets which introduce problems. To
299 use, mark the earliest changeset you know exhibits the problem as
299 use, mark the earliest changeset you know exhibits the problem as
300 bad, then mark the latest changeset which is free from the problem
300 bad, then mark the latest changeset which is free from the problem
301 as good. Bisect will update your working directory to a revision
301 as good. Bisect will update your working directory to a revision
302 for testing (unless the -U/--noupdate option is specified). Once
302 for testing (unless the -U/--noupdate option is specified). Once
303 you have performed tests, mark the working directory as good or
303 you have performed tests, mark the working directory as good or
304 bad, and bisect will either update to another candidate changeset
304 bad, and bisect will either update to another candidate changeset
305 or announce that it has found the bad revision.
305 or announce that it has found the bad revision.
306
306
307 As a shortcut, you can also use the revision argument to mark a
307 As a shortcut, you can also use the revision argument to mark a
308 revision as good or bad without checking it out first.
308 revision as good or bad without checking it out first.
309
309
310 If you supply a command, it will be used for automatic bisection.
310 If you supply a command, it will be used for automatic bisection.
311 Its exit status will be used to mark revisions as good or bad:
311 Its exit status will be used to mark revisions as good or bad:
312 status 0 means good, 125 means to skip the revision, 127
312 status 0 means good, 125 means to skip the revision, 127
313 (command not found) will abort the bisection, and any other
313 (command not found) will abort the bisection, and any other
314 non-zero exit status means the revision is bad.
314 non-zero exit status means the revision is bad.
315
315
316 Returns 0 on success.
316 Returns 0 on success.
317 """
317 """
318 def print_result(nodes, good):
318 def print_result(nodes, good):
319 displayer = cmdutil.show_changeset(ui, repo, {})
319 displayer = cmdutil.show_changeset(ui, repo, {})
320 if len(nodes) == 1:
320 if len(nodes) == 1:
321 # narrowed it down to a single revision
321 # narrowed it down to a single revision
322 if good:
322 if good:
323 ui.write(_("The first good revision is:\n"))
323 ui.write(_("The first good revision is:\n"))
324 else:
324 else:
325 ui.write(_("The first bad revision is:\n"))
325 ui.write(_("The first bad revision is:\n"))
326 displayer.show(repo[nodes[0]])
326 displayer.show(repo[nodes[0]])
327 parents = repo[nodes[0]].parents()
327 parents = repo[nodes[0]].parents()
328 if len(parents) > 1:
328 if len(parents) > 1:
329 side = good and state['bad'] or state['good']
329 side = good and state['bad'] or state['good']
330 num = len(set(i.node() for i in parents) & set(side))
330 num = len(set(i.node() for i in parents) & set(side))
331 if num == 1:
331 if num == 1:
332 common = parents[0].ancestor(parents[1])
332 common = parents[0].ancestor(parents[1])
333 ui.write(_('Not all ancestors of this changeset have been'
333 ui.write(_('Not all ancestors of this changeset have been'
334 ' checked.\nTo check the other ancestors, start'
334 ' checked.\nTo check the other ancestors, start'
335 ' from the common ancestor, %s.\n' % common))
335 ' from the common ancestor, %s.\n' % common))
336 else:
336 else:
337 # multiple possible revisions
337 # multiple possible revisions
338 if good:
338 if good:
339 ui.write(_("Due to skipped revisions, the first "
339 ui.write(_("Due to skipped revisions, the first "
340 "good revision could be any of:\n"))
340 "good revision could be any of:\n"))
341 else:
341 else:
342 ui.write(_("Due to skipped revisions, the first "
342 ui.write(_("Due to skipped revisions, the first "
343 "bad revision could be any of:\n"))
343 "bad revision could be any of:\n"))
344 for n in nodes:
344 for n in nodes:
345 displayer.show(repo[n])
345 displayer.show(repo[n])
346 displayer.close()
346 displayer.close()
347
347
348 def check_state(state, interactive=True):
348 def check_state(state, interactive=True):
349 if not state['good'] or not state['bad']:
349 if not state['good'] or not state['bad']:
350 if (good or bad or skip or reset) and interactive:
350 if (good or bad or skip or reset) and interactive:
351 return
351 return
352 if not state['good']:
352 if not state['good']:
353 raise util.Abort(_('cannot bisect (no known good revisions)'))
353 raise util.Abort(_('cannot bisect (no known good revisions)'))
354 else:
354 else:
355 raise util.Abort(_('cannot bisect (no known bad revisions)'))
355 raise util.Abort(_('cannot bisect (no known bad revisions)'))
356 return True
356 return True
357
357
358 # backward compatibility
358 # backward compatibility
359 if rev in "good bad reset init".split():
359 if rev in "good bad reset init".split():
360 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
360 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
361 cmd, rev, extra = rev, extra, None
361 cmd, rev, extra = rev, extra, None
362 if cmd == "good":
362 if cmd == "good":
363 good = True
363 good = True
364 elif cmd == "bad":
364 elif cmd == "bad":
365 bad = True
365 bad = True
366 else:
366 else:
367 reset = True
367 reset = True
368 elif extra or good + bad + skip + reset + bool(command) > 1:
368 elif extra or good + bad + skip + reset + bool(command) > 1:
369 raise util.Abort(_('incompatible arguments'))
369 raise util.Abort(_('incompatible arguments'))
370
370
371 if reset:
371 if reset:
372 p = repo.join("bisect.state")
372 p = repo.join("bisect.state")
373 if os.path.exists(p):
373 if os.path.exists(p):
374 os.unlink(p)
374 os.unlink(p)
375 return
375 return
376
376
377 state = hbisect.load_state(repo)
377 state = hbisect.load_state(repo)
378
378
379 if command:
379 if command:
380 changesets = 1
380 changesets = 1
381 try:
381 try:
382 while changesets:
382 while changesets:
383 # update state
383 # update state
384 status = util.system(command)
384 status = util.system(command)
385 if status == 125:
385 if status == 125:
386 transition = "skip"
386 transition = "skip"
387 elif status == 0:
387 elif status == 0:
388 transition = "good"
388 transition = "good"
389 # status < 0 means process was killed
389 # status < 0 means process was killed
390 elif status == 127:
390 elif status == 127:
391 raise util.Abort(_("failed to execute %s") % command)
391 raise util.Abort(_("failed to execute %s") % command)
392 elif status < 0:
392 elif status < 0:
393 raise util.Abort(_("%s killed") % command)
393 raise util.Abort(_("%s killed") % command)
394 else:
394 else:
395 transition = "bad"
395 transition = "bad"
396 ctx = repo[rev or '.']
396 ctx = repo[rev or '.']
397 state[transition].append(ctx.node())
397 state[transition].append(ctx.node())
398 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
398 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
399 check_state(state, interactive=False)
399 check_state(state, interactive=False)
400 # bisect
400 # bisect
401 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
401 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
402 # update to next check
402 # update to next check
403 cmdutil.bail_if_changed(repo)
403 cmdutil.bail_if_changed(repo)
404 hg.clean(repo, nodes[0], show_stats=False)
404 hg.clean(repo, nodes[0], show_stats=False)
405 finally:
405 finally:
406 hbisect.save_state(repo, state)
406 hbisect.save_state(repo, state)
407 print_result(nodes, good)
407 print_result(nodes, good)
408 return
408 return
409
409
410 # update state
410 # update state
411
411
412 if rev:
412 if rev:
413 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
413 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
414 else:
414 else:
415 nodes = [repo.lookup('.')]
415 nodes = [repo.lookup('.')]
416
416
417 if good or bad or skip:
417 if good or bad or skip:
418 if good:
418 if good:
419 state['good'] += nodes
419 state['good'] += nodes
420 elif bad:
420 elif bad:
421 state['bad'] += nodes
421 state['bad'] += nodes
422 elif skip:
422 elif skip:
423 state['skip'] += nodes
423 state['skip'] += nodes
424 hbisect.save_state(repo, state)
424 hbisect.save_state(repo, state)
425
425
426 if not check_state(state):
426 if not check_state(state):
427 return
427 return
428
428
429 # actually bisect
429 # actually bisect
430 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
430 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
431 if changesets == 0:
431 if changesets == 0:
432 print_result(nodes, good)
432 print_result(nodes, good)
433 else:
433 else:
434 assert len(nodes) == 1 # only a single node can be tested next
434 assert len(nodes) == 1 # only a single node can be tested next
435 node = nodes[0]
435 node = nodes[0]
436 # compute the approximate number of remaining tests
436 # compute the approximate number of remaining tests
437 tests, size = 0, 2
437 tests, size = 0, 2
438 while size <= changesets:
438 while size <= changesets:
439 tests, size = tests + 1, size * 2
439 tests, size = tests + 1, size * 2
440 rev = repo.changelog.rev(node)
440 rev = repo.changelog.rev(node)
441 ui.write(_("Testing changeset %d:%s "
441 ui.write(_("Testing changeset %d:%s "
442 "(%d changesets remaining, ~%d tests)\n")
442 "(%d changesets remaining, ~%d tests)\n")
443 % (rev, short(node), changesets, tests))
443 % (rev, short(node), changesets, tests))
444 if not noupdate:
444 if not noupdate:
445 cmdutil.bail_if_changed(repo)
445 cmdutil.bail_if_changed(repo)
446 return hg.clean(repo, node)
446 return hg.clean(repo, node)
447
447
448 def branch(ui, repo, label=None, **opts):
448 def branch(ui, repo, label=None, **opts):
449 """set or show the current branch name
449 """set or show the current branch name
450
450
451 With no argument, show the current branch name. With one argument,
451 With no argument, show the current branch name. With one argument,
452 set the working directory branch name (the branch will not exist
452 set the working directory branch name (the branch will not exist
453 in the repository until the next commit). Standard practice
453 in the repository until the next commit). Standard practice
454 recommends that primary development take place on the 'default'
454 recommends that primary development take place on the 'default'
455 branch.
455 branch.
456
456
457 Unless -f/--force is specified, branch will not let you set a
457 Unless -f/--force is specified, branch will not let you set a
458 branch name that already exists, even if it's inactive.
458 branch name that already exists, even if it's inactive.
459
459
460 Use -C/--clean to reset the working directory branch to that of
460 Use -C/--clean to reset the working directory branch to that of
461 the parent of the working directory, negating a previous branch
461 the parent of the working directory, negating a previous branch
462 change.
462 change.
463
463
464 Use the command :hg:`update` to switch to an existing branch. Use
464 Use the command :hg:`update` to switch to an existing branch. Use
465 :hg:`commit --close-branch` to mark this branch as closed.
465 :hg:`commit --close-branch` to mark this branch as closed.
466
466
467 Returns 0 on success.
467 Returns 0 on success.
468 """
468 """
469
469
470 if opts.get('clean'):
470 if opts.get('clean'):
471 label = repo[None].parents()[0].branch()
471 label = repo[None].parents()[0].branch()
472 repo.dirstate.setbranch(label)
472 repo.dirstate.setbranch(label)
473 ui.status(_('reset working directory to branch %s\n') % label)
473 ui.status(_('reset working directory to branch %s\n') % label)
474 elif label:
474 elif label:
475 utflabel = encoding.fromlocal(label)
475 utflabel = encoding.fromlocal(label)
476 if not opts.get('force') and utflabel in repo.branchtags():
476 if not opts.get('force') and utflabel in repo.branchtags():
477 if label not in [p.branch() for p in repo.parents()]:
477 if label not in [p.branch() for p in repo.parents()]:
478 raise util.Abort(_('a branch of the same name already exists'
478 raise util.Abort(_('a branch of the same name already exists'
479 " (use 'hg update' to switch to it)"))
479 " (use 'hg update' to switch to it)"))
480 repo.dirstate.setbranch(utflabel)
480 repo.dirstate.setbranch(utflabel)
481 ui.status(_('marked working directory as branch %s\n') % label)
481 ui.status(_('marked working directory as branch %s\n') % label)
482 else:
482 else:
483 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
483 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
484
484
485 def branches(ui, repo, active=False, closed=False):
485 def branches(ui, repo, active=False, closed=False):
486 """list repository named branches
486 """list repository named branches
487
487
488 List the repository's named branches, indicating which ones are
488 List the repository's named branches, indicating which ones are
489 inactive. If -c/--closed is specified, also list branches which have
489 inactive. If -c/--closed is specified, also list branches which have
490 been marked closed (see :hg:`commit --close-branch`).
490 been marked closed (see :hg:`commit --close-branch`).
491
491
492 If -a/--active is specified, only show active branches. A branch
492 If -a/--active is specified, only show active branches. A branch
493 is considered active if it contains repository heads.
493 is considered active if it contains repository heads.
494
494
495 Use the command :hg:`update` to switch to an existing branch.
495 Use the command :hg:`update` to switch to an existing branch.
496
496
497 Returns 0.
497 Returns 0.
498 """
498 """
499
499
500 hexfunc = ui.debugflag and hex or short
500 hexfunc = ui.debugflag and hex or short
501 activebranches = [repo[n].branch() for n in repo.heads()]
501 activebranches = [repo[n].branch() for n in repo.heads()]
502 def testactive(tag, node):
502 def testactive(tag, node):
503 realhead = tag in activebranches
503 realhead = tag in activebranches
504 open = node in repo.branchheads(tag, closed=False)
504 open = node in repo.branchheads(tag, closed=False)
505 return realhead and open
505 return realhead and open
506 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
506 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
507 for tag, node in repo.branchtags().items()],
507 for tag, node in repo.branchtags().items()],
508 reverse=True)
508 reverse=True)
509
509
510 for isactive, node, tag in branches:
510 for isactive, node, tag in branches:
511 if (not active) or isactive:
511 if (not active) or isactive:
512 encodedtag = encoding.tolocal(tag)
512 encodedtag = encoding.tolocal(tag)
513 if ui.quiet:
513 if ui.quiet:
514 ui.write("%s\n" % encodedtag)
514 ui.write("%s\n" % encodedtag)
515 else:
515 else:
516 hn = repo.lookup(node)
516 hn = repo.lookup(node)
517 if isactive:
517 if isactive:
518 label = 'branches.active'
518 label = 'branches.active'
519 notice = ''
519 notice = ''
520 elif hn not in repo.branchheads(tag, closed=False):
520 elif hn not in repo.branchheads(tag, closed=False):
521 if not closed:
521 if not closed:
522 continue
522 continue
523 label = 'branches.closed'
523 label = 'branches.closed'
524 notice = _(' (closed)')
524 notice = _(' (closed)')
525 else:
525 else:
526 label = 'branches.inactive'
526 label = 'branches.inactive'
527 notice = _(' (inactive)')
527 notice = _(' (inactive)')
528 if tag == repo.dirstate.branch():
528 if tag == repo.dirstate.branch():
529 label = 'branches.current'
529 label = 'branches.current'
530 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
530 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
531 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
531 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
532 encodedtag = ui.label(encodedtag, label)
532 encodedtag = ui.label(encodedtag, label)
533 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
533 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
534
534
535 def bundle(ui, repo, fname, dest=None, **opts):
535 def bundle(ui, repo, fname, dest=None, **opts):
536 """create a changegroup file
536 """create a changegroup file
537
537
538 Generate a compressed changegroup file collecting changesets not
538 Generate a compressed changegroup file collecting changesets not
539 known to be in another repository.
539 known to be in another repository.
540
540
541 If you omit the destination repository, then hg assumes the
541 If you omit the destination repository, then hg assumes the
542 destination will have all the nodes you specify with --base
542 destination will have all the nodes you specify with --base
543 parameters. To create a bundle containing all changesets, use
543 parameters. To create a bundle containing all changesets, use
544 -a/--all (or --base null).
544 -a/--all (or --base null).
545
545
546 You can change compression method with the -t/--type option.
546 You can change compression method with the -t/--type option.
547 The available compression methods are: none, bzip2, and
547 The available compression methods are: none, bzip2, and
548 gzip (by default, bundles are compressed using bzip2).
548 gzip (by default, bundles are compressed using bzip2).
549
549
550 The bundle file can then be transferred using conventional means
550 The bundle file can then be transferred using conventional means
551 and applied to another repository with the unbundle or pull
551 and applied to another repository with the unbundle or pull
552 command. This is useful when direct push and pull are not
552 command. This is useful when direct push and pull are not
553 available or when exporting an entire repository is undesirable.
553 available or when exporting an entire repository is undesirable.
554
554
555 Applying bundles preserves all changeset contents including
555 Applying bundles preserves all changeset contents including
556 permissions, copy/rename information, and revision history.
556 permissions, copy/rename information, and revision history.
557
557
558 Returns 0 on success, 1 if no changes found.
558 Returns 0 on success, 1 if no changes found.
559 """
559 """
560 revs = opts.get('rev') or None
560 revs = opts.get('rev') or None
561 if opts.get('all'):
561 if opts.get('all'):
562 base = ['null']
562 base = ['null']
563 else:
563 else:
564 base = opts.get('base')
564 base = opts.get('base')
565 if base:
565 if base:
566 if dest:
566 if dest:
567 raise util.Abort(_("--base is incompatible with specifying "
567 raise util.Abort(_("--base is incompatible with specifying "
568 "a destination"))
568 "a destination"))
569 base = [repo.lookup(rev) for rev in base]
569 base = [repo.lookup(rev) for rev in base]
570 # create the right base
570 # create the right base
571 # XXX: nodesbetween / changegroup* should be "fixed" instead
571 # XXX: nodesbetween / changegroup* should be "fixed" instead
572 o = []
572 o = []
573 has = set((nullid,))
573 has = set((nullid,))
574 for n in base:
574 for n in base:
575 has.update(repo.changelog.reachable(n))
575 has.update(repo.changelog.reachable(n))
576 if revs:
576 if revs:
577 revs = [repo.lookup(rev) for rev in revs]
577 revs = [repo.lookup(rev) for rev in revs]
578 visit = revs[:]
578 visit = revs[:]
579 has.difference_update(visit)
579 has.difference_update(visit)
580 else:
580 else:
581 visit = repo.changelog.heads()
581 visit = repo.changelog.heads()
582 seen = {}
582 seen = {}
583 while visit:
583 while visit:
584 n = visit.pop(0)
584 n = visit.pop(0)
585 parents = [p for p in repo.changelog.parents(n) if p not in has]
585 parents = [p for p in repo.changelog.parents(n) if p not in has]
586 if len(parents) == 0:
586 if len(parents) == 0:
587 if n not in has:
587 if n not in has:
588 o.append(n)
588 o.append(n)
589 else:
589 else:
590 for p in parents:
590 for p in parents:
591 if p not in seen:
591 if p not in seen:
592 seen[p] = 1
592 seen[p] = 1
593 visit.append(p)
593 visit.append(p)
594 else:
594 else:
595 dest = ui.expandpath(dest or 'default-push', dest or 'default')
595 dest = ui.expandpath(dest or 'default-push', dest or 'default')
596 dest, branches = hg.parseurl(dest, opts.get('branch'))
596 dest, branches = hg.parseurl(dest, opts.get('branch'))
597 other = hg.repository(hg.remoteui(repo, opts), dest)
597 other = hg.repository(hg.remoteui(repo, opts), dest)
598 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
598 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
599 if revs:
599 if revs:
600 revs = [repo.lookup(rev) for rev in revs]
600 revs = [repo.lookup(rev) for rev in revs]
601 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
601 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
602
602
603 if not o:
603 if not o:
604 ui.status(_("no changes found\n"))
604 ui.status(_("no changes found\n"))
605 return 1
605 return 1
606
606
607 if revs:
607 if revs:
608 cg = repo.changegroupsubset(o, revs, 'bundle')
608 cg = repo.changegroupsubset(o, revs, 'bundle')
609 else:
609 else:
610 cg = repo.changegroup(o, 'bundle')
610 cg = repo.changegroup(o, 'bundle')
611
611
612 bundletype = opts.get('type', 'bzip2').lower()
612 bundletype = opts.get('type', 'bzip2').lower()
613 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
613 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
614 bundletype = btypes.get(bundletype)
614 bundletype = btypes.get(bundletype)
615 if bundletype not in changegroup.bundletypes:
615 if bundletype not in changegroup.bundletypes:
616 raise util.Abort(_('unknown bundle type specified with --type'))
616 raise util.Abort(_('unknown bundle type specified with --type'))
617
617
618 changegroup.writebundle(cg, fname, bundletype)
618 changegroup.writebundle(cg, fname, bundletype)
619
619
620 def cat(ui, repo, file1, *pats, **opts):
620 def cat(ui, repo, file1, *pats, **opts):
621 """output the current or given revision of files
621 """output the current or given revision of files
622
622
623 Print the specified files as they were at the given revision. If
623 Print the specified files as they were at the given revision. If
624 no revision is given, the parent of the working directory is used,
624 no revision is given, the parent of the working directory is used,
625 or tip if no revision is checked out.
625 or tip if no revision is checked out.
626
626
627 Output may be to a file, in which case the name of the file is
627 Output may be to a file, in which case the name of the file is
628 given using a format string. The formatting rules are the same as
628 given using a format string. The formatting rules are the same as
629 for the export command, with the following additions:
629 for the export command, with the following additions:
630
630
631 :``%s``: basename of file being printed
631 :``%s``: basename of file being printed
632 :``%d``: dirname of file being printed, or '.' if in repository root
632 :``%d``: dirname of file being printed, or '.' if in repository root
633 :``%p``: root-relative path name of file being printed
633 :``%p``: root-relative path name of file being printed
634
634
635 Returns 0 on success.
635 Returns 0 on success.
636 """
636 """
637 ctx = repo[opts.get('rev')]
637 ctx = repo[opts.get('rev')]
638 err = 1
638 err = 1
639 m = cmdutil.match(repo, (file1,) + pats, opts)
639 m = cmdutil.match(repo, (file1,) + pats, opts)
640 for abs in ctx.walk(m):
640 for abs in ctx.walk(m):
641 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
641 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
642 data = ctx[abs].data()
642 data = ctx[abs].data()
643 if opts.get('decode'):
643 if opts.get('decode'):
644 data = repo.wwritedata(abs, data)
644 data = repo.wwritedata(abs, data)
645 fp.write(data)
645 fp.write(data)
646 err = 0
646 err = 0
647 return err
647 return err
648
648
649 def clone(ui, source, dest=None, **opts):
649 def clone(ui, source, dest=None, **opts):
650 """make a copy of an existing repository
650 """make a copy of an existing repository
651
651
652 Create a copy of an existing repository in a new directory.
652 Create a copy of an existing repository in a new directory.
653
653
654 If no destination directory name is specified, it defaults to the
654 If no destination directory name is specified, it defaults to the
655 basename of the source.
655 basename of the source.
656
656
657 The location of the source is added to the new repository's
657 The location of the source is added to the new repository's
658 .hg/hgrc file, as the default to be used for future pulls.
658 .hg/hgrc file, as the default to be used for future pulls.
659
659
660 See :hg:`help urls` for valid source format details.
660 See :hg:`help urls` for valid source format details.
661
661
662 It is possible to specify an ``ssh://`` URL as the destination, but no
662 It is possible to specify an ``ssh://`` URL as the destination, but no
663 .hg/hgrc and working directory will be created on the remote side.
663 .hg/hgrc and working directory will be created on the remote side.
664 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
664 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
665
665
666 A set of changesets (tags, or branch names) to pull may be specified
666 A set of changesets (tags, or branch names) to pull may be specified
667 by listing each changeset (tag, or branch name) with -r/--rev.
667 by listing each changeset (tag, or branch name) with -r/--rev.
668 If -r/--rev is used, the cloned repository will contain only a subset
668 If -r/--rev is used, the cloned repository will contain only a subset
669 of the changesets of the source repository. Only the set of changesets
669 of the changesets of the source repository. Only the set of changesets
670 defined by all -r/--rev options (including all their ancestors)
670 defined by all -r/--rev options (including all their ancestors)
671 will be pulled into the destination repository.
671 will be pulled into the destination repository.
672 No subsequent changesets (including subsequent tags) will be present
672 No subsequent changesets (including subsequent tags) will be present
673 in the destination.
673 in the destination.
674
674
675 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
675 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
676 local source repositories.
676 local source repositories.
677
677
678 For efficiency, hardlinks are used for cloning whenever the source
678 For efficiency, hardlinks are used for cloning whenever the source
679 and destination are on the same filesystem (note this applies only
679 and destination are on the same filesystem (note this applies only
680 to the repository data, not to the working directory). Some
680 to the repository data, not to the working directory). Some
681 filesystems, such as AFS, implement hardlinking incorrectly, but
681 filesystems, such as AFS, implement hardlinking incorrectly, but
682 do not report errors. In these cases, use the --pull option to
682 do not report errors. In these cases, use the --pull option to
683 avoid hardlinking.
683 avoid hardlinking.
684
684
685 In some cases, you can clone repositories and the working directory
685 In some cases, you can clone repositories and the working directory
686 using full hardlinks with ::
686 using full hardlinks with ::
687
687
688 $ cp -al REPO REPOCLONE
688 $ cp -al REPO REPOCLONE
689
689
690 This is the fastest way to clone, but it is not always safe. The
690 This is the fastest way to clone, but it is not always safe. The
691 operation is not atomic (making sure REPO is not modified during
691 operation is not atomic (making sure REPO is not modified during
692 the operation is up to you) and you have to make sure your editor
692 the operation is up to you) and you have to make sure your editor
693 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
693 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
694 this is not compatible with certain extensions that place their
694 this is not compatible with certain extensions that place their
695 metadata under the .hg directory, such as mq.
695 metadata under the .hg directory, such as mq.
696
696
697 Mercurial will update the working directory to the first applicable
697 Mercurial will update the working directory to the first applicable
698 revision from this list:
698 revision from this list:
699
699
700 a) null if -U or the source repository has no changesets
700 a) null if -U or the source repository has no changesets
701 b) if -u . and the source repository is local, the first parent of
701 b) if -u . and the source repository is local, the first parent of
702 the source repository's working directory
702 the source repository's working directory
703 c) the changeset specified with -u (if a branch name, this means the
703 c) the changeset specified with -u (if a branch name, this means the
704 latest head of that branch)
704 latest head of that branch)
705 d) the changeset specified with -r
705 d) the changeset specified with -r
706 e) the tipmost head specified with -b
706 e) the tipmost head specified with -b
707 f) the tipmost head specified with the url#branch source syntax
707 f) the tipmost head specified with the url#branch source syntax
708 g) the tipmost head of the default branch
708 g) the tipmost head of the default branch
709 h) tip
709 h) tip
710
710
711 Returns 0 on success.
711 Returns 0 on success.
712 """
712 """
713 if opts.get('noupdate') and opts.get('updaterev'):
713 if opts.get('noupdate') and opts.get('updaterev'):
714 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
714 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
715
715
716 r = hg.clone(hg.remoteui(ui, opts), source, dest,
716 r = hg.clone(hg.remoteui(ui, opts), source, dest,
717 pull=opts.get('pull'),
717 pull=opts.get('pull'),
718 stream=opts.get('uncompressed'),
718 stream=opts.get('uncompressed'),
719 rev=opts.get('rev'),
719 rev=opts.get('rev'),
720 update=opts.get('updaterev') or not opts.get('noupdate'),
720 update=opts.get('updaterev') or not opts.get('noupdate'),
721 branch=opts.get('branch'))
721 branch=opts.get('branch'))
722
722
723 return r is None
723 return r is None
724
724
725 def commit(ui, repo, *pats, **opts):
725 def commit(ui, repo, *pats, **opts):
726 """commit the specified files or all outstanding changes
726 """commit the specified files or all outstanding changes
727
727
728 Commit changes to the given files into the repository. Unlike a
728 Commit changes to the given files into the repository. Unlike a
729 centralized RCS, this operation is a local operation. See
729 centralized RCS, this operation is a local operation. See
730 :hg:`push` for a way to actively distribute your changes.
730 :hg:`push` for a way to actively distribute your changes.
731
731
732 If a list of files is omitted, all changes reported by :hg:`status`
732 If a list of files is omitted, all changes reported by :hg:`status`
733 will be committed.
733 will be committed.
734
734
735 If you are committing the result of a merge, do not provide any
735 If you are committing the result of a merge, do not provide any
736 filenames or -I/-X filters.
736 filenames or -I/-X filters.
737
737
738 If no commit message is specified, Mercurial starts your
738 If no commit message is specified, Mercurial starts your
739 configured editor where you can enter a message. In case your
739 configured editor where you can enter a message. In case your
740 commit fails, you will find a backup of your message in
740 commit fails, you will find a backup of your message in
741 ``.hg/last-message.txt``.
741 ``.hg/last-message.txt``.
742
742
743 See :hg:`help dates` for a list of formats valid for -d/--date.
743 See :hg:`help dates` for a list of formats valid for -d/--date.
744
744
745 Returns 0 on success, 1 if nothing changed.
745 Returns 0 on success, 1 if nothing changed.
746 """
746 """
747 extra = {}
747 extra = {}
748 if opts.get('close_branch'):
748 if opts.get('close_branch'):
749 if repo['.'].node() not in repo.branchheads():
749 if repo['.'].node() not in repo.branchheads():
750 # The topo heads set is included in the branch heads set of the
750 # The topo heads set is included in the branch heads set of the
751 # current branch, so it's sufficient to test branchheads
751 # current branch, so it's sufficient to test branchheads
752 raise util.Abort(_('can only close branch heads'))
752 raise util.Abort(_('can only close branch heads'))
753 extra['close'] = 1
753 extra['close'] = 1
754 e = cmdutil.commiteditor
754 e = cmdutil.commiteditor
755 if opts.get('force_editor'):
755 if opts.get('force_editor'):
756 e = cmdutil.commitforceeditor
756 e = cmdutil.commitforceeditor
757
757
758 def commitfunc(ui, repo, message, match, opts):
758 def commitfunc(ui, repo, message, match, opts):
759 return repo.commit(message, opts.get('user'), opts.get('date'), match,
759 return repo.commit(message, opts.get('user'), opts.get('date'), match,
760 editor=e, extra=extra)
760 editor=e, extra=extra)
761
761
762 branch = repo[None].branch()
762 branch = repo[None].branch()
763 bheads = repo.branchheads(branch)
763 bheads = repo.branchheads(branch)
764
764
765 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
765 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
766 if not node:
766 if not node:
767 ui.status(_("nothing changed\n"))
767 ui.status(_("nothing changed\n"))
768 return 1
768 return 1
769
769
770 ctx = repo[node]
770 ctx = repo[node]
771 parents = ctx.parents()
771 parents = ctx.parents()
772
772
773 if bheads and not [x for x in parents
773 if bheads and not [x for x in parents
774 if x.node() in bheads and x.branch() == branch]:
774 if x.node() in bheads and x.branch() == branch]:
775 ui.status(_('created new head\n'))
775 ui.status(_('created new head\n'))
776 # The message is not printed for initial roots. For the other
776 # The message is not printed for initial roots. For the other
777 # changesets, it is printed in the following situations:
777 # changesets, it is printed in the following situations:
778 #
778 #
779 # Par column: for the 2 parents with ...
779 # Par column: for the 2 parents with ...
780 # N: null or no parent
780 # N: null or no parent
781 # B: parent is on another named branch
781 # B: parent is on another named branch
782 # C: parent is a regular non head changeset
782 # C: parent is a regular non head changeset
783 # H: parent was a branch head of the current branch
783 # H: parent was a branch head of the current branch
784 # Msg column: whether we print "created new head" message
784 # Msg column: whether we print "created new head" message
785 # In the following, it is assumed that there already exists some
785 # In the following, it is assumed that there already exists some
786 # initial branch heads of the current branch, otherwise nothing is
786 # initial branch heads of the current branch, otherwise nothing is
787 # printed anyway.
787 # printed anyway.
788 #
788 #
789 # Par Msg Comment
789 # Par Msg Comment
790 # NN y additional topo root
790 # NN y additional topo root
791 #
791 #
792 # BN y additional branch root
792 # BN y additional branch root
793 # CN y additional topo head
793 # CN y additional topo head
794 # HN n usual case
794 # HN n usual case
795 #
795 #
796 # BB y weird additional branch root
796 # BB y weird additional branch root
797 # CB y branch merge
797 # CB y branch merge
798 # HB n merge with named branch
798 # HB n merge with named branch
799 #
799 #
800 # CC y additional head from merge
800 # CC y additional head from merge
801 # CH n merge with a head
801 # CH n merge with a head
802 #
802 #
803 # HH n head merge: head count decreases
803 # HH n head merge: head count decreases
804
804
805 if not opts.get('close_branch'):
805 if not opts.get('close_branch'):
806 for r in parents:
806 for r in parents:
807 if r.extra().get('close') and r.branch() == branch:
807 if r.extra().get('close') and r.branch() == branch:
808 ui.status(_('reopening closed branch head %d\n') % r)
808 ui.status(_('reopening closed branch head %d\n') % r)
809
809
810 if ui.debugflag:
810 if ui.debugflag:
811 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
811 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
812 elif ui.verbose:
812 elif ui.verbose:
813 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
813 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
814
814
815 def copy(ui, repo, *pats, **opts):
815 def copy(ui, repo, *pats, **opts):
816 """mark files as copied for the next commit
816 """mark files as copied for the next commit
817
817
818 Mark dest as having copies of source files. If dest is a
818 Mark dest as having copies of source files. If dest is a
819 directory, copies are put in that directory. If dest is a file,
819 directory, copies are put in that directory. If dest is a file,
820 the source must be a single file.
820 the source must be a single file.
821
821
822 By default, this command copies the contents of files as they
822 By default, this command copies the contents of files as they
823 exist in the working directory. If invoked with -A/--after, the
823 exist in the working directory. If invoked with -A/--after, the
824 operation is recorded, but no copying is performed.
824 operation is recorded, but no copying is performed.
825
825
826 This command takes effect with the next commit. To undo a copy
826 This command takes effect with the next commit. To undo a copy
827 before that, see :hg:`revert`.
827 before that, see :hg:`revert`.
828
828
829 Returns 0 on success, 1 if errors are encountered.
829 Returns 0 on success, 1 if errors are encountered.
830 """
830 """
831 wlock = repo.wlock(False)
831 wlock = repo.wlock(False)
832 try:
832 try:
833 return cmdutil.copy(ui, repo, pats, opts)
833 return cmdutil.copy(ui, repo, pats, opts)
834 finally:
834 finally:
835 wlock.release()
835 wlock.release()
836
836
837 def debugancestor(ui, repo, *args):
837 def debugancestor(ui, repo, *args):
838 """find the ancestor revision of two revisions in a given index"""
838 """find the ancestor revision of two revisions in a given index"""
839 if len(args) == 3:
839 if len(args) == 3:
840 index, rev1, rev2 = args
840 index, rev1, rev2 = args
841 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
841 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
842 lookup = r.lookup
842 lookup = r.lookup
843 elif len(args) == 2:
843 elif len(args) == 2:
844 if not repo:
844 if not repo:
845 raise util.Abort(_("there is no Mercurial repository here "
845 raise util.Abort(_("there is no Mercurial repository here "
846 "(.hg not found)"))
846 "(.hg not found)"))
847 rev1, rev2 = args
847 rev1, rev2 = args
848 r = repo.changelog
848 r = repo.changelog
849 lookup = repo.lookup
849 lookup = repo.lookup
850 else:
850 else:
851 raise util.Abort(_('either two or three arguments required'))
851 raise util.Abort(_('either two or three arguments required'))
852 a = r.ancestor(lookup(rev1), lookup(rev2))
852 a = r.ancestor(lookup(rev1), lookup(rev2))
853 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
853 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
854
854
855 def debugbuilddag(ui, repo, text,
855 def debugbuilddag(ui, repo, text,
856 mergeable_file=False,
856 mergeable_file=False,
857 appended_file=False,
857 appended_file=False,
858 overwritten_file=False,
858 overwritten_file=False,
859 new_file=False):
859 new_file=False):
860 """builds a repo with a given dag from scratch in the current empty repo
860 """builds a repo with a given dag from scratch in the current empty repo
861
861
862 Elements:
862 Elements:
863
863
864 - "+n" is a linear run of n nodes based on the current default parent
864 - "+n" is a linear run of n nodes based on the current default parent
865 - "." is a single node based on the current default parent
865 - "." is a single node based on the current default parent
866 - "$" resets the default parent to null (implied at the start);
866 - "$" resets the default parent to null (implied at the start);
867 otherwise the default parent is always the last node created
867 otherwise the default parent is always the last node created
868 - "<p" sets the default parent to the backref p
868 - "<p" sets the default parent to the backref p
869 - "*p" is a fork at parent p, which is a backref
869 - "*p" is a fork at parent p, which is a backref
870 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
870 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
871 - "/p2" is a merge of the preceding node and p2
871 - "/p2" is a merge of the preceding node and p2
872 - ":tag" defines a local tag for the preceding node
872 - ":tag" defines a local tag for the preceding node
873 - "@branch" sets the named branch for subsequent nodes
873 - "@branch" sets the named branch for subsequent nodes
874 - "!command" runs the command using your shell
874 - "!command" runs the command using your shell
875 - "!!my command\\n" is like "!", but to the end of the line
875 - "!!my command\\n" is like "!", but to the end of the line
876 - "#...\\n" is a comment up to the end of the line
876 - "#...\\n" is a comment up to the end of the line
877
877
878 Whitespace between the above elements is ignored.
878 Whitespace between the above elements is ignored.
879
879
880 A backref is either
880 A backref is either
881
881
882 - a number n, which references the node curr-n, where curr is the current
882 - a number n, which references the node curr-n, where curr is the current
883 node, or
883 node, or
884 - the name of a local tag you placed earlier using ":tag", or
884 - the name of a local tag you placed earlier using ":tag", or
885 - empty to denote the default parent.
885 - empty to denote the default parent.
886
886
887 All string valued-elements are either strictly alphanumeric, or must
887 All string valued-elements are either strictly alphanumeric, or must
888 be enclosed in double quotes ("..."), with "\\" as escape character.
888 be enclosed in double quotes ("..."), with "\\" as escape character.
889
889
890 Note that the --overwritten-file and --appended-file options imply the
890 Note that the --overwritten-file and --appended-file options imply the
891 use of "HGMERGE=internal:local" during DAG buildup.
891 use of "HGMERGE=internal:local" during DAG buildup.
892 """
892 """
893
893
894 if not (mergeable_file or appended_file or overwritten_file or new_file):
894 if not (mergeable_file or appended_file or overwritten_file or new_file):
895 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
895 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
896
896
897 if len(repo.changelog) > 0:
897 if len(repo.changelog) > 0:
898 raise util.Abort(_('repository is not empty'))
898 raise util.Abort(_('repository is not empty'))
899
899
900 if overwritten_file or appended_file:
900 if overwritten_file or appended_file:
901 # we don't want to fail in merges during buildup
901 # we don't want to fail in merges during buildup
902 os.environ['HGMERGE'] = 'internal:local'
902 os.environ['HGMERGE'] = 'internal:local'
903
903
904 def writefile(fname, text, fmode="wb"):
904 def writefile(fname, text, fmode="wb"):
905 f = open(fname, fmode)
905 f = open(fname, fmode)
906 try:
906 try:
907 f.write(text)
907 f.write(text)
908 finally:
908 finally:
909 f.close()
909 f.close()
910
910
911 if mergeable_file:
911 if mergeable_file:
912 linesperrev = 2
912 linesperrev = 2
913 # determine number of revs in DAG
913 # determine number of revs in DAG
914 n = 0
914 n = 0
915 for type, data in dagparser.parsedag(text):
915 for type, data in dagparser.parsedag(text):
916 if type == 'n':
916 if type == 'n':
917 n += 1
917 n += 1
918 # make a file with k lines per rev
918 # make a file with k lines per rev
919 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
919 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
920 + "\n")
920 + "\n")
921
921
922 at = -1
922 at = -1
923 atbranch = 'default'
923 atbranch = 'default'
924 for type, data in dagparser.parsedag(text):
924 for type, data in dagparser.parsedag(text):
925 if type == 'n':
925 if type == 'n':
926 ui.status('node %s\n' % str(data))
926 ui.status('node %s\n' % str(data))
927 id, ps = data
927 id, ps = data
928 p1 = ps[0]
928 p1 = ps[0]
929 if p1 != at:
929 if p1 != at:
930 update(ui, repo, node=p1, clean=True)
930 update(ui, repo, node=p1, clean=True)
931 at = p1
931 at = p1
932 if repo.dirstate.branch() != atbranch:
932 if repo.dirstate.branch() != atbranch:
933 branch(ui, repo, atbranch, force=True)
933 branch(ui, repo, atbranch, force=True)
934 if len(ps) > 1:
934 if len(ps) > 1:
935 p2 = ps[1]
935 p2 = ps[1]
936 merge(ui, repo, node=p2)
936 merge(ui, repo, node=p2)
937
937
938 if mergeable_file:
938 if mergeable_file:
939 f = open("mf", "rb+")
939 f = open("mf", "rb+")
940 try:
940 try:
941 lines = f.read().split("\n")
941 lines = f.read().split("\n")
942 lines[id * linesperrev] += " r%i" % id
942 lines[id * linesperrev] += " r%i" % id
943 f.seek(0)
943 f.seek(0)
944 f.write("\n".join(lines))
944 f.write("\n".join(lines))
945 finally:
945 finally:
946 f.close()
946 f.close()
947
947
948 if appended_file:
948 if appended_file:
949 writefile("af", "r%i\n" % id, "ab")
949 writefile("af", "r%i\n" % id, "ab")
950
950
951 if overwritten_file:
951 if overwritten_file:
952 writefile("of", "r%i\n" % id)
952 writefile("of", "r%i\n" % id)
953
953
954 if new_file:
954 if new_file:
955 writefile("nf%i" % id, "r%i\n" % id)
955 writefile("nf%i" % id, "r%i\n" % id)
956
956
957 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
957 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
958 at = id
958 at = id
959 elif type == 'l':
959 elif type == 'l':
960 id, name = data
960 id, name = data
961 ui.status('tag %s\n' % name)
961 ui.status('tag %s\n' % name)
962 tag(ui, repo, name, local=True)
962 tag(ui, repo, name, local=True)
963 elif type == 'a':
963 elif type == 'a':
964 ui.status('branch %s\n' % data)
964 ui.status('branch %s\n' % data)
965 atbranch = data
965 atbranch = data
966 elif type in 'cC':
966 elif type in 'cC':
967 r = util.system(data, cwd=repo.root)
967 r = util.system(data, cwd=repo.root)
968 if r:
968 if r:
969 desc, r = util.explain_exit(r)
969 desc, r = util.explain_exit(r)
970 raise util.Abort(_('%s command %s') % (data, desc))
970 raise util.Abort(_('%s command %s') % (data, desc))
971
971
972 def debugcommands(ui, cmd='', *args):
972 def debugcommands(ui, cmd='', *args):
973 """list all available commands and options"""
973 """list all available commands and options"""
974 for cmd, vals in sorted(table.iteritems()):
974 for cmd, vals in sorted(table.iteritems()):
975 cmd = cmd.split('|')[0].strip('^')
975 cmd = cmd.split('|')[0].strip('^')
976 opts = ', '.join([i[1] for i in vals[1]])
976 opts = ', '.join([i[1] for i in vals[1]])
977 ui.write('%s: %s\n' % (cmd, opts))
977 ui.write('%s: %s\n' % (cmd, opts))
978
978
979 def debugcomplete(ui, cmd='', **opts):
979 def debugcomplete(ui, cmd='', **opts):
980 """returns the completion list associated with the given command"""
980 """returns the completion list associated with the given command"""
981
981
982 if opts.get('options'):
982 if opts.get('options'):
983 options = []
983 options = []
984 otables = [globalopts]
984 otables = [globalopts]
985 if cmd:
985 if cmd:
986 aliases, entry = cmdutil.findcmd(cmd, table, False)
986 aliases, entry = cmdutil.findcmd(cmd, table, False)
987 otables.append(entry[1])
987 otables.append(entry[1])
988 for t in otables:
988 for t in otables:
989 for o in t:
989 for o in t:
990 if "(DEPRECATED)" in o[3]:
990 if "(DEPRECATED)" in o[3]:
991 continue
991 continue
992 if o[0]:
992 if o[0]:
993 options.append('-%s' % o[0])
993 options.append('-%s' % o[0])
994 options.append('--%s' % o[1])
994 options.append('--%s' % o[1])
995 ui.write("%s\n" % "\n".join(options))
995 ui.write("%s\n" % "\n".join(options))
996 return
996 return
997
997
998 cmdlist = cmdutil.findpossible(cmd, table)
998 cmdlist = cmdutil.findpossible(cmd, table)
999 if ui.verbose:
999 if ui.verbose:
1000 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1000 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1001 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1001 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1002
1002
1003 def debugfsinfo(ui, path = "."):
1003 def debugfsinfo(ui, path = "."):
1004 """show information detected about current filesystem"""
1004 """show information detected about current filesystem"""
1005 open('.debugfsinfo', 'w').write('')
1005 open('.debugfsinfo', 'w').write('')
1006 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1006 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1007 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1007 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1008 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1008 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1009 and 'yes' or 'no'))
1009 and 'yes' or 'no'))
1010 os.unlink('.debugfsinfo')
1010 os.unlink('.debugfsinfo')
1011
1011
1012 def debugrebuildstate(ui, repo, rev="tip"):
1012 def debugrebuildstate(ui, repo, rev="tip"):
1013 """rebuild the dirstate as it would look like for the given revision"""
1013 """rebuild the dirstate as it would look like for the given revision"""
1014 ctx = repo[rev]
1014 ctx = repo[rev]
1015 wlock = repo.wlock()
1015 wlock = repo.wlock()
1016 try:
1016 try:
1017 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1017 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1018 finally:
1018 finally:
1019 wlock.release()
1019 wlock.release()
1020
1020
1021 def debugcheckstate(ui, repo):
1021 def debugcheckstate(ui, repo):
1022 """validate the correctness of the current dirstate"""
1022 """validate the correctness of the current dirstate"""
1023 parent1, parent2 = repo.dirstate.parents()
1023 parent1, parent2 = repo.dirstate.parents()
1024 m1 = repo[parent1].manifest()
1024 m1 = repo[parent1].manifest()
1025 m2 = repo[parent2].manifest()
1025 m2 = repo[parent2].manifest()
1026 errors = 0
1026 errors = 0
1027 for f in repo.dirstate:
1027 for f in repo.dirstate:
1028 state = repo.dirstate[f]
1028 state = repo.dirstate[f]
1029 if state in "nr" and f not in m1:
1029 if state in "nr" and f not in m1:
1030 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1030 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1031 errors += 1
1031 errors += 1
1032 if state in "a" and f in m1:
1032 if state in "a" and f in m1:
1033 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1033 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1034 errors += 1
1034 errors += 1
1035 if state in "m" and f not in m1 and f not in m2:
1035 if state in "m" and f not in m1 and f not in m2:
1036 ui.warn(_("%s in state %s, but not in either manifest\n") %
1036 ui.warn(_("%s in state %s, but not in either manifest\n") %
1037 (f, state))
1037 (f, state))
1038 errors += 1
1038 errors += 1
1039 for f in m1:
1039 for f in m1:
1040 state = repo.dirstate[f]
1040 state = repo.dirstate[f]
1041 if state not in "nrm":
1041 if state not in "nrm":
1042 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1042 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1043 errors += 1
1043 errors += 1
1044 if errors:
1044 if errors:
1045 error = _(".hg/dirstate inconsistent with current parent's manifest")
1045 error = _(".hg/dirstate inconsistent with current parent's manifest")
1046 raise util.Abort(error)
1046 raise util.Abort(error)
1047
1047
1048 def showconfig(ui, repo, *values, **opts):
1048 def showconfig(ui, repo, *values, **opts):
1049 """show combined config settings from all hgrc files
1049 """show combined config settings from all hgrc files
1050
1050
1051 With no arguments, print names and values of all config items.
1051 With no arguments, print names and values of all config items.
1052
1052
1053 With one argument of the form section.name, print just the value
1053 With one argument of the form section.name, print just the value
1054 of that config item.
1054 of that config item.
1055
1055
1056 With multiple arguments, print names and values of all config
1056 With multiple arguments, print names and values of all config
1057 items with matching section names.
1057 items with matching section names.
1058
1058
1059 With --debug, the source (filename and line number) is printed
1059 With --debug, the source (filename and line number) is printed
1060 for each config item.
1060 for each config item.
1061
1061
1062 Returns 0 on success.
1062 Returns 0 on success.
1063 """
1063 """
1064
1064
1065 for f in util.rcpath():
1065 for f in util.rcpath():
1066 ui.debug(_('read config from: %s\n') % f)
1066 ui.debug(_('read config from: %s\n') % f)
1067 untrusted = bool(opts.get('untrusted'))
1067 untrusted = bool(opts.get('untrusted'))
1068 if values:
1068 if values:
1069 if len([v for v in values if '.' in v]) > 1:
1069 if len([v for v in values if '.' in v]) > 1:
1070 raise util.Abort(_('only one config item permitted'))
1070 raise util.Abort(_('only one config item permitted'))
1071 for section, name, value in ui.walkconfig(untrusted=untrusted):
1071 for section, name, value in ui.walkconfig(untrusted=untrusted):
1072 sectname = section + '.' + name
1072 sectname = section + '.' + name
1073 if values:
1073 if values:
1074 for v in values:
1074 for v in values:
1075 if v == section:
1075 if v == section:
1076 ui.debug('%s: ' %
1076 ui.debug('%s: ' %
1077 ui.configsource(section, name, untrusted))
1077 ui.configsource(section, name, untrusted))
1078 ui.write('%s=%s\n' % (sectname, value))
1078 ui.write('%s=%s\n' % (sectname, value))
1079 elif v == sectname:
1079 elif v == sectname:
1080 ui.debug('%s: ' %
1080 ui.debug('%s: ' %
1081 ui.configsource(section, name, untrusted))
1081 ui.configsource(section, name, untrusted))
1082 ui.write(value, '\n')
1082 ui.write(value, '\n')
1083 else:
1083 else:
1084 ui.debug('%s: ' %
1084 ui.debug('%s: ' %
1085 ui.configsource(section, name, untrusted))
1085 ui.configsource(section, name, untrusted))
1086 ui.write('%s=%s\n' % (sectname, value))
1086 ui.write('%s=%s\n' % (sectname, value))
1087
1087
1088 def debugpushkey(ui, repopath, namespace, *keyinfo):
1088 def debugpushkey(ui, repopath, namespace, *keyinfo):
1089 '''access the pushkey key/value protocol
1089 '''access the pushkey key/value protocol
1090
1090
1091 With two args, list the keys in the given namespace.
1091 With two args, list the keys in the given namespace.
1092
1092
1093 With five args, set a key to new if it currently is set to old.
1093 With five args, set a key to new if it currently is set to old.
1094 Reports success or failure.
1094 Reports success or failure.
1095 '''
1095 '''
1096
1096
1097 target = hg.repository(ui, repopath)
1097 target = hg.repository(ui, repopath)
1098 if keyinfo:
1098 if keyinfo:
1099 key, old, new = keyinfo
1099 key, old, new = keyinfo
1100 r = target.pushkey(namespace, key, old, new)
1100 r = target.pushkey(namespace, key, old, new)
1101 ui.status(str(r) + '\n')
1101 ui.status(str(r) + '\n')
1102 return not(r)
1102 return not(r)
1103 else:
1103 else:
1104 for k, v in target.listkeys(namespace).iteritems():
1104 for k, v in target.listkeys(namespace).iteritems():
1105 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1105 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1106 v.encode('string-escape')))
1106 v.encode('string-escape')))
1107
1107
1108 def debugrevspec(ui, repo, expr):
1108 def debugrevspec(ui, repo, expr):
1109 '''parse and apply a revision specification'''
1109 '''parse and apply a revision specification'''
1110 if ui.verbose:
1110 if ui.verbose:
1111 tree = revset.parse(expr)
1111 tree = revset.parse(expr)
1112 ui.note(tree, "\n")
1112 ui.note(tree, "\n")
1113 func = revset.match(expr)
1113 func = revset.match(expr)
1114 for c in func(repo, range(len(repo))):
1114 for c in func(repo, range(len(repo))):
1115 ui.write("%s\n" % c)
1115 ui.write("%s\n" % c)
1116
1116
1117 def debugsetparents(ui, repo, rev1, rev2=None):
1117 def debugsetparents(ui, repo, rev1, rev2=None):
1118 """manually set the parents of the current working directory
1118 """manually set the parents of the current working directory
1119
1119
1120 This is useful for writing repository conversion tools, but should
1120 This is useful for writing repository conversion tools, but should
1121 be used with care.
1121 be used with care.
1122
1122
1123 Returns 0 on success.
1123 Returns 0 on success.
1124 """
1124 """
1125
1125
1126 if not rev2:
1126 if not rev2:
1127 rev2 = hex(nullid)
1127 rev2 = hex(nullid)
1128
1128
1129 wlock = repo.wlock()
1129 wlock = repo.wlock()
1130 try:
1130 try:
1131 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1131 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1132 finally:
1132 finally:
1133 wlock.release()
1133 wlock.release()
1134
1134
1135 def debugstate(ui, repo, nodates=None):
1135 def debugstate(ui, repo, nodates=None):
1136 """show the contents of the current dirstate"""
1136 """show the contents of the current dirstate"""
1137 timestr = ""
1137 timestr = ""
1138 showdate = not nodates
1138 showdate = not nodates
1139 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1139 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1140 if showdate:
1140 if showdate:
1141 if ent[3] == -1:
1141 if ent[3] == -1:
1142 # Pad or slice to locale representation
1142 # Pad or slice to locale representation
1143 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1143 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1144 time.localtime(0)))
1144 time.localtime(0)))
1145 timestr = 'unset'
1145 timestr = 'unset'
1146 timestr = (timestr[:locale_len] +
1146 timestr = (timestr[:locale_len] +
1147 ' ' * (locale_len - len(timestr)))
1147 ' ' * (locale_len - len(timestr)))
1148 else:
1148 else:
1149 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1149 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1150 time.localtime(ent[3]))
1150 time.localtime(ent[3]))
1151 if ent[1] & 020000:
1151 if ent[1] & 020000:
1152 mode = 'lnk'
1152 mode = 'lnk'
1153 else:
1153 else:
1154 mode = '%3o' % (ent[1] & 0777)
1154 mode = '%3o' % (ent[1] & 0777)
1155 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1155 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1156 for f in repo.dirstate.copies():
1156 for f in repo.dirstate.copies():
1157 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1157 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1158
1158
1159 def debugsub(ui, repo, rev=None):
1159 def debugsub(ui, repo, rev=None):
1160 if rev == '':
1160 if rev == '':
1161 rev = None
1161 rev = None
1162 for k, v in sorted(repo[rev].substate.items()):
1162 for k, v in sorted(repo[rev].substate.items()):
1163 ui.write('path %s\n' % k)
1163 ui.write('path %s\n' % k)
1164 ui.write(' source %s\n' % v[0])
1164 ui.write(' source %s\n' % v[0])
1165 ui.write(' revision %s\n' % v[1])
1165 ui.write(' revision %s\n' % v[1])
1166
1166
1167 def debugdag(ui, repo, file_=None, *revs, **opts):
1167 def debugdag(ui, repo, file_=None, *revs, **opts):
1168 """format the changelog or an index DAG as a concise textual description
1168 """format the changelog or an index DAG as a concise textual description
1169
1169
1170 If you pass a revlog index, the revlog's DAG is emitted. If you list
1170 If you pass a revlog index, the revlog's DAG is emitted. If you list
1171 revision numbers, they get labelled in the output as rN.
1171 revision numbers, they get labelled in the output as rN.
1172
1172
1173 Otherwise, the changelog DAG of the current repo is emitted.
1173 Otherwise, the changelog DAG of the current repo is emitted.
1174 """
1174 """
1175 spaces = opts.get('spaces')
1175 spaces = opts.get('spaces')
1176 dots = opts.get('dots')
1176 dots = opts.get('dots')
1177 if file_:
1177 if file_:
1178 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1178 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1179 revs = set((int(r) for r in revs))
1179 revs = set((int(r) for r in revs))
1180 def events():
1180 def events():
1181 for r in rlog:
1181 for r in rlog:
1182 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1182 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1183 if r in revs:
1183 if r in revs:
1184 yield 'l', (r, "r%i" % r)
1184 yield 'l', (r, "r%i" % r)
1185 elif repo:
1185 elif repo:
1186 cl = repo.changelog
1186 cl = repo.changelog
1187 tags = opts.get('tags')
1187 tags = opts.get('tags')
1188 branches = opts.get('branches')
1188 branches = opts.get('branches')
1189 if tags:
1189 if tags:
1190 labels = {}
1190 labels = {}
1191 for l, n in repo.tags().items():
1191 for l, n in repo.tags().items():
1192 labels.setdefault(cl.rev(n), []).append(l)
1192 labels.setdefault(cl.rev(n), []).append(l)
1193 def events():
1193 def events():
1194 b = "default"
1194 b = "default"
1195 for r in cl:
1195 for r in cl:
1196 if branches:
1196 if branches:
1197 newb = cl.read(cl.node(r))[5]['branch']
1197 newb = cl.read(cl.node(r))[5]['branch']
1198 if newb != b:
1198 if newb != b:
1199 yield 'a', newb
1199 yield 'a', newb
1200 b = newb
1200 b = newb
1201 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1201 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1202 if tags:
1202 if tags:
1203 ls = labels.get(r)
1203 ls = labels.get(r)
1204 if ls:
1204 if ls:
1205 for l in ls:
1205 for l in ls:
1206 yield 'l', (r, l)
1206 yield 'l', (r, l)
1207 else:
1207 else:
1208 raise util.Abort(_('need repo for changelog dag'))
1208 raise util.Abort(_('need repo for changelog dag'))
1209
1209
1210 for line in dagparser.dagtextlines(events(),
1210 for line in dagparser.dagtextlines(events(),
1211 addspaces=spaces,
1211 addspaces=spaces,
1212 wraplabels=True,
1212 wraplabels=True,
1213 wrapannotations=True,
1213 wrapannotations=True,
1214 wrapnonlinear=dots,
1214 wrapnonlinear=dots,
1215 usedots=dots,
1215 usedots=dots,
1216 maxlinewidth=70):
1216 maxlinewidth=70):
1217 ui.write(line)
1217 ui.write(line)
1218 ui.write("\n")
1218 ui.write("\n")
1219
1219
1220 def debugdata(ui, repo, file_, rev):
1220 def debugdata(ui, repo, file_, rev):
1221 """dump the contents of a data file revision"""
1221 """dump the contents of a data file revision"""
1222 r = None
1222 r = None
1223 if repo:
1223 if repo:
1224 filelog = repo.file(file_)
1224 filelog = repo.file(file_)
1225 if len(filelog):
1225 if len(filelog):
1226 r = filelog
1226 r = filelog
1227 if not r:
1227 if not r:
1228 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1228 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1229 try:
1229 try:
1230 ui.write(r.revision(r.lookup(rev)))
1230 ui.write(r.revision(r.lookup(rev)))
1231 except KeyError:
1231 except KeyError:
1232 raise util.Abort(_('invalid revision identifier %s') % rev)
1232 raise util.Abort(_('invalid revision identifier %s') % rev)
1233
1233
1234 def debugdate(ui, date, range=None, **opts):
1234 def debugdate(ui, date, range=None, **opts):
1235 """parse and display a date"""
1235 """parse and display a date"""
1236 if opts["extended"]:
1236 if opts["extended"]:
1237 d = util.parsedate(date, util.extendeddateformats)
1237 d = util.parsedate(date, util.extendeddateformats)
1238 else:
1238 else:
1239 d = util.parsedate(date)
1239 d = util.parsedate(date)
1240 ui.write("internal: %s %s\n" % d)
1240 ui.write("internal: %s %s\n" % d)
1241 ui.write("standard: %s\n" % util.datestr(d))
1241 ui.write("standard: %s\n" % util.datestr(d))
1242 if range:
1242 if range:
1243 m = util.matchdate(range)
1243 m = util.matchdate(range)
1244 ui.write("match: %s\n" % m(d[0]))
1244 ui.write("match: %s\n" % m(d[0]))
1245
1245
1246 def debugindex(ui, repo, file_):
1246 def debugindex(ui, repo, file_):
1247 """dump the contents of an index file"""
1247 """dump the contents of an index file"""
1248 r = None
1248 r = None
1249 if repo:
1249 if repo:
1250 filelog = repo.file(file_)
1250 filelog = repo.file(file_)
1251 if len(filelog):
1251 if len(filelog):
1252 r = filelog
1252 r = filelog
1253 if not r:
1253 if not r:
1254 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1254 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1255 ui.write(" rev offset length base linkrev"
1255 ui.write(" rev offset length base linkrev"
1256 " nodeid p1 p2\n")
1256 " nodeid p1 p2\n")
1257 for i in r:
1257 for i in r:
1258 node = r.node(i)
1258 node = r.node(i)
1259 try:
1259 try:
1260 pp = r.parents(node)
1260 pp = r.parents(node)
1261 except:
1261 except:
1262 pp = [nullid, nullid]
1262 pp = [nullid, nullid]
1263 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1263 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1264 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1264 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1265 short(node), short(pp[0]), short(pp[1])))
1265 short(node), short(pp[0]), short(pp[1])))
1266
1266
1267 def debugindexdot(ui, repo, file_):
1267 def debugindexdot(ui, repo, file_):
1268 """dump an index DAG as a graphviz dot file"""
1268 """dump an index DAG as a graphviz dot file"""
1269 r = None
1269 r = None
1270 if repo:
1270 if repo:
1271 filelog = repo.file(file_)
1271 filelog = repo.file(file_)
1272 if len(filelog):
1272 if len(filelog):
1273 r = filelog
1273 r = filelog
1274 if not r:
1274 if not r:
1275 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1275 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1276 ui.write("digraph G {\n")
1276 ui.write("digraph G {\n")
1277 for i in r:
1277 for i in r:
1278 node = r.node(i)
1278 node = r.node(i)
1279 pp = r.parents(node)
1279 pp = r.parents(node)
1280 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1280 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1281 if pp[1] != nullid:
1281 if pp[1] != nullid:
1282 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1282 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1283 ui.write("}\n")
1283 ui.write("}\n")
1284
1284
1285 def debuginstall(ui):
1285 def debuginstall(ui):
1286 '''test Mercurial installation
1286 '''test Mercurial installation
1287
1287
1288 Returns 0 on success.
1288 Returns 0 on success.
1289 '''
1289 '''
1290
1290
1291 def writetemp(contents):
1291 def writetemp(contents):
1292 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1292 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1293 f = os.fdopen(fd, "wb")
1293 f = os.fdopen(fd, "wb")
1294 f.write(contents)
1294 f.write(contents)
1295 f.close()
1295 f.close()
1296 return name
1296 return name
1297
1297
1298 problems = 0
1298 problems = 0
1299
1299
1300 # encoding
1300 # encoding
1301 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1301 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1302 try:
1302 try:
1303 encoding.fromlocal("test")
1303 encoding.fromlocal("test")
1304 except util.Abort, inst:
1304 except util.Abort, inst:
1305 ui.write(" %s\n" % inst)
1305 ui.write(" %s\n" % inst)
1306 ui.write(_(" (check that your locale is properly set)\n"))
1306 ui.write(_(" (check that your locale is properly set)\n"))
1307 problems += 1
1307 problems += 1
1308
1308
1309 # compiled modules
1309 # compiled modules
1310 ui.status(_("Checking installed modules (%s)...\n")
1310 ui.status(_("Checking installed modules (%s)...\n")
1311 % os.path.dirname(__file__))
1311 % os.path.dirname(__file__))
1312 try:
1312 try:
1313 import bdiff, mpatch, base85, osutil
1313 import bdiff, mpatch, base85, osutil
1314 except Exception, inst:
1314 except Exception, inst:
1315 ui.write(" %s\n" % inst)
1315 ui.write(" %s\n" % inst)
1316 ui.write(_(" One or more extensions could not be found"))
1316 ui.write(_(" One or more extensions could not be found"))
1317 ui.write(_(" (check that you compiled the extensions)\n"))
1317 ui.write(_(" (check that you compiled the extensions)\n"))
1318 problems += 1
1318 problems += 1
1319
1319
1320 # templates
1320 # templates
1321 ui.status(_("Checking templates...\n"))
1321 ui.status(_("Checking templates...\n"))
1322 try:
1322 try:
1323 import templater
1323 import templater
1324 templater.templater(templater.templatepath("map-cmdline.default"))
1324 templater.templater(templater.templatepath("map-cmdline.default"))
1325 except Exception, inst:
1325 except Exception, inst:
1326 ui.write(" %s\n" % inst)
1326 ui.write(" %s\n" % inst)
1327 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1327 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1328 problems += 1
1328 problems += 1
1329
1329
1330 # patch
1330 # patch
1331 ui.status(_("Checking patch...\n"))
1331 ui.status(_("Checking patch...\n"))
1332 patchproblems = 0
1332 patchproblems = 0
1333 a = "1\n2\n3\n4\n"
1333 a = "1\n2\n3\n4\n"
1334 b = "1\n2\n3\ninsert\n4\n"
1334 b = "1\n2\n3\ninsert\n4\n"
1335 fa = writetemp(a)
1335 fa = writetemp(a)
1336 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1336 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1337 os.path.basename(fa))
1337 os.path.basename(fa))
1338 fd = writetemp(d)
1338 fd = writetemp(d)
1339
1339
1340 files = {}
1340 files = {}
1341 try:
1341 try:
1342 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1342 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1343 except util.Abort, e:
1343 except util.Abort, e:
1344 ui.write(_(" patch call failed:\n"))
1344 ui.write(_(" patch call failed:\n"))
1345 ui.write(" " + str(e) + "\n")
1345 ui.write(" " + str(e) + "\n")
1346 patchproblems += 1
1346 patchproblems += 1
1347 else:
1347 else:
1348 if list(files) != [os.path.basename(fa)]:
1348 if list(files) != [os.path.basename(fa)]:
1349 ui.write(_(" unexpected patch output!\n"))
1349 ui.write(_(" unexpected patch output!\n"))
1350 patchproblems += 1
1350 patchproblems += 1
1351 a = open(fa).read()
1351 a = open(fa).read()
1352 if a != b:
1352 if a != b:
1353 ui.write(_(" patch test failed!\n"))
1353 ui.write(_(" patch test failed!\n"))
1354 patchproblems += 1
1354 patchproblems += 1
1355
1355
1356 if patchproblems:
1356 if patchproblems:
1357 if ui.config('ui', 'patch'):
1357 if ui.config('ui', 'patch'):
1358 ui.write(_(" (Current patch tool may be incompatible with patch,"
1358 ui.write(_(" (Current patch tool may be incompatible with patch,"
1359 " or misconfigured. Please check your configuration"
1359 " or misconfigured. Please check your configuration"
1360 " file)\n"))
1360 " file)\n"))
1361 else:
1361 else:
1362 ui.write(_(" Internal patcher failure, please report this error"
1362 ui.write(_(" Internal patcher failure, please report this error"
1363 " to http://mercurial.selenic.com/bts/\n"))
1363 " to http://mercurial.selenic.com/bts/\n"))
1364 problems += patchproblems
1364 problems += patchproblems
1365
1365
1366 os.unlink(fa)
1366 os.unlink(fa)
1367 os.unlink(fd)
1367 os.unlink(fd)
1368
1368
1369 # editor
1369 # editor
1370 ui.status(_("Checking commit editor...\n"))
1370 ui.status(_("Checking commit editor...\n"))
1371 editor = ui.geteditor()
1371 editor = ui.geteditor()
1372 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1372 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1373 if not cmdpath:
1373 if not cmdpath:
1374 if editor == 'vi':
1374 if editor == 'vi':
1375 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1375 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1376 ui.write(_(" (specify a commit editor in your configuration"
1376 ui.write(_(" (specify a commit editor in your configuration"
1377 " file)\n"))
1377 " file)\n"))
1378 else:
1378 else:
1379 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1379 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1380 ui.write(_(" (specify a commit editor in your configuration"
1380 ui.write(_(" (specify a commit editor in your configuration"
1381 " file)\n"))
1381 " file)\n"))
1382 problems += 1
1382 problems += 1
1383
1383
1384 # check username
1384 # check username
1385 ui.status(_("Checking username...\n"))
1385 ui.status(_("Checking username...\n"))
1386 try:
1386 try:
1387 ui.username()
1387 ui.username()
1388 except util.Abort, e:
1388 except util.Abort, e:
1389 ui.write(" %s\n" % e)
1389 ui.write(" %s\n" % e)
1390 ui.write(_(" (specify a username in your configuration file)\n"))
1390 ui.write(_(" (specify a username in your configuration file)\n"))
1391 problems += 1
1391 problems += 1
1392
1392
1393 if not problems:
1393 if not problems:
1394 ui.status(_("No problems detected\n"))
1394 ui.status(_("No problems detected\n"))
1395 else:
1395 else:
1396 ui.write(_("%s problems detected,"
1396 ui.write(_("%s problems detected,"
1397 " please check your install!\n") % problems)
1397 " please check your install!\n") % problems)
1398
1398
1399 return problems
1399 return problems
1400
1400
1401 def debugrename(ui, repo, file1, *pats, **opts):
1401 def debugrename(ui, repo, file1, *pats, **opts):
1402 """dump rename information"""
1402 """dump rename information"""
1403
1403
1404 ctx = repo[opts.get('rev')]
1404 ctx = repo[opts.get('rev')]
1405 m = cmdutil.match(repo, (file1,) + pats, opts)
1405 m = cmdutil.match(repo, (file1,) + pats, opts)
1406 for abs in ctx.walk(m):
1406 for abs in ctx.walk(m):
1407 fctx = ctx[abs]
1407 fctx = ctx[abs]
1408 o = fctx.filelog().renamed(fctx.filenode())
1408 o = fctx.filelog().renamed(fctx.filenode())
1409 rel = m.rel(abs)
1409 rel = m.rel(abs)
1410 if o:
1410 if o:
1411 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1411 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1412 else:
1412 else:
1413 ui.write(_("%s not renamed\n") % rel)
1413 ui.write(_("%s not renamed\n") % rel)
1414
1414
1415 def debugwalk(ui, repo, *pats, **opts):
1415 def debugwalk(ui, repo, *pats, **opts):
1416 """show how files match on given patterns"""
1416 """show how files match on given patterns"""
1417 m = cmdutil.match(repo, pats, opts)
1417 m = cmdutil.match(repo, pats, opts)
1418 items = list(repo.walk(m))
1418 items = list(repo.walk(m))
1419 if not items:
1419 if not items:
1420 return
1420 return
1421 fmt = 'f %%-%ds %%-%ds %%s' % (
1421 fmt = 'f %%-%ds %%-%ds %%s' % (
1422 max([len(abs) for abs in items]),
1422 max([len(abs) for abs in items]),
1423 max([len(m.rel(abs)) for abs in items]))
1423 max([len(m.rel(abs)) for abs in items]))
1424 for abs in items:
1424 for abs in items:
1425 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1425 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1426 ui.write("%s\n" % line.rstrip())
1426 ui.write("%s\n" % line.rstrip())
1427
1427
1428 def diff(ui, repo, *pats, **opts):
1428 def diff(ui, repo, *pats, **opts):
1429 """diff repository (or selected files)
1429 """diff repository (or selected files)
1430
1430
1431 Show differences between revisions for the specified files.
1431 Show differences between revisions for the specified files.
1432
1432
1433 Differences between files are shown using the unified diff format.
1433 Differences between files are shown using the unified diff format.
1434
1434
1435 .. note::
1435 .. note::
1436 diff may generate unexpected results for merges, as it will
1436 diff may generate unexpected results for merges, as it will
1437 default to comparing against the working directory's first
1437 default to comparing against the working directory's first
1438 parent changeset if no revisions are specified.
1438 parent changeset if no revisions are specified.
1439
1439
1440 When two revision arguments are given, then changes are shown
1440 When two revision arguments are given, then changes are shown
1441 between those revisions. If only one revision is specified then
1441 between those revisions. If only one revision is specified then
1442 that revision is compared to the working directory, and, when no
1442 that revision is compared to the working directory, and, when no
1443 revisions are specified, the working directory files are compared
1443 revisions are specified, the working directory files are compared
1444 to its parent.
1444 to its parent.
1445
1445
1446 Alternatively you can specify -c/--change with a revision to see
1446 Alternatively you can specify -c/--change with a revision to see
1447 the changes in that changeset relative to its first parent.
1447 the changes in that changeset relative to its first parent.
1448
1448
1449 Without the -a/--text option, diff will avoid generating diffs of
1449 Without the -a/--text option, diff will avoid generating diffs of
1450 files it detects as binary. With -a, diff will generate a diff
1450 files it detects as binary. With -a, diff will generate a diff
1451 anyway, probably with undesirable results.
1451 anyway, probably with undesirable results.
1452
1452
1453 Use the -g/--git option to generate diffs in the git extended diff
1453 Use the -g/--git option to generate diffs in the git extended diff
1454 format. For more information, read :hg:`help diffs`.
1454 format. For more information, read :hg:`help diffs`.
1455
1455
1456 Returns 0 on success.
1456 Returns 0 on success.
1457 """
1457 """
1458
1458
1459 revs = opts.get('rev')
1459 revs = opts.get('rev')
1460 change = opts.get('change')
1460 change = opts.get('change')
1461 stat = opts.get('stat')
1461 stat = opts.get('stat')
1462 reverse = opts.get('reverse')
1462 reverse = opts.get('reverse')
1463
1463
1464 if revs and change:
1464 if revs and change:
1465 msg = _('cannot specify --rev and --change at the same time')
1465 msg = _('cannot specify --rev and --change at the same time')
1466 raise util.Abort(msg)
1466 raise util.Abort(msg)
1467 elif change:
1467 elif change:
1468 node2 = repo.lookup(change)
1468 node2 = repo.lookup(change)
1469 node1 = repo[node2].parents()[0].node()
1469 node1 = repo[node2].parents()[0].node()
1470 else:
1470 else:
1471 node1, node2 = cmdutil.revpair(repo, revs)
1471 node1, node2 = cmdutil.revpair(repo, revs)
1472
1472
1473 if reverse:
1473 if reverse:
1474 node1, node2 = node2, node1
1474 node1, node2 = node2, node1
1475
1475
1476 diffopts = patch.diffopts(ui, opts)
1476 diffopts = patch.diffopts(ui, opts)
1477 m = cmdutil.match(repo, pats, opts)
1477 m = cmdutil.match(repo, pats, opts)
1478 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1478 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1479 listsubrepos=opts.get('subrepos'))
1479 listsubrepos=opts.get('subrepos'))
1480
1480
1481 def export(ui, repo, *changesets, **opts):
1481 def export(ui, repo, *changesets, **opts):
1482 """dump the header and diffs for one or more changesets
1482 """dump the header and diffs for one or more changesets
1483
1483
1484 Print the changeset header and diffs for one or more revisions.
1484 Print the changeset header and diffs for one or more revisions.
1485
1485
1486 The information shown in the changeset header is: author, date,
1486 The information shown in the changeset header is: author, date,
1487 branch name (if non-default), changeset hash, parent(s) and commit
1487 branch name (if non-default), changeset hash, parent(s) and commit
1488 comment.
1488 comment.
1489
1489
1490 NOTE: export may generate unexpected diff output for merge
1490 .. note::
1491 changesets, as it will compare the merge changeset against its
1491 export may generate unexpected diff output for merge
1492 first parent only.
1492 changesets, as it will compare the merge changeset against its
1493 first parent only.
1493
1494
1494 Output may be to a file, in which case the name of the file is
1495 Output may be to a file, in which case the name of the file is
1495 given using a format string. The formatting rules are as follows:
1496 given using a format string. The formatting rules are as follows:
1496
1497
1497 :``%%``: literal "%" character
1498 :``%%``: literal "%" character
1498 :``%H``: changeset hash (40 hexadecimal digits)
1499 :``%H``: changeset hash (40 hexadecimal digits)
1499 :``%N``: number of patches being generated
1500 :``%N``: number of patches being generated
1500 :``%R``: changeset revision number
1501 :``%R``: changeset revision number
1501 :``%b``: basename of the exporting repository
1502 :``%b``: basename of the exporting repository
1502 :``%h``: short-form changeset hash (12 hexadecimal digits)
1503 :``%h``: short-form changeset hash (12 hexadecimal digits)
1503 :``%n``: zero-padded sequence number, starting at 1
1504 :``%n``: zero-padded sequence number, starting at 1
1504 :``%r``: zero-padded changeset revision number
1505 :``%r``: zero-padded changeset revision number
1505
1506
1506 Without the -a/--text option, export will avoid generating diffs
1507 Without the -a/--text option, export will avoid generating diffs
1507 of files it detects as binary. With -a, export will generate a
1508 of files it detects as binary. With -a, export will generate a
1508 diff anyway, probably with undesirable results.
1509 diff anyway, probably with undesirable results.
1509
1510
1510 Use the -g/--git option to generate diffs in the git extended diff
1511 Use the -g/--git option to generate diffs in the git extended diff
1511 format. See :hg:`help diffs` for more information.
1512 format. See :hg:`help diffs` for more information.
1512
1513
1513 With the --switch-parent option, the diff will be against the
1514 With the --switch-parent option, the diff will be against the
1514 second parent. It can be useful to review a merge.
1515 second parent. It can be useful to review a merge.
1515
1516
1516 Returns 0 on success.
1517 Returns 0 on success.
1517 """
1518 """
1518 changesets += tuple(opts.get('rev', []))
1519 changesets += tuple(opts.get('rev', []))
1519 if not changesets:
1520 if not changesets:
1520 raise util.Abort(_("export requires at least one changeset"))
1521 raise util.Abort(_("export requires at least one changeset"))
1521 revs = cmdutil.revrange(repo, changesets)
1522 revs = cmdutil.revrange(repo, changesets)
1522 if len(revs) > 1:
1523 if len(revs) > 1:
1523 ui.note(_('exporting patches:\n'))
1524 ui.note(_('exporting patches:\n'))
1524 else:
1525 else:
1525 ui.note(_('exporting patch:\n'))
1526 ui.note(_('exporting patch:\n'))
1526 cmdutil.export(repo, revs, template=opts.get('output'),
1527 cmdutil.export(repo, revs, template=opts.get('output'),
1527 switch_parent=opts.get('switch_parent'),
1528 switch_parent=opts.get('switch_parent'),
1528 opts=patch.diffopts(ui, opts))
1529 opts=patch.diffopts(ui, opts))
1529
1530
1530 def forget(ui, repo, *pats, **opts):
1531 def forget(ui, repo, *pats, **opts):
1531 """forget the specified files on the next commit
1532 """forget the specified files on the next commit
1532
1533
1533 Mark the specified files so they will no longer be tracked
1534 Mark the specified files so they will no longer be tracked
1534 after the next commit.
1535 after the next commit.
1535
1536
1536 This only removes files from the current branch, not from the
1537 This only removes files from the current branch, not from the
1537 entire project history, and it does not delete them from the
1538 entire project history, and it does not delete them from the
1538 working directory.
1539 working directory.
1539
1540
1540 To undo a forget before the next commit, see :hg:`add`.
1541 To undo a forget before the next commit, see :hg:`add`.
1541
1542
1542 Returns 0 on success.
1543 Returns 0 on success.
1543 """
1544 """
1544
1545
1545 if not pats:
1546 if not pats:
1546 raise util.Abort(_('no files specified'))
1547 raise util.Abort(_('no files specified'))
1547
1548
1548 m = cmdutil.match(repo, pats, opts)
1549 m = cmdutil.match(repo, pats, opts)
1549 s = repo.status(match=m, clean=True)
1550 s = repo.status(match=m, clean=True)
1550 forget = sorted(s[0] + s[1] + s[3] + s[6])
1551 forget = sorted(s[0] + s[1] + s[3] + s[6])
1551 errs = 0
1552 errs = 0
1552
1553
1553 for f in m.files():
1554 for f in m.files():
1554 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1555 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1555 ui.warn(_('not removing %s: file is already untracked\n')
1556 ui.warn(_('not removing %s: file is already untracked\n')
1556 % m.rel(f))
1557 % m.rel(f))
1557 errs = 1
1558 errs = 1
1558
1559
1559 for f in forget:
1560 for f in forget:
1560 if ui.verbose or not m.exact(f):
1561 if ui.verbose or not m.exact(f):
1561 ui.status(_('removing %s\n') % m.rel(f))
1562 ui.status(_('removing %s\n') % m.rel(f))
1562
1563
1563 repo[None].remove(forget, unlink=False)
1564 repo[None].remove(forget, unlink=False)
1564 return errs
1565 return errs
1565
1566
1566 def grep(ui, repo, pattern, *pats, **opts):
1567 def grep(ui, repo, pattern, *pats, **opts):
1567 """search for a pattern in specified files and revisions
1568 """search for a pattern in specified files and revisions
1568
1569
1569 Search revisions of files for a regular expression.
1570 Search revisions of files for a regular expression.
1570
1571
1571 This command behaves differently than Unix grep. It only accepts
1572 This command behaves differently than Unix grep. It only accepts
1572 Python/Perl regexps. It searches repository history, not the
1573 Python/Perl regexps. It searches repository history, not the
1573 working directory. It always prints the revision number in which a
1574 working directory. It always prints the revision number in which a
1574 match appears.
1575 match appears.
1575
1576
1576 By default, grep only prints output for the first revision of a
1577 By default, grep only prints output for the first revision of a
1577 file in which it finds a match. To get it to print every revision
1578 file in which it finds a match. To get it to print every revision
1578 that contains a change in match status ("-" for a match that
1579 that contains a change in match status ("-" for a match that
1579 becomes a non-match, or "+" for a non-match that becomes a match),
1580 becomes a non-match, or "+" for a non-match that becomes a match),
1580 use the --all flag.
1581 use the --all flag.
1581
1582
1582 Returns 0 if a match is found, 1 otherwise.
1583 Returns 0 if a match is found, 1 otherwise.
1583 """
1584 """
1584 reflags = 0
1585 reflags = 0
1585 if opts.get('ignore_case'):
1586 if opts.get('ignore_case'):
1586 reflags |= re.I
1587 reflags |= re.I
1587 try:
1588 try:
1588 regexp = re.compile(pattern, reflags)
1589 regexp = re.compile(pattern, reflags)
1589 except re.error, inst:
1590 except re.error, inst:
1590 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1591 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1591 return 1
1592 return 1
1592 sep, eol = ':', '\n'
1593 sep, eol = ':', '\n'
1593 if opts.get('print0'):
1594 if opts.get('print0'):
1594 sep = eol = '\0'
1595 sep = eol = '\0'
1595
1596
1596 getfile = util.lrucachefunc(repo.file)
1597 getfile = util.lrucachefunc(repo.file)
1597
1598
1598 def matchlines(body):
1599 def matchlines(body):
1599 begin = 0
1600 begin = 0
1600 linenum = 0
1601 linenum = 0
1601 while True:
1602 while True:
1602 match = regexp.search(body, begin)
1603 match = regexp.search(body, begin)
1603 if not match:
1604 if not match:
1604 break
1605 break
1605 mstart, mend = match.span()
1606 mstart, mend = match.span()
1606 linenum += body.count('\n', begin, mstart) + 1
1607 linenum += body.count('\n', begin, mstart) + 1
1607 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1608 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1608 begin = body.find('\n', mend) + 1 or len(body)
1609 begin = body.find('\n', mend) + 1 or len(body)
1609 lend = begin - 1
1610 lend = begin - 1
1610 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1611 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1611
1612
1612 class linestate(object):
1613 class linestate(object):
1613 def __init__(self, line, linenum, colstart, colend):
1614 def __init__(self, line, linenum, colstart, colend):
1614 self.line = line
1615 self.line = line
1615 self.linenum = linenum
1616 self.linenum = linenum
1616 self.colstart = colstart
1617 self.colstart = colstart
1617 self.colend = colend
1618 self.colend = colend
1618
1619
1619 def __hash__(self):
1620 def __hash__(self):
1620 return hash((self.linenum, self.line))
1621 return hash((self.linenum, self.line))
1621
1622
1622 def __eq__(self, other):
1623 def __eq__(self, other):
1623 return self.line == other.line
1624 return self.line == other.line
1624
1625
1625 matches = {}
1626 matches = {}
1626 copies = {}
1627 copies = {}
1627 def grepbody(fn, rev, body):
1628 def grepbody(fn, rev, body):
1628 matches[rev].setdefault(fn, [])
1629 matches[rev].setdefault(fn, [])
1629 m = matches[rev][fn]
1630 m = matches[rev][fn]
1630 for lnum, cstart, cend, line in matchlines(body):
1631 for lnum, cstart, cend, line in matchlines(body):
1631 s = linestate(line, lnum, cstart, cend)
1632 s = linestate(line, lnum, cstart, cend)
1632 m.append(s)
1633 m.append(s)
1633
1634
1634 def difflinestates(a, b):
1635 def difflinestates(a, b):
1635 sm = difflib.SequenceMatcher(None, a, b)
1636 sm = difflib.SequenceMatcher(None, a, b)
1636 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1637 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1637 if tag == 'insert':
1638 if tag == 'insert':
1638 for i in xrange(blo, bhi):
1639 for i in xrange(blo, bhi):
1639 yield ('+', b[i])
1640 yield ('+', b[i])
1640 elif tag == 'delete':
1641 elif tag == 'delete':
1641 for i in xrange(alo, ahi):
1642 for i in xrange(alo, ahi):
1642 yield ('-', a[i])
1643 yield ('-', a[i])
1643 elif tag == 'replace':
1644 elif tag == 'replace':
1644 for i in xrange(alo, ahi):
1645 for i in xrange(alo, ahi):
1645 yield ('-', a[i])
1646 yield ('-', a[i])
1646 for i in xrange(blo, bhi):
1647 for i in xrange(blo, bhi):
1647 yield ('+', b[i])
1648 yield ('+', b[i])
1648
1649
1649 def display(fn, ctx, pstates, states):
1650 def display(fn, ctx, pstates, states):
1650 rev = ctx.rev()
1651 rev = ctx.rev()
1651 datefunc = ui.quiet and util.shortdate or util.datestr
1652 datefunc = ui.quiet and util.shortdate or util.datestr
1652 found = False
1653 found = False
1653 filerevmatches = {}
1654 filerevmatches = {}
1654 if opts.get('all'):
1655 if opts.get('all'):
1655 iter = difflinestates(pstates, states)
1656 iter = difflinestates(pstates, states)
1656 else:
1657 else:
1657 iter = [('', l) for l in states]
1658 iter = [('', l) for l in states]
1658 for change, l in iter:
1659 for change, l in iter:
1659 cols = [fn, str(rev)]
1660 cols = [fn, str(rev)]
1660 before, match, after = None, None, None
1661 before, match, after = None, None, None
1661 if opts.get('line_number'):
1662 if opts.get('line_number'):
1662 cols.append(str(l.linenum))
1663 cols.append(str(l.linenum))
1663 if opts.get('all'):
1664 if opts.get('all'):
1664 cols.append(change)
1665 cols.append(change)
1665 if opts.get('user'):
1666 if opts.get('user'):
1666 cols.append(ui.shortuser(ctx.user()))
1667 cols.append(ui.shortuser(ctx.user()))
1667 if opts.get('date'):
1668 if opts.get('date'):
1668 cols.append(datefunc(ctx.date()))
1669 cols.append(datefunc(ctx.date()))
1669 if opts.get('files_with_matches'):
1670 if opts.get('files_with_matches'):
1670 c = (fn, rev)
1671 c = (fn, rev)
1671 if c in filerevmatches:
1672 if c in filerevmatches:
1672 continue
1673 continue
1673 filerevmatches[c] = 1
1674 filerevmatches[c] = 1
1674 else:
1675 else:
1675 before = l.line[:l.colstart]
1676 before = l.line[:l.colstart]
1676 match = l.line[l.colstart:l.colend]
1677 match = l.line[l.colstart:l.colend]
1677 after = l.line[l.colend:]
1678 after = l.line[l.colend:]
1678 ui.write(sep.join(cols))
1679 ui.write(sep.join(cols))
1679 if before is not None:
1680 if before is not None:
1680 ui.write(sep + before)
1681 ui.write(sep + before)
1681 ui.write(match, label='grep.match')
1682 ui.write(match, label='grep.match')
1682 ui.write(after)
1683 ui.write(after)
1683 ui.write(eol)
1684 ui.write(eol)
1684 found = True
1685 found = True
1685 return found
1686 return found
1686
1687
1687 skip = {}
1688 skip = {}
1688 revfiles = {}
1689 revfiles = {}
1689 matchfn = cmdutil.match(repo, pats, opts)
1690 matchfn = cmdutil.match(repo, pats, opts)
1690 found = False
1691 found = False
1691 follow = opts.get('follow')
1692 follow = opts.get('follow')
1692
1693
1693 def prep(ctx, fns):
1694 def prep(ctx, fns):
1694 rev = ctx.rev()
1695 rev = ctx.rev()
1695 pctx = ctx.parents()[0]
1696 pctx = ctx.parents()[0]
1696 parent = pctx.rev()
1697 parent = pctx.rev()
1697 matches.setdefault(rev, {})
1698 matches.setdefault(rev, {})
1698 matches.setdefault(parent, {})
1699 matches.setdefault(parent, {})
1699 files = revfiles.setdefault(rev, [])
1700 files = revfiles.setdefault(rev, [])
1700 for fn in fns:
1701 for fn in fns:
1701 flog = getfile(fn)
1702 flog = getfile(fn)
1702 try:
1703 try:
1703 fnode = ctx.filenode(fn)
1704 fnode = ctx.filenode(fn)
1704 except error.LookupError:
1705 except error.LookupError:
1705 continue
1706 continue
1706
1707
1707 copied = flog.renamed(fnode)
1708 copied = flog.renamed(fnode)
1708 copy = follow and copied and copied[0]
1709 copy = follow and copied and copied[0]
1709 if copy:
1710 if copy:
1710 copies.setdefault(rev, {})[fn] = copy
1711 copies.setdefault(rev, {})[fn] = copy
1711 if fn in skip:
1712 if fn in skip:
1712 if copy:
1713 if copy:
1713 skip[copy] = True
1714 skip[copy] = True
1714 continue
1715 continue
1715 files.append(fn)
1716 files.append(fn)
1716
1717
1717 if fn not in matches[rev]:
1718 if fn not in matches[rev]:
1718 grepbody(fn, rev, flog.read(fnode))
1719 grepbody(fn, rev, flog.read(fnode))
1719
1720
1720 pfn = copy or fn
1721 pfn = copy or fn
1721 if pfn not in matches[parent]:
1722 if pfn not in matches[parent]:
1722 try:
1723 try:
1723 fnode = pctx.filenode(pfn)
1724 fnode = pctx.filenode(pfn)
1724 grepbody(pfn, parent, flog.read(fnode))
1725 grepbody(pfn, parent, flog.read(fnode))
1725 except error.LookupError:
1726 except error.LookupError:
1726 pass
1727 pass
1727
1728
1728 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1729 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1729 rev = ctx.rev()
1730 rev = ctx.rev()
1730 parent = ctx.parents()[0].rev()
1731 parent = ctx.parents()[0].rev()
1731 for fn in sorted(revfiles.get(rev, [])):
1732 for fn in sorted(revfiles.get(rev, [])):
1732 states = matches[rev][fn]
1733 states = matches[rev][fn]
1733 copy = copies.get(rev, {}).get(fn)
1734 copy = copies.get(rev, {}).get(fn)
1734 if fn in skip:
1735 if fn in skip:
1735 if copy:
1736 if copy:
1736 skip[copy] = True
1737 skip[copy] = True
1737 continue
1738 continue
1738 pstates = matches.get(parent, {}).get(copy or fn, [])
1739 pstates = matches.get(parent, {}).get(copy or fn, [])
1739 if pstates or states:
1740 if pstates or states:
1740 r = display(fn, ctx, pstates, states)
1741 r = display(fn, ctx, pstates, states)
1741 found = found or r
1742 found = found or r
1742 if r and not opts.get('all'):
1743 if r and not opts.get('all'):
1743 skip[fn] = True
1744 skip[fn] = True
1744 if copy:
1745 if copy:
1745 skip[copy] = True
1746 skip[copy] = True
1746 del matches[rev]
1747 del matches[rev]
1747 del revfiles[rev]
1748 del revfiles[rev]
1748
1749
1749 return not found
1750 return not found
1750
1751
1751 def heads(ui, repo, *branchrevs, **opts):
1752 def heads(ui, repo, *branchrevs, **opts):
1752 """show current repository heads or show branch heads
1753 """show current repository heads or show branch heads
1753
1754
1754 With no arguments, show all repository branch heads.
1755 With no arguments, show all repository branch heads.
1755
1756
1756 Repository "heads" are changesets with no child changesets. They are
1757 Repository "heads" are changesets with no child changesets. They are
1757 where development generally takes place and are the usual targets
1758 where development generally takes place and are the usual targets
1758 for update and merge operations. Branch heads are changesets that have
1759 for update and merge operations. Branch heads are changesets that have
1759 no child changeset on the same branch.
1760 no child changeset on the same branch.
1760
1761
1761 If one or more REVs are given, only branch heads on the branches
1762 If one or more REVs are given, only branch heads on the branches
1762 associated with the specified changesets are shown.
1763 associated with the specified changesets are shown.
1763
1764
1764 If -c/--closed is specified, also show branch heads marked closed
1765 If -c/--closed is specified, also show branch heads marked closed
1765 (see :hg:`commit --close-branch`).
1766 (see :hg:`commit --close-branch`).
1766
1767
1767 If STARTREV is specified, only those heads that are descendants of
1768 If STARTREV is specified, only those heads that are descendants of
1768 STARTREV will be displayed.
1769 STARTREV will be displayed.
1769
1770
1770 If -t/--topo is specified, named branch mechanics will be ignored and only
1771 If -t/--topo is specified, named branch mechanics will be ignored and only
1771 changesets without children will be shown.
1772 changesets without children will be shown.
1772
1773
1773 Returns 0 if matching heads are found, 1 if not.
1774 Returns 0 if matching heads are found, 1 if not.
1774 """
1775 """
1775
1776
1776 if opts.get('rev'):
1777 if opts.get('rev'):
1777 start = repo.lookup(opts['rev'])
1778 start = repo.lookup(opts['rev'])
1778 else:
1779 else:
1779 start = None
1780 start = None
1780
1781
1781 if opts.get('topo'):
1782 if opts.get('topo'):
1782 heads = [repo[h] for h in repo.heads(start)]
1783 heads = [repo[h] for h in repo.heads(start)]
1783 else:
1784 else:
1784 heads = []
1785 heads = []
1785 for b, ls in repo.branchmap().iteritems():
1786 for b, ls in repo.branchmap().iteritems():
1786 if start is None:
1787 if start is None:
1787 heads += [repo[h] for h in ls]
1788 heads += [repo[h] for h in ls]
1788 continue
1789 continue
1789 startrev = repo.changelog.rev(start)
1790 startrev = repo.changelog.rev(start)
1790 descendants = set(repo.changelog.descendants(startrev))
1791 descendants = set(repo.changelog.descendants(startrev))
1791 descendants.add(startrev)
1792 descendants.add(startrev)
1792 rev = repo.changelog.rev
1793 rev = repo.changelog.rev
1793 heads += [repo[h] for h in ls if rev(h) in descendants]
1794 heads += [repo[h] for h in ls if rev(h) in descendants]
1794
1795
1795 if branchrevs:
1796 if branchrevs:
1796 decode, encode = encoding.fromlocal, encoding.tolocal
1797 decode, encode = encoding.fromlocal, encoding.tolocal
1797 branches = set(repo[decode(br)].branch() for br in branchrevs)
1798 branches = set(repo[decode(br)].branch() for br in branchrevs)
1798 heads = [h for h in heads if h.branch() in branches]
1799 heads = [h for h in heads if h.branch() in branches]
1799
1800
1800 if not opts.get('closed'):
1801 if not opts.get('closed'):
1801 heads = [h for h in heads if not h.extra().get('close')]
1802 heads = [h for h in heads if not h.extra().get('close')]
1802
1803
1803 if opts.get('active') and branchrevs:
1804 if opts.get('active') and branchrevs:
1804 dagheads = repo.heads(start)
1805 dagheads = repo.heads(start)
1805 heads = [h for h in heads if h.node() in dagheads]
1806 heads = [h for h in heads if h.node() in dagheads]
1806
1807
1807 if branchrevs:
1808 if branchrevs:
1808 haveheads = set(h.branch() for h in heads)
1809 haveheads = set(h.branch() for h in heads)
1809 if branches - haveheads:
1810 if branches - haveheads:
1810 headless = ', '.join(encode(b) for b in branches - haveheads)
1811 headless = ', '.join(encode(b) for b in branches - haveheads)
1811 msg = _('no open branch heads found on branches %s')
1812 msg = _('no open branch heads found on branches %s')
1812 if opts.get('rev'):
1813 if opts.get('rev'):
1813 msg += _(' (started at %s)' % opts['rev'])
1814 msg += _(' (started at %s)' % opts['rev'])
1814 ui.warn((msg + '\n') % headless)
1815 ui.warn((msg + '\n') % headless)
1815
1816
1816 if not heads:
1817 if not heads:
1817 return 1
1818 return 1
1818
1819
1819 heads = sorted(heads, key=lambda x: -x.rev())
1820 heads = sorted(heads, key=lambda x: -x.rev())
1820 displayer = cmdutil.show_changeset(ui, repo, opts)
1821 displayer = cmdutil.show_changeset(ui, repo, opts)
1821 for ctx in heads:
1822 for ctx in heads:
1822 displayer.show(ctx)
1823 displayer.show(ctx)
1823 displayer.close()
1824 displayer.close()
1824
1825
1825 def help_(ui, name=None, with_version=False, unknowncmd=False):
1826 def help_(ui, name=None, with_version=False, unknowncmd=False):
1826 """show help for a given topic or a help overview
1827 """show help for a given topic or a help overview
1827
1828
1828 With no arguments, print a list of commands with short help messages.
1829 With no arguments, print a list of commands with short help messages.
1829
1830
1830 Given a topic, extension, or command name, print help for that
1831 Given a topic, extension, or command name, print help for that
1831 topic.
1832 topic.
1832
1833
1833 Returns 0 if successful.
1834 Returns 0 if successful.
1834 """
1835 """
1835 option_lists = []
1836 option_lists = []
1836 textwidth = util.termwidth() - 2
1837 textwidth = util.termwidth() - 2
1837
1838
1838 def addglobalopts(aliases):
1839 def addglobalopts(aliases):
1839 if ui.verbose:
1840 if ui.verbose:
1840 option_lists.append((_("global options:"), globalopts))
1841 option_lists.append((_("global options:"), globalopts))
1841 if name == 'shortlist':
1842 if name == 'shortlist':
1842 option_lists.append((_('use "hg help" for the full list '
1843 option_lists.append((_('use "hg help" for the full list '
1843 'of commands'), ()))
1844 'of commands'), ()))
1844 else:
1845 else:
1845 if name == 'shortlist':
1846 if name == 'shortlist':
1846 msg = _('use "hg help" for the full list of commands '
1847 msg = _('use "hg help" for the full list of commands '
1847 'or "hg -v" for details')
1848 'or "hg -v" for details')
1848 elif aliases:
1849 elif aliases:
1849 msg = _('use "hg -v help%s" to show aliases and '
1850 msg = _('use "hg -v help%s" to show aliases and '
1850 'global options') % (name and " " + name or "")
1851 'global options') % (name and " " + name or "")
1851 else:
1852 else:
1852 msg = _('use "hg -v help %s" to show global options') % name
1853 msg = _('use "hg -v help %s" to show global options') % name
1853 option_lists.append((msg, ()))
1854 option_lists.append((msg, ()))
1854
1855
1855 def helpcmd(name):
1856 def helpcmd(name):
1856 if with_version:
1857 if with_version:
1857 version_(ui)
1858 version_(ui)
1858 ui.write('\n')
1859 ui.write('\n')
1859
1860
1860 try:
1861 try:
1861 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1862 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1862 except error.AmbiguousCommand, inst:
1863 except error.AmbiguousCommand, inst:
1863 # py3k fix: except vars can't be used outside the scope of the
1864 # py3k fix: except vars can't be used outside the scope of the
1864 # except block, nor can be used inside a lambda. python issue4617
1865 # except block, nor can be used inside a lambda. python issue4617
1865 prefix = inst.args[0]
1866 prefix = inst.args[0]
1866 select = lambda c: c.lstrip('^').startswith(prefix)
1867 select = lambda c: c.lstrip('^').startswith(prefix)
1867 helplist(_('list of commands:\n\n'), select)
1868 helplist(_('list of commands:\n\n'), select)
1868 return
1869 return
1869
1870
1870 # check if it's an invalid alias and display its error if it is
1871 # check if it's an invalid alias and display its error if it is
1871 if getattr(entry[0], 'badalias', False):
1872 if getattr(entry[0], 'badalias', False):
1872 if not unknowncmd:
1873 if not unknowncmd:
1873 entry[0](ui)
1874 entry[0](ui)
1874 return
1875 return
1875
1876
1876 # synopsis
1877 # synopsis
1877 if len(entry) > 2:
1878 if len(entry) > 2:
1878 if entry[2].startswith('hg'):
1879 if entry[2].startswith('hg'):
1879 ui.write("%s\n" % entry[2])
1880 ui.write("%s\n" % entry[2])
1880 else:
1881 else:
1881 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1882 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1882 else:
1883 else:
1883 ui.write('hg %s\n' % aliases[0])
1884 ui.write('hg %s\n' % aliases[0])
1884
1885
1885 # aliases
1886 # aliases
1886 if not ui.quiet and len(aliases) > 1:
1887 if not ui.quiet and len(aliases) > 1:
1887 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1888 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1888
1889
1889 # description
1890 # description
1890 doc = gettext(entry[0].__doc__)
1891 doc = gettext(entry[0].__doc__)
1891 if not doc:
1892 if not doc:
1892 doc = _("(no help text available)")
1893 doc = _("(no help text available)")
1893 if hasattr(entry[0], 'definition'): # aliased command
1894 if hasattr(entry[0], 'definition'): # aliased command
1894 if entry[0].definition.startswith('!'): # shell alias
1895 if entry[0].definition.startswith('!'): # shell alias
1895 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1896 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1896 else:
1897 else:
1897 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1898 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1898 if ui.quiet:
1899 if ui.quiet:
1899 doc = doc.splitlines()[0]
1900 doc = doc.splitlines()[0]
1900 keep = ui.verbose and ['verbose'] or []
1901 keep = ui.verbose and ['verbose'] or []
1901 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1902 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1902 ui.write("\n%s\n" % formatted)
1903 ui.write("\n%s\n" % formatted)
1903 if pruned:
1904 if pruned:
1904 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1905 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1905
1906
1906 if not ui.quiet:
1907 if not ui.quiet:
1907 # options
1908 # options
1908 if entry[1]:
1909 if entry[1]:
1909 option_lists.append((_("options:\n"), entry[1]))
1910 option_lists.append((_("options:\n"), entry[1]))
1910
1911
1911 addglobalopts(False)
1912 addglobalopts(False)
1912
1913
1913 def helplist(header, select=None):
1914 def helplist(header, select=None):
1914 h = {}
1915 h = {}
1915 cmds = {}
1916 cmds = {}
1916 for c, e in table.iteritems():
1917 for c, e in table.iteritems():
1917 f = c.split("|", 1)[0]
1918 f = c.split("|", 1)[0]
1918 if select and not select(f):
1919 if select and not select(f):
1919 continue
1920 continue
1920 if (not select and name != 'shortlist' and
1921 if (not select and name != 'shortlist' and
1921 e[0].__module__ != __name__):
1922 e[0].__module__ != __name__):
1922 continue
1923 continue
1923 if name == "shortlist" and not f.startswith("^"):
1924 if name == "shortlist" and not f.startswith("^"):
1924 continue
1925 continue
1925 f = f.lstrip("^")
1926 f = f.lstrip("^")
1926 if not ui.debugflag and f.startswith("debug"):
1927 if not ui.debugflag and f.startswith("debug"):
1927 continue
1928 continue
1928 doc = e[0].__doc__
1929 doc = e[0].__doc__
1929 if doc and 'DEPRECATED' in doc and not ui.verbose:
1930 if doc and 'DEPRECATED' in doc and not ui.verbose:
1930 continue
1931 continue
1931 doc = gettext(doc)
1932 doc = gettext(doc)
1932 if not doc:
1933 if not doc:
1933 doc = _("(no help text available)")
1934 doc = _("(no help text available)")
1934 h[f] = doc.splitlines()[0].rstrip()
1935 h[f] = doc.splitlines()[0].rstrip()
1935 cmds[f] = c.lstrip("^")
1936 cmds[f] = c.lstrip("^")
1936
1937
1937 if not h:
1938 if not h:
1938 ui.status(_('no commands defined\n'))
1939 ui.status(_('no commands defined\n'))
1939 return
1940 return
1940
1941
1941 ui.status(header)
1942 ui.status(header)
1942 fns = sorted(h)
1943 fns = sorted(h)
1943 m = max(map(len, fns))
1944 m = max(map(len, fns))
1944 for f in fns:
1945 for f in fns:
1945 if ui.verbose:
1946 if ui.verbose:
1946 commands = cmds[f].replace("|",", ")
1947 commands = cmds[f].replace("|",", ")
1947 ui.write(" %s:\n %s\n"%(commands, h[f]))
1948 ui.write(" %s:\n %s\n"%(commands, h[f]))
1948 else:
1949 else:
1949 ui.write('%s\n' % (util.wrap(h[f],
1950 ui.write('%s\n' % (util.wrap(h[f],
1950 initindent=' %-*s ' % (m, f),
1951 initindent=' %-*s ' % (m, f),
1951 hangindent=' ' * (m + 4))))
1952 hangindent=' ' * (m + 4))))
1952
1953
1953 if not ui.quiet:
1954 if not ui.quiet:
1954 addglobalopts(True)
1955 addglobalopts(True)
1955
1956
1956 def helptopic(name):
1957 def helptopic(name):
1957 for names, header, doc in help.helptable:
1958 for names, header, doc in help.helptable:
1958 if name in names:
1959 if name in names:
1959 break
1960 break
1960 else:
1961 else:
1961 raise error.UnknownCommand(name)
1962 raise error.UnknownCommand(name)
1962
1963
1963 # description
1964 # description
1964 if not doc:
1965 if not doc:
1965 doc = _("(no help text available)")
1966 doc = _("(no help text available)")
1966 if hasattr(doc, '__call__'):
1967 if hasattr(doc, '__call__'):
1967 doc = doc()
1968 doc = doc()
1968
1969
1969 ui.write("%s\n\n" % header)
1970 ui.write("%s\n\n" % header)
1970 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1971 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1971
1972
1972 def helpext(name):
1973 def helpext(name):
1973 try:
1974 try:
1974 mod = extensions.find(name)
1975 mod = extensions.find(name)
1975 doc = gettext(mod.__doc__) or _('no help text available')
1976 doc = gettext(mod.__doc__) or _('no help text available')
1976 except KeyError:
1977 except KeyError:
1977 mod = None
1978 mod = None
1978 doc = extensions.disabledext(name)
1979 doc = extensions.disabledext(name)
1979 if not doc:
1980 if not doc:
1980 raise error.UnknownCommand(name)
1981 raise error.UnknownCommand(name)
1981
1982
1982 if '\n' not in doc:
1983 if '\n' not in doc:
1983 head, tail = doc, ""
1984 head, tail = doc, ""
1984 else:
1985 else:
1985 head, tail = doc.split('\n', 1)
1986 head, tail = doc.split('\n', 1)
1986 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1987 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1987 if tail:
1988 if tail:
1988 ui.write(minirst.format(tail, textwidth))
1989 ui.write(minirst.format(tail, textwidth))
1989 ui.status('\n\n')
1990 ui.status('\n\n')
1990
1991
1991 if mod:
1992 if mod:
1992 try:
1993 try:
1993 ct = mod.cmdtable
1994 ct = mod.cmdtable
1994 except AttributeError:
1995 except AttributeError:
1995 ct = {}
1996 ct = {}
1996 modcmds = set([c.split('|', 1)[0] for c in ct])
1997 modcmds = set([c.split('|', 1)[0] for c in ct])
1997 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1998 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1998 else:
1999 else:
1999 ui.write(_('use "hg help extensions" for information on enabling '
2000 ui.write(_('use "hg help extensions" for information on enabling '
2000 'extensions\n'))
2001 'extensions\n'))
2001
2002
2002 def helpextcmd(name):
2003 def helpextcmd(name):
2003 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2004 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2004 doc = gettext(mod.__doc__).splitlines()[0]
2005 doc = gettext(mod.__doc__).splitlines()[0]
2005
2006
2006 msg = help.listexts(_("'%s' is provided by the following "
2007 msg = help.listexts(_("'%s' is provided by the following "
2007 "extension:") % cmd, {ext: doc}, len(ext),
2008 "extension:") % cmd, {ext: doc}, len(ext),
2008 indent=4)
2009 indent=4)
2009 ui.write(minirst.format(msg, textwidth))
2010 ui.write(minirst.format(msg, textwidth))
2010 ui.write('\n\n')
2011 ui.write('\n\n')
2011 ui.write(_('use "hg help extensions" for information on enabling '
2012 ui.write(_('use "hg help extensions" for information on enabling '
2012 'extensions\n'))
2013 'extensions\n'))
2013
2014
2014 if name and name != 'shortlist':
2015 if name and name != 'shortlist':
2015 i = None
2016 i = None
2016 if unknowncmd:
2017 if unknowncmd:
2017 queries = (helpextcmd,)
2018 queries = (helpextcmd,)
2018 else:
2019 else:
2019 queries = (helptopic, helpcmd, helpext, helpextcmd)
2020 queries = (helptopic, helpcmd, helpext, helpextcmd)
2020 for f in queries:
2021 for f in queries:
2021 try:
2022 try:
2022 f(name)
2023 f(name)
2023 i = None
2024 i = None
2024 break
2025 break
2025 except error.UnknownCommand, inst:
2026 except error.UnknownCommand, inst:
2026 i = inst
2027 i = inst
2027 if i:
2028 if i:
2028 raise i
2029 raise i
2029
2030
2030 else:
2031 else:
2031 # program name
2032 # program name
2032 if ui.verbose or with_version:
2033 if ui.verbose or with_version:
2033 version_(ui)
2034 version_(ui)
2034 else:
2035 else:
2035 ui.status(_("Mercurial Distributed SCM\n"))
2036 ui.status(_("Mercurial Distributed SCM\n"))
2036 ui.status('\n')
2037 ui.status('\n')
2037
2038
2038 # list of commands
2039 # list of commands
2039 if name == "shortlist":
2040 if name == "shortlist":
2040 header = _('basic commands:\n\n')
2041 header = _('basic commands:\n\n')
2041 else:
2042 else:
2042 header = _('list of commands:\n\n')
2043 header = _('list of commands:\n\n')
2043
2044
2044 helplist(header)
2045 helplist(header)
2045 if name != 'shortlist':
2046 if name != 'shortlist':
2046 exts, maxlength = extensions.enabled()
2047 exts, maxlength = extensions.enabled()
2047 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2048 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2048 if text:
2049 if text:
2049 ui.write("\n%s\n" % minirst.format(text, textwidth))
2050 ui.write("\n%s\n" % minirst.format(text, textwidth))
2050
2051
2051 # list all option lists
2052 # list all option lists
2052 opt_output = []
2053 opt_output = []
2053 multioccur = False
2054 multioccur = False
2054 for title, options in option_lists:
2055 for title, options in option_lists:
2055 opt_output.append(("\n%s" % title, None))
2056 opt_output.append(("\n%s" % title, None))
2056 for option in options:
2057 for option in options:
2057 if len(option) == 5:
2058 if len(option) == 5:
2058 shortopt, longopt, default, desc, optlabel = option
2059 shortopt, longopt, default, desc, optlabel = option
2059 else:
2060 else:
2060 shortopt, longopt, default, desc = option
2061 shortopt, longopt, default, desc = option
2061 optlabel = _("VALUE") # default label
2062 optlabel = _("VALUE") # default label
2062
2063
2063 if _("DEPRECATED") in desc and not ui.verbose:
2064 if _("DEPRECATED") in desc and not ui.verbose:
2064 continue
2065 continue
2065 if isinstance(default, list):
2066 if isinstance(default, list):
2066 numqualifier = " %s [+]" % optlabel
2067 numqualifier = " %s [+]" % optlabel
2067 multioccur = True
2068 multioccur = True
2068 elif (default is not None) and not isinstance(default, bool):
2069 elif (default is not None) and not isinstance(default, bool):
2069 numqualifier = " %s" % optlabel
2070 numqualifier = " %s" % optlabel
2070 else:
2071 else:
2071 numqualifier = ""
2072 numqualifier = ""
2072 opt_output.append(("%2s%s" %
2073 opt_output.append(("%2s%s" %
2073 (shortopt and "-%s" % shortopt,
2074 (shortopt and "-%s" % shortopt,
2074 longopt and " --%s%s" %
2075 longopt and " --%s%s" %
2075 (longopt, numqualifier)),
2076 (longopt, numqualifier)),
2076 "%s%s" % (desc,
2077 "%s%s" % (desc,
2077 default
2078 default
2078 and _(" (default: %s)") % default
2079 and _(" (default: %s)") % default
2079 or "")))
2080 or "")))
2080 if multioccur:
2081 if multioccur:
2081 msg = _("\n[+] marked option can be specified multiple times")
2082 msg = _("\n[+] marked option can be specified multiple times")
2082 if ui.verbose and name != 'shortlist':
2083 if ui.verbose and name != 'shortlist':
2083 opt_output.append((msg, None))
2084 opt_output.append((msg, None))
2084 else:
2085 else:
2085 opt_output.insert(-1, (msg, None))
2086 opt_output.insert(-1, (msg, None))
2086
2087
2087 if not name:
2088 if not name:
2088 ui.write(_("\nadditional help topics:\n\n"))
2089 ui.write(_("\nadditional help topics:\n\n"))
2089 topics = []
2090 topics = []
2090 for names, header, doc in help.helptable:
2091 for names, header, doc in help.helptable:
2091 topics.append((sorted(names, key=len, reverse=True)[0], header))
2092 topics.append((sorted(names, key=len, reverse=True)[0], header))
2092 topics_len = max([len(s[0]) for s in topics])
2093 topics_len = max([len(s[0]) for s in topics])
2093 for t, desc in topics:
2094 for t, desc in topics:
2094 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2095 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2095
2096
2096 if opt_output:
2097 if opt_output:
2097 colwidth = encoding.colwidth
2098 colwidth = encoding.colwidth
2098 # normalize: (opt or message, desc or None, width of opt)
2099 # normalize: (opt or message, desc or None, width of opt)
2099 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2100 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2100 for opt, desc in opt_output]
2101 for opt, desc in opt_output]
2101 hanging = max([e[2] for e in entries])
2102 hanging = max([e[2] for e in entries])
2102 for opt, desc, width in entries:
2103 for opt, desc, width in entries:
2103 if desc:
2104 if desc:
2104 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2105 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2105 hangindent = ' ' * (hanging + 3)
2106 hangindent = ' ' * (hanging + 3)
2106 ui.write('%s\n' % (util.wrap(desc,
2107 ui.write('%s\n' % (util.wrap(desc,
2107 initindent=initindent,
2108 initindent=initindent,
2108 hangindent=hangindent)))
2109 hangindent=hangindent)))
2109 else:
2110 else:
2110 ui.write("%s\n" % opt)
2111 ui.write("%s\n" % opt)
2111
2112
2112 def identify(ui, repo, source=None,
2113 def identify(ui, repo, source=None,
2113 rev=None, num=None, id=None, branch=None, tags=None):
2114 rev=None, num=None, id=None, branch=None, tags=None):
2114 """identify the working copy or specified revision
2115 """identify the working copy or specified revision
2115
2116
2116 With no revision, print a summary of the current state of the
2117 With no revision, print a summary of the current state of the
2117 repository.
2118 repository.
2118
2119
2119 Specifying a path to a repository root or Mercurial bundle will
2120 Specifying a path to a repository root or Mercurial bundle will
2120 cause lookup to operate on that repository/bundle.
2121 cause lookup to operate on that repository/bundle.
2121
2122
2122 This summary identifies the repository state using one or two
2123 This summary identifies the repository state using one or two
2123 parent hash identifiers, followed by a "+" if there are
2124 parent hash identifiers, followed by a "+" if there are
2124 uncommitted changes in the working directory, a list of tags for
2125 uncommitted changes in the working directory, a list of tags for
2125 this revision and a branch name for non-default branches.
2126 this revision and a branch name for non-default branches.
2126
2127
2127 Returns 0 if successful.
2128 Returns 0 if successful.
2128 """
2129 """
2129
2130
2130 if not repo and not source:
2131 if not repo and not source:
2131 raise util.Abort(_("there is no Mercurial repository here "
2132 raise util.Abort(_("there is no Mercurial repository here "
2132 "(.hg not found)"))
2133 "(.hg not found)"))
2133
2134
2134 hexfunc = ui.debugflag and hex or short
2135 hexfunc = ui.debugflag and hex or short
2135 default = not (num or id or branch or tags)
2136 default = not (num or id or branch or tags)
2136 output = []
2137 output = []
2137
2138
2138 revs = []
2139 revs = []
2139 if source:
2140 if source:
2140 source, branches = hg.parseurl(ui.expandpath(source))
2141 source, branches = hg.parseurl(ui.expandpath(source))
2141 repo = hg.repository(ui, source)
2142 repo = hg.repository(ui, source)
2142 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2143 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2143
2144
2144 if not repo.local():
2145 if not repo.local():
2145 if not rev and revs:
2146 if not rev and revs:
2146 rev = revs[0]
2147 rev = revs[0]
2147 if not rev:
2148 if not rev:
2148 rev = "tip"
2149 rev = "tip"
2149 if num or branch or tags:
2150 if num or branch or tags:
2150 raise util.Abort(
2151 raise util.Abort(
2151 "can't query remote revision number, branch, or tags")
2152 "can't query remote revision number, branch, or tags")
2152 output = [hexfunc(repo.lookup(rev))]
2153 output = [hexfunc(repo.lookup(rev))]
2153 elif not rev:
2154 elif not rev:
2154 ctx = repo[None]
2155 ctx = repo[None]
2155 parents = ctx.parents()
2156 parents = ctx.parents()
2156 changed = False
2157 changed = False
2157 if default or id or num:
2158 if default or id or num:
2158 changed = util.any(repo.status())
2159 changed = util.any(repo.status())
2159 if default or id:
2160 if default or id:
2160 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2161 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2161 (changed) and "+" or "")]
2162 (changed) and "+" or "")]
2162 if num:
2163 if num:
2163 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2164 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2164 (changed) and "+" or ""))
2165 (changed) and "+" or ""))
2165 else:
2166 else:
2166 ctx = repo[rev]
2167 ctx = repo[rev]
2167 if default or id:
2168 if default or id:
2168 output = [hexfunc(ctx.node())]
2169 output = [hexfunc(ctx.node())]
2169 if num:
2170 if num:
2170 output.append(str(ctx.rev()))
2171 output.append(str(ctx.rev()))
2171
2172
2172 if repo.local() and default and not ui.quiet:
2173 if repo.local() and default and not ui.quiet:
2173 b = encoding.tolocal(ctx.branch())
2174 b = encoding.tolocal(ctx.branch())
2174 if b != 'default':
2175 if b != 'default':
2175 output.append("(%s)" % b)
2176 output.append("(%s)" % b)
2176
2177
2177 # multiple tags for a single parent separated by '/'
2178 # multiple tags for a single parent separated by '/'
2178 t = "/".join(ctx.tags())
2179 t = "/".join(ctx.tags())
2179 if t:
2180 if t:
2180 output.append(t)
2181 output.append(t)
2181
2182
2182 if branch:
2183 if branch:
2183 output.append(encoding.tolocal(ctx.branch()))
2184 output.append(encoding.tolocal(ctx.branch()))
2184
2185
2185 if tags:
2186 if tags:
2186 output.extend(ctx.tags())
2187 output.extend(ctx.tags())
2187
2188
2188 ui.write("%s\n" % ' '.join(output))
2189 ui.write("%s\n" % ' '.join(output))
2189
2190
2190 def import_(ui, repo, patch1, *patches, **opts):
2191 def import_(ui, repo, patch1, *patches, **opts):
2191 """import an ordered set of patches
2192 """import an ordered set of patches
2192
2193
2193 Import a list of patches and commit them individually (unless
2194 Import a list of patches and commit them individually (unless
2194 --no-commit is specified).
2195 --no-commit is specified).
2195
2196
2196 If there are outstanding changes in the working directory, import
2197 If there are outstanding changes in the working directory, import
2197 will abort unless given the -f/--force flag.
2198 will abort unless given the -f/--force flag.
2198
2199
2199 You can import a patch straight from a mail message. Even patches
2200 You can import a patch straight from a mail message. Even patches
2200 as attachments work (to use the body part, it must have type
2201 as attachments work (to use the body part, it must have type
2201 text/plain or text/x-patch). From and Subject headers of email
2202 text/plain or text/x-patch). From and Subject headers of email
2202 message are used as default committer and commit message. All
2203 message are used as default committer and commit message. All
2203 text/plain body parts before first diff are added to commit
2204 text/plain body parts before first diff are added to commit
2204 message.
2205 message.
2205
2206
2206 If the imported patch was generated by :hg:`export`, user and
2207 If the imported patch was generated by :hg:`export`, user and
2207 description from patch override values from message headers and
2208 description from patch override values from message headers and
2208 body. Values given on command line with -m/--message and -u/--user
2209 body. Values given on command line with -m/--message and -u/--user
2209 override these.
2210 override these.
2210
2211
2211 If --exact is specified, import will set the working directory to
2212 If --exact is specified, import will set the working directory to
2212 the parent of each patch before applying it, and will abort if the
2213 the parent of each patch before applying it, and will abort if the
2213 resulting changeset has a different ID than the one recorded in
2214 resulting changeset has a different ID than the one recorded in
2214 the patch. This may happen due to character set problems or other
2215 the patch. This may happen due to character set problems or other
2215 deficiencies in the text patch format.
2216 deficiencies in the text patch format.
2216
2217
2217 With -s/--similarity, hg will attempt to discover renames and
2218 With -s/--similarity, hg will attempt to discover renames and
2218 copies in the patch in the same way as 'addremove'.
2219 copies in the patch in the same way as 'addremove'.
2219
2220
2220 To read a patch from standard input, use "-" as the patch name. If
2221 To read a patch from standard input, use "-" as the patch name. If
2221 a URL is specified, the patch will be downloaded from it.
2222 a URL is specified, the patch will be downloaded from it.
2222 See :hg:`help dates` for a list of formats valid for -d/--date.
2223 See :hg:`help dates` for a list of formats valid for -d/--date.
2223
2224
2224 Returns 0 on success.
2225 Returns 0 on success.
2225 """
2226 """
2226 patches = (patch1,) + patches
2227 patches = (patch1,) + patches
2227
2228
2228 date = opts.get('date')
2229 date = opts.get('date')
2229 if date:
2230 if date:
2230 opts['date'] = util.parsedate(date)
2231 opts['date'] = util.parsedate(date)
2231
2232
2232 try:
2233 try:
2233 sim = float(opts.get('similarity') or 0)
2234 sim = float(opts.get('similarity') or 0)
2234 except ValueError:
2235 except ValueError:
2235 raise util.Abort(_('similarity must be a number'))
2236 raise util.Abort(_('similarity must be a number'))
2236 if sim < 0 or sim > 100:
2237 if sim < 0 or sim > 100:
2237 raise util.Abort(_('similarity must be between 0 and 100'))
2238 raise util.Abort(_('similarity must be between 0 and 100'))
2238
2239
2239 if opts.get('exact') or not opts.get('force'):
2240 if opts.get('exact') or not opts.get('force'):
2240 cmdutil.bail_if_changed(repo)
2241 cmdutil.bail_if_changed(repo)
2241
2242
2242 d = opts["base"]
2243 d = opts["base"]
2243 strip = opts["strip"]
2244 strip = opts["strip"]
2244 wlock = lock = None
2245 wlock = lock = None
2245
2246
2246 def tryone(ui, hunk):
2247 def tryone(ui, hunk):
2247 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2248 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2248 patch.extract(ui, hunk)
2249 patch.extract(ui, hunk)
2249
2250
2250 if not tmpname:
2251 if not tmpname:
2251 return None
2252 return None
2252 commitid = _('to working directory')
2253 commitid = _('to working directory')
2253
2254
2254 try:
2255 try:
2255 cmdline_message = cmdutil.logmessage(opts)
2256 cmdline_message = cmdutil.logmessage(opts)
2256 if cmdline_message:
2257 if cmdline_message:
2257 # pickup the cmdline msg
2258 # pickup the cmdline msg
2258 message = cmdline_message
2259 message = cmdline_message
2259 elif message:
2260 elif message:
2260 # pickup the patch msg
2261 # pickup the patch msg
2261 message = message.strip()
2262 message = message.strip()
2262 else:
2263 else:
2263 # launch the editor
2264 # launch the editor
2264 message = None
2265 message = None
2265 ui.debug('message:\n%s\n' % message)
2266 ui.debug('message:\n%s\n' % message)
2266
2267
2267 wp = repo.parents()
2268 wp = repo.parents()
2268 if opts.get('exact'):
2269 if opts.get('exact'):
2269 if not nodeid or not p1:
2270 if not nodeid or not p1:
2270 raise util.Abort(_('not a Mercurial patch'))
2271 raise util.Abort(_('not a Mercurial patch'))
2271 p1 = repo.lookup(p1)
2272 p1 = repo.lookup(p1)
2272 p2 = repo.lookup(p2 or hex(nullid))
2273 p2 = repo.lookup(p2 or hex(nullid))
2273
2274
2274 if p1 != wp[0].node():
2275 if p1 != wp[0].node():
2275 hg.clean(repo, p1)
2276 hg.clean(repo, p1)
2276 repo.dirstate.setparents(p1, p2)
2277 repo.dirstate.setparents(p1, p2)
2277 elif p2:
2278 elif p2:
2278 try:
2279 try:
2279 p1 = repo.lookup(p1)
2280 p1 = repo.lookup(p1)
2280 p2 = repo.lookup(p2)
2281 p2 = repo.lookup(p2)
2281 if p1 == wp[0].node():
2282 if p1 == wp[0].node():
2282 repo.dirstate.setparents(p1, p2)
2283 repo.dirstate.setparents(p1, p2)
2283 except error.RepoError:
2284 except error.RepoError:
2284 pass
2285 pass
2285 if opts.get('exact') or opts.get('import_branch'):
2286 if opts.get('exact') or opts.get('import_branch'):
2286 repo.dirstate.setbranch(branch or 'default')
2287 repo.dirstate.setbranch(branch or 'default')
2287
2288
2288 files = {}
2289 files = {}
2289 try:
2290 try:
2290 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2291 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2291 files=files, eolmode=None)
2292 files=files, eolmode=None)
2292 finally:
2293 finally:
2293 files = cmdutil.updatedir(ui, repo, files,
2294 files = cmdutil.updatedir(ui, repo, files,
2294 similarity=sim / 100.0)
2295 similarity=sim / 100.0)
2295 if not opts.get('no_commit'):
2296 if not opts.get('no_commit'):
2296 if opts.get('exact'):
2297 if opts.get('exact'):
2297 m = None
2298 m = None
2298 else:
2299 else:
2299 m = cmdutil.matchfiles(repo, files or [])
2300 m = cmdutil.matchfiles(repo, files or [])
2300 n = repo.commit(message, opts.get('user') or user,
2301 n = repo.commit(message, opts.get('user') or user,
2301 opts.get('date') or date, match=m,
2302 opts.get('date') or date, match=m,
2302 editor=cmdutil.commiteditor)
2303 editor=cmdutil.commiteditor)
2303 if opts.get('exact'):
2304 if opts.get('exact'):
2304 if hex(n) != nodeid:
2305 if hex(n) != nodeid:
2305 repo.rollback()
2306 repo.rollback()
2306 raise util.Abort(_('patch is damaged'
2307 raise util.Abort(_('patch is damaged'
2307 ' or loses information'))
2308 ' or loses information'))
2308 # Force a dirstate write so that the next transaction
2309 # Force a dirstate write so that the next transaction
2309 # backups an up-do-date file.
2310 # backups an up-do-date file.
2310 repo.dirstate.write()
2311 repo.dirstate.write()
2311 if n:
2312 if n:
2312 commitid = short(n)
2313 commitid = short(n)
2313
2314
2314 return commitid
2315 return commitid
2315 finally:
2316 finally:
2316 os.unlink(tmpname)
2317 os.unlink(tmpname)
2317
2318
2318 try:
2319 try:
2319 wlock = repo.wlock()
2320 wlock = repo.wlock()
2320 lock = repo.lock()
2321 lock = repo.lock()
2321 lastcommit = None
2322 lastcommit = None
2322 for p in patches:
2323 for p in patches:
2323 pf = os.path.join(d, p)
2324 pf = os.path.join(d, p)
2324
2325
2325 if pf == '-':
2326 if pf == '-':
2326 ui.status(_("applying patch from stdin\n"))
2327 ui.status(_("applying patch from stdin\n"))
2327 pf = sys.stdin
2328 pf = sys.stdin
2328 else:
2329 else:
2329 ui.status(_("applying %s\n") % p)
2330 ui.status(_("applying %s\n") % p)
2330 pf = url.open(ui, pf)
2331 pf = url.open(ui, pf)
2331
2332
2332 haspatch = False
2333 haspatch = False
2333 for hunk in patch.split(pf):
2334 for hunk in patch.split(pf):
2334 commitid = tryone(ui, hunk)
2335 commitid = tryone(ui, hunk)
2335 if commitid:
2336 if commitid:
2336 haspatch = True
2337 haspatch = True
2337 if lastcommit:
2338 if lastcommit:
2338 ui.status(_('applied %s\n') % lastcommit)
2339 ui.status(_('applied %s\n') % lastcommit)
2339 lastcommit = commitid
2340 lastcommit = commitid
2340
2341
2341 if not haspatch:
2342 if not haspatch:
2342 raise util.Abort(_('no diffs found'))
2343 raise util.Abort(_('no diffs found'))
2343
2344
2344 finally:
2345 finally:
2345 release(lock, wlock)
2346 release(lock, wlock)
2346
2347
2347 def incoming(ui, repo, source="default", **opts):
2348 def incoming(ui, repo, source="default", **opts):
2348 """show new changesets found in source
2349 """show new changesets found in source
2349
2350
2350 Show new changesets found in the specified path/URL or the default
2351 Show new changesets found in the specified path/URL or the default
2351 pull location. These are the changesets that would have been pulled
2352 pull location. These are the changesets that would have been pulled
2352 if a pull at the time you issued this command.
2353 if a pull at the time you issued this command.
2353
2354
2354 For remote repository, using --bundle avoids downloading the
2355 For remote repository, using --bundle avoids downloading the
2355 changesets twice if the incoming is followed by a pull.
2356 changesets twice if the incoming is followed by a pull.
2356
2357
2357 See pull for valid source format details.
2358 See pull for valid source format details.
2358
2359
2359 Returns 0 if there are incoming changes, 1 otherwise.
2360 Returns 0 if there are incoming changes, 1 otherwise.
2360 """
2361 """
2361 if opts.get('bundle') and opts.get('subrepos'):
2362 if opts.get('bundle') and opts.get('subrepos'):
2362 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2363 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2363
2364
2364 ret = hg.incoming(ui, repo, source, opts)
2365 ret = hg.incoming(ui, repo, source, opts)
2365 if opts.get('subrepos'):
2366 if opts.get('subrepos'):
2366 ctx = repo[None]
2367 ctx = repo[None]
2367 for subpath in sorted(ctx.substate):
2368 for subpath in sorted(ctx.substate):
2368 sub = ctx.sub(subpath)
2369 sub = ctx.sub(subpath)
2369 ret = min(ret, sub.incoming(ui, source, opts))
2370 ret = min(ret, sub.incoming(ui, source, opts))
2370 return ret
2371 return ret
2371
2372
2372 def init(ui, dest=".", **opts):
2373 def init(ui, dest=".", **opts):
2373 """create a new repository in the given directory
2374 """create a new repository in the given directory
2374
2375
2375 Initialize a new repository in the given directory. If the given
2376 Initialize a new repository in the given directory. If the given
2376 directory does not exist, it will be created.
2377 directory does not exist, it will be created.
2377
2378
2378 If no directory is given, the current directory is used.
2379 If no directory is given, the current directory is used.
2379
2380
2380 It is possible to specify an ``ssh://`` URL as the destination.
2381 It is possible to specify an ``ssh://`` URL as the destination.
2381 See :hg:`help urls` for more information.
2382 See :hg:`help urls` for more information.
2382
2383
2383 Returns 0 on success.
2384 Returns 0 on success.
2384 """
2385 """
2385 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2386 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2386
2387
2387 def locate(ui, repo, *pats, **opts):
2388 def locate(ui, repo, *pats, **opts):
2388 """locate files matching specific patterns
2389 """locate files matching specific patterns
2389
2390
2390 Print files under Mercurial control in the working directory whose
2391 Print files under Mercurial control in the working directory whose
2391 names match the given patterns.
2392 names match the given patterns.
2392
2393
2393 By default, this command searches all directories in the working
2394 By default, this command searches all directories in the working
2394 directory. To search just the current directory and its
2395 directory. To search just the current directory and its
2395 subdirectories, use "--include .".
2396 subdirectories, use "--include .".
2396
2397
2397 If no patterns are given to match, this command prints the names
2398 If no patterns are given to match, this command prints the names
2398 of all files under Mercurial control in the working directory.
2399 of all files under Mercurial control in the working directory.
2399
2400
2400 If you want to feed the output of this command into the "xargs"
2401 If you want to feed the output of this command into the "xargs"
2401 command, use the -0 option to both this command and "xargs". This
2402 command, use the -0 option to both this command and "xargs". This
2402 will avoid the problem of "xargs" treating single filenames that
2403 will avoid the problem of "xargs" treating single filenames that
2403 contain whitespace as multiple filenames.
2404 contain whitespace as multiple filenames.
2404
2405
2405 Returns 0 if a match is found, 1 otherwise.
2406 Returns 0 if a match is found, 1 otherwise.
2406 """
2407 """
2407 end = opts.get('print0') and '\0' or '\n'
2408 end = opts.get('print0') and '\0' or '\n'
2408 rev = opts.get('rev') or None
2409 rev = opts.get('rev') or None
2409
2410
2410 ret = 1
2411 ret = 1
2411 m = cmdutil.match(repo, pats, opts, default='relglob')
2412 m = cmdutil.match(repo, pats, opts, default='relglob')
2412 m.bad = lambda x, y: False
2413 m.bad = lambda x, y: False
2413 for abs in repo[rev].walk(m):
2414 for abs in repo[rev].walk(m):
2414 if not rev and abs not in repo.dirstate:
2415 if not rev and abs not in repo.dirstate:
2415 continue
2416 continue
2416 if opts.get('fullpath'):
2417 if opts.get('fullpath'):
2417 ui.write(repo.wjoin(abs), end)
2418 ui.write(repo.wjoin(abs), end)
2418 else:
2419 else:
2419 ui.write(((pats and m.rel(abs)) or abs), end)
2420 ui.write(((pats and m.rel(abs)) or abs), end)
2420 ret = 0
2421 ret = 0
2421
2422
2422 return ret
2423 return ret
2423
2424
2424 def log(ui, repo, *pats, **opts):
2425 def log(ui, repo, *pats, **opts):
2425 """show revision history of entire repository or files
2426 """show revision history of entire repository or files
2426
2427
2427 Print the revision history of the specified files or the entire
2428 Print the revision history of the specified files or the entire
2428 project.
2429 project.
2429
2430
2430 File history is shown without following rename or copy history of
2431 File history is shown without following rename or copy history of
2431 files. Use -f/--follow with a filename to follow history across
2432 files. Use -f/--follow with a filename to follow history across
2432 renames and copies. --follow without a filename will only show
2433 renames and copies. --follow without a filename will only show
2433 ancestors or descendants of the starting revision. --follow-first
2434 ancestors or descendants of the starting revision. --follow-first
2434 only follows the first parent of merge revisions.
2435 only follows the first parent of merge revisions.
2435
2436
2436 If no revision range is specified, the default is tip:0 unless
2437 If no revision range is specified, the default is tip:0 unless
2437 --follow is set, in which case the working directory parent is
2438 --follow is set, in which case the working directory parent is
2438 used as the starting revision. You can specify a revision set for
2439 used as the starting revision. You can specify a revision set for
2439 log, see :hg:`help revsets` for more information.
2440 log, see :hg:`help revsets` for more information.
2440
2441
2441 See :hg:`help dates` for a list of formats valid for -d/--date.
2442 See :hg:`help dates` for a list of formats valid for -d/--date.
2442
2443
2443 By default this command prints revision number and changeset id,
2444 By default this command prints revision number and changeset id,
2444 tags, non-trivial parents, user, date and time, and a summary for
2445 tags, non-trivial parents, user, date and time, and a summary for
2445 each commit. When the -v/--verbose switch is used, the list of
2446 each commit. When the -v/--verbose switch is used, the list of
2446 changed files and full commit message are shown.
2447 changed files and full commit message are shown.
2447
2448
2448 NOTE: log -p/--patch may generate unexpected diff output for merge
2449 .. note::
2449 changesets, as it will only compare the merge changeset against
2450 log -p/--patch may generate unexpected diff output for merge
2450 its first parent. Also, only files different from BOTH parents
2451 changesets, as it will only compare the merge changeset against
2451 will appear in files:.
2452 its first parent. Also, only files different from BOTH parents
2453 will appear in files:.
2452
2454
2453 Returns 0 on success.
2455 Returns 0 on success.
2454 """
2456 """
2455
2457
2456 matchfn = cmdutil.match(repo, pats, opts)
2458 matchfn = cmdutil.match(repo, pats, opts)
2457 limit = cmdutil.loglimit(opts)
2459 limit = cmdutil.loglimit(opts)
2458 count = 0
2460 count = 0
2459
2461
2460 endrev = None
2462 endrev = None
2461 if opts.get('copies') and opts.get('rev'):
2463 if opts.get('copies') and opts.get('rev'):
2462 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2464 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2463
2465
2464 df = False
2466 df = False
2465 if opts["date"]:
2467 if opts["date"]:
2466 df = util.matchdate(opts["date"])
2468 df = util.matchdate(opts["date"])
2467
2469
2468 branches = opts.get('branch', []) + opts.get('only_branch', [])
2470 branches = opts.get('branch', []) + opts.get('only_branch', [])
2469 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2471 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2470
2472
2471 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2473 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2472 def prep(ctx, fns):
2474 def prep(ctx, fns):
2473 rev = ctx.rev()
2475 rev = ctx.rev()
2474 parents = [p for p in repo.changelog.parentrevs(rev)
2476 parents = [p for p in repo.changelog.parentrevs(rev)
2475 if p != nullrev]
2477 if p != nullrev]
2476 if opts.get('no_merges') and len(parents) == 2:
2478 if opts.get('no_merges') and len(parents) == 2:
2477 return
2479 return
2478 if opts.get('only_merges') and len(parents) != 2:
2480 if opts.get('only_merges') and len(parents) != 2:
2479 return
2481 return
2480 if opts.get('branch') and ctx.branch() not in opts['branch']:
2482 if opts.get('branch') and ctx.branch() not in opts['branch']:
2481 return
2483 return
2482 if df and not df(ctx.date()[0]):
2484 if df and not df(ctx.date()[0]):
2483 return
2485 return
2484 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2486 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2485 return
2487 return
2486 if opts.get('keyword'):
2488 if opts.get('keyword'):
2487 for k in [kw.lower() for kw in opts['keyword']]:
2489 for k in [kw.lower() for kw in opts['keyword']]:
2488 if (k in ctx.user().lower() or
2490 if (k in ctx.user().lower() or
2489 k in ctx.description().lower() or
2491 k in ctx.description().lower() or
2490 k in " ".join(ctx.files()).lower()):
2492 k in " ".join(ctx.files()).lower()):
2491 break
2493 break
2492 else:
2494 else:
2493 return
2495 return
2494
2496
2495 copies = None
2497 copies = None
2496 if opts.get('copies') and rev:
2498 if opts.get('copies') and rev:
2497 copies = []
2499 copies = []
2498 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2500 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2499 for fn in ctx.files():
2501 for fn in ctx.files():
2500 rename = getrenamed(fn, rev)
2502 rename = getrenamed(fn, rev)
2501 if rename:
2503 if rename:
2502 copies.append((fn, rename[0]))
2504 copies.append((fn, rename[0]))
2503
2505
2504 revmatchfn = None
2506 revmatchfn = None
2505 if opts.get('patch') or opts.get('stat'):
2507 if opts.get('patch') or opts.get('stat'):
2506 if opts.get('follow') or opts.get('follow_first'):
2508 if opts.get('follow') or opts.get('follow_first'):
2507 # note: this might be wrong when following through merges
2509 # note: this might be wrong when following through merges
2508 revmatchfn = cmdutil.match(repo, fns, default='path')
2510 revmatchfn = cmdutil.match(repo, fns, default='path')
2509 else:
2511 else:
2510 revmatchfn = matchfn
2512 revmatchfn = matchfn
2511
2513
2512 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2514 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2513
2515
2514 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2516 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2515 if count == limit:
2517 if count == limit:
2516 break
2518 break
2517 if displayer.flush(ctx.rev()):
2519 if displayer.flush(ctx.rev()):
2518 count += 1
2520 count += 1
2519 displayer.close()
2521 displayer.close()
2520
2522
2521 def manifest(ui, repo, node=None, rev=None):
2523 def manifest(ui, repo, node=None, rev=None):
2522 """output the current or given revision of the project manifest
2524 """output the current or given revision of the project manifest
2523
2525
2524 Print a list of version controlled files for the given revision.
2526 Print a list of version controlled files for the given revision.
2525 If no revision is given, the first parent of the working directory
2527 If no revision is given, the first parent of the working directory
2526 is used, or the null revision if no revision is checked out.
2528 is used, or the null revision if no revision is checked out.
2527
2529
2528 With -v, print file permissions, symlink and executable bits.
2530 With -v, print file permissions, symlink and executable bits.
2529 With --debug, print file revision hashes.
2531 With --debug, print file revision hashes.
2530
2532
2531 Returns 0 on success.
2533 Returns 0 on success.
2532 """
2534 """
2533
2535
2534 if rev and node:
2536 if rev and node:
2535 raise util.Abort(_("please specify just one revision"))
2537 raise util.Abort(_("please specify just one revision"))
2536
2538
2537 if not node:
2539 if not node:
2538 node = rev
2540 node = rev
2539
2541
2540 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2542 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2541 ctx = repo[node]
2543 ctx = repo[node]
2542 for f in ctx:
2544 for f in ctx:
2543 if ui.debugflag:
2545 if ui.debugflag:
2544 ui.write("%40s " % hex(ctx.manifest()[f]))
2546 ui.write("%40s " % hex(ctx.manifest()[f]))
2545 if ui.verbose:
2547 if ui.verbose:
2546 ui.write(decor[ctx.flags(f)])
2548 ui.write(decor[ctx.flags(f)])
2547 ui.write("%s\n" % f)
2549 ui.write("%s\n" % f)
2548
2550
2549 def merge(ui, repo, node=None, **opts):
2551 def merge(ui, repo, node=None, **opts):
2550 """merge working directory with another revision
2552 """merge working directory with another revision
2551
2553
2552 The current working directory is updated with all changes made in
2554 The current working directory is updated with all changes made in
2553 the requested revision since the last common predecessor revision.
2555 the requested revision since the last common predecessor revision.
2554
2556
2555 Files that changed between either parent are marked as changed for
2557 Files that changed between either parent are marked as changed for
2556 the next commit and a commit must be performed before any further
2558 the next commit and a commit must be performed before any further
2557 updates to the repository are allowed. The next commit will have
2559 updates to the repository are allowed. The next commit will have
2558 two parents.
2560 two parents.
2559
2561
2560 If no revision is specified, the working directory's parent is a
2562 If no revision is specified, the working directory's parent is a
2561 head revision, and the current branch contains exactly one other
2563 head revision, and the current branch contains exactly one other
2562 head, the other head is merged with by default. Otherwise, an
2564 head, the other head is merged with by default. Otherwise, an
2563 explicit revision with which to merge with must be provided.
2565 explicit revision with which to merge with must be provided.
2564
2566
2565 To undo an uncommitted merge, use :hg:`update --clean .` which
2567 To undo an uncommitted merge, use :hg:`update --clean .` which
2566 will check out a clean copy of the original merge parent, losing
2568 will check out a clean copy of the original merge parent, losing
2567 all changes.
2569 all changes.
2568
2570
2569 Returns 0 on success, 1 if there are unresolved files.
2571 Returns 0 on success, 1 if there are unresolved files.
2570 """
2572 """
2571
2573
2572 if opts.get('rev') and node:
2574 if opts.get('rev') and node:
2573 raise util.Abort(_("please specify just one revision"))
2575 raise util.Abort(_("please specify just one revision"))
2574 if not node:
2576 if not node:
2575 node = opts.get('rev')
2577 node = opts.get('rev')
2576
2578
2577 if not node:
2579 if not node:
2578 branch = repo.changectx(None).branch()
2580 branch = repo.changectx(None).branch()
2579 bheads = repo.branchheads(branch)
2581 bheads = repo.branchheads(branch)
2580 if len(bheads) > 2:
2582 if len(bheads) > 2:
2581 raise util.Abort(_(
2583 raise util.Abort(_(
2582 'branch \'%s\' has %d heads - '
2584 'branch \'%s\' has %d heads - '
2583 'please merge with an explicit rev\n'
2585 'please merge with an explicit rev\n'
2584 '(run \'hg heads .\' to see heads)')
2586 '(run \'hg heads .\' to see heads)')
2585 % (branch, len(bheads)))
2587 % (branch, len(bheads)))
2586
2588
2587 parent = repo.dirstate.parents()[0]
2589 parent = repo.dirstate.parents()[0]
2588 if len(bheads) == 1:
2590 if len(bheads) == 1:
2589 if len(repo.heads()) > 1:
2591 if len(repo.heads()) > 1:
2590 raise util.Abort(_(
2592 raise util.Abort(_(
2591 'branch \'%s\' has one head - '
2593 'branch \'%s\' has one head - '
2592 'please merge with an explicit rev\n'
2594 'please merge with an explicit rev\n'
2593 '(run \'hg heads\' to see all heads)')
2595 '(run \'hg heads\' to see all heads)')
2594 % branch)
2596 % branch)
2595 msg = _('there is nothing to merge')
2597 msg = _('there is nothing to merge')
2596 if parent != repo.lookup(repo[None].branch()):
2598 if parent != repo.lookup(repo[None].branch()):
2597 msg = _('%s - use "hg update" instead') % msg
2599 msg = _('%s - use "hg update" instead') % msg
2598 raise util.Abort(msg)
2600 raise util.Abort(msg)
2599
2601
2600 if parent not in bheads:
2602 if parent not in bheads:
2601 raise util.Abort(_('working dir not at a head rev - '
2603 raise util.Abort(_('working dir not at a head rev - '
2602 'use "hg update" or merge with an explicit rev'))
2604 'use "hg update" or merge with an explicit rev'))
2603 node = parent == bheads[0] and bheads[-1] or bheads[0]
2605 node = parent == bheads[0] and bheads[-1] or bheads[0]
2604
2606
2605 if opts.get('preview'):
2607 if opts.get('preview'):
2606 # find nodes that are ancestors of p2 but not of p1
2608 # find nodes that are ancestors of p2 but not of p1
2607 p1 = repo.lookup('.')
2609 p1 = repo.lookup('.')
2608 p2 = repo.lookup(node)
2610 p2 = repo.lookup(node)
2609 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2611 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2610
2612
2611 displayer = cmdutil.show_changeset(ui, repo, opts)
2613 displayer = cmdutil.show_changeset(ui, repo, opts)
2612 for node in nodes:
2614 for node in nodes:
2613 displayer.show(repo[node])
2615 displayer.show(repo[node])
2614 displayer.close()
2616 displayer.close()
2615 return 0
2617 return 0
2616
2618
2617 return hg.merge(repo, node, force=opts.get('force'))
2619 return hg.merge(repo, node, force=opts.get('force'))
2618
2620
2619 def outgoing(ui, repo, dest=None, **opts):
2621 def outgoing(ui, repo, dest=None, **opts):
2620 """show changesets not found in the destination
2622 """show changesets not found in the destination
2621
2623
2622 Show changesets not found in the specified destination repository
2624 Show changesets not found in the specified destination repository
2623 or the default push location. These are the changesets that would
2625 or the default push location. These are the changesets that would
2624 be pushed if a push was requested.
2626 be pushed if a push was requested.
2625
2627
2626 See pull for details of valid destination formats.
2628 See pull for details of valid destination formats.
2627
2629
2628 Returns 0 if there are outgoing changes, 1 otherwise.
2630 Returns 0 if there are outgoing changes, 1 otherwise.
2629 """
2631 """
2630 ret = hg.outgoing(ui, repo, dest, opts)
2632 ret = hg.outgoing(ui, repo, dest, opts)
2631 if opts.get('subrepos'):
2633 if opts.get('subrepos'):
2632 ctx = repo[None]
2634 ctx = repo[None]
2633 for subpath in sorted(ctx.substate):
2635 for subpath in sorted(ctx.substate):
2634 sub = ctx.sub(subpath)
2636 sub = ctx.sub(subpath)
2635 ret = min(ret, sub.outgoing(ui, dest, opts))
2637 ret = min(ret, sub.outgoing(ui, dest, opts))
2636 return ret
2638 return ret
2637
2639
2638 def parents(ui, repo, file_=None, **opts):
2640 def parents(ui, repo, file_=None, **opts):
2639 """show the parents of the working directory or revision
2641 """show the parents of the working directory or revision
2640
2642
2641 Print the working directory's parent revisions. If a revision is
2643 Print the working directory's parent revisions. If a revision is
2642 given via -r/--rev, the parent of that revision will be printed.
2644 given via -r/--rev, the parent of that revision will be printed.
2643 If a file argument is given, the revision in which the file was
2645 If a file argument is given, the revision in which the file was
2644 last changed (before the working directory revision or the
2646 last changed (before the working directory revision or the
2645 argument to --rev if given) is printed.
2647 argument to --rev if given) is printed.
2646
2648
2647 Returns 0 on success.
2649 Returns 0 on success.
2648 """
2650 """
2649 rev = opts.get('rev')
2651 rev = opts.get('rev')
2650 if rev:
2652 if rev:
2651 ctx = repo[rev]
2653 ctx = repo[rev]
2652 else:
2654 else:
2653 ctx = repo[None]
2655 ctx = repo[None]
2654
2656
2655 if file_:
2657 if file_:
2656 m = cmdutil.match(repo, (file_,), opts)
2658 m = cmdutil.match(repo, (file_,), opts)
2657 if m.anypats() or len(m.files()) != 1:
2659 if m.anypats() or len(m.files()) != 1:
2658 raise util.Abort(_('can only specify an explicit filename'))
2660 raise util.Abort(_('can only specify an explicit filename'))
2659 file_ = m.files()[0]
2661 file_ = m.files()[0]
2660 filenodes = []
2662 filenodes = []
2661 for cp in ctx.parents():
2663 for cp in ctx.parents():
2662 if not cp:
2664 if not cp:
2663 continue
2665 continue
2664 try:
2666 try:
2665 filenodes.append(cp.filenode(file_))
2667 filenodes.append(cp.filenode(file_))
2666 except error.LookupError:
2668 except error.LookupError:
2667 pass
2669 pass
2668 if not filenodes:
2670 if not filenodes:
2669 raise util.Abort(_("'%s' not found in manifest!") % file_)
2671 raise util.Abort(_("'%s' not found in manifest!") % file_)
2670 fl = repo.file(file_)
2672 fl = repo.file(file_)
2671 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2673 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2672 else:
2674 else:
2673 p = [cp.node() for cp in ctx.parents()]
2675 p = [cp.node() for cp in ctx.parents()]
2674
2676
2675 displayer = cmdutil.show_changeset(ui, repo, opts)
2677 displayer = cmdutil.show_changeset(ui, repo, opts)
2676 for n in p:
2678 for n in p:
2677 if n != nullid:
2679 if n != nullid:
2678 displayer.show(repo[n])
2680 displayer.show(repo[n])
2679 displayer.close()
2681 displayer.close()
2680
2682
2681 def paths(ui, repo, search=None):
2683 def paths(ui, repo, search=None):
2682 """show aliases for remote repositories
2684 """show aliases for remote repositories
2683
2685
2684 Show definition of symbolic path name NAME. If no name is given,
2686 Show definition of symbolic path name NAME. If no name is given,
2685 show definition of all available names.
2687 show definition of all available names.
2686
2688
2687 Path names are defined in the [paths] section of your
2689 Path names are defined in the [paths] section of your
2688 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2690 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2689 repository, ``.hg/hgrc`` is used, too.
2691 repository, ``.hg/hgrc`` is used, too.
2690
2692
2691 The path names ``default`` and ``default-push`` have a special
2693 The path names ``default`` and ``default-push`` have a special
2692 meaning. When performing a push or pull operation, they are used
2694 meaning. When performing a push or pull operation, they are used
2693 as fallbacks if no location is specified on the command-line.
2695 as fallbacks if no location is specified on the command-line.
2694 When ``default-push`` is set, it will be used for push and
2696 When ``default-push`` is set, it will be used for push and
2695 ``default`` will be used for pull; otherwise ``default`` is used
2697 ``default`` will be used for pull; otherwise ``default`` is used
2696 as the fallback for both. When cloning a repository, the clone
2698 as the fallback for both. When cloning a repository, the clone
2697 source is written as ``default`` in ``.hg/hgrc``. Note that
2699 source is written as ``default`` in ``.hg/hgrc``. Note that
2698 ``default`` and ``default-push`` apply to all inbound (e.g.
2700 ``default`` and ``default-push`` apply to all inbound (e.g.
2699 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2701 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2700 :hg:`bundle`) operations.
2702 :hg:`bundle`) operations.
2701
2703
2702 See :hg:`help urls` for more information.
2704 See :hg:`help urls` for more information.
2703
2705
2704 Returns 0 on success.
2706 Returns 0 on success.
2705 """
2707 """
2706 if search:
2708 if search:
2707 for name, path in ui.configitems("paths"):
2709 for name, path in ui.configitems("paths"):
2708 if name == search:
2710 if name == search:
2709 ui.write("%s\n" % url.hidepassword(path))
2711 ui.write("%s\n" % url.hidepassword(path))
2710 return
2712 return
2711 ui.warn(_("not found!\n"))
2713 ui.warn(_("not found!\n"))
2712 return 1
2714 return 1
2713 else:
2715 else:
2714 for name, path in ui.configitems("paths"):
2716 for name, path in ui.configitems("paths"):
2715 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2717 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2716
2718
2717 def postincoming(ui, repo, modheads, optupdate, checkout):
2719 def postincoming(ui, repo, modheads, optupdate, checkout):
2718 if modheads == 0:
2720 if modheads == 0:
2719 return
2721 return
2720 if optupdate:
2722 if optupdate:
2721 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2723 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2722 return hg.update(repo, checkout)
2724 return hg.update(repo, checkout)
2723 else:
2725 else:
2724 ui.status(_("not updating, since new heads added\n"))
2726 ui.status(_("not updating, since new heads added\n"))
2725 if modheads > 1:
2727 if modheads > 1:
2726 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2728 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2727 else:
2729 else:
2728 ui.status(_("(run 'hg update' to get a working copy)\n"))
2730 ui.status(_("(run 'hg update' to get a working copy)\n"))
2729
2731
2730 def pull(ui, repo, source="default", **opts):
2732 def pull(ui, repo, source="default", **opts):
2731 """pull changes from the specified source
2733 """pull changes from the specified source
2732
2734
2733 Pull changes from a remote repository to a local one.
2735 Pull changes from a remote repository to a local one.
2734
2736
2735 This finds all changes from the repository at the specified path
2737 This finds all changes from the repository at the specified path
2736 or URL and adds them to a local repository (the current one unless
2738 or URL and adds them to a local repository (the current one unless
2737 -R is specified). By default, this does not update the copy of the
2739 -R is specified). By default, this does not update the copy of the
2738 project in the working directory.
2740 project in the working directory.
2739
2741
2740 Use :hg:`incoming` if you want to see what would have been added
2742 Use :hg:`incoming` if you want to see what would have been added
2741 by a pull at the time you issued this command. If you then decide
2743 by a pull at the time you issued this command. If you then decide
2742 to add those changes to the repository, you should use :hg:`pull
2744 to add those changes to the repository, you should use :hg:`pull
2743 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2745 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2744
2746
2745 If SOURCE is omitted, the 'default' path will be used.
2747 If SOURCE is omitted, the 'default' path will be used.
2746 See :hg:`help urls` for more information.
2748 See :hg:`help urls` for more information.
2747
2749
2748 Returns 0 on success, 1 if an update had unresolved files.
2750 Returns 0 on success, 1 if an update had unresolved files.
2749 """
2751 """
2750 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2752 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2751 other = hg.repository(hg.remoteui(repo, opts), source)
2753 other = hg.repository(hg.remoteui(repo, opts), source)
2752 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2754 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2753 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2755 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2754 if revs:
2756 if revs:
2755 try:
2757 try:
2756 revs = [other.lookup(rev) for rev in revs]
2758 revs = [other.lookup(rev) for rev in revs]
2757 except error.CapabilityError:
2759 except error.CapabilityError:
2758 err = _("other repository doesn't support revision lookup, "
2760 err = _("other repository doesn't support revision lookup, "
2759 "so a rev cannot be specified.")
2761 "so a rev cannot be specified.")
2760 raise util.Abort(err)
2762 raise util.Abort(err)
2761
2763
2762 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2764 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2763 if checkout:
2765 if checkout:
2764 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2766 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2765 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2767 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2766
2768
2767 def push(ui, repo, dest=None, **opts):
2769 def push(ui, repo, dest=None, **opts):
2768 """push changes to the specified destination
2770 """push changes to the specified destination
2769
2771
2770 Push changesets from the local repository to the specified
2772 Push changesets from the local repository to the specified
2771 destination.
2773 destination.
2772
2774
2773 This operation is symmetrical to pull: it is identical to a pull
2775 This operation is symmetrical to pull: it is identical to a pull
2774 in the destination repository from the current one.
2776 in the destination repository from the current one.
2775
2777
2776 By default, push will not allow creation of new heads at the
2778 By default, push will not allow creation of new heads at the
2777 destination, since multiple heads would make it unclear which head
2779 destination, since multiple heads would make it unclear which head
2778 to use. In this situation, it is recommended to pull and merge
2780 to use. In this situation, it is recommended to pull and merge
2779 before pushing.
2781 before pushing.
2780
2782
2781 Use --new-branch if you want to allow push to create a new named
2783 Use --new-branch if you want to allow push to create a new named
2782 branch that is not present at the destination. This allows you to
2784 branch that is not present at the destination. This allows you to
2783 only create a new branch without forcing other changes.
2785 only create a new branch without forcing other changes.
2784
2786
2785 Use -f/--force to override the default behavior and push all
2787 Use -f/--force to override the default behavior and push all
2786 changesets on all branches.
2788 changesets on all branches.
2787
2789
2788 If -r/--rev is used, the specified revision and all its ancestors
2790 If -r/--rev is used, the specified revision and all its ancestors
2789 will be pushed to the remote repository.
2791 will be pushed to the remote repository.
2790
2792
2791 Please see :hg:`help urls` for important details about ``ssh://``
2793 Please see :hg:`help urls` for important details about ``ssh://``
2792 URLs. If DESTINATION is omitted, a default path will be used.
2794 URLs. If DESTINATION is omitted, a default path will be used.
2793
2795
2794 Returns 0 if push was successful, 1 if nothing to push.
2796 Returns 0 if push was successful, 1 if nothing to push.
2795 """
2797 """
2796 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2798 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2797 dest, branches = hg.parseurl(dest, opts.get('branch'))
2799 dest, branches = hg.parseurl(dest, opts.get('branch'))
2798 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2800 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2799 other = hg.repository(hg.remoteui(repo, opts), dest)
2801 other = hg.repository(hg.remoteui(repo, opts), dest)
2800 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2802 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2801 if revs:
2803 if revs:
2802 revs = [repo.lookup(rev) for rev in revs]
2804 revs = [repo.lookup(rev) for rev in revs]
2803
2805
2804 # push subrepos depth-first for coherent ordering
2806 # push subrepos depth-first for coherent ordering
2805 c = repo['']
2807 c = repo['']
2806 subs = c.substate # only repos that are committed
2808 subs = c.substate # only repos that are committed
2807 for s in sorted(subs):
2809 for s in sorted(subs):
2808 if not c.sub(s).push(opts.get('force')):
2810 if not c.sub(s).push(opts.get('force')):
2809 return False
2811 return False
2810
2812
2811 r = repo.push(other, opts.get('force'), revs=revs,
2813 r = repo.push(other, opts.get('force'), revs=revs,
2812 newbranch=opts.get('new_branch'))
2814 newbranch=opts.get('new_branch'))
2813 return r == 0
2815 return r == 0
2814
2816
2815 def recover(ui, repo):
2817 def recover(ui, repo):
2816 """roll back an interrupted transaction
2818 """roll back an interrupted transaction
2817
2819
2818 Recover from an interrupted commit or pull.
2820 Recover from an interrupted commit or pull.
2819
2821
2820 This command tries to fix the repository status after an
2822 This command tries to fix the repository status after an
2821 interrupted operation. It should only be necessary when Mercurial
2823 interrupted operation. It should only be necessary when Mercurial
2822 suggests it.
2824 suggests it.
2823
2825
2824 Returns 0 if successful, 1 if nothing to recover or verify fails.
2826 Returns 0 if successful, 1 if nothing to recover or verify fails.
2825 """
2827 """
2826 if repo.recover():
2828 if repo.recover():
2827 return hg.verify(repo)
2829 return hg.verify(repo)
2828 return 1
2830 return 1
2829
2831
2830 def remove(ui, repo, *pats, **opts):
2832 def remove(ui, repo, *pats, **opts):
2831 """remove the specified files on the next commit
2833 """remove the specified files on the next commit
2832
2834
2833 Schedule the indicated files for removal from the repository.
2835 Schedule the indicated files for removal from the repository.
2834
2836
2835 This only removes files from the current branch, not from the
2837 This only removes files from the current branch, not from the
2836 entire project history. -A/--after can be used to remove only
2838 entire project history. -A/--after can be used to remove only
2837 files that have already been deleted, -f/--force can be used to
2839 files that have already been deleted, -f/--force can be used to
2838 force deletion, and -Af can be used to remove files from the next
2840 force deletion, and -Af can be used to remove files from the next
2839 revision without deleting them from the working directory.
2841 revision without deleting them from the working directory.
2840
2842
2841 The following table details the behavior of remove for different
2843 The following table details the behavior of remove for different
2842 file states (columns) and option combinations (rows). The file
2844 file states (columns) and option combinations (rows). The file
2843 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2845 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2844 reported by :hg:`status`). The actions are Warn, Remove (from
2846 reported by :hg:`status`). The actions are Warn, Remove (from
2845 branch) and Delete (from disk)::
2847 branch) and Delete (from disk)::
2846
2848
2847 A C M !
2849 A C M !
2848 none W RD W R
2850 none W RD W R
2849 -f R RD RD R
2851 -f R RD RD R
2850 -A W W W R
2852 -A W W W R
2851 -Af R R R R
2853 -Af R R R R
2852
2854
2853 This command schedules the files to be removed at the next commit.
2855 This command schedules the files to be removed at the next commit.
2854 To undo a remove before that, see :hg:`revert`.
2856 To undo a remove before that, see :hg:`revert`.
2855
2857
2856 Returns 0 on success, 1 if any warnings encountered.
2858 Returns 0 on success, 1 if any warnings encountered.
2857 """
2859 """
2858
2860
2859 ret = 0
2861 ret = 0
2860 after, force = opts.get('after'), opts.get('force')
2862 after, force = opts.get('after'), opts.get('force')
2861 if not pats and not after:
2863 if not pats and not after:
2862 raise util.Abort(_('no files specified'))
2864 raise util.Abort(_('no files specified'))
2863
2865
2864 m = cmdutil.match(repo, pats, opts)
2866 m = cmdutil.match(repo, pats, opts)
2865 s = repo.status(match=m, clean=True)
2867 s = repo.status(match=m, clean=True)
2866 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2868 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2867
2869
2868 for f in m.files():
2870 for f in m.files():
2869 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2871 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2870 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2872 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2871 ret = 1
2873 ret = 1
2872
2874
2873 if force:
2875 if force:
2874 remove, forget = modified + deleted + clean, added
2876 remove, forget = modified + deleted + clean, added
2875 elif after:
2877 elif after:
2876 remove, forget = deleted, []
2878 remove, forget = deleted, []
2877 for f in modified + added + clean:
2879 for f in modified + added + clean:
2878 ui.warn(_('not removing %s: file still exists (use -f'
2880 ui.warn(_('not removing %s: file still exists (use -f'
2879 ' to force removal)\n') % m.rel(f))
2881 ' to force removal)\n') % m.rel(f))
2880 ret = 1
2882 ret = 1
2881 else:
2883 else:
2882 remove, forget = deleted + clean, []
2884 remove, forget = deleted + clean, []
2883 for f in modified:
2885 for f in modified:
2884 ui.warn(_('not removing %s: file is modified (use -f'
2886 ui.warn(_('not removing %s: file is modified (use -f'
2885 ' to force removal)\n') % m.rel(f))
2887 ' to force removal)\n') % m.rel(f))
2886 ret = 1
2888 ret = 1
2887 for f in added:
2889 for f in added:
2888 ui.warn(_('not removing %s: file has been marked for add (use -f'
2890 ui.warn(_('not removing %s: file has been marked for add (use -f'
2889 ' to force removal)\n') % m.rel(f))
2891 ' to force removal)\n') % m.rel(f))
2890 ret = 1
2892 ret = 1
2891
2893
2892 for f in sorted(remove + forget):
2894 for f in sorted(remove + forget):
2893 if ui.verbose or not m.exact(f):
2895 if ui.verbose or not m.exact(f):
2894 ui.status(_('removing %s\n') % m.rel(f))
2896 ui.status(_('removing %s\n') % m.rel(f))
2895
2897
2896 repo[None].forget(forget)
2898 repo[None].forget(forget)
2897 repo[None].remove(remove, unlink=not after)
2899 repo[None].remove(remove, unlink=not after)
2898 return ret
2900 return ret
2899
2901
2900 def rename(ui, repo, *pats, **opts):
2902 def rename(ui, repo, *pats, **opts):
2901 """rename files; equivalent of copy + remove
2903 """rename files; equivalent of copy + remove
2902
2904
2903 Mark dest as copies of sources; mark sources for deletion. If dest
2905 Mark dest as copies of sources; mark sources for deletion. If dest
2904 is a directory, copies are put in that directory. If dest is a
2906 is a directory, copies are put in that directory. If dest is a
2905 file, there can only be one source.
2907 file, there can only be one source.
2906
2908
2907 By default, this command copies the contents of files as they
2909 By default, this command copies the contents of files as they
2908 exist in the working directory. If invoked with -A/--after, the
2910 exist in the working directory. If invoked with -A/--after, the
2909 operation is recorded, but no copying is performed.
2911 operation is recorded, but no copying is performed.
2910
2912
2911 This command takes effect at the next commit. To undo a rename
2913 This command takes effect at the next commit. To undo a rename
2912 before that, see :hg:`revert`.
2914 before that, see :hg:`revert`.
2913
2915
2914 Returns 0 on success, 1 if errors are encountered.
2916 Returns 0 on success, 1 if errors are encountered.
2915 """
2917 """
2916 wlock = repo.wlock(False)
2918 wlock = repo.wlock(False)
2917 try:
2919 try:
2918 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2920 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2919 finally:
2921 finally:
2920 wlock.release()
2922 wlock.release()
2921
2923
2922 def resolve(ui, repo, *pats, **opts):
2924 def resolve(ui, repo, *pats, **opts):
2923 """redo merges or set/view the merge status of files
2925 """redo merges or set/view the merge status of files
2924
2926
2925 Merges with unresolved conflicts are often the result of
2927 Merges with unresolved conflicts are often the result of
2926 non-interactive merging using the ``internal:merge`` configuration
2928 non-interactive merging using the ``internal:merge`` configuration
2927 setting, or a command-line merge tool like ``diff3``. The resolve
2929 setting, or a command-line merge tool like ``diff3``. The resolve
2928 command is used to manage the files involved in a merge, after
2930 command is used to manage the files involved in a merge, after
2929 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2931 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2930 working directory must have two parents).
2932 working directory must have two parents).
2931
2933
2932 The resolve command can be used in the following ways:
2934 The resolve command can be used in the following ways:
2933
2935
2934 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
2936 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
2935 discarding any previous merge attempts. Re-merging is not
2937 discarding any previous merge attempts. Re-merging is not
2936 performed for files already marked as resolved. Use ``--all/-a``
2938 performed for files already marked as resolved. Use ``--all/-a``
2937 to selects all unresolved files.
2939 to selects all unresolved files.
2938
2940
2939 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2941 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2940 (e.g. after having manually fixed-up the files). The default is
2942 (e.g. after having manually fixed-up the files). The default is
2941 to mark all unresolved files.
2943 to mark all unresolved files.
2942
2944
2943 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2945 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2944 default is to mark all resolved files.
2946 default is to mark all resolved files.
2945
2947
2946 - :hg:`resolve -l`: list files which had or still have conflicts.
2948 - :hg:`resolve -l`: list files which had or still have conflicts.
2947 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2949 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2948
2950
2949 Note that Mercurial will not let you commit files with unresolved
2951 Note that Mercurial will not let you commit files with unresolved
2950 merge conflicts. You must use :hg:`resolve -m ...` before you can
2952 merge conflicts. You must use :hg:`resolve -m ...` before you can
2951 commit after a conflicting merge.
2953 commit after a conflicting merge.
2952
2954
2953 Returns 0 on success, 1 if any files fail a resolve attempt.
2955 Returns 0 on success, 1 if any files fail a resolve attempt.
2954 """
2956 """
2955
2957
2956 all, mark, unmark, show, nostatus = \
2958 all, mark, unmark, show, nostatus = \
2957 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2959 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2958
2960
2959 if (show and (mark or unmark)) or (mark and unmark):
2961 if (show and (mark or unmark)) or (mark and unmark):
2960 raise util.Abort(_("too many options specified"))
2962 raise util.Abort(_("too many options specified"))
2961 if pats and all:
2963 if pats and all:
2962 raise util.Abort(_("can't specify --all and patterns"))
2964 raise util.Abort(_("can't specify --all and patterns"))
2963 if not (all or pats or show or mark or unmark):
2965 if not (all or pats or show or mark or unmark):
2964 raise util.Abort(_('no files or directories specified; '
2966 raise util.Abort(_('no files or directories specified; '
2965 'use --all to remerge all files'))
2967 'use --all to remerge all files'))
2966
2968
2967 ms = mergemod.mergestate(repo)
2969 ms = mergemod.mergestate(repo)
2968 m = cmdutil.match(repo, pats, opts)
2970 m = cmdutil.match(repo, pats, opts)
2969 ret = 0
2971 ret = 0
2970
2972
2971 for f in ms:
2973 for f in ms:
2972 if m(f):
2974 if m(f):
2973 if show:
2975 if show:
2974 if nostatus:
2976 if nostatus:
2975 ui.write("%s\n" % f)
2977 ui.write("%s\n" % f)
2976 else:
2978 else:
2977 ui.write("%s %s\n" % (ms[f].upper(), f),
2979 ui.write("%s %s\n" % (ms[f].upper(), f),
2978 label='resolve.' +
2980 label='resolve.' +
2979 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2981 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2980 elif mark:
2982 elif mark:
2981 ms.mark(f, "r")
2983 ms.mark(f, "r")
2982 elif unmark:
2984 elif unmark:
2983 ms.mark(f, "u")
2985 ms.mark(f, "u")
2984 else:
2986 else:
2985 wctx = repo[None]
2987 wctx = repo[None]
2986 mctx = wctx.parents()[-1]
2988 mctx = wctx.parents()[-1]
2987
2989
2988 # backup pre-resolve (merge uses .orig for its own purposes)
2990 # backup pre-resolve (merge uses .orig for its own purposes)
2989 a = repo.wjoin(f)
2991 a = repo.wjoin(f)
2990 util.copyfile(a, a + ".resolve")
2992 util.copyfile(a, a + ".resolve")
2991
2993
2992 # resolve file
2994 # resolve file
2993 if ms.resolve(f, wctx, mctx):
2995 if ms.resolve(f, wctx, mctx):
2994 ret = 1
2996 ret = 1
2995
2997
2996 # replace filemerge's .orig file with our resolve file
2998 # replace filemerge's .orig file with our resolve file
2997 util.rename(a + ".resolve", a + ".orig")
2999 util.rename(a + ".resolve", a + ".orig")
2998
3000
2999 ms.commit()
3001 ms.commit()
3000 return ret
3002 return ret
3001
3003
3002 def revert(ui, repo, *pats, **opts):
3004 def revert(ui, repo, *pats, **opts):
3003 """restore individual files or directories to an earlier state
3005 """restore individual files or directories to an earlier state
3004
3006
3005 NOTE: This command is most likely not what you are looking for. revert
3007 .. note::
3006 will partially overwrite content in the working directory without changing
3008 This command is most likely not what you are looking for.
3007 the working directory parents. Use :hg:`update -r rev` to check out earlier
3009 revert will partially overwrite content in the working
3008 revisions, or :hg:`update --clean .` to undo a merge which has added
3010 directory without changing the working directory parents. Use
3009 another parent.
3011 :hg:`update -r rev` to check out earlier revisions, or
3012 :hg:`update --clean .` to undo a merge which has added another
3013 parent.
3010
3014
3011 With no revision specified, revert the named files or directories
3015 With no revision specified, revert the named files or directories
3012 to the contents they had in the parent of the working directory.
3016 to the contents they had in the parent of the working directory.
3013 This restores the contents of the affected files to an unmodified
3017 This restores the contents of the affected files to an unmodified
3014 state and unschedules adds, removes, copies, and renames. If the
3018 state and unschedules adds, removes, copies, and renames. If the
3015 working directory has two parents, you must explicitly specify a
3019 working directory has two parents, you must explicitly specify a
3016 revision.
3020 revision.
3017
3021
3018 Using the -r/--rev option, revert the given files or directories
3022 Using the -r/--rev option, revert the given files or directories
3019 to their contents as of a specific revision. This can be helpful
3023 to their contents as of a specific revision. This can be helpful
3020 to "roll back" some or all of an earlier change. See :hg:`help
3024 to "roll back" some or all of an earlier change. See :hg:`help
3021 dates` for a list of formats valid for -d/--date.
3025 dates` for a list of formats valid for -d/--date.
3022
3026
3023 Revert modifies the working directory. It does not commit any
3027 Revert modifies the working directory. It does not commit any
3024 changes, or change the parent of the working directory. If you
3028 changes, or change the parent of the working directory. If you
3025 revert to a revision other than the parent of the working
3029 revert to a revision other than the parent of the working
3026 directory, the reverted files will thus appear modified
3030 directory, the reverted files will thus appear modified
3027 afterwards.
3031 afterwards.
3028
3032
3029 If a file has been deleted, it is restored. If the executable mode
3033 If a file has been deleted, it is restored. If the executable mode
3030 of a file was changed, it is reset.
3034 of a file was changed, it is reset.
3031
3035
3032 If names are given, all files matching the names are reverted.
3036 If names are given, all files matching the names are reverted.
3033 If no arguments are given, no files are reverted.
3037 If no arguments are given, no files are reverted.
3034
3038
3035 Modified files are saved with a .orig suffix before reverting.
3039 Modified files are saved with a .orig suffix before reverting.
3036 To disable these backups, use --no-backup.
3040 To disable these backups, use --no-backup.
3037
3041
3038 Returns 0 on success.
3042 Returns 0 on success.
3039 """
3043 """
3040
3044
3041 if opts.get("date"):
3045 if opts.get("date"):
3042 if opts.get("rev"):
3046 if opts.get("rev"):
3043 raise util.Abort(_("you can't specify a revision and a date"))
3047 raise util.Abort(_("you can't specify a revision and a date"))
3044 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3048 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3045
3049
3046 if not pats and not opts.get('all'):
3050 if not pats and not opts.get('all'):
3047 raise util.Abort(_('no files or directories specified; '
3051 raise util.Abort(_('no files or directories specified; '
3048 'use --all to revert the whole repo'))
3052 'use --all to revert the whole repo'))
3049
3053
3050 parent, p2 = repo.dirstate.parents()
3054 parent, p2 = repo.dirstate.parents()
3051 if not opts.get('rev') and p2 != nullid:
3055 if not opts.get('rev') and p2 != nullid:
3052 raise util.Abort(_('uncommitted merge - please provide a '
3056 raise util.Abort(_('uncommitted merge - please provide a '
3053 'specific revision'))
3057 'specific revision'))
3054 ctx = repo[opts.get('rev')]
3058 ctx = repo[opts.get('rev')]
3055 node = ctx.node()
3059 node = ctx.node()
3056 mf = ctx.manifest()
3060 mf = ctx.manifest()
3057 if node == parent:
3061 if node == parent:
3058 pmf = mf
3062 pmf = mf
3059 else:
3063 else:
3060 pmf = None
3064 pmf = None
3061
3065
3062 # need all matching names in dirstate and manifest of target rev,
3066 # need all matching names in dirstate and manifest of target rev,
3063 # so have to walk both. do not print errors if files exist in one
3067 # so have to walk both. do not print errors if files exist in one
3064 # but not other.
3068 # but not other.
3065
3069
3066 names = {}
3070 names = {}
3067
3071
3068 wlock = repo.wlock()
3072 wlock = repo.wlock()
3069 try:
3073 try:
3070 # walk dirstate.
3074 # walk dirstate.
3071
3075
3072 m = cmdutil.match(repo, pats, opts)
3076 m = cmdutil.match(repo, pats, opts)
3073 m.bad = lambda x, y: False
3077 m.bad = lambda x, y: False
3074 for abs in repo.walk(m):
3078 for abs in repo.walk(m):
3075 names[abs] = m.rel(abs), m.exact(abs)
3079 names[abs] = m.rel(abs), m.exact(abs)
3076
3080
3077 # walk target manifest.
3081 # walk target manifest.
3078
3082
3079 def badfn(path, msg):
3083 def badfn(path, msg):
3080 if path in names:
3084 if path in names:
3081 return
3085 return
3082 path_ = path + '/'
3086 path_ = path + '/'
3083 for f in names:
3087 for f in names:
3084 if f.startswith(path_):
3088 if f.startswith(path_):
3085 return
3089 return
3086 ui.warn("%s: %s\n" % (m.rel(path), msg))
3090 ui.warn("%s: %s\n" % (m.rel(path), msg))
3087
3091
3088 m = cmdutil.match(repo, pats, opts)
3092 m = cmdutil.match(repo, pats, opts)
3089 m.bad = badfn
3093 m.bad = badfn
3090 for abs in repo[node].walk(m):
3094 for abs in repo[node].walk(m):
3091 if abs not in names:
3095 if abs not in names:
3092 names[abs] = m.rel(abs), m.exact(abs)
3096 names[abs] = m.rel(abs), m.exact(abs)
3093
3097
3094 m = cmdutil.matchfiles(repo, names)
3098 m = cmdutil.matchfiles(repo, names)
3095 changes = repo.status(match=m)[:4]
3099 changes = repo.status(match=m)[:4]
3096 modified, added, removed, deleted = map(set, changes)
3100 modified, added, removed, deleted = map(set, changes)
3097
3101
3098 # if f is a rename, also revert the source
3102 # if f is a rename, also revert the source
3099 cwd = repo.getcwd()
3103 cwd = repo.getcwd()
3100 for f in added:
3104 for f in added:
3101 src = repo.dirstate.copied(f)
3105 src = repo.dirstate.copied(f)
3102 if src and src not in names and repo.dirstate[src] == 'r':
3106 if src and src not in names and repo.dirstate[src] == 'r':
3103 removed.add(src)
3107 removed.add(src)
3104 names[src] = (repo.pathto(src, cwd), True)
3108 names[src] = (repo.pathto(src, cwd), True)
3105
3109
3106 def removeforget(abs):
3110 def removeforget(abs):
3107 if repo.dirstate[abs] == 'a':
3111 if repo.dirstate[abs] == 'a':
3108 return _('forgetting %s\n')
3112 return _('forgetting %s\n')
3109 return _('removing %s\n')
3113 return _('removing %s\n')
3110
3114
3111 revert = ([], _('reverting %s\n'))
3115 revert = ([], _('reverting %s\n'))
3112 add = ([], _('adding %s\n'))
3116 add = ([], _('adding %s\n'))
3113 remove = ([], removeforget)
3117 remove = ([], removeforget)
3114 undelete = ([], _('undeleting %s\n'))
3118 undelete = ([], _('undeleting %s\n'))
3115
3119
3116 disptable = (
3120 disptable = (
3117 # dispatch table:
3121 # dispatch table:
3118 # file state
3122 # file state
3119 # action if in target manifest
3123 # action if in target manifest
3120 # action if not in target manifest
3124 # action if not in target manifest
3121 # make backup if in target manifest
3125 # make backup if in target manifest
3122 # make backup if not in target manifest
3126 # make backup if not in target manifest
3123 (modified, revert, remove, True, True),
3127 (modified, revert, remove, True, True),
3124 (added, revert, remove, True, False),
3128 (added, revert, remove, True, False),
3125 (removed, undelete, None, False, False),
3129 (removed, undelete, None, False, False),
3126 (deleted, revert, remove, False, False),
3130 (deleted, revert, remove, False, False),
3127 )
3131 )
3128
3132
3129 for abs, (rel, exact) in sorted(names.items()):
3133 for abs, (rel, exact) in sorted(names.items()):
3130 mfentry = mf.get(abs)
3134 mfentry = mf.get(abs)
3131 target = repo.wjoin(abs)
3135 target = repo.wjoin(abs)
3132 def handle(xlist, dobackup):
3136 def handle(xlist, dobackup):
3133 xlist[0].append(abs)
3137 xlist[0].append(abs)
3134 if (dobackup and not opts.get('no_backup') and
3138 if (dobackup and not opts.get('no_backup') and
3135 os.path.lexists(target)):
3139 os.path.lexists(target)):
3136 bakname = "%s.orig" % rel
3140 bakname = "%s.orig" % rel
3137 ui.note(_('saving current version of %s as %s\n') %
3141 ui.note(_('saving current version of %s as %s\n') %
3138 (rel, bakname))
3142 (rel, bakname))
3139 if not opts.get('dry_run'):
3143 if not opts.get('dry_run'):
3140 util.rename(target, bakname)
3144 util.rename(target, bakname)
3141 if ui.verbose or not exact:
3145 if ui.verbose or not exact:
3142 msg = xlist[1]
3146 msg = xlist[1]
3143 if not isinstance(msg, basestring):
3147 if not isinstance(msg, basestring):
3144 msg = msg(abs)
3148 msg = msg(abs)
3145 ui.status(msg % rel)
3149 ui.status(msg % rel)
3146 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3150 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3147 if abs not in table:
3151 if abs not in table:
3148 continue
3152 continue
3149 # file has changed in dirstate
3153 # file has changed in dirstate
3150 if mfentry:
3154 if mfentry:
3151 handle(hitlist, backuphit)
3155 handle(hitlist, backuphit)
3152 elif misslist is not None:
3156 elif misslist is not None:
3153 handle(misslist, backupmiss)
3157 handle(misslist, backupmiss)
3154 break
3158 break
3155 else:
3159 else:
3156 if abs not in repo.dirstate:
3160 if abs not in repo.dirstate:
3157 if mfentry:
3161 if mfentry:
3158 handle(add, True)
3162 handle(add, True)
3159 elif exact:
3163 elif exact:
3160 ui.warn(_('file not managed: %s\n') % rel)
3164 ui.warn(_('file not managed: %s\n') % rel)
3161 continue
3165 continue
3162 # file has not changed in dirstate
3166 # file has not changed in dirstate
3163 if node == parent:
3167 if node == parent:
3164 if exact:
3168 if exact:
3165 ui.warn(_('no changes needed to %s\n') % rel)
3169 ui.warn(_('no changes needed to %s\n') % rel)
3166 continue
3170 continue
3167 if pmf is None:
3171 if pmf is None:
3168 # only need parent manifest in this unlikely case,
3172 # only need parent manifest in this unlikely case,
3169 # so do not read by default
3173 # so do not read by default
3170 pmf = repo[parent].manifest()
3174 pmf = repo[parent].manifest()
3171 if abs in pmf:
3175 if abs in pmf:
3172 if mfentry:
3176 if mfentry:
3173 # if version of file is same in parent and target
3177 # if version of file is same in parent and target
3174 # manifests, do nothing
3178 # manifests, do nothing
3175 if (pmf[abs] != mfentry or
3179 if (pmf[abs] != mfentry or
3176 pmf.flags(abs) != mf.flags(abs)):
3180 pmf.flags(abs) != mf.flags(abs)):
3177 handle(revert, False)
3181 handle(revert, False)
3178 else:
3182 else:
3179 handle(remove, False)
3183 handle(remove, False)
3180
3184
3181 if not opts.get('dry_run'):
3185 if not opts.get('dry_run'):
3182 def checkout(f):
3186 def checkout(f):
3183 fc = ctx[f]
3187 fc = ctx[f]
3184 repo.wwrite(f, fc.data(), fc.flags())
3188 repo.wwrite(f, fc.data(), fc.flags())
3185
3189
3186 audit_path = util.path_auditor(repo.root)
3190 audit_path = util.path_auditor(repo.root)
3187 for f in remove[0]:
3191 for f in remove[0]:
3188 if repo.dirstate[f] == 'a':
3192 if repo.dirstate[f] == 'a':
3189 repo.dirstate.forget(f)
3193 repo.dirstate.forget(f)
3190 continue
3194 continue
3191 audit_path(f)
3195 audit_path(f)
3192 try:
3196 try:
3193 util.unlink(repo.wjoin(f))
3197 util.unlink(repo.wjoin(f))
3194 except OSError:
3198 except OSError:
3195 pass
3199 pass
3196 repo.dirstate.remove(f)
3200 repo.dirstate.remove(f)
3197
3201
3198 normal = None
3202 normal = None
3199 if node == parent:
3203 if node == parent:
3200 # We're reverting to our parent. If possible, we'd like status
3204 # We're reverting to our parent. If possible, we'd like status
3201 # to report the file as clean. We have to use normallookup for
3205 # to report the file as clean. We have to use normallookup for
3202 # merges to avoid losing information about merged/dirty files.
3206 # merges to avoid losing information about merged/dirty files.
3203 if p2 != nullid:
3207 if p2 != nullid:
3204 normal = repo.dirstate.normallookup
3208 normal = repo.dirstate.normallookup
3205 else:
3209 else:
3206 normal = repo.dirstate.normal
3210 normal = repo.dirstate.normal
3207 for f in revert[0]:
3211 for f in revert[0]:
3208 checkout(f)
3212 checkout(f)
3209 if normal:
3213 if normal:
3210 normal(f)
3214 normal(f)
3211
3215
3212 for f in add[0]:
3216 for f in add[0]:
3213 checkout(f)
3217 checkout(f)
3214 repo.dirstate.add(f)
3218 repo.dirstate.add(f)
3215
3219
3216 normal = repo.dirstate.normallookup
3220 normal = repo.dirstate.normallookup
3217 if node == parent and p2 == nullid:
3221 if node == parent and p2 == nullid:
3218 normal = repo.dirstate.normal
3222 normal = repo.dirstate.normal
3219 for f in undelete[0]:
3223 for f in undelete[0]:
3220 checkout(f)
3224 checkout(f)
3221 normal(f)
3225 normal(f)
3222
3226
3223 finally:
3227 finally:
3224 wlock.release()
3228 wlock.release()
3225
3229
3226 def rollback(ui, repo, **opts):
3230 def rollback(ui, repo, **opts):
3227 """roll back the last transaction (dangerous)
3231 """roll back the last transaction (dangerous)
3228
3232
3229 This command should be used with care. There is only one level of
3233 This command should be used with care. There is only one level of
3230 rollback, and there is no way to undo a rollback. It will also
3234 rollback, and there is no way to undo a rollback. It will also
3231 restore the dirstate at the time of the last transaction, losing
3235 restore the dirstate at the time of the last transaction, losing
3232 any dirstate changes since that time. This command does not alter
3236 any dirstate changes since that time. This command does not alter
3233 the working directory.
3237 the working directory.
3234
3238
3235 Transactions are used to encapsulate the effects of all commands
3239 Transactions are used to encapsulate the effects of all commands
3236 that create new changesets or propagate existing changesets into a
3240 that create new changesets or propagate existing changesets into a
3237 repository. For example, the following commands are transactional,
3241 repository. For example, the following commands are transactional,
3238 and their effects can be rolled back:
3242 and their effects can be rolled back:
3239
3243
3240 - commit
3244 - commit
3241 - import
3245 - import
3242 - pull
3246 - pull
3243 - push (with this repository as the destination)
3247 - push (with this repository as the destination)
3244 - unbundle
3248 - unbundle
3245
3249
3246 This command is not intended for use on public repositories. Once
3250 This command is not intended for use on public repositories. Once
3247 changes are visible for pull by other users, rolling a transaction
3251 changes are visible for pull by other users, rolling a transaction
3248 back locally is ineffective (someone else may already have pulled
3252 back locally is ineffective (someone else may already have pulled
3249 the changes). Furthermore, a race is possible with readers of the
3253 the changes). Furthermore, a race is possible with readers of the
3250 repository; for example an in-progress pull from the repository
3254 repository; for example an in-progress pull from the repository
3251 may fail if a rollback is performed.
3255 may fail if a rollback is performed.
3252
3256
3253 Returns 0 on success, 1 if no rollback data is available.
3257 Returns 0 on success, 1 if no rollback data is available.
3254 """
3258 """
3255 return repo.rollback(opts.get('dry_run'))
3259 return repo.rollback(opts.get('dry_run'))
3256
3260
3257 def root(ui, repo):
3261 def root(ui, repo):
3258 """print the root (top) of the current working directory
3262 """print the root (top) of the current working directory
3259
3263
3260 Print the root directory of the current repository.
3264 Print the root directory of the current repository.
3261
3265
3262 Returns 0 on success.
3266 Returns 0 on success.
3263 """
3267 """
3264 ui.write(repo.root + "\n")
3268 ui.write(repo.root + "\n")
3265
3269
3266 def serve(ui, repo, **opts):
3270 def serve(ui, repo, **opts):
3267 """start stand-alone webserver
3271 """start stand-alone webserver
3268
3272
3269 Start a local HTTP repository browser and pull server. You can use
3273 Start a local HTTP repository browser and pull server. You can use
3270 this for ad-hoc sharing and browing of repositories. It is
3274 this for ad-hoc sharing and browing of repositories. It is
3271 recommended to use a real web server to serve a repository for
3275 recommended to use a real web server to serve a repository for
3272 longer periods of time.
3276 longer periods of time.
3273
3277
3274 Please note that the server does not implement access control.
3278 Please note that the server does not implement access control.
3275 This means that, by default, anybody can read from the server and
3279 This means that, by default, anybody can read from the server and
3276 nobody can write to it by default. Set the ``web.allow_push``
3280 nobody can write to it by default. Set the ``web.allow_push``
3277 option to ``*`` to allow everybody to push to the server. You
3281 option to ``*`` to allow everybody to push to the server. You
3278 should use a real web server if you need to authenticate users.
3282 should use a real web server if you need to authenticate users.
3279
3283
3280 By default, the server logs accesses to stdout and errors to
3284 By default, the server logs accesses to stdout and errors to
3281 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3285 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3282 files.
3286 files.
3283
3287
3284 To have the server choose a free port number to listen on, specify
3288 To have the server choose a free port number to listen on, specify
3285 a port number of 0; in this case, the server will print the port
3289 a port number of 0; in this case, the server will print the port
3286 number it uses.
3290 number it uses.
3287
3291
3288 Returns 0 on success.
3292 Returns 0 on success.
3289 """
3293 """
3290
3294
3291 if opts["stdio"]:
3295 if opts["stdio"]:
3292 if repo is None:
3296 if repo is None:
3293 raise error.RepoError(_("There is no Mercurial repository here"
3297 raise error.RepoError(_("There is no Mercurial repository here"
3294 " (.hg not found)"))
3298 " (.hg not found)"))
3295 s = sshserver.sshserver(ui, repo)
3299 s = sshserver.sshserver(ui, repo)
3296 s.serve_forever()
3300 s.serve_forever()
3297
3301
3298 # this way we can check if something was given in the command-line
3302 # this way we can check if something was given in the command-line
3299 if opts.get('port'):
3303 if opts.get('port'):
3300 opts['port'] = util.getport(opts.get('port'))
3304 opts['port'] = util.getport(opts.get('port'))
3301
3305
3302 baseui = repo and repo.baseui or ui
3306 baseui = repo and repo.baseui or ui
3303 optlist = ("name templates style address port prefix ipv6"
3307 optlist = ("name templates style address port prefix ipv6"
3304 " accesslog errorlog certificate encoding")
3308 " accesslog errorlog certificate encoding")
3305 for o in optlist.split():
3309 for o in optlist.split():
3306 val = opts.get(o, '')
3310 val = opts.get(o, '')
3307 if val in (None, ''): # should check against default options instead
3311 if val in (None, ''): # should check against default options instead
3308 continue
3312 continue
3309 baseui.setconfig("web", o, val)
3313 baseui.setconfig("web", o, val)
3310 if repo and repo.ui != baseui:
3314 if repo and repo.ui != baseui:
3311 repo.ui.setconfig("web", o, val)
3315 repo.ui.setconfig("web", o, val)
3312
3316
3313 o = opts.get('web_conf') or opts.get('webdir_conf')
3317 o = opts.get('web_conf') or opts.get('webdir_conf')
3314 if not o:
3318 if not o:
3315 if not repo:
3319 if not repo:
3316 raise error.RepoError(_("There is no Mercurial repository"
3320 raise error.RepoError(_("There is no Mercurial repository"
3317 " here (.hg not found)"))
3321 " here (.hg not found)"))
3318 o = repo.root
3322 o = repo.root
3319
3323
3320 app = hgweb.hgweb(o, baseui=ui)
3324 app = hgweb.hgweb(o, baseui=ui)
3321
3325
3322 class service(object):
3326 class service(object):
3323 def init(self):
3327 def init(self):
3324 util.set_signal_handler()
3328 util.set_signal_handler()
3325 self.httpd = hgweb.server.create_server(ui, app)
3329 self.httpd = hgweb.server.create_server(ui, app)
3326
3330
3327 if opts['port'] and not ui.verbose:
3331 if opts['port'] and not ui.verbose:
3328 return
3332 return
3329
3333
3330 if self.httpd.prefix:
3334 if self.httpd.prefix:
3331 prefix = self.httpd.prefix.strip('/') + '/'
3335 prefix = self.httpd.prefix.strip('/') + '/'
3332 else:
3336 else:
3333 prefix = ''
3337 prefix = ''
3334
3338
3335 port = ':%d' % self.httpd.port
3339 port = ':%d' % self.httpd.port
3336 if port == ':80':
3340 if port == ':80':
3337 port = ''
3341 port = ''
3338
3342
3339 bindaddr = self.httpd.addr
3343 bindaddr = self.httpd.addr
3340 if bindaddr == '0.0.0.0':
3344 if bindaddr == '0.0.0.0':
3341 bindaddr = '*'
3345 bindaddr = '*'
3342 elif ':' in bindaddr: # IPv6
3346 elif ':' in bindaddr: # IPv6
3343 bindaddr = '[%s]' % bindaddr
3347 bindaddr = '[%s]' % bindaddr
3344
3348
3345 fqaddr = self.httpd.fqaddr
3349 fqaddr = self.httpd.fqaddr
3346 if ':' in fqaddr:
3350 if ':' in fqaddr:
3347 fqaddr = '[%s]' % fqaddr
3351 fqaddr = '[%s]' % fqaddr
3348 if opts['port']:
3352 if opts['port']:
3349 write = ui.status
3353 write = ui.status
3350 else:
3354 else:
3351 write = ui.write
3355 write = ui.write
3352 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3356 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3353 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3357 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3354
3358
3355 def run(self):
3359 def run(self):
3356 self.httpd.serve_forever()
3360 self.httpd.serve_forever()
3357
3361
3358 service = service()
3362 service = service()
3359
3363
3360 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3364 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3361
3365
3362 def status(ui, repo, *pats, **opts):
3366 def status(ui, repo, *pats, **opts):
3363 """show changed files in the working directory
3367 """show changed files in the working directory
3364
3368
3365 Show status of files in the repository. If names are given, only
3369 Show status of files in the repository. If names are given, only
3366 files that match are shown. Files that are clean or ignored or
3370 files that match are shown. Files that are clean or ignored or
3367 the source of a copy/move operation, are not listed unless
3371 the source of a copy/move operation, are not listed unless
3368 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3372 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3369 Unless options described with "show only ..." are given, the
3373 Unless options described with "show only ..." are given, the
3370 options -mardu are used.
3374 options -mardu are used.
3371
3375
3372 Option -q/--quiet hides untracked (unknown and ignored) files
3376 Option -q/--quiet hides untracked (unknown and ignored) files
3373 unless explicitly requested with -u/--unknown or -i/--ignored.
3377 unless explicitly requested with -u/--unknown or -i/--ignored.
3374
3378
3375 NOTE: status may appear to disagree with diff if permissions have
3379 .. note::
3376 changed or a merge has occurred. The standard diff format does not
3380 status may appear to disagree with diff if permissions have
3377 report permission changes and diff only reports changes relative
3381 changed or a merge has occurred. The standard diff format does
3378 to one merge parent.
3382 not report permission changes and diff only reports changes
3383 relative to one merge parent.
3379
3384
3380 If one revision is given, it is used as the base revision.
3385 If one revision is given, it is used as the base revision.
3381 If two revisions are given, the differences between them are
3386 If two revisions are given, the differences between them are
3382 shown. The --change option can also be used as a shortcut to list
3387 shown. The --change option can also be used as a shortcut to list
3383 the changed files of a revision from its first parent.
3388 the changed files of a revision from its first parent.
3384
3389
3385 The codes used to show the status of files are::
3390 The codes used to show the status of files are::
3386
3391
3387 M = modified
3392 M = modified
3388 A = added
3393 A = added
3389 R = removed
3394 R = removed
3390 C = clean
3395 C = clean
3391 ! = missing (deleted by non-hg command, but still tracked)
3396 ! = missing (deleted by non-hg command, but still tracked)
3392 ? = not tracked
3397 ? = not tracked
3393 I = ignored
3398 I = ignored
3394 = origin of the previous file listed as A (added)
3399 = origin of the previous file listed as A (added)
3395
3400
3396 Returns 0 on success.
3401 Returns 0 on success.
3397 """
3402 """
3398
3403
3399 revs = opts.get('rev')
3404 revs = opts.get('rev')
3400 change = opts.get('change')
3405 change = opts.get('change')
3401
3406
3402 if revs and change:
3407 if revs and change:
3403 msg = _('cannot specify --rev and --change at the same time')
3408 msg = _('cannot specify --rev and --change at the same time')
3404 raise util.Abort(msg)
3409 raise util.Abort(msg)
3405 elif change:
3410 elif change:
3406 node2 = repo.lookup(change)
3411 node2 = repo.lookup(change)
3407 node1 = repo[node2].parents()[0].node()
3412 node1 = repo[node2].parents()[0].node()
3408 else:
3413 else:
3409 node1, node2 = cmdutil.revpair(repo, revs)
3414 node1, node2 = cmdutil.revpair(repo, revs)
3410
3415
3411 cwd = (pats and repo.getcwd()) or ''
3416 cwd = (pats and repo.getcwd()) or ''
3412 end = opts.get('print0') and '\0' or '\n'
3417 end = opts.get('print0') and '\0' or '\n'
3413 copy = {}
3418 copy = {}
3414 states = 'modified added removed deleted unknown ignored clean'.split()
3419 states = 'modified added removed deleted unknown ignored clean'.split()
3415 show = [k for k in states if opts.get(k)]
3420 show = [k for k in states if opts.get(k)]
3416 if opts.get('all'):
3421 if opts.get('all'):
3417 show += ui.quiet and (states[:4] + ['clean']) or states
3422 show += ui.quiet and (states[:4] + ['clean']) or states
3418 if not show:
3423 if not show:
3419 show = ui.quiet and states[:4] or states[:5]
3424 show = ui.quiet and states[:4] or states[:5]
3420
3425
3421 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3426 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3422 'ignored' in show, 'clean' in show, 'unknown' in show,
3427 'ignored' in show, 'clean' in show, 'unknown' in show,
3423 opts.get('subrepos'))
3428 opts.get('subrepos'))
3424 changestates = zip(states, 'MAR!?IC', stat)
3429 changestates = zip(states, 'MAR!?IC', stat)
3425
3430
3426 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3431 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3427 ctxn = repo[nullid]
3432 ctxn = repo[nullid]
3428 ctx1 = repo[node1]
3433 ctx1 = repo[node1]
3429 ctx2 = repo[node2]
3434 ctx2 = repo[node2]
3430 added = stat[1]
3435 added = stat[1]
3431 if node2 is None:
3436 if node2 is None:
3432 added = stat[0] + stat[1] # merged?
3437 added = stat[0] + stat[1] # merged?
3433
3438
3434 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3439 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3435 if k in added:
3440 if k in added:
3436 copy[k] = v
3441 copy[k] = v
3437 elif v in added:
3442 elif v in added:
3438 copy[v] = k
3443 copy[v] = k
3439
3444
3440 for state, char, files in changestates:
3445 for state, char, files in changestates:
3441 if state in show:
3446 if state in show:
3442 format = "%s %%s%s" % (char, end)
3447 format = "%s %%s%s" % (char, end)
3443 if opts.get('no_status'):
3448 if opts.get('no_status'):
3444 format = "%%s%s" % end
3449 format = "%%s%s" % end
3445
3450
3446 for f in files:
3451 for f in files:
3447 ui.write(format % repo.pathto(f, cwd),
3452 ui.write(format % repo.pathto(f, cwd),
3448 label='status.' + state)
3453 label='status.' + state)
3449 if f in copy:
3454 if f in copy:
3450 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3455 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3451 label='status.copied')
3456 label='status.copied')
3452
3457
3453 def summary(ui, repo, **opts):
3458 def summary(ui, repo, **opts):
3454 """summarize working directory state
3459 """summarize working directory state
3455
3460
3456 This generates a brief summary of the working directory state,
3461 This generates a brief summary of the working directory state,
3457 including parents, branch, commit status, and available updates.
3462 including parents, branch, commit status, and available updates.
3458
3463
3459 With the --remote option, this will check the default paths for
3464 With the --remote option, this will check the default paths for
3460 incoming and outgoing changes. This can be time-consuming.
3465 incoming and outgoing changes. This can be time-consuming.
3461
3466
3462 Returns 0 on success.
3467 Returns 0 on success.
3463 """
3468 """
3464
3469
3465 ctx = repo[None]
3470 ctx = repo[None]
3466 parents = ctx.parents()
3471 parents = ctx.parents()
3467 pnode = parents[0].node()
3472 pnode = parents[0].node()
3468
3473
3469 for p in parents:
3474 for p in parents:
3470 # label with log.changeset (instead of log.parent) since this
3475 # label with log.changeset (instead of log.parent) since this
3471 # shows a working directory parent *changeset*:
3476 # shows a working directory parent *changeset*:
3472 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3477 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3473 label='log.changeset')
3478 label='log.changeset')
3474 ui.write(' '.join(p.tags()), label='log.tag')
3479 ui.write(' '.join(p.tags()), label='log.tag')
3475 if p.rev() == -1:
3480 if p.rev() == -1:
3476 if not len(repo):
3481 if not len(repo):
3477 ui.write(_(' (empty repository)'))
3482 ui.write(_(' (empty repository)'))
3478 else:
3483 else:
3479 ui.write(_(' (no revision checked out)'))
3484 ui.write(_(' (no revision checked out)'))
3480 ui.write('\n')
3485 ui.write('\n')
3481 if p.description():
3486 if p.description():
3482 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3487 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3483 label='log.summary')
3488 label='log.summary')
3484
3489
3485 branch = ctx.branch()
3490 branch = ctx.branch()
3486 bheads = repo.branchheads(branch)
3491 bheads = repo.branchheads(branch)
3487 m = _('branch: %s\n') % branch
3492 m = _('branch: %s\n') % branch
3488 if branch != 'default':
3493 if branch != 'default':
3489 ui.write(m, label='log.branch')
3494 ui.write(m, label='log.branch')
3490 else:
3495 else:
3491 ui.status(m, label='log.branch')
3496 ui.status(m, label='log.branch')
3492
3497
3493 st = list(repo.status(unknown=True))[:6]
3498 st = list(repo.status(unknown=True))[:6]
3494
3499
3495 c = repo.dirstate.copies()
3500 c = repo.dirstate.copies()
3496 copied, renamed = [], []
3501 copied, renamed = [], []
3497 for d, s in c.iteritems():
3502 for d, s in c.iteritems():
3498 if s in st[2]:
3503 if s in st[2]:
3499 st[2].remove(s)
3504 st[2].remove(s)
3500 renamed.append(d)
3505 renamed.append(d)
3501 else:
3506 else:
3502 copied.append(d)
3507 copied.append(d)
3503 if d in st[1]:
3508 if d in st[1]:
3504 st[1].remove(d)
3509 st[1].remove(d)
3505 st.insert(3, renamed)
3510 st.insert(3, renamed)
3506 st.insert(4, copied)
3511 st.insert(4, copied)
3507
3512
3508 ms = mergemod.mergestate(repo)
3513 ms = mergemod.mergestate(repo)
3509 st.append([f for f in ms if ms[f] == 'u'])
3514 st.append([f for f in ms if ms[f] == 'u'])
3510
3515
3511 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3516 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3512 st.append(subs)
3517 st.append(subs)
3513
3518
3514 labels = [ui.label(_('%d modified'), 'status.modified'),
3519 labels = [ui.label(_('%d modified'), 'status.modified'),
3515 ui.label(_('%d added'), 'status.added'),
3520 ui.label(_('%d added'), 'status.added'),
3516 ui.label(_('%d removed'), 'status.removed'),
3521 ui.label(_('%d removed'), 'status.removed'),
3517 ui.label(_('%d renamed'), 'status.copied'),
3522 ui.label(_('%d renamed'), 'status.copied'),
3518 ui.label(_('%d copied'), 'status.copied'),
3523 ui.label(_('%d copied'), 'status.copied'),
3519 ui.label(_('%d deleted'), 'status.deleted'),
3524 ui.label(_('%d deleted'), 'status.deleted'),
3520 ui.label(_('%d unknown'), 'status.unknown'),
3525 ui.label(_('%d unknown'), 'status.unknown'),
3521 ui.label(_('%d ignored'), 'status.ignored'),
3526 ui.label(_('%d ignored'), 'status.ignored'),
3522 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3527 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3523 ui.label(_('%d subrepos'), 'status.modified')]
3528 ui.label(_('%d subrepos'), 'status.modified')]
3524 t = []
3529 t = []
3525 for s, l in zip(st, labels):
3530 for s, l in zip(st, labels):
3526 if s:
3531 if s:
3527 t.append(l % len(s))
3532 t.append(l % len(s))
3528
3533
3529 t = ', '.join(t)
3534 t = ', '.join(t)
3530 cleanworkdir = False
3535 cleanworkdir = False
3531
3536
3532 if len(parents) > 1:
3537 if len(parents) > 1:
3533 t += _(' (merge)')
3538 t += _(' (merge)')
3534 elif branch != parents[0].branch():
3539 elif branch != parents[0].branch():
3535 t += _(' (new branch)')
3540 t += _(' (new branch)')
3536 elif (parents[0].extra().get('close') and
3541 elif (parents[0].extra().get('close') and
3537 pnode in repo.branchheads(branch, closed=True)):
3542 pnode in repo.branchheads(branch, closed=True)):
3538 t += _(' (head closed)')
3543 t += _(' (head closed)')
3539 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3544 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3540 t += _(' (clean)')
3545 t += _(' (clean)')
3541 cleanworkdir = True
3546 cleanworkdir = True
3542 elif pnode not in bheads:
3547 elif pnode not in bheads:
3543 t += _(' (new branch head)')
3548 t += _(' (new branch head)')
3544
3549
3545 if cleanworkdir:
3550 if cleanworkdir:
3546 ui.status(_('commit: %s\n') % t.strip())
3551 ui.status(_('commit: %s\n') % t.strip())
3547 else:
3552 else:
3548 ui.write(_('commit: %s\n') % t.strip())
3553 ui.write(_('commit: %s\n') % t.strip())
3549
3554
3550 # all ancestors of branch heads - all ancestors of parent = new csets
3555 # all ancestors of branch heads - all ancestors of parent = new csets
3551 new = [0] * len(repo)
3556 new = [0] * len(repo)
3552 cl = repo.changelog
3557 cl = repo.changelog
3553 for a in [cl.rev(n) for n in bheads]:
3558 for a in [cl.rev(n) for n in bheads]:
3554 new[a] = 1
3559 new[a] = 1
3555 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3560 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3556 new[a] = 1
3561 new[a] = 1
3557 for a in [p.rev() for p in parents]:
3562 for a in [p.rev() for p in parents]:
3558 if a >= 0:
3563 if a >= 0:
3559 new[a] = 0
3564 new[a] = 0
3560 for a in cl.ancestors(*[p.rev() for p in parents]):
3565 for a in cl.ancestors(*[p.rev() for p in parents]):
3561 new[a] = 0
3566 new[a] = 0
3562 new = sum(new)
3567 new = sum(new)
3563
3568
3564 if new == 0:
3569 if new == 0:
3565 ui.status(_('update: (current)\n'))
3570 ui.status(_('update: (current)\n'))
3566 elif pnode not in bheads:
3571 elif pnode not in bheads:
3567 ui.write(_('update: %d new changesets (update)\n') % new)
3572 ui.write(_('update: %d new changesets (update)\n') % new)
3568 else:
3573 else:
3569 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3574 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3570 (new, len(bheads)))
3575 (new, len(bheads)))
3571
3576
3572 if opts.get('remote'):
3577 if opts.get('remote'):
3573 t = []
3578 t = []
3574 source, branches = hg.parseurl(ui.expandpath('default'))
3579 source, branches = hg.parseurl(ui.expandpath('default'))
3575 other = hg.repository(hg.remoteui(repo, {}), source)
3580 other = hg.repository(hg.remoteui(repo, {}), source)
3576 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3581 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3577 ui.debug('comparing with %s\n' % url.hidepassword(source))
3582 ui.debug('comparing with %s\n' % url.hidepassword(source))
3578 repo.ui.pushbuffer()
3583 repo.ui.pushbuffer()
3579 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3584 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3580 repo.ui.popbuffer()
3585 repo.ui.popbuffer()
3581 if incoming:
3586 if incoming:
3582 t.append(_('1 or more incoming'))
3587 t.append(_('1 or more incoming'))
3583
3588
3584 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3589 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3585 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3590 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3586 other = hg.repository(hg.remoteui(repo, {}), dest)
3591 other = hg.repository(hg.remoteui(repo, {}), dest)
3587 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3592 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3588 repo.ui.pushbuffer()
3593 repo.ui.pushbuffer()
3589 o = discovery.findoutgoing(repo, other)
3594 o = discovery.findoutgoing(repo, other)
3590 repo.ui.popbuffer()
3595 repo.ui.popbuffer()
3591 o = repo.changelog.nodesbetween(o, None)[0]
3596 o = repo.changelog.nodesbetween(o, None)[0]
3592 if o:
3597 if o:
3593 t.append(_('%d outgoing') % len(o))
3598 t.append(_('%d outgoing') % len(o))
3594
3599
3595 if t:
3600 if t:
3596 ui.write(_('remote: %s\n') % (', '.join(t)))
3601 ui.write(_('remote: %s\n') % (', '.join(t)))
3597 else:
3602 else:
3598 ui.status(_('remote: (synced)\n'))
3603 ui.status(_('remote: (synced)\n'))
3599
3604
3600 def tag(ui, repo, name1, *names, **opts):
3605 def tag(ui, repo, name1, *names, **opts):
3601 """add one or more tags for the current or given revision
3606 """add one or more tags for the current or given revision
3602
3607
3603 Name a particular revision using <name>.
3608 Name a particular revision using <name>.
3604
3609
3605 Tags are used to name particular revisions of the repository and are
3610 Tags are used to name particular revisions of the repository and are
3606 very useful to compare different revisions, to go back to significant
3611 very useful to compare different revisions, to go back to significant
3607 earlier versions or to mark branch points as releases, etc.
3612 earlier versions or to mark branch points as releases, etc.
3608
3613
3609 If no revision is given, the parent of the working directory is
3614 If no revision is given, the parent of the working directory is
3610 used, or tip if no revision is checked out.
3615 used, or tip if no revision is checked out.
3611
3616
3612 To facilitate version control, distribution, and merging of tags,
3617 To facilitate version control, distribution, and merging of tags,
3613 they are stored as a file named ".hgtags" which is managed
3618 they are stored as a file named ".hgtags" which is managed
3614 similarly to other project files and can be hand-edited if
3619 similarly to other project files and can be hand-edited if
3615 necessary. The file '.hg/localtags' is used for local tags (not
3620 necessary. The file '.hg/localtags' is used for local tags (not
3616 shared among repositories).
3621 shared among repositories).
3617
3622
3618 See :hg:`help dates` for a list of formats valid for -d/--date.
3623 See :hg:`help dates` for a list of formats valid for -d/--date.
3619
3624
3620 Since tag names have priority over branch names during revision
3625 Since tag names have priority over branch names during revision
3621 lookup, using an existing branch name as a tag name is discouraged.
3626 lookup, using an existing branch name as a tag name is discouraged.
3622
3627
3623 Returns 0 on success.
3628 Returns 0 on success.
3624 """
3629 """
3625
3630
3626 rev_ = "."
3631 rev_ = "."
3627 names = [t.strip() for t in (name1,) + names]
3632 names = [t.strip() for t in (name1,) + names]
3628 if len(names) != len(set(names)):
3633 if len(names) != len(set(names)):
3629 raise util.Abort(_('tag names must be unique'))
3634 raise util.Abort(_('tag names must be unique'))
3630 for n in names:
3635 for n in names:
3631 if n in ['tip', '.', 'null']:
3636 if n in ['tip', '.', 'null']:
3632 raise util.Abort(_('the name \'%s\' is reserved') % n)
3637 raise util.Abort(_('the name \'%s\' is reserved') % n)
3633 if not n:
3638 if not n:
3634 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3639 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3635 if opts.get('rev') and opts.get('remove'):
3640 if opts.get('rev') and opts.get('remove'):
3636 raise util.Abort(_("--rev and --remove are incompatible"))
3641 raise util.Abort(_("--rev and --remove are incompatible"))
3637 if opts.get('rev'):
3642 if opts.get('rev'):
3638 rev_ = opts['rev']
3643 rev_ = opts['rev']
3639 message = opts.get('message')
3644 message = opts.get('message')
3640 if opts.get('remove'):
3645 if opts.get('remove'):
3641 expectedtype = opts.get('local') and 'local' or 'global'
3646 expectedtype = opts.get('local') and 'local' or 'global'
3642 for n in names:
3647 for n in names:
3643 if not repo.tagtype(n):
3648 if not repo.tagtype(n):
3644 raise util.Abort(_('tag \'%s\' does not exist') % n)
3649 raise util.Abort(_('tag \'%s\' does not exist') % n)
3645 if repo.tagtype(n) != expectedtype:
3650 if repo.tagtype(n) != expectedtype:
3646 if expectedtype == 'global':
3651 if expectedtype == 'global':
3647 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3652 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3648 else:
3653 else:
3649 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3654 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3650 rev_ = nullid
3655 rev_ = nullid
3651 if not message:
3656 if not message:
3652 # we don't translate commit messages
3657 # we don't translate commit messages
3653 message = 'Removed tag %s' % ', '.join(names)
3658 message = 'Removed tag %s' % ', '.join(names)
3654 elif not opts.get('force'):
3659 elif not opts.get('force'):
3655 for n in names:
3660 for n in names:
3656 if n in repo.tags():
3661 if n in repo.tags():
3657 raise util.Abort(_('tag \'%s\' already exists '
3662 raise util.Abort(_('tag \'%s\' already exists '
3658 '(use -f to force)') % n)
3663 '(use -f to force)') % n)
3659 if not rev_ and repo.dirstate.parents()[1] != nullid:
3664 if not rev_ and repo.dirstate.parents()[1] != nullid:
3660 raise util.Abort(_('uncommitted merge - please provide a '
3665 raise util.Abort(_('uncommitted merge - please provide a '
3661 'specific revision'))
3666 'specific revision'))
3662 r = repo[rev_].node()
3667 r = repo[rev_].node()
3663
3668
3664 if not message:
3669 if not message:
3665 # we don't translate commit messages
3670 # we don't translate commit messages
3666 message = ('Added tag %s for changeset %s' %
3671 message = ('Added tag %s for changeset %s' %
3667 (', '.join(names), short(r)))
3672 (', '.join(names), short(r)))
3668
3673
3669 date = opts.get('date')
3674 date = opts.get('date')
3670 if date:
3675 if date:
3671 date = util.parsedate(date)
3676 date = util.parsedate(date)
3672
3677
3673 if opts.get('edit'):
3678 if opts.get('edit'):
3674 message = ui.edit(message, ui.username())
3679 message = ui.edit(message, ui.username())
3675
3680
3676 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3677
3682
3678 def tags(ui, repo):
3683 def tags(ui, repo):
3679 """list repository tags
3684 """list repository tags
3680
3685
3681 This lists both regular and local tags. When the -v/--verbose
3686 This lists both regular and local tags. When the -v/--verbose
3682 switch is used, a third column "local" is printed for local tags.
3687 switch is used, a third column "local" is printed for local tags.
3683
3688
3684 Returns 0 on success.
3689 Returns 0 on success.
3685 """
3690 """
3686
3691
3687 hexfunc = ui.debugflag and hex or short
3692 hexfunc = ui.debugflag and hex or short
3688 tagtype = ""
3693 tagtype = ""
3689
3694
3690 for t, n in reversed(repo.tagslist()):
3695 for t, n in reversed(repo.tagslist()):
3691 if ui.quiet:
3696 if ui.quiet:
3692 ui.write("%s\n" % t)
3697 ui.write("%s\n" % t)
3693 continue
3698 continue
3694
3699
3695 try:
3700 try:
3696 hn = hexfunc(n)
3701 hn = hexfunc(n)
3697 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3702 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3698 except error.LookupError:
3703 except error.LookupError:
3699 r = " ?:%s" % hn
3704 r = " ?:%s" % hn
3700 else:
3705 else:
3701 spaces = " " * (30 - encoding.colwidth(t))
3706 spaces = " " * (30 - encoding.colwidth(t))
3702 if ui.verbose:
3707 if ui.verbose:
3703 if repo.tagtype(t) == 'local':
3708 if repo.tagtype(t) == 'local':
3704 tagtype = " local"
3709 tagtype = " local"
3705 else:
3710 else:
3706 tagtype = ""
3711 tagtype = ""
3707 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3712 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3708
3713
3709 def tip(ui, repo, **opts):
3714 def tip(ui, repo, **opts):
3710 """show the tip revision
3715 """show the tip revision
3711
3716
3712 The tip revision (usually just called the tip) is the changeset
3717 The tip revision (usually just called the tip) is the changeset
3713 most recently added to the repository (and therefore the most
3718 most recently added to the repository (and therefore the most
3714 recently changed head).
3719 recently changed head).
3715
3720
3716 If you have just made a commit, that commit will be the tip. If
3721 If you have just made a commit, that commit will be the tip. If
3717 you have just pulled changes from another repository, the tip of
3722 you have just pulled changes from another repository, the tip of
3718 that repository becomes the current tip. The "tip" tag is special
3723 that repository becomes the current tip. The "tip" tag is special
3719 and cannot be renamed or assigned to a different changeset.
3724 and cannot be renamed or assigned to a different changeset.
3720
3725
3721 Returns 0 on success.
3726 Returns 0 on success.
3722 """
3727 """
3723 displayer = cmdutil.show_changeset(ui, repo, opts)
3728 displayer = cmdutil.show_changeset(ui, repo, opts)
3724 displayer.show(repo[len(repo) - 1])
3729 displayer.show(repo[len(repo) - 1])
3725 displayer.close()
3730 displayer.close()
3726
3731
3727 def unbundle(ui, repo, fname1, *fnames, **opts):
3732 def unbundle(ui, repo, fname1, *fnames, **opts):
3728 """apply one or more changegroup files
3733 """apply one or more changegroup files
3729
3734
3730 Apply one or more compressed changegroup files generated by the
3735 Apply one or more compressed changegroup files generated by the
3731 bundle command.
3736 bundle command.
3732
3737
3733 Returns 0 on success, 1 if an update has unresolved files.
3738 Returns 0 on success, 1 if an update has unresolved files.
3734 """
3739 """
3735 fnames = (fname1,) + fnames
3740 fnames = (fname1,) + fnames
3736
3741
3737 lock = repo.lock()
3742 lock = repo.lock()
3738 try:
3743 try:
3739 for fname in fnames:
3744 for fname in fnames:
3740 f = url.open(ui, fname)
3745 f = url.open(ui, fname)
3741 gen = changegroup.readbundle(f, fname)
3746 gen = changegroup.readbundle(f, fname)
3742 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3747 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3743 lock=lock)
3748 lock=lock)
3744 finally:
3749 finally:
3745 lock.release()
3750 lock.release()
3746
3751
3747 return postincoming(ui, repo, modheads, opts.get('update'), None)
3752 return postincoming(ui, repo, modheads, opts.get('update'), None)
3748
3753
3749 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3754 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3750 """update working directory (or switch revisions)
3755 """update working directory (or switch revisions)
3751
3756
3752 Update the repository's working directory to the specified
3757 Update the repository's working directory to the specified
3753 changeset.
3758 changeset.
3754
3759
3755 If no changeset is specified, attempt to update to the tip of the
3760 If no changeset is specified, attempt to update to the tip of the
3756 current branch. If this changeset is a descendant of the working
3761 current branch. If this changeset is a descendant of the working
3757 directory's parent, update to it, otherwise abort.
3762 directory's parent, update to it, otherwise abort.
3758
3763
3759 The following rules apply when the working directory contains
3764 The following rules apply when the working directory contains
3760 uncommitted changes:
3765 uncommitted changes:
3761
3766
3762 1. If neither -c/--check nor -C/--clean is specified, and if
3767 1. If neither -c/--check nor -C/--clean is specified, and if
3763 the requested changeset is an ancestor or descendant of
3768 the requested changeset is an ancestor or descendant of
3764 the working directory's parent, the uncommitted changes
3769 the working directory's parent, the uncommitted changes
3765 are merged into the requested changeset and the merged
3770 are merged into the requested changeset and the merged
3766 result is left uncommitted. If the requested changeset is
3771 result is left uncommitted. If the requested changeset is
3767 not an ancestor or descendant (that is, it is on another
3772 not an ancestor or descendant (that is, it is on another
3768 branch), the update is aborted and the uncommitted changes
3773 branch), the update is aborted and the uncommitted changes
3769 are preserved.
3774 are preserved.
3770
3775
3771 2. With the -c/--check option, the update is aborted and the
3776 2. With the -c/--check option, the update is aborted and the
3772 uncommitted changes are preserved.
3777 uncommitted changes are preserved.
3773
3778
3774 3. With the -C/--clean option, uncommitted changes are discarded and
3779 3. With the -C/--clean option, uncommitted changes are discarded and
3775 the working directory is updated to the requested changeset.
3780 the working directory is updated to the requested changeset.
3776
3781
3777 Use null as the changeset to remove the working directory (like
3782 Use null as the changeset to remove the working directory (like
3778 :hg:`clone -U`).
3783 :hg:`clone -U`).
3779
3784
3780 If you want to update just one file to an older changeset, use :hg:`revert`.
3785 If you want to update just one file to an older changeset, use :hg:`revert`.
3781
3786
3782 See :hg:`help dates` for a list of formats valid for -d/--date.
3787 See :hg:`help dates` for a list of formats valid for -d/--date.
3783
3788
3784 Returns 0 on success, 1 if there are unresolved files.
3789 Returns 0 on success, 1 if there are unresolved files.
3785 """
3790 """
3786 if rev and node:
3791 if rev and node:
3787 raise util.Abort(_("please specify just one revision"))
3792 raise util.Abort(_("please specify just one revision"))
3788
3793
3789 if not rev:
3794 if not rev:
3790 rev = node
3795 rev = node
3791
3796
3792 if check and clean:
3797 if check and clean:
3793 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3798 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3794
3799
3795 if check:
3800 if check:
3796 # we could use dirty() but we can ignore merge and branch trivia
3801 # we could use dirty() but we can ignore merge and branch trivia
3797 c = repo[None]
3802 c = repo[None]
3798 if c.modified() or c.added() or c.removed():
3803 if c.modified() or c.added() or c.removed():
3799 raise util.Abort(_("uncommitted local changes"))
3804 raise util.Abort(_("uncommitted local changes"))
3800
3805
3801 if date:
3806 if date:
3802 if rev:
3807 if rev:
3803 raise util.Abort(_("you can't specify a revision and a date"))
3808 raise util.Abort(_("you can't specify a revision and a date"))
3804 rev = cmdutil.finddate(ui, repo, date)
3809 rev = cmdutil.finddate(ui, repo, date)
3805
3810
3806 if clean or check:
3811 if clean or check:
3807 return hg.clean(repo, rev)
3812 return hg.clean(repo, rev)
3808 else:
3813 else:
3809 return hg.update(repo, rev)
3814 return hg.update(repo, rev)
3810
3815
3811 def verify(ui, repo):
3816 def verify(ui, repo):
3812 """verify the integrity of the repository
3817 """verify the integrity of the repository
3813
3818
3814 Verify the integrity of the current repository.
3819 Verify the integrity of the current repository.
3815
3820
3816 This will perform an extensive check of the repository's
3821 This will perform an extensive check of the repository's
3817 integrity, validating the hashes and checksums of each entry in
3822 integrity, validating the hashes and checksums of each entry in
3818 the changelog, manifest, and tracked files, as well as the
3823 the changelog, manifest, and tracked files, as well as the
3819 integrity of their crosslinks and indices.
3824 integrity of their crosslinks and indices.
3820
3825
3821 Returns 0 on success, 1 if errors are encountered.
3826 Returns 0 on success, 1 if errors are encountered.
3822 """
3827 """
3823 return hg.verify(repo)
3828 return hg.verify(repo)
3824
3829
3825 def version_(ui):
3830 def version_(ui):
3826 """output version and copyright information"""
3831 """output version and copyright information"""
3827 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3832 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3828 % util.version())
3833 % util.version())
3829 ui.status(_(
3834 ui.status(_(
3830 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3835 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3831 "This is free software; see the source for copying conditions. "
3836 "This is free software; see the source for copying conditions. "
3832 "There is NO\nwarranty; "
3837 "There is NO\nwarranty; "
3833 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3838 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3834 ))
3839 ))
3835
3840
3836 # Command options and aliases are listed here, alphabetically
3841 # Command options and aliases are listed here, alphabetically
3837
3842
3838 globalopts = [
3843 globalopts = [
3839 ('R', 'repository', '',
3844 ('R', 'repository', '',
3840 _('repository root directory or name of overlay bundle file'),
3845 _('repository root directory or name of overlay bundle file'),
3841 _('REPO')),
3846 _('REPO')),
3842 ('', 'cwd', '',
3847 ('', 'cwd', '',
3843 _('change working directory'), _('DIR')),
3848 _('change working directory'), _('DIR')),
3844 ('y', 'noninteractive', None,
3849 ('y', 'noninteractive', None,
3845 _('do not prompt, assume \'yes\' for any required answers')),
3850 _('do not prompt, assume \'yes\' for any required answers')),
3846 ('q', 'quiet', None, _('suppress output')),
3851 ('q', 'quiet', None, _('suppress output')),
3847 ('v', 'verbose', None, _('enable additional output')),
3852 ('v', 'verbose', None, _('enable additional output')),
3848 ('', 'config', [],
3853 ('', 'config', [],
3849 _('set/override config option (use \'section.name=value\')'),
3854 _('set/override config option (use \'section.name=value\')'),
3850 _('CONFIG')),
3855 _('CONFIG')),
3851 ('', 'debug', None, _('enable debugging output')),
3856 ('', 'debug', None, _('enable debugging output')),
3852 ('', 'debugger', None, _('start debugger')),
3857 ('', 'debugger', None, _('start debugger')),
3853 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3858 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3854 _('ENCODE')),
3859 _('ENCODE')),
3855 ('', 'encodingmode', encoding.encodingmode,
3860 ('', 'encodingmode', encoding.encodingmode,
3856 _('set the charset encoding mode'), _('MODE')),
3861 _('set the charset encoding mode'), _('MODE')),
3857 ('', 'traceback', None, _('always print a traceback on exception')),
3862 ('', 'traceback', None, _('always print a traceback on exception')),
3858 ('', 'time', None, _('time how long the command takes')),
3863 ('', 'time', None, _('time how long the command takes')),
3859 ('', 'profile', None, _('print command execution profile')),
3864 ('', 'profile', None, _('print command execution profile')),
3860 ('', 'version', None, _('output version information and exit')),
3865 ('', 'version', None, _('output version information and exit')),
3861 ('h', 'help', None, _('display help and exit')),
3866 ('h', 'help', None, _('display help and exit')),
3862 ]
3867 ]
3863
3868
3864 dryrunopts = [('n', 'dry-run', None,
3869 dryrunopts = [('n', 'dry-run', None,
3865 _('do not perform actions, just print output'))]
3870 _('do not perform actions, just print output'))]
3866
3871
3867 remoteopts = [
3872 remoteopts = [
3868 ('e', 'ssh', '',
3873 ('e', 'ssh', '',
3869 _('specify ssh command to use'), _('CMD')),
3874 _('specify ssh command to use'), _('CMD')),
3870 ('', 'remotecmd', '',
3875 ('', 'remotecmd', '',
3871 _('specify hg command to run on the remote side'), _('CMD')),
3876 _('specify hg command to run on the remote side'), _('CMD')),
3872 ]
3877 ]
3873
3878
3874 walkopts = [
3879 walkopts = [
3875 ('I', 'include', [],
3880 ('I', 'include', [],
3876 _('include names matching the given patterns'), _('PATTERN')),
3881 _('include names matching the given patterns'), _('PATTERN')),
3877 ('X', 'exclude', [],
3882 ('X', 'exclude', [],
3878 _('exclude names matching the given patterns'), _('PATTERN')),
3883 _('exclude names matching the given patterns'), _('PATTERN')),
3879 ]
3884 ]
3880
3885
3881 commitopts = [
3886 commitopts = [
3882 ('m', 'message', '',
3887 ('m', 'message', '',
3883 _('use text as commit message'), _('TEXT')),
3888 _('use text as commit message'), _('TEXT')),
3884 ('l', 'logfile', '',
3889 ('l', 'logfile', '',
3885 _('read commit message from file'), _('FILE')),
3890 _('read commit message from file'), _('FILE')),
3886 ]
3891 ]
3887
3892
3888 commitopts2 = [
3893 commitopts2 = [
3889 ('d', 'date', '',
3894 ('d', 'date', '',
3890 _('record datecode as commit date'), _('DATE')),
3895 _('record datecode as commit date'), _('DATE')),
3891 ('u', 'user', '',
3896 ('u', 'user', '',
3892 _('record the specified user as committer'), _('USER')),
3897 _('record the specified user as committer'), _('USER')),
3893 ]
3898 ]
3894
3899
3895 templateopts = [
3900 templateopts = [
3896 ('', 'style', '',
3901 ('', 'style', '',
3897 _('display using template map file'), _('STYLE')),
3902 _('display using template map file'), _('STYLE')),
3898 ('', 'template', '',
3903 ('', 'template', '',
3899 _('display with template'), _('TEMPLATE')),
3904 _('display with template'), _('TEMPLATE')),
3900 ]
3905 ]
3901
3906
3902 logopts = [
3907 logopts = [
3903 ('p', 'patch', None, _('show patch')),
3908 ('p', 'patch', None, _('show patch')),
3904 ('g', 'git', None, _('use git extended diff format')),
3909 ('g', 'git', None, _('use git extended diff format')),
3905 ('l', 'limit', '',
3910 ('l', 'limit', '',
3906 _('limit number of changes displayed'), _('NUM')),
3911 _('limit number of changes displayed'), _('NUM')),
3907 ('M', 'no-merges', None, _('do not show merges')),
3912 ('M', 'no-merges', None, _('do not show merges')),
3908 ('', 'stat', None, _('output diffstat-style summary of changes')),
3913 ('', 'stat', None, _('output diffstat-style summary of changes')),
3909 ] + templateopts
3914 ] + templateopts
3910
3915
3911 diffopts = [
3916 diffopts = [
3912 ('a', 'text', None, _('treat all files as text')),
3917 ('a', 'text', None, _('treat all files as text')),
3913 ('g', 'git', None, _('use git extended diff format')),
3918 ('g', 'git', None, _('use git extended diff format')),
3914 ('', 'nodates', None, _('omit dates from diff headers'))
3919 ('', 'nodates', None, _('omit dates from diff headers'))
3915 ]
3920 ]
3916
3921
3917 diffopts2 = [
3922 diffopts2 = [
3918 ('p', 'show-function', None, _('show which function each change is in')),
3923 ('p', 'show-function', None, _('show which function each change is in')),
3919 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3924 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3920 ('w', 'ignore-all-space', None,
3925 ('w', 'ignore-all-space', None,
3921 _('ignore white space when comparing lines')),
3926 _('ignore white space when comparing lines')),
3922 ('b', 'ignore-space-change', None,
3927 ('b', 'ignore-space-change', None,
3923 _('ignore changes in the amount of white space')),
3928 _('ignore changes in the amount of white space')),
3924 ('B', 'ignore-blank-lines', None,
3929 ('B', 'ignore-blank-lines', None,
3925 _('ignore changes whose lines are all blank')),
3930 _('ignore changes whose lines are all blank')),
3926 ('U', 'unified', '',
3931 ('U', 'unified', '',
3927 _('number of lines of context to show'), _('NUM')),
3932 _('number of lines of context to show'), _('NUM')),
3928 ('', 'stat', None, _('output diffstat-style summary of changes')),
3933 ('', 'stat', None, _('output diffstat-style summary of changes')),
3929 ]
3934 ]
3930
3935
3931 similarityopts = [
3936 similarityopts = [
3932 ('s', 'similarity', '',
3937 ('s', 'similarity', '',
3933 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3938 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3934 ]
3939 ]
3935
3940
3936 subrepoopts = [
3941 subrepoopts = [
3937 ('S', 'subrepos', None,
3942 ('S', 'subrepos', None,
3938 _('recurse into subrepositories'))
3943 _('recurse into subrepositories'))
3939 ]
3944 ]
3940
3945
3941 table = {
3946 table = {
3942 "^add": (add, walkopts + subrepoopts + dryrunopts,
3947 "^add": (add, walkopts + subrepoopts + dryrunopts,
3943 _('[OPTION]... [FILE]...')),
3948 _('[OPTION]... [FILE]...')),
3944 "addremove":
3949 "addremove":
3945 (addremove, similarityopts + walkopts + dryrunopts,
3950 (addremove, similarityopts + walkopts + dryrunopts,
3946 _('[OPTION]... [FILE]...')),
3951 _('[OPTION]... [FILE]...')),
3947 "^annotate|blame":
3952 "^annotate|blame":
3948 (annotate,
3953 (annotate,
3949 [('r', 'rev', '',
3954 [('r', 'rev', '',
3950 _('annotate the specified revision'), _('REV')),
3955 _('annotate the specified revision'), _('REV')),
3951 ('', 'follow', None,
3956 ('', 'follow', None,
3952 _('follow copies/renames and list the filename (DEPRECATED)')),
3957 _('follow copies/renames and list the filename (DEPRECATED)')),
3953 ('', 'no-follow', None, _("don't follow copies and renames")),
3958 ('', 'no-follow', None, _("don't follow copies and renames")),
3954 ('a', 'text', None, _('treat all files as text')),
3959 ('a', 'text', None, _('treat all files as text')),
3955 ('u', 'user', None, _('list the author (long with -v)')),
3960 ('u', 'user', None, _('list the author (long with -v)')),
3956 ('f', 'file', None, _('list the filename')),
3961 ('f', 'file', None, _('list the filename')),
3957 ('d', 'date', None, _('list the date (short with -q)')),
3962 ('d', 'date', None, _('list the date (short with -q)')),
3958 ('n', 'number', None, _('list the revision number (default)')),
3963 ('n', 'number', None, _('list the revision number (default)')),
3959 ('c', 'changeset', None, _('list the changeset')),
3964 ('c', 'changeset', None, _('list the changeset')),
3960 ('l', 'line-number', None,
3965 ('l', 'line-number', None,
3961 _('show line number at the first appearance'))
3966 _('show line number at the first appearance'))
3962 ] + walkopts,
3967 ] + walkopts,
3963 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3968 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3964 "archive":
3969 "archive":
3965 (archive,
3970 (archive,
3966 [('', 'no-decode', None, _('do not pass files through decoders')),
3971 [('', 'no-decode', None, _('do not pass files through decoders')),
3967 ('p', 'prefix', '',
3972 ('p', 'prefix', '',
3968 _('directory prefix for files in archive'), _('PREFIX')),
3973 _('directory prefix for files in archive'), _('PREFIX')),
3969 ('r', 'rev', '',
3974 ('r', 'rev', '',
3970 _('revision to distribute'), _('REV')),
3975 _('revision to distribute'), _('REV')),
3971 ('t', 'type', '',
3976 ('t', 'type', '',
3972 _('type of distribution to create'), _('TYPE')),
3977 _('type of distribution to create'), _('TYPE')),
3973 ] + subrepoopts + walkopts,
3978 ] + subrepoopts + walkopts,
3974 _('[OPTION]... DEST')),
3979 _('[OPTION]... DEST')),
3975 "backout":
3980 "backout":
3976 (backout,
3981 (backout,
3977 [('', 'merge', None,
3982 [('', 'merge', None,
3978 _('merge with old dirstate parent after backout')),
3983 _('merge with old dirstate parent after backout')),
3979 ('', 'parent', '',
3984 ('', 'parent', '',
3980 _('parent to choose when backing out merge'), _('REV')),
3985 _('parent to choose when backing out merge'), _('REV')),
3981 ('r', 'rev', '',
3986 ('r', 'rev', '',
3982 _('revision to backout'), _('REV')),
3987 _('revision to backout'), _('REV')),
3983 ] + walkopts + commitopts + commitopts2,
3988 ] + walkopts + commitopts + commitopts2,
3984 _('[OPTION]... [-r] REV')),
3989 _('[OPTION]... [-r] REV')),
3985 "bisect":
3990 "bisect":
3986 (bisect,
3991 (bisect,
3987 [('r', 'reset', False, _('reset bisect state')),
3992 [('r', 'reset', False, _('reset bisect state')),
3988 ('g', 'good', False, _('mark changeset good')),
3993 ('g', 'good', False, _('mark changeset good')),
3989 ('b', 'bad', False, _('mark changeset bad')),
3994 ('b', 'bad', False, _('mark changeset bad')),
3990 ('s', 'skip', False, _('skip testing changeset')),
3995 ('s', 'skip', False, _('skip testing changeset')),
3991 ('c', 'command', '',
3996 ('c', 'command', '',
3992 _('use command to check changeset state'), _('CMD')),
3997 _('use command to check changeset state'), _('CMD')),
3993 ('U', 'noupdate', False, _('do not update to target'))],
3998 ('U', 'noupdate', False, _('do not update to target'))],
3994 _("[-gbsr] [-U] [-c CMD] [REV]")),
3999 _("[-gbsr] [-U] [-c CMD] [REV]")),
3995 "branch":
4000 "branch":
3996 (branch,
4001 (branch,
3997 [('f', 'force', None,
4002 [('f', 'force', None,
3998 _('set branch name even if it shadows an existing branch')),
4003 _('set branch name even if it shadows an existing branch')),
3999 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4004 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4000 _('[-fC] [NAME]')),
4005 _('[-fC] [NAME]')),
4001 "branches":
4006 "branches":
4002 (branches,
4007 (branches,
4003 [('a', 'active', False,
4008 [('a', 'active', False,
4004 _('show only branches that have unmerged heads')),
4009 _('show only branches that have unmerged heads')),
4005 ('c', 'closed', False,
4010 ('c', 'closed', False,
4006 _('show normal and closed branches'))],
4011 _('show normal and closed branches'))],
4007 _('[-ac]')),
4012 _('[-ac]')),
4008 "bundle":
4013 "bundle":
4009 (bundle,
4014 (bundle,
4010 [('f', 'force', None,
4015 [('f', 'force', None,
4011 _('run even when the destination is unrelated')),
4016 _('run even when the destination is unrelated')),
4012 ('r', 'rev', [],
4017 ('r', 'rev', [],
4013 _('a changeset intended to be added to the destination'),
4018 _('a changeset intended to be added to the destination'),
4014 _('REV')),
4019 _('REV')),
4015 ('b', 'branch', [],
4020 ('b', 'branch', [],
4016 _('a specific branch you would like to bundle'),
4021 _('a specific branch you would like to bundle'),
4017 _('BRANCH')),
4022 _('BRANCH')),
4018 ('', 'base', [],
4023 ('', 'base', [],
4019 _('a base changeset assumed to be available at the destination'),
4024 _('a base changeset assumed to be available at the destination'),
4020 _('REV')),
4025 _('REV')),
4021 ('a', 'all', None, _('bundle all changesets in the repository')),
4026 ('a', 'all', None, _('bundle all changesets in the repository')),
4022 ('t', 'type', 'bzip2',
4027 ('t', 'type', 'bzip2',
4023 _('bundle compression type to use'), _('TYPE')),
4028 _('bundle compression type to use'), _('TYPE')),
4024 ] + remoteopts,
4029 ] + remoteopts,
4025 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4030 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4026 "cat":
4031 "cat":
4027 (cat,
4032 (cat,
4028 [('o', 'output', '',
4033 [('o', 'output', '',
4029 _('print output to file with formatted name'), _('FORMAT')),
4034 _('print output to file with formatted name'), _('FORMAT')),
4030 ('r', 'rev', '',
4035 ('r', 'rev', '',
4031 _('print the given revision'), _('REV')),
4036 _('print the given revision'), _('REV')),
4032 ('', 'decode', None, _('apply any matching decode filter')),
4037 ('', 'decode', None, _('apply any matching decode filter')),
4033 ] + walkopts,
4038 ] + walkopts,
4034 _('[OPTION]... FILE...')),
4039 _('[OPTION]... FILE...')),
4035 "^clone":
4040 "^clone":
4036 (clone,
4041 (clone,
4037 [('U', 'noupdate', None,
4042 [('U', 'noupdate', None,
4038 _('the clone will include an empty working copy (only a repository)')),
4043 _('the clone will include an empty working copy (only a repository)')),
4039 ('u', 'updaterev', '',
4044 ('u', 'updaterev', '',
4040 _('revision, tag or branch to check out'), _('REV')),
4045 _('revision, tag or branch to check out'), _('REV')),
4041 ('r', 'rev', [],
4046 ('r', 'rev', [],
4042 _('include the specified changeset'), _('REV')),
4047 _('include the specified changeset'), _('REV')),
4043 ('b', 'branch', [],
4048 ('b', 'branch', [],
4044 _('clone only the specified branch'), _('BRANCH')),
4049 _('clone only the specified branch'), _('BRANCH')),
4045 ('', 'pull', None, _('use pull protocol to copy metadata')),
4050 ('', 'pull', None, _('use pull protocol to copy metadata')),
4046 ('', 'uncompressed', None,
4051 ('', 'uncompressed', None,
4047 _('use uncompressed transfer (fast over LAN)')),
4052 _('use uncompressed transfer (fast over LAN)')),
4048 ] + remoteopts,
4053 ] + remoteopts,
4049 _('[OPTION]... SOURCE [DEST]')),
4054 _('[OPTION]... SOURCE [DEST]')),
4050 "^commit|ci":
4055 "^commit|ci":
4051 (commit,
4056 (commit,
4052 [('A', 'addremove', None,
4057 [('A', 'addremove', None,
4053 _('mark new/missing files as added/removed before committing')),
4058 _('mark new/missing files as added/removed before committing')),
4054 ('', 'close-branch', None,
4059 ('', 'close-branch', None,
4055 _('mark a branch as closed, hiding it from the branch list')),
4060 _('mark a branch as closed, hiding it from the branch list')),
4056 ] + walkopts + commitopts + commitopts2,
4061 ] + walkopts + commitopts + commitopts2,
4057 _('[OPTION]... [FILE]...')),
4062 _('[OPTION]... [FILE]...')),
4058 "copy|cp":
4063 "copy|cp":
4059 (copy,
4064 (copy,
4060 [('A', 'after', None, _('record a copy that has already occurred')),
4065 [('A', 'after', None, _('record a copy that has already occurred')),
4061 ('f', 'force', None,
4066 ('f', 'force', None,
4062 _('forcibly copy over an existing managed file')),
4067 _('forcibly copy over an existing managed file')),
4063 ] + walkopts + dryrunopts,
4068 ] + walkopts + dryrunopts,
4064 _('[OPTION]... [SOURCE]... DEST')),
4069 _('[OPTION]... [SOURCE]... DEST')),
4065 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4070 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4066 "debugbuilddag":
4071 "debugbuilddag":
4067 (debugbuilddag,
4072 (debugbuilddag,
4068 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4073 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4069 ('a', 'appended-file', None, _('add single file all revs append to')),
4074 ('a', 'appended-file', None, _('add single file all revs append to')),
4070 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4075 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4071 ('n', 'new-file', None, _('add new file at each rev')),
4076 ('n', 'new-file', None, _('add new file at each rev')),
4072 ],
4077 ],
4073 _('[OPTION]... TEXT')),
4078 _('[OPTION]... TEXT')),
4074 "debugcheckstate": (debugcheckstate, [], ''),
4079 "debugcheckstate": (debugcheckstate, [], ''),
4075 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4080 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4076 "debugcomplete":
4081 "debugcomplete":
4077 (debugcomplete,
4082 (debugcomplete,
4078 [('o', 'options', None, _('show the command options'))],
4083 [('o', 'options', None, _('show the command options'))],
4079 _('[-o] CMD')),
4084 _('[-o] CMD')),
4080 "debugdag":
4085 "debugdag":
4081 (debugdag,
4086 (debugdag,
4082 [('t', 'tags', None, _('use tags as labels')),
4087 [('t', 'tags', None, _('use tags as labels')),
4083 ('b', 'branches', None, _('annotate with branch names')),
4088 ('b', 'branches', None, _('annotate with branch names')),
4084 ('', 'dots', None, _('use dots for runs')),
4089 ('', 'dots', None, _('use dots for runs')),
4085 ('s', 'spaces', None, _('separate elements by spaces')),
4090 ('s', 'spaces', None, _('separate elements by spaces')),
4086 ],
4091 ],
4087 _('[OPTION]... [FILE [REV]...]')),
4092 _('[OPTION]... [FILE [REV]...]')),
4088 "debugdate":
4093 "debugdate":
4089 (debugdate,
4094 (debugdate,
4090 [('e', 'extended', None, _('try extended date formats'))],
4095 [('e', 'extended', None, _('try extended date formats'))],
4091 _('[-e] DATE [RANGE]')),
4096 _('[-e] DATE [RANGE]')),
4092 "debugdata": (debugdata, [], _('FILE REV')),
4097 "debugdata": (debugdata, [], _('FILE REV')),
4093 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4098 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4094 "debugindex": (debugindex, [], _('FILE')),
4099 "debugindex": (debugindex, [], _('FILE')),
4095 "debugindexdot": (debugindexdot, [], _('FILE')),
4100 "debugindexdot": (debugindexdot, [], _('FILE')),
4096 "debuginstall": (debuginstall, [], ''),
4101 "debuginstall": (debuginstall, [], ''),
4097 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4102 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4098 "debugrebuildstate":
4103 "debugrebuildstate":
4099 (debugrebuildstate,
4104 (debugrebuildstate,
4100 [('r', 'rev', '',
4105 [('r', 'rev', '',
4101 _('revision to rebuild to'), _('REV'))],
4106 _('revision to rebuild to'), _('REV'))],
4102 _('[-r REV] [REV]')),
4107 _('[-r REV] [REV]')),
4103 "debugrename":
4108 "debugrename":
4104 (debugrename,
4109 (debugrename,
4105 [('r', 'rev', '',
4110 [('r', 'rev', '',
4106 _('revision to debug'), _('REV'))],
4111 _('revision to debug'), _('REV'))],
4107 _('[-r REV] FILE')),
4112 _('[-r REV] FILE')),
4108 "debugrevspec":
4113 "debugrevspec":
4109 (debugrevspec, [], ('REVSPEC')),
4114 (debugrevspec, [], ('REVSPEC')),
4110 "debugsetparents":
4115 "debugsetparents":
4111 (debugsetparents, [], _('REV1 [REV2]')),
4116 (debugsetparents, [], _('REV1 [REV2]')),
4112 "debugstate":
4117 "debugstate":
4113 (debugstate,
4118 (debugstate,
4114 [('', 'nodates', None, _('do not display the saved mtime'))],
4119 [('', 'nodates', None, _('do not display the saved mtime'))],
4115 _('[OPTION]...')),
4120 _('[OPTION]...')),
4116 "debugsub":
4121 "debugsub":
4117 (debugsub,
4122 (debugsub,
4118 [('r', 'rev', '',
4123 [('r', 'rev', '',
4119 _('revision to check'), _('REV'))],
4124 _('revision to check'), _('REV'))],
4120 _('[-r REV] [REV]')),
4125 _('[-r REV] [REV]')),
4121 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4126 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4122 "^diff":
4127 "^diff":
4123 (diff,
4128 (diff,
4124 [('r', 'rev', [],
4129 [('r', 'rev', [],
4125 _('revision'), _('REV')),
4130 _('revision'), _('REV')),
4126 ('c', 'change', '',
4131 ('c', 'change', '',
4127 _('change made by revision'), _('REV'))
4132 _('change made by revision'), _('REV'))
4128 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4133 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4129 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4134 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4130 "^export":
4135 "^export":
4131 (export,
4136 (export,
4132 [('o', 'output', '',
4137 [('o', 'output', '',
4133 _('print output to file with formatted name'), _('FORMAT')),
4138 _('print output to file with formatted name'), _('FORMAT')),
4134 ('', 'switch-parent', None, _('diff against the second parent')),
4139 ('', 'switch-parent', None, _('diff against the second parent')),
4135 ('r', 'rev', [],
4140 ('r', 'rev', [],
4136 _('revisions to export'), _('REV')),
4141 _('revisions to export'), _('REV')),
4137 ] + diffopts,
4142 ] + diffopts,
4138 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4143 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4139 "^forget":
4144 "^forget":
4140 (forget,
4145 (forget,
4141 [] + walkopts,
4146 [] + walkopts,
4142 _('[OPTION]... FILE...')),
4147 _('[OPTION]... FILE...')),
4143 "grep":
4148 "grep":
4144 (grep,
4149 (grep,
4145 [('0', 'print0', None, _('end fields with NUL')),
4150 [('0', 'print0', None, _('end fields with NUL')),
4146 ('', 'all', None, _('print all revisions that match')),
4151 ('', 'all', None, _('print all revisions that match')),
4147 ('f', 'follow', None,
4152 ('f', 'follow', None,
4148 _('follow changeset history,'
4153 _('follow changeset history,'
4149 ' or file history across copies and renames')),
4154 ' or file history across copies and renames')),
4150 ('i', 'ignore-case', None, _('ignore case when matching')),
4155 ('i', 'ignore-case', None, _('ignore case when matching')),
4151 ('l', 'files-with-matches', None,
4156 ('l', 'files-with-matches', None,
4152 _('print only filenames and revisions that match')),
4157 _('print only filenames and revisions that match')),
4153 ('n', 'line-number', None, _('print matching line numbers')),
4158 ('n', 'line-number', None, _('print matching line numbers')),
4154 ('r', 'rev', [],
4159 ('r', 'rev', [],
4155 _('only search files changed within revision range'), _('REV')),
4160 _('only search files changed within revision range'), _('REV')),
4156 ('u', 'user', None, _('list the author (long with -v)')),
4161 ('u', 'user', None, _('list the author (long with -v)')),
4157 ('d', 'date', None, _('list the date (short with -q)')),
4162 ('d', 'date', None, _('list the date (short with -q)')),
4158 ] + walkopts,
4163 ] + walkopts,
4159 _('[OPTION]... PATTERN [FILE]...')),
4164 _('[OPTION]... PATTERN [FILE]...')),
4160 "heads":
4165 "heads":
4161 (heads,
4166 (heads,
4162 [('r', 'rev', '',
4167 [('r', 'rev', '',
4163 _('show only heads which are descendants of REV'), _('REV')),
4168 _('show only heads which are descendants of REV'), _('REV')),
4164 ('t', 'topo', False, _('show topological heads only')),
4169 ('t', 'topo', False, _('show topological heads only')),
4165 ('a', 'active', False,
4170 ('a', 'active', False,
4166 _('show active branchheads only (DEPRECATED)')),
4171 _('show active branchheads only (DEPRECATED)')),
4167 ('c', 'closed', False,
4172 ('c', 'closed', False,
4168 _('show normal and closed branch heads')),
4173 _('show normal and closed branch heads')),
4169 ] + templateopts,
4174 ] + templateopts,
4170 _('[-ac] [-r REV] [REV]...')),
4175 _('[-ac] [-r REV] [REV]...')),
4171 "help": (help_, [], _('[TOPIC]')),
4176 "help": (help_, [], _('[TOPIC]')),
4172 "identify|id":
4177 "identify|id":
4173 (identify,
4178 (identify,
4174 [('r', 'rev', '',
4179 [('r', 'rev', '',
4175 _('identify the specified revision'), _('REV')),
4180 _('identify the specified revision'), _('REV')),
4176 ('n', 'num', None, _('show local revision number')),
4181 ('n', 'num', None, _('show local revision number')),
4177 ('i', 'id', None, _('show global revision id')),
4182 ('i', 'id', None, _('show global revision id')),
4178 ('b', 'branch', None, _('show branch')),
4183 ('b', 'branch', None, _('show branch')),
4179 ('t', 'tags', None, _('show tags'))],
4184 ('t', 'tags', None, _('show tags'))],
4180 _('[-nibt] [-r REV] [SOURCE]')),
4185 _('[-nibt] [-r REV] [SOURCE]')),
4181 "import|patch":
4186 "import|patch":
4182 (import_,
4187 (import_,
4183 [('p', 'strip', 1,
4188 [('p', 'strip', 1,
4184 _('directory strip option for patch. This has the same '
4189 _('directory strip option for patch. This has the same '
4185 'meaning as the corresponding patch option'),
4190 'meaning as the corresponding patch option'),
4186 _('NUM')),
4191 _('NUM')),
4187 ('b', 'base', '',
4192 ('b', 'base', '',
4188 _('base path'), _('PATH')),
4193 _('base path'), _('PATH')),
4189 ('f', 'force', None,
4194 ('f', 'force', None,
4190 _('skip check for outstanding uncommitted changes')),
4195 _('skip check for outstanding uncommitted changes')),
4191 ('', 'no-commit', None,
4196 ('', 'no-commit', None,
4192 _("don't commit, just update the working directory")),
4197 _("don't commit, just update the working directory")),
4193 ('', 'exact', None,
4198 ('', 'exact', None,
4194 _('apply patch to the nodes from which it was generated')),
4199 _('apply patch to the nodes from which it was generated')),
4195 ('', 'import-branch', None,
4200 ('', 'import-branch', None,
4196 _('use any branch information in patch (implied by --exact)'))] +
4201 _('use any branch information in patch (implied by --exact)'))] +
4197 commitopts + commitopts2 + similarityopts,
4202 commitopts + commitopts2 + similarityopts,
4198 _('[OPTION]... PATCH...')),
4203 _('[OPTION]... PATCH...')),
4199 "incoming|in":
4204 "incoming|in":
4200 (incoming,
4205 (incoming,
4201 [('f', 'force', None,
4206 [('f', 'force', None,
4202 _('run even if remote repository is unrelated')),
4207 _('run even if remote repository is unrelated')),
4203 ('n', 'newest-first', None, _('show newest record first')),
4208 ('n', 'newest-first', None, _('show newest record first')),
4204 ('', 'bundle', '',
4209 ('', 'bundle', '',
4205 _('file to store the bundles into'), _('FILE')),
4210 _('file to store the bundles into'), _('FILE')),
4206 ('r', 'rev', [],
4211 ('r', 'rev', [],
4207 _('a remote changeset intended to be added'), _('REV')),
4212 _('a remote changeset intended to be added'), _('REV')),
4208 ('b', 'branch', [],
4213 ('b', 'branch', [],
4209 _('a specific branch you would like to pull'), _('BRANCH')),
4214 _('a specific branch you would like to pull'), _('BRANCH')),
4210 ] + logopts + remoteopts + subrepoopts,
4215 ] + logopts + remoteopts + subrepoopts,
4211 _('[-p] [-n] [-M] [-f] [-r REV]...'
4216 _('[-p] [-n] [-M] [-f] [-r REV]...'
4212 ' [--bundle FILENAME] [SOURCE]')),
4217 ' [--bundle FILENAME] [SOURCE]')),
4213 "^init":
4218 "^init":
4214 (init,
4219 (init,
4215 remoteopts,
4220 remoteopts,
4216 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4221 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4217 "locate":
4222 "locate":
4218 (locate,
4223 (locate,
4219 [('r', 'rev', '',
4224 [('r', 'rev', '',
4220 _('search the repository as it is in REV'), _('REV')),
4225 _('search the repository as it is in REV'), _('REV')),
4221 ('0', 'print0', None,
4226 ('0', 'print0', None,
4222 _('end filenames with NUL, for use with xargs')),
4227 _('end filenames with NUL, for use with xargs')),
4223 ('f', 'fullpath', None,
4228 ('f', 'fullpath', None,
4224 _('print complete paths from the filesystem root')),
4229 _('print complete paths from the filesystem root')),
4225 ] + walkopts,
4230 ] + walkopts,
4226 _('[OPTION]... [PATTERN]...')),
4231 _('[OPTION]... [PATTERN]...')),
4227 "^log|history":
4232 "^log|history":
4228 (log,
4233 (log,
4229 [('f', 'follow', None,
4234 [('f', 'follow', None,
4230 _('follow changeset history,'
4235 _('follow changeset history,'
4231 ' or file history across copies and renames')),
4236 ' or file history across copies and renames')),
4232 ('', 'follow-first', None,
4237 ('', 'follow-first', None,
4233 _('only follow the first parent of merge changesets')),
4238 _('only follow the first parent of merge changesets')),
4234 ('d', 'date', '',
4239 ('d', 'date', '',
4235 _('show revisions matching date spec'), _('DATE')),
4240 _('show revisions matching date spec'), _('DATE')),
4236 ('C', 'copies', None, _('show copied files')),
4241 ('C', 'copies', None, _('show copied files')),
4237 ('k', 'keyword', [],
4242 ('k', 'keyword', [],
4238 _('do case-insensitive search for a given text'), _('TEXT')),
4243 _('do case-insensitive search for a given text'), _('TEXT')),
4239 ('r', 'rev', [],
4244 ('r', 'rev', [],
4240 _('show the specified revision or range'), _('REV')),
4245 _('show the specified revision or range'), _('REV')),
4241 ('', 'removed', None, _('include revisions where files were removed')),
4246 ('', 'removed', None, _('include revisions where files were removed')),
4242 ('m', 'only-merges', None, _('show only merges')),
4247 ('m', 'only-merges', None, _('show only merges')),
4243 ('u', 'user', [],
4248 ('u', 'user', [],
4244 _('revisions committed by user'), _('USER')),
4249 _('revisions committed by user'), _('USER')),
4245 ('', 'only-branch', [],
4250 ('', 'only-branch', [],
4246 _('show only changesets within the given named branch (DEPRECATED)'),
4251 _('show only changesets within the given named branch (DEPRECATED)'),
4247 _('BRANCH')),
4252 _('BRANCH')),
4248 ('b', 'branch', [],
4253 ('b', 'branch', [],
4249 _('show changesets within the given named branch'), _('BRANCH')),
4254 _('show changesets within the given named branch'), _('BRANCH')),
4250 ('P', 'prune', [],
4255 ('P', 'prune', [],
4251 _('do not display revision or any of its ancestors'), _('REV')),
4256 _('do not display revision or any of its ancestors'), _('REV')),
4252 ] + logopts + walkopts,
4257 ] + logopts + walkopts,
4253 _('[OPTION]... [FILE]')),
4258 _('[OPTION]... [FILE]')),
4254 "manifest":
4259 "manifest":
4255 (manifest,
4260 (manifest,
4256 [('r', 'rev', '',
4261 [('r', 'rev', '',
4257 _('revision to display'), _('REV'))],
4262 _('revision to display'), _('REV'))],
4258 _('[-r REV]')),
4263 _('[-r REV]')),
4259 "^merge":
4264 "^merge":
4260 (merge,
4265 (merge,
4261 [('f', 'force', None, _('force a merge with outstanding changes')),
4266 [('f', 'force', None, _('force a merge with outstanding changes')),
4262 ('r', 'rev', '',
4267 ('r', 'rev', '',
4263 _('revision to merge'), _('REV')),
4268 _('revision to merge'), _('REV')),
4264 ('P', 'preview', None,
4269 ('P', 'preview', None,
4265 _('review revisions to merge (no merge is performed)'))],
4270 _('review revisions to merge (no merge is performed)'))],
4266 _('[-P] [-f] [[-r] REV]')),
4271 _('[-P] [-f] [[-r] REV]')),
4267 "outgoing|out":
4272 "outgoing|out":
4268 (outgoing,
4273 (outgoing,
4269 [('f', 'force', None,
4274 [('f', 'force', None,
4270 _('run even when the destination is unrelated')),
4275 _('run even when the destination is unrelated')),
4271 ('r', 'rev', [],
4276 ('r', 'rev', [],
4272 _('a changeset intended to be included in the destination'),
4277 _('a changeset intended to be included in the destination'),
4273 _('REV')),
4278 _('REV')),
4274 ('n', 'newest-first', None, _('show newest record first')),
4279 ('n', 'newest-first', None, _('show newest record first')),
4275 ('b', 'branch', [],
4280 ('b', 'branch', [],
4276 _('a specific branch you would like to push'), _('BRANCH')),
4281 _('a specific branch you would like to push'), _('BRANCH')),
4277 ] + logopts + remoteopts + subrepoopts,
4282 ] + logopts + remoteopts + subrepoopts,
4278 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4283 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4279 "parents":
4284 "parents":
4280 (parents,
4285 (parents,
4281 [('r', 'rev', '',
4286 [('r', 'rev', '',
4282 _('show parents of the specified revision'), _('REV')),
4287 _('show parents of the specified revision'), _('REV')),
4283 ] + templateopts,
4288 ] + templateopts,
4284 _('[-r REV] [FILE]')),
4289 _('[-r REV] [FILE]')),
4285 "paths": (paths, [], _('[NAME]')),
4290 "paths": (paths, [], _('[NAME]')),
4286 "^pull":
4291 "^pull":
4287 (pull,
4292 (pull,
4288 [('u', 'update', None,
4293 [('u', 'update', None,
4289 _('update to new branch head if changesets were pulled')),
4294 _('update to new branch head if changesets were pulled')),
4290 ('f', 'force', None,
4295 ('f', 'force', None,
4291 _('run even when remote repository is unrelated')),
4296 _('run even when remote repository is unrelated')),
4292 ('r', 'rev', [],
4297 ('r', 'rev', [],
4293 _('a remote changeset intended to be added'), _('REV')),
4298 _('a remote changeset intended to be added'), _('REV')),
4294 ('b', 'branch', [],
4299 ('b', 'branch', [],
4295 _('a specific branch you would like to pull'), _('BRANCH')),
4300 _('a specific branch you would like to pull'), _('BRANCH')),
4296 ] + remoteopts,
4301 ] + remoteopts,
4297 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4302 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4298 "^push":
4303 "^push":
4299 (push,
4304 (push,
4300 [('f', 'force', None, _('force push')),
4305 [('f', 'force', None, _('force push')),
4301 ('r', 'rev', [],
4306 ('r', 'rev', [],
4302 _('a changeset intended to be included in the destination'),
4307 _('a changeset intended to be included in the destination'),
4303 _('REV')),
4308 _('REV')),
4304 ('b', 'branch', [],
4309 ('b', 'branch', [],
4305 _('a specific branch you would like to push'), _('BRANCH')),
4310 _('a specific branch you would like to push'), _('BRANCH')),
4306 ('', 'new-branch', False, _('allow pushing a new branch')),
4311 ('', 'new-branch', False, _('allow pushing a new branch')),
4307 ] + remoteopts,
4312 ] + remoteopts,
4308 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4313 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4309 "recover": (recover, []),
4314 "recover": (recover, []),
4310 "^remove|rm":
4315 "^remove|rm":
4311 (remove,
4316 (remove,
4312 [('A', 'after', None, _('record delete for missing files')),
4317 [('A', 'after', None, _('record delete for missing files')),
4313 ('f', 'force', None,
4318 ('f', 'force', None,
4314 _('remove (and delete) file even if added or modified')),
4319 _('remove (and delete) file even if added or modified')),
4315 ] + walkopts,
4320 ] + walkopts,
4316 _('[OPTION]... FILE...')),
4321 _('[OPTION]... FILE...')),
4317 "rename|mv":
4322 "rename|mv":
4318 (rename,
4323 (rename,
4319 [('A', 'after', None, _('record a rename that has already occurred')),
4324 [('A', 'after', None, _('record a rename that has already occurred')),
4320 ('f', 'force', None,
4325 ('f', 'force', None,
4321 _('forcibly copy over an existing managed file')),
4326 _('forcibly copy over an existing managed file')),
4322 ] + walkopts + dryrunopts,
4327 ] + walkopts + dryrunopts,
4323 _('[OPTION]... SOURCE... DEST')),
4328 _('[OPTION]... SOURCE... DEST')),
4324 "resolve":
4329 "resolve":
4325 (resolve,
4330 (resolve,
4326 [('a', 'all', None, _('select all unresolved files')),
4331 [('a', 'all', None, _('select all unresolved files')),
4327 ('l', 'list', None, _('list state of files needing merge')),
4332 ('l', 'list', None, _('list state of files needing merge')),
4328 ('m', 'mark', None, _('mark files as resolved')),
4333 ('m', 'mark', None, _('mark files as resolved')),
4329 ('u', 'unmark', None, _('mark files as unresolved')),
4334 ('u', 'unmark', None, _('mark files as unresolved')),
4330 ('n', 'no-status', None, _('hide status prefix'))]
4335 ('n', 'no-status', None, _('hide status prefix'))]
4331 + walkopts,
4336 + walkopts,
4332 _('[OPTION]... [FILE]...')),
4337 _('[OPTION]... [FILE]...')),
4333 "revert":
4338 "revert":
4334 (revert,
4339 (revert,
4335 [('a', 'all', None, _('revert all changes when no arguments given')),
4340 [('a', 'all', None, _('revert all changes when no arguments given')),
4336 ('d', 'date', '',
4341 ('d', 'date', '',
4337 _('tipmost revision matching date'), _('DATE')),
4342 _('tipmost revision matching date'), _('DATE')),
4338 ('r', 'rev', '',
4343 ('r', 'rev', '',
4339 _('revert to the specified revision'), _('REV')),
4344 _('revert to the specified revision'), _('REV')),
4340 ('', 'no-backup', None, _('do not save backup copies of files')),
4345 ('', 'no-backup', None, _('do not save backup copies of files')),
4341 ] + walkopts + dryrunopts,
4346 ] + walkopts + dryrunopts,
4342 _('[OPTION]... [-r REV] [NAME]...')),
4347 _('[OPTION]... [-r REV] [NAME]...')),
4343 "rollback": (rollback, dryrunopts),
4348 "rollback": (rollback, dryrunopts),
4344 "root": (root, []),
4349 "root": (root, []),
4345 "^serve":
4350 "^serve":
4346 (serve,
4351 (serve,
4347 [('A', 'accesslog', '',
4352 [('A', 'accesslog', '',
4348 _('name of access log file to write to'), _('FILE')),
4353 _('name of access log file to write to'), _('FILE')),
4349 ('d', 'daemon', None, _('run server in background')),
4354 ('d', 'daemon', None, _('run server in background')),
4350 ('', 'daemon-pipefds', '',
4355 ('', 'daemon-pipefds', '',
4351 _('used internally by daemon mode'), _('NUM')),
4356 _('used internally by daemon mode'), _('NUM')),
4352 ('E', 'errorlog', '',
4357 ('E', 'errorlog', '',
4353 _('name of error log file to write to'), _('FILE')),
4358 _('name of error log file to write to'), _('FILE')),
4354 # use string type, then we can check if something was passed
4359 # use string type, then we can check if something was passed
4355 ('p', 'port', '',
4360 ('p', 'port', '',
4356 _('port to listen on (default: 8000)'), _('PORT')),
4361 _('port to listen on (default: 8000)'), _('PORT')),
4357 ('a', 'address', '',
4362 ('a', 'address', '',
4358 _('address to listen on (default: all interfaces)'), _('ADDR')),
4363 _('address to listen on (default: all interfaces)'), _('ADDR')),
4359 ('', 'prefix', '',
4364 ('', 'prefix', '',
4360 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4365 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4361 ('n', 'name', '',
4366 ('n', 'name', '',
4362 _('name to show in web pages (default: working directory)'),
4367 _('name to show in web pages (default: working directory)'),
4363 _('NAME')),
4368 _('NAME')),
4364 ('', 'web-conf', '',
4369 ('', 'web-conf', '',
4365 _('name of the hgweb config file (serve more than one repository)'),
4370 _('name of the hgweb config file (serve more than one repository)'),
4366 _('FILE')),
4371 _('FILE')),
4367 ('', 'webdir-conf', '',
4372 ('', 'webdir-conf', '',
4368 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4373 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4369 ('', 'pid-file', '',
4374 ('', 'pid-file', '',
4370 _('name of file to write process ID to'), _('FILE')),
4375 _('name of file to write process ID to'), _('FILE')),
4371 ('', 'stdio', None, _('for remote clients')),
4376 ('', 'stdio', None, _('for remote clients')),
4372 ('t', 'templates', '',
4377 ('t', 'templates', '',
4373 _('web templates to use'), _('TEMPLATE')),
4378 _('web templates to use'), _('TEMPLATE')),
4374 ('', 'style', '',
4379 ('', 'style', '',
4375 _('template style to use'), _('STYLE')),
4380 _('template style to use'), _('STYLE')),
4376 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4381 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4377 ('', 'certificate', '',
4382 ('', 'certificate', '',
4378 _('SSL certificate file'), _('FILE'))],
4383 _('SSL certificate file'), _('FILE'))],
4379 _('[OPTION]...')),
4384 _('[OPTION]...')),
4380 "showconfig|debugconfig":
4385 "showconfig|debugconfig":
4381 (showconfig,
4386 (showconfig,
4382 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4387 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4383 _('[-u] [NAME]...')),
4388 _('[-u] [NAME]...')),
4384 "^summary|sum":
4389 "^summary|sum":
4385 (summary,
4390 (summary,
4386 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4391 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4387 "^status|st":
4392 "^status|st":
4388 (status,
4393 (status,
4389 [('A', 'all', None, _('show status of all files')),
4394 [('A', 'all', None, _('show status of all files')),
4390 ('m', 'modified', None, _('show only modified files')),
4395 ('m', 'modified', None, _('show only modified files')),
4391 ('a', 'added', None, _('show only added files')),
4396 ('a', 'added', None, _('show only added files')),
4392 ('r', 'removed', None, _('show only removed files')),
4397 ('r', 'removed', None, _('show only removed files')),
4393 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4398 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4394 ('c', 'clean', None, _('show only files without changes')),
4399 ('c', 'clean', None, _('show only files without changes')),
4395 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4400 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4396 ('i', 'ignored', None, _('show only ignored files')),
4401 ('i', 'ignored', None, _('show only ignored files')),
4397 ('n', 'no-status', None, _('hide status prefix')),
4402 ('n', 'no-status', None, _('hide status prefix')),
4398 ('C', 'copies', None, _('show source of copied files')),
4403 ('C', 'copies', None, _('show source of copied files')),
4399 ('0', 'print0', None,
4404 ('0', 'print0', None,
4400 _('end filenames with NUL, for use with xargs')),
4405 _('end filenames with NUL, for use with xargs')),
4401 ('', 'rev', [],
4406 ('', 'rev', [],
4402 _('show difference from revision'), _('REV')),
4407 _('show difference from revision'), _('REV')),
4403 ('', 'change', '',
4408 ('', 'change', '',
4404 _('list the changed files of a revision'), _('REV')),
4409 _('list the changed files of a revision'), _('REV')),
4405 ] + walkopts + subrepoopts,
4410 ] + walkopts + subrepoopts,
4406 _('[OPTION]... [FILE]...')),
4411 _('[OPTION]... [FILE]...')),
4407 "tag":
4412 "tag":
4408 (tag,
4413 (tag,
4409 [('f', 'force', None, _('replace existing tag')),
4414 [('f', 'force', None, _('replace existing tag')),
4410 ('l', 'local', None, _('make the tag local')),
4415 ('l', 'local', None, _('make the tag local')),
4411 ('r', 'rev', '',
4416 ('r', 'rev', '',
4412 _('revision to tag'), _('REV')),
4417 _('revision to tag'), _('REV')),
4413 ('', 'remove', None, _('remove a tag')),
4418 ('', 'remove', None, _('remove a tag')),
4414 # -l/--local is already there, commitopts cannot be used
4419 # -l/--local is already there, commitopts cannot be used
4415 ('e', 'edit', None, _('edit commit message')),
4420 ('e', 'edit', None, _('edit commit message')),
4416 ('m', 'message', '',
4421 ('m', 'message', '',
4417 _('use <text> as commit message'), _('TEXT')),
4422 _('use <text> as commit message'), _('TEXT')),
4418 ] + commitopts2,
4423 ] + commitopts2,
4419 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4424 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4420 "tags": (tags, [], ''),
4425 "tags": (tags, [], ''),
4421 "tip":
4426 "tip":
4422 (tip,
4427 (tip,
4423 [('p', 'patch', None, _('show patch')),
4428 [('p', 'patch', None, _('show patch')),
4424 ('g', 'git', None, _('use git extended diff format')),
4429 ('g', 'git', None, _('use git extended diff format')),
4425 ] + templateopts,
4430 ] + templateopts,
4426 _('[-p] [-g]')),
4431 _('[-p] [-g]')),
4427 "unbundle":
4432 "unbundle":
4428 (unbundle,
4433 (unbundle,
4429 [('u', 'update', None,
4434 [('u', 'update', None,
4430 _('update to new branch head if changesets were unbundled'))],
4435 _('update to new branch head if changesets were unbundled'))],
4431 _('[-u] FILE...')),
4436 _('[-u] FILE...')),
4432 "^update|up|checkout|co":
4437 "^update|up|checkout|co":
4433 (update,
4438 (update,
4434 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4439 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4435 ('c', 'check', None, _('check for uncommitted changes')),
4440 ('c', 'check', None, _('check for uncommitted changes')),
4436 ('d', 'date', '',
4441 ('d', 'date', '',
4437 _('tipmost revision matching date'), _('DATE')),
4442 _('tipmost revision matching date'), _('DATE')),
4438 ('r', 'rev', '',
4443 ('r', 'rev', '',
4439 _('revision'), _('REV'))],
4444 _('revision'), _('REV'))],
4440 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4445 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4441 "verify": (verify, []),
4446 "verify": (verify, []),
4442 "version": (version_, []),
4447 "version": (version_, []),
4443 }
4448 }
4444
4449
4445 norepo = ("clone init version help debugcommands debugcomplete"
4450 norepo = ("clone init version help debugcommands debugcomplete"
4446 " debugdate debuginstall debugfsinfo debugpushkey")
4451 " debugdate debuginstall debugfsinfo debugpushkey")
4447 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4452 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4448 " debugdata debugindex debugindexdot")
4453 " debugdata debugindex debugindexdot")
@@ -1,754 +1,755 b''
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge working directory with another revision
17 merge merge working directory with another revision
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 use "hg help" for the full list of commands or "hg -v" for details
26 use "hg help" for the full list of commands or "hg -v" for details
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge working directory with another revision
38 merge merge working directory with another revision
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 $ hg help
47 $ hg help
48 Mercurial Distributed SCM
48 Mercurial Distributed SCM
49
49
50 list of commands:
50 list of commands:
51
51
52 add add the specified files on the next commit
52 add add the specified files on the next commit
53 addremove add all new files, delete all missing files
53 addremove add all new files, delete all missing files
54 annotate show changeset information by line for each file
54 annotate show changeset information by line for each file
55 archive create an unversioned archive of a repository revision
55 archive create an unversioned archive of a repository revision
56 backout reverse effect of earlier changeset
56 backout reverse effect of earlier changeset
57 bisect subdivision search of changesets
57 bisect subdivision search of changesets
58 branch set or show the current branch name
58 branch set or show the current branch name
59 branches list repository named branches
59 branches list repository named branches
60 bundle create a changegroup file
60 bundle create a changegroup file
61 cat output the current or given revision of files
61 cat output the current or given revision of files
62 clone make a copy of an existing repository
62 clone make a copy of an existing repository
63 commit commit the specified files or all outstanding changes
63 commit commit the specified files or all outstanding changes
64 copy mark files as copied for the next commit
64 copy mark files as copied for the next commit
65 diff diff repository (or selected files)
65 diff diff repository (or selected files)
66 export dump the header and diffs for one or more changesets
66 export dump the header and diffs for one or more changesets
67 forget forget the specified files on the next commit
67 forget forget the specified files on the next commit
68 grep search for a pattern in specified files and revisions
68 grep search for a pattern in specified files and revisions
69 heads show current repository heads or show branch heads
69 heads show current repository heads or show branch heads
70 help show help for a given topic or a help overview
70 help show help for a given topic or a help overview
71 identify identify the working copy or specified revision
71 identify identify the working copy or specified revision
72 import import an ordered set of patches
72 import import an ordered set of patches
73 incoming show new changesets found in source
73 incoming show new changesets found in source
74 init create a new repository in the given directory
74 init create a new repository in the given directory
75 locate locate files matching specific patterns
75 locate locate files matching specific patterns
76 log show revision history of entire repository or files
76 log show revision history of entire repository or files
77 manifest output the current or given revision of the project manifest
77 manifest output the current or given revision of the project manifest
78 merge merge working directory with another revision
78 merge merge working directory with another revision
79 outgoing show changesets not found in the destination
79 outgoing show changesets not found in the destination
80 parents show the parents of the working directory or revision
80 parents show the parents of the working directory or revision
81 paths show aliases for remote repositories
81 paths show aliases for remote repositories
82 pull pull changes from the specified source
82 pull pull changes from the specified source
83 push push changes to the specified destination
83 push push changes to the specified destination
84 recover roll back an interrupted transaction
84 recover roll back an interrupted transaction
85 remove remove the specified files on the next commit
85 remove remove the specified files on the next commit
86 rename rename files; equivalent of copy + remove
86 rename rename files; equivalent of copy + remove
87 resolve redo merges or set/view the merge status of files
87 resolve redo merges or set/view the merge status of files
88 revert restore individual files or directories to an earlier state
88 revert restore individual files or directories to an earlier state
89 rollback roll back the last transaction (dangerous)
89 rollback roll back the last transaction (dangerous)
90 root print the root (top) of the current working directory
90 root print the root (top) of the current working directory
91 serve start stand-alone webserver
91 serve start stand-alone webserver
92 showconfig show combined config settings from all hgrc files
92 showconfig show combined config settings from all hgrc files
93 status show changed files in the working directory
93 status show changed files in the working directory
94 summary summarize working directory state
94 summary summarize working directory state
95 tag add one or more tags for the current or given revision
95 tag add one or more tags for the current or given revision
96 tags list repository tags
96 tags list repository tags
97 tip show the tip revision
97 tip show the tip revision
98 unbundle apply one or more changegroup files
98 unbundle apply one or more changegroup files
99 update update working directory (or switch revisions)
99 update update working directory (or switch revisions)
100 verify verify the integrity of the repository
100 verify verify the integrity of the repository
101 version output version and copyright information
101 version output version and copyright information
102
102
103 additional help topics:
103 additional help topics:
104
104
105 config Configuration Files
105 config Configuration Files
106 dates Date Formats
106 dates Date Formats
107 patterns File Name Patterns
107 patterns File Name Patterns
108 environment Environment Variables
108 environment Environment Variables
109 revisions Specifying Single Revisions
109 revisions Specifying Single Revisions
110 multirevs Specifying Multiple Revisions
110 multirevs Specifying Multiple Revisions
111 revsets Specifying Revision Sets
111 revsets Specifying Revision Sets
112 diffs Diff Formats
112 diffs Diff Formats
113 templating Template Usage
113 templating Template Usage
114 urls URL Paths
114 urls URL Paths
115 extensions Using additional features
115 extensions Using additional features
116 hgweb Configuring hgweb
116 hgweb Configuring hgweb
117 glossary Glossary
117 glossary Glossary
118
118
119 use "hg -v help" to show aliases and global options
119 use "hg -v help" to show aliases and global options
120
120
121 $ hg -q help
121 $ hg -q help
122 add add the specified files on the next commit
122 add add the specified files on the next commit
123 addremove add all new files, delete all missing files
123 addremove add all new files, delete all missing files
124 annotate show changeset information by line for each file
124 annotate show changeset information by line for each file
125 archive create an unversioned archive of a repository revision
125 archive create an unversioned archive of a repository revision
126 backout reverse effect of earlier changeset
126 backout reverse effect of earlier changeset
127 bisect subdivision search of changesets
127 bisect subdivision search of changesets
128 branch set or show the current branch name
128 branch set or show the current branch name
129 branches list repository named branches
129 branches list repository named branches
130 bundle create a changegroup file
130 bundle create a changegroup file
131 cat output the current or given revision of files
131 cat output the current or given revision of files
132 clone make a copy of an existing repository
132 clone make a copy of an existing repository
133 commit commit the specified files or all outstanding changes
133 commit commit the specified files or all outstanding changes
134 copy mark files as copied for the next commit
134 copy mark files as copied for the next commit
135 diff diff repository (or selected files)
135 diff diff repository (or selected files)
136 export dump the header and diffs for one or more changesets
136 export dump the header and diffs for one or more changesets
137 forget forget the specified files on the next commit
137 forget forget the specified files on the next commit
138 grep search for a pattern in specified files and revisions
138 grep search for a pattern in specified files and revisions
139 heads show current repository heads or show branch heads
139 heads show current repository heads or show branch heads
140 help show help for a given topic or a help overview
140 help show help for a given topic or a help overview
141 identify identify the working copy or specified revision
141 identify identify the working copy or specified revision
142 import import an ordered set of patches
142 import import an ordered set of patches
143 incoming show new changesets found in source
143 incoming show new changesets found in source
144 init create a new repository in the given directory
144 init create a new repository in the given directory
145 locate locate files matching specific patterns
145 locate locate files matching specific patterns
146 log show revision history of entire repository or files
146 log show revision history of entire repository or files
147 manifest output the current or given revision of the project manifest
147 manifest output the current or given revision of the project manifest
148 merge merge working directory with another revision
148 merge merge working directory with another revision
149 outgoing show changesets not found in the destination
149 outgoing show changesets not found in the destination
150 parents show the parents of the working directory or revision
150 parents show the parents of the working directory or revision
151 paths show aliases for remote repositories
151 paths show aliases for remote repositories
152 pull pull changes from the specified source
152 pull pull changes from the specified source
153 push push changes to the specified destination
153 push push changes to the specified destination
154 recover roll back an interrupted transaction
154 recover roll back an interrupted transaction
155 remove remove the specified files on the next commit
155 remove remove the specified files on the next commit
156 rename rename files; equivalent of copy + remove
156 rename rename files; equivalent of copy + remove
157 resolve redo merges or set/view the merge status of files
157 resolve redo merges or set/view the merge status of files
158 revert restore individual files or directories to an earlier state
158 revert restore individual files or directories to an earlier state
159 rollback roll back the last transaction (dangerous)
159 rollback roll back the last transaction (dangerous)
160 root print the root (top) of the current working directory
160 root print the root (top) of the current working directory
161 serve start stand-alone webserver
161 serve start stand-alone webserver
162 showconfig show combined config settings from all hgrc files
162 showconfig show combined config settings from all hgrc files
163 status show changed files in the working directory
163 status show changed files in the working directory
164 summary summarize working directory state
164 summary summarize working directory state
165 tag add one or more tags for the current or given revision
165 tag add one or more tags for the current or given revision
166 tags list repository tags
166 tags list repository tags
167 tip show the tip revision
167 tip show the tip revision
168 unbundle apply one or more changegroup files
168 unbundle apply one or more changegroup files
169 update update working directory (or switch revisions)
169 update update working directory (or switch revisions)
170 verify verify the integrity of the repository
170 verify verify the integrity of the repository
171 version output version and copyright information
171 version output version and copyright information
172
172
173 additional help topics:
173 additional help topics:
174
174
175 config Configuration Files
175 config Configuration Files
176 dates Date Formats
176 dates Date Formats
177 patterns File Name Patterns
177 patterns File Name Patterns
178 environment Environment Variables
178 environment Environment Variables
179 revisions Specifying Single Revisions
179 revisions Specifying Single Revisions
180 multirevs Specifying Multiple Revisions
180 multirevs Specifying Multiple Revisions
181 revsets Specifying Revision Sets
181 revsets Specifying Revision Sets
182 diffs Diff Formats
182 diffs Diff Formats
183 templating Template Usage
183 templating Template Usage
184 urls URL Paths
184 urls URL Paths
185 extensions Using additional features
185 extensions Using additional features
186 hgweb Configuring hgweb
186 hgweb Configuring hgweb
187 glossary Glossary
187 glossary Glossary
188
188
189 Test short command list with verbose option
189 Test short command list with verbose option
190
190
191 $ hg -v help shortlist
191 $ hg -v help shortlist
192 Mercurial Distributed SCM (version *) (glob)
192 Mercurial Distributed SCM (version *) (glob)
193
193
194 Copyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others
194 Copyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others
195 This is free software; see the source for copying conditions. There is NO
195 This is free software; see the source for copying conditions. There is NO
196 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
196 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
197
197
198 basic commands:
198 basic commands:
199
199
200 add:
200 add:
201 add the specified files on the next commit
201 add the specified files on the next commit
202 annotate, blame:
202 annotate, blame:
203 show changeset information by line for each file
203 show changeset information by line for each file
204 clone:
204 clone:
205 make a copy of an existing repository
205 make a copy of an existing repository
206 commit, ci:
206 commit, ci:
207 commit the specified files or all outstanding changes
207 commit the specified files or all outstanding changes
208 diff:
208 diff:
209 diff repository (or selected files)
209 diff repository (or selected files)
210 export:
210 export:
211 dump the header and diffs for one or more changesets
211 dump the header and diffs for one or more changesets
212 forget:
212 forget:
213 forget the specified files on the next commit
213 forget the specified files on the next commit
214 init:
214 init:
215 create a new repository in the given directory
215 create a new repository in the given directory
216 log, history:
216 log, history:
217 show revision history of entire repository or files
217 show revision history of entire repository or files
218 merge:
218 merge:
219 merge working directory with another revision
219 merge working directory with another revision
220 pull:
220 pull:
221 pull changes from the specified source
221 pull changes from the specified source
222 push:
222 push:
223 push changes to the specified destination
223 push changes to the specified destination
224 remove, rm:
224 remove, rm:
225 remove the specified files on the next commit
225 remove the specified files on the next commit
226 serve:
226 serve:
227 start stand-alone webserver
227 start stand-alone webserver
228 status, st:
228 status, st:
229 show changed files in the working directory
229 show changed files in the working directory
230 summary, sum:
230 summary, sum:
231 summarize working directory state
231 summarize working directory state
232 update, up, checkout, co:
232 update, up, checkout, co:
233 update working directory (or switch revisions)
233 update working directory (or switch revisions)
234
234
235 global options:
235 global options:
236 -R --repository REPO repository root directory or name of overlay bundle
236 -R --repository REPO repository root directory or name of overlay bundle
237 file
237 file
238 --cwd DIR change working directory
238 --cwd DIR change working directory
239 -y --noninteractive do not prompt, assume 'yes' for any required answers
239 -y --noninteractive do not prompt, assume 'yes' for any required answers
240 -q --quiet suppress output
240 -q --quiet suppress output
241 -v --verbose enable additional output
241 -v --verbose enable additional output
242 --config CONFIG [+] set/override config option (use 'section.name=value')
242 --config CONFIG [+] set/override config option (use 'section.name=value')
243 --debug enable debugging output
243 --debug enable debugging output
244 --debugger start debugger
244 --debugger start debugger
245 --encoding ENCODE set the charset encoding (default: ascii)
245 --encoding ENCODE set the charset encoding (default: ascii)
246 --encodingmode MODE set the charset encoding mode (default: strict)
246 --encodingmode MODE set the charset encoding mode (default: strict)
247 --traceback always print a traceback on exception
247 --traceback always print a traceback on exception
248 --time time how long the command takes
248 --time time how long the command takes
249 --profile print command execution profile
249 --profile print command execution profile
250 --version output version information and exit
250 --version output version information and exit
251 -h --help display help and exit
251 -h --help display help and exit
252
252
253 [+] marked option can be specified multiple times
253 [+] marked option can be specified multiple times
254
254
255 use "hg help" for the full list of commands
255 use "hg help" for the full list of commands
256
256
257 $ hg add -h
257 $ hg add -h
258 hg add [OPTION]... [FILE]...
258 hg add [OPTION]... [FILE]...
259
259
260 add the specified files on the next commit
260 add the specified files on the next commit
261
261
262 Schedule files to be version controlled and added to the repository.
262 Schedule files to be version controlled and added to the repository.
263
263
264 The files will be added to the repository at the next commit. To undo an
264 The files will be added to the repository at the next commit. To undo an
265 add before that, see "hg forget".
265 add before that, see "hg forget".
266
266
267 If no names are given, add all files to the repository.
267 If no names are given, add all files to the repository.
268
268
269 Returns 0 if all files are successfully added.
269 Returns 0 if all files are successfully added.
270
270
271 use "hg -v help add" to show verbose help
271 use "hg -v help add" to show verbose help
272
272
273 options:
273 options:
274
274
275 -I --include PATTERN [+] include names matching the given patterns
275 -I --include PATTERN [+] include names matching the given patterns
276 -X --exclude PATTERN [+] exclude names matching the given patterns
276 -X --exclude PATTERN [+] exclude names matching the given patterns
277 -S --subrepos recurse into subrepositories
277 -S --subrepos recurse into subrepositories
278 -n --dry-run do not perform actions, just print output
278 -n --dry-run do not perform actions, just print output
279
279
280 [+] marked option can be specified multiple times
280 [+] marked option can be specified multiple times
281
281
282 use "hg -v help add" to show global options
282 use "hg -v help add" to show global options
283
283
284 Verbose help for add
284 Verbose help for add
285
285
286 $ hg add -hv
286 $ hg add -hv
287 hg add [OPTION]... [FILE]...
287 hg add [OPTION]... [FILE]...
288
288
289 add the specified files on the next commit
289 add the specified files on the next commit
290
290
291 Schedule files to be version controlled and added to the repository.
291 Schedule files to be version controlled and added to the repository.
292
292
293 The files will be added to the repository at the next commit. To undo an
293 The files will be added to the repository at the next commit. To undo an
294 add before that, see "hg forget".
294 add before that, see "hg forget".
295
295
296 If no names are given, add all files to the repository.
296 If no names are given, add all files to the repository.
297
297
298 An example showing how new (unknown) files are added automatically by "hg
298 An example showing how new (unknown) files are added automatically by "hg
299 add":
299 add":
300
300
301 $ ls
301 $ ls
302 foo.c
302 foo.c
303 $ hg status
303 $ hg status
304 ? foo.c
304 ? foo.c
305 $ hg add
305 $ hg add
306 adding foo.c
306 adding foo.c
307 $ hg status
307 $ hg status
308 A foo.c
308 A foo.c
309
309
310 Returns 0 if all files are successfully added.
310 Returns 0 if all files are successfully added.
311
311
312 options:
312 options:
313
313
314 -I --include PATTERN [+] include names matching the given patterns
314 -I --include PATTERN [+] include names matching the given patterns
315 -X --exclude PATTERN [+] exclude names matching the given patterns
315 -X --exclude PATTERN [+] exclude names matching the given patterns
316 -S --subrepos recurse into subrepositories
316 -S --subrepos recurse into subrepositories
317 -n --dry-run do not perform actions, just print output
317 -n --dry-run do not perform actions, just print output
318
318
319 global options:
319 global options:
320 -R --repository REPO repository root directory or name of overlay bundle
320 -R --repository REPO repository root directory or name of overlay bundle
321 file
321 file
322 --cwd DIR change working directory
322 --cwd DIR change working directory
323 -y --noninteractive do not prompt, assume 'yes' for any required
323 -y --noninteractive do not prompt, assume 'yes' for any required
324 answers
324 answers
325 -q --quiet suppress output
325 -q --quiet suppress output
326 -v --verbose enable additional output
326 -v --verbose enable additional output
327 --config CONFIG [+] set/override config option (use
327 --config CONFIG [+] set/override config option (use
328 'section.name=value')
328 'section.name=value')
329 --debug enable debugging output
329 --debug enable debugging output
330 --debugger start debugger
330 --debugger start debugger
331 --encoding ENCODE set the charset encoding (default: ascii)
331 --encoding ENCODE set the charset encoding (default: ascii)
332 --encodingmode MODE set the charset encoding mode (default: strict)
332 --encodingmode MODE set the charset encoding mode (default: strict)
333 --traceback always print a traceback on exception
333 --traceback always print a traceback on exception
334 --time time how long the command takes
334 --time time how long the command takes
335 --profile print command execution profile
335 --profile print command execution profile
336 --version output version information and exit
336 --version output version information and exit
337 -h --help display help and exit
337 -h --help display help and exit
338
338
339 [+] marked option can be specified multiple times
339 [+] marked option can be specified multiple times
340
340
341 Test help option with version option
341 Test help option with version option
342
342
343 $ hg add -h --version
343 $ hg add -h --version
344 Mercurial Distributed SCM (version *) (glob)
344 Mercurial Distributed SCM (version *) (glob)
345
345
346 Copyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others
346 Copyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others
347 This is free software; see the source for copying conditions. There is NO
347 This is free software; see the source for copying conditions. There is NO
348 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
348 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
349
349
350 hg add [OPTION]... [FILE]...
350 hg add [OPTION]... [FILE]...
351
351
352 add the specified files on the next commit
352 add the specified files on the next commit
353
353
354 Schedule files to be version controlled and added to the repository.
354 Schedule files to be version controlled and added to the repository.
355
355
356 The files will be added to the repository at the next commit. To undo an
356 The files will be added to the repository at the next commit. To undo an
357 add before that, see "hg forget".
357 add before that, see "hg forget".
358
358
359 If no names are given, add all files to the repository.
359 If no names are given, add all files to the repository.
360
360
361 Returns 0 if all files are successfully added.
361 Returns 0 if all files are successfully added.
362
362
363 use "hg -v help add" to show verbose help
363 use "hg -v help add" to show verbose help
364
364
365 options:
365 options:
366
366
367 -I --include PATTERN [+] include names matching the given patterns
367 -I --include PATTERN [+] include names matching the given patterns
368 -X --exclude PATTERN [+] exclude names matching the given patterns
368 -X --exclude PATTERN [+] exclude names matching the given patterns
369 -S --subrepos recurse into subrepositories
369 -S --subrepos recurse into subrepositories
370 -n --dry-run do not perform actions, just print output
370 -n --dry-run do not perform actions, just print output
371
371
372 [+] marked option can be specified multiple times
372 [+] marked option can be specified multiple times
373
373
374 use "hg -v help add" to show global options
374 use "hg -v help add" to show global options
375
375
376 $ hg add --skjdfks
376 $ hg add --skjdfks
377 hg add: option --skjdfks not recognized
377 hg add: option --skjdfks not recognized
378 hg add [OPTION]... [FILE]...
378 hg add [OPTION]... [FILE]...
379
379
380 add the specified files on the next commit
380 add the specified files on the next commit
381
381
382 Schedule files to be version controlled and added to the repository.
382 Schedule files to be version controlled and added to the repository.
383
383
384 The files will be added to the repository at the next commit. To undo an
384 The files will be added to the repository at the next commit. To undo an
385 add before that, see "hg forget".
385 add before that, see "hg forget".
386
386
387 If no names are given, add all files to the repository.
387 If no names are given, add all files to the repository.
388
388
389 Returns 0 if all files are successfully added.
389 Returns 0 if all files are successfully added.
390
390
391 use "hg -v help add" to show verbose help
391 use "hg -v help add" to show verbose help
392
392
393 options:
393 options:
394
394
395 -I --include PATTERN [+] include names matching the given patterns
395 -I --include PATTERN [+] include names matching the given patterns
396 -X --exclude PATTERN [+] exclude names matching the given patterns
396 -X --exclude PATTERN [+] exclude names matching the given patterns
397 -S --subrepos recurse into subrepositories
397 -S --subrepos recurse into subrepositories
398 -n --dry-run do not perform actions, just print output
398 -n --dry-run do not perform actions, just print output
399
399
400 [+] marked option can be specified multiple times
400 [+] marked option can be specified multiple times
401
401
402 use "hg -v help add" to show global options
402 use "hg -v help add" to show global options
403 [255]
403 [255]
404
404
405 Test ambiguous command help
405 Test ambiguous command help
406
406
407 $ hg help ad
407 $ hg help ad
408 list of commands:
408 list of commands:
409
409
410 add add the specified files on the next commit
410 add add the specified files on the next commit
411 addremove add all new files, delete all missing files
411 addremove add all new files, delete all missing files
412
412
413 use "hg -v help ad" to show aliases and global options
413 use "hg -v help ad" to show aliases and global options
414
414
415 Test command without options
415 Test command without options
416
416
417 $ hg help verify
417 $ hg help verify
418 hg verify
418 hg verify
419
419
420 verify the integrity of the repository
420 verify the integrity of the repository
421
421
422 Verify the integrity of the current repository.
422 Verify the integrity of the current repository.
423
423
424 This will perform an extensive check of the repository's integrity,
424 This will perform an extensive check of the repository's integrity,
425 validating the hashes and checksums of each entry in the changelog,
425 validating the hashes and checksums of each entry in the changelog,
426 manifest, and tracked files, as well as the integrity of their crosslinks
426 manifest, and tracked files, as well as the integrity of their crosslinks
427 and indices.
427 and indices.
428
428
429 Returns 0 on success, 1 if errors are encountered.
429 Returns 0 on success, 1 if errors are encountered.
430
430
431 use "hg -v help verify" to show global options
431 use "hg -v help verify" to show global options
432
432
433 $ hg help diff
433 $ hg help diff
434 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
434 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
435
435
436 diff repository (or selected files)
436 diff repository (or selected files)
437
437
438 Show differences between revisions for the specified files.
438 Show differences between revisions for the specified files.
439
439
440 Differences between files are shown using the unified diff format.
440 Differences between files are shown using the unified diff format.
441
441
442 Note:
442 Note:
443 diff may generate unexpected results for merges, as it will default to
443 diff may generate unexpected results for merges, as it will default to
444 comparing against the working directory's first parent changeset if no
444 comparing against the working directory's first parent changeset if no
445 revisions are specified.
445 revisions are specified.
446
446
447 When two revision arguments are given, then changes are shown between
447 When two revision arguments are given, then changes are shown between
448 those revisions. If only one revision is specified then that revision is
448 those revisions. If only one revision is specified then that revision is
449 compared to the working directory, and, when no revisions are specified,
449 compared to the working directory, and, when no revisions are specified,
450 the working directory files are compared to its parent.
450 the working directory files are compared to its parent.
451
451
452 Alternatively you can specify -c/--change with a revision to see the
452 Alternatively you can specify -c/--change with a revision to see the
453 changes in that changeset relative to its first parent.
453 changes in that changeset relative to its first parent.
454
454
455 Without the -a/--text option, diff will avoid generating diffs of files it
455 Without the -a/--text option, diff will avoid generating diffs of files it
456 detects as binary. With -a, diff will generate a diff anyway, probably
456 detects as binary. With -a, diff will generate a diff anyway, probably
457 with undesirable results.
457 with undesirable results.
458
458
459 Use the -g/--git option to generate diffs in the git extended diff format.
459 Use the -g/--git option to generate diffs in the git extended diff format.
460 For more information, read "hg help diffs".
460 For more information, read "hg help diffs".
461
461
462 Returns 0 on success.
462 Returns 0 on success.
463
463
464 options:
464 options:
465
465
466 -r --rev REV [+] revision
466 -r --rev REV [+] revision
467 -c --change REV change made by revision
467 -c --change REV change made by revision
468 -a --text treat all files as text
468 -a --text treat all files as text
469 -g --git use git extended diff format
469 -g --git use git extended diff format
470 --nodates omit dates from diff headers
470 --nodates omit dates from diff headers
471 -p --show-function show which function each change is in
471 -p --show-function show which function each change is in
472 --reverse produce a diff that undoes the changes
472 --reverse produce a diff that undoes the changes
473 -w --ignore-all-space ignore white space when comparing lines
473 -w --ignore-all-space ignore white space when comparing lines
474 -b --ignore-space-change ignore changes in the amount of white space
474 -b --ignore-space-change ignore changes in the amount of white space
475 -B --ignore-blank-lines ignore changes whose lines are all blank
475 -B --ignore-blank-lines ignore changes whose lines are all blank
476 -U --unified NUM number of lines of context to show
476 -U --unified NUM number of lines of context to show
477 --stat output diffstat-style summary of changes
477 --stat output diffstat-style summary of changes
478 -I --include PATTERN [+] include names matching the given patterns
478 -I --include PATTERN [+] include names matching the given patterns
479 -X --exclude PATTERN [+] exclude names matching the given patterns
479 -X --exclude PATTERN [+] exclude names matching the given patterns
480 -S --subrepos recurse into subrepositories
480 -S --subrepos recurse into subrepositories
481
481
482 [+] marked option can be specified multiple times
482 [+] marked option can be specified multiple times
483
483
484 use "hg -v help diff" to show global options
484 use "hg -v help diff" to show global options
485
485
486 $ hg help status
486 $ hg help status
487 hg status [OPTION]... [FILE]...
487 hg status [OPTION]... [FILE]...
488
488
489 aliases: st
489 aliases: st
490
490
491 show changed files in the working directory
491 show changed files in the working directory
492
492
493 Show status of files in the repository. If names are given, only files
493 Show status of files in the repository. If names are given, only files
494 that match are shown. Files that are clean or ignored or the source of a
494 that match are shown. Files that are clean or ignored or the source of a
495 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
495 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
496 -C/--copies or -A/--all are given. Unless options described with "show
496 -C/--copies or -A/--all are given. Unless options described with "show
497 only ..." are given, the options -mardu are used.
497 only ..." are given, the options -mardu are used.
498
498
499 Option -q/--quiet hides untracked (unknown and ignored) files unless
499 Option -q/--quiet hides untracked (unknown and ignored) files unless
500 explicitly requested with -u/--unknown or -i/--ignored.
500 explicitly requested with -u/--unknown or -i/--ignored.
501
501
502 NOTE: status may appear to disagree with diff if permissions have changed
502 Note:
503 or a merge has occurred. The standard diff format does not report
503 status may appear to disagree with diff if permissions have changed or
504 permission changes and diff only reports changes relative to one merge
504 a merge has occurred. The standard diff format does not report
505 parent.
505 permission changes and diff only reports changes relative to one merge
506 parent.
506
507
507 If one revision is given, it is used as the base revision. If two
508 If one revision is given, it is used as the base revision. If two
508 revisions are given, the differences between them are shown. The --change
509 revisions are given, the differences between them are shown. The --change
509 option can also be used as a shortcut to list the changed files of a
510 option can also be used as a shortcut to list the changed files of a
510 revision from its first parent.
511 revision from its first parent.
511
512
512 The codes used to show the status of files are:
513 The codes used to show the status of files are:
513
514
514 M = modified
515 M = modified
515 A = added
516 A = added
516 R = removed
517 R = removed
517 C = clean
518 C = clean
518 ! = missing (deleted by non-hg command, but still tracked)
519 ! = missing (deleted by non-hg command, but still tracked)
519 ? = not tracked
520 ? = not tracked
520 I = ignored
521 I = ignored
521 = origin of the previous file listed as A (added)
522 = origin of the previous file listed as A (added)
522
523
523 Returns 0 on success.
524 Returns 0 on success.
524
525
525 options:
526 options:
526
527
527 -A --all show status of all files
528 -A --all show status of all files
528 -m --modified show only modified files
529 -m --modified show only modified files
529 -a --added show only added files
530 -a --added show only added files
530 -r --removed show only removed files
531 -r --removed show only removed files
531 -d --deleted show only deleted (but tracked) files
532 -d --deleted show only deleted (but tracked) files
532 -c --clean show only files without changes
533 -c --clean show only files without changes
533 -u --unknown show only unknown (not tracked) files
534 -u --unknown show only unknown (not tracked) files
534 -i --ignored show only ignored files
535 -i --ignored show only ignored files
535 -n --no-status hide status prefix
536 -n --no-status hide status prefix
536 -C --copies show source of copied files
537 -C --copies show source of copied files
537 -0 --print0 end filenames with NUL, for use with xargs
538 -0 --print0 end filenames with NUL, for use with xargs
538 --rev REV [+] show difference from revision
539 --rev REV [+] show difference from revision
539 --change REV list the changed files of a revision
540 --change REV list the changed files of a revision
540 -I --include PATTERN [+] include names matching the given patterns
541 -I --include PATTERN [+] include names matching the given patterns
541 -X --exclude PATTERN [+] exclude names matching the given patterns
542 -X --exclude PATTERN [+] exclude names matching the given patterns
542 -S --subrepos recurse into subrepositories
543 -S --subrepos recurse into subrepositories
543
544
544 [+] marked option can be specified multiple times
545 [+] marked option can be specified multiple times
545
546
546 use "hg -v help status" to show global options
547 use "hg -v help status" to show global options
547
548
548 $ hg -q help status
549 $ hg -q help status
549 hg status [OPTION]... [FILE]...
550 hg status [OPTION]... [FILE]...
550
551
551 show changed files in the working directory
552 show changed files in the working directory
552
553
553 $ hg help foo
554 $ hg help foo
554 hg: unknown command 'foo'
555 hg: unknown command 'foo'
555 Mercurial Distributed SCM
556 Mercurial Distributed SCM
556
557
557 basic commands:
558 basic commands:
558
559
559 add add the specified files on the next commit
560 add add the specified files on the next commit
560 annotate show changeset information by line for each file
561 annotate show changeset information by line for each file
561 clone make a copy of an existing repository
562 clone make a copy of an existing repository
562 commit commit the specified files or all outstanding changes
563 commit commit the specified files or all outstanding changes
563 diff diff repository (or selected files)
564 diff diff repository (or selected files)
564 export dump the header and diffs for one or more changesets
565 export dump the header and diffs for one or more changesets
565 forget forget the specified files on the next commit
566 forget forget the specified files on the next commit
566 init create a new repository in the given directory
567 init create a new repository in the given directory
567 log show revision history of entire repository or files
568 log show revision history of entire repository or files
568 merge merge working directory with another revision
569 merge merge working directory with another revision
569 pull pull changes from the specified source
570 pull pull changes from the specified source
570 push push changes to the specified destination
571 push push changes to the specified destination
571 remove remove the specified files on the next commit
572 remove remove the specified files on the next commit
572 serve start stand-alone webserver
573 serve start stand-alone webserver
573 status show changed files in the working directory
574 status show changed files in the working directory
574 summary summarize working directory state
575 summary summarize working directory state
575 update update working directory (or switch revisions)
576 update update working directory (or switch revisions)
576
577
577 use "hg help" for the full list of commands or "hg -v" for details
578 use "hg help" for the full list of commands or "hg -v" for details
578 [255]
579 [255]
579
580
580 $ hg skjdfks
581 $ hg skjdfks
581 hg: unknown command 'skjdfks'
582 hg: unknown command 'skjdfks'
582 Mercurial Distributed SCM
583 Mercurial Distributed SCM
583
584
584 basic commands:
585 basic commands:
585
586
586 add add the specified files on the next commit
587 add add the specified files on the next commit
587 annotate show changeset information by line for each file
588 annotate show changeset information by line for each file
588 clone make a copy of an existing repository
589 clone make a copy of an existing repository
589 commit commit the specified files or all outstanding changes
590 commit commit the specified files or all outstanding changes
590 diff diff repository (or selected files)
591 diff diff repository (or selected files)
591 export dump the header and diffs for one or more changesets
592 export dump the header and diffs for one or more changesets
592 forget forget the specified files on the next commit
593 forget forget the specified files on the next commit
593 init create a new repository in the given directory
594 init create a new repository in the given directory
594 log show revision history of entire repository or files
595 log show revision history of entire repository or files
595 merge merge working directory with another revision
596 merge merge working directory with another revision
596 pull pull changes from the specified source
597 pull pull changes from the specified source
597 push push changes to the specified destination
598 push push changes to the specified destination
598 remove remove the specified files on the next commit
599 remove remove the specified files on the next commit
599 serve start stand-alone webserver
600 serve start stand-alone webserver
600 status show changed files in the working directory
601 status show changed files in the working directory
601 summary summarize working directory state
602 summary summarize working directory state
602 update update working directory (or switch revisions)
603 update update working directory (or switch revisions)
603
604
604 use "hg help" for the full list of commands or "hg -v" for details
605 use "hg help" for the full list of commands or "hg -v" for details
605 [255]
606 [255]
606
607
607 $ cat > helpext.py <<EOF
608 $ cat > helpext.py <<EOF
608 > import os
609 > import os
609 > from mercurial import commands
610 > from mercurial import commands
610 >
611 >
611 > def nohelp(ui, *args, **kwargs):
612 > def nohelp(ui, *args, **kwargs):
612 > pass
613 > pass
613 >
614 >
614 > cmdtable = {
615 > cmdtable = {
615 > "nohelp": (nohelp, [], "hg nohelp"),
616 > "nohelp": (nohelp, [], "hg nohelp"),
616 > }
617 > }
617 >
618 >
618 > commands.norepo += ' nohelp'
619 > commands.norepo += ' nohelp'
619 > EOF
620 > EOF
620 $ echo '[extensions]' >> $HGRCPATH
621 $ echo '[extensions]' >> $HGRCPATH
621 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
622 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
622
623
623 Test command with no help text
624 Test command with no help text
624
625
625 $ hg help nohelp
626 $ hg help nohelp
626 hg nohelp
627 hg nohelp
627
628
628 (no help text available)
629 (no help text available)
629
630
630 use "hg -v help nohelp" to show global options
631 use "hg -v help nohelp" to show global options
631
632
632 Test that default list of commands omits extension commands
633 Test that default list of commands omits extension commands
633
634
634 $ hg help
635 $ hg help
635 Mercurial Distributed SCM
636 Mercurial Distributed SCM
636
637
637 list of commands:
638 list of commands:
638
639
639 add add the specified files on the next commit
640 add add the specified files on the next commit
640 addremove add all new files, delete all missing files
641 addremove add all new files, delete all missing files
641 annotate show changeset information by line for each file
642 annotate show changeset information by line for each file
642 archive create an unversioned archive of a repository revision
643 archive create an unversioned archive of a repository revision
643 backout reverse effect of earlier changeset
644 backout reverse effect of earlier changeset
644 bisect subdivision search of changesets
645 bisect subdivision search of changesets
645 branch set or show the current branch name
646 branch set or show the current branch name
646 branches list repository named branches
647 branches list repository named branches
647 bundle create a changegroup file
648 bundle create a changegroup file
648 cat output the current or given revision of files
649 cat output the current or given revision of files
649 clone make a copy of an existing repository
650 clone make a copy of an existing repository
650 commit commit the specified files or all outstanding changes
651 commit commit the specified files or all outstanding changes
651 copy mark files as copied for the next commit
652 copy mark files as copied for the next commit
652 diff diff repository (or selected files)
653 diff diff repository (or selected files)
653 export dump the header and diffs for one or more changesets
654 export dump the header and diffs for one or more changesets
654 forget forget the specified files on the next commit
655 forget forget the specified files on the next commit
655 grep search for a pattern in specified files and revisions
656 grep search for a pattern in specified files and revisions
656 heads show current repository heads or show branch heads
657 heads show current repository heads or show branch heads
657 help show help for a given topic or a help overview
658 help show help for a given topic or a help overview
658 identify identify the working copy or specified revision
659 identify identify the working copy or specified revision
659 import import an ordered set of patches
660 import import an ordered set of patches
660 incoming show new changesets found in source
661 incoming show new changesets found in source
661 init create a new repository in the given directory
662 init create a new repository in the given directory
662 locate locate files matching specific patterns
663 locate locate files matching specific patterns
663 log show revision history of entire repository or files
664 log show revision history of entire repository or files
664 manifest output the current or given revision of the project manifest
665 manifest output the current or given revision of the project manifest
665 merge merge working directory with another revision
666 merge merge working directory with another revision
666 outgoing show changesets not found in the destination
667 outgoing show changesets not found in the destination
667 parents show the parents of the working directory or revision
668 parents show the parents of the working directory or revision
668 paths show aliases for remote repositories
669 paths show aliases for remote repositories
669 pull pull changes from the specified source
670 pull pull changes from the specified source
670 push push changes to the specified destination
671 push push changes to the specified destination
671 recover roll back an interrupted transaction
672 recover roll back an interrupted transaction
672 remove remove the specified files on the next commit
673 remove remove the specified files on the next commit
673 rename rename files; equivalent of copy + remove
674 rename rename files; equivalent of copy + remove
674 resolve redo merges or set/view the merge status of files
675 resolve redo merges or set/view the merge status of files
675 revert restore individual files or directories to an earlier state
676 revert restore individual files or directories to an earlier state
676 rollback roll back the last transaction (dangerous)
677 rollback roll back the last transaction (dangerous)
677 root print the root (top) of the current working directory
678 root print the root (top) of the current working directory
678 serve start stand-alone webserver
679 serve start stand-alone webserver
679 showconfig show combined config settings from all hgrc files
680 showconfig show combined config settings from all hgrc files
680 status show changed files in the working directory
681 status show changed files in the working directory
681 summary summarize working directory state
682 summary summarize working directory state
682 tag add one or more tags for the current or given revision
683 tag add one or more tags for the current or given revision
683 tags list repository tags
684 tags list repository tags
684 tip show the tip revision
685 tip show the tip revision
685 unbundle apply one or more changegroup files
686 unbundle apply one or more changegroup files
686 update update working directory (or switch revisions)
687 update update working directory (or switch revisions)
687 verify verify the integrity of the repository
688 verify verify the integrity of the repository
688 version output version and copyright information
689 version output version and copyright information
689
690
690 enabled extensions:
691 enabled extensions:
691
692
692 helpext (no help text available)
693 helpext (no help text available)
693
694
694 additional help topics:
695 additional help topics:
695
696
696 config Configuration Files
697 config Configuration Files
697 dates Date Formats
698 dates Date Formats
698 patterns File Name Patterns
699 patterns File Name Patterns
699 environment Environment Variables
700 environment Environment Variables
700 revisions Specifying Single Revisions
701 revisions Specifying Single Revisions
701 multirevs Specifying Multiple Revisions
702 multirevs Specifying Multiple Revisions
702 revsets Specifying Revision Sets
703 revsets Specifying Revision Sets
703 diffs Diff Formats
704 diffs Diff Formats
704 templating Template Usage
705 templating Template Usage
705 urls URL Paths
706 urls URL Paths
706 extensions Using additional features
707 extensions Using additional features
707 hgweb Configuring hgweb
708 hgweb Configuring hgweb
708 glossary Glossary
709 glossary Glossary
709
710
710 use "hg -v help" to show aliases and global options
711 use "hg -v help" to show aliases and global options
711
712
712 Test list of commands with command with no help text
713 Test list of commands with command with no help text
713
714
714 $ hg help helpext
715 $ hg help helpext
715 helpext extension - no help text available
716 helpext extension - no help text available
716
717
717 list of commands:
718 list of commands:
718
719
719 nohelp (no help text available)
720 nohelp (no help text available)
720
721
721 use "hg -v help helpext" to show aliases and global options
722 use "hg -v help helpext" to show aliases and global options
722
723
723 Test a help topic
724 Test a help topic
724
725
725 $ hg help revs
726 $ hg help revs
726 Specifying Single Revisions
727 Specifying Single Revisions
727
728
728 Mercurial supports several ways to specify individual revisions.
729 Mercurial supports several ways to specify individual revisions.
729
730
730 A plain integer is treated as a revision number. Negative integers are
731 A plain integer is treated as a revision number. Negative integers are
731 treated as sequential offsets from the tip, with -1 denoting the tip, -2
732 treated as sequential offsets from the tip, with -1 denoting the tip, -2
732 denoting the revision prior to the tip, and so forth.
733 denoting the revision prior to the tip, and so forth.
733
734
734 A 40-digit hexadecimal string is treated as a unique revision identifier.
735 A 40-digit hexadecimal string is treated as a unique revision identifier.
735
736
736 A hexadecimal string less than 40 characters long is treated as a unique
737 A hexadecimal string less than 40 characters long is treated as a unique
737 revision identifier and is referred to as a short-form identifier. A
738 revision identifier and is referred to as a short-form identifier. A
738 short-form identifier is only valid if it is the prefix of exactly one
739 short-form identifier is only valid if it is the prefix of exactly one
739 full-length identifier.
740 full-length identifier.
740
741
741 Any other string is treated as a tag or branch name. A tag name is a
742 Any other string is treated as a tag or branch name. A tag name is a
742 symbolic name associated with a revision identifier. A branch name denotes
743 symbolic name associated with a revision identifier. A branch name denotes
743 the tipmost revision of that branch. Tag and branch names must not contain
744 the tipmost revision of that branch. Tag and branch names must not contain
744 the ":" character.
745 the ":" character.
745
746
746 The reserved name "tip" is a special tag that always identifies the most
747 The reserved name "tip" is a special tag that always identifies the most
747 recent revision.
748 recent revision.
748
749
749 The reserved name "null" indicates the null revision. This is the revision
750 The reserved name "null" indicates the null revision. This is the revision
750 of an empty repository, and the parent of revision 0.
751 of an empty repository, and the parent of revision 0.
751
752
752 The reserved name "." indicates the working directory parent. If no
753 The reserved name "." indicates the working directory parent. If no
753 working directory is checked out, it is equivalent to null. If an
754 working directory is checked out, it is equivalent to null. If an
754 uncommitted merge is in progress, "." is the revision of the first parent.
755 uncommitted merge is in progress, "." is the revision of the first parent.
General Comments 0
You need to be logged in to leave comments. Login now