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