From 4c73e9cd66c77934f8a262b0c1bab9c2f15449ba Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 12 Oct 2009 17:03:01 +0200 Subject: refs now take repo as first argument and derive from LazyMixin to allow them to dynamically retrieve their objects Improved way commits are returned by refs as they now use the path to be sure they always point to the ref even if it changes - previously it would use the sha intead so it would not update after being cached on the ref object --- lib/git/objects/base.py | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 43aa8dd1..5007f3a1 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -4,30 +4,7 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php import os - -class LazyMixin(object): - lazy_properties = [] - __slots__ = tuple() - - def __getattr__(self, attr): - """ - Whenever an attribute is requested that we do not know, we allow it - to be created and set. Next time the same attribute is reqeusted, it is simply - returned from our dict/slots. - """ - self._set_cache_(attr) - # will raise in case the cache was not created - return object.__getattribute__(self, attr) - - def _set_cache_(self, attr): - """ This method should be overridden in the derived class. - It should check whether the attribute named by attr can be created - and cached. Do nothing if you do not know the attribute or call your subclass - - The derived class may create as many additional attributes as it deems - necessary in case a git command returns more information than represented - in the single attribute.""" - pass +from git.utils import LazyMixin class Object(LazyMixin): -- cgit v1.2.1 From af9e37c5c8714136974124621d20c0436bb0735f Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 12 Oct 2009 17:40:13 +0200 Subject: IndexObjects are now checking their slots to raise a proper error message in case someone tries to access an unset path or mode - this information cannot be retrieved afterwards as IndexObject information is kept in the object that pointed at them. To find this information, one would have to search all objects which is not feasible --- lib/git/objects/base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 5007f3a1..d3e0d943 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -120,8 +120,15 @@ class IndexObject(Object): if isinstance(mode, basestring): self.mode = self._mode_str_to_int(mode) + def _set_cache_(self, attr): + if attr in self.__slots__: + # they cannot be retrieved lateron ( not without searching for them ) + raise AttributeError( "path and mode attributes must have been set during %s object creation" % type(self).__name__ ) + else: + super(IndexObject, self)._set_cache_(attr) + @classmethod - def _mode_str_to_int( cls, modestr ): + def _mode_str_to_int(cls, modestr): """ ``modestr`` string like 755 or 644 or 100644 - only the last 3 chars will be used -- cgit v1.2.1 From 6eeae8b24135b4de05f6d725b009c287577f053d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 14 Oct 2009 17:24:15 +0200 Subject: test: Added time-consuming test which could also be a benchmark in fact - currently it cause hundreds of command invocations which is slow Fixed issue with trees not properly initialized with their default mode _set_cache_: some objects checked whether the attribute was within their __slots__ although it should have been accessed through its class --- lib/git/objects/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index d3e0d943..9789d72a 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -121,7 +121,7 @@ class IndexObject(Object): self.mode = self._mode_str_to_int(mode) def _set_cache_(self, attr): - if attr in self.__slots__: + if attr in IndexObject.__slots__: # they cannot be retrieved lateron ( not without searching for them ) raise AttributeError( "path and mode attributes must have been set during %s object creation" % type(self).__name__ ) else: -- cgit v1.2.1 From 6745f4542cfb74bbf3b933dba7a59ef2f54a4380 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 14 Oct 2009 19:34:45 +0200 Subject: test_blob: removed many redundant tests that would fail now as the mock cannot handle the complexity of the command backend All objects but Tree now use the persistent command to read their object information - Trees get binary data and would need their own pretty-printing or they need to parse the data themselves which is my favorite --- lib/git/objects/base.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 9789d72a..7b693be9 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -48,9 +48,13 @@ class Object(LazyMixin): Retrieve object information """ if attr == "size": - self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) + typename, self.size = self.repo.git.get_object_header(self.id) + assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) elif attr == "data": - self.data = self.repo.git.cat_file(self.id, p=True, with_raw_output=True) + typename, self.size, self.data = self.repo.git.get_object_data(self.id) + assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) + else: + super(Object,self)._set_cache_(attr) def __eq__(self, other): """ -- cgit v1.2.1 From c5df44408218003eb49e3b8fc94329c5e8b46c7d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 14 Oct 2009 19:41:27 +0200 Subject: persistent command signature changed to also return the hexsha from a possible input ref - the objects pointed to by refs are now baked on demand - perhaps it should change to always be re-retrieved using a property as it is relatively fast - this way refs can always be cached --- lib/git/objects/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 7b693be9..6752a25e 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -48,10 +48,10 @@ class Object(LazyMixin): Retrieve object information """ if attr == "size": - typename, self.size = self.repo.git.get_object_header(self.id) + hexsha, typename, self.size = self.repo.git.get_object_header(self.id) assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) elif attr == "data": - typename, self.size, self.data = self.repo.git.get_object_data(self.id) + hexsha, typename, self.size, self.data = self.repo.git.get_object_data(self.id) assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) else: super(Object,self)._set_cache_(attr) -- cgit v1.2.1 From 2e6d110fbfa1f2e6a96bc8329e936d0cf1192844 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 14 Oct 2009 23:37:45 +0200 Subject: tree: now reads tress directly by parsing the binary data, allowing it to safe possibly hundreds of command calls --- lib/git/objects/base.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/git/objects/base.py') diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 6752a25e..07538ada 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -6,7 +6,8 @@ import os from git.utils import LazyMixin - +_assertion_msg_format = "Created object %r whose python type %r disagrees with the acutal git object type %r" + class Object(LazyMixin): """ Implements an Object which may be Blobs, Trees, Commits and Tags @@ -49,10 +50,10 @@ class Object(LazyMixin): """ if attr == "size": hexsha, typename, self.size = self.repo.git.get_object_header(self.id) - assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) + assert typename == self.type, _assertion_msg_format % (self.id, typename, self.type) elif attr == "data": hexsha, typename, self.size, self.data = self.repo.git.get_object_data(self.id) - assert typename == self.type, "Created object whose python type %r disagrees with the acutal git object type %r" % (typename, self.type) + assert typename == self.type, _assertion_msg_format % (self.id, typename, self.type) else: super(Object,self)._set_cache_(attr) -- cgit v1.2.1