# HG changeset patch # User Martin von Zweigbergk # Date 2017-12-11 17:27:40 # Node ID 8a0cac20a1ad1cefd20fa34a60a6306b1a4ab95a # Parent dffc35a5be9f52a47fc7732367c234bf5dba9275 memfilectx: make changectx argument mandatory in constructor (API) committablefilectx has three subclasses: workingfilectx, memfilectx, and overlayfilectx. committablefilectx takes an optional (change) ctx instance to its constructor. If it's provided, it's set on the instance as self._changectx. If not, that property is supposed to be defined by the class. However, only workingfilectx does that. The other two will have the property undefined if it's not passed in the constructor. That seems bad to me. This patch makes the changectx argument to the memfilectx constructor mandatory because that fixes the failure I ran into. It seems like we should also fix the overlayfilectx case. Differential Revision: https://phab.mercurial-scm.org/D1658 diff --git a/contrib/synthrepo.py b/contrib/synthrepo.py --- a/contrib/synthrepo.py +++ b/contrib/synthrepo.py @@ -376,7 +376,7 @@ def synthesize(ui, repo, descpath, **opt dir = os.path.dirname(dir) def filectxfn(repo, memctx, path): - return context.memfilectx(repo, path, files[path]) + return context.memfilectx(repo, memctx, path, files[path]) ui.progress(_synthesizing, None) message = 'synthesized wide repo with %d files' % (len(files),) @@ -468,7 +468,7 @@ def synthesize(ui, repo, descpath, **opt def filectxfn(repo, memctx, path): if path not in changes: return None - return context.memfilectx(repo, path, changes[path]) + return context.memfilectx(repo, memctx, path, changes[path]) if not changes: continue if revs: diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -253,7 +253,7 @@ class mercurial_sink(common.converter_si data = self._rewritetags(source, revmap, data) if f == '.hgsubstate': data = self._rewritesubstate(source, data) - return context.memfilectx(self.repo, f, data, 'l' in mode, + return context.memfilectx(self.repo, memctx, f, data, 'l' in mode, 'x' in mode, copies.get(f)) pl = [] @@ -401,7 +401,7 @@ class mercurial_sink(common.converter_si data = "".join(newlines) def getfilectx(repo, memctx, f): - return context.memfilectx(repo, f, data, False, False, None) + return context.memfilectx(repo, memctx, f, data, False, False, None) self.ui.status(_("updating tags\n")) date = "%s 0" % int(time.mktime(time.gmtime())) diff --git a/hgext/histedit.py b/hgext/histedit.py --- a/hgext/histedit.py +++ b/hgext/histedit.py @@ -602,7 +602,7 @@ def collapse(repo, first, last, commitop if path in headmf: fctx = last[path] flags = fctx.flags() - mctx = context.memfilectx(repo, + mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(), islink='l' in flags, isexec='x' in flags, diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py --- a/hgext/largefiles/lfcommands.py +++ b/hgext/largefiles/lfcommands.py @@ -261,7 +261,8 @@ def _lfconvert_addchangeset(rsrc, rdst, # doesn't change after rename or copy renamed = lfutil.standin(renamed[0]) - return context.memfilectx(repo, f, lfiletohash[srcfname] + '\n', + return context.memfilectx(repo, memctx, f, + lfiletohash[srcfname] + '\n', 'l' in fctx.flags(), 'x' in fctx.flags(), renamed) else: @@ -313,7 +314,7 @@ def _getnormalcontext(repo, ctx, f, revm data = fctx.data() if f == '.hgtags': data = _converttags (repo.ui, revmap, data) - return context.memfilectx(repo, f, data, 'l' in fctx.flags(), + return context.memfilectx(repo, ctx, f, data, 'l' in fctx.flags(), 'x' in fctx.flags(), renamed) # Remap tag data using a revision map diff --git a/hgext/uncommit.py b/hgext/uncommit.py --- a/hgext/uncommit.py +++ b/hgext/uncommit.py @@ -77,7 +77,7 @@ def _commitfiltered(repo, ctx, match, al if path not in contentctx: return None fctx = contentctx[path] - mctx = context.memfilectx(repo, fctx.path(), fctx.data(), + mctx = context.memfilectx(repo, memctx, fctx.path(), fctx.data(), fctx.islink(), fctx.isexec(), copied=copied.get(path)) diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -3195,7 +3195,7 @@ def amend(ui, repo, old, extra, pats, op fctx = wctx[path] flags = fctx.flags() - mctx = context.memfilectx(repo, + mctx = context.memfilectx(repo, ctx_, fctx.path(), fctx.data(), islink='l' in flags, isexec='x' in flags, diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -2204,12 +2204,11 @@ class overlayworkingctx(committablectx): files = self._cache.keys() def getfile(repo, memctx, path): if self._cache[path]['exists']: - return memfilectx(repo, path, + return memfilectx(repo, memctx, path, self._cache[path]['data'], 'l' in self._cache[path]['flags'], 'x' in self._cache[path]['flags'], - self._cache[path]['copied'], - memctx) + self._cache[path]['copied']) else: # Returning None, but including the path in `files`, is # necessary for memctx to register a deletion. @@ -2389,9 +2388,9 @@ def memfilefromctx(ctx): copied = fctx.renamed() if copied: copied = copied[0] - return memfilectx(repo, path, fctx.data(), + return memfilectx(repo, memctx, path, fctx.data(), islink=fctx.islink(), isexec=fctx.isexec(), - copied=copied, memctx=memctx) + copied=copied) return getfilectx @@ -2405,9 +2404,8 @@ def memfilefrompatch(patchstore): if data is None: return None islink, isexec = mode - return memfilectx(repo, path, data, islink=islink, - isexec=isexec, copied=copied, - memctx=memctx) + return memfilectx(repo, memctx, path, data, islink=islink, + isexec=isexec, copied=copied) return getfilectx @@ -2539,8 +2537,8 @@ class memfilectx(committablefilectx): See memctx and committablefilectx for more details. """ - def __init__(self, repo, path, data, islink=False, - isexec=False, copied=None, memctx=None): + def __init__(self, repo, changectx, path, data, islink=False, + isexec=False, copied=None): """ path is the normalized file path relative to repository root. data is the file content as a string. @@ -2548,7 +2546,7 @@ class memfilectx(committablefilectx): isexec is True if the file is executable. copied is the source file path if current file was copied in the revision being committed, or None.""" - super(memfilectx, self).__init__(repo, path, None, memctx) + super(memfilectx, self).__init__(repo, path, None, changectx) self._data = data self._flags = (islink and 'l' or '') + (isexec and 'x' or '') self._copied = None diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -225,7 +225,8 @@ def debugbuilddag(ui, repo, text=None, def fctxfn(repo, cx, path): if path in filecontent: - return context.memfilectx(repo, path, filecontent[path]) + return context.memfilectx(repo, cx, path, + filecontent[path]) return None if len(ps) == 0 or ps[0] < 0: diff --git a/tests/test-commit.t b/tests/test-commit.t --- a/tests/test-commit.t +++ b/tests/test-commit.t @@ -648,7 +648,8 @@ verify pathauditor blocks evil filepaths > u = uimod.ui.load() > r = hg.repository(u, '.') > def filectxfn(repo, memctx, path): - > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned') + > return context.memfilectx(repo, memctx, path, + > '[hooks]\nupdate = echo owned') > c = context.memctx(r, [r['tip'].node(), node.nullid], > 'evil', [notrc], filectxfn, 0) > r.commitctx(c) @@ -673,7 +674,8 @@ verify pathauditor blocks evil filepaths > u = uimod.ui.load() > r = hg.repository(u, '.') > def filectxfn(repo, memctx, path): - > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned') + > return context.memfilectx(repo, memctx, path, + > '[hooks]\nupdate = echo owned') > c = context.memctx(r, [r['tip'].node(), node.nullid], > 'evil', [notrc], filectxfn, 0) > r.commitctx(c) @@ -692,7 +694,8 @@ verify pathauditor blocks evil filepaths > u = uimod.ui.load() > r = hg.repository(u, '.') > def filectxfn(repo, memctx, path): - > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned') + > return context.memfilectx(repo, memctx, path, + > '[hooks]\nupdate = echo owned') > c = context.memctx(r, [r['tip'].node(), node.nullid], > 'evil', [notrc], filectxfn, 0) > r.commitctx(c) diff --git a/tests/test-context.py b/tests/test-context.py --- a/tests/test-context.py +++ b/tests/test-context.py @@ -32,7 +32,7 @@ print("workingfilectx.date = (%d, %d)" % # test memctx with non-ASCII commit message def filectxfn(repo, memctx, path): - return context.memfilectx(repo, "foo", "") + return context.memfilectx(repo, memctx, "foo", "") ctx = context.memctx(repo, ['tip', None], encoding.tolocal("Gr\xc3\xbcezi!"), @@ -49,7 +49,7 @@ def getfilectx(repo, memctx, f): data, flags = fctx.data(), fctx.flags() if f == 'foo': data += 'bar\n' - return context.memfilectx(repo, f, data, 'l' in flags, 'x' in flags) + return context.memfilectx(repo, memctx, f, data, 'l' in flags, 'x' in flags) ctxa = repo.changectx(0) ctxb = context.memctx(repo, [ctxa.node(), None], "test diff", ["foo"],