# HG changeset patch # User Augie Fackler # Date 1595470178 14400 # Node ID 4b923da0cb86f0e1ce3302b72471319c18bb4470 # Parent ce9ee81df9ff869e991777a50cc1d2d68b697b01# Parent fc54f52779dd6c9523e9cc4de8a6e61e62e75bd8 merge with stable diff -r fc54f52779dd -r 4b923da0cb86 mercurial/commit.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/commit.py Wed Jul 22 22:09:38 2020 -0400 @@ -0,0 +1,354 @@ +# commit.py - fonction to perform commit +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from __future__ import absolute_import + +import errno +import weakref + +from .i18n import _ +from .node import ( + hex, + nullid, + nullrev, +) + +from . import ( + context, + mergestate, + metadata, + phases, + scmutil, + subrepoutil, +) + + +def commitctx(repo, ctx, error=False, origctx=None): + """Add a new revision to the target repository. + Revision information is passed via the context argument. + + ctx.files() should list all files involved in this commit, i.e. + modified/added/removed files. On merge, it may be wider than the + ctx.files() to be committed, since any file nodes derived directly + from p1 or p2 are excluded from the committed ctx.files(). + + origctx is for convert to work around the problem that bug + fixes to the files list in changesets change hashes. For + convert to be the identity, it can pass an origctx and this + function will use the same files list when it makes sense to + do so. + """ + repo = repo.unfiltered() + + p1, p2 = ctx.p1(), ctx.p2() + user = ctx.user() + + if repo.filecopiesmode == b'changeset-sidedata': + writechangesetcopy = True + writefilecopymeta = True + writecopiesto = None + else: + writecopiesto = repo.ui.config(b'experimental', b'copies.write-to') + writefilecopymeta = writecopiesto != b'changeset-only' + writechangesetcopy = writecopiesto in ( + b'changeset-only', + b'compatibility', + ) + p1copies, p2copies = None, None + if writechangesetcopy: + p1copies = ctx.p1copies() + p2copies = ctx.p2copies() + filesadded, filesremoved = None, None + with repo.lock(), repo.transaction(b"commit") as tr: + trp = weakref.proxy(tr) + + if ctx.manifestnode(): + # reuse an existing manifest revision + repo.ui.debug(b'reusing known manifest\n') + mn = ctx.manifestnode() + files = ctx.files() + if writechangesetcopy: + filesadded = ctx.filesadded() + filesremoved = ctx.filesremoved() + elif not ctx.files(): + repo.ui.debug(b'reusing manifest from p1 (no file change)\n') + mn = p1.manifestnode() + files = [] + else: + m1ctx = p1.manifestctx() + m2ctx = p2.manifestctx() + mctx = m1ctx.copy() + + m = mctx.read() + m1 = m1ctx.read() + m2 = m2ctx.read() + + # check in files + added = [] + filesadded = [] + removed = list(ctx.removed()) + touched = [] + linkrev = len(repo) + repo.ui.note(_(b"committing files:\n")) + uipathfn = scmutil.getuipathfn(repo) + for f in sorted(ctx.modified() + ctx.added()): + repo.ui.note(uipathfn(f) + b"\n") + try: + fctx = ctx[f] + if fctx is None: + removed.append(f) + else: + added.append(f) + m[f], is_touched = _filecommit( + repo, fctx, m1, m2, linkrev, trp, writefilecopymeta, + ) + if is_touched: + touched.append(f) + if writechangesetcopy and is_touched == 'added': + filesadded.append(f) + m.setflag(f, fctx.flags()) + except OSError: + repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f)) + raise + except IOError as inst: + errcode = getattr(inst, 'errno', errno.ENOENT) + if error or errcode and errcode != errno.ENOENT: + repo.ui.warn( + _(b"trouble committing %s!\n") % uipathfn(f) + ) + raise + + # update manifest + removed = [f for f in removed if f in m1 or f in m2] + drop = sorted([f for f in removed if f in m]) + for f in drop: + del m[f] + if p2.rev() != nullrev: + rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2)) + removed = [f for f in removed if not rf(f)] + + touched.extend(removed) + + if writechangesetcopy: + filesremoved = removed + + files = touched + md = None + if not files: + # if no "files" actually changed in terms of the changelog, + # try hard to detect unmodified manifest entry so that the + # exact same commit can be reproduced later on convert. + md = m1.diff(m, scmutil.matchfiles(repo, ctx.files())) + if not files and md: + repo.ui.debug( + b'not reusing manifest (no file change in ' + b'changelog, but manifest differs)\n' + ) + if files or md: + repo.ui.note(_(b"committing manifest\n")) + # we're using narrowmatch here since it's already applied at + # other stages (such as dirstate.walk), so we're already + # ignoring things outside of narrowspec in most cases. The + # one case where we might have files outside the narrowspec + # at this point is merges, and we already error out in the + # case where the merge has files outside of the narrowspec, + # so this is safe. + mn = mctx.write( + trp, + linkrev, + p1.manifestnode(), + p2.manifestnode(), + added, + drop, + match=repo.narrowmatch(), + ) + else: + repo.ui.debug( + b'reusing manifest from p1 (listed files ' + b'actually unchanged)\n' + ) + mn = p1.manifestnode() + + if writecopiesto == b'changeset-only': + # If writing only to changeset extras, use None to indicate that + # no entry should be written. If writing to both, write an empty + # entry to prevent the reader from falling back to reading + # filelogs. + p1copies = p1copies or None + p2copies = p2copies or None + filesadded = filesadded or None + filesremoved = filesremoved or None + + if origctx and origctx.manifestnode() == mn: + files = origctx.files() + + # update changelog + repo.ui.note(_(b"committing changelog\n")) + repo.changelog.delayupdate(tr) + n = repo.changelog.add( + mn, + files, + ctx.description(), + trp, + p1.node(), + p2.node(), + user, + ctx.date(), + ctx.extra().copy(), + p1copies, + p2copies, + filesadded, + filesremoved, + ) + xp1, xp2 = p1.hex(), p2 and p2.hex() or b'' + repo.hook( + b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2, + ) + # set the new commit is proper phase + targetphase = subrepoutil.newcommitphase(repo.ui, ctx) + if targetphase: + # retract boundary do not alter parent changeset. + # if a parent have higher the resulting phase will + # be compliant anyway + # + # if minimal phase was 0 we don't need to retract anything + phases.registernew(repo, tr, targetphase, [n]) + return n + + +def _filecommit( + repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta, +): + """ + commit an individual file as part of a larger transaction + + input: + + fctx: a file context with the content we are trying to commit + manifest1: manifest of changeset first parent + manifest2: manifest of changeset second parent + linkrev: revision number of the changeset being created + tr: current transation + individual: boolean, set to False to skip storing the copy data + (only used by the Google specific feature of using + changeset extra as copy source of truth). + + output: (filenode, touched) + + filenode: the filenode that should be used by this changeset + touched: one of: None, 'added' or 'modified' + """ + + fname = fctx.path() + fparent1 = manifest1.get(fname, nullid) + fparent2 = manifest2.get(fname, nullid) + touched = None + if fparent1 == fparent2 == nullid: + touched = 'added' + + if isinstance(fctx, context.filectx): + # This block fast path most comparisons which are usually done. It + # assumes that bare filectx is used and no merge happened, hence no + # need to create a new file revision in this case. + node = fctx.filenode() + if node in [fparent1, fparent2]: + repo.ui.debug(b'reusing %s filelog entry\n' % fname) + if ( + fparent1 != nullid and manifest1.flags(fname) != fctx.flags() + ) or ( + fparent2 != nullid and manifest2.flags(fname) != fctx.flags() + ): + touched = 'modified' + return node, touched + + flog = repo.file(fname) + meta = {} + cfname = fctx.copysource() + fnode = None + + if cfname and cfname != fname: + # Mark the new revision of this file as a copy of another + # file. This copy data will effectively act as a parent + # of this new revision. If this is a merge, the first + # parent will be the nullid (meaning "look up the copy data") + # and the second one will be the other parent. For example: + # + # 0 --- 1 --- 3 rev1 changes file foo + # \ / rev2 renames foo to bar and changes it + # \- 2 -/ rev3 should have bar with all changes and + # should record that bar descends from + # bar in rev2 and foo in rev1 + # + # this allows this merge to succeed: + # + # 0 --- 1 --- 3 rev4 reverts the content change from rev2 + # \ / merging rev3 and rev4 should use bar@rev2 + # \- 2 --- 4 as the merge base + # + + cnode = manifest1.get(cfname) + newfparent = fparent2 + + if manifest2: # branch merge + if fparent2 == nullid or cnode is None: # copied on remote side + if cfname in manifest2: + cnode = manifest2[cfname] + newfparent = fparent1 + + # Here, we used to search backwards through history to try to find + # where the file copy came from if the source of a copy was not in + # the parent directory. However, this doesn't actually make sense to + # do (what does a copy from something not in your working copy even + # mean?) and it causes bugs (eg, issue4476). Instead, we will warn + # the user that copy information was dropped, so if they didn't + # expect this outcome it can be fixed, but this is the correct + # behavior in this circumstance. + + if cnode: + repo.ui.debug(b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode))) + if includecopymeta: + meta[b"copy"] = cfname + meta[b"copyrev"] = hex(cnode) + fparent1, fparent2 = nullid, newfparent + else: + repo.ui.warn( + _( + b"warning: can't find ancestor for '%s' " + b"copied from '%s'!\n" + ) + % (fname, cfname) + ) + + elif fparent1 == nullid: + fparent1, fparent2 = fparent2, nullid + elif fparent2 != nullid: + # is one parent an ancestor of the other? + fparentancestors = flog.commonancestorsheads(fparent1, fparent2) + if fparent1 in fparentancestors: + fparent1, fparent2 = fparent2, nullid + elif fparent2 in fparentancestors: + fparent2 = nullid + elif not fparentancestors: + # TODO: this whole if-else might be simplified much more + ms = mergestate.mergestate.read(repo) + if ( + fname in ms + and ms[fname] == mergestate.MERGE_RECORD_MERGED_OTHER + ): + fparent1, fparent2 = fparent2, nullid + + # is the file changed? + text = fctx.data() + if fparent2 != nullid or meta or flog.cmp(fparent1, text): + if touched is None: # do not overwrite added + touched = 'modified' + fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2) + # are just the flags changed during merge? + elif fname in manifest1 and manifest1.flags(fname) != fctx.flags(): + touched = 'modified' + fnode = fparent1 + else: + fnode = fparent1 + return fnode, touched diff -r fc54f52779dd -r 4b923da0cb86 mercurial/debugcommands.py --- a/mercurial/debugcommands.py Tue Jul 21 01:04:19 2020 +0200 +++ b/mercurial/debugcommands.py Wed Jul 22 22:09:38 2020 -0400 @@ -1668,8 +1668,8 @@ fm.data(re2=bool(util._re2)) # templates - p = templater.templatepaths() - fm.write(b'templatedirs', b'checking templates (%s)...\n', b' '.join(p)) + p = templater.templatedir() + fm.write(b'templatedirs', b'checking templates (%s)...\n', p) fm.condwrite(not p, b'', _(b" no template directories found\n")) if p: m = templater.templatepath(b"map-cmdline.default") diff -r fc54f52779dd -r 4b923da0cb86 mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py Tue Jul 21 01:04:19 2020 +0200 +++ b/mercurial/hgweb/hgwebdir_mod.py Wed Jul 22 22:09:38 2020 -0400 @@ -414,10 +414,8 @@ fname = req.qsparams[b'static'] static = self.ui.config(b"web", b"static", untrusted=False) if not static: - tp = self.templatepath or templater.templatepaths() - if isinstance(tp, bytes): - tp = [tp] - static = [os.path.join(p, b'static') for p in tp] + tp = self.templatepath or templater.templatedir() + static = [os.path.join(tp, b'static')] staticfile(static, fname, res) return res.sendresponse() diff -r fc54f52779dd -r 4b923da0cb86 mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py Tue Jul 21 01:04:19 2020 +0200 +++ b/mercurial/hgweb/webcommands.py Wed Jul 22 22:09:38 2020 -0400 @@ -1319,10 +1319,8 @@ # readable by the user running the CGI script static = web.config(b"web", b"static", untrusted=False) if not static: - tp = web.templatepath or templater.templatepaths() - if isinstance(tp, bytes): - tp = [tp] - static = [os.path.join(p, b'static') for p in tp] + tp = web.templatepath or templater.templatedir() + static = [os.path.join(tp, b'static')] staticfile(static, fname, web.res) return web.res.sendresponse() diff -r fc54f52779dd -r 4b923da0cb86 mercurial/localrepo.py --- a/mercurial/localrepo.py Tue Jul 21 01:04:19 2020 +0200 +++ b/mercurial/localrepo.py Wed Jul 22 22:09:38 2020 -0400 @@ -32,6 +32,7 @@ bundle2, changegroup, color, + commit, context, dirstate, dirstateguard, @@ -46,7 +47,6 @@ match as matchmod, mergestate as mergestatemod, mergeutil, - metadata, namespaces, narrowspec, obsolete, @@ -2771,140 +2771,6 @@ """Returns the wlock if it's held, or None if it's not.""" return self._currentlock(self._wlockref) - def _filecommit( - self, - fctx, - manifest1, - manifest2, - linkrev, - tr, - changelist, - includecopymeta, - ): - """ - commit an individual file as part of a larger transaction - - input: - - fctx: a file context with the content we are trying to commit - manifest1: manifest of changeset first parent - manifest2: manifest of changeset second parent - linkrev: revision number of the changeset being created - tr: current transation - changelist: list of file being changed (modified inplace) - individual: boolean, set to False to skip storing the copy data - (only used by the Google specific feature of using - changeset extra as copy source of truth). - - output: - - The resulting filenode - """ - - fname = fctx.path() - fparent1 = manifest1.get(fname, nullid) - fparent2 = manifest2.get(fname, nullid) - if isinstance(fctx, context.filectx): - node = fctx.filenode() - if node in [fparent1, fparent2]: - self.ui.debug(b'reusing %s filelog entry\n' % fname) - if ( - fparent1 != nullid - and manifest1.flags(fname) != fctx.flags() - ) or ( - fparent2 != nullid - and manifest2.flags(fname) != fctx.flags() - ): - changelist.append(fname) - return node - - flog = self.file(fname) - meta = {} - cfname = fctx.copysource() - if cfname and cfname != fname: - # Mark the new revision of this file as a copy of another - # file. This copy data will effectively act as a parent - # of this new revision. If this is a merge, the first - # parent will be the nullid (meaning "look up the copy data") - # and the second one will be the other parent. For example: - # - # 0 --- 1 --- 3 rev1 changes file foo - # \ / rev2 renames foo to bar and changes it - # \- 2 -/ rev3 should have bar with all changes and - # should record that bar descends from - # bar in rev2 and foo in rev1 - # - # this allows this merge to succeed: - # - # 0 --- 1 --- 3 rev4 reverts the content change from rev2 - # \ / merging rev3 and rev4 should use bar@rev2 - # \- 2 --- 4 as the merge base - # - - cnode = manifest1.get(cfname) - newfparent = fparent2 - - if manifest2: # branch merge - if fparent2 == nullid or cnode is None: # copied on remote side - if cfname in manifest2: - cnode = manifest2[cfname] - newfparent = fparent1 - - # Here, we used to search backwards through history to try to find - # where the file copy came from if the source of a copy was not in - # the parent directory. However, this doesn't actually make sense to - # do (what does a copy from something not in your working copy even - # mean?) and it causes bugs (eg, issue4476). Instead, we will warn - # the user that copy information was dropped, so if they didn't - # expect this outcome it can be fixed, but this is the correct - # behavior in this circumstance. - - if cnode: - self.ui.debug( - b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)) - ) - if includecopymeta: - meta[b"copy"] = cfname - meta[b"copyrev"] = hex(cnode) - fparent1, fparent2 = nullid, newfparent - else: - self.ui.warn( - _( - b"warning: can't find ancestor for '%s' " - b"copied from '%s'!\n" - ) - % (fname, cfname) - ) - - elif fparent1 == nullid: - fparent1, fparent2 = fparent2, nullid - elif fparent2 != nullid: - # is one parent an ancestor of the other? - fparentancestors = flog.commonancestorsheads(fparent1, fparent2) - if fparent1 in fparentancestors: - fparent1, fparent2 = fparent2, nullid - elif fparent2 in fparentancestors: - fparent2 = nullid - elif not fparentancestors: - # TODO: this whole if-else might be simplified much more - ms = mergestatemod.mergestate.read(self) - if ( - fname in ms - and ms[fname] == mergestatemod.MERGE_RECORD_MERGED_OTHER - ): - fparent1, fparent2 = fparent2, nullid - - # is the file changed? - text = fctx.data() - if fparent2 != nullid or meta or flog.cmp(fparent1, text): - changelist.append(fname) - return flog.add(text, meta, tr, linkrev, fparent1, fparent2) - # are just the flags changed during merge? - elif fname in manifest1 and manifest1.flags(fname) != fctx.flags(): - changelist.append(fname) - - return fparent1 - def checkcommitpatterns(self, wctx, match, status, fail): """check for commit arguments that aren't committable""" if match.isexact() or match.prefix(): @@ -3062,203 +2928,7 @@ @unfilteredmethod def commitctx(self, ctx, error=False, origctx=None): - """Add a new revision to current repository. - Revision information is passed via the context argument. - - ctx.files() should list all files involved in this commit, i.e. - modified/added/removed files. On merge, it may be wider than the - ctx.files() to be committed, since any file nodes derived directly - from p1 or p2 are excluded from the committed ctx.files(). - - origctx is for convert to work around the problem that bug - fixes to the files list in changesets change hashes. For - convert to be the identity, it can pass an origctx and this - function will use the same files list when it makes sense to - do so. - """ - - p1, p2 = ctx.p1(), ctx.p2() - user = ctx.user() - - if self.filecopiesmode == b'changeset-sidedata': - writechangesetcopy = True - writefilecopymeta = True - writecopiesto = None - else: - writecopiesto = self.ui.config(b'experimental', b'copies.write-to') - writefilecopymeta = writecopiesto != b'changeset-only' - writechangesetcopy = writecopiesto in ( - b'changeset-only', - b'compatibility', - ) - p1copies, p2copies = None, None - if writechangesetcopy: - p1copies = ctx.p1copies() - p2copies = ctx.p2copies() - filesadded, filesremoved = None, None - with self.lock(), self.transaction(b"commit") as tr: - trp = weakref.proxy(tr) - - if ctx.manifestnode(): - # reuse an existing manifest revision - self.ui.debug(b'reusing known manifest\n') - mn = ctx.manifestnode() - files = ctx.files() - if writechangesetcopy: - filesadded = ctx.filesadded() - filesremoved = ctx.filesremoved() - elif ctx.files(): - m1ctx = p1.manifestctx() - m2ctx = p2.manifestctx() - mctx = m1ctx.copy() - - m = mctx.read() - m1 = m1ctx.read() - m2 = m2ctx.read() - - # check in files - added = [] - changed = [] - removed = list(ctx.removed()) - linkrev = len(self) - self.ui.note(_(b"committing files:\n")) - uipathfn = scmutil.getuipathfn(self) - for f in sorted(ctx.modified() + ctx.added()): - self.ui.note(uipathfn(f) + b"\n") - try: - fctx = ctx[f] - if fctx is None: - removed.append(f) - else: - added.append(f) - m[f] = self._filecommit( - fctx, - m1, - m2, - linkrev, - trp, - changed, - writefilecopymeta, - ) - m.setflag(f, fctx.flags()) - except OSError: - self.ui.warn( - _(b"trouble committing %s!\n") % uipathfn(f) - ) - raise - except IOError as inst: - errcode = getattr(inst, 'errno', errno.ENOENT) - if error or errcode and errcode != errno.ENOENT: - self.ui.warn( - _(b"trouble committing %s!\n") % uipathfn(f) - ) - raise - - # update manifest - removed = [f for f in removed if f in m1 or f in m2] - drop = sorted([f for f in removed if f in m]) - for f in drop: - del m[f] - if p2.rev() != nullrev: - rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2)) - removed = [f for f in removed if not rf(f)] - - files = changed + removed - md = None - if not files: - # if no "files" actually changed in terms of the changelog, - # try hard to detect unmodified manifest entry so that the - # exact same commit can be reproduced later on convert. - md = m1.diff(m, scmutil.matchfiles(self, ctx.files())) - if not files and md: - self.ui.debug( - b'not reusing manifest (no file change in ' - b'changelog, but manifest differs)\n' - ) - if files or md: - self.ui.note(_(b"committing manifest\n")) - # we're using narrowmatch here since it's already applied at - # other stages (such as dirstate.walk), so we're already - # ignoring things outside of narrowspec in most cases. The - # one case where we might have files outside the narrowspec - # at this point is merges, and we already error out in the - # case where the merge has files outside of the narrowspec, - # so this is safe. - mn = mctx.write( - trp, - linkrev, - p1.manifestnode(), - p2.manifestnode(), - added, - drop, - match=self.narrowmatch(), - ) - - if writechangesetcopy: - filesadded = [ - f for f in changed if not (f in m1 or f in m2) - ] - filesremoved = removed - else: - self.ui.debug( - b'reusing manifest from p1 (listed files ' - b'actually unchanged)\n' - ) - mn = p1.manifestnode() - else: - self.ui.debug(b'reusing manifest from p1 (no file change)\n') - mn = p1.manifestnode() - files = [] - - if writecopiesto == b'changeset-only': - # If writing only to changeset extras, use None to indicate that - # no entry should be written. If writing to both, write an empty - # entry to prevent the reader from falling back to reading - # filelogs. - p1copies = p1copies or None - p2copies = p2copies or None - filesadded = filesadded or None - filesremoved = filesremoved or None - - if origctx and origctx.manifestnode() == mn: - files = origctx.files() - - # update changelog - self.ui.note(_(b"committing changelog\n")) - self.changelog.delayupdate(tr) - n = self.changelog.add( - mn, - files, - ctx.description(), - trp, - p1.node(), - p2.node(), - user, - ctx.date(), - ctx.extra().copy(), - p1copies, - p2copies, - filesadded, - filesremoved, - ) - xp1, xp2 = p1.hex(), p2 and p2.hex() or b'' - self.hook( - b'pretxncommit', - throw=True, - node=hex(n), - parent1=xp1, - parent2=xp2, - ) - # set the new commit is proper phase - targetphase = subrepoutil.newcommitphase(self.ui, ctx) - if targetphase: - # retract boundary do not alter parent changeset. - # if a parent have higher the resulting phase will - # be compliant anyway - # - # if minimal phase was 0 we don't need to retract anything - phases.registernew(self, tr, targetphase, [n]) - return n + return commit.commitctx(self, ctx, error=error, origctx=origctx) @unfilteredmethod def destroying(self): diff -r fc54f52779dd -r 4b923da0cb86 mercurial/templater.py --- a/mercurial/templater.py Tue Jul 21 01:04:19 2020 +0200 +++ b/mercurial/templater.py Wed Jul 22 22:09:38 2020 -0400 @@ -800,10 +800,10 @@ def stylelist(): - paths = templatepaths() - if not paths: + path = templatedir() + if not path: return _(b'no templates found, try `hg debuginstall` for more info') - dirlist = os.listdir(paths[0]) + dirlist = os.listdir(path) stylelist = [] for file in dirlist: split = file.split(b".") @@ -823,7 +823,7 @@ ) base = os.path.dirname(mapfile) - conf = config.config(includepaths=templatepaths()) + conf = config.config(includepaths=[templatedir()]) conf.read(mapfile, remap={b'': b'templates'}) cache = {} @@ -837,15 +837,13 @@ # fallback check in template paths if not os.path.exists(path): - for p in templatepaths(): - p2 = util.normpath(os.path.join(p, val)) - if os.path.isfile(p2): - path = p2 - break + p2 = util.normpath(os.path.join(templatedir(), val)) + if os.path.isfile(p2): + path = p2 + else: p3 = util.normpath(os.path.join(p2, b"map")) if os.path.isfile(p3): path = p3 - break cache, tmap, aliases = _readmapfile(path) @@ -1045,26 +1043,21 @@ return stream -def templatepaths(): - '''return locations used for template files.''' - pathsrel = [b'templates'] - paths = [ - os.path.normpath(os.path.join(resourceutil.datapath, f)) - for f in pathsrel - ] - return [p for p in paths if os.path.isdir(p)] +def templatedir(): + '''return the directory used for template files, or None.''' + path = os.path.normpath(os.path.join(resourceutil.datapath, b'templates')) + return path if os.path.isdir(path) else None def templatepath(name): '''return location of template file. returns None if not found.''' - for p in templatepaths(): - f = os.path.join(p, name) - if os.path.exists(f): - return f + f = os.path.join(templatedir(), name) + if f and os.path.exists(f): + return f return None -def stylemap(styles, paths=None): +def stylemap(styles, path=None): """Return path to mapfile for a given style. Searches mapfile in the following locations: @@ -1073,10 +1066,8 @@ 3. templatepath/map """ - if paths is None: - paths = templatepaths() - elif isinstance(paths, bytes): - paths = [paths] + if path is None: + path = templatedir() if isinstance(styles, bytes): styles = [styles] @@ -1094,10 +1085,9 @@ locations = [os.path.join(style, b'map'), b'map-' + style] locations.append(b'map') - for path in paths: - for location in locations: - mapfile = os.path.join(path, location) - if os.path.isfile(mapfile): - return style, mapfile + for location in locations: + mapfile = os.path.join(path, location) + if os.path.isfile(mapfile): + return style, mapfile - raise RuntimeError(b"No hgweb templates found in %r" % paths) + raise RuntimeError(b"No hgweb templates found in %r" % path) diff -r fc54f52779dd -r 4b923da0cb86 tests/test-annotate.t --- a/tests/test-annotate.t Tue Jul 21 01:04:19 2020 +0200 +++ b/tests/test-annotate.t Wed Jul 22 22:09:38 2020 -0400 @@ -479,26 +479,24 @@ $ cat > ../legacyrepo.py < from __future__ import absolute_import - > from mercurial import error, node - > def reposetup(ui, repo): - > class legacyrepo(repo.__class__): - > def _filecommit(self, fctx, manifest1, manifest2, - > linkrev, tr, changelist, includecopymeta): - > fname = fctx.path() - > text = fctx.data() - > flog = self.file(fname) - > fparent1 = manifest1.get(fname, node.nullid) - > fparent2 = manifest2.get(fname, node.nullid) - > meta = {} - > copy = fctx.copysource() - > if copy and copy != fname: - > raise error.Abort('copying is not supported') - > if fparent2 != node.nullid: - > changelist.append(fname) - > return flog.add(text, meta, tr, linkrev, - > fparent1, fparent2) - > raise error.Abort('only merging is supported') - > repo.__class__ = legacyrepo + > from mercurial import commit, error, extensions, node + > def _filecommit(orig, repo, fctx, manifest1, manifest2, + > linkrev, tr, includecopymeta): + > fname = fctx.path() + > text = fctx.data() + > flog = repo.file(fname) + > fparent1 = manifest1.get(fname, node.nullid) + > fparent2 = manifest2.get(fname, node.nullid) + > meta = {} + > copy = fctx.copysource() + > if copy and copy != fname: + > raise error.Abort('copying is not supported') + > if fparent2 != node.nullid: + > return flog.add(text, meta, tr, linkrev, + > fparent1, fparent2), 'modified' + > raise error.Abort('only merging is supported') + > def uisetup(ui): + > extensions.wrapfunction(commit, '_filecommit', _filecommit) > EOF $ cat > baz < ../legacyrepo.py < from mercurial import error, node - > def reposetup(ui, repo): - > class legacyrepo(repo.__class__): - > def _filecommit(self, fctx, manifest1, manifest2, - > linkrev, tr, changelist, includecopymeta): - > fname = fctx.path() - > text = fctx.data() - > flog = self.file(fname) - > fparent1 = manifest1.get(fname, node.nullid) - > fparent2 = manifest2.get(fname, node.nullid) - > meta = {} - > copy = fctx.renamed() - > if copy and copy[0] != fname: - > raise error.Abort('copying is not supported') - > if fparent2 != node.nullid: - > changelist.append(fname) - > return flog.add(text, meta, tr, linkrev, - > fparent1, fparent2) - > raise error.Abort('only merging is supported') - > repo.__class__ = legacyrepo + > from __future__ import absolute_import + > from mercurial import commit, error, extensions, node + > def _filecommit(orig, repo, fctx, manifest1, manifest2, + > linkrev, tr, includecopymeta): + > fname = fctx.path() + > text = fctx.data() + > flog = repo.file(fname) + > fparent1 = manifest1.get(fname, node.nullid) + > fparent2 = manifest2.get(fname, node.nullid) + > meta = {} + > copy = fctx.copysource() + > if copy and copy != fname: + > raise error.Abort('copying is not supported') + > if fparent2 != node.nullid: + > return flog.add(text, meta, tr, linkrev, + > fparent1, fparent2), 'modified' + > raise error.Abort('only merging is supported') + > def uisetup(ui): + > extensions.wrapfunction(commit, '_filecommit', _filecommit) > EOF $ cat > baz <