Patchwork D7143: largefiles: avoid dynamically subclassing context instances

login
register
mail settings
Submitter phabricator
Date Oct. 19, 2019, 7:38 a.m.
Message ID <differential-rev-PHID-DREV-jvtpwm5bnnwxib2qrlns-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/42489/
State Superseded
Headers show

Comments

phabricator - Oct. 19, 2019, 7:38 a.m.
martinvonz created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  E.g. copies.pathcopies() compares context objects for equality and
  basectx.__eq__ compares the type. But since largefiles was dynamically
  creating classes, they would all be unequal. That led pathcopies(),
  after some changes I made, to not short-circuit to get copy info only
  from the dirstate. This patch fixes that short-circuiting (and other
  places where context are being compared for equality).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D7143

AFFECTED FILES
  hgext/largefiles/reposetup.py

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/hgext/largefiles/reposetup.py b/hgext/largefiles/reposetup.py
--- a/hgext/largefiles/reposetup.py
+++ b/hgext/largefiles/reposetup.py
@@ -15,6 +15,7 @@ 
 
 from mercurial import (
     error,
+    extensions,
     localrepo,
     match as matchmod,
     scmutil,
@@ -47,45 +48,46 @@ 
             ctx = super(lfilesrepo, self).__getitem__(changeid)
             if self.lfstatus:
 
-                class lfilesctx(ctx.__class__):
-                    def files(self):
-                        filenames = super(lfilesctx, self).files()
-                        return [lfutil.splitstandin(f) or f for f in filenames]
+                def files(orig):
+                    filenames = orig()
+                    return [lfutil.splitstandin(f) or f for f in filenames]
 
-                    def manifest(self):
-                        man1 = super(lfilesctx, self).manifest()
+                extensions.wrapfunction(ctx, 'files', files)
+
+                def manifest(orig):
+                    man1 = orig()
 
-                        class lfilesmanifest(man1.__class__):
-                            def __contains__(self, filename):
-                                orig = super(lfilesmanifest, self).__contains__
-                                return orig(filename) or orig(
-                                    lfutil.standin(filename)
-                                )
+                    class lfilesmanifest(man1.__class__):
+                        def __contains__(self, filename):
+                            orig = super(lfilesmanifest, self).__contains__
+                            return orig(filename) or orig(
+                                lfutil.standin(filename)
+                            )
 
-                        man1.__class__ = lfilesmanifest
-                        return man1
+                    man1.__class__ = lfilesmanifest
+                    return man1
 
-                    def filectx(self, path, fileid=None, filelog=None):
-                        orig = super(lfilesctx, self).filectx
-                        try:
-                            if filelog is not None:
-                                result = orig(path, fileid, filelog)
-                            else:
-                                result = orig(path, fileid)
-                        except error.LookupError:
-                            # Adding a null character will cause Mercurial to
-                            # identify this as a binary file.
-                            if filelog is not None:
-                                result = orig(
-                                    lfutil.standin(path), fileid, filelog
-                                )
-                            else:
-                                result = orig(lfutil.standin(path), fileid)
-                            olddata = result.data
-                            result.data = lambda: olddata() + b'\0'
-                        return result
+                extensions.wrapfunction(ctx, 'manifest', manifest)
 
-                ctx.__class__ = lfilesctx
+                def filectx(orig, path, fileid=None, filelog=None):
+                    try:
+                        if filelog is not None:
+                            result = orig(path, fileid, filelog)
+                        else:
+                            result = orig(path, fileid)
+                    except error.LookupError:
+                        # Adding a null character will cause Mercurial to
+                        # identify this as a binary file.
+                        if filelog is not None:
+                            result = orig(lfutil.standin(path), fileid, filelog)
+                        else:
+                            result = orig(lfutil.standin(path), fileid)
+                        olddata = result.data
+                        result.data = lambda: olddata() + b'\0'
+                    return result
+
+                extensions.wrapfunction(ctx, 'filectx', filectx)
+
             return ctx
 
         # Figure out the status of big files and insert them into the