[PATCH] keyword: make repo.commit use a custom commitctx wrapper

Christian Ebert blacktrash at gmx.net
Thu Jul 2 12:49:20 CDT 2009


* Matt Mackall on Thursday, July 02, 2009 at 09:40:44 -0500
> On Thu, 2009-07-02 at 11:18 +0200, Christian Ebert wrote:
>> * Christian Ebert on Tuesday, June 30, 2009 at 10:13:28 -0000
>>> # HG changeset patch
>>> # User Christian Ebert <blacktrash at gmx.net>
>>> # Date 1246354203 -7200
>>> # Node ID 02f1d60fe9bf5274d5b4cf409963815694c24338
>>> # Parent  bacb06d1e8b60b6083e3139fc5fb23355612eef8
>>> keyword: make repo.commit use a custom commitctx wrapper
>> 
>> <snip>
>> 
>> A question about my own patch ;-)
>> 
>>> @@ -460,8 +461,14 @@
>>> 
>>>        def commit(self, text='', user=None, date=None, match=None,
>>>                   force=False, editor=None, extra={}):
>>> +            # use custom commitctx for user commands
>>> +            # other extensions can still wrap repo.commitctx directly
>>> +            repo.commitctx = self.kwcommitctx
>> 
>> The above line works also as:
>> 
>>             self.commitctx = self.kwcommitctx
>> 
>> Background:
>> 
>> In reposetup(ui, repo) I override the repo class:
>> 
>>    class kwrepo(repo.__class__):
>> 
>> and later on do things like:
>>   
>>        lock = self.wlock()
>> 
>> even though wlock is not defined in kwrepo. Playing around with
>> pylint, it complained about that "kwrepo has no wlock member",
>> but felt better after I changed the above to
>> 
>>        lock = repo.wlock()
>> 
>> as it would have complained if I had
>> 
>>             self.commitctx = self.kwcommitctx
>> 
>> instead of
>> 
>>             repo.commitctx = self.kwcommitctx
>> 
>> in my patch. 
>> 
>> mq does something similar and uses self consistently (with pylint
>> complaining accordingly). Which is the way to go? Is there a
>> difference wrt to safety? According to test-keyword it doesn't
>> make a difference, but which way should I choose for consistency?
> 
> See cset 5726bb290bfe.

Will try to understand the relevance of this wrt to my question
in the next few days/many months ;-)

> However, member functions turn out to be a special issue, see
> 5726bb290bfe. When you do:
> 
> a = object.func
> 
> you're effectively doing:
> 
> a = lambda *args, **kwargs: object.func(*args, **kwargs)
> 
> which binds a reference to object up inside of a. So when you do:
> 
> self.func2 = self.func1
> 
> you're effectively making a reference cycle inside self and making self
> immortal. A kwrepo wrapping a bundlerepo will thus cause problems
> because bundlerepo won't be able to clean up after itself. So how do we
> wrap an object's method without introducing a cycle? The best way I know
> is to do it at the class level:
> 
> class a(b.__class__):
>    def func(self, *args):
>       super(a, self).func(*args)

Yup. I use that quite often already, but not consistently (mq
doesn't either btw).

A patch for keyword making consistency corrections would look
like this:


# HG changeset patch
# User Christian Ebert <blacktrash at gmx.net>
# Date 1246554781 -7200
# Node ID 8a46927ec390ae31c7a90875dc2837f8e952af47
# Parent  c24c9ce0cdcf74e8377d4e0c5e177682f3d76c32
keyword: use super(kwrepo, self) whereever possible

diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -453,7 +453,7 @@
         def file(self, f):
             if f[0] == '/':
                 f = f[1:]
-            return kwfilelog(self.sopener, kwt, f)
+            return kwfilelog(repo.sopener, kwt, f)
 
         def wread(self, filename):
             data = super(kwrepo, self).wread(filename)
@@ -470,8 +470,8 @@
         def kwcommitctx(self, ctx, error=False):
             wlock = lock = None
             try:
-                wlock = self.wlock()
-                lock = self.lock()
+                wlock = super(kwrepo, self).wlock()
+                lock = super(kwrepo, self).lock()
                 # store and postpone commit hooks
                 commithooks = {}
                 for name, cmd in ui.configitems('hooks'):
@@ -489,7 +489,8 @@
                 if commithooks:
                     for name, cmd in commithooks.iteritems():
                         ui.setconfig('hooks', name, cmd)
-                    repo.hook('commit', node=n, parent1=xp1, parent2=xp2)
+                    super(kwrepo, self).hook('commit',
+                                             node=n, parent1=xp1, parent2=xp2)
                 return n
             finally:
                 release(lock, wlock)


Now look at the sopener thing; the following breaks (changed from
self.opener to repo.sopener above):

class kwrepo(repo.__class__):
        def file(self, f):
            if f[0] == '/':
                f = f[1:]
            return kwfilelog(self.wrapsopener, kwt, f)

        def wrapsopener(self, *args):
            return super(kwrepo, self).sopener(*args)

I know, naïve, sopener comes from store and it's used as an
attribute. And of course the line that sort of triggered my
confusion:

            repo.commitctx = self.kwcommitctx

I don't see how I could do this with super.

Still puzzled

c


More information about the Mercurial-devel mailing list