o
    Ďi                  	   @   s  U d dl Z g dZe jdkre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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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/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 e2rd dl7m8Z8 d dl9m:Z:m;Z; d dl<m=Z= d dl>m?Z? d dl@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZI e3de4d ddZJe
KeLZMdeNdeOdeOfddZPdeNdeOdeOfddZQeQddZReQddZSe3dZTde(deTf de(deTf fd d!ZUejVd"eEde*eEddf fd#d$ZWejVdeNd%eNde*d& fd'd(ZXd)eEddfd*d+ZYd)eEddfd,d-ZZdd/e'd0e'd1e[de[fd2d3Z\d4eEd5eEdeEfd6d7Z]e jdkryd)eEdeEfd8dZ^d)eEdeNfd9d:Z_e^Z`nd)eEdeNfd;d:Z_e_Z`d4eEd5eEdeEfd<d=Zadd)eEd?eOdeOfd@dAZbde0eN fdBdCZcddDeNd)e.eE de-eN fdEdFZddGe.eN d)eNdeNfdHdIZeefdJdKdL d>fefdMeed>fefdNeed>fefdOejgdPdL dfefdQdRdL d>ffZhe1e1e/eN e(eOf df eidS< d)eNdeNfdTdUZjefdVZkd)eEdeNfdWdXZli Zme)eNe.eO f eidY< dZeNdeOfd[d\Zne6dZddeDd> fd]d^Zoe6dZeEdeOfd_d^ZodZe4deEf deOfd`d^ZodeNfdadbZpdce4ejqddf dee%ddfdfdgZre6dd5ddheOddfdidjZse6dd5eEdheOdeNfdkdjZsdd5e4deEf dheOde.eE fdldjZsdme0eN de-eN fdndoZtG dpdq dqZuG drds dseuZvG dtdu duZwG dvdw dwZxG dxdy dyZyG dzd{ d{ZzG d|d} d}ezZ{G d~d de-eJ Z|eIG dd deFZ}G dd de~ZG dd dedZd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)Path)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   sj   zt j|  }W n ty   | Y S w td|  |  }|dv r%dS |dv r+d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.>    0nofalseF>   1yestrueTz-%s has unrecognized value %r, treating as %r.)osenvironKeyError_loggerwarningstriplower)rG   rH   valueadjusted_value rZ   D/home/jeff/fluffinator/venv/lib/python3.10/site-packages/git/util.py_read_env_flags   s    r\   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platformr\   )rG   rH   rZ   rZ   r[   _read_win_env_flag   s   
r_   r   HIDE_WINDOWS_FREEZE_ERRORSTfunc.c              	      s8   ddl m  tdddtdtdtf fdd	}|S )
ztMethods with this decorator raise :exc:`~git.exc.InvalidGitRepositoryError` if
    they encounter a bare repository.   )InvalidGitRepositoryErrorselfr9   argskwargsrI   c                    s,   | j jr dj | g|R i |S )Nz/Method '%s' cannot operate on bare repositories)repobare__name__re   rf   rg   rd   rb   rZ   r[   wrapper   s   zunbare_repo.<locals>.wrapper)excrd   r   r$   ra   )rb   rm   rZ   rl   r[   r      s   "r   new_dirc              	   c   s8    t  }t |  z| V  W t | dS t | w )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)rQ   getcwdchdir)ro   old_dirrZ   rZ   r[   cwd   s   
rs   rX   )NNNc              	   c   s`    t | }|t j| < zdV  W |du rt j| = dS |t j| < dS |du r*t j| = w |t j| < w )z=Context manager to temporarily patch an environment variable.N)rQ   getenvrR   )rG   rX   	old_valuerZ   rZ   r[   	patch_env   s   

rv   pathc                 C   s`   dt dtdtddfdd}tjdkrt|  dS tjd	kr'tj| |d
 dS 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.
    functionrw   _excinforI   Nc              
   S   sX   t |tj z| | W dS  ty+ } ztr&ddlm} |d| | d}~ww )zuCallback for :func:`shutil.rmtree`.

        This works as either a ``onexc`` or ``onerror`` style callback.
        r   )SkipTestz%FIXME: fails with: PermissionError
  N)rQ   chmodstatS_IWUSRPermissionErrorr   unittestrz   )rx   rw   ry   exrz   rZ   rZ   r[   handler   s   zrmtree.<locals>.handlerr   )      )onexc)onerror)r'   r?   r$   r]   r^   shutilr   version_info)rw   r   rZ   rZ   r[   r      s   

r   c                 C   s2   t | rtjdkrt| d t|  dS dS )zWEnsure file deleted also on *Windows* where read-only files need special
    treatment.r   i  N)ospisfiler]   r^   rQ   r{   removerw   rZ   rZ   r[   rmfile   s
   

r      sourcedestination
chunk_sizec                 C   s:   d}	 |  |}|| |t|7 }t||k r	 |S q)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chunkrZ   rZ   r[   r      s   

r   apc                 G   sl   t | }|D ],}t |}|sq|dr||dd 7 }q|dks(|dr-||7 }q|d| 7 }q|S )zmJoin path tokens together similar to osp.join, but always use ``/`` instead of
    possibly ``\`` on Windows./rc   NrJ   )rQ   fspath
startswithendswith)r   r   rw   brZ   rZ   r[   r     s   



r   c                 C      t | } | ddS )Nr   \rQ   r   replacer   rZ   rZ   r[   r   $     
c                 C   r   )Nr   r   r   r   rZ   rZ   r[   r   (  r   r   c                 C   s
   t | S N)rQ   r   r   rZ   rZ   r[   r   /     
c                 G   s   t t| g|R  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   rZ   rZ   r[   r   5  s   r   Fis_filec                 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isdirrQ   makedirs)rw   r   rZ   rZ   r[   r   >  s   


r   c                  C   s>   t jdd } | rtdd | t jD S tjdkrdS dS )NPATHEXTc                 s   s    | ]}|  V  qd S r   )upper).0r   rZ   rZ   r[   	<genexpr>T  s    z&_get_exe_extensions.<locals>.<genexpr>r   )z.BATz.COMz.EXErZ   )rQ   rR   gettuplesplitpathsepr]   r^   )r   rZ   rZ   r[   _get_exe_extensionsQ  s   
r   programc                    s   t  dtdtffdd}g }|stjd }t|tjD ]'}|d}|rGt	
||   g fddD  D ]}||rF|| q;q |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.
    fpathrI   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   rZ   r[   r   p  s    z,py_where.<locals>.is_exec.<locals>.<genexpr>)r   r   rQ   accessX_OKr]   r^   anyr   )winprog_extsr   r[   is_execk  s
   
$zpy_where.<locals>.is_execPATH"c                    s   g | ]}d  |f qS )z%s%srZ   )r   e)exe_pathrZ   r[   
<listcomp>{  s    zpy_where.<locals>.<listcomp>)r   strboolrQ   rR   r   r   r   rV   r   joinappend)r   rw   r   progsfolderfrZ   )r   r   r[   py_where[  s   	


r   drivec                 C   sv   t |r
| s
|}n&|ot t t |}t |r&| r!|}nt|}n
| r0d|  |f }t|}|	ddS )Nz/proc/cygdrive/%s/%sr   r   )
r   isabsnormpath
expandvars
expandusercygpathrW   rQ   r   r   )r   rw   r   p_strrZ   rZ   r[   
_cygexpath  s   


r   z*\\\\\?\\UNC\\([^\\]+)\\([^\\]+)(?:\\(.*))?c                 C   s   d| || ddf S )Nz
//%s/%s/%sr   r   )r   )servershare	rest_pathrZ   rZ   r[   <lambda>  s    r   z\\\\\?\\(\w):[/\\](.*)z(\w):[/\\](.*)z	file:(.*)c                 C      | S r   rZ   )r   rZ   rZ   r[   r         z(\w{2,}:.*)c                 C   r   r   rZ   )urlrZ   rZ   r[   r     r   _cygpath_parsersc                 C   s^   t | } | ds-tD ]\}}}|| }|r'||  } |r$t| }  | S qtd| } | S )zJUse :meth:`git.cmd.Git.polish_url` instead, that works on any environment.)z	/cygdrivez//z/proc/cygdriveN)rQ   r   r   r   matchgroupsr   r   )rw   regexparserrecurser   rZ   rZ   r[   r     s   



r   z(?:/proc)?/cygdrive/(\w)(/.*)?c                 C   sD   t | } t| }|r| \}}d| |pdf } | ddS )Nz%s:%srJ   r   r   )rQ   r   _decygpath_regexr   r   r   r   )rw   mr   r   rZ   rZ   r[   	decygpath  s   

r   _is_cygwin_cachegit_executablec           	   
   C   s   t | }|d u rwd}zOt| }|s"t| }|r t|d nd}t|d}t| r5t	|tj
sEtd| d |t | < |W S tj|gtjdd}| \}}d	|v }W n tyr } ztd
| W Y d }~nd }~ww |t | < |S )NFr   rJ   unamez&Failed checking if running in CYGWIN: z is not an executableT)stdoutuniversal_newlinesCYGWINz/Failed checking if running in CYGWIN due to: %r)r   r   r   r   r   r   r   r   rQ   r   r   rT   debug
subprocessPopenPIPEcommunicate	Exception)	r   	is_cygwingit_dirres	uname_cmdprocess	uname_out_r   rZ   rZ   r[   _is_cygwin_git  s,   

r   c                 C      d S r   rZ   r   rZ   rZ   r[   is_cygwin_git     r   c                 C   r   r   rZ   r   rZ   rZ   r[   r     r   c                 C   s>   t dtjd|  tjdkrdS | d u rdS tt| S )Nzsys.platform=z, git_executable=cygwinF)rT   r   r]   r^   r   r   r   rZ   rZ   r[   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^   noderZ   rZ   rZ   r[   r     s   r   proczGit.AutoInterruptrg   c                 K   s   | j di | dS )zXWait for the process (clone, fetch, pull or push) and handle its errors
    accordingly.NrZ   )wait)r   rg   rZ   rZ   r[   finalize_process  s   r   expand_varsc                 C   r   r   rZ   r   r   rZ   rZ   r[   expand_path  r   r  c                 C   r   r   rZ   r  rZ   rZ   r[   r    s   c                 C   sR   t | tr	|  S zt| } |rt| } tt| W S  ty(   Y d S w r   )	
isinstancer   resolver   r   r   r   abspathr   r  rZ   rZ   r[   r    s   


cmdlinec              	   C   s   g }t | D ]L\}}|| z:t|}|jdu r |jdu r W q|jdur1|j|j|jdd}|jdurB|j|j|jdd}t|||< W q t	yR   Y qw |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  new_cmdlineindexto_parser   rZ   rZ   r[   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ZdeddfddZdeegdf fddZdeddfddZ 		ddede!ee"f de!ee"df deddf
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 )rc   rZ   )r   xrZ   rZ   r[   r   K  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+)\)(.*)rI   Nc                 C   s   g | _ d | _g | _g | _d S r   )r  r  r  r  re   rZ   rZ   r[   __init__[  s   
zRemoteProgress.__init__linec                 C   s  t |tr|d}n|}|| _| jdr| j| j dS d\}}| j|}|du r3| j	|}|sB| 
| | j| dS d}| \}}}	}}}
|dkrX|| jO }nC|dkrb|| jO }n9|dkrl|| jO }n/|d	krv|| jO }n%|d
kr|| jO }n|dkr|| jO }n|dkr|| jO }n| 
| dS || jvr| j| || jO }|
du rd}
|
 }
|
| 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 filesrJ   )r  bytesdecoder  r   r  r   re_op_relativer   re_op_absoluteline_droppedr  r   COUNTINGCOMPRESSINGWRITING	RECEIVING	RESOLVINGFINDING_SOURCESCHECKING_OUTr  BEGINrV   r   
DONE_TOKENENDr   TOKEN_SEPARATORupdatefloat)re   r  line_str	cur_count	max_countr   op_code_remoteop_name_percentmessagerZ   rZ   r[   _parse_progress_linea  sb   







z#RemoteProgress._parse_progress_linec                    s   dt ddf 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.
        r  rI   Nc                    s     |  S r   )r5  rstrip)r  r  rZ   r[   r     s   z3RemoteProgress.new_message_handler.<locals>.handler)r%   )re   r   rZ   r  r[   new_message_handler  s   z"RemoteProgress.new_message_handlerc                 C      dS )zICalled whenever a line could not be understood and was therefore dropped.NrZ   )re   r  rZ   rZ   r[   r    s   zRemoteProgress.line_droppedrJ   r0  r.  r/  r4  c                 C   r8  )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>`.
        NrZ   )re   r0  r.  r/  r4  rZ   rZ   r[   r+    s   $zRemoteProgress.updaterI   NNrJ   )$rj   
__module____qualname____doc__r  int__annotations__ranger'  r)  r   r!  r"  r#  r$  r%  r&  
STAGE_MASKOP_MASKr(  r*  	__slots__recompiler  r  r  r%   r5  r'   r   r7  r  r3   r,  r+  rZ   rZ   rZ   r[   r   ;  sL   
 


Y
r   c                       sD   e Zd ZdZdZdeddf fddZded	eddf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`.
    	_callablefnrI   Nc                    s   || _ t   d S r   )rG  superr  )re   rH  	__class__rZ   r[   r       zCallableRemoteProgress.__init__rf   rg   c                 O   s   | j |i | d S r   rF  rk   rZ   rZ   r[   r+    s   zCallableRemoteProgress.update)
rj   r;  r<  r=  rC  r'   r  r$   r+  __classcell__rZ   rZ   rJ  r[   r     s
    	r   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dee d	ee ddfddZdedefddZdedefddZdefddZdefddZdefddZededd fddZe	d'dededed  dd fd!d"Zed'ded  dd fd#d$Zed'ded  dd f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(.*) <(.*?)>GIT_AUTHOR_NAMEGIT_AUTHOR_EMAILGIT_COMMITTER_NAMEGIT_COMMITTER_EMAILrG   emailrG   rR  rI   Nc                 C      || _ || _d S r   rS  )re   rG   rR  rZ   rZ   r[   r       
zActor.__init__otherc                 C   s   | j |j ko| j|jkS r   rS  re   rV  rZ   rZ   r[   __eq__!  s   zActor.__eq__c                 C   s
   | |k S r   rZ   rW  rZ   rZ   r[   __ne__$  r   zActor.__ne__c                 C   s   t | j| jfS r   )hashrG   rR  r  rZ   rZ   r[   __hash__'     zActor.__hash__c                 C   s   | j r| j S dS r:  )rG   r  rZ   rZ   r[   __str__*  r\  zActor.__str__c                 C   s   d| j | jf S )Nz<git.Actor "%s <%s>">rS  r  rZ   rZ   r[   __repr__-  r\  zActor.__repr__stringc                 C   sP   | j |}|r| \}}t||S | j|}|r#t|ddS t|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`
        rc   N)name_email_regexsearchr   r   name_only_regexgroup)clsr_  r   rG   rR  rZ   rZ   r[   _from_string0  s   

zActor._from_stringenv_name	env_emailconfig_reader)Nr7   r8   c                    s   t dd}d dtffdd dtf fdd}d|| j|fd|| j ffD ]G\}}}}	ztj| }
t|||
 W q' tyn   |d ur`z|d	|}
W n t	yY   |	 }
Y nw t|||
 t
||slt|||	  Y q'w |S )
NrJ   rI   c                      s    st    S r   )r   rZ   )user_idrZ   r[   default_emailS  s   z(Actor._main_actor.<locals>.default_emailc                      s      dd S )N@r   )r   rZ   )rj  rZ   r[   default_nameY  r\  z'Actor._main_actor.<locals>.default_namerG   rR  user)r   r   	conf_name
conf_emailrQ   rR   setattrrS   r   r   getattr)rd  rf  rg  rh  actorrl  attrevarcvarrH   valrZ   )rj  ri  r[   _main_actorI  s.   



zActor._main_actorc                 C      |  | 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.
        )rw  env_committer_nameenv_committer_emailrd  rh  rZ   rZ   r[   	committerq  s   zActor.committerc                 C   rx  )zSame as :meth:`committer`, but defines the main author. It may be specified
        in the environment, but defaults to the committer.)rw  env_author_nameenv_author_emailr{  rZ   rZ   r[   author  s   zActor.authorr   ) rj   r;  r<  r=  rD  rE  rb  r`  r}  r~  ry  rz  rn  ro  rC  r-   r   r  r$   r   rX  rY  r>  r[  r]  r^  classmethodre  r3   rw  r|  r  rZ   rZ   rZ   r[   r     sD    

'r   c                   @   sL   e Zd ZdZdZdedeeef ddfddZ	e
d	d
dedd f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
      change_type = type of change as str, A|C|D|M|R|T|U|X|B

    ``full-stat-dict``

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

     files = number of changed files as int
    totalfilesr  r  rI   Nc                 C   rT  r   r  )re   r  r  rZ   rZ   r[   r    rU  zStats.__init__rh   r:   textc                 C   s   dddddi d}|  D ]Z}|d\}}}}|dkr!t|p"d}	|dkr+t|p,d}
|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  r  	-r  r  r  r  r  rc   )r  r  r  change_type)
splitlinesr   r>  rV   r   )rd  rh   r  hshr  r  raw_insertionsraw_deletionsfilenamer  r  
files_dictrZ   rZ   r[   _list_from_string  s$   
zStats._list_from_string)rj   r;  r<  r=  rC  rB   r(   r?   r;   r  r  r   r  rZ   rZ   rZ   r[   r     s    r   c                   @   sb   e Zd ZdZdZdeddfddZdedefd	d
Z	de
fddZde
fddZdef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   sha1r   rI   Nc                 C   s   || _ td| _d S )N    )r   r!   r  )re   r   rZ   rZ   r[   r    rL  zIndexFileSHA1Writer.__init__datac                 C   s   | j | | j|S r   )r  r+  r   r   )re   r  rZ   rZ   r[   r     s   zIndexFileSHA1Writer.writec                 C   s   | j  }| j| |S r   )r  digestr   r   re   sharZ   rZ   r[   	write_sha  s   
zIndexFileSHA1Writer.write_shac                 C   s   |   }| j  |S r   )r  r   closer  rZ   rZ   r[   r    s   
zIndexFileSHA1Writer.closec                 C   s
   | j  S r   )r   tellr  rZ   rZ   r[   r    r   zIndexFileSHA1Writer.tell)rj   r;  r<  r=  rC  r*   r  r%   r>  r   r  r  r  r  rZ   rZ   rZ   r[   r     s    
r   c                   @   sj   e Zd ZdZdZdeddfddZddd	Zdefd
dZ	de
fddZdddZdddZ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_lock	file_pathrI   Nc                 C   s   || _ d| _d S )NFr  )re   r  rZ   rZ   r[   r    rU  zLockFile.__init__c                 C   s   |    d S r   )_release_lockr  rZ   rZ   r[   __del__     zLockFile.__del__c                 C   s
   d| j  S )z:return: Path to lockfilez%s.lock)r  r  rZ   rZ   r[   _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.
        )r  r  rZ   rZ   r[   	_has_lock   s   zLockFile._has_lockc              
   C   s   |   rdS |  }t|rtd| j|f zt|dd W d   n1 s*w   Y  W n tyC } ztt||d}~ww 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)
r  r  r   r   IOErrorr  openOSErrorr   r  )re   	lock_filer   rZ   rZ   r[   _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.
        )r  r  rZ   rZ   r[   _obtain_lock"  s   zLockFile._obtain_lockc                 C   s>   |   sdS |  }zt| W n	 ty   Y nw d| _dS )z Release our lock if we have one.NF)r  r  r   r  r  )re   lfprZ   rZ   r[   r  )  s   
zLockFile._release_lockr9  )rj   r;  r<  r=  rC  r?   r  r  r   r  r   r  r  r  r  rZ   rZ   rZ   r[   r     s    



r   c                	       sL   e Zd ZdZdZdejfdedede	ddf fd	d
Z
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?r  check_interval_smax_block_time_srI   Nc                    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)rI  r  r  r  )re   r  r  r  rJ  rZ   r[   r  C  s   
zBlockingLockFile.__init__c              
      s   t   }|t| j }	 zt   W dS  ty\ } z<t   }tt| 	 s9d| 	 || f }t||||krLd|| | 	 f }t||t 
| j W Y d}~nd}~ww q)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.
        TzVDirectory containing the lockfile %r was not readable anymore after waiting %g secondsz Waited %g seconds for lock at %rN)timer,  r  rI  r  r  r   r   r   r  sleepr  )re   	starttimemaxtimer   curtimemsgrJ  rZ   r[   r  V  s0   

zBlockingLockFile._obtain_lockr9  )rj   r;  r<  r=  rC  r]   maxsizer?   r,  r>  r  r  rM  rZ   rZ   rJ  r[   r
   8  s    r
   c                       s   e Zd ZdZdZddededdf fdd	Zddededd
fddZdede	fddZ
dedefddZdeeeeef defddZdeeeeef dd
f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_prefixrJ   id_attrprefixrI   zIterableList[T_IterableObj]c                    s   t  | S r   )rI  __new__)rd  r  r  rJ  rZ   r[   r    r  zIterableList.__new__Nc                 C   rT  r   r  )re   r  r  rZ   rZ   r[   r    rU  zIterableList.__init__rs  c              	   C   sb   zt | |}|r|W S W n ttfy   Y nw zt| tt| W dS  ttfy0   Y dS w )NTF)list__contains__AttributeError	TypeErrorrq  r4   r   )re   rs  rvalrZ   rZ   r[   r    s   zIterableList.__contains__c                 C   s8   | j | }| D ]}t|| j|kr|  S qt| |S r   )r  rq  r  r  __getattribute__)re   rs  itemrZ   rZ   r[   __getattr__  s   
zIterableList.__getattr__r  c              
   C   sj   t |trt| |S t |trtdz	t| tt|W S  t	y4 } zt
d| j | |d }~ww )NzIndex should be an int or strzNo item found with id )r  r>  r  __getitem__slicer  rq  r4   r   r  
IndexErrorr  )re   r  r   rZ   rZ   r[   r    s   

zIterableList.__getitem__c                 C   sp   t t|}t|tr0d}| j| }t| D ]\}}t|| j|kr%|} nq|dkr0td| t	
| | d S )NzItem with name %s not found)r4   r>  r  r   r  r  rq  r  r  r  __delitem__)re   r  delindexrG   ir  rZ   rZ   r[   r    s   


zIterableList.__delitem__)rJ   )rj   r;  r<  r=  rC  r   r  r  objectr   r  rD   r  r3   rA   r>  r  r  r  rM  rZ   rZ   rJ  r[   r	   z  s    &r	   c                   @   sf   e Zd ZU dZdZeed< eeddde	de	de
e fd	d
Zeddde	de	dee f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>`
    rZ   _id_attribute_rh   r:   rf   rg   rI   c                 O      t d)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 SubclassNotImplementedErrorrd  rh   rf   rg   rZ   rZ   r[   
iter_items  s   zIterableObj.iter_itemsc                 O   ,   t | j}|| j|g|R i | |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  rd  rh   rf   rg   out_listrZ   rZ   r[   
list_items  s   
zIterableObj.list_itemsN)rj   r;  r<  r=  rC  r   r?  r  r   r$   r+   rD   r  r	   r  rZ   rZ   rZ   r[   r     s   
 "$r   c                   @   s*   e Zd ZdZdedededdfddZdS )	IterableClassWatcherzbMetaclass that issues :exc:`DeprecationWarning` when :class:`git.util.Iterable`
    is subclassed.rG   basesclsdictrI   Nc                 C   s2   |D ]}t |tu 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)rd  rG   r  r  baserZ   rZ   r[   r    s   
zIterableClassWatcher.__init__)rj   r;  r<  r=  r   r0   r(   r  rZ   rZ   rZ   r[   r    s    r  c                	   @   sT   e Zd ZdZdZdZedddededefd	d
Zedddededef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.
    rZ   z5attribute that most suitably identifies your instancerh   r:   rf   rg   rI   c                 O   r  )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  r  r  rZ   rZ   r[   r  )  s   zIterable.iter_itemsc                 O   r  )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  rZ   rZ   r[   r  6  s   
zIterable.list_itemsN)
rj   r;  r<  r=  rC  r  r  r$   r  r  rZ   rZ   rZ   r[   r    s     r  )	metaclass)r   )Fr   ).)T)r]   __all__r^   r   abcr   
contextlib	functoolsr   r   loggingrQ   os.pathrw   r   pathlibr   rD  r   r|   r   r  urllib.parser   r   r  
gitdb.utilr   r   r   r   r   r    r!   r"   r#   typingr$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   git.cmdr6   
git.configr7   r8   
git.remoter9   git.repo.baser:   	git.typesr;   r<   r=   r>   r?   r@   rA   rB   rC   rD   	getLoggerrj   rT   r   r   r\   r_   r   r`   ra   r   contextmanagerrs   rv   r   r   r>  r   r   r   r   r   r   r   r   r   r   rE  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  rZ   rZ   rZ   r[   <module>   s   


,P,


"!		 
&"
 $" 9 @#NB^4