hgmo: refactor filelog entries modification (bug 1360007); r?glob draft
authorGregory Szorc <gps@mozilla.com>
Tue, 23 May 2017 17:08:19 -0700
changeset 11086 14ec72b176be821c84337805a13372d1f1d3434c
parent 11085 f8a2a76ca20b3bd26ec04acb2f67b852b41b0c98
child 11087 6d37df879a6288a17a2d23852f5b123c036b50e5
push id1683
push userbmo:gps@mozilla.com
push dateWed, 24 May 2017 01:08:55 +0000
reviewersglob
bugs1360007
hgmo: refactor filelog entries modification (bug 1360007); r?glob We have a custom wrapper function for the "filelog" web command that adds pushlog info. This was added in 3ac7f2de1e6b. The previous implementation was a bit fragile in that it relied on implementation details of the templater too much. We constructed a fake templater class and passed it into the original function. Then, we inspected the arguments passed to __call__, modified them in place, then called the original templater with those arguments. Something - I'm not sure what - broke in 4.2. This commit refactors the code to instead create a new proxy class for the templater that intercepts __call__ and does modification there. This fixes whatever the problem was with 4.2. While we could probably leave the .__class__ monkeypatched, it is restored out of paranoia. MozReview-Commit-ID: 5qugurPWzOh
hgext/hgmo/__init__.py
--- a/hgext/hgmo/__init__.py
+++ b/hgext/hgmo/__init__.py
@@ -708,42 +708,40 @@ def processbundlesmanifest(orig, repo, p
 
     except Exception as e:
         repo.ui.log('hgmo', 'exception filtering bundle source IPs: %s\n', e)
         return manifest
 
 
 def filelog(orig, web, req, tmpl):
     """Wraps webcommands.filelog to provide pushlog metadata to template."""
-
-    if hasattr(web.repo, 'pushlog'):
-
-        class _tmpl(object):
-
-            def __init__(self):
-                self.defaults = tmpl.defaults
-
-            def __call__(self, *args, **kwargs):
-                self.args = args
-                self.kwargs = kwargs
-                return self
+    # Template wrapper to add pushlog data to entries when the template is
+    # evaluated.
+    class tmplwrapper(tmpl.__class__):
+        def __call__(self, *args, **kwargs):
+            for entry in kwargs.get('entries', []):
+                push = web.repo.pushlog.pushfromnode(bin(entry['node']))
+                if push:
+                    entry['pushid'] = push.pushid
+                    entry['pushdate'] = util.makedate(push.when)
+                else:
+                    entry['pushid'] = None
+                    entry['pushdate'] = None
 
-        t = orig(web, req, _tmpl())
-        for entry in t.kwargs['entries']:
-            push = web.repo.pushlog.pushfromnode(bin(entry['node']))
-            if push:
-                entry['pushid'] = push.pushid
-                entry['pushdate'] = util.makedate(push.when)
-            else:
-                entry['pushid'] = None
-                entry['pushdate'] = None
+            return super(tmplwrapper, self).__call__(*args, **kwargs)
 
-        return tmpl(*t.args, **t.kwargs)
-    else:
-        return orig(web, req, tmpl)
+    orig_class = tmpl.__class__
+    try:
+        if hasattr(web.repo, 'pushlog'):
+            tmpl.__class__ = tmplwrapper
+
+        for r in orig(web, req, tmpl):
+            yield r
+    finally:
+        tmpl.__class__ = orig_class
 
 
 def extsetup(ui):
     extensions.wrapfunction(exchange, 'pull', pull)
     extensions.wrapfunction(webutil, 'changesetentry', changesetentry)
     extensions.wrapfunction(webutil, 'changelistentry', changelistentry)
     extensions.wrapfunction(bookmarks, 'updatefromremote', bmupdatefromremote)
     extensions.wrapfunction(webcommands, 'filelog', filelog)