
                  	          d Z ddlZddlmZ ddlmZ ddlZddlZddlZddl	m
Z
mZmZmZ ddlZddlZddlmZ ddlmZmZmZmZmZmZmZ ddlmZ d	Zd
ZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ* G d de      Z+d Z,d Z-d Z.d Z/d Z0d Z1d  Z2d!e3d"e3d#e4fd$Z5dHd%e6d&e
e6   fd'Z7d( Z8d) Z9d* Z:d+ Z;d, Z< G d- d.e=      Z> G d/ d0e=      Z? G d1 d2e?      Z@d3 ZA G d4 d5e?      ZB G d6 d7 ed7g d8            ZCdId9ZDd: ZEd; ZFd< ZGd= ZHdJd>ZI G d? d@e?      ZJdA ZKdIdBZLdC ZMdD ZN G dE dFe?      ZOeOeJe@eBfZPi ZQePD ]   ZReReQeRj                  <   eReQeRj                  <   " eDZUeFZV	 ddGlWmDZDmFZF y# eX$ r Y yw xY w)KzAccess to base git objects.    N)BytesIO)
namedtuple)OptionalDictUnionType)sha1)ChecksumMismatchNotBlobErrorNotCommitErrorNotTagErrorNotTreeErrorObjectFormatExceptionFileFormatException)GitFiles(   0000000000000000000000000000000000000000   trees   parents   authors	   committers   encodings   mergetags   gpgsigs   objects   type   tags   taggeri   l    s   -----BEGIN PGP SIGNATURE-----c                       e Zd ZdZy)EmptyFileExceptionz+An unexpectedly empty file was encountered.N)__name__
__module____qualname____doc__     "lib/third_party/dulwich/objects.pyr   r   N   s    5r   r   c                 :    t        j                  |       t        k(  S )zhCheck if a mode indicates a submodule.

    Args:
      m: Mode to check
    Returns: a ``boolean``
    )statS_IFMTS_IFGITLINK)ms    r   S_ISGITLINKr"   R   s     ;;q>[((r   c                 v    t        j                         }|j                  |       }||j                         z  }|S N)zlibdecompressobj
decompressflush)stringdcompdcompeds      r   _decompressr,   \   s5     Ev&Gu{{}GNr   c                 `    t        j                  |       }t        |      dk(  s
J d|z         |S )z4Takes a string and returns the hex of the sha within(   z#Incorrect length of sha1 string: %d)binasciihexlifylen)shahexshas     r   
sha_to_hexr4   c   s4    c"Fv;"LCfLLMr   c                     t        |       dk(  s
J d| z         	 t        j                  |       S # t        $ r.}t	        | t
              s t        |j                  d         d}~ww xY w)z(Takes a hex sha and returns a binary shar.   zIncorrect length of hexsha: %sr   N)r1   r/   	unhexlify	TypeError
isinstancebytes
ValueErrorargs)hexexcs     r   
hex_to_shar>   j   sc    s8r>A;cAA>&!!#&& &#u%!%%&s   / 	A&)A!!A&c                     t        |       dk7  ry	 t        j                  |        y# t        t        j                  f$ r Y yw xY w)Nr.   FT)r1   r/   r6   r7   Error)r<   s    r   valid_hexsharA   u   sE    
3x2~3  x~~& s   ' AAc                     t        | dd      |j                  d      }|dd }|dd }t        j                  j	                  | ||      S )zDTakes a hex sha and returns its filename relative to the given path.encodeNascii   )getattrdecodeospathjoin)rI   r<   dirfiles       r   hex_to_filenamerM      sN    
 tXt$0jj!
bq'Cqr7D77<<c4((r   c                 "   | j                  t        j                  j                  d      dd }d| z  }t	        |      dk(  sJ |       |\  }}t	        |      dk(  rt	        |      dk(  sJ |       ||z   j                  d      }t        |       |S )z?Takes an object filename and returns its corresponding hex sha.rE   NzInvalid object filename: %s&   rD   )rsplitrH   rI   sepr1   rC   r>   )filenamenameserrmsgbaserestr<   s         r   filename_to_hexrX      s     OOBGGKK+BC0E*X5Fu:?"F"?JD$t9>c$i2o5v5-$;

w
'CsOJr   num_typelengthreturnc                 n    t        |       j                  dz   t        |      j                  d      z   dz   S )zCReturn an object header for the given numeric type and text length.    rD       )object_class	type_namestrrC   )rY   rZ   s     r   object_headerrb      s2    !++d2S[5G5G5PPSXXXr   name	docstringc                 4      fd} fd}t        |||      S )zBA property that helps tracking whether serialization is necessary.c                 4    t        | dz   |       d| _        y )N_T)setattr_needs_serialization)objvaluerc   s     r   setz"serializable_property.<locals>.set   s    S4Z'#' r   c                 "    t        | dz         S )Nrg   )rF   )rj   rc   s    r   getz"serializable_property.<locals>.get   s    sC$J''r   doc)property)rc   rd   rl   rn   s   `   r   serializable_propertyrr      s    (( C),,r   c                 .    t         j                  | d      S )zGet the object class corresponding to the given type.

    Args:
      type: Either a type name string or a numeric type.
    Returns: The ShaFile subclass corresponding to the given type, or None if
        type is not a valid type name/number.
    N)	_TYPE_MAPrn   )types    r   r_   r_      s     ==t$$r   c                 :    t        |       st        |d|       y)zCheck if a string is a valid hex sha string.

    Args:
      hex: Hex string to check
      error_msg: Error message to use in exception
    Raises:
      ObjectFormatException: Raised when the string is not valid
     N)rA   r   )r<   	error_msgs     r   check_hexshary      s!     #y#$>?? r   c                     | j                  d      }| j                  d      }|dk  sK|dk  sF||k  sA| j                  d|dz         dk\  s)| j                  d|dz         dk\  s| j                  d      st        |      y)zCheck if the specified identity is valid.

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

    Args:
      identity: Identity string
      error_msg: Error message to use in exception
       <   >r      N)findendswithr   )identityrx   email_start	email_ends       r   check_identityr      s     --%Kd#Iaq=#=={Q/14==y1}-2  &#I.. 'r   c                 :    | t         kD  rt        dt         z        y)zCheck if the specified time is not prone to overflow error.

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

    Args:
      time_info: author/committer/tagger info

    zDate field should not exceed %sN)MAX_TIMEr   )time_secondss    r   
check_timer      s"     h#$E$PQQ r   c                  *    dj                  |       dz   S )z*Formats items into a space separated line.r]      
)rJ   )itemss    r   git_liner      s    99Ue##r   c                   &    e Zd ZdZdZd Zd Zd Zy)FixedShazBSHA object that behaves like hashlib's but is given a fixed value.)_hexsha_shac                     t        |dd       |j                  d      }t        |t              st	        d|z        || _        t        |      | _        y )NrC   rD   z!Expected bytes for hexsha, got %r)rF   rC   r8   r9   r7   r   r>   r   )selfr3   s     r   __init__zFixedSha.__init__   sM    68T*6]]7+F&%(?&HIIv&	r   c                     | j                   S )zReturn the raw SHA digest.)r   r   s    r   digestzFixedSha.digest   s    yyr   c                 8    | j                   j                  d      S )zReturn the hex SHA digest.rD   )r   rG   r   s    r   	hexdigestzFixedSha.hexdigest   s    ||""7++r   N)r   r   r   r   	__slots__r   r   r   r   r   r   r   r      s    L#I',r   r   c                      e Zd ZdZdZdZdZed        Zd Z	d*dZ
d*dZd Zd	 Zd
 Zd Zd Zd+dZd+dZed        Zd Zed        Zed        Zd Zd Zd Zed        Zed        Zed+d       Zed+d       Zed        Zd Z d Z!d Z"d Z#d Z$d  Z%e&d!        Z'd" Z(d# Z) e&e(e)      Z*d$ Z+d% Z,d& Z-d' Z.d( Z/d) Z0y),ShaFilezA git SHA file.)_chunked_textr   ri   Nc                    d}t        j                         }|j                  |       }d}d}|dk  rM|j                  |      }||j                  |      z  }| |z  } |j	                  d|      }t        |      }|dk  rM|d| }|j                  dd      \  }}		 t        |	       t        |      }|st        d	|z         |       S # t        $ r}
t        d|
z        d}
~
ww xY w)
z<Parse a legacy object, creating it but not reading the file.i   r   r^   Nr]   r}   zObject size not an integer: %sNot a known type: %s)r%   r&   r'   readr~   r1   splitintr:   r   r_   )magicfbufsizedecompheaderstartendextrar`   sizee	obj_classs               r   _parse_legacy_object_headerz#ShaFile._parse_legacy_object_header  s     ##%""5)AgFF7OEf''..FUNE++eU+CKE Ag  ,,tQ/	4	NI !+	'(>(JKK{  	N'(H1(LMM	Ns   C 	C"CC"c                     t        |      }|j                  d      }|dk  rt        d      | j                  ||dz   d        y)z.Parse a legacy object, setting the raw string.r^   r   zInvalid object header, no \0r}   N)r,   r~   r   set_raw_string)r   maptext
header_ends       r   _parse_legacy_objectzShaFile._parse_legacy_object$  sG    3YYu%
>'(GHHDa!123r   c              #      K   t        j                  |      }|j                  | j                                | j	                         D ]  }|j                  |        |j                          yw)zlReturn chunks representing the object in the experimental format.

        Returns: List of strings
        N)r%   compressobjcompress_headeras_raw_chunksr(   )r   compression_levelcompobjchunks       r   as_legacy_object_chunkszShaFile.as_legacy_object_chunks,  s`     
 ""#45t||~..'')E""5)) *mmos   A2A4c                 D    dj                  | j                  |            S )zAReturn string representing the object in the experimental format.r   )r   )rJ   r   )r   r   s     r   as_legacy_objectzShaFile.as_legacy_object7  s%    xx((;L(M
 	
r   c                 x    | j                   r#d| _        | j                         | _        d| _         | j                  S )zxReturn chunks with serialization of the object.

        Returns: List of strings, not necessarily one per line
        NF)ri   r   
_serializer   r   s    r   r   zShaFile.as_raw_chunks=  s7    
 $$DI!%!2D(-D%!!!r   c                 @    dj                  | j                               S )z\Return raw string with serialization of the object.

        Returns: String object
        r   )rJ   r   r   s    r   as_raw_stringzShaFile.as_raw_stringH  s    
 xx**,--r   c                 "    | j                         S )z/Return raw string serialization of this object.r   r   s    r   	__bytes__zShaFile.__bytes__O      !!##r   c                 ,    t        | j                        S )z#Return unique hash for this object.)hashidr   s    r   __hash__zShaFile.__hash__S  s    DGG}r   c                 "    | j                         S )z:Return a string representing this object, fit for display.r   r   s    r   as_pretty_stringzShaFile.as_pretty_stringW  r   r   c                 f    t        |t              st        d|z        | j                  |g|       y)z9Set the contents of this object from a serialized string.zExpected bytes for text, got %rN)r8   r9   r7   set_raw_chunks)r   r   r2   s      r   r   zShaFile.set_raw_string[  s/    $&=DEETFC(r   c                     || _         | j                  |       |d| _        d| _        yt        |      | _        d| _        y)z6Set the contents of this object from a list of chunks.NF)r   _deserializer   r   ri   )r   chunksr2   s      r   r   zShaFile.set_raw_chunksa  sC    #&!;DI %*! !DI$)!r   c                 n    t        | dd       dz	  dz  }t        |      }|st        d|z         |       S )z?Parse a new style object, creating it but not reading the file.r   r}         zNot a known type %d)ordr_   r   )r   r   rY   r   s       r   _parse_object_headerzShaFile._parse_object_headerk  sC     a
Oq(A- *	'(=(HII{r   c                     t        |dd       }d}|dz  dk7  rt        |||dz          }|dz  }|dz  dk7  r||d }| j                  t        |             y)z-Parse a new style object, setting self._text.r   r}      N)r   r   r,   )r   r   byteusedraws        r   _parse_objectzShaFile._parse_objectt  sp     3q8}d{q s4$(+,DAID d{q  $%jK,-r   c                 n    t        |dd       }t        |dd       }|dz  |z   }|dz  dk(  xr |dz  dk(  S )Nr   r}   rE            )r   )clsr   b0b1words        r   _is_legacy_objectzShaFile._is_legacy_object  sJ    q_q_a2~T	d"7r	a'77r   c                     |j                         }|st        d      | j                  |      r%| j                  ||      }|j	                  |       |S | j                  ||      }|j                  |       |S )NzCorrupted empty file detected)r   r   r   r   r   r   r   )r   r   r   rj   s       r   _parse_filezShaFile._parse_file  sx    ffh$%DEE  %11#q9C$$S) 
 **32Cc"
r   c                 .    d| _         g | _        d| _        y)zDon't call this directlyNT)r   r   ri   r   s    r   r   zShaFile.__init__  s    	$(!r   c                 ,    t        | j                        r$   )NotImplementedErrorr   r   r   s     r   r   zShaFile._deserialize  s    !$"3"344r   c                 ,    t        | j                        r$   )r   r   r   s    r   r   zShaFile._serialize  s    !$//22r   c                 h    t        |d      5 }| j                  |      cddd       S # 1 sw Y   yxY w)zOpen a SHA file from disk.rbN)r   	from_file)r   rI   r   s      r   	from_pathzShaFile.from_path  s(     T4 A==# !  s   (1c                 t    	 | j                  |      }d|_        |S # t        t        f$ r t	        d      w xY w)z'Get the contents of a SHA file on disk.Nzinvalid object header)r   r   
IndexErrorr:   r   )r   r   rj   s      r   r   zShaFile.from_file  sD    	A//!$CCHJJ' 	A'(?@@	As    7c                 J     t        |              }|j                  ||       |S )zCreates an object of the indicated type from the raw string given.

        Args:
          type_num: The numeric type of the object.
          string: The raw uncompressed contents.
          sha: Optional known sha for the object
        )r_   r   )type_numr)   r2   rj   s       r   from_raw_stringzShaFile.from_raw_string  (     %l8$&63'
r   c                 J     t        |              }|j                  ||       |S )zCreates an object of the indicated type from the raw chunks given.

        Args:
          type_num: The numeric type of the object.
          chunks: An iterable of the raw uncompressed contents.
          sha: Optional known sha for the object
        )r_   r   )r   r   r2   rj   s       r   from_raw_chunkszShaFile.from_raw_chunks  r   r   c                 6     |        }|j                  |       |S )zCreate a ShaFile from a string.r   )r   r)   rj   s      r   from_stringzShaFile.from_string  s     e6"
r   c                 4    t        | |d      t        |      y)a:  Check that the object has a given member variable.

        Args:
          member: the member variable to check for
          error_msg: the message for an error if the member is missing
        Raises:
          ObjectFormatException: with the given error_msg if member is
            missing or is None
        N)rF   r   )r   memberrx   s      r   _check_has_memberzShaFile._check_has_member  s#     4&.'	22 /r   c                     | j                   }	 | j                  | j                                d| _        | j                   }||k7  rt        ||      y# t        $ r}t        |      d}~ww xY w)zCheck this object for internal consistency.

        Raises:
          ObjectFormatException: if the object is malformed in some way
          ChecksumMismatch: if the object was created with a SHA that does
            not match its contents
        N)r   r   r   r   	Exceptionr   r
   )r   old_shanew_shar   s       r   checkzShaFile.check  sr     ''	+d0023DIggG g"7G44   	+'**	+s   2A 	A+A&&A+c                 J    t        | j                  | j                               S r$   )rb   ru   
raw_lengthr   s    r   r   zShaFile._header  s    TYY(9::r   c                 P    d}| j                         D ]  }|t        |      z  } |S )z4Returns the length of the raw string of this object.r   )r   r1   )r   retr   s      r   r  zShaFile.raw_length  s-    '')E3u:C *
r   c                     | j                   | j                  rVt               }|j                  | j	                                | j                         D ]  }|j                  |        || _         | j                   S )z0The SHA1 object that is the name of this object.)r   ri   r	   updater   r   )r   r  r   s      r   r2   zShaFile.sha  s]    99 9 9fGNN4<<>*++-u% .DIyyr   c                     t        | j                               }|j                  | j                         | j                         | j                        S )z9Create a new copy of this SHA1 object from its raw string)r_   get_typer   r   r   )r   r   s     r   copyzShaFile.copy
  s=     1	(($:L:L:NPTPWPWXXr   c                 \    | j                         j                         j                  d      S )zThe hex SHA of this object.rD   )r2   r   rC   r   s    r   r   z
ShaFile.id  s$     xxz##%,,W55r   c                     | j                   S )z-Return the type number for this object class.r   r   s    r   r  zShaFile.get_type      }}r   c                     || _         y)z*Set the type number for this object class.Nr  )r   ru   s     r   set_typezShaFile.set_type  s	    r   c                 P    d| j                   j                  d| j                  dS )N<rw   >)	__class__r   r   r   s    r   __repr__zShaFile.__repr__  s     NN33TWW==r   c                 Z    t        |t               xs | j                  |j                  k7  S )z3Check whether this object does not match the other.r8   r   r   r   others     r   __ne__zShaFile.__ne__"  s$    eW--DEHH1DDr   c                 X    t        |t              xr | j                  |j                  k(  S )z1Return True if the SHAs of the two objects match.r  r  s     r   __eq__zShaFile.__eq__&  s!    %)Adgg.AAr   c                 `    t        |t              st        | j                  |j                  k  S )z9Return whether SHA of this object is less than the other.r8   r   r7   r   r  s     r   __lt__zShaFile.__lt__*  s$    %)Oww!!r   c                 `    t        |t              st        | j                  |j                  k  S )zDCheck whether SHA of this object is less than or equal to the other.r   r  s     r   __le__zShaFile.__le__0  s$    %)Oww%((""r   c                 n    t        |t              st        t        | j                  |j                        S )z=Compare the SHA of this object with that of the other object.)r8   r   r7   cmpr   r  s     r   __cmp__zShaFile.__cmp__6  s&    %)O477EHH%%r   )r   r$   )1r   r   r   r   r   r`   r   staticmethodr   r   r   r   r   r   r   r   r   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   r  r   r  r2   r  rq   r   r  r  ru   r  r  r  r!  r#  r&  r   r   r   r   r     sy   AIIH 04	
	".$$)*  
. 8 8  )53 $ $
 A A 
 
 
 
  35,;	Y
 6 6
 Hh'D>EB"#&r   r   c                        e Zd ZdZdZdZdZ fdZd Zd Z	 e
ee	d	      Zd
 Zd Zd Zd Z e
eed	      Zed        Z fdZd Z xZS )BlobzA Git Blob object.r   s   blob   c                 F    t         t        |           g | _        d| _        y NF)superr*  r   r   ri   r   r  s    r   r   zBlob.__init__E  s     dD"$$)!r   c                 "    | j                         S r$   r   r   s    r   	_get_datazBlob._get_dataJ  s    !!##r   c                 &    | j                  |       y r$   r   )r   datas     r   	_set_datazBlob._set_dataM  s    D!r   z*The text contained within the blob object.ro   c                     | j                   S r$   r   r   s    r   _get_chunkedzBlob._get_chunkedT      !!!r   c                     || _         y r$   r6  r   s     r   _set_chunkedzBlob._set_chunkedW  
    #r   c                     | j                   S r$   r6  r   s    r   r   zBlob._serializeZ  r8  r   c                     || _         y r$   r6  r   s     r   r   zBlob._deserialize]  r;  r   z>The text in the blob object, as chunks (not necessarily lines)c                 ^    t         j                  |      }t        ||       st        |      |S r$   )r   r   r8   r   )r   rI   blobs      r   r   zBlob.from_pathf  s,      &$$t$$r   c                 *    t         t        |           y)Check this object for internal consistency.

        Raises:
          ObjectFormatException: if the object is malformed in some way
        N)r.  r*  r  r/  s    r   r  z
Blob.checkm  s     	dD!r   c                    | j                   }|sg S t        |      dk(  r|d   j                  d      S d}g }|D ]  }|j                  d      }t        |      dkD  r5|j                  |xs d|d   z          |j	                  |dd        |d   }Wt        |      dk(  sf||j                         }y||j                         z  } ||j                  |       |S )z^Return list of lines in this blob.

        This preserves the original line endings.
        r}   r   TNr   r   )chunkedr1   
splitlinesappendextendpop)r   r   	remainingr  r   liness         r   rD  zBlob.splitlinesu  s    
 Iv;!!9''--	E$$T*E5zA~

I,a89

52;'!"I	Uq$ %		I,I   JJy!
r   )r   r   r   r   r   r`   r   r   r1  r4  rq   r3  r7  r:  r   r   rC  r(  r   r  rD  __classcell__r  s   @r   r*  r*  =  s    IIH*
$" 9"ND"$"$ LG  "r   r*  c              #   \  K   t        dj                  |             }d}d}d}d }|D ]F  }|j                  d      r	||dd z  }|| ||      f |dk(  r n+|j                  dd      \  }}H d	}|| ||      f d
 |sd|j	                         f |j                          yw)aQ  Parse a message with a list of fields and a body.

    Args:
      chunks: the raw chunks of the tag or commit object.
    Returns: iterator of tuples of (field, value), one per header line, in the
        order read from the text, possibly including duplicates. Includes a
        field named None for the freeform tag/commit text.
    r   N Fc                 6    | r| j                  d      r| dd S | S )z!Strip the last newline from valuer   Nr   )r   )rk   s    r   _strip_last_newlinez+_parse_message.<locals>._strip_last_newline  s!    U^^E*":r   r]   r}   r   TNN)r   rJ   
startswithr   r   close)r   r   kveofrO  lines          r   _parse_messagerW    s      	 !AA
A
C ??4 abMA}-a011u}ZZa(FQ " =)!,-- QVVXGGIs   B*B,c                        e Zd ZdZdZdZdZ fdZed        Z	 fdZ
d Zd	 Zd
 Zd Z eee      Z edd      Z edd      Z edd      Z edd      Z edd      Z edd      Z xZS )TagzA Git Tag object.r   r   )	_tag_timezone_neg_utc_name_object_sha_object_class	_tag_time_tag_timezone_tagger_message
_signaturec                 p    t         t        |           d | _        d | _        d | _        d| _        d | _        y r-  )r.  rY  r   r`  r^  r_  rZ  rb  r/  s    r   r   zTag.__init__  s5    c4!#!%*"r   c                 ^    t         j                  |      }t        ||       st        |      |S r$   )r   r   r8   r   )r   rS   tags      r   r   zTag.from_path  s,    )#s#h''
r   c                    t         t        |           | j                  dd       | j                  dd       | j                  dd       | j                  st        d      t        | j                  d       t        | d	d
      rt        | j                  d       | j                  dd       t        | j                         d
}t        | j                        D ]t  \  }}|t        k(  r|t        d      |t         k(  r|t        k7  rt        d      |t"        k(  r|t         k7  rt        d      |t$        k(  r|t"        k7  rt        d      |}v y
)rA  r\  zmissing object shar]  zmissing object typer[  zmissing tag namezempty tag namezinvalid object shar`  Nzinvalid taggerr^  zmissing tag timezunexpected objectzunexpected typezunexpected tag namezunexpected tagger)r.  rY  r  r   r[  r   ry   r\  rF   r   r`  r   r^  rW  r   _OBJECT_HEADER_TYPE_HEADER_TAG_HEADER_TAGGER_HEADER)r   lastfieldrg   r  s       r   r  z	Tag.check  s.    	c4 }.BC0EFw(:;zz'(899T%%';<4D)4<<)9:{,>?4>>"&t'9'9:HE1&4+;+,?@@,&4>+A+,=>>+%$,*>+,ABB.(T[-@+,?@@D ;r   c                 ,   g }|j                  t        t        | j                               |j                  t        t        | j
                  j                               |j                  t        t        | j                               | j                  r| j                  *|j                  t        t        | j                               nk|j                  t        t        | j                  t        | j                        j                  d      t        | j                  | j                                      | j"                  ,|j                  d       |j                  | j"                         | j$                  |j                  | j$                         |S )NrD   r   )rE  r   rg  r\  rh  r]  r`   ri  r[  r`  r^  rj  ra   rC   format_timezoner_  rZ  ra  rb  r   s     r   r   zTag._serialize
  s   h~t/?/?@Ah|T-?-?-I-IJKh{DJJ78<<~~%h~t||DE&DNN+227;'(:(:D<V<VW	 ==$MM% MM$--(??&MM$//*r   c                 .   d| _         d| _        d| _        d| _        t	        |      D ]  \  }}|t
        k(  r|| _        |t        k(  r#t        |      }|st        d|z        || _
        C|t        k(  r|| _        T|t        k(  r't        |      \  | _         | _        \  | _        | _        |<|d| _        d| _        	 |j#                  t$              }|d| | _        ||d | _        t        d|z         y# t&        $ r || _        d| _        Y w xY w)z%Grab the metadata attached to the tagNFr   zUnknown field %s)r`  r^  r_  rZ  rW  rg  r\  rh  r_   r   r]  ri  r[  rj  parse_time_entryra  rb  indexBEGIN_PGP_SIGNATUREr:   )r   r   rl  rk   r   sig_idxs         r   r   zTag._deserialize"  s&   !%*"*62LE5&#( ,&(/	 /0F0NOO%."+%"
.(
 %U+	LNDT')C=$(DM&*DO:"'++.A"B
 ).hw*//+,>,FGG= 3. & /(-*./s    C::DDc                 2    | j                   | j                  fS )z_Get the object pointed to by this tag.

        Returns: tuple of (object class, sha).
        )r]  r\  r   s    r   _get_objectzTag._get_objectH  s    
 ""D$4$455r   c                 0    |\  | _         | _        d| _        y NT)r]  r\  ri   r   rk   s     r   _set_objectzTag._set_objectO  s    16.	T-$(!r   rc   zThe name of this tagtaggerz3Returns the name of the person who created this tagtag_timezLThe creation timestamp of the tag.  As the number of seconds since the epochtag_timezonez!The timezone that tag_time is in.messagez the message attached to this tag	signaturezOptional detached GPG signature)r   r   r   r   r`   r   r   r   r(  r   r  r   r   ru  ry  rq   objectrr   rc   rz  r{  r|  r}  r~  rJ  rK  s   @r   rY  rY    s    IH
I   D0$HL6) k;/F )?@D"GF %	H
 );L $I/QRG%k3TUIr   rY  c                       e Zd ZdZd Zy)	TreeEntryz.Named tuple encapsulating a single tree entry.c                     t        | j                  t              st        d|z        t	        t        j                  || j                        | j                  | j                        S )z:Return a copy of this entry with the given path prepended.zExpected bytes for path, got %r)	r8   rI   r9   r7   r  	posixpathrJ   moder2   )r   rI   s     r   in_pathzTreeEntry.in_pathi  sG    $))U+=DEEdii8$))TXXNNr   N)r   r   r   r   r  r   r   r   r  r  f  s    8Or   r  )rI   r  r2   c              #     K   d}t        |       }||k  r| j                  d|      }| || }|r|j                  d      rt        d|z        	 t	        |d      }| j                  d|      }| |dz   | }|dz   }| |dz   | }	t        |	      d	k7  rt        d
      t        |	      }
|||
f ||k  ryy# t
        $ r t        d|z        w xY ww)zParse a tree text.

    Args:
      text: Serialized text to parse
    Returns: iterator of tuples of (name, mode, sha)
    Raises:
      ObjectFormatException: if the object was malformed in some way
    r   r]      0zInvalid mode '%s'r   r^   r}         zSha has invalid lengthN)r1   rq  rQ  r   r   r:   r4   )r   strictcountrZ   mode_end	mode_textr  name_endrc   r2   r3   s              r   
parse_treer  p  s      EYF
&.::dE*x(	i**40'(;i(GHH	Iy!$D ::eX.HqL8,28a<%(s8r>'(@AACT6""! &.  	I'(;i(GHH	Is%   ACB4 AC2C4CCc              #   x   K   | D ]1  \  }}}d|z  j                  d      dz   |z   dz   t        |      z    3 yw)zSerialize the items in a tree to a text.

    Args:
      items: Sorted iterable over (name, mode, sha) tuples
    Returns: Serialized tree text as chunks
    z%04orD   r]   r^   N)rC   r>   )r   rc   r  r3   s       r   serialize_treer    sI      $dFd]""7+d2T9EAJvDVV	
 $s   8:c              #      K   |xr t         xs t        }t        | j                         |      D ]B  \  }}|\  }}t	        |      }t        |t              st        d|z        t        |||       D yw)aX  Iterate over a tree entries dictionary.

    Args:
      name_order: If True, iterate entries in order of their name. If
        False, iterate entries in tree order, that is, treat subtree entries as
        having '/' appended.
      entries: Dictionary mapping names to (mode, sha) tuples
    Returns: Iterator over (name, mode, hexsha)
    )keyzExpected bytes for SHA, got %rN)	key_entry_name_order	key_entrysortedr   r   r8   r9   r7   r  )entries
name_orderkey_funcrc   entryr  r3   s          r   sorted_tree_itemsr    so      22?iHgmmo8<ef4y&%(<vEFFdF++ =s   A4A6c                 J    | \  }}t        j                  |d         r|dz  }|S )zJSort key for tree entry.

    Args:
      entry: (name, value) tuplee
    r      /)r   S_ISDIR)r  rc   rk   s      r   r  r    s+     MT5||E!HKr   c                     | d   S )z&Sort key for tree entry in name order.r   r   )r  s    r   r  r    s    8Or   c                     |t         j                  z  rd}nd}d|||j                  d      | j                  |d      fz  S )zPretty format tree entry.

    Args:
      name: Name of the directory entry
      mode: Mode of entry
      hexsha: Hexsha of the referenced object
    Returns: string describing the tree entry
    treer?  z%04o %s %s	%s
rD   replace)r   S_IFDIRrG   )rc   r  r3   encodingkinds        r   pretty_format_tree_entryr    sL     dllgHi(	!  r   c                        e Zd ZdZdZdZdZ fdZed        Z	d Z
d Zd	 Zd
 Zd Zd Zd ZddZd Zd Z fdZd Zd Zd Z xZS )TreezA Git tree objectr   rE   _entriesc                 8    t         t        |           i | _        y r$   )r.  r  r   r  r/  s    r   r   zTree.__init__  s    dD"$r   c                 ^    t         j                  |      }t        ||       st        |      |S r$   )r   r   r8   r   )r   rS   r  s      r   r   zTree.from_path  s,      *$$x((r   c                     || j                   v S r$   r  r   rc   s     r   __contains__zTree.__contains__  s    t}}$$r   c                      | j                   |   S r$   r  r  s     r   __getitem__zTree.__getitem__  s    }}T""r   c                 >    |\  }}||f| j                   |<   d| _        y)a  Set a tree entry by name.

        Args:
          name: The name of the entry, as a string.
          value: A tuple of (mode, hexsha), where mode is the mode of the
            entry as an integral type and hexsha is the hex SHA of the entry as
            a string.
        TNr  ri   )r   rc   rk   r  r3   s        r   __setitem__zTree.__setitem__  s'     f#Vnd$(!r   c                 ,    | j                   |= d| _        y rw  r  r  s     r   __delitem__zTree.__delitem__  s    MM$$(!r   c                 ,    t        | j                        S r$   )r1   r  r   s    r   __len__zTree.__len__  s    4==!!r   c                 ,    t        | j                        S r$   )iterr  r   s    r   __iter__zTree.__iter__  s    DMM""r   c                     t        |t              r0t        |t              r ||}}t        j                  dt
        d       ||f| j                  |<   d| _        y)a*  Add an entry to the tree.

        Args:
          mode: The mode of the entry as an integral type. Not all
            possible modes are supported by git; see check() for details.
          name: The name of the entry, as a string.
          hexsha: The hex SHA of the entry as a string.
        z'Please use Tree.add(name, mode, hexsha)rE   )category
stacklevelTN)r8   r   r9   warningswarnDeprecationWarningr  ri   )r   rc   r  r3   s       r   addzTree.add  sQ     dC Ze%< $4TMM9+
 #Fld$(!r   c                 .    t        | j                  |      S )zIterate over entries.

        Args:
          name_order: If True, iterate in name order instead of tree
            order.
        Returns: Iterator over (name, mode, sha) tuples
        )r  r  )r   r  s     r   	iteritemszTree.iteritems  s     !
;;r   c                 4    t        | j                               S )zeReturn the sorted entries in this tree.

        Returns: List with (name, mode, sha) tuples
        )listr  r   s    r   r   z
Tree.items"  s    
 DNN$%%r   c           
          	 t        dj                  |            }t	        |D cg c]  \  }}}|||ff c}}}      | _        y# t        $ r}t        |      d}~ww xY wc c}}}w )zGrab the entries in the treer   N)r  rJ   r:   r   dictr  )r   r   parsed_entriesr   nr!   ss          r   r   zTree._deserialize)  sg    	+'(89N HgaAq1a&kHI  	+'**	+
 Is   A A#	A AA c                 R   t         t        |           d}t        j                  dz  t        j                  dz  t        j
                  t        j                  t        t        j                  dz  f}t        dj                  | j                        d      D ]  \  }}}t        |d|z         d|v s|d	v rt        d
|j                  dd      z        ||vrt        d|z        |||ff}|r8t        |      t        |      kD  rt        d      ||d   k(  rt        d|z        |} y)rA  Ni  i  i  r   Tzinvalid sha %sr  )r      .s   ..s   .gitzinvalid name %sutf-8r  zinvalid mode %06ozentries not sortedr   zduplicate entry %s)r.  r  r  r   S_IFREGS_IFLNKr  r    r  rJ   r   ry   r   rG   r  )r   rk  allowed_modesrc   r  r2   r  r  s          r   r  z
Tree.check4  s%    	dD!LL5 LL5 LLLLLL5 
  *#((43E3E*FMOD$.45t|t'BB+%GY(GG  =(+,?$,FGGD#;'ET?Yu%55/0DEE47?/0Dt0KLLD!  Nr   c                 F    t        t        | j                                     S r$   )r  r  r  r   s    r   r   zTree._serializeW  s    N4>>#3455r   c                     g }| j                         D ]"  \  }}}|j                  t        |||             $ dj                  |      S )NrM  )r  rE  r  rJ   )r   r   rc   r  r3   s        r   r   zTree.as_pretty_stringZ  sC    "&.."2D$KK0tVDE #3wwt}r   c                     |j                  d      }| j                  }d}|D ]0  }|s ||      }t        |t              st	        |      ||   \  }}2 ||fS )zLook up an object in a Git tree.

        Args:
          lookup_obj: Callback for retrieving object by SHA1
          path: Path to lookup
        Returns: A tuple of (mode, SHA) of the resulting path.
        r  N)r   r   r8   r  r   )r   
lookup_objrI   partsr2   r  prj   s           r   lookup_pathzTree.lookup_path`  sg     

4 ggAS/Cc4("3''AID#  Syr   F)r   r   r   r   r`   r   r   r   r(  r   r  r  r  r  r  r  r  r  r   r   r  r   r   r  rJ  rK  s   @r   r  r    sv    IHI  %#))"#)&<&	J!F6r   r  c                     | d   dvrt        dt               z        | dd }t        | dd       }|dk(  r| }|dk\  xr |dk(  }|dk  xr dxs d}t        |      }t        |dz        }|dz  }||d	z  |d
z  z   z  |fS )a  Parse a timezone text fragment (e.g. '+0100').

    Args:
      text: Text to parse.
    Returns: Tuple with timezone as seconds difference to UTC
        and a boolean indicating whether this was a UTC timezone
        prefixed with a negative sign (-0000).
    r   s   +-z*Timezone must start with + or - (%(text)s)Nr}      -r   d     <   )r:   varsr   abs)r   signoffsetunnecessary_negative_timezonesignumhoursminutess          r   parse_timezoner  u  s     7eENOO8Dab]Ft|$*aK$@DDL!qj b%AF[FEslG%$,2-.% r   c                     | dz  dk7  rt        d      | dk  s|rd}|  } nd}d|| dz  | dz  dz  fz  j                  d      S )	a  Format a timezone for Git serialization.

    Args:
      offset: Timezone offset as seconds difference to UTC
      unnecessary_negative_timezone: Whether to use a minus sign for
        UTC or positive timezones (-0000 and --700 rather than +0000 / +0700).
    r  r   z#Unable to handle non-minute offset.-+z
%c%02d%02dr  rD   )r:   rC   )r  r  r  s      r   rn  rn    sa     {a>??z2D&4-&2+1CDDLLWUUr   c                    	 | j                  d      }	 | d|dz    }| |dz   d }|j                  dd      \  }}t        |      }t	        |      \  }}||||ffS # t        $ r | ddfcY S w xY w# t        $ r}	t        |	      d}	~	ww xY w)a   Parse time entry behavior

    Args:
      value: Bytes representing a git commit/tag line
    Raises:
      ObjectFormatException in case of parsing error (malformed
      field date)
    Returns: Tuple of (author, time, (timezone, timezone_neg_utc))
    s   > Nr-  r   r}   rE   r]   )rindexr:   rQ   r   r  r   )
rk   rR   personrW   timetexttimezonetexttimetimezonetimezone_neg_utcr   s
             r   rp  rp    s    ,ll5!'q37#S1WY!%T1!5,8}%3L%A"" 4($4555  ,t]++,  '#A&&'s(   A >A- A*)A*-	B6BBc           	         g }g }d}d}d}d}g }d}d}	t        |       D ]  \  }
}|
t        k(  r|}|
t        k(  r|j                  |       -|
t        k(  rt        |      }B|
t        k(  rt        |      }W|
t        k(  r|}c|
t        k(  r(|j                  t        j                  |dz                |
t        k(  r|}	|
|}|j                  |
|f        |||||||	||f	S )zParse a commit object from chunks.

    Args:
      chunks: Chunks to parse
    Returns: Tuple of (tree, parents, author_info, commit_info,
        encoding, mergetag, gpgsig, message, extra)
    N)NNrP  r   )rW  _TREE_HEADER_PARENT_HEADERrE  _AUTHOR_HEADERrp  _COMMITTER_HEADER_ENCODING_HEADER_MERGETAG_HEADERrY  r   _GPGSIG_HEADER)r   parentsr   r  author_infocommit_infor  mergetagr}  gpgsigrl  rk   s               r   parse_commitr     s    GED,K,KHHGF&v.uL Dn$NN5!n$*51K''*51K&&H&&OOCOOEEM:;n$F]GLL%(' /* 	
 
r   c                   V    e Zd ZdZdZdZdZ fdZed        Z	d Z
 fdZd	 Z ed
d      Zd Zd Z eeed      Zd Z eed      Z edd      Z edd      Z edd      Z edd      Z edd      Z edd      Z edd      Z ed d!      Z ed"d#      Z ed$d%      Z xZS )&CommitzA git commit objects   commitr}   )_parents	_encoding_extra_author_timezone_neg_utc_commit_timezone_neg_utc_commit_time_author_time_author_timezone_commit_timezone_author
_committer_treera  	_mergetag_gpgsigc                     t         t        |           g | _        d | _        g | _        d | _        g | _        d| _        d| _	        y r-  )
r.  r  r   r  r  r  r  r  r  r  r/  s    r   r   zCommit.__init__  sC    fd$&(-%(-%r   c                 ^    t         j                  |      }t        ||       st        |      |S r$   )r   r   r8   r   )r   rI   commits      r   r   zCommit.from_path  s,    ""4(&#& &&r   c           
          t        |      \	  | _        | _        }}| _        | _        | _        | _        | _        |\  | _        | _	        \  | _
        | _        |\  | _        | _        \  | _        | _        y r$   )r   r  r  r  r  r  ra  r  r  r	  r
  r  r  r  r  r  )r   r   r  r  s       r   r   zCommit._deserialize  s~      
	
JMNNLMK 		
LBT"D$A 		
OBT"D$Ar   c                 Z   t         t        |           | j                  dd       | j                  dd       | j                  dd       | j                  dd       | j                  d	d
       | j                  D ]  }t        |d        t        | j                  d       t        | j                  d       t        | j                  d       t        | j                         t        | j                         d}t        | j                        D ]  \  }}|t        k(  r|t!        d      |t"        k(  r|t"        t        fvrt!        d      |t$        k(  r|t        t"        fvrt!        d      |t&        k(  r|t$        k7  rt!        d      |t(        k(  r|t&        k7  rt!        d      |} y)rA  r  zmissing treer  zmissing authorr  zmissing committerr	  zmissing author timer  zmissing commit timezinvalid parent shazinvalid tree shazinvalid authorzinvalid committerNzunexpected treezunexpected parentzunexpected authorzunexpected committerzunexpected encoding)r.  r  r  r   r  ry   r  r   r  r  r   r	  r  rW  r   r  r   r  r  r  r  )r   parentrk  rl  rg   r  s        r   r  zCommit.check0  s    	fd!#w7y*:;|-@A~/DE~/DEmmF!56 $TZZ!34t||%56t(;<4$$%4$$%&t'9'9:HE1$)9+,=>>.(T: . ,,?@@.(T: . ,,?@@++0F+,BCC**t7H/H+,ABBD# ;r   c                     g }t        | j                  t              r| j                  j                  n| j                  }|j	                  t        t        |             | j                  D ]!  }|j	                  t        t        |             # |j	                  t        t        | j                  t        | j                        j                  d      t        | j                  | j                                      |j	                  t        t"        | j$                  t        | j&                        j                  d      t        | j(                  | j*                                     | j,                  r)|j	                  t        t.        | j,                               | j0                  D ]  }|j3                         j5                  d      }|j	                  t        t6        |d                |dd  D ]  }|j	                  d|z   dz           |d   j9                  d      sz|d   d d |d<    | j:                  D ]9  \  }}d|v sd|v rt=        d	|d
|      |j	                  t        ||             ; | j>                  rb| j>                  j5                  d      }	|j	                  t        t@        |	d                |	dd  D ]  }|j	                  t        d|              |j	                  d       |j	                  | jB                         |S )NrD   r   r   r}   r]   r   s    
rO   znewline in extra data: z -> r   )"r8   r  r  r   rE  r   r  r  r  r  r  ra   r	  rC   rn  r
  r  r  r  r  r  r  r  r  r  r   r   r  r   r   AssertionErrorr  r  ra  )
r   r   
tree_bytesr  r  mergetag_chunksr   rS  rT  
sig_chunkss
             r   r   zCommit._serialize]  s`   &0T&BTZZ]]


h|Z89AMM(>156 D%%&--g6 5 5t7T7TU		
 	!D%%&--g6 5 5t7T7TU		
 ==MM(#3T]]CDH&446<<UCOMM(#3_Q5GHI(,dUlU23 - bz""6*#BZ_r
 & JJDAqzUaZ$!Q%OPPMM(1a.)  ;;**51JMM(>:a=AB#ABhsE23 (edmm$r   r  z%Tree that is the state of this commitc                     | j                   S )z(Return a list of parents of this commit.)r  r   s    r   _get_parentszCommit._get_parents  r  r   c                      d| _         || _        y)z%Set a list of parents of this commit.TN)ri   r  rx  s     r   _set_parentszCommit._set_parents  s    $(!r   z&Parents of this commit, by their SHA1.ro   c                     | j                   S )z%Return extra settings of this commit.)r  r   s    r   
_get_extrazCommit._get_extra  s    {{r   zExtra header fields not understood (presumably added in a newer version of git). Kept verbatim so the object can be correctly reserialized. For private commit metadata, use pseudo-headers in Commit.message, rather than this field.authorz$The name of the author of the commit	committerz'The name of the committer of the commitr}  zThe commit messagecommit_timezFThe timestamp of the commit. As the number of seconds since the epoch.commit_timezonezThe zone the commit time is inauthor_timezOThe timestamp the commit was written. As the number of seconds since the epoch.author_timezonez'Returns the zone the author time is in.r  zEncoding of the commit message.r  zAssociated signed tag.r  zGPG Signature.) r   r   r   r   r`   r   r   r   r(  r   r   r  r   rr   r  r  r  rq   r  r!  r   r"  r#  r}  r$  r%  r&  r'  r  r  r  rJ  rK  s   @r   r  r    s(   IHI$.  .)Z.` !)PQD
 4G DE #8-STF%>I $I/CDG'SK
 ,;O (	#K ,DO %Z1RSH$Z1IJH"8-=>Fr   r  )r  r  r$   r  )r  )Yr   r/   ior   collectionsr   rH   r  r   typingr   r   r   r   r  r%   hashlibr	   dulwich.errorsr
   r   r   r   r   r   r   dulwich.filer   ZERO_SHAr  r  r  r  r  r  r  rg  rh  ri  rj  r    r   rr  r   r"   r,   r4   r>   rA   rM   rX   r   r9   rb   ra   rr   r_   ry   r   r   r   r  r   r   r*  rW  rY  r  r  r  r  r  r  r  r  r  rn  rp  r   r  OBJECT_CLASSESrt   r   r`   r   _parse_tree_py_sorted_tree_items_pydulwich._objectsImportErrorr   r   r   <module>r4     s3  , "   " 	         !         6 6, 6)&
)
YC Y Y Y

- 
- 
-%
@/,R$
,v ,,w&f w&t	Q7 Qh3l\V' \V~O
;(?@ O#<

,(	
*]7 ]@:V$620fY?W Y?z 	 	C"Icmm!Icll  ) 	>> 		s    E) )E10E1