diff options
Diffstat (limited to 'lib/git/objects/base.py')
-rw-r--r-- | lib/git/objects/base.py | 196 |
1 files changed, 68 insertions, 128 deletions
diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 90aa8ca2..118bc3ca 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -3,179 +3,140 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php -import os from git.utils import LazyMixin, join_path_native, stream_copy -import utils +from utils import get_object_type_by_name +from gitdb.util import ( + hex_to_bin, + bin_to_hex, + basename + ) + +import gitdb.typ as dbtyp _assertion_msg_format = "Created object %r whose python type %r disagrees with the acutal git object type %r" +__all__ = ("Object", "IndexObject") + class Object(LazyMixin): - """ - Implements an Object which may be Blobs, Trees, Commits and Tags - - This Object also serves as a constructor for instances of the correct type:: - - inst = Object.new(repo,id) - inst.sha # objects sha in hex - inst.size # objects uncompressed data size - inst.data # byte string containing the whole data of the object - """ + """Implements an Object which may be Blobs, Trees, Commits and Tags""" NULL_HEX_SHA = '0'*40 NULL_BIN_SHA = '\0'*20 - TYPES = ("blob", "tree", "commit", "tag") - __slots__ = ("repo", "sha", "size", "data" ) + + TYPES = (dbtyp.str_blob_type, dbtyp.str_tree_type, dbtyp.str_commit_type, dbtyp.str_tag_type) + __slots__ = ("repo", "binsha", "size" ) type = None # to be set by subclass - def __init__(self, repo, id): - """ - Initialize an object by identifying it by its id. All keyword arguments - will be set on demand if None. + def __init__(self, repo, binsha): + """Initialize an object by identifying it by its binary sha. + All keyword arguments will be set on demand if None. - ``repo`` - repository this object is located in + :param repo: repository this object is located in - ``id`` - SHA1 or ref suitable for git-rev-parse - """ + :param binsha: 20 byte SHA1""" super(Object,self).__init__() self.repo = repo - self.sha = id + self.binsha = binsha @classmethod def new(cls, repo, id): """ - Return - New Object instance of a type appropriate to the object type behind - id. The id of the newly created object will be a hexsha even though + :return: New Object instance of a type appropriate to the object type behind + id. The id of the newly created object will be a binsha even though the input id may have been a Reference or Rev-Spec - Note - This cannot be a __new__ method as it would always call __init__ - with the input id which is not necessarily a hexsha. - """ + :param id: reference, rev-spec, or hexsha + + :note: This cannot be a __new__ method as it would always call __init__ + with the input id which is not necessarily a binsha.""" hexsha, typename, size = repo.git.get_object_header(id) - obj_type = utils.get_object_type_by_name(typename) - inst = obj_type(repo, hexsha) + inst = get_object_type_by_name(typename)(repo, hex_to_bin(hexsha)) inst.size = size return inst def _set_self_from_args_(self, args_dict): - """ - Initialize attributes on self from the given dict that was retrieved + """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 - """ + 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 - """ + """Retrieve object information""" if attr == "size": - oinfo = self.repo.odb.info(self.sha) + oinfo = self.repo.odb.info(self.binsha) self.size = oinfo.size - assert oinfo.type == self.type, _assertion_msg_format % (self.sha, oinfo.type, self.type) - elif attr == "data": - ostream = self.repo.odb.stream(self.sha) - self.size = ostream.size - self.data = ostream.read() - assert ostream.type == self.type, _assertion_msg_format % (self.sha, ostream.type, self.type) + # assert oinfo.type == self.type, _assertion_msg_format % (self.binsha, oinfo.type, self.type) else: super(Object,self)._set_cache_(attr) def __eq__(self, other): - """ - Returns - True if the objects have the same SHA1 - """ - return self.sha == other.sha + """:return: True if the objects have the same SHA1""" + return self.binsha == other.binsha def __ne__(self, other): - """ - Returns - True if the objects do not have the same SHA1 - """ - return self.sha != other.sha + """:return: True if the objects do not have the same SHA1 """ + return self.binsha != other.binsha def __hash__(self): - """ - Returns - Hash of our id allowing objects to be used in dicts and sets - """ - return hash(self.sha) + """:return: Hash of our id allowing objects to be used in dicts and sets""" + return hash(self.binsha) def __str__(self): - """ - Returns - string of our SHA1 as understood by all git commands - """ - return self.sha + """:return: string of our SHA1 as understood by all git commands""" + return bin_to_hex(self.binsha) def __repr__(self): - """ - Returns - string with pythonic representation of our object - """ - return '<git.%s "%s">' % (self.__class__.__name__, self.sha) + """:return: string with pythonic representation of our object""" + return '<git.%s "%s">' % (self.__class__.__name__, self.hexsha) + + @property + def hexsha(self): + """:return: 40 byte hex version of our 20 byte binary sha""" + return bin_to_hex(self.binsha) @property def data_stream(self): """ :return: File Object compatible stream to the uncompressed raw data of the object :note: returned streams must be read in order""" - return self.repo.odb.stream(self.sha) + return self.repo.odb.stream(self.binsha) def stream_data(self, ostream): """Writes our data directly to the given output stream :param ostream: File object compatible stream object. :return: self""" - istream = self.repo.odb.stream(self.sha) + istream = self.repo.odb.stream(self.binsha) stream_copy(istream, ostream) return self class IndexObject(Object): - """ - Base for all objects that can be part of the index file , namely Tree, Blob and - SubModule objects - """ + """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, sha, mode=None, path=None): - """ - Initialize a newly instanced IndexObject - ``repo`` - is the Repo we are located in - - ``sha`` : 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 + def __init__(self, repo, binsha, mode=None, path=None): + """Initialize a newly instanced IndexObject + :param repo: is the Repo we are located in + :param binsha: 20 byte sha1 + :param mode: is the stat compatible file mode as int, use the stat module + to evaluate the infomration + :param path: 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 + :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, sha) + be retrieved without knowing the parent tree.""" + super(IndexObject, self).__init__(repo, binsha) self._set_self_from_args_(locals()) - if isinstance(mode, basestring): - self.mode = self._mode_str_to_int(mode) def __hash__(self): - """ - Returns + """:return: Hash of our path as index items are uniquely identifyable by path, not - by their data ! - """ + by their data !""" return hash(self.path) def _set_cache_(self, attr): @@ -184,41 +145,20 @@ class IndexObject(Object): raise AttributeError( "path and mode attributes must have been set during %s object creation" % type(self).__name__ ) else: super(IndexObject, self)._set_cache_(attr) + # END hanlde slot attribute - @classmethod - def _mode_str_to_int(cls, modestr): - """ - ``modestr`` - string like 755 or 644 or 100644 - only the last 6 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, - special flags and file system flags, i.e. whether it is a symlink - for example. - """ - mode = 0 - for iteration, char in enumerate(reversed(modestr[-6:])): - mode += int(char) << iteration*3 - # END for each char - return mode - @property def name(self): - """ - Returns - Name portion of the path, effectively being the basename - """ - return os.path.basename(self.path) + """:return: Name portion of the path, effectively being the basename""" + return basename(self.path) @property def abspath(self): """ - Returns + :return: Absolute path to this index object in the file system ( as opposed to the .path field which is a path relative to the git repository ). - The returned path will be native to the system and contains '\' on windows. - """ + The returned path will be native to the system and contains '\' on windows. """ return join_path_native(self.repo.working_tree_dir, self.path) |