U
    楡c7                     @   s  U d dl mZmZ d dlmZ d dl mZ ddlmZ ddl	m
Z
m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mZmZmZmZmZmZmZmZmZ d dlm Z m!Z! erd dl"m#Z# d dl$m%Z% ee&e'e(f Z)eeed eed f  Z*dd Z+ee(e(ge'f e,d< dZ-e)e)e'dddZ.ee) ee)e)ge'f ddddZ/G dd de0Z1G dd de
ej2ej3ej4Z5e5e5j6e5j7< dS )    )IterableList	join_pathN)
to_bin_sha   )util)IndexObjectIndexObjUnion)Blob)	Submodule)tree_entries_from_datatree_to_stream)AnyCallableDictIterableIteratorListTupleTypeUnioncastTYPE_CHECKING)PathLikeLiteral)Repo)BytesIO)TreeN)r
   r
   c                 C   s   | |k| |k  S N )abr   r   4/tmp/pip-unpacked-wheel-_pbxsds5/git/objects/tree.py<lambda>4       r"   cmp)TreeModifierr   )t1t2returnc                 C   sX   | d |d  }}t |t | }}t||}t|d | |d | }|rP|S || S )N   )lenminr$   )r&   r'   r   r    Zlen_alen_bZmin_lenZmin_cmpr   r   r!   git_cmp9   s    
r-   )r   r$   r(   c                 C   s  t | dk rd S t | d }| d | }| |d  }t|| t|| d}d}d}|t |k r|t |k r||| || dkr|| | |< |d }n|| | |< |d }|d }qT|t |k r|| | |< |d }|d }q|t |k r|| | |< |d }|d }qd S )Nr)   r   r   )r*   
merge_sort)r   r$   ZmidZlefthalfZ	righthalfijkr   r   r!   r.   F   s2    




r.   c                   @   s   e Zd ZdZdZee ddddZee	ddd	Z
d d
ddZdee	eed dddZee	eddddZeddddZdS )r%   zA utility class providing methods to alter the underlying cache in a list-like fashion.

    Once all adjustments are complete, the _cache, which really is a reference to
    the cache of a tree, will be sorted. Assuring it will be in a serializable state_cacheN)cacher(   c                 C   s
   || _ d S r   )r2   )selfr3   r   r   r!   __init__r   s    zTreeModifier.__init__)namer(   c                 C   s,   t | jD ]\}}|d |kr
|  S q
dS )z7:return: index of an item with name, or -1 if not foundr)   )	enumerater2   )r4   r6   r/   tr   r   r!   _index_by_nameu   s    
zTreeModifier._index_by_namer(   c                 C   s   t | jt | S )zCall this method once you are done modifying the tree information.
        It may be called several times, but be aware that each call will cause
        a sort operation
        :return self:)r.   r2   r-   r4   r   r   r!   set_done   s    zTreeModifier.set_doneF)shamoder6   forcer(   c                 C   s   d|krt d|d? tjkr*t d| t|}| |}|||f}|dkr\| j| n>|rl|| j|< n.| j| }|d |ks|d |krt d| | S )	aA  Add the given item to the tree. If an item with the given name already
        exists, nothing will be done, but a ValueError will be raised if the
        sha and mode of the existing item do not match the one you add, unless
        force is True

        :param sha: The 20 or 40 byte sha of the item to add
        :param mode: int representing the stat compatible mode of the item
        :param force: If True, an item with your name and information will overwrite
            any existing item with the same name, no matter which information it has
        :return: self/z$Name must not contain '/' characters   z(Invalid object type according to mode %or7   r   r   z)Item %r existed with different properties)
ValueErrorr   _map_id_to_typer   r:   r2   append)r4   r>   r?   r6   r@   indexitemZex_itemr   r   r!   add   s    


zTreeModifier.add)binshar?   r6   r(   c                 C   s<   t |trt |trt |ts"t|||f}| j| dS )zAdd the given item to the tree, its correctness is assumed, which
        puts the caller into responsibility to assure the input is correct.
        For more information on the parameters, see ``add``
        :param binsha: 20 byte binary shaN)
isinstancebytesintstrAssertionErrorr2   rE   )r4   rI   r?   r6   Z
tree_cacher   r   r!   add_unchecked   s    "
zTreeModifier.add_uncheckedc                 C   s   |  |}|dkr| j|= dS )z0Deletes an item with the given name if it existsr7   N)r:   r2   )r4   r6   rF   r   r   r!   __delitem__   s    
zTreeModifier.__delitem__)F)__name__
__module____qualname____doc__	__slots__r   TreeCacheTupr5   rM   rL   r:   r=   rK   boolrH   rO   rP   r   r   r   r!   r%   i   s   
$
r%   c                       sZ  e Zd ZU dZdZed ed< dZdZdZ	dZ
dZeee	ee
eiZeeee f ed	< ed
> dfdeeeedf d fddZeeeed ed f dddZedd fddZee ee dddZeedddZ eedddZ!e"e#d  d d!d"Z$e"e#e d d#d$Z%e"e&d d%d&Z'd'd( d)d( d*d+d,d-d,fe(eee)f ege*f e(eee)f ege*f ee*e*ee*eee ee) f d. fd/d0Z+e,e,e-e d1 fd2d3Z.eee#e d4d5d6Z/ee d d7d8Z0ed d9d:Z1eeee2f ed;d<d=Z3eeef e*d;d>d?Z4ee d d@dAZ5dBd dCdDdEZ6dBd dCdFdGZ7  Z8S )Hr   zTree objects represent an ordered list of Blobs and other Trees.

    ``Tree as a list``::

        Access a specific blob using the
        tree['filename'] notation.

        You may as well access by index
        blob = tree[0]
    treetyper2         
      rD   rB   Nr   )reporI   r?   pathc                    s   t t| |||| d S r   )superr   r5   )r4   r^   rI   r?   r_   	__class__r   r!   r5      s    zTree.__init__)r   .r   )index_objectr(   c                 C   s   |j dkrt||jS dS )NrX   r   )rY   tuple_iter_convert_to_objectr2   )clsrc   r   r   r!   _get_intermediate_items   s    
zTree._get_intermediate_items)attrr(   c                    s<   |dkr(| j j| j}t| | _ntt| 	| d S )Nr2   )
r^   ZodbstreamrI   r   readr2   r`   r   _set_cache_)r4   rh   Zostreamra   r   r!   rk      s    zTree._set_cache_)iterabler(   c                 c   sv   |D ]l\}}}t | j|}z | j|d?  | j|||V  W q tk
rn } ztd||f |W 5 d}~X Y qX qdS )zwIterable yields tuples of (binsha, mode, name), which will be converted
        to the respective object representationrB   z0Unknown mode %o found in tree data for path '%s'N)r   r_   rD   r^   KeyError	TypeError)r4   rl   rI   r?   r6   r_   er   r   r!   re      s     zTree._iter_convert_to_object)filer(   c           	   	   C   s   d}d|kr| }| }| d}t|D ]D\}}|| }|jdkrF|}q&|t|d krbt|| |  S q&|| krt|| |S | jD ]F}|d |kr| j|d d?  | j|d |d t| j	|d   S qt|| dS )	zFind the named object in this tree's contents
        :return: ``git.Blob`` or ``git.Tree`` or ``git.Submodule``

        :raise KeyError: if given file or tree does not exist in treezBlob or Tree named %r not foundrA   rX   r   r)   rB   r   N)
splitr8   rY   r*   rm   r2   rD   r^   r   r_   )	r4   rp   msgrX   rG   tokensr/   tokeninfor   r   r!   join  s0    



   
z	Tree.joinc                 C   s
   |  |S )zFor PY3 only)rv   )r4   rp   r   r   r!   __truediv__&  s    zTree.__truediv__r;   c                 C   s   dd | D S )z?:return: list(Tree, ...) list of trees directly below this treec                 S   s   g | ]}|j d kr|qS )rX   rY   .0r/   r   r   r!   
<listcomp>-  s     
 zTree.trees.<locals>.<listcomp>r   r<   r   r   r!   trees*  s    z
Tree.treesc                 C   s   dd | D S )z?:return: list(Blob, ...) list of blobs directly below this treec                 S   s   g | ]}|j d kr|qS )blobrx   ry   r   r   r!   r{   2  s     
 zTree.blobs.<locals>.<listcomp>r   r<   r   r   r!   blobs/  s    z
Tree.blobsc                 C   s
   t | jS )aM  
        :return: An object allowing to modify the internal cache. This can be used
            to change the tree's contents. When done, make sure you call ``set_done``
            on the tree modifier, or serialization behaviour will be incorrect.
            See the ``TreeModifier`` for more information on how to alter the cache)r%   r2   r<   r   r   r!   r3   4  s    z
Tree.cachec                 C   s   dS )NTr   r/   dr   r   r!   r"   ?  r#   zTree.<lambda>c                 C   s   dS )NFr   r   r   r   r!   r"   @  r#   r7   TFr   )	predicateprunedepthbranch_first
visit_onceignore_selfas_edger(   c              
      s0   t ttt tt f tt| ||||||S )zFor documentation, see util.Traversable._traverse()
        Trees are set to visit_once = False to gain more performance in the traversal)r   r   r   r   TraversedTreeTupr`   r   Z	_traverse)r4   r   r   r   r   r   r   r   ra   r   r!   traverse=  s    
zTree.traverse)argskwargsr(   c                    s   t t| j||S )z
        :return: IterableList with the results of the traversal as produced by
            traverse()
            Tree -> IterableList[Union['Submodule', 'Tree', 'Blob']]
        )r`   r   Z_list_traverse)r4   r   r   ra   r   r!   list_traverse`  s    zTree.list_traverse)r/   r0   r(   c                 C   s   t | | j|| S r   )listre   r2   )r4   r/   r0   r   r   r!   __getslice__j  s    zTree.__getslice__c                 C   s   |  | jS r   )re   r2   r<   r   r   r!   __iter__m  s    zTree.__iter__c                 C   s
   t | jS r   )r*   r2   r<   r   r   r!   __len__p  s    zTree.__len__)rG   r(   c                 C   sj   t |trF| j| }| j|d d?  | j|d |d t| j|d S t |trZ| |S t	d| d S )Nr   rB   r   r)   zInvalid index type: %r)
rJ   rL   r2   rD   r^   r   r_   rM   rv   rn   )r4   rG   ru   r   r   r!   __getitem__s  s    

2

zTree.__getitem__c                 C   sZ   t |tr,| jD ]}|j|d kr dS qn*| j}| jD ]}|t||d kr8 dS q8dS )Nr   Tr)   F)rJ   r   r2   rI   r_   r   )r4   rG   ru   r_   r   r   r!   __contains__  s    



zTree.__contains__c                 C   s   t | | jS r   )reversedre   r2   r<   r   r   r!   __reversed__  s    zTree.__reversed__r   )ri   r(   c                 C   s   t | j|j | S )a
  Serialize this tree into the stream. Please note that we will assume
        our tree data to be in a sorted state. If this is not the case, serialization
        will not generate a correct tree representation as these are assumed to be sorted
        by algorithms)r   r2   writer4   ri   r   r   r!   
_serialize  s    zTree._serializec                 C   s   t | | _| S r   )r   rj   r2   r   r   r   r!   _deserialize  s    zTree._deserialize)9rQ   rR   rS   rT   rY   r   __annotations__rU   Z	commit_idZblob_idZ
symlink_idtree_idr
   r	   rD   r   rL   r   r   rK   r   r   r5   classmethodr   rg   rM   rk   r   rV   r   re   rv   rw   propertyr   r|   r~   r%   r3   r   r   rW   r   r   r   r   r   r   r   slicer   r   r   r   r   __classcell__r   r   ra   r!   r      s|   
   
		"
#
r   )8Zgit.utilr   r   Zgit.diffZdiffZgit_diffr    r   baser   r   r}   r	   Zsubmodule.baser
   Zfunr   r   typingr   r   r   r   r   r   r   r   r   r   r   Z	git.typesr   r   Zgit.repor   ior   rK   rL   rM   rV   r   r$   r   __all__r-   r.   objectr%   ZDiffableZTraversableZSerializabler   rD   r   r   r   r   r!   <module>   s.    4	"#X e