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