From 8430529e1a9fb28d8586d24ee507a8195c370fa5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 8 Oct 2009 14:34:29 +0200 Subject: Renamed lazy.py to base.py to have a file for base classes - lazy not yet changed to allow proper rename tracking --- lib/git/base.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 lib/git/base.py (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py new file mode 100644 index 00000000..5e470181 --- /dev/null +++ b/lib/git/base.py @@ -0,0 +1,32 @@ +# lazy.py +# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors +# +# This module is part of GitPython and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php + +class LazyMixin(object): + lazy_properties = [] + + def __init__(self): + self.__baked__ = False + + def __getattribute__(self, attr): + val = object.__getattribute__(self, attr) + if val is not None: + return val + else: + self.__prebake__() + return object.__getattribute__(self, attr) + + def __bake__(self): + """ This method should be overridden in the derived class. """ + raise NotImplementedError(" '__bake__' method has not been implemented.") + + def __prebake__(self): + if self.__baked__: + return + self.__bake__() + self.__baked__ = True + + def __bake_it__(self): + self.__baked__ = True -- cgit v1.2.1 From 9ee31065abea645cbc2cf3e54b691d5983a228b2 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 11:01:12 +0200 Subject: Intermediate commit: commit,tree and blob objects now derive from object - test is in place which still fails on purpose. Need to integrate tags which can be objects or just a special form of a ref --- lib/git/base.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 5e470181..687fb50a 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -1,4 +1,4 @@ -# lazy.py +# base.py # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors # # This module is part of GitPython and is released under @@ -30,3 +30,70 @@ class LazyMixin(object): def __bake_it__(self): self.__baked__ = True + + +class Object(LazyMixin): + """ + Implements an Object which may be Blobs, Trees, Commits and Tags + """ + TYPES = ("blob", "tree", "commit", "tag") + __slots__ = ("repo", "id", "size") + type = None # to be set by subclass + + def __init__(self, repo, id, size=None): + """ + Initialize an object by identifying it by its id. All keyword arguments + will be set on demand if None. + + ``repo`` + repository this object is located in + ``id`` + SHA1 or ref suitable for git-rev-parse + ``size`` + Size of the object's data in bytes + """ + super(Object,self).__init__() + self.repo = repo + self.id = id + self.size = size + + def __bake__(self): + """ + Retrieve object information + """ + self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) + + def __eq__(self, other): + """ + Returns + True if the objects have the same SHA1 + """ + return self.id == other.id + + def __ne__(self, other): + """ + Returns + True if the objects do not have the same SHA1 + """ + return self.id != other.id + + def __hash__(self): + """ + Returns + Hash of our id allowing objects to be used in dicts and sets + """ + return hash(self.id) + + def __str__(self): + """ + Returns + string of our SHA1 as understood by all git commands + """ + return self.id + + def __repr__(self): + """ + Returns + string with pythonic representation of our object + """ + return '' % (self.__class__.__name__, self.id) -- cgit v1.2.1 From 20f202d83bdf1f332a3cb8f010bcf8bf3c2807bd Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 16:36:51 +0200 Subject: Re-designed the tag testing - it does not use fixtures anymore but dyamically checks the existance of tags within the repository - it basically tests the interface and checks that expected return types are actually returned --- lib/git/base.py | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 3 deletions(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 687fb50a..84dd0754 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -3,10 +3,13 @@ # # 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__ = "__baked__" + def __init__(self): self.__baked__ = False @@ -38,7 +41,7 @@ class Object(LazyMixin): """ TYPES = ("blob", "tree", "commit", "tag") __slots__ = ("repo", "id", "size") - type = None # to be set by subclass + type = None # to be set by subclass def __init__(self, repo, id, size=None): """ @@ -46,9 +49,11 @@ class Object(LazyMixin): will be set on demand if None. ``repo`` - repository this object is located in + repository this object is located in + ``id`` SHA1 or ref suitable for git-rev-parse + ``size`` Size of the object's data in bytes """ @@ -97,3 +102,153 @@ class Object(LazyMixin): string with pythonic representation of our object """ return '' % (self.__class__.__name__, self.id) + + @classmethod + def get_type_by_name(cls, object_type_name): + """ + Returns + type suitable to handle the given object type name. + Use the type to create new instances. + + ``object_type_name`` + Member of TYPES + + Raises + ValueError: In case object_type_name is unknown + """ + if object_type_name == "commit": + import commit + return commit.Commit + elif object_type_name == "tag": + import tag + return tag.TagObject + elif object_type_name == "blob": + import blob + return blob.Blob + elif object_type_name == "tree": + import tree + return tree.Tree + else: + raise ValueError("Cannot handle unknown object type: %s" % object_type_name) + + +class Ref(object): + """ + Represents a named reference to any object + """ + __slots__ = ("path", "object") + + def __init__(self, path, object = None): + """ + Initialize this instance + + ``path`` + Path relative to the .git/ directory pointing to the ref in question, i.e. + refs/heads/master + + ``object`` + Object instance, will be retrieved on demand if None + """ + self.path = path + self.object = object + + def __str__(self): + return self.name() + + def __repr__(self): + return '' % (self.__class__.__name__, self.path) + + def __eq__(self, other): + return self.path == other.path and self.object == other.object + + def __ne__(self, other): + return not ( self == other ) + + def __hash__(self): + return hash(self.path) + + @property + def name(self): + """ + Returns + Name of this reference + """ + return os.path.basename(self.path) + + @classmethod + def find_all(cls, repo, common_path = "refs", **kwargs): + """ + Find all refs in the repository + + ``repo`` + is the Repo + + ``common_path`` + Optional keyword argument to the path which is to be shared by all + returned Ref objects + + ``kwargs`` + Additional options given as keyword arguments, will be passed + to git-for-each-ref + + Returns + git.Ref[] + + List is sorted by committerdate + The returned objects are compatible to the Ref base, but represent the + actual type, such as Head or Tag + """ + + options = {'sort': "committerdate", + 'format': "%(refname)%00%(objectname)%00%(objecttype)%00%(objectsize)"} + + options.update(kwargs) + + output = repo.git.for_each_ref(common_path, **options) + return cls.list_from_string(repo, output) + + @classmethod + def list_from_string(cls, repo, text): + """ + Parse out ref information into a list of Ref compatible objects + + ``repo`` + is the Repo + ``text`` + is the text output from the git-for-each-ref command + + Returns + git.Ref[] + + list of Ref objects + """ + heads = [] + + for line in text.splitlines(): + heads.append(cls.from_string(repo, line)) + + return heads + + @classmethod + def from_string(cls, repo, line): + """ + Create a new Ref instance from the given string. + + ``repo`` + is the Repo + + ``line`` + is the formatted ref information + + Format:: + + name: [a-zA-Z_/]+ + + id: [0-9A-Fa-f]{40} + + Returns + git.Head + """ + full_path, hexsha, type_name, object_size = line.split("\x00") + obj = Object.get_type_by_name(type_name)(repo, hexsha, object_size) + return cls(full_path, obj) -- cgit v1.2.1 From 9374a916588d9fe7169937ba262c86ad710cfa74 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 16:49:05 +0200 Subject: converted all spaces to tabs ( 4 spaces = 1 tab ) just to allow me and my editor to work with the files properly. Can convert it back for releaes --- lib/git/base.py | 488 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 244 insertions(+), 244 deletions(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 84dd0754..1f8e085d 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -6,249 +6,249 @@ import os class LazyMixin(object): - lazy_properties = [] - - __slots__ = "__baked__" - - def __init__(self): - self.__baked__ = False - - def __getattribute__(self, attr): - val = object.__getattribute__(self, attr) - if val is not None: - return val - else: - self.__prebake__() - return object.__getattribute__(self, attr) - - def __bake__(self): - """ This method should be overridden in the derived class. """ - raise NotImplementedError(" '__bake__' method has not been implemented.") - - def __prebake__(self): - if self.__baked__: - return - self.__bake__() - self.__baked__ = True - - def __bake_it__(self): - self.__baked__ = True - - + lazy_properties = [] + + __slots__ = "__baked__" + + def __init__(self): + self.__baked__ = False + + def __getattribute__(self, attr): + val = object.__getattribute__(self, attr) + if val is not None: + return val + else: + self.__prebake__() + return object.__getattribute__(self, attr) + + def __bake__(self): + """ This method should be overridden in the derived class. """ + raise NotImplementedError(" '__bake__' method has not been implemented.") + + def __prebake__(self): + if self.__baked__: + return + self.__bake__() + self.__baked__ = True + + def __bake_it__(self): + self.__baked__ = True + + class Object(LazyMixin): - """ - Implements an Object which may be Blobs, Trees, Commits and Tags - """ - TYPES = ("blob", "tree", "commit", "tag") - __slots__ = ("repo", "id", "size") - type = None # to be set by subclass - - def __init__(self, repo, id, size=None): - """ - Initialize an object by identifying it by its id. All keyword arguments - will be set on demand if None. - - ``repo`` - repository this object is located in - - ``id`` - SHA1 or ref suitable for git-rev-parse - - ``size`` - Size of the object's data in bytes - """ - super(Object,self).__init__() - self.repo = repo - self.id = id - self.size = size - - def __bake__(self): - """ - Retrieve object information - """ - self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) - - def __eq__(self, other): - """ - Returns - True if the objects have the same SHA1 - """ - return self.id == other.id - - def __ne__(self, other): - """ - Returns - True if the objects do not have the same SHA1 - """ - return self.id != other.id - - def __hash__(self): - """ - Returns - Hash of our id allowing objects to be used in dicts and sets - """ - return hash(self.id) - - def __str__(self): - """ - Returns - string of our SHA1 as understood by all git commands - """ - return self.id - - def __repr__(self): - """ - Returns - string with pythonic representation of our object - """ - return '' % (self.__class__.__name__, self.id) - - @classmethod - def get_type_by_name(cls, object_type_name): - """ - Returns - type suitable to handle the given object type name. - Use the type to create new instances. - - ``object_type_name`` - Member of TYPES - - Raises - ValueError: In case object_type_name is unknown - """ - if object_type_name == "commit": - import commit - return commit.Commit - elif object_type_name == "tag": - import tag - return tag.TagObject - elif object_type_name == "blob": - import blob - return blob.Blob - elif object_type_name == "tree": - import tree - return tree.Tree - else: - raise ValueError("Cannot handle unknown object type: %s" % object_type_name) - - + """ + Implements an Object which may be Blobs, Trees, Commits and Tags + """ + TYPES = ("blob", "tree", "commit", "tag") + __slots__ = ("repo", "id", "size") + type = None # to be set by subclass + + def __init__(self, repo, id, size=None): + """ + Initialize an object by identifying it by its id. All keyword arguments + will be set on demand if None. + + ``repo`` + repository this object is located in + + ``id`` + SHA1 or ref suitable for git-rev-parse + + ``size`` + Size of the object's data in bytes + """ + super(Object,self).__init__() + self.repo = repo + self.id = id + self.size = size + + def __bake__(self): + """ + Retrieve object information + """ + self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) + + def __eq__(self, other): + """ + Returns + True if the objects have the same SHA1 + """ + return self.id == other.id + + def __ne__(self, other): + """ + Returns + True if the objects do not have the same SHA1 + """ + return self.id != other.id + + def __hash__(self): + """ + Returns + Hash of our id allowing objects to be used in dicts and sets + """ + return hash(self.id) + + def __str__(self): + """ + Returns + string of our SHA1 as understood by all git commands + """ + return self.id + + def __repr__(self): + """ + Returns + string with pythonic representation of our object + """ + return '' % (self.__class__.__name__, self.id) + + @classmethod + def get_type_by_name(cls, object_type_name): + """ + Returns + type suitable to handle the given object type name. + Use the type to create new instances. + + ``object_type_name`` + Member of TYPES + + Raises + ValueError: In case object_type_name is unknown + """ + if object_type_name == "commit": + import commit + return commit.Commit + elif object_type_name == "tag": + import tag + return tag.TagObject + elif object_type_name == "blob": + import blob + return blob.Blob + elif object_type_name == "tree": + import tree + return tree.Tree + else: + raise ValueError("Cannot handle unknown object type: %s" % object_type_name) + + class Ref(object): - """ - Represents a named reference to any object - """ - __slots__ = ("path", "object") - - def __init__(self, path, object = None): - """ - Initialize this instance - - ``path`` - Path relative to the .git/ directory pointing to the ref in question, i.e. - refs/heads/master - - ``object`` - Object instance, will be retrieved on demand if None - """ - self.path = path - self.object = object - - def __str__(self): - return self.name() - - def __repr__(self): - return '' % (self.__class__.__name__, self.path) - - def __eq__(self, other): - return self.path == other.path and self.object == other.object - - def __ne__(self, other): - return not ( self == other ) - - def __hash__(self): - return hash(self.path) - - @property - def name(self): - """ - Returns - Name of this reference - """ - return os.path.basename(self.path) - - @classmethod - def find_all(cls, repo, common_path = "refs", **kwargs): - """ - Find all refs in the repository - - ``repo`` - is the Repo - - ``common_path`` - Optional keyword argument to the path which is to be shared by all - returned Ref objects - - ``kwargs`` - Additional options given as keyword arguments, will be passed - to git-for-each-ref - - Returns - git.Ref[] - - List is sorted by committerdate - The returned objects are compatible to the Ref base, but represent the - actual type, such as Head or Tag - """ - - options = {'sort': "committerdate", - 'format': "%(refname)%00%(objectname)%00%(objecttype)%00%(objectsize)"} - - options.update(kwargs) - - output = repo.git.for_each_ref(common_path, **options) - return cls.list_from_string(repo, output) - - @classmethod - def list_from_string(cls, repo, text): - """ - Parse out ref information into a list of Ref compatible objects - - ``repo`` - is the Repo - ``text`` - is the text output from the git-for-each-ref command - - Returns - git.Ref[] - - list of Ref objects - """ - heads = [] - - for line in text.splitlines(): - heads.append(cls.from_string(repo, line)) - - return heads - - @classmethod - def from_string(cls, repo, line): - """ - Create a new Ref instance from the given string. - - ``repo`` - is the Repo - - ``line`` - is the formatted ref information - - Format:: - - name: [a-zA-Z_/]+ - - id: [0-9A-Fa-f]{40} - - Returns - git.Head - """ - full_path, hexsha, type_name, object_size = line.split("\x00") - obj = Object.get_type_by_name(type_name)(repo, hexsha, object_size) - return cls(full_path, obj) + """ + Represents a named reference to any object + """ + __slots__ = ("path", "object") + + def __init__(self, path, object = None): + """ + Initialize this instance + + ``path`` + Path relative to the .git/ directory pointing to the ref in question, i.e. + refs/heads/master + + ``object`` + Object instance, will be retrieved on demand if None + """ + self.path = path + self.object = object + + def __str__(self): + return self.name() + + def __repr__(self): + return '' % (self.__class__.__name__, self.path) + + def __eq__(self, other): + return self.path == other.path and self.object == other.object + + def __ne__(self, other): + return not ( self == other ) + + def __hash__(self): + return hash(self.path) + + @property + def name(self): + """ + Returns + Name of this reference + """ + return os.path.basename(self.path) + + @classmethod + def find_all(cls, repo, common_path = "refs", **kwargs): + """ + Find all refs in the repository + + ``repo`` + is the Repo + + ``common_path`` + Optional keyword argument to the path which is to be shared by all + returned Ref objects + + ``kwargs`` + Additional options given as keyword arguments, will be passed + to git-for-each-ref + + Returns + git.Ref[] + + List is sorted by committerdate + The returned objects are compatible to the Ref base, but represent the + actual type, such as Head or Tag + """ + + options = {'sort': "committerdate", + 'format': "%(refname)%00%(objectname)%00%(objecttype)%00%(objectsize)"} + + options.update(kwargs) + + output = repo.git.for_each_ref(common_path, **options) + return cls.list_from_string(repo, output) + + @classmethod + def list_from_string(cls, repo, text): + """ + Parse out ref information into a list of Ref compatible objects + + ``repo`` + is the Repo + ``text`` + is the text output from the git-for-each-ref command + + Returns + git.Ref[] + + list of Ref objects + """ + heads = [] + + for line in text.splitlines(): + heads.append(cls.from_string(repo, line)) + + return heads + + @classmethod + def from_string(cls, repo, line): + """ + Create a new Ref instance from the given string. + + ``repo`` + is the Repo + + ``line`` + is the formatted ref information + + Format:: + + name: [a-zA-Z_/]+ + + id: [0-9A-Fa-f]{40} + + Returns + git.Head + """ + full_path, hexsha, type_name, object_size = line.split("\x00") + obj = Object.get_type_by_name(type_name)(repo, hexsha, object_size) + return cls(full_path, obj) -- cgit v1.2.1 From 7a7eedde7f5d5082f7f207ef76acccd24a6113b1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 18:06:18 +0200 Subject: put Tree and Blob onto a new base class suitable to deal with IndexObjects --- lib/git/base.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 1f8e085d..22c73491 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -40,7 +40,7 @@ class Object(LazyMixin): Implements an Object which may be Blobs, Trees, Commits and Tags """ TYPES = ("blob", "tree", "commit", "tag") - __slots__ = ("repo", "id", "size") + __slots__ = ("repo", "id", "size", "_data_cached" ) type = None # to be set by subclass def __init__(self, repo, id, size=None): @@ -61,6 +61,7 @@ class Object(LazyMixin): self.repo = repo self.id = id self.size = size + self._data_cached = type(None) def __bake__(self): """ @@ -103,6 +104,20 @@ class Object(LazyMixin): """ return '' % (self.__class__.__name__, self.id) + @property + def data(self): + """ + The binary contents of this object. + + Returns + str + + NOTE + The data will be cached after the first access. + """ + self._data_cached = ( self._data_cached is not type(None) and self._data_cached ) or self.repo.git.cat_file(self.id, p=True, with_raw_output=True) + return self._data_cached + @classmethod def get_type_by_name(cls, object_type_name): """ @@ -132,6 +147,45 @@ class Object(LazyMixin): raise ValueError("Cannot handle unknown object type: %s" % object_type_name) +class IndexObject(Object): + """ + Base for all objects that can be part of the index file , namely Tree, Blob and + SubModule objects + """ + __slots__ = ("path", "mode") + + def __init__(self, repo, id, mode=None, path=None, size = None): + """ + Initialize a newly instanced IndexObject + ``repo`` + is the Repo we are located in + + ``id`` : string + is the git object id as hex sha + + ``mode`` : int + is the file mode as int, use the stat module to evaluate the infomration + + ``path`` : str + is the path to the file in the file system, relative to the git repository root, i.e. + file.ext or folder/other.ext + + ``size`` : int + size of the object data in bytes + """ + super(IndexObject, self).__init__(repo, id, size) + self.mode = mode + self.path = path + + @property + def basename(self): + """ + Returns + The basename of the IndexObject's file path + """ + return os.path.basename(self.path) + + class Ref(object): """ Represents a named reference to any object -- cgit v1.2.1 From 15b9129ec639112e94ea96b6a395ad9b149515d1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 19:07:03 +0200 Subject: lazymixin system now supports per-attribute baking, it is up to the class whether it bakes more. This also leads to more efficient use of memory as values are only cached and set when required - the baking system does not require an own tracking variable anymore, and values are only to be cached once - then python will natively find the cache without involving any additional overhead. This works by using __getattr__ instead of __get_attribute__ which would always be called --- lib/git/base.py | 96 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 49 deletions(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 22c73491..f3510558 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -7,43 +7,38 @@ import os class LazyMixin(object): lazy_properties = [] + __slots__ = tuple() - __slots__ = "__baked__" - - def __init__(self): - self.__baked__ = False - - def __getattribute__(self, attr): - val = object.__getattribute__(self, attr) - if val is not None: - return val - else: - self.__prebake__() - return object.__getattribute__(self, attr) - - def __bake__(self): - """ This method should be overridden in the derived class. """ - raise NotImplementedError(" '__bake__' method has not been implemented.") - - def __prebake__(self): - if self.__baked__: - return - self.__bake__() - self.__baked__ = True + 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 __bake_it__(self): - self.__baked__ = True + 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 + class Object(LazyMixin): """ Implements an Object which may be Blobs, Trees, Commits and Tags """ TYPES = ("blob", "tree", "commit", "tag") - __slots__ = ("repo", "id", "size", "_data_cached" ) + __slots__ = ("repo", "id", "size", "data" ) type = None # to be set by subclass - def __init__(self, repo, id, size=None): + def __init__(self, repo, id): """ Initialize an object by identifying it by its id. All keyword arguments will be set on demand if None. @@ -53,21 +48,32 @@ class Object(LazyMixin): ``id`` SHA1 or ref suitable for git-rev-parse - - ``size`` - Size of the object's data in bytes """ super(Object,self).__init__() self.repo = repo self.id = id - self.size = size - self._data_cached = type(None) - def __bake__(self): + def _set_self_from_args_(self, args_dict): + """ + Initialize attributes on self from the given dict that was retrieved + from locals() in the calling method. + + Will only set an attribute on self if the corresponding value in args_dict + is not None + """ + for attr, val in args_dict.items(): + if attr != "self" and val is not None: + setattr( self, attr, val ) + # END set all non-None attributes + + def _set_cache_(self, attr): """ Retrieve object information """ - self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) + if attr == "size": + self.size = int(self.repo.git.cat_file(self.id, s=True).rstrip()) + elif attr == "data": + self.data = self.repo.git.cat_file(self.id, p=True, with_raw_output=True) def __eq__(self, other): """ @@ -105,18 +111,12 @@ class Object(LazyMixin): return '' % (self.__class__.__name__, self.id) @property - def data(self): + def id_abbrev(self): """ - The binary contents of this object. - Returns - str - - NOTE - The data will be cached after the first access. + First 7 bytes of the commit's sha id as an abbreviation of the full string. """ - self._data_cached = ( self._data_cached is not type(None) and self._data_cached ) or self.repo.git.cat_file(self.id, p=True, with_raw_output=True) - return self._data_cached + return self.id[0:7] @classmethod def get_type_by_name(cls, object_type_name): @@ -154,7 +154,7 @@ class IndexObject(Object): """ __slots__ = ("path", "mode") - def __init__(self, repo, id, mode=None, path=None, size = None): + def __init__(self, repo, id, mode=None, path=None): """ Initialize a newly instanced IndexObject ``repo`` @@ -169,14 +169,11 @@ class IndexObject(Object): ``path`` : str is the path to the file in the file system, relative to the git repository root, i.e. file.ext or folder/other.ext - - ``size`` : int - size of the object data in bytes """ - super(IndexObject, self).__init__(repo, id, size) + super(IndexObject, self).__init__(repo, id) self.mode = mode self.path = path - + @property def basename(self): """ @@ -304,5 +301,6 @@ class Ref(object): git.Head """ full_path, hexsha, type_name, object_size = line.split("\x00") - obj = Object.get_type_by_name(type_name)(repo, hexsha, object_size) + obj = Object.get_type_by_name(type_name)(repo, hexsha) + obj.size = object_size return cls(full_path, obj) -- cgit v1.2.1 From 9a119924bd314934158515a1a5f5877be63f6f91 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 20:21:22 +0200 Subject: fixed issue in Ref.name implementation which would not handle components properly --- lib/git/base.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index f3510558..b7976dab 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -222,9 +222,15 @@ class Ref(object): def name(self): """ Returns - Name of this reference + (shortest) Name of this reference - it may contain path components """ - return os.path.basename(self.path) + # first two path tokens are can be removed as they are + # refs/heads or refs/tags or refs/remotes + tokens = self.path.split('/') + if len(tokens) < 3: + return self.path # could be refs/HEAD + + return '/'.join(tokens[2:]) @classmethod def find_all(cls, repo, common_path = "refs", **kwargs): -- cgit v1.2.1 From b01824b1aecf8aadae4501e22feb45c20fb26bce Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 22:22:28 +0200 Subject: Fixed remaining tests to deal with the changes mode is now generally an int compatible to the stat module --- lib/git/base.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index b7976dab..4e5298e4 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -171,9 +171,27 @@ class IndexObject(Object): file.ext or folder/other.ext """ super(IndexObject, self).__init__(repo, id) + if isinstance(mode, basestring): + mode = self._mode_str_to_int(mode) self.mode = mode self.path = path + @classmethod + def _mode_str_to_int( cls, modestr ): + """ + ``modestr`` + string like 755 or 644 or 100644 - only the last 3 chars will be used + + Returns + String identifying a mode compatible to the mode methods ids of the + stat module regarding the rwx permissions for user, group and other + """ + mode = 0 + for iteration,char in enumerate(reversed(modestr[-3:])): + mode += int(char) << iteration*3 + # END for each char + return mode + @property def basename(self): """ -- cgit v1.2.1 From c68459a17ff59043d29c90020fffe651b2164e6a Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 11 Oct 2009 22:50:07 +0200 Subject: Added remaining tests for new base classes and removed some methods whose existance was doubtful or unsafe --- lib/git/base.py | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'lib/git/base.py') diff --git a/lib/git/base.py b/lib/git/base.py index 4e5298e4..252ebe4b 100644 --- a/lib/git/base.py +++ b/lib/git/base.py @@ -110,14 +110,6 @@ class Object(LazyMixin): """ return '' % (self.__class__.__name__, self.id) - @property - def id_abbrev(self): - """ - Returns - First 7 bytes of the commit's sha id as an abbreviation of the full string. - """ - return self.id[0:7] - @classmethod def get_type_by_name(cls, object_type_name): """ @@ -169,12 +161,15 @@ class IndexObject(Object): ``path`` : str is the path to the file in the file system, relative to the git repository root, i.e. file.ext or folder/other.ext + + NOTE + Path may not be set of the index object has been created directly as it cannot + be retrieved without knowing the parent tree. """ super(IndexObject, self).__init__(repo, id) + self._set_self_from_args_(locals()) if isinstance(mode, basestring): - mode = self._mode_str_to_int(mode) - self.mode = mode - self.path = path + self.mode = self._mode_str_to_int(mode) @classmethod def _mode_str_to_int( cls, modestr ): @@ -191,14 +186,6 @@ class IndexObject(Object): mode += int(char) << iteration*3 # END for each char return mode - - @property - def basename(self): - """ - Returns - The basename of the IndexObject's file path - """ - return os.path.basename(self.path) class Ref(object): @@ -222,7 +209,7 @@ class Ref(object): self.object = object def __str__(self): - return self.name() + return self.name def __repr__(self): return '' % (self.__class__.__name__, self.path) -- cgit v1.2.1