U
    )3g                     @   s  U d dl Z dddddddd	d
dddddddddgZe jdkrFed d dlmZ d dlZd dlmZ d dl	Z	d dl
Z
d dlZd dlmZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlmZmZ d dlZd dl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%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 e1rd dl6m7Z7 d dl8m9Z9m:Z: d dl;m<Z< d dl=m>Z> d dl?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZH e2d e3d! d"d#ZIe
JeKZLeMeNeNd$d%d&ZOeMeNeNd$d'd(ZPePdd"ZQePd)d"ZRe2d*ZSe'd+eSf e'd+eSf d,d-dZTejUeDe)eDddf d.d/d0ZVejUeMeMe)d1 d2d3d4ZWeDdd5d6dZXeDdd5d7d8ZYde&e&eZeZd:d;dZ[eDeDeDd<d=dZ\e jdkreDeDd5d>dZ]eDeMd5d?dZ^e]Z_neDeMd5d@dZ^e^Z_eDeDeDd<dAdZ`deDeNeNdCdDdZae/eM dEdFdGZbdeMe-eD e,eM dHdIdJZce-eM eMeMdKdLdMZdeedNdOdP dBfeedQeddBfeedReddBfeedSejfdTdP d"feedUdVdP dBffZge0e0e.eM e'eNf d+f ehdW< eMeMd5dXdYZieedZZjeDeMd5d[d\Zki Zle(eMe-eN f ehd]< eMeNd^d_d`Zme5deCdB d^dadbZne5eDeNd^dcdbZne3deDf eNd^dddbZneMdEdedZoe3ejpdff e$ddgdhdiZqe5ddeNddjdkdlZre5deDeNeMdjdmdlZrde3deDf eNe-eD djdndlZre/eM e,eM dodpdqZsG drd dZtG dsd detZuG dtd dZvG dud dZwG dvd dZxG dwd dZyG dxd
 d
eyZzG dyd	 d	e,eI Z{eHG dzd deEZ|G d{d| d|e}Z~G d}d~ d~e~dZdS )    Nstream_copy	join_pathto_native_path_linuxjoin_path_nativeStatsIndexFileSHA1WriterIterableObjIterableListBlockingLockFileLockFileActorget_user_idassure_directory_existsRemoteProgressCallableRemoteProgressrmtreeunbare_repoHIDE_WINDOWS_KNOWN_ERRORSwin32to_native_path_windows)abstractmethod)wraps)urlsplit
urlunsplit)		LazyMixinLockedFD
bin_to_hexfile_contents_rofile_contents_ro_filepath
hex_to_binmake_sha
to_bin_sha
to_hex_sha)AnyAnyStrBinaryIOCallableDict	GeneratorIOIteratorListOptionalPatternSequenceTupleTYPE_CHECKINGTypeVarUnioncastoverload)Git)GitConfigParserSectionConstraint)Remote)Repo)	Files_TDHas_id_attributeHSH_TDLiteralPathLikeProtocolSupportsIndexTotal_TDruntime_checkableT_IterableObj)r   r;   T)bound	covariant)namedefaultreturnc                 C   sl   zt j|  }W n tk
r&   | Y S X td|  |  }|dkrLdS |dkrXdS td| || |S )zRead a boolean flag from an environment variable.

    :return:
        The flag, or the `default` value if absent or ambiguous.
    zlThe %s environment variable is deprecated. Its effect has never been documented and changes without warning.>    falseno0F>   1yestrueTz-%s has unrecognized value %r, treating as %r.)osenvironKeyError_loggerwarningstriplower)rF   rG   valueZadjusted_value rX   ,/tmp/pip-unpacked-wheel-3opeica4/git/util.py_read_env_flags   s    
rZ   c                 C   s   t jdkot| |S )a  Read a boolean flag from an environment variable on Windows.

    :return:
        On Windows, the flag, or the `default` value if absent or ambiguous.
        On all other operating systems, ``False``.

    :note:
        This only accesses the environment on Windows.
    r   )sysplatformrZ   )rF   rG   rX   rX   rY   _read_win_env_flag   s    
r]   HIDE_WINDOWS_FREEZE_ERRORST.)funcrH   c                    s2   ddl m  tdtttd fdd}|S )ztMethods with this decorator raise :exc:`~git.exc.InvalidGitRepositoryError` if
    they encounter a bare repository.   )InvalidGitRepositoryErrorr8   )selfargskwargsrH   c                    s&   | j jr dj | f||S )Nz/Method '%s' cannot operate on bare repositories)repoZbare__name__rc   rd   re   rb   r`   rX   rY   wrapper   s    zunbare_repo.<locals>.wrapper)excrb   r   r#   r_   )r`   rj   rX   ri   rY   r      s    )new_dirrH   c              	   c   s.   t  }t |  z
| V  W 5 t | X dS )zContext manager to temporarily change directory.

    This is similar to :func:`contextlib.chdir` introduced in Python 3.11, but the
    context manager object returned by a single call to this function is not reentrant.
    N)rP   getcwdchdir)rl   Zold_dirrX   rX   rY   cwd   s
    

ro   )NNN)rF   rW   rH   c              	   c   sB   t | }|t j| < z
dV  W 5 |dkr2t j| = n
|t j| < X dS )z=Context manager to temporarily patch an environment variable.N)rP   getenvrQ   )rF   rW   	old_valuerX   rX   rY   	patch_env   s    



rr   )pathrH   c                 C   sV   t ttdddd}tjdkr*t|  n(tjdkrDtj| |d ntj| |d dS )	zRemove the given directory tree recursively.

    :note:
        We use :func:`shutil.rmtree` but adjust its behaviour to see whether files that
        couldn't be deleted are read-only. Windows will not remove them in that case.
    N)functionrs   _excinforH   c              
   S   sd   t |tj z| | W nD tk
r^ } z&trLddlm} |d| | W 5 d}~X Y nX dS )zuCallback for :func:`shutil.rmtree`.

        This works as either a ``onexc`` or ``onerror`` style callback.
        r   )SkipTestz%FIXME: fails with: PermissionError
  N)rP   chmodstatS_IWUSRPermissionErrorr   Zunittestrv   )rt   rs   ru   exrv   rX   rX   rY   handler   s    zrmtree.<locals>.handlerr   )      )Zonexc)onerror)r&   r>   r#   r[   r\   shutilr   version_info)rs   r|   rX   rX   rY   r      s    

c                 C   s.   t | r*tjdkr t| d t|  dS )zWEnsure file deleted also on *Windows* where read-only files need special
    treatment.r   i  N)ospisfiler[   r\   rP   rw   removers   rX   rX   rY   rmfile   s    

r      )sourcedestination
chunk_sizerH   c                 C   s8   d}|  |}|| |t|7 }t||k rq4q|S )zCopy all data from the `source` stream into the `destination` stream in chunks
    of size `chunk_size`.

    :return:
        Number of bytes written
    r   )readwritelen)r   r   r   brchunkrX   rX   rY   r      s    

)aprH   c                 G   sh   t | }|D ]V}t |}|sq|dr:||dd 7 }q|dksL|drV||7 }q|d| 7 }q|S )zmJoin path tokens together similar to osp.join, but always use ``/`` instead of
    possibly ``\`` on Windows./ra   NrI   )str
startswithendswith)r   r   rs   brX   rX   rY   r     s    

c                 C   s   t | } | ddS )Nr   \r   replacer   rX   rX   rY   r   $  s    c                 C   s   t | } | ddS )Nr   r   r   r   rX   rX   rY   r   (  s    c                 C   s   t | S N)r   r   rX   rX   rY   r   /  s    c                 G   s   t t| f| S )zLike :func:`join_path`, but makes sure an OS native path is returned.

    This is only needed to play it safe on Windows and to ensure nice paths that only
    use ``\``.
    )to_native_pathr   )r   r   rX   rX   rY   r   5  s    F)rs   is_filerH   c                 C   s.   |rt | } t | s*tj| dd dS dS )a$  Make sure that the directory pointed to by path exists.

    :param is_file:
        If ``True``, `path` is assumed to be a file and handled correctly.
        Otherwise it must be a directory.

    :return:
        ``True`` if the directory was created, ``False`` if it already existed.
    T)exist_okF)r   dirnameisdirrP   makedirs)rs   r   rX   rX   rY   r   >  s    


rH   c                  C   sB   t jdd } | r,tdd | t jD S tjdkr:dS dS d S )NPATHEXTc                 s   s   | ]}|  V  qd S r   )upper).0r   rX   rX   rY   	<genexpr>T  s     z&_get_exe_extensions.<locals>.<genexpr>r   )z.BATZCOMz.EXErX   )rP   rQ   gettuplesplitpathsepr[   r\   )r   rX   rX   rY   _get_exe_extensionsQ  s    
r   )programrs   rH   c                    s   t  ttdfdd}g }|s,tjd }t|tjD ]N}|d}|r<t	||   g fddD  D ]}||rr|
| qrq<|S )a6  Perform a path search to assist :func:`is_cygwin_git`.

    This is not robust for general use. It is an implementation detail of
    :func:`is_cygwin_git`. When a search following all shell rules is needed,
    :func:`shutil.which` can be used instead.

    :note:
        Neither this function nor :func:`shutil.which` will predict the effect of an
        executable search on a native Windows system due to a :class:`subprocess.Popen`
        call without ``shell=True``, because shell and non-shell executable search on
        Windows differ considerably.
    )fpathrH   c                    s>   t  o<t tjo<tjdkp< p<t fddD S )Nr   c                 3   s   | ]}   |V  qd S r   )r   r   )r   extr   rX   rY   r   p  s     z,py_where.<locals>.is_exec.<locals>.<genexpr>)r   r   rP   accessX_OKr[   r\   anyr   )winprog_extsr   rY   is_execk  s
    
$zpy_where.<locals>.is_execPATH"c                    s   g | ]}d  |f qS )z%s%srX   )r   e)exe_pathrX   rY   
<listcomp>{  s     zpy_where.<locals>.<listcomp>)r   r   boolrP   rQ   r   r   rU   r   joinappend)r   rs   r   ZprogsfolderfrX   )r   r   rY   py_where[  s    	

r   )drivers   rH   c                 C   st   t |r| s|}nL|o,t t t |}t |rL| rB|}q`t|}n| r`d|  |f }t|}|ddS )Nz/proc/cygdrive/%s/%sr   r   )	r   isabsnormpath
expandvars
expandusercygpathrV   r   r   )r   rs   r   Zp_strrX   rX   rY   
_cygexpath  s    

r   z*\\\\\?\\UNC\\([^\\]+)\\([^\\]+)(?:\\(.*))?c                 C   s   d| || ddf S )Nz
//%s/%s/%sr   r   )r   )serverZshare	rest_pathrX   rX   rY   <lambda>      r   z\\\\\?\\(\w):[/\\](.*)z(\w):[/\\](.*)z	file:(.*)c                 C   s   | S r   rX   )r   rX   rX   rY   r     r   z(\w{2,}:.*)c                 C   s   | S r   rX   )urlrX   rX   rY   r     r   _cygpath_parsersc                 C   sZ   t | } | dsVtD ]4\}}}|| }|r||  } |rFt| }  qVqtd| } | S )zJUse :meth:`git.cmd.Git.polish_url` instead, that works on any environment.)z	/cygdrivez//z/proc/cygdriveN)r   r   r   matchgroupsr   r   )rs   regexparserZrecurser   rX   rX   rY   r     s    


r   z(?:/proc)?/cygdrive/(\w)(/.*)?c                 C   sB   t | } t| }|r6| \}}d| |p0df } | ddS )Nz%s:%srI   r   r   )r   _decygpath_regexr   r   r   r   )rs   mr   r   rX   rX   rY   	decygpath  s    
r   _is_cygwin_cache)git_executablerH   c           	   
   C   s   t | }|d krd}zdt| }|sDt| }|r@t|d nd}t|d}tj|gtjdd}|	 \}}d|k}W n. t
k
r } ztd| W 5 d }~X Y nX |t | < |S )	NFr   rI   unameT)stdoutuniversal_newlinesZCYGWINz/Failed checking if running in CYGWIN due to: %r)r   r   r   r   r   r   
subprocessPopenPIPEcommunicate	ExceptionrS   debug)	r   Z	is_cygwingit_dirresZ	uname_cmdprocessZ	uname_out_r{   rX   rX   rY   _is_cygwin_git  s     

r   c                 C   s   d S r   rX   r   rX   rX   rY   is_cygwin_git  s    r   c                 C   s   d S r   rX   r   rX   rX   rY   r     s    c                 C   s*   t jdkrdS | d krdS tt| S d S )Nr   F)r[   r\   r   r   r   rX   rX   rY   r     s
    
c                   C   s   dt  t f S )zM:return: String identifying the currently active system user as ``name@node``z%s@%s)getpassgetuserr\   noderX   rX   rX   rY   r     s    zGit.AutoInterrupt)procre   rH   c                 K   s   | j f | dS )zXWait for the process (clone, fetch, pull or push) and handle its errors
    accordingly.N)wait)r   re   rX   rX   rY   finalize_process  s    r   )r   expand_varsrH   c                 C   s   d S r   rX   r   r   rX   rX   rY   expand_path  s    r   c                 C   s   d S r   rX   r   rX   rX   rY   r     s    c                 C   sZ   t | tjr|  S z*t| } |r.t| } tt| W S  t	k
rT   Y d S X d S r   )

isinstancepathlibPathresolver   r   r   r   abspathr   r   rX   rX   rY   r     s    

)cmdlinerH   c              	   C   s   g }t | D ]\}}|| ztt|}|jdkr@|jdkr@W q|jdk	rb|j|j|jdd}|jdk	r|j|j|jdd}t|||< W q t	k
r   Y qY qX q|S )a>  Parse any command line argument and if one of the elements is an URL with a
    username and/or password, replace them by stars (in-place).

    If nothing is found, this just returns the command line as-is.

    This should be used for every log line that print a command line, as well as
    exception messages.
    Nz*****)netloc)
	enumerater   r   passwordusername_replacer   r   r   
ValueError)r   Znew_cmdlineindexZto_parser   rX   rX   rY   remove_password_if_present  s    	


r   c                	   @   s   e Zd ZU dZdZeed< dd eeD \	ZZ	Z
ZZZZZZee	B Ze ZdZdZdZed	Zed
ZddddZeddddZeegdf dddZeddddZ dee!ee"f e!ee"df eddddZ#dS )r   zHandler providing an interface to parse progress information emitted by
    :manpage:`git-push(1)` and :manpage:`git-fetch(1)` and to dispatch callbacks
    allowing subclasses to react to the progress.	   _num_op_codesc                 C   s   g | ]}d |> qS )ra   rX   )r   xrX   rX   rY   r   C  s     zRemoteProgress.<listcomp>zdone.z, )	_cur_line	_seen_opserror_linesother_linesz%(remote: )?([\w\s]+):\s+()(\d+)()(.*)z2(remote: )?([\w\s]+):\s+(\d+)% \((\d+)/(\d+)\)(.*)Nr   c                 C   s   g | _ d | _g | _g | _d S r   )r   r   r  r  rc   rX   rX   rY   __init__S  s    zRemoteProgress.__init__linerH   c                 C   s  t |tr|d}n|}|| _| jdr>| j| j dS d\}}| j|}|dkrf| j	|}|s| 
| | j| dS d}| \}}}	}}}
|dkr|| jO }n|dkr|| jO }nx|dkr|| jO }nd|d	kr|| jO }nP|d
kr|| jO }n:|dkr|| jO }n$|dkr.|| jO }n| 
| dS || jkr^| j| || jO }|
dkrld}
|
 }
|
| jr|| jO }|
dt| j  }
|
| j}
| ||ot||ot||
 dS )a^  Parse progress information from the given line as retrieved by
        :manpage:`git-push(1)` or :manpage:`git-fetch(1)`.

        - Lines that do not contain progress info are stored in :attr:`other_lines`.
        - Lines that seem to contain an error (i.e. start with ``error:`` or ``fatal:``)
          are stored in :attr:`error_lines`.
        zutf-8)zerror:zfatal:N)NNr   zCounting objectszCompressing objectszWriting objectszReceiving objectszResolving deltaszFinding sourceszChecking out filesrI   )r   bytesdecoder   r   r  r   re_op_relativer   re_op_absoluteline_droppedr  r   COUNTINGCOMPRESSINGWRITING	RECEIVING	RESOLVINGFINDING_SOURCESCHECKING_OUTr   BEGINrU   r   
DONE_TOKENENDr   TOKEN_SEPARATORupdatefloat)rc   r  line_str	cur_count	max_countr   op_codeZ_remoteZop_nameZ_percentmessagerX   rX   rY   _parse_progress_lineY  sb    








z#RemoteProgress._parse_progress_linec                    s   t dd fdd}|S )z
        :return:
            A progress handler suitable for :func:`~git.cmd.handle_process_output`,
            passing lines on to this progress handler in a suitable format.
        Nr  c                    s     |  S r   )r  rstrip)r  r  rX   rY   r|     s    z3RemoteProgress.new_message_handler.<locals>.handler)r$   )rc   r|   rX   r  rY   new_message_handler  s    z"RemoteProgress.new_message_handlerc                 C   s   dS )zICalled whenever a line could not be understood and was therefore dropped.NrX   )rc   r  rX   rX   rY   r    s    zRemoteProgress.line_droppedrI   )r  r  r  r  rH   c                 C   s   dS )a  Called whenever the progress changes.

        :param op_code:
            Integer allowing to be compared against Operation IDs and stage IDs.

            Stage IDs are :const:`BEGIN` and :const:`END`. :const:`BEGIN` will only be
            set once for each Operation ID as well as :const:`END`. It may be that
            :const:`BEGIN` and :const:`END` are set at once in case only one progress
            message was emitted due to the speed of the operation. Between
            :const:`BEGIN` and :const:`END`, none of these flags will be set.

            Operation IDs are all held within the :const:`OP_MASK`. Only one Operation
            ID will be active per call.

        :param cur_count:
            Current absolute count of items.

        :param max_count:
            The maximum count of items we expect. It may be ``None`` in case there is no
            maximum number of items or if it is (yet) unknown.

        :param message:
            In case of the :const:`WRITING` operation, it contains the amount of bytes
            transferred. It may possibly be used for other purposes as well.

        :note:
            You may read the contents of the current line in
            :attr:`self._cur_line <_cur_line>`.
        NrX   )rc   r  r  r  r  rX   rX   rY   r    s    $zRemoteProgress.update)NrI   )$rg   
__module____qualname____doc__r   int__annotations__ranger  r  r  r  r  r  r  r  r  Z
STAGE_MASKZOP_MASKr  r  	__slots__recompiler
  r	  r  r$   r  r&   r   r   r  r2   r  r  rX   rX   rX   rY   r   3  sB   


Y  
c                       s>   e Zd ZdZdZedd fddZeedddd	Z  Z	S )
r   a  A :class:`RemoteProgress` implementation forwarding updates to any callable.

    :note:
        Like direct instances of :class:`RemoteProgress`, instances of this
        :class:`CallableRemoteProgress` class are not themselves directly callable.
        Rather, instances of this class wrap a callable and forward to it. This should
        therefore not be confused with :class:`git.types.CallableProgress`.
    	_callableN)fnrH   c                    s   || _ t   d S r   )r+  superr  )rc   r,  	__class__rX   rY   r    s    zCallableRemoteProgress.__init__)rd   re   rH   c                 O   s   | j || d S r   r*  rh   rX   rX   rY   r    s    zCallableRemoteProgress.update)
rg   r!  r"  r#  r'  r&   r  r#   r  __classcell__rX   rX   r.  rY   r     s   	c                   @   s
  e Zd ZdZedZedZdZdZ	dZ
dZdZd	Zd
Zee ee ddddZeedddZeedddZedddZedddZedddZeed dddZed'eeed d dd d!Zed(ed d d"d#d$Zed)ed d d"d%d&ZdS )*r   zActors hold information about a person acting on the repository. They can be
    committers and authors or anything with a name and an email as mentioned in the git
    log entries.z<(.*)>z(.*) <(.*?)>ZGIT_AUTHOR_NAMEZGIT_AUTHOR_EMAILZGIT_COMMITTER_NAMEZGIT_COMMITTER_EMAILrF   emailrF   r1  N)rF   r1  rH   c                 C   s   || _ || _d S r   r2  )rc   rF   r1  rX   rX   rY   r    s    zActor.__init__)otherrH   c                 C   s   | j |j ko| j|jkS r   r2  rc   r3  rX   rX   rY   __eq__  s    zActor.__eq__c                 C   s
   | |k S r   rX   r4  rX   rX   rY   __ne__  s    zActor.__ne__r   c                 C   s   t | j| jfS r   )hashrF   r1  r  rX   rX   rY   __hash__  s    zActor.__hash__c                 C   s   | j r| j S dS )NrI   )rF   r  rX   rX   rY   __str__"  s    zActor.__str__c                 C   s   d| j | jf S )Nz<git.Actor "%s <%s>">r2  r  rX   rX   rY   __repr__%  s    zActor.__repr__)stringrH   c                 C   sT   | j |}|r&| \}}t||S | j|}|rFt|ddS t|dS dS )zCreate an :class:`Actor` from a string.

        :param string:
            The string, which is expected to be in regular git format::

                John Doe <jdoe@example.com>

        :return:
            :class:`Actor`
        ra   N)name_email_regexsearchr   r   name_only_regexgroup)clsr;  r   rF   r1  rX   rX   rY   _from_string(  s    
zActor._from_string)Nr6   r7   )env_name	env_emailconfig_readerrH   c                    s   t dd}d tdfdd td fdd}d|| j|fd|| j ffD ]\}}}}	ztj| }
t|||
 W qN tk
r   |d k	rz|d	|}
W n t	k
r   |	 }
Y nX t|||
 t
||st|||	  Y qNX qN|S )
NrI   r   c                      s    s
t    S r   )r   rX   )user_idrX   rY   default_emailK  s    z(Actor._main_actor.<locals>.default_emailc                      s      dd S )N@r   )r   rX   )rF  rX   rY   default_nameQ  s    z'Actor._main_actor.<locals>.default_namerF   r1  user)r   r   	conf_name
conf_emailrP   rQ   setattrrR   r   r   getattr)r@  rB  rC  rD  ZactorrH  attrZevarZcvarrG   valrX   )rF  rE  rY   _main_actorA  s(    


zActor._main_actor)rD  rH   c                 C   s   |  | j| j|S )a  
        :return:
            :class:`Actor` instance corresponding to the configured committer. It
            behaves similar to the git implementation, such that the environment will
            override configuration values of `config_reader`. If no value is set at all,
            it will be generated.

        :param config_reader:
            ConfigReader to use to retrieve the values from in case they are not set in
            the environment.
        )rP  env_committer_nameenv_committer_emailr@  rD  rX   rX   rY   	committeri  s    zActor.committerc                 C   s   |  | j| j|S )zSame as :meth:`committer`, but defines the main author. It may be specified
        in the environment, but defaults to the committer.)rP  env_author_nameenv_author_emailrS  rX   rX   rY   authorx  s    zActor.author)N)N)N) rg   r!  r"  r#  r(  r)  r>  r<  rU  rV  rQ  rR  rJ  rK  r'  r,   r   r  r#   r   r5  r6  r$  r8  r9  r:  classmethodrA  r2   rP  rT  rW  rX   rX   rX   rY   r     s<   

 'c                   @   sD   e Zd ZdZdZeeeef ddddZ	e
ded dd	d
ZdS )r   a  Represents stat information as presented by git at the end of a merge. It is
    created from the output of a diff operation.

    Example::

     c = Commit( sha1 )
     s = c.stats
     s.total         # full-stat-dict
     s.files         # dict( filepath : stat-dict )

    ``stat-dict``

    A dictionary with the following keys and values::

      deletions = number of deleted lines as int
      insertions = number of inserted lines as int
      lines = total number of lines changed as int, or deletions + insertions

    ``full-stat-dict``

    In addition to the items in the stat-dict, it features additional information::

     files = number of changed files as int
    totalfilesN)rZ  r[  rH   c                 C   s   || _ || _d S r   rY  )rc   rZ  r[  rX   rX   rY   r    s    zStats.__init__r9   )rf   textrH   c                 C   s   dddddi d}|  D ]}|d\}}}|dkr@t|pBd}|dkrTt|pVd}	|d d  |7  < |d d  |	7  < |d d	  ||	 7  < |d d
  d7  < ||	||	 d}
|
|d
 | < qt|d |d
 S )zCreate a :class:`Stats` object from output retrieved by
        :manpage:`git-diff(1)`.

        :return:
            :class:`git.Stats`
        r   )
insertions	deletionslinesr[  rY  	-rZ  r]  r^  r_  r[  ra   )r]  r^  r_  )
splitlinesr   r$  rU   r   )r@  rf   r\  Zhshr  Zraw_insertionsZraw_deletionsfilenamer]  r^  Z
files_dictrX   rX   rY   _list_from_string  s"    
zStats._list_from_string)rg   r!  r"  r#  r'  rA   r'   r>   r:   r  rX  r   rd  rX   rX   rX   rY   r     s
   c                   @   s^   e Zd ZdZdZeddddZeeddd	Z	e
d
ddZe
d
ddZed
ddZdS )r   a  Wrapper around a file-like object that remembers the SHA1 of the data written to
    it. It will write a sha when the stream is closed or if asked for explicitly using
    :meth:`write_sha`.

    Only useful to the index file.

    :note:
        Based on the dulwich project.
    )r   sha1N)r   rH   c                 C   s   || _ td| _d S )Nr   )r   r    re  )rc   r   rX   rX   rY   r    s    zIndexFileSHA1Writer.__init__)datarH   c                 C   s   | j | | j|S r   )re  r  r   r   )rc   rf  rX   rX   rY   r     s    zIndexFileSHA1Writer.writer   c                 C   s   | j  }| j| |S r   )re  digestr   r   rc   sharX   rX   rY   	write_sha  s    
zIndexFileSHA1Writer.write_shac                 C   s   |   }| j  |S r   )rj  r   closerh  rX   rX   rY   rk    s    
zIndexFileSHA1Writer.closec                 C   s
   | j  S r   )r   tellr  rX   rX   rY   rl    s    zIndexFileSHA1Writer.tell)rg   r!  r"  r#  r'  r)   r  r$   r$  r   r  rj  rk  rl  rX   rX   rX   rY   r     s   
c                   @   sx   e Zd ZdZdZeddddZdddd	Zedd
dZ	e
dddZddddZddddZddddZdS )r   a  Provides methods to obtain, check for, and release a file based lock which
    should be used to handle concurrent access to the same file.

    As we are a utility class to be derived from, we only use protected methods.

    Locks will automatically be released on destruction.
    
_file_path
_owns_lockN)	file_pathrH   c                 C   s   || _ d| _d S )NFrm  )rc   rp  rX   rX   rY   r    s    zLockFile.__init__r   c                 C   s   |    d S r   )_release_lockr  rX   rX   rY   __del__  s    zLockFile.__del__c                 C   s
   d| j  S )z:return: Path to lockfilez%s.lock)rn  r  rX   rX   rY   _lock_file_path  s    zLockFile._lock_file_pathc                 C   s   | j S )z
        :return:
            True if we have a lock and if the lockfile still exists

        :raise AssertionError:
            If our lock-file does not exist.
        )ro  r  rX   rX   rY   	_has_lock  s    zLockFile._has_lockc              
   C   s   |   rdS |  }t|r0td| j|f zt|dd W 5 Q R X W n0 tk
r| } ztt||W 5 d}~X Y nX d| _	dS )zCreate a lock file as flag for other instances, mark our instance as
        lock-holder.

        :raise IOError:
            If a lock was already present or a lock file could not be written.
        NzILock for file %r did already exist, delete %r in case the lock is illegalw)modeT)
rt  rs  r   r   IOErrorrn  openOSErrorr   ro  )rc   Z	lock_filer   rX   rX   rY   _obtain_lock_or_raise   s    
 zLockFile._obtain_lock_or_raisec                 C   s   |   S )zThe default implementation will raise if a lock cannot be obtained.

        Subclasses may override this method to provide a different implementation.
        )rz  r  rX   rX   rY   _obtain_lock  s    zLockFile._obtain_lockc                 C   s@   |   sdS |  }zt| W n tk
r4   Y nX d| _dS )z Release our lock if we have one.NF)rt  rs  r   ry  ro  )rc   ZlfprX   rX   rY   rq    s    zLockFile._release_lock)rg   r!  r"  r#  r'  r>   r  rr  r   rs  r   rt  rz  r{  rq  rX   rX   rX   rY   r     s   
c                       sJ   e Zd ZdZdZdejfeee	dd fddZ
dd fd	d
Z  ZS )r
   a  The lock file will block until a lock could be obtained, or fail after a
    specified timeout.

    :note:
        If the directory containing the lock was removed, an exception will be raised
        during the blocking period, preventing hangs as the lock can never be obtained.
    )_check_interval_max_block_timeg333333?N)rp  check_interval_smax_block_time_srH   c                    s   t  | || _|| _dS )a  Configure the instance.

        :param check_interval_s:
            Period of time to sleep until the lock is checked the next time.
            By default, it waits a nearly unlimited time.

        :param max_block_time_s:
            Maximum amount of seconds we may lock.
        N)r-  r  r|  r}  )rc   rp  r~  r  r.  rX   rY   r  9  s    zBlockingLockFile.__init__r   c              
      s   t   }|t| j }zt   W q tk
r } zpt   }tt| 	 spd| 	 || f }t||||krd|| | 	 f }t||t 
| j W 5 d}~X Y qX qqdS )zThis method blocks until it obtained the lock, or raises :exc:`IOError` if it
        ran out of time or if the parent directory was not available anymore.

        If this method returns, you are guaranteed to own the lock.
        zVDirectory containing the lockfile %r was not readable anymore after waiting %g secondsz Waited %g seconds for lock at %rN)timer  r}  r-  r{  rw  r   r   r   rs  sleepr|  )rc   Z	starttimeZmaxtimer   Zcurtimemsgr.  rX   rY   r{  L  s(    

zBlockingLockFile._obtain_lock)rg   r!  r"  r#  r'  r[   maxsizer>   r  r$  r  r{  r0  rX   rX   r.  rY   r
   .  s   c                       s   e Zd ZdZdZdeedd fddZdeeddd	d
Zee	dddZ
eedddZeeeeef edddZeeeeef ddddZ  ZS )r	   a  List of iterable objects allowing to query an object by id or by named index::

     heads = repo.heads
     heads.master
     heads['master']
     heads[0]

    Iterable parent objects:

    * :class:`Commit <git.objects.Commit>`
    * :class:`Submodule <git.objects.submodule.base.Submodule>`
    * :class:`Reference <git.refs.reference.Reference>`
    * :class:`FetchInfo <git.remote.FetchInfo>`
    * :class:`PushInfo <git.remote.PushInfo>`

    Iterable via inheritance:

    * :class:`Head <git.refs.head.Head>`
    * :class:`TagReference <git.refs.tag.TagReference>`
    * :class:`RemoteReference <git.refs.remote.RemoteReference>`

    This requires an ``id_attribute`` name to be set which will be queried from its
    contained items to have a means for comparison.

    A prefix can be specified which is to be used in case the id returned by the items
    always contains a prefix that does not matter to the user, so it can be left out.
    _id_attr_prefixrI   zIterableList[T_IterableObj])id_attrprefixrH   c                    s   t  | S r   )r-  __new__)r@  r  r  r.  rX   rY   r    s    zIterableList.__new__Nc                 C   s   || _ || _d S r   r  )rc   r  r  rX   rX   rY   r    s    zIterableList.__init__)rN  rH   c              	   C   sj   zt | |}|r|W S W n ttfk
r2   Y nX zt| tt| W dS  ttfk
rd   Y dS X d S )NTF)list__contains__AttributeError	TypeErrorrM  r3   r   )rc   rN  rvalrX   rX   rY   r    s    
zIterableList.__contains__c                 C   s8   | j | }| D ]}t|| j|kr|  S qt| |S r   )r  rM  r  r  __getattribute__)rc   rN  itemrX   rX   rY   __getattr__  s
    

zIterableList.__getattr__)r   rH   c              
   C   s   t |tttfstdt |tr.t| |S t |trBtdnDzt| |W S  t	k
r } zt
d| j|  |W 5 d }~X Y nX d S )N-Index of IterableList should be an int or strzIndex should be an int or strzNo item found with id %r)r   r$  r   sliceAssertionErrorr  __getitem__r   rM  r  
IndexErrorr  )rc   r   r   rX   rX   rY   r    s    


zIterableList.__getitem__c                 C   s   t |ttfstdtt|}t |tsvd}| j| }t| D ] \}}t|| j|kr@|} qbq@|dkrvt	d| t
| | d S )Nr  zItem with name %s not found)r   r$  r   r  r3   r  r   rM  r  r  r  __delitem__)rc   r   ZdelindexrF   ir  rX   rX   rY   r    s    


zIterableList.__delitem__)rI   )rI   )rg   r!  r"  r#  r'  r   r  r  objectr   r  rC   r  r2   r@   r$  r  r  r  r0  rX   rX   r.  rY   r	   p  s   c                   @   sZ   e Zd ZU dZdZeed< eede	e	e
e dddZede	e	ee ddd	Zd
S )r   a  Defines an interface for iterable items, so there is a uniform way to retrieve
    and iterate items within the git repository.

    Subclasses:

    * :class:`Submodule <git.objects.submodule.base.Submodule>`
    * :class:`Commit <git.objects.Commit>`
    * :class:`Reference <git.refs.reference.Reference>`
    * :class:`PushInfo <git.remote.PushInfo>`
    * :class:`FetchInfo <git.remote.FetchInfo>`
    * :class:`Remote <git.remote.Remote>`
    rX   _id_attribute_r9   rf   rd   re   rH   c                 O   s   t ddS )aS  Find (all) items of this type.

        Subclasses can specify `args` and `kwargs` differently, and may use them for
        filtering. However, when the method is called with no additional positional or
        keyword arguments, subclasses are obliged to to yield all items.

        :return:
            Iterator yielding Items
        To be implemented by SubclassNNotImplementedErrorr@  rf   rd   re   rX   rX   rY   
iter_items  s    zIterableObj.iter_itemsc                 O   s&   t | j}|| j|f|| |S )a  Find (all) items of this type and collect them into a list.

        For more information about the arguments, see :meth:`iter_items`.

        :note:
            Favor the :meth:`iter_items` method as it will avoid eagerly collecting all
            items. When there are many items, that can slow performance and increase
            memory usage.

        :return:
            list(Item,...) list of item instances
        r	   r  extendr  r@  rf   rd   re   Zout_listrX   rX   rY   
list_items  s    
zIterableObj.list_itemsN)rg   r!  r"  r#  r'  r   r%  rX  r   r#   r*   rC   r  r	   r  rX   rX   rX   rY   r     s   
c                   @   s$   e Zd ZdZeeeddddZdS )IterableClassWatcherzbMetaclass that issues :exc:`DeprecationWarning` when :class:`git.util.Iterable`
    is subclassed.N)rF   basesclsdictrH   c                 C   s2   |D ](}t |tkrtjd| dtdd qd S )Nz!GitPython Iterable subclassed by zq. Iterable is deprecated due to naming clash since v3.1.18 and will be removed in 4.0.0. Use IterableObj instead.   )
stacklevel)typer  warningswarnDeprecationWarning)r@  rF   r  r  baserX   rX   rY   r    s    
zIterableClassWatcher.__init__)rg   r!  r"  r#  r   r/   r'   r  rX   rX   rX   rY   r    s   r  c                   @   sH   e Zd ZdZdZdZedeeedddZedeeeddd	Z	d
S )IterablezDeprecated, use :class:`IterableObj` instead.

    Defines an interface for iterable items, so there is a uniform way to retrieve
    and iterate items within the git repository.
    rX   z5attribute that most suitably identifies your instancer9   r  c                 O   s   t ddS )zDeprecated, use :class:`IterableObj` instead.

        Find (all) items of this type.

        See :meth:`IterableObj.iter_items` for details on usage.

        :return:
            Iterator yielding Items
        r  Nr  r  rX   rX   rY   r  #  s    zIterable.iter_itemsc                 O   s&   t | j}|| j|f|| |S )a  Deprecated, use :class:`IterableObj` instead.

        Find (all) items of this type and collect them into a list.

        See :meth:`IterableObj.list_items` for details on usage.

        :return:
            list(Item,...) list of item instances
        r  r  rX   rX   rY   r  0  s    
zIterable.list_itemsN)
rg   r!  r"  r#  r'  r  rX  r#   r  r  rX   rX   rX   rY   r    s   r  )	metaclass)r   )F)N).).)T)r[   __all__r\   r   abcr   
contextlib	functoolsr   r   loggingrP   os.pathrs   r   r   r(  r   rx   r   r  urllib.parser   r   r  Z
gitdb.utilr   r   r   r   r   r   r    r!   r"   typingr#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   Zgit.cmdr5   Z
git.configr6   r7   Z
git.remoter8   Zgit.repo.baser9   Z	git.typesr:   r;   r<   r=   r>   r?   r@   rA   rB   rC   	getLoggerrg   rS   r   r   rZ   r]   r   r^   r_   r   contextmanagerro   rr   r   r   r$  r   r   r   r   r   r   r   r   r   r   r)  Ir   r%  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
   r	   r   r  r  r  rX   rX   rX   rY   <module>   s    

,P,


 !		
&"
	 " 9 >#NBb4