o
    Uh [                     @   s  d Z ddlZ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 dd	lmZmZmZmZmZ d
ZdZdZdZdZdZeefZedddZdZdZdZdZG dd dedg dZde dede!e fddZ"de dedede!e#eef  fddZ$dd  Z%d>d"d#Z&d$d% Z'	!		!	!d?d&d'Z(de)fd(d)Z*d*d+ Z+	d@d,ed-e!e d.efd/d0Z,d1Z-d2ede.e/e/f fd3d4Z0d5d6 Z1d@d7d8Z2d9d: Z3G d;d< d<Z4e%Z5e$Z6e0Z7zdd=l8m0Z0m%Z%m$Z$ W dS  e9y   Y dS w )Az&Utilities for diffing files and trees.    N)defaultdict
namedtuple)BytesIO)chain)Optional   )BaseObjectStore)S_ISGITLINKObjectIDShaFileTree	TreeEntryaddmodifydeleterenamecopy	unchangedd   <      c                   @   s(   e Zd ZdZedd Zedd ZdS )
TreeChangez.Named tuple a single change between two trees.c                 C   s   | t t|S N)
CHANGE_ADD_NULL_ENTRY)clsnew r   e/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/diff_tree.pyr   6      zTreeChange.addc                 C   s   | t |tS r   )CHANGE_DELETEr   )r   oldr   r   r   r   :   r   zTreeChange.deleteN)__name__
__module____qualname____doc__classmethodr   r   r   r   r   r   r   3   s    
r   )typer!   r   pathtreereturnc                 C   s2   g }|s|S |j ddD ]
}|||  q|S )NT)
name_order)	iteritemsappendin_path)r(   r)   resultentryr   r   r   _tree_entries?   s   r1   tree1tree2c                 C   s  t | |}t | |}d }}t|}t|}g }	||k rc||k rc|| }
|| }|
j|jk r:|	|
tf |d7 }n!|
j|jkrL|	t|f |d7 }n|	|
|f |d7 }|d7 }||k rc||k s t||D ]}|	|| tf qht||D ]}|	t|| f qy|	S )a  Merge the entries of two trees.

    Args:
      path: A path to prepend to all tree entry names.
      tree1: The first Tree object to iterate, or None.
      tree2: The second Tree object to iterate, or None.

    Returns:
      A list of pairs of TreeEntry objects for each pair of entries in
        the trees. If an entry exists in one tree but not the other, the other
        entry will have all attributes set to None. If neither entry's path is
        None, they are guaranteed to match.
    r   r   )r1   lenr(   r-   r   range)r(   r2   r3   entries1entries2i1i2len1len2r/   entry1entry2ir   r   r   _merge_entriesH   s0   



r?   c                 C   s   | j }|d u r	dS t|S NF)modestatS_ISDIR)r0   rA   r   r   r   _is_trees   s   
rD   Fc                 c   s    |rt jpd}|rt jpd}td||td||fg}|rc| \}}t|}	t|}
|r7|	r7|
r7||kr7q|	r>| |j p?d}|
rG| |j pHd}|jpN|j}|tt	||| ||fV  |sdS dS )a  Recursively walk all the entries of two trees.

    Iteration is depth-first pre-order, as in e.g. os.walk.

    Args:
      store: An ObjectStore for looking up objects.
      tree1_id: The SHA of the first Tree object to iterate, or None.
      tree2_id: The SHA of the second Tree object to iterate, or None.
      prune_identical: If True, identical subtrees will not be walked.

    Returns:
      Iterator over Pairs of TreeEntry objects for each pair of entries
        in the trees and their subtrees recursively. If an entry exists in one
        tree but not the other, the other entry will have all attributes set
        to None. If neither entry's path is None, they are guaranteed to
        match.
    N    )
rB   S_IFDIRr   poprD   shar(   extendreversedr?   )storetree1_idtree2_idprune_identicalmode1mode2todor<   r=   is_tree1is_tree2r2   r3   r(   r   r   r   
walk_treesz   s    
rT   c                 C   s"   | j d u s|st| j rtS | S r   )rA   rB   rC   r   )r0   include_treesr   r   r   
_skip_tree   s   rV   c                 c   s    |dur|dur|dur|j ||||dE dH  dS t| ||| d}|D ]V\}}	||	kr1|s1q&t||}t|	|}	|tkrf|	tkrft|jt|	jkr\|s\t|V  t}t	}
n||	krct
}
nt}
n|tkrmt}
n|	tkrtt	}
nq&t|
||	V  q&dS )av  Find the differences between the contents of two trees.

    Args:
      store: An ObjectStore for looking up objects.
      tree1_id: The SHA of the source tree.
      tree2_id: The SHA of the target tree.
      want_unchanged: If True, include TreeChanges for unmodified entries
        as well.
      include_trees: Whether to include trees
      rename_detector: RenameDetector object for detecting renames.
      change_type_same: Whether to report change types in the same
        entry or as delete+add.

    Returns:
      Iterator over TreeChange instances for each change between the
        source and target tree.
    Nwant_unchangedrU   )rN   )changes_with_renamesrT   rV   r   rB   S_IFMTrA   r   r   r   CHANGE_UNCHANGEDCHANGE_MODIFYr    )rK   rL   rM   rX   rename_detectorrU   change_type_sameentriesr<   r=   change_typer   r   r   tree_changes   sD   


ra   c                 C   s    | D ]}|||kr dS qdS )NFTr   )seqkeyvalueer   r   r   _all_eq   s
   rf   c                 C   s   t | dd  ||| d S )Nr   r   )rf   )rb   rc   r   r   r   	_all_same   s   rg   rK   parent_tree_idstree_idc                 #   s    fdd|D }t | t fdd}t|D ]\}}|D ]}|jtkr.|jj}	n|jj}	|||	 |< q"qdd }
dd }t|	 D ]2\}}t | ksTJ d	d |D }t
||trjt||
si|V  qHt||ss|V  qHd
|vrz|V  qHd
S )aB  Get the tree changes for a merge tree relative to all its parents.

    Args:
      store: An ObjectStore for looking up objects.
      parent_tree_ids: An iterable of the SHAs of the parent trees.
      tree_id: The SHA of the merge tree.
      rename_detector: RenameDetector object for detecting renames.

    Returns:
      Iterator over lists of TreeChange objects, one per conflicted path
      in the merge.

      Each list contains one element per parent, with the TreeChange for that
      path relative to that parent. An element may be None if it never
      existed in one parent and was deleted in two others.

      A path is only included in the output if it is a conflict, i.e. its SHA
      in the merge tree is not found in any of the parents, or in the case of
      deletes, if not all of the old SHAs match.
    c                    s   g | ]
}t | d qS ))r]   )ra   ).0t)r]   rK   ri   r   r   
<listcomp>  s    z*tree_changes_for_merge.<locals>.<listcomp>c                      s
   d g  S r   r   r   )num_parentsr   r   <lambda>  s   
 z(tree_changes_for_merge.<locals>.<lambda>c                 S   s   | j jS r   )r!   rH   cr   r   r   old_sha!  s   z'tree_changes_for_merge.<locals>.old_shac                 S   s   | j S r   )r'   ro   r   r   r   r`   $  s   z+tree_changes_for_merge.<locals>.change_typec                 S   s   g | ]}|d ur|qS r   r   )rj   rp   r   r   r   rl   *  s    N)r4   r   	enumerater'   r    r!   r(   r   sorteditemsrf   rg   )rK   rh   ri   r]   all_parent_changeschanges_by_pathr>   parent_changeschanger(   rq   r`   _changeshaver   )rm   r]   rK   ri   r   tree_changes_for_merge   s<   




r|   @   objc                 C   s   t t}t }d}|j}|j}|j}|j}t| 	 D ]0}|
dd}	||	 |d7 }|	dks4|tkrL| }
|t|
  t|
7  < |d |  d}q|dkr`| }|t|  t|7  < |S )zCount the blocks in an object.

    Splits the data into blocks either on lines or <=64-byte chunks of lines.

    Args:
      obj: The object to count blocks for.

    Returns:
      A dict of block hashcode -> total bytes occurring.
    r   r   big   
)r   intr   writeseektruncategetvaluer   from_iterableas_raw_chunksto_bytes_BLOCK_SIZEhashr4   )r~   block_countsblocknblock_write
block_seekblock_truncateblock_getvaluerp   cbrd   
last_blockr   r   r   _count_blocks:  s,   r   c                 C   sP   t | t |kr|| } }d}|  D ]\}}||}|r%|t||7 }q|S )aZ  Count the number of common bytes in two block count dicts.

    Args:
      blocks1: The first dict of block hashcode -> total bytes.
      blocks2: The second dict of block hashcode -> total bytes.

    Returns:
      The number of bytes in common between blocks1 and blocks2. This is
      only approximate due to possible hash collisions.
    r   )r4   rt   getmin)blocks1blocks2scorer   count1count2r   r   r   _common_bytes_  s   

r   c                 C   s   |du ri }| j |vrt| || j < |j |vrt|||j < t|| j  ||j  }t|  | }|s6tS tt|t | S )a  Compute a similarity score for two objects.

    Args:
      obj1: The first object to score.
      obj2: The second object to score.
      block_cache: An optional dict of SHA to block counts to cache
        results between calls.

    Returns:
      The similarity score between the two objects, defined as the
        number of bytes in common between the two objects divided by the
        maximum size, scaled to the range 0-100.
    N)idr   r   max
raw_length
_MAX_SCOREr   float)obj1obj2block_cachecommon_bytesmax_sizer   r   r   _similarity_scoreu  s   

r   c                 C   s0   | j j}| jj}|d u r|}|d u r|}||fS r   )r!   r(   r   )r0   path1path2r   r   r   _tree_change_key  s   r   c                   @   s   e Zd ZU dZee ed< ee ed< ee ed< eeeef  ed< e	e
edf	d'd	d
Zd'ddZdd Zd'ddZd'ddZd'ddZd'ddZdd Zdd Zd'ddZd'ddZd'dd Zd!d" Zd'd#d$Z	d(d%d&ZdS ))RenameDetectorz7Object for handling rename detection between two trees._adds_deletes_changes_candidatesFr*   Nc                 C   s(   || _ || _|| _|| _|| _d| _dS )a  Initialize the rename detector.

        Args:
          store: An ObjectStore for looking up objects.
          rename_threshold: The threshold similarity score for considering
            an add/delete pair to be a rename/copy; see _similarity_score.
          max_files: The maximum number of adds and deletes to consider,
            or None for no limit. The detector is guaranteed to compare no more
            than max_files ** 2 add/delete pairs. This limit is provided
            because rename detection can be quadratic in the project size. If
            the limit is exceeded, no content rename detection is attempted.
          rewrite_threshold: The threshold similarity score below which a
            modify should be considered a delete/add, or None to not break
            modifies; see _similarity_score.
          find_copies_harder: If True, consider unmodified files when
            detecting copies.
        FN)_store_rename_threshold_rewrite_threshold
_max_files_find_copies_harder_want_unchanged)selfrK   rename_threshold	max_filesrewrite_thresholdfind_copies_harderr   r   r   __init__  s   
zRenameDetector.__init__c                 C   s   g | _ g | _g | _d S r   )r   r   r   r   r   r   r   _reset  s   
zRenameDetector._resetc                 C   sT   | j d u s|jtks|jj|jjkrdS | j|jj }| j|jj }t||| j k S r@   )r   r'   r\   r!   rH   r   r   r   )r   rx   old_objnew_objr   r   r   _should_split  s   

zRenameDetector._should_splitc                 C   s   |j tkr| j| d S |j tkr| j| d S | |r5| jt|j	 | jt
|j d S | jr=|j tksB|j tkrJ| j| d S | j| d S r   )r'   r   r   r-   r    r   r   r   r   r!   r   r   r   r[   r\   r   )r   rx   r   r   r   _add_change  s   




zRenameDetector._add_changec                 C   s6   | j p| j}t| j|||| jdD ]}| | qd S )NrW   )r   r   ra   r   _include_treesr   )r   rL   rM   rX   rx   r   r   r   _collect_changes  s   
zRenameDetector._collect_changesc                    s0    fdd| j D | _ fdd| jD | _d S )Nc                       g | ]
}|j j vr|qS r   r   r(   rj   a)	add_pathsr   r   rl         z)RenameDetector._prune.<locals>.<listcomp>c                    r   r   r!   r(   rj   d)delete_pathsr   r   rl     r   )r   r   )r   r   r   r   )r   r   r   _prune  s   zRenameDetector._prunec                 C   sZ  t t}| jD ]}||jj |j qt t}| jD ]}|jtk}||j	j |j	|f qt
 }t
 }| D ]k\}}	|| }
t|	|
D ]1\\}}}t|jt|jkrYqF|ra||j ||j |rktplt}| jt||| qFt|
t|	 }|	d d }|dkr|
| d  D ]}||j | jtt|| qq9| || d S )Nr   )r   listr   r   rH   r-   r   r'   r    r!   setrt   ziprB   rZ   rA   r   r(   CHANGE_RENAMECHANGE_COPYr   r   r4   r   )r   add_mapr   
delete_mapr   	is_deleter   r   rH   sha_deletessha_addsr!   r   new_typenum_extra_addsr   r   r   _find_exact_renames  s6   


z"RenameDetector._find_exact_renamesc                 C   s   t | jt | j | jd kS )N   )r4   r   r   r   r   r   r   r   _should_find_content_renames  s   z+RenameDetector._should_find_content_renamesc                 C   s*   |r|j j|jjkrtS |jtkrtS tS r   )r!   r(   r   r\   r'   r    r   r   )r   check_pathsr   r   r   r   r   _rename_type  s
   
zRenameDetector._rename_typec                 C   s   g  }| _ |  sd S i }| jd u}| jD ]W}t|jjrq|jj}| j| }t	|||< | j
D ];}t|jjt|jjkrAq0| j|jj }t|||d}	|	| jkrk| |||}
t|
|j|j}||	 |f q0qd S )N)r   )r   r   r   r   r	   r!   rA   rH   r   r   r   rB   rZ   r   r   r   r   r-   )r   
candidatesr   r   r   rq   r   r   r   r   r   r   r   r   r   _find_content_rename_candidates&  s.   





z.RenameDetector._find_content_rename_candidatesc                 C   s   | j   t }t }| j D ]4\}}|jj}||v rq|jj}|j}||v r.tt|j|j}|tkr7|	| |	| | j
| q| || d S r   )r   sortr   r   r(   r!   r'   r   r   r   r   r-   r   )r   r   r   ry   rx   new_pathold_path	orig_typer   r   r   _choose_content_renamesC  s    


z&RenameDetector._choose_content_renamesc                    s   | j d u rd S i  dd | jD }| jD ]'}|jj}||}|d ur;t|jj	t|jj	kr;t
t|j|j |< q fdd| jD | _ fdd| jD | _|  j  7  _d S )Nc                 S   s   i | ]}|j j|qS r   r   r   r   r   r   
<dictcomp>`  s    z1RenameDetector._join_modifies.<locals>.<dictcomp>c                    r   r   r   r   modifiesr   r   rl   i  r   z1RenameDetector._join_modifies.<locals>.<listcomp>c                    r   r   r   r   r   r   r   rl   j  r   )r   r   r   r   r(   r   rB   rZ   r!   rA   r   r\   r   values)r   r   r   r(   r   r   r   r   _join_modifies[  s   


zRenameDetector._join_modifiesc                 C   s8   g }| | j | | j | | j |jtd |S )N)rc   )rI   r   r   r   r   r   )r   r/   r   r   r   _sorted_changesm  s   zRenameDetector._sorted_changesc                 C   s    | j rd S dd | jD | _d S )Nc                 S   s   g | ]	}|j tkr|qS r   )r'   r[   r   r   r   r   rl   x  s    z3RenameDetector._prune_unchanged.<locals>.<listcomp>)r   r   r   r   r   r   _prune_unchangedu  s   zRenameDetector._prune_unchangedc                 C   sP   |    || _|| _| || |   |   |   |   |   | 	 S )zAIterate TreeChanges between two tree SHAs, with rename detection.)
r   r   r   r   r   r   r   r   r   r   )r   rL   rM   rX   rU   r   r   r   rY   z  s   z#RenameDetector.changes_with_renames)r*   N)FF)r"   r#   r$   r%   r   r   __annotations__tupler   RENAME_THRESHOLD	MAX_FILESREWRITE_THRESHOLDr   r   r   r   r   r   r   r   r   r   r   r   r   r   rY   r   r   r   r   r     s8   
 

 



!



r   )r   rD   r?   )F)FNFFr   ):r%   rB   collectionsr   r   ior   	itertoolsr   typingr   object_storer   objectsr	   r
   r   r   r   r   r\   r    r   r   r[   RENAME_CHANGE_TYPESr   r   r   r   r   r   bytesr   r1   r   r?   rD   rT   rV   ra   boolrf   rg   r|   r   dictr   r   r   r   r   r   _is_tree_py_merge_entries_py_count_blocks_pydulwich._diff_treeImportErrorr   r   r   r   <module>   s   	
+
%

E
B%
 p