
                         &   d Z ddlZddlmZmZ ddlmZmZmZ ddl	m
Z
mZ dZdZdZ ed	      Zd
Zd Zd Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Zd Zd Zd Zd!dZd Zd Z d Z!d  Z"y)"zRef handling.

    N)PackedRefsExceptionRefFormatError)git_linevalid_hexshaZERO_SHA)GitFileensure_dir_existss   ref: s   refs/heads/s
   refs/tags/s    ~^:?*[s   ^{}c                     | j                  t              r!| t        t              d j                  d      S t	        |       )z`Parse a symref value.

    Args:
      contents: Contents to parse
    Returns: Destination
    N   
)
startswithSYMREFlenrstrip
ValueError)contentss    lib/third_party/dulwich/refs.pyparse_symref_valuer   1   s9     6"F&--g66
X
    c                     d| v s| j                  d      ryd| vryd| v ryt        |       D ]#  \  }}t        | ||dz          dk  s	|t        v s# y | d   dv ry| j	                  d	      ryd
| v ryd| v ryy)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   ..       s   .locks   @{   \T)r   	enumerateordBAD_REF_CHARSendswith)refnameics      r   check_ref_formatr#   =   s     7--d37'"1wq1q5!"T)Q--? # r{e!r   c                       e Zd ZdZddZ	 	 	 	 ddZ	 	 	 	 ddZd Zd Z	 	 	 	 	 ddZ	d	 Z
d
 ZddZd ZddZd Zd Zd Zd Zd Zd Zd Z	 	 	 	 ddZd Zd Z	 	 	 	 ddZd Zd Zd Zy)RefsContainerzA container for refs.Nc                     || _         y N_logger)selfloggers     r   __init__zRefsContainer.__init__b   s	    r   c           	      R    | j                   y |y | j                  |||||||       y r'   r(   )r*   refold_shanew_sha	committer	timestamptimezonemessages           r   _logzRefsContainer._loge   s1     <<?S'7Iy(GTr   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otherr1   r2   r3   r4   s          r   r8   zRefsContainer.set_symbolic_refu   s      "$"7"788r   c                 ,    t        | j                        )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.
        )r7   get_packed_refsr*   s    r   r=   zRefsContainer.get_packed_refs   s     "$"6"677r   c                      y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.
        N r*   r9   s     r   
get_peeledzRefsContainer.get_peeled   s     r   c                    |rt        | j                  |            }n
t               }|j                         D ]T  \  }	}
|
|j                  |	       n&| j	                  dj                  ||	f      d |
|       |sC	 |j                  |	       V |D ]'  }| j                  dj                  ||f      d |       ) y # t        $ r Y w xY w)Nr   )r4   )	setsubkeysitemsaddset_if_equalsjoinremoveKeyErrorremove_if_equals)r*   baser:   r1   r2   r3   r4   prune	to_deleter9   valuer.   s               r   import_refszRefsContainer.import_refs   s     DLL./II ;;=KD%}d#""IItTl+T5' #  $$T* ) C!!$))T3K"8$!P    s   <B<<	CCc                 ,    t        | j                        )z#All refs present in this container.)r7   allkeysr>   s    r   rT   zRefsContainer.allkeys   s    !$,,//r   c                 4    t        | j                               S r'   )iterrT   r>   s    r   __iter__zRefsContainer.__iter__   s    DLLN##r   c                 H    || j                  |      S | j                         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.
        )rF   rT   )r*   rN   s     r   keyszRefsContainer.keys   s%     <<%%<<>!r   c                     t               }t        |      dz   }| j                         D ](  }|j                  |      s|j	                  ||d        * |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)rE   r   rT   r   rH   )r*   rN   rY   base_lenr    s        r   rF   zRefsContainer.subkeys   sP     ut9q=||~G!!$'+, & r   c                     i }| j                  |      }|d}n|j                  d      }|D ]   }	 | |dz   |z   j                  d         ||<   " |S # t        $ r Y 0w xY w)z6Return the contents of this container as a dictionary.r   r   )rY   r   striprL   )r*   rN   retrY   keys        r   as_dictzRefsContainer.as_dict   sx    yy<D;;t$DCs!2 9 9$ ?@C  
  s   A	AAc                 b    |dv ry|j                  d      rt        |dd       st        |      y)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.
        )   HEADs
   refs/stashNs   refs/   )r   r#   r   rB   s     r   _check_refnamezRefsContainer._check_refname   s;     ++x(0@ab0J && 1Kr   c                 l    | j                  |      }|s | j                         j                  |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_refr=   get)r*   r    r   s      r   read_refzRefsContainer.read_ref   s7     &&w/++-11'4@Hr   c                 ,    t        | j                        )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.
        )r7   rf   rB   s     r   rf   zRefsContainer.read_loose_ref  s     "$"5"566r   c                    t         |z   }d}g }|j                  t               rf|t        t               d }|j                  |       | j	                  |      }|s	 ||fS |dz  }|dkD  rt        |      |j                  t               rf||fS )zFollow a reference name.

        Returns: a tuple of (refnames, sha), wheres refnames are the names of
            references in the chain
        r   Nr   rc   )r   r   r   appendrh   rL   )r*   r9   r   depthrefnamesr    s         r   followzRefsContainer.follow  s     D=!!&)s6{}-GOOG$}}W-H !! QJEqytn$ !!&) !!r   c                 x    dd l }|j                  dt               | j                  |      \  }}|sd |fS |d   |fS )Nr   zFRefsContainer._follow is deprecated. Use RefsContainer.follow instead.r   )warningswarnDeprecationWarningrn   )r*   r9   rp   rm   r   s        r   _followzRefsContainer._follow)  sI    W	
 "[[.((##h''r   c                 (    | j                  |      ryy)NTF)rh   )r*   r    s     r   __contains__zRefsContainer.__contains__5  s    ==!r   c                 H    | j                  |      \  }}|t        |      |S )zaGet the SHA1 for a reference name.

        This method follows all symbolic references.
        )rn   rL   )r*   r9   _shas       r   __getitem__zRefsContainer.__getitem__:  s*    
 T"3;4. 
r   c                 ,    t        | j                        )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.
        )r7   rI   )r*   r9   old_refnew_refr1   r2   r3   r4   s           r   rI   zRefsContainer.set_if_equalsD  s    0 "$"4"455r   c                 ,    t        | j                        )zAdd a new reference only if it does not already exist.

        Args:
          name: Ref name
          ref: Ref value
          message: Message for reflog
        )r7   
add_if_newr*   r9   r.   s      r   r~   zRefsContainer.add_if_new^  s     "$//22r   c                 *    | j                  |d|       y)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.
        N)rI   r   s      r   __setitem__zRefsContainer.__setitem__h  s     	4s+r   c                 ,    t        | j                        )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.
        )r7   rM   )r*   r9   r{   r1   r2   r3   r4   s          r   rM   zRefsContainer.remove_if_equalsx  s    , "$"7"788r   c                 (    | j                  |d       y)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)rM   rB   s     r   __delitem__zRefsContainer.__delitem__  s     	dD)r   c                     i }| j                         D ]"  }	 t        | j                  |            }|||<   $ |S # t        $ r Y 2w xY w)zuGet a dict with all symrefs in this container.

        Returns: Dictionary mapping source ref to target ref
        )rT   r   rh   r   )r*   r^   srcdsts       r   get_symrefszRefsContainer.get_symrefs  sW    
 <<>C(s);< C " 
	  s   :	AAc                 ,    t        | j                        )zWatch for changes to the refs in this container.

        Returns a context manager that yields tuples with (refname, new_sha)
        )r7   watchr>   s    r   r   zRefsContainer.watch  s    
 "$**--r   r'   NNNN)NNNNF)__name__
__module____qualname____doc__r,   r5   r8   r=   rC   rR   rT   rW   rY   rF   r`   rd   rh   rf   rn   rs   ru   ry   rI   r~   r   rM   r   r   r   rA   r   r   r%   r%   _   s     U( 9$8	 Q:0$" '$7"(
(
 643,( 90*.r   r%   c                   *    e Zd Zd Zd Zd Zd Zd Zy)_DictRefsWatcherc                     || _         y r'   )_refs)r*   refss     r   r,   z_DictRefsWatcher.__init__  s	    
r   c                 t    ddl m}  |       | _         | j                  j                  j	                  |        | S )Nr   Queue)queuer   r   	_watchersrH   )r*   r   s     r   	__enter__z_DictRefsWatcher.__enter__  s+    W


  &r   c                 6    | j                   j                         S r'   r   rg   r>   s    r   __next__z_DictRefsWatcher.__next__      zz~~r   c                 :    | j                   j                  |       y r'   )r   
put_nowait)r*   entrys     r   _notifyz_DictRefsWatcher._notify  s    

e$r   c                 N    | j                   j                  j                  |        yNF)r   r   rK   r*   exc_typeexc_valexc_tbs       r   __exit__z_DictRefsWatcher.__exit__  s    

##D)r   N)r   r   r   r,   r   r   r   r   rA   r   r   r   r     s     %r   r   c                        e Zd ZdZd fd	Zd Zd Zd Zd Zd Z		 	 	 	 ddZ
	 	 	 	 dd	Z	 	 	 	 dd
Z	 	 	 	 ddZd Zd Zd Z xZS )DictRefsContainerzRefsContainer backed by a simple dict.

    This container does not support symbolic or packed references and is not
    threadsafe.
    c                 h    t         t        |   |       || _        i | _        t               | _        y )Nr+   )superr   r,   r   _peeledrE   r   )r*   r   r+   	__class__s      r   r,   zDictRefsContainer.__init__  s-    /v/>
r   c                 6    | j                   j                         S r'   r   rY   r>   s    r   rT   zDictRefsContainer.allkeys      zz  r   c                 :    | j                   j                  |d       S r'   r   rg   rB   s     r   rf   z DictRefsContainer.read_loose_ref      zz~~dD))r   c                     i S r'   rA   r>   s    r   r=   z!DictRefsContainer.get_packed_refs      	r   c                 L    | j                   D ]  }|j                  ||f        y r'   )r   r   )r*   r.   newshawatchers       r   r   zDictRefsContainer._notify  s     ~~GOOS&M* &r   c                     t        |       S r'   )r   r>   s    r   r   zDictRefsContainer.watch  s    %%r   c           	          | j                  |      d   }t        |z   }|| j                  |<   | j                  ||       | j	                  |||||||       y )Nr   r1   r2   r3   r4   )rn   r   r   r   r5   )	r*   r9   r:   r1   r2   r3   r4   oldnews	            r   r8   z"DictRefsContainer.set_symbolic_ref  sb     kk$#un

4T3		 	 	
r   c           
      P   |$| j                   j                  |t              |k7  ry| j                  |      \  }}	|D ]g  }
| j	                  |
       | j                   j                  |
      }|| j                   |
<   | j                  |
|       | j                  |
||||||       i yNFr   T)r   rg   r   rn   rd   r   r5   )r*   r9   r{   r|   r1   r2   r3   r4   	realnamesrw   realnamer   s               r   rI   zDictRefsContainer.set_if_equals   s     4::>>$#AW#L{{4(	1!H)**..*C#*DJJx LL7+II##!   " r   c           	          || j                   v ry|| j                   |<   | j                  ||       | j                  |d |||||       yr   )r   r   r5   )r*   r9   r.   r1   r2   r3   r4   s          r   r~   zDictRefsContainer.add_if_new  sZ     4::

4T3		 	 	
 r   c           	          |$| j                   j                  |t              |k7  ry	 | j                   j                  |      }| j	                  |d        | j                  ||d ||||       y# t        $ r Y yw xY wr   )r   rg   r   popr   r5   rL   )r*   r9   r{   r1   r2   r3   r4   r   s           r   rM   z"DictRefsContainer.remove_if_equals5  s     4::>>$#AW#L	**..&C LLt$II##!     	 	s   A. .	A:9A:c                 8    | j                   j                  |      S r'   )r   rg   rB   s     r   rC   zDictRefsContainer.get_peeledQ  s    ||%%r   c                 Z    |j                         D ]  \  }}| j                  |d|        y)z0Update multiple refs; intended only for testing.N)rG   rI   )r*   r   r.   rx   s       r   _updatezDictRefsContainer._updateT  s*     

HCsD#. %r   c                 :    | j                   j                  |       y)z5Update cached peeled refs; intended only for testing.N)r   update)r*   peeleds     r   _update_peeledz DictRefsContainer._update_peeled[  s    F#r   r'   r   )r   r   r   r   r,   rT   rf   r=   r   r   r8   rI   r~   rM   rC   r   r   __classcell__r   s   @r   r   r     s    !*+& 
8 B 8 8&/$r   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)InfoRefsContainerz5Refs container that reads refs from a info/refs file.c                 f   i | _         i | _        |j                         D ]  }|j                  d      j	                  d      \  }}|j                  t              r.|d d }t        |      st        d|z        || j                  |<   it        |      st        d|z        || j                   |<    y )N   
   	invalid ref name %r)	r   r   	readlinesr   splitr   ANNOTATED_TAG_SUFFIXr#   r   )r*   flinerx   r9   s        r   r,   zInfoRefsContainer.__init__c  s    
KKMDE*007IC}}12CRy'-$%:T%ABB%(T"'-$%:T%ABB#&

4  "r   c                 6    | j                   j                         S r'   r   r>   s    r   rT   zInfoRefsContainer.allkeysr  r   r   c                 :    | j                   j                  |d       S r'   r   rB   s     r   rf   z InfoRefsContainer.read_loose_refu  r   r   c                     i S r'   rA   r>   s    r   r=   z!InfoRefsContainer.get_packed_refsx  r   r   c                 ^    	 | j                   |   S # t        $ r | j                  |   cY S w xY wr'   )r   rL   r   rB   s     r   rC   zInfoRefsContainer.get_peeled{  s4    	$<<%% 	$::d##	$s    ,,N)	r   r   r   r   r,   rT   rf   r=   rC   rA   r   r   r   r   `  s    ?'!*$r   r   c                   *    e Zd Zd Zd Zd Zd Zd Zy)_InotifyRefsWatcherc                    dd l }ddlm} t        j                  |      | _        |j                         | _        | j                  j                  | j
                  |j                  |j                  z  |j                  z  dd       |j                  | j                  | j                        | _         |       | _        y )Nr   r   T)recauto_add)default_proc_fun)	pyinotifyr   r   osfsdecodepathWatchManagermanager	add_watch	IN_DELETEIN_CLOSE_WRITEIN_MOVED_TOThreadedNotifierr   notifier)r*   r   r   r   s       r   r,   z_InotifyRefsWatcher.__init__  s    KK%	 --/II)":"::Y=R=RR	 	 	
 "22LL4<< 3 
 W
r   c                 *   |j                   ry |j                  j                  d      ry t        j                  t        j
                  j                  |j                  | j
                              }|j                  dk(  r| j                  j                  |d f       y |j                  dv r\t        |j                  d      5 }|j                         j                  d      }| j                  j                  ||f       d d d        y y # 1 sw Y   y xY w)Nz.lockr   )r   r   rb   
)dirpathnamer   r   fsencoder   relpathmasknamer   r   openreadliner   )r*   eventr.   r   rx   s        r   r   z_InotifyRefsWatcher._notify  s    99>>""7+kk"''//%..$))DE>>[(JJ!!3+.^^@@ennd+qjjl))'2

%%sCj1 ,+ A++s   =D		Dc                 6    | j                   j                         S r'   r   r>   s    r   r   z_InotifyRefsWatcher.__next__  r   r   c                 :    | j                   j                          | S r'   )r   startr>   s    r   r   z_InotifyRefsWatcher.__enter__  s    r   c                 8    | j                   j                          yr   )r   stopr   s       r   r   z_InotifyRefsWatcher.__exit__  s    r   N)r   r   r   r,   r   r   r   r   rA   r   r   r   r     s    $2 r   r   c                        e Zd ZdZd fd	Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Z	 	 	 	 ddZ	 	 	 	 ddZ	 	 	 	 ddZ	 	 	 	 ddZd Z xZS )DiskRefsContainerz)Refs container that reads refs from disk.c                     t         t        |   |       t        |dd       t	        j
                  |      }|| _        ||}t        |dd       t	        j
                  |      }|| _        d | _        d | _	        y )Nr   encode)
r   r  r,   getattrr   r   r   worktree_path_packed_refs_peeled_refs)r*   r   r  r+   r   s       r   r,   zDiskRefsContainer.__init__  sz    /v/>44(4;;t$D	  M=(D1=KK6M*  r   c                 N    | j                   j                  d| j                  dS )N())r   r   r   r>   s    r   __repr__zDiskRefsContainer.__repr__  s    >>22DII>>r   c                    t               }| j                  |      }t        j                  |      D ]  \  }}}|t	        |      d  }t        j
                  j                  dk7  r=|j                  t        j                  t        j
                  j                        d      }|j                  d      }|D ]?  }dj                  |r|gng |gz         }	t        |dz   |	z         s/|j                  |	       A  | j                         D ]@  }
|
j                  |      s|j                  |
t	        |      d  j                  d             B |S )N/r   )rE   refpathr   walkr   r   sepreplacer   r]   rJ   r#   rH   r=   r   )r*   rN   rF   r   rootunused_dirsfilesr   filenamer    r_   s              r   rF   zDiskRefsContainer.subkeys  s   %||D!(*$D+us4y{#Cww{{c!kk"++bggkk":DA))D/C!))ccUrhZ$GH $D4K'$9:KK( " )6 '')C~~d#CD	,22489 * r   c                    t               }t        j                  j                  | j	                  d            r|j                  d       | j	                  d      }| j	                  d      }t        j                  |      D ]  \  }}}|t        |      d  }t        j                  j                  dk7  r=|j                  t        j                  t        j                  j                        d      }|D ]2  }dj                  ||g      }	t        |	      s"|j                  |	       4  |j                  | j                                |S )Nrb   r   s   refsr  r   )rE   r   r   existsr  rH   r  r   r  r  r   rJ   r#   r   r=   )
r*   rT   r   refspathr  r  r  r   r  r    s
             r   rT   zDiskRefsContainer.allkeys  s    %77>>$,,w/0KK ||C <<((*(9$D+us4y{#Cww{{c!kk"++bggkk":DA!))S(O4#G,KK( "	 ): 	t++-.r   c                 h   t         j                  j                  dk7  r=|j                  dt        j                  t         j                  j                              }|dk(  r*t         j                  j                  | j                  |      S t         j                  j                  | j                  |      S )zReturn the disk path of a ref.r  r   rb   )r   r   r  r  r   rJ   r  rB   s     r   r  zDiskRefsContainer.refpath  sp    77;;#<<bkk"''++&>?D 7?77<< 2 2D9977<<		400r   c                 z   | j                   i | _         i | _        t        j                  j	                  | j                  d      }	 t        |d      }|5  t        t        |            j                         }|j                  d      r:d|v r6t        |      D ]'  \  }}}|| j                   |<   |s|| j                  |<   ) n3|j                  d       t        |      D ]  \  }}|| j                   |<    ddd       | j                   S | j                   S # t        $ r i cY S w xY w# 1 sw Y   | j                   S xY w)r<   N   packed-refsr   s   # pack-refss    peeledr   )r	  r
  r   r   rJ   r   FileNotFoundErrornextrV   r   r   read_packed_refs_with_peeledseekread_packed_refs)r*   r   r   
first_linerx   r9   r   s          r   r=   z!DiskRefsContainer.get_packed_refs  s+    $ !#D "D77<<		>:DD$' !$q']113
((8Z:=U-I!-L)T625))$/!6<D--d3 .M
 FF1I%5a%8	T25))$/ &9     t    % 	    s&   D AD&0AD&D#"D#&D:c                     | j                          | j                  || j                  vry|| j                  v r| j                  |   S | |   S r@   )r=   r
  r	  rB   s     r   rC   zDiskRefsContainer.get_peeled  sW     	$D4E4E(E4$$$$$T** :r   c                    | j                  |      }	 t        |d      5 }|j                  t        t                    }|t        k(  r/|t        t        |            j                  d      z   cddd       S ||j                  dt        t              z
        z   cddd       S # 1 sw Y   yxY w# t        t        t        f$ r Y yw xY 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   rV   r   r  IsADirectoryErrorNotADirectoryError)r*   r9   r  r   headers        r   rf   z DiskRefsContainer.read_loose_ref#  s     <<%
	4(AF,V#!DaM$8$8$AA	 )( "AFF2F+;$<< )(( "#46HI 		s;   B/ AB#,	B/ 6#B#	B/ #B,(B/ ,B/ /CCc                    | j                   y t        j                  j                  | j                  d      }t	        |d      }	 d | _         | j                          || j                   vr	 |j                          y | j                   |= || j                  v r| j                  |= t        || j                   | j                         |j                          |j                          y # |j                          w xY w)Nr  wb)
r	  r   r   rJ   r   r=   abortr
  write_packed_refsclose)r*   r9   r  r   s       r   _remove_packed_refz$DiskRefsContainer._remove_packed_ref=  s    $77<<		>:Hd#	 $D  "4,,, GGI !!$'t(((%%d+a!2!2D4E4EFGGIGGIAGGIs   %C& <AC& &C8c           	      n   | j                  |       | j                  |       | j                  |      }t        |d      }	 |j                  t        |z   dz          | j                  |      d   }	| j                  ||	|	||||       |j                          y# t        $ r |j                           w xY w)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   r   N)
rd   r  r   writer   rn   r5   r0  BaseExceptionr.  )
r*   r9   r:   r1   r2   r3   r4   r  r   rx   s
             r   r8   z"DiskRefsContainer.set_symbolic_refR  s      	D!E"<<%Hd#	GGFUNU*+++d#B'CII##!   GGI	  	GGI	s   AB B4c           
         | j                  |       	 | j                  |      \  }}	|d   }
| j	                  |
      }t
        j                  j                  |
      }| j                         }|r?|j                  |d      t        |      t
        j                  j                  |      }|r?t        t
        j                  j                  |             t        |d      5 }|X	 | j                  |
      }|$| j                         j                  |
t              }||k7  r|j                          	 ddd       y	 	 |j%                  |dz          | j'                  |
||||||       ddd       y# t        t        f$ r |}
Y Zw xY w# t         t"        f$ r |j                           w xY w# t         t"        f$ r |j                           w xY w# 1 sw Y   yxY w)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)rd   rn   rL   
IndexErrorr  r   r   dirnamer=   rg   r*  r	   r   rf   r   r.  OSErrorIOErrorr3  r5   )r*   r9   r{   r|   r1   r2   r3   r4   r   rw   r   r  	probe_refpacked_refsr   orig_refs                   r   rI   zDiskRefsContainer.set_if_equalsx  s   . 	D!	;;t,LIq }H <<) GGOOH-	**,y$/;(22	2I 
 	"''//(34Xt$"
#228<H'#'#7#7#9#=#=h#Q7*	$ %$ +%( II##!  % %6 Q *% 	H	.  ) GGI
 W% 	 %6 sN   E2 !G%AF
;G=F.G2FF
!F++G.!GGGc           
      |   	 | j                  |      \  }}|y|d   }	| j                  |	       | j	                  |	      }
t        t        j                  j                  |
             t        |
d      5 }t        j                  j                  |
      s|| j                         v r|j                          	 ddd       y	 |j                  |dz          | j                  |d|||||       	 ddd       y# t        t        f$ r |}	Y w xY w# t        t         f$ r |j                           w xY w# 1 sw Y   yxY w)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)rn   rL   r6  rd   r  r	   r   r   r7  r   r  r=   r.  r3  r5   r8  r9  )r*   r9   r.   r1   r2   r3   r4   r   r   r   r  r   s               r   r~   zDiskRefsContainer.add_if_new  s-   (	"&++d"3Ix# }H 	H%<<)"''//(34Xt$ww~~h'443G3G3I+I	 %$e$
 		''%#   %& 1 *% 	H	 W% 	 %& s;   C7 C7 4AD2DD27D
D!D//D22D;c           	         | j                  |       | j                  |      }t        t        j                  j                  |             t        |d      }	 |N| j                  |      }	|	$| j                         j                  |t              }	|	|k7  r	 |j                          y	 t        j                  |       | j                  |       | j                  ||d||||       |j                          |}
	 	 |
j!                  dd      \  }
}| j                  |
      }	 t        j$                  |       ># t        $ r Y w xY w# |j                          w xY w# t"        $ r Y yw xY w# t&        $ r Y yw xY w)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   )rd   r  r	   r   r   r7  r   rf   r=   rg   r   r.  rK   r  r1  r5   rsplitr   rmdirr8  )r*   r9   r{   r1   r2   r3   r4   r  r   r<  parentrw   parent_filenames                r   rM   z"DiskRefsContainer.remove_if_equals  s~   * 	D!<<%"''//(34Hd#	"..t4##33599$IHw& ( GGI#		(# ##D)II##!   GGI
 "MM$2	 #ll62O) + %  GGI     
 sT   >E )D8 >)E ;E "E+ 8	EE EE E	E('E(+	E76E7c                 4    dd l }t        | j                        S )Nr   )r   r   r   )r*   r   s     r   r   zDiskRefsContainer.watch;  s    "499--r   )NNr   )r   r   r   r   r,   r  rF   rT   r  r=   rC   rf   r1  r8   rI   r~   rM   r   r   r   s   @r   r  r    s    3!?&"	1!@&42 $V CR 1n IV.r   r  c                     | j                  d      j                  d      }t        |      dk7  rt        d| z        |\  }}t	        |      st        d|z        t        |      st        d|z        ||fS )z6Split a single ref line into a tuple of SHA1 and name.r          zinvalid ref line %rInvalid hex sha %rr   )r   r   r   r   r   r#   )r   fieldsrx   r9   s       r   _split_ref_linerI  A  s}    [[!''-F
6{a!"7$">??IC!"6"<==D!!"7$">??;r   c              #      K   | D ]=  }|j                  d      r|j                  d      rt        d      t        |       ? yw)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   rI  )r   r   s     r   r#  r#  N  sD      ??4 ??4 %&VWWd## s   AAc              #   d  K   d}| D ]  }|d   dk(  r|j                  d      }|j                  d      rG|st        d      t        |dd       st        d|dd z        t	        |      \  }}d}|||dd f u|rt	        |      \  }}||df |} |rt	        |      \  }}||df yyw)	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   rK  r   rL  zunexpected peeled ref liner   rG  )r   r   r   r   rI  )r   lastr   rx   r9   s        r   r!  r!  ^  s      D7d?{{7#??4 )*FGGQR))*>ab*IJJ'-ICDd12h''+D1	TD$''D! " #D)	TD$ s   B.B0c                     |i }n| j                  d       t        |j                               D ]?  }| j                  t        ||   |             ||v s&| j                  d||   z   dz          A y)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
rL  r   )r3  sortedrY   r   )r   r;  peeled_refsr    s       r   r/  r/  ~  so     	-.+**,-	W-w78k!GGD;w//%78 .r   c                     i }| j                         D ]+  }|j                  d      j                  dd      \  }}|||<   - |S )Nr   r   r   )r   r   r   )r   r^   r   rx   r9   s        r   read_info_refsrS    sF    
Ckk'*00:dD	  Jr   c              #   D  K   t        | j                               D ]q  \  }}|dk(  r	 ||   }|j                  |      }|j                  dz   |z   dz    |j                  |j                  k7  sT|j                  dz   |z   t
        z   dz    s y# t        $ r Y w xY ww)zGenerate info refs.rb   r   r   N)rP  rG   rL   peel_shaidr   )r   storer9   rx   or   s         r   write_info_refsrY    s     DJJL)	c 7?	c
A $ddUlT!E))44699))e#d*-AAEII *  		s.   &B BAB 0!B 	BB BB c                 ,    | j                  t              S r'   )r   LOCAL_BRANCH_PREFIX)xs    r   is_local_branchr]    s    <<+,,r   c                     | j                         D ci c]  \  }}|j                  t              s|| c}}S c c}}w )zRemove all peeled refs)rG   r   r   )r   r.   rx   s      r   strip_peeled_refsr_    sD     **,&JS#||01 	S&  s   ":r'   )#r   r   dulwich.errorsr   r   dulwich.objectsr   r   r   dulwich.filer   r	   r   r[  LOCAL_TAG_PREFIXrE   r   r   r   r#   objectr%   r   r   r   r   r  rI  r#  r!  r/  rS  rY  r]  r_  rA   r   r   <module>re     s   , 
 
 
$   N# 	DT.F T.n
v ,Q$ Q$h$ $D)& )XP. P.f
$  @9$J"-r   