B
    %d@              	   @   s  d dl mZ d dlmZ d dlZd dlmZmZmZm	Z	m
Z
mZmZ d dlZd dlmZmZ d dlmZmZmZmZmZm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 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- ddl.m/Z/m0Z0 d dl1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z: d dl;m<Z< e6r^ddl=m>Z> d dl?m@Z@ d dlAmBZB eeB ZCe, ZDdZEeFe<eFdddZGdd ZHeFdeFddddZIeJeJddd ZKde fe5e9e*d!f  e3eL e9deLf e8e  dd"d#d$ZMe3eL e7eJeJf d%d&d'ZNe9e*e<eJf e7e<eJf d(d)d*ZOe3eL e7eJe2e7e<eJf d!f eLeLf d%d+d,ZPd8e4e+ d-eQeJe7eLe4d. f d/d0d1ZRd.eJe*d2d3d4ZSd-e5eL e4e* d5d6d7ZTdS )9    )BytesIO)PathN)S_IFDIRS_IFLNKS_ISLNKS_ISDIRS_IFMTS_IFREGS_IXUSR)PROC_CREATIONFLAGShandle_process_output)defenc
force_textforce_bytesis_posixis_winsafe_decode)UnmergedEntriesErrorHookExecutionError)tree_to_streamtraverse_tree_recursivetraverse_trees_recursive)IndexFileSHA1Writerfinalize_process)IStream)str_tree_type   )BaseIndexEntry
IndexEntryCE_NAMEMASKCE_STAGESHIFT)packunpack)	DictIOListSequenceTYPE_CHECKINGTupleTypeUnioncast)PathLike)	IndexFile)GitCmdObjectDB)TreeCacheTup)write_cache
read_cachewrite_tree_from_cache	entry_keystat_mode_to_index_modeS_IFGITLINKrun_commit_hook	hook_path)namegit_dirreturnc             C   s   t |d| S )zK:return: path to the given named hook in the given git repository directoryhooks)ospjoin)r8   r9    r>   Z/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/git/index/fun.pyr7   J   s    r7   c             C   s   t | d S )Nr   )r<   splitext)pathr>   r>   r?   _has_file_extensionO   s    rB   r-   )r8   indexargsr:   c          
   G   s2  t | |jj}t|tjs dS tj }tt	|j
|d< d|d< |g}yVtrvt|svt||jj }d|g}tj|t| |tjtj|jjttd}W n. tk
r } zt|||W dd}~X Y n`X g }g }	t||j|	jt d|}
d|	}|jdkr.t|
t}
t|t}t||j||
dS )	zRun the commit hook of the given name. Silently ignores hooks that do not exist.

    :param name: name of hook, like 'pre-commit'
    :param index: IndexFile instance
    :param args: arguments passed to hook file
    :raises HookExecutionError:NZGIT_INDEX_FILE:Z
GIT_EDITORzbash.exe)envstdoutstderrcwd	close_fdscreationflags r   ) r7   repor9   osaccessX_OKenvironcopyr   strrA   r   rB   r   relative_toZworking_diras_posix
subprocessPopenlistPIPEr   r   	Exceptionr   r   appendr   r=   
returncoder   r   )r8   rC   rD   hprF   cmdZrelative_hpexZstdout_listZstderr_listrG   rH   r>   r>   r?   r6   S   s<    





r6   )moder:   c             C   s8   t | rtS t| s t| tkr$tS t| t@ r2dp4dB S )zYConvert the given mode from a stat call to the corresponding index mode
    and return iti  i  )r   r   r   r   r5   r	   r
   )r`   r>   r>   r?   r4      s
    r4   r   )entriesstreamextension_dataShaStreamClsr:   c             C   s   ||}|j }|j}d}|d |td|t|  x| D ]}| }	||j ||j t|j}
t|
t	d}t|t
@ }|t|kstd|j ||jt@ B }|td|j|j|j|j|j|j|j|	 || | |	 d d@ }|d	|	| |    q:W |d
k	r|| |  d
S )a  Write the cache represented by entries to a stream

    :param entries: **sorted** list of entries
    :param stream: stream to wrap into the AdapterStreamCls - it is used for
        final output.

    :param ShaStreamCls: Type to use when writing to the stream. It produces a sha
        while writing to it, before the data is passed on to the wrapped stream

    :param extension_data: any kind of data to write as a trailer, it must begin
        a 4 byte identifier, followed by its size ( 4 bytes )   s   DIRCz>LL)encodingz"Path %s too long to fit into indexz>LLLLLL20sH   i    N)tellwriter!   lenZctime_bytesZmtime_bytesrS   rA   r   r   r   AssertionErrorflagsCE_NAMEMASK_INVdevinoder`   uidgidsizebinshaZ	write_sha)ra   rb   rc   rd   Z
stream_shari   rj   versionentrybeginoffsetZpath_strrA   plenrm   	real_sizer>   r>   r?   r0      s@    





r0   )rb   r:   c             C   sX   |  d}|dkrtd| ttttf td|  d}|\}}|dksPt||fS )z=Return tuple(version_long, num_entries) from the given stream   s   DIRCzInvalid index file header: %rz>LLrg   )r   re   )readrl   r+   r(   intr"   )rb   Ztype_idunpackedru   num_entriesr>   r>   r?   read_header   s    
r   )rv   r:   c              G   sH   t | dkr.| d }t|ts"t|j|jfS tttt	f | } | S dS )z:return: Key suitable to be used for the index.entries dictionary
    :param entry: One instance of type BaseIndexEntry or the path and the stager   r   N)
rk   
isinstancer   rl   rA   stager+   r(   r,   r|   )rv   Zentry_firstr>   r>   r?   r3      s    r3   c             C   s0  t | \}}d}i }| j}| j}x||k r| }td|dd }td|dd }	td|d\}
}}}}}}}|t@ }||t}| | d d@ }||| |   t||||||	|
||||f}||||jf< |d7 }q"W | d}t	|d	kst
d
t	| |dd }|dd }||||fS )a  Read a cache file from the given stream

    :return: tuple(version, entries_dict, extension_data, content_sha)

      * version is the integer version number
      * entries dict is a dictionary which maps IndexEntry instances to a path at a stage
      * extension_data is '' or 4 bytes of type + 4 bytes of size + size bytes
      * content_sha is a 20 byte sha on all cache file contentsr   z>8srg   z>LLLLLL20sH.   ir      zNIndex Footer was not at least a sha on content as it was only %i bytes in sizeiN)r   r{   ri   r"   r   decoder   r   r   rk   rl   )rb   ru   r~   countra   r{   ri   rw   ctimemtimero   inor`   rq   rr   rs   sharm   Z	path_sizerA   ry   rv   rc   Zcontent_shar>   r>   r?   r1      s.    
	
r1   r.   r/   )ra   odbslsir:   c             C   sF  g }|j }|j}x||k r| | }|jdkr6t||d7 }|jd|}|dkrt||j|j|j|d f q|j|| }	|}
xF|
|k r| |
 }|jd|}|dks|j|| |	krP |
d7 }
qW t	| |t
|d |
|d \}}||t|	f |
}qW t }t||j |d |ttt| |}|j|fS )a  Create a tree from the given sorted list of entries and put the respective
    trees into the given object database

    :param entries: **sorted** list of IndexEntries
    :param odb: object database to store the trees in
    :param si: start index at which we should start creating subtrees
    :param sl: slice indicating the range we should process on the entries list
    :return: tuple(binsha, list(tree_entry, ...)) a tuple of a sha and a list of
        tree entries being a tuple of hexsha, mode, namer   r   /r   N)startstopr   r   rA   findr[   rt   r`   r2   slicer   r   r   rj   seekstorer   r   rk   getvalue)ra   r   r   r   Z
tree_itemsciendrv   ZrboundbasexiZoentryZorboundr   Z_tree_entry_listsioZistreamr>   r>   r?   r2     s6    
 
 
r2   )
tree_entryr   r:   c             C   s    t | d | d |t> | d fS )Nr   r   re   )r   r    )r   r   r>   r>   r?   _tree_entry_to_baseindexentryX  s    r   )r   	tree_shasr:   c             C   s  g }t |dkr>x(t| |d dD ]}|t|d q"W |S t |dkrZtdt | xNt| |dD ]<\}}}|dk	r|dk	r|dk	rt|d |d kr|d |d kr|d |d ks|d |d kr,|d |d kr,|d |d kr,|t|d |t|d	 |t|d nF|d |d ksP|d |d krb|t|d n|t|d nD|d |d ks|d |d kr
|t|d |t|d	 nP|dkrnD|d |d ks|d |d kr|t|d |t|d qj|dkr6|dk	s$t|t|d qj|dkrR|t|d qj|d |d ksv|d |d kr|t|d	 |t|d qj|t|d qjW |S )
a  
    :return: list of BaseIndexEntries representing the aggressive merge of the given
        trees. All valid entries are on stage 0, whereas the conflicting ones are left
        on stage 1, 2 or 3, whereas stage 1 corresponds to the common ancestor tree,
        2 to our tree and 3 to 'their' tree.
    :param tree_shas: 1, 2 or 3 trees as identified by their binary 20 byte shas
        If 1 or two, the entries will effectively correspond to the last given tree
        If 3 are given, a 3 way merge is performed)r   re   r   rL   r      zCannot handle %i trees at onceNr   re   )rk   r   r[   r   
ValueErrorr   rl   )r   r   outrv   r   ZoursZtheirsr>   r>   r?   aggressive_tree_merge\  sJ    	


06$$
$	

$r   )r   )Uior   pathlibr   rN   statr   r   r   r   r   r	   r
   rV   Zgit.cmdr   r   Z
git.compatr   r   r   r   r   r   Zgit.excr   r   Zgit.objects.funr   r   r   Zgit.utilr   r   Z
gitdb.baser   Z	gitdb.typr   os.pathrA   r<   typr   r   r   r    utilr!   r"   typingr#   r$   r%   r&   r'   r(   r)   r*   r+   Z	git.typesr,   r   r-   Zgit.dbr.   Zgit.objects.treer/   r5   rn   __all__rS   r7   rB   r6   r|   r4   bytesr0   r   r3   r1   r   r2   r   r   r>   r>   r>   r?   <module>   sL   $	 ,.(;"*38