o
    Uhܟ                     @   s  d Z ddlZddlZddlmZ ddlmZ ddlmZm	Z	 ddl
mZmZ ddlmZmZ dd	lmZmZmZmZmZ dd
lmZ eZdZdZdZdZdZedZ dZ!e!Z"G dd de#Z$dedefddZ%dede&fddZ'G dd dZ(G dd de(Z)G dd  d e(Z*G d!d" d"e(Z+d#d$ Z,d%d& Z-d'd( Z.dKdLd)d*Z/d+d, Z0d-efd.d/Z1d0d1 Z2d2d3 Z3d4d5 Z4dLd6d7Z5d8e(d9ed:e	e d;ed<e	e defd=d>Z6d?d@ Z7		A	AdMdBe(dCe8d8e9e8e8f dDe	e dEe&dFe&ddfdGdHZ:dIdJ Z;dS )NzRef handling.    N)Iterator)suppress)AnyOptional   )PackedRefsExceptionRefFormatError)GitFileensure_dir_exists)ZERO_SHAObjectIDTaggit_linevalid_hexsha)ObjectContainers   HEADs   ref: s   refs/heads/s
   refs/tags/   refs/remotes/s    ~^:?*[s   ^{}c                   @   s   e Zd ZdZdddZdS )
SymrefLoopz,There is a loop between one or more symrefs.returnNc                 C   s   || _ || _d S N)refdepth)selfr   r    r   `/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/refs.py__init__5   s   
zSymrefLoop.__init__r   N)__name__
__module____qualname____doc__r   r   r   r   r   r   2   s    r   contentsr   c                 C   s(   |  tr| ttd dS t| )z`Parse a symref value.

    Args:
      contents: Contents to parse
    Returns: Destination
    N   
)
startswithSYMREFlenrstrip
ValueError)r    r   r   r   parse_symref_value:   s   
r'   refnamec                 C   s   d| v s	|  drdS d| vrdS d| v rdS t| D ]\}}t| ||d  dk s/|tv r2 dS q| d dv r;dS | d	rBdS d
| v rHdS d| v rNdS dS )a+  Check if a refname is correctly formatted.

    Implements all the same rules as git-check-ref-format[1].

    [1]
    http://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html

    Args:
      refname: The refname to check
    Returns: True if refname is valid, False otherwise
    s   /.   .F   /s   ..r       s   .locks   @{   \T)r"   	enumerateordBAD_REF_CHARSendswith)r(   icr   r   r   check_ref_formatF   s&    
r4   c                   @   s  e Zd ZdZd=d>ddZ				d?	d>ddZ				d?	d>dd	Zdeee	f fd
dZ
deeee	 f ddfddZdee	 fddZ					d@dedeee	f dee dee dee dee deddfddZdee fddZdd Zd=dd Zd!d" Zd=deee	f fd#d$Zd>d%d&Zd'd( Zdefd)d*Zdeee ef fd+d,Zdefd-d.Zde	fd/d0Z				d?defd1d2Z	d?defd3d4Z d>d5d6Z!				d?defd7d8Z"d>d9d:Z#d;d< Z$dS )ARefsContainerzA container for refs.Nr   c                 C   s
   || _ d S r   _logger)r   loggerr   r   r   r   k      
zRefsContainer.__init__c              	   C   s4   | j d u rd S |d u rd S |  ||||||| d S r   r6   )r   r   old_shanew_sha	committer	timestamptimezonemessager   r   r   _logn   s
   

zRefsContainer._logc                 C   
   t | j)zMake a ref point at another ref.

        Args:
          name: Name of the ref to set
          other: Name of the ref to point at
          message: Optional message
        )NotImplementedErrorset_symbolic_ref)r   nameotherr<   r=   r>   r?   r   r   r   rC   ~   s   
zRefsContainer.set_symbolic_refc                 C   rA   )Get contents of the packed-refs file.

        Returns: Dictionary mapping ref names to SHA1s

        Note: Will return an empty dictionary when no packed-refs file is
            present.
        )rB   get_packed_refsr   r   r   r   rG         
zRefsContainer.get_packed_refsnew_refsc                 C   rA   )Add the given refs as packed refs.

        Args:
          new_refs: A mapping of ref names to targets; if a target is None that
            means remove the ref
        )rB   add_packed_refs)r   rJ   r   r   r   rL      s   
zRefsContainer.add_packed_refsc                 C   s   dS ae  Return the cached peeled value of a ref, if available.

        Args:
          name: Name of the ref to peel
        Returns: The peeled value of the ref. If the ref is known not point to
            a tag, this will be the SHA the ref refers to. If the ref may point
            to a tag, but no cached information is available, None is returned.
        Nr   r   rD   r   r   r   
get_peeled   s   	zRefsContainer.get_peeledFbaserE   r<   r=   r>   r?   prunec              	   C   s   |r
t | |}nt  }| D ]/\}	}
|
d u r||	 n| jd||	fd |
|d |r@z||	 W q ty?   Y qw q|D ]}| jd||fd |d qCd S )Nr*   r?   )	setsubkeysitemsaddset_if_equalsjoinremoveKeyErrorremove_if_equals)r   rP   rE   r<   r=   r>   r?   rQ   	to_deleterD   valuer   r   r   r   import_refs   s&   
zRefsContainer.import_refsc                 C   rA   )z#All refs present in this container.)rB   allkeysrH   r   r   r   r_      s   
zRefsContainer.allkeysc                 C   s   t |  S r   )iterr_   rH   r   r   r   __iter__      zRefsContainer.__iter__c                 C   s   |dur	|  |S |  S )zRefs present in this container.

        Args:
          base: An optional base to return refs under.
        Returns: An unsorted set of valid refs in this container, including
            packed refs.
        N)rT   r_   )r   rP   r   r   r   keys   s   
zRefsContainer.keysc                 C   s@   t  }t|d }|  D ]}||r|||d  q|S )zRefs present in this container under a base.

        Args:
          base: The base to return refs under.
        Returns: A set of valid refs in this container under the base; the base
            prefix is stripped from the ref names returned.
        r   N)rS   r$   r_   r"   rV   )r   rP   rc   base_lenr(   r   r   r   rT      s   
zRefsContainer.subkeysc              
   C   sh   i }|  |}|du rd}n|d}|D ]}z| |d | d ||< W q ttfy1   Y qw |S )z6Return the contents of this container as a dictionary.N    r*   )rc   r%   stripr   rZ   )r   rP   retrc   keyr   r   r   as_dict   s   

zRefsContainer.as_dictc                 C   s6   |t dfv rdS |drt|dd st|dS )a   Ensure a refname is valid and lives in refs or is HEAD.

        HEAD is not a valid refname according to git-check-ref-format, but this
        class needs to be able to touch HEAD. Also, check_ref_format expects
        refnames without the leading 'refs/', but this class requires that
        so it cannot touch anything outside the refs dir (or HEAD).

        Args:
          name: The name of the reference.

        Raises:
          KeyError: if a refname is not HEAD or is otherwise not valid.
        s
   refs/stashNs   refs/   )HEADREFr"   r4   r   rN   r   r   r   _check_refname   s
   zRefsContainer._check_refnamec                 C   s"   |  |}|s|  |d}|S )zRead a reference without following any references.

        Args:
          refname: The name of the reference
        Returns: The contents of the ref file, or None if it does
            not exist.
        N)read_loose_refrG   get)r   r(   r    r   r   r   read_ref  s   
zRefsContainer.read_refc                 C   rA   )zRead a loose reference and return its contents.

        Args:
          name: the refname to read
        Returns: The contents of the ref file, or None if it does
            not exist.
        )rB   rm   rN   r   r   r   rm     rI   zRefsContainer.read_loose_refc                 C   sx   t | }d}g }|t r8|tt d }|| | |}|s&	 ||fS |d7 }|dkr3t|||t s||fS )zFollow a reference name.

        Returns: a tuple of (refnames, sha), wheres refnames are the names of
            references in the chain
        r   Nr   rj   )r#   r"   r$   appendro   r   )r   rD   r    r   refnamesr(   r   r   r   follow(  s   




	zRefsContainer.followc                 C   s   |  |rdS dS )NTF)ro   )r   r(   r   r   r   __contains__<  s   
zRefsContainer.__contains__c                 C   s"   |  |\}}|du rt||S )zaGet the SHA1 for a reference name.

        This method follows all symbolic references.
        N)rr   rZ   )r   rD   _shar   r   r   __getitem__A  s   zRefsContainer.__getitem__c                 C   rA   )a'  Set a refname to new_ref only if it currently equals old_ref.

        This method follows all symbolic references if applicable for the
        subclass, and can be used to perform an atomic compare-and-swap
        operation.

        Args:
          name: The refname to set.
          old_ref: The old sha the refname must refer to, or None to set
            unconditionally.
          new_ref: The new sha the refname will refer to.
          message: Message for reflog
        Returns: True if the set was successful, False otherwise.
        )rB   rW   )r   rD   old_refnew_refr<   r=   r>   r?   r   r   r   rW   K  s   
zRefsContainer.set_if_equalsc                 C   rA   )zAdd a new reference only if it does not already exist.

        Args:
          name: Ref name
          ref: Ref value
        )rB   
add_if_newr   rD   r   r<   r=   r>   r?   r   r   r   ry   e  s   
	zRefsContainer.add_if_newc                 C   s2   t |s|tst|d| |d| dS )a  Set a reference name to point to the given SHA1.

        This method follows all symbolic references if applicable for the
        subclass.

        Note: This method unconditionally overwrites the contents of a
            reference. To update atomically only if the reference has not
            changed, use set_if_equals().

        Args:
          name: The refname to set.
          ref: The new sha the refname will refer to.
        z+ must be a valid sha (40 chars) or a symrefN)r   r"   r#   r&   rW   )r   rD   r   r   r   r   __setitem__p  s   zRefsContainer.__setitem__c                 C   rA   )a  Remove a refname only if it currently equals old_ref.

        This method does not follow symbolic references, even if applicable for
        the subclass. It can be used to perform an atomic compare-and-delete
        operation.

        Args:
          name: The refname to delete.
          old_ref: The old sha the refname must refer to, or None to
            delete unconditionally.
          message: Message for reflog
        Returns: True if the delete was successful, False otherwise.
        )rB   r[   )r   rD   rw   r<   r=   r>   r?   r   r   r   r[     s   
zRefsContainer.remove_if_equalsc                 C   s   |  |d dS )as  Remove a refname.

        This method does not follow symbolic references, even if applicable for
        the subclass.

        Note: This method unconditionally deletes the contents of a reference.
            To delete atomically only if the reference has not changed, use
            remove_if_equals().

        Args:
          name: The refname to delete.
        N)r[   rN   r   r   r   __delitem__  s   zRefsContainer.__delitem__c              	   C   sD   i }|   D ]}z	t| |}W n	 ty   Y qw |||< q|S )zuGet a dict with all symrefs in this container.

        Returns: Dictionary mapping source ref to target ref
        )r_   r'   ro   r&   )r   rg   srcdstr   r   r   get_symrefs  s   
zRefsContainer.get_symrefsr   r   NNNN)NNNNF)%r   r   r   r   r   r@   rC   dictRefr   rG   r   rL   rO   bytesboolr^   r   r_   ra   rc   rT   ri   rl   ro   rm   tuplelistrr   rs   rv   rW   ry   r{   r[   r|   r   r   r   r   r   r5   h   s    	


	
	



	




r5   c                	       s   e Zd ZdZd d! fddZdd Zdd	 Zd
d Zd!ddZ				d"de	de	ddfddZ
				d"defddZ				d"de	dedee defddZ				d"defddZdd Zd!ddZd!ddZ  ZS )#DictRefsContainerzRefsContainer backed by a simple dict.

    This container does not support symbolic or packed references and is not
    threadsafe.
    Nr   c                    s&   t  j|d || _i | _t | _d S )Nr8   )superr   _refs_peeledrS   	_watchers)r   refsr8   	__class__r   r   r     s   zDictRefsContainer.__init__c                 C   
   | j  S r   r   rc   rH   r   r   r   r_     r9   zDictRefsContainer.allkeysc                 C      | j |d S r   r   rn   rN   r   r   r   rm        z DictRefsContainer.read_loose_refc                 C      i S r   r   rH   r   r   r   rG        z!DictRefsContainer.get_packed_refsc                 C   s   | j D ]	}|||f qd S r   )r   _notify)r   r   newshawatcherr   r   r   r     s   
zDictRefsContainer._notifyrD   rE   c           	   	   C   sH   |  |d }t| }|| j|< | || | j|||||||d d S )Nr,   r<   r=   r>   r?   )rr   r#   r   r   r@   )	r   rD   rE   r<   r=   r>   r?   oldnewr   r   r   rC     s   	

z"DictRefsContainer.set_symbolic_refc              
   C   s~   |d ur| j |t|krdS | |\}}	|D ]$}
| |
 | j |
}|| j |
< | |
| | j|
||||||d qdS NFr   T)r   rn   r   rr   rl   r   r@   )r   rD   rw   rx   r<   r=   r>   r?   	realnamesrt   realnamer   r   r   r   rW     s$   


	zDictRefsContainer.set_if_equalsr   r?   c              	   C   s@   || j v rdS || j |< | || | j|d |||||d dS r   )r   r   r@   rz   r   r   r   ry     s   
	
	zDictRefsContainer.add_if_newc              	   C   sl   |d ur| j |t|krdS z| j |}W n
 ty!   Y dS w | |d  | j||d ||||d dS r   )r   rn   r   poprZ   r   r@   )r   rD   rw   r<   r=   r>   r?   r   r   r   r   r[     s&   		z"DictRefsContainer.remove_if_equalsc                 C   s   | j |S r   )r   rn   rN   r   r   r   rO   ;  rb   zDictRefsContainer.get_peeledc                 C   s$   |  D ]\}}| |d| qdS )z0Update multiple refs; intended only for testing.N)rU   rW   )r   r   r   ru   r   r   r   _update>  s   zDictRefsContainer._updatec                 C   s   | j | dS )z5Update cached peeled refs; intended only for testing.N)r   update)r   peeledr   r   r   _update_peeledE  s   z DictRefsContainer._update_peeledr   r   r   )r   r   r   r   r   r_   rm   rG   r   r   rC   r   rW   r   r   r   ry   r[   rO   r   r   __classcell__r   r   r   r   r     s`    

	
!


r   c                   @   s:   e Zd ZdZdddZdd Zdd	 Zd
d Zdd ZdS )InfoRefsContainerz5Refs container that reads refs from a info/refs file.r   Nc                 C   s(   i | _ i | _t|}t|\| _ | _d S r   )r   r   read_info_refssplit_peeled_refs)r   fr   r   r   r   r   M  s   zInfoRefsContainer.__init__c                 C   r   r   r   rH   r   r   r   r_   S  r9   zInfoRefsContainer.allkeysc                 C   r   r   r   rN   r   r   r   rm   V  r   z InfoRefsContainer.read_loose_refc                 C   r   r   r   rH   r   r   r   rG   Y  r   z!InfoRefsContainer.get_packed_refsc                 C   s*   z| j | W S  ty   | j|  Y S w r   )r   rZ   r   rN   r   r   r   rO   \  s
   zInfoRefsContainer.get_peeledr   )	r   r   r   r   r   r_   rm   rG   rO   r   r   r   r   r   J  s    
r   c                	       s   e Zd ZdZd$d% fddZdefddZdd	 Zd
d Zdd Z	dd Z
deeee f ddfddZdd Zdd Zd%ddZ				d&	d%ddZ				d&defddZ				d&dededee defd d!Z				d&defd"d#Z  ZS )'DiskRefsContainerz)Refs container that reads refs from disk.Nr   c                    sj   t  j|d t|dd d urt|}|| _|d u r|}t|dd d ur*t|}|| _d | _d | _d S )Nr   encode)	r   r   getattrosfsencodepathworktree_path_packed_refs_peeled_refs)r   r   r   r8   r   r   r   r   f  s   


zDiskRefsContainer.__init__c                 C   s   | j j d| jdS )N())r   r   r   rH   r   r   r   __repr__s  s   zDiskRefsContainer.__repr__c                 C   s   t  }| |}t|D ]B\}}}|t|d  }tjjdkr+|ttjjd}|	d}|D ]}d
|r;|gng |g }	t|d |	 rN||	 q2q|  D ]}
|
|ri||
t|d  	d qT|S )N/r*   )rS   refpathr   walkr$   r   sepreplacer   rf   rX   r4   rV   rG   r"   )r   rP   rT   r   rootunused_dirsfilesdirfilenamer(   rh   r   r   r   rT   v  s$   



zDiskRefsContainer.subkeysc           
      C   s   t  }tj| tr|t | d}| d}t|D ]3\}}}|t|d  }tjj	dkr>|
ttjj	d}|D ]}d||g}	t|	rR||	 q@q ||   |S )Nre      refsr   r*   )rS   r   r   existsr   rk   rV   r   r$   r   r   r   rX   r4   r   rG   )
r   r_   r   refspathr   r   r   r   r   r(   r   r   r   r_     s"   



zDiskRefsContainer.allkeysc                 C   sJ   t jjdkr|dt t jj}|tkrt j| j|S t j| j|S )zReturn the disk path of a ref.r   r*   )r   r   r   r   r   rk   rX   r   rN   r   r   r   r     s
   zDiskRefsContainer.refpathc                 C   s  | j du r~i | _ i | _tj| jd}zt|d}W n ty%   i  Y S w |N tt|	 }|
drQd|v rQt|D ]\}}}|| j |< |rO|| j|< q>n|d t|D ]\}}|| j |< qZW d   | j S W d   | j S 1 syw   Y  | j S )rF   N   packed-refsrbs   # pack-refss    peeledr   )r   r   r   r   rX   r	   FileNotFoundErrornextr`   r%   r"   read_packed_refs_with_peeledseekread_packed_refs)r   r   r   
first_lineru   rD   r   r   r   r   rG     s:   
	




z!DiskRefsContainer.get_packed_refsrJ   c              
   C   s   |sdS t j| jd}t|dU}|   }| D ]7\}}|tkr(tdt	t
 t | | W d   n1 s?w   Y  |durM|||< q||d qt||| j || _W d   dS 1 siw   Y  dS )rK   Nr   wbzcannot pack HEAD)r   r   rX   r	   rG   copyrU   rk   r&   r   OSErrorrY   r   r   write_packed_refsr   r   )r   rJ   r   r   packed_refsr   targetr   r   r   rL     s"   

"z!DiskRefsContainer.add_packed_refsc                 C   s<   |    | jdu s|| jvrdS || jv r| j| S | | S rM   )rG   r   r   rN   r   r   r   rO     s   	

zDiskRefsContainer.get_peeledc              	   C   s   |  |}zBt|d2}|tt}|tkr*|tt|d W  d   W S ||dtt  W  d   W S 1 s@w   Y  W dS  tt	fyS   Y dS w )a  Read a reference file and return its contents.

        If the reference file a symbolic reference, only read the first line of
        the file. Otherwise, only read the first 40 bytes.

        Args:
          name: the refname to read, relative to refpath
        Returns: The contents of the ref file, or None if the file does not
            exist.

        Raises:
          IOError: if any other error occurs
        r   r!   N(   )
r   r	   readr$   r#   r   r`   r%   r   UnicodeError)r   rD   r   r   headerr   r   r   rm     s   
(z DiskRefsContainer.read_loose_refc                 C   s   | j d u rd S tj| jd}t|d}zBd | _ |   || j vr(W |  d S | j |= tt | j	|= W d    n1 s?w   Y  t
|| j | j	 |  W |  d S |  w )Nr   r   )r   r   r   rX   r	   rG   abortr   rZ   r   r   close)r   rD   r   r   r   r   r   _remove_packed_ref  s"   





z$DiskRefsContainer._remove_packed_refc           
   	   C   s   |  | |  | | |}t|d}z|t| d  | |d }	| j||	|	||||d W n ty>   |   w |	  dS )zMake a ref point at another ref.

        Args:
          name: Name of the ref to set
          other: Name of the ref to point at
          message: Optional message to describe the change
        r      
r,   r   N)
rl   r   r	   writer#   rr   r@   BaseExceptionr   r   )
r   rD   rE   r<   r=   r>   r?   r   r   ru   r   r   r   rC   /  s*   




	z"DiskRefsContainer.set_symbolic_refc              
   C   sz  |  | z| |\}}	|d }
W n tttfy    |}
Y nw | |
}tj|
}| 	 }|rF|
|ddur>t|tj|}|s2ttj| t|d`}|durz$| |
}|du rj| 	 
|
t}||kr{|  W W d   dS W n ty   |   w z	||d  W n ty   |   w | j|
||||||d W d   dS 1 sw   Y  dS )a  Set a refname to new_ref only if it currently equals old_ref.

        This method follows all symbolic references, and can be used to perform
        an atomic compare-and-swap operation.

        Args:
          name: The refname to set.
          old_ref: The old sha the refname must refer to, or None to set
            unconditionally.
          new_ref: The new sha the refname will refer to.
          message: Set message for reflog
        Returns: True if the set was successful, False otherwise.
        r,   Nr   Fr   r   T)rl   rr   rZ   
IndexErrorr   r   r   r   dirnamerG   rn   NotADirectoryErrorr
   r	   rm   r   r   r   r   r@   )r   rD   rw   rx   r<   r=   r>   r?   r   rt   r   r   	probe_refr   r   orig_refr   r   r   rW   U  sd   



zDiskRefsContainer.set_if_equalsrD   r   r?   c              
   C   s  z|  |\}}|durW dS |d }	W n ttfy!   |}	Y nw | |	 | |	}
ttj|
 t	|
dD}tj
|
sF||  v rS|  	 W d   dS z	||d  W n tyh   |   w | j|d|||||d W d   dS 1 sw   Y  dS )a  Add a new reference only if it does not already exist.

        This method follows symrefs, and only ensures that the last ref in the
        chain does not exist.

        Args:
          name: The refname to set.
          ref: The new sha the refname will refer to.
          message: Optional message for reflog
        Returns: True if the add was successful, False otherwise.
        NFr,   r   r   r   T)rr   rZ   r   rl   r   r
   r   r   r   r	   r   rG   r   r   r   r@   )r   rD   r   r<   r=   r>   r?   r   r    r   r   r   r   r   r   ry     sF   


zDiskRefsContainer.add_if_newc              	   C   sL  |  | | |}ttj| t|d}zR|dur8| |}	|	du r-|  	|t
}	|	|kr8W |  dS ztj|}
W n tyK   d}
Y nw |
rSt| | | | j||d||||d W |  n|  w |}	 z
|dd\}}W n
 ty   Y dS w |dkr	 dS | |}zt| W n
 ty   Y dS w qr)	a  Remove a refname only if it currently equals old_ref.

        This method does not follow symbolic references. It can be used to
        perform an atomic compare-and-delete operation.

        Args:
          name: The refname to delete.
          old_ref: The old sha the refname must refer to, or None to
            delete unconditionally.
          message: Optional message
        Returns: True if the delete was successful, False otherwise.
        r   NFr   Tr*   r   r   )rl   r   r
   r   r   r   r	   rm   rG   rn   r   r   lexistsr   rY   r   r@   rsplitr&   rmdir)r   rD   rw   r<   r=   r>   r?   r   r   r   foundparentrt   parent_filenamer   r   r   r[     sb   






z"DiskRefsContainer.remove_if_equals)NNr   r   )r   r   r   r   r   strr   rT   r_   r   rG   r   r   r   r   rL   rO   rm   r   rC   r   rW   r   ry   r[   r   r   r   r   r   r   c  s\     $

+	
I
7r   c                 C   sf   |  dd}t|dkrtd| |\}}t|s$td|t|s/td|||fS )z6Split a single ref line into a tuple of SHA1 and name.s   
       zinvalid ref line Invalid hex sha zinvalid ref name )r%   splitr$   r   r   r4   )linefieldsru   rD   r   r   r   _split_ref_line  s   r   c                 c   s8    | D ]}| drq| drtdt|V  qdS )zRead a packed refs file.

    Args:
      f: file-like object to read from
    Returns: Iterator over tuples with SHA1s and ref names.
       #   ^z.found peeled ref in packed-refs without peeledN)r"   r   r   )r   r   r   r   r   r   ,  s   

r   c                 c   s    d}| D ]O}|d dkrq| d}|drD|stdt|dd s1td|dd t|\}}d}|||dd fV  q|rRt|\}}||dfV  |}q|ret|\}}||dfV  dS dS )	a	  Read a packed refs file including peeled refs.

    Assumes the "# pack-refs with: peeled" line was already read. Yields tuples
    with ref names, SHA1s, and peeled SHA1s (or None).

    Args:
      f: file-like object to read from, seek'ed to the second line
    Nr   r   r!   r   zunexpected peeled ref liner   r   )r%   r"   r   r   r   )r   lastr   ru   rD   r   r   r   r   <  s,   	

r   c                 C   s`   |du ri }n|  d t| D ]}|  t|| | ||v r-|  d||  d  qdS )zWrite a packed refs file.

    Args:
      f: empty file-like object to write to
      packed_refs: dict of refname to sha of packed refs to write
      peeled_refs: dict of refname to peeled value of sha
    Ns   # pack-refs with: peeled
r   r   )r   sortedrc   r   )r   r   peeled_refsr(   r   r   r   r   \  s   
r   c                 C   s4   i }|   D ]}|ddd\}}|||< q|S )Nr!      	r   )	readlinesr%   r   )r   rg   r   ru   rD   r   r   r   r   n  s
   
r   storec              	   c   s    ddl m} t|  D ]<\}}|tkrqz|| }W n	 ty%   Y qw |||\}}|jd | d V  |j|jkrI|jd | t d V  qdS )zGenerate info refs.r   peel_shar   r   N)object_storer   r   rU   rk   rZ   idPEELED_TAG_SUFFIX)r   r   r   rD   ru   ounpeeledr   r   r   r   write_info_refsv  s    r   c                 C   s
   |  tS r   )r"   LOCAL_BRANCH_PREFIX)xr   r   r   is_local_branch  r9   r   c                 C   s   dd |   D S )zRemove all peeled refs.c                 S   s    i | ]\}}| ts||qS r   )r1   r   ).0r   ru   r   r   r   
<dictcomp>  s
    z%strip_peeled_refs.<locals>.<dictcomp>)rU   )r   r   r   r   strip_peeled_refs  s   r  c                 C   sL   i }i }|   D ]\}}|tr|||dtt  < q|||< q||fS )z$Split peeled refs from regular refs.N)rU   r1   r   r$   )r   r   regularr   ru   r   r   r   r     s   

r   c                 C   sZ   d| d }|r'| tr)|t }||ttd   }|| v r+| || d S d S d S d S )Nr   r*   )r"   r   rk   r$   rC   )r   originorigin_headorigin_base
origin_ref
target_refr   r   r   _set_origin_head  s   r
  r   r  r  branchref_messagec           	      C   s   d| d }|r7|| }|| v r!t | }| || | | |}|S t| | v r-t| }|S tt|d|rd|}|t rK||tt d  }n|}z| || | | W |S  tyc   Y |S w td)zSet the default branch.r   r*   z is not a valid branch or tagNz+neither origin_head nor branch are provided)	r   ry   LOCAL_TAG_PREFIXr&   r   r   r"   r$   rZ   )	r   r  r  r  r  r  r  	local_refhead_refr   r   r   _set_default_branch  s2   
r  c                 C   s   | tr'| | }t|tr|j\}}||j}| t= | jtd ||d |S z| | }| 	t| | jtd ||d W |S  t
yI   d }Y |S w )NrR   )r"   r  
isinstancer   object
get_objectr   rk   rW   rC   rZ   )r   r  r  head_clsobjr   r   r   	_set_head  s"   


	r  Frefs_containerremote_namer?   rQ   
prune_tagsc           	      C   s\   t |}dd | D }| jd|  |||d dd | D }| jt|||d d S )Nc                 S   s,   i | ]\}}| tr|ttd  |qS r   )r"   r   r$   r  nvr   r   r   r    s    z'_import_remote_refs.<locals>.<dictcomp>r   )r?   rQ   c                 S   s6   i | ]\}}| tr|ts|ttd  |qS r   )r"   r  r1   r   r$   r  r   r   r   r    s    )r  rU   r^   r   r  )	r  r  r   r?   rQ   r  stripped_refsbranchestagsr   r   r   _import_remote_refs  s    

r!  c                 C   s   ddl m} i }| D ]9\}}z	|| |\}}W n ty3   td|dd|dt Y qw t	|t
r@|j||t < |j||< q|S )Nr   r   z#ref {} points at non-present sha {}zutf-8r   ascii)r   r   rU   rZ   warningswarnformatdecodeUserWarningr  r   r   r   )r   r   r   rg   r   ru   r   r   r   r   r   serialize_refs  s$   
	r(  r   r   )NFF)<r   r   r#  collections.abcr   
contextlibr   typingr   r   errorsr   r   filer	   r
   objectsr   r   r   r   r   packr   r   r   rk   r#   r   r  LOCAL_REMOTE_PREFIXrS   r0   r   ANNOTATED_TAG_SUFFIX	Exceptionr   r'   r   r4   r5   r   r   r   r   r   r   r   r   r   r   r  r   r
  r  r  r   r   r!  r(  r   r   r   r   <module>   s   "  S    ? 


"

