# base.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 import os from git.utils import LazyMixin import utils _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 This Object also serves as a constructor for instances of the correct type:: inst = Object(repo,id) """ TYPES = ("blob", "tree", "commit", "tag") __slots__ = ("repo", "id", "size", "data" ) type = None # to be set by subclass def __new__(cls, repo, id, *args, **kwargs): if cls is Object: hexsha, typename, size = repo.git.get_object_header(id) obj_type = utils.get_object_type_by_name(typename) inst = super(Object,cls).__new__(obj_type, repo, hexsha, *args, **kwargs) inst.size = size return inst else: return super(Object,cls).__new__(cls, repo, id, *args, **kwargs) def __init__(self, repo, id): """ 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 """ super(Object,self).__init__() self.repo = repo self.id = id 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 """ if attr == "size": hexsha, typename, self.size = self.repo.git.get_object_header(self.id) 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, _assertion_msg_format % (self.id, typename, self.type) else: super(Object,self)._set_cache_(attr) 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) 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): """ 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 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): self.mode = self._mode_str_to_int(mode) def _set_cache_(self, attr): 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: super(IndexObject, self)._set_cache_(attr) @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