Exemple #1
0
 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