def __init__(self, sha): """Constructor.""" GitObject.__init__(self, sha) self.parents = [] self.children = [] self.author = None self.date_authored = None self.committer = None self.date_committed = None self.message = None
def _get_git_object_contents(self, git_obj_sha): """ Return the decompressed contents of the git object with the given SHA-1, or None if the object is not found Git objects are stored either loose or packed. Loose objects are stored in the .git/objects/ directory. They are organized into subdirectories with names corresponding to the first two characters of the SHA-1 IDs of git objects contained within them. The objects are stored in zlib-compressed files with names corresponding to the last 38 characters of the SHA-1 IDs of the git objects they represent. Git can further compress loose git objects into packfiles when a repository grows too large, or garbage collection is run. There are two files we care about in the pack: the pack index and the pack file. See the `Git Community Book by Scott Chacon <http://schacon.github.io/gitbook/7_the_packfile.html>`_ or the `git documentation <http://repo.or.cz/w/git.git/blob_plain/HEAD:/Documentation/technical/pack-format.txt>`_ for detailed information on the data format of packfiles. :param git_obj_sha: The SHA-1 hash of the git object to be fetched """ git_obj_contents = None git_obj = GitObject(git_obj_sha) loose_obj_path = os.path.join(self.path, PATH_TO_GIT_OBJECTS, git_obj.get_subdirectory_name(), git_obj.get_file_name()) # Get the decompressed contents of the git object with the given SHA-1 if os.path.exists(loose_obj_path): # Object is loose, so just decompress it git_obj_file = open(os.path.join(self.path, PATH_TO_GIT_OBJECTS, git_obj.get_subdirectory_name(), git_obj.get_file_name()), "rb") git_obj_contents = git_obj_file.read() git_obj_contents = zlib.decompress(git_obj_contents).decode() git_obj_file.close() # Log the decompressed object app_logger.debug("Loose git object {0} contents:\n{1}" .format(git_obj_sha[:8], git_obj_contents)) elif os.path.exists(os.path.join(self.path, PATH_TO_PACKFILES)): # Check for the object in the pack file packfiles_path = os.path.join(self.path, PATH_TO_PACKFILES) packfile_name = glob.glob(packfiles_path + "*.pack")[0] packfile = open(packfile_name, "rb") # Get the packfile version number packfile.seek(4) packfile_version = int.from_bytes(packfile.read(4), byteorder="big") # Get the number of git objects in the packfile packfile_numobjects = int.from_bytes(packfile.read(4), byteorder="big") # Get the pack index file packindex_filename = glob.glob(packfiles_path + "*.idx")[0] packindex = open(packindex_filename, "rb") # Use the index fanout table to find the range within the sha/offset table to search lowerbound, upperbound = _get_fanout_range(git_obj_sha, packindex, packfile_version) # Find the offset of git object within the pack file, if it exists offset = _get_pack_offset_v2(git_obj_sha, packindex, lowerbound, upperbound, packfile_numobjects) if offset: # Git object found in pack index # Unpack the git object at the given offset git_obj_contents = self._unpack_git_object_v2(packfile, offset, git_obj_sha) app_logger.debug("Packed git object {0} contents:\n{1}" .format(git_obj_sha[:8], git_obj_contents)) else: # Git object not found in pack index app_logger.error("Git object {0} not found".format(git_obj_sha[:10])) # Close packfiles packfile.close() packindex.close() else: # Git object not found in git directory # Make a last ditch effort to find the object via command line git_terminal = GitTerminal(self.path) git_obj_contents = git_terminal.show_git_objects_contents(git_obj_sha) if git_obj_contents: # Log the decompressed object app_logger.debug("Loose git object {0} contents:\n{1}" .format(git_obj_sha[:8], git_obj_contents)) else: # Git object not found anywhere app_logger.error("Git object {0} not found".format(git_obj_sha[:10])) return git_obj_contents