##// END OF EJS Templates
commit: change "editform" to distinguish merge commits from other (--amend)...
FUJIWARA Katsunori -
r22249:f5ff18f6 default
parent child Browse files
Show More
@@ -1,2715 +1,2715 b''
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in 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 i18n import _
9 from i18n import _
10 import os, sys, errno, re, tempfile
10 import os, sys, errno, re, tempfile
11 import util, scmutil, templater, patch, error, templatekw, revlog, copies
11 import util, scmutil, templater, patch, error, templatekw, revlog, copies
12 import match as matchmod
12 import match as matchmod
13 import context, repair, graphmod, revset, phases, obsolete, pathutil
13 import context, repair, graphmod, revset, phases, obsolete, pathutil
14 import changelog
14 import changelog
15 import bookmarks
15 import bookmarks
16 import lock as lockmod
16 import lock as lockmod
17
17
18 def parsealiases(cmd):
18 def parsealiases(cmd):
19 return cmd.lstrip("^").split("|")
19 return cmd.lstrip("^").split("|")
20
20
21 def findpossible(cmd, table, strict=False):
21 def findpossible(cmd, table, strict=False):
22 """
22 """
23 Return cmd -> (aliases, command table entry)
23 Return cmd -> (aliases, command table entry)
24 for each matching command.
24 for each matching command.
25 Return debug commands (or their aliases) only if no normal command matches.
25 Return debug commands (or their aliases) only if no normal command matches.
26 """
26 """
27 choice = {}
27 choice = {}
28 debugchoice = {}
28 debugchoice = {}
29
29
30 if cmd in table:
30 if cmd in table:
31 # short-circuit exact matches, "log" alias beats "^log|history"
31 # short-circuit exact matches, "log" alias beats "^log|history"
32 keys = [cmd]
32 keys = [cmd]
33 else:
33 else:
34 keys = table.keys()
34 keys = table.keys()
35
35
36 for e in keys:
36 for e in keys:
37 aliases = parsealiases(e)
37 aliases = parsealiases(e)
38 found = None
38 found = None
39 if cmd in aliases:
39 if cmd in aliases:
40 found = cmd
40 found = cmd
41 elif not strict:
41 elif not strict:
42 for a in aliases:
42 for a in aliases:
43 if a.startswith(cmd):
43 if a.startswith(cmd):
44 found = a
44 found = a
45 break
45 break
46 if found is not None:
46 if found is not None:
47 if aliases[0].startswith("debug") or found.startswith("debug"):
47 if aliases[0].startswith("debug") or found.startswith("debug"):
48 debugchoice[found] = (aliases, table[e])
48 debugchoice[found] = (aliases, table[e])
49 else:
49 else:
50 choice[found] = (aliases, table[e])
50 choice[found] = (aliases, table[e])
51
51
52 if not choice and debugchoice:
52 if not choice and debugchoice:
53 choice = debugchoice
53 choice = debugchoice
54
54
55 return choice
55 return choice
56
56
57 def findcmd(cmd, table, strict=True):
57 def findcmd(cmd, table, strict=True):
58 """Return (aliases, command table entry) for command string."""
58 """Return (aliases, command table entry) for command string."""
59 choice = findpossible(cmd, table, strict)
59 choice = findpossible(cmd, table, strict)
60
60
61 if cmd in choice:
61 if cmd in choice:
62 return choice[cmd]
62 return choice[cmd]
63
63
64 if len(choice) > 1:
64 if len(choice) > 1:
65 clist = choice.keys()
65 clist = choice.keys()
66 clist.sort()
66 clist.sort()
67 raise error.AmbiguousCommand(cmd, clist)
67 raise error.AmbiguousCommand(cmd, clist)
68
68
69 if choice:
69 if choice:
70 return choice.values()[0]
70 return choice.values()[0]
71
71
72 raise error.UnknownCommand(cmd)
72 raise error.UnknownCommand(cmd)
73
73
74 def findrepo(p):
74 def findrepo(p):
75 while not os.path.isdir(os.path.join(p, ".hg")):
75 while not os.path.isdir(os.path.join(p, ".hg")):
76 oldp, p = p, os.path.dirname(p)
76 oldp, p = p, os.path.dirname(p)
77 if p == oldp:
77 if p == oldp:
78 return None
78 return None
79
79
80 return p
80 return p
81
81
82 def bailifchanged(repo):
82 def bailifchanged(repo):
83 if repo.dirstate.p2() != nullid:
83 if repo.dirstate.p2() != nullid:
84 raise util.Abort(_('outstanding uncommitted merge'))
84 raise util.Abort(_('outstanding uncommitted merge'))
85 modified, added, removed, deleted = repo.status()[:4]
85 modified, added, removed, deleted = repo.status()[:4]
86 if modified or added or removed or deleted:
86 if modified or added or removed or deleted:
87 raise util.Abort(_('uncommitted changes'))
87 raise util.Abort(_('uncommitted changes'))
88 ctx = repo[None]
88 ctx = repo[None]
89 for s in sorted(ctx.substate):
89 for s in sorted(ctx.substate):
90 if ctx.sub(s).dirty():
90 if ctx.sub(s).dirty():
91 raise util.Abort(_("uncommitted changes in subrepo %s") % s)
91 raise util.Abort(_("uncommitted changes in subrepo %s") % s)
92
92
93 def logmessage(ui, opts):
93 def logmessage(ui, opts):
94 """ get the log message according to -m and -l option """
94 """ get the log message according to -m and -l option """
95 message = opts.get('message')
95 message = opts.get('message')
96 logfile = opts.get('logfile')
96 logfile = opts.get('logfile')
97
97
98 if message and logfile:
98 if message and logfile:
99 raise util.Abort(_('options --message and --logfile are mutually '
99 raise util.Abort(_('options --message and --logfile are mutually '
100 'exclusive'))
100 'exclusive'))
101 if not message and logfile:
101 if not message and logfile:
102 try:
102 try:
103 if logfile == '-':
103 if logfile == '-':
104 message = ui.fin.read()
104 message = ui.fin.read()
105 else:
105 else:
106 message = '\n'.join(util.readfile(logfile).splitlines())
106 message = '\n'.join(util.readfile(logfile).splitlines())
107 except IOError, inst:
107 except IOError, inst:
108 raise util.Abort(_("can't read commit message '%s': %s") %
108 raise util.Abort(_("can't read commit message '%s': %s") %
109 (logfile, inst.strerror))
109 (logfile, inst.strerror))
110 return message
110 return message
111
111
112 def mergeeditform(ctxorbool, baseform):
112 def mergeeditform(ctxorbool, baseform):
113 """build appropriate editform from ctxorbool and baseform
113 """build appropriate editform from ctxorbool and baseform
114
114
115 'cxtorbool' is one of a ctx to be committed, or a bool whether
115 'cxtorbool' is one of a ctx to be committed, or a bool whether
116 merging is committed.
116 merging is committed.
117
117
118 This returns editform 'baseform' with '.merge' if merging is
118 This returns editform 'baseform' with '.merge' if merging is
119 committed, or one with '.normal' suffix otherwise.
119 committed, or one with '.normal' suffix otherwise.
120 """
120 """
121 if isinstance(ctxorbool, bool):
121 if isinstance(ctxorbool, bool):
122 if ctxorbool:
122 if ctxorbool:
123 return baseform + ".merge"
123 return baseform + ".merge"
124 elif 1 < len(ctxorbool.parents()):
124 elif 1 < len(ctxorbool.parents()):
125 return baseform + ".merge"
125 return baseform + ".merge"
126
126
127 return baseform + ".normal"
127 return baseform + ".normal"
128
128
129 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
129 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
130 editform='', **opts):
130 editform='', **opts):
131 """get appropriate commit message editor according to '--edit' option
131 """get appropriate commit message editor according to '--edit' option
132
132
133 'finishdesc' is a function to be called with edited commit message
133 'finishdesc' is a function to be called with edited commit message
134 (= 'description' of the new changeset) just after editing, but
134 (= 'description' of the new changeset) just after editing, but
135 before checking empty-ness. It should return actual text to be
135 before checking empty-ness. It should return actual text to be
136 stored into history. This allows to change description before
136 stored into history. This allows to change description before
137 storing.
137 storing.
138
138
139 'extramsg' is a extra message to be shown in the editor instead of
139 'extramsg' is a extra message to be shown in the editor instead of
140 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
140 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
141 is automatically added.
141 is automatically added.
142
142
143 'editform' is a dot-separated list of names, to distinguish
143 'editform' is a dot-separated list of names, to distinguish
144 the purpose of commit text editing.
144 the purpose of commit text editing.
145
145
146 'getcommiteditor' returns 'commitforceeditor' regardless of
146 'getcommiteditor' returns 'commitforceeditor' regardless of
147 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
147 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
148 they are specific for usage in MQ.
148 they are specific for usage in MQ.
149 """
149 """
150 if edit or finishdesc or extramsg:
150 if edit or finishdesc or extramsg:
151 return lambda r, c, s: commitforceeditor(r, c, s,
151 return lambda r, c, s: commitforceeditor(r, c, s,
152 finishdesc=finishdesc,
152 finishdesc=finishdesc,
153 extramsg=extramsg,
153 extramsg=extramsg,
154 editform=editform)
154 editform=editform)
155 elif editform:
155 elif editform:
156 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
156 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
157 else:
157 else:
158 return commiteditor
158 return commiteditor
159
159
160 def loglimit(opts):
160 def loglimit(opts):
161 """get the log limit according to option -l/--limit"""
161 """get the log limit according to option -l/--limit"""
162 limit = opts.get('limit')
162 limit = opts.get('limit')
163 if limit:
163 if limit:
164 try:
164 try:
165 limit = int(limit)
165 limit = int(limit)
166 except ValueError:
166 except ValueError:
167 raise util.Abort(_('limit must be a positive integer'))
167 raise util.Abort(_('limit must be a positive integer'))
168 if limit <= 0:
168 if limit <= 0:
169 raise util.Abort(_('limit must be positive'))
169 raise util.Abort(_('limit must be positive'))
170 else:
170 else:
171 limit = None
171 limit = None
172 return limit
172 return limit
173
173
174 def makefilename(repo, pat, node, desc=None,
174 def makefilename(repo, pat, node, desc=None,
175 total=None, seqno=None, revwidth=None, pathname=None):
175 total=None, seqno=None, revwidth=None, pathname=None):
176 node_expander = {
176 node_expander = {
177 'H': lambda: hex(node),
177 'H': lambda: hex(node),
178 'R': lambda: str(repo.changelog.rev(node)),
178 'R': lambda: str(repo.changelog.rev(node)),
179 'h': lambda: short(node),
179 'h': lambda: short(node),
180 'm': lambda: re.sub('[^\w]', '_', str(desc))
180 'm': lambda: re.sub('[^\w]', '_', str(desc))
181 }
181 }
182 expander = {
182 expander = {
183 '%': lambda: '%',
183 '%': lambda: '%',
184 'b': lambda: os.path.basename(repo.root),
184 'b': lambda: os.path.basename(repo.root),
185 }
185 }
186
186
187 try:
187 try:
188 if node:
188 if node:
189 expander.update(node_expander)
189 expander.update(node_expander)
190 if node:
190 if node:
191 expander['r'] = (lambda:
191 expander['r'] = (lambda:
192 str(repo.changelog.rev(node)).zfill(revwidth or 0))
192 str(repo.changelog.rev(node)).zfill(revwidth or 0))
193 if total is not None:
193 if total is not None:
194 expander['N'] = lambda: str(total)
194 expander['N'] = lambda: str(total)
195 if seqno is not None:
195 if seqno is not None:
196 expander['n'] = lambda: str(seqno)
196 expander['n'] = lambda: str(seqno)
197 if total is not None and seqno is not None:
197 if total is not None and seqno is not None:
198 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
198 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
199 if pathname is not None:
199 if pathname is not None:
200 expander['s'] = lambda: os.path.basename(pathname)
200 expander['s'] = lambda: os.path.basename(pathname)
201 expander['d'] = lambda: os.path.dirname(pathname) or '.'
201 expander['d'] = lambda: os.path.dirname(pathname) or '.'
202 expander['p'] = lambda: pathname
202 expander['p'] = lambda: pathname
203
203
204 newname = []
204 newname = []
205 patlen = len(pat)
205 patlen = len(pat)
206 i = 0
206 i = 0
207 while i < patlen:
207 while i < patlen:
208 c = pat[i]
208 c = pat[i]
209 if c == '%':
209 if c == '%':
210 i += 1
210 i += 1
211 c = pat[i]
211 c = pat[i]
212 c = expander[c]()
212 c = expander[c]()
213 newname.append(c)
213 newname.append(c)
214 i += 1
214 i += 1
215 return ''.join(newname)
215 return ''.join(newname)
216 except KeyError, inst:
216 except KeyError, inst:
217 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
217 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
218 inst.args[0])
218 inst.args[0])
219
219
220 def makefileobj(repo, pat, node=None, desc=None, total=None,
220 def makefileobj(repo, pat, node=None, desc=None, total=None,
221 seqno=None, revwidth=None, mode='wb', modemap=None,
221 seqno=None, revwidth=None, mode='wb', modemap=None,
222 pathname=None):
222 pathname=None):
223
223
224 writable = mode not in ('r', 'rb')
224 writable = mode not in ('r', 'rb')
225
225
226 if not pat or pat == '-':
226 if not pat or pat == '-':
227 fp = writable and repo.ui.fout or repo.ui.fin
227 fp = writable and repo.ui.fout or repo.ui.fin
228 if util.safehasattr(fp, 'fileno'):
228 if util.safehasattr(fp, 'fileno'):
229 return os.fdopen(os.dup(fp.fileno()), mode)
229 return os.fdopen(os.dup(fp.fileno()), mode)
230 else:
230 else:
231 # if this fp can't be duped properly, return
231 # if this fp can't be duped properly, return
232 # a dummy object that can be closed
232 # a dummy object that can be closed
233 class wrappedfileobj(object):
233 class wrappedfileobj(object):
234 noop = lambda x: None
234 noop = lambda x: None
235 def __init__(self, f):
235 def __init__(self, f):
236 self.f = f
236 self.f = f
237 def __getattr__(self, attr):
237 def __getattr__(self, attr):
238 if attr == 'close':
238 if attr == 'close':
239 return self.noop
239 return self.noop
240 else:
240 else:
241 return getattr(self.f, attr)
241 return getattr(self.f, attr)
242
242
243 return wrappedfileobj(fp)
243 return wrappedfileobj(fp)
244 if util.safehasattr(pat, 'write') and writable:
244 if util.safehasattr(pat, 'write') and writable:
245 return pat
245 return pat
246 if util.safehasattr(pat, 'read') and 'r' in mode:
246 if util.safehasattr(pat, 'read') and 'r' in mode:
247 return pat
247 return pat
248 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
248 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
249 if modemap is not None:
249 if modemap is not None:
250 mode = modemap.get(fn, mode)
250 mode = modemap.get(fn, mode)
251 if mode == 'wb':
251 if mode == 'wb':
252 modemap[fn] = 'ab'
252 modemap[fn] = 'ab'
253 return open(fn, mode)
253 return open(fn, mode)
254
254
255 def openrevlog(repo, cmd, file_, opts):
255 def openrevlog(repo, cmd, file_, opts):
256 """opens the changelog, manifest, a filelog or a given revlog"""
256 """opens the changelog, manifest, a filelog or a given revlog"""
257 cl = opts['changelog']
257 cl = opts['changelog']
258 mf = opts['manifest']
258 mf = opts['manifest']
259 msg = None
259 msg = None
260 if cl and mf:
260 if cl and mf:
261 msg = _('cannot specify --changelog and --manifest at the same time')
261 msg = _('cannot specify --changelog and --manifest at the same time')
262 elif cl or mf:
262 elif cl or mf:
263 if file_:
263 if file_:
264 msg = _('cannot specify filename with --changelog or --manifest')
264 msg = _('cannot specify filename with --changelog or --manifest')
265 elif not repo:
265 elif not repo:
266 msg = _('cannot specify --changelog or --manifest '
266 msg = _('cannot specify --changelog or --manifest '
267 'without a repository')
267 'without a repository')
268 if msg:
268 if msg:
269 raise util.Abort(msg)
269 raise util.Abort(msg)
270
270
271 r = None
271 r = None
272 if repo:
272 if repo:
273 if cl:
273 if cl:
274 r = repo.unfiltered().changelog
274 r = repo.unfiltered().changelog
275 elif mf:
275 elif mf:
276 r = repo.manifest
276 r = repo.manifest
277 elif file_:
277 elif file_:
278 filelog = repo.file(file_)
278 filelog = repo.file(file_)
279 if len(filelog):
279 if len(filelog):
280 r = filelog
280 r = filelog
281 if not r:
281 if not r:
282 if not file_:
282 if not file_:
283 raise error.CommandError(cmd, _('invalid arguments'))
283 raise error.CommandError(cmd, _('invalid arguments'))
284 if not os.path.isfile(file_):
284 if not os.path.isfile(file_):
285 raise util.Abort(_("revlog '%s' not found") % file_)
285 raise util.Abort(_("revlog '%s' not found") % file_)
286 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
286 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
287 file_[:-2] + ".i")
287 file_[:-2] + ".i")
288 return r
288 return r
289
289
290 def copy(ui, repo, pats, opts, rename=False):
290 def copy(ui, repo, pats, opts, rename=False):
291 # called with the repo lock held
291 # called with the repo lock held
292 #
292 #
293 # hgsep => pathname that uses "/" to separate directories
293 # hgsep => pathname that uses "/" to separate directories
294 # ossep => pathname that uses os.sep to separate directories
294 # ossep => pathname that uses os.sep to separate directories
295 cwd = repo.getcwd()
295 cwd = repo.getcwd()
296 targets = {}
296 targets = {}
297 after = opts.get("after")
297 after = opts.get("after")
298 dryrun = opts.get("dry_run")
298 dryrun = opts.get("dry_run")
299 wctx = repo[None]
299 wctx = repo[None]
300
300
301 def walkpat(pat):
301 def walkpat(pat):
302 srcs = []
302 srcs = []
303 badstates = after and '?' or '?r'
303 badstates = after and '?' or '?r'
304 m = scmutil.match(repo[None], [pat], opts, globbed=True)
304 m = scmutil.match(repo[None], [pat], opts, globbed=True)
305 for abs in repo.walk(m):
305 for abs in repo.walk(m):
306 state = repo.dirstate[abs]
306 state = repo.dirstate[abs]
307 rel = m.rel(abs)
307 rel = m.rel(abs)
308 exact = m.exact(abs)
308 exact = m.exact(abs)
309 if state in badstates:
309 if state in badstates:
310 if exact and state == '?':
310 if exact and state == '?':
311 ui.warn(_('%s: not copying - file is not managed\n') % rel)
311 ui.warn(_('%s: not copying - file is not managed\n') % rel)
312 if exact and state == 'r':
312 if exact and state == 'r':
313 ui.warn(_('%s: not copying - file has been marked for'
313 ui.warn(_('%s: not copying - file has been marked for'
314 ' remove\n') % rel)
314 ' remove\n') % rel)
315 continue
315 continue
316 # abs: hgsep
316 # abs: hgsep
317 # rel: ossep
317 # rel: ossep
318 srcs.append((abs, rel, exact))
318 srcs.append((abs, rel, exact))
319 return srcs
319 return srcs
320
320
321 # abssrc: hgsep
321 # abssrc: hgsep
322 # relsrc: ossep
322 # relsrc: ossep
323 # otarget: ossep
323 # otarget: ossep
324 def copyfile(abssrc, relsrc, otarget, exact):
324 def copyfile(abssrc, relsrc, otarget, exact):
325 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
325 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
326 if '/' in abstarget:
326 if '/' in abstarget:
327 # We cannot normalize abstarget itself, this would prevent
327 # We cannot normalize abstarget itself, this would prevent
328 # case only renames, like a => A.
328 # case only renames, like a => A.
329 abspath, absname = abstarget.rsplit('/', 1)
329 abspath, absname = abstarget.rsplit('/', 1)
330 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
330 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
331 reltarget = repo.pathto(abstarget, cwd)
331 reltarget = repo.pathto(abstarget, cwd)
332 target = repo.wjoin(abstarget)
332 target = repo.wjoin(abstarget)
333 src = repo.wjoin(abssrc)
333 src = repo.wjoin(abssrc)
334 state = repo.dirstate[abstarget]
334 state = repo.dirstate[abstarget]
335
335
336 scmutil.checkportable(ui, abstarget)
336 scmutil.checkportable(ui, abstarget)
337
337
338 # check for collisions
338 # check for collisions
339 prevsrc = targets.get(abstarget)
339 prevsrc = targets.get(abstarget)
340 if prevsrc is not None:
340 if prevsrc is not None:
341 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
341 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
342 (reltarget, repo.pathto(abssrc, cwd),
342 (reltarget, repo.pathto(abssrc, cwd),
343 repo.pathto(prevsrc, cwd)))
343 repo.pathto(prevsrc, cwd)))
344 return
344 return
345
345
346 # check for overwrites
346 # check for overwrites
347 exists = os.path.lexists(target)
347 exists = os.path.lexists(target)
348 samefile = False
348 samefile = False
349 if exists and abssrc != abstarget:
349 if exists and abssrc != abstarget:
350 if (repo.dirstate.normalize(abssrc) ==
350 if (repo.dirstate.normalize(abssrc) ==
351 repo.dirstate.normalize(abstarget)):
351 repo.dirstate.normalize(abstarget)):
352 if not rename:
352 if not rename:
353 ui.warn(_("%s: can't copy - same file\n") % reltarget)
353 ui.warn(_("%s: can't copy - same file\n") % reltarget)
354 return
354 return
355 exists = False
355 exists = False
356 samefile = True
356 samefile = True
357
357
358 if not after and exists or after and state in 'mn':
358 if not after and exists or after and state in 'mn':
359 if not opts['force']:
359 if not opts['force']:
360 ui.warn(_('%s: not overwriting - file exists\n') %
360 ui.warn(_('%s: not overwriting - file exists\n') %
361 reltarget)
361 reltarget)
362 return
362 return
363
363
364 if after:
364 if after:
365 if not exists:
365 if not exists:
366 if rename:
366 if rename:
367 ui.warn(_('%s: not recording move - %s does not exist\n') %
367 ui.warn(_('%s: not recording move - %s does not exist\n') %
368 (relsrc, reltarget))
368 (relsrc, reltarget))
369 else:
369 else:
370 ui.warn(_('%s: not recording copy - %s does not exist\n') %
370 ui.warn(_('%s: not recording copy - %s does not exist\n') %
371 (relsrc, reltarget))
371 (relsrc, reltarget))
372 return
372 return
373 elif not dryrun:
373 elif not dryrun:
374 try:
374 try:
375 if exists:
375 if exists:
376 os.unlink(target)
376 os.unlink(target)
377 targetdir = os.path.dirname(target) or '.'
377 targetdir = os.path.dirname(target) or '.'
378 if not os.path.isdir(targetdir):
378 if not os.path.isdir(targetdir):
379 os.makedirs(targetdir)
379 os.makedirs(targetdir)
380 if samefile:
380 if samefile:
381 tmp = target + "~hgrename"
381 tmp = target + "~hgrename"
382 os.rename(src, tmp)
382 os.rename(src, tmp)
383 os.rename(tmp, target)
383 os.rename(tmp, target)
384 else:
384 else:
385 util.copyfile(src, target)
385 util.copyfile(src, target)
386 srcexists = True
386 srcexists = True
387 except IOError, inst:
387 except IOError, inst:
388 if inst.errno == errno.ENOENT:
388 if inst.errno == errno.ENOENT:
389 ui.warn(_('%s: deleted in working copy\n') % relsrc)
389 ui.warn(_('%s: deleted in working copy\n') % relsrc)
390 srcexists = False
390 srcexists = False
391 else:
391 else:
392 ui.warn(_('%s: cannot copy - %s\n') %
392 ui.warn(_('%s: cannot copy - %s\n') %
393 (relsrc, inst.strerror))
393 (relsrc, inst.strerror))
394 return True # report a failure
394 return True # report a failure
395
395
396 if ui.verbose or not exact:
396 if ui.verbose or not exact:
397 if rename:
397 if rename:
398 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
398 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
399 else:
399 else:
400 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
400 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
401
401
402 targets[abstarget] = abssrc
402 targets[abstarget] = abssrc
403
403
404 # fix up dirstate
404 # fix up dirstate
405 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
405 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
406 dryrun=dryrun, cwd=cwd)
406 dryrun=dryrun, cwd=cwd)
407 if rename and not dryrun:
407 if rename and not dryrun:
408 if not after and srcexists and not samefile:
408 if not after and srcexists and not samefile:
409 util.unlinkpath(repo.wjoin(abssrc))
409 util.unlinkpath(repo.wjoin(abssrc))
410 wctx.forget([abssrc])
410 wctx.forget([abssrc])
411
411
412 # pat: ossep
412 # pat: ossep
413 # dest ossep
413 # dest ossep
414 # srcs: list of (hgsep, hgsep, ossep, bool)
414 # srcs: list of (hgsep, hgsep, ossep, bool)
415 # return: function that takes hgsep and returns ossep
415 # return: function that takes hgsep and returns ossep
416 def targetpathfn(pat, dest, srcs):
416 def targetpathfn(pat, dest, srcs):
417 if os.path.isdir(pat):
417 if os.path.isdir(pat):
418 abspfx = pathutil.canonpath(repo.root, cwd, pat)
418 abspfx = pathutil.canonpath(repo.root, cwd, pat)
419 abspfx = util.localpath(abspfx)
419 abspfx = util.localpath(abspfx)
420 if destdirexists:
420 if destdirexists:
421 striplen = len(os.path.split(abspfx)[0])
421 striplen = len(os.path.split(abspfx)[0])
422 else:
422 else:
423 striplen = len(abspfx)
423 striplen = len(abspfx)
424 if striplen:
424 if striplen:
425 striplen += len(os.sep)
425 striplen += len(os.sep)
426 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
426 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
427 elif destdirexists:
427 elif destdirexists:
428 res = lambda p: os.path.join(dest,
428 res = lambda p: os.path.join(dest,
429 os.path.basename(util.localpath(p)))
429 os.path.basename(util.localpath(p)))
430 else:
430 else:
431 res = lambda p: dest
431 res = lambda p: dest
432 return res
432 return res
433
433
434 # pat: ossep
434 # pat: ossep
435 # dest ossep
435 # dest ossep
436 # srcs: list of (hgsep, hgsep, ossep, bool)
436 # srcs: list of (hgsep, hgsep, ossep, bool)
437 # return: function that takes hgsep and returns ossep
437 # return: function that takes hgsep and returns ossep
438 def targetpathafterfn(pat, dest, srcs):
438 def targetpathafterfn(pat, dest, srcs):
439 if matchmod.patkind(pat):
439 if matchmod.patkind(pat):
440 # a mercurial pattern
440 # a mercurial pattern
441 res = lambda p: os.path.join(dest,
441 res = lambda p: os.path.join(dest,
442 os.path.basename(util.localpath(p)))
442 os.path.basename(util.localpath(p)))
443 else:
443 else:
444 abspfx = pathutil.canonpath(repo.root, cwd, pat)
444 abspfx = pathutil.canonpath(repo.root, cwd, pat)
445 if len(abspfx) < len(srcs[0][0]):
445 if len(abspfx) < len(srcs[0][0]):
446 # A directory. Either the target path contains the last
446 # A directory. Either the target path contains the last
447 # component of the source path or it does not.
447 # component of the source path or it does not.
448 def evalpath(striplen):
448 def evalpath(striplen):
449 score = 0
449 score = 0
450 for s in srcs:
450 for s in srcs:
451 t = os.path.join(dest, util.localpath(s[0])[striplen:])
451 t = os.path.join(dest, util.localpath(s[0])[striplen:])
452 if os.path.lexists(t):
452 if os.path.lexists(t):
453 score += 1
453 score += 1
454 return score
454 return score
455
455
456 abspfx = util.localpath(abspfx)
456 abspfx = util.localpath(abspfx)
457 striplen = len(abspfx)
457 striplen = len(abspfx)
458 if striplen:
458 if striplen:
459 striplen += len(os.sep)
459 striplen += len(os.sep)
460 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
460 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
461 score = evalpath(striplen)
461 score = evalpath(striplen)
462 striplen1 = len(os.path.split(abspfx)[0])
462 striplen1 = len(os.path.split(abspfx)[0])
463 if striplen1:
463 if striplen1:
464 striplen1 += len(os.sep)
464 striplen1 += len(os.sep)
465 if evalpath(striplen1) > score:
465 if evalpath(striplen1) > score:
466 striplen = striplen1
466 striplen = striplen1
467 res = lambda p: os.path.join(dest,
467 res = lambda p: os.path.join(dest,
468 util.localpath(p)[striplen:])
468 util.localpath(p)[striplen:])
469 else:
469 else:
470 # a file
470 # a file
471 if destdirexists:
471 if destdirexists:
472 res = lambda p: os.path.join(dest,
472 res = lambda p: os.path.join(dest,
473 os.path.basename(util.localpath(p)))
473 os.path.basename(util.localpath(p)))
474 else:
474 else:
475 res = lambda p: dest
475 res = lambda p: dest
476 return res
476 return res
477
477
478
478
479 pats = scmutil.expandpats(pats)
479 pats = scmutil.expandpats(pats)
480 if not pats:
480 if not pats:
481 raise util.Abort(_('no source or destination specified'))
481 raise util.Abort(_('no source or destination specified'))
482 if len(pats) == 1:
482 if len(pats) == 1:
483 raise util.Abort(_('no destination specified'))
483 raise util.Abort(_('no destination specified'))
484 dest = pats.pop()
484 dest = pats.pop()
485 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
485 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
486 if not destdirexists:
486 if not destdirexists:
487 if len(pats) > 1 or matchmod.patkind(pats[0]):
487 if len(pats) > 1 or matchmod.patkind(pats[0]):
488 raise util.Abort(_('with multiple sources, destination must be an '
488 raise util.Abort(_('with multiple sources, destination must be an '
489 'existing directory'))
489 'existing directory'))
490 if util.endswithsep(dest):
490 if util.endswithsep(dest):
491 raise util.Abort(_('destination %s is not a directory') % dest)
491 raise util.Abort(_('destination %s is not a directory') % dest)
492
492
493 tfn = targetpathfn
493 tfn = targetpathfn
494 if after:
494 if after:
495 tfn = targetpathafterfn
495 tfn = targetpathafterfn
496 copylist = []
496 copylist = []
497 for pat in pats:
497 for pat in pats:
498 srcs = walkpat(pat)
498 srcs = walkpat(pat)
499 if not srcs:
499 if not srcs:
500 continue
500 continue
501 copylist.append((tfn(pat, dest, srcs), srcs))
501 copylist.append((tfn(pat, dest, srcs), srcs))
502 if not copylist:
502 if not copylist:
503 raise util.Abort(_('no files to copy'))
503 raise util.Abort(_('no files to copy'))
504
504
505 errors = 0
505 errors = 0
506 for targetpath, srcs in copylist:
506 for targetpath, srcs in copylist:
507 for abssrc, relsrc, exact in srcs:
507 for abssrc, relsrc, exact in srcs:
508 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
508 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
509 errors += 1
509 errors += 1
510
510
511 if errors:
511 if errors:
512 ui.warn(_('(consider using --after)\n'))
512 ui.warn(_('(consider using --after)\n'))
513
513
514 return errors != 0
514 return errors != 0
515
515
516 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
516 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
517 runargs=None, appendpid=False):
517 runargs=None, appendpid=False):
518 '''Run a command as a service.'''
518 '''Run a command as a service.'''
519
519
520 def writepid(pid):
520 def writepid(pid):
521 if opts['pid_file']:
521 if opts['pid_file']:
522 mode = appendpid and 'a' or 'w'
522 mode = appendpid and 'a' or 'w'
523 fp = open(opts['pid_file'], mode)
523 fp = open(opts['pid_file'], mode)
524 fp.write(str(pid) + '\n')
524 fp.write(str(pid) + '\n')
525 fp.close()
525 fp.close()
526
526
527 if opts['daemon'] and not opts['daemon_pipefds']:
527 if opts['daemon'] and not opts['daemon_pipefds']:
528 # Signal child process startup with file removal
528 # Signal child process startup with file removal
529 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
529 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
530 os.close(lockfd)
530 os.close(lockfd)
531 try:
531 try:
532 if not runargs:
532 if not runargs:
533 runargs = util.hgcmd() + sys.argv[1:]
533 runargs = util.hgcmd() + sys.argv[1:]
534 runargs.append('--daemon-pipefds=%s' % lockpath)
534 runargs.append('--daemon-pipefds=%s' % lockpath)
535 # Don't pass --cwd to the child process, because we've already
535 # Don't pass --cwd to the child process, because we've already
536 # changed directory.
536 # changed directory.
537 for i in xrange(1, len(runargs)):
537 for i in xrange(1, len(runargs)):
538 if runargs[i].startswith('--cwd='):
538 if runargs[i].startswith('--cwd='):
539 del runargs[i]
539 del runargs[i]
540 break
540 break
541 elif runargs[i].startswith('--cwd'):
541 elif runargs[i].startswith('--cwd'):
542 del runargs[i:i + 2]
542 del runargs[i:i + 2]
543 break
543 break
544 def condfn():
544 def condfn():
545 return not os.path.exists(lockpath)
545 return not os.path.exists(lockpath)
546 pid = util.rundetached(runargs, condfn)
546 pid = util.rundetached(runargs, condfn)
547 if pid < 0:
547 if pid < 0:
548 raise util.Abort(_('child process failed to start'))
548 raise util.Abort(_('child process failed to start'))
549 writepid(pid)
549 writepid(pid)
550 finally:
550 finally:
551 try:
551 try:
552 os.unlink(lockpath)
552 os.unlink(lockpath)
553 except OSError, e:
553 except OSError, e:
554 if e.errno != errno.ENOENT:
554 if e.errno != errno.ENOENT:
555 raise
555 raise
556 if parentfn:
556 if parentfn:
557 return parentfn(pid)
557 return parentfn(pid)
558 else:
558 else:
559 return
559 return
560
560
561 if initfn:
561 if initfn:
562 initfn()
562 initfn()
563
563
564 if not opts['daemon']:
564 if not opts['daemon']:
565 writepid(os.getpid())
565 writepid(os.getpid())
566
566
567 if opts['daemon_pipefds']:
567 if opts['daemon_pipefds']:
568 lockpath = opts['daemon_pipefds']
568 lockpath = opts['daemon_pipefds']
569 try:
569 try:
570 os.setsid()
570 os.setsid()
571 except AttributeError:
571 except AttributeError:
572 pass
572 pass
573 os.unlink(lockpath)
573 os.unlink(lockpath)
574 util.hidewindow()
574 util.hidewindow()
575 sys.stdout.flush()
575 sys.stdout.flush()
576 sys.stderr.flush()
576 sys.stderr.flush()
577
577
578 nullfd = os.open(os.devnull, os.O_RDWR)
578 nullfd = os.open(os.devnull, os.O_RDWR)
579 logfilefd = nullfd
579 logfilefd = nullfd
580 if logfile:
580 if logfile:
581 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
581 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
582 os.dup2(nullfd, 0)
582 os.dup2(nullfd, 0)
583 os.dup2(logfilefd, 1)
583 os.dup2(logfilefd, 1)
584 os.dup2(logfilefd, 2)
584 os.dup2(logfilefd, 2)
585 if nullfd not in (0, 1, 2):
585 if nullfd not in (0, 1, 2):
586 os.close(nullfd)
586 os.close(nullfd)
587 if logfile and logfilefd not in (0, 1, 2):
587 if logfile and logfilefd not in (0, 1, 2):
588 os.close(logfilefd)
588 os.close(logfilefd)
589
589
590 if runfn:
590 if runfn:
591 return runfn()
591 return runfn()
592
592
593 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
593 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
594 """Utility function used by commands.import to import a single patch
594 """Utility function used by commands.import to import a single patch
595
595
596 This function is explicitly defined here to help the evolve extension to
596 This function is explicitly defined here to help the evolve extension to
597 wrap this part of the import logic.
597 wrap this part of the import logic.
598
598
599 The API is currently a bit ugly because it a simple code translation from
599 The API is currently a bit ugly because it a simple code translation from
600 the import command. Feel free to make it better.
600 the import command. Feel free to make it better.
601
601
602 :hunk: a patch (as a binary string)
602 :hunk: a patch (as a binary string)
603 :parents: nodes that will be parent of the created commit
603 :parents: nodes that will be parent of the created commit
604 :opts: the full dict of option passed to the import command
604 :opts: the full dict of option passed to the import command
605 :msgs: list to save commit message to.
605 :msgs: list to save commit message to.
606 (used in case we need to save it when failing)
606 (used in case we need to save it when failing)
607 :updatefunc: a function that update a repo to a given node
607 :updatefunc: a function that update a repo to a given node
608 updatefunc(<repo>, <node>)
608 updatefunc(<repo>, <node>)
609 """
609 """
610 tmpname, message, user, date, branch, nodeid, p1, p2 = \
610 tmpname, message, user, date, branch, nodeid, p1, p2 = \
611 patch.extract(ui, hunk)
611 patch.extract(ui, hunk)
612
612
613 editor = getcommiteditor(editform='import.normal', **opts)
613 editor = getcommiteditor(editform='import.normal', **opts)
614 update = not opts.get('bypass')
614 update = not opts.get('bypass')
615 strip = opts["strip"]
615 strip = opts["strip"]
616 sim = float(opts.get('similarity') or 0)
616 sim = float(opts.get('similarity') or 0)
617 if not tmpname:
617 if not tmpname:
618 return (None, None, False)
618 return (None, None, False)
619 msg = _('applied to working directory')
619 msg = _('applied to working directory')
620
620
621 rejects = False
621 rejects = False
622
622
623 try:
623 try:
624 cmdline_message = logmessage(ui, opts)
624 cmdline_message = logmessage(ui, opts)
625 if cmdline_message:
625 if cmdline_message:
626 # pickup the cmdline msg
626 # pickup the cmdline msg
627 message = cmdline_message
627 message = cmdline_message
628 elif message:
628 elif message:
629 # pickup the patch msg
629 # pickup the patch msg
630 message = message.strip()
630 message = message.strip()
631 else:
631 else:
632 # launch the editor
632 # launch the editor
633 message = None
633 message = None
634 ui.debug('message:\n%s\n' % message)
634 ui.debug('message:\n%s\n' % message)
635
635
636 if len(parents) == 1:
636 if len(parents) == 1:
637 parents.append(repo[nullid])
637 parents.append(repo[nullid])
638 if opts.get('exact'):
638 if opts.get('exact'):
639 if not nodeid or not p1:
639 if not nodeid or not p1:
640 raise util.Abort(_('not a Mercurial patch'))
640 raise util.Abort(_('not a Mercurial patch'))
641 p1 = repo[p1]
641 p1 = repo[p1]
642 p2 = repo[p2 or nullid]
642 p2 = repo[p2 or nullid]
643 elif p2:
643 elif p2:
644 try:
644 try:
645 p1 = repo[p1]
645 p1 = repo[p1]
646 p2 = repo[p2]
646 p2 = repo[p2]
647 # Without any options, consider p2 only if the
647 # Without any options, consider p2 only if the
648 # patch is being applied on top of the recorded
648 # patch is being applied on top of the recorded
649 # first parent.
649 # first parent.
650 if p1 != parents[0]:
650 if p1 != parents[0]:
651 p1 = parents[0]
651 p1 = parents[0]
652 p2 = repo[nullid]
652 p2 = repo[nullid]
653 except error.RepoError:
653 except error.RepoError:
654 p1, p2 = parents
654 p1, p2 = parents
655 else:
655 else:
656 p1, p2 = parents
656 p1, p2 = parents
657
657
658 n = None
658 n = None
659 if update:
659 if update:
660 if p1 != parents[0]:
660 if p1 != parents[0]:
661 updatefunc(repo, p1.node())
661 updatefunc(repo, p1.node())
662 if p2 != parents[1]:
662 if p2 != parents[1]:
663 repo.setparents(p1.node(), p2.node())
663 repo.setparents(p1.node(), p2.node())
664
664
665 if opts.get('exact') or opts.get('import_branch'):
665 if opts.get('exact') or opts.get('import_branch'):
666 repo.dirstate.setbranch(branch or 'default')
666 repo.dirstate.setbranch(branch or 'default')
667
667
668 partial = opts.get('partial', False)
668 partial = opts.get('partial', False)
669 files = set()
669 files = set()
670 try:
670 try:
671 patch.patch(ui, repo, tmpname, strip=strip, files=files,
671 patch.patch(ui, repo, tmpname, strip=strip, files=files,
672 eolmode=None, similarity=sim / 100.0)
672 eolmode=None, similarity=sim / 100.0)
673 except patch.PatchError, e:
673 except patch.PatchError, e:
674 if not partial:
674 if not partial:
675 raise util.Abort(str(e))
675 raise util.Abort(str(e))
676 if partial:
676 if partial:
677 rejects = True
677 rejects = True
678
678
679 files = list(files)
679 files = list(files)
680 if opts.get('no_commit'):
680 if opts.get('no_commit'):
681 if message:
681 if message:
682 msgs.append(message)
682 msgs.append(message)
683 else:
683 else:
684 if opts.get('exact') or p2:
684 if opts.get('exact') or p2:
685 # If you got here, you either use --force and know what
685 # If you got here, you either use --force and know what
686 # you are doing or used --exact or a merge patch while
686 # you are doing or used --exact or a merge patch while
687 # being updated to its first parent.
687 # being updated to its first parent.
688 m = None
688 m = None
689 else:
689 else:
690 m = scmutil.matchfiles(repo, files or [])
690 m = scmutil.matchfiles(repo, files or [])
691 n = repo.commit(message, opts.get('user') or user,
691 n = repo.commit(message, opts.get('user') or user,
692 opts.get('date') or date, match=m,
692 opts.get('date') or date, match=m,
693 editor=editor, force=partial)
693 editor=editor, force=partial)
694 else:
694 else:
695 if opts.get('exact') or opts.get('import_branch'):
695 if opts.get('exact') or opts.get('import_branch'):
696 branch = branch or 'default'
696 branch = branch or 'default'
697 else:
697 else:
698 branch = p1.branch()
698 branch = p1.branch()
699 store = patch.filestore()
699 store = patch.filestore()
700 try:
700 try:
701 files = set()
701 files = set()
702 try:
702 try:
703 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
703 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
704 files, eolmode=None)
704 files, eolmode=None)
705 except patch.PatchError, e:
705 except patch.PatchError, e:
706 raise util.Abort(str(e))
706 raise util.Abort(str(e))
707 editor = getcommiteditor(editform='import.bypass')
707 editor = getcommiteditor(editform='import.bypass')
708 memctx = context.makememctx(repo, (p1.node(), p2.node()),
708 memctx = context.makememctx(repo, (p1.node(), p2.node()),
709 message,
709 message,
710 opts.get('user') or user,
710 opts.get('user') or user,
711 opts.get('date') or date,
711 opts.get('date') or date,
712 branch, files, store,
712 branch, files, store,
713 editor=editor)
713 editor=editor)
714 n = memctx.commit()
714 n = memctx.commit()
715 finally:
715 finally:
716 store.close()
716 store.close()
717 if opts.get('exact') and hex(n) != nodeid:
717 if opts.get('exact') and hex(n) != nodeid:
718 raise util.Abort(_('patch is damaged or loses information'))
718 raise util.Abort(_('patch is damaged or loses information'))
719 if n:
719 if n:
720 # i18n: refers to a short changeset id
720 # i18n: refers to a short changeset id
721 msg = _('created %s') % short(n)
721 msg = _('created %s') % short(n)
722 return (msg, n, rejects)
722 return (msg, n, rejects)
723 finally:
723 finally:
724 os.unlink(tmpname)
724 os.unlink(tmpname)
725
725
726 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
726 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
727 opts=None):
727 opts=None):
728 '''export changesets as hg patches.'''
728 '''export changesets as hg patches.'''
729
729
730 total = len(revs)
730 total = len(revs)
731 revwidth = max([len(str(rev)) for rev in revs])
731 revwidth = max([len(str(rev)) for rev in revs])
732 filemode = {}
732 filemode = {}
733
733
734 def single(rev, seqno, fp):
734 def single(rev, seqno, fp):
735 ctx = repo[rev]
735 ctx = repo[rev]
736 node = ctx.node()
736 node = ctx.node()
737 parents = [p.node() for p in ctx.parents() if p]
737 parents = [p.node() for p in ctx.parents() if p]
738 branch = ctx.branch()
738 branch = ctx.branch()
739 if switch_parent:
739 if switch_parent:
740 parents.reverse()
740 parents.reverse()
741 prev = (parents and parents[0]) or nullid
741 prev = (parents and parents[0]) or nullid
742
742
743 shouldclose = False
743 shouldclose = False
744 if not fp and len(template) > 0:
744 if not fp and len(template) > 0:
745 desc_lines = ctx.description().rstrip().split('\n')
745 desc_lines = ctx.description().rstrip().split('\n')
746 desc = desc_lines[0] #Commit always has a first line.
746 desc = desc_lines[0] #Commit always has a first line.
747 fp = makefileobj(repo, template, node, desc=desc, total=total,
747 fp = makefileobj(repo, template, node, desc=desc, total=total,
748 seqno=seqno, revwidth=revwidth, mode='wb',
748 seqno=seqno, revwidth=revwidth, mode='wb',
749 modemap=filemode)
749 modemap=filemode)
750 if fp != template:
750 if fp != template:
751 shouldclose = True
751 shouldclose = True
752 if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
752 if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
753 repo.ui.note("%s\n" % fp.name)
753 repo.ui.note("%s\n" % fp.name)
754
754
755 if not fp:
755 if not fp:
756 write = repo.ui.write
756 write = repo.ui.write
757 else:
757 else:
758 def write(s, **kw):
758 def write(s, **kw):
759 fp.write(s)
759 fp.write(s)
760
760
761
761
762 write("# HG changeset patch\n")
762 write("# HG changeset patch\n")
763 write("# User %s\n" % ctx.user())
763 write("# User %s\n" % ctx.user())
764 write("# Date %d %d\n" % ctx.date())
764 write("# Date %d %d\n" % ctx.date())
765 write("# %s\n" % util.datestr(ctx.date()))
765 write("# %s\n" % util.datestr(ctx.date()))
766 if branch and branch != 'default':
766 if branch and branch != 'default':
767 write("# Branch %s\n" % branch)
767 write("# Branch %s\n" % branch)
768 write("# Node ID %s\n" % hex(node))
768 write("# Node ID %s\n" % hex(node))
769 write("# Parent %s\n" % hex(prev))
769 write("# Parent %s\n" % hex(prev))
770 if len(parents) > 1:
770 if len(parents) > 1:
771 write("# Parent %s\n" % hex(parents[1]))
771 write("# Parent %s\n" % hex(parents[1]))
772 write(ctx.description().rstrip())
772 write(ctx.description().rstrip())
773 write("\n\n")
773 write("\n\n")
774
774
775 for chunk, label in patch.diffui(repo, prev, node, opts=opts):
775 for chunk, label in patch.diffui(repo, prev, node, opts=opts):
776 write(chunk, label=label)
776 write(chunk, label=label)
777
777
778 if shouldclose:
778 if shouldclose:
779 fp.close()
779 fp.close()
780
780
781 for seqno, rev in enumerate(revs):
781 for seqno, rev in enumerate(revs):
782 single(rev, seqno + 1, fp)
782 single(rev, seqno + 1, fp)
783
783
784 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
784 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
785 changes=None, stat=False, fp=None, prefix='',
785 changes=None, stat=False, fp=None, prefix='',
786 listsubrepos=False):
786 listsubrepos=False):
787 '''show diff or diffstat.'''
787 '''show diff or diffstat.'''
788 if fp is None:
788 if fp is None:
789 write = ui.write
789 write = ui.write
790 else:
790 else:
791 def write(s, **kw):
791 def write(s, **kw):
792 fp.write(s)
792 fp.write(s)
793
793
794 if stat:
794 if stat:
795 diffopts = diffopts.copy(context=0)
795 diffopts = diffopts.copy(context=0)
796 width = 80
796 width = 80
797 if not ui.plain():
797 if not ui.plain():
798 width = ui.termwidth()
798 width = ui.termwidth()
799 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
799 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
800 prefix=prefix)
800 prefix=prefix)
801 for chunk, label in patch.diffstatui(util.iterlines(chunks),
801 for chunk, label in patch.diffstatui(util.iterlines(chunks),
802 width=width,
802 width=width,
803 git=diffopts.git):
803 git=diffopts.git):
804 write(chunk, label=label)
804 write(chunk, label=label)
805 else:
805 else:
806 for chunk, label in patch.diffui(repo, node1, node2, match,
806 for chunk, label in patch.diffui(repo, node1, node2, match,
807 changes, diffopts, prefix=prefix):
807 changes, diffopts, prefix=prefix):
808 write(chunk, label=label)
808 write(chunk, label=label)
809
809
810 if listsubrepos:
810 if listsubrepos:
811 ctx1 = repo[node1]
811 ctx1 = repo[node1]
812 ctx2 = repo[node2]
812 ctx2 = repo[node2]
813 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
813 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
814 tempnode2 = node2
814 tempnode2 = node2
815 try:
815 try:
816 if node2 is not None:
816 if node2 is not None:
817 tempnode2 = ctx2.substate[subpath][1]
817 tempnode2 = ctx2.substate[subpath][1]
818 except KeyError:
818 except KeyError:
819 # A subrepo that existed in node1 was deleted between node1 and
819 # A subrepo that existed in node1 was deleted between node1 and
820 # node2 (inclusive). Thus, ctx2's substate won't contain that
820 # node2 (inclusive). Thus, ctx2's substate won't contain that
821 # subpath. The best we can do is to ignore it.
821 # subpath. The best we can do is to ignore it.
822 tempnode2 = None
822 tempnode2 = None
823 submatch = matchmod.narrowmatcher(subpath, match)
823 submatch = matchmod.narrowmatcher(subpath, match)
824 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
824 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
825 stat=stat, fp=fp, prefix=prefix)
825 stat=stat, fp=fp, prefix=prefix)
826
826
827 class changeset_printer(object):
827 class changeset_printer(object):
828 '''show changeset information when templating not requested.'''
828 '''show changeset information when templating not requested.'''
829
829
830 def __init__(self, ui, repo, patch, diffopts, buffered):
830 def __init__(self, ui, repo, patch, diffopts, buffered):
831 self.ui = ui
831 self.ui = ui
832 self.repo = repo
832 self.repo = repo
833 self.buffered = buffered
833 self.buffered = buffered
834 self.patch = patch
834 self.patch = patch
835 self.diffopts = diffopts
835 self.diffopts = diffopts
836 self.header = {}
836 self.header = {}
837 self.hunk = {}
837 self.hunk = {}
838 self.lastheader = None
838 self.lastheader = None
839 self.footer = None
839 self.footer = None
840
840
841 def flush(self, rev):
841 def flush(self, rev):
842 if rev in self.header:
842 if rev in self.header:
843 h = self.header[rev]
843 h = self.header[rev]
844 if h != self.lastheader:
844 if h != self.lastheader:
845 self.lastheader = h
845 self.lastheader = h
846 self.ui.write(h)
846 self.ui.write(h)
847 del self.header[rev]
847 del self.header[rev]
848 if rev in self.hunk:
848 if rev in self.hunk:
849 self.ui.write(self.hunk[rev])
849 self.ui.write(self.hunk[rev])
850 del self.hunk[rev]
850 del self.hunk[rev]
851 return 1
851 return 1
852 return 0
852 return 0
853
853
854 def close(self):
854 def close(self):
855 if self.footer:
855 if self.footer:
856 self.ui.write(self.footer)
856 self.ui.write(self.footer)
857
857
858 def show(self, ctx, copies=None, matchfn=None, **props):
858 def show(self, ctx, copies=None, matchfn=None, **props):
859 if self.buffered:
859 if self.buffered:
860 self.ui.pushbuffer()
860 self.ui.pushbuffer()
861 self._show(ctx, copies, matchfn, props)
861 self._show(ctx, copies, matchfn, props)
862 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
862 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
863 else:
863 else:
864 self._show(ctx, copies, matchfn, props)
864 self._show(ctx, copies, matchfn, props)
865
865
866 def _show(self, ctx, copies, matchfn, props):
866 def _show(self, ctx, copies, matchfn, props):
867 '''show a single changeset or file revision'''
867 '''show a single changeset or file revision'''
868 changenode = ctx.node()
868 changenode = ctx.node()
869 rev = ctx.rev()
869 rev = ctx.rev()
870
870
871 if self.ui.quiet:
871 if self.ui.quiet:
872 self.ui.write("%d:%s\n" % (rev, short(changenode)),
872 self.ui.write("%d:%s\n" % (rev, short(changenode)),
873 label='log.node')
873 label='log.node')
874 return
874 return
875
875
876 log = self.repo.changelog
876 log = self.repo.changelog
877 date = util.datestr(ctx.date())
877 date = util.datestr(ctx.date())
878
878
879 hexfunc = self.ui.debugflag and hex or short
879 hexfunc = self.ui.debugflag and hex or short
880
880
881 parents = [(p, hexfunc(log.node(p)))
881 parents = [(p, hexfunc(log.node(p)))
882 for p in self._meaningful_parentrevs(log, rev)]
882 for p in self._meaningful_parentrevs(log, rev)]
883
883
884 # i18n: column positioning for "hg log"
884 # i18n: column positioning for "hg log"
885 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
885 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
886 label='log.changeset changeset.%s' % ctx.phasestr())
886 label='log.changeset changeset.%s' % ctx.phasestr())
887
887
888 branch = ctx.branch()
888 branch = ctx.branch()
889 # don't show the default branch name
889 # don't show the default branch name
890 if branch != 'default':
890 if branch != 'default':
891 # i18n: column positioning for "hg log"
891 # i18n: column positioning for "hg log"
892 self.ui.write(_("branch: %s\n") % branch,
892 self.ui.write(_("branch: %s\n") % branch,
893 label='log.branch')
893 label='log.branch')
894 for bookmark in self.repo.nodebookmarks(changenode):
894 for bookmark in self.repo.nodebookmarks(changenode):
895 # i18n: column positioning for "hg log"
895 # i18n: column positioning for "hg log"
896 self.ui.write(_("bookmark: %s\n") % bookmark,
896 self.ui.write(_("bookmark: %s\n") % bookmark,
897 label='log.bookmark')
897 label='log.bookmark')
898 for tag in self.repo.nodetags(changenode):
898 for tag in self.repo.nodetags(changenode):
899 # i18n: column positioning for "hg log"
899 # i18n: column positioning for "hg log"
900 self.ui.write(_("tag: %s\n") % tag,
900 self.ui.write(_("tag: %s\n") % tag,
901 label='log.tag')
901 label='log.tag')
902 if self.ui.debugflag and ctx.phase():
902 if self.ui.debugflag and ctx.phase():
903 # i18n: column positioning for "hg log"
903 # i18n: column positioning for "hg log"
904 self.ui.write(_("phase: %s\n") % _(ctx.phasestr()),
904 self.ui.write(_("phase: %s\n") % _(ctx.phasestr()),
905 label='log.phase')
905 label='log.phase')
906 for parent in parents:
906 for parent in parents:
907 # i18n: column positioning for "hg log"
907 # i18n: column positioning for "hg log"
908 self.ui.write(_("parent: %d:%s\n") % parent,
908 self.ui.write(_("parent: %d:%s\n") % parent,
909 label='log.parent changeset.%s' % ctx.phasestr())
909 label='log.parent changeset.%s' % ctx.phasestr())
910
910
911 if self.ui.debugflag:
911 if self.ui.debugflag:
912 mnode = ctx.manifestnode()
912 mnode = ctx.manifestnode()
913 # i18n: column positioning for "hg log"
913 # i18n: column positioning for "hg log"
914 self.ui.write(_("manifest: %d:%s\n") %
914 self.ui.write(_("manifest: %d:%s\n") %
915 (self.repo.manifest.rev(mnode), hex(mnode)),
915 (self.repo.manifest.rev(mnode), hex(mnode)),
916 label='ui.debug log.manifest')
916 label='ui.debug log.manifest')
917 # i18n: column positioning for "hg log"
917 # i18n: column positioning for "hg log"
918 self.ui.write(_("user: %s\n") % ctx.user(),
918 self.ui.write(_("user: %s\n") % ctx.user(),
919 label='log.user')
919 label='log.user')
920 # i18n: column positioning for "hg log"
920 # i18n: column positioning for "hg log"
921 self.ui.write(_("date: %s\n") % date,
921 self.ui.write(_("date: %s\n") % date,
922 label='log.date')
922 label='log.date')
923
923
924 if self.ui.debugflag:
924 if self.ui.debugflag:
925 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
925 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
926 for key, value in zip([# i18n: column positioning for "hg log"
926 for key, value in zip([# i18n: column positioning for "hg log"
927 _("files:"),
927 _("files:"),
928 # i18n: column positioning for "hg log"
928 # i18n: column positioning for "hg log"
929 _("files+:"),
929 _("files+:"),
930 # i18n: column positioning for "hg log"
930 # i18n: column positioning for "hg log"
931 _("files-:")], files):
931 _("files-:")], files):
932 if value:
932 if value:
933 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
933 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
934 label='ui.debug log.files')
934 label='ui.debug log.files')
935 elif ctx.files() and self.ui.verbose:
935 elif ctx.files() and self.ui.verbose:
936 # i18n: column positioning for "hg log"
936 # i18n: column positioning for "hg log"
937 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
937 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
938 label='ui.note log.files')
938 label='ui.note log.files')
939 if copies and self.ui.verbose:
939 if copies and self.ui.verbose:
940 copies = ['%s (%s)' % c for c in copies]
940 copies = ['%s (%s)' % c for c in copies]
941 # i18n: column positioning for "hg log"
941 # i18n: column positioning for "hg log"
942 self.ui.write(_("copies: %s\n") % ' '.join(copies),
942 self.ui.write(_("copies: %s\n") % ' '.join(copies),
943 label='ui.note log.copies')
943 label='ui.note log.copies')
944
944
945 extra = ctx.extra()
945 extra = ctx.extra()
946 if extra and self.ui.debugflag:
946 if extra and self.ui.debugflag:
947 for key, value in sorted(extra.items()):
947 for key, value in sorted(extra.items()):
948 # i18n: column positioning for "hg log"
948 # i18n: column positioning for "hg log"
949 self.ui.write(_("extra: %s=%s\n")
949 self.ui.write(_("extra: %s=%s\n")
950 % (key, value.encode('string_escape')),
950 % (key, value.encode('string_escape')),
951 label='ui.debug log.extra')
951 label='ui.debug log.extra')
952
952
953 description = ctx.description().strip()
953 description = ctx.description().strip()
954 if description:
954 if description:
955 if self.ui.verbose:
955 if self.ui.verbose:
956 self.ui.write(_("description:\n"),
956 self.ui.write(_("description:\n"),
957 label='ui.note log.description')
957 label='ui.note log.description')
958 self.ui.write(description,
958 self.ui.write(description,
959 label='ui.note log.description')
959 label='ui.note log.description')
960 self.ui.write("\n\n")
960 self.ui.write("\n\n")
961 else:
961 else:
962 # i18n: column positioning for "hg log"
962 # i18n: column positioning for "hg log"
963 self.ui.write(_("summary: %s\n") %
963 self.ui.write(_("summary: %s\n") %
964 description.splitlines()[0],
964 description.splitlines()[0],
965 label='log.summary')
965 label='log.summary')
966 self.ui.write("\n")
966 self.ui.write("\n")
967
967
968 self.showpatch(changenode, matchfn)
968 self.showpatch(changenode, matchfn)
969
969
970 def showpatch(self, node, matchfn):
970 def showpatch(self, node, matchfn):
971 if not matchfn:
971 if not matchfn:
972 matchfn = self.patch
972 matchfn = self.patch
973 if matchfn:
973 if matchfn:
974 stat = self.diffopts.get('stat')
974 stat = self.diffopts.get('stat')
975 diff = self.diffopts.get('patch')
975 diff = self.diffopts.get('patch')
976 diffopts = patch.diffopts(self.ui, self.diffopts)
976 diffopts = patch.diffopts(self.ui, self.diffopts)
977 prev = self.repo.changelog.parents(node)[0]
977 prev = self.repo.changelog.parents(node)[0]
978 if stat:
978 if stat:
979 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
979 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
980 match=matchfn, stat=True)
980 match=matchfn, stat=True)
981 if diff:
981 if diff:
982 if stat:
982 if stat:
983 self.ui.write("\n")
983 self.ui.write("\n")
984 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
984 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
985 match=matchfn, stat=False)
985 match=matchfn, stat=False)
986 self.ui.write("\n")
986 self.ui.write("\n")
987
987
988 def _meaningful_parentrevs(self, log, rev):
988 def _meaningful_parentrevs(self, log, rev):
989 """Return list of meaningful (or all if debug) parentrevs for rev.
989 """Return list of meaningful (or all if debug) parentrevs for rev.
990
990
991 For merges (two non-nullrev revisions) both parents are meaningful.
991 For merges (two non-nullrev revisions) both parents are meaningful.
992 Otherwise the first parent revision is considered meaningful if it
992 Otherwise the first parent revision is considered meaningful if it
993 is not the preceding revision.
993 is not the preceding revision.
994 """
994 """
995 parents = log.parentrevs(rev)
995 parents = log.parentrevs(rev)
996 if not self.ui.debugflag and parents[1] == nullrev:
996 if not self.ui.debugflag and parents[1] == nullrev:
997 if parents[0] >= rev - 1:
997 if parents[0] >= rev - 1:
998 parents = []
998 parents = []
999 else:
999 else:
1000 parents = [parents[0]]
1000 parents = [parents[0]]
1001 return parents
1001 return parents
1002
1002
1003
1003
1004 class changeset_templater(changeset_printer):
1004 class changeset_templater(changeset_printer):
1005 '''format changeset information.'''
1005 '''format changeset information.'''
1006
1006
1007 def __init__(self, ui, repo, patch, diffopts, tmpl, mapfile, buffered):
1007 def __init__(self, ui, repo, patch, diffopts, tmpl, mapfile, buffered):
1008 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
1008 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
1009 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
1009 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
1010 defaulttempl = {
1010 defaulttempl = {
1011 'parent': '{rev}:{node|formatnode} ',
1011 'parent': '{rev}:{node|formatnode} ',
1012 'manifest': '{rev}:{node|formatnode}',
1012 'manifest': '{rev}:{node|formatnode}',
1013 'file_copy': '{name} ({source})',
1013 'file_copy': '{name} ({source})',
1014 'extra': '{key}={value|stringescape}'
1014 'extra': '{key}={value|stringescape}'
1015 }
1015 }
1016 # filecopy is preserved for compatibility reasons
1016 # filecopy is preserved for compatibility reasons
1017 defaulttempl['filecopy'] = defaulttempl['file_copy']
1017 defaulttempl['filecopy'] = defaulttempl['file_copy']
1018 self.t = templater.templater(mapfile, {'formatnode': formatnode},
1018 self.t = templater.templater(mapfile, {'formatnode': formatnode},
1019 cache=defaulttempl)
1019 cache=defaulttempl)
1020 if tmpl:
1020 if tmpl:
1021 self.t.cache['changeset'] = tmpl
1021 self.t.cache['changeset'] = tmpl
1022
1022
1023 self.cache = {}
1023 self.cache = {}
1024
1024
1025 def _meaningful_parentrevs(self, ctx):
1025 def _meaningful_parentrevs(self, ctx):
1026 """Return list of meaningful (or all if debug) parentrevs for rev.
1026 """Return list of meaningful (or all if debug) parentrevs for rev.
1027 """
1027 """
1028 parents = ctx.parents()
1028 parents = ctx.parents()
1029 if len(parents) > 1:
1029 if len(parents) > 1:
1030 return parents
1030 return parents
1031 if self.ui.debugflag:
1031 if self.ui.debugflag:
1032 return [parents[0], self.repo['null']]
1032 return [parents[0], self.repo['null']]
1033 if parents[0].rev() >= ctx.rev() - 1:
1033 if parents[0].rev() >= ctx.rev() - 1:
1034 return []
1034 return []
1035 return parents
1035 return parents
1036
1036
1037 def _show(self, ctx, copies, matchfn, props):
1037 def _show(self, ctx, copies, matchfn, props):
1038 '''show a single changeset or file revision'''
1038 '''show a single changeset or file revision'''
1039
1039
1040 showlist = templatekw.showlist
1040 showlist = templatekw.showlist
1041
1041
1042 # showparents() behaviour depends on ui trace level which
1042 # showparents() behaviour depends on ui trace level which
1043 # causes unexpected behaviours at templating level and makes
1043 # causes unexpected behaviours at templating level and makes
1044 # it harder to extract it in a standalone function. Its
1044 # it harder to extract it in a standalone function. Its
1045 # behaviour cannot be changed so leave it here for now.
1045 # behaviour cannot be changed so leave it here for now.
1046 def showparents(**args):
1046 def showparents(**args):
1047 ctx = args['ctx']
1047 ctx = args['ctx']
1048 parents = [[('rev', p.rev()), ('node', p.hex())]
1048 parents = [[('rev', p.rev()), ('node', p.hex())]
1049 for p in self._meaningful_parentrevs(ctx)]
1049 for p in self._meaningful_parentrevs(ctx)]
1050 return showlist('parent', parents, **args)
1050 return showlist('parent', parents, **args)
1051
1051
1052 props = props.copy()
1052 props = props.copy()
1053 props.update(templatekw.keywords)
1053 props.update(templatekw.keywords)
1054 props['parents'] = showparents
1054 props['parents'] = showparents
1055 props['templ'] = self.t
1055 props['templ'] = self.t
1056 props['ctx'] = ctx
1056 props['ctx'] = ctx
1057 props['repo'] = self.repo
1057 props['repo'] = self.repo
1058 props['revcache'] = {'copies': copies}
1058 props['revcache'] = {'copies': copies}
1059 props['cache'] = self.cache
1059 props['cache'] = self.cache
1060
1060
1061 # find correct templates for current mode
1061 # find correct templates for current mode
1062
1062
1063 tmplmodes = [
1063 tmplmodes = [
1064 (True, None),
1064 (True, None),
1065 (self.ui.verbose, 'verbose'),
1065 (self.ui.verbose, 'verbose'),
1066 (self.ui.quiet, 'quiet'),
1066 (self.ui.quiet, 'quiet'),
1067 (self.ui.debugflag, 'debug'),
1067 (self.ui.debugflag, 'debug'),
1068 ]
1068 ]
1069
1069
1070 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
1070 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
1071 for mode, postfix in tmplmodes:
1071 for mode, postfix in tmplmodes:
1072 for type in types:
1072 for type in types:
1073 cur = postfix and ('%s_%s' % (type, postfix)) or type
1073 cur = postfix and ('%s_%s' % (type, postfix)) or type
1074 if mode and cur in self.t:
1074 if mode and cur in self.t:
1075 types[type] = cur
1075 types[type] = cur
1076
1076
1077 try:
1077 try:
1078
1078
1079 # write header
1079 # write header
1080 if types['header']:
1080 if types['header']:
1081 h = templater.stringify(self.t(types['header'], **props))
1081 h = templater.stringify(self.t(types['header'], **props))
1082 if self.buffered:
1082 if self.buffered:
1083 self.header[ctx.rev()] = h
1083 self.header[ctx.rev()] = h
1084 else:
1084 else:
1085 if self.lastheader != h:
1085 if self.lastheader != h:
1086 self.lastheader = h
1086 self.lastheader = h
1087 self.ui.write(h)
1087 self.ui.write(h)
1088
1088
1089 # write changeset metadata, then patch if requested
1089 # write changeset metadata, then patch if requested
1090 key = types['changeset']
1090 key = types['changeset']
1091 self.ui.write(templater.stringify(self.t(key, **props)))
1091 self.ui.write(templater.stringify(self.t(key, **props)))
1092 self.showpatch(ctx.node(), matchfn)
1092 self.showpatch(ctx.node(), matchfn)
1093
1093
1094 if types['footer']:
1094 if types['footer']:
1095 if not self.footer:
1095 if not self.footer:
1096 self.footer = templater.stringify(self.t(types['footer'],
1096 self.footer = templater.stringify(self.t(types['footer'],
1097 **props))
1097 **props))
1098
1098
1099 except KeyError, inst:
1099 except KeyError, inst:
1100 msg = _("%s: no key named '%s'")
1100 msg = _("%s: no key named '%s'")
1101 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
1101 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
1102 except SyntaxError, inst:
1102 except SyntaxError, inst:
1103 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
1103 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
1104
1104
1105 def gettemplate(ui, tmpl, style):
1105 def gettemplate(ui, tmpl, style):
1106 """
1106 """
1107 Find the template matching the given template spec or style.
1107 Find the template matching the given template spec or style.
1108 """
1108 """
1109
1109
1110 # ui settings
1110 # ui settings
1111 if not tmpl and not style:
1111 if not tmpl and not style:
1112 tmpl = ui.config('ui', 'logtemplate')
1112 tmpl = ui.config('ui', 'logtemplate')
1113 if tmpl:
1113 if tmpl:
1114 try:
1114 try:
1115 tmpl = templater.parsestring(tmpl)
1115 tmpl = templater.parsestring(tmpl)
1116 except SyntaxError:
1116 except SyntaxError:
1117 tmpl = templater.parsestring(tmpl, quoted=False)
1117 tmpl = templater.parsestring(tmpl, quoted=False)
1118 return tmpl, None
1118 return tmpl, None
1119 else:
1119 else:
1120 style = util.expandpath(ui.config('ui', 'style', ''))
1120 style = util.expandpath(ui.config('ui', 'style', ''))
1121
1121
1122 if style:
1122 if style:
1123 mapfile = style
1123 mapfile = style
1124 if not os.path.split(mapfile)[0]:
1124 if not os.path.split(mapfile)[0]:
1125 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1125 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1126 or templater.templatepath(mapfile))
1126 or templater.templatepath(mapfile))
1127 if mapname:
1127 if mapname:
1128 mapfile = mapname
1128 mapfile = mapname
1129 return None, mapfile
1129 return None, mapfile
1130
1130
1131 if not tmpl:
1131 if not tmpl:
1132 return None, None
1132 return None, None
1133
1133
1134 # looks like a literal template?
1134 # looks like a literal template?
1135 if '{' in tmpl:
1135 if '{' in tmpl:
1136 return tmpl, None
1136 return tmpl, None
1137
1137
1138 # perhaps a stock style?
1138 # perhaps a stock style?
1139 if not os.path.split(tmpl)[0]:
1139 if not os.path.split(tmpl)[0]:
1140 mapname = (templater.templatepath('map-cmdline.' + tmpl)
1140 mapname = (templater.templatepath('map-cmdline.' + tmpl)
1141 or templater.templatepath(tmpl))
1141 or templater.templatepath(tmpl))
1142 if mapname and os.path.isfile(mapname):
1142 if mapname and os.path.isfile(mapname):
1143 return None, mapname
1143 return None, mapname
1144
1144
1145 # perhaps it's a reference to [templates]
1145 # perhaps it's a reference to [templates]
1146 t = ui.config('templates', tmpl)
1146 t = ui.config('templates', tmpl)
1147 if t:
1147 if t:
1148 try:
1148 try:
1149 tmpl = templater.parsestring(t)
1149 tmpl = templater.parsestring(t)
1150 except SyntaxError:
1150 except SyntaxError:
1151 tmpl = templater.parsestring(t, quoted=False)
1151 tmpl = templater.parsestring(t, quoted=False)
1152 return tmpl, None
1152 return tmpl, None
1153
1153
1154 if tmpl == 'list':
1154 if tmpl == 'list':
1155 ui.write(_("available styles: %s\n") % templater.stylelist())
1155 ui.write(_("available styles: %s\n") % templater.stylelist())
1156 raise util.Abort(_("specify a template"))
1156 raise util.Abort(_("specify a template"))
1157
1157
1158 # perhaps it's a path to a map or a template
1158 # perhaps it's a path to a map or a template
1159 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
1159 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
1160 # is it a mapfile for a style?
1160 # is it a mapfile for a style?
1161 if os.path.basename(tmpl).startswith("map-"):
1161 if os.path.basename(tmpl).startswith("map-"):
1162 return None, os.path.realpath(tmpl)
1162 return None, os.path.realpath(tmpl)
1163 tmpl = open(tmpl).read()
1163 tmpl = open(tmpl).read()
1164 return tmpl, None
1164 return tmpl, None
1165
1165
1166 # constant string?
1166 # constant string?
1167 return tmpl, None
1167 return tmpl, None
1168
1168
1169 def show_changeset(ui, repo, opts, buffered=False):
1169 def show_changeset(ui, repo, opts, buffered=False):
1170 """show one changeset using template or regular display.
1170 """show one changeset using template or regular display.
1171
1171
1172 Display format will be the first non-empty hit of:
1172 Display format will be the first non-empty hit of:
1173 1. option 'template'
1173 1. option 'template'
1174 2. option 'style'
1174 2. option 'style'
1175 3. [ui] setting 'logtemplate'
1175 3. [ui] setting 'logtemplate'
1176 4. [ui] setting 'style'
1176 4. [ui] setting 'style'
1177 If all of these values are either the unset or the empty string,
1177 If all of these values are either the unset or the empty string,
1178 regular display via changeset_printer() is done.
1178 regular display via changeset_printer() is done.
1179 """
1179 """
1180 # options
1180 # options
1181 patch = None
1181 patch = None
1182 if opts.get('patch') or opts.get('stat'):
1182 if opts.get('patch') or opts.get('stat'):
1183 patch = scmutil.matchall(repo)
1183 patch = scmutil.matchall(repo)
1184
1184
1185 tmpl, mapfile = gettemplate(ui, opts.get('template'), opts.get('style'))
1185 tmpl, mapfile = gettemplate(ui, opts.get('template'), opts.get('style'))
1186
1186
1187 if not tmpl and not mapfile:
1187 if not tmpl and not mapfile:
1188 return changeset_printer(ui, repo, patch, opts, buffered)
1188 return changeset_printer(ui, repo, patch, opts, buffered)
1189
1189
1190 try:
1190 try:
1191 t = changeset_templater(ui, repo, patch, opts, tmpl, mapfile, buffered)
1191 t = changeset_templater(ui, repo, patch, opts, tmpl, mapfile, buffered)
1192 except SyntaxError, inst:
1192 except SyntaxError, inst:
1193 raise util.Abort(inst.args[0])
1193 raise util.Abort(inst.args[0])
1194 return t
1194 return t
1195
1195
1196 def showmarker(ui, marker):
1196 def showmarker(ui, marker):
1197 """utility function to display obsolescence marker in a readable way
1197 """utility function to display obsolescence marker in a readable way
1198
1198
1199 To be used by debug function."""
1199 To be used by debug function."""
1200 ui.write(hex(marker.precnode()))
1200 ui.write(hex(marker.precnode()))
1201 for repl in marker.succnodes():
1201 for repl in marker.succnodes():
1202 ui.write(' ')
1202 ui.write(' ')
1203 ui.write(hex(repl))
1203 ui.write(hex(repl))
1204 ui.write(' %X ' % marker.flags())
1204 ui.write(' %X ' % marker.flags())
1205 ui.write('(%s) ' % util.datestr(marker.date()))
1205 ui.write('(%s) ' % util.datestr(marker.date()))
1206 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
1206 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
1207 sorted(marker.metadata().items())
1207 sorted(marker.metadata().items())
1208 if t[0] != 'date')))
1208 if t[0] != 'date')))
1209 ui.write('\n')
1209 ui.write('\n')
1210
1210
1211 def finddate(ui, repo, date):
1211 def finddate(ui, repo, date):
1212 """Find the tipmost changeset that matches the given date spec"""
1212 """Find the tipmost changeset that matches the given date spec"""
1213
1213
1214 df = util.matchdate(date)
1214 df = util.matchdate(date)
1215 m = scmutil.matchall(repo)
1215 m = scmutil.matchall(repo)
1216 results = {}
1216 results = {}
1217
1217
1218 def prep(ctx, fns):
1218 def prep(ctx, fns):
1219 d = ctx.date()
1219 d = ctx.date()
1220 if df(d[0]):
1220 if df(d[0]):
1221 results[ctx.rev()] = d
1221 results[ctx.rev()] = d
1222
1222
1223 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1223 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1224 rev = ctx.rev()
1224 rev = ctx.rev()
1225 if rev in results:
1225 if rev in results:
1226 ui.status(_("found revision %s from %s\n") %
1226 ui.status(_("found revision %s from %s\n") %
1227 (rev, util.datestr(results[rev])))
1227 (rev, util.datestr(results[rev])))
1228 return str(rev)
1228 return str(rev)
1229
1229
1230 raise util.Abort(_("revision matching date not found"))
1230 raise util.Abort(_("revision matching date not found"))
1231
1231
1232 def increasingwindows(windowsize=8, sizelimit=512):
1232 def increasingwindows(windowsize=8, sizelimit=512):
1233 while True:
1233 while True:
1234 yield windowsize
1234 yield windowsize
1235 if windowsize < sizelimit:
1235 if windowsize < sizelimit:
1236 windowsize *= 2
1236 windowsize *= 2
1237
1237
1238 class FileWalkError(Exception):
1238 class FileWalkError(Exception):
1239 pass
1239 pass
1240
1240
1241 def walkfilerevs(repo, match, follow, revs, fncache):
1241 def walkfilerevs(repo, match, follow, revs, fncache):
1242 '''Walks the file history for the matched files.
1242 '''Walks the file history for the matched files.
1243
1243
1244 Returns the changeset revs that are involved in the file history.
1244 Returns the changeset revs that are involved in the file history.
1245
1245
1246 Throws FileWalkError if the file history can't be walked using
1246 Throws FileWalkError if the file history can't be walked using
1247 filelogs alone.
1247 filelogs alone.
1248 '''
1248 '''
1249 wanted = set()
1249 wanted = set()
1250 copies = []
1250 copies = []
1251 minrev, maxrev = min(revs), max(revs)
1251 minrev, maxrev = min(revs), max(revs)
1252 def filerevgen(filelog, last):
1252 def filerevgen(filelog, last):
1253 """
1253 """
1254 Only files, no patterns. Check the history of each file.
1254 Only files, no patterns. Check the history of each file.
1255
1255
1256 Examines filelog entries within minrev, maxrev linkrev range
1256 Examines filelog entries within minrev, maxrev linkrev range
1257 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1257 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1258 tuples in backwards order
1258 tuples in backwards order
1259 """
1259 """
1260 cl_count = len(repo)
1260 cl_count = len(repo)
1261 revs = []
1261 revs = []
1262 for j in xrange(0, last + 1):
1262 for j in xrange(0, last + 1):
1263 linkrev = filelog.linkrev(j)
1263 linkrev = filelog.linkrev(j)
1264 if linkrev < minrev:
1264 if linkrev < minrev:
1265 continue
1265 continue
1266 # only yield rev for which we have the changelog, it can
1266 # only yield rev for which we have the changelog, it can
1267 # happen while doing "hg log" during a pull or commit
1267 # happen while doing "hg log" during a pull or commit
1268 if linkrev >= cl_count:
1268 if linkrev >= cl_count:
1269 break
1269 break
1270
1270
1271 parentlinkrevs = []
1271 parentlinkrevs = []
1272 for p in filelog.parentrevs(j):
1272 for p in filelog.parentrevs(j):
1273 if p != nullrev:
1273 if p != nullrev:
1274 parentlinkrevs.append(filelog.linkrev(p))
1274 parentlinkrevs.append(filelog.linkrev(p))
1275 n = filelog.node(j)
1275 n = filelog.node(j)
1276 revs.append((linkrev, parentlinkrevs,
1276 revs.append((linkrev, parentlinkrevs,
1277 follow and filelog.renamed(n)))
1277 follow and filelog.renamed(n)))
1278
1278
1279 return reversed(revs)
1279 return reversed(revs)
1280 def iterfiles():
1280 def iterfiles():
1281 pctx = repo['.']
1281 pctx = repo['.']
1282 for filename in match.files():
1282 for filename in match.files():
1283 if follow:
1283 if follow:
1284 if filename not in pctx:
1284 if filename not in pctx:
1285 raise util.Abort(_('cannot follow file not in parent '
1285 raise util.Abort(_('cannot follow file not in parent '
1286 'revision: "%s"') % filename)
1286 'revision: "%s"') % filename)
1287 yield filename, pctx[filename].filenode()
1287 yield filename, pctx[filename].filenode()
1288 else:
1288 else:
1289 yield filename, None
1289 yield filename, None
1290 for filename_node in copies:
1290 for filename_node in copies:
1291 yield filename_node
1291 yield filename_node
1292
1292
1293 for file_, node in iterfiles():
1293 for file_, node in iterfiles():
1294 filelog = repo.file(file_)
1294 filelog = repo.file(file_)
1295 if not len(filelog):
1295 if not len(filelog):
1296 if node is None:
1296 if node is None:
1297 # A zero count may be a directory or deleted file, so
1297 # A zero count may be a directory or deleted file, so
1298 # try to find matching entries on the slow path.
1298 # try to find matching entries on the slow path.
1299 if follow:
1299 if follow:
1300 raise util.Abort(
1300 raise util.Abort(
1301 _('cannot follow nonexistent file: "%s"') % file_)
1301 _('cannot follow nonexistent file: "%s"') % file_)
1302 raise FileWalkError("Cannot walk via filelog")
1302 raise FileWalkError("Cannot walk via filelog")
1303 else:
1303 else:
1304 continue
1304 continue
1305
1305
1306 if node is None:
1306 if node is None:
1307 last = len(filelog) - 1
1307 last = len(filelog) - 1
1308 else:
1308 else:
1309 last = filelog.rev(node)
1309 last = filelog.rev(node)
1310
1310
1311
1311
1312 # keep track of all ancestors of the file
1312 # keep track of all ancestors of the file
1313 ancestors = set([filelog.linkrev(last)])
1313 ancestors = set([filelog.linkrev(last)])
1314
1314
1315 # iterate from latest to oldest revision
1315 # iterate from latest to oldest revision
1316 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1316 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1317 if not follow:
1317 if not follow:
1318 if rev > maxrev:
1318 if rev > maxrev:
1319 continue
1319 continue
1320 else:
1320 else:
1321 # Note that last might not be the first interesting
1321 # Note that last might not be the first interesting
1322 # rev to us:
1322 # rev to us:
1323 # if the file has been changed after maxrev, we'll
1323 # if the file has been changed after maxrev, we'll
1324 # have linkrev(last) > maxrev, and we still need
1324 # have linkrev(last) > maxrev, and we still need
1325 # to explore the file graph
1325 # to explore the file graph
1326 if rev not in ancestors:
1326 if rev not in ancestors:
1327 continue
1327 continue
1328 # XXX insert 1327 fix here
1328 # XXX insert 1327 fix here
1329 if flparentlinkrevs:
1329 if flparentlinkrevs:
1330 ancestors.update(flparentlinkrevs)
1330 ancestors.update(flparentlinkrevs)
1331
1331
1332 fncache.setdefault(rev, []).append(file_)
1332 fncache.setdefault(rev, []).append(file_)
1333 wanted.add(rev)
1333 wanted.add(rev)
1334 if copied:
1334 if copied:
1335 copies.append(copied)
1335 copies.append(copied)
1336
1336
1337 return wanted
1337 return wanted
1338
1338
1339 def walkchangerevs(repo, match, opts, prepare):
1339 def walkchangerevs(repo, match, opts, prepare):
1340 '''Iterate over files and the revs in which they changed.
1340 '''Iterate over files and the revs in which they changed.
1341
1341
1342 Callers most commonly need to iterate backwards over the history
1342 Callers most commonly need to iterate backwards over the history
1343 in which they are interested. Doing so has awful (quadratic-looking)
1343 in which they are interested. Doing so has awful (quadratic-looking)
1344 performance, so we use iterators in a "windowed" way.
1344 performance, so we use iterators in a "windowed" way.
1345
1345
1346 We walk a window of revisions in the desired order. Within the
1346 We walk a window of revisions in the desired order. Within the
1347 window, we first walk forwards to gather data, then in the desired
1347 window, we first walk forwards to gather data, then in the desired
1348 order (usually backwards) to display it.
1348 order (usually backwards) to display it.
1349
1349
1350 This function returns an iterator yielding contexts. Before
1350 This function returns an iterator yielding contexts. Before
1351 yielding each context, the iterator will first call the prepare
1351 yielding each context, the iterator will first call the prepare
1352 function on each context in the window in forward order.'''
1352 function on each context in the window in forward order.'''
1353
1353
1354 follow = opts.get('follow') or opts.get('follow_first')
1354 follow = opts.get('follow') or opts.get('follow_first')
1355
1355
1356 if opts.get('rev'):
1356 if opts.get('rev'):
1357 revs = scmutil.revrange(repo, opts.get('rev'))
1357 revs = scmutil.revrange(repo, opts.get('rev'))
1358 elif follow:
1358 elif follow:
1359 revs = repo.revs('reverse(:.)')
1359 revs = repo.revs('reverse(:.)')
1360 else:
1360 else:
1361 revs = revset.spanset(repo)
1361 revs = revset.spanset(repo)
1362 revs.reverse()
1362 revs.reverse()
1363 if not revs:
1363 if not revs:
1364 return []
1364 return []
1365 wanted = set()
1365 wanted = set()
1366 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1366 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1367 fncache = {}
1367 fncache = {}
1368 change = repo.changectx
1368 change = repo.changectx
1369
1369
1370 # First step is to fill wanted, the set of revisions that we want to yield.
1370 # First step is to fill wanted, the set of revisions that we want to yield.
1371 # When it does not induce extra cost, we also fill fncache for revisions in
1371 # When it does not induce extra cost, we also fill fncache for revisions in
1372 # wanted: a cache of filenames that were changed (ctx.files()) and that
1372 # wanted: a cache of filenames that were changed (ctx.files()) and that
1373 # match the file filtering conditions.
1373 # match the file filtering conditions.
1374
1374
1375 if not slowpath and not match.files():
1375 if not slowpath and not match.files():
1376 # No files, no patterns. Display all revs.
1376 # No files, no patterns. Display all revs.
1377 wanted = revs
1377 wanted = revs
1378
1378
1379 if not slowpath and match.files():
1379 if not slowpath and match.files():
1380 # We only have to read through the filelog to find wanted revisions
1380 # We only have to read through the filelog to find wanted revisions
1381
1381
1382 try:
1382 try:
1383 wanted = walkfilerevs(repo, match, follow, revs, fncache)
1383 wanted = walkfilerevs(repo, match, follow, revs, fncache)
1384 except FileWalkError:
1384 except FileWalkError:
1385 slowpath = True
1385 slowpath = True
1386
1386
1387 # We decided to fall back to the slowpath because at least one
1387 # We decided to fall back to the slowpath because at least one
1388 # of the paths was not a file. Check to see if at least one of them
1388 # of the paths was not a file. Check to see if at least one of them
1389 # existed in history, otherwise simply return
1389 # existed in history, otherwise simply return
1390 for path in match.files():
1390 for path in match.files():
1391 if path == '.' or path in repo.store:
1391 if path == '.' or path in repo.store:
1392 break
1392 break
1393 else:
1393 else:
1394 return []
1394 return []
1395
1395
1396 if slowpath:
1396 if slowpath:
1397 # We have to read the changelog to match filenames against
1397 # We have to read the changelog to match filenames against
1398 # changed files
1398 # changed files
1399
1399
1400 if follow:
1400 if follow:
1401 raise util.Abort(_('can only follow copies/renames for explicit '
1401 raise util.Abort(_('can only follow copies/renames for explicit '
1402 'filenames'))
1402 'filenames'))
1403
1403
1404 # The slow path checks files modified in every changeset.
1404 # The slow path checks files modified in every changeset.
1405 # This is really slow on large repos, so compute the set lazily.
1405 # This is really slow on large repos, so compute the set lazily.
1406 class lazywantedset(object):
1406 class lazywantedset(object):
1407 def __init__(self):
1407 def __init__(self):
1408 self.set = set()
1408 self.set = set()
1409 self.revs = set(revs)
1409 self.revs = set(revs)
1410
1410
1411 # No need to worry about locality here because it will be accessed
1411 # No need to worry about locality here because it will be accessed
1412 # in the same order as the increasing window below.
1412 # in the same order as the increasing window below.
1413 def __contains__(self, value):
1413 def __contains__(self, value):
1414 if value in self.set:
1414 if value in self.set:
1415 return True
1415 return True
1416 elif not value in self.revs:
1416 elif not value in self.revs:
1417 return False
1417 return False
1418 else:
1418 else:
1419 self.revs.discard(value)
1419 self.revs.discard(value)
1420 ctx = change(value)
1420 ctx = change(value)
1421 matches = filter(match, ctx.files())
1421 matches = filter(match, ctx.files())
1422 if matches:
1422 if matches:
1423 fncache[value] = matches
1423 fncache[value] = matches
1424 self.set.add(value)
1424 self.set.add(value)
1425 return True
1425 return True
1426 return False
1426 return False
1427
1427
1428 def discard(self, value):
1428 def discard(self, value):
1429 self.revs.discard(value)
1429 self.revs.discard(value)
1430 self.set.discard(value)
1430 self.set.discard(value)
1431
1431
1432 wanted = lazywantedset()
1432 wanted = lazywantedset()
1433
1433
1434 class followfilter(object):
1434 class followfilter(object):
1435 def __init__(self, onlyfirst=False):
1435 def __init__(self, onlyfirst=False):
1436 self.startrev = nullrev
1436 self.startrev = nullrev
1437 self.roots = set()
1437 self.roots = set()
1438 self.onlyfirst = onlyfirst
1438 self.onlyfirst = onlyfirst
1439
1439
1440 def match(self, rev):
1440 def match(self, rev):
1441 def realparents(rev):
1441 def realparents(rev):
1442 if self.onlyfirst:
1442 if self.onlyfirst:
1443 return repo.changelog.parentrevs(rev)[0:1]
1443 return repo.changelog.parentrevs(rev)[0:1]
1444 else:
1444 else:
1445 return filter(lambda x: x != nullrev,
1445 return filter(lambda x: x != nullrev,
1446 repo.changelog.parentrevs(rev))
1446 repo.changelog.parentrevs(rev))
1447
1447
1448 if self.startrev == nullrev:
1448 if self.startrev == nullrev:
1449 self.startrev = rev
1449 self.startrev = rev
1450 return True
1450 return True
1451
1451
1452 if rev > self.startrev:
1452 if rev > self.startrev:
1453 # forward: all descendants
1453 # forward: all descendants
1454 if not self.roots:
1454 if not self.roots:
1455 self.roots.add(self.startrev)
1455 self.roots.add(self.startrev)
1456 for parent in realparents(rev):
1456 for parent in realparents(rev):
1457 if parent in self.roots:
1457 if parent in self.roots:
1458 self.roots.add(rev)
1458 self.roots.add(rev)
1459 return True
1459 return True
1460 else:
1460 else:
1461 # backwards: all parents
1461 # backwards: all parents
1462 if not self.roots:
1462 if not self.roots:
1463 self.roots.update(realparents(self.startrev))
1463 self.roots.update(realparents(self.startrev))
1464 if rev in self.roots:
1464 if rev in self.roots:
1465 self.roots.remove(rev)
1465 self.roots.remove(rev)
1466 self.roots.update(realparents(rev))
1466 self.roots.update(realparents(rev))
1467 return True
1467 return True
1468
1468
1469 return False
1469 return False
1470
1470
1471 # it might be worthwhile to do this in the iterator if the rev range
1471 # it might be worthwhile to do this in the iterator if the rev range
1472 # is descending and the prune args are all within that range
1472 # is descending and the prune args are all within that range
1473 for rev in opts.get('prune', ()):
1473 for rev in opts.get('prune', ()):
1474 rev = repo[rev].rev()
1474 rev = repo[rev].rev()
1475 ff = followfilter()
1475 ff = followfilter()
1476 stop = min(revs[0], revs[-1])
1476 stop = min(revs[0], revs[-1])
1477 for x in xrange(rev, stop - 1, -1):
1477 for x in xrange(rev, stop - 1, -1):
1478 if ff.match(x):
1478 if ff.match(x):
1479 wanted = wanted - [x]
1479 wanted = wanted - [x]
1480
1480
1481 # Now that wanted is correctly initialized, we can iterate over the
1481 # Now that wanted is correctly initialized, we can iterate over the
1482 # revision range, yielding only revisions in wanted.
1482 # revision range, yielding only revisions in wanted.
1483 def iterate():
1483 def iterate():
1484 if follow and not match.files():
1484 if follow and not match.files():
1485 ff = followfilter(onlyfirst=opts.get('follow_first'))
1485 ff = followfilter(onlyfirst=opts.get('follow_first'))
1486 def want(rev):
1486 def want(rev):
1487 return ff.match(rev) and rev in wanted
1487 return ff.match(rev) and rev in wanted
1488 else:
1488 else:
1489 def want(rev):
1489 def want(rev):
1490 return rev in wanted
1490 return rev in wanted
1491
1491
1492 it = iter(revs)
1492 it = iter(revs)
1493 stopiteration = False
1493 stopiteration = False
1494 for windowsize in increasingwindows():
1494 for windowsize in increasingwindows():
1495 nrevs = []
1495 nrevs = []
1496 for i in xrange(windowsize):
1496 for i in xrange(windowsize):
1497 try:
1497 try:
1498 rev = it.next()
1498 rev = it.next()
1499 if want(rev):
1499 if want(rev):
1500 nrevs.append(rev)
1500 nrevs.append(rev)
1501 except (StopIteration):
1501 except (StopIteration):
1502 stopiteration = True
1502 stopiteration = True
1503 break
1503 break
1504 for rev in sorted(nrevs):
1504 for rev in sorted(nrevs):
1505 fns = fncache.get(rev)
1505 fns = fncache.get(rev)
1506 ctx = change(rev)
1506 ctx = change(rev)
1507 if not fns:
1507 if not fns:
1508 def fns_generator():
1508 def fns_generator():
1509 for f in ctx.files():
1509 for f in ctx.files():
1510 if match(f):
1510 if match(f):
1511 yield f
1511 yield f
1512 fns = fns_generator()
1512 fns = fns_generator()
1513 prepare(ctx, fns)
1513 prepare(ctx, fns)
1514 for rev in nrevs:
1514 for rev in nrevs:
1515 yield change(rev)
1515 yield change(rev)
1516
1516
1517 if stopiteration:
1517 if stopiteration:
1518 break
1518 break
1519
1519
1520 return iterate()
1520 return iterate()
1521
1521
1522 def _makefollowlogfilematcher(repo, files, followfirst):
1522 def _makefollowlogfilematcher(repo, files, followfirst):
1523 # When displaying a revision with --patch --follow FILE, we have
1523 # When displaying a revision with --patch --follow FILE, we have
1524 # to know which file of the revision must be diffed. With
1524 # to know which file of the revision must be diffed. With
1525 # --follow, we want the names of the ancestors of FILE in the
1525 # --follow, we want the names of the ancestors of FILE in the
1526 # revision, stored in "fcache". "fcache" is populated by
1526 # revision, stored in "fcache". "fcache" is populated by
1527 # reproducing the graph traversal already done by --follow revset
1527 # reproducing the graph traversal already done by --follow revset
1528 # and relating linkrevs to file names (which is not "correct" but
1528 # and relating linkrevs to file names (which is not "correct" but
1529 # good enough).
1529 # good enough).
1530 fcache = {}
1530 fcache = {}
1531 fcacheready = [False]
1531 fcacheready = [False]
1532 pctx = repo['.']
1532 pctx = repo['.']
1533
1533
1534 def populate():
1534 def populate():
1535 for fn in files:
1535 for fn in files:
1536 for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
1536 for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
1537 for c in i:
1537 for c in i:
1538 fcache.setdefault(c.linkrev(), set()).add(c.path())
1538 fcache.setdefault(c.linkrev(), set()).add(c.path())
1539
1539
1540 def filematcher(rev):
1540 def filematcher(rev):
1541 if not fcacheready[0]:
1541 if not fcacheready[0]:
1542 # Lazy initialization
1542 # Lazy initialization
1543 fcacheready[0] = True
1543 fcacheready[0] = True
1544 populate()
1544 populate()
1545 return scmutil.matchfiles(repo, fcache.get(rev, []))
1545 return scmutil.matchfiles(repo, fcache.get(rev, []))
1546
1546
1547 return filematcher
1547 return filematcher
1548
1548
1549 def _makenofollowlogfilematcher(repo, pats, opts):
1549 def _makenofollowlogfilematcher(repo, pats, opts):
1550 '''hook for extensions to override the filematcher for non-follow cases'''
1550 '''hook for extensions to override the filematcher for non-follow cases'''
1551 return None
1551 return None
1552
1552
1553 def _makelogrevset(repo, pats, opts, revs):
1553 def _makelogrevset(repo, pats, opts, revs):
1554 """Return (expr, filematcher) where expr is a revset string built
1554 """Return (expr, filematcher) where expr is a revset string built
1555 from log options and file patterns or None. If --stat or --patch
1555 from log options and file patterns or None. If --stat or --patch
1556 are not passed filematcher is None. Otherwise it is a callable
1556 are not passed filematcher is None. Otherwise it is a callable
1557 taking a revision number and returning a match objects filtering
1557 taking a revision number and returning a match objects filtering
1558 the files to be detailed when displaying the revision.
1558 the files to be detailed when displaying the revision.
1559 """
1559 """
1560 opt2revset = {
1560 opt2revset = {
1561 'no_merges': ('not merge()', None),
1561 'no_merges': ('not merge()', None),
1562 'only_merges': ('merge()', None),
1562 'only_merges': ('merge()', None),
1563 '_ancestors': ('ancestors(%(val)s)', None),
1563 '_ancestors': ('ancestors(%(val)s)', None),
1564 '_fancestors': ('_firstancestors(%(val)s)', None),
1564 '_fancestors': ('_firstancestors(%(val)s)', None),
1565 '_descendants': ('descendants(%(val)s)', None),
1565 '_descendants': ('descendants(%(val)s)', None),
1566 '_fdescendants': ('_firstdescendants(%(val)s)', None),
1566 '_fdescendants': ('_firstdescendants(%(val)s)', None),
1567 '_matchfiles': ('_matchfiles(%(val)s)', None),
1567 '_matchfiles': ('_matchfiles(%(val)s)', None),
1568 'date': ('date(%(val)r)', None),
1568 'date': ('date(%(val)r)', None),
1569 'branch': ('branch(%(val)r)', ' or '),
1569 'branch': ('branch(%(val)r)', ' or '),
1570 '_patslog': ('filelog(%(val)r)', ' or '),
1570 '_patslog': ('filelog(%(val)r)', ' or '),
1571 '_patsfollow': ('follow(%(val)r)', ' or '),
1571 '_patsfollow': ('follow(%(val)r)', ' or '),
1572 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
1572 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
1573 'keyword': ('keyword(%(val)r)', ' or '),
1573 'keyword': ('keyword(%(val)r)', ' or '),
1574 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
1574 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
1575 'user': ('user(%(val)r)', ' or '),
1575 'user': ('user(%(val)r)', ' or '),
1576 }
1576 }
1577
1577
1578 opts = dict(opts)
1578 opts = dict(opts)
1579 # follow or not follow?
1579 # follow or not follow?
1580 follow = opts.get('follow') or opts.get('follow_first')
1580 follow = opts.get('follow') or opts.get('follow_first')
1581 followfirst = opts.get('follow_first') and 1 or 0
1581 followfirst = opts.get('follow_first') and 1 or 0
1582 # --follow with FILE behaviour depends on revs...
1582 # --follow with FILE behaviour depends on revs...
1583 it = iter(revs)
1583 it = iter(revs)
1584 startrev = it.next()
1584 startrev = it.next()
1585 try:
1585 try:
1586 followdescendants = startrev < it.next()
1586 followdescendants = startrev < it.next()
1587 except (StopIteration):
1587 except (StopIteration):
1588 followdescendants = False
1588 followdescendants = False
1589
1589
1590 # branch and only_branch are really aliases and must be handled at
1590 # branch and only_branch are really aliases and must be handled at
1591 # the same time
1591 # the same time
1592 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
1592 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
1593 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
1593 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
1594 # pats/include/exclude are passed to match.match() directly in
1594 # pats/include/exclude are passed to match.match() directly in
1595 # _matchfiles() revset but walkchangerevs() builds its matcher with
1595 # _matchfiles() revset but walkchangerevs() builds its matcher with
1596 # scmutil.match(). The difference is input pats are globbed on
1596 # scmutil.match(). The difference is input pats are globbed on
1597 # platforms without shell expansion (windows).
1597 # platforms without shell expansion (windows).
1598 pctx = repo[None]
1598 pctx = repo[None]
1599 match, pats = scmutil.matchandpats(pctx, pats, opts)
1599 match, pats = scmutil.matchandpats(pctx, pats, opts)
1600 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1600 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1601 if not slowpath:
1601 if not slowpath:
1602 for f in match.files():
1602 for f in match.files():
1603 if follow and f not in pctx:
1603 if follow and f not in pctx:
1604 # If the file exists, it may be a directory, so let it
1604 # If the file exists, it may be a directory, so let it
1605 # take the slow path.
1605 # take the slow path.
1606 if os.path.exists(repo.wjoin(f)):
1606 if os.path.exists(repo.wjoin(f)):
1607 slowpath = True
1607 slowpath = True
1608 continue
1608 continue
1609 else:
1609 else:
1610 raise util.Abort(_('cannot follow file not in parent '
1610 raise util.Abort(_('cannot follow file not in parent '
1611 'revision: "%s"') % f)
1611 'revision: "%s"') % f)
1612 filelog = repo.file(f)
1612 filelog = repo.file(f)
1613 if not filelog:
1613 if not filelog:
1614 # A zero count may be a directory or deleted file, so
1614 # A zero count may be a directory or deleted file, so
1615 # try to find matching entries on the slow path.
1615 # try to find matching entries on the slow path.
1616 if follow:
1616 if follow:
1617 raise util.Abort(
1617 raise util.Abort(
1618 _('cannot follow nonexistent file: "%s"') % f)
1618 _('cannot follow nonexistent file: "%s"') % f)
1619 slowpath = True
1619 slowpath = True
1620
1620
1621 # We decided to fall back to the slowpath because at least one
1621 # We decided to fall back to the slowpath because at least one
1622 # of the paths was not a file. Check to see if at least one of them
1622 # of the paths was not a file. Check to see if at least one of them
1623 # existed in history - in that case, we'll continue down the
1623 # existed in history - in that case, we'll continue down the
1624 # slowpath; otherwise, we can turn off the slowpath
1624 # slowpath; otherwise, we can turn off the slowpath
1625 if slowpath:
1625 if slowpath:
1626 for path in match.files():
1626 for path in match.files():
1627 if path == '.' or path in repo.store:
1627 if path == '.' or path in repo.store:
1628 break
1628 break
1629 else:
1629 else:
1630 slowpath = False
1630 slowpath = False
1631
1631
1632 if slowpath:
1632 if slowpath:
1633 # See walkchangerevs() slow path.
1633 # See walkchangerevs() slow path.
1634 #
1634 #
1635 # pats/include/exclude cannot be represented as separate
1635 # pats/include/exclude cannot be represented as separate
1636 # revset expressions as their filtering logic applies at file
1636 # revset expressions as their filtering logic applies at file
1637 # level. For instance "-I a -X a" matches a revision touching
1637 # level. For instance "-I a -X a" matches a revision touching
1638 # "a" and "b" while "file(a) and not file(b)" does
1638 # "a" and "b" while "file(a) and not file(b)" does
1639 # not. Besides, filesets are evaluated against the working
1639 # not. Besides, filesets are evaluated against the working
1640 # directory.
1640 # directory.
1641 matchargs = ['r:', 'd:relpath']
1641 matchargs = ['r:', 'd:relpath']
1642 for p in pats:
1642 for p in pats:
1643 matchargs.append('p:' + p)
1643 matchargs.append('p:' + p)
1644 for p in opts.get('include', []):
1644 for p in opts.get('include', []):
1645 matchargs.append('i:' + p)
1645 matchargs.append('i:' + p)
1646 for p in opts.get('exclude', []):
1646 for p in opts.get('exclude', []):
1647 matchargs.append('x:' + p)
1647 matchargs.append('x:' + p)
1648 matchargs = ','.join(('%r' % p) for p in matchargs)
1648 matchargs = ','.join(('%r' % p) for p in matchargs)
1649 opts['_matchfiles'] = matchargs
1649 opts['_matchfiles'] = matchargs
1650 else:
1650 else:
1651 if follow:
1651 if follow:
1652 fpats = ('_patsfollow', '_patsfollowfirst')
1652 fpats = ('_patsfollow', '_patsfollowfirst')
1653 fnopats = (('_ancestors', '_fancestors'),
1653 fnopats = (('_ancestors', '_fancestors'),
1654 ('_descendants', '_fdescendants'))
1654 ('_descendants', '_fdescendants'))
1655 if pats:
1655 if pats:
1656 # follow() revset interprets its file argument as a
1656 # follow() revset interprets its file argument as a
1657 # manifest entry, so use match.files(), not pats.
1657 # manifest entry, so use match.files(), not pats.
1658 opts[fpats[followfirst]] = list(match.files())
1658 opts[fpats[followfirst]] = list(match.files())
1659 else:
1659 else:
1660 opts[fnopats[followdescendants][followfirst]] = str(startrev)
1660 opts[fnopats[followdescendants][followfirst]] = str(startrev)
1661 else:
1661 else:
1662 opts['_patslog'] = list(pats)
1662 opts['_patslog'] = list(pats)
1663
1663
1664 filematcher = None
1664 filematcher = None
1665 if opts.get('patch') or opts.get('stat'):
1665 if opts.get('patch') or opts.get('stat'):
1666 # When following files, track renames via a special matcher.
1666 # When following files, track renames via a special matcher.
1667 # If we're forced to take the slowpath it means we're following
1667 # If we're forced to take the slowpath it means we're following
1668 # at least one pattern/directory, so don't bother with rename tracking.
1668 # at least one pattern/directory, so don't bother with rename tracking.
1669 if follow and not match.always() and not slowpath:
1669 if follow and not match.always() and not slowpath:
1670 # _makelogfilematcher expects its files argument to be relative to
1670 # _makelogfilematcher expects its files argument to be relative to
1671 # the repo root, so use match.files(), not pats.
1671 # the repo root, so use match.files(), not pats.
1672 filematcher = _makefollowlogfilematcher(repo, match.files(),
1672 filematcher = _makefollowlogfilematcher(repo, match.files(),
1673 followfirst)
1673 followfirst)
1674 else:
1674 else:
1675 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
1675 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
1676 if filematcher is None:
1676 if filematcher is None:
1677 filematcher = lambda rev: match
1677 filematcher = lambda rev: match
1678
1678
1679 expr = []
1679 expr = []
1680 for op, val in opts.iteritems():
1680 for op, val in opts.iteritems():
1681 if not val:
1681 if not val:
1682 continue
1682 continue
1683 if op not in opt2revset:
1683 if op not in opt2revset:
1684 continue
1684 continue
1685 revop, andor = opt2revset[op]
1685 revop, andor = opt2revset[op]
1686 if '%(val)' not in revop:
1686 if '%(val)' not in revop:
1687 expr.append(revop)
1687 expr.append(revop)
1688 else:
1688 else:
1689 if not isinstance(val, list):
1689 if not isinstance(val, list):
1690 e = revop % {'val': val}
1690 e = revop % {'val': val}
1691 else:
1691 else:
1692 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
1692 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
1693 expr.append(e)
1693 expr.append(e)
1694
1694
1695 if expr:
1695 if expr:
1696 expr = '(' + ' and '.join(expr) + ')'
1696 expr = '(' + ' and '.join(expr) + ')'
1697 else:
1697 else:
1698 expr = None
1698 expr = None
1699 return expr, filematcher
1699 return expr, filematcher
1700
1700
1701 def getgraphlogrevs(repo, pats, opts):
1701 def getgraphlogrevs(repo, pats, opts):
1702 """Return (revs, expr, filematcher) where revs is an iterable of
1702 """Return (revs, expr, filematcher) where revs is an iterable of
1703 revision numbers, expr is a revset string built from log options
1703 revision numbers, expr is a revset string built from log options
1704 and file patterns or None, and used to filter 'revs'. If --stat or
1704 and file patterns or None, and used to filter 'revs'. If --stat or
1705 --patch are not passed filematcher is None. Otherwise it is a
1705 --patch are not passed filematcher is None. Otherwise it is a
1706 callable taking a revision number and returning a match objects
1706 callable taking a revision number and returning a match objects
1707 filtering the files to be detailed when displaying the revision.
1707 filtering the files to be detailed when displaying the revision.
1708 """
1708 """
1709 if not len(repo):
1709 if not len(repo):
1710 return [], None, None
1710 return [], None, None
1711 limit = loglimit(opts)
1711 limit = loglimit(opts)
1712 # Default --rev value depends on --follow but --follow behaviour
1712 # Default --rev value depends on --follow but --follow behaviour
1713 # depends on revisions resolved from --rev...
1713 # depends on revisions resolved from --rev...
1714 follow = opts.get('follow') or opts.get('follow_first')
1714 follow = opts.get('follow') or opts.get('follow_first')
1715 possiblyunsorted = False # whether revs might need sorting
1715 possiblyunsorted = False # whether revs might need sorting
1716 if opts.get('rev'):
1716 if opts.get('rev'):
1717 revs = scmutil.revrange(repo, opts['rev'])
1717 revs = scmutil.revrange(repo, opts['rev'])
1718 # Don't sort here because _makelogrevset might depend on the
1718 # Don't sort here because _makelogrevset might depend on the
1719 # order of revs
1719 # order of revs
1720 possiblyunsorted = True
1720 possiblyunsorted = True
1721 else:
1721 else:
1722 if follow and len(repo) > 0:
1722 if follow and len(repo) > 0:
1723 revs = repo.revs('reverse(:.)')
1723 revs = repo.revs('reverse(:.)')
1724 else:
1724 else:
1725 revs = revset.spanset(repo)
1725 revs = revset.spanset(repo)
1726 revs.reverse()
1726 revs.reverse()
1727 if not revs:
1727 if not revs:
1728 return revset.baseset(), None, None
1728 return revset.baseset(), None, None
1729 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1729 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1730 if possiblyunsorted:
1730 if possiblyunsorted:
1731 revs.sort(reverse=True)
1731 revs.sort(reverse=True)
1732 if expr:
1732 if expr:
1733 # Revset matchers often operate faster on revisions in changelog
1733 # Revset matchers often operate faster on revisions in changelog
1734 # order, because most filters deal with the changelog.
1734 # order, because most filters deal with the changelog.
1735 revs.reverse()
1735 revs.reverse()
1736 matcher = revset.match(repo.ui, expr)
1736 matcher = revset.match(repo.ui, expr)
1737 # Revset matches can reorder revisions. "A or B" typically returns
1737 # Revset matches can reorder revisions. "A or B" typically returns
1738 # returns the revision matching A then the revision matching B. Sort
1738 # returns the revision matching A then the revision matching B. Sort
1739 # again to fix that.
1739 # again to fix that.
1740 revs = matcher(repo, revs)
1740 revs = matcher(repo, revs)
1741 revs.sort(reverse=True)
1741 revs.sort(reverse=True)
1742 if limit is not None:
1742 if limit is not None:
1743 limitedrevs = revset.baseset()
1743 limitedrevs = revset.baseset()
1744 for idx, rev in enumerate(revs):
1744 for idx, rev in enumerate(revs):
1745 if idx >= limit:
1745 if idx >= limit:
1746 break
1746 break
1747 limitedrevs.append(rev)
1747 limitedrevs.append(rev)
1748 revs = limitedrevs
1748 revs = limitedrevs
1749
1749
1750 return revs, expr, filematcher
1750 return revs, expr, filematcher
1751
1751
1752 def getlogrevs(repo, pats, opts):
1752 def getlogrevs(repo, pats, opts):
1753 """Return (revs, expr, filematcher) where revs is an iterable of
1753 """Return (revs, expr, filematcher) where revs is an iterable of
1754 revision numbers, expr is a revset string built from log options
1754 revision numbers, expr is a revset string built from log options
1755 and file patterns or None, and used to filter 'revs'. If --stat or
1755 and file patterns or None, and used to filter 'revs'. If --stat or
1756 --patch are not passed filematcher is None. Otherwise it is a
1756 --patch are not passed filematcher is None. Otherwise it is a
1757 callable taking a revision number and returning a match objects
1757 callable taking a revision number and returning a match objects
1758 filtering the files to be detailed when displaying the revision.
1758 filtering the files to be detailed when displaying the revision.
1759 """
1759 """
1760 limit = loglimit(opts)
1760 limit = loglimit(opts)
1761 # Default --rev value depends on --follow but --follow behaviour
1761 # Default --rev value depends on --follow but --follow behaviour
1762 # depends on revisions resolved from --rev...
1762 # depends on revisions resolved from --rev...
1763 follow = opts.get('follow') or opts.get('follow_first')
1763 follow = opts.get('follow') or opts.get('follow_first')
1764 if opts.get('rev'):
1764 if opts.get('rev'):
1765 revs = scmutil.revrange(repo, opts['rev'])
1765 revs = scmutil.revrange(repo, opts['rev'])
1766 elif follow:
1766 elif follow:
1767 revs = repo.revs('reverse(:.)')
1767 revs = repo.revs('reverse(:.)')
1768 else:
1768 else:
1769 revs = revset.spanset(repo)
1769 revs = revset.spanset(repo)
1770 revs.reverse()
1770 revs.reverse()
1771 if not revs:
1771 if not revs:
1772 return revset.baseset([]), None, None
1772 return revset.baseset([]), None, None
1773 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1773 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1774 if expr:
1774 if expr:
1775 # Revset matchers often operate faster on revisions in changelog
1775 # Revset matchers often operate faster on revisions in changelog
1776 # order, because most filters deal with the changelog.
1776 # order, because most filters deal with the changelog.
1777 if not opts.get('rev'):
1777 if not opts.get('rev'):
1778 revs.reverse()
1778 revs.reverse()
1779 matcher = revset.match(repo.ui, expr)
1779 matcher = revset.match(repo.ui, expr)
1780 # Revset matches can reorder revisions. "A or B" typically returns
1780 # Revset matches can reorder revisions. "A or B" typically returns
1781 # returns the revision matching A then the revision matching B. Sort
1781 # returns the revision matching A then the revision matching B. Sort
1782 # again to fix that.
1782 # again to fix that.
1783 revs = matcher(repo, revs)
1783 revs = matcher(repo, revs)
1784 if not opts.get('rev'):
1784 if not opts.get('rev'):
1785 revs.sort(reverse=True)
1785 revs.sort(reverse=True)
1786 if limit is not None:
1786 if limit is not None:
1787 count = 0
1787 count = 0
1788 limitedrevs = revset.baseset([])
1788 limitedrevs = revset.baseset([])
1789 it = iter(revs)
1789 it = iter(revs)
1790 while count < limit:
1790 while count < limit:
1791 try:
1791 try:
1792 limitedrevs.append(it.next())
1792 limitedrevs.append(it.next())
1793 except (StopIteration):
1793 except (StopIteration):
1794 break
1794 break
1795 count += 1
1795 count += 1
1796 revs = limitedrevs
1796 revs = limitedrevs
1797
1797
1798 return revs, expr, filematcher
1798 return revs, expr, filematcher
1799
1799
1800 def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None,
1800 def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None,
1801 filematcher=None):
1801 filematcher=None):
1802 seen, state = [], graphmod.asciistate()
1802 seen, state = [], graphmod.asciistate()
1803 for rev, type, ctx, parents in dag:
1803 for rev, type, ctx, parents in dag:
1804 char = 'o'
1804 char = 'o'
1805 if ctx.node() in showparents:
1805 if ctx.node() in showparents:
1806 char = '@'
1806 char = '@'
1807 elif ctx.obsolete():
1807 elif ctx.obsolete():
1808 char = 'x'
1808 char = 'x'
1809 copies = None
1809 copies = None
1810 if getrenamed and ctx.rev():
1810 if getrenamed and ctx.rev():
1811 copies = []
1811 copies = []
1812 for fn in ctx.files():
1812 for fn in ctx.files():
1813 rename = getrenamed(fn, ctx.rev())
1813 rename = getrenamed(fn, ctx.rev())
1814 if rename:
1814 if rename:
1815 copies.append((fn, rename[0]))
1815 copies.append((fn, rename[0]))
1816 revmatchfn = None
1816 revmatchfn = None
1817 if filematcher is not None:
1817 if filematcher is not None:
1818 revmatchfn = filematcher(ctx.rev())
1818 revmatchfn = filematcher(ctx.rev())
1819 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
1819 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
1820 lines = displayer.hunk.pop(rev).split('\n')
1820 lines = displayer.hunk.pop(rev).split('\n')
1821 if not lines[-1]:
1821 if not lines[-1]:
1822 del lines[-1]
1822 del lines[-1]
1823 displayer.flush(rev)
1823 displayer.flush(rev)
1824 edges = edgefn(type, char, lines, seen, rev, parents)
1824 edges = edgefn(type, char, lines, seen, rev, parents)
1825 for type, char, lines, coldata in edges:
1825 for type, char, lines, coldata in edges:
1826 graphmod.ascii(ui, state, type, char, lines, coldata)
1826 graphmod.ascii(ui, state, type, char, lines, coldata)
1827 displayer.close()
1827 displayer.close()
1828
1828
1829 def graphlog(ui, repo, *pats, **opts):
1829 def graphlog(ui, repo, *pats, **opts):
1830 # Parameters are identical to log command ones
1830 # Parameters are identical to log command ones
1831 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
1831 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
1832 revdag = graphmod.dagwalker(repo, revs)
1832 revdag = graphmod.dagwalker(repo, revs)
1833
1833
1834 getrenamed = None
1834 getrenamed = None
1835 if opts.get('copies'):
1835 if opts.get('copies'):
1836 endrev = None
1836 endrev = None
1837 if opts.get('rev'):
1837 if opts.get('rev'):
1838 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
1838 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
1839 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
1839 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
1840 displayer = show_changeset(ui, repo, opts, buffered=True)
1840 displayer = show_changeset(ui, repo, opts, buffered=True)
1841 showparents = [ctx.node() for ctx in repo[None].parents()]
1841 showparents = [ctx.node() for ctx in repo[None].parents()]
1842 displaygraph(ui, revdag, displayer, showparents,
1842 displaygraph(ui, revdag, displayer, showparents,
1843 graphmod.asciiedges, getrenamed, filematcher)
1843 graphmod.asciiedges, getrenamed, filematcher)
1844
1844
1845 def checkunsupportedgraphflags(pats, opts):
1845 def checkunsupportedgraphflags(pats, opts):
1846 for op in ["newest_first"]:
1846 for op in ["newest_first"]:
1847 if op in opts and opts[op]:
1847 if op in opts and opts[op]:
1848 raise util.Abort(_("-G/--graph option is incompatible with --%s")
1848 raise util.Abort(_("-G/--graph option is incompatible with --%s")
1849 % op.replace("_", "-"))
1849 % op.replace("_", "-"))
1850
1850
1851 def graphrevs(repo, nodes, opts):
1851 def graphrevs(repo, nodes, opts):
1852 limit = loglimit(opts)
1852 limit = loglimit(opts)
1853 nodes.reverse()
1853 nodes.reverse()
1854 if limit is not None:
1854 if limit is not None:
1855 nodes = nodes[:limit]
1855 nodes = nodes[:limit]
1856 return graphmod.nodes(repo, nodes)
1856 return graphmod.nodes(repo, nodes)
1857
1857
1858 def add(ui, repo, match, dryrun, listsubrepos, prefix, explicitonly):
1858 def add(ui, repo, match, dryrun, listsubrepos, prefix, explicitonly):
1859 join = lambda f: os.path.join(prefix, f)
1859 join = lambda f: os.path.join(prefix, f)
1860 bad = []
1860 bad = []
1861 oldbad = match.bad
1861 oldbad = match.bad
1862 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1862 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1863 names = []
1863 names = []
1864 wctx = repo[None]
1864 wctx = repo[None]
1865 cca = None
1865 cca = None
1866 abort, warn = scmutil.checkportabilityalert(ui)
1866 abort, warn = scmutil.checkportabilityalert(ui)
1867 if abort or warn:
1867 if abort or warn:
1868 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
1868 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
1869 for f in repo.walk(match):
1869 for f in repo.walk(match):
1870 exact = match.exact(f)
1870 exact = match.exact(f)
1871 if exact or not explicitonly and f not in repo.dirstate:
1871 if exact or not explicitonly and f not in repo.dirstate:
1872 if cca:
1872 if cca:
1873 cca(f)
1873 cca(f)
1874 names.append(f)
1874 names.append(f)
1875 if ui.verbose or not exact:
1875 if ui.verbose or not exact:
1876 ui.status(_('adding %s\n') % match.rel(join(f)))
1876 ui.status(_('adding %s\n') % match.rel(join(f)))
1877
1877
1878 for subpath in sorted(wctx.substate):
1878 for subpath in sorted(wctx.substate):
1879 sub = wctx.sub(subpath)
1879 sub = wctx.sub(subpath)
1880 try:
1880 try:
1881 submatch = matchmod.narrowmatcher(subpath, match)
1881 submatch = matchmod.narrowmatcher(subpath, match)
1882 if listsubrepos:
1882 if listsubrepos:
1883 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1883 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1884 False))
1884 False))
1885 else:
1885 else:
1886 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1886 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1887 True))
1887 True))
1888 except error.LookupError:
1888 except error.LookupError:
1889 ui.status(_("skipping missing subrepository: %s\n")
1889 ui.status(_("skipping missing subrepository: %s\n")
1890 % join(subpath))
1890 % join(subpath))
1891
1891
1892 if not dryrun:
1892 if not dryrun:
1893 rejected = wctx.add(names, prefix)
1893 rejected = wctx.add(names, prefix)
1894 bad.extend(f for f in rejected if f in match.files())
1894 bad.extend(f for f in rejected if f in match.files())
1895 return bad
1895 return bad
1896
1896
1897 def forget(ui, repo, match, prefix, explicitonly):
1897 def forget(ui, repo, match, prefix, explicitonly):
1898 join = lambda f: os.path.join(prefix, f)
1898 join = lambda f: os.path.join(prefix, f)
1899 bad = []
1899 bad = []
1900 oldbad = match.bad
1900 oldbad = match.bad
1901 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1901 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1902 wctx = repo[None]
1902 wctx = repo[None]
1903 forgot = []
1903 forgot = []
1904 s = repo.status(match=match, clean=True)
1904 s = repo.status(match=match, clean=True)
1905 forget = sorted(s[0] + s[1] + s[3] + s[6])
1905 forget = sorted(s[0] + s[1] + s[3] + s[6])
1906 if explicitonly:
1906 if explicitonly:
1907 forget = [f for f in forget if match.exact(f)]
1907 forget = [f for f in forget if match.exact(f)]
1908
1908
1909 for subpath in sorted(wctx.substate):
1909 for subpath in sorted(wctx.substate):
1910 sub = wctx.sub(subpath)
1910 sub = wctx.sub(subpath)
1911 try:
1911 try:
1912 submatch = matchmod.narrowmatcher(subpath, match)
1912 submatch = matchmod.narrowmatcher(subpath, match)
1913 subbad, subforgot = sub.forget(ui, submatch, prefix)
1913 subbad, subforgot = sub.forget(ui, submatch, prefix)
1914 bad.extend([subpath + '/' + f for f in subbad])
1914 bad.extend([subpath + '/' + f for f in subbad])
1915 forgot.extend([subpath + '/' + f for f in subforgot])
1915 forgot.extend([subpath + '/' + f for f in subforgot])
1916 except error.LookupError:
1916 except error.LookupError:
1917 ui.status(_("skipping missing subrepository: %s\n")
1917 ui.status(_("skipping missing subrepository: %s\n")
1918 % join(subpath))
1918 % join(subpath))
1919
1919
1920 if not explicitonly:
1920 if not explicitonly:
1921 for f in match.files():
1921 for f in match.files():
1922 if f not in repo.dirstate and not os.path.isdir(match.rel(join(f))):
1922 if f not in repo.dirstate and not os.path.isdir(match.rel(join(f))):
1923 if f not in forgot:
1923 if f not in forgot:
1924 if os.path.exists(match.rel(join(f))):
1924 if os.path.exists(match.rel(join(f))):
1925 ui.warn(_('not removing %s: '
1925 ui.warn(_('not removing %s: '
1926 'file is already untracked\n')
1926 'file is already untracked\n')
1927 % match.rel(join(f)))
1927 % match.rel(join(f)))
1928 bad.append(f)
1928 bad.append(f)
1929
1929
1930 for f in forget:
1930 for f in forget:
1931 if ui.verbose or not match.exact(f):
1931 if ui.verbose or not match.exact(f):
1932 ui.status(_('removing %s\n') % match.rel(join(f)))
1932 ui.status(_('removing %s\n') % match.rel(join(f)))
1933
1933
1934 rejected = wctx.forget(forget, prefix)
1934 rejected = wctx.forget(forget, prefix)
1935 bad.extend(f for f in rejected if f in match.files())
1935 bad.extend(f for f in rejected if f in match.files())
1936 forgot.extend(forget)
1936 forgot.extend(forget)
1937 return bad, forgot
1937 return bad, forgot
1938
1938
1939 def cat(ui, repo, ctx, matcher, prefix, **opts):
1939 def cat(ui, repo, ctx, matcher, prefix, **opts):
1940 err = 1
1940 err = 1
1941
1941
1942 def write(path):
1942 def write(path):
1943 fp = makefileobj(repo, opts.get('output'), ctx.node(),
1943 fp = makefileobj(repo, opts.get('output'), ctx.node(),
1944 pathname=os.path.join(prefix, path))
1944 pathname=os.path.join(prefix, path))
1945 data = ctx[path].data()
1945 data = ctx[path].data()
1946 if opts.get('decode'):
1946 if opts.get('decode'):
1947 data = repo.wwritedata(path, data)
1947 data = repo.wwritedata(path, data)
1948 fp.write(data)
1948 fp.write(data)
1949 fp.close()
1949 fp.close()
1950
1950
1951 # Automation often uses hg cat on single files, so special case it
1951 # Automation often uses hg cat on single files, so special case it
1952 # for performance to avoid the cost of parsing the manifest.
1952 # for performance to avoid the cost of parsing the manifest.
1953 if len(matcher.files()) == 1 and not matcher.anypats():
1953 if len(matcher.files()) == 1 and not matcher.anypats():
1954 file = matcher.files()[0]
1954 file = matcher.files()[0]
1955 mf = repo.manifest
1955 mf = repo.manifest
1956 mfnode = ctx._changeset[0]
1956 mfnode = ctx._changeset[0]
1957 if mf.find(mfnode, file)[0]:
1957 if mf.find(mfnode, file)[0]:
1958 write(file)
1958 write(file)
1959 return 0
1959 return 0
1960
1960
1961 # Don't warn about "missing" files that are really in subrepos
1961 # Don't warn about "missing" files that are really in subrepos
1962 bad = matcher.bad
1962 bad = matcher.bad
1963
1963
1964 def badfn(path, msg):
1964 def badfn(path, msg):
1965 for subpath in ctx.substate:
1965 for subpath in ctx.substate:
1966 if path.startswith(subpath):
1966 if path.startswith(subpath):
1967 return
1967 return
1968 bad(path, msg)
1968 bad(path, msg)
1969
1969
1970 matcher.bad = badfn
1970 matcher.bad = badfn
1971
1971
1972 for abs in ctx.walk(matcher):
1972 for abs in ctx.walk(matcher):
1973 write(abs)
1973 write(abs)
1974 err = 0
1974 err = 0
1975
1975
1976 matcher.bad = bad
1976 matcher.bad = bad
1977
1977
1978 for subpath in sorted(ctx.substate):
1978 for subpath in sorted(ctx.substate):
1979 sub = ctx.sub(subpath)
1979 sub = ctx.sub(subpath)
1980 try:
1980 try:
1981 submatch = matchmod.narrowmatcher(subpath, matcher)
1981 submatch = matchmod.narrowmatcher(subpath, matcher)
1982
1982
1983 if not sub.cat(ui, submatch, os.path.join(prefix, sub._path),
1983 if not sub.cat(ui, submatch, os.path.join(prefix, sub._path),
1984 **opts):
1984 **opts):
1985 err = 0
1985 err = 0
1986 except error.RepoLookupError:
1986 except error.RepoLookupError:
1987 ui.status(_("skipping missing subrepository: %s\n")
1987 ui.status(_("skipping missing subrepository: %s\n")
1988 % os.path.join(prefix, subpath))
1988 % os.path.join(prefix, subpath))
1989
1989
1990 return err
1990 return err
1991
1991
1992 def duplicatecopies(repo, rev, fromrev, skiprev=None):
1992 def duplicatecopies(repo, rev, fromrev, skiprev=None):
1993 '''reproduce copies from fromrev to rev in the dirstate
1993 '''reproduce copies from fromrev to rev in the dirstate
1994
1994
1995 If skiprev is specified, it's a revision that should be used to
1995 If skiprev is specified, it's a revision that should be used to
1996 filter copy records. Any copies that occur between fromrev and
1996 filter copy records. Any copies that occur between fromrev and
1997 skiprev will not be duplicated, even if they appear in the set of
1997 skiprev will not be duplicated, even if they appear in the set of
1998 copies between fromrev and rev.
1998 copies between fromrev and rev.
1999 '''
1999 '''
2000 exclude = {}
2000 exclude = {}
2001 if skiprev is not None:
2001 if skiprev is not None:
2002 exclude = copies.pathcopies(repo[fromrev], repo[skiprev])
2002 exclude = copies.pathcopies(repo[fromrev], repo[skiprev])
2003 for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems():
2003 for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems():
2004 # copies.pathcopies returns backward renames, so dst might not
2004 # copies.pathcopies returns backward renames, so dst might not
2005 # actually be in the dirstate
2005 # actually be in the dirstate
2006 if dst in exclude:
2006 if dst in exclude:
2007 continue
2007 continue
2008 if repo.dirstate[dst] in "nma":
2008 if repo.dirstate[dst] in "nma":
2009 repo.dirstate.copy(src, dst)
2009 repo.dirstate.copy(src, dst)
2010
2010
2011 def commit(ui, repo, commitfunc, pats, opts):
2011 def commit(ui, repo, commitfunc, pats, opts):
2012 '''commit the specified files or all outstanding changes'''
2012 '''commit the specified files or all outstanding changes'''
2013 date = opts.get('date')
2013 date = opts.get('date')
2014 if date:
2014 if date:
2015 opts['date'] = util.parsedate(date)
2015 opts['date'] = util.parsedate(date)
2016 message = logmessage(ui, opts)
2016 message = logmessage(ui, opts)
2017
2017
2018 # extract addremove carefully -- this function can be called from a command
2018 # extract addremove carefully -- this function can be called from a command
2019 # that doesn't support addremove
2019 # that doesn't support addremove
2020 if opts.get('addremove'):
2020 if opts.get('addremove'):
2021 scmutil.addremove(repo, pats, opts)
2021 scmutil.addremove(repo, pats, opts)
2022
2022
2023 return commitfunc(ui, repo, message,
2023 return commitfunc(ui, repo, message,
2024 scmutil.match(repo[None], pats, opts), opts)
2024 scmutil.match(repo[None], pats, opts), opts)
2025
2025
2026 def amend(ui, repo, commitfunc, old, extra, pats, opts):
2026 def amend(ui, repo, commitfunc, old, extra, pats, opts):
2027 ui.note(_('amending changeset %s\n') % old)
2027 ui.note(_('amending changeset %s\n') % old)
2028 base = old.p1()
2028 base = old.p1()
2029
2029
2030 wlock = lock = newid = None
2030 wlock = lock = newid = None
2031 try:
2031 try:
2032 wlock = repo.wlock()
2032 wlock = repo.wlock()
2033 lock = repo.lock()
2033 lock = repo.lock()
2034 tr = repo.transaction('amend')
2034 tr = repo.transaction('amend')
2035 try:
2035 try:
2036 # See if we got a message from -m or -l, if not, open the editor
2036 # See if we got a message from -m or -l, if not, open the editor
2037 # with the message of the changeset to amend
2037 # with the message of the changeset to amend
2038 message = logmessage(ui, opts)
2038 message = logmessage(ui, opts)
2039 # ensure logfile does not conflict with later enforcement of the
2039 # ensure logfile does not conflict with later enforcement of the
2040 # message. potential logfile content has been processed by
2040 # message. potential logfile content has been processed by
2041 # `logmessage` anyway.
2041 # `logmessage` anyway.
2042 opts.pop('logfile')
2042 opts.pop('logfile')
2043 # First, do a regular commit to record all changes in the working
2043 # First, do a regular commit to record all changes in the working
2044 # directory (if there are any)
2044 # directory (if there are any)
2045 ui.callhooks = False
2045 ui.callhooks = False
2046 currentbookmark = repo._bookmarkcurrent
2046 currentbookmark = repo._bookmarkcurrent
2047 try:
2047 try:
2048 repo._bookmarkcurrent = None
2048 repo._bookmarkcurrent = None
2049 opts['message'] = 'temporary amend commit for %s' % old
2049 opts['message'] = 'temporary amend commit for %s' % old
2050 node = commit(ui, repo, commitfunc, pats, opts)
2050 node = commit(ui, repo, commitfunc, pats, opts)
2051 finally:
2051 finally:
2052 repo._bookmarkcurrent = currentbookmark
2052 repo._bookmarkcurrent = currentbookmark
2053 ui.callhooks = True
2053 ui.callhooks = True
2054 ctx = repo[node]
2054 ctx = repo[node]
2055
2055
2056 # Participating changesets:
2056 # Participating changesets:
2057 #
2057 #
2058 # node/ctx o - new (intermediate) commit that contains changes
2058 # node/ctx o - new (intermediate) commit that contains changes
2059 # | from working dir to go into amending commit
2059 # | from working dir to go into amending commit
2060 # | (or a workingctx if there were no changes)
2060 # | (or a workingctx if there were no changes)
2061 # |
2061 # |
2062 # old o - changeset to amend
2062 # old o - changeset to amend
2063 # |
2063 # |
2064 # base o - parent of amending changeset
2064 # base o - parent of amending changeset
2065
2065
2066 # Update extra dict from amended commit (e.g. to preserve graft
2066 # Update extra dict from amended commit (e.g. to preserve graft
2067 # source)
2067 # source)
2068 extra.update(old.extra())
2068 extra.update(old.extra())
2069
2069
2070 # Also update it from the intermediate commit or from the wctx
2070 # Also update it from the intermediate commit or from the wctx
2071 extra.update(ctx.extra())
2071 extra.update(ctx.extra())
2072
2072
2073 if len(old.parents()) > 1:
2073 if len(old.parents()) > 1:
2074 # ctx.files() isn't reliable for merges, so fall back to the
2074 # ctx.files() isn't reliable for merges, so fall back to the
2075 # slower repo.status() method
2075 # slower repo.status() method
2076 files = set([fn for st in repo.status(base, old)[:3]
2076 files = set([fn for st in repo.status(base, old)[:3]
2077 for fn in st])
2077 for fn in st])
2078 else:
2078 else:
2079 files = set(old.files())
2079 files = set(old.files())
2080
2080
2081 # Second, we use either the commit we just did, or if there were no
2081 # Second, we use either the commit we just did, or if there were no
2082 # changes the parent of the working directory as the version of the
2082 # changes the parent of the working directory as the version of the
2083 # files in the final amend commit
2083 # files in the final amend commit
2084 if node:
2084 if node:
2085 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
2085 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
2086
2086
2087 user = ctx.user()
2087 user = ctx.user()
2088 date = ctx.date()
2088 date = ctx.date()
2089 # Recompute copies (avoid recording a -> b -> a)
2089 # Recompute copies (avoid recording a -> b -> a)
2090 copied = copies.pathcopies(base, ctx)
2090 copied = copies.pathcopies(base, ctx)
2091
2091
2092 # Prune files which were reverted by the updates: if old
2092 # Prune files which were reverted by the updates: if old
2093 # introduced file X and our intermediate commit, node,
2093 # introduced file X and our intermediate commit, node,
2094 # renamed that file, then those two files are the same and
2094 # renamed that file, then those two files are the same and
2095 # we can discard X from our list of files. Likewise if X
2095 # we can discard X from our list of files. Likewise if X
2096 # was deleted, it's no longer relevant
2096 # was deleted, it's no longer relevant
2097 files.update(ctx.files())
2097 files.update(ctx.files())
2098
2098
2099 def samefile(f):
2099 def samefile(f):
2100 if f in ctx.manifest():
2100 if f in ctx.manifest():
2101 a = ctx.filectx(f)
2101 a = ctx.filectx(f)
2102 if f in base.manifest():
2102 if f in base.manifest():
2103 b = base.filectx(f)
2103 b = base.filectx(f)
2104 return (not a.cmp(b)
2104 return (not a.cmp(b)
2105 and a.flags() == b.flags())
2105 and a.flags() == b.flags())
2106 else:
2106 else:
2107 return False
2107 return False
2108 else:
2108 else:
2109 return f not in base.manifest()
2109 return f not in base.manifest()
2110 files = [f for f in files if not samefile(f)]
2110 files = [f for f in files if not samefile(f)]
2111
2111
2112 def filectxfn(repo, ctx_, path):
2112 def filectxfn(repo, ctx_, path):
2113 try:
2113 try:
2114 fctx = ctx[path]
2114 fctx = ctx[path]
2115 flags = fctx.flags()
2115 flags = fctx.flags()
2116 mctx = context.memfilectx(repo,
2116 mctx = context.memfilectx(repo,
2117 fctx.path(), fctx.data(),
2117 fctx.path(), fctx.data(),
2118 islink='l' in flags,
2118 islink='l' in flags,
2119 isexec='x' in flags,
2119 isexec='x' in flags,
2120 copied=copied.get(path))
2120 copied=copied.get(path))
2121 return mctx
2121 return mctx
2122 except KeyError:
2122 except KeyError:
2123 raise IOError
2123 raise IOError
2124 else:
2124 else:
2125 ui.note(_('copying changeset %s to %s\n') % (old, base))
2125 ui.note(_('copying changeset %s to %s\n') % (old, base))
2126
2126
2127 # Use version of files as in the old cset
2127 # Use version of files as in the old cset
2128 def filectxfn(repo, ctx_, path):
2128 def filectxfn(repo, ctx_, path):
2129 try:
2129 try:
2130 return old.filectx(path)
2130 return old.filectx(path)
2131 except KeyError:
2131 except KeyError:
2132 raise IOError
2132 raise IOError
2133
2133
2134 user = opts.get('user') or old.user()
2134 user = opts.get('user') or old.user()
2135 date = opts.get('date') or old.date()
2135 date = opts.get('date') or old.date()
2136 editform = 'commit.amend'
2136 editform = mergeeditform(old, 'commit.amend')
2137 editor = getcommiteditor(editform=editform, **opts)
2137 editor = getcommiteditor(editform=editform, **opts)
2138 if not message:
2138 if not message:
2139 editor = getcommiteditor(edit=True, editform=editform)
2139 editor = getcommiteditor(edit=True, editform=editform)
2140 message = old.description()
2140 message = old.description()
2141
2141
2142 pureextra = extra.copy()
2142 pureextra = extra.copy()
2143 extra['amend_source'] = old.hex()
2143 extra['amend_source'] = old.hex()
2144
2144
2145 new = context.memctx(repo,
2145 new = context.memctx(repo,
2146 parents=[base.node(), old.p2().node()],
2146 parents=[base.node(), old.p2().node()],
2147 text=message,
2147 text=message,
2148 files=files,
2148 files=files,
2149 filectxfn=filectxfn,
2149 filectxfn=filectxfn,
2150 user=user,
2150 user=user,
2151 date=date,
2151 date=date,
2152 extra=extra,
2152 extra=extra,
2153 editor=editor)
2153 editor=editor)
2154
2154
2155 newdesc = changelog.stripdesc(new.description())
2155 newdesc = changelog.stripdesc(new.description())
2156 if ((not node)
2156 if ((not node)
2157 and newdesc == old.description()
2157 and newdesc == old.description()
2158 and user == old.user()
2158 and user == old.user()
2159 and date == old.date()
2159 and date == old.date()
2160 and pureextra == old.extra()):
2160 and pureextra == old.extra()):
2161 # nothing changed. continuing here would create a new node
2161 # nothing changed. continuing here would create a new node
2162 # anyway because of the amend_source noise.
2162 # anyway because of the amend_source noise.
2163 #
2163 #
2164 # This not what we expect from amend.
2164 # This not what we expect from amend.
2165 return old.node()
2165 return old.node()
2166
2166
2167 ph = repo.ui.config('phases', 'new-commit', phases.draft)
2167 ph = repo.ui.config('phases', 'new-commit', phases.draft)
2168 try:
2168 try:
2169 if opts.get('secret'):
2169 if opts.get('secret'):
2170 commitphase = 'secret'
2170 commitphase = 'secret'
2171 else:
2171 else:
2172 commitphase = old.phase()
2172 commitphase = old.phase()
2173 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend')
2173 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend')
2174 newid = repo.commitctx(new)
2174 newid = repo.commitctx(new)
2175 finally:
2175 finally:
2176 repo.ui.setconfig('phases', 'new-commit', ph, 'amend')
2176 repo.ui.setconfig('phases', 'new-commit', ph, 'amend')
2177 if newid != old.node():
2177 if newid != old.node():
2178 # Reroute the working copy parent to the new changeset
2178 # Reroute the working copy parent to the new changeset
2179 repo.setparents(newid, nullid)
2179 repo.setparents(newid, nullid)
2180
2180
2181 # Move bookmarks from old parent to amend commit
2181 # Move bookmarks from old parent to amend commit
2182 bms = repo.nodebookmarks(old.node())
2182 bms = repo.nodebookmarks(old.node())
2183 if bms:
2183 if bms:
2184 marks = repo._bookmarks
2184 marks = repo._bookmarks
2185 for bm in bms:
2185 for bm in bms:
2186 marks[bm] = newid
2186 marks[bm] = newid
2187 marks.write()
2187 marks.write()
2188 #commit the whole amend process
2188 #commit the whole amend process
2189 if obsolete._enabled and newid != old.node():
2189 if obsolete._enabled and newid != old.node():
2190 # mark the new changeset as successor of the rewritten one
2190 # mark the new changeset as successor of the rewritten one
2191 new = repo[newid]
2191 new = repo[newid]
2192 obs = [(old, (new,))]
2192 obs = [(old, (new,))]
2193 if node:
2193 if node:
2194 obs.append((ctx, ()))
2194 obs.append((ctx, ()))
2195
2195
2196 obsolete.createmarkers(repo, obs)
2196 obsolete.createmarkers(repo, obs)
2197 tr.close()
2197 tr.close()
2198 finally:
2198 finally:
2199 tr.release()
2199 tr.release()
2200 if (not obsolete._enabled) and newid != old.node():
2200 if (not obsolete._enabled) and newid != old.node():
2201 # Strip the intermediate commit (if there was one) and the amended
2201 # Strip the intermediate commit (if there was one) and the amended
2202 # commit
2202 # commit
2203 if node:
2203 if node:
2204 ui.note(_('stripping intermediate changeset %s\n') % ctx)
2204 ui.note(_('stripping intermediate changeset %s\n') % ctx)
2205 ui.note(_('stripping amended changeset %s\n') % old)
2205 ui.note(_('stripping amended changeset %s\n') % old)
2206 repair.strip(ui, repo, old.node(), topic='amend-backup')
2206 repair.strip(ui, repo, old.node(), topic='amend-backup')
2207 finally:
2207 finally:
2208 if newid is None:
2208 if newid is None:
2209 repo.dirstate.invalidate()
2209 repo.dirstate.invalidate()
2210 lockmod.release(lock, wlock)
2210 lockmod.release(lock, wlock)
2211 return newid
2211 return newid
2212
2212
2213 def commiteditor(repo, ctx, subs, editform=''):
2213 def commiteditor(repo, ctx, subs, editform=''):
2214 if ctx.description():
2214 if ctx.description():
2215 return ctx.description()
2215 return ctx.description()
2216 return commitforceeditor(repo, ctx, subs, editform=editform)
2216 return commitforceeditor(repo, ctx, subs, editform=editform)
2217
2217
2218 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
2218 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
2219 editform=''):
2219 editform=''):
2220 if not extramsg:
2220 if not extramsg:
2221 extramsg = _("Leave message empty to abort commit.")
2221 extramsg = _("Leave message empty to abort commit.")
2222
2222
2223 forms = [e for e in editform.split('.') if e]
2223 forms = [e for e in editform.split('.') if e]
2224 forms.insert(0, 'changeset')
2224 forms.insert(0, 'changeset')
2225 while forms:
2225 while forms:
2226 tmpl = repo.ui.config('committemplate', '.'.join(forms))
2226 tmpl = repo.ui.config('committemplate', '.'.join(forms))
2227 if tmpl:
2227 if tmpl:
2228 committext = buildcommittemplate(repo, ctx, subs, extramsg, tmpl)
2228 committext = buildcommittemplate(repo, ctx, subs, extramsg, tmpl)
2229 break
2229 break
2230 forms.pop()
2230 forms.pop()
2231 else:
2231 else:
2232 committext = buildcommittext(repo, ctx, subs, extramsg)
2232 committext = buildcommittext(repo, ctx, subs, extramsg)
2233
2233
2234 # run editor in the repository root
2234 # run editor in the repository root
2235 olddir = os.getcwd()
2235 olddir = os.getcwd()
2236 os.chdir(repo.root)
2236 os.chdir(repo.root)
2237 text = repo.ui.edit(committext, ctx.user(), ctx.extra(), editform=editform)
2237 text = repo.ui.edit(committext, ctx.user(), ctx.extra(), editform=editform)
2238 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
2238 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
2239 os.chdir(olddir)
2239 os.chdir(olddir)
2240
2240
2241 if finishdesc:
2241 if finishdesc:
2242 text = finishdesc(text)
2242 text = finishdesc(text)
2243 if not text.strip():
2243 if not text.strip():
2244 raise util.Abort(_("empty commit message"))
2244 raise util.Abort(_("empty commit message"))
2245
2245
2246 return text
2246 return text
2247
2247
2248 def buildcommittemplate(repo, ctx, subs, extramsg, tmpl):
2248 def buildcommittemplate(repo, ctx, subs, extramsg, tmpl):
2249 ui = repo.ui
2249 ui = repo.ui
2250 tmpl, mapfile = gettemplate(ui, tmpl, None)
2250 tmpl, mapfile = gettemplate(ui, tmpl, None)
2251
2251
2252 try:
2252 try:
2253 t = changeset_templater(ui, repo, None, {}, tmpl, mapfile, False)
2253 t = changeset_templater(ui, repo, None, {}, tmpl, mapfile, False)
2254 except SyntaxError, inst:
2254 except SyntaxError, inst:
2255 raise util.Abort(inst.args[0])
2255 raise util.Abort(inst.args[0])
2256
2256
2257 for k, v in repo.ui.configitems('committemplate'):
2257 for k, v in repo.ui.configitems('committemplate'):
2258 if k != 'changeset':
2258 if k != 'changeset':
2259 t.t.cache[k] = v
2259 t.t.cache[k] = v
2260
2260
2261 if not extramsg:
2261 if not extramsg:
2262 extramsg = '' # ensure that extramsg is string
2262 extramsg = '' # ensure that extramsg is string
2263
2263
2264 ui.pushbuffer()
2264 ui.pushbuffer()
2265 t.show(ctx, extramsg=extramsg)
2265 t.show(ctx, extramsg=extramsg)
2266 return ui.popbuffer()
2266 return ui.popbuffer()
2267
2267
2268 def buildcommittext(repo, ctx, subs, extramsg):
2268 def buildcommittext(repo, ctx, subs, extramsg):
2269 edittext = []
2269 edittext = []
2270 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
2270 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
2271 if ctx.description():
2271 if ctx.description():
2272 edittext.append(ctx.description())
2272 edittext.append(ctx.description())
2273 edittext.append("")
2273 edittext.append("")
2274 edittext.append("") # Empty line between message and comments.
2274 edittext.append("") # Empty line between message and comments.
2275 edittext.append(_("HG: Enter commit message."
2275 edittext.append(_("HG: Enter commit message."
2276 " Lines beginning with 'HG:' are removed."))
2276 " Lines beginning with 'HG:' are removed."))
2277 edittext.append("HG: %s" % extramsg)
2277 edittext.append("HG: %s" % extramsg)
2278 edittext.append("HG: --")
2278 edittext.append("HG: --")
2279 edittext.append(_("HG: user: %s") % ctx.user())
2279 edittext.append(_("HG: user: %s") % ctx.user())
2280 if ctx.p2():
2280 if ctx.p2():
2281 edittext.append(_("HG: branch merge"))
2281 edittext.append(_("HG: branch merge"))
2282 if ctx.branch():
2282 if ctx.branch():
2283 edittext.append(_("HG: branch '%s'") % ctx.branch())
2283 edittext.append(_("HG: branch '%s'") % ctx.branch())
2284 if bookmarks.iscurrent(repo):
2284 if bookmarks.iscurrent(repo):
2285 edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
2285 edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
2286 edittext.extend([_("HG: subrepo %s") % s for s in subs])
2286 edittext.extend([_("HG: subrepo %s") % s for s in subs])
2287 edittext.extend([_("HG: added %s") % f for f in added])
2287 edittext.extend([_("HG: added %s") % f for f in added])
2288 edittext.extend([_("HG: changed %s") % f for f in modified])
2288 edittext.extend([_("HG: changed %s") % f for f in modified])
2289 edittext.extend([_("HG: removed %s") % f for f in removed])
2289 edittext.extend([_("HG: removed %s") % f for f in removed])
2290 if not added and not modified and not removed:
2290 if not added and not modified and not removed:
2291 edittext.append(_("HG: no files changed"))
2291 edittext.append(_("HG: no files changed"))
2292 edittext.append("")
2292 edittext.append("")
2293
2293
2294 return "\n".join(edittext)
2294 return "\n".join(edittext)
2295
2295
2296 def commitstatus(repo, node, branch, bheads=None, opts={}):
2296 def commitstatus(repo, node, branch, bheads=None, opts={}):
2297 ctx = repo[node]
2297 ctx = repo[node]
2298 parents = ctx.parents()
2298 parents = ctx.parents()
2299
2299
2300 if (not opts.get('amend') and bheads and node not in bheads and not
2300 if (not opts.get('amend') and bheads and node not in bheads and not
2301 [x for x in parents if x.node() in bheads and x.branch() == branch]):
2301 [x for x in parents if x.node() in bheads and x.branch() == branch]):
2302 repo.ui.status(_('created new head\n'))
2302 repo.ui.status(_('created new head\n'))
2303 # The message is not printed for initial roots. For the other
2303 # The message is not printed for initial roots. For the other
2304 # changesets, it is printed in the following situations:
2304 # changesets, it is printed in the following situations:
2305 #
2305 #
2306 # Par column: for the 2 parents with ...
2306 # Par column: for the 2 parents with ...
2307 # N: null or no parent
2307 # N: null or no parent
2308 # B: parent is on another named branch
2308 # B: parent is on another named branch
2309 # C: parent is a regular non head changeset
2309 # C: parent is a regular non head changeset
2310 # H: parent was a branch head of the current branch
2310 # H: parent was a branch head of the current branch
2311 # Msg column: whether we print "created new head" message
2311 # Msg column: whether we print "created new head" message
2312 # In the following, it is assumed that there already exists some
2312 # In the following, it is assumed that there already exists some
2313 # initial branch heads of the current branch, otherwise nothing is
2313 # initial branch heads of the current branch, otherwise nothing is
2314 # printed anyway.
2314 # printed anyway.
2315 #
2315 #
2316 # Par Msg Comment
2316 # Par Msg Comment
2317 # N N y additional topo root
2317 # N N y additional topo root
2318 #
2318 #
2319 # B N y additional branch root
2319 # B N y additional branch root
2320 # C N y additional topo head
2320 # C N y additional topo head
2321 # H N n usual case
2321 # H N n usual case
2322 #
2322 #
2323 # B B y weird additional branch root
2323 # B B y weird additional branch root
2324 # C B y branch merge
2324 # C B y branch merge
2325 # H B n merge with named branch
2325 # H B n merge with named branch
2326 #
2326 #
2327 # C C y additional head from merge
2327 # C C y additional head from merge
2328 # C H n merge with a head
2328 # C H n merge with a head
2329 #
2329 #
2330 # H H n head merge: head count decreases
2330 # H H n head merge: head count decreases
2331
2331
2332 if not opts.get('close_branch'):
2332 if not opts.get('close_branch'):
2333 for r in parents:
2333 for r in parents:
2334 if r.closesbranch() and r.branch() == branch:
2334 if r.closesbranch() and r.branch() == branch:
2335 repo.ui.status(_('reopening closed branch head %d\n') % r)
2335 repo.ui.status(_('reopening closed branch head %d\n') % r)
2336
2336
2337 if repo.ui.debugflag:
2337 if repo.ui.debugflag:
2338 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
2338 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
2339 elif repo.ui.verbose:
2339 elif repo.ui.verbose:
2340 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
2340 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
2341
2341
2342 def revert(ui, repo, ctx, parents, *pats, **opts):
2342 def revert(ui, repo, ctx, parents, *pats, **opts):
2343 parent, p2 = parents
2343 parent, p2 = parents
2344 node = ctx.node()
2344 node = ctx.node()
2345
2345
2346 mf = ctx.manifest()
2346 mf = ctx.manifest()
2347 if node == p2:
2347 if node == p2:
2348 parent = p2
2348 parent = p2
2349 if node == parent:
2349 if node == parent:
2350 pmf = mf
2350 pmf = mf
2351 else:
2351 else:
2352 pmf = None
2352 pmf = None
2353
2353
2354 # need all matching names in dirstate and manifest of target rev,
2354 # need all matching names in dirstate and manifest of target rev,
2355 # so have to walk both. do not print errors if files exist in one
2355 # so have to walk both. do not print errors if files exist in one
2356 # but not other.
2356 # but not other.
2357
2357
2358 # `names` is a mapping for all elements in working copy and target revision
2358 # `names` is a mapping for all elements in working copy and target revision
2359 # The mapping is in the form:
2359 # The mapping is in the form:
2360 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
2360 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
2361 names = {}
2361 names = {}
2362
2362
2363 wlock = repo.wlock()
2363 wlock = repo.wlock()
2364 try:
2364 try:
2365 ## filling of the `names` mapping
2365 ## filling of the `names` mapping
2366 # walk dirstate to fill `names`
2366 # walk dirstate to fill `names`
2367
2367
2368 m = scmutil.match(repo[None], pats, opts)
2368 m = scmutil.match(repo[None], pats, opts)
2369 m.bad = lambda x, y: False
2369 m.bad = lambda x, y: False
2370 for abs in repo.walk(m):
2370 for abs in repo.walk(m):
2371 names[abs] = m.rel(abs), m.exact(abs)
2371 names[abs] = m.rel(abs), m.exact(abs)
2372
2372
2373 # walk target manifest to fill `names`
2373 # walk target manifest to fill `names`
2374
2374
2375 def badfn(path, msg):
2375 def badfn(path, msg):
2376 if path in names:
2376 if path in names:
2377 return
2377 return
2378 if path in ctx.substate:
2378 if path in ctx.substate:
2379 return
2379 return
2380 path_ = path + '/'
2380 path_ = path + '/'
2381 for f in names:
2381 for f in names:
2382 if f.startswith(path_):
2382 if f.startswith(path_):
2383 return
2383 return
2384 ui.warn("%s: %s\n" % (m.rel(path), msg))
2384 ui.warn("%s: %s\n" % (m.rel(path), msg))
2385
2385
2386 m = scmutil.match(ctx, pats, opts)
2386 m = scmutil.match(ctx, pats, opts)
2387 m.bad = badfn
2387 m.bad = badfn
2388 for abs in ctx.walk(m):
2388 for abs in ctx.walk(m):
2389 if abs not in names:
2389 if abs not in names:
2390 names[abs] = m.rel(abs), m.exact(abs)
2390 names[abs] = m.rel(abs), m.exact(abs)
2391
2391
2392 # get the list of subrepos that must be reverted
2392 # get the list of subrepos that must be reverted
2393 targetsubs = sorted(s for s in ctx.substate if m(s))
2393 targetsubs = sorted(s for s in ctx.substate if m(s))
2394
2394
2395 # Find status of all file in `names`.
2395 # Find status of all file in `names`.
2396 m = scmutil.matchfiles(repo, names)
2396 m = scmutil.matchfiles(repo, names)
2397
2397
2398 changes = repo.status(node1=node, match=m,
2398 changes = repo.status(node1=node, match=m,
2399 unknown=True, ignored=True, clean=True)
2399 unknown=True, ignored=True, clean=True)
2400 modified = set(changes[0])
2400 modified = set(changes[0])
2401 added = set(changes[1])
2401 added = set(changes[1])
2402 removed = set(changes[2])
2402 removed = set(changes[2])
2403 _deleted = set(changes[3])
2403 _deleted = set(changes[3])
2404 unknown = set(changes[4])
2404 unknown = set(changes[4])
2405 unknown.update(changes[5])
2405 unknown.update(changes[5])
2406 clean = set(changes[6])
2406 clean = set(changes[6])
2407
2407
2408 # split between files known in target manifest and the others
2408 # split between files known in target manifest and the others
2409 smf = set(mf)
2409 smf = set(mf)
2410
2410
2411 # determine the exact nature of the deleted changesets
2411 # determine the exact nature of the deleted changesets
2412 _deletedadded = _deleted - smf
2412 _deletedadded = _deleted - smf
2413 _deletedmodified = _deleted - _deletedadded
2413 _deletedmodified = _deleted - _deletedadded
2414 added |= _deletedadded
2414 added |= _deletedadded
2415 modified |= _deletedmodified
2415 modified |= _deletedmodified
2416
2416
2417 # We need to account for the state of file in the dirstate
2417 # We need to account for the state of file in the dirstate
2418 #
2418 #
2419 # Even, when we revert agains something else than parent. this will
2419 # Even, when we revert agains something else than parent. this will
2420 # slightly alter the behavior of revert (doing back up or not, delete
2420 # slightly alter the behavior of revert (doing back up or not, delete
2421 # or just forget etc)
2421 # or just forget etc)
2422 if parent == node:
2422 if parent == node:
2423 dsmodified = modified
2423 dsmodified = modified
2424 dsadded = added
2424 dsadded = added
2425 dsremoved = removed
2425 dsremoved = removed
2426 modified, added, removed = set(), set(), set()
2426 modified, added, removed = set(), set(), set()
2427 else:
2427 else:
2428 changes = repo.status(node1=parent, match=m)
2428 changes = repo.status(node1=parent, match=m)
2429 dsmodified = set(changes[0])
2429 dsmodified = set(changes[0])
2430 dsadded = set(changes[1])
2430 dsadded = set(changes[1])
2431 dsremoved = set(changes[2])
2431 dsremoved = set(changes[2])
2432
2432
2433 # only take into account for removes between wc and target
2433 # only take into account for removes between wc and target
2434 clean |= dsremoved - removed
2434 clean |= dsremoved - removed
2435 dsremoved &= removed
2435 dsremoved &= removed
2436 # distinct between dirstate remove and other
2436 # distinct between dirstate remove and other
2437 removed -= dsremoved
2437 removed -= dsremoved
2438
2438
2439 # tell newly modified apart.
2439 # tell newly modified apart.
2440 dsmodified &= modified
2440 dsmodified &= modified
2441 dsmodified |= modified & dsadded # dirstate added may needs backup
2441 dsmodified |= modified & dsadded # dirstate added may needs backup
2442 modified -= dsmodified
2442 modified -= dsmodified
2443
2443
2444 # There are three categories of added files
2444 # There are three categories of added files
2445 #
2445 #
2446 # 1. addition that just happened in the dirstate
2446 # 1. addition that just happened in the dirstate
2447 # (should be forgotten)
2447 # (should be forgotten)
2448 # 2. file is added since target revision and has local changes
2448 # 2. file is added since target revision and has local changes
2449 # (should be backed up and removed)
2449 # (should be backed up and removed)
2450 # 3. file is added since target revision and is clean
2450 # 3. file is added since target revision and is clean
2451 # (should be removed)
2451 # (should be removed)
2452 #
2452 #
2453 # However we do not need to split them yet. The current revert code
2453 # However we do not need to split them yet. The current revert code
2454 # will automatically recognize (1) when performing operation. And
2454 # will automatically recognize (1) when performing operation. And
2455 # the backup system is currently unabled to handle (2).
2455 # the backup system is currently unabled to handle (2).
2456 #
2456 #
2457 # So we just put them all in the same group.
2457 # So we just put them all in the same group.
2458 dsadded = added
2458 dsadded = added
2459
2459
2460 # in case of merge, files that are actually added can be reported as
2460 # in case of merge, files that are actually added can be reported as
2461 # modified, we need to post process the result
2461 # modified, we need to post process the result
2462 if p2 != nullid:
2462 if p2 != nullid:
2463 if pmf is None:
2463 if pmf is None:
2464 # only need parent manifest in the merge case,
2464 # only need parent manifest in the merge case,
2465 # so do not read by default
2465 # so do not read by default
2466 pmf = repo[parent].manifest()
2466 pmf = repo[parent].manifest()
2467 mergeadd = dsmodified - set(pmf)
2467 mergeadd = dsmodified - set(pmf)
2468 dsadded |= mergeadd
2468 dsadded |= mergeadd
2469 dsmodified -= mergeadd
2469 dsmodified -= mergeadd
2470
2470
2471 # if f is a rename, update `names` to also revert the source
2471 # if f is a rename, update `names` to also revert the source
2472 cwd = repo.getcwd()
2472 cwd = repo.getcwd()
2473 for f in dsadded:
2473 for f in dsadded:
2474 src = repo.dirstate.copied(f)
2474 src = repo.dirstate.copied(f)
2475 # XXX should we check for rename down to target node?
2475 # XXX should we check for rename down to target node?
2476 if src and src not in names and repo.dirstate[src] == 'r':
2476 if src and src not in names and repo.dirstate[src] == 'r':
2477 dsremoved.add(src)
2477 dsremoved.add(src)
2478 names[src] = (repo.pathto(src, cwd), True)
2478 names[src] = (repo.pathto(src, cwd), True)
2479
2479
2480 ## computation of the action to performs on `names` content.
2480 ## computation of the action to performs on `names` content.
2481
2481
2482 def removeforget(abs):
2482 def removeforget(abs):
2483 if repo.dirstate[abs] == 'a':
2483 if repo.dirstate[abs] == 'a':
2484 return _('forgetting %s\n')
2484 return _('forgetting %s\n')
2485 return _('removing %s\n')
2485 return _('removing %s\n')
2486
2486
2487 # action to be actually performed by revert
2487 # action to be actually performed by revert
2488 # (<list of file>, message>) tuple
2488 # (<list of file>, message>) tuple
2489 actions = {'revert': ([], _('reverting %s\n')),
2489 actions = {'revert': ([], _('reverting %s\n')),
2490 'add': ([], _('adding %s\n')),
2490 'add': ([], _('adding %s\n')),
2491 'remove': ([], removeforget),
2491 'remove': ([], removeforget),
2492 'undelete': ([], _('undeleting %s\n')),
2492 'undelete': ([], _('undeleting %s\n')),
2493 'noop': (None, _('no changes needed to %s\n')),
2493 'noop': (None, _('no changes needed to %s\n')),
2494 'unknown': (None, _('file not managed: %s\n')),
2494 'unknown': (None, _('file not managed: %s\n')),
2495 }
2495 }
2496
2496
2497
2497
2498 # should we do a backup?
2498 # should we do a backup?
2499 backup = not opts.get('no_backup')
2499 backup = not opts.get('no_backup')
2500 discard = False
2500 discard = False
2501
2501
2502 disptable = (
2502 disptable = (
2503 # dispatch table:
2503 # dispatch table:
2504 # file state
2504 # file state
2505 # action
2505 # action
2506 # make backup
2506 # make backup
2507 (modified, actions['revert'], discard),
2507 (modified, actions['revert'], discard),
2508 (dsmodified, actions['revert'], backup),
2508 (dsmodified, actions['revert'], backup),
2509 (dsadded, actions['remove'], backup),
2509 (dsadded, actions['remove'], backup),
2510 (removed, actions['add'], backup),
2510 (removed, actions['add'], backup),
2511 (dsremoved, actions['undelete'], backup),
2511 (dsremoved, actions['undelete'], backup),
2512 (clean, actions['noop'], discard),
2512 (clean, actions['noop'], discard),
2513 (unknown, actions['unknown'], discard),
2513 (unknown, actions['unknown'], discard),
2514 )
2514 )
2515
2515
2516 for abs, (rel, exact) in sorted(names.items()):
2516 for abs, (rel, exact) in sorted(names.items()):
2517 # target file to be touch on disk (relative to cwd)
2517 # target file to be touch on disk (relative to cwd)
2518 target = repo.wjoin(abs)
2518 target = repo.wjoin(abs)
2519 # search the entry in the dispatch table.
2519 # search the entry in the dispatch table.
2520 # if the file is in any of these sets, it was touched in the working
2520 # if the file is in any of these sets, it was touched in the working
2521 # directory parent and we are sure it needs to be reverted.
2521 # directory parent and we are sure it needs to be reverted.
2522 for table, (xlist, msg), dobackup in disptable:
2522 for table, (xlist, msg), dobackup in disptable:
2523 if abs not in table:
2523 if abs not in table:
2524 continue
2524 continue
2525 if xlist is not None:
2525 if xlist is not None:
2526 xlist.append(abs)
2526 xlist.append(abs)
2527 if (dobackup and os.path.lexists(target) and
2527 if (dobackup and os.path.lexists(target) and
2528 abs in ctx and repo[None][abs].cmp(ctx[abs])):
2528 abs in ctx and repo[None][abs].cmp(ctx[abs])):
2529 bakname = "%s.orig" % rel
2529 bakname = "%s.orig" % rel
2530 ui.note(_('saving current version of %s as %s\n') %
2530 ui.note(_('saving current version of %s as %s\n') %
2531 (rel, bakname))
2531 (rel, bakname))
2532 if not opts.get('dry_run'):
2532 if not opts.get('dry_run'):
2533 util.rename(target, bakname)
2533 util.rename(target, bakname)
2534 if ui.verbose or not exact:
2534 if ui.verbose or not exact:
2535 if not isinstance(msg, basestring):
2535 if not isinstance(msg, basestring):
2536 msg = msg(abs)
2536 msg = msg(abs)
2537 ui.status(msg % rel)
2537 ui.status(msg % rel)
2538 elif exact:
2538 elif exact:
2539 ui.warn(msg % rel)
2539 ui.warn(msg % rel)
2540 break
2540 break
2541
2541
2542
2542
2543 if not opts.get('dry_run'):
2543 if not opts.get('dry_run'):
2544 _performrevert(repo, parents, ctx, actions)
2544 _performrevert(repo, parents, ctx, actions)
2545
2545
2546 if targetsubs:
2546 if targetsubs:
2547 # Revert the subrepos on the revert list
2547 # Revert the subrepos on the revert list
2548 for sub in targetsubs:
2548 for sub in targetsubs:
2549 ctx.sub(sub).revert(ui, ctx.substate[sub], *pats, **opts)
2549 ctx.sub(sub).revert(ui, ctx.substate[sub], *pats, **opts)
2550 finally:
2550 finally:
2551 wlock.release()
2551 wlock.release()
2552
2552
2553 def _performrevert(repo, parents, ctx, actions):
2553 def _performrevert(repo, parents, ctx, actions):
2554 """function that actually perform all the actions computed for revert
2554 """function that actually perform all the actions computed for revert
2555
2555
2556 This is an independent function to let extension to plug in and react to
2556 This is an independent function to let extension to plug in and react to
2557 the imminent revert.
2557 the imminent revert.
2558
2558
2559 Make sure you have the working directory locked when calling this function.
2559 Make sure you have the working directory locked when calling this function.
2560 """
2560 """
2561 parent, p2 = parents
2561 parent, p2 = parents
2562 node = ctx.node()
2562 node = ctx.node()
2563 def checkout(f):
2563 def checkout(f):
2564 fc = ctx[f]
2564 fc = ctx[f]
2565 repo.wwrite(f, fc.data(), fc.flags())
2565 repo.wwrite(f, fc.data(), fc.flags())
2566
2566
2567 audit_path = pathutil.pathauditor(repo.root)
2567 audit_path = pathutil.pathauditor(repo.root)
2568 for f in actions['remove'][0]:
2568 for f in actions['remove'][0]:
2569 if repo.dirstate[f] == 'a':
2569 if repo.dirstate[f] == 'a':
2570 repo.dirstate.drop(f)
2570 repo.dirstate.drop(f)
2571 continue
2571 continue
2572 audit_path(f)
2572 audit_path(f)
2573 try:
2573 try:
2574 util.unlinkpath(repo.wjoin(f))
2574 util.unlinkpath(repo.wjoin(f))
2575 except OSError:
2575 except OSError:
2576 pass
2576 pass
2577 repo.dirstate.remove(f)
2577 repo.dirstate.remove(f)
2578
2578
2579 normal = None
2579 normal = None
2580 if node == parent:
2580 if node == parent:
2581 # We're reverting to our parent. If possible, we'd like status
2581 # We're reverting to our parent. If possible, we'd like status
2582 # to report the file as clean. We have to use normallookup for
2582 # to report the file as clean. We have to use normallookup for
2583 # merges to avoid losing information about merged/dirty files.
2583 # merges to avoid losing information about merged/dirty files.
2584 if p2 != nullid:
2584 if p2 != nullid:
2585 normal = repo.dirstate.normallookup
2585 normal = repo.dirstate.normallookup
2586 else:
2586 else:
2587 normal = repo.dirstate.normal
2587 normal = repo.dirstate.normal
2588 for f in actions['revert'][0]:
2588 for f in actions['revert'][0]:
2589 checkout(f)
2589 checkout(f)
2590 if normal:
2590 if normal:
2591 normal(f)
2591 normal(f)
2592
2592
2593 for f in actions['add'][0]:
2593 for f in actions['add'][0]:
2594 checkout(f)
2594 checkout(f)
2595 repo.dirstate.add(f)
2595 repo.dirstate.add(f)
2596
2596
2597 normal = repo.dirstate.normallookup
2597 normal = repo.dirstate.normallookup
2598 if node == parent and p2 == nullid:
2598 if node == parent and p2 == nullid:
2599 normal = repo.dirstate.normal
2599 normal = repo.dirstate.normal
2600 for f in actions['undelete'][0]:
2600 for f in actions['undelete'][0]:
2601 checkout(f)
2601 checkout(f)
2602 normal(f)
2602 normal(f)
2603
2603
2604 copied = copies.pathcopies(repo[parent], ctx)
2604 copied = copies.pathcopies(repo[parent], ctx)
2605
2605
2606 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
2606 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
2607 if f in copied:
2607 if f in copied:
2608 repo.dirstate.copy(copied[f], f)
2608 repo.dirstate.copy(copied[f], f)
2609
2609
2610 def command(table):
2610 def command(table):
2611 """Returns a function object to be used as a decorator for making commands.
2611 """Returns a function object to be used as a decorator for making commands.
2612
2612
2613 This function receives a command table as its argument. The table should
2613 This function receives a command table as its argument. The table should
2614 be a dict.
2614 be a dict.
2615
2615
2616 The returned function can be used as a decorator for adding commands
2616 The returned function can be used as a decorator for adding commands
2617 to that command table. This function accepts multiple arguments to define
2617 to that command table. This function accepts multiple arguments to define
2618 a command.
2618 a command.
2619
2619
2620 The first argument is the command name.
2620 The first argument is the command name.
2621
2621
2622 The options argument is an iterable of tuples defining command arguments.
2622 The options argument is an iterable of tuples defining command arguments.
2623 See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
2623 See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
2624
2624
2625 The synopsis argument defines a short, one line summary of how to use the
2625 The synopsis argument defines a short, one line summary of how to use the
2626 command. This shows up in the help output.
2626 command. This shows up in the help output.
2627
2627
2628 The norepo argument defines whether the command does not require a
2628 The norepo argument defines whether the command does not require a
2629 local repository. Most commands operate against a repository, thus the
2629 local repository. Most commands operate against a repository, thus the
2630 default is False.
2630 default is False.
2631
2631
2632 The optionalrepo argument defines whether the command optionally requires
2632 The optionalrepo argument defines whether the command optionally requires
2633 a local repository.
2633 a local repository.
2634
2634
2635 The inferrepo argument defines whether to try to find a repository from the
2635 The inferrepo argument defines whether to try to find a repository from the
2636 command line arguments. If True, arguments will be examined for potential
2636 command line arguments. If True, arguments will be examined for potential
2637 repository locations. See ``findrepo()``. If a repository is found, it
2637 repository locations. See ``findrepo()``. If a repository is found, it
2638 will be used.
2638 will be used.
2639 """
2639 """
2640 def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
2640 def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
2641 inferrepo=False):
2641 inferrepo=False):
2642 def decorator(func):
2642 def decorator(func):
2643 if synopsis:
2643 if synopsis:
2644 table[name] = func, list(options), synopsis
2644 table[name] = func, list(options), synopsis
2645 else:
2645 else:
2646 table[name] = func, list(options)
2646 table[name] = func, list(options)
2647
2647
2648 if norepo:
2648 if norepo:
2649 # Avoid import cycle.
2649 # Avoid import cycle.
2650 import commands
2650 import commands
2651 commands.norepo += ' %s' % ' '.join(parsealiases(name))
2651 commands.norepo += ' %s' % ' '.join(parsealiases(name))
2652
2652
2653 if optionalrepo:
2653 if optionalrepo:
2654 import commands
2654 import commands
2655 commands.optionalrepo += ' %s' % ' '.join(parsealiases(name))
2655 commands.optionalrepo += ' %s' % ' '.join(parsealiases(name))
2656
2656
2657 if inferrepo:
2657 if inferrepo:
2658 import commands
2658 import commands
2659 commands.inferrepo += ' %s' % ' '.join(parsealiases(name))
2659 commands.inferrepo += ' %s' % ' '.join(parsealiases(name))
2660
2660
2661 return func
2661 return func
2662 return decorator
2662 return decorator
2663
2663
2664 return cmd
2664 return cmd
2665
2665
2666 # a list of (ui, repo, otherpeer, opts, missing) functions called by
2666 # a list of (ui, repo, otherpeer, opts, missing) functions called by
2667 # commands.outgoing. "missing" is "missing" of the result of
2667 # commands.outgoing. "missing" is "missing" of the result of
2668 # "findcommonoutgoing()"
2668 # "findcommonoutgoing()"
2669 outgoinghooks = util.hooks()
2669 outgoinghooks = util.hooks()
2670
2670
2671 # a list of (ui, repo) functions called by commands.summary
2671 # a list of (ui, repo) functions called by commands.summary
2672 summaryhooks = util.hooks()
2672 summaryhooks = util.hooks()
2673
2673
2674 # a list of (ui, repo, opts, changes) functions called by commands.summary.
2674 # a list of (ui, repo, opts, changes) functions called by commands.summary.
2675 #
2675 #
2676 # functions should return tuple of booleans below, if 'changes' is None:
2676 # functions should return tuple of booleans below, if 'changes' is None:
2677 # (whether-incomings-are-needed, whether-outgoings-are-needed)
2677 # (whether-incomings-are-needed, whether-outgoings-are-needed)
2678 #
2678 #
2679 # otherwise, 'changes' is a tuple of tuples below:
2679 # otherwise, 'changes' is a tuple of tuples below:
2680 # - (sourceurl, sourcebranch, sourcepeer, incoming)
2680 # - (sourceurl, sourcebranch, sourcepeer, incoming)
2681 # - (desturl, destbranch, destpeer, outgoing)
2681 # - (desturl, destbranch, destpeer, outgoing)
2682 summaryremotehooks = util.hooks()
2682 summaryremotehooks = util.hooks()
2683
2683
2684 # A list of state files kept by multistep operations like graft.
2684 # A list of state files kept by multistep operations like graft.
2685 # Since graft cannot be aborted, it is considered 'clearable' by update.
2685 # Since graft cannot be aborted, it is considered 'clearable' by update.
2686 # note: bisect is intentionally excluded
2686 # note: bisect is intentionally excluded
2687 # (state file, clearable, allowcommit, error, hint)
2687 # (state file, clearable, allowcommit, error, hint)
2688 unfinishedstates = [
2688 unfinishedstates = [
2689 ('graftstate', True, False, _('graft in progress'),
2689 ('graftstate', True, False, _('graft in progress'),
2690 _("use 'hg graft --continue' or 'hg update' to abort")),
2690 _("use 'hg graft --continue' or 'hg update' to abort")),
2691 ('updatestate', True, False, _('last update was interrupted'),
2691 ('updatestate', True, False, _('last update was interrupted'),
2692 _("use 'hg update' to get a consistent checkout"))
2692 _("use 'hg update' to get a consistent checkout"))
2693 ]
2693 ]
2694
2694
2695 def checkunfinished(repo, commit=False):
2695 def checkunfinished(repo, commit=False):
2696 '''Look for an unfinished multistep operation, like graft, and abort
2696 '''Look for an unfinished multistep operation, like graft, and abort
2697 if found. It's probably good to check this right before
2697 if found. It's probably good to check this right before
2698 bailifchanged().
2698 bailifchanged().
2699 '''
2699 '''
2700 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2700 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2701 if commit and allowcommit:
2701 if commit and allowcommit:
2702 continue
2702 continue
2703 if repo.vfs.exists(f):
2703 if repo.vfs.exists(f):
2704 raise util.Abort(msg, hint=hint)
2704 raise util.Abort(msg, hint=hint)
2705
2705
2706 def clearunfinished(repo):
2706 def clearunfinished(repo):
2707 '''Check for unfinished operations (as above), and clear the ones
2707 '''Check for unfinished operations (as above), and clear the ones
2708 that are clearable.
2708 that are clearable.
2709 '''
2709 '''
2710 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2710 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2711 if not clearable and repo.vfs.exists(f):
2711 if not clearable and repo.vfs.exists(f):
2712 raise util.Abort(msg, hint=hint)
2712 raise util.Abort(msg, hint=hint)
2713 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2713 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2714 if clearable and repo.vfs.exists(f):
2714 if clearable and repo.vfs.exists(f):
2715 util.unlink(repo.join(f))
2715 util.unlink(repo.join(f))
@@ -1,1687 +1,1688 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 The configuration files use a simple ini-file format. A configuration
4 The configuration files use a simple ini-file format. A configuration
5 file consists of sections, led by a ``[section]`` header and followed
5 file consists of sections, led by a ``[section]`` header and followed
6 by ``name = value`` entries::
6 by ``name = value`` entries::
7
7
8 [ui]
8 [ui]
9 username = Firstname Lastname <firstname.lastname@example.net>
9 username = Firstname Lastname <firstname.lastname@example.net>
10 verbose = True
10 verbose = True
11
11
12 The above entries will be referred to as ``ui.username`` and
12 The above entries will be referred to as ``ui.username`` and
13 ``ui.verbose``, respectively. See the Syntax section below.
13 ``ui.verbose``, respectively. See the Syntax section below.
14
14
15 Files
15 Files
16 =====
16 =====
17
17
18 Mercurial reads configuration data from several files, if they exist.
18 Mercurial reads configuration data from several files, if they exist.
19 These files do not exist by default and you will have to create the
19 These files do not exist by default and you will have to create the
20 appropriate configuration files yourself: global configuration like
20 appropriate configuration files yourself: global configuration like
21 the username setting is typically put into
21 the username setting is typically put into
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24
24
25 The names of these files depend on the system on which Mercurial is
25 The names of these files depend on the system on which Mercurial is
26 installed. ``*.rc`` files from a single directory are read in
26 installed. ``*.rc`` files from a single directory are read in
27 alphabetical order, later ones overriding earlier ones. Where multiple
27 alphabetical order, later ones overriding earlier ones. Where multiple
28 paths are given below, settings from earlier paths override later
28 paths are given below, settings from earlier paths override later
29 ones.
29 ones.
30
30
31 | (All) ``<repo>/.hg/hgrc``
31 | (All) ``<repo>/.hg/hgrc``
32
32
33 Per-repository configuration options that only apply in a
33 Per-repository configuration options that only apply in a
34 particular repository. This file is not version-controlled, and
34 particular repository. This file is not version-controlled, and
35 will not get transferred during a "clone" operation. Options in
35 will not get transferred during a "clone" operation. Options in
36 this file override options in all other configuration files. On
36 this file override options in all other configuration files. On
37 Plan 9 and Unix, most of this file will be ignored if it doesn't
37 Plan 9 and Unix, most of this file will be ignored if it doesn't
38 belong to a trusted user or to a trusted group. See the documentation
38 belong to a trusted user or to a trusted group. See the documentation
39 for the ``[trusted]`` section below for more details.
39 for the ``[trusted]`` section below for more details.
40
40
41 | (Plan 9) ``$home/lib/hgrc``
41 | (Plan 9) ``$home/lib/hgrc``
42 | (Unix) ``$HOME/.hgrc``
42 | (Unix) ``$HOME/.hgrc``
43 | (Windows) ``%USERPROFILE%\.hgrc``
43 | (Windows) ``%USERPROFILE%\.hgrc``
44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
45 | (Windows) ``%HOME%\.hgrc``
45 | (Windows) ``%HOME%\.hgrc``
46 | (Windows) ``%HOME%\Mercurial.ini``
46 | (Windows) ``%HOME%\Mercurial.ini``
47
47
48 Per-user configuration file(s), for the user running Mercurial. On
48 Per-user configuration file(s), for the user running Mercurial. On
49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
50 files apply to all Mercurial commands executed by this user in any
50 files apply to all Mercurial commands executed by this user in any
51 directory. Options in these files override per-system and per-installation
51 directory. Options in these files override per-system and per-installation
52 options.
52 options.
53
53
54 | (Plan 9) ``/lib/mercurial/hgrc``
54 | (Plan 9) ``/lib/mercurial/hgrc``
55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
56 | (Unix) ``/etc/mercurial/hgrc``
56 | (Unix) ``/etc/mercurial/hgrc``
57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58
58
59 Per-system configuration files, for the system on which Mercurial
59 Per-system configuration files, for the system on which Mercurial
60 is running. Options in these files apply to all Mercurial commands
60 is running. Options in these files apply to all Mercurial commands
61 executed by any user in any directory. Options in these files
61 executed by any user in any directory. Options in these files
62 override per-installation options.
62 override per-installation options.
63
63
64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
68
68
69 Per-installation configuration files, searched for in the
69 Per-installation configuration files, searched for in the
70 directory where Mercurial is installed. ``<install-root>`` is the
70 directory where Mercurial is installed. ``<install-root>`` is the
71 parent directory of the **hg** executable (or symlink) being run. For
71 parent directory of the **hg** executable (or symlink) being run. For
72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
74 to all Mercurial commands executed by any user in any directory.
74 to all Mercurial commands executed by any user in any directory.
75
75
76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
79
79
80 Per-installation/system configuration files, for the system on
80 Per-installation/system configuration files, for the system on
81 which Mercurial is running. Options in these files apply to all
81 which Mercurial is running. Options in these files apply to all
82 Mercurial commands executed by any user in any directory. Registry
82 Mercurial commands executed by any user in any directory. Registry
83 keys contain PATH-like strings, every part of which must reference
83 keys contain PATH-like strings, every part of which must reference
84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
85 be read. Mercurial checks each of these locations in the specified
85 be read. Mercurial checks each of these locations in the specified
86 order until one or more configuration files are detected.
86 order until one or more configuration files are detected.
87
87
88 .. note::
88 .. note::
89
89
90 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
90 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
91 is used when running 32-bit Python on 64-bit Windows.
91 is used when running 32-bit Python on 64-bit Windows.
92
92
93 Syntax
93 Syntax
94 ======
94 ======
95
95
96 A configuration file consists of sections, led by a ``[section]`` header
96 A configuration file consists of sections, led by a ``[section]`` header
97 and followed by ``name = value`` entries (sometimes called
97 and followed by ``name = value`` entries (sometimes called
98 ``configuration keys``)::
98 ``configuration keys``)::
99
99
100 [spam]
100 [spam]
101 eggs=ham
101 eggs=ham
102 green=
102 green=
103 eggs
103 eggs
104
104
105 Each line contains one entry. If the lines that follow are indented,
105 Each line contains one entry. If the lines that follow are indented,
106 they are treated as continuations of that entry. Leading whitespace is
106 they are treated as continuations of that entry. Leading whitespace is
107 removed from values. Empty lines are skipped. Lines beginning with
107 removed from values. Empty lines are skipped. Lines beginning with
108 ``#`` or ``;`` are ignored and may be used to provide comments.
108 ``#`` or ``;`` are ignored and may be used to provide comments.
109
109
110 Configuration keys can be set multiple times, in which case Mercurial
110 Configuration keys can be set multiple times, in which case Mercurial
111 will use the value that was configured last. As an example::
111 will use the value that was configured last. As an example::
112
112
113 [spam]
113 [spam]
114 eggs=large
114 eggs=large
115 ham=serrano
115 ham=serrano
116 eggs=small
116 eggs=small
117
117
118 This would set the configuration key named ``eggs`` to ``small``.
118 This would set the configuration key named ``eggs`` to ``small``.
119
119
120 It is also possible to define a section multiple times. A section can
120 It is also possible to define a section multiple times. A section can
121 be redefined on the same and/or on different configuration files. For
121 be redefined on the same and/or on different configuration files. For
122 example::
122 example::
123
123
124 [foo]
124 [foo]
125 eggs=large
125 eggs=large
126 ham=serrano
126 ham=serrano
127 eggs=small
127 eggs=small
128
128
129 [bar]
129 [bar]
130 eggs=ham
130 eggs=ham
131 green=
131 green=
132 eggs
132 eggs
133
133
134 [foo]
134 [foo]
135 ham=prosciutto
135 ham=prosciutto
136 eggs=medium
136 eggs=medium
137 bread=toasted
137 bread=toasted
138
138
139 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
139 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
140 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
140 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
141 respectively. As you can see there only thing that matters is the last
141 respectively. As you can see there only thing that matters is the last
142 value that was set for each of the configuration keys.
142 value that was set for each of the configuration keys.
143
143
144 If a configuration key is set multiple times in different
144 If a configuration key is set multiple times in different
145 configuration files the final value will depend on the order in which
145 configuration files the final value will depend on the order in which
146 the different configuration files are read, with settings from earlier
146 the different configuration files are read, with settings from earlier
147 paths overriding later ones as described on the ``Files`` section
147 paths overriding later ones as described on the ``Files`` section
148 above.
148 above.
149
149
150 A line of the form ``%include file`` will include ``file`` into the
150 A line of the form ``%include file`` will include ``file`` into the
151 current configuration file. The inclusion is recursive, which means
151 current configuration file. The inclusion is recursive, which means
152 that included files can include other files. Filenames are relative to
152 that included files can include other files. Filenames are relative to
153 the configuration file in which the ``%include`` directive is found.
153 the configuration file in which the ``%include`` directive is found.
154 Environment variables and ``~user`` constructs are expanded in
154 Environment variables and ``~user`` constructs are expanded in
155 ``file``. This lets you do something like::
155 ``file``. This lets you do something like::
156
156
157 %include ~/.hgrc.d/$HOST.rc
157 %include ~/.hgrc.d/$HOST.rc
158
158
159 to include a different configuration file on each computer you use.
159 to include a different configuration file on each computer you use.
160
160
161 A line with ``%unset name`` will remove ``name`` from the current
161 A line with ``%unset name`` will remove ``name`` from the current
162 section, if it has been set previously.
162 section, if it has been set previously.
163
163
164 The values are either free-form text strings, lists of text strings,
164 The values are either free-form text strings, lists of text strings,
165 or Boolean values. Boolean values can be set to true using any of "1",
165 or Boolean values. Boolean values can be set to true using any of "1",
166 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
166 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
167 (all case insensitive).
167 (all case insensitive).
168
168
169 List values are separated by whitespace or comma, except when values are
169 List values are separated by whitespace or comma, except when values are
170 placed in double quotation marks::
170 placed in double quotation marks::
171
171
172 allow_read = "John Doe, PhD", brian, betty
172 allow_read = "John Doe, PhD", brian, betty
173
173
174 Quotation marks can be escaped by prefixing them with a backslash. Only
174 Quotation marks can be escaped by prefixing them with a backslash. Only
175 quotation marks at the beginning of a word is counted as a quotation
175 quotation marks at the beginning of a word is counted as a quotation
176 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
176 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
177
177
178 Sections
178 Sections
179 ========
179 ========
180
180
181 This section describes the different sections that may appear in a
181 This section describes the different sections that may appear in a
182 Mercurial configuration file, the purpose of each section, its possible
182 Mercurial configuration file, the purpose of each section, its possible
183 keys, and their possible values.
183 keys, and their possible values.
184
184
185 ``alias``
185 ``alias``
186 ---------
186 ---------
187
187
188 Defines command aliases.
188 Defines command aliases.
189 Aliases allow you to define your own commands in terms of other
189 Aliases allow you to define your own commands in terms of other
190 commands (or aliases), optionally including arguments. Positional
190 commands (or aliases), optionally including arguments. Positional
191 arguments in the form of ``$1``, ``$2``, etc in the alias definition
191 arguments in the form of ``$1``, ``$2``, etc in the alias definition
192 are expanded by Mercurial before execution. Positional arguments not
192 are expanded by Mercurial before execution. Positional arguments not
193 already used by ``$N`` in the definition are put at the end of the
193 already used by ``$N`` in the definition are put at the end of the
194 command to be executed.
194 command to be executed.
195
195
196 Alias definitions consist of lines of the form::
196 Alias definitions consist of lines of the form::
197
197
198 <alias> = <command> [<argument>]...
198 <alias> = <command> [<argument>]...
199
199
200 For example, this definition::
200 For example, this definition::
201
201
202 latest = log --limit 5
202 latest = log --limit 5
203
203
204 creates a new command ``latest`` that shows only the five most recent
204 creates a new command ``latest`` that shows only the five most recent
205 changesets. You can define subsequent aliases using earlier ones::
205 changesets. You can define subsequent aliases using earlier ones::
206
206
207 stable5 = latest -b stable
207 stable5 = latest -b stable
208
208
209 .. note::
209 .. note::
210
210
211 It is possible to create aliases with the same names as
211 It is possible to create aliases with the same names as
212 existing commands, which will then override the original
212 existing commands, which will then override the original
213 definitions. This is almost always a bad idea!
213 definitions. This is almost always a bad idea!
214
214
215 An alias can start with an exclamation point (``!``) to make it a
215 An alias can start with an exclamation point (``!``) to make it a
216 shell alias. A shell alias is executed with the shell and will let you
216 shell alias. A shell alias is executed with the shell and will let you
217 run arbitrary commands. As an example, ::
217 run arbitrary commands. As an example, ::
218
218
219 echo = !echo $@
219 echo = !echo $@
220
220
221 will let you do ``hg echo foo`` to have ``foo`` printed in your
221 will let you do ``hg echo foo`` to have ``foo`` printed in your
222 terminal. A better example might be::
222 terminal. A better example might be::
223
223
224 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
224 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
225
225
226 which will make ``hg purge`` delete all unknown files in the
226 which will make ``hg purge`` delete all unknown files in the
227 repository in the same manner as the purge extension.
227 repository in the same manner as the purge extension.
228
228
229 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
229 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
230 expand to the command arguments. Unmatched arguments are
230 expand to the command arguments. Unmatched arguments are
231 removed. ``$0`` expands to the alias name and ``$@`` expands to all
231 removed. ``$0`` expands to the alias name and ``$@`` expands to all
232 arguments separated by a space. ``"$@"`` (with quotes) expands to all
232 arguments separated by a space. ``"$@"`` (with quotes) expands to all
233 arguments quoted individually and separated by a space. These expansions
233 arguments quoted individually and separated by a space. These expansions
234 happen before the command is passed to the shell.
234 happen before the command is passed to the shell.
235
235
236 Shell aliases are executed in an environment where ``$HG`` expands to
236 Shell aliases are executed in an environment where ``$HG`` expands to
237 the path of the Mercurial that was used to execute the alias. This is
237 the path of the Mercurial that was used to execute the alias. This is
238 useful when you want to call further Mercurial commands in a shell
238 useful when you want to call further Mercurial commands in a shell
239 alias, as was done above for the purge alias. In addition,
239 alias, as was done above for the purge alias. In addition,
240 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
240 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
241 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
241 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
242
242
243 .. note::
243 .. note::
244
244
245 Some global configuration options such as ``-R`` are
245 Some global configuration options such as ``-R`` are
246 processed before shell aliases and will thus not be passed to
246 processed before shell aliases and will thus not be passed to
247 aliases.
247 aliases.
248
248
249
249
250 ``annotate``
250 ``annotate``
251 ------------
251 ------------
252
252
253 Settings used when displaying file annotations. All values are
253 Settings used when displaying file annotations. All values are
254 Booleans and default to False. See ``diff`` section for related
254 Booleans and default to False. See ``diff`` section for related
255 options for the diff command.
255 options for the diff command.
256
256
257 ``ignorews``
257 ``ignorews``
258 Ignore white space when comparing lines.
258 Ignore white space when comparing lines.
259
259
260 ``ignorewsamount``
260 ``ignorewsamount``
261 Ignore changes in the amount of white space.
261 Ignore changes in the amount of white space.
262
262
263 ``ignoreblanklines``
263 ``ignoreblanklines``
264 Ignore changes whose lines are all blank.
264 Ignore changes whose lines are all blank.
265
265
266
266
267 ``auth``
267 ``auth``
268 --------
268 --------
269
269
270 Authentication credentials for HTTP authentication. This section
270 Authentication credentials for HTTP authentication. This section
271 allows you to store usernames and passwords for use when logging
271 allows you to store usernames and passwords for use when logging
272 *into* HTTP servers. See the ``[web]`` configuration section if
272 *into* HTTP servers. See the ``[web]`` configuration section if
273 you want to configure *who* can login to your HTTP server.
273 you want to configure *who* can login to your HTTP server.
274
274
275 Each line has the following format::
275 Each line has the following format::
276
276
277 <name>.<argument> = <value>
277 <name>.<argument> = <value>
278
278
279 where ``<name>`` is used to group arguments into authentication
279 where ``<name>`` is used to group arguments into authentication
280 entries. Example::
280 entries. Example::
281
281
282 foo.prefix = hg.intevation.org/mercurial
282 foo.prefix = hg.intevation.org/mercurial
283 foo.username = foo
283 foo.username = foo
284 foo.password = bar
284 foo.password = bar
285 foo.schemes = http https
285 foo.schemes = http https
286
286
287 bar.prefix = secure.example.org
287 bar.prefix = secure.example.org
288 bar.key = path/to/file.key
288 bar.key = path/to/file.key
289 bar.cert = path/to/file.cert
289 bar.cert = path/to/file.cert
290 bar.schemes = https
290 bar.schemes = https
291
291
292 Supported arguments:
292 Supported arguments:
293
293
294 ``prefix``
294 ``prefix``
295 Either ``*`` or a URI prefix with or without the scheme part.
295 Either ``*`` or a URI prefix with or without the scheme part.
296 The authentication entry with the longest matching prefix is used
296 The authentication entry with the longest matching prefix is used
297 (where ``*`` matches everything and counts as a match of length
297 (where ``*`` matches everything and counts as a match of length
298 1). If the prefix doesn't include a scheme, the match is performed
298 1). If the prefix doesn't include a scheme, the match is performed
299 against the URI with its scheme stripped as well, and the schemes
299 against the URI with its scheme stripped as well, and the schemes
300 argument, q.v., is then subsequently consulted.
300 argument, q.v., is then subsequently consulted.
301
301
302 ``username``
302 ``username``
303 Optional. Username to authenticate with. If not given, and the
303 Optional. Username to authenticate with. If not given, and the
304 remote site requires basic or digest authentication, the user will
304 remote site requires basic or digest authentication, the user will
305 be prompted for it. Environment variables are expanded in the
305 be prompted for it. Environment variables are expanded in the
306 username letting you do ``foo.username = $USER``. If the URI
306 username letting you do ``foo.username = $USER``. If the URI
307 includes a username, only ``[auth]`` entries with a matching
307 includes a username, only ``[auth]`` entries with a matching
308 username or without a username will be considered.
308 username or without a username will be considered.
309
309
310 ``password``
310 ``password``
311 Optional. Password to authenticate with. If not given, and the
311 Optional. Password to authenticate with. If not given, and the
312 remote site requires basic or digest authentication, the user
312 remote site requires basic or digest authentication, the user
313 will be prompted for it.
313 will be prompted for it.
314
314
315 ``key``
315 ``key``
316 Optional. PEM encoded client certificate key file. Environment
316 Optional. PEM encoded client certificate key file. Environment
317 variables are expanded in the filename.
317 variables are expanded in the filename.
318
318
319 ``cert``
319 ``cert``
320 Optional. PEM encoded client certificate chain file. Environment
320 Optional. PEM encoded client certificate chain file. Environment
321 variables are expanded in the filename.
321 variables are expanded in the filename.
322
322
323 ``schemes``
323 ``schemes``
324 Optional. Space separated list of URI schemes to use this
324 Optional. Space separated list of URI schemes to use this
325 authentication entry with. Only used if the prefix doesn't include
325 authentication entry with. Only used if the prefix doesn't include
326 a scheme. Supported schemes are http and https. They will match
326 a scheme. Supported schemes are http and https. They will match
327 static-http and static-https respectively, as well.
327 static-http and static-https respectively, as well.
328 Default: https.
328 Default: https.
329
329
330 If no suitable authentication entry is found, the user is prompted
330 If no suitable authentication entry is found, the user is prompted
331 for credentials as usual if required by the remote.
331 for credentials as usual if required by the remote.
332
332
333
333
334 ``committemplate``
334 ``committemplate``
335 ------------------
335 ------------------
336
336
337 ``changeset`` configuration in this section is used as the template to
337 ``changeset`` configuration in this section is used as the template to
338 customize the text shown in the editor when committing.
338 customize the text shown in the editor when committing.
339
339
340 In addition to pre-defined template keywords, commit log specific one
340 In addition to pre-defined template keywords, commit log specific one
341 below can be used for customization:
341 below can be used for customization:
342
342
343 ``extramsg``
343 ``extramsg``
344 String: Extra message (typically 'Leave message empty to abort
344 String: Extra message (typically 'Leave message empty to abort
345 commit.'). This may be changed by some commands or extensions.
345 commit.'). This may be changed by some commands or extensions.
346
346
347 For example, the template configuration below shows as same text as
347 For example, the template configuration below shows as same text as
348 one shown by default::
348 one shown by default::
349
349
350 [committemplate]
350 [committemplate]
351 changeset = {desc}\n\n
351 changeset = {desc}\n\n
352 HG: Enter commit message. Lines beginning with 'HG:' are removed.
352 HG: Enter commit message. Lines beginning with 'HG:' are removed.
353 HG: {extramsg}
353 HG: {extramsg}
354 HG: --
354 HG: --
355 HG: user: {author}\n{ifeq(p2rev, "-1", "",
355 HG: user: {author}\n{ifeq(p2rev, "-1", "",
356 "HG: branch merge\n")
356 "HG: branch merge\n")
357 }HG: branch '{branch}'\n{if(currentbookmark,
357 }HG: branch '{branch}'\n{if(currentbookmark,
358 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
358 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
359 "HG: subrepo {subrepo}\n" }{file_adds %
359 "HG: subrepo {subrepo}\n" }{file_adds %
360 "HG: added {file}\n" }{file_mods %
360 "HG: added {file}\n" }{file_mods %
361 "HG: changed {file}\n" }{file_dels %
361 "HG: changed {file}\n" }{file_dels %
362 "HG: removed {file}\n" }{if(files, "",
362 "HG: removed {file}\n" }{if(files, "",
363 "HG: no files changed\n")}
363 "HG: no files changed\n")}
364
364
365 .. note::
365 .. note::
366
366
367 For some problematic encodings (see :hg:`help win32mbcs` for
367 For some problematic encodings (see :hg:`help win32mbcs` for
368 detail), this customization should be configured carefully, to
368 detail), this customization should be configured carefully, to
369 avoid showing broken characters.
369 avoid showing broken characters.
370
370
371 For example, if multibyte character ending with backslash (0x5c) is
371 For example, if multibyte character ending with backslash (0x5c) is
372 followed by ASCII character 'n' in the customized template,
372 followed by ASCII character 'n' in the customized template,
373 sequence of backslash and 'n' is treated as line-feed unexpectedly
373 sequence of backslash and 'n' is treated as line-feed unexpectedly
374 (and multibyte character is broken, too).
374 (and multibyte character is broken, too).
375
375
376 Customized template is used for commands below (``--edit`` may be
376 Customized template is used for commands below (``--edit`` may be
377 required):
377 required):
378
378
379 - :hg:`backout`
379 - :hg:`backout`
380 - :hg:`commit`
380 - :hg:`commit`
381 - :hg:`fetch` (for merge commit only)
381 - :hg:`fetch` (for merge commit only)
382 - :hg:`graft`
382 - :hg:`graft`
383 - :hg:`histedit`
383 - :hg:`histedit`
384 - :hg:`import`
384 - :hg:`import`
385 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
385 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
386 - :hg:`rebase`
386 - :hg:`rebase`
387 - :hg:`shelve`
387 - :hg:`shelve`
388 - :hg:`sign`
388 - :hg:`sign`
389 - :hg:`tag`
389 - :hg:`tag`
390 - :hg:`transplant`
390 - :hg:`transplant`
391
391
392 Configuring items below instead of ``changeset`` allows showing
392 Configuring items below instead of ``changeset`` allows showing
393 customized message only for specific actions, or showing different
393 customized message only for specific actions, or showing different
394 messages for each actions.
394 messages for each actions.
395
395
396 - ``changeset.backout`` for :hg:`backout`
396 - ``changeset.backout`` for :hg:`backout`
397 - ``changeset.commit.amend`` for :hg:`commit --amend`
397 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
398 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
398 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
399 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
399 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
400 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
400 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
401 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
401 - ``changeset.gpg.sign`` for :hg:`sign`
402 - ``changeset.gpg.sign`` for :hg:`sign`
402 - ``changeset.graft`` for :hg:`graft`
403 - ``changeset.graft`` for :hg:`graft`
403 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
404 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
404 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
405 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
405 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
406 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
406 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
407 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
407 - ``changeset.import.bypass`` for :hg:`import --bypass`
408 - ``changeset.import.bypass`` for :hg:`import --bypass`
408 - ``changeset.import.normal`` for :hg:`import` without ``--bypass``
409 - ``changeset.import.normal`` for :hg:`import` without ``--bypass``
409 - ``changeset.mq.qnew`` for :hg:`qnew`
410 - ``changeset.mq.qnew`` for :hg:`qnew`
410 - ``changeset.mq.qfold`` for :hg:`qfold`
411 - ``changeset.mq.qfold`` for :hg:`qfold`
411 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
412 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
412 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
413 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
413 - ``changeset.rebase.normal`` for :hg:`rebase` without ``--collapse``
414 - ``changeset.rebase.normal`` for :hg:`rebase` without ``--collapse``
414 - ``changeset.shelve.shelve`` for :hg:`shelve`
415 - ``changeset.shelve.shelve`` for :hg:`shelve`
415 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
416 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
416 - ``changeset.tag.remove`` for :hg:`tag --remove`
417 - ``changeset.tag.remove`` for :hg:`tag --remove`
417 - ``changeset.transplant`` for :hg:`transplant`
418 - ``changeset.transplant`` for :hg:`transplant`
418
419
419 These dot-separated lists of names are treated as hierarchical ones.
420 These dot-separated lists of names are treated as hierarchical ones.
420 For example, ``changeset.tag.remove`` customizes the commit message
421 For example, ``changeset.tag.remove`` customizes the commit message
421 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
422 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
422 commit message for :hg:`tag` regardless of ``--remove`` option.
423 commit message for :hg:`tag` regardless of ``--remove`` option.
423
424
424 At the external editor invocation for committing, corresponding
425 At the external editor invocation for committing, corresponding
425 dot-separated list of names without ``changeset.`` prefix
426 dot-separated list of names without ``changeset.`` prefix
426 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
427 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
427
428
428 In this section, items other than ``changeset`` can be referred from
429 In this section, items other than ``changeset`` can be referred from
429 others. For example, the configuration to list committed files up
430 others. For example, the configuration to list committed files up
430 below can be referred as ``{listupfiles}``::
431 below can be referred as ``{listupfiles}``::
431
432
432 [committemplate]
433 [committemplate]
433 listupfiles = {file_adds %
434 listupfiles = {file_adds %
434 "HG: added {file}\n" }{file_mods %
435 "HG: added {file}\n" }{file_mods %
435 "HG: changed {file}\n" }{file_dels %
436 "HG: changed {file}\n" }{file_dels %
436 "HG: removed {file}\n" }{if(files, "",
437 "HG: removed {file}\n" }{if(files, "",
437 "HG: no files changed\n")}
438 "HG: no files changed\n")}
438
439
439 ``decode/encode``
440 ``decode/encode``
440 -----------------
441 -----------------
441
442
442 Filters for transforming files on checkout/checkin. This would
443 Filters for transforming files on checkout/checkin. This would
443 typically be used for newline processing or other
444 typically be used for newline processing or other
444 localization/canonicalization of files.
445 localization/canonicalization of files.
445
446
446 Filters consist of a filter pattern followed by a filter command.
447 Filters consist of a filter pattern followed by a filter command.
447 Filter patterns are globs by default, rooted at the repository root.
448 Filter patterns are globs by default, rooted at the repository root.
448 For example, to match any file ending in ``.txt`` in the root
449 For example, to match any file ending in ``.txt`` in the root
449 directory only, use the pattern ``*.txt``. To match any file ending
450 directory only, use the pattern ``*.txt``. To match any file ending
450 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
451 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
451 For each file only the first matching filter applies.
452 For each file only the first matching filter applies.
452
453
453 The filter command can start with a specifier, either ``pipe:`` or
454 The filter command can start with a specifier, either ``pipe:`` or
454 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
455 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
455
456
456 A ``pipe:`` command must accept data on stdin and return the transformed
457 A ``pipe:`` command must accept data on stdin and return the transformed
457 data on stdout.
458 data on stdout.
458
459
459 Pipe example::
460 Pipe example::
460
461
461 [encode]
462 [encode]
462 # uncompress gzip files on checkin to improve delta compression
463 # uncompress gzip files on checkin to improve delta compression
463 # note: not necessarily a good idea, just an example
464 # note: not necessarily a good idea, just an example
464 *.gz = pipe: gunzip
465 *.gz = pipe: gunzip
465
466
466 [decode]
467 [decode]
467 # recompress gzip files when writing them to the working dir (we
468 # recompress gzip files when writing them to the working dir (we
468 # can safely omit "pipe:", because it's the default)
469 # can safely omit "pipe:", because it's the default)
469 *.gz = gzip
470 *.gz = gzip
470
471
471 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
472 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
472 with the name of a temporary file that contains the data to be
473 with the name of a temporary file that contains the data to be
473 filtered by the command. The string ``OUTFILE`` is replaced with the name
474 filtered by the command. The string ``OUTFILE`` is replaced with the name
474 of an empty temporary file, where the filtered data must be written by
475 of an empty temporary file, where the filtered data must be written by
475 the command.
476 the command.
476
477
477 .. note::
478 .. note::
478
479
479 The tempfile mechanism is recommended for Windows systems,
480 The tempfile mechanism is recommended for Windows systems,
480 where the standard shell I/O redirection operators often have
481 where the standard shell I/O redirection operators often have
481 strange effects and may corrupt the contents of your files.
482 strange effects and may corrupt the contents of your files.
482
483
483 This filter mechanism is used internally by the ``eol`` extension to
484 This filter mechanism is used internally by the ``eol`` extension to
484 translate line ending characters between Windows (CRLF) and Unix (LF)
485 translate line ending characters between Windows (CRLF) and Unix (LF)
485 format. We suggest you use the ``eol`` extension for convenience.
486 format. We suggest you use the ``eol`` extension for convenience.
486
487
487
488
488 ``defaults``
489 ``defaults``
489 ------------
490 ------------
490
491
491 (defaults are deprecated. Don't use them. Use aliases instead)
492 (defaults are deprecated. Don't use them. Use aliases instead)
492
493
493 Use the ``[defaults]`` section to define command defaults, i.e. the
494 Use the ``[defaults]`` section to define command defaults, i.e. the
494 default options/arguments to pass to the specified commands.
495 default options/arguments to pass to the specified commands.
495
496
496 The following example makes :hg:`log` run in verbose mode, and
497 The following example makes :hg:`log` run in verbose mode, and
497 :hg:`status` show only the modified files, by default::
498 :hg:`status` show only the modified files, by default::
498
499
499 [defaults]
500 [defaults]
500 log = -v
501 log = -v
501 status = -m
502 status = -m
502
503
503 The actual commands, instead of their aliases, must be used when
504 The actual commands, instead of their aliases, must be used when
504 defining command defaults. The command defaults will also be applied
505 defining command defaults. The command defaults will also be applied
505 to the aliases of the commands defined.
506 to the aliases of the commands defined.
506
507
507
508
508 ``diff``
509 ``diff``
509 --------
510 --------
510
511
511 Settings used when displaying diffs. Everything except for ``unified``
512 Settings used when displaying diffs. Everything except for ``unified``
512 is a Boolean and defaults to False. See ``annotate`` section for
513 is a Boolean and defaults to False. See ``annotate`` section for
513 related options for the annotate command.
514 related options for the annotate command.
514
515
515 ``git``
516 ``git``
516 Use git extended diff format.
517 Use git extended diff format.
517
518
518 ``nodates``
519 ``nodates``
519 Don't include dates in diff headers.
520 Don't include dates in diff headers.
520
521
521 ``showfunc``
522 ``showfunc``
522 Show which function each change is in.
523 Show which function each change is in.
523
524
524 ``ignorews``
525 ``ignorews``
525 Ignore white space when comparing lines.
526 Ignore white space when comparing lines.
526
527
527 ``ignorewsamount``
528 ``ignorewsamount``
528 Ignore changes in the amount of white space.
529 Ignore changes in the amount of white space.
529
530
530 ``ignoreblanklines``
531 ``ignoreblanklines``
531 Ignore changes whose lines are all blank.
532 Ignore changes whose lines are all blank.
532
533
533 ``unified``
534 ``unified``
534 Number of lines of context to show.
535 Number of lines of context to show.
535
536
536 ``email``
537 ``email``
537 ---------
538 ---------
538
539
539 Settings for extensions that send email messages.
540 Settings for extensions that send email messages.
540
541
541 ``from``
542 ``from``
542 Optional. Email address to use in "From" header and SMTP envelope
543 Optional. Email address to use in "From" header and SMTP envelope
543 of outgoing messages.
544 of outgoing messages.
544
545
545 ``to``
546 ``to``
546 Optional. Comma-separated list of recipients' email addresses.
547 Optional. Comma-separated list of recipients' email addresses.
547
548
548 ``cc``
549 ``cc``
549 Optional. Comma-separated list of carbon copy recipients'
550 Optional. Comma-separated list of carbon copy recipients'
550 email addresses.
551 email addresses.
551
552
552 ``bcc``
553 ``bcc``
553 Optional. Comma-separated list of blind carbon copy recipients'
554 Optional. Comma-separated list of blind carbon copy recipients'
554 email addresses.
555 email addresses.
555
556
556 ``method``
557 ``method``
557 Optional. Method to use to send email messages. If value is ``smtp``
558 Optional. Method to use to send email messages. If value is ``smtp``
558 (default), use SMTP (see the ``[smtp]`` section for configuration).
559 (default), use SMTP (see the ``[smtp]`` section for configuration).
559 Otherwise, use as name of program to run that acts like sendmail
560 Otherwise, use as name of program to run that acts like sendmail
560 (takes ``-f`` option for sender, list of recipients on command line,
561 (takes ``-f`` option for sender, list of recipients on command line,
561 message on stdin). Normally, setting this to ``sendmail`` or
562 message on stdin). Normally, setting this to ``sendmail`` or
562 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
563 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
563
564
564 ``charsets``
565 ``charsets``
565 Optional. Comma-separated list of character sets considered
566 Optional. Comma-separated list of character sets considered
566 convenient for recipients. Addresses, headers, and parts not
567 convenient for recipients. Addresses, headers, and parts not
567 containing patches of outgoing messages will be encoded in the
568 containing patches of outgoing messages will be encoded in the
568 first character set to which conversion from local encoding
569 first character set to which conversion from local encoding
569 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
570 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
570 conversion fails, the text in question is sent as is. Defaults to
571 conversion fails, the text in question is sent as is. Defaults to
571 empty (explicit) list.
572 empty (explicit) list.
572
573
573 Order of outgoing email character sets:
574 Order of outgoing email character sets:
574
575
575 1. ``us-ascii``: always first, regardless of settings
576 1. ``us-ascii``: always first, regardless of settings
576 2. ``email.charsets``: in order given by user
577 2. ``email.charsets``: in order given by user
577 3. ``ui.fallbackencoding``: if not in email.charsets
578 3. ``ui.fallbackencoding``: if not in email.charsets
578 4. ``$HGENCODING``: if not in email.charsets
579 4. ``$HGENCODING``: if not in email.charsets
579 5. ``utf-8``: always last, regardless of settings
580 5. ``utf-8``: always last, regardless of settings
580
581
581 Email example::
582 Email example::
582
583
583 [email]
584 [email]
584 from = Joseph User <joe.user@example.com>
585 from = Joseph User <joe.user@example.com>
585 method = /usr/sbin/sendmail
586 method = /usr/sbin/sendmail
586 # charsets for western Europeans
587 # charsets for western Europeans
587 # us-ascii, utf-8 omitted, as they are tried first and last
588 # us-ascii, utf-8 omitted, as they are tried first and last
588 charsets = iso-8859-1, iso-8859-15, windows-1252
589 charsets = iso-8859-1, iso-8859-15, windows-1252
589
590
590
591
591 ``extensions``
592 ``extensions``
592 --------------
593 --------------
593
594
594 Mercurial has an extension mechanism for adding new features. To
595 Mercurial has an extension mechanism for adding new features. To
595 enable an extension, create an entry for it in this section.
596 enable an extension, create an entry for it in this section.
596
597
597 If you know that the extension is already in Python's search path,
598 If you know that the extension is already in Python's search path,
598 you can give the name of the module, followed by ``=``, with nothing
599 you can give the name of the module, followed by ``=``, with nothing
599 after the ``=``.
600 after the ``=``.
600
601
601 Otherwise, give a name that you choose, followed by ``=``, followed by
602 Otherwise, give a name that you choose, followed by ``=``, followed by
602 the path to the ``.py`` file (including the file name extension) that
603 the path to the ``.py`` file (including the file name extension) that
603 defines the extension.
604 defines the extension.
604
605
605 To explicitly disable an extension that is enabled in an hgrc of
606 To explicitly disable an extension that is enabled in an hgrc of
606 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
607 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
607 or ``foo = !`` when path is not supplied.
608 or ``foo = !`` when path is not supplied.
608
609
609 Example for ``~/.hgrc``::
610 Example for ``~/.hgrc``::
610
611
611 [extensions]
612 [extensions]
612 # (the progress extension will get loaded from Mercurial's path)
613 # (the progress extension will get loaded from Mercurial's path)
613 progress =
614 progress =
614 # (this extension will get loaded from the file specified)
615 # (this extension will get loaded from the file specified)
615 myfeature = ~/.hgext/myfeature.py
616 myfeature = ~/.hgext/myfeature.py
616
617
617
618
618 ``format``
619 ``format``
619 ----------
620 ----------
620
621
621 ``usestore``
622 ``usestore``
622 Enable or disable the "store" repository format which improves
623 Enable or disable the "store" repository format which improves
623 compatibility with systems that fold case or otherwise mangle
624 compatibility with systems that fold case or otherwise mangle
624 filenames. Enabled by default. Disabling this option will allow
625 filenames. Enabled by default. Disabling this option will allow
625 you to store longer filenames in some situations at the expense of
626 you to store longer filenames in some situations at the expense of
626 compatibility and ensures that the on-disk format of newly created
627 compatibility and ensures that the on-disk format of newly created
627 repositories will be compatible with Mercurial before version 0.9.4.
628 repositories will be compatible with Mercurial before version 0.9.4.
628
629
629 ``usefncache``
630 ``usefncache``
630 Enable or disable the "fncache" repository format which enhances
631 Enable or disable the "fncache" repository format which enhances
631 the "store" repository format (which has to be enabled to use
632 the "store" repository format (which has to be enabled to use
632 fncache) to allow longer filenames and avoids using Windows
633 fncache) to allow longer filenames and avoids using Windows
633 reserved names, e.g. "nul". Enabled by default. Disabling this
634 reserved names, e.g. "nul". Enabled by default. Disabling this
634 option ensures that the on-disk format of newly created
635 option ensures that the on-disk format of newly created
635 repositories will be compatible with Mercurial before version 1.1.
636 repositories will be compatible with Mercurial before version 1.1.
636
637
637 ``dotencode``
638 ``dotencode``
638 Enable or disable the "dotencode" repository format which enhances
639 Enable or disable the "dotencode" repository format which enhances
639 the "fncache" repository format (which has to be enabled to use
640 the "fncache" repository format (which has to be enabled to use
640 dotencode) to avoid issues with filenames starting with ._ on
641 dotencode) to avoid issues with filenames starting with ._ on
641 Mac OS X and spaces on Windows. Enabled by default. Disabling this
642 Mac OS X and spaces on Windows. Enabled by default. Disabling this
642 option ensures that the on-disk format of newly created
643 option ensures that the on-disk format of newly created
643 repositories will be compatible with Mercurial before version 1.7.
644 repositories will be compatible with Mercurial before version 1.7.
644
645
645 ``graph``
646 ``graph``
646 ---------
647 ---------
647
648
648 Web graph view configuration. This section let you change graph
649 Web graph view configuration. This section let you change graph
649 elements display properties by branches, for instance to make the
650 elements display properties by branches, for instance to make the
650 ``default`` branch stand out.
651 ``default`` branch stand out.
651
652
652 Each line has the following format::
653 Each line has the following format::
653
654
654 <branch>.<argument> = <value>
655 <branch>.<argument> = <value>
655
656
656 where ``<branch>`` is the name of the branch being
657 where ``<branch>`` is the name of the branch being
657 customized. Example::
658 customized. Example::
658
659
659 [graph]
660 [graph]
660 # 2px width
661 # 2px width
661 default.width = 2
662 default.width = 2
662 # red color
663 # red color
663 default.color = FF0000
664 default.color = FF0000
664
665
665 Supported arguments:
666 Supported arguments:
666
667
667 ``width``
668 ``width``
668 Set branch edges width in pixels.
669 Set branch edges width in pixels.
669
670
670 ``color``
671 ``color``
671 Set branch edges color in hexadecimal RGB notation.
672 Set branch edges color in hexadecimal RGB notation.
672
673
673 ``hooks``
674 ``hooks``
674 ---------
675 ---------
675
676
676 Commands or Python functions that get automatically executed by
677 Commands or Python functions that get automatically executed by
677 various actions such as starting or finishing a commit. Multiple
678 various actions such as starting or finishing a commit. Multiple
678 hooks can be run for the same action by appending a suffix to the
679 hooks can be run for the same action by appending a suffix to the
679 action. Overriding a site-wide hook can be done by changing its
680 action. Overriding a site-wide hook can be done by changing its
680 value or setting it to an empty string. Hooks can be prioritized
681 value or setting it to an empty string. Hooks can be prioritized
681 by adding a prefix of ``priority`` to the hook name on a new line
682 by adding a prefix of ``priority`` to the hook name on a new line
682 and setting the priority. The default priority is 0 if
683 and setting the priority. The default priority is 0 if
683 not specified.
684 not specified.
684
685
685 Example ``.hg/hgrc``::
686 Example ``.hg/hgrc``::
686
687
687 [hooks]
688 [hooks]
688 # update working directory after adding changesets
689 # update working directory after adding changesets
689 changegroup.update = hg update
690 changegroup.update = hg update
690 # do not use the site-wide hook
691 # do not use the site-wide hook
691 incoming =
692 incoming =
692 incoming.email = /my/email/hook
693 incoming.email = /my/email/hook
693 incoming.autobuild = /my/build/hook
694 incoming.autobuild = /my/build/hook
694 # force autobuild hook to run before other incoming hooks
695 # force autobuild hook to run before other incoming hooks
695 priority.incoming.autobuild = 1
696 priority.incoming.autobuild = 1
696
697
697 Most hooks are run with environment variables set that give useful
698 Most hooks are run with environment variables set that give useful
698 additional information. For each hook below, the environment
699 additional information. For each hook below, the environment
699 variables it is passed are listed with names of the form ``$HG_foo``.
700 variables it is passed are listed with names of the form ``$HG_foo``.
700
701
701 ``changegroup``
702 ``changegroup``
702 Run after a changegroup has been added via push, pull or unbundle.
703 Run after a changegroup has been added via push, pull or unbundle.
703 ID of the first new changeset is in ``$HG_NODE``. URL from which
704 ID of the first new changeset is in ``$HG_NODE``. URL from which
704 changes came is in ``$HG_URL``.
705 changes came is in ``$HG_URL``.
705
706
706 ``commit``
707 ``commit``
707 Run after a changeset has been created in the local repository. ID
708 Run after a changeset has been created in the local repository. ID
708 of the newly created changeset is in ``$HG_NODE``. Parent changeset
709 of the newly created changeset is in ``$HG_NODE``. Parent changeset
709 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
710 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
710
711
711 ``incoming``
712 ``incoming``
712 Run after a changeset has been pulled, pushed, or unbundled into
713 Run after a changeset has been pulled, pushed, or unbundled into
713 the local repository. The ID of the newly arrived changeset is in
714 the local repository. The ID of the newly arrived changeset is in
714 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
715 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
715
716
716 ``outgoing``
717 ``outgoing``
717 Run after sending changes from local repository to another. ID of
718 Run after sending changes from local repository to another. ID of
718 first changeset sent is in ``$HG_NODE``. Source of operation is in
719 first changeset sent is in ``$HG_NODE``. Source of operation is in
719 ``$HG_SOURCE``; see "preoutgoing" hook for description.
720 ``$HG_SOURCE``; see "preoutgoing" hook for description.
720
721
721 ``post-<command>``
722 ``post-<command>``
722 Run after successful invocations of the associated command. The
723 Run after successful invocations of the associated command. The
723 contents of the command line are passed as ``$HG_ARGS`` and the result
724 contents of the command line are passed as ``$HG_ARGS`` and the result
724 code in ``$HG_RESULT``. Parsed command line arguments are passed as
725 code in ``$HG_RESULT``. Parsed command line arguments are passed as
725 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
726 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
726 the python data internally passed to <command>. ``$HG_OPTS`` is a
727 the python data internally passed to <command>. ``$HG_OPTS`` is a
727 dictionary of options (with unspecified options set to their defaults).
728 dictionary of options (with unspecified options set to their defaults).
728 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
729 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
729
730
730 ``pre-<command>``
731 ``pre-<command>``
731 Run before executing the associated command. The contents of the
732 Run before executing the associated command. The contents of the
732 command line are passed as ``$HG_ARGS``. Parsed command line arguments
733 command line are passed as ``$HG_ARGS``. Parsed command line arguments
733 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
734 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
734 representations of the data internally passed to <command>. ``$HG_OPTS``
735 representations of the data internally passed to <command>. ``$HG_OPTS``
735 is a dictionary of options (with unspecified options set to their
736 is a dictionary of options (with unspecified options set to their
736 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
737 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
737 failure, the command doesn't execute and Mercurial returns the failure
738 failure, the command doesn't execute and Mercurial returns the failure
738 code.
739 code.
739
740
740 ``prechangegroup``
741 ``prechangegroup``
741 Run before a changegroup is added via push, pull or unbundle. Exit
742 Run before a changegroup is added via push, pull or unbundle. Exit
742 status 0 allows the changegroup to proceed. Non-zero status will
743 status 0 allows the changegroup to proceed. Non-zero status will
743 cause the push, pull or unbundle to fail. URL from which changes
744 cause the push, pull or unbundle to fail. URL from which changes
744 will come is in ``$HG_URL``.
745 will come is in ``$HG_URL``.
745
746
746 ``precommit``
747 ``precommit``
747 Run before starting a local commit. Exit status 0 allows the
748 Run before starting a local commit. Exit status 0 allows the
748 commit to proceed. Non-zero status will cause the commit to fail.
749 commit to proceed. Non-zero status will cause the commit to fail.
749 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
750 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
750
751
751 ``prelistkeys``
752 ``prelistkeys``
752 Run before listing pushkeys (like bookmarks) in the
753 Run before listing pushkeys (like bookmarks) in the
753 repository. Non-zero status will cause failure. The key namespace is
754 repository. Non-zero status will cause failure. The key namespace is
754 in ``$HG_NAMESPACE``.
755 in ``$HG_NAMESPACE``.
755
756
756 ``preoutgoing``
757 ``preoutgoing``
757 Run before collecting changes to send from the local repository to
758 Run before collecting changes to send from the local repository to
758 another. Non-zero status will cause failure. This lets you prevent
759 another. Non-zero status will cause failure. This lets you prevent
759 pull over HTTP or SSH. Also prevents against local pull, push
760 pull over HTTP or SSH. Also prevents against local pull, push
760 (outbound) or bundle commands, but not effective, since you can
761 (outbound) or bundle commands, but not effective, since you can
761 just copy files instead then. Source of operation is in
762 just copy files instead then. Source of operation is in
762 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
763 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
763 SSH or HTTP repository. If "push", "pull" or "bundle", operation
764 SSH or HTTP repository. If "push", "pull" or "bundle", operation
764 is happening on behalf of repository on same system.
765 is happening on behalf of repository on same system.
765
766
766 ``prepushkey``
767 ``prepushkey``
767 Run before a pushkey (like a bookmark) is added to the
768 Run before a pushkey (like a bookmark) is added to the
768 repository. Non-zero status will cause the key to be rejected. The
769 repository. Non-zero status will cause the key to be rejected. The
769 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
770 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
770 the old value (if any) is in ``$HG_OLD``, and the new value is in
771 the old value (if any) is in ``$HG_OLD``, and the new value is in
771 ``$HG_NEW``.
772 ``$HG_NEW``.
772
773
773 ``pretag``
774 ``pretag``
774 Run before creating a tag. Exit status 0 allows the tag to be
775 Run before creating a tag. Exit status 0 allows the tag to be
775 created. Non-zero status will cause the tag to fail. ID of
776 created. Non-zero status will cause the tag to fail. ID of
776 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
777 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
777 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
778 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
778
779
779 ``pretxnchangegroup``
780 ``pretxnchangegroup``
780 Run after a changegroup has been added via push, pull or unbundle,
781 Run after a changegroup has been added via push, pull or unbundle,
781 but before the transaction has been committed. Changegroup is
782 but before the transaction has been committed. Changegroup is
782 visible to hook program. This lets you validate incoming changes
783 visible to hook program. This lets you validate incoming changes
783 before accepting them. Passed the ID of the first new changeset in
784 before accepting them. Passed the ID of the first new changeset in
784 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
785 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
785 status will cause the transaction to be rolled back and the push,
786 status will cause the transaction to be rolled back and the push,
786 pull or unbundle will fail. URL that was source of changes is in
787 pull or unbundle will fail. URL that was source of changes is in
787 ``$HG_URL``.
788 ``$HG_URL``.
788
789
789 ``pretxncommit``
790 ``pretxncommit``
790 Run after a changeset has been created but the transaction not yet
791 Run after a changeset has been created but the transaction not yet
791 committed. Changeset is visible to hook program. This lets you
792 committed. Changeset is visible to hook program. This lets you
792 validate commit message and changes. Exit status 0 allows the
793 validate commit message and changes. Exit status 0 allows the
793 commit to proceed. Non-zero status will cause the transaction to
794 commit to proceed. Non-zero status will cause the transaction to
794 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
795 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
795 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
796 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
796
797
797 ``preupdate``
798 ``preupdate``
798 Run before updating the working directory. Exit status 0 allows
799 Run before updating the working directory. Exit status 0 allows
799 the update to proceed. Non-zero status will prevent the update.
800 the update to proceed. Non-zero status will prevent the update.
800 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
801 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
801 of second new parent is in ``$HG_PARENT2``.
802 of second new parent is in ``$HG_PARENT2``.
802
803
803 ``listkeys``
804 ``listkeys``
804 Run after listing pushkeys (like bookmarks) in the repository. The
805 Run after listing pushkeys (like bookmarks) in the repository. The
805 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
806 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
806 dictionary containing the keys and values.
807 dictionary containing the keys and values.
807
808
808 ``pushkey``
809 ``pushkey``
809 Run after a pushkey (like a bookmark) is added to the
810 Run after a pushkey (like a bookmark) is added to the
810 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
811 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
811 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
812 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
812 value is in ``$HG_NEW``.
813 value is in ``$HG_NEW``.
813
814
814 ``tag``
815 ``tag``
815 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
816 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
816 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
817 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
817 repository if ``$HG_LOCAL=0``.
818 repository if ``$HG_LOCAL=0``.
818
819
819 ``update``
820 ``update``
820 Run after updating the working directory. Changeset ID of first
821 Run after updating the working directory. Changeset ID of first
821 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
822 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
822 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
823 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
823 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
824 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
824
825
825 .. note::
826 .. note::
826
827
827 It is generally better to use standard hooks rather than the
828 It is generally better to use standard hooks rather than the
828 generic pre- and post- command hooks as they are guaranteed to be
829 generic pre- and post- command hooks as they are guaranteed to be
829 called in the appropriate contexts for influencing transactions.
830 called in the appropriate contexts for influencing transactions.
830 Also, hooks like "commit" will be called in all contexts that
831 Also, hooks like "commit" will be called in all contexts that
831 generate a commit (e.g. tag) and not just the commit command.
832 generate a commit (e.g. tag) and not just the commit command.
832
833
833 .. note::
834 .. note::
834
835
835 Environment variables with empty values may not be passed to
836 Environment variables with empty values may not be passed to
836 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
837 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
837 will have an empty value under Unix-like platforms for non-merge
838 will have an empty value under Unix-like platforms for non-merge
838 changesets, while it will not be available at all under Windows.
839 changesets, while it will not be available at all under Windows.
839
840
840 The syntax for Python hooks is as follows::
841 The syntax for Python hooks is as follows::
841
842
842 hookname = python:modulename.submodule.callable
843 hookname = python:modulename.submodule.callable
843 hookname = python:/path/to/python/module.py:callable
844 hookname = python:/path/to/python/module.py:callable
844
845
845 Python hooks are run within the Mercurial process. Each hook is
846 Python hooks are run within the Mercurial process. Each hook is
846 called with at least three keyword arguments: a ui object (keyword
847 called with at least three keyword arguments: a ui object (keyword
847 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
848 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
848 keyword that tells what kind of hook is used. Arguments listed as
849 keyword that tells what kind of hook is used. Arguments listed as
849 environment variables above are passed as keyword arguments, with no
850 environment variables above are passed as keyword arguments, with no
850 ``HG_`` prefix, and names in lower case.
851 ``HG_`` prefix, and names in lower case.
851
852
852 If a Python hook returns a "true" value or raises an exception, this
853 If a Python hook returns a "true" value or raises an exception, this
853 is treated as a failure.
854 is treated as a failure.
854
855
855
856
856 ``hostfingerprints``
857 ``hostfingerprints``
857 --------------------
858 --------------------
858
859
859 Fingerprints of the certificates of known HTTPS servers.
860 Fingerprints of the certificates of known HTTPS servers.
860 A HTTPS connection to a server with a fingerprint configured here will
861 A HTTPS connection to a server with a fingerprint configured here will
861 only succeed if the servers certificate matches the fingerprint.
862 only succeed if the servers certificate matches the fingerprint.
862 This is very similar to how ssh known hosts works.
863 This is very similar to how ssh known hosts works.
863 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
864 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
864 The CA chain and web.cacerts is not used for servers with a fingerprint.
865 The CA chain and web.cacerts is not used for servers with a fingerprint.
865
866
866 For example::
867 For example::
867
868
868 [hostfingerprints]
869 [hostfingerprints]
869 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
870 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
870
871
871 This feature is only supported when using Python 2.6 or later.
872 This feature is only supported when using Python 2.6 or later.
872
873
873
874
874 ``http_proxy``
875 ``http_proxy``
875 --------------
876 --------------
876
877
877 Used to access web-based Mercurial repositories through a HTTP
878 Used to access web-based Mercurial repositories through a HTTP
878 proxy.
879 proxy.
879
880
880 ``host``
881 ``host``
881 Host name and (optional) port of the proxy server, for example
882 Host name and (optional) port of the proxy server, for example
882 "myproxy:8000".
883 "myproxy:8000".
883
884
884 ``no``
885 ``no``
885 Optional. Comma-separated list of host names that should bypass
886 Optional. Comma-separated list of host names that should bypass
886 the proxy.
887 the proxy.
887
888
888 ``passwd``
889 ``passwd``
889 Optional. Password to authenticate with at the proxy server.
890 Optional. Password to authenticate with at the proxy server.
890
891
891 ``user``
892 ``user``
892 Optional. User name to authenticate with at the proxy server.
893 Optional. User name to authenticate with at the proxy server.
893
894
894 ``always``
895 ``always``
895 Optional. Always use the proxy, even for localhost and any entries
896 Optional. Always use the proxy, even for localhost and any entries
896 in ``http_proxy.no``. True or False. Default: False.
897 in ``http_proxy.no``. True or False. Default: False.
897
898
898 ``merge-patterns``
899 ``merge-patterns``
899 ------------------
900 ------------------
900
901
901 This section specifies merge tools to associate with particular file
902 This section specifies merge tools to associate with particular file
902 patterns. Tools matched here will take precedence over the default
903 patterns. Tools matched here will take precedence over the default
903 merge tool. Patterns are globs by default, rooted at the repository
904 merge tool. Patterns are globs by default, rooted at the repository
904 root.
905 root.
905
906
906 Example::
907 Example::
907
908
908 [merge-patterns]
909 [merge-patterns]
909 **.c = kdiff3
910 **.c = kdiff3
910 **.jpg = myimgmerge
911 **.jpg = myimgmerge
911
912
912 ``merge-tools``
913 ``merge-tools``
913 ---------------
914 ---------------
914
915
915 This section configures external merge tools to use for file-level
916 This section configures external merge tools to use for file-level
916 merges. This section has likely been preconfigured at install time.
917 merges. This section has likely been preconfigured at install time.
917 Use :hg:`config merge-tools` to check the existing configuration.
918 Use :hg:`config merge-tools` to check the existing configuration.
918 Also see :hg:`help merge-tools` for more details.
919 Also see :hg:`help merge-tools` for more details.
919
920
920 Example ``~/.hgrc``::
921 Example ``~/.hgrc``::
921
922
922 [merge-tools]
923 [merge-tools]
923 # Override stock tool location
924 # Override stock tool location
924 kdiff3.executable = ~/bin/kdiff3
925 kdiff3.executable = ~/bin/kdiff3
925 # Specify command line
926 # Specify command line
926 kdiff3.args = $base $local $other -o $output
927 kdiff3.args = $base $local $other -o $output
927 # Give higher priority
928 # Give higher priority
928 kdiff3.priority = 1
929 kdiff3.priority = 1
929
930
930 # Changing the priority of preconfigured tool
931 # Changing the priority of preconfigured tool
931 vimdiff.priority = 0
932 vimdiff.priority = 0
932
933
933 # Define new tool
934 # Define new tool
934 myHtmlTool.args = -m $local $other $base $output
935 myHtmlTool.args = -m $local $other $base $output
935 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
936 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
936 myHtmlTool.priority = 1
937 myHtmlTool.priority = 1
937
938
938 Supported arguments:
939 Supported arguments:
939
940
940 ``priority``
941 ``priority``
941 The priority in which to evaluate this tool.
942 The priority in which to evaluate this tool.
942 Default: 0.
943 Default: 0.
943
944
944 ``executable``
945 ``executable``
945 Either just the name of the executable or its pathname. On Windows,
946 Either just the name of the executable or its pathname. On Windows,
946 the path can use environment variables with ${ProgramFiles} syntax.
947 the path can use environment variables with ${ProgramFiles} syntax.
947 Default: the tool name.
948 Default: the tool name.
948
949
949 ``args``
950 ``args``
950 The arguments to pass to the tool executable. You can refer to the
951 The arguments to pass to the tool executable. You can refer to the
951 files being merged as well as the output file through these
952 files being merged as well as the output file through these
952 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
953 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
953 of ``$local`` and ``$other`` can vary depending on which action is being
954 of ``$local`` and ``$other`` can vary depending on which action is being
954 performed. During and update or merge, ``$local`` represents the original
955 performed. During and update or merge, ``$local`` represents the original
955 state of the file, while ``$other`` represents the commit you are updating
956 state of the file, while ``$other`` represents the commit you are updating
956 to or the commit you are merging with. During a rebase ``$local``
957 to or the commit you are merging with. During a rebase ``$local``
957 represents the destination of the rebase, and ``$other`` represents the
958 represents the destination of the rebase, and ``$other`` represents the
958 commit being rebased.
959 commit being rebased.
959 Default: ``$local $base $other``
960 Default: ``$local $base $other``
960
961
961 ``premerge``
962 ``premerge``
962 Attempt to run internal non-interactive 3-way merge tool before
963 Attempt to run internal non-interactive 3-way merge tool before
963 launching external tool. Options are ``true``, ``false``, ``keep`` or
964 launching external tool. Options are ``true``, ``false``, ``keep`` or
964 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
965 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
965 premerge fails. The ``keep-merge3`` will do the same but include information
966 premerge fails. The ``keep-merge3`` will do the same but include information
966 about the base of the merge in the marker (see internal:merge3).
967 about the base of the merge in the marker (see internal:merge3).
967 Default: True
968 Default: True
968
969
969 ``binary``
970 ``binary``
970 This tool can merge binary files. Defaults to False, unless tool
971 This tool can merge binary files. Defaults to False, unless tool
971 was selected by file pattern match.
972 was selected by file pattern match.
972
973
973 ``symlink``
974 ``symlink``
974 This tool can merge symlinks. Defaults to False, even if tool was
975 This tool can merge symlinks. Defaults to False, even if tool was
975 selected by file pattern match.
976 selected by file pattern match.
976
977
977 ``check``
978 ``check``
978 A list of merge success-checking options:
979 A list of merge success-checking options:
979
980
980 ``changed``
981 ``changed``
981 Ask whether merge was successful when the merged file shows no changes.
982 Ask whether merge was successful when the merged file shows no changes.
982 ``conflicts``
983 ``conflicts``
983 Check whether there are conflicts even though the tool reported success.
984 Check whether there are conflicts even though the tool reported success.
984 ``prompt``
985 ``prompt``
985 Always prompt for merge success, regardless of success reported by tool.
986 Always prompt for merge success, regardless of success reported by tool.
986
987
987 ``fixeol``
988 ``fixeol``
988 Attempt to fix up EOL changes caused by the merge tool.
989 Attempt to fix up EOL changes caused by the merge tool.
989 Default: False
990 Default: False
990
991
991 ``gui``
992 ``gui``
992 This tool requires a graphical interface to run. Default: False
993 This tool requires a graphical interface to run. Default: False
993
994
994 ``regkey``
995 ``regkey``
995 Windows registry key which describes install location of this
996 Windows registry key which describes install location of this
996 tool. Mercurial will search for this key first under
997 tool. Mercurial will search for this key first under
997 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
998 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
998 Default: None
999 Default: None
999
1000
1000 ``regkeyalt``
1001 ``regkeyalt``
1001 An alternate Windows registry key to try if the first key is not
1002 An alternate Windows registry key to try if the first key is not
1002 found. The alternate key uses the same ``regname`` and ``regappend``
1003 found. The alternate key uses the same ``regname`` and ``regappend``
1003 semantics of the primary key. The most common use for this key
1004 semantics of the primary key. The most common use for this key
1004 is to search for 32bit applications on 64bit operating systems.
1005 is to search for 32bit applications on 64bit operating systems.
1005 Default: None
1006 Default: None
1006
1007
1007 ``regname``
1008 ``regname``
1008 Name of value to read from specified registry key. Defaults to the
1009 Name of value to read from specified registry key. Defaults to the
1009 unnamed (default) value.
1010 unnamed (default) value.
1010
1011
1011 ``regappend``
1012 ``regappend``
1012 String to append to the value read from the registry, typically
1013 String to append to the value read from the registry, typically
1013 the executable name of the tool.
1014 the executable name of the tool.
1014 Default: None
1015 Default: None
1015
1016
1016
1017
1017 ``patch``
1018 ``patch``
1018 ---------
1019 ---------
1019
1020
1020 Settings used when applying patches, for instance through the 'import'
1021 Settings used when applying patches, for instance through the 'import'
1021 command or with Mercurial Queues extension.
1022 command or with Mercurial Queues extension.
1022
1023
1023 ``eol``
1024 ``eol``
1024 When set to 'strict' patch content and patched files end of lines
1025 When set to 'strict' patch content and patched files end of lines
1025 are preserved. When set to ``lf`` or ``crlf``, both files end of
1026 are preserved. When set to ``lf`` or ``crlf``, both files end of
1026 lines are ignored when patching and the result line endings are
1027 lines are ignored when patching and the result line endings are
1027 normalized to either LF (Unix) or CRLF (Windows). When set to
1028 normalized to either LF (Unix) or CRLF (Windows). When set to
1028 ``auto``, end of lines are again ignored while patching but line
1029 ``auto``, end of lines are again ignored while patching but line
1029 endings in patched files are normalized to their original setting
1030 endings in patched files are normalized to their original setting
1030 on a per-file basis. If target file does not exist or has no end
1031 on a per-file basis. If target file does not exist or has no end
1031 of line, patch line endings are preserved.
1032 of line, patch line endings are preserved.
1032 Default: strict.
1033 Default: strict.
1033
1034
1034
1035
1035 ``paths``
1036 ``paths``
1036 ---------
1037 ---------
1037
1038
1038 Assigns symbolic names to repositories. The left side is the
1039 Assigns symbolic names to repositories. The left side is the
1039 symbolic name, and the right gives the directory or URL that is the
1040 symbolic name, and the right gives the directory or URL that is the
1040 location of the repository. Default paths can be declared by setting
1041 location of the repository. Default paths can be declared by setting
1041 the following entries.
1042 the following entries.
1042
1043
1043 ``default``
1044 ``default``
1044 Directory or URL to use when pulling if no source is specified.
1045 Directory or URL to use when pulling if no source is specified.
1045 Default is set to repository from which the current repository was
1046 Default is set to repository from which the current repository was
1046 cloned.
1047 cloned.
1047
1048
1048 ``default-push``
1049 ``default-push``
1049 Optional. Directory or URL to use when pushing if no destination
1050 Optional. Directory or URL to use when pushing if no destination
1050 is specified.
1051 is specified.
1051
1052
1052 Custom paths can be defined by assigning the path to a name that later can be
1053 Custom paths can be defined by assigning the path to a name that later can be
1053 used from the command line. Example::
1054 used from the command line. Example::
1054
1055
1055 [paths]
1056 [paths]
1056 my_path = http://example.com/path
1057 my_path = http://example.com/path
1057
1058
1058 To push to the path defined in ``my_path`` run the command::
1059 To push to the path defined in ``my_path`` run the command::
1059
1060
1060 hg push my_path
1061 hg push my_path
1061
1062
1062
1063
1063 ``phases``
1064 ``phases``
1064 ----------
1065 ----------
1065
1066
1066 Specifies default handling of phases. See :hg:`help phases` for more
1067 Specifies default handling of phases. See :hg:`help phases` for more
1067 information about working with phases.
1068 information about working with phases.
1068
1069
1069 ``publish``
1070 ``publish``
1070 Controls draft phase behavior when working as a server. When true,
1071 Controls draft phase behavior when working as a server. When true,
1071 pushed changesets are set to public in both client and server and
1072 pushed changesets are set to public in both client and server and
1072 pulled or cloned changesets are set to public in the client.
1073 pulled or cloned changesets are set to public in the client.
1073 Default: True
1074 Default: True
1074
1075
1075 ``new-commit``
1076 ``new-commit``
1076 Phase of newly-created commits.
1077 Phase of newly-created commits.
1077 Default: draft
1078 Default: draft
1078
1079
1079 ``checksubrepos``
1080 ``checksubrepos``
1080 Check the phase of the current revision of each subrepository. Allowed
1081 Check the phase of the current revision of each subrepository. Allowed
1081 values are "ignore", "follow" and "abort". For settings other than
1082 values are "ignore", "follow" and "abort". For settings other than
1082 "ignore", the phase of the current revision of each subrepository is
1083 "ignore", the phase of the current revision of each subrepository is
1083 checked before committing the parent repository. If any of those phases is
1084 checked before committing the parent repository. If any of those phases is
1084 greater than the phase of the parent repository (e.g. if a subrepo is in a
1085 greater than the phase of the parent repository (e.g. if a subrepo is in a
1085 "secret" phase while the parent repo is in "draft" phase), the commit is
1086 "secret" phase while the parent repo is in "draft" phase), the commit is
1086 either aborted (if checksubrepos is set to "abort") or the higher phase is
1087 either aborted (if checksubrepos is set to "abort") or the higher phase is
1087 used for the parent repository commit (if set to "follow").
1088 used for the parent repository commit (if set to "follow").
1088 Default: "follow"
1089 Default: "follow"
1089
1090
1090
1091
1091 ``profiling``
1092 ``profiling``
1092 -------------
1093 -------------
1093
1094
1094 Specifies profiling type, format, and file output. Two profilers are
1095 Specifies profiling type, format, and file output. Two profilers are
1095 supported: an instrumenting profiler (named ``ls``), and a sampling
1096 supported: an instrumenting profiler (named ``ls``), and a sampling
1096 profiler (named ``stat``).
1097 profiler (named ``stat``).
1097
1098
1098 In this section description, 'profiling data' stands for the raw data
1099 In this section description, 'profiling data' stands for the raw data
1099 collected during profiling, while 'profiling report' stands for a
1100 collected during profiling, while 'profiling report' stands for a
1100 statistical text report generated from the profiling data. The
1101 statistical text report generated from the profiling data. The
1101 profiling is done using lsprof.
1102 profiling is done using lsprof.
1102
1103
1103 ``type``
1104 ``type``
1104 The type of profiler to use.
1105 The type of profiler to use.
1105 Default: ls.
1106 Default: ls.
1106
1107
1107 ``ls``
1108 ``ls``
1108 Use Python's built-in instrumenting profiler. This profiler
1109 Use Python's built-in instrumenting profiler. This profiler
1109 works on all platforms, but each line number it reports is the
1110 works on all platforms, but each line number it reports is the
1110 first line of a function. This restriction makes it difficult to
1111 first line of a function. This restriction makes it difficult to
1111 identify the expensive parts of a non-trivial function.
1112 identify the expensive parts of a non-trivial function.
1112 ``stat``
1113 ``stat``
1113 Use a third-party statistical profiler, statprof. This profiler
1114 Use a third-party statistical profiler, statprof. This profiler
1114 currently runs only on Unix systems, and is most useful for
1115 currently runs only on Unix systems, and is most useful for
1115 profiling commands that run for longer than about 0.1 seconds.
1116 profiling commands that run for longer than about 0.1 seconds.
1116
1117
1117 ``format``
1118 ``format``
1118 Profiling format. Specific to the ``ls`` instrumenting profiler.
1119 Profiling format. Specific to the ``ls`` instrumenting profiler.
1119 Default: text.
1120 Default: text.
1120
1121
1121 ``text``
1122 ``text``
1122 Generate a profiling report. When saving to a file, it should be
1123 Generate a profiling report. When saving to a file, it should be
1123 noted that only the report is saved, and the profiling data is
1124 noted that only the report is saved, and the profiling data is
1124 not kept.
1125 not kept.
1125 ``kcachegrind``
1126 ``kcachegrind``
1126 Format profiling data for kcachegrind use: when saving to a
1127 Format profiling data for kcachegrind use: when saving to a
1127 file, the generated file can directly be loaded into
1128 file, the generated file can directly be loaded into
1128 kcachegrind.
1129 kcachegrind.
1129
1130
1130 ``frequency``
1131 ``frequency``
1131 Sampling frequency. Specific to the ``stat`` sampling profiler.
1132 Sampling frequency. Specific to the ``stat`` sampling profiler.
1132 Default: 1000.
1133 Default: 1000.
1133
1134
1134 ``output``
1135 ``output``
1135 File path where profiling data or report should be saved. If the
1136 File path where profiling data or report should be saved. If the
1136 file exists, it is replaced. Default: None, data is printed on
1137 file exists, it is replaced. Default: None, data is printed on
1137 stderr
1138 stderr
1138
1139
1139 ``sort``
1140 ``sort``
1140 Sort field. Specific to the ``ls`` instrumenting profiler.
1141 Sort field. Specific to the ``ls`` instrumenting profiler.
1141 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1142 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1142 ``inlinetime``.
1143 ``inlinetime``.
1143 Default: inlinetime.
1144 Default: inlinetime.
1144
1145
1145 ``limit``
1146 ``limit``
1146 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1147 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1147 Default: 30.
1148 Default: 30.
1148
1149
1149 ``nested``
1150 ``nested``
1150 Show at most this number of lines of drill-down info after each main entry.
1151 Show at most this number of lines of drill-down info after each main entry.
1151 This can help explain the difference between Total and Inline.
1152 This can help explain the difference between Total and Inline.
1152 Specific to the ``ls`` instrumenting profiler.
1153 Specific to the ``ls`` instrumenting profiler.
1153 Default: 5.
1154 Default: 5.
1154
1155
1155 ``revsetalias``
1156 ``revsetalias``
1156 ---------------
1157 ---------------
1157
1158
1158 Alias definitions for revsets. See :hg:`help revsets` for details.
1159 Alias definitions for revsets. See :hg:`help revsets` for details.
1159
1160
1160 ``server``
1161 ``server``
1161 ----------
1162 ----------
1162
1163
1163 Controls generic server settings.
1164 Controls generic server settings.
1164
1165
1165 ``uncompressed``
1166 ``uncompressed``
1166 Whether to allow clients to clone a repository using the
1167 Whether to allow clients to clone a repository using the
1167 uncompressed streaming protocol. This transfers about 40% more
1168 uncompressed streaming protocol. This transfers about 40% more
1168 data than a regular clone, but uses less memory and CPU on both
1169 data than a regular clone, but uses less memory and CPU on both
1169 server and client. Over a LAN (100 Mbps or better) or a very fast
1170 server and client. Over a LAN (100 Mbps or better) or a very fast
1170 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1171 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1171 regular clone. Over most WAN connections (anything slower than
1172 regular clone. Over most WAN connections (anything slower than
1172 about 6 Mbps), uncompressed streaming is slower, because of the
1173 about 6 Mbps), uncompressed streaming is slower, because of the
1173 extra data transfer overhead. This mode will also temporarily hold
1174 extra data transfer overhead. This mode will also temporarily hold
1174 the write lock while determining what data to transfer.
1175 the write lock while determining what data to transfer.
1175 Default is True.
1176 Default is True.
1176
1177
1177 ``preferuncompressed``
1178 ``preferuncompressed``
1178 When set, clients will try to use the uncompressed streaming
1179 When set, clients will try to use the uncompressed streaming
1179 protocol. Default is False.
1180 protocol. Default is False.
1180
1181
1181 ``validate``
1182 ``validate``
1182 Whether to validate the completeness of pushed changesets by
1183 Whether to validate the completeness of pushed changesets by
1183 checking that all new file revisions specified in manifests are
1184 checking that all new file revisions specified in manifests are
1184 present. Default is False.
1185 present. Default is False.
1185
1186
1186 ``smtp``
1187 ``smtp``
1187 --------
1188 --------
1188
1189
1189 Configuration for extensions that need to send email messages.
1190 Configuration for extensions that need to send email messages.
1190
1191
1191 ``host``
1192 ``host``
1192 Host name of mail server, e.g. "mail.example.com".
1193 Host name of mail server, e.g. "mail.example.com".
1193
1194
1194 ``port``
1195 ``port``
1195 Optional. Port to connect to on mail server. Default: 465 (if
1196 Optional. Port to connect to on mail server. Default: 465 (if
1196 ``tls`` is smtps) or 25 (otherwise).
1197 ``tls`` is smtps) or 25 (otherwise).
1197
1198
1198 ``tls``
1199 ``tls``
1199 Optional. Method to enable TLS when connecting to mail server: starttls,
1200 Optional. Method to enable TLS when connecting to mail server: starttls,
1200 smtps or none. Default: none.
1201 smtps or none. Default: none.
1201
1202
1202 ``verifycert``
1203 ``verifycert``
1203 Optional. Verification for the certificate of mail server, when
1204 Optional. Verification for the certificate of mail server, when
1204 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1205 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1205 "strict" or "loose", the certificate is verified as same as the
1206 "strict" or "loose", the certificate is verified as same as the
1206 verification for HTTPS connections (see ``[hostfingerprints]`` and
1207 verification for HTTPS connections (see ``[hostfingerprints]`` and
1207 ``[web] cacerts`` also). For "strict", sending email is also
1208 ``[web] cacerts`` also). For "strict", sending email is also
1208 aborted, if there is no configuration for mail server in
1209 aborted, if there is no configuration for mail server in
1209 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1210 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1210 :hg:`email` overwrites this as "loose". Default: "strict".
1211 :hg:`email` overwrites this as "loose". Default: "strict".
1211
1212
1212 ``username``
1213 ``username``
1213 Optional. User name for authenticating with the SMTP server.
1214 Optional. User name for authenticating with the SMTP server.
1214 Default: none.
1215 Default: none.
1215
1216
1216 ``password``
1217 ``password``
1217 Optional. Password for authenticating with the SMTP server. If not
1218 Optional. Password for authenticating with the SMTP server. If not
1218 specified, interactive sessions will prompt the user for a
1219 specified, interactive sessions will prompt the user for a
1219 password; non-interactive sessions will fail. Default: none.
1220 password; non-interactive sessions will fail. Default: none.
1220
1221
1221 ``local_hostname``
1222 ``local_hostname``
1222 Optional. It's the hostname that the sender can use to identify
1223 Optional. It's the hostname that the sender can use to identify
1223 itself to the MTA.
1224 itself to the MTA.
1224
1225
1225
1226
1226 ``subpaths``
1227 ``subpaths``
1227 ------------
1228 ------------
1228
1229
1229 Subrepository source URLs can go stale if a remote server changes name
1230 Subrepository source URLs can go stale if a remote server changes name
1230 or becomes temporarily unavailable. This section lets you define
1231 or becomes temporarily unavailable. This section lets you define
1231 rewrite rules of the form::
1232 rewrite rules of the form::
1232
1233
1233 <pattern> = <replacement>
1234 <pattern> = <replacement>
1234
1235
1235 where ``pattern`` is a regular expression matching a subrepository
1236 where ``pattern`` is a regular expression matching a subrepository
1236 source URL and ``replacement`` is the replacement string used to
1237 source URL and ``replacement`` is the replacement string used to
1237 rewrite it. Groups can be matched in ``pattern`` and referenced in
1238 rewrite it. Groups can be matched in ``pattern`` and referenced in
1238 ``replacements``. For instance::
1239 ``replacements``. For instance::
1239
1240
1240 http://server/(.*)-hg/ = http://hg.server/\1/
1241 http://server/(.*)-hg/ = http://hg.server/\1/
1241
1242
1242 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1243 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1243
1244
1244 Relative subrepository paths are first made absolute, and the
1245 Relative subrepository paths are first made absolute, and the
1245 rewrite rules are then applied on the full (absolute) path. The rules
1246 rewrite rules are then applied on the full (absolute) path. The rules
1246 are applied in definition order.
1247 are applied in definition order.
1247
1248
1248 ``trusted``
1249 ``trusted``
1249 -----------
1250 -----------
1250
1251
1251 Mercurial will not use the settings in the
1252 Mercurial will not use the settings in the
1252 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1253 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1253 user or to a trusted group, as various hgrc features allow arbitrary
1254 user or to a trusted group, as various hgrc features allow arbitrary
1254 commands to be run. This issue is often encountered when configuring
1255 commands to be run. This issue is often encountered when configuring
1255 hooks or extensions for shared repositories or servers. However,
1256 hooks or extensions for shared repositories or servers. However,
1256 the web interface will use some safe settings from the ``[web]``
1257 the web interface will use some safe settings from the ``[web]``
1257 section.
1258 section.
1258
1259
1259 This section specifies what users and groups are trusted. The
1260 This section specifies what users and groups are trusted. The
1260 current user is always trusted. To trust everybody, list a user or a
1261 current user is always trusted. To trust everybody, list a user or a
1261 group with name ``*``. These settings must be placed in an
1262 group with name ``*``. These settings must be placed in an
1262 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1263 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1263 user or service running Mercurial.
1264 user or service running Mercurial.
1264
1265
1265 ``users``
1266 ``users``
1266 Comma-separated list of trusted users.
1267 Comma-separated list of trusted users.
1267
1268
1268 ``groups``
1269 ``groups``
1269 Comma-separated list of trusted groups.
1270 Comma-separated list of trusted groups.
1270
1271
1271
1272
1272 ``ui``
1273 ``ui``
1273 ------
1274 ------
1274
1275
1275 User interface controls.
1276 User interface controls.
1276
1277
1277 ``archivemeta``
1278 ``archivemeta``
1278 Whether to include the .hg_archival.txt file containing meta data
1279 Whether to include the .hg_archival.txt file containing meta data
1279 (hashes for the repository base and for tip) in archives created
1280 (hashes for the repository base and for tip) in archives created
1280 by the :hg:`archive` command or downloaded via hgweb.
1281 by the :hg:`archive` command or downloaded via hgweb.
1281 Default is True.
1282 Default is True.
1282
1283
1283 ``askusername``
1284 ``askusername``
1284 Whether to prompt for a username when committing. If True, and
1285 Whether to prompt for a username when committing. If True, and
1285 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1286 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1286 be prompted to enter a username. If no username is entered, the
1287 be prompted to enter a username. If no username is entered, the
1287 default ``USER@HOST`` is used instead.
1288 default ``USER@HOST`` is used instead.
1288 Default is False.
1289 Default is False.
1289
1290
1290 ``commitsubrepos``
1291 ``commitsubrepos``
1291 Whether to commit modified subrepositories when committing the
1292 Whether to commit modified subrepositories when committing the
1292 parent repository. If False and one subrepository has uncommitted
1293 parent repository. If False and one subrepository has uncommitted
1293 changes, abort the commit.
1294 changes, abort the commit.
1294 Default is False.
1295 Default is False.
1295
1296
1296 ``debug``
1297 ``debug``
1297 Print debugging information. True or False. Default is False.
1298 Print debugging information. True or False. Default is False.
1298
1299
1299 ``editor``
1300 ``editor``
1300 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1301 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1301
1302
1302 ``fallbackencoding``
1303 ``fallbackencoding``
1303 Encoding to try if it's not possible to decode the changelog using
1304 Encoding to try if it's not possible to decode the changelog using
1304 UTF-8. Default is ISO-8859-1.
1305 UTF-8. Default is ISO-8859-1.
1305
1306
1306 ``ignore``
1307 ``ignore``
1307 A file to read per-user ignore patterns from. This file should be
1308 A file to read per-user ignore patterns from. This file should be
1308 in the same format as a repository-wide .hgignore file. This
1309 in the same format as a repository-wide .hgignore file. This
1309 option supports hook syntax, so if you want to specify multiple
1310 option supports hook syntax, so if you want to specify multiple
1310 ignore files, you can do so by setting something like
1311 ignore files, you can do so by setting something like
1311 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1312 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1312 format, see the ``hgignore(5)`` man page.
1313 format, see the ``hgignore(5)`` man page.
1313
1314
1314 ``interactive``
1315 ``interactive``
1315 Allow to prompt the user. True or False. Default is True.
1316 Allow to prompt the user. True or False. Default is True.
1316
1317
1317 ``logtemplate``
1318 ``logtemplate``
1318 Template string for commands that print changesets.
1319 Template string for commands that print changesets.
1319
1320
1320 ``merge``
1321 ``merge``
1321 The conflict resolution program to use during a manual merge.
1322 The conflict resolution program to use during a manual merge.
1322 For more information on merge tools see :hg:`help merge-tools`.
1323 For more information on merge tools see :hg:`help merge-tools`.
1323 For configuring merge tools see the ``[merge-tools]`` section.
1324 For configuring merge tools see the ``[merge-tools]`` section.
1324
1325
1325 ``mergemarkers``
1326 ``mergemarkers``
1326 Sets the merge conflict marker label styling. The ``detailed``
1327 Sets the merge conflict marker label styling. The ``detailed``
1327 style uses the ``mergemarkertemplate`` setting to style the labels.
1328 style uses the ``mergemarkertemplate`` setting to style the labels.
1328 The ``basic`` style just uses 'local' and 'other' as the marker label.
1329 The ``basic`` style just uses 'local' and 'other' as the marker label.
1329 One of ``basic`` or ``detailed``.
1330 One of ``basic`` or ``detailed``.
1330 Default is ``basic``.
1331 Default is ``basic``.
1331
1332
1332 ``mergemarkertemplate``
1333 ``mergemarkertemplate``
1333 The template used to print the commit description next to each conflict
1334 The template used to print the commit description next to each conflict
1334 marker during merge conflicts. See :hg:`help templates` for the template
1335 marker during merge conflicts. See :hg:`help templates` for the template
1335 format.
1336 format.
1336 Defaults to showing the hash, tags, branches, bookmarks, author, and
1337 Defaults to showing the hash, tags, branches, bookmarks, author, and
1337 the first line of the commit description.
1338 the first line of the commit description.
1338 You have to pay attention to encodings of managed files, if you
1339 You have to pay attention to encodings of managed files, if you
1339 use non-ASCII characters in tags, branches, bookmarks, author
1340 use non-ASCII characters in tags, branches, bookmarks, author
1340 and/or commit descriptions. At template expansion, non-ASCII
1341 and/or commit descriptions. At template expansion, non-ASCII
1341 characters use the encoding specified by ``--encoding`` global
1342 characters use the encoding specified by ``--encoding`` global
1342 option, ``HGENCODING`` or other locale setting environment
1343 option, ``HGENCODING`` or other locale setting environment
1343 variables. The difference of encoding between merged file and
1344 variables. The difference of encoding between merged file and
1344 conflict markers causes serious problem.
1345 conflict markers causes serious problem.
1345
1346
1346 ``portablefilenames``
1347 ``portablefilenames``
1347 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1348 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1348 Default is ``warn``.
1349 Default is ``warn``.
1349 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1350 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1350 platforms, if a file with a non-portable filename is added (e.g. a file
1351 platforms, if a file with a non-portable filename is added (e.g. a file
1351 with a name that can't be created on Windows because it contains reserved
1352 with a name that can't be created on Windows because it contains reserved
1352 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1353 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1353 collision with an existing file).
1354 collision with an existing file).
1354 If set to ``ignore`` (or ``false``), no warning is printed.
1355 If set to ``ignore`` (or ``false``), no warning is printed.
1355 If set to ``abort``, the command is aborted.
1356 If set to ``abort``, the command is aborted.
1356 On Windows, this configuration option is ignored and the command aborted.
1357 On Windows, this configuration option is ignored and the command aborted.
1357
1358
1358 ``quiet``
1359 ``quiet``
1359 Reduce the amount of output printed. True or False. Default is False.
1360 Reduce the amount of output printed. True or False. Default is False.
1360
1361
1361 ``remotecmd``
1362 ``remotecmd``
1362 remote command to use for clone/push/pull operations. Default is ``hg``.
1363 remote command to use for clone/push/pull operations. Default is ``hg``.
1363
1364
1364 ``reportoldssl``
1365 ``reportoldssl``
1365 Warn if an SSL certificate is unable to be due to using Python
1366 Warn if an SSL certificate is unable to be due to using Python
1366 2.5 or earlier. True or False. Default is True.
1367 2.5 or earlier. True or False. Default is True.
1367
1368
1368 ``report_untrusted``
1369 ``report_untrusted``
1369 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1370 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1370 trusted user or group. True or False. Default is True.
1371 trusted user or group. True or False. Default is True.
1371
1372
1372 ``slash``
1373 ``slash``
1373 Display paths using a slash (``/``) as the path separator. This
1374 Display paths using a slash (``/``) as the path separator. This
1374 only makes a difference on systems where the default path
1375 only makes a difference on systems where the default path
1375 separator is not the slash character (e.g. Windows uses the
1376 separator is not the slash character (e.g. Windows uses the
1376 backslash character (``\``)).
1377 backslash character (``\``)).
1377 Default is False.
1378 Default is False.
1378
1379
1379 ``ssh``
1380 ``ssh``
1380 command to use for SSH connections. Default is ``ssh``.
1381 command to use for SSH connections. Default is ``ssh``.
1381
1382
1382 ``strict``
1383 ``strict``
1383 Require exact command names, instead of allowing unambiguous
1384 Require exact command names, instead of allowing unambiguous
1384 abbreviations. True or False. Default is False.
1385 abbreviations. True or False. Default is False.
1385
1386
1386 ``style``
1387 ``style``
1387 Name of style to use for command output.
1388 Name of style to use for command output.
1388
1389
1389 ``timeout``
1390 ``timeout``
1390 The timeout used when a lock is held (in seconds), a negative value
1391 The timeout used when a lock is held (in seconds), a negative value
1391 means no timeout. Default is 600.
1392 means no timeout. Default is 600.
1392
1393
1393 ``traceback``
1394 ``traceback``
1394 Mercurial always prints a traceback when an unknown exception
1395 Mercurial always prints a traceback when an unknown exception
1395 occurs. Setting this to True will make Mercurial print a traceback
1396 occurs. Setting this to True will make Mercurial print a traceback
1396 on all exceptions, even those recognized by Mercurial (such as
1397 on all exceptions, even those recognized by Mercurial (such as
1397 IOError or MemoryError). Default is False.
1398 IOError or MemoryError). Default is False.
1398
1399
1399 ``username``
1400 ``username``
1400 The committer of a changeset created when running "commit".
1401 The committer of a changeset created when running "commit".
1401 Typically a person's name and email address, e.g. ``Fred Widget
1402 Typically a person's name and email address, e.g. ``Fred Widget
1402 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1403 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1403 the username in hgrc is empty, it has to be specified manually or
1404 the username in hgrc is empty, it has to be specified manually or
1404 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1405 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1405 ``username =`` in the system hgrc). Environment variables in the
1406 ``username =`` in the system hgrc). Environment variables in the
1406 username are expanded.
1407 username are expanded.
1407
1408
1408 ``verbose``
1409 ``verbose``
1409 Increase the amount of output printed. True or False. Default is False.
1410 Increase the amount of output printed. True or False. Default is False.
1410
1411
1411
1412
1412 ``web``
1413 ``web``
1413 -------
1414 -------
1414
1415
1415 Web interface configuration. The settings in this section apply to
1416 Web interface configuration. The settings in this section apply to
1416 both the builtin webserver (started by :hg:`serve`) and the script you
1417 both the builtin webserver (started by :hg:`serve`) and the script you
1417 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1418 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1418 and WSGI).
1419 and WSGI).
1419
1420
1420 The Mercurial webserver does no authentication (it does not prompt for
1421 The Mercurial webserver does no authentication (it does not prompt for
1421 usernames and passwords to validate *who* users are), but it does do
1422 usernames and passwords to validate *who* users are), but it does do
1422 authorization (it grants or denies access for *authenticated users*
1423 authorization (it grants or denies access for *authenticated users*
1423 based on settings in this section). You must either configure your
1424 based on settings in this section). You must either configure your
1424 webserver to do authentication for you, or disable the authorization
1425 webserver to do authentication for you, or disable the authorization
1425 checks.
1426 checks.
1426
1427
1427 For a quick setup in a trusted environment, e.g., a private LAN, where
1428 For a quick setup in a trusted environment, e.g., a private LAN, where
1428 you want it to accept pushes from anybody, you can use the following
1429 you want it to accept pushes from anybody, you can use the following
1429 command line::
1430 command line::
1430
1431
1431 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1432 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1432
1433
1433 Note that this will allow anybody to push anything to the server and
1434 Note that this will allow anybody to push anything to the server and
1434 that this should not be used for public servers.
1435 that this should not be used for public servers.
1435
1436
1436 The full set of options is:
1437 The full set of options is:
1437
1438
1438 ``accesslog``
1439 ``accesslog``
1439 Where to output the access log. Default is stdout.
1440 Where to output the access log. Default is stdout.
1440
1441
1441 ``address``
1442 ``address``
1442 Interface address to bind to. Default is all.
1443 Interface address to bind to. Default is all.
1443
1444
1444 ``allow_archive``
1445 ``allow_archive``
1445 List of archive format (bz2, gz, zip) allowed for downloading.
1446 List of archive format (bz2, gz, zip) allowed for downloading.
1446 Default is empty.
1447 Default is empty.
1447
1448
1448 ``allowbz2``
1449 ``allowbz2``
1449 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1450 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1450 revisions.
1451 revisions.
1451 Default is False.
1452 Default is False.
1452
1453
1453 ``allowgz``
1454 ``allowgz``
1454 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1455 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1455 revisions.
1456 revisions.
1456 Default is False.
1457 Default is False.
1457
1458
1458 ``allowpull``
1459 ``allowpull``
1459 Whether to allow pulling from the repository. Default is True.
1460 Whether to allow pulling from the repository. Default is True.
1460
1461
1461 ``allow_push``
1462 ``allow_push``
1462 Whether to allow pushing to the repository. If empty or not set,
1463 Whether to allow pushing to the repository. If empty or not set,
1463 push is not allowed. If the special value ``*``, any remote user can
1464 push is not allowed. If the special value ``*``, any remote user can
1464 push, including unauthenticated users. Otherwise, the remote user
1465 push, including unauthenticated users. Otherwise, the remote user
1465 must have been authenticated, and the authenticated user name must
1466 must have been authenticated, and the authenticated user name must
1466 be present in this list. The contents of the allow_push list are
1467 be present in this list. The contents of the allow_push list are
1467 examined after the deny_push list.
1468 examined after the deny_push list.
1468
1469
1469 ``allow_read``
1470 ``allow_read``
1470 If the user has not already been denied repository access due to
1471 If the user has not already been denied repository access due to
1471 the contents of deny_read, this list determines whether to grant
1472 the contents of deny_read, this list determines whether to grant
1472 repository access to the user. If this list is not empty, and the
1473 repository access to the user. If this list is not empty, and the
1473 user is unauthenticated or not present in the list, then access is
1474 user is unauthenticated or not present in the list, then access is
1474 denied for the user. If the list is empty or not set, then access
1475 denied for the user. If the list is empty or not set, then access
1475 is permitted to all users by default. Setting allow_read to the
1476 is permitted to all users by default. Setting allow_read to the
1476 special value ``*`` is equivalent to it not being set (i.e. access
1477 special value ``*`` is equivalent to it not being set (i.e. access
1477 is permitted to all users). The contents of the allow_read list are
1478 is permitted to all users). The contents of the allow_read list are
1478 examined after the deny_read list.
1479 examined after the deny_read list.
1479
1480
1480 ``allowzip``
1481 ``allowzip``
1481 (DEPRECATED) Whether to allow .zip downloading of repository
1482 (DEPRECATED) Whether to allow .zip downloading of repository
1482 revisions. Default is False. This feature creates temporary files.
1483 revisions. Default is False. This feature creates temporary files.
1483
1484
1484 ``archivesubrepos``
1485 ``archivesubrepos``
1485 Whether to recurse into subrepositories when archiving. Default is
1486 Whether to recurse into subrepositories when archiving. Default is
1486 False.
1487 False.
1487
1488
1488 ``baseurl``
1489 ``baseurl``
1489 Base URL to use when publishing URLs in other locations, so
1490 Base URL to use when publishing URLs in other locations, so
1490 third-party tools like email notification hooks can construct
1491 third-party tools like email notification hooks can construct
1491 URLs. Example: ``http://hgserver/repos/``.
1492 URLs. Example: ``http://hgserver/repos/``.
1492
1493
1493 ``cacerts``
1494 ``cacerts``
1494 Path to file containing a list of PEM encoded certificate
1495 Path to file containing a list of PEM encoded certificate
1495 authority certificates. Environment variables and ``~user``
1496 authority certificates. Environment variables and ``~user``
1496 constructs are expanded in the filename. If specified on the
1497 constructs are expanded in the filename. If specified on the
1497 client, then it will verify the identity of remote HTTPS servers
1498 client, then it will verify the identity of remote HTTPS servers
1498 with these certificates.
1499 with these certificates.
1499
1500
1500 This feature is only supported when using Python 2.6 or later. If you wish
1501 This feature is only supported when using Python 2.6 or later. If you wish
1501 to use it with earlier versions of Python, install the backported
1502 to use it with earlier versions of Python, install the backported
1502 version of the ssl library that is available from
1503 version of the ssl library that is available from
1503 ``http://pypi.python.org``.
1504 ``http://pypi.python.org``.
1504
1505
1505 To disable SSL verification temporarily, specify ``--insecure`` from
1506 To disable SSL verification temporarily, specify ``--insecure`` from
1506 command line.
1507 command line.
1507
1508
1508 You can use OpenSSL's CA certificate file if your platform has
1509 You can use OpenSSL's CA certificate file if your platform has
1509 one. On most Linux systems this will be
1510 one. On most Linux systems this will be
1510 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1511 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1511 generate this file manually. The form must be as follows::
1512 generate this file manually. The form must be as follows::
1512
1513
1513 -----BEGIN CERTIFICATE-----
1514 -----BEGIN CERTIFICATE-----
1514 ... (certificate in base64 PEM encoding) ...
1515 ... (certificate in base64 PEM encoding) ...
1515 -----END CERTIFICATE-----
1516 -----END CERTIFICATE-----
1516 -----BEGIN CERTIFICATE-----
1517 -----BEGIN CERTIFICATE-----
1517 ... (certificate in base64 PEM encoding) ...
1518 ... (certificate in base64 PEM encoding) ...
1518 -----END CERTIFICATE-----
1519 -----END CERTIFICATE-----
1519
1520
1520 ``cache``
1521 ``cache``
1521 Whether to support caching in hgweb. Defaults to True.
1522 Whether to support caching in hgweb. Defaults to True.
1522
1523
1523 ``collapse``
1524 ``collapse``
1524 With ``descend`` enabled, repositories in subdirectories are shown at
1525 With ``descend`` enabled, repositories in subdirectories are shown at
1525 a single level alongside repositories in the current path. With
1526 a single level alongside repositories in the current path. With
1526 ``collapse`` also enabled, repositories residing at a deeper level than
1527 ``collapse`` also enabled, repositories residing at a deeper level than
1527 the current path are grouped behind navigable directory entries that
1528 the current path are grouped behind navigable directory entries that
1528 lead to the locations of these repositories. In effect, this setting
1529 lead to the locations of these repositories. In effect, this setting
1529 collapses each collection of repositories found within a subdirectory
1530 collapses each collection of repositories found within a subdirectory
1530 into a single entry for that subdirectory. Default is False.
1531 into a single entry for that subdirectory. Default is False.
1531
1532
1532 ``comparisoncontext``
1533 ``comparisoncontext``
1533 Number of lines of context to show in side-by-side file comparison. If
1534 Number of lines of context to show in side-by-side file comparison. If
1534 negative or the value ``full``, whole files are shown. Default is 5.
1535 negative or the value ``full``, whole files are shown. Default is 5.
1535 This setting can be overridden by a ``context`` request parameter to the
1536 This setting can be overridden by a ``context`` request parameter to the
1536 ``comparison`` command, taking the same values.
1537 ``comparison`` command, taking the same values.
1537
1538
1538 ``contact``
1539 ``contact``
1539 Name or email address of the person in charge of the repository.
1540 Name or email address of the person in charge of the repository.
1540 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1541 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1541
1542
1542 ``deny_push``
1543 ``deny_push``
1543 Whether to deny pushing to the repository. If empty or not set,
1544 Whether to deny pushing to the repository. If empty or not set,
1544 push is not denied. If the special value ``*``, all remote users are
1545 push is not denied. If the special value ``*``, all remote users are
1545 denied push. Otherwise, unauthenticated users are all denied, and
1546 denied push. Otherwise, unauthenticated users are all denied, and
1546 any authenticated user name present in this list is also denied. The
1547 any authenticated user name present in this list is also denied. The
1547 contents of the deny_push list are examined before the allow_push list.
1548 contents of the deny_push list are examined before the allow_push list.
1548
1549
1549 ``deny_read``
1550 ``deny_read``
1550 Whether to deny reading/viewing of the repository. If this list is
1551 Whether to deny reading/viewing of the repository. If this list is
1551 not empty, unauthenticated users are all denied, and any
1552 not empty, unauthenticated users are all denied, and any
1552 authenticated user name present in this list is also denied access to
1553 authenticated user name present in this list is also denied access to
1553 the repository. If set to the special value ``*``, all remote users
1554 the repository. If set to the special value ``*``, all remote users
1554 are denied access (rarely needed ;). If deny_read is empty or not set,
1555 are denied access (rarely needed ;). If deny_read is empty or not set,
1555 the determination of repository access depends on the presence and
1556 the determination of repository access depends on the presence and
1556 content of the allow_read list (see description). If both
1557 content of the allow_read list (see description). If both
1557 deny_read and allow_read are empty or not set, then access is
1558 deny_read and allow_read are empty or not set, then access is
1558 permitted to all users by default. If the repository is being
1559 permitted to all users by default. If the repository is being
1559 served via hgwebdir, denied users will not be able to see it in
1560 served via hgwebdir, denied users will not be able to see it in
1560 the list of repositories. The contents of the deny_read list have
1561 the list of repositories. The contents of the deny_read list have
1561 priority over (are examined before) the contents of the allow_read
1562 priority over (are examined before) the contents of the allow_read
1562 list.
1563 list.
1563
1564
1564 ``descend``
1565 ``descend``
1565 hgwebdir indexes will not descend into subdirectories. Only repositories
1566 hgwebdir indexes will not descend into subdirectories. Only repositories
1566 directly in the current path will be shown (other repositories are still
1567 directly in the current path will be shown (other repositories are still
1567 available from the index corresponding to their containing path).
1568 available from the index corresponding to their containing path).
1568
1569
1569 ``description``
1570 ``description``
1570 Textual description of the repository's purpose or contents.
1571 Textual description of the repository's purpose or contents.
1571 Default is "unknown".
1572 Default is "unknown".
1572
1573
1573 ``encoding``
1574 ``encoding``
1574 Character encoding name. Default is the current locale charset.
1575 Character encoding name. Default is the current locale charset.
1575 Example: "UTF-8"
1576 Example: "UTF-8"
1576
1577
1577 ``errorlog``
1578 ``errorlog``
1578 Where to output the error log. Default is stderr.
1579 Where to output the error log. Default is stderr.
1579
1580
1580 ``guessmime``
1581 ``guessmime``
1581 Control MIME types for raw download of file content.
1582 Control MIME types for raw download of file content.
1582 Set to True to let hgweb guess the content type from the file
1583 Set to True to let hgweb guess the content type from the file
1583 extension. This will serve HTML files as ``text/html`` and might
1584 extension. This will serve HTML files as ``text/html`` and might
1584 allow cross-site scripting attacks when serving untrusted
1585 allow cross-site scripting attacks when serving untrusted
1585 repositories. Default is False.
1586 repositories. Default is False.
1586
1587
1587 ``hidden``
1588 ``hidden``
1588 Whether to hide the repository in the hgwebdir index.
1589 Whether to hide the repository in the hgwebdir index.
1589 Default is False.
1590 Default is False.
1590
1591
1591 ``ipv6``
1592 ``ipv6``
1592 Whether to use IPv6. Default is False.
1593 Whether to use IPv6. Default is False.
1593
1594
1594 ``logoimg``
1595 ``logoimg``
1595 File name of the logo image that some templates display on each page.
1596 File name of the logo image that some templates display on each page.
1596 The file name is relative to ``staticurl``. That is, the full path to
1597 The file name is relative to ``staticurl``. That is, the full path to
1597 the logo image is "staticurl/logoimg".
1598 the logo image is "staticurl/logoimg".
1598 If unset, ``hglogo.png`` will be used.
1599 If unset, ``hglogo.png`` will be used.
1599
1600
1600 ``logourl``
1601 ``logourl``
1601 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1602 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1602 will be used.
1603 will be used.
1603
1604
1604 ``maxchanges``
1605 ``maxchanges``
1605 Maximum number of changes to list on the changelog. Default is 10.
1606 Maximum number of changes to list on the changelog. Default is 10.
1606
1607
1607 ``maxfiles``
1608 ``maxfiles``
1608 Maximum number of files to list per changeset. Default is 10.
1609 Maximum number of files to list per changeset. Default is 10.
1609
1610
1610 ``maxshortchanges``
1611 ``maxshortchanges``
1611 Maximum number of changes to list on the shortlog, graph or filelog
1612 Maximum number of changes to list on the shortlog, graph or filelog
1612 pages. Default is 60.
1613 pages. Default is 60.
1613
1614
1614 ``name``
1615 ``name``
1615 Repository name to use in the web interface. Default is current
1616 Repository name to use in the web interface. Default is current
1616 working directory.
1617 working directory.
1617
1618
1618 ``port``
1619 ``port``
1619 Port to listen on. Default is 8000.
1620 Port to listen on. Default is 8000.
1620
1621
1621 ``prefix``
1622 ``prefix``
1622 Prefix path to serve from. Default is '' (server root).
1623 Prefix path to serve from. Default is '' (server root).
1623
1624
1624 ``push_ssl``
1625 ``push_ssl``
1625 Whether to require that inbound pushes be transported over SSL to
1626 Whether to require that inbound pushes be transported over SSL to
1626 prevent password sniffing. Default is True.
1627 prevent password sniffing. Default is True.
1627
1628
1628 ``staticurl``
1629 ``staticurl``
1629 Base URL to use for static files. If unset, static files (e.g. the
1630 Base URL to use for static files. If unset, static files (e.g. the
1630 hgicon.png favicon) will be served by the CGI script itself. Use
1631 hgicon.png favicon) will be served by the CGI script itself. Use
1631 this setting to serve them directly with the HTTP server.
1632 this setting to serve them directly with the HTTP server.
1632 Example: ``http://hgserver/static/``.
1633 Example: ``http://hgserver/static/``.
1633
1634
1634 ``stripes``
1635 ``stripes``
1635 How many lines a "zebra stripe" should span in multi-line output.
1636 How many lines a "zebra stripe" should span in multi-line output.
1636 Default is 1; set to 0 to disable.
1637 Default is 1; set to 0 to disable.
1637
1638
1638 ``style``
1639 ``style``
1639 Which template map style to use.
1640 Which template map style to use.
1640
1641
1641 ``templates``
1642 ``templates``
1642 Where to find the HTML templates. Default is install path.
1643 Where to find the HTML templates. Default is install path.
1643
1644
1644 ``websub``
1645 ``websub``
1645 ----------
1646 ----------
1646
1647
1647 Web substitution filter definition. You can use this section to
1648 Web substitution filter definition. You can use this section to
1648 define a set of regular expression substitution patterns which
1649 define a set of regular expression substitution patterns which
1649 let you automatically modify the hgweb server output.
1650 let you automatically modify the hgweb server output.
1650
1651
1651 The default hgweb templates only apply these substitution patterns
1652 The default hgweb templates only apply these substitution patterns
1652 on the revision description fields. You can apply them anywhere
1653 on the revision description fields. You can apply them anywhere
1653 you want when you create your own templates by adding calls to the
1654 you want when you create your own templates by adding calls to the
1654 "websub" filter (usually after calling the "escape" filter).
1655 "websub" filter (usually after calling the "escape" filter).
1655
1656
1656 This can be used, for example, to convert issue references to links
1657 This can be used, for example, to convert issue references to links
1657 to your issue tracker, or to convert "markdown-like" syntax into
1658 to your issue tracker, or to convert "markdown-like" syntax into
1658 HTML (see the examples below).
1659 HTML (see the examples below).
1659
1660
1660 Each entry in this section names a substitution filter.
1661 Each entry in this section names a substitution filter.
1661 The value of each entry defines the substitution expression itself.
1662 The value of each entry defines the substitution expression itself.
1662 The websub expressions follow the old interhg extension syntax,
1663 The websub expressions follow the old interhg extension syntax,
1663 which in turn imitates the Unix sed replacement syntax::
1664 which in turn imitates the Unix sed replacement syntax::
1664
1665
1665 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1666 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1666
1667
1667 You can use any separator other than "/". The final "i" is optional
1668 You can use any separator other than "/". The final "i" is optional
1668 and indicates that the search must be case insensitive.
1669 and indicates that the search must be case insensitive.
1669
1670
1670 Examples::
1671 Examples::
1671
1672
1672 [websub]
1673 [websub]
1673 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1674 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1674 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1675 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1675 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1676 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1676
1677
1677 ``worker``
1678 ``worker``
1678 ----------
1679 ----------
1679
1680
1680 Parallel master/worker configuration. We currently perform working
1681 Parallel master/worker configuration. We currently perform working
1681 directory updates in parallel on Unix-like systems, which greatly
1682 directory updates in parallel on Unix-like systems, which greatly
1682 helps performance.
1683 helps performance.
1683
1684
1684 ``numcpus``
1685 ``numcpus``
1685 Number of CPUs to use for parallel operations. Default is 4 or the
1686 Number of CPUs to use for parallel operations. Default is 4 or the
1686 number of CPUs on the system, whichever is larger. A zero or
1687 number of CPUs on the system, whichever is larger. A zero or
1687 negative value is treated as ``use the default``.
1688 negative value is treated as ``use the default``.
@@ -1,852 +1,858 b''
1 $ hg init
1 $ hg init
2
2
3 Setup:
3 Setup:
4
4
5 $ echo a >> a
5 $ echo a >> a
6 $ hg ci -Am 'base'
6 $ hg ci -Am 'base'
7 adding a
7 adding a
8
8
9 Refuse to amend public csets:
9 Refuse to amend public csets:
10
10
11 $ hg phase -r . -p
11 $ hg phase -r . -p
12 $ hg ci --amend
12 $ hg ci --amend
13 abort: cannot amend public changesets
13 abort: cannot amend public changesets
14 [255]
14 [255]
15 $ hg phase -r . -f -d
15 $ hg phase -r . -f -d
16
16
17 $ echo a >> a
17 $ echo a >> a
18 $ hg ci -Am 'base1'
18 $ hg ci -Am 'base1'
19
19
20 Nothing to amend:
20 Nothing to amend:
21
21
22 $ hg ci --amend
22 $ hg ci --amend
23 nothing changed
23 nothing changed
24 [1]
24 [1]
25
25
26 $ cat >> $HGRCPATH <<EOF
26 $ cat >> $HGRCPATH <<EOF
27 > [hooks]
27 > [hooks]
28 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
28 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
29 > EOF
29 > EOF
30
30
31 Amending changeset with changes in working dir:
31 Amending changeset with changes in working dir:
32 (and check that --message does not trigger an editor)
32 (and check that --message does not trigger an editor)
33
33
34 $ echo a >> a
34 $ echo a >> a
35 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
35 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
36 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
36 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
37 43f1ba15f28a tip
37 43f1ba15f28a tip
38 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-amend-backup.hg (glob)
38 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-amend-backup.hg (glob)
39 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
39 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
40 $ hg diff -c .
40 $ hg diff -c .
41 diff -r ad120869acf0 -r 43f1ba15f28a a
41 diff -r ad120869acf0 -r 43f1ba15f28a a
42 --- a/a Thu Jan 01 00:00:00 1970 +0000
42 --- a/a Thu Jan 01 00:00:00 1970 +0000
43 +++ b/a Thu Jan 01 00:00:00 1970 +0000
43 +++ b/a Thu Jan 01 00:00:00 1970 +0000
44 @@ -1,1 +1,3 @@
44 @@ -1,1 +1,3 @@
45 a
45 a
46 +a
46 +a
47 +a
47 +a
48 $ hg log
48 $ hg log
49 changeset: 1:43f1ba15f28a
49 changeset: 1:43f1ba15f28a
50 tag: tip
50 tag: tip
51 user: test
51 user: test
52 date: Thu Jan 01 00:00:00 1970 +0000
52 date: Thu Jan 01 00:00:00 1970 +0000
53 summary: amend base1
53 summary: amend base1
54
54
55 changeset: 0:ad120869acf0
55 changeset: 0:ad120869acf0
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
57 date: Thu Jan 01 00:00:00 1970 +0000
58 summary: base
58 summary: base
59
59
60
60
61 Check proper abort for empty message
61 Check proper abort for empty message
62
62
63 $ cat > editor.sh << '__EOF__'
63 $ cat > editor.sh << '__EOF__'
64 > #!/bin/sh
64 > #!/bin/sh
65 > echo "" > "$1"
65 > echo "" > "$1"
66 > __EOF__
66 > __EOF__
67 $ echo b > b
67 $ echo b > b
68 $ hg add b
68 $ hg add b
69 $ hg summary
69 $ hg summary
70 parent: 1:43f1ba15f28a tip
70 parent: 1:43f1ba15f28a tip
71 amend base1
71 amend base1
72 branch: default
72 branch: default
73 commit: 1 added, 1 unknown
73 commit: 1 added, 1 unknown
74 update: (current)
74 update: (current)
75 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
75 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
76 transaction abort!
76 transaction abort!
77 rollback completed
77 rollback completed
78 abort: empty commit message
78 abort: empty commit message
79 [255]
79 [255]
80 $ hg summary
80 $ hg summary
81 parent: 1:43f1ba15f28a tip
81 parent: 1:43f1ba15f28a tip
82 amend base1
82 amend base1
83 branch: default
83 branch: default
84 commit: 1 added, 1 unknown
84 commit: 1 added, 1 unknown
85 update: (current)
85 update: (current)
86
86
87 Add new file:
87 Add new file:
88 $ hg ci --amend -m 'amend base1 new file'
88 $ hg ci --amend -m 'amend base1 new file'
89 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-amend-backup.hg (glob)
89 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-amend-backup.hg (glob)
90
90
91 Remove file that was added in amended commit:
91 Remove file that was added in amended commit:
92 (and test logfile option)
92 (and test logfile option)
93 (and test that logfile option do not trigger an editor)
93 (and test that logfile option do not trigger an editor)
94
94
95 $ hg rm b
95 $ hg rm b
96 $ echo 'amend base1 remove new file' > ../logfile
96 $ echo 'amend base1 remove new file' > ../logfile
97 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
97 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
98 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-amend-backup.hg (glob)
98 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-amend-backup.hg (glob)
99
99
100 $ hg cat b
100 $ hg cat b
101 b: no such file in rev 74609c7f506e
101 b: no such file in rev 74609c7f506e
102 [1]
102 [1]
103
103
104 No changes, just a different message:
104 No changes, just a different message:
105
105
106 $ hg ci -v --amend -m 'no changes, new message'
106 $ hg ci -v --amend -m 'no changes, new message'
107 amending changeset 74609c7f506e
107 amending changeset 74609c7f506e
108 copying changeset 74609c7f506e to ad120869acf0
108 copying changeset 74609c7f506e to ad120869acf0
109 a
109 a
110 stripping amended changeset 74609c7f506e
110 stripping amended changeset 74609c7f506e
111 1 changesets found
111 1 changesets found
112 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-amend-backup.hg (glob)
112 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-amend-backup.hg (glob)
113 1 changesets found
113 1 changesets found
114 adding branch
114 adding branch
115 adding changesets
115 adding changesets
116 adding manifests
116 adding manifests
117 adding file changes
117 adding file changes
118 added 1 changesets with 1 changes to 1 files
118 added 1 changesets with 1 changes to 1 files
119 committed changeset 1:1cd866679df8
119 committed changeset 1:1cd866679df8
120 $ hg diff -c .
120 $ hg diff -c .
121 diff -r ad120869acf0 -r 1cd866679df8 a
121 diff -r ad120869acf0 -r 1cd866679df8 a
122 --- a/a Thu Jan 01 00:00:00 1970 +0000
122 --- a/a Thu Jan 01 00:00:00 1970 +0000
123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
124 @@ -1,1 +1,3 @@
124 @@ -1,1 +1,3 @@
125 a
125 a
126 +a
126 +a
127 +a
127 +a
128 $ hg log
128 $ hg log
129 changeset: 1:1cd866679df8
129 changeset: 1:1cd866679df8
130 tag: tip
130 tag: tip
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 summary: no changes, new message
133 summary: no changes, new message
134
134
135 changeset: 0:ad120869acf0
135 changeset: 0:ad120869acf0
136 user: test
136 user: test
137 date: Thu Jan 01 00:00:00 1970 +0000
137 date: Thu Jan 01 00:00:00 1970 +0000
138 summary: base
138 summary: base
139
139
140
140
141 Disable default date on commit so when -d isn't given, the old date is preserved:
141 Disable default date on commit so when -d isn't given, the old date is preserved:
142
142
143 $ echo '[defaults]' >> $HGRCPATH
143 $ echo '[defaults]' >> $HGRCPATH
144 $ echo 'commit=' >> $HGRCPATH
144 $ echo 'commit=' >> $HGRCPATH
145
145
146 Test -u/-d:
146 Test -u/-d:
147
147
148 $ hg ci --amend -u foo -d '1 0'
148 $ cat > .hg/checkeditform.sh <<EOF
149 > env | grep HGEDITFORM
150 > true
151 > EOF
152 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -u foo -d '1 0'
153 HGEDITFORM=commit.amend.normal
149 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-amend-backup.hg (glob)
154 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-amend-backup.hg (glob)
150 $ echo a >> a
155 $ echo a >> a
151 $ hg ci --amend -u foo -d '1 0'
156 $ hg ci --amend -u foo -d '1 0'
152 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-amend-backup.hg (glob)
157 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-amend-backup.hg (glob)
153 $ hg log -r .
158 $ hg log -r .
154 changeset: 1:5f357c7560ab
159 changeset: 1:5f357c7560ab
155 tag: tip
160 tag: tip
156 user: foo
161 user: foo
157 date: Thu Jan 01 00:00:01 1970 +0000
162 date: Thu Jan 01 00:00:01 1970 +0000
158 summary: no changes, new message
163 summary: no changes, new message
159
164
160
165
161 Open editor with old commit message if a message isn't given otherwise:
166 Open editor with old commit message if a message isn't given otherwise:
162
167
163 $ cat > editor.sh << '__EOF__'
168 $ cat > editor.sh << '__EOF__'
164 > #!/bin/sh
169 > #!/bin/sh
165 > cat $1
170 > cat $1
166 > echo "another precious commit message" > "$1"
171 > echo "another precious commit message" > "$1"
167 > __EOF__
172 > __EOF__
168
173
169 at first, test saving last-message.txt
174 at first, test saving last-message.txt
170
175
171 $ cat > .hg/hgrc << '__EOF__'
176 $ cat > .hg/hgrc << '__EOF__'
172 > [hooks]
177 > [hooks]
173 > pretxncommit.test-saving-last-message = false
178 > pretxncommit.test-saving-last-message = false
174 > __EOF__
179 > __EOF__
175
180
176 $ rm -f .hg/last-message.txt
181 $ rm -f .hg/last-message.txt
177 $ hg commit --amend -v -m "message given from command line"
182 $ hg commit --amend -v -m "message given from command line"
178 amending changeset 5f357c7560ab
183 amending changeset 5f357c7560ab
179 copying changeset 5f357c7560ab to ad120869acf0
184 copying changeset 5f357c7560ab to ad120869acf0
180 a
185 a
181 running hook pretxncommit.test-saving-last-message: false
186 running hook pretxncommit.test-saving-last-message: false
182 transaction abort!
187 transaction abort!
183 rollback completed
188 rollback completed
184 abort: pretxncommit.test-saving-last-message hook exited with status 1
189 abort: pretxncommit.test-saving-last-message hook exited with status 1
185 [255]
190 [255]
186 $ cat .hg/last-message.txt
191 $ cat .hg/last-message.txt
187 message given from command line (no-eol)
192 message given from command line (no-eol)
188
193
189 $ rm -f .hg/last-message.txt
194 $ rm -f .hg/last-message.txt
190 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
195 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
191 amending changeset 5f357c7560ab
196 amending changeset 5f357c7560ab
192 copying changeset 5f357c7560ab to ad120869acf0
197 copying changeset 5f357c7560ab to ad120869acf0
193 no changes, new message
198 no changes, new message
194
199
195
200
196 HG: Enter commit message. Lines beginning with 'HG:' are removed.
201 HG: Enter commit message. Lines beginning with 'HG:' are removed.
197 HG: Leave message empty to abort commit.
202 HG: Leave message empty to abort commit.
198 HG: --
203 HG: --
199 HG: user: foo
204 HG: user: foo
200 HG: branch 'default'
205 HG: branch 'default'
201 HG: changed a
206 HG: changed a
202 a
207 a
203 running hook pretxncommit.test-saving-last-message: false
208 running hook pretxncommit.test-saving-last-message: false
204 transaction abort!
209 transaction abort!
205 rollback completed
210 rollback completed
206 abort: pretxncommit.test-saving-last-message hook exited with status 1
211 abort: pretxncommit.test-saving-last-message hook exited with status 1
207 [255]
212 [255]
208
213
209 $ cat .hg/last-message.txt
214 $ cat .hg/last-message.txt
210 another precious commit message
215 another precious commit message
211
216
212 $ cat > .hg/hgrc << '__EOF__'
217 $ cat > .hg/hgrc << '__EOF__'
213 > [hooks]
218 > [hooks]
214 > pretxncommit.test-saving-last-message =
219 > pretxncommit.test-saving-last-message =
215 > __EOF__
220 > __EOF__
216
221
217 then, test editing custom commit message
222 then, test editing custom commit message
218
223
219 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
224 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
220 amending changeset 5f357c7560ab
225 amending changeset 5f357c7560ab
221 copying changeset 5f357c7560ab to ad120869acf0
226 copying changeset 5f357c7560ab to ad120869acf0
222 no changes, new message
227 no changes, new message
223
228
224
229
225 HG: Enter commit message. Lines beginning with 'HG:' are removed.
230 HG: Enter commit message. Lines beginning with 'HG:' are removed.
226 HG: Leave message empty to abort commit.
231 HG: Leave message empty to abort commit.
227 HG: --
232 HG: --
228 HG: user: foo
233 HG: user: foo
229 HG: branch 'default'
234 HG: branch 'default'
230 HG: changed a
235 HG: changed a
231 a
236 a
232 stripping amended changeset 5f357c7560ab
237 stripping amended changeset 5f357c7560ab
233 1 changesets found
238 1 changesets found
234 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-amend-backup.hg (glob)
239 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-amend-backup.hg (glob)
235 1 changesets found
240 1 changesets found
236 adding branch
241 adding branch
237 adding changesets
242 adding changesets
238 adding manifests
243 adding manifests
239 adding file changes
244 adding file changes
240 added 1 changesets with 1 changes to 1 files
245 added 1 changesets with 1 changes to 1 files
241 committed changeset 1:7ab3bf440b54
246 committed changeset 1:7ab3bf440b54
242
247
243 Same, but with changes in working dir (different code path):
248 Same, but with changes in working dir (different code path):
244
249
245 $ echo a >> a
250 $ echo a >> a
246 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
251 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
247 amending changeset 7ab3bf440b54
252 amending changeset 7ab3bf440b54
248 a
253 a
249 copying changeset a0ea9b1a4c8c to ad120869acf0
254 copying changeset a0ea9b1a4c8c to ad120869acf0
250 another precious commit message
255 another precious commit message
251
256
252
257
253 HG: Enter commit message. Lines beginning with 'HG:' are removed.
258 HG: Enter commit message. Lines beginning with 'HG:' are removed.
254 HG: Leave message empty to abort commit.
259 HG: Leave message empty to abort commit.
255 HG: --
260 HG: --
256 HG: user: foo
261 HG: user: foo
257 HG: branch 'default'
262 HG: branch 'default'
258 HG: changed a
263 HG: changed a
259 a
264 a
260 stripping intermediate changeset a0ea9b1a4c8c
265 stripping intermediate changeset a0ea9b1a4c8c
261 stripping amended changeset 7ab3bf440b54
266 stripping amended changeset 7ab3bf440b54
262 2 changesets found
267 2 changesets found
263 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-amend-backup.hg (glob)
268 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-amend-backup.hg (glob)
264 1 changesets found
269 1 changesets found
265 adding branch
270 adding branch
266 adding changesets
271 adding changesets
267 adding manifests
272 adding manifests
268 adding file changes
273 adding file changes
269 added 1 changesets with 1 changes to 1 files
274 added 1 changesets with 1 changes to 1 files
270 committed changeset 1:ea22a388757c
275 committed changeset 1:ea22a388757c
271
276
272 $ rm editor.sh
277 $ rm editor.sh
273 $ hg log -r .
278 $ hg log -r .
274 changeset: 1:ea22a388757c
279 changeset: 1:ea22a388757c
275 tag: tip
280 tag: tip
276 user: foo
281 user: foo
277 date: Thu Jan 01 00:00:01 1970 +0000
282 date: Thu Jan 01 00:00:01 1970 +0000
278 summary: another precious commit message
283 summary: another precious commit message
279
284
280
285
281 Moving bookmarks, preserve active bookmark:
286 Moving bookmarks, preserve active bookmark:
282
287
283 $ hg book book1
288 $ hg book book1
284 $ hg book book2
289 $ hg book book2
285 $ hg ci --amend -m 'move bookmarks'
290 $ hg ci --amend -m 'move bookmarks'
286 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-amend-backup.hg (glob)
291 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-amend-backup.hg (glob)
287 $ hg book
292 $ hg book
288 book1 1:6cec5aa930e2
293 book1 1:6cec5aa930e2
289 * book2 1:6cec5aa930e2
294 * book2 1:6cec5aa930e2
290 $ echo a >> a
295 $ echo a >> a
291 $ hg ci --amend -m 'move bookmarks'
296 $ hg ci --amend -m 'move bookmarks'
292 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-amend-backup.hg (glob)
297 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-amend-backup.hg (glob)
293 $ hg book
298 $ hg book
294 book1 1:48bb6e53a15f
299 book1 1:48bb6e53a15f
295 * book2 1:48bb6e53a15f
300 * book2 1:48bb6e53a15f
296
301
297 abort does not loose bookmarks
302 abort does not loose bookmarks
298
303
299 $ cat > editor.sh << '__EOF__'
304 $ cat > editor.sh << '__EOF__'
300 > #!/bin/sh
305 > #!/bin/sh
301 > echo "" > "$1"
306 > echo "" > "$1"
302 > __EOF__
307 > __EOF__
303 $ echo a >> a
308 $ echo a >> a
304 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
309 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
305 transaction abort!
310 transaction abort!
306 rollback completed
311 rollback completed
307 abort: empty commit message
312 abort: empty commit message
308 [255]
313 [255]
309 $ hg book
314 $ hg book
310 book1 1:48bb6e53a15f
315 book1 1:48bb6e53a15f
311 * book2 1:48bb6e53a15f
316 * book2 1:48bb6e53a15f
312 $ hg revert -Caq
317 $ hg revert -Caq
313 $ rm editor.sh
318 $ rm editor.sh
314
319
315 $ echo '[defaults]' >> $HGRCPATH
320 $ echo '[defaults]' >> $HGRCPATH
316 $ echo "commit=-d '0 0'" >> $HGRCPATH
321 $ echo "commit=-d '0 0'" >> $HGRCPATH
317
322
318 Moving branches:
323 Moving branches:
319
324
320 $ hg branch foo
325 $ hg branch foo
321 marked working directory as branch foo
326 marked working directory as branch foo
322 (branches are permanent and global, did you want a bookmark?)
327 (branches are permanent and global, did you want a bookmark?)
323 $ echo a >> a
328 $ echo a >> a
324 $ hg ci -m 'branch foo'
329 $ hg ci -m 'branch foo'
325 $ hg branch default -f
330 $ hg branch default -f
326 marked working directory as branch default
331 marked working directory as branch default
327 (branches are permanent and global, did you want a bookmark?)
332 (branches are permanent and global, did you want a bookmark?)
328 $ hg ci --amend -m 'back to default'
333 $ hg ci --amend -m 'back to default'
329 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-amend-backup.hg (glob)
334 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-amend-backup.hg (glob)
330 $ hg branches
335 $ hg branches
331 default 2:ce12b0b57d46
336 default 2:ce12b0b57d46
332
337
333 Close branch:
338 Close branch:
334
339
335 $ hg up -q 0
340 $ hg up -q 0
336 $ echo b >> b
341 $ echo b >> b
337 $ hg branch foo
342 $ hg branch foo
338 marked working directory as branch foo
343 marked working directory as branch foo
339 (branches are permanent and global, did you want a bookmark?)
344 (branches are permanent and global, did you want a bookmark?)
340 $ hg ci -Am 'fork'
345 $ hg ci -Am 'fork'
341 adding b
346 adding b
342 $ echo b >> b
347 $ echo b >> b
343 $ hg ci -mb
348 $ hg ci -mb
344 $ hg ci --amend --close-branch -m 'closing branch foo'
349 $ hg ci --amend --close-branch -m 'closing branch foo'
345 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-amend-backup.hg (glob)
350 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-amend-backup.hg (glob)
346
351
347 Same thing, different code path:
352 Same thing, different code path:
348
353
349 $ echo b >> b
354 $ echo b >> b
350 $ hg ci -m 'reopen branch'
355 $ hg ci -m 'reopen branch'
351 reopening closed branch head 4
356 reopening closed branch head 4
352 $ echo b >> b
357 $ echo b >> b
353 $ hg ci --amend --close-branch
358 $ hg ci --amend --close-branch
354 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-amend-backup.hg (glob)
359 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-amend-backup.hg (glob)
355 $ hg branches
360 $ hg branches
356 default 2:ce12b0b57d46
361 default 2:ce12b0b57d46
357
362
358 Refuse to amend during a merge:
363 Refuse to amend during a merge:
359
364
360 $ hg up -q default
365 $ hg up -q default
361 $ hg merge foo
366 $ hg merge foo
362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
367 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 (branch merge, don't forget to commit)
368 (branch merge, don't forget to commit)
364 $ hg ci --amend
369 $ hg ci --amend
365 abort: cannot amend while merging
370 abort: cannot amend while merging
366 [255]
371 [255]
367 $ hg ci -m 'merge'
372 $ hg ci -m 'merge'
368
373
369 Follow copies/renames:
374 Follow copies/renames:
370
375
371 $ hg mv b c
376 $ hg mv b c
372 $ hg ci -m 'b -> c'
377 $ hg ci -m 'b -> c'
373 $ hg mv c d
378 $ hg mv c d
374 $ hg ci --amend -m 'b -> d'
379 $ hg ci --amend -m 'b -> d'
375 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-amend-backup.hg (glob)
380 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-amend-backup.hg (glob)
376 $ hg st --rev '.^' --copies d
381 $ hg st --rev '.^' --copies d
377 A d
382 A d
378 b
383 b
379 $ hg cp d e
384 $ hg cp d e
380 $ hg ci -m 'e = d'
385 $ hg ci -m 'e = d'
381 $ hg cp e f
386 $ hg cp e f
382 $ hg ci --amend -m 'f = d'
387 $ hg ci --amend -m 'f = d'
383 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-amend-backup.hg (glob)
388 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-amend-backup.hg (glob)
384 $ hg st --rev '.^' --copies f
389 $ hg st --rev '.^' --copies f
385 A f
390 A f
386 d
391 d
387
392
388 $ mv f f.orig
393 $ mv f f.orig
389 $ hg rm -A f
394 $ hg rm -A f
390 $ hg ci -m removef
395 $ hg ci -m removef
391 $ hg cp a f
396 $ hg cp a f
392 $ mv f.orig f
397 $ mv f.orig f
393 $ hg ci --amend -m replacef
398 $ hg ci --amend -m replacef
394 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-amend-backup.hg (glob)
399 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-amend-backup.hg (glob)
395 $ hg st --change . --copies
400 $ hg st --change . --copies
396 $ hg log -r . --template "{file_copies}\n"
401 $ hg log -r . --template "{file_copies}\n"
397
402
398
403
399 Move added file (issue3410):
404 Move added file (issue3410):
400
405
401 $ echo g >> g
406 $ echo g >> g
402 $ hg ci -Am g
407 $ hg ci -Am g
403 adding g
408 adding g
404 $ hg mv g h
409 $ hg mv g h
405 $ hg ci --amend
410 $ hg ci --amend
406 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-amend-backup.hg (glob)
411 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-amend-backup.hg (glob)
407 $ hg st --change . --copies h
412 $ hg st --change . --copies h
408 A h
413 A h
409 $ hg log -r . --template "{file_copies}\n"
414 $ hg log -r . --template "{file_copies}\n"
410
415
411
416
412 Can't rollback an amend:
417 Can't rollback an amend:
413
418
414 $ hg rollback
419 $ hg rollback
415 no rollback information available
420 no rollback information available
416 [1]
421 [1]
417
422
418 Preserve extra dict (issue3430):
423 Preserve extra dict (issue3430):
419
424
420 $ hg branch a
425 $ hg branch a
421 marked working directory as branch a
426 marked working directory as branch a
422 (branches are permanent and global, did you want a bookmark?)
427 (branches are permanent and global, did you want a bookmark?)
423 $ echo a >> a
428 $ echo a >> a
424 $ hg ci -ma
429 $ hg ci -ma
425 $ hg ci --amend -m "a'"
430 $ hg ci --amend -m "a'"
426 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-amend-backup.hg (glob)
431 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-amend-backup.hg (glob)
427 $ hg log -r . --template "{branch}\n"
432 $ hg log -r . --template "{branch}\n"
428 a
433 a
429 $ hg ci --amend -m "a''"
434 $ hg ci --amend -m "a''"
430 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-amend-backup.hg (glob)
435 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-amend-backup.hg (glob)
431 $ hg log -r . --template "{branch}\n"
436 $ hg log -r . --template "{branch}\n"
432 a
437 a
433
438
434 Also preserve other entries in the dict that are in the old commit,
439 Also preserve other entries in the dict that are in the old commit,
435 first graft something so there's an additional entry:
440 first graft something so there's an additional entry:
436
441
437 $ hg up 0 -q
442 $ hg up 0 -q
438 $ echo z > z
443 $ echo z > z
439 $ hg ci -Am 'fork'
444 $ hg ci -Am 'fork'
440 adding z
445 adding z
441 created new head
446 created new head
442 $ hg up 11
447 $ hg up 11
443 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
448 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
444 $ hg graft 12
449 $ hg graft 12
445 grafting revision 12
450 grafting revision 12
446 $ hg ci --amend -m 'graft amend'
451 $ hg ci --amend -m 'graft amend'
447 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-amend-backup.hg (glob)
452 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-amend-backup.hg (glob)
448 $ hg log -r . --debug | grep extra
453 $ hg log -r . --debug | grep extra
449 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
454 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
450 extra: branch=a
455 extra: branch=a
451 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
456 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
452
457
453 Preserve phase
458 Preserve phase
454
459
455 $ hg phase '.^::.'
460 $ hg phase '.^::.'
456 11: draft
461 11: draft
457 13: draft
462 13: draft
458 $ hg phase --secret --force .
463 $ hg phase --secret --force .
459 $ hg phase '.^::.'
464 $ hg phase '.^::.'
460 11: draft
465 11: draft
461 13: secret
466 13: secret
462 $ hg commit --amend -m 'amend for phase' -q
467 $ hg commit --amend -m 'amend for phase' -q
463 $ hg phase '.^::.'
468 $ hg phase '.^::.'
464 11: draft
469 11: draft
465 13: secret
470 13: secret
466
471
467 Test amend with obsolete
472 Test amend with obsolete
468 ---------------------------
473 ---------------------------
469
474
470 Enable obsolete
475 Enable obsolete
471
476
472 $ cat > ${TESTTMP}/obs.py << EOF
477 $ cat > ${TESTTMP}/obs.py << EOF
473 > import mercurial.obsolete
478 > import mercurial.obsolete
474 > mercurial.obsolete._enabled = True
479 > mercurial.obsolete._enabled = True
475 > EOF
480 > EOF
476 $ echo '[extensions]' >> $HGRCPATH
481 $ echo '[extensions]' >> $HGRCPATH
477 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
482 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
478
483
479
484
480 Amend with no files changes
485 Amend with no files changes
481
486
482 $ hg id -n
487 $ hg id -n
483 13
488 13
484 $ hg ci --amend -m 'babar'
489 $ hg ci --amend -m 'babar'
485 $ hg id -n
490 $ hg id -n
486 14
491 14
487 $ hg log -Gl 3 --style=compact
492 $ hg log -Gl 3 --style=compact
488 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
493 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
489 | babar
494 | babar
490 |
495 |
491 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
496 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
492 | | fork
497 | | fork
493 | |
498 | |
494 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
499 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
495 | | a''
500 | | a''
496 | |
501 | |
497 $ hg log -Gl 4 --hidden --style=compact
502 $ hg log -Gl 4 --hidden --style=compact
498 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
503 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
499 | babar
504 | babar
500 |
505 |
501 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
506 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
502 |/ amend for phase
507 |/ amend for phase
503 |
508 |
504 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
509 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
505 | | fork
510 | | fork
506 | |
511 | |
507 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
512 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
508 | | a''
513 | | a''
509 | |
514 | |
510
515
511 Amend with files changes
516 Amend with files changes
512
517
513 (note: the extra commit over 15 is a temporary junk I would be happy to get
518 (note: the extra commit over 15 is a temporary junk I would be happy to get
514 ride of)
519 ride of)
515
520
516 $ echo 'babar' >> a
521 $ echo 'babar' >> a
517 $ hg commit --amend
522 $ hg commit --amend
518 $ hg log -Gl 6 --hidden --style=compact
523 $ hg log -Gl 6 --hidden --style=compact
519 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
524 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
520 | babar
525 | babar
521 |
526 |
522 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
527 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
523 | | temporary amend commit for b650e6ee8614
528 | | temporary amend commit for b650e6ee8614
524 | |
529 | |
525 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
530 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
526 |/ babar
531 |/ babar
527 |
532 |
528 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
533 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
529 |/ amend for phase
534 |/ amend for phase
530 |
535 |
531 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
536 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
532 | | fork
537 | | fork
533 | |
538 | |
534 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
539 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
535 | | a''
540 | | a''
536 | |
541 | |
537
542
538
543
539 Test that amend does not make it easy to create obsolescence cycle
544 Test that amend does not make it easy to create obsolescence cycle
540 ---------------------------------------------------------------------
545 ---------------------------------------------------------------------
541
546
542 $ hg id -r 14 --hidden
547 $ hg id -r 14 --hidden
543 b650e6ee8614 (a)
548 b650e6ee8614 (a)
544 $ hg revert -ar 14 --hidden
549 $ hg revert -ar 14 --hidden
545 reverting a
550 reverting a
546 $ hg commit --amend
551 $ hg commit --amend
547 $ hg id
552 $ hg id
548 b99e5df575f7 (a) tip
553 b99e5df575f7 (a) tip
549
554
550 Test that rewriting leaving instability behind is allowed
555 Test that rewriting leaving instability behind is allowed
551 ---------------------------------------------------------------------
556 ---------------------------------------------------------------------
552
557
553 $ hg up '.^'
558 $ hg up '.^'
554 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
559 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
555 $ echo 'b' >> a
560 $ echo 'b' >> a
556 $ hg log --style compact -r 'children(.)'
561 $ hg log --style compact -r 'children(.)'
557 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
562 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
558 babar
563 babar
559
564
560 $ hg commit --amend
565 $ hg commit --amend
561 $ hg log -r 'unstable()'
566 $ hg log -r 'unstable()'
562 changeset: 18:b99e5df575f7
567 changeset: 18:b99e5df575f7
563 branch: a
568 branch: a
564 parent: 11:3334b7925910
569 parent: 11:3334b7925910
565 user: test
570 user: test
566 date: Thu Jan 01 00:00:00 1970 +0000
571 date: Thu Jan 01 00:00:00 1970 +0000
567 summary: babar
572 summary: babar
568
573
569
574
570 Amend a merge changeset (with renames and conflicts from the second parent):
575 Amend a merge changeset (with renames and conflicts from the second parent):
571
576
572 $ hg up -q default
577 $ hg up -q default
573 $ hg branch -q bar
578 $ hg branch -q bar
574 $ hg cp a aa
579 $ hg cp a aa
575 $ hg mv z zz
580 $ hg mv z zz
576 $ echo cc > cc
581 $ echo cc > cc
577 $ hg add cc
582 $ hg add cc
578 $ hg ci -m aazzcc
583 $ hg ci -m aazzcc
579 $ hg up -q default
584 $ hg up -q default
580 $ echo a >> a
585 $ echo a >> a
581 $ echo dd > cc
586 $ echo dd > cc
582 $ hg add cc
587 $ hg add cc
583 $ hg ci -m aa
588 $ hg ci -m aa
584 $ hg merge -q bar
589 $ hg merge -q bar
585 warning: conflicts during merge.
590 warning: conflicts during merge.
586 merging cc incomplete! (edit conflicts, then use 'hg resolve --mark')
591 merging cc incomplete! (edit conflicts, then use 'hg resolve --mark')
587 [1]
592 [1]
588 $ hg resolve -m cc
593 $ hg resolve -m cc
589 (no more unresolved files)
594 (no more unresolved files)
590 $ hg ci -m 'merge bar'
595 $ hg ci -m 'merge bar'
591 $ hg log --config diff.git=1 -pr .
596 $ hg log --config diff.git=1 -pr .
592 changeset: 23:93cd4445f720
597 changeset: 23:93cd4445f720
593 tag: tip
598 tag: tip
594 parent: 22:30d96aeaf27b
599 parent: 22:30d96aeaf27b
595 parent: 21:1aa437659d19
600 parent: 21:1aa437659d19
596 user: test
601 user: test
597 date: Thu Jan 01 00:00:00 1970 +0000
602 date: Thu Jan 01 00:00:00 1970 +0000
598 summary: merge bar
603 summary: merge bar
599
604
600 diff --git a/a b/aa
605 diff --git a/a b/aa
601 copy from a
606 copy from a
602 copy to aa
607 copy to aa
603 diff --git a/cc b/cc
608 diff --git a/cc b/cc
604 --- a/cc
609 --- a/cc
605 +++ b/cc
610 +++ b/cc
606 @@ -1,1 +1,5 @@
611 @@ -1,1 +1,5 @@
607 +<<<<<<< local: 30d96aeaf27b - test: aa
612 +<<<<<<< local: 30d96aeaf27b - test: aa
608 dd
613 dd
609 +=======
614 +=======
610 +cc
615 +cc
611 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
616 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
612 diff --git a/z b/zz
617 diff --git a/z b/zz
613 rename from z
618 rename from z
614 rename to zz
619 rename to zz
615
620
616 $ hg debugrename aa
621 $ hg debugrename aa
617 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
622 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
618 $ hg debugrename zz
623 $ hg debugrename zz
619 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
624 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
620 $ hg debugrename cc
625 $ hg debugrename cc
621 cc not renamed
626 cc not renamed
622 $ hg ci --amend -m 'merge bar (amend message)'
627 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -m 'merge bar (amend message)' --edit
628 HGEDITFORM=commit.amend.merge
623 $ hg log --config diff.git=1 -pr .
629 $ hg log --config diff.git=1 -pr .
624 changeset: 24:832b50f2c271
630 changeset: 24:832b50f2c271
625 tag: tip
631 tag: tip
626 parent: 22:30d96aeaf27b
632 parent: 22:30d96aeaf27b
627 parent: 21:1aa437659d19
633 parent: 21:1aa437659d19
628 user: test
634 user: test
629 date: Thu Jan 01 00:00:00 1970 +0000
635 date: Thu Jan 01 00:00:00 1970 +0000
630 summary: merge bar (amend message)
636 summary: merge bar (amend message)
631
637
632 diff --git a/a b/aa
638 diff --git a/a b/aa
633 copy from a
639 copy from a
634 copy to aa
640 copy to aa
635 diff --git a/cc b/cc
641 diff --git a/cc b/cc
636 --- a/cc
642 --- a/cc
637 +++ b/cc
643 +++ b/cc
638 @@ -1,1 +1,5 @@
644 @@ -1,1 +1,5 @@
639 +<<<<<<< local: 30d96aeaf27b - test: aa
645 +<<<<<<< local: 30d96aeaf27b - test: aa
640 dd
646 dd
641 +=======
647 +=======
642 +cc
648 +cc
643 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
649 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
644 diff --git a/z b/zz
650 diff --git a/z b/zz
645 rename from z
651 rename from z
646 rename to zz
652 rename to zz
647
653
648 $ hg debugrename aa
654 $ hg debugrename aa
649 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
655 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
650 $ hg debugrename zz
656 $ hg debugrename zz
651 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
657 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
652 $ hg debugrename cc
658 $ hg debugrename cc
653 cc not renamed
659 cc not renamed
654 $ hg mv zz z
660 $ hg mv zz z
655 $ hg ci --amend -m 'merge bar (undo rename)'
661 $ hg ci --amend -m 'merge bar (undo rename)'
656 $ hg log --config diff.git=1 -pr .
662 $ hg log --config diff.git=1 -pr .
657 changeset: 26:bdafc5c72f74
663 changeset: 26:bdafc5c72f74
658 tag: tip
664 tag: tip
659 parent: 22:30d96aeaf27b
665 parent: 22:30d96aeaf27b
660 parent: 21:1aa437659d19
666 parent: 21:1aa437659d19
661 user: test
667 user: test
662 date: Thu Jan 01 00:00:00 1970 +0000
668 date: Thu Jan 01 00:00:00 1970 +0000
663 summary: merge bar (undo rename)
669 summary: merge bar (undo rename)
664
670
665 diff --git a/a b/aa
671 diff --git a/a b/aa
666 copy from a
672 copy from a
667 copy to aa
673 copy to aa
668 diff --git a/cc b/cc
674 diff --git a/cc b/cc
669 --- a/cc
675 --- a/cc
670 +++ b/cc
676 +++ b/cc
671 @@ -1,1 +1,5 @@
677 @@ -1,1 +1,5 @@
672 +<<<<<<< local: 30d96aeaf27b - test: aa
678 +<<<<<<< local: 30d96aeaf27b - test: aa
673 dd
679 dd
674 +=======
680 +=======
675 +cc
681 +cc
676 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
682 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
677
683
678 $ hg debugrename z
684 $ hg debugrename z
679 z not renamed
685 z not renamed
680
686
681 Amend a merge changeset (with renames during the merge):
687 Amend a merge changeset (with renames during the merge):
682
688
683 $ hg up -q bar
689 $ hg up -q bar
684 $ echo x > x
690 $ echo x > x
685 $ hg add x
691 $ hg add x
686 $ hg ci -m x
692 $ hg ci -m x
687 $ hg up -q default
693 $ hg up -q default
688 $ hg merge -q bar
694 $ hg merge -q bar
689 $ hg mv aa aaa
695 $ hg mv aa aaa
690 $ echo aa >> aaa
696 $ echo aa >> aaa
691 $ hg ci -m 'merge bar again'
697 $ hg ci -m 'merge bar again'
692 $ hg log --config diff.git=1 -pr .
698 $ hg log --config diff.git=1 -pr .
693 changeset: 28:32f19415b634
699 changeset: 28:32f19415b634
694 tag: tip
700 tag: tip
695 parent: 26:bdafc5c72f74
701 parent: 26:bdafc5c72f74
696 parent: 27:4c94d5bc65f5
702 parent: 27:4c94d5bc65f5
697 user: test
703 user: test
698 date: Thu Jan 01 00:00:00 1970 +0000
704 date: Thu Jan 01 00:00:00 1970 +0000
699 summary: merge bar again
705 summary: merge bar again
700
706
701 diff --git a/aa b/aa
707 diff --git a/aa b/aa
702 deleted file mode 100644
708 deleted file mode 100644
703 --- a/aa
709 --- a/aa
704 +++ /dev/null
710 +++ /dev/null
705 @@ -1,2 +0,0 @@
711 @@ -1,2 +0,0 @@
706 -a
712 -a
707 -a
713 -a
708 diff --git a/aaa b/aaa
714 diff --git a/aaa b/aaa
709 new file mode 100644
715 new file mode 100644
710 --- /dev/null
716 --- /dev/null
711 +++ b/aaa
717 +++ b/aaa
712 @@ -0,0 +1,3 @@
718 @@ -0,0 +1,3 @@
713 +a
719 +a
714 +a
720 +a
715 +aa
721 +aa
716 diff --git a/x b/x
722 diff --git a/x b/x
717 new file mode 100644
723 new file mode 100644
718 --- /dev/null
724 --- /dev/null
719 +++ b/x
725 +++ b/x
720 @@ -0,0 +1,1 @@
726 @@ -0,0 +1,1 @@
721 +x
727 +x
722
728
723 $ hg debugrename aaa
729 $ hg debugrename aaa
724 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
730 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
725 $ hg mv aaa aa
731 $ hg mv aaa aa
726 $ hg ci --amend -m 'merge bar again (undo rename)'
732 $ hg ci --amend -m 'merge bar again (undo rename)'
727 $ hg log --config diff.git=1 -pr .
733 $ hg log --config diff.git=1 -pr .
728 changeset: 30:1e2a06b3d312
734 changeset: 30:1e2a06b3d312
729 tag: tip
735 tag: tip
730 parent: 26:bdafc5c72f74
736 parent: 26:bdafc5c72f74
731 parent: 27:4c94d5bc65f5
737 parent: 27:4c94d5bc65f5
732 user: test
738 user: test
733 date: Thu Jan 01 00:00:00 1970 +0000
739 date: Thu Jan 01 00:00:00 1970 +0000
734 summary: merge bar again (undo rename)
740 summary: merge bar again (undo rename)
735
741
736 diff --git a/aa b/aa
742 diff --git a/aa b/aa
737 --- a/aa
743 --- a/aa
738 +++ b/aa
744 +++ b/aa
739 @@ -1,2 +1,3 @@
745 @@ -1,2 +1,3 @@
740 a
746 a
741 a
747 a
742 +aa
748 +aa
743 diff --git a/x b/x
749 diff --git a/x b/x
744 new file mode 100644
750 new file mode 100644
745 --- /dev/null
751 --- /dev/null
746 +++ b/x
752 +++ b/x
747 @@ -0,0 +1,1 @@
753 @@ -0,0 +1,1 @@
748 +x
754 +x
749
755
750 $ hg debugrename aa
756 $ hg debugrename aa
751 aa not renamed
757 aa not renamed
752 $ hg debugrename -r '.^' aa
758 $ hg debugrename -r '.^' aa
753 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
759 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
754
760
755 Amend a merge changeset (with manifest-level conflicts):
761 Amend a merge changeset (with manifest-level conflicts):
756
762
757 $ hg up -q bar
763 $ hg up -q bar
758 $ hg rm aa
764 $ hg rm aa
759 $ hg ci -m 'rm aa'
765 $ hg ci -m 'rm aa'
760 $ hg up -q default
766 $ hg up -q default
761 $ echo aa >> aa
767 $ echo aa >> aa
762 $ hg ci -m aa
768 $ hg ci -m aa
763 $ hg merge -q bar
769 $ hg merge -q bar
764 local changed aa which remote deleted
770 local changed aa which remote deleted
765 use (c)hanged version or (d)elete? c
771 use (c)hanged version or (d)elete? c
766 $ hg ci -m 'merge bar (with conflicts)'
772 $ hg ci -m 'merge bar (with conflicts)'
767 $ hg log --config diff.git=1 -pr .
773 $ hg log --config diff.git=1 -pr .
768 changeset: 33:97a298b0c59f
774 changeset: 33:97a298b0c59f
769 tag: tip
775 tag: tip
770 parent: 32:3d78ce4226b8
776 parent: 32:3d78ce4226b8
771 parent: 31:67db8847a540
777 parent: 31:67db8847a540
772 user: test
778 user: test
773 date: Thu Jan 01 00:00:00 1970 +0000
779 date: Thu Jan 01 00:00:00 1970 +0000
774 summary: merge bar (with conflicts)
780 summary: merge bar (with conflicts)
775
781
776
782
777 $ hg rm aa
783 $ hg rm aa
778 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
784 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
779 $ hg log --config diff.git=1 -pr .
785 $ hg log --config diff.git=1 -pr .
780 changeset: 35:6de0c1bde1c8
786 changeset: 35:6de0c1bde1c8
781 tag: tip
787 tag: tip
782 parent: 32:3d78ce4226b8
788 parent: 32:3d78ce4226b8
783 parent: 31:67db8847a540
789 parent: 31:67db8847a540
784 user: test
790 user: test
785 date: Thu Jan 01 00:00:00 1970 +0000
791 date: Thu Jan 01 00:00:00 1970 +0000
786 summary: merge bar (with conflicts, amended)
792 summary: merge bar (with conflicts, amended)
787
793
788 diff --git a/aa b/aa
794 diff --git a/aa b/aa
789 deleted file mode 100644
795 deleted file mode 100644
790 --- a/aa
796 --- a/aa
791 +++ /dev/null
797 +++ /dev/null
792 @@ -1,4 +0,0 @@
798 @@ -1,4 +0,0 @@
793 -a
799 -a
794 -a
800 -a
795 -aa
801 -aa
796 -aa
802 -aa
797
803
798 Issue 3445: amending with --close-branch a commit that created a new head should fail
804 Issue 3445: amending with --close-branch a commit that created a new head should fail
799 This shouldn't be possible:
805 This shouldn't be possible:
800
806
801 $ hg up -q default
807 $ hg up -q default
802 $ hg branch closewithamend
808 $ hg branch closewithamend
803 marked working directory as branch closewithamend
809 marked working directory as branch closewithamend
804 (branches are permanent and global, did you want a bookmark?)
810 (branches are permanent and global, did you want a bookmark?)
805 $ hg add obs.py
811 $ hg add obs.py
806 $ hg ci -m..
812 $ hg ci -m..
807 $ hg ci --amend --close-branch -m 'closing'
813 $ hg ci --amend --close-branch -m 'closing'
808 abort: can only close branch heads
814 abort: can only close branch heads
809 [255]
815 [255]
810
816
811 This silliness fails:
817 This silliness fails:
812
818
813 $ hg branch silliness
819 $ hg branch silliness
814 marked working directory as branch silliness
820 marked working directory as branch silliness
815 (branches are permanent and global, did you want a bookmark?)
821 (branches are permanent and global, did you want a bookmark?)
816 $ echo b >> b
822 $ echo b >> b
817 $ hg ci --close-branch -m'open and close'
823 $ hg ci --close-branch -m'open and close'
818 abort: can only close branch heads
824 abort: can only close branch heads
819 [255]
825 [255]
820
826
821 Test that amend with --secret creates new secret changeset forcibly
827 Test that amend with --secret creates new secret changeset forcibly
822 ---------------------------------------------------------------------
828 ---------------------------------------------------------------------
823
829
824 $ hg phase '.^::.'
830 $ hg phase '.^::.'
825 35: draft
831 35: draft
826 36: draft
832 36: draft
827 $ hg commit --amend --secret -m 'amend as secret' -q
833 $ hg commit --amend --secret -m 'amend as secret' -q
828 $ hg phase '.^::.'
834 $ hg phase '.^::.'
829 35: draft
835 35: draft
830 38: secret
836 38: secret
831
837
832 Test that amend with --edit invokes editor forcibly
838 Test that amend with --edit invokes editor forcibly
833 ---------------------------------------------------
839 ---------------------------------------------------
834
840
835 $ hg parents --template "{desc}\n"
841 $ hg parents --template "{desc}\n"
836 amend as secret
842 amend as secret
837 $ HGEDITOR=cat hg commit --amend -m "editor should be suppressed"
843 $ HGEDITOR=cat hg commit --amend -m "editor should be suppressed"
838 $ hg parents --template "{desc}\n"
844 $ hg parents --template "{desc}\n"
839 editor should be suppressed
845 editor should be suppressed
840
846
841 $ HGEDITOR=cat hg commit --amend -m "editor should be invoked" --edit
847 $ HGEDITOR=cat hg commit --amend -m "editor should be invoked" --edit
842 editor should be invoked
848 editor should be invoked
843
849
844
850
845 HG: Enter commit message. Lines beginning with 'HG:' are removed.
851 HG: Enter commit message. Lines beginning with 'HG:' are removed.
846 HG: Leave message empty to abort commit.
852 HG: Leave message empty to abort commit.
847 HG: --
853 HG: --
848 HG: user: test
854 HG: user: test
849 HG: branch 'silliness'
855 HG: branch 'silliness'
850 HG: changed obs.py
856 HG: changed obs.py
851 $ hg parents --template "{desc}\n"
857 $ hg parents --template "{desc}\n"
852 editor should be invoked
858 editor should be invoked
General Comments 0
You need to be logged in to leave comments. Login now