Beispiel #1
0
 def _parse_legacy_object(self, map):
     """Parse a legacy object, setting the raw string."""
     text = _decompress(map)
     header_end = text.find(b'\0')
     if header_end < 0:
         raise ObjectFormatException("Invalid object header, no \\0")
     self.set_raw_string(text[header_end + 1:])
Beispiel #2
0
 def _parse_object_header(magic, f):
     """Parse a new style object, creating it but not reading the file."""
     num_type = (ord(magic[0:1]) >> 4) & 7
     obj_class = object_class(num_type)
     if not obj_class:
         raise ObjectFormatException("Not a known type %d" % num_type)
     return obj_class()
Beispiel #3
0
 def from_file(cls, f):
     """Get the contents of a SHA file on disk."""
     try:
         obj = cls._parse_file(f)
         obj._sha = None
         return obj
     except (IndexError, ValueError):
         raise ObjectFormatException("invalid object header")
Beispiel #4
0
def check_hexsha(hex, error_msg):
    """Check if a string is a valid hex sha string.

    :param hex: Hex string to check
    :param error_msg: Error message to use in exception
    :raise ObjectFormatException: Raised when the string is not valid
    """
    if not valid_hexsha(hex):
        raise ObjectFormatException("%s %s" % (error_msg, hex))
Beispiel #5
0
 def _deserialize(self, chunks):
     """Grab the entries in the tree"""
     try:
         parsed_entries = parse_tree(b''.join(chunks))
     except ValueError as e:
         raise ObjectFormatException(e)
     # TODO: list comprehension is for efficiency in the common (small)
     # case; if memory efficiency in the large case is a concern, use a genexp.
     self._entries = dict([(n, (m, s)) for n, m, s in parsed_entries])
Beispiel #6
0
    def _check_has_member(self, member, error_msg):
        """Check that the object has a given member variable.

        :param member: the member variable to check for
        :param error_msg: the message for an error if the member is missing
        :raise ObjectFormatException: with the given error_msg if member is
            missing or is None
        """
        if getattr(self, member, None) is None:
            raise ObjectFormatException(error_msg)
Beispiel #7
0
    def check(self):
        """Check this object for internal consistency.

        Raises:
          ObjectFormatException: if the object is malformed in some way
        """
        super(Commit, self).check()
        self._check_has_member("_tree", "missing tree")
        self._check_has_member("_author", "missing author")
        self._check_has_member("_committer", "missing committer")
        self._check_has_member("_author_time", "missing author time")
        self._check_has_member("_commit_time", "missing commit time")

        for parent in self._parents:
            check_hexsha(parent, "invalid parent sha")
        check_hexsha(self._tree, "invalid tree sha")

        check_identity(self._author, "invalid author")
        check_identity(self._committer, "invalid committer")

        check_time(self._author_time)
        check_time(self._commit_time)

        last = None
        for field, _ in _parse_message(self._chunked_text):
            if field == _TREE_HEADER and last is not None:
                raise ObjectFormatException("unexpected tree")
            elif field == _PARENT_HEADER and last not in (
                    _PARENT_HEADER,
                    _TREE_HEADER,
            ):
                raise ObjectFormatException("unexpected parent")
            elif field == _AUTHOR_HEADER and last not in (
                    _TREE_HEADER,
                    _PARENT_HEADER,
            ):
                raise ObjectFormatException("unexpected author")
            elif field == _COMMITTER_HEADER and last != _AUTHOR_HEADER:
                raise ObjectFormatException("unexpected committer")
            elif field == _ENCODING_HEADER and last != _COMMITTER_HEADER:
                raise ObjectFormatException("unexpected encoding")
            last = field
Beispiel #8
0
def check_hexsha(hex, error_msg):
    """Check if a string is a valid hex sha string.

    :param hex: Hex string to check
    :param error_msg: Error message to use in exception
    :raise ObjectFormatException: Raised when the string is not valid
    """
    try:
        hex_to_sha(hex)
    except (TypeError, AssertionError, ValueError):
        raise ObjectFormatException("%s %s" % (error_msg, hex))
Beispiel #9
0
 def from_file(cls, f):
     """Get the contents of a SHA file on disk."""
     try:
         obj = cls._parse_file_header(f)
         obj._sha = None
         obj._needs_parsing = True
         obj._needs_serialization = True
         obj._file = f
         return obj
     except (IndexError, ValueError), e:
         raise ObjectFormatException("invalid object header")
Beispiel #10
0
def check_time(time_seconds):
    """Check if the specified time is not prone to overflow error.

    This will raise an exception if the time is not valid.

    :param time_info: author/committer/tagger info

    """
    # Prevent overflow error
    if time_seconds > MAX_TIME:
        raise ObjectFormatException(
            'Date field should not exceed %s' % MAX_TIME)
def check_time(time_seconds):
    """Check if the specified time is not prone to overflow error.

    This will raise an exception if the time is not valid.

    Args:
      time_seconds: time in seconds

    """
    # Prevent overflow error
    if time_seconds > MAX_TIME:
        raise ObjectFormatException("Date field should not exceed %s" % MAX_TIME)
Beispiel #12
0
 def _deserialize(self, chunks):
     """Grab the metadata attached to the tag"""
     self._tagger = None
     self._tag_time = None
     self._tag_timezone = None
     self._tag_timezone_neg_utc = False
     for field, value in _parse_message(chunks):
         if field == _OBJECT_HEADER:
             self._object_sha = value
         elif field == _TYPE_HEADER:
             obj_class = object_class(value)
             if not obj_class:
                 raise ObjectFormatException("Not a known type: %s" % value)
             self._object_class = obj_class
         elif field == _TAG_HEADER:
             self._name = value
         elif field == _TAGGER_HEADER:
             try:
                 sep = value.index(b'> ')
             except ValueError:
                 self._tagger = value
                 self._tag_time = None
                 self._tag_timezone = None
                 self._tag_timezone_neg_utc = False
             else:
                 self._tagger = value[0:sep + 1]
                 try:
                     (timetext,
                      timezonetext) = (value[sep + 2:].rsplit(b' ', 1))
                     self._tag_time = int(timetext)
                     self._tag_timezone, self._tag_timezone_neg_utc = (
                         parse_timezone(timezonetext))
                 except ValueError as e:
                     raise ObjectFormatException(e)
         elif field is None:
             self._message = value
         else:
             raise ObjectFormatException("Unknown field %s" % field)
Beispiel #13
0
 def _parse_legacy_object_header(magic, f):
     """Parse a legacy object, creating it but not reading the file."""
     bufsize = 1024
     decomp = zlib.decompressobj()
     header = decomp.decompress(magic)
     start = 0
     end = -1
     while end < 0:
         extra = f.read(bufsize)
         header += decomp.decompress(extra)
         magic += extra
         end = header.find(b'\0', start)
         start = len(header)
     header = header[:end]
     type_name, size = header.split(b' ', 1)
     try:
         int(size)  # sanity check
     except ValueError as e:
         raise ObjectFormatException("Object size not an integer: %s" % e)
     obj_class = object_class(type_name)
     if not obj_class:
         raise ObjectFormatException("Not a known type: %s" % type_name)
     return obj_class()
Beispiel #14
0
 def _deserialize(self, chunks):
     """Grab the metadata attached to the tag"""
     self._tagger = None
     self._tag_time = None
     self._tag_timezone = None
     self._tag_timezone_neg_utc = False
     for field, value in _parse_message(chunks):
         if field == _OBJECT_HEADER:
             self._object_sha = value
         elif field == _TYPE_HEADER:
             obj_class = object_class(value)
             if not obj_class:
                 raise ObjectFormatException("Not a known type: %s" % value)
             self._object_class = obj_class
         elif field == _TAG_HEADER:
             self._name = value
         elif field == _TAGGER_HEADER:
             (
                 self._tagger,
                 self._tag_time,
                 (self._tag_timezone, self._tag_timezone_neg_utc),
             ) = parse_time_entry(value)
         elif field is None:
             if value is None:
                 self._message = None
                 self._signature = None
             else:
                 try:
                     sig_idx = value.index(BEGIN_PGP_SIGNATURE)
                 except ValueError:
                     self._message = value
                     self._signature = None
                 else:
                     self._message = value[:sig_idx]
                     self._signature = value[sig_idx:]
         else:
             raise ObjectFormatException("Unknown field %s" % field)
Beispiel #15
0
def check_identity(identity, error_msg):
    """Check if the specified identity is valid.

    This will raise an exception if the identity is not valid.

    :param identity: Identity string
    :param error_msg: Error message to use in exception
    """
    email_start = identity.find("<")
    email_end = identity.find(">")
    if (email_start < 0 or email_end < 0 or email_end <= email_start
            or identity.find("<", email_start + 1) >= 0
            or identity.find(">", email_end + 1) >= 0
            or not identity.endswith(">")):
        raise ObjectFormatException(error_msg)
Beispiel #16
0
 def _deserialize(self, chunks):
     """Grab the metadata attached to the tag"""
     self._tagger = None
     self._tag_time = None
     self._tag_timezone = None
     self._tag_timezone_neg_utc = False
     for field, value in _parse_message(chunks):
         if field == _OBJECT_HEADER:
             self._object_sha = value
         elif field == _TYPE_HEADER:
             obj_class = object_class(value)
             if not obj_class:
                 raise ObjectFormatException("Not a known type: %s" % value)
             self._object_class = obj_class
         elif field == _TAG_HEADER:
             self._name = value
         elif field == _TAGGER_HEADER:
             (self._tagger, self._tag_time,
              (self._tag_timezone,
               self._tag_timezone_neg_utc)) = parse_time_entry(value)
         elif field is None:
             self._message = value
         else:
             raise ObjectFormatException("Unknown field %s" % field)
Beispiel #17
0
    def check(self):
        """Check this object for internal consistency.

        :raise ObjectFormatException: if the object is malformed in some way
        :raise ChecksumMismatch: if the object was created with a SHA that does
            not match its contents
        """
        # TODO: if we find that error-checking during object parsing is a
        # performance bottleneck, those checks should be moved to the class's
        # check() method during optimization so we can still check the object
        # when necessary.
        old_sha = self.id
        try:
            self._deserialize(self.as_raw_chunks())
            self._sha = None
            new_sha = self.id
        except Exception, e:
            raise ObjectFormatException(e)
Beispiel #18
0
def parse_time_entry(value):
    """Parse time entry behavior

    :param value: Bytes representing a git commit/tag line
    :raise: ObjectFormatException in case of parsing error (malformed
            field date)
    :return: Tuple of (author, time, (timezone, timezone_neg_utc))
    """
    try:
        sep = value.rindex(b'> ')
    except ValueError:
        return (value, None, (None, False))
    try:
        person = value[0:sep+1]
        rest = value[sep+2:]
        timetext, timezonetext = rest.rsplit(b' ', 1)
        time = int(timetext)
        timezone, timezone_neg_utc = parse_timezone(timezonetext)
    except ValueError as e:
        raise ObjectFormatException(e)
    return person, time, (timezone, timezone_neg_utc)
Beispiel #19
0
 def _parse_legacy_object_header(magic, f):
     """Parse a legacy object, creating it but not reading the file."""
     bufsize = 1024
     decomp = zlib.decompressobj()
     header = decomp.decompress(magic)
     start = 0
     end = -1
     while end < 0:
         extra = f.read(bufsize)
         header += decomp.decompress(extra)
         magic += extra
         end = header.find("\0", start)
         start = len(header)
     header = header[:end]
     type_name, size = header.split(" ", 1)
     size = int(size)  # sanity check
     obj_class = object_class(type_name)
     if not obj_class:
         raise ObjectFormatException("Not a known type: %s" % type_name)
     ret = obj_class()
     ret._magic = magic
     return ret
Beispiel #20
0
                    self._tag_timezone = None
                    self._tag_timezone_neg_utc = False
                else:
                    self._tagger = value[0:sep + 1]
                    try:
                        (timetext,
                         timezonetext) = value[sep + 2:].rsplit(" ", 1)
                        self._tag_time = int(timetext)
                        self._tag_timezone, self._tag_timezone_neg_utc = \
                                parse_timezone(timezonetext)
                    except ValueError, e:
                        raise ObjectFormatException(e)
            elif field is None:
                self._message = value
            else:
                raise ObjectFormatException("Unknown field %s" % field)

    def _get_object(self):
        """Get the object pointed to by this tag.

        :return: tuple of (object class, sha).
        """
        self._ensure_parsed()
        return (self._object_class, self._object_sha)

    def _set_object(self, value):
        self._ensure_parsed()
        (self._object_class, self._object_sha) = value
        self._needs_serialization = True

    object = property(_get_object, _set_object)
Beispiel #21
0
 def _deserialize(self, chunks):
     """Grab the entries in the tree"""
     try:
         parsed_entries = parse_tree("".join(chunks))
     except ValueError, e:
         raise ObjectFormatException(e)
Beispiel #22
0
def check_hexsha(hex, error_msg):
    try:
        hex_to_sha(hex)
    except (TypeError, AssertionError):
        raise ObjectFormatException("%s %s" % (error_msg, hex))