o
    ﯪg`A                     @   s  d Z g dZddlmZ ddlZddlmZ ddlm	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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 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+m,Z,m-Z-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; ddl<m=Z= e7rddl>m?Z? ddl@mAZA ddlBmCZC eeB ZD	 e- ZEdeFde=deFfddZGdeFdeFfddZHdeFddd eFddfd!d"ZId#eJdeJfd$d%ZKde(fd&e6e:e+d'f  d(e4eL d)e:deLf d*e9e( ddf
d+d,ZMd(e4eL de8eJeJf fd-d.ZNd/e:e+e=eJf de8e=eJf fd0d1ZOd(e4eL de8eJe3e8e=eJf d'f eLeLf fd2d3ZP	dBd&e5e, d4d5d6eQd7eJde8eLe5d8 f f
d9d:ZRd;d8d<eJde+fd=d>ZSd4d5d?e6eL de5e+ fd@dAZTdS )CzVStandalone functions to accompany the index implementation and make it more
versatile.)write_cache
read_cachewrite_tree_from_cache	entry_keystat_mode_to_index_modeS_IFGITLINKrun_commit_hook	hook_path    )BytesION)Path)S_IFDIRS_IFLNKS_IFMTS_IFREGS_ISDIRS_ISLNKS_IXUSR)IStream)str_tree_type)handle_process_outputsafer_popen)defencforce_bytes
force_textsafe_decode)HookExecutionErrorUnmergedEntriesError)traverse_tree_recursivetraverse_trees_recursivetree_to_stream)IndexFileSHA1Writerfinalize_process   )BaseIndexEntry
IndexEntryCE_NAMEMASKCE_STAGESHIFT)packunpack)	DictIOListSequenceTYPE_CHECKINGTupleTypeUnioncast)PathLike)GitCmdObjectDB)TreeCacheTup)	IndexFile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)r6   r7    r<   I/var/www/html/chatdoc2/venv/lib/python3.10/site-packages/git/index/fun.pyr   >   s   r   pathc                 C   s   t | d S )Nr"   )r:   splitext)r>   r<   r<   r=   _has_file_extensionC   s   r@   indexr5   argsc              
   G   s&  t | |jj}t|tjsdS tj }tt	|j
|d< d|d< |g}z+tjdkr>t|s>t||jj }d|g}t|t| |tjtj|jjd}W n tyb } zt|||d}~ww g }	g }
t||	j|
jt d|	}d|
}|jd	krt|t}t|t}t||j||dS )
a:  Run the commit hook of the given name. Silently ignore hooks that do not exist.

    :param name:
        Name of hook, like ``pre-commit``.

    :param index:
        :class:`~git.index.base.IndexFile` instance.

    :param args:
        Arguments passed to hook file.

    :raise git.exc.HookExecutionError:
    NGIT_INDEX_FILE:
GIT_EDITORwin32zbash.exe)envstdoutstderrcwd r	   )r   repor7   osaccessX_OKenvironcopyr   strr>   sysplatformr@   r   relative_toworking_diras_posixr   list
subprocessPIPE	Exceptionr   r   appendr!   r;   
returncoder   r   )r6   rA   rB   hprG   cmdrelative_hpprocessexstdout_liststderr_listrH   rI   r<   r<   r=   r   G   s@   







r   modec                 C   s8   t | rtS t| st| tkrtS t| t@ rdpdB S )zZConvert the given mode from a stat call to the corresponding index mode and
    return it.i  i  )r   r   r   r   r   r   r   )re   r<   r<   r=   r   z   s
   r   entriesr$   streamextension_dataShaStreamClsc                 C   s  ||}|j }|j}d}|d |td|t|  | D ]a}| }	||j ||j t|j}
t|
t	d}t|t
@ }|t|ksIJ d|j ||jt@ B }|td|j|j|j|j|j|j|j|	 || | |	 d d@ }|d	|	| |    q|d
u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).
          DIRC>LL)encodingz"Path %s too long to fit into index>LLLLLL20sH       N)tellwriter'   lenctime_bytesmtime_bytesrR   r>   r   r   r%   flagsCE_NAMEMASK_INVdevinodere   uidgidsizebinsha	write_sha)rf   rg   rh   ri   
stream_sharr   rs   versionentrybeginoffsetpath_strr>   plenrw   	real_sizer<   r<   r=   r      sD   



r   c                 C   sX   |  d}|dkrtd| ttttf td|  d}|\}}|dv s(J ||fS )z>Return tuple(version_long, num_entries) from the given stream.   rk   zInvalid index file header: %rrl   ro   r"   rj   )readAssertionErrorr1   r.   intr(   )rg   type_idunpackedr   num_entriesr<   r<   r=   read_header   s   
r   r   c                  G   sD   t | dkr| d }t|tsJ |j|jfS ttttf | } | S )z
    :return:
        Key suitable to be used for the
        :attr:`index.entries <git.index.base.IndexFile.entries>` dictionary.

    :param entry:
        One instance of type BaseIndexEntry or the path and the stage.
    r"   r	   )	rt   
isinstancer#   r>   stager1   r.   r2   r   )r   entry_firstr<   r<   r=   r      s   r   c                 C   s0  t | \}}d}i }| j}| j}||k rs| }td|dd }td|dd }	td|d\}
}}}}}}}|t@ }||t}| | d d@ }||| |   t||||||	|
||||f}||||jf< |d7 }||k s| d}t	|d	ksJ 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 contents.
    r	   z>8sro   rn   .   rp   r"      zNIndex Footer was not at least a sha on content as it was only %i bytes in sizeiN)
r   r   rr   r(   r%   decoder   r$   r   rt   )rg   r   r   countrf   r   rr   r   ctimemtimery   inore   r{   r|   r}   sharw   	path_sizer>   r   r   rh   content_shar<   r<   r=   r      s2   

r   odbr3   slsir4   c                 C   sH  g }|j }|j}||k r| | }|jdkrt||d7 }|jd|}|dkr8||j|j|j|d f nH|j|| }	|}
|
|k rf| |
 }|jd|}|dks]|j|| |	kr^n|
d7 }
|
|k sEt	| |t
|d |
|d \}}||t|	f |
}||k st }t||j |d |ttt| |}|j|fS )aN  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 :class:`~git.index.typ.IndexEntry`\s.

    :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, name.
    r	   r"   /r   N)startstopr   r   r>   findr\   r~   re   r   slicer   r
   r   rs   seekstorer   r   rt   getvalue)rf   r   r   r   
tree_itemsciendr   rboundbasexioentryorboundr   _tree_entry_listsioistreamr<   r<   r=   r   %  s:   
  "

r   
tree_entryr   c                 C   s    t | d | d |t> | d fS )Nr"   r	   rj   )r#   r&   )r   r   r<   r<   r=   _tree_entry_to_baseindexentryj  s    r   	tree_shasc                 C   s  g }t |dv rt| |d dD ]
}|t|d q|S t |dkr+tdt | t| |dD ]\}}}|dur|dur|dur|d |d kr[|d |d kr[|d |d kss|d |d kr|d |d kr|d |d kr|t|d |t|d	 |t|d q1|d |d ks|d |d kr|t|d q1|t|d q1|d |d ks|d |d kr|t|d |t|d	 q1|du rq1|d |d ks|d |d kr|t|d |t|d q1|du r
|dusJ |t|d q1|du r|t|d q1|d |d ks*|d |d kr;|t|d	 |t|d q1|t|d q1|S )
a7  
    :return:
        List of :class:`~git.index.typ.BaseIndexEntry`\s 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   r   rK   r	      zCannot handle %i trees at onceNr"   rj   )rt   r   r\   r   
ValueErrorr   )r   r   outr   r   ourstheirsr<   r<   r=   aggressive_tree_mergen  sN   00   
	
$r   )r	   )U__doc____all__ior
   rM   os.pathr>   r:   pathlibr   statr   r   r   r   r   r   r   rY   rS   
gitdb.baser   	gitdb.typr   git.cmdr   r   
git.compatr   r   r   r   git.excr   r   git.objects.funr   r   r   git.utilr    r!   typr#   r$   r%   r&   utilr'   r(   typingr)   r*   r+   r,   r-   r.   r/   r0   r1   	git.typesr2   git.dbr3   git.objects.treer4   r   r5   r   rx   rR   r   r@   r   r   r   bytesr   r   r   r   r   r   r   r   r<   r<   r<   r=   <module>   s   $,3

E$
8
E"